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 apps/mu.subx
    6 #   $ ./a.elf < prog.mu > prog.elf
    7 
    8 # == Goals
    9 # 1. Be memory safe. It should be impossible to corrupt the heap, or to create
   10 # a bad pointer. (Requires strong type safety.)
   11 # 2. Do as little as possible to achieve goal 1. The translator should be
   12 # implementable in machine code.
   13 #   - minimize impedance mismatch between source language and SubX target
   14 #     (e.g. programmer manages registers manually)
   15 #   - checks over syntax
   16 #     (e.g. programmer's register allocation is checked)
   17 #   - runtime checks to avoid complex static analysis
   18 #     (e.g. array indexing always checks bounds)
   19 
   20 # == Language description
   21 # A program is a sequence of function and type definitions.
   22 #
   23 # Function example:
   24 #   fn foo n: int -> _/eax: int {
   25 #     ...
   26 #   }
   27 #
   28 # Functions consist of a name, optional inputs, optional outputs and a block.
   29 #
   30 # Function inputs and outputs are variables. All variables have a type and
   31 # storage specifier. They can be placed either in memory (on the stack) or in
   32 # one of 6 named registers.
   33 #   eax ecx edx ebx esi edi
   34 # Variables in registers must be primitive 32-bit types.
   35 # Variables not explicitly placed in a register are on the stack.
   36 #
   37 # Function inputs are always passed in memory (on the stack), while outputs
   38 # are always returned in registers. Outputs can't be named; they use the
   39 # dummy value '_'.
   40 #
   41 # Blocks mostly consist of statements.
   42 #
   43 # Statements mostly consist of a name, optional inputs and optional outputs.
   44 #
   45 # Statement inputs are variables or literals. Variables need to specify type
   46 # (and storage) the first time they're mentioned but not later.
   47 #
   48 # Statement outputs, like function outputs, must be variables in registers.
   49 #
   50 # Statement names must be either primitives or user-defined functions.
   51 #
   52 # Primitives can write to any register.
   53 # User-defined functions only write to hard-coded registers. Outputs of each
   54 # call must have the same registers as in the function definition.
   55 #
   56 # There are some other statement types:
   57 #   - blocks. Multiple statements surrounded by '{...}' and optionally
   58 #     prefixed with a label name and ':'
   59 #       - {
   60 #           ...
   61 #         }
   62 #       - foo: {
   63 #           ...
   64 #         }
   65 #
   66 #   - variable definitions on the stack. E.g.:
   67 #       - var foo: int
   68 #       - var bar: (array int 3)
   69 #     There's no initializer; variables are automatically initialized.
   70 #     The type of a local variable is either word-length (4 bytes) or starts with 'ref'.
   71 #
   72 #   - variables definitions in a register. E.g.:
   73 #       - var foo/eax: int <- add bar 1
   74 #     The initializer is mandatory and must be a valid instruction that writes
   75 #     a single output to the right register. In practice registers will
   76 #     usually be either initialized by primitives or copied from eax.
   77 #       - var eax: int <- foo bar quux
   78 #         var floo/ecx: int <- copy eax
   79 #
   80 # Still todo:
   81 #   global variables
   82 #   union types
   83 #
   84 # Formal types:
   85 #   A program is a linked list of functions
   86 #   A function contains:
   87 #     name: (handle array byte)
   88 #     inouts: linked list of vars  <-- 'inouts' is more precise than 'inputs'
   89 #       data: (handle var)
   90 #       next: (handle list)
   91 #     outputs: linked list of vars
   92 #       data: (handle var)
   93 #       next: (handle list)
   94 #     body: (handle block)
   95 #   A var-type contains:
   96 #     name: (handle array byte)
   97 #     type: (handle type-tree)
   98 #
   99 #   A statement can be:
  100 #     tag 0: a block
  101 #     tag 1: a simple statement (stmt1)
  102 #     tag 2: a variable defined on the stack
  103 #     tag 3: a variable defined in a register
  104 #
  105 #   A block contains:
  106 #     tag: 0
  107 #     statements: (handle list stmt)
  108 #     name: (handle array byte) -- starting with '$'
  109 #
  110 #   A regular statement contains:
  111 #     tag: 1
  112 #     operation: (handle array byte)
  113 #     inouts: (handle list operand)
  114 #     outputs: (handle list var)
  115 #
  116 #   A variable defined on the stack contains:
  117 #     tag: 2
  118 #     name: (handle array byte)
  119 #     type: (handle type-tree)
  120 #
  121 #   A variable defined in a register contains:
  122 #     tag: 3
  123 #     name: (handle array byte)
  124 #     type: (handle type-tree)
  125 #     reg: (handle array byte)
  126 
  127 # == Translation: managing the stack
  128 # Now that we know what the language looks like in the large, let's think
  129 # about how translation happens from the bottom up. One crucial piece of the
  130 # puzzle is how Mu will clean up variables defined on the stack for you.
  131 #
  132 # Assume that we maintain a 'functions' list while parsing source code. And a
  133 # 'primitives' list is a global constant. Both these contain enough information
  134 # to perform type-checking on function calls or primitive statements, respectively.
  135 #
  136 # Defining variables pushes them on a stack with the current block depth and
  137 # enough information about their location (stack offset or register).
  138 # Starting a block increments the current block id.
  139 # Each statement now has enough information to emit code for it.
  140 # Ending a block is where the magic happens:
  141 #   pop all variables at the current block depth
  142 #   emit code to restore all register variables introduced at the current depth
  143 #   emit code to clean up all stack variables at the current depth (just increment esp)
  144 #   decrement the current block depth
  145 #
  146 # Formal types:
  147 #   live-vars: stack of vars
  148 #   var:
  149 #     name: (handle array byte)
  150 #     type: (handle type-tree)
  151 #     block: int
  152 #     stack-offset: int  (added to ebp)
  153 #     register: (handle array byte)
  154 #       either usual register names
  155 #       or '*' to indicate any register
  156 #   At most one of stack-offset or register-index must be non-zero.
  157 #   A register of '*' designates a variable _template_. Only legal in formal
  158 #   parameters for primitives.
  159 
  160 # == Translating a single function call
  161 # This one's easy. Assuming we've already checked things, we just drop the
  162 # outputs (which use hard-coded registers) and emit inputs in a standard format.
  163 #
  164 # out1, out2, out3, ... <- name inout1, inout2, inout3, ...
  165 # =>
  166 # (name inout1 inout2 inout3)
  167 #
  168 # Formal types:
  169 #   functions: linked list of info
  170 #     name: (handle array byte)
  171 #     inouts: linked list of vars
  172 #     outputs: linked list of vars
  173 #     body: block (linked list of statements)
  174 
  175 # == Translating a single primitive instruction
  176 # A second crucial piece of the puzzle is how Mu converts fairly regular
  177 # primitives with their uniform syntax to SubX instructions with their gnarly
  178 # x86 details.
  179 #
  180 # Mu instructions have inputs and outputs. Primitives can have up to 2 of
  181 # them.
  182 # SubX instructions have rm32 and r32 operands.
  183 # The translation between them covers almost all the possibilities.
  184 #   Instructions with 1 inout may turn into ones with 1 rm32
  185 #     (e.g. incrementing a var on the stack)
  186 #   Instructions with 1 output may turn into ones with 1 rm32
  187 #     (e.g. incrementing a var in a register)
  188 #   1 inout and 1 output may turn into 1 rm32 and 1 r32
  189 #     (e.g. adding a var to a reg)
  190 #   2 inouts may turn into 1 rm32 and 1 r32
  191 #     (e.g. adding a reg to a var)
  192 #   1 inout and 1 literal may turn into 1 rm32 and 1 imm32
  193 #     (e.g. adding a constant to a var)
  194 #   1 output and 1 literal may turn into 1 rm32 and 1 imm32
  195 #     (e.g. adding a constant to a reg)
  196 #   2 outputs to hardcoded registers and 1 inout may turn into 1 rm32
  197 #     (special-case: divide edx:eax by a var or reg)
  198 # Observations:
  199 #   We always emit rm32. It may be the first inout or the first output.
  200 #   We may emit r32 or imm32 or neither.
  201 #   When we emit r32 it may come from first inout or second inout or first output.
  202 #
  203 # Accordingly, the formal data structure for a primitive looks like this:
  204 #   primitives: linked list of info
  205 #     name: (handle array byte)
  206 #     mu-inouts: linked list of vars to check
  207 #     mu-outputs: linked list of vars to check; at most a singleton
  208 #     subx-name: (handle array byte)
  209 #     subx-rm32: enum arg-location
  210 #     subx-r32: enum arg-location
  211 #     subx-imm32: enum arg-location
  212 #     subx-imm8: enum arg-location
  213 #     subx-disp32: enum arg-location
  214 #     subx-xm32: enum arg-location
  215 #     subx-x32: enum arg-location
  216 #   arg-location: enum
  217 #     0 means none
  218 #     1 means first inout
  219 #     2 means second inout
  220 #     3 means first output
  221 
  222 # == Translating a block
  223 # Emit block name if necessary
  224 # Emit '{'
  225 # When you encounter a statement, emit it as above
  226 # When you encounter a variable declaration
  227 #   emit any code needed for it (bzeros)
  228 #   push it on the var stack
  229 #   update register dict if necessary
  230 # When you encounter '}'
  231 #   While popping variables off the var stack until block id changes
  232 #     Emit code needed to clean up the stack
  233 #       either increment esp
  234 #       or pop into appropriate register
  235 
  236 # The rest is straightforward.
  237 
  238 == data
  239 
  240 Program:
  241 _Program-functions:  # (handle function)
  242   0/imm32
  243 _Program-functions->payload:
  244   0/imm32
  245 _Program-types:  # (handle typeinfo)
  246   0/imm32
  247 _Program-types->payload:
  248   0/imm32
  249 _Program-signatures:  # (handle function)
  250   0/imm32
  251 _Program-signatures->payload:
  252   0/imm32
  253 
  254 # Some constants for simulating the data structures described above.
  255 # Many constants here come with a type in a comment.
  256 #
  257 # Sometimes the type is of the value at that offset for the given type. For
  258 # example, if you start at a function record and move forward Function-inouts
  259 # bytes, you'll find a (handle list var).
  260 #
  261 # At other times, the type is of the constant itself. For example, the type of
  262 # the constant Function-size is (addr int). To get the size of a function,
  263 # look in *Function-size.
  264 
  265 Function-name:  # (handle array byte)
  266   0/imm32
  267 Function-inouts:  # (handle list var)
  268   8/imm32
  269 Function-outputs:  # (handle list var)
  270   0x10/imm32
  271 Function-body:  # (handle block)
  272   0x18/imm32
  273 Function-next:  # (handle function)
  274   0x20/imm32
  275 Function-size:  # (addr int)
  276   0x28/imm32/40
  277 
  278 Primitive-name:  # (handle array byte)
  279   0/imm32
  280 Primitive-inouts:  # (handle list var)
  281   8/imm32
  282 Primitive-outputs:  # (handle list var)
  283   0x10/imm32
  284 Primitive-subx-name:  # (handle array byte)
  285   0x18/imm32
  286 Primitive-subx-rm32:  # enum arg-location
  287   0x20/imm32
  288 Primitive-subx-r32:  # enum arg-location
  289   0x24/imm32
  290 Primitive-subx-imm32:  # enum arg-location
  291   0x28/imm32
  292 Primitive-subx-imm8:  # enum arg-location  -- only for bit shifts
  293   0x2c/imm32
  294 Primitive-subx-disp32:  # enum arg-location  -- only for branches
  295   0x30/imm32
  296 Primitive-subx-xm32:  # enum arg-location
  297   0x34/imm32
  298 Primitive-subx-x32:  # enum arg-location
  299   0x38/imm32
  300 Primitive-next:  # (handle function)
  301   0x3c/imm32
  302 Primitive-size:  # (addr int)
  303   0x44/imm32/68
  304 
  305 Stmt-tag:  # int
  306   0/imm32
  307 
  308 Block-stmts:  # (handle list stmt)
  309   4/imm32
  310 Block-var:  # (handle var)
  311   0xc/imm32
  312 
  313 Stmt1-operation:  # (handle array byte)
  314   4/imm32
  315 Stmt1-inouts:  # (handle stmt-var)
  316   0xc/imm32
  317 Stmt1-outputs:  # (handle stmt-var)
  318   0x14/imm32
  319 
  320 Vardef-var:  # (handle var)
  321   4/imm32
  322 
  323 Regvardef-operation:  # (handle array byte)
  324   4/imm32
  325 Regvardef-inouts:  # (handle stmt-var)
  326   0xc/imm32
  327 Regvardef-outputs:  # (handle stmt-var)  # will have exactly one element
  328   0x14/imm32
  329 
  330 Stmt-size:  # (addr int)
  331   0x1c/imm32
  332 
  333 Var-name:  # (handle array byte)
  334   0/imm32
  335 Var-type:  # (handle type-tree)
  336   8/imm32
  337 Var-block-depth:  # int -- not available until code-generation time
  338   0x10/imm32
  339 Var-offset:  # int -- not available until code-generation time
  340   0x14/imm32
  341 Var-register:  # (handle array byte) -- name of a register
  342   0x18/imm32
  343 Var-size:  # (addr int)
  344   0x20/imm32
  345 
  346 List-value:  # (handle _)
  347   0/imm32
  348 List-next:  # (handle list _)
  349   8/imm32
  350 List-size:  # (addr int)
  351   0x10/imm32
  352 
  353 # A stmt-var is like a list of vars with call-site specific metadata
  354 Stmt-var-value:  # (handle var)
  355   0/imm32
  356 Stmt-var-next:  # (handle stmt-var)
  357   8/imm32
  358 Stmt-var-is-deref:  # boolean
  359   0x10/imm32
  360 Stmt-var-size:  # (addr int)
  361   0x14/imm32
  362 
  363 # A live-var is a var augmented with information needed for tracking live
  364 # variables.
  365 Live-var-value:  # (handle var)
  366   0/imm32
  367 Live-var-register-spilled:  # boolean; only used if value is in a register, and only during code-gen
  368   8/imm32
  369 Live-var-size:  # (addr int)
  370   0xc/imm32
  371 
  372 # Types are expressed as trees (s-expressions) of type-ids (ints).
  373 
  374 Type-tree-is-atom:  # boolean
  375   0/imm32
  376 # if is-atom?
  377 Type-tree-value:  # type-id
  378   4/imm32
  379 Type-tree-value-size:  # int (for static data structure sizes)
  380   8/imm32
  381 Type-tree-parameter-name:  # (handle array byte) for type parameters
  382   8/imm32
  383 # unless is-atom?
  384 Type-tree-left:  # (addr type-tree)
  385   4/imm32
  386 Type-tree-right:  # (addr type-tree)
  387   0xc/imm32
  388 #
  389 Type-tree-size:  # (addr int)
  390   0x14/imm32
  391 
  392 # Types
  393 
  394 # TODO: Turn this data structure into valid Mu, with (fake) handles rather than addrs.
  395 Type-id:  # (stream (addr array byte))
  396   0/imm32/write  # initialized later from Primitive-type-ids
  397   0/imm32/read
  398   0x100/imm32/size
  399   # data
  400   0/imm32  # 0 reserved for literals; value is just the name
  401            # Not to be used directly, so we don't include a name here.
  402   "int"/imm32  # 1
  403   "addr"/imm32  # 2
  404   "array"/imm32  # 3
  405   "handle"/imm32  # 4
  406   "boolean"/imm32  # 5
  407   0/imm32  # 6 reserved for constants; they're like literals, but value is an int in Var-offset
  408            # Not to be used directly, so we don't include a name here.
  409   "offset"/imm32  # 7: (offset T) is guaranteed to be a 32-bit multiple of size-of(T)
  410   # 0x20
  411   "byte"/imm32  # 8
  412   0/imm32  # 9 reserved for array-capacity; value is in Type-tree-size.
  413            # Not to be used directly, so we don't include a name here.
  414   0/imm32  # 10 reserved for type parameters; value is (address array byte) in Type-tree-value2.
  415            # Not to be used directly, so we don't include a name here.
  416   "stream"/imm32  # 11
  417   "slice"/imm32  # 12
  418   "code-point"/imm32  # 13; smallest scannable unit from a text stream
  419   "grapheme"/imm32  # 14; smallest printable unit; will eventually be composed of multiple code-points, but currently corresponds 1:1
  420                     # only 4-byte graphemes in utf-8 are currently supported;
  421                     # unclear how we should deal with larger clusters.
  422   "float"/imm32     # 15
  423   # 0x40
  424   0/imm32  # 16 reserved for literal strings; value is just the name
  425            # Not to be used directly, so we don't include a name here.
  426            # TODO: move this up next to literal ints
  427   # Keep Primitive-type-ids in sync if you add types here.
  428           0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  429   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  430   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  431   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  432   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  433   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  434 
  435 Primitive-type-ids:  # (addr int)
  436   0x44
  437 
  438 # == Type definitions
  439 # Program->types contains some typeinfo for each type definition.
  440 # Types contain vars with types, but can't specify registers.
  441 Typeinfo-id:  # type-id
  442   0/imm32
  443 Typeinfo-fields:  # (handle table (handle array byte) (handle typeinfo-entry))
  444   4/imm32
  445 # Total size must be >= 0
  446 # During parsing it may take on two additional values:
  447 #   -2: not yet initialized
  448 #   -1: in process of being computed
  449 # See populate-mu-type-sizes for details.
  450 Typeinfo-total-size-in-bytes:  # int
  451   0xc/imm32
  452 Typeinfo-next:  # (handle typeinfo)
  453   0x10/imm32
  454 Typeinfo-size:  # (addr int)
  455   0x18/imm32
  456 
  457 # Each entry in the typeinfo->fields table has a pointer to a string and a
  458 # pointer to a typeinfo-entry.
  459 Typeinfo-fields-row-size:  # (addr int)
  460   0x10/imm32
  461 
  462 # typeinfo-entry objects have information about a field in a single record type
  463 #
  464 # each field of a type is represented using two var's:
  465 #   1. the input var: expected type of the field; convenient for creating using parse-var-with-type
  466 #   2. the output var: a constant containing the byte offset; convenient for code-generation
  467 # computing the output happens after parsing; in the meantime we preserve the
  468 # order of fields in the 'index' field.
  469 Typeinfo-entry-input-var:  # (handle var)
  470   0/imm32
  471 Typeinfo-entry-index:  # int
  472   8/imm32
  473 Typeinfo-entry-output-var:  # (handle var)
  474   0xc/imm32
  475 Typeinfo-entry-size:  # (addr int)
  476   0x14/imm32
  477 
  478 == code
  479 
  480 Entry:
  481     # . prologue
  482     89/<- %ebp 4/r32/esp
  483     (new-segment *Heap-size Heap)
  484     # if (argv[1] == "test') run-tests()
  485     {
  486       # if (argc <= 1) break
  487       81 7/subop/compare *ebp 1/imm32
  488       7e/jump-if-<= break/disp8
  489       # if (argv[1] != "test") break
  490       (kernel-string-equal? *(ebp+8) "test")  # => eax
  491       3d/compare-eax-and 0/imm32/false
  492       74/jump-if-= break/disp8
  493       #
  494       (run-tests)
  495       # syscall(exit, *Num-test-failures)
  496       8b/-> *Num-test-failures 3/r32/ebx
  497       eb/jump $mu-main:end/disp8
  498     }
  499     # otherwise convert Stdin
  500     (convert-mu Stdin Stdout Stderr 0)
  501     (flush Stdout)
  502     # syscall(exit, 0)
  503     bb/copy-to-ebx 0/imm32
  504 $mu-main:end:
  505     e8/call syscall_exit/disp32
  506 
  507 convert-mu:  # in: (addr buffered-file), out: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
  508     # . prologue
  509     55/push-ebp
  510     89/<- %ebp 4/r32/esp
  511     # . save registers
  512     50/push-eax
  513     # initialize global data structures
  514     c7 0/subop/copy *Next-block-index 1/imm32
  515     8b/-> *Primitive-type-ids 0/r32/eax
  516     89/<- *Type-id 0/r32/eax  # stream-write
  517     c7 0/subop/copy *_Program-functions 0/imm32
  518     c7 0/subop/copy *_Program-functions->payload 0/imm32
  519     c7 0/subop/copy *_Program-types 0/imm32
  520     c7 0/subop/copy *_Program-types->payload 0/imm32
  521     c7 0/subop/copy *_Program-signatures 0/imm32
  522     c7 0/subop/copy *_Program-signatures->payload 0/imm32
  523     #
  524     (parse-mu *(ebp+8) *(ebp+0x10) *(ebp+0x14))
  525     (populate-mu-type-sizes *(ebp+0x10) *(ebp+0x14))
  526 #?     (dump-typeinfos "=== typeinfos\n")
  527     (check-mu-types *(ebp+0x10) *(ebp+0x14))
  528     (emit-subx *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
  529 $convert-mu:end:
  530     # . restore registers
  531     58/pop-to-eax
  532     # . epilogue
  533     89/<- %esp 5/r32/ebp
  534     5d/pop-to-ebp
  535     c3/return
  536 
  537 test-convert-empty-input:
  538     # empty input => empty output
  539     # . prologue
  540     55/push-ebp
  541     89/<- %ebp 4/r32/esp
  542     # setup
  543     (clear-stream _test-input-stream)
  544     (clear-stream $_test-input-buffered-file->buffer)
  545     (clear-stream _test-output-stream)
  546     (clear-stream $_test-output-buffered-file->buffer)
  547     #
  548     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  549     (flush _test-output-buffered-file)
  550     (check-stream-equal _test-output-stream "" "F - test-convert-empty-input")
  551     # . epilogue
  552     89/<- %esp 5/r32/ebp
  553     5d/pop-to-ebp
  554     c3/return
  555 
  556 test-convert-function-skeleton:
  557     # . prologue
  558     55/push-ebp
  559     89/<- %ebp 4/r32/esp
  560     # setup
  561     (clear-stream _test-input-stream)
  562     (clear-stream $_test-input-buffered-file->buffer)
  563     (clear-stream _test-output-stream)
  564     (clear-stream $_test-output-buffered-file->buffer)
  565     #
  566     (write _test-input-stream "fn foo {\n")
  567     (write _test-input-stream "}\n")
  568     # convert
  569     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  570     (flush _test-output-buffered-file)
  571 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
  577     # check output
  578     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-skeleton/0")
  579     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-skeleton/1")
  580     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-skeleton/2")
  581     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-skeleton/3")
  582     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-skeleton/4")
  583     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-skeleton/5")
  584     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-skeleton/6")
  585     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-skeleton/7")
  586     # . epilogue
  587     89/<- %esp 5/r32/ebp
  588     5d/pop-to-ebp
  589     c3/return
  590 
  591 test-convert-multiple-function-skeletons:
  592     # . prologue
  593     55/push-ebp
  594     89/<- %ebp 4/r32/esp
  595     # setup
  596     (clear-stream _test-input-stream)
  597     (clear-stream $_test-input-buffered-file->buffer)
  598     (clear-stream _test-output-stream)
  599     (clear-stream $_test-output-buffered-file->buffer)
  600     #
  601     (write _test-input-stream "fn foo {\n")
  602     (write _test-input-stream "}\n")
  603     (write _test-input-stream "fn bar {\n")
  604     (write _test-input-stream "}\n")
  605     # convert
  606     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  607     (flush _test-output-buffered-file)
  608 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
  614     # check first function
  615     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-multiple-function-skeletons/0")
  616     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-multiple-function-skeletons/1")
  617     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-multiple-function-skeletons/2")
  618     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-multiple-function-skeletons/3")
  619     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-multiple-function-skeletons/4")
  620     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-multiple-function-skeletons/5")
  621     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-multiple-function-skeletons/6")
  622     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-multiple-function-skeletons/7")
  623     # check second function
  624     (check-next-stream-line-equal _test-output-stream "bar:"                    "F - test-convert-multiple-function-skeletons/10")
  625     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-multiple-function-skeletons/11")
  626     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-multiple-function-skeletons/12")
  627     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-multiple-function-skeletons/13")
  628     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-multiple-function-skeletons/14")
  629     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-multiple-function-skeletons/15")
  630     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-multiple-function-skeletons/16")
  631     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-multiple-function-skeletons/17")
  632     # . epilogue
  633     89/<- %esp 5/r32/ebp
  634     5d/pop-to-ebp
  635     c3/return
  636 
  637 test-convert-function-with-arg:
  638     # . prologue
  639     55/push-ebp
  640     89/<- %ebp 4/r32/esp
  641     # setup
  642     (clear-stream _test-input-stream)
  643     (clear-stream $_test-input-buffered-file->buffer)
  644     (clear-stream _test-output-stream)
  645     (clear-stream $_test-output-buffered-file->buffer)
  646     #
  647     (write _test-input-stream "fn foo n: int {\n")
  648     (write _test-input-stream "}\n")
  649     # convert
  650     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  651     (flush _test-output-buffered-file)
  652 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
  658     # check output
  659     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-arg/0")
  660     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-arg/1")
  661     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-arg/2")
  662     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-arg/3")
  663     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-arg/4")
  664     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-arg/5")
  665     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-arg/6")
  666     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-arg/7")
  667     # . epilogue
  668     89/<- %esp 5/r32/ebp
  669     5d/pop-to-ebp
  670     c3/return
  671 
  672 test-function-with-redefined-name:
  673     # . prologue
  674     55/push-ebp
  675     89/<- %ebp 4/r32/esp
  676     # setup
  677     (clear-stream _test-input-stream)
  678     (clear-stream $_test-input-buffered-file->buffer)
  679     (clear-stream _test-output-stream)
  680     (clear-stream $_test-output-buffered-file->buffer)
  681     (clear-stream _test-error-stream)
  682     (clear-stream $_test-error-buffered-file->buffer)
  683     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  684     68/push 0/imm32
  685     68/push 0/imm32
  686     89/<- %edx 4/r32/esp
  687     (tailor-exit-descriptor %edx 0x10)
  688     #
  689     (write _test-input-stream "fn foo {\n")
  690     (write _test-input-stream "}\n")
  691     (write _test-input-stream "fn foo {\n")
  692     (write _test-input-stream "}\n")
  693     # convert
  694     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  695     # registers except esp clobbered at this point
  696     # restore ed
  697     89/<- %edx 4/r32/esp
  698     (flush _test-output-buffered-file)
  699     (flush _test-error-buffered-file)
  700 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
  706     # check output
  707     (check-stream-equal _test-output-stream  ""  "F - test-function-with-redefined-name: output should be empty")
  708     (check-next-stream-line-equal _test-error-stream  "fn foo defined more than once"  "F - test-function-with-redefined-name: error message")
  709     # check that stop(1) was called
  710     (check-ints-equal *(edx+4) 2 "F - test-function-with-redefined-name: exit status")
  711     # don't restore from ebp
  712     81 0/subop/add %esp 8/imm32
  713     # . epilogue
  714     5d/pop-to-ebp
  715     c3/return
  716 
  717 test-function-with-redefined-name-2:
  718     # . prologue
  719     55/push-ebp
  720     89/<- %ebp 4/r32/esp
  721     # setup
  722     (clear-stream _test-input-stream)
  723     (clear-stream $_test-input-buffered-file->buffer)
  724     (clear-stream _test-output-stream)
  725     (clear-stream $_test-output-buffered-file->buffer)
  726     (clear-stream _test-error-stream)
  727     (clear-stream $_test-error-buffered-file->buffer)
  728     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  729     68/push 0/imm32
  730     68/push 0/imm32
  731     89/<- %edx 4/r32/esp
  732     (tailor-exit-descriptor %edx 0x10)
  733     #
  734     (write _test-input-stream "fn foo {\n")
  735     (write _test-input-stream "}\n")
  736     (write _test-input-stream "sig foo\n")
  737     # convert
  738     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  739     # registers except esp clobbered at this point
  740     # restore ed
  741     89/<- %edx 4/r32/esp
  742     (flush _test-output-buffered-file)
  743     (flush _test-error-buffered-file)
  744 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
  750     # check output
  751     (check-stream-equal _test-output-stream  ""  "F - test-function-with-redefined-name-2: output should be empty")
  752     (check-next-stream-line-equal _test-error-stream  "fn foo defined more than once"  "F - test-function-with-redefined-name-2: error message")
  753     # check that stop(1) was called
  754     (check-ints-equal *(edx+4) 2 "F - test-function-with-redefined-name-2: exit status")
  755     # don't restore from ebp
  756     81 0/subop/add %esp 8/imm32
  757     # . epilogue
  758     5d/pop-to-ebp
  759     c3/return
  760 
  761 test-function-with-redefined-name-3:
  762     # . prologue
  763     55/push-ebp
  764     89/<- %ebp 4/r32/esp
  765     # setup
  766     (clear-stream _test-input-stream)
  767     (clear-stream $_test-input-buffered-file->buffer)
  768     (clear-stream _test-output-stream)
  769     (clear-stream $_test-output-buffered-file->buffer)
  770     (clear-stream _test-error-stream)
  771     (clear-stream $_test-error-buffered-file->buffer)
  772     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  773     68/push 0/imm32
  774     68/push 0/imm32
  775     89/<- %edx 4/r32/esp
  776     (tailor-exit-descriptor %edx 0x10)
  777     #
  778     (write _test-input-stream "sig foo\n")
  779     (write _test-input-stream "fn foo {\n")
  780     (write _test-input-stream "}\n")
  781     # convert
  782     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  783     # registers except esp clobbered at this point
  784     # restore ed
  785     89/<- %edx 4/r32/esp
  786     (flush _test-output-buffered-file)
  787     (flush _test-error-buffered-file)
  788 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
  794     # check output
  795     (check-stream-equal _test-output-stream  ""  "F - test-function-with-redefined-name-3: output should be empty")
  796     (check-next-stream-line-equal _test-error-stream  "fn foo defined more than once"  "F - test-function-with-redefined-name-3: error message")
  797     # check that stop(1) was called
  798     (check-ints-equal *(edx+4) 2 "F - test-function-with-redefined-name-3: exit status")
  799     # don't restore from ebp
  800     81 0/subop/add %esp 8/imm32
  801     # . epilogue
  802     5d/pop-to-ebp
  803     c3/return
  804 
  805 test-function-with-inout-in-register:
  806     # . prologue
  807     55/push-ebp
  808     89/<- %ebp 4/r32/esp
  809     # setup
  810     (clear-stream _test-input-stream)
  811     (clear-stream $_test-input-buffered-file->buffer)
  812     (clear-stream _test-output-stream)
  813     (clear-stream $_test-output-buffered-file->buffer)
  814     (clear-stream _test-error-stream)
  815     (clear-stream $_test-error-buffered-file->buffer)
  816     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  817     68/push 0/imm32
  818     68/push 0/imm32
  819     89/<- %edx 4/r32/esp
  820     (tailor-exit-descriptor %edx 0x10)
  821     #
  822     (write _test-input-stream "fn foo x/eax: int {\n")
  823     (write _test-input-stream "}\n")
  824     # convert
  825     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  826     # registers except esp clobbered at this point
  827     # restore ed
  828     89/<- %edx 4/r32/esp
  829     (flush _test-output-buffered-file)
  830     (flush _test-error-buffered-file)
  831 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
  837     # check output
  838     (check-stream-equal _test-output-stream  ""  "F - test-function-with-inout-in-register: output should be empty")
  839     (check-next-stream-line-equal _test-error-stream  "fn foo: function inout 'x' cannot be in a register"  "F - test-function-with-inout-in-register: error message")
  840     # check that stop(1) was called
  841     (check-ints-equal *(edx+4) 2 "F - test-function-with-inout-in-register: exit status")
  842     # don't restore from ebp
  843     81 0/subop/add %esp 8/imm32
  844     # . epilogue
  845     5d/pop-to-ebp
  846     c3/return
  847 
  848 test-function-with-addr-output:
  849     # . prologue
  850     55/push-ebp
  851     89/<- %ebp 4/r32/esp
  852     # setup
  853     (clear-stream _test-input-stream)
  854     (clear-stream $_test-input-buffered-file->buffer)
  855     (clear-stream _test-output-stream)
  856     (clear-stream $_test-output-buffered-file->buffer)
  857     (clear-stream _test-error-stream)
  858     (clear-stream $_test-error-buffered-file->buffer)
  859     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  860     68/push 0/imm32
  861     68/push 0/imm32
  862     89/<- %edx 4/r32/esp
  863     (tailor-exit-descriptor %edx 0x10)
  864     #
  865     (write _test-input-stream "fn foo -> _/eax: (addr int) {\n")
  866     (write _test-input-stream "}\n")
  867     # convert
  868     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  869     # registers except esp clobbered at this point
  870     # restore ed
  871     89/<- %edx 4/r32/esp
  872     (flush _test-output-buffered-file)
  873     (flush _test-error-buffered-file)
  874 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
  880     # check output
  881     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-output: output should be empty")
  882     (check-next-stream-line-equal _test-error-stream  "fn foo: output cannot have an addr type; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-output: error message")
  883     # check that stop(1) was called
  884     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-output: exit status")
  885     # don't restore from ebp
  886     81 0/subop/add %esp 8/imm32
  887     # . epilogue
  888     5d/pop-to-ebp
  889     c3/return
  890 
  891 test-function-with-addr-inout:
  892     # . prologue
  893     55/push-ebp
  894     89/<- %ebp 4/r32/esp
  895     # setup
  896     (clear-stream _test-input-stream)
  897     (clear-stream $_test-input-buffered-file->buffer)
  898     (clear-stream _test-output-stream)
  899     (clear-stream $_test-output-buffered-file->buffer)
  900     (clear-stream _test-error-stream)
  901     (clear-stream $_test-error-buffered-file->buffer)
  902     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  903     68/push 0/imm32
  904     68/push 0/imm32
  905     89/<- %edx 4/r32/esp
  906     (tailor-exit-descriptor %edx 0x10)
  907     #
  908     (write _test-input-stream "fn foo a: (addr addr int) {\n")
  909     (write _test-input-stream "}\n")
  910     # convert
  911     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  912     # registers except esp clobbered at this point
  913     # restore ed
  914     89/<- %edx 4/r32/esp
  915     (flush _test-output-buffered-file)
  916     (flush _test-error-buffered-file)
  917 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
  923     # check output
  924     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout: output should be empty")
  925     (check-next-stream-line-equal _test-error-stream  "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-inout: error message")
  926     # check that stop(1) was called
  927     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout: exit status")
  928     # don't restore from ebp
  929     81 0/subop/add %esp 8/imm32
  930     # . epilogue
  931     5d/pop-to-ebp
  932     c3/return
  933 
  934 test-function-with-addr-inout-2:
  935     # . prologue
  936     55/push-ebp
  937     89/<- %ebp 4/r32/esp
  938     # setup
  939     (clear-stream _test-input-stream)
  940     (clear-stream $_test-input-buffered-file->buffer)
  941     (clear-stream _test-output-stream)
  942     (clear-stream $_test-output-buffered-file->buffer)
  943     (clear-stream _test-error-stream)
  944     (clear-stream $_test-error-buffered-file->buffer)
  945     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  946     68/push 0/imm32
  947     68/push 0/imm32
  948     89/<- %edx 4/r32/esp
  949     (tailor-exit-descriptor %edx 0x10)
  950     #
  951     (write _test-input-stream "fn foo a: (addr array addr int) {\n")
  952     (write _test-input-stream "}\n")
  953     # convert
  954     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  955     # registers except esp clobbered at this point
  956     # restore ed
  957     89/<- %edx 4/r32/esp
  958     (flush _test-output-buffered-file)
  959     (flush _test-error-buffered-file)
  960 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
  966     # check output
  967     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout-2: output should be empty")
  968     (check-next-stream-line-equal _test-error-stream  "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-inout-2: error message")
  969     # check that stop(1) was called
  970     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout-2: exit status")
  971     # don't restore from ebp
  972     81 0/subop/add %esp 8/imm32
  973     # . epilogue
  974     5d/pop-to-ebp
  975     c3/return
  976 
  977 test-function-with-addr-inout-3:
  978     # . prologue
  979     55/push-ebp
  980     89/<- %ebp 4/r32/esp
  981     # setup
  982     (clear-stream _test-input-stream)
  983     (clear-stream $_test-input-buffered-file->buffer)
  984     (clear-stream _test-output-stream)
  985     (clear-stream $_test-output-buffered-file->buffer)
  986     (clear-stream _test-error-stream)
  987     (clear-stream $_test-error-buffered-file->buffer)
  988     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  989     68/push 0/imm32
  990     68/push 0/imm32
  991     89/<- %edx 4/r32/esp
  992     (tailor-exit-descriptor %edx 0x10)
  993     #
  994     (write _test-input-stream "fn foo a: (addr array (addr int) 3) {\n")
  995     (write _test-input-stream "}\n")
  996     # convert
  997     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  998     # registers except esp clobbered at this point
  999     # restore ed
 1000     89/<- %edx 4/r32/esp
 1001     (flush _test-output-buffered-file)
 1002     (flush _test-error-buffered-file)
 1003 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1009     # check output
 1010     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout-3: output should be empty")
 1011     (check-next-stream-line-equal _test-error-stream  "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-inout-3: error message")
 1012     # check that stop(1) was called
 1013     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout-3: exit status")
 1014     # don't restore from ebp
 1015     81 0/subop/add %esp 8/imm32
 1016     # . epilogue
 1017     5d/pop-to-ebp
 1018     c3/return
 1019 
 1020 test-function-with-addr-inout-4:
 1021     # . prologue
 1022     55/push-ebp
 1023     89/<- %ebp 4/r32/esp
 1024     # setup
 1025     (clear-stream _test-input-stream)
 1026     (clear-stream $_test-input-buffered-file->buffer)
 1027     (clear-stream _test-output-stream)
 1028     (clear-stream $_test-output-buffered-file->buffer)
 1029     (clear-stream _test-error-stream)
 1030     (clear-stream $_test-error-buffered-file->buffer)
 1031     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1032     68/push 0/imm32
 1033     68/push 0/imm32
 1034     89/<- %edx 4/r32/esp
 1035     (tailor-exit-descriptor %edx 0x10)
 1036     #
 1037     (write _test-input-stream "fn foo a: (array (addr int) 3) {\n")
 1038     (write _test-input-stream "}\n")
 1039     # convert
 1040     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1041     # registers except esp clobbered at this point
 1042     # restore ed
 1043     89/<- %edx 4/r32/esp
 1044     (flush _test-output-buffered-file)
 1045     (flush _test-error-buffered-file)
 1046 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1052     # check output
 1053     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout-4: output should be empty")
 1054     (check-next-stream-line-equal _test-error-stream  "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-inout-4: error message")
 1055     # check that stop(1) was called
 1056     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout-4: exit status")
 1057     # don't restore from ebp
 1058     81 0/subop/add %esp 8/imm32
 1059     # . epilogue
 1060     5d/pop-to-ebp
 1061     c3/return
 1062 
 1063 # 'main' is an exception
 1064 test-function-main-with-addr-inout:
 1065     # . prologue
 1066     55/push-ebp
 1067     89/<- %ebp 4/r32/esp
 1068     # setup
 1069     (clear-stream _test-input-stream)
 1070     (clear-stream $_test-input-buffered-file->buffer)
 1071     (clear-stream _test-output-stream)
 1072     (clear-stream $_test-output-buffered-file->buffer)
 1073     #
 1074     (write _test-input-stream "fn main a: (addr addr int) {\n")
 1075     (write _test-input-stream "}\n")
 1076     # convert
 1077     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1078     (flush _test-output-buffered-file)
 1079     # no errors
 1080     # . epilogue
 1081     89/<- %esp 5/r32/ebp
 1082     5d/pop-to-ebp
 1083     c3/return
 1084 
 1085 # 'lookup' is an exception, but only in signatures
 1086 test-signature-lookup-with-addr-inout:
 1087     # . prologue
 1088     55/push-ebp
 1089     89/<- %ebp 4/r32/esp
 1090     # setup
 1091     (clear-stream _test-input-stream)
 1092     (clear-stream $_test-input-buffered-file->buffer)
 1093     (clear-stream _test-output-stream)
 1094     (clear-stream $_test-output-buffered-file->buffer)
 1095     #
 1096     (write _test-input-stream "sig lookup h: (handle _T) -> _/eax: (addr _T)\n")
 1097     # convert
 1098     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1099     (flush _test-output-buffered-file)
 1100     # no errors
 1101     # . epilogue
 1102     89/<- %esp 5/r32/ebp
 1103     5d/pop-to-ebp
 1104     c3/return
 1105 
 1106 test-convert-function-with-arg-and-body:
 1107     # . prologue
 1108     55/push-ebp
 1109     89/<- %ebp 4/r32/esp
 1110     # setup
 1111     (clear-stream _test-input-stream)
 1112     (clear-stream $_test-input-buffered-file->buffer)
 1113     (clear-stream _test-output-stream)
 1114     (clear-stream $_test-output-buffered-file->buffer)
 1115     #
 1116     (write _test-input-stream "fn foo n: int {\n")
 1117     (write _test-input-stream "  increment n\n")
 1118     (write _test-input-stream "}\n")
 1119     # convert
 1120     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1121     (flush _test-output-buffered-file)
 1122 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1128     # check output
 1129     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-arg-and-body/0")
 1130     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-arg-and-body/1")
 1131     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-arg-and-body/2")
 1132     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-arg-and-body/3")
 1133     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-arg-and-body/4")
 1134     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-arg-and-body/5")
 1135     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-arg-and-body/6")
 1136     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-arg-and-body/7")
 1137     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-arg-and-body/8")
 1138     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-arg-and-body/9")
 1139     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-arg-and-body/10")
 1140     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-arg-and-body/11")
 1141     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-arg-and-body/12")
 1142     # . epilogue
 1143     89/<- %esp 5/r32/ebp
 1144     5d/pop-to-ebp
 1145     c3/return
 1146 
 1147 test-convert-function-distinguishes-args:
 1148     # . prologue
 1149     55/push-ebp
 1150     89/<- %ebp 4/r32/esp
 1151     # setup
 1152     (clear-stream _test-input-stream)
 1153     (clear-stream $_test-input-buffered-file->buffer)
 1154     (clear-stream _test-output-stream)
 1155     (clear-stream $_test-output-buffered-file->buffer)
 1156     #
 1157     (write _test-input-stream "fn foo a: int, b: int {\n")
 1158     (write _test-input-stream "  increment b\n")
 1159     (write _test-input-stream "}\n")
 1160     # convert
 1161     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1162     (flush _test-output-buffered-file)
 1163 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1169     # check output
 1170     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-distinguishes-args/0")
 1171     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-distinguishes-args/1")
 1172     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-distinguishes-args/2")
 1173     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-distinguishes-args/3")
 1174     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-distinguishes-args/4")
 1175     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-distinguishes-args/5")
 1176     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0x0000000c)"  "F - test-convert-function-distinguishes-args/6")
 1177     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-distinguishes-args/7")
 1178     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-distinguishes-args/8")
 1179     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-distinguishes-args/9")
 1180     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-distinguishes-args/10")
 1181     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-distinguishes-args/11")
 1182     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-distinguishes-args/12")
 1183     # . epilogue
 1184     89/<- %esp 5/r32/ebp
 1185     5d/pop-to-ebp
 1186     c3/return
 1187 
 1188 test-convert-function-with-return-literal:
 1189     # . prologue
 1190     55/push-ebp
 1191     89/<- %ebp 4/r32/esp
 1192     # setup
 1193     (clear-stream _test-input-stream)
 1194     (clear-stream $_test-input-buffered-file->buffer)
 1195     (clear-stream _test-output-stream)
 1196     (clear-stream $_test-output-buffered-file->buffer)
 1197     #
 1198     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1199     (write _test-input-stream "  return 0\n")
 1200     (write _test-input-stream "}\n")
 1201     # convert
 1202     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1203     (flush _test-output-buffered-file)
 1204 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1210     # check output
 1211     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-literal/0")
 1212     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-literal/1")
 1213     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-literal/2")
 1214     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-literal/3")
 1215     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-literal/4")
 1216     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-literal/5")
 1217     (check-next-stream-line-equal _test-output-stream "    c7 0/subop/copy %eax 0/imm32"  "F - test-convert-function-with-return-literal/6")
 1218     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-literal/7")
 1219     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-literal/8")
 1220     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-literal/9")
 1221     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-literal/10")
 1222     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-literal/11")
 1223     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-literal/12")
 1224     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-literal/13")
 1225     # . epilogue
 1226     89/<- %esp 5/r32/ebp
 1227     5d/pop-to-ebp
 1228     c3/return
 1229 
 1230 test-convert-function-with-return:
 1231     # . prologue
 1232     55/push-ebp
 1233     89/<- %ebp 4/r32/esp
 1234     # setup
 1235     (clear-stream _test-input-stream)
 1236     (clear-stream $_test-input-buffered-file->buffer)
 1237     (clear-stream _test-output-stream)
 1238     (clear-stream $_test-output-buffered-file->buffer)
 1239     #
 1240     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1241     (write _test-input-stream "  var y: int\n")
 1242     (write _test-input-stream "  return y\n")
 1243     (write _test-input-stream "}\n")
 1244     # convert
 1245     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1246     (flush _test-output-buffered-file)
 1247 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1253     # check output
 1254     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return/0")
 1255     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return/1")
 1256     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return/2")
 1257     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return/3")
 1258     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return/4")
 1259     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return/5")
 1260     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-return/6")  # y
 1261     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0xfffffffc) 0x00000000/r32" "F - test-convert-function-with-return/7")
 1262     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-return/8")
 1263     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return/9")
 1264     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return/10")
 1265     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return/11")
 1266     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return/12")
 1267     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return/13")
 1268     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return/14")
 1269     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return/15")
 1270     # . epilogue
 1271     89/<- %esp 5/r32/ebp
 1272     5d/pop-to-ebp
 1273     c3/return
 1274 
 1275 test-convert-function-with-return-float:
 1276     # . prologue
 1277     55/push-ebp
 1278     89/<- %ebp 4/r32/esp
 1279     # setup
 1280     (clear-stream _test-input-stream)
 1281     (clear-stream $_test-input-buffered-file->buffer)
 1282     (clear-stream _test-output-stream)
 1283     (clear-stream $_test-output-buffered-file->buffer)
 1284     #
 1285     (write _test-input-stream "fn foo -> _/xmm0: float {\n")
 1286     (write _test-input-stream "  var y: float\n")
 1287     (write _test-input-stream "  return y\n")
 1288     (write _test-input-stream "}\n")
 1289     # convert
 1290     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1291     (flush _test-output-buffered-file)
 1292 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1298     # check output
 1299     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return/0")
 1300     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return/1")
 1301     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return/2")
 1302     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return/3")
 1303     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return/4")
 1304     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return/5")
 1305     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-return/6")  # y
 1306     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *(ebp+0xfffffffc) 0x00000000/x32" "F - test-convert-function-with-return/7")
 1307     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-return/8")
 1308     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return/9")
 1309     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return/10")
 1310     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return/11")
 1311     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return/12")
 1312     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return/13")
 1313     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return/14")
 1314     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return/15")
 1315     # . epilogue
 1316     89/<- %esp 5/r32/ebp
 1317     5d/pop-to-ebp
 1318     c3/return
 1319 
 1320 test-convert-function-with-return-register:
 1321     # . prologue
 1322     55/push-ebp
 1323     89/<- %ebp 4/r32/esp
 1324     # setup
 1325     (clear-stream _test-input-stream)
 1326     (clear-stream $_test-input-buffered-file->buffer)
 1327     (clear-stream _test-output-stream)
 1328     (clear-stream $_test-output-buffered-file->buffer)
 1329     #
 1330     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1331     (write _test-input-stream "  var y/eax: int <- copy 3\n")
 1332     (write _test-input-stream "  return y\n")
 1333     (write _test-input-stream "}\n")
 1334     # convert
 1335     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1336     (flush _test-output-buffered-file)
 1337 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1343     # check output
 1344     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register/0")
 1345     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register/1")
 1346     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register/2")
 1347     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register/3")
 1348     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register/4")
 1349     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register/5")
 1350     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register/6")
 1351     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-convert-function-with-return-register/7")
 1352     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-return-register/8")
 1353     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-return-register/9")
 1354     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-register/10")
 1355     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register/11")
 1356     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register/12")
 1357     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register/13")
 1358     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register/14")
 1359     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register/15")
 1360     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register/16")
 1361     # . epilogue
 1362     89/<- %esp 5/r32/ebp
 1363     5d/pop-to-ebp
 1364     c3/return
 1365 
 1366 test-function-with-output-without-register:
 1367     # . prologue
 1368     55/push-ebp
 1369     89/<- %ebp 4/r32/esp
 1370     # setup
 1371     (clear-stream _test-input-stream)
 1372     (clear-stream $_test-input-buffered-file->buffer)
 1373     (clear-stream _test-output-stream)
 1374     (clear-stream $_test-output-buffered-file->buffer)
 1375     (clear-stream _test-error-stream)
 1376     (clear-stream $_test-error-buffered-file->buffer)
 1377     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1378     68/push 0/imm32
 1379     68/push 0/imm32
 1380     89/<- %edx 4/r32/esp
 1381     (tailor-exit-descriptor %edx 0x10)
 1382     #
 1383     (write _test-input-stream "fn foo -> _: int {\n")
 1384     (write _test-input-stream "}\n")
 1385     # convert
 1386     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1387     # registers except esp clobbered at this point
 1388     # restore ed
 1389     89/<- %edx 4/r32/esp
 1390     (flush _test-output-buffered-file)
 1391     (flush _test-error-buffered-file)
 1392 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1398     # check output
 1399     (check-stream-equal _test-output-stream  ""  "F - test-function-with-output-without-register: output should be empty")
 1400     (check-next-stream-line-equal _test-error-stream  "fn foo: function output '_' must be in a register, in instruction 'fn foo -> _: int {"  "F - test-function-with-output-without-register: error message")
 1401     # check that stop(1) was called
 1402     (check-ints-equal *(edx+4) 2 "F - test-function-with-output-without-register: exit status")
 1403     # don't restore from ebp
 1404     81 0/subop/add %esp 8/imm32
 1405     # . epilogue
 1406     5d/pop-to-ebp
 1407     c3/return
 1408 
 1409 test-function-with-outputs-in-conflicting-registers:
 1410     # . prologue
 1411     55/push-ebp
 1412     89/<- %ebp 4/r32/esp
 1413     # setup
 1414     (clear-stream _test-input-stream)
 1415     (clear-stream $_test-input-buffered-file->buffer)
 1416     (clear-stream _test-output-stream)
 1417     (clear-stream $_test-output-buffered-file->buffer)
 1418     (clear-stream _test-error-stream)
 1419     (clear-stream $_test-error-buffered-file->buffer)
 1420     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1421     68/push 0/imm32
 1422     68/push 0/imm32
 1423     89/<- %edx 4/r32/esp
 1424     (tailor-exit-descriptor %edx 0x10)
 1425     #
 1426     (write _test-input-stream "fn foo -> _/eax: int, _/eax: int {\n")
 1427     (write _test-input-stream "}\n")
 1428     # convert
 1429     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1430     # registers except esp clobbered at this point
 1431     # restore ed
 1432     89/<- %edx 4/r32/esp
 1433     (flush _test-output-buffered-file)
 1434     (flush _test-error-buffered-file)
 1435 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1441     # check output
 1442     (check-stream-equal _test-output-stream  ""  "F - test-function-with-outputs-in-conflicting-registers: output should be empty")
 1443     (check-next-stream-line-equal _test-error-stream  "fn foo: outputs must be in unique registers"  "F - test-function-with-outputs-in-conflicting-registers: error message")
 1444     # check that stop(1) was called
 1445     (check-ints-equal *(edx+4) 2 "F - test-function-with-outputs-in-conflicting-registers: exit status")
 1446     # don't restore from ebp
 1447     81 0/subop/add %esp 8/imm32
 1448     # . epilogue
 1449     5d/pop-to-ebp
 1450     c3/return
 1451 
 1452 test-function-with-named-output:
 1453     # . prologue
 1454     55/push-ebp
 1455     89/<- %ebp 4/r32/esp
 1456     # setup
 1457     (clear-stream _test-input-stream)
 1458     (clear-stream $_test-input-buffered-file->buffer)
 1459     (clear-stream _test-output-stream)
 1460     (clear-stream $_test-output-buffered-file->buffer)
 1461     (clear-stream _test-error-stream)
 1462     (clear-stream $_test-error-buffered-file->buffer)
 1463     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1464     68/push 0/imm32
 1465     68/push 0/imm32
 1466     89/<- %edx 4/r32/esp
 1467     (tailor-exit-descriptor %edx 0x10)
 1468     #
 1469     (write _test-input-stream "fn foo -> x/eax: int {\n")
 1470     (write _test-input-stream "  return 0\n")
 1471     (write _test-input-stream "}\n")
 1472     # convert
 1473     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1474     # registers except esp clobbered at this point
 1475     # restore ed
 1476     89/<- %edx 4/r32/esp
 1477     (flush _test-output-buffered-file)
 1478     (flush _test-error-buffered-file)
 1479 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1485     # check output
 1486     (check-stream-equal _test-output-stream  ""  "F - test-function-with-named-output: output should be empty")
 1487     (check-next-stream-line-equal _test-error-stream  "fn foo: function outputs cannot be named; rename 'x' in the header to '_'"  "F - test-function-with-named-output: error message")
 1488     # check that stop(1) was called
 1489     (check-ints-equal *(edx+4) 2 "F - test-function-with-named-output: exit status")
 1490     # don't restore from ebp
 1491     81 0/subop/add %esp 8/imm32
 1492     # . epilogue
 1493     5d/pop-to-ebp
 1494     c3/return
 1495 
 1496 test-return-with-wrong-type:
 1497     # . prologue
 1498     55/push-ebp
 1499     89/<- %ebp 4/r32/esp
 1500     # setup
 1501     (clear-stream _test-input-stream)
 1502     (clear-stream $_test-input-buffered-file->buffer)
 1503     (clear-stream _test-output-stream)
 1504     (clear-stream $_test-output-buffered-file->buffer)
 1505     (clear-stream _test-error-stream)
 1506     (clear-stream $_test-error-buffered-file->buffer)
 1507     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1508     68/push 0/imm32
 1509     68/push 0/imm32
 1510     89/<- %edx 4/r32/esp
 1511     (tailor-exit-descriptor %edx 0x10)
 1512     #
 1513     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1514     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 1515     (write _test-input-stream "  return x\n")
 1516     (write _test-input-stream "}\n")
 1517     # convert
 1518     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1519     # registers except esp clobbered at this point
 1520     # restore ed
 1521     89/<- %edx 4/r32/esp
 1522     (flush _test-output-buffered-file)
 1523     (flush _test-error-buffered-file)
 1524 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1530     # check output
 1531     (check-stream-equal _test-output-stream  ""  "F - test-return-with-wrong-type: output should be empty")
 1532     (check-next-stream-line-equal _test-error-stream  "fn foo: return: 'x' has the wrong type"  "F - test-return-with-wrong-type: error message")
 1533     # check that stop(1) was called
 1534     (check-ints-equal *(edx+4) 2 "F - test-return-with-wrong-type: exit status")
 1535     # don't restore from ebp
 1536     81 0/subop/add %esp 8/imm32
 1537     # . epilogue
 1538     5d/pop-to-ebp
 1539     c3/return
 1540 
 1541 test-missing-return:
 1542     # . prologue
 1543     55/push-ebp
 1544     89/<- %ebp 4/r32/esp
 1545     # setup
 1546     (clear-stream _test-input-stream)
 1547     (clear-stream $_test-input-buffered-file->buffer)
 1548     (clear-stream _test-output-stream)
 1549     (clear-stream $_test-output-buffered-file->buffer)
 1550     (clear-stream _test-error-stream)
 1551     (clear-stream $_test-error-buffered-file->buffer)
 1552     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1553     68/push 0/imm32
 1554     68/push 0/imm32
 1555     89/<- %edx 4/r32/esp
 1556     (tailor-exit-descriptor %edx 0x10)
 1557     #
 1558     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1559     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 1560     (write _test-input-stream "}\n")
 1561     # convert
 1562     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1563     # registers except esp clobbered at this point
 1564     # restore ed
 1565     89/<- %edx 4/r32/esp
 1566     (flush _test-output-buffered-file)
 1567     (flush _test-error-buffered-file)
 1568 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1574     # check output
 1575     (check-stream-equal _test-output-stream  ""  "F - test-missing-return: output should be empty")
 1576     (check-next-stream-line-equal _test-error-stream  "fn foo: final statement should be a 'return'"  "F - test-missing-return: error message")
 1577     # check that stop(1) was called
 1578     (check-ints-equal *(edx+4) 2 "F - test-missing-return: exit status")
 1579     # don't restore from ebp
 1580     81 0/subop/add %esp 8/imm32
 1581     # . epilogue
 1582     5d/pop-to-ebp
 1583     c3/return
 1584 
 1585 test-missing-return-2:
 1586     # . prologue
 1587     55/push-ebp
 1588     89/<- %ebp 4/r32/esp
 1589     # setup
 1590     (clear-stream _test-input-stream)
 1591     (clear-stream $_test-input-buffered-file->buffer)
 1592     (clear-stream _test-output-stream)
 1593     (clear-stream $_test-output-buffered-file->buffer)
 1594     (clear-stream _test-error-stream)
 1595     (clear-stream $_test-error-buffered-file->buffer)
 1596     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1597     68/push 0/imm32
 1598     68/push 0/imm32
 1599     89/<- %edx 4/r32/esp
 1600     (tailor-exit-descriptor %edx 0x10)
 1601     #
 1602     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1603     (write _test-input-stream "}\n")
 1604     # convert
 1605     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1606     # registers except esp clobbered at this point
 1607     # restore ed
 1608     89/<- %edx 4/r32/esp
 1609     (flush _test-output-buffered-file)
 1610     (flush _test-error-buffered-file)
 1611 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1617     # check output
 1618     (check-stream-equal _test-output-stream  ""  "F - test-missing-return-2: output should be empty")
 1619     (check-next-stream-line-equal _test-error-stream  "fn foo: final statement should be a 'return'"  "F - test-missing-return-2: error message")
 1620     # check that stop(1) was called
 1621     (check-ints-equal *(edx+4) 2 "F - test-missing-return-2: exit status")
 1622     # don't restore from ebp
 1623     81 0/subop/add %esp 8/imm32
 1624     # . epilogue
 1625     5d/pop-to-ebp
 1626     c3/return
 1627 
 1628 test-early-exit-without-return:
 1629     # . prologue
 1630     55/push-ebp
 1631     89/<- %ebp 4/r32/esp
 1632     # setup
 1633     (clear-stream _test-input-stream)
 1634     (clear-stream $_test-input-buffered-file->buffer)
 1635     (clear-stream _test-output-stream)
 1636     (clear-stream $_test-output-buffered-file->buffer)
 1637     (clear-stream _test-error-stream)
 1638     (clear-stream $_test-error-buffered-file->buffer)
 1639     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1640     68/push 0/imm32
 1641     68/push 0/imm32
 1642     89/<- %edx 4/r32/esp
 1643     (tailor-exit-descriptor %edx 0x10)
 1644     #
 1645     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1646     (write _test-input-stream "  break\n")
 1647     (write _test-input-stream "  return 0\n")
 1648     (write _test-input-stream "}\n")
 1649     # convert
 1650     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1651     # registers except esp clobbered at this point
 1652     # restore ed
 1653     89/<- %edx 4/r32/esp
 1654     (flush _test-output-buffered-file)
 1655     (flush _test-error-buffered-file)
 1656 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1662     # check output
 1663     (check-stream-equal _test-output-stream  ""  "F - test-early-exit-without-return: output should be empty")
 1664     (check-next-stream-line-equal _test-error-stream  "fn foo has outputs, so you cannot 'break' out of the outermost block. Use 'return'."  "F - test-early-exit-without-return: error message")
 1665     # check that stop(1) was called
 1666     (check-ints-equal *(edx+4) 2 "F - test-early-exit-without-return: exit status")
 1667     # don't restore from ebp
 1668     81 0/subop/add %esp 8/imm32
 1669     # . epilogue
 1670     5d/pop-to-ebp
 1671     c3/return
 1672 
 1673 test-return-with-too-few-inouts:
 1674     # . prologue
 1675     55/push-ebp
 1676     89/<- %ebp 4/r32/esp
 1677     # setup
 1678     (clear-stream _test-input-stream)
 1679     (clear-stream $_test-input-buffered-file->buffer)
 1680     (clear-stream _test-output-stream)
 1681     (clear-stream $_test-output-buffered-file->buffer)
 1682     (clear-stream _test-error-stream)
 1683     (clear-stream $_test-error-buffered-file->buffer)
 1684     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1685     68/push 0/imm32
 1686     68/push 0/imm32
 1687     89/<- %edx 4/r32/esp
 1688     (tailor-exit-descriptor %edx 0x10)
 1689     #
 1690     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1691     (write _test-input-stream "  return\n")
 1692     (write _test-input-stream "}\n")
 1693     # convert
 1694     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1695     # registers except esp clobbered at this point
 1696     # restore ed
 1697     89/<- %edx 4/r32/esp
 1698     (flush _test-output-buffered-file)
 1699     (flush _test-error-buffered-file)
 1700 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1706     # check output
 1707     (check-stream-equal _test-output-stream  ""  "F - test-return-with-too-few-inouts: output should be empty")
 1708     (check-next-stream-line-equal _test-error-stream  "fn foo: return: too few inouts"  "F - test-return-with-too-few-inouts: error message")
 1709     # check that stop(1) was called
 1710     (check-ints-equal *(edx+4) 2 "F - test-return-with-too-few-inouts: exit status")
 1711     # don't restore from ebp
 1712     81 0/subop/add %esp 8/imm32
 1713     # . epilogue
 1714     5d/pop-to-ebp
 1715     c3/return
 1716 
 1717 test-return-with-too-many-inouts:
 1718     # . prologue
 1719     55/push-ebp
 1720     89/<- %ebp 4/r32/esp
 1721     # setup
 1722     (clear-stream _test-input-stream)
 1723     (clear-stream $_test-input-buffered-file->buffer)
 1724     (clear-stream _test-output-stream)
 1725     (clear-stream $_test-output-buffered-file->buffer)
 1726     (clear-stream _test-error-stream)
 1727     (clear-stream $_test-error-buffered-file->buffer)
 1728     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1729     68/push 0/imm32
 1730     68/push 0/imm32
 1731     89/<- %edx 4/r32/esp
 1732     (tailor-exit-descriptor %edx 0x10)
 1733     #
 1734     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1735     (write _test-input-stream "  return 0, 0\n")
 1736     (write _test-input-stream "}\n")
 1737     # convert
 1738     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1739     # registers except esp clobbered at this point
 1740     # restore ed
 1741     89/<- %edx 4/r32/esp
 1742     (flush _test-output-buffered-file)
 1743     (flush _test-error-buffered-file)
 1744 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1750     # check output
 1751     (check-stream-equal _test-output-stream  ""  "F - test-return-with-too-many-inouts: output should be empty")
 1752     (check-next-stream-line-equal _test-error-stream  "fn foo: return: too many inouts"  "F - test-return-with-too-many-inouts: error message")
 1753     # check that stop(1) was called
 1754     (check-ints-equal *(edx+4) 2 "F - test-return-with-too-many-inouts: exit status")
 1755     # don't restore from ebp
 1756     81 0/subop/add %esp 8/imm32
 1757     # . epilogue
 1758     5d/pop-to-ebp
 1759     c3/return
 1760 
 1761 test-return-unavailable-value:
 1762     # . prologue
 1763     55/push-ebp
 1764     89/<- %ebp 4/r32/esp
 1765     # setup
 1766     (clear-stream _test-input-stream)
 1767     (clear-stream $_test-input-buffered-file->buffer)
 1768     (clear-stream _test-output-stream)
 1769     (clear-stream $_test-output-buffered-file->buffer)
 1770     (clear-stream _test-error-stream)
 1771     (clear-stream $_test-error-buffered-file->buffer)
 1772     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1773     68/push 0/imm32
 1774     68/push 0/imm32
 1775     89/<- %edx 4/r32/esp
 1776     (tailor-exit-descriptor %edx 0x10)
 1777     #
 1778     (write _test-input-stream "fn foo -> _/eax: int, _/ecx: int {\n")
 1779     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 1780     (write _test-input-stream "  var y/ecx: int <- copy 0\n")
 1781     (write _test-input-stream "  return y, x\n")
 1782     (write _test-input-stream "}\n")
 1783     # convert
 1784     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1785     # registers except esp clobbered at this point
 1786     # restore ed
 1787     89/<- %edx 4/r32/esp
 1788     (flush _test-output-buffered-file)
 1789     (flush _test-error-buffered-file)
 1790 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1796     # check output
 1797     (check-stream-equal _test-output-stream  ""  "F - test-return-unavailable-value: output should be empty")
 1798     (check-next-stream-line-equal _test-error-stream  "fn foo: return: 'x' is no longer available"  "F - test-return-unavailable-value: error message")
 1799     # check that stop(1) was called
 1800     (check-ints-equal *(edx+4) 2 "F - test-return-unavailable-value: exit status")
 1801     # don't restore from ebp
 1802     81 0/subop/add %esp 8/imm32
 1803     # . epilogue
 1804     5d/pop-to-ebp
 1805     c3/return
 1806 
 1807 test-return-literal-to-float:
 1808     # . prologue
 1809     55/push-ebp
 1810     89/<- %ebp 4/r32/esp
 1811     # setup
 1812     (clear-stream _test-input-stream)
 1813     (clear-stream $_test-input-buffered-file->buffer)
 1814     (clear-stream _test-output-stream)
 1815     (clear-stream $_test-output-buffered-file->buffer)
 1816     (clear-stream _test-error-stream)
 1817     (clear-stream $_test-error-buffered-file->buffer)
 1818     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1819     68/push 0/imm32
 1820     68/push 0/imm32
 1821     89/<- %edx 4/r32/esp
 1822     (tailor-exit-descriptor %edx 0x10)
 1823     #
 1824     (write _test-input-stream "fn foo -> _/xmm0: float {\n")
 1825     (write _test-input-stream "  return 0\n")
 1826     (write _test-input-stream "}\n")
 1827     # convert
 1828     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1829     # registers except esp clobbered at this point
 1830     # restore ed
 1831     89/<- %edx 4/r32/esp
 1832     (flush _test-output-buffered-file)
 1833     (flush _test-error-buffered-file)
 1834 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1840     # check output
 1841     (check-stream-equal _test-output-stream  ""  "F - test-return-literal-to-float: output should be empty")
 1842     (check-next-stream-line-equal _test-error-stream  "fn foo: return: cannot copy literal '0' to float"  "F - test-return-literal-to-float: error message")
 1843     # check that stop(1) was called
 1844     (check-ints-equal *(edx+4) 2 "F - test-return-literal-to-float: exit status")
 1845     # don't restore from ebp
 1846     81 0/subop/add %esp 8/imm32
 1847     # . epilogue
 1848     5d/pop-to-ebp
 1849     c3/return
 1850 
 1851 test-convert-return-with-duplicate-values:
 1852     # . prologue
 1853     55/push-ebp
 1854     89/<- %ebp 4/r32/esp
 1855     # setup
 1856     (clear-stream _test-input-stream)
 1857     (clear-stream $_test-input-buffered-file->buffer)
 1858     (clear-stream _test-output-stream)
 1859     (clear-stream $_test-output-buffered-file->buffer)
 1860     #
 1861     (write _test-input-stream "fn foo -> _/eax: int, _/ecx: int {\n")
 1862     (write _test-input-stream "  var x/eax: int <- copy 0x34\n")
 1863     (write _test-input-stream "  return x, x\n")
 1864     (write _test-input-stream "}\n")
 1865     # convert
 1866     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1867     (flush _test-output-buffered-file)
 1868 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1874     # check output
 1875     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-return-with-duplicate-values/0")
 1876     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-return-with-duplicate-values/1")
 1877     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-return-with-duplicate-values/2")
 1878     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-return-with-duplicate-values/3")
 1879     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-return-with-duplicate-values/4")
 1880     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-return-with-duplicate-values/5")
 1881     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-return-with-duplicate-values/6")
 1882     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0x34/imm32"  "F - test-convert-return-with-duplicate-values/7")
 1883     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32"  "F - test-convert-return-with-duplicate-values/8")
 1884     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000001/r32"  "F - test-convert-return-with-duplicate-values/9")
 1885     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-return-with-duplicate-values/10")
 1886     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-return-with-duplicate-values/11")
 1887     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-return-with-duplicate-values/12")
 1888     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-return-with-duplicate-values/13")
 1889     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-return-with-duplicate-values/14")
 1890     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-return-with-duplicate-values/15")
 1891     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-return-with-duplicate-values/16")
 1892     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-return-with-duplicate-values/17")
 1893     # . epilogue
 1894     89/<- %esp 5/r32/ebp
 1895     5d/pop-to-ebp
 1896     c3/return
 1897 
 1898 test-convert-return-with-duplicate-values-2:
 1899     # . prologue
 1900     55/push-ebp
 1901     89/<- %ebp 4/r32/esp
 1902     # setup
 1903     (clear-stream _test-input-stream)
 1904     (clear-stream $_test-input-buffered-file->buffer)
 1905     (clear-stream _test-output-stream)
 1906     (clear-stream $_test-output-buffered-file->buffer)
 1907     #
 1908     (write _test-input-stream "fn foo -> _/eax: int, _/ecx: int {\n")
 1909     (write _test-input-stream "  var x/ecx: int <- copy 0x34\n")
 1910     (write _test-input-stream "  return x, x\n")
 1911     (write _test-input-stream "}\n")
 1912     # convert
 1913     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1914     (flush _test-output-buffered-file)
 1915 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1921     # check output
 1922     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-return-with-duplicate-values-2/0")
 1923     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-return-with-duplicate-values-2/1")
 1924     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-return-with-duplicate-values-2/2")
 1925     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-return-with-duplicate-values-2/3")
 1926     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-return-with-duplicate-values-2/4")
 1927     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-return-with-duplicate-values-2/5")
 1928     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-return-with-duplicate-values-2/6")
 1929     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0x34/imm32"  "F - test-convert-return-with-duplicate-values-2/7")
 1930     (check-next-stream-line-equal _test-output-stream "    8b/-> %ecx 0x00000000/r32"  "F - test-convert-return-with-duplicate-values-2/8")
 1931     (check-next-stream-line-equal _test-output-stream "    8b/-> %ecx 0x00000001/r32"  "F - test-convert-return-with-duplicate-values-2/9")
 1932     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-return-with-duplicate-values-2/10")
 1933     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-return-with-duplicate-values-2/11")
 1934     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-return-with-duplicate-values-2/12")
 1935     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-return-with-duplicate-values-2/13")
 1936     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-return-with-duplicate-values-2/14")
 1937     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-return-with-duplicate-values-2/15")
 1938     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-return-with-duplicate-values-2/16")
 1939     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-return-with-duplicate-values-2/17")
 1940     # . epilogue
 1941     89/<- %esp 5/r32/ebp
 1942     5d/pop-to-ebp
 1943     c3/return
 1944 
 1945 test-stmt-with-unknown-var:
 1946     # . prologue
 1947     55/push-ebp
 1948     89/<- %ebp 4/r32/esp
 1949     # setup
 1950     (clear-stream _test-input-stream)
 1951     (clear-stream $_test-input-buffered-file->buffer)
 1952     (clear-stream _test-output-stream)
 1953     (clear-stream $_test-output-buffered-file->buffer)
 1954     (clear-stream _test-error-stream)
 1955     (clear-stream $_test-error-buffered-file->buffer)
 1956     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1957     68/push 0/imm32
 1958     68/push 0/imm32
 1959     89/<- %edx 4/r32/esp
 1960     (tailor-exit-descriptor %edx 0x10)
 1961     #
 1962     (write _test-input-stream "fn foo {\n")
 1963     (write _test-input-stream "  x <- copy 0x34\n")
 1964     (write _test-input-stream "}\n")
 1965     # convert
 1966     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1967     # registers except esp clobbered at this point
 1968     # restore ed
 1969     89/<- %edx 4/r32/esp
 1970     (flush _test-output-buffered-file)
 1971     (flush _test-error-buffered-file)
 1972 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1978     # check output
 1979     (check-stream-equal _test-output-stream  ""  "F - test-stmt-with-unknown-var: output should be empty")
 1980     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-stmt-with-unknown-var: error message")
 1981     # check that stop(1) was called
 1982     (check-ints-equal *(edx+4) 2 "F - test-stmt-with-unknown-var: exit status")
 1983     # don't restore from ebp
 1984     81 0/subop/add %esp 8/imm32
 1985     # . epilogue
 1986     5d/pop-to-ebp
 1987     c3/return
 1988 
 1989 test-stmt-with-invalid-identifier:
 1990     # . prologue
 1991     55/push-ebp
 1992     89/<- %ebp 4/r32/esp
 1993     # setup
 1994     (clear-stream _test-input-stream)
 1995     (clear-stream $_test-input-buffered-file->buffer)
 1996     (clear-stream _test-output-stream)
 1997     (clear-stream $_test-output-buffered-file->buffer)
 1998     (clear-stream _test-error-stream)
 1999     (clear-stream $_test-error-buffered-file->buffer)
 2000     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2001     68/push 0/imm32
 2002     68/push 0/imm32
 2003     89/<- %edx 4/r32/esp
 2004     (tailor-exit-descriptor %edx 0x10)
 2005     #
 2006     (write _test-input-stream "fn foo {\n")
 2007     (write _test-input-stream "  1 <- copy 0x34\n")
 2008     (write _test-input-stream "}\n")
 2009     # convert
 2010     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2011     # registers except esp clobbered at this point
 2012     # restore ed
 2013     89/<- %edx 4/r32/esp
 2014     (flush _test-output-buffered-file)
 2015     (flush _test-error-buffered-file)
 2016 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2022     # check output
 2023     (check-stream-equal _test-output-stream  ""  "F - test-stmt-with-invalid-identifier: output should be empty")
 2024     (check-next-stream-line-equal _test-error-stream  "fn foo: invalid identifier '1'"  "F - test-stmt-with-invalid-identifier: error message")
 2025     # check that stop(1) was called
 2026     (check-ints-equal *(edx+4) 2 "F - test-stmt-with-invalid-identifier: exit status")
 2027     # don't restore from ebp
 2028     81 0/subop/add %esp 8/imm32
 2029     # . epilogue
 2030     5d/pop-to-ebp
 2031     c3/return
 2032 
 2033 test-stmt-with-deref-var:
 2034     # . prologue
 2035     55/push-ebp
 2036     89/<- %ebp 4/r32/esp
 2037     # setup
 2038     (clear-stream _test-input-stream)
 2039     (clear-stream $_test-input-buffered-file->buffer)
 2040     (clear-stream _test-output-stream)
 2041     (clear-stream $_test-output-buffered-file->buffer)
 2042     (clear-stream _test-error-stream)
 2043     (clear-stream $_test-error-buffered-file->buffer)
 2044     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2045     68/push 0/imm32
 2046     68/push 0/imm32
 2047     89/<- %edx 4/r32/esp
 2048     (tailor-exit-descriptor %edx 0x10)
 2049     #
 2050     (write _test-input-stream "fn foo {\n")
 2051     (write _test-input-stream "  *x <- copy 0x34\n")
 2052     (write _test-input-stream "}\n")
 2053     # convert
 2054     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2055     # registers except esp clobbered at this point
 2056     # restore ed
 2057     89/<- %edx 4/r32/esp
 2058     (flush _test-output-buffered-file)
 2059     (flush _test-error-buffered-file)
 2060 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2066     # check output
 2067     (check-stream-equal _test-output-stream  ""  "F - test-stmt-with-deref-var: output should be empty")
 2068     (check-next-stream-line-equal _test-error-stream  "fn foo: output '*x' should write to a register, and therefore cannot be dereferenced"  "F - test-stmt-with-deref-var: error message")
 2069     # check that stop(1) was called
 2070     (check-ints-equal *(edx+4) 2 "F - test-stmt-with-deref-var: exit status")
 2071     # don't restore from ebp
 2072     81 0/subop/add %esp 8/imm32
 2073     # . epilogue
 2074     5d/pop-to-ebp
 2075     c3/return
 2076 
 2077 test-convert-function-with-literal-arg:
 2078     # . prologue
 2079     55/push-ebp
 2080     89/<- %ebp 4/r32/esp
 2081     # setup
 2082     (clear-stream _test-input-stream)
 2083     (clear-stream $_test-input-buffered-file->buffer)
 2084     (clear-stream _test-output-stream)
 2085     (clear-stream $_test-output-buffered-file->buffer)
 2086     #
 2087     (write _test-input-stream "fn foo a: int, b: int -> _/eax: int {\n")
 2088     (write _test-input-stream "  var result/eax: int <- copy a\n")
 2089     (write _test-input-stream "  result <- add 1\n")
 2090     (write _test-input-stream "  return result\n")
 2091     (write _test-input-stream "}\n")
 2092     # convert
 2093     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2094     (flush _test-output-buffered-file)
 2095 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2101     # check output
 2102     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-literal-arg/0")
 2103     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-literal-arg/1")
 2104     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-literal-arg/2")
 2105     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-literal-arg/3")
 2106     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-literal-arg/4")
 2107     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-literal-arg/5")
 2108     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-literal-arg/6")
 2109     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-with-literal-arg/7")
 2110     (check-next-stream-line-equal _test-output-stream "    05/add-to-eax 1/imm32"  "F - test-convert-function-with-literal-arg/8")
 2111     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-literal-arg/9")
 2112     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-literal-arg/10")
 2113     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-literal-arg/11")
 2114     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-literal-arg/12")
 2115     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-literal-arg/13")
 2116     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-literal-arg/14")
 2117     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-literal-arg/15")
 2118     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-literal-arg/16")
 2119     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-literal-arg/17")
 2120     # . epilogue
 2121     89/<- %esp 5/r32/ebp
 2122     5d/pop-to-ebp
 2123     c3/return
 2124 
 2125 test-convert-function-with-literal-arg-2:
 2126     # . prologue
 2127     55/push-ebp
 2128     89/<- %ebp 4/r32/esp
 2129     # setup
 2130     (clear-stream _test-input-stream)
 2131     (clear-stream $_test-input-buffered-file->buffer)
 2132     (clear-stream _test-output-stream)
 2133     (clear-stream $_test-output-buffered-file->buffer)
 2134     #
 2135     (write _test-input-stream "fn foo a: int, b: int -> _/ebx: int {\n")
 2136     (write _test-input-stream "  var result/ebx: int <- copy a\n")
 2137     (write _test-input-stream "  result <- add 1\n")
 2138     (write _test-input-stream "  return result\n")
 2139     (write _test-input-stream "}\n")
 2140     # convert
 2141     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2142     (flush _test-output-buffered-file)
 2143 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2149     # check output
 2150     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-literal-arg-2/0")
 2151     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-literal-arg-2/1")
 2152     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-literal-arg-2/2")
 2153     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-literal-arg-2/3")
 2154     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-literal-arg-2/4")
 2155     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-literal-arg-2/5")
 2156     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-with-literal-arg-2/6")
 2157     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000003/r32"  "F - test-convert-function-with-literal-arg-2/7")
 2158     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %ebx 1/imm32"  "F - test-convert-function-with-literal-arg-2/8")
 2159     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-with-literal-arg-2/9")
 2160     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-literal-arg-2/10")
 2161     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-literal-arg-2/11")
 2162     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-literal-arg-2/12")
 2163     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-literal-arg-2/13")
 2164     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-literal-arg-2/14")
 2165     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-literal-arg-2/15")
 2166     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-literal-arg-2/16")
 2167     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-literal-arg-2/17")
 2168     # . epilogue
 2169     89/<- %esp 5/r32/ebp
 2170     5d/pop-to-ebp
 2171     c3/return
 2172 
 2173 test-convert-function-call-with-literal-arg:
 2174     # . prologue
 2175     55/push-ebp
 2176     89/<- %ebp 4/r32/esp
 2177     # setup
 2178     (clear-stream _test-input-stream)
 2179     (clear-stream $_test-input-buffered-file->buffer)
 2180     (clear-stream _test-output-stream)
 2181     (clear-stream $_test-output-buffered-file->buffer)
 2182     #
 2183     (write _test-input-stream "fn main -> _/ebx: int {\n")
 2184     (write _test-input-stream "  var result/eax: int <- do-add 3 4\n")
 2185     (write _test-input-stream "  return result\n")
 2186     (write _test-input-stream "}\n")
 2187     (write _test-input-stream "fn do-add a: int, b: int -> _/eax: int {\n")
 2188     (write _test-input-stream "  var result/eax: int <- copy a\n")
 2189     (write _test-input-stream "  result <- add b\n")
 2190     (write _test-input-stream "  return result\n")
 2191     (write _test-input-stream "}\n")
 2192     # convert
 2193     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2194     (flush _test-output-buffered-file)
 2195 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2201     # check output
 2202     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call-with-literal-arg/0")
 2203     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-literal-arg/1")
 2204     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-literal-arg/2")
 2205     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-literal-arg/3")
 2206     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-literal-arg/4")
 2207     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call-with-literal-arg/5")
 2208     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/6")
 2209     (check-next-stream-line-equal _test-output-stream "    (do-add 3 4)"        "F - test-convert-function-call-with-literal-arg/7")
 2210     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 2211     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-with-local-var-in-reg/9")
 2212     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 2213     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-literal-arg/11")
 2214     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call-with-literal-arg/12")
 2215     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-literal-arg/13")
 2216     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-literal-arg/14")
 2217     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-literal-arg/15")
 2218     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-literal-arg/16")
 2219     (check-next-stream-line-equal _test-output-stream "do-add:"                 "F - test-convert-function-call-with-literal-arg/17")
 2220     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-literal-arg/18")
 2221     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-literal-arg/19")
 2222     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-literal-arg/20")
 2223     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-literal-arg/21")
 2224     (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:loop:"  "F - test-convert-function-call-with-literal-arg/22")
 2225     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/23")
 2226     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-call-with-literal-arg/24")
 2227     (check-next-stream-line-equal _test-output-stream "    03/add *(ebp+0x0000000c) 0x00000000/r32"  "F - test-convert-function-call-with-literal-arg/25")
 2228     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-call-with-literal-arg/26")
 2229     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
 2230     (check-next-stream-line-equal _test-output-stream "    e9/jump $do-add:0x00000002:break/disp32"  "F - test-convert-function-call-with-literal-arg/28")
 2231     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-literal-arg/29")
 2232     (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:break:"  "F - test-convert-function-call-with-literal-arg/30")
 2233     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-literal-arg/31")
 2234     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-literal-arg/32")
 2235     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-literal-arg/33")
 2236     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-literal-arg/34")
 2237     # . epilogue
 2238     89/<- %esp 5/r32/ebp
 2239     5d/pop-to-ebp
 2240     c3/return
 2241 
 2242 test-convert-function-call-with-literal-string-arg:
 2243     # . prologue
 2244     55/push-ebp
 2245     89/<- %ebp 4/r32/esp
 2246     # setup
 2247     (clear-stream _test-input-stream)
 2248     (clear-stream $_test-input-buffered-file->buffer)
 2249     (clear-stream _test-output-stream)
 2250     (clear-stream $_test-output-buffered-file->buffer)
 2251     #
 2252     (write _test-input-stream "fn foo {\n")
 2253     (write _test-input-stream "  string-func \"abc\"\n")
 2254     (write _test-input-stream "}\n")
 2255     (write _test-input-stream "sig string-func in: (addr array byte)\n")
 2256     # convert
 2257     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2258     # no errors
 2259     # not bothering checking output
 2260     # . epilogue
 2261     89/<- %esp 5/r32/ebp
 2262     5d/pop-to-ebp
 2263     c3/return
 2264 
 2265 test-convert-function-call-with-null-addr:
 2266     # . prologue
 2267     55/push-ebp
 2268     89/<- %ebp 4/r32/esp
 2269     # setup
 2270     (clear-stream _test-input-stream)
 2271     (clear-stream $_test-input-buffered-file->buffer)
 2272     (clear-stream _test-output-stream)
 2273     (clear-stream $_test-output-buffered-file->buffer)
 2274     #
 2275     (write _test-input-stream "fn foo {\n")
 2276     (write _test-input-stream "  bar 0\n")
 2277     (write _test-input-stream "}\n")
 2278     (write _test-input-stream "sig bar in: (addr int)\n")
 2279     # convert
 2280     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2281     # no errors
 2282     # not bothering checking output
 2283     # . epilogue
 2284     89/<- %esp 5/r32/ebp
 2285     5d/pop-to-ebp
 2286     c3/return
 2287 
 2288 test-convert-function-call-with-signature:
 2289     # . prologue
 2290     55/push-ebp
 2291     89/<- %ebp 4/r32/esp
 2292     # setup
 2293     (clear-stream _test-input-stream)
 2294     (clear-stream $_test-input-buffered-file->buffer)
 2295     (clear-stream _test-output-stream)
 2296     (clear-stream $_test-output-buffered-file->buffer)
 2297     #
 2298     (write _test-input-stream "fn main -> _/ebx: int {\n")
 2299     (write _test-input-stream "  var result/eax: int <- do-add 3 4\n")
 2300     (write _test-input-stream "  return result\n")
 2301     (write _test-input-stream "}\n")
 2302     (write _test-input-stream "sig do-add a: int, b: int -> _/eax: int\n")
 2303     # convert
 2304     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2305     (flush _test-output-buffered-file)
 2306 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2312     # check output
 2313     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call-with-signature/0")
 2314     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-signature/1")
 2315     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-signature/2")
 2316     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-signature/3")
 2317     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-signature/4")
 2318     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call-with-signature/5")
 2319     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/6")
 2320     (check-next-stream-line-equal _test-output-stream "    (do-add 3 4)"        "F - test-convert-function-call-with-signature/6")
 2321     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 2322     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-with-local-var-in-reg/9")
 2323     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 2324     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-signature/7")
 2325     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call-with-signature/8")
 2326     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-signature/9")
 2327     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-signature/10")
 2328     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-signature/11")
 2329     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-signature/12")
 2330     # . epilogue
 2331     89/<- %esp 5/r32/ebp
 2332     5d/pop-to-ebp
 2333     c3/return
 2334 
 2335 test-convert-function-with-local-var-in-mem:
 2336     # . prologue
 2337     55/push-ebp
 2338     89/<- %ebp 4/r32/esp
 2339     # setup
 2340     (clear-stream _test-input-stream)
 2341     (clear-stream $_test-input-buffered-file->buffer)
 2342     (clear-stream _test-output-stream)
 2343     (clear-stream $_test-output-buffered-file->buffer)
 2344     #
 2345     (write _test-input-stream "fn foo {\n")
 2346     (write _test-input-stream "  var x: int\n")
 2347     (write _test-input-stream "  increment x\n")
 2348     (write _test-input-stream "}\n")
 2349     # convert
 2350     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2351     (flush _test-output-buffered-file)
 2352 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2358     # check output
 2359     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-mem/0")
 2360     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-mem/1")
 2361     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-mem/2")
 2362     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-mem/3")
 2363     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-mem/4")
 2364     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-mem/5")
 2365     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-in-mem/6")
 2366     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-local-var-in-mem/7")
 2367     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-local-var-in-mem/8")
 2368     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-mem/9")
 2369     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-mem/10")
 2370     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-mem/11")
 2371     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-mem/12")
 2372     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-mem/13")
 2373     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-mem/14")
 2374     # . epilogue
 2375     89/<- %esp 5/r32/ebp
 2376     5d/pop-to-ebp
 2377     c3/return
 2378 
 2379 test-convert-invalid-literal:
 2380     # . prologue
 2381     55/push-ebp
 2382     89/<- %ebp 4/r32/esp
 2383     # setup
 2384     (clear-stream _test-input-stream)
 2385     (clear-stream $_test-input-buffered-file->buffer)
 2386     (clear-stream _test-output-stream)
 2387     (clear-stream $_test-output-buffered-file->buffer)
 2388     (clear-stream _test-error-stream)
 2389     (clear-stream $_test-error-buffered-file->buffer)
 2390     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2391     68/push 0/imm32
 2392     68/push 0/imm32
 2393     89/<- %edx 4/r32/esp
 2394     (tailor-exit-descriptor %edx 0x10)
 2395     #
 2396     (write _test-input-stream "fn foo {\n")
 2397     (write _test-input-stream "  increment 1n\n")
 2398     (write _test-input-stream "}\n")
 2399     # convert
 2400     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2401     # registers except esp clobbered at this point
 2402     # restore ed
 2403     89/<- %edx 4/r32/esp
 2404     (flush _test-output-buffered-file)
 2405     (flush _test-error-buffered-file)
 2406 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2412     # check output
 2413     (check-stream-equal _test-output-stream  ""  "F - test-convert-invalid-literal: output should be empty")
 2414     (check-next-stream-line-equal _test-error-stream  "fn foo: variable '1n' cannot begin with a digit (or do you have a typo in a number?)"  "F - test-convert-invalid-literal: error message")
 2415     # check that stop(1) was called
 2416     (check-ints-equal *(edx+4) 2 "F - test-convert-invalid-literal: exit status")
 2417     # don't restore from ebp
 2418     81 0/subop/add %esp 8/imm32
 2419     # . epilogue
 2420     5d/pop-to-ebp
 2421     c3/return
 2422 
 2423 test-convert-valid-literal-with-metadata:
 2424     # . prologue
 2425     55/push-ebp
 2426     89/<- %ebp 4/r32/esp
 2427     # setup
 2428     (clear-stream _test-input-stream)
 2429     (clear-stream $_test-input-buffered-file->buffer)
 2430     (clear-stream _test-output-stream)
 2431     (clear-stream $_test-output-buffered-file->buffer)
 2432     #
 2433     (write _test-input-stream "fn foo {\n")
 2434     (write _test-input-stream "  var x/eax: int <- copy 1/abc\n")
 2435     (write _test-input-stream "}\n")
 2436     # convert
 2437     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2438     (flush _test-output-buffered-file)
 2439 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2445     # no errors
 2446     # . epilogue
 2447     89/<- %esp 5/r32/ebp
 2448     5d/pop-to-ebp
 2449     c3/return
 2450 
 2451 test-local-var-in-mem-has-no-initializer:
 2452     # . prologue
 2453     55/push-ebp
 2454     89/<- %ebp 4/r32/esp
 2455     # setup
 2456     (clear-stream _test-input-stream)
 2457     (clear-stream $_test-input-buffered-file->buffer)
 2458     (clear-stream _test-output-stream)
 2459     (clear-stream $_test-output-buffered-file->buffer)
 2460     (clear-stream _test-error-stream)
 2461     (clear-stream $_test-error-buffered-file->buffer)
 2462     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2463     68/push 0/imm32
 2464     68/push 0/imm32
 2465     89/<- %edx 4/r32/esp
 2466     (tailor-exit-descriptor %edx 0x10)
 2467     #
 2468     (write _test-input-stream "fn foo {\n")
 2469     (write _test-input-stream "  var x: int <- copy 0\n")
 2470     (write _test-input-stream "  increment x\n")
 2471     (write _test-input-stream "}\n")
 2472     # convert
 2473     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2474     # registers except esp clobbered at this point
 2475     # restore ed
 2476     89/<- %edx 4/r32/esp
 2477     (flush _test-output-buffered-file)
 2478     (flush _test-error-buffered-file)
 2479 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2485     # check output
 2486     (check-stream-equal _test-output-stream  ""  "F - test-var-in-mem-has-no-initializer: output should be empty")
 2487     (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")
 2488     # check that stop(1) was called
 2489     (check-ints-equal *(edx+4) 2 "F - test-var-in-mem-has-no-initializer: exit status")
 2490     # don't restore from ebp
 2491     81 0/subop/add %esp 8/imm32
 2492     # . epilogue
 2493     5d/pop-to-ebp
 2494     c3/return
 2495 
 2496 test-convert-function-with-local-var-with-compound-type-in-mem:
 2497     # . prologue
 2498     55/push-ebp
 2499     89/<- %ebp 4/r32/esp
 2500     # setup
 2501     (clear-stream _test-input-stream)
 2502     (clear-stream $_test-input-buffered-file->buffer)
 2503     (clear-stream _test-output-stream)
 2504     (clear-stream $_test-output-buffered-file->buffer)
 2505     #
 2506     (write _test-input-stream "fn foo {\n")
 2507     (write _test-input-stream "  var x: (addr int)\n")
 2508     (write _test-input-stream "  copy-to x, 0\n")
 2509     (write _test-input-stream "}\n")
 2510     # convert
 2511     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2512     (flush _test-output-buffered-file)
 2513 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2519     # check output
 2520     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-with-compound-type-in-mem/0")
 2521     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-with-compound-type-in-mem/1")
 2522     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-with-compound-type-in-mem/2")
 2523     (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")
 2524     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-compound-type-in-mem/4")
 2525     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-with-compound-type-in-mem/5")
 2526     (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")
 2527     (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")
 2528     (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")
 2529     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-compound-type-in-mem/9")
 2530     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-with-compound-type-in-mem/10")
 2531     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-with-compound-type-in-mem/11")
 2532     (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")
 2533     (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")
 2534     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-with-compound-type-in-mem/14")
 2535     # . epilogue
 2536     89/<- %esp 5/r32/ebp
 2537     5d/pop-to-ebp
 2538     c3/return
 2539 
 2540 test-convert-function-with-local-var-in-reg:
 2541     # . prologue
 2542     55/push-ebp
 2543     89/<- %ebp 4/r32/esp
 2544     # setup
 2545     (clear-stream _test-input-stream)
 2546     (clear-stream $_test-input-buffered-file->buffer)
 2547     (clear-stream _test-output-stream)
 2548     (clear-stream $_test-output-buffered-file->buffer)
 2549     #
 2550     (write _test-input-stream "fn foo {\n")
 2551     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2552     (write _test-input-stream "  x <- increment\n")
 2553     (write _test-input-stream "}\n")
 2554     # convert
 2555     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2556     (flush _test-output-buffered-file)
 2557 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2563     # check output
 2564     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-reg/0")
 2565     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-reg/1")
 2566     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-reg/2")
 2567     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-reg/3")
 2568     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-reg/4")
 2569     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-reg/5")
 2570     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-in-reg/6")
 2571     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-convert-function-with-local-var-in-reg/7")
 2572     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-convert-function-with-local-var-in-reg/8")
 2573     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-in-reg/9")
 2574     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-reg/10")
 2575     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-reg/11")
 2576     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-reg/12")
 2577     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-reg/13")
 2578     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-reg/14")
 2579     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-reg/15")
 2580     # . epilogue
 2581     89/<- %esp 5/r32/ebp
 2582     5d/pop-to-ebp
 2583     c3/return
 2584 
 2585 test-convert-function-with-local-var-in-same-reg:
 2586     # . prologue
 2587     55/push-ebp
 2588     89/<- %ebp 4/r32/esp
 2589     # setup
 2590     (clear-stream _test-input-stream)
 2591     (clear-stream $_test-input-buffered-file->buffer)
 2592     (clear-stream _test-output-stream)
 2593     (clear-stream $_test-output-buffered-file->buffer)
 2594     #
 2595     (write _test-input-stream "fn foo {\n")
 2596     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2597     (write _test-input-stream "  var y/ecx: int <- copy x\n")
 2598     (write _test-input-stream "}\n")
 2599     # convert
 2600     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2601     (flush _test-output-buffered-file)
 2602 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2608     # check output
 2609     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-same-reg/0")
 2610     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-same-reg/1")
 2611     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-same-reg/2")
 2612     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-same-reg/3")
 2613     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-same-reg/4")
 2614     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-same-reg/5")
 2615     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-in-same-reg/6")
 2616     (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")
 2617     # optimization: skip the second copy
 2618     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-in-same-reg/8")
 2619     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-same-reg/9")
 2620     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-same-reg/10")
 2621     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-same-reg/11")
 2622     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-same-reg/12")
 2623     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-same-reg/13")
 2624     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-same-reg/14")
 2625     # . epilogue
 2626     89/<- %esp 5/r32/ebp
 2627     5d/pop-to-ebp
 2628     c3/return
 2629 
 2630 test-convert-function-with-local-var-in-same-reg-dereferenced:
 2631     # . prologue
 2632     55/push-ebp
 2633     89/<- %ebp 4/r32/esp
 2634     # setup
 2635     (clear-stream _test-input-stream)
 2636     (clear-stream $_test-input-buffered-file->buffer)
 2637     (clear-stream _test-output-stream)
 2638     (clear-stream $_test-output-buffered-file->buffer)
 2639     #
 2640     (write _test-input-stream "fn foo {\n")
 2641     (write _test-input-stream "  var x/ecx: (addr int) <- copy 0\n")
 2642     (write _test-input-stream "  var y/ecx: int <- copy *x\n")
 2643     (write _test-input-stream "}\n")
 2644     # convert
 2645     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2646     (flush _test-output-buffered-file)
 2647 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2653     # check output
 2654     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-same-reg-dereferenced/0")
 2655     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-same-reg-dereferenced/1")
 2656     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-same-reg-dereferenced/2")
 2657     (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")
 2658     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-same-reg-dereferenced/4")
 2659     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-same-reg-dereferenced/5")
 2660     (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")
 2661     (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")
 2662     (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
 2663     (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")
 2664     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-same-reg-dereferenced/10")
 2665     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-same-reg-dereferenced/11")
 2666     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-same-reg-dereferenced/12")
 2667     (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")
 2668     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-same-reg-dereferenced/14")
 2669     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-same-reg-dereferenced/15")
 2670     # . epilogue
 2671     89/<- %esp 5/r32/ebp
 2672     5d/pop-to-ebp
 2673     c3/return
 2674 
 2675 test-float-var-in-wrong-register:
 2676     # . prologue
 2677     55/push-ebp
 2678     89/<- %ebp 4/r32/esp
 2679     # setup
 2680     (clear-stream _test-input-stream)
 2681     (clear-stream $_test-input-buffered-file->buffer)
 2682     (clear-stream _test-output-stream)
 2683     (clear-stream $_test-output-buffered-file->buffer)
 2684     (clear-stream _test-error-stream)
 2685     (clear-stream $_test-error-buffered-file->buffer)
 2686     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2687     68/push 0/imm32
 2688     68/push 0/imm32
 2689     89/<- %edx 4/r32/esp
 2690     (tailor-exit-descriptor %edx 0x10)
 2691     #
 2692     (write _test-input-stream "fn foo {\n")
 2693     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 2694     (write _test-input-stream "  var y/eax: float <- convert x\n")
 2695     (write _test-input-stream "}\n")
 2696     # convert
 2697     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2698     # registers except esp clobbered at this point
 2699     # restore ed
 2700     89/<- %edx 4/r32/esp
 2701     (flush _test-output-buffered-file)
 2702     (flush _test-error-buffered-file)
 2703 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2709     # check output
 2710     (check-stream-equal _test-output-stream  ""  "F - test-float-var-in-wrong-register: output should be empty")
 2711     (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")
 2712     # check that stop(1) was called
 2713     (check-ints-equal *(edx+4) 2 "F - test-float-var-in-wrong-register: exit status")
 2714     # don't restore from ebp
 2715     81 0/subop/add %esp 8/imm32
 2716     # . epilogue
 2717     5d/pop-to-ebp
 2718     c3/return
 2719 
 2720 test-non-float-var-in-wrong-register:
 2721     # . prologue
 2722     55/push-ebp
 2723     89/<- %ebp 4/r32/esp
 2724     # setup
 2725     (clear-stream _test-input-stream)
 2726     (clear-stream $_test-input-buffered-file->buffer)
 2727     (clear-stream _test-output-stream)
 2728     (clear-stream $_test-output-buffered-file->buffer)
 2729     (clear-stream _test-error-stream)
 2730     (clear-stream $_test-error-buffered-file->buffer)
 2731     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2732     68/push 0/imm32
 2733     68/push 0/imm32
 2734     89/<- %edx 4/r32/esp
 2735     (tailor-exit-descriptor %edx 0x10)
 2736     #
 2737     (write _test-input-stream "fn foo {\n")
 2738     (write _test-input-stream "  var x/xmm5: int <- copy 0\n")
 2739     (write _test-input-stream "}\n")
 2740     # convert
 2741     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2742     # registers except esp clobbered at this point
 2743     # restore ed
 2744     89/<- %edx 4/r32/esp
 2745     (flush _test-output-buffered-file)
 2746     (flush _test-error-buffered-file)
 2747 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2753     # check output
 2754     (check-stream-equal _test-output-stream  ""  "F - test-non-float-var-in-wrong-register: output should be empty")
 2755     (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")
 2756     # check that stop(1) was called
 2757     (check-ints-equal *(edx+4) 2 "F - test-non-float-var-in-wrong-register: exit status")
 2758     # don't restore from ebp
 2759     81 0/subop/add %esp 8/imm32
 2760     # . epilogue
 2761     5d/pop-to-ebp
 2762     c3/return
 2763 
 2764 test-convert-function-with-allocate:
 2765     # . prologue
 2766     55/push-ebp
 2767     89/<- %ebp 4/r32/esp
 2768     # setup
 2769     (clear-stream _test-input-stream)
 2770     (clear-stream $_test-input-buffered-file->buffer)
 2771     (clear-stream _test-output-stream)
 2772     (clear-stream $_test-output-buffered-file->buffer)
 2773     #
 2774     (write _test-input-stream "fn foo {\n")
 2775     (write _test-input-stream "  var x/ecx: (addr handle int) <- copy 0\n")
 2776     (write _test-input-stream "  allocate x\n")
 2777     (write _test-input-stream "}\n")
 2778     # convert
 2779     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2780     (flush _test-output-buffered-file)
 2781 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2787     # check output
 2788     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-allocate/0")
 2789     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-allocate/1")
 2790     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-allocate/2")
 2791     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-allocate/3")
 2792     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-allocate/4")
 2793     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-allocate/5")
 2794     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-allocate/6")
 2795     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-allocate/7")
 2796     (check-next-stream-line-equal _test-output-stream "    (allocate Heap 0x00000004 %ecx)"  "F - test-convert-function-with-allocate/8")  # 4 = size-of(int)
 2797     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-allocate/9")
 2798     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-allocate/10")
 2799     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-allocate/11")
 2800     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-allocate/12")
 2801     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-allocate/13")
 2802     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-allocate/14")
 2803     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-allocate/15")
 2804     # . epilogue
 2805     89/<- %esp 5/r32/ebp
 2806     5d/pop-to-ebp
 2807     c3/return
 2808 
 2809 test-initializer-in-hex:
 2810     # . prologue
 2811     55/push-ebp
 2812     89/<- %ebp 4/r32/esp
 2813     # setup
 2814     (clear-stream _test-input-stream)
 2815     (clear-stream $_test-input-buffered-file->buffer)
 2816     (clear-stream _test-output-stream)
 2817     (clear-stream $_test-output-buffered-file->buffer)
 2818     (clear-stream _test-error-stream)
 2819     (clear-stream $_test-error-buffered-file->buffer)
 2820     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2821     68/push 0/imm32
 2822     68/push 0/imm32
 2823     89/<- %edx 4/r32/esp
 2824     (tailor-exit-descriptor %edx 0x10)
 2825     #
 2826     (write _test-input-stream "fn foo {\n")
 2827     (write _test-input-stream "  var x/ecx: int <- copy 10\n")
 2828     (write _test-input-stream "}\n")
 2829     # convert
 2830     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2831     # registers except esp clobbered at this point
 2832     # restore ed
 2833     89/<- %edx 4/r32/esp
 2834     (flush _test-output-buffered-file)
 2835     (flush _test-error-buffered-file)
 2836 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2842     # check output
 2843     (check-stream-equal _test-output-stream  ""  "F - test-initializer-in-hex: output should be empty")
 2844     (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")
 2845     # check that stop(1) was called
 2846     (check-ints-equal *(edx+4) 2 "F - test-initializer-in-hex: exit status")
 2847     # don't restore from ebp
 2848     81 0/subop/add %esp 8/imm32
 2849     # . epilogue
 2850     5d/pop-to-ebp
 2851     c3/return
 2852 
 2853 test-convert-function-with-second-local-var-in-same-reg:
 2854     # . prologue
 2855     55/push-ebp
 2856     89/<- %ebp 4/r32/esp
 2857     # setup
 2858     (clear-stream _test-input-stream)
 2859     (clear-stream $_test-input-buffered-file->buffer)
 2860     (clear-stream _test-output-stream)
 2861     (clear-stream $_test-output-buffered-file->buffer)
 2862     #
 2863     (write _test-input-stream "fn foo {\n")
 2864     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2865     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 2866     (write _test-input-stream "  y <- increment\n")
 2867     (write _test-input-stream "}\n")
 2868     # convert
 2869     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2870     (flush _test-output-buffered-file)
 2871 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2877     # check output
 2878     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-second-local-var-in-same-reg/0")
 2879     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-second-local-var-in-same-reg/1")
 2880     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-second-local-var-in-same-reg/2")
 2881     (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")
 2882     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-second-local-var-in-same-reg/4")
 2883     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-second-local-var-in-same-reg/5")
 2884     (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")
 2885     (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")
 2886     (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")
 2887     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-convert-function-with-second-local-var-in-same-reg/9")
 2888     (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")
 2889     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-second-local-var-in-same-reg/11")
 2890     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-second-local-var-in-same-reg/12")
 2891     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-second-local-var-in-same-reg/13")
 2892     (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")
 2893     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-second-local-var-in-same-reg/15")
 2894     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-second-local-var-in-same-reg/16")
 2895     # . epilogue
 2896     89/<- %esp 5/r32/ebp
 2897     5d/pop-to-ebp
 2898     c3/return
 2899 
 2900 test-read-clobbered-reg-var:
 2901     # . prologue
 2902     55/push-ebp
 2903     89/<- %ebp 4/r32/esp
 2904     # setup
 2905     (clear-stream _test-input-stream)
 2906     (clear-stream $_test-input-buffered-file->buffer)
 2907     (clear-stream _test-output-stream)
 2908     (clear-stream $_test-output-buffered-file->buffer)
 2909     (clear-stream _test-error-stream)
 2910     (clear-stream $_test-error-buffered-file->buffer)
 2911     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
 2912     68/push 0/imm32
 2913     68/push 0/imm32
 2914     89/<- %edx 4/r32/esp
 2915     (tailor-exit-descriptor %edx 0x10)
 2916     #
 2917     (write _test-input-stream "fn foo {\n")
 2918     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2919     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 2920     (write _test-input-stream "  x <- increment\n")
 2921     (write _test-input-stream "}\n")
 2922     # convert
 2923     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2924     # registers except esp clobbered at this point
 2925     # restore ed
 2926     89/<- %edx 4/r32/esp
 2927     (flush _test-output-buffered-file)
 2928     (flush _test-error-buffered-file)
 2929 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2935     # check output
 2936     (check-stream-equal _test-output-stream  ""  "F - test-read-clobbered-reg-var: output should be empty")
 2937     (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")
 2938     # check that stop(1) was called
 2939     (check-ints-equal *(edx+4) 2 "F - test-read-clobbered-reg-var: exit status")
 2940     # don't restore from ebp
 2941     81 0/subop/add %esp 8/imm32
 2942     # . epilogue
 2943     5d/pop-to-ebp
 2944     c3/return
 2945 
 2946 test-overlapping-int-fp-registers:
 2947     # . prologue
 2948     55/push-ebp
 2949     89/<- %ebp 4/r32/esp
 2950     # setup
 2951     (clear-stream _test-input-stream)
 2952     (clear-stream $_test-input-buffered-file->buffer)
 2953     (clear-stream _test-output-stream)
 2954     (clear-stream $_test-output-buffered-file->buffer)
 2955     (clear-stream _test-error-stream)
 2956     (clear-stream $_test-error-buffered-file->buffer)
 2957     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
 2958     68/push 0/imm32
 2959     68/push 0/imm32
 2960     89/<- %edx 4/r32/esp
 2961     (tailor-exit-descriptor %edx 0x10)
 2962     #
 2963     (write _test-input-stream "fn foo {\n")
 2964     (write _test-input-stream "  var x/eax: int <- copy 3\n")
 2965     (write _test-input-stream "  var y/xmm0: float <- convert x\n")
 2966     (write _test-input-stream "  x <- increment\n")
 2967     (write _test-input-stream "}\n")
 2968     # convert
 2969     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2970     # registers except esp clobbered at this point
 2971     # restore ed
 2972     89/<- %edx 4/r32/esp
 2973     (flush _test-output-buffered-file)
 2974     (flush _test-error-buffered-file)
 2975 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2981     # no errors
 2982     (check-next-stream-line-equal _test-error-stream  ""  "F - test-overlapping-int-fp-registers: error message")
 2983     # don't bother checking the generated code
 2984     # don't restore from ebp
 2985     81 0/subop/add %esp 8/imm32
 2986     # . epilogue
 2987     5d/pop-to-ebp
 2988     c3/return
 2989 
 2990 test-convert-function-call:
 2991     # . prologue
 2992     55/push-ebp
 2993     89/<- %ebp 4/r32/esp
 2994     # setup
 2995     (clear-stream _test-input-stream)
 2996     (clear-stream $_test-input-buffered-file->buffer)
 2997     (clear-stream _test-output-stream)
 2998     (clear-stream $_test-output-buffered-file->buffer)
 2999     #
 3000     (write _test-input-stream "fn main -> _/ebx: int {\n")
 3001     (write _test-input-stream "  var result/ebx: int <- foo\n")
 3002     (write _test-input-stream "  return result\n")
 3003     (write _test-input-stream "}\n")
 3004     (write _test-input-stream "fn foo -> _/ebx: int {\n")
 3005     (write _test-input-stream "  var result/ebx: int <- copy 3\n")
 3006     (write _test-input-stream "  return result\n")
 3007     (write _test-input-stream "}\n")
 3008     # convert
 3009     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3010     (flush _test-output-buffered-file)
 3011 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3017     # check output
 3018     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call/0")
 3019     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call/1")
 3020     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call/2")
 3021     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call/3")
 3022     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call/4")
 3023     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call/5")
 3024     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-call-with-literal-arg/6")
 3025     (check-next-stream-line-equal _test-output-stream "    (foo)"               "F - test-convert-function-call/6")
 3026     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 3027     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
 3028     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 3029     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call/7")
 3030     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call/8")
 3031     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call/9")
 3032     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call/10")
 3033     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call/11")
 3034     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call/12")
 3035     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call/13")
 3036     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call/14")
 3037     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call/15")
 3038     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call/16")
 3039     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call/17")
 3040     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"  "F - test-convert-function-call/18")
 3041     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-call-with-literal-arg/6")
 3042     (check-next-stream-line-equal _test-output-stream "    bb/copy-to-ebx 3/imm32"  "F - test-convert-function-call/19")
 3043     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 3044     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
 3045     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 3046     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call/20")
 3047     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-call/21")
 3048     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call/22")
 3049     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call/23")
 3050     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call/24")
 3051     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call/25")
 3052     # . epilogue
 3053     89/<- %esp 5/r32/ebp
 3054     5d/pop-to-ebp
 3055     c3/return
 3056 
 3057 test-convert-function-call-with-inout-with-compound-type:
 3058     # . prologue
 3059     55/push-ebp
 3060     89/<- %ebp 4/r32/esp
 3061     # setup
 3062     (clear-stream _test-input-stream)
 3063     (clear-stream $_test-input-buffered-file->buffer)
 3064     (clear-stream _test-output-stream)
 3065     (clear-stream $_test-output-buffered-file->buffer)
 3066     #
 3067     (write _test-input-stream "fn f {\n")
 3068     (write _test-input-stream "  var x: (addr int)\n")
 3069     (write _test-input-stream "  g x\n")
 3070     (write _test-input-stream "}\n")
 3071     (write _test-input-stream "fn g a: (addr int) {\n")
 3072     (write _test-input-stream "}\n")
 3073     # convert
 3074     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3075     (flush _test-output-buffered-file)
 3076 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3082     # check output
 3083     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-inout-with-compound-type/0")
 3084     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-inout-with-compound-type/1")
 3085     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-inout-with-compound-type/2")
 3086     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-inout-with-compound-type/3")
 3087     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-inout-with-compound-type/4")
 3088     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-inout-with-compound-type/5")
 3089     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-inout-with-compound-type/6")
 3090     (check-next-stream-line-equal _test-output-stream "    (g *(ebp+0xfffffffc))"  "F - test-convert-function-call-with-inout-with-compound-type/7")
 3091     (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")
 3092     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-inout-with-compound-type/9")
 3093     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-inout-with-compound-type/10")
 3094     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-inout-with-compound-type/11")
 3095     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-inout-with-compound-type/12")
 3096     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-inout-with-compound-type/13")
 3097     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-inout-with-compound-type/14")
 3098     (check-next-stream-line-equal _test-output-stream "g:"                      "F - test-convert-function-call-with-inout-with-compound-type/15")
 3099     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-inout-with-compound-type/16")
 3100     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-inout-with-compound-type/17")
 3101     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-inout-with-compound-type/18")
 3102     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-inout-with-compound-type/19")
 3103     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-inout-with-compound-type/20")
 3104     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-inout-with-compound-type/21")
 3105     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-inout-with-compound-type/22")
 3106     # . epilogue
 3107     89/<- %esp 5/r32/ebp
 3108     5d/pop-to-ebp
 3109     c3/return
 3110 
 3111 test-convert-function-call-with-inout-with-type-parameter:
 3112     # . prologue
 3113     55/push-ebp
 3114     89/<- %ebp 4/r32/esp
 3115     # setup
 3116     (clear-stream _test-input-stream)
 3117     (clear-stream $_test-input-buffered-file->buffer)
 3118     (clear-stream _test-output-stream)
 3119     (clear-stream $_test-output-buffered-file->buffer)
 3120     (clear-stream _test-error-stream)
 3121     (clear-stream $_test-error-buffered-file->buffer)
 3122     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3123     68/push 0/imm32
 3124     68/push 0/imm32
 3125     89/<- %edx 4/r32/esp
 3126     (tailor-exit-descriptor %edx 0x10)
 3127     #
 3128     (write _test-input-stream "fn f {\n")
 3129     (write _test-input-stream "  var x: (addr int)\n")
 3130     (write _test-input-stream "  g x\n")
 3131     (write _test-input-stream "}\n")
 3132     (write _test-input-stream "fn g a: (addr _) {\n")
 3133     (write _test-input-stream "}\n")
 3134     # convert
 3135     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3136     # registers except esp clobbered at this point
 3137     # restore ed
 3138     89/<- %edx 4/r32/esp
 3139     (flush _test-output-buffered-file)
 3140     (flush _test-error-buffered-file)
 3141 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3147     # no error; types matched
 3148     (check-stream-equal _test-error-stream  ""  "F - test-convert-function-call-with-inout-with-type-parameter: error stream should be empty")
 3149     # don't bother checking the generated code; that's in the test 'test-local-clobbered-by-fn-output' below
 3150     # don't restore from ebp
 3151     81 0/subop/add %esp 8/imm32
 3152     # . epilogue
 3153     5d/pop-to-ebp
 3154     c3/return
 3155 
 3156 test-convert-function-call-with-incorrect-inout-type:
 3157     # . prologue
 3158     55/push-ebp
 3159     89/<- %ebp 4/r32/esp
 3160     # setup
 3161     (clear-stream _test-input-stream)
 3162     (clear-stream $_test-input-buffered-file->buffer)
 3163     (clear-stream _test-output-stream)
 3164     (clear-stream $_test-output-buffered-file->buffer)
 3165     (clear-stream _test-error-stream)
 3166     (clear-stream $_test-error-buffered-file->buffer)
 3167     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3168     68/push 0/imm32
 3169     68/push 0/imm32
 3170     89/<- %edx 4/r32/esp
 3171     (tailor-exit-descriptor %edx 0x10)
 3172     #
 3173     (write _test-input-stream "fn f {\n")
 3174     (write _test-input-stream "  var x: int\n")
 3175     (write _test-input-stream "  g x\n")
 3176     (write _test-input-stream "}\n")
 3177     (write _test-input-stream "fn g a: foo {\n")
 3178     (write _test-input-stream "}\n")
 3179     # convert
 3180     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3181     # registers except esp clobbered at this point
 3182     # restore ed
 3183     89/<- %edx 4/r32/esp
 3184     (flush _test-output-buffered-file)
 3185     (flush _test-error-buffered-file)
 3186 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3192     # check output
 3193     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-inout-type: output should be empty")
 3194     (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")
 3195     # check that stop(1) was called
 3196     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-inout-type: exit status")
 3197     # don't restore from ebp
 3198     81 0/subop/add %esp 8/imm32
 3199     5d/pop-to-ebp
 3200     c3/return
 3201 
 3202 test-convert-function-call-with-inout-with-incorrect-compound-type:
 3203     # . prologue
 3204     55/push-ebp
 3205     89/<- %ebp 4/r32/esp
 3206     # setup
 3207     (clear-stream _test-input-stream)
 3208     (clear-stream $_test-input-buffered-file->buffer)
 3209     (clear-stream _test-output-stream)
 3210     (clear-stream $_test-output-buffered-file->buffer)
 3211     (clear-stream _test-error-stream)
 3212     (clear-stream $_test-error-buffered-file->buffer)
 3213     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3214     68/push 0/imm32
 3215     68/push 0/imm32
 3216     89/<- %edx 4/r32/esp
 3217     (tailor-exit-descriptor %edx 0x10)
 3218     #
 3219     (write _test-input-stream "fn f {\n")
 3220     (write _test-input-stream "  var x: (addr int)\n")
 3221     (write _test-input-stream "  g x\n")
 3222     (write _test-input-stream "}\n")
 3223     (write _test-input-stream "fn g a: (addr bool) {\n")
 3224     (write _test-input-stream "}\n")
 3225     # convert
 3226     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3227     # registers except esp clobbered at this point
 3228     # restore ed
 3229     89/<- %edx 4/r32/esp
 3230     (flush _test-output-buffered-file)
 3231     (flush _test-error-buffered-file)
 3232 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3238     # check output
 3239     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-inout-with-incorrect-compound-type: output should be empty")
 3240     (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")
 3241     # don't restore from ebp
 3242     81 0/subop/add %esp 8/imm32
 3243     # . epilogue
 3244     5d/pop-to-ebp
 3245     c3/return
 3246 
 3247 test-convert-function-call-with-inout-with-multiple-type-parameters:
 3248     # . prologue
 3249     55/push-ebp
 3250     89/<- %ebp 4/r32/esp
 3251     # setup
 3252     (clear-stream _test-input-stream)
 3253     (clear-stream $_test-input-buffered-file->buffer)
 3254     (clear-stream _test-output-stream)
 3255     (clear-stream $_test-output-buffered-file->buffer)
 3256     (clear-stream _test-error-stream)
 3257     (clear-stream $_test-error-buffered-file->buffer)
 3258     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3259     68/push 0/imm32
 3260     68/push 0/imm32
 3261     89/<- %edx 4/r32/esp
 3262     (tailor-exit-descriptor %edx 0x10)
 3263     #
 3264     (write _test-input-stream "fn f {\n")
 3265     (write _test-input-stream "  var x: (addr int)\n")
 3266     (write _test-input-stream "  var y: (addr int)\n")
 3267     (write _test-input-stream "  g x, y\n")
 3268     (write _test-input-stream "}\n")
 3269     (write _test-input-stream "fn g a: (addr _), b: (addr _) {\n")
 3270     (write _test-input-stream "}\n")
 3271     # convert
 3272     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3273     # registers except esp clobbered at this point
 3274     # restore ed
 3275     89/<- %edx 4/r32/esp
 3276     (flush _test-output-buffered-file)
 3277     (flush _test-error-buffered-file)
 3278 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3284     # no errors
 3285     (check-stream-equal _test-error-stream  ""  "F - test-convert-function-call-with-inout-with-multiple-type-parameters: error stream should be empty")
 3286     # don't bother checking the generated code
 3287     # don't restore from ebp
 3288     81 0/subop/add %esp 8/imm32
 3289     # . epilogue
 3290     5d/pop-to-ebp
 3291     c3/return
 3292 
 3293 test-type-parameter-matches-rest-of-type:
 3294     # . prologue
 3295     55/push-ebp
 3296     89/<- %ebp 4/r32/esp
 3297     # setup
 3298     (clear-stream _test-input-stream)
 3299     (clear-stream $_test-input-buffered-file->buffer)
 3300     (clear-stream _test-output-stream)
 3301     (clear-stream $_test-output-buffered-file->buffer)
 3302     (clear-stream _test-error-stream)
 3303     (clear-stream $_test-error-buffered-file->buffer)
 3304     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3305     68/push 0/imm32
 3306     68/push 0/imm32
 3307     89/<- %edx 4/r32/esp
 3308     (tailor-exit-descriptor %edx 0x10)
 3309     #
 3310     (write _test-input-stream "fn f {\n")
 3311     (write _test-input-stream "  var x: (addr array int)\n")
 3312     (write _test-input-stream "  g x\n")
 3313     (write _test-input-stream "}\n")
 3314     (write _test-input-stream "fn g a: (addr _) {\n")
 3315     (write _test-input-stream "}\n")
 3316     # convert
 3317     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3318     # registers except esp clobbered at this point
 3319     # restore ed
 3320     89/<- %edx 4/r32/esp
 3321     (flush _test-output-buffered-file)
 3322     (flush _test-error-buffered-file)
 3323 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3329     # no errors
 3330     (check-stream-equal _test-error-stream  ""  "F - test-type-parameter-matches-rest-of-type: error stream should be empty")
 3331     # don't bother checking the generated code
 3332     # don't restore from ebp
 3333     81 0/subop/add %esp 8/imm32
 3334     # . epilogue
 3335     5d/pop-to-ebp
 3336     c3/return
 3337 
 3338 test-convert-function-call-with-inout-with-incompatible-type-parameters:
 3339     # . prologue
 3340     55/push-ebp
 3341     89/<- %ebp 4/r32/esp
 3342     # setup
 3343     (clear-stream _test-input-stream)
 3344     (clear-stream $_test-input-buffered-file->buffer)
 3345     (clear-stream _test-output-stream)
 3346     (clear-stream $_test-output-buffered-file->buffer)
 3347     (clear-stream _test-error-stream)
 3348     (clear-stream $_test-error-buffered-file->buffer)
 3349     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3350     68/push 0/imm32
 3351     68/push 0/imm32
 3352     89/<- %edx 4/r32/esp
 3353     (tailor-exit-descriptor %edx 0x10)
 3354     #
 3355     (write _test-input-stream "fn f {\n")
 3356     (write _test-input-stream "  var x: (addr int)\n")
 3357     (write _test-input-stream "  var y: (addr boolean)\n")
 3358     (write _test-input-stream "  g x, y\n")
 3359     (write _test-input-stream "}\n")
 3360     (write _test-input-stream "fn g a: (addr _T), b: (addr _T) {\n")
 3361     (write _test-input-stream "}\n")
 3362     # convert
 3363     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3364     # registers except esp clobbered at this point
 3365     # restore ed
 3366     89/<- %edx 4/r32/esp
 3367     (flush _test-output-buffered-file)
 3368     (flush _test-error-buffered-file)
 3369 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3375     # check output
 3376     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-inout-with-incompatible-type-parameters: output should be empty")
 3377     (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")
 3378     # don't restore from ebp
 3379     81 0/subop/add %esp 8/imm32
 3380     # . epilogue
 3381     5d/pop-to-ebp
 3382     c3/return
 3383 
 3384 test-convert-function-call-with-too-few-inouts:
 3385     # . prologue
 3386     55/push-ebp
 3387     89/<- %ebp 4/r32/esp
 3388     # setup
 3389     (clear-stream _test-input-stream)
 3390     (clear-stream $_test-input-buffered-file->buffer)
 3391     (clear-stream _test-output-stream)
 3392     (clear-stream $_test-output-buffered-file->buffer)
 3393     (clear-stream _test-error-stream)
 3394     (clear-stream $_test-error-buffered-file->buffer)
 3395     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3396     68/push 0/imm32
 3397     68/push 0/imm32
 3398     89/<- %edx 4/r32/esp
 3399     (tailor-exit-descriptor %edx 0x10)
 3400     #
 3401     (write _test-input-stream "fn f {\n")
 3402     (write _test-input-stream "  g\n")
 3403     (write _test-input-stream "}\n")
 3404     (write _test-input-stream "fn g a: int {\n")
 3405     (write _test-input-stream "}\n")
 3406     # convert
 3407     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3408     # registers except esp clobbered at this point
 3409     # restore ed
 3410     89/<- %edx 4/r32/esp
 3411     (flush _test-output-buffered-file)
 3412     (flush _test-error-buffered-file)
 3413 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3419     # check output
 3420     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-few-inouts: output should be empty")
 3421     (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")
 3422     # check that stop(1) was called
 3423     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-few-inouts: exit status")
 3424     # don't restore from ebp
 3425     81 0/subop/add %esp 8/imm32
 3426     5d/pop-to-ebp
 3427     c3/return
 3428 
 3429 test-convert-function-call-with-too-many-inouts:
 3430     # . prologue
 3431     55/push-ebp
 3432     89/<- %ebp 4/r32/esp
 3433     # setup
 3434     (clear-stream _test-input-stream)
 3435     (clear-stream $_test-input-buffered-file->buffer)
 3436     (clear-stream _test-output-stream)
 3437     (clear-stream $_test-output-buffered-file->buffer)
 3438     (clear-stream _test-error-stream)
 3439     (clear-stream $_test-error-buffered-file->buffer)
 3440     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3441     68/push 0/imm32
 3442     68/push 0/imm32
 3443     89/<- %edx 4/r32/esp
 3444     (tailor-exit-descriptor %edx 0x10)
 3445     #
 3446     (write _test-input-stream "fn f {\n")
 3447     (write _test-input-stream "  var x: int\n")
 3448     (write _test-input-stream "  g x\n")
 3449     (write _test-input-stream "}\n")
 3450     (write _test-input-stream "fn g {\n")
 3451     (write _test-input-stream "}\n")
 3452     # convert
 3453     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3454     # registers except esp clobbered at this point
 3455     # restore ed
 3456     89/<- %edx 4/r32/esp
 3457     (flush _test-output-buffered-file)
 3458     (flush _test-error-buffered-file)
 3459 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3465     # check output
 3466     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-many-inouts: output should be empty")
 3467     (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")
 3468     # check that stop(1) was called
 3469     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-many-inouts: exit status")
 3470     # don't restore from ebp
 3471     81 0/subop/add %esp 8/imm32
 3472     5d/pop-to-ebp
 3473     c3/return
 3474 
 3475 test-convert-function-call-with-incorrect-output-type:
 3476     # . prologue
 3477     55/push-ebp
 3478     89/<- %ebp 4/r32/esp
 3479     # setup
 3480     (clear-stream _test-input-stream)
 3481     (clear-stream $_test-input-buffered-file->buffer)
 3482     (clear-stream _test-output-stream)
 3483     (clear-stream $_test-output-buffered-file->buffer)
 3484     (clear-stream _test-error-stream)
 3485     (clear-stream $_test-error-buffered-file->buffer)
 3486     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3487     68/push 0/imm32
 3488     68/push 0/imm32
 3489     89/<- %edx 4/r32/esp
 3490     (tailor-exit-descriptor %edx 0x10)
 3491     #
 3492     (write _test-input-stream "fn f {\n")
 3493     (write _test-input-stream "  var x/eax: int <- g\n")
 3494     (write _test-input-stream "}\n")
 3495     (write _test-input-stream "fn g -> _/eax: foo {\n")
 3496     (write _test-input-stream "}\n")
 3497     # convert
 3498     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3499     # registers except esp clobbered at this point
 3500     # restore ed
 3501     89/<- %edx 4/r32/esp
 3502     (flush _test-output-buffered-file)
 3503     (flush _test-error-buffered-file)
 3504 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3510     # check output
 3511     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-output-type: output should be empty")
 3512     (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")
 3513     # check that stop(1) was called
 3514     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-output-type: exit status")
 3515     # don't restore from ebp
 3516     81 0/subop/add %esp 8/imm32
 3517     5d/pop-to-ebp
 3518     c3/return
 3519 
 3520 test-convert-function-call-with-too-few-outputs:
 3521     # . prologue
 3522     55/push-ebp
 3523     89/<- %ebp 4/r32/esp
 3524     # setup
 3525     (clear-stream _test-input-stream)
 3526     (clear-stream $_test-input-buffered-file->buffer)
 3527     (clear-stream _test-output-stream)
 3528     (clear-stream $_test-output-buffered-file->buffer)
 3529     (clear-stream _test-error-stream)
 3530     (clear-stream $_test-error-buffered-file->buffer)
 3531     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3532     68/push 0/imm32
 3533     68/push 0/imm32
 3534     89/<- %edx 4/r32/esp
 3535     (tailor-exit-descriptor %edx 0x10)
 3536     #
 3537     (write _test-input-stream "fn f {\n")
 3538     (write _test-input-stream "  g\n")
 3539     (write _test-input-stream "}\n")
 3540     (write _test-input-stream "fn g -> _/eax: int {\n")
 3541     (write _test-input-stream "}\n")
 3542     # convert
 3543     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3544     # registers except esp clobbered at this point
 3545     # restore ed
 3546     89/<- %edx 4/r32/esp
 3547     (flush _test-output-buffered-file)
 3548     (flush _test-error-buffered-file)
 3549 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3555     # check output
 3556     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-few-outputs: output should be empty")
 3557     (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")
 3558     # check that stop(1) was called
 3559     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-few-outputs: exit status")
 3560     # don't restore from ebp
 3561     81 0/subop/add %esp 8/imm32
 3562     5d/pop-to-ebp
 3563     c3/return
 3564 
 3565 test-convert-function-call-with-too-many-outputs:
 3566     # . prologue
 3567     55/push-ebp
 3568     89/<- %ebp 4/r32/esp
 3569     # setup
 3570     (clear-stream _test-input-stream)
 3571     (clear-stream $_test-input-buffered-file->buffer)
 3572     (clear-stream _test-output-stream)
 3573     (clear-stream $_test-output-buffered-file->buffer)
 3574     (clear-stream _test-error-stream)
 3575     (clear-stream $_test-error-buffered-file->buffer)
 3576     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3577     68/push 0/imm32
 3578     68/push 0/imm32
 3579     89/<- %edx 4/r32/esp
 3580     (tailor-exit-descriptor %edx 0x10)
 3581     #
 3582     (write _test-input-stream "fn f {\n")
 3583     (write _test-input-stream "  var x/eax: int <- g\n")
 3584     (write _test-input-stream "}\n")
 3585     (write _test-input-stream "fn g {\n")
 3586     (write _test-input-stream "}\n")
 3587     # convert
 3588     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3589     # registers except esp clobbered at this point
 3590     # restore ed
 3591     89/<- %edx 4/r32/esp
 3592     (flush _test-output-buffered-file)
 3593     (flush _test-error-buffered-file)
 3594 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3600     # check output
 3601     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-many-outputs: output should be empty")
 3602     (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")
 3603     # check that stop(1) was called
 3604     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-many-outputs: exit status")
 3605     # don't restore from ebp
 3606     81 0/subop/add %esp 8/imm32
 3607     5d/pop-to-ebp
 3608     c3/return
 3609 
 3610 test-convert-function-call-with-missing-output-register:
 3611     # . prologue
 3612     55/push-ebp
 3613     89/<- %ebp 4/r32/esp
 3614     # setup
 3615     (clear-stream _test-input-stream)
 3616     (clear-stream $_test-input-buffered-file->buffer)
 3617     (clear-stream _test-output-stream)
 3618     (clear-stream $_test-output-buffered-file->buffer)
 3619     (clear-stream _test-error-stream)
 3620     (clear-stream $_test-error-buffered-file->buffer)
 3621     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3622     68/push 0/imm32
 3623     68/push 0/imm32
 3624     89/<- %edx 4/r32/esp
 3625     (tailor-exit-descriptor %edx 0x10)
 3626     #
 3627     (write _test-input-stream "fn f {\n")
 3628     (write _test-input-stream "  var x: int\n")
 3629     (write _test-input-stream "  x <- g\n")
 3630     (write _test-input-stream "}\n")
 3631     (write _test-input-stream "fn g -> _/eax: int {\n")
 3632     (write _test-input-stream "}\n")
 3633     # convert
 3634     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3635     # registers except esp clobbered at this point
 3636     # restore ed
 3637     89/<- %edx 4/r32/esp
 3638     (flush _test-output-buffered-file)
 3639     (flush _test-error-buffered-file)
 3640 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3646     # check output
 3647     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-missing-output-register: output should be empty")
 3648     (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")
 3649     # check that stop(1) was called
 3650     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-missing-output-register: exit status")
 3651     # don't restore from ebp
 3652     81 0/subop/add %esp 8/imm32
 3653     5d/pop-to-ebp
 3654     c3/return
 3655 
 3656 test-convert-function-call-with-incorrect-output-register:
 3657     # . prologue
 3658     55/push-ebp
 3659     89/<- %ebp 4/r32/esp
 3660     # setup
 3661     (clear-stream _test-input-stream)
 3662     (clear-stream $_test-input-buffered-file->buffer)
 3663     (clear-stream _test-output-stream)
 3664     (clear-stream $_test-output-buffered-file->buffer)
 3665     (clear-stream _test-error-stream)
 3666     (clear-stream $_test-error-buffered-file->buffer)
 3667     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3668     68/push 0/imm32
 3669     68/push 0/imm32
 3670     89/<- %edx 4/r32/esp
 3671     (tailor-exit-descriptor %edx 0x10)
 3672     #
 3673     (write _test-input-stream "fn f {\n")
 3674     (write _test-input-stream "  var x/ecx: int <- g\n")
 3675     (write _test-input-stream "}\n")
 3676     (write _test-input-stream "fn g -> _/eax: int {\n")
 3677     (write _test-input-stream "}\n")
 3678     # convert
 3679     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3680     # registers except esp clobbered at this point
 3681     # restore ed
 3682     89/<- %edx 4/r32/esp
 3683     (flush _test-output-buffered-file)
 3684     (flush _test-error-buffered-file)
 3685 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3691     # check output
 3692     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-output-register: output should be empty")
 3693     (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")
 3694     # check that stop(1) was called
 3695     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-output-register: exit status")
 3696     # don't restore from ebp
 3697     81 0/subop/add %esp 8/imm32
 3698     5d/pop-to-ebp
 3699     c3/return
 3700 
 3701 test-convert-function-with-local-var-dereferenced:
 3702     # . prologue
 3703     55/push-ebp
 3704     89/<- %ebp 4/r32/esp
 3705     # setup
 3706     (clear-stream _test-input-stream)
 3707     (clear-stream $_test-input-buffered-file->buffer)
 3708     (clear-stream _test-output-stream)
 3709     (clear-stream $_test-output-buffered-file->buffer)
 3710     #
 3711     (write _test-input-stream "fn foo {\n")
 3712     (write _test-input-stream "  var x/ecx: (addr int) <- copy 0\n")
 3713     (write _test-input-stream "  increment *x\n")
 3714     (write _test-input-stream "}\n")
 3715     # convert
 3716     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3717     (flush _test-output-buffered-file)
 3718 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3724     # check output
 3725     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-dereferenced/0")
 3726     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-dereferenced/1")
 3727     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-dereferenced/2")
 3728     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-dereferenced/3")
 3729     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-dereferenced/4")
 3730     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-dereferenced/5")
 3731     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-dereferenced/6")
 3732     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-local-var-dereferenced/7")
 3733     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *ecx"  "F - test-convert-function-with-local-var-dereferenced/8")
 3734     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-dereferenced/9")
 3735     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-dereferenced/10")
 3736     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-dereferenced/11")
 3737     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-dereferenced/12")
 3738     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-dereferenced/13")
 3739     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-dereferenced/14")
 3740     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-dereferenced/15")
 3741     # . epilogue
 3742     89/<- %esp 5/r32/ebp
 3743     5d/pop-to-ebp
 3744     c3/return
 3745 
 3746 test-dereference-of-var-on-stack:
 3747     # . prologue
 3748     55/push-ebp
 3749     89/<- %ebp 4/r32/esp
 3750     # setup
 3751     (clear-stream _test-input-stream)
 3752     (clear-stream $_test-input-buffered-file->buffer)
 3753     (clear-stream _test-output-stream)
 3754     (clear-stream $_test-output-buffered-file->buffer)
 3755     (clear-stream _test-error-stream)
 3756     (clear-stream $_test-error-buffered-file->buffer)
 3757     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3758     68/push 0/imm32
 3759     68/push 0/imm32
 3760     89/<- %edx 4/r32/esp
 3761     (tailor-exit-descriptor %edx 0x10)
 3762     #
 3763     (write _test-input-stream "fn foo {\n")
 3764     (write _test-input-stream "  var x: (addr int)\n")
 3765     (write _test-input-stream "  increment *x\n")
 3766     (write _test-input-stream "}\n")
 3767     # convert
 3768     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3769     # registers except esp clobbered at this point
 3770     # restore ed
 3771     89/<- %edx 4/r32/esp
 3772     (flush _test-output-buffered-file)
 3773     (flush _test-error-buffered-file)
 3774 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3780     # check output
 3781     (check-stream-equal _test-output-stream  ""  "F - test-dereference-of-var-on-stack: output should be empty")
 3782     (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")
 3783     # check that stop(1) was called
 3784     (check-ints-equal *(edx+4) 2 "F - test-dereference-of-var-on-stack: exit status")
 3785     # don't restore from ebp
 3786     81 0/subop/add %esp 8/imm32
 3787     # . epilogue
 3788     5d/pop-to-ebp
 3789     c3/return
 3790 
 3791 test-convert-function-with-byte-operations:
 3792     # . prologue
 3793     55/push-ebp
 3794     89/<- %ebp 4/r32/esp
 3795     # setup
 3796     (clear-stream _test-input-stream)
 3797     (clear-stream $_test-input-buffered-file->buffer)
 3798     (clear-stream _test-output-stream)
 3799     (clear-stream $_test-output-buffered-file->buffer)
 3800     #
 3801     (write _test-input-stream "fn foo {\n")
 3802     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
 3803     (write _test-input-stream "  var y/ecx: byte <- copy 0\n")
 3804     (write _test-input-stream "  y <- copy-byte x\n")
 3805     (write _test-input-stream "  var z/edx: (addr byte) <- copy 0\n")
 3806     (write _test-input-stream "  y <- copy-byte *z\n")
 3807     (write _test-input-stream "  copy-byte-to *z, x\n")
 3808     (write _test-input-stream "}\n")
 3809     # convert
 3810     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3811     (flush _test-output-buffered-file)
 3812 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3818     # check output
 3819     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-function-with-byte-operations/0")
 3820     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-function-with-byte-operations/1")
 3821     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-function-with-byte-operations/2")
 3822     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-function-with-byte-operations/3")
 3823     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-function-with-byte-operations/4")
 3824     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-function-with-byte-operations/5")
 3825     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-function-with-byte-operations/6")
 3826     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-function-with-byte-operations/7")
 3827     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-function-with-byte-operations/8")
 3828     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"                  "F - test-convert-function-with-byte-operations/9")
 3829     (check-next-stream-line-equal _test-output-stream "    8a/byte-> %eax 0x00000001/r32"           "F - test-convert-function-with-byte-operations/10")
 3830     (check-next-stream-line-equal _test-output-stream "    81 4/subop/and %ecx 0xff/imm32"          "F - test-convert-function-with-byte-operations/11")
 3831     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %edx"                    "F - test-convert-function-with-byte-operations/12")
 3832     (check-next-stream-line-equal _test-output-stream "    ba/copy-to-edx 0/imm32"                  "F - test-convert-function-with-byte-operations/13")
 3833     (check-next-stream-line-equal _test-output-stream "    8a/byte-> *edx 0x00000001/r32"           "F - test-convert-function-with-byte-operations/14")
 3834     (check-next-stream-line-equal _test-output-stream "    81 4/subop/and %ecx 0xff/imm32"          "F - test-convert-function-with-byte-operations/15")
 3835     (check-next-stream-line-equal _test-output-stream "    88/byte<- *edx 0x00000000/r32"           "F - test-convert-function-with-byte-operations/16")
 3836     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %edx"                     "F - test-convert-function-with-byte-operations/17")
 3837     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-function-with-byte-operations/18")
 3838     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-function-with-byte-operations/19")
 3839     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-function-with-byte-operations/20")
 3840     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-function-with-byte-operations/21")
 3841     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-function-with-byte-operations/22")
 3842     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-function-with-byte-operations/23")
 3843     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-function-with-byte-operations/24")
 3844     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-function-with-byte-operations/25")
 3845     # . epilogue
 3846     89/<- %esp 5/r32/ebp
 3847     5d/pop-to-ebp
 3848     c3/return
 3849 
 3850 # variables of type 'byte' are not allowed on the stack
 3851 test-byte-values-on-stack:
 3852     # . prologue
 3853     55/push-ebp
 3854     89/<- %ebp 4/r32/esp
 3855     # setup
 3856     (clear-stream _test-input-stream)
 3857     (clear-stream $_test-input-buffered-file->buffer)
 3858     (clear-stream _test-output-stream)
 3859     (clear-stream $_test-output-buffered-file->buffer)
 3860     (clear-stream _test-error-stream)
 3861     (clear-stream $_test-error-buffered-file->buffer)
 3862     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3863     68/push 0/imm32
 3864     68/push 0/imm32
 3865     89/<- %edx 4/r32/esp
 3866     (tailor-exit-descriptor %edx 0x10)
 3867     #
 3868     (write _test-input-stream "fn foo {\n")
 3869     (write _test-input-stream "  var x: byte\n")
 3870     (write _test-input-stream "}\n")
 3871     # convert
 3872     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3873     # registers except esp clobbered at this point
 3874     # restore ed
 3875     89/<- %edx 4/r32/esp
 3876     (flush _test-output-buffered-file)
 3877     (flush _test-error-buffered-file)
 3878 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3884     # check output
 3885     (check-stream-equal _test-output-stream  ""  "F - test-byte-values-on-stack: output should be empty")
 3886     (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")
 3887     # check that stop(1) was called
 3888     (check-ints-equal *(edx+4) 2 "F - test-byte-values-on-stack: exit status")
 3889     # don't restore from ebp
 3890     81 0/subop/add %esp 8/imm32
 3891     # . epilogue
 3892     5d/pop-to-ebp
 3893     c3/return
 3894 
 3895 # variables of type 'byte' are not allowed in esi or edi
 3896 test-byte-values-in-unsupported-registers:
 3897     # . prologue
 3898     55/push-ebp
 3899     89/<- %ebp 4/r32/esp
 3900     # setup
 3901     (clear-stream _test-input-stream)
 3902     (clear-stream $_test-input-buffered-file->buffer)
 3903     (clear-stream _test-output-stream)
 3904     (clear-stream $_test-output-buffered-file->buffer)
 3905     (clear-stream _test-error-stream)
 3906     (clear-stream $_test-error-buffered-file->buffer)
 3907     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3908     68/push 0/imm32
 3909     68/push 0/imm32
 3910     89/<- %edx 4/r32/esp
 3911     (tailor-exit-descriptor %edx 0x10)
 3912     #
 3913     (write _test-input-stream "fn foo {\n")
 3914     (write _test-input-stream "  var x/esi: byte <- copy 0\n")
 3915     (write _test-input-stream "}\n")
 3916     # convert
 3917     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3918     # registers except esp clobbered at this point
 3919     # restore ed
 3920     89/<- %edx 4/r32/esp
 3921     (flush _test-output-buffered-file)
 3922     (flush _test-error-buffered-file)
 3923 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3929     # check output
 3930     (check-stream-equal _test-output-stream  ""  "F - test-byte-values-in-unsupported-registers: output should be empty")
 3931     (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")
 3932     # check that stop(1) was called
 3933     (check-ints-equal *(edx+4) 2 "F - test-byte-values-in-unsupported-registers: exit status")
 3934     # don't restore from ebp
 3935     81 0/subop/add %esp 8/imm32
 3936     # . epilogue
 3937     5d/pop-to-ebp
 3938     c3/return
 3939 
 3940 # variables of type 'byte' _can_ be function args. They then occupy 4 bytes.
 3941 test-copy-byte-var-from-fn-arg:
 3942     # . prologue
 3943     55/push-ebp
 3944     89/<- %ebp 4/r32/esp
 3945     # setup
 3946     (clear-stream _test-input-stream)
 3947     (clear-stream $_test-input-buffered-file->buffer)
 3948     (clear-stream _test-output-stream)
 3949     (clear-stream $_test-output-buffered-file->buffer)
 3950     #
 3951     (write _test-input-stream "fn foo x: byte, y: int {\n")
 3952     (write _test-input-stream "  var a/eax: byte <- copy x\n")
 3953     (write _test-input-stream "  var b/eax: int <- copy y\n")
 3954     (write _test-input-stream "}\n")
 3955     # convert
 3956     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3957     (flush _test-output-buffered-file)
 3958 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3964     # check output
 3965     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-copy-byte-from-fn-arg/0")
 3966     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-copy-byte-from-fn-arg/1")
 3967     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-copy-byte-from-fn-arg/2")
 3968     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-copy-byte-from-fn-arg/3")
 3969     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-copy-byte-from-fn-arg/4")
 3970     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-copy-byte-from-fn-arg/5")
 3971     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-copy-byte-from-fn-arg/6")
 3972     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-copy-byte-from-fn-arg/7")
 3973     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x0000000c) 0x00000000/r32"  "F - test-copy-byte-from-fn-arg/8")
 3974     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"   "F - test-copy-byte-from-fn-arg/9")
 3975     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-copy-byte-from-fn-arg/10")
 3976     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-copy-byte-from-fn-arg/11")
 3977     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-copy-byte-from-fn-arg/12")
 3978     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-copy-byte-from-fn-arg/13")
 3979     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-copy-byte-from-fn-arg/14")
 3980     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-copy-byte-from-fn-arg/15")
 3981     # . epilogue
 3982     89/<- %esp 5/r32/ebp
 3983     5d/pop-to-ebp
 3984     c3/return
 3985 
 3986 test-convert-compare-register-with-literal:
 3987     # . prologue
 3988     55/push-ebp
 3989     89/<- %ebp 4/r32/esp
 3990     # setup
 3991     (clear-stream _test-input-stream)
 3992     (clear-stream $_test-input-buffered-file->buffer)
 3993     (clear-stream _test-output-stream)
 3994     (clear-stream $_test-output-buffered-file->buffer)
 3995     #
 3996     (write _test-input-stream "fn foo {\n")
 3997     (write _test-input-stream "  var x/ecx: int <- copy 0\n")
 3998     (write _test-input-stream "  compare x, 0\n")
 3999     (write _test-input-stream "}\n")
 4000     # convert
 4001     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4002     (flush _test-output-buffered-file)
 4003 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4009     # check output
 4010     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-compare-register-with-literal/0")
 4011     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-compare-register-with-literal/1")
 4012     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-compare-register-with-literal/2")
 4013     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-compare-register-with-literal/3")
 4014     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-compare-register-with-literal/4")
 4015     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-compare-register-with-literal/5")
 4016     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-compare-register-with-literal/6")
 4017     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-compare-register-with-literal/7")
 4018     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %ecx 0/imm32"  "F - test-convert-compare-register-with-literal/8")
 4019     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-compare-register-with-literal/9")
 4020     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-compare-register-with-literal/10")
 4021     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-compare-register-with-literal/11")
 4022     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-compare-register-with-literal/12")
 4023     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-compare-register-with-literal/13")
 4024     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-compare-register-with-literal/14")
 4025     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-compare-register-with-literal/15")
 4026     # . epilogue
 4027     89/<- %esp 5/r32/ebp
 4028     5d/pop-to-ebp
 4029     c3/return
 4030 
 4031 test-convert-compare-byte-with-literal:
 4032     # . prologue
 4033     55/push-ebp
 4034     89/<- %ebp 4/r32/esp
 4035     # setup
 4036     (clear-stream _test-input-stream)
 4037     (clear-stream $_test-input-buffered-file->buffer)
 4038     (clear-stream _test-output-stream)
 4039     (clear-stream $_test-output-buffered-file->buffer)
 4040     #
 4041     (write _test-input-stream "fn foo {\n")
 4042     (write _test-input-stream "  var x/ecx: byte <- copy 0\n")
 4043     (write _test-input-stream "  compare x, 0\n")
 4044     (write _test-input-stream "}\n")
 4045     # convert
 4046     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4047     (flush _test-output-buffered-file)
 4048 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4054     # no errors; output is identical to test-convert-compare-register-with-literal
 4055     # . epilogue
 4056     89/<- %esp 5/r32/ebp
 4057     5d/pop-to-ebp
 4058     c3/return
 4059 
 4060 test-unknown-variable:
 4061     # . prologue
 4062     55/push-ebp
 4063     89/<- %ebp 4/r32/esp
 4064     # setup
 4065     (clear-stream _test-input-stream)
 4066     (clear-stream $_test-input-buffered-file->buffer)
 4067     (clear-stream _test-output-stream)
 4068     (clear-stream $_test-output-buffered-file->buffer)
 4069     (clear-stream _test-error-stream)
 4070     (clear-stream $_test-error-buffered-file->buffer)
 4071     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 4072     68/push 0/imm32
 4073     68/push 0/imm32
 4074     89/<- %edx 4/r32/esp
 4075     (tailor-exit-descriptor %edx 0x10)
 4076     #
 4077     (write _test-input-stream "fn foo {\n")
 4078     (write _test-input-stream "  compare x, 0\n")
 4079     (write _test-input-stream "}\n")
 4080     # convert
 4081     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 4082     # registers except esp clobbered at this point
 4083     # restore ed
 4084     89/<- %edx 4/r32/esp
 4085     (flush _test-output-buffered-file)
 4086     (flush _test-error-buffered-file)
 4087 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 4093     # check output
 4094     (check-stream-equal _test-output-stream  ""  "F - test-unknown-variable: output should be empty")
 4095     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-unknown-variable: error message")
 4096     # check that stop(1) was called
 4097     (check-ints-equal *(edx+4) 2 "F - test-unknown-variable: exit status")
 4098     # don't restore from ebp
 4099     81 0/subop/add %esp 8/imm32
 4100     # . epilogue
 4101     5d/pop-to-ebp
 4102     c3/return
 4103 
 4104 test-convert-function-with-local-var-in-block:
 4105     # . prologue
 4106     55/push-ebp
 4107     89/<- %ebp 4/r32/esp
 4108     # setup
 4109     (clear-stream _test-input-stream)
 4110     (clear-stream $_test-input-buffered-file->buffer)
 4111     (clear-stream _test-output-stream)
 4112     (clear-stream $_test-output-buffered-file->buffer)
 4113     #
 4114     (write _test-input-stream "fn foo {\n")
 4115     (write _test-input-stream "  {\n")
 4116     (write _test-input-stream "    var x: int\n")
 4117     (write _test-input-stream "    increment x\n")
 4118     (write _test-input-stream "  }\n")
 4119     (write _test-input-stream "}\n")
 4120     # convert
 4121     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4122     (flush _test-output-buffered-file)
 4123 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4129     # check output
 4130     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-block/0")
 4131     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-block/1")
 4132     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-block/2")
 4133     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-block/3")
 4134     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-block/4")
 4135     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-block/5")
 4136     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-block/6")
 4137     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-local-var-in-block/7")
 4138     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-block/8")
 4139     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-local-var-in-block/9")
 4140     (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")
 4141     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-block/11")
 4142     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-local-var-in-block/12")
 4143     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-block/13")
 4144     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-block/14")
 4145     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-block/15")
 4146     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-block/16")
 4147     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-block/17")
 4148     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-block/18")
 4149     # . epilogue
 4150     89/<- %esp 5/r32/ebp
 4151     5d/pop-to-ebp
 4152     c3/return
 4153 
 4154 test-convert-function-with-local-var-in-mem-after-block:
 4155     # . prologue
 4156     55/push-ebp
 4157     89/<- %ebp 4/r32/esp
 4158     # setup
 4159     (clear-stream _test-input-stream)
 4160     (clear-stream $_test-input-buffered-file->buffer)
 4161     (clear-stream _test-output-stream)
 4162     (clear-stream $_test-output-buffered-file->buffer)
 4163     #
 4164     (write _test-input-stream "fn foo {\n")
 4165     (write _test-input-stream "  {\n")
 4166     (write _test-input-stream "    var y: int\n")
 4167     (write _test-input-stream "  }\n")
 4168     (write _test-input-stream "  var x: int\n")
 4169     (write _test-input-stream "  increment x\n")
 4170     (write _test-input-stream "}\n")
 4171     # convert
 4172     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4173     (flush _test-output-buffered-file)
 4174 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4180     # check output
 4181     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-mem-after-block/0")
 4182     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-mem-after-block/1")
 4183     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-mem-after-block/2")
 4184     (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")
 4185     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-mem-after-block/4")
 4186     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-mem-after-block/5")
 4187     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-mem-after-block/6")
 4188     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-local-var-in-mem-after-block/7")
 4189     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-mem-after-block/8")
 4190     (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")
 4191     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-mem-after-block/10")
 4192     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-local-var-in-mem-after-block/11")
 4193     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-in-mem-after-block/12")
 4194     (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")
 4195     (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")
 4196     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-mem-after-block/15")
 4197     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-mem-after-block/16")
 4198     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-mem-after-block/17")
 4199     (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")
 4200     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-mem-after-block/19")
 4201     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-mem-after-block/20")
 4202     # . epilogue
 4203     89/<- %esp 5/r32/ebp
 4204     5d/pop-to-ebp
 4205     c3/return
 4206 
 4207 test-convert-function-with-local-var-in-named-block:
 4208     # . prologue
 4209     55/push-ebp
 4210     89/<- %ebp 4/r32/esp
 4211     # setup
 4212     (clear-stream _test-input-stream)
 4213     (clear-stream $_test-input-buffered-file->buffer)
 4214     (clear-stream _test-output-stream)
 4215     (clear-stream $_test-output-buffered-file->buffer)
 4216     #
 4217     (write _test-input-stream "fn foo {\n")
 4218     (write _test-input-stream "  $bar: {\n")
 4219     (write _test-input-stream "    var x: int\n")
 4220     (write _test-input-stream "    increment x\n")
 4221     (write _test-input-stream "  }\n")
 4222     (write _test-input-stream "}\n")
 4223     # convert
 4224     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4225     (flush _test-output-buffered-file)
 4226 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4232     # check output
 4233     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-named-block/0")
 4234     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-named-block/1")
 4235     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-named-block/2")
 4236     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-named-block/3")
 4237     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-named-block/4")
 4238     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-named-block/5")
 4239     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-named-block/6")
 4240     (check-next-stream-line-equal _test-output-stream "$bar:loop:"              "F - test-convert-function-with-local-var-in-named-block/7")
 4241     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-named-block/8")
 4242     (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")
 4243     (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")
 4244     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-named-block/11")
 4245     (check-next-stream-line-equal _test-output-stream "$bar:break:"             "F - test-convert-function-with-local-var-in-named-block/12")
 4246     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-named-block/13")
 4247     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-named-block/14")
 4248     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-named-block/15")
 4249     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-named-block/16")
 4250     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-named-block/17")
 4251     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-named-block/18")
 4252     # . epilogue
 4253     89/<- %esp 5/r32/ebp
 4254     5d/pop-to-ebp
 4255     c3/return
 4256 
 4257 test-unknown-variable-in-named-block:
 4258     # . prologue
 4259     55/push-ebp
 4260     89/<- %ebp 4/r32/esp
 4261     # setup
 4262     (clear-stream _test-input-stream)
 4263     (clear-stream $_test-input-buffered-file->buffer)
 4264     (clear-stream _test-output-stream)
 4265     (clear-stream $_test-output-buffered-file->buffer)
 4266     (clear-stream _test-error-stream)
 4267     (clear-stream $_test-error-buffered-file->buffer)
 4268     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 4269     68/push 0/imm32
 4270     68/push 0/imm32
 4271     89/<- %edx 4/r32/esp
 4272     (tailor-exit-descriptor %edx 0x10)
 4273     #
 4274     (write _test-input-stream "fn foo {\n")
 4275     (write _test-input-stream "  $a: {\n")
 4276     (write _test-input-stream "    compare x, 0\n")
 4277     (write _test-input-stream "  }\n")
 4278     (write _test-input-stream "}\n")
 4279     # convert
 4280     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 4281     # registers except esp clobbered at this point
 4282     # restore ed
 4283     89/<- %edx 4/r32/esp
 4284     (flush _test-output-buffered-file)
 4285     (flush _test-error-buffered-file)
 4286 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 4292     # check output
 4293     (check-stream-equal _test-output-stream  ""  "F - test-unknown-variable-in-named-block: output should be empty")
 4294     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-unknown-variable-in-named-block: error message")
 4295     # check that stop(1) was called
 4296     (check-ints-equal *(edx+4) 2 "F - test-unknown-variable-in-named-block: exit status")
 4297     # don't restore from ebp
 4298     81 0/subop/add %esp 8/imm32
 4299     # . epilogue
 4300     5d/pop-to-ebp
 4301     c3/return
 4302 
 4303 test-always-shadow-outermost-reg-vars-in-function:
 4304     # . prologue
 4305     55/push-ebp
 4306     89/<- %ebp 4/r32/esp
 4307     # setup
 4308     (clear-stream _test-input-stream)
 4309     (clear-stream $_test-input-buffered-file->buffer)
 4310     (clear-stream _test-output-stream)
 4311     (clear-stream $_test-output-buffered-file->buffer)
 4312     #
 4313     (write _test-input-stream "fn foo {\n")
 4314     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4315     (write _test-input-stream "}\n")
 4316     # convert
 4317     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4318     (flush _test-output-buffered-file)
 4319 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4325     # check output
 4326     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-always-shadow-outermost-reg-vars-in-function/0")
 4327     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-always-shadow-outermost-reg-vars-in-function/1")
 4328     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-always-shadow-outermost-reg-vars-in-function/2")
 4329     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-always-shadow-outermost-reg-vars-in-function/3")
 4330     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-always-shadow-outermost-reg-vars-in-function/4")
 4331     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-always-shadow-outermost-reg-vars-in-function/5")
 4332     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-compare-register-with-literal/6")
 4333     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-always-shadow-outermost-reg-vars-in-function/8")
 4334     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-compare-register-with-literal/9")
 4335     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-always-shadow-outermost-reg-vars-in-function/12")
 4336     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-always-shadow-outermost-reg-vars-in-function/13")
 4337     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-always-shadow-outermost-reg-vars-in-function/14")
 4338     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-always-shadow-outermost-reg-vars-in-function/15")
 4339     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-always-shadow-outermost-reg-vars-in-function/16")
 4340     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-always-shadow-outermost-reg-vars-in-function/17")
 4341     # . epilogue
 4342     89/<- %esp 5/r32/ebp
 4343     5d/pop-to-ebp
 4344     c3/return
 4345 
 4346 test-shadow-local:
 4347     # . prologue
 4348     55/push-ebp
 4349     89/<- %ebp 4/r32/esp
 4350     # setup
 4351     (clear-stream _test-input-stream)
 4352     (clear-stream $_test-input-buffered-file->buffer)
 4353     (clear-stream _test-output-stream)
 4354     (clear-stream $_test-output-buffered-file->buffer)
 4355     #
 4356     (write _test-input-stream "fn foo {\n")
 4357     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4358     (write _test-input-stream "  {\n")
 4359     (write _test-input-stream "    var y/ecx: int <- copy 4\n")
 4360     (write _test-input-stream "  }\n")
 4361     (write _test-input-stream "  x <- increment\n")
 4362     (write _test-input-stream "}\n")
 4363     # convert
 4364     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4365     (flush _test-output-buffered-file)
 4366 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4372     # check output
 4373     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-local/0")
 4374     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-local/1")
 4375     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-local/2")
 4376     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-local/3")
 4377     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-local/4")
 4378     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-local/5")
 4379     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-local/6")
 4380     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-local/7")
 4381     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-local/8")
 4382     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-local/9")
 4383     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %ecx"  "F - test-shadow-local/10")
 4384     (check-next-stream-line-equal _test-output-stream "      b9/copy-to-ecx 4/imm32"  "F - test-shadow-local/11")
 4385     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %ecx" "F - test-shadow-local/12")
 4386     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-local/13")
 4387     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-local/14")
 4388     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-local/15")
 4389     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-local/16")
 4390     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-local/17")
 4391     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-local/18")
 4392     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-local/19")
 4393     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-local/20")
 4394     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-local/21")
 4395     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-local/22")
 4396     # . epilogue
 4397     89/<- %esp 5/r32/ebp
 4398     5d/pop-to-ebp
 4399     c3/return
 4400 
 4401 test-shadow-name:
 4402     # . prologue
 4403     55/push-ebp
 4404     89/<- %ebp 4/r32/esp
 4405     # setup
 4406     (clear-stream _test-input-stream)
 4407     (clear-stream $_test-input-buffered-file->buffer)
 4408     (clear-stream _test-output-stream)
 4409     (clear-stream $_test-output-buffered-file->buffer)
 4410     #
 4411     (write _test-input-stream "fn foo {\n")
 4412     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4413     (write _test-input-stream "  {\n")
 4414     (write _test-input-stream "    var x/edx: int <- copy 4\n")
 4415     (write _test-input-stream "  }\n")
 4416     (write _test-input-stream "  x <- increment\n")
 4417     (write _test-input-stream "}\n")
 4418     # convert
 4419     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4420     (flush _test-output-buffered-file)
 4421 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4427     # check output
 4428     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-name/0")
 4429     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-name/1")
 4430     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-name/2")
 4431     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-name/3")
 4432     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-name/4")
 4433     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-name/5")
 4434     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-name/6")
 4435     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-name/7")
 4436     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-name/8")
 4437     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-name/9")
 4438     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %edx"  "F - test-shadow-name/10")
 4439     (check-next-stream-line-equal _test-output-stream "      ba/copy-to-edx 4/imm32"  "F - test-shadow-name/11")
 4440     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %edx" "F - test-shadow-name/12")
 4441     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-name/13")
 4442     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-name/14")
 4443     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-name/15")
 4444     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-name/16")
 4445     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-name/17")
 4446     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-name/18")
 4447     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-name/19")
 4448     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-name/20")
 4449     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-name/21")
 4450     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-name/22")
 4451     # . epilogue
 4452     89/<- %esp 5/r32/ebp
 4453     5d/pop-to-ebp
 4454     c3/return
 4455 
 4456 test-shadow-name-2:
 4457     # . prologue
 4458     55/push-ebp
 4459     89/<- %ebp 4/r32/esp
 4460     # setup
 4461     (clear-stream _test-input-stream)
 4462     (clear-stream $_test-input-buffered-file->buffer)
 4463     (clear-stream _test-output-stream)
 4464     (clear-stream $_test-output-buffered-file->buffer)
 4465     #
 4466     (write _test-input-stream "fn foo {\n")
 4467     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4468     (write _test-input-stream "  {\n")
 4469     (write _test-input-stream "    var x/edx: int <- copy 4\n")
 4470     (write _test-input-stream "    var y/ecx: int <- copy 5\n")
 4471     (write _test-input-stream "  }\n")
 4472     (write _test-input-stream "  x <- increment\n")
 4473     (write _test-input-stream "}\n")
 4474     # convert
 4475     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4476     (flush _test-output-buffered-file)
 4477 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4483     # check output
 4484     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-name-2/0")
 4485     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-name-2/1")
 4486     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-name-2/2")
 4487     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-name-2/3")
 4488     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-name-2/4")
 4489     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-name-2/5")
 4490     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-name-2/6")
 4491     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-name-2/7")
 4492     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-name-2/8")
 4493     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-name-2/9")
 4494     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %edx"  "F - test-shadow-name-2/10")
 4495     (check-next-stream-line-equal _test-output-stream "      ba/copy-to-edx 4/imm32"  "F - test-shadow-name-2/11")
 4496     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %ecx"  "F - test-shadow-name-2/12")
 4497     (check-next-stream-line-equal _test-output-stream "      b9/copy-to-ecx 5/imm32"  "F - test-shadow-name-2/13")
 4498     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %ecx" "F - test-shadow-name-2/14")
 4499     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %edx" "F - test-shadow-name-2/15")
 4500     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-name-2/16")
 4501     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-name-2/17")
 4502     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-name-2/18")
 4503     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-name-2/19")
 4504     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-name-2/20")
 4505     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-name-2/21")
 4506     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-name-2/22")
 4507     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-name-2/23")
 4508     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-name-2/24")
 4509     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-name-2/25")
 4510     # . epilogue
 4511     89/<- %esp 5/r32/ebp
 4512     5d/pop-to-ebp
 4513     c3/return
 4514 
 4515 test-do-not-spill-same-register-in-block:
 4516     # . prologue
 4517     55/push-ebp
 4518     89/<- %ebp 4/r32/esp
 4519     # setup
 4520     (clear-stream _test-input-stream)
 4521     (clear-stream $_test-input-buffered-file->buffer)
 4522     (clear-stream _test-output-stream)
 4523     (clear-stream $_test-output-buffered-file->buffer)
 4524     #
 4525     (write _test-input-stream "fn foo {\n")
 4526     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4527     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 4528     (write _test-input-stream "  y <- increment\n")
 4529     (write _test-input-stream "}\n")
 4530     # convert
 4531     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4532     (flush _test-output-buffered-file)
 4533 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4539     # check output
 4540     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-do-not-spill-same-register-in-block/0")
 4541     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-do-not-spill-same-register-in-block/1")
 4542     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-do-not-spill-same-register-in-block/2")
 4543     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-do-not-spill-same-register-in-block/3")
 4544     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-do-not-spill-same-register-in-block/4")
 4545     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-do-not-spill-same-register-in-block/5")
 4546     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-do-not-spill-same-register-in-block/6")
 4547     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-do-not-spill-same-register-in-block/7")
 4548     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-do-not-spill-same-register-in-block/8")
 4549     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-do-not-spill-same-register-in-block/9")
 4550     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-do-not-spill-same-register-in-block/10")
 4551     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-do-not-spill-same-register-in-block/11")
 4552     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-do-not-spill-same-register-in-block/12")
 4553     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-do-not-spill-same-register-in-block/13")
 4554     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-do-not-spill-same-register-in-block/14")
 4555     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-do-not-spill-same-register-in-block/15")
 4556     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-do-not-spill-same-register-in-block/16")
 4557     # . epilogue
 4558     89/<- %esp 5/r32/ebp
 4559     5d/pop-to-ebp
 4560     c3/return
 4561 
 4562 test-spill-different-register-in-block:
 4563     # . prologue
 4564     55/push-ebp
 4565     89/<- %ebp 4/r32/esp
 4566     # setup
 4567     (clear-stream _test-input-stream)
 4568     (clear-stream $_test-input-buffered-file->buffer)
 4569     (clear-stream _test-output-stream)
 4570     (clear-stream $_test-output-buffered-file->buffer)
 4571     #
 4572     (write _test-input-stream "fn foo {\n")
 4573     (write _test-input-stream "  var x/eax: int <- copy 3\n")
 4574     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 4575     (write _test-input-stream "  y <- increment\n")
 4576     (write _test-input-stream "}\n")
 4577     # convert
 4578     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4579     (flush _test-output-buffered-file)
 4580 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4586     # check output
 4587     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-spill-different-register-in-block/0")
 4588     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-spill-different-register-in-block/1")
 4589     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-spill-different-register-in-block/2")
 4590     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-spill-different-register-in-block/3")
 4591     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-spill-different-register-in-block/4")
 4592     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-spill-different-register-in-block/5")
 4593     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-spill-different-register-in-block/6")
 4594     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-spill-different-register-in-block/7")
 4595     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-spill-different-register-in-block/8")
 4596     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-spill-different-register-in-block/9")
 4597     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-spill-different-register-in-block/10")
 4598     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-spill-different-register-in-block/11")
 4599     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-spill-different-register-in-block/12")
 4600     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-spill-different-register-in-block/13")
 4601     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-spill-different-register-in-block/14")
 4602     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-spill-different-register-in-block/15")
 4603     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-spill-different-register-in-block/16")
 4604     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-spill-different-register-in-block/17")
 4605     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-spill-different-register-in-block/18")
 4606     # . epilogue
 4607     89/<- %esp 5/r32/ebp
 4608     5d/pop-to-ebp
 4609     c3/return
 4610 
 4611 test-convert-function-with-branches-in-block:
 4612     # . prologue
 4613     55/push-ebp
 4614     89/<- %ebp 4/r32/esp
 4615     # setup
 4616     (clear-stream _test-input-stream)
 4617     (clear-stream $_test-input-buffered-file->buffer)
 4618     (clear-stream _test-output-stream)
 4619     (clear-stream $_test-output-buffered-file->buffer)
 4620     #
 4621     (write _test-input-stream "fn foo x: int {\n")
 4622     (write _test-input-stream "  {\n")
 4623     (write _test-input-stream "    break-if->=\n")
 4624     (write _test-input-stream "    loop-if-addr<\n")
 4625     (write _test-input-stream "    increment x\n")
 4626     (write _test-input-stream "    loop\n")
 4627     (write _test-input-stream "  }\n")
 4628     (write _test-input-stream "}\n")
 4629     # convert
 4630     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4631     (flush _test-output-buffered-file)
 4632 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4638     # check output
 4639     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-block/0")
 4640     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-block/1")
 4641     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-block/2")
 4642     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-block/3")
 4643     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-block/4")
 4644     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-block/5")
 4645     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-block/6")
 4646     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-in-block/7")
 4647     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/8")
 4648     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-block/9")
 4649     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-in-block/10")
 4650     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/11")
 4651     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/12")
 4652     (check-next-stream-line-equal _test-output-stream "        0f 83/jump-if-addr>= break/disp32"  "F - test-convert-function-with-branches-in-block/13")
 4653     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:loop/disp32"  "F - test-convert-function-with-branches-in-block/14")
 4654     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/15")
 4655     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-block/16")
 4656     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-in-block/17")
 4657     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-block/18")
 4658     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-in-block/19")
 4659     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-block/20")
 4660     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-block/21")
 4661     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-block/22")
 4662     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-block/23")
 4663     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-block/24")
 4664     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-block/25")
 4665     # . epilogue
 4666     89/<- %esp 5/r32/ebp
 4667     5d/pop-to-ebp
 4668     c3/return
 4669 
 4670 test-convert-function-with-branches-in-block-2:
 4671     # . prologue
 4672     55/push-ebp
 4673     89/<- %ebp 4/r32/esp
 4674     # setup
 4675     (clear-stream _test-input-stream)
 4676     (clear-stream $_test-input-buffered-file->buffer)
 4677     (clear-stream _test-output-stream)
 4678     (clear-stream $_test-output-buffered-file->buffer)
 4679     #
 4680     (write _test-input-stream "fn foo x: int {\n")
 4681     (write _test-input-stream "  {\n")
 4682     (write _test-input-stream "    break-if->=\n")
 4683     (write _test-input-stream "    loop-if-float<\n")
 4684     (write _test-input-stream "    increment x\n")
 4685     (write _test-input-stream "    loop\n")
 4686     (write _test-input-stream "  }\n")
 4687     (write _test-input-stream "}\n")
 4688     # convert
 4689     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4690     (flush _test-output-buffered-file)
 4691 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4697     # check output
 4698     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-block/0")
 4699     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-block/1")
 4700     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-block/2")
 4701     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-block/3")
 4702     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-block/4")
 4703     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-block/5")
 4704     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-block/6")
 4705     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-in-block/7")
 4706     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/8")
 4707     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-block/9")
 4708     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-in-block/10")
 4709     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/11")
 4710     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/12")
 4711     (check-next-stream-line-equal _test-output-stream "        0f 83/jump-if-addr>= break/disp32"  "F - test-convert-function-with-branches-in-block/13")
 4712     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:loop/disp32"  "F - test-convert-function-with-branches-in-block/14")
 4713     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/15")
 4714     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-block/16")
 4715     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-in-block/17")
 4716     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-block/18")
 4717     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-in-block/19")
 4718     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-block/20")
 4719     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-block/21")
 4720     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-block/22")
 4721     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-block/23")
 4722     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-block/24")
 4723     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-block/25")
 4724     # . epilogue
 4725     89/<- %esp 5/r32/ebp
 4726     5d/pop-to-ebp
 4727     c3/return
 4728 
 4729 test-convert-function-with-branches-in-named-block:
 4730     # . prologue
 4731     55/push-ebp
 4732     89/<- %ebp 4/r32/esp
 4733     # setup
 4734     (clear-stream _test-input-stream)
 4735     (clear-stream $_test-input-buffered-file->buffer)
 4736     (clear-stream _test-output-stream)
 4737     (clear-stream $_test-output-buffered-file->buffer)
 4738     #
 4739     (write _test-input-stream "fn foo x: int {\n")
 4740     (write _test-input-stream "  $bar: {\n")
 4741     (write _test-input-stream "    break-if->= $bar\n")
 4742     (write _test-input-stream "    loop-if-addr< $bar\n")
 4743     (write _test-input-stream "    increment x\n")
 4744     (write _test-input-stream "    loop\n")
 4745     (write _test-input-stream "  }\n")
 4746     (write _test-input-stream "}\n")
 4747     # convert
 4748     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4749     (flush _test-output-buffered-file)
 4750 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4756     # check output
 4757     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-named-block/0")
 4758     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-named-block/1")
 4759     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-named-block/2")
 4760     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-named-block/3")
 4761     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-named-block/4")
 4762     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-named-block/5")
 4763     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-named-block/6")
 4764     (check-next-stream-line-equal _test-output-stream "$bar:loop:"              "F - test-convert-function-with-branches-in-named-block/7")
 4765     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-named-block/8")
 4766     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-named-block/9")
 4767     (check-next-stream-line-equal _test-output-stream "        e9/jump $bar:break/disp32"  "F - test-convert-function-with-branches-in-named-block/10")
 4768     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-named-block/11")
 4769     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-named-block/12")
 4770     (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")
 4771     (check-next-stream-line-equal _test-output-stream "        e9/jump $bar:loop/disp32"  "F - test-convert-function-with-branches-in-named-block/14")
 4772     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-named-block/15")
 4773     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-named-block/16")
 4774     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"   "F - test-convert-function-with-branches-in-named-block/17")
 4775     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-named-block/18")
 4776     (check-next-stream-line-equal _test-output-stream "$bar:break:"             "F - test-convert-function-with-branches-in-named-block/19")
 4777     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-named-block/20")
 4778     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-named-block/21")
 4779     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-named-block/22")
 4780     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-named-block/23")
 4781     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-named-block/24")
 4782     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-named-block/25")
 4783     # . epilogue
 4784     89/<- %esp 5/r32/ebp
 4785     5d/pop-to-ebp
 4786     c3/return
 4787 
 4788 test-convert-function-with-var-in-nested-block:
 4789     # . prologue
 4790     55/push-ebp
 4791     89/<- %ebp 4/r32/esp
 4792     # setup
 4793     (clear-stream _test-input-stream)
 4794     (clear-stream $_test-input-buffered-file->buffer)
 4795     (clear-stream _test-output-stream)
 4796     (clear-stream $_test-output-buffered-file->buffer)
 4797     #
 4798     (write _test-input-stream "fn foo x: int {\n")
 4799     (write _test-input-stream "  {\n")
 4800     (write _test-input-stream "    {\n")
 4801     (write _test-input-stream "      var x: int\n")
 4802     (write _test-input-stream "      increment x\n")
 4803     (write _test-input-stream "    }\n")
 4804     (write _test-input-stream "  }\n")
 4805     (write _test-input-stream "}\n")
 4806     # convert
 4807     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4808     (flush _test-output-buffered-file)
 4809 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4815     # check output
 4816     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-var-in-nested-block/0")
 4817     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-var-in-nested-block/1")
 4818     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-var-in-nested-block/2")
 4819     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-var-in-nested-block/3")
 4820     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-var-in-nested-block/4")
 4821     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-var-in-nested-block/5")
 4822     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-var-in-nested-block/6")
 4823     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-var-in-nested-block/7")
 4824     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-var-in-nested-block/8")
 4825     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-var-in-nested-block/9")
 4826     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-var-in-nested-block/10")
 4827     (check-next-stream-line-equal _test-output-stream "        ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-var-in-nested-block/11")
 4828     (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")
 4829     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-var-in-nested-block/13")
 4830     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-var-in-nested-block/14")
 4831     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-var-in-nested-block/15")
 4832     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-var-in-nested-block/16")
 4833     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-var-in-nested-block/17")
 4834     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-var-in-nested-block/18")
 4835     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-var-in-nested-block/19")
 4836     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-var-in-nested-block/20")
 4837     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-var-in-nested-block/21")
 4838     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-var-in-nested-block/22")
 4839     # . epilogue
 4840     89/<- %esp 5/r32/ebp
 4841     5d/pop-to-ebp
 4842     c3/return
 4843 
 4844 test-convert-function-with-multiple-vars-in-nested-blocks:
 4845     # . prologue
 4846     55/push-ebp
 4847     89/<- %ebp 4/r32/esp
 4848     # setup
 4849     (clear-stream _test-input-stream)
 4850     (clear-stream $_test-input-buffered-file->buffer)
 4851     (clear-stream _test-output-stream)
 4852     (clear-stream $_test-output-buffered-file->buffer)
 4853     #
 4854     (write _test-input-stream "fn foo x: int {\n")
 4855     (write _test-input-stream "  {\n")
 4856     (write _test-input-stream "    var x/eax: int <- copy 0\n")
 4857     (write _test-input-stream "    {\n")
 4858     (write _test-input-stream "      var y: int\n")
 4859     (write _test-input-stream "      x <- add y\n")
 4860     (write _test-input-stream "    }\n")
 4861     (write _test-input-stream "  }\n")
 4862     (write _test-input-stream "}\n")
 4863     # convert
 4864     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4865     (flush _test-output-buffered-file)
 4866 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4872     # check output
 4873     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-multiple-vars-in-nested-blocks/0")
 4874     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-multiple-vars-in-nested-blocks/1")
 4875     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-multiple-vars-in-nested-blocks/2")
 4876     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/3")
 4877     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-multiple-vars-in-nested-blocks/4")
 4878     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/5")
 4879     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-multiple-vars-in-nested-blocks/6")
 4880     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/7")
 4881     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %eax"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/8")
 4882     (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")
 4883     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-multiple-vars-in-nested-blocks/10")
 4884     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/11")
 4885     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-multiple-vars-in-nested-blocks/12")
 4886     (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")
 4887     (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")
 4888     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-multiple-vars-in-nested-blocks/15")
 4889     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/16")
 4890     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %eax"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/17")
 4891     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-multiple-vars-in-nested-blocks/18")
 4892     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/19")
 4893     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-multiple-vars-in-nested-blocks/20")
 4894     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/21")
 4895     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-multiple-vars-in-nested-blocks/22")
 4896     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/23")
 4897     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-multiple-vars-in-nested-blocks/24")
 4898     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-multiple-vars-in-nested-blocks/25")
 4899     # . epilogue
 4900     89/<- %esp 5/r32/ebp
 4901     5d/pop-to-ebp
 4902     c3/return
 4903 
 4904 test-convert-function-with-branches-and-local-vars:
 4905     # A conditional 'break' after a 'var' in a block is converted into a
 4906     # nested block that performs all necessary cleanup before jumping. This
 4907     # results in some ugly code duplication.
 4908     # . prologue
 4909     55/push-ebp
 4910     89/<- %ebp 4/r32/esp
 4911     # setup
 4912     (clear-stream _test-input-stream)
 4913     (clear-stream $_test-input-buffered-file->buffer)
 4914     (clear-stream _test-output-stream)
 4915     (clear-stream $_test-output-buffered-file->buffer)
 4916     #
 4917     (write _test-input-stream "fn foo {\n")
 4918     (write _test-input-stream "  {\n")
 4919     (write _test-input-stream "    var x: int\n")
 4920     (write _test-input-stream "    break-if->=\n")
 4921     (write _test-input-stream "    increment x\n")
 4922     (write _test-input-stream "  }\n")
 4923     (write _test-input-stream "}\n")
 4924     # convert
 4925     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4926     (flush _test-output-buffered-file)
 4927 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4933     # check output
 4934     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-and-local-vars/0")
 4935     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-and-local-vars/1")
 4936     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-and-local-vars/2")
 4937     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-and-local-vars/3")
 4938     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-and-local-vars/4")
 4939     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-and-local-vars/5")
 4940     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-and-local-vars/6")
 4941     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-and-local-vars/7")
 4942     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-branches-and-local-vars/8")
 4943     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-and-local-vars/9")
 4944     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-and-local-vars/10")
 4945     (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")
 4946     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-and-local-vars/12")
 4947     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-and-local-vars/13")
 4948     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-branches-and-local-vars/14")
 4949     (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")
 4950     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-and-local-vars/16")
 4951     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-and-local-vars/17")
 4952     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-and-local-vars/18")
 4953     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-and-local-vars/19")
 4954     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-and-local-vars/20")
 4955     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-and-local-vars/21")
 4956     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-and-local-vars/22")
 4957     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-and-local-vars/23")
 4958     # . epilogue
 4959     89/<- %esp 5/r32/ebp
 4960     5d/pop-to-ebp
 4961     c3/return
 4962 
 4963 test-convert-function-with-conditional-loops-and-local-vars:
 4964     # A conditional 'loop' after a 'var' in a block is converted into a nested
 4965     # block that performs all necessary cleanup before jumping. This results
 4966     # in some ugly code duplication.
 4967     # . prologue
 4968     55/push-ebp
 4969     89/<- %ebp 4/r32/esp
 4970     # setup
 4971     (clear-stream _test-input-stream)
 4972     (clear-stream $_test-input-buffered-file->buffer)
 4973     (clear-stream _test-output-stream)
 4974     (clear-stream $_test-output-buffered-file->buffer)
 4975     #
 4976     (write _test-input-stream "fn foo {\n")
 4977     (write _test-input-stream "  {\n")
 4978     (write _test-input-stream "    var x: int\n")
 4979     (write _test-input-stream "    loop-if->=\n")
 4980     (write _test-input-stream "    increment x\n")
 4981     (write _test-input-stream "  }\n")
 4982     (write _test-input-stream "}\n")
 4983     # convert
 4984     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4985     (flush _test-output-buffered-file)
 4986 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4992     # check output
 4993     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-conditional-loops-and-local-vars/0")
 4994     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-conditional-loops-and-local-vars/1")
 4995     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-conditional-loops-and-local-vars/2")
 4996     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-conditional-loops-and-local-vars/3")
 4997     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-conditional-loops-and-local-vars/4")
 4998     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-conditional-loops-and-local-vars/5")
 4999     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-conditional-loops-and-local-vars/6")
 5000     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-conditional-loops-and-local-vars/7")
 5001     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-conditional-loops-and-local-vars/8")
 5002     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-conditional-loops-and-local-vars/9")
 5003     (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")
 5004     (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")
 5005     (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")
 5006     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-conditional-loops-and-local-vars/13")
 5007     (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")
 5008     (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")
 5009     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-conditional-loops-and-local-vars/16")
 5010     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-conditional-loops-and-local-vars/17")
 5011     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-conditional-loops-and-local-vars/18")
 5012     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-conditional-loops-and-local-vars/19")
 5013     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-conditional-loops-and-local-vars/20")
 5014     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-conditional-loops-and-local-vars/21")
 5015     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-conditional-loops-and-local-vars/22")
 5016     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-conditional-loops-and-local-vars/23")
 5017     # . epilogue
 5018     89/<- %esp 5/r32/ebp
 5019     5d/pop-to-ebp
 5020     c3/return
 5021 
 5022 test-convert-function-with-unconditional-loops-and-local-vars:
 5023     # An unconditional 'loop' after a 'var' in a block is emitted _after_ the
 5024     # regular block cleanup. Any instructions after 'loop' are dead and
 5025     # therefore skipped.
 5026     # . prologue
 5027     55/push-ebp
 5028     89/<- %ebp 4/r32/esp
 5029     # setup
 5030     (clear-stream _test-input-stream)
 5031     (clear-stream $_test-input-buffered-file->buffer)
 5032     (clear-stream _test-output-stream)
 5033     (clear-stream $_test-output-buffered-file->buffer)
 5034     #
 5035     (write _test-input-stream "fn foo {\n")
 5036     (write _test-input-stream "  {\n")
 5037     (write _test-input-stream "    var x: int\n")
 5038     (write _test-input-stream "    loop\n")
 5039     (write _test-input-stream "    increment x\n")
 5040     (write _test-input-stream "  }\n")
 5041     (write _test-input-stream "}\n")
 5042     # convert
 5043     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5044     (flush _test-output-buffered-file)
 5045 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5051     # check output
 5052     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-unconditional-loops-and-local-vars/0")
 5053     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-unconditional-loops-and-local-vars/1")
 5054     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-unconditional-loops-and-local-vars/2")
 5055     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-unconditional-loops-and-local-vars/3")
 5056     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-unconditional-loops-and-local-vars/4")
 5057     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-unconditional-loops-and-local-vars/5")
 5058     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-unconditional-loops-and-local-vars/6")
 5059     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-unconditional-loops-and-local-vars/7")
 5060     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-unconditional-loops-and-local-vars/8")
 5061     (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")
 5062     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-unconditional-loops-and-local-vars/10")
 5063     # not emitted:                                           ff 0/subop/increment *(ebp+0xfffffffc)
 5064     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-unconditional-loops-and-local-vars/11")
 5065     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-unconditional-loops-and-local-vars/12")
 5066     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-unconditional-loops-and-local-vars/13")
 5067     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-unconditional-loops-and-local-vars/14")
 5068     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-unconditional-loops-and-local-vars/15")
 5069     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-unconditional-loops-and-local-vars/16")
 5070     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-unconditional-loops-and-local-vars/17")
 5071     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-unconditional-loops-and-local-vars/18")
 5072     # . epilogue
 5073     89/<- %esp 5/r32/ebp
 5074     5d/pop-to-ebp
 5075     c3/return
 5076 
 5077 test-convert-function-with-branches-and-loops-and-local-vars:
 5078     # . prologue
 5079     55/push-ebp
 5080     89/<- %ebp 4/r32/esp
 5081     # setup
 5082     (clear-stream _test-input-stream)
 5083     (clear-stream $_test-input-buffered-file->buffer)
 5084     (clear-stream _test-output-stream)
 5085     (clear-stream $_test-output-buffered-file->buffer)
 5086     #
 5087     (write _test-input-stream "fn foo {\n")
 5088     (write _test-input-stream "  {\n")
 5089     (write _test-input-stream "    var x: int\n")
 5090     (write _test-input-stream "    break-if->=\n")
 5091     (write _test-input-stream "    increment x\n")
 5092     (write _test-input-stream "    loop\n")
 5093     (write _test-input-stream "  }\n")
 5094     (write _test-input-stream "}\n")
 5095     # convert
 5096     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5097     (flush _test-output-buffered-file)
 5098 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5104     # check output
 5105     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-and-loops-and-local-vars/0")
 5106     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-and-loops-and-local-vars/1")
 5107     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-and-loops-and-local-vars/2")
 5108     (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")
 5109     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-and-loops-and-local-vars/4")
 5110     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-and-loops-and-local-vars/5")
 5111     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-and-loops-and-local-vars/6")
 5112     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-and-loops-and-local-vars/7")
 5113     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-branches-and-loops-and-local-vars/8")
 5114     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-and-loops-and-local-vars/9")
 5115     (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")
 5116     (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")
 5117     (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")
 5118     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-and-loops-and-local-vars/13")
 5119     (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")
 5120     (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")
 5121     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-and-loops-and-local-vars/16")
 5122     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-and-loops-and-local-vars/17")
 5123     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-and-loops-and-local-vars/18")
 5124     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-and-loops-and-local-vars/19")
 5125     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-and-loops-and-local-vars/20")
 5126     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-and-loops-and-local-vars/21")
 5127     (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")
 5128     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-and-loops-and-local-vars/23")
 5129     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-and-loops-and-local-vars/24")
 5130     # . epilogue
 5131     89/<- %esp 5/r32/ebp
 5132     5d/pop-to-ebp
 5133     c3/return
 5134 
 5135 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars:
 5136     # . prologue
 5137     55/push-ebp
 5138     89/<- %ebp 4/r32/esp
 5139     # setup
 5140     (clear-stream _test-input-stream)
 5141     (clear-stream $_test-input-buffered-file->buffer)
 5142     (clear-stream _test-output-stream)
 5143     (clear-stream $_test-output-buffered-file->buffer)
 5144     #
 5145     (write _test-input-stream "fn foo {\n")
 5146     (write _test-input-stream "  a: {\n")
 5147     (write _test-input-stream "    var x: int\n")
 5148     (write _test-input-stream "    {\n")
 5149     (write _test-input-stream "      var y: int\n")
 5150     (write _test-input-stream "      break-if->= a\n")
 5151     (write _test-input-stream "      increment x\n")
 5152     (write _test-input-stream "      loop\n")
 5153     (write _test-input-stream "    }\n")
 5154     (write _test-input-stream "  }\n")
 5155     (write _test-input-stream "}\n")
 5156     # convert
 5157     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5158     (flush _test-output-buffered-file)
 5159 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5165     # check output
 5166     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/0")
 5167     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/1")
 5168     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/2")
 5169     (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")
 5170     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/4")
 5171     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/5")
 5172     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/6")
 5173     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/7")
 5174     (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")
 5175     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/9")
 5176     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/10")
 5177     (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")
 5178     (check-next-stream-line-equal _test-output-stream "        {"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/12")
 5179     (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")
 5180     (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")
 5181     (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")
 5182     (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")
 5183     (check-next-stream-line-equal _test-output-stream "        }"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/17")
 5184     (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")
 5185     (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")
 5186     (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")
 5187     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/21")
 5188     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/22")
 5189     (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")
 5190     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/24")
 5191     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/25")
 5192     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/26")
 5193     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/27")
 5194     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/28")
 5195     (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")
 5196     (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")
 5197     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/31")
 5198     # . epilogue
 5199     89/<- %esp 5/r32/ebp
 5200     5d/pop-to-ebp
 5201     c3/return
 5202 
 5203 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2:
 5204     # . prologue
 5205     55/push-ebp
 5206     89/<- %ebp 4/r32/esp
 5207     # setup
 5208     (clear-stream _test-input-stream)
 5209     (clear-stream $_test-input-buffered-file->buffer)
 5210     (clear-stream _test-output-stream)
 5211     (clear-stream $_test-output-buffered-file->buffer)
 5212     # non-local conditional branch from a block without a local variable,
 5213     # unwinding a local on the stack
 5214     (write _test-input-stream "fn foo {\n")
 5215     (write _test-input-stream "  a: {\n")
 5216     (write _test-input-stream "    var x: int\n")
 5217     (write _test-input-stream "    {\n")
 5218     (write _test-input-stream "      break-if->= a\n")
 5219     (write _test-input-stream "    }\n")
 5220     (write _test-input-stream "  }\n")
 5221     (write _test-input-stream "}\n")
 5222     # convert
 5223     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5224     (flush _test-output-buffered-file)
 5225 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5231     # check output
 5232     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/0")
 5233     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/1")
 5234     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/2")
 5235     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/3")
 5236     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/4")
 5237     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/5")
 5238     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/6")
 5239     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/7")
 5240     (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")
 5241     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/9")
 5242     (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")
 5243     (check-next-stream-line-equal _test-output-stream "        {"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/11")
 5244     (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")
 5245     (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")
 5246     (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")
 5247     (check-next-stream-line-equal _test-output-stream "        }"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/15")
 5248     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/16")
 5249     (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")
 5250     (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")
 5251     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/19")
 5252     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/20")
 5253     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/21")
 5254     (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")
 5255     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/23")
 5256     (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")
 5257     (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")
 5258     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/26")
 5259     # . epilogue
 5260     89/<- %esp 5/r32/ebp
 5261     5d/pop-to-ebp
 5262     c3/return
 5263 
 5264 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3:
 5265     # . prologue
 5266     55/push-ebp
 5267     89/<- %ebp 4/r32/esp
 5268     # setup
 5269     (clear-stream _test-input-stream)
 5270     (clear-stream $_test-input-buffered-file->buffer)
 5271     (clear-stream _test-output-stream)
 5272     (clear-stream $_test-output-buffered-file->buffer)
 5273     # non-local unconditional branch from a block without a local variable,
 5274     # unwinding a local on the stack
 5275     (write _test-input-stream "fn foo {\n")
 5276     (write _test-input-stream "  a: {\n")
 5277     (write _test-input-stream "    var x: int\n")
 5278     (write _test-input-stream "    {\n")
 5279     (write _test-input-stream "      break a\n")
 5280     (write _test-input-stream "    }\n")
 5281     (write _test-input-stream "  }\n")
 5282     (write _test-input-stream "}\n")
 5283     # convert
 5284     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5285     (flush _test-output-buffered-file)
 5286 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5292     # check output
 5293     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/0")
 5294     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/1")
 5295     (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")
 5296     (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")
 5297     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/4")
 5298     (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")
 5299     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/6")
 5300     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/7")
 5301     (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")
 5302     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/9")
 5303     (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")
 5304     (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")
 5305     (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")
 5306     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/14")
 5307     (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")
 5308     (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")
 5309     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/17")
 5310     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/18")
 5311     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/19")
 5312     (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")
 5313     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/21")
 5314     (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")
 5315     (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")
 5316     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/24")
 5317     # . epilogue
 5318     89/<- %esp 5/r32/ebp
 5319     5d/pop-to-ebp
 5320     c3/return
 5321 
 5322 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4:
 5323     # . prologue
 5324     55/push-ebp
 5325     89/<- %ebp 4/r32/esp
 5326     # setup
 5327     (clear-stream _test-input-stream)
 5328     (clear-stream $_test-input-buffered-file->buffer)
 5329     (clear-stream _test-output-stream)
 5330     (clear-stream $_test-output-buffered-file->buffer)
 5331     #
 5332     (write _test-input-stream "fn foo {\n")
 5333     (write _test-input-stream "  a: {\n")
 5334     (write _test-input-stream "    var x/esi: int <- copy 0\n")
 5335     (write _test-input-stream "    {\n")
 5336     (write _test-input-stream "      break a\n")
 5337     (write _test-input-stream "    }\n")
 5338     (write _test-input-stream "  }\n")
 5339     (write _test-input-stream "}\n")
 5340     # convert
 5341     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5342     (flush _test-output-buffered-file)
 5343 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5349     # check output
 5350     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/0")
 5351     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/1")
 5352     (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")
 5353     (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")
 5354     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/4")
 5355     (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")
 5356     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/6")
 5357     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/7")
 5358     (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")
 5359     (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")
 5360     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/10")
 5361     (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")
 5362     (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")
 5363     (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")
 5364     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/14")
 5365     (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")
 5366     (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")
 5367     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/17")
 5368     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/18")
 5369     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/19")
 5370     (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")
 5371     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/21")
 5372     (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")
 5373     (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")
 5374     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/24")
 5375     # . epilogue
 5376     89/<- %esp 5/r32/ebp
 5377     5d/pop-to-ebp
 5378     c3/return
 5379 
 5380 test-convert-function-with-nonlocal-unconditional-break-and-local-vars:
 5381     # . prologue
 5382     55/push-ebp
 5383     89/<- %ebp 4/r32/esp
 5384     # setup
 5385     (clear-stream _test-input-stream)
 5386     (clear-stream $_test-input-buffered-file->buffer)
 5387     (clear-stream _test-output-stream)
 5388     (clear-stream $_test-output-buffered-file->buffer)
 5389     #
 5390     (write _test-input-stream "fn foo {\n")
 5391     (write _test-input-stream "  a: {\n")
 5392     (write _test-input-stream "    var x: int\n")
 5393     (write _test-input-stream "    {\n")
 5394     (write _test-input-stream "      var y: int\n")
 5395     (write _test-input-stream "      break a\n")
 5396     (write _test-input-stream "      increment x\n")
 5397     (write _test-input-stream "    }\n")
 5398     (write _test-input-stream "  }\n")
 5399     (write _test-input-stream "}\n")
 5400     # convert
 5401     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5402     (flush _test-output-buffered-file)
 5403 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5409     # check output
 5410     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/0")
 5411     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/1")
 5412     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/2")
 5413     (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")
 5414     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/4")
 5415     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/5")
 5416     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/6")
 5417     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/7")
 5418     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/8")
 5419     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/9")
 5420     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/10")
 5421     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/11")
 5422     (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")
 5423     (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")
 5424     (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")
 5425     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/15")
 5426     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/16")
 5427     (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")
 5428     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/18")
 5429     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/19")
 5430     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/20")
 5431     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/21")
 5432     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/22")
 5433     (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")
 5434     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/24")
 5435     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/25")
 5436     # . epilogue
 5437     89/<- %esp 5/r32/ebp
 5438     5d/pop-to-ebp
 5439     c3/return
 5440 
 5441 test-convert-function-with-unconditional-break-and-local-vars:
 5442     # . prologue
 5443     55/push-ebp
 5444     89/<- %ebp 4/r32/esp
 5445     # setup
 5446     (clear-stream _test-input-stream)
 5447     (clear-stream $_test-input-buffered-file->buffer)
 5448     (clear-stream _test-output-stream)
 5449     (clear-stream $_test-output-buffered-file->buffer)
 5450     #
 5451     (write _test-input-stream "fn foo {\n")
 5452     (write _test-input-stream "  {\n")
 5453     (write _test-input-stream "    var x: int\n")
 5454     (write _test-input-stream "    {\n")
 5455     (write _test-input-stream "      var y: int\n")
 5456     (write _test-input-stream "      break\n")
 5457     (write _test-input-stream "      increment x\n")
 5458     (write _test-input-stream "    }\n")
 5459     (write _test-input-stream "  }\n")
 5460     (write _test-input-stream "}\n")
 5461     # convert
 5462     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5463     (flush _test-output-buffered-file)
 5464 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5470     # check output
 5471     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-unconditional-break-and-local-vars/0")
 5472     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-unconditional-break-and-local-vars/1")
 5473     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-unconditional-break-and-local-vars/2")
 5474     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-unconditional-break-and-local-vars/3")
 5475     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-unconditional-break-and-local-vars/4")
 5476     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/5")
 5477     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-unconditional-break-and-local-vars/6")
 5478     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/7")
 5479     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-unconditional-break-and-local-vars/8")
 5480     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-unconditional-break-and-local-vars/9")
 5481     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/10")
 5482     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-unconditional-break-and-local-vars/11")
 5483     (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")
 5484     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-unconditional-break-and-local-vars/13")
 5485     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/14")
 5486     (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")
 5487     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-unconditional-break-and-local-vars/16")
 5488     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/17")
 5489     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-unconditional-break-and-local-vars/18")
 5490     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/19")
 5491     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-unconditional-break-and-local-vars/20")
 5492     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-unconditional-break-and-local-vars/21")
 5493     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-unconditional-break-and-local-vars/22")
 5494     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-unconditional-break-and-local-vars/23")
 5495     # . epilogue
 5496     89/<- %esp 5/r32/ebp
 5497     5d/pop-to-ebp
 5498     c3/return
 5499 
 5500 test-convert-function-with-nonlocal-unconditional-loop-and-local-vars:
 5501     # . prologue
 5502     55/push-ebp
 5503     89/<- %ebp 4/r32/esp
 5504     # setup
 5505     (clear-stream _test-input-stream)
 5506     (clear-stream $_test-input-buffered-file->buffer)
 5507     (clear-stream _test-output-stream)
 5508     (clear-stream $_test-output-buffered-file->buffer)
 5509     #
 5510     (write _test-input-stream "fn foo {\n")
 5511     (write _test-input-stream "  a: {\n")
 5512     (write _test-input-stream "    var x: int\n")
 5513     (write _test-input-stream "    {\n")
 5514     (write _test-input-stream "      var y: int\n")
 5515     (write _test-input-stream "      loop a\n")
 5516     (write _test-input-stream "      increment x\n")
 5517     (write _test-input-stream "    }\n")
 5518     (write _test-input-stream "  }\n")
 5519     (write _test-input-stream "}\n")
 5520     # convert
 5521     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5522     (flush _test-output-buffered-file)
 5523 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5529     # check output
 5530     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/0")
 5531     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/1")
 5532     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/2")
 5533     (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")
 5534     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/4")
 5535     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/5")
 5536     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/6")
 5537     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/7")
 5538     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/8")
 5539     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/9")
 5540     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/10")
 5541     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/11")
 5542     (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")
 5543     (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")
 5544     (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")
 5545     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/15")
 5546     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/16")
 5547     (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")
 5548     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/18")
 5549     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/19")
 5550     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/20")
 5551     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/21")
 5552     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/22")
 5553     (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")
 5554     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/24")
 5555     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/25")
 5556     # . epilogue
 5557     89/<- %esp 5/r32/ebp
 5558     5d/pop-to-ebp
 5559     c3/return
 5560 
 5561 test-convert-function-with-local-array-var-in-mem:
 5562     # . prologue
 5563     55/push-ebp
 5564     89/<- %ebp 4/r32/esp
 5565     # setup
 5566     (clear-stream _test-input-stream)
 5567     (clear-stream $_test-input-buffered-file->buffer)
 5568     (clear-stream _test-output-stream)
 5569     (clear-stream $_test-output-buffered-file->buffer)
 5570     #
 5571     (write _test-input-stream "fn foo {\n")
 5572     (write _test-input-stream "  var x: (array int 3)\n")
 5573     (write _test-input-stream "}\n")
 5574     # convert
 5575     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5576     (flush _test-output-buffered-file)
 5577 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5583     # check output
 5584     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-array-var-in-mem/0")
 5585     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-array-var-in-mem/1")
 5586     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-array-var-in-mem/2")
 5587     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-array-var-in-mem/3")
 5588     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-array-var-in-mem/4")
 5589     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-array-var-in-mem/5")
 5590     # define x
 5591     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"  "F - test-convert-function-with-local-array-var-in-mem/7")
 5592     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"  "F - test-convert-function-with-local-array-var-in-mem/8")
 5593     # reclaim x
 5594     (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")
 5595     #
 5596     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-array-var-in-mem/10")
 5597     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-array-var-in-mem/11")
 5598     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-array-var-in-mem/12")
 5599     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-array-var-in-mem/13")
 5600     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-array-var-in-mem/14")
 5601     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-array-var-in-mem/15")
 5602     # . epilogue
 5603     89/<- %esp 5/r32/ebp
 5604     5d/pop-to-ebp
 5605     c3/return
 5606 
 5607 test-array-size-in-hex:
 5608     # . prologue
 5609     55/push-ebp
 5610     89/<- %ebp 4/r32/esp
 5611     # setup
 5612     (clear-stream _test-input-stream)
 5613     (clear-stream $_test-input-buffered-file->buffer)
 5614     (clear-stream _test-output-stream)
 5615     (clear-stream $_test-output-buffered-file->buffer)
 5616     (clear-stream _test-error-stream)
 5617     (clear-stream $_test-error-buffered-file->buffer)
 5618     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 5619     68/push 0/imm32
 5620     68/push 0/imm32
 5621     89/<- %edx 4/r32/esp
 5622     (tailor-exit-descriptor %edx 0x10)
 5623     #
 5624     (write _test-input-stream "fn foo {\n")
 5625     (write _test-input-stream "  var x: (array int 10)\n")
 5626     (write _test-input-stream "}\n")
 5627     # convert
 5628     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 5629     # registers except esp clobbered at this point
 5630     # restore ed
 5631     89/<- %edx 4/r32/esp
 5632     (flush _test-output-buffered-file)
 5633     (flush _test-error-buffered-file)
 5634 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 5640     # check output
 5641     (check-stream-equal _test-output-stream  ""  "F - test-array-size-in-hex: output should be empty")
 5642     (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")
 5643     # check that stop(1) was called
 5644     (check-ints-equal *(edx+4) 2 "F - test-array-size-in-hex: exit status")
 5645     # don't restore from ebp
 5646     81 0/subop/add %esp 8/imm32
 5647     # . epilogue
 5648     5d/pop-to-ebp
 5649     c3/return
 5650 
 5651 test-array-size-with-metadata:
 5652     # . prologue
 5653     55/push-ebp
 5654     89/<- %ebp 4/r32/esp
 5655     # setup
 5656     (clear-stream _test-input-stream)
 5657     (clear-stream $_test-input-buffered-file->buffer)
 5658     (clear-stream _test-output-stream)
 5659     (clear-stream $_test-output-buffered-file->buffer)
 5660     #
 5661     (write _test-input-stream "fn foo {\n")
 5662     (write _test-input-stream "  var x: (array int 3/bar)\n")
 5663     (write _test-input-stream "}\n")
 5664     # convert
 5665     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5666     (flush _test-output-buffered-file)
 5667 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5673     # no errors
 5674     # . epilogue
 5675     89/<- %esp 5/r32/ebp
 5676     5d/pop-to-ebp
 5677     c3/return
 5678 
 5679 test-convert-function-with-populate:
 5680     # . prologue
 5681     55/push-ebp
 5682     89/<- %ebp 4/r32/esp
 5683     # setup
 5684     (clear-stream _test-input-stream)
 5685     (clear-stream $_test-input-buffered-file->buffer)
 5686     (clear-stream _test-output-stream)
 5687     (clear-stream $_test-output-buffered-file->buffer)
 5688     #
 5689     (write _test-input-stream "fn foo {\n")
 5690     (write _test-input-stream "  var x/ecx: (addr handle array int) <- copy 0\n")
 5691     (write _test-input-stream "  populate x, 7\n")
 5692     (write _test-input-stream "}\n")
 5693     # convert
 5694     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5695     (flush _test-output-buffered-file)
 5696 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5702     # check output
 5703     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-populate/0")
 5704     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-populate/1")
 5705     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-populate/2")
 5706     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-populate/3")
 5707     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-populate/4")
 5708     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-populate/5")
 5709     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-populate/6")
 5710     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-populate/7")
 5711     (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)
 5712     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-populate/9")
 5713     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-populate/10")
 5714     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-populate/11")
 5715     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-populate/12")
 5716     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-populate/13")
 5717     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-populate/14")
 5718     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-populate/15")
 5719     # . epilogue
 5720     89/<- %esp 5/r32/ebp
 5721     5d/pop-to-ebp
 5722     c3/return
 5723 
 5724 # special-case for size(byte) when allocating array
 5725 test-convert-function-with-local-array-of-bytes-in-mem:
 5726     # . prologue
 5727     55/push-ebp
 5728     89/<- %ebp 4/r32/esp
 5729     # setup
 5730     (clear-stream _test-input-stream)
 5731     (clear-stream $_test-input-buffered-file->buffer)
 5732     (clear-stream _test-output-stream)
 5733     (clear-stream $_test-output-buffered-file->buffer)
 5734     #
 5735     (write _test-input-stream "fn foo {\n")
 5736     (write _test-input-stream "  var x: (array byte 3)\n")
 5737     (write _test-input-stream "}\n")
 5738     # convert
 5739     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5740     (flush _test-output-buffered-file)
 5741 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5747     # check output
 5748     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-array-of-bytes-in-mem/0")
 5749     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-array-of-bytes-in-mem/1")
 5750     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-array-of-bytes-in-mem/2")
 5751     (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")
 5752     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-array-of-bytes-in-mem/4")
 5753     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-array-of-bytes-in-mem/5")
 5754     # define x
 5755     (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")
 5756     (check-next-stream-line-equal _test-output-stream "    68/push 0x00000003/imm32"  "F - test-convert-function-with-local-array-of-bytes-in-mem/8")
 5757     # reclaim x
 5758     (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")
 5759     #
 5760     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-array-of-bytes-in-mem/10")
 5761     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-array-of-bytes-in-mem/11")
 5762     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-array-of-bytes-in-mem/12")
 5763     (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")
 5764     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-array-of-bytes-in-mem/14")
 5765     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-array-of-bytes-in-mem/15")
 5766     # . epilogue
 5767     89/<- %esp 5/r32/ebp
 5768     5d/pop-to-ebp
 5769     c3/return
 5770 
 5771 test-convert-address:
 5772     # . prologue
 5773     55/push-ebp
 5774     89/<- %ebp 4/r32/esp
 5775     # setup
 5776     (clear-stream _test-input-stream)
 5777     (clear-stream $_test-input-buffered-file->buffer)
 5778     (clear-stream _test-output-stream)
 5779     (clear-stream $_test-output-buffered-file->buffer)
 5780     #
 5781     (write _test-input-stream "fn foo {\n")
 5782     (write _test-input-stream "  var a: int\n")
 5783     (write _test-input-stream "  var b/eax: (addr int) <- address a\n")
 5784     (write _test-input-stream "}\n")
 5785     # convert
 5786     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5787     (flush _test-output-buffered-file)
 5788 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5794     # check output
 5795     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-address/0")
 5796     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-address/1")
 5797     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-address/2")
 5798     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-address/3")
 5799     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-address/4")
 5800     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-address/5")
 5801     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-address/6")
 5802     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-address/7")
 5803     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0xfffffffc) 0x00000000/r32"  "F - test-convert-address/8")
 5804     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-address/9")
 5805     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-address/10")
 5806     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-address/11")
 5807     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-address/12")
 5808     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-address/13")
 5809     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-address/14")
 5810     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-address/15")
 5811     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-address/16")
 5812     # . epilogue
 5813     89/<- %esp 5/r32/ebp
 5814     5d/pop-to-ebp
 5815     c3/return
 5816 
 5817 test-convert-floating-point-convert:
 5818     # . prologue
 5819     55/push-ebp
 5820     89/<- %ebp 4/r32/esp
 5821     # setup
 5822     (clear-stream _test-input-stream)
 5823     (clear-stream $_test-input-buffered-file->buffer)
 5824     (clear-stream _test-output-stream)
 5825     (clear-stream $_test-output-buffered-file->buffer)
 5826     #
 5827     (write _test-input-stream "fn foo {\n")
 5828     (write _test-input-stream "  var a/eax: int <- copy 0\n")
 5829     (write _test-input-stream "  var b/xmm1: float <- convert a\n")
 5830     (write _test-input-stream "}\n")
 5831     # convert
 5832     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5833     (flush _test-output-buffered-file)
 5834 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5840     # check output
 5841     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-floating-point-convert/0")
 5842     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-floating-point-convert/1")
 5843     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-floating-point-convert/2")
 5844     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-floating-point-convert/3")
 5845     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-floating-point-convert/4")
 5846     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-floating-point-convert/5")
 5847     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-floating-point-convert/6")
 5848     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-floating-point-convert/7")
 5849     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"  "F - test-convert-floating-point-convert/8")
 5850     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"  "F - test-convert-floating-point-convert/9")
 5851     (check-next-stream-line-equal _test-output-stream "    f3 0f 2a/convert-to-float %eax 0x00000001/x32"  "F - test-convert-floating-point-convert/10")
 5852     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"  "F - test-convert-floating-point-convert/11")
 5853     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-floating-point-convert/12")
 5854     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-floating-point-convert/13")
 5855     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-floating-point-convert/14")
 5856     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-floating-point-convert/15")
 5857     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-floating-point-convert/16")
 5858     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-floating-point-convert/17")
 5859     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-floating-point-convert/18")
 5860     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-floating-point-convert/19")
 5861     # . epilogue
 5862     89/<- %esp 5/r32/ebp
 5863     5d/pop-to-ebp
 5864     c3/return
 5865 
 5866 test-convert-floating-point-convert-2:
 5867     # . prologue
 5868     55/push-ebp
 5869     89/<- %ebp 4/r32/esp
 5870     # setup
 5871     (clear-stream _test-input-stream)
 5872     (clear-stream $_test-input-buffered-file->buffer)
 5873     (clear-stream _test-output-stream)
 5874     (clear-stream $_test-output-buffered-file->buffer)
 5875     #
 5876     (write _test-input-stream "fn foo {\n")
 5877     (write _test-input-stream "  var a/eax: int <- copy 0\n")
 5878     (write _test-input-stream "  var b/xmm1: float <- convert a\n")
 5879     (write _test-input-stream "  a <- convert b\n")
 5880     (write _test-input-stream "}\n")
 5881     # convert
 5882     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5883     (flush _test-output-buffered-file)
 5884 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5890     # check output
 5891     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-floating-point-convert-2/0")
 5892     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-floating-point-convert-2/1")
 5893     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-floating-point-convert-2/2")
 5894     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-floating-point-convert-2/3")
 5895     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-floating-point-convert-2/4")
 5896     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-floating-point-convert-2/5")
 5897     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-floating-point-convert-2/6")
 5898     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-floating-point-convert-2/7")
 5899     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"  "F - test-convert-floating-point-convert-2/8")
 5900     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"  "F - test-convert-floating-point-convert-2/9")
 5901     (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")
 5902     (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")
 5903     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"  "F - test-convert-floating-point-convert-2/12")
 5904     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-floating-point-convert-2/13")
 5905     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-floating-point-convert-2/14")
 5906     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-floating-point-convert-2/15")
 5907     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-floating-point-convert-2/16")
 5908     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-floating-point-convert-2/17")
 5909     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-floating-point-convert-2/18")
 5910     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-floating-point-convert-2/19")
 5911     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-floating-point-convert-2/20")
 5912     # . epilogue
 5913     89/<- %esp 5/r32/ebp
 5914     5d/pop-to-ebp
 5915     c3/return
 5916 
 5917 test-convert-floating-point-operation:
 5918     # . prologue
 5919     55/push-ebp
 5920     89/<- %ebp 4/r32/esp
 5921     # setup
 5922     (clear-stream _test-input-stream)
 5923     (clear-stream $_test-input-buffered-file->buffer)
 5924     (clear-stream _test-output-stream)
 5925     (clear-stream $_test-output-buffered-file->buffer)
 5926     #
 5927     (write _test-input-stream "fn f {\n")
 5928     (write _test-input-stream "  var m: float\n")
 5929     (write _test-input-stream "  var x/xmm1: float <- copy m\n")
 5930     (write _test-input-stream "  var y/xmm5: float <- copy m\n")
 5931     (write _test-input-stream "  x <- copy y\n")
 5932     (write _test-input-stream "  copy-to m, y\n")
 5933     (write _test-input-stream "  x <- add y\n")
 5934     (write _test-input-stream "  x <- add m\n")
 5935     (write _test-input-stream "  x <- subtract y\n")
 5936     (write _test-input-stream "  x <- subtract m\n")
 5937     (write _test-input-stream "  x <- multiply y\n")
 5938     (write _test-input-stream "  x <- multiply m\n")
 5939     (write _test-input-stream "  x <- divide y\n")
 5940     (write _test-input-stream "  x <- divide m\n")
 5941     (write _test-input-stream "  x <- reciprocal y\n")
 5942     (write _test-input-stream "  x <- reciprocal m\n")
 5943     (write _test-input-stream "  x <- square-root y\n")
 5944     (write _test-input-stream "  x <- square-root m\n")
 5945     (write _test-input-stream "  x <- inverse-square-root y\n")
 5946     (write _test-input-stream "  x <- inverse-square-root m\n")
 5947     (write _test-input-stream "  x <- max y\n")
 5948     (write _test-input-stream "  x <- max m\n")
 5949     (write _test-input-stream "  x <- min y\n")
 5950     (write _test-input-stream "  x <- min m\n")
 5951     (write _test-input-stream "  compare x, y\n")
 5952     (write _test-input-stream "  compare x, m\n")
 5953     (write _test-input-stream "}\n")
 5954     # convert
 5955     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5956     (flush _test-output-buffered-file)
 5957 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5963     # check output
 5964     (check-next-stream-line-equal _test-output-stream "f:"                                                                     "F - test-convert-floating-point-operation/0")
 5965     (check-next-stream-line-equal _test-output-stream "  # . prologue"                                                         "F - test-convert-floating-point-operation/1")
 5966     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                                                          "F - test-convert-floating-point-operation/2")
 5967     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                                                 "F - test-convert-floating-point-operation/3")
 5968     (check-next-stream-line-equal _test-output-stream "  {"                                                                    "F - test-convert-floating-point-operation/4")
 5969     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"                                                    "F - test-convert-floating-point-operation/5")
 5970     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                                                    "F - test-convert-floating-point-operation/6")
 5971     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-operation/7")
 5972     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"                                             "F - test-convert-floating-point-operation/8")
 5973     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-operation/9")
 5974     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-operation/10")
 5975     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 5/x32"                                             "F - test-convert-floating-point-operation/11")
 5976     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000005/x32"                     "F - test-convert-floating-point-operation/12")
 5977     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/copy %xmm1 0x00000005/x32"                                 "F - test-convert-floating-point-operation/13")
 5978     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/copy *(ebp+0xfffffffc) 0x00000005/x32"                     "F - test-convert-floating-point-operation/14")
 5979     (check-next-stream-line-equal _test-output-stream "    f3 0f 58/add %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/15")
 5980     (check-next-stream-line-equal _test-output-stream "    f3 0f 58/add *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/16")
 5981     (check-next-stream-line-equal _test-output-stream "    f3 0f 5c/subtract %xmm5 0x00000001/x32"                             "F - test-convert-floating-point-operation/17")
 5982     (check-next-stream-line-equal _test-output-stream "    f3 0f 5c/subtract *(ebp+0xfffffffc) 0x00000001/x32"                 "F - test-convert-floating-point-operation/18")
 5983     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply %xmm5 0x00000001/x32"                             "F - test-convert-floating-point-operation/19")
 5984     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply *(ebp+0xfffffffc) 0x00000001/x32"                 "F - test-convert-floating-point-operation/20")
 5985     (check-next-stream-line-equal _test-output-stream "    f3 0f 5e/divide %xmm5 0x00000001/x32"                               "F - test-convert-floating-point-operation/21")
 5986     (check-next-stream-line-equal _test-output-stream "    f3 0f 5e/divide *(ebp+0xfffffffc) 0x00000001/x32"                   "F - test-convert-floating-point-operation/22")
 5987     (check-next-stream-line-equal _test-output-stream "    f3 0f 53/reciprocal %xmm5 0x00000001/x32"                           "F - test-convert-floating-point-operation/23")
 5988     (check-next-stream-line-equal _test-output-stream "    f3 0f 53/reciprocal *(ebp+0xfffffffc) 0x00000001/x32"               "F - test-convert-floating-point-operation/24")
 5989     (check-next-stream-line-equal _test-output-stream "    f3 0f 51/square-root %xmm5 0x00000001/x32"                          "F - test-convert-floating-point-operation/25")
 5990     (check-next-stream-line-equal _test-output-stream "    f3 0f 51/square-root *(ebp+0xfffffffc) 0x00000001/x32"              "F - test-convert-floating-point-operation/26")
 5991     (check-next-stream-line-equal _test-output-stream "    f3 0f 52/inverse-square-root %xmm5 0x00000001/x32"                  "F - test-convert-floating-point-operation/27")
 5992     (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")
 5993     (check-next-stream-line-equal _test-output-stream "    f3 0f 5f/max %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/29")
 5994     (check-next-stream-line-equal _test-output-stream "    f3 0f 5f/max *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/30")
 5995     (check-next-stream-line-equal _test-output-stream "    f3 0f 5d/min %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/31")
 5996     (check-next-stream-line-equal _test-output-stream "    f3 0f 5d/min *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/32")
 5997     (check-next-stream-line-equal _test-output-stream "    0f 2f/compare %xmm5 0x00000001/x32"                                 "F - test-convert-floating-point-operation/33")
 5998     (check-next-stream-line-equal _test-output-stream "    0f 2f/compare *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-operation/34")
 5999     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 5/x32"                                             "F - test-convert-floating-point-operation/35")
 6000     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-operation/36")
 6001     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"                                             "F - test-convert-floating-point-operation/37")
 6002     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-operation/38")
 6003     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"                               "F - test-convert-floating-point-operation/39")
 6004     (check-next-stream-line-equal _test-output-stream "  }"                                                                    "F - test-convert-floating-point-operation/40")
 6005     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"                                                   "F - test-convert-floating-point-operation/41")
 6006     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                                                         "F - test-convert-floating-point-operation/42")
 6007     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                                                 "F - test-convert-floating-point-operation/43")
 6008     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                                                        "F - test-convert-floating-point-operation/44")
 6009     (check-next-stream-line-equal _test-output-stream "  c3/return"                                                            "F - test-convert-floating-point-operation/45")
 6010     # . epilogue
 6011     89/<- %esp 5/r32/ebp
 6012     5d/pop-to-ebp
 6013     c3/return
 6014 
 6015 test-convert-floating-point-dereferenced:
 6016     # . prologue
 6017     55/push-ebp
 6018     89/<- %ebp 4/r32/esp
 6019     # setup
 6020     (clear-stream _test-input-stream)
 6021     (clear-stream $_test-input-buffered-file->buffer)
 6022     (clear-stream _test-output-stream)
 6023     (clear-stream $_test-output-buffered-file->buffer)
 6024     #
 6025     (write _test-input-stream "fn f {\n")
 6026     (write _test-input-stream "  var m: float\n")
 6027     (write _test-input-stream "  var x/xmm1: float <- copy m\n")
 6028     (write _test-input-stream "  var y/eax: (addr float) <- copy 0\n")
 6029     (write _test-input-stream "  x <- multiply *y\n")
 6030     (write _test-input-stream "}\n")
 6031     # convert
 6032     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6033     (flush _test-output-buffered-file)
 6034 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6040     # check output
 6041     (check-next-stream-line-equal _test-output-stream "f:"                                                                     "F - test-convert-floating-point-dereferenced/0")
 6042     (check-next-stream-line-equal _test-output-stream "  # . prologue"                                                         "F - test-convert-floating-point-dereferenced/1")
 6043     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                                                          "F - test-convert-floating-point-dereferenced/2")
 6044     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                                                 "F - test-convert-floating-point-dereferenced/3")
 6045     (check-next-stream-line-equal _test-output-stream "  {"                                                                    "F - test-convert-floating-point-dereferenced/4")
 6046     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"                                                    "F - test-convert-floating-point-dereferenced/5")
 6047     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                                                    "F - test-convert-floating-point-dereferenced/6")
 6048     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-dereferenced/7")
 6049     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"                                             "F - test-convert-floating-point-dereferenced/8")
 6050     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-dereferenced/9")
 6051     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                                               "F - test-convert-floating-point-dereferenced/10")
 6052     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                                             "F - test-convert-floating-point-dereferenced/11")
 6053     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply *eax 0x00000001/x32"                              "F - test-convert-floating-point-dereferenced/12")
 6054     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                                                "F - test-convert-floating-point-dereferenced/13")
 6055     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"                                             "F - test-convert-floating-point-dereferenced/14")
 6056     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-dereferenced/15")
 6057     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"                               "F - test-convert-floating-point-dereferenced/16")
 6058     (check-next-stream-line-equal _test-output-stream "  }"                                                                    "F - test-convert-floating-point-dereferenced/17")
 6059     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"                                                   "F - test-convert-floating-point-dereferenced/18")
 6060     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                                                         "F - test-convert-floating-point-dereferenced/19")
 6061     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                                                 "F - test-convert-floating-point-dereferenced/20")
 6062     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                                                        "F - test-convert-floating-point-dereferenced/21")
 6063     (check-next-stream-line-equal _test-output-stream "  c3/return"                                                            "F - test-convert-floating-point-dereferenced/22")
 6064     # . epilogue
 6065     89/<- %esp 5/r32/ebp
 6066     5d/pop-to-ebp
 6067     c3/return
 6068 
 6069 test-convert-length-of-array:
 6070     # . prologue
 6071     55/push-ebp
 6072     89/<- %ebp 4/r32/esp
 6073     # setup
 6074     (clear-stream _test-input-stream)
 6075     (clear-stream $_test-input-buffered-file->buffer)
 6076     (clear-stream _test-output-stream)
 6077     (clear-stream $_test-output-buffered-file->buffer)
 6078     #
 6079     (write _test-input-stream "fn foo a: (addr array int) {\n")
 6080     (write _test-input-stream "  var b/eax: (addr array int) <- copy a\n")
 6081     (write _test-input-stream "  var c/eax: int <- length b\n")
 6082     (write _test-input-stream "}\n")
 6083     # convert
 6084     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6085     (flush _test-output-buffered-file)
 6086 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6092     # check output
 6093     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array/0")
 6094     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array/1")
 6095     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array/2")
 6096     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array/3")
 6097     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array/4")
 6098     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array/5")
 6099     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array/6")
 6100     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-length-of-array/7")
 6101     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array/8")
 6102     (check-next-stream-line-equal _test-output-stream "    c1/shift 5/subop/>> %eax 0x00000002/imm8"  "F - test-convert-length-of-array/9")
 6103     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array/10")
 6104     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array/11")
 6105     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array/12")
 6106     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array/13")
 6107     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array/14")
 6108     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array/15")
 6109     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array/16")
 6110     # . epilogue
 6111     89/<- %esp 5/r32/ebp
 6112     5d/pop-to-ebp
 6113     c3/return
 6114 
 6115 # special-case for size(byte) when computing array length
 6116 test-convert-length-of-array-of-bytes:
 6117     # . prologue
 6118     55/push-ebp
 6119     89/<- %ebp 4/r32/esp
 6120     # setup
 6121     (clear-stream _test-input-stream)
 6122     (clear-stream $_test-input-buffered-file->buffer)
 6123     (clear-stream _test-output-stream)
 6124     (clear-stream $_test-output-buffered-file->buffer)
 6125     #
 6126     (write _test-input-stream "fn foo a: (addr array byte) {\n")
 6127     (write _test-input-stream "  var b/eax: (addr array byte) <- copy a\n")
 6128     (write _test-input-stream "  var c/eax: int <- length b\n")
 6129     (write _test-input-stream "}\n")
 6130     # convert
 6131     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6132     (flush _test-output-buffered-file)
 6133 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6139     # check output
 6140     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-bytes/0")
 6141     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-bytes/1")
 6142     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-bytes/2")
 6143     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-bytes/3")
 6144     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-bytes/4")
 6145     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-bytes/5")
 6146     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-of-bytes/6")
 6147     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-length-of-array-of-bytes/7")
 6148     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array-of-bytes/8")
 6149     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-of-bytes/9")
 6150     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-bytes/10")
 6151     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-bytes/11")
 6152     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-bytes/12")
 6153     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-of-bytes/13")
 6154     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-of-bytes/14")
 6155     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-bytes/15")
 6156     # . epilogue
 6157     89/<- %esp 5/r32/ebp
 6158     5d/pop-to-ebp
 6159     c3/return
 6160 
 6161 test-convert-length-of-array-on-stack:
 6162     # . prologue
 6163     55/push-ebp
 6164     89/<- %ebp 4/r32/esp
 6165     # setup
 6166     (clear-stream _test-input-stream)
 6167     (clear-stream $_test-input-buffered-file->buffer)
 6168     (clear-stream _test-output-stream)
 6169     (clear-stream $_test-output-buffered-file->buffer)
 6170     #
 6171     (write _test-input-stream "fn foo {\n")
 6172     (write _test-input-stream "  var a: (array int 3)\n")
 6173     (write _test-input-stream "  var b/eax: int <- length a\n")
 6174     (write _test-input-stream "}\n")
 6175     # convert
 6176     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6177     (flush _test-output-buffered-file)
 6178 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6184     # check output
 6185     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-on-stack/0")
 6186     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-on-stack/1")
 6187     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-on-stack/2")
 6188     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-on-stack/3")
 6189     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-on-stack/4")
 6190     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-on-stack/5")
 6191     # define x
 6192     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"  "F - test-convert-length-of-array-on-stack/6")
 6193     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"  "F - test-convert-length-of-array-on-stack/7")
 6194     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-on-stack/8")
 6195     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0xfffffff0) 0x00000000/r32"  "F - test-convert-length-of-array-on-stack/9")
 6196     (check-next-stream-line-equal _test-output-stream "    c1/shift 5/subop/>> %eax 0x00000002/imm8"  "F - test-convert-length-of-array-on-stack/10")
 6197     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-on-stack/11")
 6198     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"  "F - test-convert-length-of-array-on-stack/12")
 6199     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-on-stack/13")
 6200     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-on-stack/14")
 6201     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-on-stack/15")
 6202     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-on-stack/16")
 6203     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-on-stack/17")
 6204     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-on-stack/18")
 6205     # . epilogue
 6206     89/<- %esp 5/r32/ebp
 6207     5d/pop-to-ebp
 6208     c3/return
 6209 
 6210 test-reg-var-def-with-read-of-same-register:
 6211     # . prologue
 6212     55/push-ebp
 6213     89/<- %ebp 4/r32/esp
 6214     # setup
 6215     (clear-stream _test-input-stream)
 6216     (clear-stream $_test-input-buffered-file->buffer)
 6217     (clear-stream _test-output-stream)
 6218     (clear-stream $_test-output-buffered-file->buffer)
 6219     (clear-stream _test-error-stream)
 6220     (clear-stream $_test-error-buffered-file->buffer)
 6221     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
 6222     68/push 0/imm32
 6223     68/push 0/imm32
 6224     89/<- %edx 4/r32/esp
 6225     (tailor-exit-descriptor %edx 0x10)
 6226     #
 6227     (write _test-input-stream "fn foo {\n")
 6228     (write _test-input-stream "  var x/eax: int <- copy 3\n")
 6229     (write _test-input-stream "  var y/eax: int <- add x\n")
 6230     (write _test-input-stream "}\n")
 6231     # convert
 6232     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6233     # registers except esp could be clobbered at this point (though they shouldn't be)
 6234     # restore ed
 6235     89/<- %edx 4/r32/esp
 6236     (flush _test-output-buffered-file)
 6237     (flush _test-error-buffered-file)
 6238 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6244 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 6250     (check-stream-equal _test-error-stream  ""  "F - test-reg-var-def-with-read-of-same-register: error stream should be empty")
 6251     # check output
 6252     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-reg-var-def-with-read-of-same-register/0")
 6253     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-reg-var-def-with-read-of-same-register/1")
 6254     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-reg-var-def-with-read-of-same-register/2")
 6255     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-reg-var-def-with-read-of-same-register/3")
 6256     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-reg-var-def-with-read-of-same-register/4")
 6257     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-reg-var-def-with-read-of-same-register/5")
 6258     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-reg-var-def-with-read-of-same-register/6")
 6259     (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")
 6260     (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")
 6261     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-reg-var-def-with-read-of-same-register/9")
 6262     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-reg-var-def-with-read-of-same-register/10")
 6263     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-reg-var-def-with-read-of-same-register/11")
 6264     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-reg-var-def-with-read-of-same-register/12")
 6265     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-reg-var-def-with-read-of-same-register/13")
 6266     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-reg-var-def-with-read-of-same-register/14")
 6267     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-reg-var-def-with-read-of-same-register/15")
 6268     # don't restore from ebp
 6269     81 0/subop/add %esp 8/imm32
 6270     # . epilogue
 6271     5d/pop-to-ebp
 6272     c3/return
 6273 
 6274 test-convert-index-into-array:
 6275     # . prologue
 6276     55/push-ebp
 6277     89/<- %ebp 4/r32/esp
 6278     # setup
 6279     (clear-stream _test-input-stream)
 6280     (clear-stream $_test-input-buffered-file->buffer)
 6281     (clear-stream _test-output-stream)
 6282     (clear-stream $_test-output-buffered-file->buffer)
 6283     #
 6284     (write _test-input-stream "fn foo {\n")
 6285     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 6286     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 6287     (write _test-input-stream "  var x/eax: (addr int) <- index arr, idx\n")
 6288     (write _test-input-stream "}\n")
 6289     # convert
 6290     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6291     (flush _test-output-buffered-file)
 6292 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6298     # check output
 6299     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array/0")
 6300     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array/1")
 6301     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array/2")
 6302     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array/3")
 6303     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array/4")
 6304     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array/5")
 6305     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array/6")
 6306     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array/7")
 6307     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array/8")
 6308     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array/9")
 6309     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 0x00000004 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array/10")
 6310     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx<<0x00000002 + 4) 0x00000000/r32"  "F - test-convert-index-into-array/11")
 6311     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array/12")
 6312     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array/13")
 6313     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array/14")
 6314     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array/15")
 6315     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array/16")
 6316     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array/17")
 6317     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array/18")
 6318     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array/19")
 6319     # . epilogue
 6320     89/<- %esp 5/r32/ebp
 6321     5d/pop-to-ebp
 6322     c3/return
 6323 
 6324 test-convert-index-into-array-of-bytes:
 6325     # . prologue
 6326     55/push-ebp
 6327     89/<- %ebp 4/r32/esp
 6328     # setup
 6329     (clear-stream _test-input-stream)
 6330     (clear-stream $_test-input-buffered-file->buffer)
 6331     (clear-stream _test-output-stream)
 6332     (clear-stream $_test-output-buffered-file->buffer)
 6333     #
 6334     (write _test-input-stream "fn foo {\n")
 6335     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 6336     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 6337     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, idx\n")
 6338     (write _test-input-stream "}\n")
 6339     # convert
 6340     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6341     (flush _test-output-buffered-file)
 6342 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6348     # check output
 6349     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes/0")
 6350     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes/1")
 6351     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes/2")
 6352     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes/3")
 6353     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes/4")
 6354     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes/5")
 6355     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes/6")
 6356     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-of-bytes/7")
 6357     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-of-bytes/8")
 6358     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array-of-bytes/9")
 6359     (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")
 6360     (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")
 6361     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes/12")
 6362     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes/13")
 6363     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes/14")
 6364     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes/15")
 6365     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes/16")
 6366     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes/17")
 6367     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes/18")
 6368     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes/19")
 6369     # . epilogue
 6370     89/<- %esp 5/r32/ebp
 6371     5d/pop-to-ebp
 6372     c3/return
 6373 
 6374 test-convert-index-into-array-with-literal:
 6375     # . prologue
 6376     55/push-ebp
 6377     89/<- %ebp 4/r32/esp
 6378     # setup
 6379     (clear-stream _test-input-stream)
 6380     (clear-stream $_test-input-buffered-file->buffer)
 6381     (clear-stream _test-output-stream)
 6382     (clear-stream $_test-output-buffered-file->buffer)
 6383     #
 6384     (write _test-input-stream "fn foo {\n")
 6385     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 6386     (write _test-input-stream "  var x/eax: (addr int) <- index arr, 2\n")
 6387     (write _test-input-stream "}\n")
 6388     # convert
 6389     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6390     (flush _test-output-buffered-file)
 6391 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6397     # check output
 6398     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-with-literal/0")
 6399     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-with-literal/1")
 6400     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-with-literal/2")
 6401     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-with-literal/3")
 6402     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-with-literal/4")
 6403     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-with-literal/5")
 6404     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-with-literal/6")
 6405     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-with-literal/7")
 6406     (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")
 6407                                                                                  # 2 * 4 bytes/elem + 4 bytes for size = offset 12
 6408     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x0000000c) 0x00000000/r32"  "F - test-convert-index-into-array-with-literal/9")
 6409     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-with-literal/10")
 6410     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-with-literal/11")
 6411     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-with-literal/12")
 6412     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-with-literal/13")
 6413     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-with-literal/14")
 6414     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-with-literal/15")
 6415     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-with-literal/16")
 6416     # . epilogue
 6417     89/<- %esp 5/r32/ebp
 6418     5d/pop-to-ebp
 6419     c3/return
 6420 
 6421 test-convert-index-into-array-of-bytes-with-literal:
 6422     # . prologue
 6423     55/push-ebp
 6424     89/<- %ebp 4/r32/esp
 6425     # setup
 6426     (clear-stream _test-input-stream)
 6427     (clear-stream $_test-input-buffered-file->buffer)
 6428     (clear-stream _test-output-stream)
 6429     (clear-stream $_test-output-buffered-file->buffer)
 6430     #
 6431     (write _test-input-stream "fn foo {\n")
 6432     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 6433     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, 2\n")
 6434     (write _test-input-stream "}\n")
 6435     # convert
 6436     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6437     (flush _test-output-buffered-file)
 6438 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6444     # check output
 6445     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-with-literal/0")
 6446     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-with-literal/1")
 6447     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-with-literal/2")
 6448     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes-with-literal/3")
 6449     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-with-literal/4")
 6450     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-with-literal/5")
 6451     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes-with-literal/6")
 6452     (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")
 6453     (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")
 6454                                                                                  # 2 * 1 byte/elem + 4 bytes for size = offset 6
 6455     (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")
 6456     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-with-literal/9")
 6457     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-with-literal/10")
 6458     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-with-literal/11")
 6459     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-with-literal/12")
 6460     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-with-literal/13")
 6461     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-with-literal/14")
 6462     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-with-literal/15")
 6463     # . epilogue
 6464     89/<- %esp 5/r32/ebp
 6465     5d/pop-to-ebp
 6466     c3/return
 6467 
 6468 test-convert-index-into-array-on-stack:
 6469     # . prologue
 6470     55/push-ebp
 6471     89/<- %ebp 4/r32/esp
 6472     # setup
 6473     (clear-stream _test-input-stream)
 6474     (clear-stream $_test-input-buffered-file->buffer)
 6475     (clear-stream _test-output-stream)
 6476     (clear-stream $_test-output-buffered-file->buffer)
 6477     #
 6478     (write _test-input-stream "fn foo {\n")
 6479     (write _test-input-stream "  var arr: (array int 3)\n")
 6480     (write _test-input-stream "  var idx/eax: int <- copy 2\n")
 6481     (write _test-input-stream "  var x/eax: (addr int) <- index arr, idx\n")
 6482     (write _test-input-stream "}\n")
 6483     # convert
 6484     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6485     (flush _test-output-buffered-file)
 6486 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6492     # check output
 6493     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-on-stack/0")
 6494     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-on-stack/1")
 6495     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-on-stack/2")
 6496     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-on-stack/3")
 6497     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-on-stack/4")
 6498     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-on-stack/5")
 6499     # var arr
 6500     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"          "F - test-convert-index-into-array-on-stack/6")
 6501     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"                "F - test-convert-index-into-array-on-stack/7")
 6502     # var idx
 6503     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-on-stack/8")
 6504     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 2/imm32"                  "F - test-convert-index-into-array-on-stack/9")
 6505     (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")
 6506     # var x is at (ebp-0x10) + idx<<2 + 4 = ebp + idx<<2 - 0xc
 6507     (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")
 6508     # reclaim idx
 6509     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-on-stack/12")
 6510     # reclaim arr
 6511     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"    "F - test-convert-index-into-array-on-stack/13")
 6512     #
 6513     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-on-stack/14")
 6514     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-on-stack/15")
 6515     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-on-stack/16")
 6516     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-on-stack/17")
 6517     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-on-stack/18")
 6518     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-on-stack/19")
 6519     # . epilogue
 6520     89/<- %esp 5/r32/ebp
 6521     5d/pop-to-ebp
 6522     c3/return
 6523 
 6524 test-convert-index-into-array-on-stack-with-literal:
 6525     # . prologue
 6526     55/push-ebp
 6527     89/<- %ebp 4/r32/esp
 6528     # setup
 6529     (clear-stream _test-input-stream)
 6530     (clear-stream $_test-input-buffered-file->buffer)
 6531     (clear-stream _test-output-stream)
 6532     (clear-stream $_test-output-buffered-file->buffer)
 6533     #
 6534     (write _test-input-stream "fn foo {\n")
 6535     (write _test-input-stream "  var arr: (array int 3)\n")
 6536     (write _test-input-stream "  var x/eax: (addr int) <- index arr, 2\n")
 6537     (write _test-input-stream "}\n")
 6538     # convert
 6539     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6540     (flush _test-output-buffered-file)
 6541 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6547     # check output
 6548     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-on-stack-with-literal/0")
 6549     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-on-stack-with-literal/1")
 6550     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-on-stack-with-literal/2")
 6551     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-on-stack-with-literal/3")
 6552     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-on-stack-with-literal/4")
 6553     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-on-stack-with-literal/5")
 6554     # var arr
 6555     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"          "F - test-convert-index-into-array-on-stack-with-literal/6")
 6556     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"                "F - test-convert-index-into-array-on-stack-with-literal/7")
 6557     # var x
 6558     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-on-stack-with-literal/8")
 6559     (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")
 6560     # x is at (ebp-0x10) + 4 + 2*4 = ebp-4
 6561     (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")
 6562     # reclaim x
 6563     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-on-stack-with-literal/11")
 6564     # reclaim arr
 6565     (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")
 6566     #
 6567     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-on-stack-with-literal/13")
 6568     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-on-stack-with-literal/14")
 6569     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-on-stack-with-literal/15")
 6570     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-on-stack-with-literal/16")
 6571     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-on-stack-with-literal/17")
 6572     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-on-stack-with-literal/18")
 6573     # . epilogue
 6574     89/<- %esp 5/r32/ebp
 6575     5d/pop-to-ebp
 6576     c3/return
 6577 
 6578 test-convert-index-into-array-of-bytes-on-stack-with-literal:
 6579     # . prologue
 6580     55/push-ebp
 6581     89/<- %ebp 4/r32/esp
 6582     # setup
 6583     (clear-stream _test-input-stream)
 6584     (clear-stream $_test-input-buffered-file->buffer)
 6585     (clear-stream _test-output-stream)
 6586     (clear-stream $_test-output-buffered-file->buffer)
 6587     #
 6588     (write _test-input-stream "fn foo {\n")
 6589     (write _test-input-stream "  var arr: (array byte 3)\n")
 6590     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, 2\n")
 6591     (write _test-input-stream "}\n")
 6592     # convert
 6593     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6594     (flush _test-output-buffered-file)
 6595 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6601     # check output
 6602     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/0")
 6603     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/1")
 6604     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/2")
 6605     (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")
 6606     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/4")
 6607     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/5")
 6608     # var arr
 6609     (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")
 6610     (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")
 6611     # var x
 6612     (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")
 6613     (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")
 6614     # x is at (ebp-7) + 4 + 2 = ebp-1
 6615     (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")
 6616     # reclaim x
 6617     (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")
 6618     # reclaim arr
 6619     (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")
 6620     #
 6621     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/13")
 6622     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/14")
 6623     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/15")
 6624     (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")
 6625     (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")
 6626     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/18")
 6627     # . epilogue
 6628     89/<- %esp 5/r32/ebp
 6629     5d/pop-to-ebp
 6630     c3/return
 6631 
 6632 test-convert-index-into-array-using-offset:
 6633     # . prologue
 6634     55/push-ebp
 6635     89/<- %ebp 4/r32/esp
 6636     # setup
 6637     (clear-stream _test-input-stream)
 6638     (clear-stream $_test-input-buffered-file->buffer)
 6639     (clear-stream _test-output-stream)
 6640     (clear-stream $_test-output-buffered-file->buffer)
 6641     #
 6642     (write _test-input-stream "fn foo {\n")
 6643     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 6644     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 6645     (write _test-input-stream "  var off/ecx: (offset int) <- compute-offset arr, idx\n")
 6646     (write _test-input-stream "  var x/eax: (addr int) <- index arr, off\n")
 6647     (write _test-input-stream "}\n")
 6648     # convert
 6649     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6650     (flush _test-output-buffered-file)
 6651 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6657     # check output
 6658     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-using-offset/0")
 6659     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-using-offset/1")
 6660     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-using-offset/2")
 6661     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-using-offset/3")
 6662     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-using-offset/4")
 6663     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-using-offset/5")
 6664     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-using-offset/6")
 6665     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-using-offset/7")
 6666     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-using-offset/8")
 6667     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array-using-offset/9")
 6668     (check-next-stream-line-equal _test-output-stream "    69/multiply %ecx 0x00000004/imm32 0x00000001/r32"  "F - test-convert-index-into-array-using-offset/10")
 6669     (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")
 6670     (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")
 6671     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-using-offset/13")
 6672     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-using-offset/14")
 6673     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-using-offset/15")
 6674     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-using-offset/16")
 6675     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-using-offset/17")
 6676     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-using-offset/18")
 6677     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-using-offset/19")
 6678     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-using-offset/20")
 6679     # . epilogue
 6680     89/<- %esp 5/r32/ebp
 6681     5d/pop-to-ebp
 6682     c3/return
 6683 
 6684 test-convert-index-into-array-of-bytes-using-offset:
 6685     # . prologue
 6686     55/push-ebp
 6687     89/<- %ebp 4/r32/esp
 6688     # setup
 6689     (clear-stream _test-input-stream)
 6690     (clear-stream $_test-input-buffered-file->buffer)
 6691     (clear-stream _test-output-stream)
 6692     (clear-stream $_test-output-buffered-file->buffer)
 6693     #
 6694     (write _test-input-stream "fn foo {\n")
 6695     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 6696     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 6697     (write _test-input-stream "  var off/ecx: (offset byte) <- compute-offset arr, idx\n")
 6698     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, off\n")
 6699     (write _test-input-stream "}\n")
 6700     # convert
 6701     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6702     (flush _test-output-buffered-file)
 6703 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6709     # check output
 6710     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-using-offset/0")
 6711     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-using-offset/1")
 6712     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-using-offset/2")
 6713     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes-using-offset/3")
 6714     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-using-offset/4")
 6715     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-using-offset/5")
 6716     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes-using-offset/6")
 6717     (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")
 6718     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-of-bytes-using-offset/8")
 6719     (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")
 6720     (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")
 6721     (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")
 6722     (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")
 6723     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes-using-offset/13")
 6724     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-using-offset/14")
 6725     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-using-offset/15")
 6726     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-using-offset/16")
 6727     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-using-offset/17")
 6728     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-using-offset/18")
 6729     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-using-offset/19")
 6730     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-using-offset/20")
 6731     # . epilogue
 6732     89/<- %esp 5/r32/ebp
 6733     5d/pop-to-ebp
 6734     c3/return
 6735 
 6736 test-convert-index-into-array-using-offset-on-stack:
 6737     # . prologue
 6738     55/push-ebp
 6739     89/<- %ebp 4/r32/esp
 6740     # setup
 6741     (clear-stream _test-input-stream)
 6742     (clear-stream $_test-input-buffered-file->buffer)
 6743     (clear-stream _test-output-stream)
 6744     (clear-stream $_test-output-buffered-file->buffer)
 6745     #
 6746     (write _test-input-stream "fn foo {\n")
 6747     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 6748     (write _test-input-stream "  var idx: int\n")
 6749     (write _test-input-stream "  var off/ecx: (offset int) <- compute-offset arr, idx\n")
 6750     (write _test-input-stream "  var x/eax: (addr int) <- index arr, off\n")
 6751     (write _test-input-stream "}\n")
 6752     # convert
 6753     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6754     (flush _test-output-buffered-file)
 6755 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6761     # check output
 6762     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-using-offset-on-stack/0")
 6763     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-using-offset-on-stack/1")
 6764     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-using-offset-on-stack/2")
 6765     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-using-offset-on-stack/3")
 6766     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-using-offset-on-stack/4")
 6767     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-using-offset-on-stack/5")
 6768     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-using-offset-on-stack/6")
 6769     (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")
 6770     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                         "F - test-convert-index-into-array-using-offset-on-stack/8")
 6771     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-using-offset-on-stack/9")
 6772     (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")
 6773     (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")
 6774     (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")
 6775     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-using-offset-on-stack/13")
 6776     (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")
 6777     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-using-offset-on-stack/15")
 6778     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-using-offset-on-stack/16")
 6779     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-using-offset-on-stack/17")
 6780     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-using-offset-on-stack/18")
 6781     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-using-offset-on-stack/19")
 6782     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-using-offset-on-stack/20")
 6783     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-using-offset-on-stack/21")
 6784     # . epilogue
 6785     89/<- %esp 5/r32/ebp
 6786     5d/pop-to-ebp
 6787     c3/return
 6788 
 6789 test-convert-index-into-array-of-bytes-using-offset-on-stack:
 6790     # . prologue
 6791     55/push-ebp
 6792     89/<- %ebp 4/r32/esp
 6793     # setup
 6794     (clear-stream _test-input-stream)
 6795     (clear-stream $_test-input-buffered-file->buffer)
 6796     (clear-stream _test-output-stream)
 6797     (clear-stream $_test-output-buffered-file->buffer)
 6798     #
 6799     (write _test-input-stream "fn foo {\n")
 6800     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 6801     (write _test-input-stream "  var idx: int\n")
 6802     (write _test-input-stream "  var off/ecx: (offset byte) <- compute-offset arr, idx\n")
 6803     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, off\n")
 6804     (write _test-input-stream "}\n")
 6805     # convert
 6806     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6807     (flush _test-output-buffered-file)
 6808 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6814     # check output
 6815     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/0")
 6816     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/1")
 6817     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/2")
 6818     (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")
 6819     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/4")
 6820     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/5")
 6821     (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")
 6822     (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")
 6823     (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")
 6824     (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")
 6825     (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")
 6826     (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")
 6827     (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")
 6828     (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")
 6829     (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")
 6830     (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")
 6831     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/16")
 6832     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/17")
 6833     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/18")
 6834     (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")
 6835     (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")
 6836     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/21")
 6837     # . epilogue
 6838     89/<- %esp 5/r32/ebp
 6839     5d/pop-to-ebp
 6840     c3/return
 6841 
 6842 test-convert-function-and-type-definition:
 6843     # . prologue
 6844     55/push-ebp
 6845     89/<- %ebp 4/r32/esp
 6846     # setup
 6847     (clear-stream _test-input-stream)
 6848     (clear-stream $_test-input-buffered-file->buffer)
 6849     (clear-stream _test-output-stream)
 6850     (clear-stream $_test-output-buffered-file->buffer)
 6851     #
 6852     (write _test-input-stream "fn foo a: (addr t) {\n")
 6853     (write _test-input-stream "  var _a/eax: (addr t) <- copy a\n")
 6854     (write _test-input-stream "  var b/ecx: (addr int) <- get _a, x\n")
 6855     (write _test-input-stream "  var c/ecx: (addr int) <- get _a, y\n")
 6856     (write _test-input-stream "}\n")
 6857     (write _test-input-stream "type t {\n")
 6858     (write _test-input-stream "  x: int\n")
 6859     (write _test-input-stream "  y: int\n")
 6860     (write _test-input-stream "}\n")
 6861     # convert
 6862     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6863     (flush _test-output-buffered-file)
 6864 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6870     # check output
 6871     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-and-type-definition/0")
 6872     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-and-type-definition/1")
 6873     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-and-type-definition/2")
 6874     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-and-type-definition/3")
 6875     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-and-type-definition/4")
 6876     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-and-type-definition/5")
 6877     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-and-type-definition/6")
 6878     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-and-type-definition/7")
 6879     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-and-type-definition/8")
 6880     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x00000000) 0x00000001/r32"  "F - test-convert-function-and-type-definition/9")
 6881     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x00000004) 0x00000001/r32"  "F - test-convert-function-and-type-definition/11")
 6882     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-and-type-definition/13")
 6883     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-and-type-definition/14")
 6884     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-and-type-definition/15")
 6885     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-and-type-definition/16")
 6886     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-and-type-definition/17")
 6887     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-and-type-definition/18")
 6888     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-and-type-definition/19")
 6889     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-and-type-definition/20")
 6890     # . epilogue
 6891     89/<- %esp 5/r32/ebp
 6892     5d/pop-to-ebp
 6893     c3/return
 6894 
 6895 test-type-definition-with-array:
 6896     # . prologue
 6897     55/push-ebp
 6898     89/<- %ebp 4/r32/esp
 6899     # setup
 6900     (clear-stream _test-input-stream)
 6901     (clear-stream $_test-input-buffered-file->buffer)
 6902     (clear-stream _test-output-stream)
 6903     (clear-stream $_test-output-buffered-file->buffer)
 6904     (clear-stream _test-error-stream)
 6905     (clear-stream $_test-error-buffered-file->buffer)
 6906     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6907     68/push 0/imm32
 6908     68/push 0/imm32
 6909     89/<- %edx 4/r32/esp
 6910     (tailor-exit-descriptor %edx 0x10)
 6911     #
 6912     (write _test-input-stream "type t {\n")
 6913     (write _test-input-stream "  a: (array int 3)\n")
 6914     (write _test-input-stream "}\n")
 6915     # convert
 6916     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6917     # registers except esp clobbered at this point
 6918     # restore ed
 6919     89/<- %edx 4/r32/esp
 6920     (flush _test-output-buffered-file)
 6921     (flush _test-error-buffered-file)
 6922 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 6928     # check output
 6929     (check-stream-equal _test-output-stream  ""  "F - test-type-definition-with-array: output should be empty")
 6930     (check-next-stream-line-equal _test-error-stream  "type t: 'array' elements not allowed for now"  "F - test-type-definition-with-array: error message")
 6931     # check that stop(1) was called
 6932     (check-ints-equal *(edx+4) 2 "F - test-type-definition-with-array: exit status")
 6933     # don't restore from ebp
 6934     81 0/subop/add %esp 8/imm32
 6935     # . epilogue
 6936     5d/pop-to-ebp
 6937     c3/return
 6938 
 6939 test-type-definition-with-addr:
 6940     # . prologue
 6941     55/push-ebp
 6942     89/<- %ebp 4/r32/esp
 6943     # setup
 6944     (clear-stream _test-input-stream)
 6945     (clear-stream $_test-input-buffered-file->buffer)
 6946     (clear-stream _test-output-stream)
 6947     (clear-stream $_test-output-buffered-file->buffer)
 6948     (clear-stream _test-error-stream)
 6949     (clear-stream $_test-error-buffered-file->buffer)
 6950     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6951     68/push 0/imm32
 6952     68/push 0/imm32
 6953     89/<- %edx 4/r32/esp
 6954     (tailor-exit-descriptor %edx 0x10)
 6955     #
 6956     (write _test-input-stream "type t {\n")
 6957     (write _test-input-stream "  a: (addr int)\n")
 6958     (write _test-input-stream "}\n")
 6959     # convert
 6960     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6961     # registers except esp clobbered at this point
 6962     # restore ed
 6963     89/<- %edx 4/r32/esp
 6964     (flush _test-output-buffered-file)
 6965     (flush _test-error-buffered-file)
 6966 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 6972     # check output
 6973     (check-stream-equal _test-output-stream  ""  "F - test-type-definition-with-addr: output should be empty")
 6974     (check-next-stream-line-equal _test-error-stream  "type t: 'addr' elements not allowed"  "F - test-type-definition-with-addr: error message")
 6975     # check that stop(1) was called
 6976     (check-ints-equal *(edx+4) 2 "F - test-type-definition-with-addr: exit status")
 6977     # don't restore from ebp
 6978     81 0/subop/add %esp 8/imm32
 6979     # . epilogue
 6980     5d/pop-to-ebp
 6981     c3/return
 6982 
 6983 test-convert-function-with-local-var-with-user-defined-type:
 6984     # . prologue
 6985     55/push-ebp
 6986     89/<- %ebp 4/r32/esp
 6987     # setup
 6988     (clear-stream _test-input-stream)
 6989     (clear-stream $_test-input-buffered-file->buffer)
 6990     (clear-stream _test-output-stream)
 6991     (clear-stream $_test-output-buffered-file->buffer)
 6992     #
 6993     (write _test-input-stream "fn foo {\n")
 6994     (write _test-input-stream "  var a: t\n")
 6995     (write _test-input-stream "}\n")
 6996     (write _test-input-stream "type t {\n")
 6997     (write _test-input-stream "  x: int\n")
 6998     (write _test-input-stream "  y: int\n")
 6999     (write _test-input-stream "}\n")
 7000     # convert
 7001     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7002     (flush _test-output-buffered-file)
 7003 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7009     # check output
 7010     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-with-user-defined-type/0")
 7011     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-with-user-defined-type/1")
 7012     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-with-user-defined-type/2")
 7013     (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")
 7014     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-user-defined-type/4")
 7015     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-with-user-defined-type/5")
 7016     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-user-defined-type/6")
 7017     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-user-defined-type/7")
 7018     (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")
 7019     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-user-defined-type/9")
 7020     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-with-user-defined-type/10")
 7021     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-with-user-defined-type/11")
 7022     (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")
 7023     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-with-user-defined-type/13")
 7024     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-with-user-defined-type/14")
 7025     # . epilogue
 7026     89/<- %esp 5/r32/ebp
 7027     5d/pop-to-ebp
 7028     c3/return
 7029 
 7030 test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type:
 7031     # . prologue
 7032     55/push-ebp
 7033     89/<- %ebp 4/r32/esp
 7034     # setup
 7035     (clear-stream _test-input-stream)
 7036     (clear-stream $_test-input-buffered-file->buffer)
 7037     (clear-stream _test-output-stream)
 7038     (clear-stream $_test-output-buffered-file->buffer)
 7039     #
 7040     (write _test-input-stream "fn foo {\n")
 7041     (write _test-input-stream "  var a: t\n")
 7042     (write _test-input-stream "}\n")
 7043     (write _test-input-stream "type t {\n")
 7044     (write _test-input-stream "  x: s\n")
 7045     (write _test-input-stream "}\n")
 7046     (write _test-input-stream "type s {\n")
 7047     (write _test-input-stream "  z: int\n")
 7048     (write _test-input-stream "}\n")
 7049     # convert
 7050     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7051     (flush _test-output-buffered-file)
 7052 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7058     # check output
 7059     (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")
 7060     (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")
 7061     (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")
 7062     (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")
 7063     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/4")
 7064     (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")
 7065     (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")
 7066     (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")
 7067     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/9")
 7068     (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")
 7069     (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")
 7070     (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")
 7071     (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")
 7072     (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")
 7073     # . epilogue
 7074     89/<- %esp 5/r32/ebp
 7075     5d/pop-to-ebp
 7076     c3/return
 7077 
 7078 test-convert-function-call-with-arg-of-user-defined-type:
 7079     # . prologue
 7080     55/push-ebp
 7081     89/<- %ebp 4/r32/esp
 7082     # setup
 7083     (clear-stream _test-input-stream)
 7084     (clear-stream $_test-input-buffered-file->buffer)
 7085     (clear-stream _test-output-stream)
 7086     (clear-stream $_test-output-buffered-file->buffer)
 7087     #
 7088     (write _test-input-stream "fn f {\n")
 7089     (write _test-input-stream "  var a: t\n")
 7090     (write _test-input-stream "  foo a\n")
 7091     (write _test-input-stream "}\n")
 7092     (write _test-input-stream "fn foo x: t {\n")
 7093     (write _test-input-stream "}\n")
 7094     (write _test-input-stream "type t {\n")
 7095     (write _test-input-stream "  x: int\n")
 7096     (write _test-input-stream "  y: int\n")
 7097     (write _test-input-stream "}\n")
 7098     # convert
 7099     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7100     (flush _test-output-buffered-file)
 7101 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7107     # check output
 7108     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type/0")
 7109     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/1")
 7110     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/2")
 7111     (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")
 7112     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type/4")
 7113     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-arg-of-user-defined-type/5")
 7114     # var a: t
 7115     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-arg-of-user-defined-type/6")
 7116     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-arg-of-user-defined-type/7")
 7117     # foo a
 7118     (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")
 7119     #
 7120     (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")
 7121     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type/10")
 7122     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-arg-of-user-defined-type/11")
 7123     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/12")
 7124     (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")
 7125     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/14")
 7126     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/15")
 7127     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type/16")
 7128     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/17")
 7129     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/18")
 7130     (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")
 7131     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/20")
 7132     (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")
 7133     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/22")
 7134     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/23")
 7135     # . epilogue
 7136     89/<- %esp 5/r32/ebp
 7137     5d/pop-to-ebp
 7138     c3/return
 7139 
 7140 test-convert-function-call-with-arg-of-user-defined-type-register-indirect:
 7141     # . prologue
 7142     55/push-ebp
 7143     89/<- %ebp 4/r32/esp
 7144     # setup
 7145     (clear-stream _test-input-stream)
 7146     (clear-stream $_test-input-buffered-file->buffer)
 7147     (clear-stream _test-output-stream)
 7148     (clear-stream $_test-output-buffered-file->buffer)
 7149     #
 7150     (write _test-input-stream "fn f {\n")
 7151     (write _test-input-stream "  var a/eax: (addr t) <- copy 0\n")
 7152     (write _test-input-stream "  foo *a\n")
 7153     (write _test-input-stream "}\n")
 7154     (write _test-input-stream "fn foo x: t {\n")
 7155     (write _test-input-stream "}\n")
 7156     (write _test-input-stream "type t {\n")
 7157     (write _test-input-stream "  x: int\n")
 7158     (write _test-input-stream "  y: int\n")
 7159     (write _test-input-stream "}\n")
 7160     # convert
 7161     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7162     (flush _test-output-buffered-file)
 7163 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7169     # check output
 7170     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type/0")
 7171     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/1")
 7172     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/2")
 7173     (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")
 7174     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type/4")
 7175     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-arg-of-user-defined-type/5")
 7176     # var a
 7177     (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")
 7178     (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")
 7179     # foo a
 7180     (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")
 7181     #
 7182     (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")
 7183     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type/10")
 7184     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-arg-of-user-defined-type/11")
 7185     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/12")
 7186     (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")
 7187     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/14")
 7188     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/15")
 7189     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type/16")
 7190     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/17")
 7191     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/18")
 7192     (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")
 7193     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/20")
 7194     (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")
 7195     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/22")
 7196     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/23")
 7197     # . epilogue
 7198     89/<- %esp 5/r32/ebp
 7199     5d/pop-to-ebp
 7200     c3/return
 7201 
 7202 # we don't have special support for call-by-reference; just explicitly create
 7203 # a new variable with the address of the arg
 7204 test-convert-function-call-with-arg-of-user-defined-type-by-reference:
 7205     # . prologue
 7206     55/push-ebp
 7207     89/<- %ebp 4/r32/esp
 7208     # setup
 7209     (clear-stream _test-input-stream)
 7210     (clear-stream $_test-input-buffered-file->buffer)
 7211     (clear-stream _test-output-stream)
 7212     (clear-stream $_test-output-buffered-file->buffer)
 7213     #
 7214     (write _test-input-stream "fn f {\n")
 7215     (write _test-input-stream "  var a: t\n")
 7216     (write _test-input-stream "  var b/eax: (addr t) <- address a\n")
 7217     (write _test-input-stream "  foo b\n")
 7218     (write _test-input-stream "}\n")
 7219     (write _test-input-stream "fn foo x: (addr t) {\n")
 7220     (write _test-input-stream "  var x/ecx: (addr t) <- copy x\n")
 7221     (write _test-input-stream "}\n")
 7222     (write _test-input-stream "type t {\n")
 7223     (write _test-input-stream "  x: int\n")
 7224     (write _test-input-stream "  y: int\n")
 7225     (write _test-input-stream "}\n")
 7226     # convert
 7227     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7228     (flush _test-output-buffered-file)
 7229 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7235     # check output
 7236     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/0")
 7237     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/1")
 7238     (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")
 7239     (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")
 7240     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/4")
 7241     (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")
 7242     # var a: t
 7243     (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")
 7244     (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")
 7245     # var b/eax: (addr t)
 7246     (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")
 7247     (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")
 7248     # foo a
 7249     (check-next-stream-line-equal _test-output-stream "    (foo %eax)"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/10")
 7250     #
 7251     (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")
 7252     (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")
 7253     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/13")
 7254     (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")
 7255     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/15")
 7256     (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")
 7257     (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")
 7258     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/18")
 7259     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/19")
 7260     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/20")
 7261     (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")
 7262     (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")
 7263     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/23")
 7264     (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")
 7265     (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")
 7266     (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")
 7267     (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")
 7268     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/28")
 7269     (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")
 7270     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/30")
 7271     (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")
 7272     (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")
 7273     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/33")
 7274     # . epilogue
 7275     89/<- %esp 5/r32/ebp
 7276     5d/pop-to-ebp
 7277     c3/return
 7278 
 7279 test-convert-get-on-local-variable:
 7280     # . prologue
 7281     55/push-ebp
 7282     89/<- %ebp 4/r32/esp
 7283     # setup
 7284     (clear-stream _test-input-stream)
 7285     (clear-stream $_test-input-buffered-file->buffer)
 7286     (clear-stream _test-output-stream)
 7287     (clear-stream $_test-output-buffered-file->buffer)
 7288     #
 7289     (write _test-input-stream "fn foo {\n")
 7290     (write _test-input-stream "  var a: t\n")
 7291     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 7292     (write _test-input-stream "}\n")
 7293     (write _test-input-stream "type t {\n")
 7294     (write _test-input-stream "  x: int\n")
 7295     (write _test-input-stream "  y: int\n")
 7296     (write _test-input-stream "}\n")
 7297     # convert
 7298     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7299     (flush _test-output-buffered-file)
 7300 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7306     # check output
 7307     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-local-variable/0")
 7308     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-local-variable/1")
 7309     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-local-variable/2")
 7310     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-local-variable/3")
 7311     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-local-variable/4")
 7312     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-local-variable/5")
 7313     # var a
 7314     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-get-on-local-variable/6")
 7315     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-get-on-local-variable/7")
 7316     # var c
 7317     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-local-variable/8")
 7318     # get
 7319     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0xfffffffc) 0x00000001/r32"  "F - test-convert-get-on-local-variable/9")
 7320     # reclaim c
 7321     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-local-variable/10")
 7322     # reclaim a
 7323     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000008/imm32"  "F - test-convert-get-on-local-variable/11")
 7324     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-local-variable/12")
 7325     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-local-variable/13")
 7326     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-local-variable/14")
 7327     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-local-variable/15")
 7328     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-local-variable/16")
 7329     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-local-variable/17")
 7330     # . epilogue
 7331     89/<- %esp 5/r32/ebp
 7332     5d/pop-to-ebp
 7333     c3/return
 7334 
 7335 test-convert-get-on-function-argument:
 7336     # . prologue
 7337     55/push-ebp
 7338     89/<- %ebp 4/r32/esp
 7339     # setup
 7340     (clear-stream _test-input-stream)
 7341     (clear-stream $_test-input-buffered-file->buffer)
 7342     (clear-stream _test-output-stream)
 7343     (clear-stream $_test-output-buffered-file->buffer)
 7344     #
 7345     (write _test-input-stream "fn foo a: t {\n")
 7346     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 7347     (write _test-input-stream "}\n")
 7348     (write _test-input-stream "type t {\n")
 7349     (write _test-input-stream "  x: int\n")
 7350     (write _test-input-stream "  y: int\n")
 7351     (write _test-input-stream "}\n")
 7352     # convert
 7353     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7354     (flush _test-output-buffered-file)
 7355 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7361     # check output
 7362     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-function-argument/0")
 7363     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-function-argument/1")
 7364     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-function-argument/2")
 7365     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-function-argument/3")
 7366     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-function-argument/4")
 7367     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-function-argument/5")
 7368     # var c
 7369     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-function-argument/6")
 7370     # get
 7371     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0x0000000c) 0x00000001/r32"  "F - test-convert-get-on-function-argument/7")
 7372     # reclaim c
 7373     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-function-argument/8")
 7374     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-function-argument/9")
 7375     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-function-argument/10")
 7376     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-function-argument/11")
 7377     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-function-argument/12")
 7378     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-function-argument/13")
 7379     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-function-argument/14")
 7380     # . epilogue
 7381     89/<- %esp 5/r32/ebp
 7382     5d/pop-to-ebp
 7383     c3/return
 7384 
 7385 test-convert-get-on-function-argument-with-known-type:
 7386     # . prologue
 7387     55/push-ebp
 7388     89/<- %ebp 4/r32/esp
 7389     # setup
 7390     (clear-stream _test-input-stream)
 7391     (clear-stream $_test-input-buffered-file->buffer)
 7392     (clear-stream _test-output-stream)
 7393     (clear-stream $_test-output-buffered-file->buffer)
 7394     #
 7395     (write _test-input-stream "type t {\n")
 7396     (write _test-input-stream "  x: int\n")
 7397     (write _test-input-stream "  y: int\n")
 7398     (write _test-input-stream "}\n")
 7399     (write _test-input-stream "fn foo a: t {\n")
 7400     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 7401     (write _test-input-stream "}\n")
 7402     # convert
 7403     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7404     (flush _test-output-buffered-file)
 7405 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7411     # check output
 7412     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-function-argument-with-known-type/0")
 7413     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-function-argument-with-known-type/1")
 7414     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-function-argument-with-known-type/2")
 7415     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-function-argument-with-known-type/3")
 7416     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-function-argument-with-known-type/4")
 7417     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-function-argument-with-known-type/5")
 7418     # var c
 7419     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-function-argument-with-known-type/6")
 7420     # get
 7421     (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")
 7422     # reclaim c
 7423     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-function-argument-with-known-type/8")
 7424     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-function-argument-with-known-type/9")
 7425     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-function-argument-with-known-type/10")
 7426     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-function-argument-with-known-type/11")
 7427     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-function-argument-with-known-type/12")
 7428     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-function-argument-with-known-type/13")
 7429     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-function-argument-with-known-type/14")
 7430     # . epilogue
 7431     89/<- %esp 5/r32/ebp
 7432     5d/pop-to-ebp
 7433     c3/return
 7434 
 7435 test-add-with-too-many-inouts:
 7436     # . prologue
 7437     55/push-ebp
 7438     89/<- %ebp 4/r32/esp
 7439     # setup
 7440     (clear-stream _test-input-stream)
 7441     (clear-stream $_test-input-buffered-file->buffer)
 7442     (clear-stream _test-output-stream)
 7443     (clear-stream $_test-output-buffered-file->buffer)
 7444     (clear-stream _test-error-stream)
 7445     (clear-stream $_test-error-buffered-file->buffer)
 7446     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7447     68/push 0/imm32
 7448     68/push 0/imm32
 7449     89/<- %edx 4/r32/esp
 7450     (tailor-exit-descriptor %edx 0x10)
 7451     #
 7452     (write _test-input-stream "fn foo {\n")
 7453     (write _test-input-stream "  var a: int\n")
 7454     (write _test-input-stream "  var b/ecx: int <- add a, 0\n")
 7455     (write _test-input-stream "}\n")
 7456     # convert
 7457     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7458     # registers except esp clobbered at this point
 7459     # restore ed
 7460     89/<- %edx 4/r32/esp
 7461     (flush _test-output-buffered-file)
 7462     (flush _test-error-buffered-file)
 7463 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7469     # check output
 7470     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-inouts: output should be empty")
 7471     (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")
 7472     # check that stop(1) was called
 7473     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-inouts: exit status")
 7474     # don't restore from ebp
 7475     81 0/subop/add %esp 8/imm32
 7476     # . epilogue
 7477     5d/pop-to-ebp
 7478     c3/return
 7479 
 7480 test-add-with-too-many-inouts-2:
 7481     # . prologue
 7482     55/push-ebp
 7483     89/<- %ebp 4/r32/esp
 7484     # setup
 7485     (clear-stream _test-input-stream)
 7486     (clear-stream $_test-input-buffered-file->buffer)
 7487     (clear-stream _test-output-stream)
 7488     (clear-stream $_test-output-buffered-file->buffer)
 7489     (clear-stream _test-error-stream)
 7490     (clear-stream $_test-error-buffered-file->buffer)
 7491     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7492     68/push 0/imm32
 7493     68/push 0/imm32
 7494     89/<- %edx 4/r32/esp
 7495     (tailor-exit-descriptor %edx 0x10)
 7496     #
 7497     (write _test-input-stream "fn foo {\n")
 7498     (write _test-input-stream "  var a: int\n")
 7499     (write _test-input-stream "  add-to a, 0, 1\n")
 7500     (write _test-input-stream "}\n")
 7501     # convert
 7502     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7503     # registers except esp clobbered at this point
 7504     # restore ed
 7505     89/<- %edx 4/r32/esp
 7506     (flush _test-output-buffered-file)
 7507     (flush _test-error-buffered-file)
 7508 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7514     # check output
 7515     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-inouts-2: output should be empty")
 7516     (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")
 7517     # check that stop(1) was called
 7518     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-inouts-2: exit status")
 7519     # don't restore from ebp
 7520     81 0/subop/add %esp 8/imm32
 7521     # . epilogue
 7522     5d/pop-to-ebp
 7523     c3/return
 7524 
 7525 test-add-with-too-many-outputs:
 7526     # . prologue
 7527     55/push-ebp
 7528     89/<- %ebp 4/r32/esp
 7529     # setup
 7530     (clear-stream _test-input-stream)
 7531     (clear-stream $_test-input-buffered-file->buffer)
 7532     (clear-stream _test-output-stream)
 7533     (clear-stream $_test-output-buffered-file->buffer)
 7534     (clear-stream _test-error-stream)
 7535     (clear-stream $_test-error-buffered-file->buffer)
 7536     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7537     68/push 0/imm32
 7538     68/push 0/imm32
 7539     89/<- %edx 4/r32/esp
 7540     (tailor-exit-descriptor %edx 0x10)
 7541     #
 7542     (write _test-input-stream "fn foo {\n")
 7543     (write _test-input-stream "  var a/eax: int <- copy 0\n")
 7544     (write _test-input-stream "  var b/ebx: int <- copy 0\n")
 7545     (write _test-input-stream "  var c/ecx: int <- copy 0\n")
 7546     (write _test-input-stream "  c, b <- add a\n")
 7547     (write _test-input-stream "}\n")
 7548     # convert
 7549     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7550     # registers except esp clobbered at this point
 7551     # restore ed
 7552     89/<- %edx 4/r32/esp
 7553     (flush _test-output-buffered-file)
 7554     (flush _test-error-buffered-file)
 7555 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7561     # check output
 7562     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-outputs: output should be empty")
 7563     (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")
 7564     # check that stop(1) was called
 7565     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-outputs: exit status")
 7566     # don't restore from ebp
 7567     81 0/subop/add %esp 8/imm32
 7568     # . epilogue
 7569     5d/pop-to-ebp
 7570     c3/return
 7571 
 7572 test-add-with-non-number:
 7573     # . prologue
 7574     55/push-ebp
 7575     89/<- %ebp 4/r32/esp
 7576     # setup
 7577     (clear-stream _test-input-stream)
 7578     (clear-stream $_test-input-buffered-file->buffer)
 7579     (clear-stream _test-output-stream)
 7580     (clear-stream $_test-output-buffered-file->buffer)
 7581     (clear-stream _test-error-stream)
 7582     (clear-stream $_test-error-buffered-file->buffer)
 7583     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7584     68/push 0/imm32
 7585     68/push 0/imm32
 7586     89/<- %edx 4/r32/esp
 7587     (tailor-exit-descriptor %edx 0x10)
 7588     #
 7589     (write _test-input-stream "fn foo {\n")
 7590     (write _test-input-stream "  var a: int\n")
 7591     (write _test-input-stream "  var b/ecx: (addr int) <- add a\n")
 7592     (write _test-input-stream "}\n")
 7593     # convert
 7594     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7595     # registers except esp clobbered at this point
 7596     # restore ed
 7597     89/<- %edx 4/r32/esp
 7598     (flush _test-output-buffered-file)
 7599     (flush _test-error-buffered-file)
 7600 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7606     # check output
 7607     (check-stream-equal _test-output-stream  ""  "F - test-add-with-non-number: output should be empty")
 7608     (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")
 7609     # check that stop(1) was called
 7610     (check-ints-equal *(edx+4) 2 "F - test-add-with-non-number: exit status")
 7611     # don't restore from ebp
 7612     81 0/subop/add %esp 8/imm32
 7613     # . epilogue
 7614     5d/pop-to-ebp
 7615     c3/return
 7616 
 7617 test-add-with-addr-dereferenced:
 7618     # . prologue
 7619     55/push-ebp
 7620     89/<- %ebp 4/r32/esp
 7621     # setup
 7622     (clear-stream _test-input-stream)
 7623     (clear-stream $_test-input-buffered-file->buffer)
 7624     (clear-stream _test-output-stream)
 7625     (clear-stream $_test-output-buffered-file->buffer)
 7626     #
 7627     (write _test-input-stream "fn foo {\n")
 7628     (write _test-input-stream "  var a/eax: (addr int) <- copy 0\n")
 7629     (write _test-input-stream "  add-to *a, 1\n")
 7630     (write _test-input-stream "}\n")
 7631     # convert
 7632     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7633     (flush _test-output-buffered-file)
 7634     # no error
 7635     # . epilogue
 7636     89/<- %esp 5/r32/ebp
 7637     5d/pop-to-ebp
 7638     c3/return
 7639 
 7640 test-copy-with-no-inout:
 7641     # . prologue
 7642     55/push-ebp
 7643     89/<- %ebp 4/r32/esp
 7644     # setup
 7645     (clear-stream _test-input-stream)
 7646     (clear-stream $_test-input-buffered-file->buffer)
 7647     (clear-stream _test-output-stream)
 7648     (clear-stream $_test-output-buffered-file->buffer)
 7649     (clear-stream _test-error-stream)
 7650     (clear-stream $_test-error-buffered-file->buffer)
 7651     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7652     68/push 0/imm32
 7653     68/push 0/imm32
 7654     89/<- %edx 4/r32/esp
 7655     (tailor-exit-descriptor %edx 0x10)
 7656     #
 7657     (write _test-input-stream "fn foo {\n")
 7658     (write _test-input-stream "  var x/eax: boolean <- copy\n")
 7659     (write _test-input-stream "}\n")
 7660     # convert
 7661     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7662     # registers except esp clobbered at this point
 7663     # restore ed
 7664     89/<- %edx 4/r32/esp
 7665     (flush _test-output-buffered-file)
 7666     (flush _test-error-buffered-file)
 7667 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7673     # check output
 7674     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-no-inout: output should be empty")
 7675     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy' expects an inout"  "F - test-copy-with-no-inout: error message")
 7676     # check that stop(1) was called
 7677     (check-ints-equal *(edx+4) 2 "F - test-copy-with-no-inout: exit status")
 7678     # don't restore from ebp
 7679     81 0/subop/add %esp 8/imm32
 7680     # . epilogue
 7681     5d/pop-to-ebp
 7682     c3/return
 7683 
 7684 test-copy-with-multiple-inouts:
 7685     # . prologue
 7686     55/push-ebp
 7687     89/<- %ebp 4/r32/esp
 7688     # setup
 7689     (clear-stream _test-input-stream)
 7690     (clear-stream $_test-input-buffered-file->buffer)
 7691     (clear-stream _test-output-stream)
 7692     (clear-stream $_test-output-buffered-file->buffer)
 7693     (clear-stream _test-error-stream)
 7694     (clear-stream $_test-error-buffered-file->buffer)
 7695     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7696     68/push 0/imm32
 7697     68/push 0/imm32
 7698     89/<- %edx 4/r32/esp
 7699     (tailor-exit-descriptor %edx 0x10)
 7700     #
 7701     (write _test-input-stream "fn foo {\n")
 7702     (write _test-input-stream "  var x/eax: boolean <- copy 0, 0\n")
 7703     (write _test-input-stream "}\n")
 7704     # convert
 7705     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7706     # registers except esp clobbered at this point
 7707     # restore ed
 7708     89/<- %edx 4/r32/esp
 7709     (flush _test-output-buffered-file)
 7710     (flush _test-error-buffered-file)
 7711 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7717     # check output
 7718     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-multiple-inouts: output should be empty")
 7719     (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")
 7720     # check that stop(1) was called
 7721     (check-ints-equal *(edx+4) 2 "F - test-copy-with-multiple-inouts: exit status")
 7722     # don't restore from ebp
 7723     81 0/subop/add %esp 8/imm32
 7724     # . epilogue
 7725     5d/pop-to-ebp
 7726     c3/return
 7727 
 7728 test-copy-with-no-output:
 7729     # . prologue
 7730     55/push-ebp
 7731     89/<- %ebp 4/r32/esp
 7732     # setup
 7733     (clear-stream _test-input-stream)
 7734     (clear-stream $_test-input-buffered-file->buffer)
 7735     (clear-stream _test-output-stream)
 7736     (clear-stream $_test-output-buffered-file->buffer)
 7737     (clear-stream _test-error-stream)
 7738     (clear-stream $_test-error-buffered-file->buffer)
 7739     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7740     68/push 0/imm32
 7741     68/push 0/imm32
 7742     89/<- %edx 4/r32/esp
 7743     (tailor-exit-descriptor %edx 0x10)
 7744     #
 7745     (write _test-input-stream "fn foo {\n")
 7746     (write _test-input-stream "  copy 0\n")
 7747     (write _test-input-stream "}\n")
 7748     # convert
 7749     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7750     # registers except esp clobbered at this point
 7751     # restore ed
 7752     89/<- %edx 4/r32/esp
 7753     (flush _test-output-buffered-file)
 7754     (flush _test-error-buffered-file)
 7755 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7761     # check output
 7762     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-no-output: output should be empty")
 7763     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy' expects an output"  "F - test-copy-with-no-output: error message")
 7764     # check that stop(1) was called
 7765     (check-ints-equal *(edx+4) 2 "F - test-copy-with-no-output: exit status")
 7766     # don't restore from ebp
 7767     81 0/subop/add %esp 8/imm32
 7768     # . epilogue
 7769     5d/pop-to-ebp
 7770     c3/return
 7771 
 7772 test-copy-with-multiple-outputs:
 7773     # . prologue
 7774     55/push-ebp
 7775     89/<- %ebp 4/r32/esp
 7776     # setup
 7777     (clear-stream _test-input-stream)
 7778     (clear-stream $_test-input-buffered-file->buffer)
 7779     (clear-stream _test-output-stream)
 7780     (clear-stream $_test-output-buffered-file->buffer)
 7781     (clear-stream _test-error-stream)
 7782     (clear-stream $_test-error-buffered-file->buffer)
 7783     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7784     68/push 0/imm32
 7785     68/push 0/imm32
 7786     89/<- %edx 4/r32/esp
 7787     (tailor-exit-descriptor %edx 0x10)
 7788     #
 7789     (write _test-input-stream "fn foo {\n")
 7790     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 7791     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
 7792     (write _test-input-stream "  x, y <- copy 0\n")
 7793     (write _test-input-stream "}\n")
 7794     # convert
 7795     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7796     # registers except esp clobbered at this point
 7797     # restore ed
 7798     89/<- %edx 4/r32/esp
 7799     (flush _test-output-buffered-file)
 7800     (flush _test-error-buffered-file)
 7801 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7807     # check output
 7808     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-multiple-outputs: output should be empty")
 7809     (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")
 7810     # check that stop(1) was called
 7811     (check-ints-equal *(edx+4) 2 "F - test-copy-with-multiple-outputs: exit status")
 7812     # don't restore from ebp
 7813     81 0/subop/add %esp 8/imm32
 7814     # . epilogue
 7815     5d/pop-to-ebp
 7816     c3/return
 7817 
 7818 test-copy-invalid-value-to-address:
 7819     # . prologue
 7820     55/push-ebp
 7821     89/<- %ebp 4/r32/esp
 7822     # setup
 7823     (clear-stream _test-input-stream)
 7824     (clear-stream $_test-input-buffered-file->buffer)
 7825     (clear-stream _test-output-stream)
 7826     (clear-stream $_test-output-buffered-file->buffer)
 7827     (clear-stream _test-error-stream)
 7828     (clear-stream $_test-error-buffered-file->buffer)
 7829     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7830     68/push 0/imm32
 7831     68/push 0/imm32
 7832     89/<- %edx 4/r32/esp
 7833     (tailor-exit-descriptor %edx 0x10)
 7834     #
 7835     (write _test-input-stream "fn foo {\n")
 7836     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 7837     (write _test-input-stream "  var y/ecx: (addr int) <- copy x\n")
 7838     (write _test-input-stream "}\n")
 7839     # convert
 7840     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7841     # registers except esp clobbered at this point
 7842     # restore ed
 7843     89/<- %edx 4/r32/esp
 7844     (flush _test-output-buffered-file)
 7845     (flush _test-error-buffered-file)
 7846 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7852     # check output
 7853     (check-stream-equal _test-output-stream  ""  "F - test-copy-invalid-value-to-address: output should be empty")
 7854     (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")
 7855     # check that stop(1) was called
 7856     (check-ints-equal *(edx+4) 2 "F - test-copy-invalid-value-to-address: exit status")
 7857     # don't restore from ebp
 7858     81 0/subop/add %esp 8/imm32
 7859     # . epilogue
 7860     5d/pop-to-ebp
 7861     c3/return
 7862 
 7863 test-copy-null-value-to-address:
 7864     # . prologue
 7865     55/push-ebp
 7866     89/<- %ebp 4/r32/esp
 7867     # setup
 7868     (clear-stream _test-input-stream)
 7869     (clear-stream $_test-input-buffered-file->buffer)
 7870     (clear-stream _test-output-stream)
 7871     (clear-stream $_test-output-buffered-file->buffer)
 7872     #
 7873     (write _test-input-stream "fn foo {\n")
 7874     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
 7875     (write _test-input-stream "}\n")
 7876     # convert
 7877     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7878     (flush _test-output-buffered-file)
 7879     # no errors
 7880     # . epilogue
 7881     89/<- %esp 5/r32/ebp
 7882     5d/pop-to-ebp
 7883     c3/return
 7884 
 7885 test-copy-invalid-value-to-offset:
 7886     # . prologue
 7887     55/push-ebp
 7888     89/<- %ebp 4/r32/esp
 7889     # setup
 7890     (clear-stream _test-input-stream)
 7891     (clear-stream $_test-input-buffered-file->buffer)
 7892     (clear-stream _test-output-stream)
 7893     (clear-stream $_test-output-buffered-file->buffer)
 7894     (clear-stream _test-error-stream)
 7895     (clear-stream $_test-error-buffered-file->buffer)
 7896     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7897     68/push 0/imm32
 7898     68/push 0/imm32
 7899     89/<- %edx 4/r32/esp
 7900     (tailor-exit-descriptor %edx 0x10)
 7901     #
 7902     (write _test-input-stream "fn foo {\n")
 7903     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 7904     (write _test-input-stream "  var y/ecx: (offset int) <- copy x\n")
 7905     (write _test-input-stream "}\n")
 7906     # convert
 7907     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7908     # registers except esp clobbered at this point
 7909     # restore ed
 7910     89/<- %edx 4/r32/esp
 7911     (flush _test-output-buffered-file)
 7912     (flush _test-error-buffered-file)
 7913 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7919     # check output
 7920     (check-stream-equal _test-output-stream  ""  "F - test-copy-invalid-value-to-address: output should be empty")
 7921     (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")
 7922     # check that stop(1) was called
 7923     (check-ints-equal *(edx+4) 2 "F - test-copy-invalid-value-to-offset: exit status")
 7924     # don't restore from ebp
 7925     81 0/subop/add %esp 8/imm32
 7926     # . epilogue
 7927     5d/pop-to-ebp
 7928     c3/return
 7929 
 7930 test-copy-null-value-to-offset:
 7931     # . prologue
 7932     55/push-ebp
 7933     89/<- %ebp 4/r32/esp
 7934     # setup
 7935     (clear-stream _test-input-stream)
 7936     (clear-stream $_test-input-buffered-file->buffer)
 7937     (clear-stream _test-output-stream)
 7938     (clear-stream $_test-output-buffered-file->buffer)
 7939     #
 7940     (write _test-input-stream "fn foo {\n")
 7941     (write _test-input-stream "  var y/ecx: (offset int) <- copy 0\n")
 7942     (write _test-input-stream "}\n")
 7943     # convert
 7944     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7945     (flush _test-output-buffered-file)
 7946 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7952     # no errors
 7953     # . epilogue
 7954     89/<- %esp 5/r32/ebp
 7955     5d/pop-to-ebp
 7956     c3/return
 7957 
 7958 test-copy-non-literal-to-byte:
 7959     # . prologue
 7960     55/push-ebp
 7961     89/<- %ebp 4/r32/esp
 7962     # setup
 7963     (clear-stream _test-input-stream)
 7964     (clear-stream $_test-input-buffered-file->buffer)
 7965     (clear-stream _test-output-stream)
 7966     (clear-stream $_test-output-buffered-file->buffer)
 7967     (clear-stream _test-error-stream)
 7968     (clear-stream $_test-error-buffered-file->buffer)
 7969     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7970     68/push 0/imm32
 7971     68/push 0/imm32
 7972     89/<- %edx 4/r32/esp
 7973     (tailor-exit-descriptor %edx 0x10)
 7974     #
 7975     (write _test-input-stream "fn foo {\n")
 7976     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 7977     (write _test-input-stream "  var y/ecx: byte <- copy x\n")
 7978     (write _test-input-stream "}\n")
 7979     # convert
 7980     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7981     # registers except esp clobbered at this point
 7982     # restore ed
 7983     89/<- %edx 4/r32/esp
 7984     (flush _test-output-buffered-file)
 7985     (flush _test-error-buffered-file)
 7986 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7992     # check output
 7993     (check-stream-equal _test-output-stream  ""  "F - test-copy-non-literal-to-byte: output should be empty")
 7994     (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")
 7995     # check that stop(1) was called
 7996     (check-ints-equal *(edx+4) 2 "F - test-copy-non-literal-to-byte: exit status")
 7997     # don't restore from ebp
 7998     81 0/subop/add %esp 8/imm32
 7999     # . epilogue
 8000     5d/pop-to-ebp
 8001     c3/return
 8002 
 8003 test-copy-deref-address:
 8004     # . prologue
 8005     55/push-ebp
 8006     89/<- %ebp 4/r32/esp
 8007     # setup
 8008     (clear-stream _test-input-stream)
 8009     (clear-stream $_test-input-buffered-file->buffer)
 8010     (clear-stream _test-output-stream)
 8011     (clear-stream $_test-output-buffered-file->buffer)
 8012     #
 8013     (write _test-input-stream "fn foo {\n")
 8014     (write _test-input-stream "  var x/eax: (addr addr int) <- copy 0\n")
 8015     (write _test-input-stream "  var y/ecx: (addr int) <- copy *x\n")
 8016     (write _test-input-stream "}\n")
 8017     # convert
 8018     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8019     (flush _test-output-buffered-file)
 8020     # no errors
 8021     # . epilogue
 8022     5d/pop-to-ebp
 8023     c3/return
 8024 
 8025 test-copy-to-non-register:
 8026     # . prologue
 8027     55/push-ebp
 8028     89/<- %ebp 4/r32/esp
 8029     # setup
 8030     (clear-stream _test-input-stream)
 8031     (clear-stream $_test-input-buffered-file->buffer)
 8032     (clear-stream _test-output-stream)
 8033     (clear-stream $_test-output-buffered-file->buffer)
 8034     (clear-stream _test-error-stream)
 8035     (clear-stream $_test-error-buffered-file->buffer)
 8036     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8037     68/push 0/imm32
 8038     68/push 0/imm32
 8039     89/<- %edx 4/r32/esp
 8040     (tailor-exit-descriptor %edx 0x10)
 8041     #
 8042     (write _test-input-stream "fn foo {\n")
 8043     (write _test-input-stream "  var x: int\n")
 8044     (write _test-input-stream "  x <- copy 0\n")
 8045     (write _test-input-stream "}\n")
 8046     # convert
 8047     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8048     # registers except esp clobbered at this point
 8049     # restore ed
 8050     89/<- %edx 4/r32/esp
 8051     (flush _test-output-buffered-file)
 8052     (flush _test-error-buffered-file)
 8053 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8059     # check output
 8060     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-non-register: output should be empty")
 8061     (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")
 8062     # check that stop(1) was called
 8063     (check-ints-equal *(edx+4) 2 "F - test-copy-to-non-register: exit status")
 8064     # don't restore from ebp
 8065     81 0/subop/add %esp 8/imm32
 8066     # . epilogue
 8067     5d/pop-to-ebp
 8068     c3/return
 8069 
 8070 test-copy-from-non-scalar-inout:
 8071     # . prologue
 8072     55/push-ebp
 8073     89/<- %ebp 4/r32/esp
 8074     # setup
 8075     (clear-stream _test-input-stream)
 8076     (clear-stream $_test-input-buffered-file->buffer)
 8077     (clear-stream _test-output-stream)
 8078     (clear-stream $_test-output-buffered-file->buffer)
 8079     (clear-stream _test-error-stream)
 8080     (clear-stream $_test-error-buffered-file->buffer)
 8081     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8082     68/push 0/imm32
 8083     68/push 0/imm32
 8084     89/<- %edx 4/r32/esp
 8085     (tailor-exit-descriptor %edx 0x10)
 8086     #
 8087     (write _test-input-stream "fn foo {\n")
 8088     (write _test-input-stream "  var x: (handle int)\n")
 8089     (write _test-input-stream "  var y/eax: int <- copy x\n")
 8090     (write _test-input-stream "}\n")
 8091     # convert
 8092     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8093     # registers except esp clobbered at this point
 8094     # restore ed
 8095     89/<- %edx 4/r32/esp
 8096     (flush _test-output-buffered-file)
 8097     (flush _test-error-buffered-file)
 8098 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8104     # check output
 8105     (check-stream-equal _test-output-stream  ""  "F - test-copy-from-non-scalar-inout: output should be empty")
 8106     (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")
 8107     # check that stop(1) was called
 8108     (check-ints-equal *(edx+4) 2 "F - test-copy-from-non-scalar-inout: exit status")
 8109     # don't restore from ebp
 8110     81 0/subop/add %esp 8/imm32
 8111     # . epilogue
 8112     5d/pop-to-ebp
 8113     c3/return
 8114 
 8115 test-copy-to-with-no-inout:
 8116     # . prologue
 8117     55/push-ebp
 8118     89/<- %ebp 4/r32/esp
 8119     # setup
 8120     (clear-stream _test-input-stream)
 8121     (clear-stream $_test-input-buffered-file->buffer)
 8122     (clear-stream _test-output-stream)
 8123     (clear-stream $_test-output-buffered-file->buffer)
 8124     (clear-stream _test-error-stream)
 8125     (clear-stream $_test-error-buffered-file->buffer)
 8126     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8127     68/push 0/imm32
 8128     68/push 0/imm32
 8129     89/<- %edx 4/r32/esp
 8130     (tailor-exit-descriptor %edx 0x10)
 8131     #
 8132     (write _test-input-stream "fn foo {\n")
 8133     (write _test-input-stream "  copy-to\n")
 8134     (write _test-input-stream "}\n")
 8135     # convert
 8136     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8137     # registers except esp clobbered at this point
 8138     # restore ed
 8139     89/<- %edx 4/r32/esp
 8140     (flush _test-output-buffered-file)
 8141     (flush _test-error-buffered-file)
 8142 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8148     # check output
 8149     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-no-inout: output should be empty")
 8150     (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")
 8151     # check that stop(1) was called
 8152     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-inout: exit status")
 8153     # don't restore from ebp
 8154     81 0/subop/add %esp 8/imm32
 8155     # . epilogue
 8156     5d/pop-to-ebp
 8157     c3/return
 8158 
 8159 test-copy-to-with-no-source:
 8160     # . prologue
 8161     55/push-ebp
 8162     89/<- %ebp 4/r32/esp
 8163     # setup
 8164     (clear-stream _test-input-stream)
 8165     (clear-stream $_test-input-buffered-file->buffer)
 8166     (clear-stream _test-output-stream)
 8167     (clear-stream $_test-output-buffered-file->buffer)
 8168     (clear-stream _test-error-stream)
 8169     (clear-stream $_test-error-buffered-file->buffer)
 8170     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8171     68/push 0/imm32
 8172     68/push 0/imm32
 8173     89/<- %edx 4/r32/esp
 8174     (tailor-exit-descriptor %edx 0x10)
 8175     #
 8176     (write _test-input-stream "fn foo {\n")
 8177     (write _test-input-stream "  var x: boolean\n")
 8178     (write _test-input-stream "  copy-to x\n")
 8179     (write _test-input-stream "}\n")
 8180     # convert
 8181     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8182     # registers except esp clobbered at this point
 8183     # restore ed
 8184     89/<- %edx 4/r32/esp
 8185     (flush _test-output-buffered-file)
 8186     (flush _test-error-buffered-file)
 8187 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8193     # check output
 8194     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-no-source: output should be empty")
 8195     (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")
 8196     # check that stop(1) was called
 8197     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-source: exit status")
 8198     # don't restore from ebp
 8199     81 0/subop/add %esp 8/imm32
 8200     # . epilogue
 8201     5d/pop-to-ebp
 8202     c3/return
 8203 
 8204 test-copy-to-with-no-register:
 8205     # . prologue
 8206     55/push-ebp
 8207     89/<- %ebp 4/r32/esp
 8208     # setup
 8209     (clear-stream _test-input-stream)
 8210     (clear-stream $_test-input-buffered-file->buffer)
 8211     (clear-stream _test-output-stream)
 8212     (clear-stream $_test-output-buffered-file->buffer)
 8213     (clear-stream _test-error-stream)
 8214     (clear-stream $_test-error-buffered-file->buffer)
 8215     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8216     68/push 0/imm32
 8217     68/push 0/imm32
 8218     89/<- %edx 4/r32/esp
 8219     (tailor-exit-descriptor %edx 0x10)
 8220     #
 8221     (write _test-input-stream "fn foo {\n")
 8222     (write _test-input-stream "  var x: boolean\n")
 8223     (write _test-input-stream "  copy-to x, x\n")
 8224     (write _test-input-stream "}\n")
 8225     # convert
 8226     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8227     # registers except esp clobbered at this point
 8228     # restore ed
 8229     89/<- %edx 4/r32/esp
 8230     (flush _test-output-buffered-file)
 8231     (flush _test-error-buffered-file)
 8232 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8238     # check output
 8239     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-no-register: output should be empty")
 8240     (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")
 8241     # check that stop(1) was called
 8242     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-register: exit status")
 8243     # don't restore from ebp
 8244     81 0/subop/add %esp 8/imm32
 8245     # . epilogue
 8246     5d/pop-to-ebp
 8247     c3/return
 8248 
 8249 test-copy-to-with-too-many-inouts:
 8250     # . prologue
 8251     55/push-ebp
 8252     89/<- %ebp 4/r32/esp
 8253     # setup
 8254     (clear-stream _test-input-stream)
 8255     (clear-stream $_test-input-buffered-file->buffer)
 8256     (clear-stream _test-output-stream)
 8257     (clear-stream $_test-output-buffered-file->buffer)
 8258     (clear-stream _test-error-stream)
 8259     (clear-stream $_test-error-buffered-file->buffer)
 8260     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8261     68/push 0/imm32
 8262     68/push 0/imm32
 8263     89/<- %edx 4/r32/esp
 8264     (tailor-exit-descriptor %edx 0x10)
 8265     #
 8266     (write _test-input-stream "fn foo {\n")
 8267     (write _test-input-stream "  var x: boolean\n")
 8268     (write _test-input-stream "  copy-to x, 0, 0\n")
 8269     (write _test-input-stream "}\n")
 8270     # convert
 8271     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8272     # registers except esp clobbered at this point
 8273     # restore ed
 8274     89/<- %edx 4/r32/esp
 8275     (flush _test-output-buffered-file)
 8276     (flush _test-error-buffered-file)
 8277 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8283     # check output
 8284     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-too-many-inouts: output should be empty")
 8285     (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")
 8286     # check that stop(1) was called
 8287     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-too-many-inouts: exit status")
 8288     # don't restore from ebp
 8289     81 0/subop/add %esp 8/imm32
 8290     # . epilogue
 8291     5d/pop-to-ebp
 8292     c3/return
 8293 
 8294 test-copy-to-with-output:
 8295     # . prologue
 8296     55/push-ebp
 8297     89/<- %ebp 4/r32/esp
 8298     # setup
 8299     (clear-stream _test-input-stream)
 8300     (clear-stream $_test-input-buffered-file->buffer)
 8301     (clear-stream _test-output-stream)
 8302     (clear-stream $_test-output-buffered-file->buffer)
 8303     (clear-stream _test-error-stream)
 8304     (clear-stream $_test-error-buffered-file->buffer)
 8305     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8306     68/push 0/imm32
 8307     68/push 0/imm32
 8308     89/<- %edx 4/r32/esp
 8309     (tailor-exit-descriptor %edx 0x10)
 8310     #
 8311     (write _test-input-stream "fn foo {\n")
 8312     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 8313     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
 8314     (write _test-input-stream "  x <- copy-to y, 0\n")
 8315     (write _test-input-stream "}\n")
 8316     # convert
 8317     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8318     # registers except esp clobbered at this point
 8319     # restore ed
 8320     89/<- %edx 4/r32/esp
 8321     (flush _test-output-buffered-file)
 8322     (flush _test-error-buffered-file)
 8323 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8329     # check output
 8330     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-output: output should be empty")
 8331     (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")
 8332     # check that stop(1) was called
 8333     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-output: exit status")
 8334     # don't restore from ebp
 8335     81 0/subop/add %esp 8/imm32
 8336     # . epilogue
 8337     5d/pop-to-ebp
 8338     c3/return
 8339 
 8340 test-copy-to-invalid-value-to-address:
 8341     # . prologue
 8342     55/push-ebp
 8343     89/<- %ebp 4/r32/esp
 8344     # setup
 8345     (clear-stream _test-input-stream)
 8346     (clear-stream $_test-input-buffered-file->buffer)
 8347     (clear-stream _test-output-stream)
 8348     (clear-stream $_test-output-buffered-file->buffer)
 8349     (clear-stream _test-error-stream)
 8350     (clear-stream $_test-error-buffered-file->buffer)
 8351     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8352     68/push 0/imm32
 8353     68/push 0/imm32
 8354     89/<- %edx 4/r32/esp
 8355     (tailor-exit-descriptor %edx 0x10)
 8356     #
 8357     (write _test-input-stream "fn foo {\n")
 8358     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 8359     (write _test-input-stream "  var y: (addr int)\n")
 8360     (write _test-input-stream "  copy-to y, x\n")
 8361     (write _test-input-stream "}\n")
 8362     # convert
 8363     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8364     # registers except esp clobbered at this point
 8365     # restore ed
 8366     89/<- %edx 4/r32/esp
 8367     (flush _test-output-buffered-file)
 8368     (flush _test-error-buffered-file)
 8369 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8375     # check output
 8376     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-invalid-value-to-address: output should be empty")
 8377     (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")
 8378     # check that stop(1) was called
 8379     (check-ints-equal *(edx+4) 2 "F - test-copy-to-invalid-value-to-address: exit status")
 8380     # don't restore from ebp
 8381     81 0/subop/add %esp 8/imm32
 8382     # . epilogue
 8383     5d/pop-to-ebp
 8384     c3/return
 8385 
 8386 test-copy-to-null-value-to-address:
 8387     # . prologue
 8388     55/push-ebp
 8389     89/<- %ebp 4/r32/esp
 8390     # setup
 8391     (clear-stream _test-input-stream)
 8392     (clear-stream $_test-input-buffered-file->buffer)
 8393     (clear-stream _test-output-stream)
 8394     (clear-stream $_test-output-buffered-file->buffer)
 8395     #
 8396     (write _test-input-stream "fn foo {\n")
 8397     (write _test-input-stream "  var y: (addr int)\n")
 8398     (write _test-input-stream "  copy-to y, 0\n")
 8399     (write _test-input-stream "}\n")
 8400     # convert
 8401     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8402     (flush _test-output-buffered-file)
 8403     # no errors
 8404     # . epilogue
 8405     89/<- %esp 5/r32/ebp
 8406     5d/pop-to-ebp
 8407     c3/return
 8408 
 8409 test-copy-to-invalid-value-to-offset:
 8410     # . prologue
 8411     55/push-ebp
 8412     89/<- %ebp 4/r32/esp
 8413     # setup
 8414     (clear-stream _test-input-stream)
 8415     (clear-stream $_test-input-buffered-file->buffer)
 8416     (clear-stream _test-output-stream)
 8417     (clear-stream $_test-output-buffered-file->buffer)
 8418     (clear-stream _test-error-stream)
 8419     (clear-stream $_test-error-buffered-file->buffer)
 8420     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8421     68/push 0/imm32
 8422     68/push 0/imm32
 8423     89/<- %edx 4/r32/esp
 8424     (tailor-exit-descriptor %edx 0x10)
 8425     #
 8426     (write _test-input-stream "fn foo {\n")
 8427     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 8428     (write _test-input-stream "  var y: (offset int)\n")
 8429     (write _test-input-stream "  copy-to y, x\n")
 8430     (write _test-input-stream "}\n")
 8431     # convert
 8432     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8433     # registers except esp clobbered at this point
 8434     # restore ed
 8435     89/<- %edx 4/r32/esp
 8436     (flush _test-output-buffered-file)
 8437     (flush _test-error-buffered-file)
 8438 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8444     # check output
 8445     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-invalid-value-to-offset: output should be empty")
 8446     (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")
 8447     # check that stop(1) was called
 8448     (check-ints-equal *(edx+4) 2 "F - test-copy-to-invalid-value-to-offset: exit status")
 8449     # don't restore from ebp
 8450     81 0/subop/add %esp 8/imm32
 8451     # . epilogue
 8452     5d/pop-to-ebp
 8453     c3/return
 8454 
 8455 test-copy-to-null-value-to-offset:
 8456     # . prologue
 8457     55/push-ebp
 8458     89/<- %ebp 4/r32/esp
 8459     # setup
 8460     (clear-stream _test-input-stream)
 8461     (clear-stream $_test-input-buffered-file->buffer)
 8462     (clear-stream _test-output-stream)
 8463     (clear-stream $_test-output-buffered-file->buffer)
 8464     #
 8465     (write _test-input-stream "fn foo {\n")
 8466     (write _test-input-stream "  var y: (offset int)\n")
 8467     (write _test-input-stream "  copy-to y, 0\n")
 8468     (write _test-input-stream "}\n")
 8469     # convert
 8470     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8471     (flush _test-output-buffered-file)
 8472     # no errors
 8473     # . epilogue
 8474     89/<- %esp 5/r32/ebp
 8475     5d/pop-to-ebp
 8476     c3/return
 8477 
 8478 test-copy-to-non-literal-to-byte:
 8479     # . prologue
 8480     55/push-ebp
 8481     89/<- %ebp 4/r32/esp
 8482     # setup
 8483     (clear-stream _test-input-stream)
 8484     (clear-stream $_test-input-buffered-file->buffer)
 8485     (clear-stream _test-output-stream)
 8486     (clear-stream $_test-output-buffered-file->buffer)
 8487     (clear-stream _test-error-stream)
 8488     (clear-stream $_test-error-buffered-file->buffer)
 8489     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8490     68/push 0/imm32
 8491     68/push 0/imm32
 8492     89/<- %edx 4/r32/esp
 8493     (tailor-exit-descriptor %edx 0x10)
 8494     #
 8495     (write _test-input-stream "fn foo {\n")
 8496     (write _test-input-stream "  var x/ecx: byte <- copy 3\n")
 8497     (write _test-input-stream "  var y/eax: (addr byte) <- copy 0\n")
 8498     (write _test-input-stream "  copy-to *y, x\n")
 8499     (write _test-input-stream "}\n")
 8500     # convert
 8501     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8502     # registers except esp clobbered at this point
 8503     # restore ed
 8504     89/<- %edx 4/r32/esp
 8505     (flush _test-output-buffered-file)
 8506     (flush _test-error-buffered-file)
 8507 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8513     # check output
 8514     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-non-literal-to-byte: output should be empty")
 8515     (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")
 8516     # check that stop(1) was called
 8517     (check-ints-equal *(edx+4) 2 "F - test-copy-to-non-literal-to-byte: exit status")
 8518     # don't restore from ebp
 8519     81 0/subop/add %esp 8/imm32
 8520     # . epilogue
 8521     5d/pop-to-ebp
 8522     c3/return
 8523 
 8524 test-copy-to-deref-address:
 8525     # . prologue
 8526     55/push-ebp
 8527     89/<- %ebp 4/r32/esp
 8528     # setup
 8529     (clear-stream _test-input-stream)
 8530     (clear-stream $_test-input-buffered-file->buffer)
 8531     (clear-stream _test-output-stream)
 8532     (clear-stream $_test-output-buffered-file->buffer)
 8533     #
 8534     (write _test-input-stream "fn foo {\n")
 8535     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
 8536     (write _test-input-stream "  var y/ecx: (addr addr int) <- copy 0\n")
 8537     (write _test-input-stream "  copy-to *y, x\n")
 8538     (write _test-input-stream "}\n")
 8539     # convert
 8540     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8541     (flush _test-output-buffered-file)
 8542     # no errors
 8543     # . epilogue
 8544     5d/pop-to-ebp
 8545     c3/return
 8546 
 8547 test-copy-to-from-non-scalar-inout:
 8548     # . prologue
 8549     55/push-ebp
 8550     89/<- %ebp 4/r32/esp
 8551     # setup
 8552     (clear-stream _test-input-stream)
 8553     (clear-stream $_test-input-buffered-file->buffer)
 8554     (clear-stream _test-output-stream)
 8555     (clear-stream $_test-output-buffered-file->buffer)
 8556     (clear-stream _test-error-stream)
 8557     (clear-stream $_test-error-buffered-file->buffer)
 8558     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8559     68/push 0/imm32
 8560     68/push 0/imm32
 8561     89/<- %edx 4/r32/esp
 8562     (tailor-exit-descriptor %edx 0x10)
 8563     #
 8564     (write _test-input-stream "fn foo {\n")
 8565     (write _test-input-stream "  var x: (handle int)\n")
 8566     (write _test-input-stream "  var y: int\n")
 8567     (write _test-input-stream "  copy-to y, x\n")
 8568     (write _test-input-stream "}\n")
 8569     # convert
 8570     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8571     # registers except esp clobbered at this point
 8572     # restore ed
 8573     89/<- %edx 4/r32/esp
 8574     (flush _test-output-buffered-file)
 8575     (flush _test-error-buffered-file)
 8576 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8582     # check output
 8583     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-from-non-scalar-inout: output should be empty")
 8584     (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")
 8585     # check that stop(1) was called
 8586     (check-ints-equal *(edx+4) 2 "F - test-copy-to-from-non-scalar-inout: exit status")
 8587     # don't restore from ebp
 8588     81 0/subop/add %esp 8/imm32
 8589     # . epilogue
 8590     5d/pop-to-ebp
 8591     c3/return
 8592 
 8593 test-copy-byte-with-no-inout:
 8594     # . prologue
 8595     55/push-ebp
 8596     89/<- %ebp 4/r32/esp
 8597     # setup
 8598     (clear-stream _test-input-stream)
 8599     (clear-stream $_test-input-buffered-file->buffer)
 8600     (clear-stream _test-output-stream)
 8601     (clear-stream $_test-output-buffered-file->buffer)
 8602     (clear-stream _test-error-stream)
 8603     (clear-stream $_test-error-buffered-file->buffer)
 8604     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8605     68/push 0/imm32
 8606     68/push 0/imm32
 8607     89/<- %edx 4/r32/esp
 8608     (tailor-exit-descriptor %edx 0x10)
 8609     #
 8610     (write _test-input-stream "fn foo {\n")
 8611     (write _test-input-stream "  var x/eax: byte <- copy-byte\n")
 8612     (write _test-input-stream "}\n")
 8613     # convert
 8614     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8615     # registers except esp clobbered at this point
 8616     # restore ed
 8617     89/<- %edx 4/r32/esp
 8618     (flush _test-output-buffered-file)
 8619     (flush _test-error-buffered-file)
 8620 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8626     # check output
 8627     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-no-inout: output should be empty")
 8628     (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")
 8629     # check that stop(1) was called
 8630     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-no-inout: exit status")
 8631     # don't restore from ebp
 8632     81 0/subop/add %esp 8/imm32
 8633     # . epilogue
 8634     5d/pop-to-ebp
 8635     c3/return
 8636 
 8637 test-copy-byte-with-multiple-inouts:
 8638     # . prologue
 8639     55/push-ebp
 8640     89/<- %ebp 4/r32/esp
 8641     # setup
 8642     (clear-stream _test-input-stream)
 8643     (clear-stream $_test-input-buffered-file->buffer)
 8644     (clear-stream _test-output-stream)
 8645     (clear-stream $_test-output-buffered-file->buffer)
 8646     (clear-stream _test-error-stream)
 8647     (clear-stream $_test-error-buffered-file->buffer)
 8648     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8649     68/push 0/imm32
 8650     68/push 0/imm32
 8651     89/<- %edx 4/r32/esp
 8652     (tailor-exit-descriptor %edx 0x10)
 8653     #
 8654     (write _test-input-stream "fn foo {\n")
 8655     (write _test-input-stream "  var x/eax: byte <- copy-byte 0, 0\n")
 8656     (write _test-input-stream "}\n")
 8657     # convert
 8658     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8659     # registers except esp clobbered at this point
 8660     # restore ed
 8661     89/<- %edx 4/r32/esp
 8662     (flush _test-output-buffered-file)
 8663     (flush _test-error-buffered-file)
 8664 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8670     # check output
 8671     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-multiple-inouts: output should be empty")
 8672     (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")
 8673     # check that stop(1) was called
 8674     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-multiple-inouts: exit status")
 8675     # don't restore from ebp
 8676     81 0/subop/add %esp 8/imm32
 8677     # . epilogue
 8678     5d/pop-to-ebp
 8679     c3/return
 8680 
 8681 test-copy-byte-with-no-output:
 8682     # . prologue
 8683     55/push-ebp
 8684     89/<- %ebp 4/r32/esp
 8685     # setup
 8686     (clear-stream _test-input-stream)
 8687     (clear-stream $_test-input-buffered-file->buffer)
 8688     (clear-stream _test-output-stream)
 8689     (clear-stream $_test-output-buffered-file->buffer)
 8690     (clear-stream _test-error-stream)
 8691     (clear-stream $_test-error-buffered-file->buffer)
 8692     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8693     68/push 0/imm32
 8694     68/push 0/imm32
 8695     89/<- %edx 4/r32/esp
 8696     (tailor-exit-descriptor %edx 0x10)
 8697     #
 8698     (write _test-input-stream "fn foo {\n")
 8699     (write _test-input-stream "  copy-byte 0\n")
 8700     (write _test-input-stream "}\n")
 8701     # convert
 8702     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8703     # registers except esp clobbered at this point
 8704     # restore ed
 8705     89/<- %edx 4/r32/esp
 8706     (flush _test-output-buffered-file)
 8707     (flush _test-error-buffered-file)
 8708 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8714     # check output
 8715     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-no-output: output should be empty")
 8716     (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")
 8717     # check that stop(1) was called
 8718     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-no-output: exit status")
 8719     # don't restore from ebp
 8720     81 0/subop/add %esp 8/imm32
 8721     # . epilogue
 8722     5d/pop-to-ebp
 8723     c3/return
 8724 
 8725 test-copy-byte-with-multiple-outputs:
 8726     # . prologue
 8727     55/push-ebp
 8728     89/<- %ebp 4/r32/esp
 8729     # setup
 8730     (clear-stream _test-input-stream)
 8731     (clear-stream $_test-input-buffered-file->buffer)
 8732     (clear-stream _test-output-stream)
 8733     (clear-stream $_test-output-buffered-file->buffer)
 8734     (clear-stream _test-error-stream)
 8735     (clear-stream $_test-error-buffered-file->buffer)
 8736     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8737     68/push 0/imm32
 8738     68/push 0/imm32
 8739     89/<- %edx 4/r32/esp
 8740     (tailor-exit-descriptor %edx 0x10)
 8741     #
 8742     (write _test-input-stream "fn foo {\n")
 8743     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
 8744     (write _test-input-stream "  var y/ecx: byte <- copy 0\n")
 8745     (write _test-input-stream "  x, y <- copy-byte 0\n")
 8746     (write _test-input-stream "}\n")
 8747     # convert
 8748     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8749     # registers except esp clobbered at this point
 8750     # restore ed
 8751     89/<- %edx 4/r32/esp
 8752     (flush _test-output-buffered-file)
 8753     (flush _test-error-buffered-file)
 8754 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8760     # check output
 8761     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-multiple-outputs: output should be empty")
 8762     (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")
 8763     # check that stop(1) was called
 8764     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-multiple-outputs: exit status")
 8765     # don't restore from ebp
 8766     81 0/subop/add %esp 8/imm32
 8767     # . epilogue
 8768     5d/pop-to-ebp
 8769     c3/return
 8770 
 8771 test-copy-byte-deref-address:
 8772     # . prologue
 8773     55/push-ebp
 8774     89/<- %ebp 4/r32/esp
 8775     # setup
 8776     (clear-stream _test-input-stream)
 8777     (clear-stream $_test-input-buffered-file->buffer)
 8778     (clear-stream _test-output-stream)
 8779     (clear-stream $_test-output-buffered-file->buffer)
 8780     #
 8781     (write _test-input-stream "fn foo {\n")
 8782     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
 8783     (write _test-input-stream "  var y/ecx: byte <- copy-byte *x\n")
 8784     (write _test-input-stream "}\n")
 8785     # convert
 8786     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8787     (flush _test-output-buffered-file)
 8788 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8794     # not bothering checking output
 8795     (check-next-stream-line-equal _test-error-stream  ""  "F - test-copy-byte-deref-address: error message")
 8796     # . epilogue
 8797     5d/pop-to-ebp
 8798     c3/return
 8799 
 8800 test-copy-byte-with-invalid-output-type:
 8801     # . prologue
 8802     55/push-ebp
 8803     89/<- %ebp 4/r32/esp
 8804     # setup
 8805     (clear-stream _test-input-stream)
 8806     (clear-stream $_test-input-buffered-file->buffer)
 8807     (clear-stream _test-output-stream)
 8808     (clear-stream $_test-output-buffered-file->buffer)
 8809     (clear-stream _test-error-stream)
 8810     (clear-stream $_test-error-buffered-file->buffer)
 8811     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8812     68/push 0/imm32
 8813     68/push 0/imm32
 8814     89/<- %edx 4/r32/esp
 8815     (tailor-exit-descriptor %edx 0x10)
 8816     #
 8817     (write _test-input-stream "fn foo {\n")
 8818     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
 8819     (write _test-input-stream "  var y/eax: int <- copy-byte *x\n")
 8820     (write _test-input-stream "}\n")
 8821     # convert
 8822     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8823     # registers except esp clobbered at this point
 8824     # restore ed
 8825     89/<- %edx 4/r32/esp
 8826     (flush _test-output-buffered-file)
 8827     (flush _test-error-buffered-file)
 8828 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8834     # check output
 8835     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-invalid-output-type: output should be empty")
 8836     (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")
 8837     # check that stop(1) was called
 8838     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-invalid-output-type: exit status")
 8839     # don't restore from ebp
 8840     81 0/subop/add %esp 8/imm32
 8841     # . epilogue
 8842     5d/pop-to-ebp
 8843     c3/return
 8844 
 8845 test-copy-byte-from-non-scalar-inout:
 8846     # . prologue
 8847     55/push-ebp
 8848     89/<- %ebp 4/r32/esp
 8849     # setup
 8850     (clear-stream _test-input-stream)
 8851     (clear-stream $_test-input-buffered-file->buffer)
 8852     (clear-stream _test-output-stream)
 8853     (clear-stream $_test-output-buffered-file->buffer)
 8854     (clear-stream _test-error-stream)
 8855     (clear-stream $_test-error-buffered-file->buffer)
 8856     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8857     68/push 0/imm32
 8858     68/push 0/imm32
 8859     89/<- %edx 4/r32/esp
 8860     (tailor-exit-descriptor %edx 0x10)
 8861     #
 8862     (write _test-input-stream "fn foo {\n")
 8863     (write _test-input-stream "  var x: (handle int)\n")
 8864     (write _test-input-stream "  var y/eax: byte <- copy-byte x\n")
 8865     (write _test-input-stream "}\n")
 8866     # convert
 8867     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8868     # registers except esp clobbered at this point
 8869     # restore ed
 8870     89/<- %edx 4/r32/esp
 8871     (flush _test-output-buffered-file)
 8872     (flush _test-error-buffered-file)
 8873 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8879     # check output
 8880     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-from-non-scalar-inout: output should be empty")
 8881     (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")
 8882     # check that stop(1) was called
 8883     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-from-non-scalar-inout: exit status")
 8884     # don't restore from ebp
 8885     81 0/subop/add %esp 8/imm32
 8886     # . epilogue
 8887     5d/pop-to-ebp
 8888     c3/return
 8889 
 8890 test-copy-byte-to-with-no-inout:
 8891     # . prologue
 8892     55/push-ebp
 8893     89/<- %ebp 4/r32/esp
 8894     # setup
 8895     (clear-stream _test-input-stream)
 8896     (clear-stream $_test-input-buffered-file->buffer)
 8897     (clear-stream _test-output-stream)
 8898     (clear-stream $_test-output-buffered-file->buffer)
 8899     (clear-stream _test-error-stream)
 8900     (clear-stream $_test-error-buffered-file->buffer)
 8901     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8902     68/push 0/imm32
 8903     68/push 0/imm32
 8904     89/<- %edx 4/r32/esp
 8905     (tailor-exit-descriptor %edx 0x10)
 8906     #
 8907     (write _test-input-stream "fn foo {\n")
 8908     (write _test-input-stream "  copy-byte-to\n")
 8909     (write _test-input-stream "}\n")
 8910     # convert
 8911     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8912     # registers except esp clobbered at this point
 8913     # restore ed
 8914     89/<- %edx 4/r32/esp
 8915     (flush _test-output-buffered-file)
 8916     (flush _test-error-buffered-file)
 8917 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8923     # check output
 8924     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-no-inout: output should be empty")
 8925     (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")
 8926     # check that stop(1) was called
 8927     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-no-inout: exit status")
 8928     # don't restore from ebp
 8929     81 0/subop/add %esp 8/imm32
 8930     # . epilogue
 8931     5d/pop-to-ebp
 8932     c3/return
 8933 
 8934 test-copy-byte-to-with-no-source:
 8935     # . prologue
 8936     55/push-ebp
 8937     89/<- %ebp 4/r32/esp
 8938     # setup
 8939     (clear-stream _test-input-stream)
 8940     (clear-stream $_test-input-buffered-file->buffer)
 8941     (clear-stream _test-output-stream)
 8942     (clear-stream $_test-output-buffered-file->buffer)
 8943     (clear-stream _test-error-stream)
 8944     (clear-stream $_test-error-buffered-file->buffer)
 8945     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8946     68/push 0/imm32
 8947     68/push 0/imm32
 8948     89/<- %edx 4/r32/esp
 8949     (tailor-exit-descriptor %edx 0x10)
 8950     #
 8951     (write _test-input-stream "fn foo {\n")
 8952     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
 8953     (write _test-input-stream "  copy-byte-to *x\n")
 8954     (write _test-input-stream "}\n")
 8955     # convert
 8956     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8957     # registers except esp clobbered at this point
 8958     # restore ed
 8959     89/<- %edx 4/r32/esp
 8960     (flush _test-output-buffered-file)
 8961     (flush _test-error-buffered-file)
 8962 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8968     # check output
 8969     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-no-source: output should be empty")
 8970     (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")
 8971     # check that stop(1) was called
 8972     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-no-source: exit status")
 8973     # don't restore from ebp
 8974     81 0/subop/add %esp 8/imm32
 8975     # . epilogue
 8976     5d/pop-to-ebp
 8977     c3/return
 8978 
 8979 test-copy-byte-to-with-too-many-inouts:
 8980     # . prologue
 8981     55/push-ebp
 8982     89/<- %ebp 4/r32/esp
 8983     # setup
 8984     (clear-stream _test-input-stream)
 8985     (clear-stream $_test-input-buffered-file->buffer)
 8986     (clear-stream _test-output-stream)
 8987     (clear-stream $_test-output-buffered-file->buffer)
 8988     (clear-stream _test-error-stream)
 8989     (clear-stream $_test-error-buffered-file->buffer)
 8990     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8991     68/push 0/imm32
 8992     68/push 0/imm32
 8993     89/<- %edx 4/r32/esp
 8994     (tailor-exit-descriptor %edx 0x10)
 8995     #
 8996     (write _test-input-stream "fn foo {\n")
 8997     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
 8998     (write _test-input-stream "  copy-byte-to *x, 0, 0\n")
 8999     (write _test-input-stream "}\n")
 9000     # convert
 9001     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9002     # registers except esp clobbered at this point
 9003     # restore ed
 9004     89/<- %edx 4/r32/esp
 9005     (flush _test-output-buffered-file)
 9006     (flush _test-error-buffered-file)
 9007 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9013     # check output
 9014     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-too-many-inouts: output should be empty")
 9015     (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")
 9016     # check that stop(1) was called
 9017     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-too-many-inouts: exit status")
 9018     # don't restore from ebp
 9019     81 0/subop/add %esp 8/imm32
 9020     # . epilogue
 9021     5d/pop-to-ebp
 9022     c3/return
 9023 
 9024 test-copy-byte-to-with-output:
 9025     # . prologue
 9026     55/push-ebp
 9027     89/<- %ebp 4/r32/esp
 9028     # setup
 9029     (clear-stream _test-input-stream)
 9030     (clear-stream $_test-input-buffered-file->buffer)
 9031     (clear-stream _test-output-stream)
 9032     (clear-stream $_test-output-buffered-file->buffer)
 9033     (clear-stream _test-error-stream)
 9034     (clear-stream $_test-error-buffered-file->buffer)
 9035     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9036     68/push 0/imm32
 9037     68/push 0/imm32
 9038     89/<- %edx 4/r32/esp
 9039     (tailor-exit-descriptor %edx 0x10)
 9040     #
 9041     (write _test-input-stream "fn foo {\n")
 9042     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
 9043     (write _test-input-stream "  var y/ecx: (addr byte) <- copy 0\n")
 9044     (write _test-input-stream "  x <- copy-byte-to *y, 0\n")
 9045     (write _test-input-stream "}\n")
 9046     # convert
 9047     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9048     # registers except esp clobbered at this point
 9049     # restore ed
 9050     89/<- %edx 4/r32/esp
 9051     (flush _test-output-buffered-file)
 9052     (flush _test-error-buffered-file)
 9053 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9059     # check output
 9060     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-output: output should be empty")
 9061     (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")
 9062     # check that stop(1) was called
 9063     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-output: exit status")
 9064     # don't restore from ebp
 9065     81 0/subop/add %esp 8/imm32
 9066     # . epilogue
 9067     5d/pop-to-ebp
 9068     c3/return
 9069 
 9070 test-copy-byte-to-with-invalid-output-type:
 9071     # . prologue
 9072     55/push-ebp
 9073     89/<- %ebp 4/r32/esp
 9074     # setup
 9075     (clear-stream _test-input-stream)
 9076     (clear-stream $_test-input-buffered-file->buffer)
 9077     (clear-stream _test-output-stream)
 9078     (clear-stream $_test-output-buffered-file->buffer)
 9079     (clear-stream _test-error-stream)
 9080     (clear-stream $_test-error-buffered-file->buffer)
 9081     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9082     68/push 0/imm32
 9083     68/push 0/imm32
 9084     89/<- %edx 4/r32/esp
 9085     (tailor-exit-descriptor %edx 0x10)
 9086     #
 9087     (write _test-input-stream "fn foo {\n")
 9088     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
 9089     (write _test-input-stream "  var y: int\n")
 9090     (write _test-input-stream "  copy-byte-to y, x\n")
 9091     (write _test-input-stream "}\n")
 9092     # convert
 9093     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9094     # registers except esp clobbered at this point
 9095     # restore ed
 9096     89/<- %edx 4/r32/esp
 9097     (flush _test-output-buffered-file)
 9098     (flush _test-error-buffered-file)
 9099 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9105     # check output
 9106     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-invalid-output-type: output should be empty")
 9107     (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")
 9108     # check that stop(1) was called
 9109     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-invalid-output-type: exit status")
 9110     # don't restore from ebp
 9111     81 0/subop/add %esp 8/imm32
 9112     # . epilogue
 9113     5d/pop-to-ebp
 9114     c3/return
 9115 
 9116 test-copy-byte-to-with-literal-inout:
 9117     # . prologue
 9118     55/push-ebp
 9119     89/<- %ebp 4/r32/esp
 9120     # setup
 9121     (clear-stream _test-input-stream)
 9122     (clear-stream $_test-input-buffered-file->buffer)
 9123     (clear-stream _test-output-stream)
 9124     (clear-stream $_test-output-buffered-file->buffer)
 9125     (clear-stream _test-error-stream)
 9126     (clear-stream $_test-error-buffered-file->buffer)
 9127     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9128     68/push 0/imm32
 9129     68/push 0/imm32
 9130     89/<- %edx 4/r32/esp
 9131     (tailor-exit-descriptor %edx 0x10)
 9132     #
 9133     (write _test-input-stream "fn foo {\n")
 9134     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
 9135     (write _test-input-stream "  copy-byte-to *x, 0\n")
 9136     (write _test-input-stream "}\n")
 9137     # convert
 9138     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9139     # registers except esp clobbered at this point
 9140     # restore ed
 9141     89/<- %edx 4/r32/esp
 9142     (flush _test-output-buffered-file)
 9143     (flush _test-error-buffered-file)
 9144 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9150     # check output
 9151     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-literal-inout: output should be empty")
 9152     (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")
 9153     # check that stop(1) was called
 9154     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-literal-inout: exit status")
 9155     # don't restore from ebp
 9156     81 0/subop/add %esp 8/imm32
 9157     # . epilogue
 9158     5d/pop-to-ebp
 9159     c3/return
 9160 
 9161 test-copy-byte-to-deref-address:
 9162     # . prologue
 9163     55/push-ebp
 9164     89/<- %ebp 4/r32/esp
 9165     # setup
 9166     (clear-stream _test-input-stream)
 9167     (clear-stream $_test-input-buffered-file->buffer)
 9168     (clear-stream _test-output-stream)
 9169     (clear-stream $_test-output-buffered-file->buffer)
 9170     #
 9171     (write _test-input-stream "fn foo {\n")
 9172     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
 9173     (write _test-input-stream "  var y/ecx: (addr byte) <- copy 0\n")
 9174     (write _test-input-stream "  copy-byte-to *y, x\n")
 9175     (write _test-input-stream "}\n")
 9176     # convert
 9177     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9178     (flush _test-output-buffered-file)
 9179     # no errors
 9180     # . epilogue
 9181     5d/pop-to-ebp
 9182     c3/return
 9183 
 9184 test-copy-byte-to-from-non-scalar-inout:
 9185     # . prologue
 9186     55/push-ebp
 9187     89/<- %ebp 4/r32/esp
 9188     # setup
 9189     (clear-stream _test-input-stream)
 9190     (clear-stream $_test-input-buffered-file->buffer)
 9191     (clear-stream _test-output-stream)
 9192     (clear-stream $_test-output-buffered-file->buffer)
 9193     (clear-stream _test-error-stream)
 9194     (clear-stream $_test-error-buffered-file->buffer)
 9195     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9196     68/push 0/imm32
 9197     68/push 0/imm32
 9198     89/<- %edx 4/r32/esp
 9199     (tailor-exit-descriptor %edx 0x10)
 9200     #
 9201     (write _test-input-stream "fn foo {\n")
 9202     (write _test-input-stream "  var x: (handle int)\n")
 9203     (write _test-input-stream "  var y/eax: (addr byte) <- copy 0\n")
 9204     (write _test-input-stream "  copy-byte-to *y, x\n")
 9205     (write _test-input-stream "}\n")
 9206     # convert
 9207     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9208     # registers except esp clobbered at this point
 9209     # restore ed
 9210     89/<- %edx 4/r32/esp
 9211     (flush _test-output-buffered-file)
 9212     (flush _test-error-buffered-file)
 9213 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9219     # check output
 9220     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-from-non-scalar-inout: output should be empty")
 9221     (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")
 9222     # check that stop(1) was called
 9223     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-from-non-scalar-inout: exit status")
 9224     # don't restore from ebp
 9225     81 0/subop/add %esp 8/imm32
 9226     # . epilogue
 9227     5d/pop-to-ebp
 9228     c3/return
 9229 
 9230 test-compare-with-no-inout:
 9231     # . prologue
 9232     55/push-ebp
 9233     89/<- %ebp 4/r32/esp
 9234     # setup
 9235     (clear-stream _test-input-stream)
 9236     (clear-stream $_test-input-buffered-file->buffer)
 9237     (clear-stream _test-output-stream)
 9238     (clear-stream $_test-output-buffered-file->buffer)
 9239     (clear-stream _test-error-stream)
 9240     (clear-stream $_test-error-buffered-file->buffer)
 9241     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9242     68/push 0/imm32
 9243     68/push 0/imm32
 9244     89/<- %edx 4/r32/esp
 9245     (tailor-exit-descriptor %edx 0x10)
 9246     #
 9247     (write _test-input-stream "fn foo {\n")
 9248     (write _test-input-stream "  var x: boolean\n")
 9249     (write _test-input-stream "  compare\n")
 9250     (write _test-input-stream "}\n")
 9251     # convert
 9252     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9253     # registers except esp clobbered at this point
 9254     # restore ed
 9255     89/<- %edx 4/r32/esp
 9256     (flush _test-output-buffered-file)
 9257     (flush _test-error-buffered-file)
 9258 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9264     # check output
 9265     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-no-inout: output should be empty")
 9266     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must have two inouts"  "F - test-compare-with-no-inout: error message")
 9267     # check that stop(1) was called
 9268     (check-ints-equal *(edx+4) 2 "F - test-compare-with-no-inout: exit status")
 9269     # don't restore from ebp
 9270     81 0/subop/add %esp 8/imm32
 9271     # . epilogue
 9272     5d/pop-to-ebp
 9273     c3/return
 9274 
 9275 test-compare-with-just-one-inout:
 9276     # . prologue
 9277     55/push-ebp
 9278     89/<- %ebp 4/r32/esp
 9279     # setup
 9280     (clear-stream _test-input-stream)
 9281     (clear-stream $_test-input-buffered-file->buffer)
 9282     (clear-stream _test-output-stream)
 9283     (clear-stream $_test-output-buffered-file->buffer)
 9284     (clear-stream _test-error-stream)
 9285     (clear-stream $_test-error-buffered-file->buffer)
 9286     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9287     68/push 0/imm32
 9288     68/push 0/imm32
 9289     89/<- %edx 4/r32/esp
 9290     (tailor-exit-descriptor %edx 0x10)
 9291     #
 9292     (write _test-input-stream "fn foo {\n")
 9293     (write _test-input-stream "  var x: boolean\n")
 9294     (write _test-input-stream "  compare x\n")
 9295     (write _test-input-stream "}\n")
 9296     # convert
 9297     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9298     # registers except esp clobbered at this point
 9299     # restore ed
 9300     89/<- %edx 4/r32/esp
 9301     (flush _test-output-buffered-file)
 9302     (flush _test-error-buffered-file)
 9303 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9309     # check output
 9310     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-just-one-inout: output should be empty")
 9311     (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")
 9312     # check that stop(1) was called
 9313     (check-ints-equal *(edx+4) 2 "F - test-compare-with-just-one-inout: exit status")
 9314     # don't restore from ebp
 9315     81 0/subop/add %esp 8/imm32
 9316     # . epilogue
 9317     5d/pop-to-ebp
 9318     c3/return
 9319 
 9320 test-compare-with-too-many-inouts:
 9321     # . prologue
 9322     55/push-ebp
 9323     89/<- %ebp 4/r32/esp
 9324     # setup
 9325     (clear-stream _test-input-stream)
 9326     (clear-stream $_test-input-buffered-file->buffer)
 9327     (clear-stream _test-output-stream)
 9328     (clear-stream $_test-output-buffered-file->buffer)
 9329     (clear-stream _test-error-stream)
 9330     (clear-stream $_test-error-buffered-file->buffer)
 9331     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9332     68/push 0/imm32
 9333     68/push 0/imm32
 9334     89/<- %edx 4/r32/esp
 9335     (tailor-exit-descriptor %edx 0x10)
 9336     #
 9337     (write _test-input-stream "fn foo {\n")
 9338     (write _test-input-stream "  var x: boolean\n")
 9339     (write _test-input-stream "  compare x, 0, 0\n")
 9340     (write _test-input-stream "}\n")
 9341     # convert
 9342     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9343     # registers except esp clobbered at this point
 9344     # restore ed
 9345     89/<- %edx 4/r32/esp
 9346     (flush _test-output-buffered-file)
 9347     (flush _test-error-buffered-file)
 9348 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9354     # check output
 9355     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-too-many-inouts: output should be empty")
 9356     (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")
 9357     # check that stop(1) was called
 9358     (check-ints-equal *(edx+4) 2 "F - test-compare-with-too-many-inouts: exit status")
 9359     # don't restore from ebp
 9360     81 0/subop/add %esp 8/imm32
 9361     # . epilogue
 9362     5d/pop-to-ebp
 9363     c3/return
 9364 
 9365 test-compare-with-output:
 9366     # . prologue
 9367     55/push-ebp
 9368     89/<- %ebp 4/r32/esp
 9369     # setup
 9370     (clear-stream _test-input-stream)
 9371     (clear-stream $_test-input-buffered-file->buffer)
 9372     (clear-stream _test-output-stream)
 9373     (clear-stream $_test-output-buffered-file->buffer)
 9374     (clear-stream _test-error-stream)
 9375     (clear-stream $_test-error-buffered-file->buffer)
 9376     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9377     68/push 0/imm32
 9378     68/push 0/imm32
 9379     89/<- %edx 4/r32/esp
 9380     (tailor-exit-descriptor %edx 0x10)
 9381     #
 9382     (write _test-input-stream "fn foo {\n")
 9383     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 9384     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
 9385     (write _test-input-stream "  x <- compare y, 0\n")
 9386     (write _test-input-stream "}\n")
 9387     # convert
 9388     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9389     # registers except esp clobbered at this point
 9390     # restore ed
 9391     89/<- %edx 4/r32/esp
 9392     (flush _test-output-buffered-file)
 9393     (flush _test-error-buffered-file)
 9394 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9400     # check output
 9401     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-output: output should be empty")
 9402     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must not have any outputs"  "F - test-compare-with-output: error message")
 9403     # check that stop(1) was called
 9404     (check-ints-equal *(edx+4) 2 "F - test-compare-with-output: exit status")
 9405     # don't restore from ebp
 9406     81 0/subop/add %esp 8/imm32
 9407     # . epilogue
 9408     5d/pop-to-ebp
 9409     c3/return
 9410 
 9411 test-compare-invalid-value-to-address:
 9412     # . prologue
 9413     55/push-ebp
 9414     89/<- %ebp 4/r32/esp
 9415     # setup
 9416     (clear-stream _test-input-stream)
 9417     (clear-stream $_test-input-buffered-file->buffer)
 9418     (clear-stream _test-output-stream)
 9419     (clear-stream $_test-output-buffered-file->buffer)
 9420     (clear-stream _test-error-stream)
 9421     (clear-stream $_test-error-buffered-file->buffer)
 9422     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9423     68/push 0/imm32
 9424     68/push 0/imm32
 9425     89/<- %edx 4/r32/esp
 9426     (tailor-exit-descriptor %edx 0x10)
 9427     #
 9428     (write _test-input-stream "fn foo {\n")
 9429     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 9430     (write _test-input-stream "  var y: (addr int)\n")
 9431     (write _test-input-stream "  compare y, x\n")
 9432     (write _test-input-stream "}\n")
 9433     # convert
 9434     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9435     # registers except esp clobbered at this point
 9436     # restore ed
 9437     89/<- %edx 4/r32/esp
 9438     (flush _test-output-buffered-file)
 9439     (flush _test-error-buffered-file)
 9440 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9446     # check output
 9447     (check-stream-equal _test-output-stream  ""  "F - test-compare-invalid-value-to-address: output should be empty")
 9448     (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")
 9449     # check that stop(1) was called
 9450     (check-ints-equal *(edx+4) 2 "F - test-compare-invalid-value-to-address: exit status")
 9451     # don't restore from ebp
 9452     81 0/subop/add %esp 8/imm32
 9453     # . epilogue
 9454     5d/pop-to-ebp
 9455     c3/return
 9456 
 9457 test-compare-address:
 9458     # . prologue
 9459     55/push-ebp
 9460     89/<- %ebp 4/r32/esp
 9461     # setup
 9462     (clear-stream _test-input-stream)
 9463     (clear-stream $_test-input-buffered-file->buffer)
 9464     (clear-stream _test-output-stream)
 9465     (clear-stream $_test-output-buffered-file->buffer)
 9466     #
 9467     (write _test-input-stream "fn foo {\n")
 9468     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
 9469     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
 9470     (write _test-input-stream "  compare y, x\n")
 9471     (write _test-input-stream "}\n")
 9472     # convert
 9473     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9474     (flush _test-output-buffered-file)
 9475     # no errors
 9476     # . epilogue
 9477     5d/pop-to-ebp
 9478     c3/return
 9479 
 9480 test-compare-deref-address:
 9481     # . prologue
 9482     55/push-ebp
 9483     89/<- %ebp 4/r32/esp
 9484     # setup
 9485     (clear-stream _test-input-stream)
 9486     (clear-stream $_test-input-buffered-file->buffer)
 9487     (clear-stream _test-output-stream)
 9488     (clear-stream $_test-output-buffered-file->buffer)
 9489     #
 9490     (write _test-input-stream "fn foo {\n")
 9491     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
 9492     (write _test-input-stream "  var y/ecx: (addr addr int) <- copy 0\n")
 9493     (write _test-input-stream "  compare *y, x\n")
 9494     (write _test-input-stream "}\n")
 9495     # convert
 9496     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9497     (flush _test-output-buffered-file)
 9498     # no errors
 9499     # . epilogue
 9500     5d/pop-to-ebp
 9501     c3/return
 9502 
 9503 test-compare-two-vars-in-memory:
 9504     # . prologue
 9505     55/push-ebp
 9506     89/<- %ebp 4/r32/esp
 9507     # setup
 9508     (clear-stream _test-input-stream)
 9509     (clear-stream $_test-input-buffered-file->buffer)
 9510     (clear-stream _test-output-stream)
 9511     (clear-stream $_test-output-buffered-file->buffer)
 9512     (clear-stream _test-error-stream)
 9513     (clear-stream $_test-error-buffered-file->buffer)
 9514     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9515     68/push 0/imm32
 9516     68/push 0/imm32
 9517     89/<- %edx 4/r32/esp
 9518     (tailor-exit-descriptor %edx 0x10)
 9519     #
 9520     (write _test-input-stream "fn foo {\n")
 9521     (write _test-input-stream "  var x: boolean\n")
 9522     (write _test-input-stream "  compare x, x\n")
 9523     (write _test-input-stream "}\n")
 9524     # convert
 9525     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9526     # registers except esp clobbered at this point
 9527     # restore ed
 9528     89/<- %edx 4/r32/esp
 9529     (flush _test-output-buffered-file)
 9530     (flush _test-error-buffered-file)
 9531 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9537     # check output
 9538     (check-stream-equal _test-output-stream  ""  "F - test-compare-two-vars-in-memory: output should be empty")
 9539     (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")
 9540     # check that stop(1) was called
 9541     (check-ints-equal *(edx+4) 2 "F - test-compare-two-vars-in-memory: exit status")
 9542     # don't restore from ebp
 9543     81 0/subop/add %esp 8/imm32
 9544     # . epilogue
 9545     5d/pop-to-ebp
 9546     c3/return
 9547 
 9548 test-compare-non-scalar:
 9549     # . prologue
 9550     55/push-ebp
 9551     89/<- %ebp 4/r32/esp
 9552     # setup
 9553     (clear-stream _test-input-stream)
 9554     (clear-stream $_test-input-buffered-file->buffer)
 9555     (clear-stream _test-output-stream)
 9556     (clear-stream $_test-output-buffered-file->buffer)
 9557     (clear-stream _test-error-stream)
 9558     (clear-stream $_test-error-buffered-file->buffer)
 9559     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9560     68/push 0/imm32
 9561     68/push 0/imm32
 9562     89/<- %edx 4/r32/esp
 9563     (tailor-exit-descriptor %edx 0x10)
 9564     #
 9565     (write _test-input-stream "fn foo {\n")
 9566     (write _test-input-stream "  var x: (handle int)\n")
 9567     (write _test-input-stream "  var y: int\n")
 9568     (write _test-input-stream "  compare y, x\n")
 9569     (write _test-input-stream "}\n")
 9570     # convert
 9571     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9572     # registers except esp clobbered at this point
 9573     # restore ed
 9574     89/<- %edx 4/r32/esp
 9575     (flush _test-output-buffered-file)
 9576     (flush _test-error-buffered-file)
 9577 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9583     # check output
 9584     (check-stream-equal _test-output-stream  ""  "F - test-compare-non-scalar: output should be empty")
 9585 #?     (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")
 9586     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compare: both inouts are in memory"  "F - test-compare-non-scalar: error message")
 9587     # check that stop(1) was called
 9588     (check-ints-equal *(edx+4) 2 "F - test-compare-non-scalar: exit status")
 9589     # don't restore from ebp
 9590     81 0/subop/add %esp 8/imm32
 9591     # . epilogue
 9592     5d/pop-to-ebp
 9593     c3/return
 9594 
 9595 test-compare-with-string-literal:
 9596     # . prologue
 9597     55/push-ebp
 9598     89/<- %ebp 4/r32/esp
 9599     # setup
 9600     (clear-stream _test-input-stream)
 9601     (clear-stream $_test-input-buffered-file->buffer)
 9602     (clear-stream _test-output-stream)
 9603     (clear-stream $_test-output-buffered-file->buffer)
 9604     (clear-stream _test-error-stream)
 9605     (clear-stream $_test-error-buffered-file->buffer)
 9606     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9607     68/push 0/imm32
 9608     68/push 0/imm32
 9609     89/<- %edx 4/r32/esp
 9610     (tailor-exit-descriptor %edx 0x10)
 9611     #
 9612     (write _test-input-stream "fn foo {\n")
 9613     (write _test-input-stream "  var x/eax: (addr array byte) <- copy 0\n")
 9614     (write _test-input-stream "  compare x, \"abc\"\n")
 9615     (write _test-input-stream "}\n")
 9616     # convert
 9617     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9618     # registers except esp clobbered at this point
 9619     # restore ed
 9620     89/<- %edx 4/r32/esp
 9621     (flush _test-output-buffered-file)
 9622     (flush _test-error-buffered-file)
 9623 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9629     # check output
 9630     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-string-literal: output should be empty")
 9631     (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")
 9632     # check that stop(1) was called
 9633     (check-ints-equal *(edx+4) 2 "F - test-compare-with-string-literal: exit status")
 9634     # don't restore from ebp
 9635     81 0/subop/add %esp 8/imm32
 9636     # . epilogue
 9637     5d/pop-to-ebp
 9638     c3/return
 9639 
 9640 test-address-with-no-inout:
 9641     # . prologue
 9642     55/push-ebp
 9643     89/<- %ebp 4/r32/esp
 9644     # setup
 9645     (clear-stream _test-input-stream)
 9646     (clear-stream $_test-input-buffered-file->buffer)
 9647     (clear-stream _test-output-stream)
 9648     (clear-stream $_test-output-buffered-file->buffer)
 9649     (clear-stream _test-error-stream)
 9650     (clear-stream $_test-error-buffered-file->buffer)
 9651     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9652     68/push 0/imm32
 9653     68/push 0/imm32
 9654     89/<- %edx 4/r32/esp
 9655     (tailor-exit-descriptor %edx 0x10)
 9656     #
 9657     (write _test-input-stream "fn foo {\n")
 9658     (write _test-input-stream "  var x/eax: boolean <- address\n")
 9659     (write _test-input-stream "}\n")
 9660     # convert
 9661     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9662     # registers except esp clobbered at this point
 9663     # restore ed
 9664     89/<- %edx 4/r32/esp
 9665     (flush _test-output-buffered-file)
 9666     (flush _test-error-buffered-file)
 9667 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9673     # check output
 9674     (check-stream-equal _test-output-stream  ""  "F - test-address-with-no-inout: output should be empty")
 9675     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'address' expects an inout"  "F - test-address-with-no-inout: error message")
 9676     # check that stop(1) was called
 9677     (check-ints-equal *(edx+4) 2 "F - test-address-with-no-inout: exit status")
 9678     # don't restore from ebp
 9679     81 0/subop/add %esp 8/imm32
 9680     # . epilogue
 9681     5d/pop-to-ebp
 9682     c3/return
 9683 
 9684 test-address-with-multiple-inouts:
 9685     # . prologue
 9686     55/push-ebp
 9687     89/<- %ebp 4/r32/esp
 9688     # setup
 9689     (clear-stream _test-input-stream)
 9690     (clear-stream $_test-input-buffered-file->buffer)
 9691     (clear-stream _test-output-stream)
 9692     (clear-stream $_test-output-buffered-file->buffer)
 9693     (clear-stream _test-error-stream)
 9694     (clear-stream $_test-error-buffered-file->buffer)
 9695     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9696     68/push 0/imm32
 9697     68/push 0/imm32
 9698     89/<- %edx 4/r32/esp
 9699     (tailor-exit-descriptor %edx 0x10)
 9700     #
 9701     (write _test-input-stream "fn foo {\n")
 9702     (write _test-input-stream "  var x/eax: boolean <- address 0, 0\n")
 9703     (write _test-input-stream "}\n")
 9704     # convert
 9705     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9706     # registers except esp clobbered at this point
 9707     # restore ed
 9708     89/<- %edx 4/r32/esp
 9709     (flush _test-output-buffered-file)
 9710     (flush _test-error-buffered-file)
 9711 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9717     # check output
 9718     (check-stream-equal _test-output-stream  ""  "F - test-address-with-multiple-inouts: output should be empty")
 9719     (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")
 9720     # check that stop(1) was called
 9721     (check-ints-equal *(edx+4) 2 "F - test-address-with-multiple-inouts: exit status")
 9722     # don't restore from ebp
 9723     81 0/subop/add %esp 8/imm32
 9724     # . epilogue
 9725     5d/pop-to-ebp
 9726     c3/return
 9727 
 9728 test-address-with-no-output:
 9729     # . prologue
 9730     55/push-ebp
 9731     89/<- %ebp 4/r32/esp
 9732     # setup
 9733     (clear-stream _test-input-stream)
 9734     (clear-stream $_test-input-buffered-file->buffer)
 9735     (clear-stream _test-output-stream)
 9736     (clear-stream $_test-output-buffered-file->buffer)
 9737     (clear-stream _test-error-stream)
 9738     (clear-stream $_test-error-buffered-file->buffer)
 9739     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9740     68/push 0/imm32
 9741     68/push 0/imm32
 9742     89/<- %edx 4/r32/esp
 9743     (tailor-exit-descriptor %edx 0x10)
 9744     #
 9745     (write _test-input-stream "fn foo {\n")
 9746     (write _test-input-stream "  address 0\n")
 9747     (write _test-input-stream "}\n")
 9748     # convert
 9749     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9750     # registers except esp clobbered at this point
 9751     # restore ed
 9752     89/<- %edx 4/r32/esp
 9753     (flush _test-output-buffered-file)
 9754     (flush _test-error-buffered-file)
 9755 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9761     # check output
 9762     (check-stream-equal _test-output-stream  ""  "F - test-address-with-no-output: output should be empty")
 9763     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'address' expects an output"  "F - test-address-with-no-output: error message")
 9764     # check that stop(1) was called
 9765     (check-ints-equal *(edx+4) 2 "F - test-address-with-no-output: exit status")
 9766     # don't restore from ebp
 9767     81 0/subop/add %esp 8/imm32
 9768     # . epilogue
 9769     5d/pop-to-ebp
 9770     c3/return
 9771 
 9772 test-address-with-multiple-outputs:
 9773     # . prologue
 9774     55/push-ebp
 9775     89/<- %ebp 4/r32/esp
 9776     # setup
 9777     (clear-stream _test-input-stream)
 9778     (clear-stream $_test-input-buffered-file->buffer)
 9779     (clear-stream _test-output-stream)
 9780     (clear-stream $_test-output-buffered-file->buffer)
 9781     (clear-stream _test-error-stream)
 9782     (clear-stream $_test-error-buffered-file->buffer)
 9783     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9784     68/push 0/imm32
 9785     68/push 0/imm32
 9786     89/<- %edx 4/r32/esp
 9787     (tailor-exit-descriptor %edx 0x10)
 9788     #
 9789     (write _test-input-stream "fn foo {\n")
 9790     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 9791     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
 9792     (write _test-input-stream "  x, y <- address 0\n")
 9793     (write _test-input-stream "}\n")
 9794     # convert
 9795     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9796     # registers except esp clobbered at this point
 9797     # restore ed
 9798     89/<- %edx 4/r32/esp
 9799     (flush _test-output-buffered-file)
 9800     (flush _test-error-buffered-file)
 9801 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9807     # check output
 9808     (check-stream-equal _test-output-stream  ""  "F - test-address-with-multiple-outputs: output should be empty")
 9809     (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")
 9810     # check that stop(1) was called
 9811     (check-ints-equal *(edx+4) 2 "F - test-address-with-multiple-outputs: exit status")
 9812     # don't restore from ebp
 9813     81 0/subop/add %esp 8/imm32
 9814     # . epilogue
 9815     5d/pop-to-ebp
 9816     c3/return
 9817 
 9818 # silly but it works
 9819 test-address-of-deref:
 9820     # . prologue
 9821     55/push-ebp
 9822     89/<- %ebp 4/r32/esp
 9823     # setup
 9824     (clear-stream _test-input-stream)
 9825     (clear-stream $_test-input-buffered-file->buffer)
 9826     (clear-stream _test-output-stream)
 9827     (clear-stream $_test-output-buffered-file->buffer)
 9828     #
 9829     (write _test-input-stream "fn foo {\n")
 9830     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
 9831     (write _test-input-stream "  var y/ecx: (addr int) <- address *x\n")
 9832     (write _test-input-stream "}\n")
 9833     # convert
 9834     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9835     (flush _test-output-buffered-file)
 9836     # no errors
 9837     # . epilogue
 9838     5d/pop-to-ebp
 9839     c3/return
 9840 
 9841 test-address-to-non-register:
 9842     # . prologue
 9843     55/push-ebp
 9844     89/<- %ebp 4/r32/esp
 9845     # setup
 9846     (clear-stream _test-input-stream)
 9847     (clear-stream $_test-input-buffered-file->buffer)
 9848     (clear-stream _test-output-stream)
 9849     (clear-stream $_test-output-buffered-file->buffer)
 9850     (clear-stream _test-error-stream)
 9851     (clear-stream $_test-error-buffered-file->buffer)
 9852     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9853     68/push 0/imm32
 9854     68/push 0/imm32
 9855     89/<- %edx 4/r32/esp
 9856     (tailor-exit-descriptor %edx 0x10)
 9857     #
 9858     (write _test-input-stream "fn foo {\n")
 9859     (write _test-input-stream "  var x: (addr int)\n")
 9860     (write _test-input-stream "  x <- address 0\n")
 9861     (write _test-input-stream "}\n")
 9862     # convert
 9863     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9864     # registers except esp clobbered at this point
 9865     # restore ed
 9866     89/<- %edx 4/r32/esp
 9867     (flush _test-output-buffered-file)
 9868     (flush _test-error-buffered-file)
 9869 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9875     # check output
 9876     (check-stream-equal _test-output-stream  ""  "F - test-address-to-non-register: output should be empty")
 9877     (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")
 9878     # check that stop(1) was called
 9879     (check-ints-equal *(edx+4) 2 "F - test-address-to-non-register: exit status")
 9880     # don't restore from ebp
 9881     81 0/subop/add %esp 8/imm32
 9882     # . epilogue
 9883     5d/pop-to-ebp
 9884     c3/return
 9885 
 9886 test-address-with-wrong-type:
 9887     # . prologue
 9888     55/push-ebp
 9889     89/<- %ebp 4/r32/esp
 9890     # setup
 9891     (clear-stream _test-input-stream)
 9892     (clear-stream $_test-input-buffered-file->buffer)
 9893     (clear-stream _test-output-stream)
 9894     (clear-stream $_test-output-buffered-file->buffer)
 9895     (clear-stream _test-error-stream)
 9896     (clear-stream $_test-error-buffered-file->buffer)
 9897     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9898     68/push 0/imm32
 9899     68/push 0/imm32
 9900     89/<- %edx 4/r32/esp
 9901     (tailor-exit-descriptor %edx 0x10)
 9902     #
 9903     (write _test-input-stream "fn foo {\n")
 9904     (write _test-input-stream "  var x: int\n")
 9905     (write _test-input-stream "  var y/eax: (addr boolean) <- address x\n")
 9906     (write _test-input-stream "}\n")
 9907     # convert
 9908     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9909     # registers except esp clobbered at this point
 9910     # restore ed
 9911     89/<- %edx 4/r32/esp
 9912     (flush _test-output-buffered-file)
 9913     (flush _test-error-buffered-file)
 9914 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9920     # check output
 9921     (check-stream-equal _test-output-stream  ""  "F - test-address-with-wrong-type: output should be empty")
 9922     (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")
 9923     # check that stop(1) was called
 9924     (check-ints-equal *(edx+4) 2 "F - test-address-with-wrong-type: exit status")
 9925     # don't restore from ebp
 9926     81 0/subop/add %esp 8/imm32
 9927     # . epilogue
 9928     5d/pop-to-ebp
 9929     c3/return
 9930 
 9931 test-address-with-right-type-for-array:
 9932     # . prologue
 9933     55/push-ebp
 9934     89/<- %ebp 4/r32/esp
 9935     # setup
 9936     (clear-stream _test-input-stream)
 9937     (clear-stream $_test-input-buffered-file->buffer)
 9938     (clear-stream _test-output-stream)
 9939     (clear-stream $_test-output-buffered-file->buffer)
 9940     #
 9941     (write _test-input-stream "fn foo {\n")
 9942     (write _test-input-stream "  var x: (array int 3)\n")
 9943     (write _test-input-stream "  var y/eax: (addr array int) <- address x\n")
 9944     (write _test-input-stream "}\n")
 9945     # convert
 9946     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9947     (flush _test-output-buffered-file)
 9948     # no errors
 9949     # . epilogue
 9950     89/<- %esp 5/r32/ebp
 9951     5d/pop-to-ebp
 9952     c3/return
 9953 
 9954 test-address-with-right-type-for-stream:
 9955     # . prologue
 9956     55/push-ebp
 9957     89/<- %ebp 4/r32/esp
 9958     # setup
 9959     (clear-stream _test-input-stream)
 9960     (clear-stream $_test-input-buffered-file->buffer)
 9961     (clear-stream _test-output-stream)
 9962     (clear-stream $_test-output-buffered-file->buffer)
 9963     #
 9964     (write _test-input-stream "fn foo {\n")
 9965     (write _test-input-stream "  var x: (stream int 3)\n")
 9966     (write _test-input-stream "  var y/eax: (addr stream int) <- address x\n")
 9967     (write _test-input-stream "}\n")
 9968     # convert
 9969     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9970     (flush _test-output-buffered-file)
 9971     # no errors
 9972     # . epilogue
 9973     89/<- %esp 5/r32/ebp
 9974     5d/pop-to-ebp
 9975     c3/return
 9976 
 9977 test-get-with-wrong-field:
 9978     # . prologue
 9979     55/push-ebp
 9980     89/<- %ebp 4/r32/esp
 9981     # setup
 9982     (clear-stream _test-input-stream)
 9983     (clear-stream $_test-input-buffered-file->buffer)
 9984     (clear-stream _test-output-stream)
 9985     (clear-stream $_test-output-buffered-file->buffer)
 9986     (clear-stream _test-error-stream)
 9987     (clear-stream $_test-error-buffered-file->buffer)
 9988     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9989     68/push 0/imm32
 9990     68/push 0/imm32
 9991     89/<- %edx 4/r32/esp
 9992     (tailor-exit-descriptor %edx 0x10)
 9993     #
 9994     (write _test-input-stream "fn foo {\n")
 9995     (write _test-input-stream "  var a: t\n")
 9996     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 9997     (write _test-input-stream "}\n")
 9998     (write _test-input-stream "type t {\n")
 9999     (write _test-input-stream "  x: int\n")
10000     (write _test-input-stream "}\n")
10001     # convert
10002     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10003     # registers except esp clobbered at this point
10004     # restore ed
10005     89/<- %edx 4/r32/esp
10006     (flush _test-output-buffered-file)
10007     (flush _test-error-buffered-file)
10008 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10014     # check output
10015     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-field: output should be empty")
10016     (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")
10017     # check that stop(1) was called
10018     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-field: exit status")
10019     # don't restore from ebp
10020     81 0/subop/add %esp 8/imm32
10021     # . epilogue
10022     5d/pop-to-ebp
10023     c3/return
10024 
10025 test-get-with-wrong-base-type:
10026     # . prologue
10027     55/push-ebp
10028     89/<- %ebp 4/r32/esp
10029     # setup
10030     (clear-stream _test-input-stream)
10031     (clear-stream $_test-input-buffered-file->buffer)
10032     (clear-stream _test-output-stream)
10033     (clear-stream $_test-output-buffered-file->buffer)
10034     (clear-stream _test-error-stream)
10035     (clear-stream $_test-error-buffered-file->buffer)
10036     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10037     68/push 0/imm32
10038     68/push 0/imm32
10039     89/<- %edx 4/r32/esp
10040     (tailor-exit-descriptor %edx 0x10)
10041     #
10042     (write _test-input-stream "fn foo {\n")
10043     (write _test-input-stream "  var a: int\n")
10044     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
10045     (write _test-input-stream "}\n")
10046     # convert
10047     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10048     # registers except esp clobbered at this point
10049     # restore ed
10050     89/<- %edx 4/r32/esp
10051     (flush _test-output-buffered-file)
10052     (flush _test-error-buffered-file)
10053 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10059     # check output
10060     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type: output should be empty")
10061     (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")
10062     # check that stop(1) was called
10063     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type: exit status")
10064     # don't restore from ebp
10065     81 0/subop/add %esp 8/imm32
10066     # . epilogue
10067     5d/pop-to-ebp
10068     c3/return
10069 
10070 test-get-with-wrong-base-type-2:
10071     # . prologue
10072     55/push-ebp
10073     89/<- %ebp 4/r32/esp
10074     # setup
10075     (clear-stream _test-input-stream)
10076     (clear-stream $_test-input-buffered-file->buffer)
10077     (clear-stream _test-output-stream)
10078     (clear-stream $_test-output-buffered-file->buffer)
10079     (clear-stream _test-error-stream)
10080     (clear-stream $_test-error-buffered-file->buffer)
10081     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10082     68/push 0/imm32
10083     68/push 0/imm32
10084     89/<- %edx 4/r32/esp
10085     (tailor-exit-descriptor %edx 0x10)
10086     #
10087     (write _test-input-stream "fn foo {\n")
10088     (write _test-input-stream "  var a: (addr t)\n")
10089     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
10090     (write _test-input-stream "}\n")
10091     (write _test-input-stream "type t {\n")
10092     (write _test-input-stream "  x: int\n")
10093     (write _test-input-stream "}\n")
10094     # convert
10095     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10096     # registers except esp clobbered at this point
10097     # restore ed
10098     89/<- %edx 4/r32/esp
10099     (flush _test-output-buffered-file)
10100     (flush _test-error-buffered-file)
10101 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10107     # check output
10108     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type-2: output should be empty")
10109     (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")
10110     # check that stop(1) was called
10111     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type-2: exit status")
10112     # don't restore from ebp
10113     81 0/subop/add %esp 8/imm32
10114     # . epilogue
10115     5d/pop-to-ebp
10116     c3/return
10117 
10118 test-get-with-wrong-base-type-3:
10119     # . prologue
10120     55/push-ebp
10121     89/<- %ebp 4/r32/esp
10122     # setup
10123     (clear-stream _test-input-stream)
10124     (clear-stream $_test-input-buffered-file->buffer)
10125     (clear-stream _test-output-stream)
10126     (clear-stream $_test-output-buffered-file->buffer)
10127     (clear-stream _test-error-stream)
10128     (clear-stream $_test-error-buffered-file->buffer)
10129     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10130     68/push 0/imm32
10131     68/push 0/imm32
10132     89/<- %edx 4/r32/esp
10133     (tailor-exit-descriptor %edx 0x10)
10134     #
10135     (write _test-input-stream "fn foo {\n")
10136     (write _test-input-stream "  var a: (handle int)\n")
10137     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
10138     (write _test-input-stream "}\n")
10139     # convert
10140     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10141     # registers except esp clobbered at this point
10142     # restore ed
10143     89/<- %edx 4/r32/esp
10144     (flush _test-output-buffered-file)
10145     (flush _test-error-buffered-file)
10146 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10152     # check output
10153     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type-3: output should be empty")
10154     (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")
10155     # check that stop(1) was called
10156     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type-3: exit status")
10157     # don't restore from ebp
10158     81 0/subop/add %esp 8/imm32
10159     # . epilogue
10160     5d/pop-to-ebp
10161     c3/return
10162 
10163 test-get-with-wrong-offset-type:
10164     # . prologue
10165     55/push-ebp
10166     89/<- %ebp 4/r32/esp
10167     # setup
10168     (clear-stream _test-input-stream)
10169     (clear-stream $_test-input-buffered-file->buffer)
10170     (clear-stream _test-output-stream)
10171     (clear-stream $_test-output-buffered-file->buffer)
10172     (clear-stream _test-error-stream)
10173     (clear-stream $_test-error-buffered-file->buffer)
10174     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10175     68/push 0/imm32
10176     68/push 0/imm32
10177     89/<- %edx 4/r32/esp
10178     (tailor-exit-descriptor %edx 0x10)
10179     #
10180     (write _test-input-stream "fn foo {\n")
10181     (write _test-input-stream "  var a: t\n")
10182     (write _test-input-stream "  var b: int\n")
10183     (write _test-input-stream "  var c/ecx: (addr int) <- get a, b\n")
10184     (write _test-input-stream "}\n")
10185     (write _test-input-stream "type t {\n")
10186     (write _test-input-stream "  x: int\n")
10187     (write _test-input-stream "}\n")
10188     # convert
10189     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10190     # registers except esp clobbered at this point
10191     # restore ed
10192     89/<- %edx 4/r32/esp
10193     (flush _test-output-buffered-file)
10194     (flush _test-error-buffered-file)
10195 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10201     # check output
10202     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-offset-type: output should be empty")
10203     (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")
10204     # check that stop(1) was called
10205     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-offset-type: exit status")
10206     # don't restore from ebp
10207     81 0/subop/add %esp 8/imm32
10208     # . epilogue
10209     5d/pop-to-ebp
10210     c3/return
10211 
10212 test-get-with-wrong-output-type:
10213     # . prologue
10214     55/push-ebp
10215     89/<- %ebp 4/r32/esp
10216     # setup
10217     (clear-stream _test-input-stream)
10218     (clear-stream $_test-input-buffered-file->buffer)
10219     (clear-stream _test-output-stream)
10220     (clear-stream $_test-output-buffered-file->buffer)
10221     (clear-stream _test-error-stream)
10222     (clear-stream $_test-error-buffered-file->buffer)
10223     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10224     68/push 0/imm32
10225     68/push 0/imm32
10226     89/<- %edx 4/r32/esp
10227     (tailor-exit-descriptor %edx 0x10)
10228     #
10229     (write _test-input-stream "fn foo {\n")
10230     (write _test-input-stream "  var a: t\n")
10231     (write _test-input-stream "  var c: (addr int)\n")
10232     (write _test-input-stream "  c <- get a, x\n")
10233     (write _test-input-stream "}\n")
10234     (write _test-input-stream "type t {\n")
10235     (write _test-input-stream "  x: int\n")
10236     (write _test-input-stream "}\n")
10237     # convert
10238     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10239     # registers except esp clobbered at this point
10240     # restore ed
10241     89/<- %edx 4/r32/esp
10242     (flush _test-output-buffered-file)
10243     (flush _test-error-buffered-file)
10244 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10250     # check output
10251     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type: output should be empty")
10252     (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")
10253     # check that stop(1) was called
10254     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type: exit status")
10255     # don't restore from ebp
10256     81 0/subop/add %esp 8/imm32
10257     # . epilogue
10258     5d/pop-to-ebp
10259     c3/return
10260 
10261 test-get-with-wrong-output-type-2:
10262     # . prologue
10263     55/push-ebp
10264     89/<- %ebp 4/r32/esp
10265     # setup
10266     (clear-stream _test-input-stream)
10267     (clear-stream $_test-input-buffered-file->buffer)
10268     (clear-stream _test-output-stream)
10269     (clear-stream $_test-output-buffered-file->buffer)
10270     (clear-stream _test-error-stream)
10271     (clear-stream $_test-error-buffered-file->buffer)
10272     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10273     68/push 0/imm32
10274     68/push 0/imm32
10275     89/<- %edx 4/r32/esp
10276     (tailor-exit-descriptor %edx 0x10)
10277     #
10278     (write _test-input-stream "fn foo {\n")
10279     (write _test-input-stream "  var a: t\n")
10280     (write _test-input-stream "  var c/ecx: int <- get a, x\n")
10281     (write _test-input-stream "}\n")
10282     (write _test-input-stream "type t {\n")
10283     (write _test-input-stream "  x: int\n")
10284     (write _test-input-stream "}\n")
10285     # convert
10286     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10287     # registers except esp clobbered at this point
10288     # restore ed
10289     89/<- %edx 4/r32/esp
10290     (flush _test-output-buffered-file)
10291     (flush _test-error-buffered-file)
10292 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10298     # check output
10299     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-2: output should be empty")
10300     (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")
10301     # check that stop(1) was called
10302     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-2: exit status")
10303     # don't restore from ebp
10304     81 0/subop/add %esp 8/imm32
10305     # . epilogue
10306     5d/pop-to-ebp
10307     c3/return
10308 
10309 test-get-with-wrong-output-type-3:
10310     # . prologue
10311     55/push-ebp
10312     89/<- %ebp 4/r32/esp
10313     # setup
10314     (clear-stream _test-input-stream)
10315     (clear-stream $_test-input-buffered-file->buffer)
10316     (clear-stream _test-output-stream)
10317     (clear-stream $_test-output-buffered-file->buffer)
10318     (clear-stream _test-error-stream)
10319     (clear-stream $_test-error-buffered-file->buffer)
10320     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10321     68/push 0/imm32
10322     68/push 0/imm32
10323     89/<- %edx 4/r32/esp
10324     (tailor-exit-descriptor %edx 0x10)
10325     #
10326     (write _test-input-stream "fn foo {\n")
10327     (write _test-input-stream "  var a: t\n")
10328     (write _test-input-stream "  var c/ecx: (array int) <- get a, x\n")
10329     (write _test-input-stream "}\n")
10330     (write _test-input-stream "type t {\n")
10331     (write _test-input-stream "  x: int\n")
10332     (write _test-input-stream "}\n")
10333     # convert
10334     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10335     # registers except esp clobbered at this point
10336     # restore ed
10337     89/<- %edx 4/r32/esp
10338     (flush _test-output-buffered-file)
10339     (flush _test-error-buffered-file)
10340 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10346     # check output
10347     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-3: output should be empty")
10348     (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")
10349     # check that stop(1) was called
10350     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-3: exit status")
10351     # don't restore from ebp
10352     81 0/subop/add %esp 8/imm32
10353     # . epilogue
10354     5d/pop-to-ebp
10355     c3/return
10356 
10357 test-get-with-wrong-output-type-4:
10358     # . prologue
10359     55/push-ebp
10360     89/<- %ebp 4/r32/esp
10361     # setup
10362     (clear-stream _test-input-stream)
10363     (clear-stream $_test-input-buffered-file->buffer)
10364     (clear-stream _test-output-stream)
10365     (clear-stream $_test-output-buffered-file->buffer)
10366     (clear-stream _test-error-stream)
10367     (clear-stream $_test-error-buffered-file->buffer)
10368     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10369     68/push 0/imm32
10370     68/push 0/imm32
10371     89/<- %edx 4/r32/esp
10372     (tailor-exit-descriptor %edx 0x10)
10373     #
10374     (write _test-input-stream "fn foo {\n")
10375     (write _test-input-stream "  var a: t\n")
10376     (write _test-input-stream "  var c/ecx: (addr boolean) <- get a, x\n")
10377     (write _test-input-stream "}\n")
10378     (write _test-input-stream "type t {\n")
10379     (write _test-input-stream "  x: int\n")
10380     (write _test-input-stream "}\n")
10381     # convert
10382     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10383     # registers except esp clobbered at this point
10384     # restore ed
10385     89/<- %edx 4/r32/esp
10386     (flush _test-output-buffered-file)
10387     (flush _test-error-buffered-file)
10388 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10394     # check output
10395     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-4: output should be empty")
10396     (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")
10397     # check that stop(1) was called
10398     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-4: exit status")
10399     # don't restore from ebp
10400     81 0/subop/add %esp 8/imm32
10401     # . epilogue
10402     5d/pop-to-ebp
10403     c3/return
10404 
10405 test-get-with-wrong-output-type-5:
10406     # . prologue
10407     55/push-ebp
10408     89/<- %ebp 4/r32/esp
10409     # setup
10410     (clear-stream _test-input-stream)
10411     (clear-stream $_test-input-buffered-file->buffer)
10412     (clear-stream _test-output-stream)
10413     (clear-stream $_test-output-buffered-file->buffer)
10414     #
10415     (write _test-input-stream "fn foo {\n")
10416     (write _test-input-stream "  var a: t\n")
10417     (write _test-input-stream "  var c/ecx: (addr handle int) <- get a, x\n")
10418     (write _test-input-stream "}\n")
10419     (write _test-input-stream "type t {\n")
10420     (write _test-input-stream "  x: (handle int)\n")
10421     (write _test-input-stream "}\n")
10422     # convert
10423     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10424     (flush _test-output-buffered-file)
10425     # no errors
10426     # . epilogue
10427     89/<- %esp 5/r32/ebp
10428     5d/pop-to-ebp
10429     c3/return
10430 
10431 test-get-with-too-few-inouts:
10432     # . prologue
10433     55/push-ebp
10434     89/<- %ebp 4/r32/esp
10435     # setup
10436     (clear-stream _test-input-stream)
10437     (clear-stream $_test-input-buffered-file->buffer)
10438     (clear-stream _test-output-stream)
10439     (clear-stream $_test-output-buffered-file->buffer)
10440     (clear-stream _test-error-stream)
10441     (clear-stream $_test-error-buffered-file->buffer)
10442     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10443     68/push 0/imm32
10444     68/push 0/imm32
10445     89/<- %edx 4/r32/esp
10446     (tailor-exit-descriptor %edx 0x10)
10447     #
10448     (write _test-input-stream "fn foo {\n")
10449     (write _test-input-stream "  var a: t\n")
10450     (write _test-input-stream "  var c/ecx: (addr int) <- get a\n")
10451     (write _test-input-stream "}\n")
10452     (write _test-input-stream "type t {\n")
10453     (write _test-input-stream "  x: int\n")
10454     (write _test-input-stream "}\n")
10455     # convert
10456     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10457     # registers except esp clobbered at this point
10458     # restore ed
10459     89/<- %edx 4/r32/esp
10460     (flush _test-output-buffered-file)
10461     (flush _test-error-buffered-file)
10462 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10468     # check output
10469     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-few-inouts: output should be empty")
10470     (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")
10471     # check that stop(1) was called
10472     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-few-inouts: exit status")
10473     # don't restore from ebp
10474     81 0/subop/add %esp 8/imm32
10475     # . epilogue
10476     5d/pop-to-ebp
10477     c3/return
10478 
10479 test-get-with-too-many-inouts:
10480     # . prologue
10481     55/push-ebp
10482     89/<- %ebp 4/r32/esp
10483     # setup
10484     (clear-stream _test-input-stream)
10485     (clear-stream $_test-input-buffered-file->buffer)
10486     (clear-stream _test-output-stream)
10487     (clear-stream $_test-output-buffered-file->buffer)
10488     (clear-stream _test-error-stream)
10489     (clear-stream $_test-error-buffered-file->buffer)
10490     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10491     68/push 0/imm32
10492     68/push 0/imm32
10493     89/<- %edx 4/r32/esp
10494     (tailor-exit-descriptor %edx 0x10)
10495     #
10496     (write _test-input-stream "fn foo {\n")
10497     (write _test-input-stream "  var a: t\n")
10498     (write _test-input-stream "  var c/ecx: (addr int) <- get a, x, 0\n")
10499     (write _test-input-stream "}\n")
10500     (write _test-input-stream "type t {\n")
10501     (write _test-input-stream "  x: int\n")
10502     (write _test-input-stream "}\n")
10503     # convert
10504     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10505     # registers except esp clobbered at this point
10506     # restore ed
10507     89/<- %edx 4/r32/esp
10508     (flush _test-output-buffered-file)
10509     (flush _test-error-buffered-file)
10510 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10516     # check output
10517     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-many-inouts: output should be empty")
10518     (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")
10519     # check that stop(1) was called
10520     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-many-inouts: exit status")
10521     # don't restore from ebp
10522     81 0/subop/add %esp 8/imm32
10523     # . epilogue
10524     5d/pop-to-ebp
10525     c3/return
10526 
10527 test-get-with-no-output:
10528     # . prologue
10529     55/push-ebp
10530     89/<- %ebp 4/r32/esp
10531     # setup
10532     (clear-stream _test-input-stream)
10533     (clear-stream $_test-input-buffered-file->buffer)
10534     (clear-stream _test-output-stream)
10535     (clear-stream $_test-output-buffered-file->buffer)
10536     (clear-stream _test-error-stream)
10537     (clear-stream $_test-error-buffered-file->buffer)
10538     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10539     68/push 0/imm32
10540     68/push 0/imm32
10541     89/<- %edx 4/r32/esp
10542     (tailor-exit-descriptor %edx 0x10)
10543     #
10544     (write _test-input-stream "fn foo {\n")
10545     (write _test-input-stream "  var a: t\n")
10546     (write _test-input-stream "  get a, x\n")
10547     (write _test-input-stream "}\n")
10548     (write _test-input-stream "type t {\n")
10549     (write _test-input-stream "  x: int\n")
10550     (write _test-input-stream "}\n")
10551     # convert
10552     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10553     # registers except esp clobbered at this point
10554     # restore ed
10555     89/<- %edx 4/r32/esp
10556     (flush _test-output-buffered-file)
10557     (flush _test-error-buffered-file)
10558 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10564     # check output
10565     (check-stream-equal _test-output-stream  ""  "F - test-get-with-no-output: output should be empty")
10566     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: must have an output"  "F - test-get-with-no-output: error message")
10567     # check that stop(1) was called
10568     (check-ints-equal *(edx+4) 2 "F - test-get-with-no-output: exit status")
10569     # don't restore from ebp
10570     81 0/subop/add %esp 8/imm32
10571     # . epilogue
10572     5d/pop-to-ebp
10573     c3/return
10574 
10575 test-get-with-too-many-outputs:
10576     # . prologue
10577     55/push-ebp
10578     89/<- %ebp 4/r32/esp
10579     # setup
10580     (clear-stream _test-input-stream)
10581     (clear-stream $_test-input-buffered-file->buffer)
10582     (clear-stream _test-output-stream)
10583     (clear-stream $_test-output-buffered-file->buffer)
10584     (clear-stream _test-error-stream)
10585     (clear-stream $_test-error-buffered-file->buffer)
10586     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10587     68/push 0/imm32
10588     68/push 0/imm32
10589     89/<- %edx 4/r32/esp
10590     (tailor-exit-descriptor %edx 0x10)
10591     #
10592     (write _test-input-stream "fn foo {\n")
10593     (write _test-input-stream "  var a: t\n")
10594     (write _test-input-stream "  var b: int\n")
10595     (write _test-input-stream "  var c/eax: (addr int) <- copy 0\n")
10596     (write _test-input-stream "  c, b <- get a, x\n")
10597     (write _test-input-stream "}\n")
10598     (write _test-input-stream "type t {\n")
10599     (write _test-input-stream "  x: int\n")
10600     (write _test-input-stream "}\n")
10601     # convert
10602     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10603     # registers except esp clobbered at this point
10604     # restore ed
10605     89/<- %edx 4/r32/esp
10606     (flush _test-output-buffered-file)
10607     (flush _test-error-buffered-file)
10608 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10614     # check output
10615     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-many-outputs: output should be empty")
10616     (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")
10617     # check that stop(1) was called
10618     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-many-outputs: exit status")
10619     # don't restore from ebp
10620     81 0/subop/add %esp 8/imm32
10621     # . epilogue
10622     5d/pop-to-ebp
10623     c3/return
10624 
10625 test-convert-array-of-user-defined-types:
10626     # . prologue
10627     55/push-ebp
10628     89/<- %ebp 4/r32/esp
10629     # setup
10630     (clear-stream _test-input-stream)
10631     (clear-stream $_test-input-buffered-file->buffer)
10632     (clear-stream _test-output-stream)
10633     (clear-stream $_test-output-buffered-file->buffer)
10634     #
10635     (write _test-input-stream "type t {\n")  # each t is 8 bytes, which is a power of 2
10636     (write _test-input-stream "  x: int\n")
10637     (write _test-input-stream "  y: int\n")
10638     (write _test-input-stream "}\n")
10639     (write _test-input-stream "fn foo {\n")
10640     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
10641     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
10642     (write _test-input-stream "  var x/eax: (addr t) <- index arr, idx\n")
10643     (write _test-input-stream "}\n")
10644     # convert
10645     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10646     (flush _test-output-buffered-file)
10647 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
10653     # check output
10654     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-array-of-user-defined-types/0")
10655     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-array-of-user-defined-types/1")
10656     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-array-of-user-defined-types/2")
10657     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-array-of-user-defined-types/3")
10658     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-array-of-user-defined-types/4")
10659     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-array-of-user-defined-types/5")
10660     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-array-of-user-defined-types/6")
10661     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-array-of-user-defined-types/7")
10662     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-array-of-user-defined-types/8")
10663     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-array-of-user-defined-types/9")
10664     (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")
10665     (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")
10666     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-array-of-user-defined-types/12")
10667     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-array-of-user-defined-types/13")
10668     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-array-of-user-defined-types/14")
10669     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-array-of-user-defined-types/15")
10670     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-array-of-user-defined-types/16")
10671     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-array-of-user-defined-types/17")
10672     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-array-of-user-defined-types/18")
10673     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-array-of-user-defined-types/19")
10674     # . epilogue
10675     89/<- %esp 5/r32/ebp
10676     5d/pop-to-ebp
10677     c3/return
10678 
10679 test-convert-length-of-array-of-user-defined-types-to-eax:
10680     # . prologue
10681     55/push-ebp
10682     89/<- %ebp 4/r32/esp
10683     # setup
10684     (clear-stream _test-input-stream)
10685     (clear-stream $_test-input-buffered-file->buffer)
10686     (clear-stream _test-output-stream)
10687     (clear-stream $_test-output-buffered-file->buffer)
10688     #
10689     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
10690     (write _test-input-stream "  x: int\n")
10691     (write _test-input-stream "  y: int\n")
10692     (write _test-input-stream "  z: int\n")
10693     (write _test-input-stream "}\n")
10694     (write _test-input-stream "fn foo {\n")
10695     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
10696     (write _test-input-stream "  var x/eax: int <- length arr\n")
10697     (write _test-input-stream "}\n")
10698     # convert
10699     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10700     (flush _test-output-buffered-file)
10701 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
10707     # check output
10708     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-eax/0")
10709     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-eax/1")
10710     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-eax/2")
10711     (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")
10712     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-eax/4")
10713     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-eax/5")
10714     # var arr
10715     (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")
10716     (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")
10717     # length instruction
10718     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types-to-eax/8")
10719     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types-to-eax/9")
10720     (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")
10721     (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")
10722     (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")
10723     (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")
10724     (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")
10725     (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")
10726     # reclaim arr
10727     (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")
10728     #
10729     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-eax/17")
10730     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/18")
10731     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-eax/19")
10732     (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")
10733     (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")
10734     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-eax/22")
10735     # . epilogue
10736     89/<- %esp 5/r32/ebp
10737     5d/pop-to-ebp
10738     c3/return
10739 
10740 test-convert-length-of-array-of-user-defined-types-to-ecx:
10741     # . prologue
10742     55/push-ebp
10743     89/<- %ebp 4/r32/esp
10744     # setup
10745     (clear-stream _test-input-stream)
10746     (clear-stream $_test-input-buffered-file->buffer)
10747     (clear-stream _test-output-stream)
10748     (clear-stream $_test-output-buffered-file->buffer)
10749     #
10750     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
10751     (write _test-input-stream "  x: int\n")
10752     (write _test-input-stream "  y: int\n")
10753     (write _test-input-stream "  z: int\n")
10754     (write _test-input-stream "}\n")
10755     (write _test-input-stream "fn foo {\n")
10756     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
10757     (write _test-input-stream "  var x/ecx: int <- length arr\n")
10758     (write _test-input-stream "}\n")
10759     # convert
10760     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10761     (flush _test-output-buffered-file)
10762 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
10768     # check output
10769     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-ecx/0")
10770     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-ecx/1")
10771     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-ecx/2")
10772     (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")
10773     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-ecx/4")
10774     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-ecx/5")
10775     # var a
10776     (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")
10777     (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")
10778     # var x
10779     (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")
10780     # length instruction
10781     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types-to-ecx/9")
10782     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types-to-ecx/10")
10783     (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")
10784     (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")
10785     (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")
10786     (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")
10787     (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")
10788     (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")
10789     (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")
10790     # reclaim x
10791     (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")
10792     # reclaim a
10793     (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")
10794     #
10795     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-ecx/20")
10796     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/21")
10797     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-ecx/22")
10798     (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")
10799     (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")
10800     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-ecx/25")
10801     # . epilogue
10802     89/<- %esp 5/r32/ebp
10803     5d/pop-to-ebp
10804     c3/return
10805 
10806 test-convert-length-of-array-of-user-defined-types-to-edx:
10807     # . prologue
10808     55/push-ebp
10809     89/<- %ebp 4/r32/esp
10810     # setup
10811     (clear-stream _test-input-stream)
10812     (clear-stream $_test-input-buffered-file->buffer)
10813     (clear-stream _test-output-stream)
10814     (clear-stream $_test-output-buffered-file->buffer)
10815     #
10816     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
10817     (write _test-input-stream "  x: int\n")
10818     (write _test-input-stream "  y: int\n")
10819     (write _test-input-stream "  z: int\n")
10820     (write _test-input-stream "}\n")
10821     (write _test-input-stream "fn foo {\n")
10822     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
10823     (write _test-input-stream "  var x/edx: int <- length arr\n")
10824     (write _test-input-stream "}\n")
10825     # convert
10826     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10827     (flush _test-output-buffered-file)
10828 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
10834     # check output
10835     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-edx/0")
10836     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-edx/1")
10837     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-edx/2")
10838     (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")
10839     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-edx/4")
10840     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-edx/5")
10841     # var a
10842     (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")
10843     (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")
10844     # var x
10845     (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")
10846     # length instruction
10847     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types-to-edx/9")
10848     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types-to-edx/10")
10849     (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")
10850     (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")
10851     (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")
10852     (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")
10853     (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")
10854     (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")
10855     (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")
10856     # reclaim x
10857     (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")
10858     # reclaim a
10859     (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")
10860     #
10861     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-edx/20")
10862     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/21")
10863     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-edx/22")
10864     (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")
10865     (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")
10866     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-edx/25")
10867     # . epilogue
10868     89/<- %esp 5/r32/ebp
10869     5d/pop-to-ebp
10870     c3/return
10871 
10872 test-convert-length-of-array-of-user-defined-types:
10873     # . prologue
10874     55/push-ebp
10875     89/<- %ebp 4/r32/esp
10876     # setup
10877     (clear-stream _test-input-stream)
10878     (clear-stream $_test-input-buffered-file->buffer)
10879     (clear-stream _test-output-stream)
10880     (clear-stream $_test-output-buffered-file->buffer)
10881     #
10882     (write _test-input-stream "type t {\n")  # each t is 8 bytes, which is a power of 2
10883     (write _test-input-stream "  x: int\n")
10884     (write _test-input-stream "  y: int\n")
10885     (write _test-input-stream "  z: int\n")
10886     (write _test-input-stream "}\n")
10887     (write _test-input-stream "fn foo {\n")
10888     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
10889     (write _test-input-stream "  var x/ebx: int <- length arr\n")
10890     (write _test-input-stream "}\n")
10891     # convert
10892     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10893     (flush _test-output-buffered-file)
10894 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
10900     # check output
10901     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types/0")
10902     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types/1")
10903     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types/2")
10904     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-user-defined-types/3")
10905     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types/4")
10906     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types/5")
10907     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-of-user-defined-types/6")
10908     (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")
10909     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-length-of-array-of-user-defined-types/8")
10910     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types/9")
10911     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types/10")
10912     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types/11")
10913     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array-of-user-defined-types/12")
10914     (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")
10915     (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")
10916     (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")
10917     (check-next-stream-line-equal _test-output-stream "    89/<- %ebx 0/r32/eax"  "F - test-convert-length-of-array-of-user-defined-types/16")
10918     (check-next-stream-line-equal _test-output-stream "    5a/pop-to-edx"       "F - test-convert-length-of-array-of-user-defined-types/17")
10919     (check-next-stream-line-equal _test-output-stream "    59/pop-to-ecx"       "F - test-convert-length-of-array-of-user-defined-types/18")
10920     (check-next-stream-line-equal _test-output-stream "    58/pop-to-eax"       "F - test-convert-length-of-array-of-user-defined-types/19")
10921     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ebx"  "F - test-convert-length-of-array-of-user-defined-types/20")
10922     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-of-user-defined-types/21")
10923     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types/22")
10924     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types/23")
10925     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types/24")
10926     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-of-user-defined-types/25")
10927     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-of-user-defined-types/26")
10928     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types/27")
10929     # . epilogue
10930     89/<- %esp 5/r32/ebp
10931     5d/pop-to-ebp
10932     c3/return
10933 
10934 test-index-with-non-array-atom-base-type:
10935     # . prologue
10936     55/push-ebp
10937     89/<- %ebp 4/r32/esp
10938     # setup
10939     (clear-stream _test-input-stream)
10940     (clear-stream $_test-input-buffered-file->buffer)
10941     (clear-stream _test-output-stream)
10942     (clear-stream $_test-output-buffered-file->buffer)
10943     (clear-stream _test-error-stream)
10944     (clear-stream $_test-error-buffered-file->buffer)
10945     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10946     68/push 0/imm32
10947     68/push 0/imm32
10948     89/<- %edx 4/r32/esp
10949     (tailor-exit-descriptor %edx 0x10)
10950     #
10951     (write _test-input-stream "fn foo {\n")
10952     (write _test-input-stream "  var a: int\n")
10953     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
10954     (write _test-input-stream "}\n")
10955     # convert
10956     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10957     # registers except esp clobbered at this point
10958     # restore ed
10959     89/<- %edx 4/r32/esp
10960     (flush _test-output-buffered-file)
10961     (flush _test-error-buffered-file)
10962 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10968     # check output
10969     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-atom-base-type: output should be empty")
10970     (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")
10971     # check that stop(1) was called
10972     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-atom-base-type: exit status")
10973     # don't restore from ebp
10974     81 0/subop/add %esp 8/imm32
10975     # . epilogue
10976     5d/pop-to-ebp
10977     c3/return
10978 
10979 test-index-with-non-array-compound-base-type:
10980     # . prologue
10981     55/push-ebp
10982     89/<- %ebp 4/r32/esp
10983     # setup
10984     (clear-stream _test-input-stream)
10985     (clear-stream $_test-input-buffered-file->buffer)
10986     (clear-stream _test-output-stream)
10987     (clear-stream $_test-output-buffered-file->buffer)
10988     (clear-stream _test-error-stream)
10989     (clear-stream $_test-error-buffered-file->buffer)
10990     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10991     68/push 0/imm32
10992     68/push 0/imm32
10993     89/<- %edx 4/r32/esp
10994     (tailor-exit-descriptor %edx 0x10)
10995     #
10996     (write _test-input-stream "fn foo {\n")
10997     (write _test-input-stream "  var a: (handle int)\n")
10998     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
10999     (write _test-input-stream "}\n")
11000     # convert
11001     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11002     # registers except esp clobbered at this point
11003     # restore ed
11004     89/<- %edx 4/r32/esp
11005     (flush _test-output-buffered-file)
11006     (flush _test-error-buffered-file)
11007 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11013     # check output
11014     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-compound-base-type: output should be empty")
11015     (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")
11016     # check that stop(1) was called
11017     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-compound-base-type: exit status")
11018     # don't restore from ebp
11019     81 0/subop/add %esp 8/imm32
11020     # . epilogue
11021     5d/pop-to-ebp
11022     c3/return
11023 
11024 test-index-with-non-array-compound-base-type-2:
11025     # . prologue
11026     55/push-ebp
11027     89/<- %ebp 4/r32/esp
11028     # setup
11029     (clear-stream _test-input-stream)
11030     (clear-stream $_test-input-buffered-file->buffer)
11031     (clear-stream _test-output-stream)
11032     (clear-stream $_test-output-buffered-file->buffer)
11033     (clear-stream _test-error-stream)
11034     (clear-stream $_test-error-buffered-file->buffer)
11035     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11036     68/push 0/imm32
11037     68/push 0/imm32
11038     89/<- %edx 4/r32/esp
11039     (tailor-exit-descriptor %edx 0x10)
11040     #
11041     (write _test-input-stream "fn foo {\n")
11042     (write _test-input-stream "  var a: (addr int)\n")
11043     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
11044     (write _test-input-stream "}\n")
11045     # convert
11046     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11047     # registers except esp clobbered at this point
11048     # restore ed
11049     89/<- %edx 4/r32/esp
11050     (flush _test-output-buffered-file)
11051     (flush _test-error-buffered-file)
11052 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11058     # check output
11059     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-compound-base-type-2: output should be empty")
11060     (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")
11061     # check that stop(1) was called
11062     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-compound-base-type-2: exit status")
11063     # don't restore from ebp
11064     81 0/subop/add %esp 8/imm32
11065     # . epilogue
11066     5d/pop-to-ebp
11067     c3/return
11068 
11069 test-index-with-array-atom-base-type:
11070     # . prologue
11071     55/push-ebp
11072     89/<- %ebp 4/r32/esp
11073     # setup
11074     (clear-stream _test-input-stream)
11075     (clear-stream $_test-input-buffered-file->buffer)
11076     (clear-stream _test-output-stream)
11077     (clear-stream $_test-output-buffered-file->buffer)
11078     (clear-stream _test-error-stream)
11079     (clear-stream $_test-error-buffered-file->buffer)
11080     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11081     68/push 0/imm32
11082     68/push 0/imm32
11083     89/<- %edx 4/r32/esp
11084     (tailor-exit-descriptor %edx 0x10)
11085     #
11086     (write _test-input-stream "fn foo {\n")
11087     (write _test-input-stream "  var a: array\n")
11088     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
11089     (write _test-input-stream "}\n")
11090     # convert
11091     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11092     # registers except esp clobbered at this point
11093     # restore ed
11094     89/<- %edx 4/r32/esp
11095     (flush _test-output-buffered-file)
11096     (flush _test-error-buffered-file)
11097 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11103     # check output
11104     (check-stream-equal _test-output-stream  ""  "F - test-index-with-array-atom-base-type: output should be empty")
11105     (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")
11106     # check that stop(1) was called
11107     (check-ints-equal *(edx+4) 2 "F - test-index-with-array-atom-base-type: exit status")
11108     # don't restore from ebp
11109     81 0/subop/add %esp 8/imm32
11110     # . epilogue
11111     5d/pop-to-ebp
11112     c3/return
11113 
11114 test-index-with-addr-base-on-stack:
11115     # . prologue
11116     55/push-ebp
11117     89/<- %ebp 4/r32/esp
11118     # setup
11119     (clear-stream _test-input-stream)
11120     (clear-stream $_test-input-buffered-file->buffer)
11121     (clear-stream _test-output-stream)
11122     (clear-stream $_test-output-buffered-file->buffer)
11123     (clear-stream _test-error-stream)
11124     (clear-stream $_test-error-buffered-file->buffer)
11125     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11126     68/push 0/imm32
11127     68/push 0/imm32
11128     89/<- %edx 4/r32/esp
11129     (tailor-exit-descriptor %edx 0x10)
11130     #
11131     (write _test-input-stream "fn foo {\n")
11132     (write _test-input-stream "  var a: (addr array int)\n")
11133     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
11134     (write _test-input-stream "}\n")
11135     # convert
11136     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11137     # registers except esp clobbered at this point
11138     # restore ed
11139     89/<- %edx 4/r32/esp
11140     (flush _test-output-buffered-file)
11141     (flush _test-error-buffered-file)
11142 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11148     # check output
11149     (check-stream-equal _test-output-stream  ""  "F - test-index-with-addr-base-on-stack: output should be empty")
11150     (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")
11151     # check that stop(1) was called
11152     (check-ints-equal *(edx+4) 2 "F - test-index-with-addr-base-on-stack: exit status")
11153     # don't restore from ebp
11154     81 0/subop/add %esp 8/imm32
11155     # . epilogue
11156     5d/pop-to-ebp
11157     c3/return
11158 
11159 test-index-with-wrong-index-type:
11160     # . prologue
11161     55/push-ebp
11162     89/<- %ebp 4/r32/esp
11163     # setup
11164     (clear-stream _test-input-stream)
11165     (clear-stream $_test-input-buffered-file->buffer)
11166     (clear-stream _test-output-stream)
11167     (clear-stream $_test-output-buffered-file->buffer)
11168     (clear-stream _test-error-stream)
11169     (clear-stream $_test-error-buffered-file->buffer)
11170     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11171     68/push 0/imm32
11172     68/push 0/imm32
11173     89/<- %edx 4/r32/esp
11174     (tailor-exit-descriptor %edx 0x10)
11175     #
11176     (write _test-input-stream "fn foo {\n")
11177     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
11178     (write _test-input-stream "  var b: boolean\n")
11179     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
11180     (write _test-input-stream "}\n")
11181     # convert
11182     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11183     # registers except esp clobbered at this point
11184     # restore ed
11185     89/<- %edx 4/r32/esp
11186     (flush _test-output-buffered-file)
11187     (flush _test-error-buffered-file)
11188 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11194     # check output
11195     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-index-type: output should be empty")
11196     (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")
11197     # check that stop(1) was called
11198     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-index-type: exit status")
11199     # don't restore from ebp
11200     81 0/subop/add %esp 8/imm32
11201     # . epilogue
11202     5d/pop-to-ebp
11203     c3/return
11204 
11205 test-index-with-offset-atom-index-type:
11206     # . prologue
11207     55/push-ebp
11208     89/<- %ebp 4/r32/esp
11209     # setup
11210     (clear-stream _test-input-stream)
11211     (clear-stream $_test-input-buffered-file->buffer)
11212     (clear-stream _test-output-stream)
11213     (clear-stream $_test-output-buffered-file->buffer)
11214     (clear-stream _test-error-stream)
11215     (clear-stream $_test-error-buffered-file->buffer)
11216     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11217     68/push 0/imm32
11218     68/push 0/imm32
11219     89/<- %edx 4/r32/esp
11220     (tailor-exit-descriptor %edx 0x10)
11221     #
11222     (write _test-input-stream "fn foo {\n")
11223     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
11224     (write _test-input-stream "  var b: offset\n")
11225     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
11226     (write _test-input-stream "}\n")
11227     # convert
11228     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11229     # registers except esp clobbered at this point
11230     # restore ed
11231     89/<- %edx 4/r32/esp
11232     (flush _test-output-buffered-file)
11233     (flush _test-error-buffered-file)
11234 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11240     # check output
11241     (check-stream-equal _test-output-stream  ""  "F - test-index-with-offset-atom-index-type: output should be empty")
11242     (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")
11243     # check that stop(1) was called
11244     (check-ints-equal *(edx+4) 2 "F - test-index-with-offset-atom-index-type: exit status")
11245     # don't restore from ebp
11246     81 0/subop/add %esp 8/imm32
11247     # . epilogue
11248     5d/pop-to-ebp
11249     c3/return
11250 
11251 test-index-with-offset-on-stack:
11252     # . prologue
11253     55/push-ebp
11254     89/<- %ebp 4/r32/esp
11255     # setup
11256     (clear-stream _test-input-stream)
11257     (clear-stream $_test-input-buffered-file->buffer)
11258     (clear-stream _test-output-stream)
11259     (clear-stream $_test-output-buffered-file->buffer)
11260     (clear-stream _test-error-stream)
11261     (clear-stream $_test-error-buffered-file->buffer)
11262     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11263     68/push 0/imm32
11264     68/push 0/imm32
11265     89/<- %edx 4/r32/esp
11266     (tailor-exit-descriptor %edx 0x10)
11267     #
11268     (write _test-input-stream "fn foo {\n")
11269     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
11270     (write _test-input-stream "  var b: int\n")
11271     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
11272     (write _test-input-stream "}\n")
11273     # convert
11274     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11275     # registers except esp clobbered at this point
11276     # restore ed
11277     89/<- %edx 4/r32/esp
11278     (flush _test-output-buffered-file)
11279     (flush _test-error-buffered-file)
11280 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11286     # check output
11287     (check-stream-equal _test-output-stream  ""  "F - test-index-with-offset-on-stack: output should be empty")
11288     (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")
11289     # check that stop(1) was called
11290     (check-ints-equal *(edx+4) 2 "F - test-index-with-offset-on-stack: exit status")
11291     # don't restore from ebp
11292     81 0/subop/add %esp 8/imm32
11293     # . epilogue
11294     5d/pop-to-ebp
11295     c3/return
11296 
11297 test-index-needs-offset-type:
11298     # . prologue
11299     55/push-ebp
11300     89/<- %ebp 4/r32/esp
11301     # setup
11302     (clear-stream _test-input-stream)
11303     (clear-stream $_test-input-buffered-file->buffer)
11304     (clear-stream _test-output-stream)
11305     (clear-stream $_test-output-buffered-file->buffer)
11306     (clear-stream _test-error-stream)
11307     (clear-stream $_test-error-buffered-file->buffer)
11308     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11309     68/push 0/imm32
11310     68/push 0/imm32
11311     89/<- %edx 4/r32/esp
11312     (tailor-exit-descriptor %edx 0x10)
11313     #
11314     (write _test-input-stream "fn foo {\n")
11315     (write _test-input-stream "  var a/eax: (addr array t) <- copy 0\n")
11316     (write _test-input-stream "  var b/ebx: int <- copy 0\n")
11317     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
11318     (write _test-input-stream "}\n")
11319     (write _test-input-stream "type t {\n")  # size 12 is not a power of two
11320     (write _test-input-stream "  x: int\n")
11321     (write _test-input-stream "  y: int\n")
11322     (write _test-input-stream "  z: int\n")
11323     (write _test-input-stream "}\n")
11324     # convert
11325     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11326     # registers except esp clobbered at this point
11327     # restore ed
11328     89/<- %edx 4/r32/esp
11329     (flush _test-output-buffered-file)
11330     (flush _test-error-buffered-file)
11331 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11337     # check output
11338     (check-stream-equal _test-output-stream  ""  "F - test-index-needs-offset-type: output should be empty")
11339     (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")
11340     # check that stop(1) was called
11341     (check-ints-equal *(edx+4) 2 "F - test-index-needs-offset-type: exit status")
11342     # don't restore from ebp
11343     81 0/subop/add %esp 8/imm32
11344     # . epilogue
11345     5d/pop-to-ebp
11346     c3/return
11347 
11348 test-index-with-output-not-address:
11349     # . prologue
11350     55/push-ebp
11351     89/<- %ebp 4/r32/esp
11352     # setup
11353     (clear-stream _test-input-stream)
11354     (clear-stream $_test-input-buffered-file->buffer)
11355     (clear-stream _test-output-stream)
11356     (clear-stream $_test-output-buffered-file->buffer)
11357     (clear-stream _test-error-stream)
11358     (clear-stream $_test-error-buffered-file->buffer)
11359     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11360     68/push 0/imm32
11361     68/push 0/imm32
11362     89/<- %edx 4/r32/esp
11363     (tailor-exit-descriptor %edx 0x10)
11364     #
11365     (write _test-input-stream "fn foo {\n")
11366     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
11367     (write _test-input-stream "  var o/edi: int <- index a, 0\n")
11368     (write _test-input-stream "}\n")
11369     # convert
11370     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11371     # registers except esp clobbered at this point
11372     # restore ed
11373     89/<- %edx 4/r32/esp
11374     (flush _test-output-buffered-file)
11375     (flush _test-error-buffered-file)
11376 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11382     # check output
11383     (check-stream-equal _test-output-stream  ""  "F - test-index-with-output-not-address: output should be empty")
11384     (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")
11385     # check that stop(1) was called
11386     (check-ints-equal *(edx+4) 2 "F - test-index-with-output-not-address: exit status")
11387     # don't restore from ebp
11388     81 0/subop/add %esp 8/imm32
11389     # . epilogue
11390     5d/pop-to-ebp
11391     c3/return
11392 
11393 test-index-with-output-not-address-2:
11394     # . prologue
11395     55/push-ebp
11396     89/<- %ebp 4/r32/esp
11397     # setup
11398     (clear-stream _test-input-stream)
11399     (clear-stream $_test-input-buffered-file->buffer)
11400     (clear-stream _test-output-stream)
11401     (clear-stream $_test-output-buffered-file->buffer)
11402     (clear-stream _test-error-stream)
11403     (clear-stream $_test-error-buffered-file->buffer)
11404     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11405     68/push 0/imm32
11406     68/push 0/imm32
11407     89/<- %edx 4/r32/esp
11408     (tailor-exit-descriptor %edx 0x10)
11409     #
11410     (write _test-input-stream "fn foo {\n")
11411     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
11412     (write _test-input-stream "  var o/edi: (int) <- index a, 0\n")
11413     (write _test-input-stream "}\n")
11414     # convert
11415     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11416     # registers except esp clobbered at this point
11417     # restore ed
11418     89/<- %edx 4/r32/esp
11419     (flush _test-output-buffered-file)
11420     (flush _test-error-buffered-file)
11421 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11427     # check output
11428     (check-stream-equal _test-output-stream  ""  "F - test-index-with-output-not-address-2: output should be empty")
11429     (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")
11430     # check that stop(1) was called
11431     (check-ints-equal *(edx+4) 2 "F - test-index-with-output-not-address-2: exit status")
11432     # don't restore from ebp
11433     81 0/subop/add %esp 8/imm32
11434     # . epilogue
11435     5d/pop-to-ebp
11436     c3/return
11437 
11438 test-index-with-wrong-output-type:
11439     # . prologue
11440     55/push-ebp
11441     89/<- %ebp 4/r32/esp
11442     # setup
11443     (clear-stream _test-input-stream)
11444     (clear-stream $_test-input-buffered-file->buffer)
11445     (clear-stream _test-output-stream)
11446     (clear-stream $_test-output-buffered-file->buffer)
11447     (clear-stream _test-error-stream)
11448     (clear-stream $_test-error-buffered-file->buffer)
11449     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11450     68/push 0/imm32
11451     68/push 0/imm32
11452     89/<- %edx 4/r32/esp
11453     (tailor-exit-descriptor %edx 0x10)
11454     #
11455     (write _test-input-stream "fn foo {\n")
11456     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
11457     (write _test-input-stream "  var o/edi: (addr int) <- index a, 0\n")
11458     (write _test-input-stream "}\n")
11459     # convert
11460     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11461     # registers except esp clobbered at this point
11462     # restore ed
11463     89/<- %edx 4/r32/esp
11464     (flush _test-output-buffered-file)
11465     (flush _test-error-buffered-file)
11466 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11472     # check output
11473     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-output-type: output should be empty")
11474     (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")
11475     # check that stop(1) was called
11476     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-output-type: exit status")
11477     # don't restore from ebp
11478     81 0/subop/add %esp 8/imm32
11479     # . epilogue
11480     5d/pop-to-ebp
11481     c3/return
11482 
11483 test-index-with-wrong-output-compound-type:
11484     # . prologue
11485     55/push-ebp
11486     89/<- %ebp 4/r32/esp
11487     # setup
11488     (clear-stream _test-input-stream)
11489     (clear-stream $_test-input-buffered-file->buffer)
11490     (clear-stream _test-output-stream)
11491     (clear-stream $_test-output-buffered-file->buffer)
11492     (clear-stream _test-error-stream)
11493     (clear-stream $_test-error-buffered-file->buffer)
11494     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11495     68/push 0/imm32
11496     68/push 0/imm32
11497     89/<- %edx 4/r32/esp
11498     (tailor-exit-descriptor %edx 0x10)
11499     #
11500     (write _test-input-stream "fn foo {\n")
11501     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
11502     (write _test-input-stream "  var o/edi: (addr handle int) <- index a, 0\n")
11503     (write _test-input-stream "}\n")
11504     # convert
11505     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11506     # registers except esp clobbered at this point
11507     # restore ed
11508     89/<- %edx 4/r32/esp
11509     (flush _test-output-buffered-file)
11510     (flush _test-error-buffered-file)
11511 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11517     # check output
11518     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-output-compound-type: output should be empty")
11519     (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")
11520     # check that stop(1) was called
11521     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-output-compound-type: exit status")
11522     # don't restore from ebp
11523     81 0/subop/add %esp 8/imm32
11524     # . epilogue
11525     5d/pop-to-ebp
11526     c3/return
11527 
11528 test-index-with-no-inouts:
11529     # . prologue
11530     55/push-ebp
11531     89/<- %ebp 4/r32/esp
11532     # setup
11533     (clear-stream _test-input-stream)
11534     (clear-stream $_test-input-buffered-file->buffer)
11535     (clear-stream _test-output-stream)
11536     (clear-stream $_test-output-buffered-file->buffer)
11537     (clear-stream _test-error-stream)
11538     (clear-stream $_test-error-buffered-file->buffer)
11539     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11540     68/push 0/imm32
11541     68/push 0/imm32
11542     89/<- %edx 4/r32/esp
11543     (tailor-exit-descriptor %edx 0x10)
11544     #
11545     (write _test-input-stream "fn foo {\n")
11546     (write _test-input-stream "  var c/ecx: (addr int) <- index\n")
11547     (write _test-input-stream "}\n")
11548     # convert
11549     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11550     # registers except esp clobbered at this point
11551     # restore ed
11552     89/<- %edx 4/r32/esp
11553     (flush _test-output-buffered-file)
11554     (flush _test-error-buffered-file)
11555 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11561     # check output
11562     (check-stream-equal _test-output-stream  ""  "F - test-index-with-no-inouts: output should be empty")
11563     (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")
11564     # check that stop(1) was called
11565     (check-ints-equal *(edx+4) 2 "F - test-index-with-no-inouts: exit status")
11566     # don't restore from ebp
11567     81 0/subop/add %esp 8/imm32
11568     # . epilogue
11569     5d/pop-to-ebp
11570     c3/return
11571 
11572 test-index-with-too-few-inouts:
11573     # . prologue
11574     55/push-ebp
11575     89/<- %ebp 4/r32/esp
11576     # setup
11577     (clear-stream _test-input-stream)
11578     (clear-stream $_test-input-buffered-file->buffer)
11579     (clear-stream _test-output-stream)
11580     (clear-stream $_test-output-buffered-file->buffer)
11581     (clear-stream _test-error-stream)
11582     (clear-stream $_test-error-buffered-file->buffer)
11583     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11584     68/push 0/imm32
11585     68/push 0/imm32
11586     89/<- %edx 4/r32/esp
11587     (tailor-exit-descriptor %edx 0x10)
11588     #
11589     (write _test-input-stream "fn foo {\n")
11590     (write _test-input-stream "  var a: (array int 3)\n")
11591     (write _test-input-stream "  var c/ecx: (addr int) <- index a\n")
11592     (write _test-input-stream "}\n")
11593     # convert
11594     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11595     # registers except esp clobbered at this point
11596     # restore ed
11597     89/<- %edx 4/r32/esp
11598     (flush _test-output-buffered-file)
11599     (flush _test-error-buffered-file)
11600 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11606     # check output
11607     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-few-inouts: output should be empty")
11608     (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")
11609     # check that stop(1) was called
11610     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-few-inouts: exit status")
11611     # don't restore from ebp
11612     81 0/subop/add %esp 8/imm32
11613     # . epilogue
11614     5d/pop-to-ebp
11615     c3/return
11616 
11617 test-index-with-too-many-inouts:
11618     # . prologue
11619     55/push-ebp
11620     89/<- %ebp 4/r32/esp
11621     # setup
11622     (clear-stream _test-input-stream)
11623     (clear-stream $_test-input-buffered-file->buffer)
11624     (clear-stream _test-output-stream)
11625     (clear-stream $_test-output-buffered-file->buffer)
11626     (clear-stream _test-error-stream)
11627     (clear-stream $_test-error-buffered-file->buffer)
11628     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11629     68/push 0/imm32
11630     68/push 0/imm32
11631     89/<- %edx 4/r32/esp
11632     (tailor-exit-descriptor %edx 0x10)
11633     #
11634     (write _test-input-stream "fn foo {\n")
11635     (write _test-input-stream "  var a: (array int 3)\n")
11636     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0, 0\n")
11637     (write _test-input-stream "}\n")
11638     # convert
11639     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11640     # registers except esp clobbered at this point
11641     # restore ed
11642     89/<- %edx 4/r32/esp
11643     (flush _test-output-buffered-file)
11644     (flush _test-error-buffered-file)
11645 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11651     # check output
11652     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-many-inouts: output should be empty")
11653     (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")
11654     # check that stop(1) was called
11655     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-many-inouts: exit status")
11656     # don't restore from ebp
11657     81 0/subop/add %esp 8/imm32
11658     # . epilogue
11659     5d/pop-to-ebp
11660     c3/return
11661 
11662 test-index-with-no-output:
11663     # . prologue
11664     55/push-ebp
11665     89/<- %ebp 4/r32/esp
11666     # setup
11667     (clear-stream _test-input-stream)
11668     (clear-stream $_test-input-buffered-file->buffer)
11669     (clear-stream _test-output-stream)
11670     (clear-stream $_test-output-buffered-file->buffer)
11671     (clear-stream _test-error-stream)
11672     (clear-stream $_test-error-buffered-file->buffer)
11673     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11674     68/push 0/imm32
11675     68/push 0/imm32
11676     89/<- %edx 4/r32/esp
11677     (tailor-exit-descriptor %edx 0x10)
11678     #
11679     (write _test-input-stream "fn foo {\n")
11680     (write _test-input-stream "  var a: (array int 3)\n")
11681     (write _test-input-stream "  index a, 0\n")
11682     (write _test-input-stream "}\n")
11683     # convert
11684     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11685     # registers except esp clobbered at this point
11686     # restore ed
11687     89/<- %edx 4/r32/esp
11688     (flush _test-output-buffered-file)
11689     (flush _test-error-buffered-file)
11690 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11696     # check output
11697     (check-stream-equal _test-output-stream  ""  "F - test-index-with-no-output: output should be empty")
11698     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: must have an output"  "F - test-index-with-no-output: error message")
11699     # check that stop(1) was called
11700     (check-ints-equal *(edx+4) 2 "F - test-index-with-no-output: exit status")
11701     # don't restore from ebp
11702     81 0/subop/add %esp 8/imm32
11703     # . epilogue
11704     5d/pop-to-ebp
11705     c3/return
11706 
11707 test-index-with-too-many-outputs:
11708     # . prologue
11709     55/push-ebp
11710     89/<- %ebp 4/r32/esp
11711     # setup
11712     (clear-stream _test-input-stream)
11713     (clear-stream $_test-input-buffered-file->buffer)
11714     (clear-stream _test-output-stream)
11715     (clear-stream $_test-output-buffered-file->buffer)
11716     (clear-stream _test-error-stream)
11717     (clear-stream $_test-error-buffered-file->buffer)
11718     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11719     68/push 0/imm32
11720     68/push 0/imm32
11721     89/<- %edx 4/r32/esp
11722     (tailor-exit-descriptor %edx 0x10)
11723     #
11724     (write _test-input-stream "fn foo {\n")
11725     (write _test-input-stream "  var a: (array int 3)\n")
11726     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
11727     (write _test-input-stream "  var c/ecx: (addr int) <- copy 0\n")
11728     (write _test-input-stream "  b, c <- index a, 0\n")
11729     (write _test-input-stream "}\n")
11730     # convert
11731     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11732     # registers except esp clobbered at this point
11733     # restore ed
11734     89/<- %edx 4/r32/esp
11735     (flush _test-output-buffered-file)
11736     (flush _test-error-buffered-file)
11737 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11743     # check output
11744     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-many-outputs: output should be empty")
11745     (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")
11746     # check that stop(1) was called
11747     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-many-outputs: exit status")
11748     # don't restore from ebp
11749     81 0/subop/add %esp 8/imm32
11750     # . epilogue
11751     5d/pop-to-ebp
11752     c3/return
11753 
11754 test-compute-offset-with-non-array-atom-base-type:
11755     # . prologue
11756     55/push-ebp
11757     89/<- %ebp 4/r32/esp
11758     # setup
11759     (clear-stream _test-input-stream)
11760     (clear-stream $_test-input-buffered-file->buffer)
11761     (clear-stream _test-output-stream)
11762     (clear-stream $_test-output-buffered-file->buffer)
11763     (clear-stream _test-error-stream)
11764     (clear-stream $_test-error-buffered-file->buffer)
11765     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11766     68/push 0/imm32
11767     68/push 0/imm32
11768     89/<- %edx 4/r32/esp
11769     (tailor-exit-descriptor %edx 0x10)
11770     #
11771     (write _test-input-stream "fn foo {\n")
11772     (write _test-input-stream "  var a: int\n")
11773     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
11774     (write _test-input-stream "}\n")
11775     # convert
11776     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11777     # registers except esp clobbered at this point
11778     # restore ed
11779     89/<- %edx 4/r32/esp
11780     (flush _test-output-buffered-file)
11781     (flush _test-error-buffered-file)
11782 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11788     # check output
11789     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-atom-base-type: output should be empty")
11790     (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")
11791     # check that stop(1) was called
11792     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-atom-base-type: exit status")
11793     # don't restore from ebp
11794     81 0/subop/add %esp 8/imm32
11795     # . epilogue
11796     5d/pop-to-ebp
11797     c3/return
11798 
11799 test-compute-offset-with-non-array-compound-base-type:
11800     # . prologue
11801     55/push-ebp
11802     89/<- %ebp 4/r32/esp
11803     # setup
11804     (clear-stream _test-input-stream)
11805     (clear-stream $_test-input-buffered-file->buffer)
11806     (clear-stream _test-output-stream)
11807     (clear-stream $_test-output-buffered-file->buffer)
11808     (clear-stream _test-error-stream)
11809     (clear-stream $_test-error-buffered-file->buffer)
11810     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11811     68/push 0/imm32
11812     68/push 0/imm32
11813     89/<- %edx 4/r32/esp
11814     (tailor-exit-descriptor %edx 0x10)
11815     #
11816     (write _test-input-stream "fn foo {\n")
11817     (write _test-input-stream "  var a: (handle int)\n")
11818     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
11819     (write _test-input-stream "}\n")
11820     # convert
11821     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11822     # registers except esp clobbered at this point
11823     # restore ed
11824     89/<- %edx 4/r32/esp
11825     (flush _test-output-buffered-file)
11826     (flush _test-error-buffered-file)
11827 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11833     # check output
11834     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-compound-base-type: output should be empty")
11835     (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")
11836     # check that stop(1) was called
11837     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-compound-base-type: exit status")
11838     # don't restore from ebp
11839     81 0/subop/add %esp 8/imm32
11840     # . epilogue
11841     5d/pop-to-ebp
11842     c3/return
11843 
11844 test-compute-offset-with-non-array-compound-base-type-2:
11845     # . prologue
11846     55/push-ebp
11847     89/<- %ebp 4/r32/esp
11848     # setup
11849     (clear-stream _test-input-stream)
11850     (clear-stream $_test-input-buffered-file->buffer)
11851     (clear-stream _test-output-stream)
11852     (clear-stream $_test-output-buffered-file->buffer)
11853     (clear-stream _test-error-stream)
11854     (clear-stream $_test-error-buffered-file->buffer)
11855     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11856     68/push 0/imm32
11857     68/push 0/imm32
11858     89/<- %edx 4/r32/esp
11859     (tailor-exit-descriptor %edx 0x10)
11860     #
11861     (write _test-input-stream "fn foo {\n")
11862     (write _test-input-stream "  var a: (addr int)\n")
11863     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
11864     (write _test-input-stream "}\n")
11865     # convert
11866     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11867     # registers except esp clobbered at this point
11868     # restore ed
11869     89/<- %edx 4/r32/esp
11870     (flush _test-output-buffered-file)
11871     (flush _test-error-buffered-file)
11872 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11878     # check output
11879     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-compound-base-type-2: output should be empty")
11880     (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")
11881     # check that stop(1) was called
11882     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-compound-base-type-2: exit status")
11883     # don't restore from ebp
11884     81 0/subop/add %esp 8/imm32
11885     # . epilogue
11886     5d/pop-to-ebp
11887     c3/return
11888 
11889 test-compute-offset-with-array-atom-base-type:
11890     # . prologue
11891     55/push-ebp
11892     89/<- %ebp 4/r32/esp
11893     # setup
11894     (clear-stream _test-input-stream)
11895     (clear-stream $_test-input-buffered-file->buffer)
11896     (clear-stream _test-output-stream)
11897     (clear-stream $_test-output-buffered-file->buffer)
11898     (clear-stream _test-error-stream)
11899     (clear-stream $_test-error-buffered-file->buffer)
11900     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11901     68/push 0/imm32
11902     68/push 0/imm32
11903     89/<- %edx 4/r32/esp
11904     (tailor-exit-descriptor %edx 0x10)
11905     #
11906     (write _test-input-stream "fn foo {\n")
11907     (write _test-input-stream "  var a: array\n")
11908     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
11909     (write _test-input-stream "}\n")
11910     # convert
11911     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11912     # registers except esp clobbered at this point
11913     # restore ed
11914     89/<- %edx 4/r32/esp
11915     (flush _test-output-buffered-file)
11916     (flush _test-error-buffered-file)
11917 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11923     # check output
11924     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-array-atom-base-type: output should be empty")
11925     (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")
11926     # check that stop(1) was called
11927     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-array-atom-base-type: exit status")
11928     # don't restore from ebp
11929     81 0/subop/add %esp 8/imm32
11930     # . epilogue
11931     5d/pop-to-ebp
11932     c3/return
11933 
11934 test-compute-offset-with-wrong-index-type:
11935     # . prologue
11936     55/push-ebp
11937     89/<- %ebp 4/r32/esp
11938     # setup
11939     (clear-stream _test-input-stream)
11940     (clear-stream $_test-input-buffered-file->buffer)
11941     (clear-stream _test-output-stream)
11942     (clear-stream $_test-output-buffered-file->buffer)
11943     (clear-stream _test-error-stream)
11944     (clear-stream $_test-error-buffered-file->buffer)
11945     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11946     68/push 0/imm32
11947     68/push 0/imm32
11948     89/<- %edx 4/r32/esp
11949     (tailor-exit-descriptor %edx 0x10)
11950     #
11951     (write _test-input-stream "fn foo {\n")
11952     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
11953     (write _test-input-stream "  var b: boolean\n")
11954     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, b\n")
11955     (write _test-input-stream "}\n")
11956     # convert
11957     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11958     # registers except esp clobbered at this point
11959     # restore ed
11960     89/<- %edx 4/r32/esp
11961     (flush _test-output-buffered-file)
11962     (flush _test-error-buffered-file)
11963 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11969     # check output
11970     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-index-type: output should be empty")
11971     (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")
11972     # check that stop(1) was called
11973     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-index-type: exit status")
11974     # don't restore from ebp
11975     81 0/subop/add %esp 8/imm32
11976     # . epilogue
11977     5d/pop-to-ebp
11978     c3/return
11979 
11980 test-compute-offset-with-output-not-offset:
11981     # . prologue
11982     55/push-ebp
11983     89/<- %ebp 4/r32/esp
11984     # setup
11985     (clear-stream _test-input-stream)
11986     (clear-stream $_test-input-buffered-file->buffer)
11987     (clear-stream _test-output-stream)
11988     (clear-stream $_test-output-buffered-file->buffer)
11989     (clear-stream _test-error-stream)
11990     (clear-stream $_test-error-buffered-file->buffer)
11991     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11992     68/push 0/imm32
11993     68/push 0/imm32
11994     89/<- %edx 4/r32/esp
11995     (tailor-exit-descriptor %edx 0x10)
11996     #
11997     (write _test-input-stream "fn foo {\n")
11998     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
11999     (write _test-input-stream "  var o/edi: int <- compute-offset a, 0\n")
12000     (write _test-input-stream "}\n")
12001     # convert
12002     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12003     # registers except esp clobbered at this point
12004     # restore ed
12005     89/<- %edx 4/r32/esp
12006     (flush _test-output-buffered-file)
12007     (flush _test-error-buffered-file)
12008 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12014     # check output
12015     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-output-not-offset: output should be empty")
12016     (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")
12017     # check that stop(1) was called
12018     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-output-not-offset: exit status")
12019     # don't restore from ebp
12020     81 0/subop/add %esp 8/imm32
12021     # . epilogue
12022     5d/pop-to-ebp
12023     c3/return
12024 
12025 test-compute-offset-with-output-not-address-2:
12026     # . prologue
12027     55/push-ebp
12028     89/<- %ebp 4/r32/esp
12029     # setup
12030     (clear-stream _test-input-stream)
12031     (clear-stream $_test-input-buffered-file->buffer)
12032     (clear-stream _test-output-stream)
12033     (clear-stream $_test-output-buffered-file->buffer)
12034     (clear-stream _test-error-stream)
12035     (clear-stream $_test-error-buffered-file->buffer)
12036     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12037     68/push 0/imm32
12038     68/push 0/imm32
12039     89/<- %edx 4/r32/esp
12040     (tailor-exit-descriptor %edx 0x10)
12041     #
12042     (write _test-input-stream "fn foo {\n")
12043     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
12044     (write _test-input-stream "  var o/edi: (int) <- compute-offset a, 0\n")
12045     (write _test-input-stream "}\n")
12046     # convert
12047     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12048     # registers except esp clobbered at this point
12049     # restore ed
12050     89/<- %edx 4/r32/esp
12051     (flush _test-output-buffered-file)
12052     (flush _test-error-buffered-file)
12053 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12059     # check output
12060     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-output-not-address-2: output should be empty")
12061     (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")
12062     # check that stop(1) was called
12063     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-output-not-address-2: exit status")
12064     # don't restore from ebp
12065     81 0/subop/add %esp 8/imm32
12066     # . epilogue
12067     5d/pop-to-ebp
12068     c3/return
12069 
12070 test-compute-offset-with-wrong-output-type:
12071     # . prologue
12072     55/push-ebp
12073     89/<- %ebp 4/r32/esp
12074     # setup
12075     (clear-stream _test-input-stream)
12076     (clear-stream $_test-input-buffered-file->buffer)
12077     (clear-stream _test-output-stream)
12078     (clear-stream $_test-output-buffered-file->buffer)
12079     (clear-stream _test-error-stream)
12080     (clear-stream $_test-error-buffered-file->buffer)
12081     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12082     68/push 0/imm32
12083     68/push 0/imm32
12084     89/<- %edx 4/r32/esp
12085     (tailor-exit-descriptor %edx 0x10)
12086     #
12087     (write _test-input-stream "fn foo {\n")
12088     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
12089     (write _test-input-stream "  var o/edi: (offset int) <- compute-offset a, 0\n")
12090     (write _test-input-stream "}\n")
12091     # convert
12092     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12093     # registers except esp clobbered at this point
12094     # restore ed
12095     89/<- %edx 4/r32/esp
12096     (flush _test-output-buffered-file)
12097     (flush _test-error-buffered-file)
12098 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12104     # check output
12105     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-output-type: output should be empty")
12106     (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")
12107     # check that stop(1) was called
12108     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-output-type: exit status")
12109     # don't restore from ebp
12110     81 0/subop/add %esp 8/imm32
12111     # . epilogue
12112     5d/pop-to-ebp
12113     c3/return
12114 
12115 test-compute-offset-with-wrong-output-compound-type:
12116     # . prologue
12117     55/push-ebp
12118     89/<- %ebp 4/r32/esp
12119     # setup
12120     (clear-stream _test-input-stream)
12121     (clear-stream $_test-input-buffered-file->buffer)
12122     (clear-stream _test-output-stream)
12123     (clear-stream $_test-output-buffered-file->buffer)
12124     (clear-stream _test-error-stream)
12125     (clear-stream $_test-error-buffered-file->buffer)
12126     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12127     68/push 0/imm32
12128     68/push 0/imm32
12129     89/<- %edx 4/r32/esp
12130     (tailor-exit-descriptor %edx 0x10)
12131     #
12132     (write _test-input-stream "fn foo {\n")
12133     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
12134     (write _test-input-stream "  var o/edi: (offset handle int) <- compute-offset a, 0\n")
12135     (write _test-input-stream "}\n")
12136     # convert
12137     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12138     # registers except esp clobbered at this point
12139     # restore ed
12140     89/<- %edx 4/r32/esp
12141     (flush _test-output-buffered-file)
12142     (flush _test-error-buffered-file)
12143 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12149     # check output
12150     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-output-compound-type: output should be empty")
12151     (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")
12152     # check that stop(1) was called
12153     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-output-compound-type: exit status")
12154     # don't restore from ebp
12155     81 0/subop/add %esp 8/imm32
12156     # . epilogue
12157     5d/pop-to-ebp
12158     c3/return
12159 
12160 test-compute-offset-with-no-inouts:
12161     # . prologue
12162     55/push-ebp
12163     89/<- %ebp 4/r32/esp
12164     # setup
12165     (clear-stream _test-input-stream)
12166     (clear-stream $_test-input-buffered-file->buffer)
12167     (clear-stream _test-output-stream)
12168     (clear-stream $_test-output-buffered-file->buffer)
12169     (clear-stream _test-error-stream)
12170     (clear-stream $_test-error-buffered-file->buffer)
12171     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12172     68/push 0/imm32
12173     68/push 0/imm32
12174     89/<- %edx 4/r32/esp
12175     (tailor-exit-descriptor %edx 0x10)
12176     #
12177     (write _test-input-stream "fn foo {\n")
12178     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset\n")
12179     (write _test-input-stream "}\n")
12180     # convert
12181     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12182     # registers except esp clobbered at this point
12183     # restore ed
12184     89/<- %edx 4/r32/esp
12185     (flush _test-output-buffered-file)
12186     (flush _test-error-buffered-file)
12187 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12193     # check output
12194     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-no-inouts: output should be empty")
12195     (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")
12196     # check that stop(1) was called
12197     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-no-inouts: exit status")
12198     # don't restore from ebp
12199     81 0/subop/add %esp 8/imm32
12200     # . epilogue
12201     5d/pop-to-ebp
12202     c3/return
12203 
12204 test-compute-offset-with-too-few-inouts:
12205     # . prologue
12206     55/push-ebp
12207     89/<- %ebp 4/r32/esp
12208     # setup
12209     (clear-stream _test-input-stream)
12210     (clear-stream $_test-input-buffered-file->buffer)
12211     (clear-stream _test-output-stream)
12212     (clear-stream $_test-output-buffered-file->buffer)
12213     (clear-stream _test-error-stream)
12214     (clear-stream $_test-error-buffered-file->buffer)
12215     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12216     68/push 0/imm32
12217     68/push 0/imm32
12218     89/<- %edx 4/r32/esp
12219     (tailor-exit-descriptor %edx 0x10)
12220     #
12221     (write _test-input-stream "fn foo {\n")
12222     (write _test-input-stream "  var a: (array int 3)\n")
12223     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a\n")
12224     (write _test-input-stream "}\n")
12225     # convert
12226     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12227     # registers except esp clobbered at this point
12228     # restore ed
12229     89/<- %edx 4/r32/esp
12230     (flush _test-output-buffered-file)
12231     (flush _test-error-buffered-file)
12232 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12238     # check output
12239     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-few-inouts: output should be empty")
12240     (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")
12241     # check that stop(1) was called
12242     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-few-inouts: exit status")
12243     # don't restore from ebp
12244     81 0/subop/add %esp 8/imm32
12245     # . epilogue
12246     5d/pop-to-ebp
12247     c3/return
12248 
12249 test-compute-offset-with-too-many-inouts:
12250     # . prologue
12251     55/push-ebp
12252     89/<- %ebp 4/r32/esp
12253     # setup
12254     (clear-stream _test-input-stream)
12255     (clear-stream $_test-input-buffered-file->buffer)
12256     (clear-stream _test-output-stream)
12257     (clear-stream $_test-output-buffered-file->buffer)
12258     (clear-stream _test-error-stream)
12259     (clear-stream $_test-error-buffered-file->buffer)
12260     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12261     68/push 0/imm32
12262     68/push 0/imm32
12263     89/<- %edx 4/r32/esp
12264     (tailor-exit-descriptor %edx 0x10)
12265     #
12266     (write _test-input-stream "fn foo {\n")
12267     (write _test-input-stream "  var a: (array int 3)\n")
12268     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0, 0\n")
12269     (write _test-input-stream "}\n")
12270     # convert
12271     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12272     # registers except esp clobbered at this point
12273     # restore ed
12274     89/<- %edx 4/r32/esp
12275     (flush _test-output-buffered-file)
12276     (flush _test-error-buffered-file)
12277 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12283     # check output
12284     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-many-inouts: output should be empty")
12285     (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")
12286     # check that stop(1) was called
12287     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-many-inouts: exit status")
12288     # don't restore from ebp
12289     81 0/subop/add %esp 8/imm32
12290     # . epilogue
12291     5d/pop-to-ebp
12292     c3/return
12293 
12294 test-compute-offset-with-no-output:
12295     # . prologue
12296     55/push-ebp
12297     89/<- %ebp 4/r32/esp
12298     # setup
12299     (clear-stream _test-input-stream)
12300     (clear-stream $_test-input-buffered-file->buffer)
12301     (clear-stream _test-output-stream)
12302     (clear-stream $_test-output-buffered-file->buffer)
12303     (clear-stream _test-error-stream)
12304     (clear-stream $_test-error-buffered-file->buffer)
12305     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12306     68/push 0/imm32
12307     68/push 0/imm32
12308     89/<- %edx 4/r32/esp
12309     (tailor-exit-descriptor %edx 0x10)
12310     #
12311     (write _test-input-stream "fn foo {\n")
12312     (write _test-input-stream "  var a: (array int 3)\n")
12313     (write _test-input-stream "  compute-offset a, 0\n")
12314     (write _test-input-stream "}\n")
12315     # convert
12316     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12317     # registers except esp clobbered at this point
12318     # restore ed
12319     89/<- %edx 4/r32/esp
12320     (flush _test-output-buffered-file)
12321     (flush _test-error-buffered-file)
12322 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12328     # check output
12329     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-no-output: output should be empty")
12330     (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")
12331     # check that stop(1) was called
12332     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-no-output: exit status")
12333     # don't restore from ebp
12334     81 0/subop/add %esp 8/imm32
12335     # . epilogue
12336     5d/pop-to-ebp
12337     c3/return
12338 
12339 test-compute-offset-with-too-many-outputs:
12340     # . prologue
12341     55/push-ebp
12342     89/<- %ebp 4/r32/esp
12343     # setup
12344     (clear-stream _test-input-stream)
12345     (clear-stream $_test-input-buffered-file->buffer)
12346     (clear-stream _test-output-stream)
12347     (clear-stream $_test-output-buffered-file->buffer)
12348     (clear-stream _test-error-stream)
12349     (clear-stream $_test-error-buffered-file->buffer)
12350     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12351     68/push 0/imm32
12352     68/push 0/imm32
12353     89/<- %edx 4/r32/esp
12354     (tailor-exit-descriptor %edx 0x10)
12355     #
12356     (write _test-input-stream "fn foo {\n")
12357     (write _test-input-stream "  var a: (array int 3)\n")
12358     (write _test-input-stream "  var b/eax: (offset int) <- compute-offset a, 0\n")
12359     (write _test-input-stream "  var c/ecx: (addr int) <- copy 0\n")
12360     (write _test-input-stream "  b, c <- compute-offset a, 0\n")
12361     (write _test-input-stream "}\n")
12362     # convert
12363     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12364     # registers except esp clobbered at this point
12365     # restore ed
12366     89/<- %edx 4/r32/esp
12367     (flush _test-output-buffered-file)
12368     (flush _test-error-buffered-file)
12369 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12375     # check output
12376     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-many-outputs: output should be empty")
12377     (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")
12378     # check that stop(1) was called
12379     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-many-outputs: exit status")
12380     # don't restore from ebp
12381     81 0/subop/add %esp 8/imm32
12382     # . epilogue
12383     5d/pop-to-ebp
12384     c3/return
12385 
12386 test-convert-read-from-stream:
12387     # . prologue
12388     55/push-ebp
12389     89/<- %ebp 4/r32/esp
12390     # setup
12391     (clear-stream _test-input-stream)
12392     (clear-stream $_test-input-buffered-file->buffer)
12393     (clear-stream _test-output-stream)
12394     (clear-stream $_test-output-buffered-file->buffer)
12395     #
12396     (write _test-input-stream "fn foo {\n")
12397     (write _test-input-stream "  var s/esi: (addr stream int) <- copy 0\n")
12398     (write _test-input-stream "  var o/ecx: (addr int) <- copy 0\n")
12399     (write _test-input-stream "  read-from-stream s, o\n")
12400     (write _test-input-stream "}\n")
12401     # convert
12402     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
12403     # registers except esp clobbered at this point
12404     # restore ed
12405     89/<- %edx 4/r32/esp
12406     (flush _test-output-buffered-file)
12407     (flush _test-error-buffered-file)
12408 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
12414     # check output
12415     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-read-from-stream/0")
12416     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-read-from-stream/1")
12417     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-read-from-stream/2")
12418     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-read-from-stream/3")
12419     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-read-from-stream/4")
12420     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-read-from-stream/5")
12421     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-read-from-stream/6")
12422     (check-next-stream-line-equal _test-output-stream "    be/copy-to-esi 0/imm32"      "F - test-convert-read-from-stream/7")
12423     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-read-from-stream/8")
12424     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"      "F - test-convert-read-from-stream/9")
12425     (check-next-stream-line-equal _test-output-stream "    (read-from-stream %esi %ecx 0x00000004)"  "F - test-convert-read-from-stream/10")
12426     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-read-from-stream/11")
12427     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-read-from-stream/12")
12428     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-read-from-stream/13")
12429     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-read-from-stream/14")
12430     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-read-from-stream/15")
12431     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-read-from-stream/16")
12432     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-read-from-stream/17")
12433     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-read-from-stream/18")
12434     # . epilogue
12435     89/<- %esp 5/r32/ebp
12436     5d/pop-to-ebp
12437     c3/return
12438 
12439 test-convert-read-from-stream-with-correct-payload-size:
12440     # . prologue
12441     55/push-ebp
12442     89/<- %ebp 4/r32/esp
12443     # setup
12444     (clear-stream _test-input-stream)
12445     (clear-stream $_test-input-buffered-file->buffer)
12446     (clear-stream _test-output-stream)
12447     (clear-stream $_test-output-buffered-file->buffer)
12448     #
12449     (write _test-input-stream "fn foo {\n")
12450     (write _test-input-stream "  var s/esi: (addr stream handle int) <- copy 0\n")
12451     (write _test-input-stream "  var o/ecx: (addr handle int) <- copy 0\n")
12452     (write _test-input-stream "  read-from-stream s, o\n")
12453     (write _test-input-stream "}\n")
12454     # convert
12455     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
12456     # registers except esp clobbered at this point
12457     # restore ed
12458     89/<- %edx 4/r32/esp
12459     (flush _test-output-buffered-file)
12460     (flush _test-error-buffered-file)
12461 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
12467     # check output
12468     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-read-from-stream-with-correct-payload-size/0")
12469     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-read-from-stream-with-correct-payload-size/1")
12470     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-read-from-stream-with-correct-payload-size/2")
12471     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-read-from-stream-with-correct-payload-size/3")
12472     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-read-from-stream-with-correct-payload-size/4")
12473     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-read-from-stream-with-correct-payload-size/5")
12474     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-read-from-stream-with-correct-payload-size/6")
12475     (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")
12476     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-read-from-stream-with-correct-payload-size/8")
12477     (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")
12478     (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")
12479     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-read-from-stream-with-correct-payload-size/11")
12480     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-read-from-stream-with-correct-payload-size/12")
12481     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-read-from-stream-with-correct-payload-size/13")
12482     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-read-from-stream-with-correct-payload-size/14")
12483     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-read-from-stream-with-correct-payload-size/15")
12484     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-read-from-stream-with-correct-payload-size/16")
12485     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-read-from-stream-with-correct-payload-size/17")
12486     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-read-from-stream-with-correct-payload-size/18")
12487     # . epilogue
12488     89/<- %esp 5/r32/ebp
12489     5d/pop-to-ebp
12490     c3/return
12491 
12492 test-read-from-stream-with-non-stream-atom-base-type:
12493     # . prologue
12494     55/push-ebp
12495     89/<- %ebp 4/r32/esp
12496     # setup
12497     (clear-stream _test-input-stream)
12498     (clear-stream $_test-input-buffered-file->buffer)
12499     (clear-stream _test-output-stream)
12500     (clear-stream $_test-output-buffered-file->buffer)
12501     (clear-stream _test-error-stream)
12502     (clear-stream $_test-error-buffered-file->buffer)
12503     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12504     68/push 0/imm32
12505     68/push 0/imm32
12506     89/<- %edx 4/r32/esp
12507     (tailor-exit-descriptor %edx 0x10)
12508     #
12509     (write _test-input-stream "fn foo {\n")
12510     (write _test-input-stream "  var a: int\n")
12511     (write _test-input-stream "  read-from-stream a, 0\n")
12512     (write _test-input-stream "}\n")
12513     # convert
12514     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12515     # registers except esp clobbered at this point
12516     # restore ed
12517     89/<- %edx 4/r32/esp
12518     (flush _test-output-buffered-file)
12519     (flush _test-error-buffered-file)
12520 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12526     # check output
12527     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-atom-base-type: output should be empty")
12528     (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")
12529     # check that stop(1) was called
12530     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-atom-base-type: exit status")
12531     # don't restore from ebp
12532     81 0/subop/add %esp 8/imm32
12533     # . epilogue
12534     5d/pop-to-ebp
12535     c3/return
12536 
12537 test-read-from-stream-with-non-stream-compound-base-type:
12538     # . prologue
12539     55/push-ebp
12540     89/<- %ebp 4/r32/esp
12541     # setup
12542     (clear-stream _test-input-stream)
12543     (clear-stream $_test-input-buffered-file->buffer)
12544     (clear-stream _test-output-stream)
12545     (clear-stream $_test-output-buffered-file->buffer)
12546     (clear-stream _test-error-stream)
12547     (clear-stream $_test-error-buffered-file->buffer)
12548     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12549     68/push 0/imm32
12550     68/push 0/imm32
12551     89/<- %edx 4/r32/esp
12552     (tailor-exit-descriptor %edx 0x10)
12553     #
12554     (write _test-input-stream "fn foo {\n")
12555     (write _test-input-stream "  var a: (handle int)\n")
12556     (write _test-input-stream "  read-from-stream a, 0\n")
12557     (write _test-input-stream "}\n")
12558     # convert
12559     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12560     # registers except esp clobbered at this point
12561     # restore ed
12562     89/<- %edx 4/r32/esp
12563     (flush _test-output-buffered-file)
12564     (flush _test-error-buffered-file)
12565 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12571     # check output
12572     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-compound-base-type: output should be empty")
12573     (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")
12574     # check that stop(1) was called
12575     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-compound-base-type: exit status")
12576     # don't restore from ebp
12577     81 0/subop/add %esp 8/imm32
12578     # . epilogue
12579     5d/pop-to-ebp
12580     c3/return
12581 
12582 test-read-from-stream-with-non-stream-compound-base-type-2:
12583     # . prologue
12584     55/push-ebp
12585     89/<- %ebp 4/r32/esp
12586     # setup
12587     (clear-stream _test-input-stream)
12588     (clear-stream $_test-input-buffered-file->buffer)
12589     (clear-stream _test-output-stream)
12590     (clear-stream $_test-output-buffered-file->buffer)
12591     (clear-stream _test-error-stream)
12592     (clear-stream $_test-error-buffered-file->buffer)
12593     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12594     68/push 0/imm32
12595     68/push 0/imm32
12596     89/<- %edx 4/r32/esp
12597     (tailor-exit-descriptor %edx 0x10)
12598     #
12599     (write _test-input-stream "fn foo {\n")
12600     (write _test-input-stream "  var a: (addr int)\n")
12601     (write _test-input-stream "  read-from-stream a, 0\n")
12602     (write _test-input-stream "}\n")
12603     # convert
12604     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12605     # registers except esp clobbered at this point
12606     # restore ed
12607     89/<- %edx 4/r32/esp
12608     (flush _test-output-buffered-file)
12609     (flush _test-error-buffered-file)
12610 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12616     # check output
12617     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-compound-base-type-2: output should be empty")
12618     (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")
12619     # check that stop(1) was called
12620     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-compound-base-type-2: exit status")
12621     # don't restore from ebp
12622     81 0/subop/add %esp 8/imm32
12623     # . epilogue
12624     5d/pop-to-ebp
12625     c3/return
12626 
12627 test-read-from-stream-with-stream-atom-base-type:
12628     # . prologue
12629     55/push-ebp
12630     89/<- %ebp 4/r32/esp
12631     # setup
12632     (clear-stream _test-input-stream)
12633     (clear-stream $_test-input-buffered-file->buffer)
12634     (clear-stream _test-output-stream)
12635     (clear-stream $_test-output-buffered-file->buffer)
12636     (clear-stream _test-error-stream)
12637     (clear-stream $_test-error-buffered-file->buffer)
12638     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12639     68/push 0/imm32
12640     68/push 0/imm32
12641     89/<- %edx 4/r32/esp
12642     (tailor-exit-descriptor %edx 0x10)
12643     #
12644     (write _test-input-stream "fn foo {\n")
12645     (write _test-input-stream "  var a: stream\n")
12646     (write _test-input-stream "  read-from-stream a, 0\n")
12647     (write _test-input-stream "}\n")
12648     # convert
12649     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12650     # registers except esp clobbered at this point
12651     # restore ed
12652     89/<- %edx 4/r32/esp
12653     (flush _test-output-buffered-file)
12654     (flush _test-error-buffered-file)
12655 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12661     # check output
12662     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-stream-atom-base-type: output should be empty")
12663     (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")
12664     # check that stop(1) was called
12665     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-stream-atom-base-type: exit status")
12666     # don't restore from ebp
12667     81 0/subop/add %esp 8/imm32
12668     # . epilogue
12669     5d/pop-to-ebp
12670     c3/return
12671 
12672 test-read-from-stream-with-wrong-index-type:
12673     # . prologue
12674     55/push-ebp
12675     89/<- %ebp 4/r32/esp
12676     # setup
12677     (clear-stream _test-input-stream)
12678     (clear-stream $_test-input-buffered-file->buffer)
12679     (clear-stream _test-output-stream)
12680     (clear-stream $_test-output-buffered-file->buffer)
12681     (clear-stream _test-error-stream)
12682     (clear-stream $_test-error-buffered-file->buffer)
12683     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12684     68/push 0/imm32
12685     68/push 0/imm32
12686     89/<- %edx 4/r32/esp
12687     (tailor-exit-descriptor %edx 0x10)
12688     #
12689     (write _test-input-stream "fn foo {\n")
12690     (write _test-input-stream "  var a/eax: (addr stream int) <- copy 0\n")
12691     (write _test-input-stream "  var b: boolean\n")
12692     (write _test-input-stream "  read-from-stream a, b\n")
12693     (write _test-input-stream "}\n")
12694     # convert
12695     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12696     # registers except esp clobbered at this point
12697     # restore ed
12698     89/<- %edx 4/r32/esp
12699     (flush _test-output-buffered-file)
12700     (flush _test-error-buffered-file)
12701 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12707     # check output
12708     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-wrong-index-type: output should be empty")
12709     (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")
12710     # check that stop(1) was called
12711     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-wrong-index-type: exit status")
12712     # don't restore from ebp
12713     81 0/subop/add %esp 8/imm32
12714     # . epilogue
12715     5d/pop-to-ebp
12716     c3/return
12717 
12718 test-read-from-stream-with-no-inouts:
12719     # . prologue
12720     55/push-ebp
12721     89/<- %ebp 4/r32/esp
12722     # setup
12723     (clear-stream _test-input-stream)
12724     (clear-stream $_test-input-buffered-file->buffer)
12725     (clear-stream _test-output-stream)
12726     (clear-stream $_test-output-buffered-file->buffer)
12727     (clear-stream _test-error-stream)
12728     (clear-stream $_test-error-buffered-file->buffer)
12729     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12730     68/push 0/imm32
12731     68/push 0/imm32
12732     89/<- %edx 4/r32/esp
12733     (tailor-exit-descriptor %edx 0x10)
12734     #
12735     (write _test-input-stream "fn foo {\n")
12736     (write _test-input-stream "  read-from-stream\n")
12737     (write _test-input-stream "}\n")
12738     # convert
12739     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12740     # registers except esp clobbered at this point
12741     # restore ed
12742     89/<- %edx 4/r32/esp
12743     (flush _test-output-buffered-file)
12744     (flush _test-error-buffered-file)
12745 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12751     # check output
12752     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-no-inouts: output should be empty")
12753     (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")
12754     # check that stop(1) was called
12755     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-no-inouts: exit status")
12756     # don't restore from ebp
12757     81 0/subop/add %esp 8/imm32
12758     # . epilogue
12759     5d/pop-to-ebp
12760     c3/return
12761 
12762 test-read-from-stream-with-too-few-inouts:
12763     # . prologue
12764     55/push-ebp
12765     89/<- %ebp 4/r32/esp
12766     # setup
12767     (clear-stream _test-input-stream)
12768     (clear-stream $_test-input-buffered-file->buffer)
12769     (clear-stream _test-output-stream)
12770     (clear-stream $_test-output-buffered-file->buffer)
12771     (clear-stream _test-error-stream)
12772     (clear-stream $_test-error-buffered-file->buffer)
12773     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12774     68/push 0/imm32
12775     68/push 0/imm32
12776     89/<- %edx 4/r32/esp
12777     (tailor-exit-descriptor %edx 0x10)
12778     #
12779     (write _test-input-stream "fn foo {\n")
12780     (write _test-input-stream "  var a: (addr stream int)\n")
12781     (write _test-input-stream "  read-from-stream a\n")
12782     (write _test-input-stream "}\n")
12783     # convert
12784     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12785     # registers except esp clobbered at this point
12786     # restore ed
12787     89/<- %edx 4/r32/esp
12788     (flush _test-output-buffered-file)
12789     (flush _test-error-buffered-file)
12790 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12796     # check output
12797     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-too-few-inouts: output should be empty")
12798     (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")
12799     # check that stop(1) was called
12800     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-too-few-inouts: exit status")
12801     # don't restore from ebp
12802     81 0/subop/add %esp 8/imm32
12803     # . epilogue
12804     5d/pop-to-ebp
12805     c3/return
12806 
12807 test-read-from-stream-with-too-many-inouts:
12808     # . prologue
12809     55/push-ebp
12810     89/<- %ebp 4/r32/esp
12811     # setup
12812     (clear-stream _test-input-stream)
12813     (clear-stream $_test-input-buffered-file->buffer)
12814     (clear-stream _test-output-stream)
12815     (clear-stream $_test-output-buffered-file->buffer)
12816     (clear-stream _test-error-stream)
12817     (clear-stream $_test-error-buffered-file->buffer)
12818     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12819     68/push 0/imm32
12820     68/push 0/imm32
12821     89/<- %edx 4/r32/esp
12822     (tailor-exit-descriptor %edx 0x10)
12823     #
12824     (write _test-input-stream "fn foo {\n")
12825     (write _test-input-stream "  var a: (addr stream int)\n")
12826     (write _test-input-stream "  var b: (addr int)\n")
12827     (write _test-input-stream "  read-from-stream a, b, 0\n")
12828     (write _test-input-stream "}\n")
12829     # convert
12830     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12831     # registers except esp clobbered at this point
12832     # restore ed
12833     89/<- %edx 4/r32/esp
12834     (flush _test-output-buffered-file)
12835     (flush _test-error-buffered-file)
12836 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12842     # check output
12843     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-too-many-inouts: output should be empty")
12844     (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")
12845     # check that stop(1) was called
12846     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-too-many-inouts: exit status")
12847     # don't restore from ebp
12848     81 0/subop/add %esp 8/imm32
12849     # . epilogue
12850     5d/pop-to-ebp
12851     c3/return
12852 
12853 test-read-from-stream-with-output:
12854     # . prologue
12855     55/push-ebp
12856     89/<- %ebp 4/r32/esp
12857     # setup
12858     (clear-stream _test-input-stream)
12859     (clear-stream $_test-input-buffered-file->buffer)
12860     (clear-stream _test-output-stream)
12861     (clear-stream $_test-output-buffered-file->buffer)
12862     (clear-stream _test-error-stream)
12863     (clear-stream $_test-error-buffered-file->buffer)
12864     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12865     68/push 0/imm32
12866     68/push 0/imm32
12867     89/<- %edx 4/r32/esp
12868     (tailor-exit-descriptor %edx 0x10)
12869     #
12870     (write _test-input-stream "fn foo {\n")
12871     (write _test-input-stream "  var a: (addr stream int)\n")
12872     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
12873     (write _test-input-stream "  b <- read-from-stream a, b\n")
12874     (write _test-input-stream "}\n")
12875     # convert
12876     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12877     # registers except esp clobbered at this point
12878     # restore ed
12879     89/<- %edx 4/r32/esp
12880     (flush _test-output-buffered-file)
12881     (flush _test-error-buffered-file)
12882 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12888     # check output
12889     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-output: output should be empty")
12890     (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")
12891     # check that stop(1) was called
12892     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-output: exit status")
12893     # don't restore from ebp
12894     81 0/subop/add %esp 8/imm32
12895     # . epilogue
12896     5d/pop-to-ebp
12897     c3/return
12898 
12899 test-convert-write-to-stream:
12900     # . prologue
12901     55/push-ebp
12902     89/<- %ebp 4/r32/esp
12903     # setup
12904     (clear-stream _test-input-stream)
12905     (clear-stream $_test-input-buffered-file->buffer)
12906     (clear-stream _test-output-stream)
12907     (clear-stream $_test-output-buffered-file->buffer)
12908     #
12909     (write _test-input-stream "fn foo {\n")
12910     (write _test-input-stream "  var s/esi: (addr stream int) <- copy 0\n")
12911     (write _test-input-stream "  var o/ecx: (addr int) <- copy 0\n")
12912     (write _test-input-stream "  write-to-stream s, o\n")
12913     (write _test-input-stream "}\n")
12914     # convert
12915     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
12916     # registers except esp clobbered at this point
12917     # restore ed
12918     89/<- %edx 4/r32/esp
12919     (flush _test-output-buffered-file)
12920     (flush _test-error-buffered-file)
12921 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
12927     # check output
12928     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-write-to-stream/0")
12929     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-write-to-stream/1")
12930     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-write-to-stream/2")
12931     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-write-to-stream/3")
12932     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-write-to-stream/4")
12933     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-write-to-stream/5")
12934     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-write-to-stream/6")
12935     (check-next-stream-line-equal _test-output-stream "    be/copy-to-esi 0/imm32"      "F - test-convert-write-to-stream/7")
12936     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-write-to-stream/8")
12937     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"      "F - test-convert-write-to-stream/9")
12938     (check-next-stream-line-equal _test-output-stream "    (write-to-stream %esi %ecx 0x00000004)"  "F - test-convert-write-to-stream/10")
12939     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-write-to-stream/11")
12940     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-write-to-stream/12")
12941     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-write-to-stream/13")
12942     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-write-to-stream/14")
12943     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-write-to-stream/15")
12944     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-write-to-stream/16")
12945     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-write-to-stream/17")
12946     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-write-to-stream/18")
12947     # . epilogue
12948     89/<- %esp 5/r32/ebp
12949     5d/pop-to-ebp
12950     c3/return
12951 
12952 test-convert-write-to-stream-with-correct-payload-size:
12953     # . prologue
12954     55/push-ebp
12955     89/<- %ebp 4/r32/esp
12956     # setup
12957     (clear-stream _test-input-stream)
12958     (clear-stream $_test-input-buffered-file->buffer)
12959     (clear-stream _test-output-stream)
12960     (clear-stream $_test-output-buffered-file->buffer)
12961     #
12962     (write _test-input-stream "fn foo {\n")
12963     (write _test-input-stream "  var s/esi: (addr stream handle int) <- copy 0\n")
12964     (write _test-input-stream "  var o/ecx: (addr handle int) <- copy 0\n")
12965     (write _test-input-stream "  write-to-stream s, o\n")
12966     (write _test-input-stream "}\n")
12967     # convert
12968     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
12969     # registers except esp clobbered at this point
12970     # restore ed
12971     89/<- %edx 4/r32/esp
12972     (flush _test-output-buffered-file)
12973     (flush _test-error-buffered-file)
12974 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
12980     # check output
12981     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-write-to-stream-with-correct-payload-size/0")
12982     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-write-to-stream-with-correct-payload-size/1")
12983     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-write-to-stream-with-correct-payload-size/2")
12984     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-write-to-stream-with-correct-payload-size/3")
12985     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-write-to-stream-with-correct-payload-size/4")
12986     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-write-to-stream-with-correct-payload-size/5")
12987     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-write-to-stream-with-correct-payload-size/6")
12988     (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")
12989     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-write-to-stream-with-correct-payload-size/8")
12990     (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")
12991     (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")
12992     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-write-to-stream-with-correct-payload-size/11")
12993     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-write-to-stream-with-correct-payload-size/12")
12994     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-write-to-stream-with-correct-payload-size/13")
12995     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-write-to-stream-with-correct-payload-size/14")
12996     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-write-to-stream-with-correct-payload-size/15")
12997     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-write-to-stream-with-correct-payload-size/16")
12998     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-write-to-stream-with-correct-payload-size/17")
12999     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-write-to-stream-with-correct-payload-size/18")
13000     # . epilogue
13001     89/<- %esp 5/r32/ebp
13002     5d/pop-to-ebp
13003     c3/return
13004 
13005 test-write-to-stream-with-non-stream-atom-base-type:
13006     # . prologue
13007     55/push-ebp
13008     89/<- %ebp 4/r32/esp
13009     # setup
13010     (clear-stream _test-input-stream)
13011     (clear-stream $_test-input-buffered-file->buffer)
13012     (clear-stream _test-output-stream)
13013     (clear-stream $_test-output-buffered-file->buffer)
13014     (clear-stream _test-error-stream)
13015     (clear-stream $_test-error-buffered-file->buffer)
13016     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13017     68/push 0/imm32
13018     68/push 0/imm32
13019     89/<- %edx 4/r32/esp
13020     (tailor-exit-descriptor %edx 0x10)
13021     #
13022     (write _test-input-stream "fn foo {\n")
13023     (write _test-input-stream "  var a: int\n")
13024     (write _test-input-stream "  write-to-stream a, 0\n")
13025     (write _test-input-stream "}\n")
13026     # convert
13027     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13028     # registers except esp clobbered at this point
13029     # restore ed
13030     89/<- %edx 4/r32/esp
13031     (flush _test-output-buffered-file)
13032     (flush _test-error-buffered-file)
13033 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13039     # check output
13040     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-atom-base-type: output should be empty")
13041     (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")
13042     # check that stop(1) was called
13043     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-atom-base-type: exit status")
13044     # don't restore from ebp
13045     81 0/subop/add %esp 8/imm32
13046     # . epilogue
13047     5d/pop-to-ebp
13048     c3/return
13049 
13050 test-write-to-stream-with-non-stream-compound-base-type:
13051     # . prologue
13052     55/push-ebp
13053     89/<- %ebp 4/r32/esp
13054     # setup
13055     (clear-stream _test-input-stream)
13056     (clear-stream $_test-input-buffered-file->buffer)
13057     (clear-stream _test-output-stream)
13058     (clear-stream $_test-output-buffered-file->buffer)
13059     (clear-stream _test-error-stream)
13060     (clear-stream $_test-error-buffered-file->buffer)
13061     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13062     68/push 0/imm32
13063     68/push 0/imm32
13064     89/<- %edx 4/r32/esp
13065     (tailor-exit-descriptor %edx 0x10)
13066     #
13067     (write _test-input-stream "fn foo {\n")
13068     (write _test-input-stream "  var a: (handle int)\n")
13069     (write _test-input-stream "  write-to-stream a, 0\n")
13070     (write _test-input-stream "}\n")
13071     # convert
13072     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13073     # registers except esp clobbered at this point
13074     # restore ed
13075     89/<- %edx 4/r32/esp
13076     (flush _test-output-buffered-file)
13077     (flush _test-error-buffered-file)
13078 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13084     # check output
13085     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-compound-base-type: output should be empty")
13086     (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")
13087     # check that stop(1) was called
13088     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-compound-base-type: exit status")
13089     # don't restore from ebp
13090     81 0/subop/add %esp 8/imm32
13091     # . epilogue
13092     5d/pop-to-ebp
13093     c3/return
13094 
13095 test-write-to-stream-with-non-stream-compound-base-type-2:
13096     # . prologue
13097     55/push-ebp
13098     89/<- %ebp 4/r32/esp
13099     # setup
13100     (clear-stream _test-input-stream)
13101     (clear-stream $_test-input-buffered-file->buffer)
13102     (clear-stream _test-output-stream)
13103     (clear-stream $_test-output-buffered-file->buffer)
13104     (clear-stream _test-error-stream)
13105     (clear-stream $_test-error-buffered-file->buffer)
13106     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13107     68/push 0/imm32
13108     68/push 0/imm32
13109     89/<- %edx 4/r32/esp
13110     (tailor-exit-descriptor %edx 0x10)
13111     #
13112     (write _test-input-stream "fn foo {\n")
13113     (write _test-input-stream "  var a: (addr int)\n")
13114     (write _test-input-stream "  write-to-stream a, 0\n")
13115     (write _test-input-stream "}\n")
13116     # convert
13117     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13118     # registers except esp clobbered at this point
13119     # restore ed
13120     89/<- %edx 4/r32/esp
13121     (flush _test-output-buffered-file)
13122     (flush _test-error-buffered-file)
13123 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13129     # check output
13130     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-compound-base-type-2: output should be empty")
13131     (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")
13132     # check that stop(1) was called
13133     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-compound-base-type-2: exit status")
13134     # don't restore from ebp
13135     81 0/subop/add %esp 8/imm32
13136     # . epilogue
13137     5d/pop-to-ebp
13138     c3/return
13139 
13140 test-write-to-stream-with-stream-atom-base-type:
13141     # . prologue
13142     55/push-ebp
13143     89/<- %ebp 4/r32/esp
13144     # setup
13145     (clear-stream _test-input-stream)
13146     (clear-stream $_test-input-buffered-file->buffer)
13147     (clear-stream _test-output-stream)
13148     (clear-stream $_test-output-buffered-file->buffer)
13149     (clear-stream _test-error-stream)
13150     (clear-stream $_test-error-buffered-file->buffer)
13151     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13152     68/push 0/imm32
13153     68/push 0/imm32
13154     89/<- %edx 4/r32/esp
13155     (tailor-exit-descriptor %edx 0x10)
13156     #
13157     (write _test-input-stream "fn foo {\n")
13158     (write _test-input-stream "  var a: stream\n")
13159     (write _test-input-stream "  write-to-stream a, 0\n")
13160     (write _test-input-stream "}\n")
13161     # convert
13162     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13163     # registers except esp clobbered at this point
13164     # restore ed
13165     89/<- %edx 4/r32/esp
13166     (flush _test-output-buffered-file)
13167     (flush _test-error-buffered-file)
13168 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13174     # check output
13175     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-stream-atom-base-type: output should be empty")
13176     (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")
13177     # check that stop(1) was called
13178     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-stream-atom-base-type: exit status")
13179     # don't restore from ebp
13180     81 0/subop/add %esp 8/imm32
13181     # . epilogue
13182     5d/pop-to-ebp
13183     c3/return
13184 
13185 test-write-to-stream-with-wrong-index-type:
13186     # . prologue
13187     55/push-ebp
13188     89/<- %ebp 4/r32/esp
13189     # setup
13190     (clear-stream _test-input-stream)
13191     (clear-stream $_test-input-buffered-file->buffer)
13192     (clear-stream _test-output-stream)
13193     (clear-stream $_test-output-buffered-file->buffer)
13194     (clear-stream _test-error-stream)
13195     (clear-stream $_test-error-buffered-file->buffer)
13196     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13197     68/push 0/imm32
13198     68/push 0/imm32
13199     89/<- %edx 4/r32/esp
13200     (tailor-exit-descriptor %edx 0x10)
13201     #
13202     (write _test-input-stream "fn foo {\n")
13203     (write _test-input-stream "  var a/eax: (addr stream int) <- copy 0\n")
13204     (write _test-input-stream "  var b: boolean\n")
13205     (write _test-input-stream "  write-to-stream a, b\n")
13206     (write _test-input-stream "}\n")
13207     # convert
13208     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13209     # registers except esp clobbered at this point
13210     # restore ed
13211     89/<- %edx 4/r32/esp
13212     (flush _test-output-buffered-file)
13213     (flush _test-error-buffered-file)
13214 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13220     # check output
13221     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-wrong-index-type: output should be empty")
13222     (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")
13223     # check that stop(1) was called
13224     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-wrong-index-type: exit status")
13225     # don't restore from ebp
13226     81 0/subop/add %esp 8/imm32
13227     # . epilogue
13228     5d/pop-to-ebp
13229     c3/return
13230 
13231 test-write-to-stream-with-no-inouts:
13232     # . prologue
13233     55/push-ebp
13234     89/<- %ebp 4/r32/esp
13235     # setup
13236     (clear-stream _test-input-stream)
13237     (clear-stream $_test-input-buffered-file->buffer)
13238     (clear-stream _test-output-stream)
13239     (clear-stream $_test-output-buffered-file->buffer)
13240     (clear-stream _test-error-stream)
13241     (clear-stream $_test-error-buffered-file->buffer)
13242     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13243     68/push 0/imm32
13244     68/push 0/imm32
13245     89/<- %edx 4/r32/esp
13246     (tailor-exit-descriptor %edx 0x10)
13247     #
13248     (write _test-input-stream "fn foo {\n")
13249     (write _test-input-stream "  write-to-stream\n")
13250     (write _test-input-stream "}\n")
13251     # convert
13252     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13253     # registers except esp clobbered at this point
13254     # restore ed
13255     89/<- %edx 4/r32/esp
13256     (flush _test-output-buffered-file)
13257     (flush _test-error-buffered-file)
13258 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13264     # check output
13265     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-no-inouts: output should be empty")
13266     (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")
13267     # check that stop(1) was called
13268     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-no-inouts: exit status")
13269     # don't restore from ebp
13270     81 0/subop/add %esp 8/imm32
13271     # . epilogue
13272     5d/pop-to-ebp
13273     c3/return
13274 
13275 test-write-to-stream-with-too-few-inouts:
13276     # . prologue
13277     55/push-ebp
13278     89/<- %ebp 4/r32/esp
13279     # setup
13280     (clear-stream _test-input-stream)
13281     (clear-stream $_test-input-buffered-file->buffer)
13282     (clear-stream _test-output-stream)
13283     (clear-stream $_test-output-buffered-file->buffer)
13284     (clear-stream _test-error-stream)
13285     (clear-stream $_test-error-buffered-file->buffer)
13286     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13287     68/push 0/imm32
13288     68/push 0/imm32
13289     89/<- %edx 4/r32/esp
13290     (tailor-exit-descriptor %edx 0x10)
13291     #
13292     (write _test-input-stream "fn foo {\n")
13293     (write _test-input-stream "  var a: (addr stream int)\n")
13294     (write _test-input-stream "  write-to-stream a\n")
13295     (write _test-input-stream "}\n")
13296     # convert
13297     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13298     # registers except esp clobbered at this point
13299     # restore ed
13300     89/<- %edx 4/r32/esp
13301     (flush _test-output-buffered-file)
13302     (flush _test-error-buffered-file)
13303 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13309     # check output
13310     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-too-few-inouts: output should be empty")
13311     (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")
13312     # check that stop(1) was called
13313     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-too-few-inouts: exit status")
13314     # don't restore from ebp
13315     81 0/subop/add %esp 8/imm32
13316     # . epilogue
13317     5d/pop-to-ebp
13318     c3/return
13319 
13320 test-write-to-stream-with-too-many-inouts:
13321     # . prologue
13322     55/push-ebp
13323     89/<- %ebp 4/r32/esp
13324     # setup
13325     (clear-stream _test-input-stream)
13326     (clear-stream $_test-input-buffered-file->buffer)
13327     (clear-stream _test-output-stream)
13328     (clear-stream $_test-output-buffered-file->buffer)
13329     (clear-stream _test-error-stream)
13330     (clear-stream $_test-error-buffered-file->buffer)
13331     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13332     68/push 0/imm32
13333     68/push 0/imm32
13334     89/<- %edx 4/r32/esp
13335     (tailor-exit-descriptor %edx 0x10)
13336     #
13337     (write _test-input-stream "fn foo {\n")
13338     (write _test-input-stream "  var a: (addr stream int)\n")
13339     (write _test-input-stream "  var b: (addr int)\n")
13340     (write _test-input-stream "  write-to-stream a, b, 0\n")
13341     (write _test-input-stream "}\n")
13342     # convert
13343     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13344     # registers except esp clobbered at this point
13345     # restore ed
13346     89/<- %edx 4/r32/esp
13347     (flush _test-output-buffered-file)
13348     (flush _test-error-buffered-file)
13349 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13355     # check output
13356     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-too-many-inouts: output should be empty")
13357     (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")
13358     # check that stop(1) was called
13359     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-too-many-inouts: exit status")
13360     # don't restore from ebp
13361     81 0/subop/add %esp 8/imm32
13362     # . epilogue
13363     5d/pop-to-ebp
13364     c3/return
13365 
13366 test-write-to-stream-with-output:
13367     # . prologue
13368     55/push-ebp
13369     89/<- %ebp 4/r32/esp
13370     # setup
13371     (clear-stream _test-input-stream)
13372     (clear-stream $_test-input-buffered-file->buffer)
13373     (clear-stream _test-output-stream)
13374     (clear-stream $_test-output-buffered-file->buffer)
13375     (clear-stream _test-error-stream)
13376     (clear-stream $_test-error-buffered-file->buffer)
13377     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13378     68/push 0/imm32
13379     68/push 0/imm32
13380     89/<- %edx 4/r32/esp
13381     (tailor-exit-descriptor %edx 0x10)
13382     #
13383     (write _test-input-stream "fn foo {\n")
13384     (write _test-input-stream "  var a: (addr stream int)\n")
13385     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
13386     (write _test-input-stream "  b <- write-to-stream a, b\n")
13387     (write _test-input-stream "}\n")
13388     # convert
13389     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13390     # registers except esp clobbered at this point
13391     # restore ed
13392     89/<- %edx 4/r32/esp
13393     (flush _test-output-buffered-file)
13394     (flush _test-error-buffered-file)
13395 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13401     # check output
13402     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-output: output should be empty")
13403     (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")
13404     # check that stop(1) was called
13405     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-output: exit status")
13406     # don't restore from ebp
13407     81 0/subop/add %esp 8/imm32
13408     # . epilogue
13409     5d/pop-to-ebp
13410     c3/return
13411 
13412 test-length-with-non-array-atom-base-type:
13413     # . prologue
13414     55/push-ebp
13415     89/<- %ebp 4/r32/esp
13416     # setup
13417     (clear-stream _test-input-stream)
13418     (clear-stream $_test-input-buffered-file->buffer)
13419     (clear-stream _test-output-stream)
13420     (clear-stream $_test-output-buffered-file->buffer)
13421     (clear-stream _test-error-stream)
13422     (clear-stream $_test-error-buffered-file->buffer)
13423     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13424     68/push 0/imm32
13425     68/push 0/imm32
13426     89/<- %edx 4/r32/esp
13427     (tailor-exit-descriptor %edx 0x10)
13428     #
13429     (write _test-input-stream "fn foo {\n")
13430     (write _test-input-stream "  var a: int\n")
13431     (write _test-input-stream "  var c/ecx: int <- length a\n")
13432     (write _test-input-stream "}\n")
13433     # convert
13434     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13435     # registers except esp clobbered at this point
13436     # restore ed
13437     89/<- %edx 4/r32/esp
13438     (flush _test-output-buffered-file)
13439     (flush _test-error-buffered-file)
13440 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13446     # check output
13447     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-atom-base-type: output should be empty")
13448     (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")
13449     # check that stop(1) was called
13450     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-atom-base-type: exit status")
13451     # don't restore from ebp
13452     81 0/subop/add %esp 8/imm32
13453     # . epilogue
13454     5d/pop-to-ebp
13455     c3/return
13456 
13457 test-length-with-non-array-compound-base-type:
13458     # . prologue
13459     55/push-ebp
13460     89/<- %ebp 4/r32/esp
13461     # setup
13462     (clear-stream _test-input-stream)
13463     (clear-stream $_test-input-buffered-file->buffer)
13464     (clear-stream _test-output-stream)
13465     (clear-stream $_test-output-buffered-file->buffer)
13466     (clear-stream _test-error-stream)
13467     (clear-stream $_test-error-buffered-file->buffer)
13468     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13469     68/push 0/imm32
13470     68/push 0/imm32
13471     89/<- %edx 4/r32/esp
13472     (tailor-exit-descriptor %edx 0x10)
13473     #
13474     (write _test-input-stream "fn foo {\n")
13475     (write _test-input-stream "  var a: (handle int)\n")
13476     (write _test-input-stream "  var c/ecx: (addr int) <- length a, 0\n")
13477     (write _test-input-stream "}\n")
13478     # convert
13479     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13480     # registers except esp clobbered at this point
13481     # restore ed
13482     89/<- %edx 4/r32/esp
13483     (flush _test-output-buffered-file)
13484     (flush _test-error-buffered-file)
13485 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13491     # check output
13492     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-compound-base-type: output should be empty")
13493     (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")
13494     # check that stop(1) was called
13495     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-compound-base-type: exit status")
13496     # don't restore from ebp
13497     81 0/subop/add %esp 8/imm32
13498     # . epilogue
13499     5d/pop-to-ebp
13500     c3/return
13501 
13502 test-length-with-non-array-compound-base-type-2:
13503     # . prologue
13504     55/push-ebp
13505     89/<- %ebp 4/r32/esp
13506     # setup
13507     (clear-stream _test-input-stream)
13508     (clear-stream $_test-input-buffered-file->buffer)
13509     (clear-stream _test-output-stream)
13510     (clear-stream $_test-output-buffered-file->buffer)
13511     (clear-stream _test-error-stream)
13512     (clear-stream $_test-error-buffered-file->buffer)
13513     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13514     68/push 0/imm32
13515     68/push 0/imm32
13516     89/<- %edx 4/r32/esp
13517     (tailor-exit-descriptor %edx 0x10)
13518     #
13519     (write _test-input-stream "fn foo {\n")
13520     (write _test-input-stream "  var a: (addr int)\n")
13521     (write _test-input-stream "  var c/ecx: (addr int) <- length a, 0\n")
13522     (write _test-input-stream "}\n")
13523     # convert
13524     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13525     # registers except esp clobbered at this point
13526     # restore ed
13527     89/<- %edx 4/r32/esp
13528     (flush _test-output-buffered-file)
13529     (flush _test-error-buffered-file)
13530 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13536     # check output
13537     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-compound-base-type-2: output should be empty")
13538     (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")
13539     # check that stop(1) was called
13540     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-compound-base-type-2: exit status")
13541     # don't restore from ebp
13542     81 0/subop/add %esp 8/imm32
13543     # . epilogue
13544     5d/pop-to-ebp
13545     c3/return
13546 
13547 test-length-with-array-atom-base-type:
13548     # . prologue
13549     55/push-ebp
13550     89/<- %ebp 4/r32/esp
13551     # setup
13552     (clear-stream _test-input-stream)
13553     (clear-stream $_test-input-buffered-file->buffer)
13554     (clear-stream _test-output-stream)
13555     (clear-stream $_test-output-buffered-file->buffer)
13556     (clear-stream _test-error-stream)
13557     (clear-stream $_test-error-buffered-file->buffer)
13558     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13559     68/push 0/imm32
13560     68/push 0/imm32
13561     89/<- %edx 4/r32/esp
13562     (tailor-exit-descriptor %edx 0x10)
13563     #
13564     (write _test-input-stream "fn foo {\n")
13565     (write _test-input-stream "  var a: array\n")
13566     (write _test-input-stream "  var c/ecx: (addr int) <- length a\n")
13567     (write _test-input-stream "}\n")
13568     # convert
13569     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13570     # registers except esp clobbered at this point
13571     # restore ed
13572     89/<- %edx 4/r32/esp
13573     (flush _test-output-buffered-file)
13574     (flush _test-error-buffered-file)
13575 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13581     # check output
13582     (check-stream-equal _test-output-stream  ""  "F - test-length-with-array-atom-base-type: output should be empty")
13583     (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")
13584     # check that stop(1) was called
13585     (check-ints-equal *(edx+4) 2 "F - test-length-with-array-atom-base-type: exit status")
13586     # don't restore from ebp
13587     81 0/subop/add %esp 8/imm32
13588     # . epilogue
13589     5d/pop-to-ebp
13590     c3/return
13591 
13592 test-length-with-addr-base-on-stack:
13593     # . prologue
13594     55/push-ebp
13595     89/<- %ebp 4/r32/esp
13596     # setup
13597     (clear-stream _test-input-stream)
13598     (clear-stream $_test-input-buffered-file->buffer)
13599     (clear-stream _test-output-stream)
13600     (clear-stream $_test-output-buffered-file->buffer)
13601     (clear-stream _test-error-stream)
13602     (clear-stream $_test-error-buffered-file->buffer)
13603     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13604     68/push 0/imm32
13605     68/push 0/imm32
13606     89/<- %edx 4/r32/esp
13607     (tailor-exit-descriptor %edx 0x10)
13608     #
13609     (write _test-input-stream "fn foo {\n")
13610     (write _test-input-stream "  var a: (addr array int)\n")
13611     (write _test-input-stream "  var c/ecx: (addr int) <- length a\n")
13612     (write _test-input-stream "}\n")
13613     # convert
13614     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13615     # registers except esp clobbered at this point
13616     # restore ed
13617     89/<- %edx 4/r32/esp
13618     (flush _test-output-buffered-file)
13619     (flush _test-error-buffered-file)
13620 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13626     # check output
13627     (check-stream-equal _test-output-stream  ""  "F - test-length-with-addr-base-on-stack: output should be empty")
13628     (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")
13629     # check that stop(1) was called
13630     (check-ints-equal *(edx+4) 2 "F - test-length-with-addr-base-on-stack: exit status")
13631     # don't restore from ebp
13632     81 0/subop/add %esp 8/imm32
13633     # . epilogue
13634     5d/pop-to-ebp
13635     c3/return
13636 
13637 test-length-with-wrong-output-type:
13638     # . prologue
13639     55/push-ebp
13640     89/<- %ebp 4/r32/esp
13641     # setup
13642     (clear-stream _test-input-stream)
13643     (clear-stream $_test-input-buffered-file->buffer)
13644     (clear-stream _test-output-stream)
13645     (clear-stream $_test-output-buffered-file->buffer)
13646     (clear-stream _test-error-stream)
13647     (clear-stream $_test-error-buffered-file->buffer)
13648     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13649     68/push 0/imm32
13650     68/push 0/imm32
13651     89/<- %edx 4/r32/esp
13652     (tailor-exit-descriptor %edx 0x10)
13653     #
13654     (write _test-input-stream "fn foo {\n")
13655     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
13656     (write _test-input-stream "  var o/edi: (addr int) <- length a\n")
13657     (write _test-input-stream "}\n")
13658     # convert
13659     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13660     # registers except esp clobbered at this point
13661     # restore ed
13662     89/<- %edx 4/r32/esp
13663     (flush _test-output-buffered-file)
13664     (flush _test-error-buffered-file)
13665 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13671     # check output
13672     (check-stream-equal _test-output-stream  ""  "F - test-length-with-wrong-output-type: output should be empty")
13673     (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")
13674     # check that stop(1) was called
13675     (check-ints-equal *(edx+4) 2 "F - test-length-with-wrong-output-type: exit status")
13676     # don't restore from ebp
13677     81 0/subop/add %esp 8/imm32
13678     # . epilogue
13679     5d/pop-to-ebp
13680     c3/return
13681 
13682 test-length-with-wrong-output-compound-type:
13683     # . prologue
13684     55/push-ebp
13685     89/<- %ebp 4/r32/esp
13686     # setup
13687     (clear-stream _test-input-stream)
13688     (clear-stream $_test-input-buffered-file->buffer)
13689     (clear-stream _test-output-stream)
13690     (clear-stream $_test-output-buffered-file->buffer)
13691     (clear-stream _test-error-stream)
13692     (clear-stream $_test-error-buffered-file->buffer)
13693     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13694     68/push 0/imm32
13695     68/push 0/imm32
13696     89/<- %edx 4/r32/esp
13697     (tailor-exit-descriptor %edx 0x10)
13698     #
13699     (write _test-input-stream "fn foo {\n")
13700     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
13701     (write _test-input-stream "  var o/edi: (addr handle int) <- length a\n")
13702     (write _test-input-stream "}\n")
13703     # convert
13704     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13705     # registers except esp clobbered at this point
13706     # restore ed
13707     89/<- %edx 4/r32/esp
13708     (flush _test-output-buffered-file)
13709     (flush _test-error-buffered-file)
13710 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13716     # check output
13717     (check-stream-equal _test-output-stream  ""  "F - test-length-with-wrong-output-compound-type: output should be empty")
13718     (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")
13719     # check that stop(1) was called
13720     (check-ints-equal *(edx+4) 2 "F - test-length-with-wrong-output-compound-type: exit status")
13721     # don't restore from ebp
13722     81 0/subop/add %esp 8/imm32
13723     # . epilogue
13724     5d/pop-to-ebp
13725     c3/return
13726 
13727 test-length-with-no-inouts:
13728     # . prologue
13729     55/push-ebp
13730     89/<- %ebp 4/r32/esp
13731     # setup
13732     (clear-stream _test-input-stream)
13733     (clear-stream $_test-input-buffered-file->buffer)
13734     (clear-stream _test-output-stream)
13735     (clear-stream $_test-output-buffered-file->buffer)
13736     (clear-stream _test-error-stream)
13737     (clear-stream $_test-error-buffered-file->buffer)
13738     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13739     68/push 0/imm32
13740     68/push 0/imm32
13741     89/<- %edx 4/r32/esp
13742     (tailor-exit-descriptor %edx 0x10)
13743     #
13744     (write _test-input-stream "fn foo {\n")
13745     (write _test-input-stream "  var c/ecx: int <- length\n")
13746     (write _test-input-stream "}\n")
13747     # convert
13748     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13749     # registers except esp clobbered at this point
13750     # restore ed
13751     89/<- %edx 4/r32/esp
13752     (flush _test-output-buffered-file)
13753     (flush _test-error-buffered-file)
13754 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13760     # check output
13761     (check-stream-equal _test-output-stream  ""  "F - test-length-with-no-inouts: output should be empty")
13762     (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")
13763     # check that stop(1) was called
13764     (check-ints-equal *(edx+4) 2 "F - test-length-with-no-inouts: exit status")
13765     # don't restore from ebp
13766     81 0/subop/add %esp 8/imm32
13767     # . epilogue
13768     5d/pop-to-ebp
13769     c3/return
13770 
13771 test-length-with-too-many-inouts:
13772     # . prologue
13773     55/push-ebp
13774     89/<- %ebp 4/r32/esp
13775     # setup
13776     (clear-stream _test-input-stream)
13777     (clear-stream $_test-input-buffered-file->buffer)
13778     (clear-stream _test-output-stream)
13779     (clear-stream $_test-output-buffered-file->buffer)
13780     (clear-stream _test-error-stream)
13781     (clear-stream $_test-error-buffered-file->buffer)
13782     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13783     68/push 0/imm32
13784     68/push 0/imm32
13785     89/<- %edx 4/r32/esp
13786     (tailor-exit-descriptor %edx 0x10)
13787     #
13788     (write _test-input-stream "fn foo {\n")
13789     (write _test-input-stream "  var a: (array int 3)\n")
13790     (write _test-input-stream "  var c/ecx: int <- length a, 0, 0\n")
13791     (write _test-input-stream "}\n")
13792     # convert
13793     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13794     # registers except esp clobbered at this point
13795     # restore ed
13796     89/<- %edx 4/r32/esp
13797     (flush _test-output-buffered-file)
13798     (flush _test-error-buffered-file)
13799 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13805     # check output
13806     (check-stream-equal _test-output-stream  ""  "F - test-length-with-too-many-inouts: output should be empty")
13807     (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")
13808     # check that stop(1) was called
13809     (check-ints-equal *(edx+4) 2 "F - test-length-with-too-many-inouts: exit status")
13810     # don't restore from ebp
13811     81 0/subop/add %esp 8/imm32
13812     # . epilogue
13813     5d/pop-to-ebp
13814     c3/return
13815 
13816 test-length-with-no-output:
13817     # . prologue
13818     55/push-ebp
13819     89/<- %ebp 4/r32/esp
13820     # setup
13821     (clear-stream _test-input-stream)
13822     (clear-stream $_test-input-buffered-file->buffer)
13823     (clear-stream _test-output-stream)
13824     (clear-stream $_test-output-buffered-file->buffer)
13825     (clear-stream _test-error-stream)
13826     (clear-stream $_test-error-buffered-file->buffer)
13827     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13828     68/push 0/imm32
13829     68/push 0/imm32
13830     89/<- %edx 4/r32/esp
13831     (tailor-exit-descriptor %edx 0x10)
13832     #
13833     (write _test-input-stream "fn foo {\n")
13834     (write _test-input-stream "  var a: (array int 3)\n")
13835     (write _test-input-stream "  length a\n")
13836     (write _test-input-stream "}\n")
13837     # convert
13838     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13839     # registers except esp clobbered at this point
13840     # restore ed
13841     89/<- %edx 4/r32/esp
13842     (flush _test-output-buffered-file)
13843     (flush _test-error-buffered-file)
13844 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13850     # check output
13851     (check-stream-equal _test-output-stream  ""  "F - test-length-with-no-output: output should be empty")
13852     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: must have an output"  "F - test-length-with-no-output: error message")
13853     # check that stop(1) was called
13854     (check-ints-equal *(edx+4) 2 "F - test-length-with-no-output: exit status")
13855     # don't restore from ebp
13856     81 0/subop/add %esp 8/imm32
13857     # . epilogue
13858     5d/pop-to-ebp
13859     c3/return
13860 
13861 test-length-with-too-many-outputs:
13862     # . prologue
13863     55/push-ebp
13864     89/<- %ebp 4/r32/esp
13865     # setup
13866     (clear-stream _test-input-stream)
13867     (clear-stream $_test-input-buffered-file->buffer)
13868     (clear-stream _test-output-stream)
13869     (clear-stream $_test-output-buffered-file->buffer)
13870     (clear-stream _test-error-stream)
13871     (clear-stream $_test-error-buffered-file->buffer)
13872     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13873     68/push 0/imm32
13874     68/push 0/imm32
13875     89/<- %edx 4/r32/esp
13876     (tailor-exit-descriptor %edx 0x10)
13877     #
13878     (write _test-input-stream "fn foo {\n")
13879     (write _test-input-stream "  var a: (array int 3)\n")
13880     (write _test-input-stream "  var b/eax: int <- copy 0\n")
13881     (write _test-input-stream "  var c/ecx: int <- copy 0\n")
13882     (write _test-input-stream "  b, c <- length a\n")
13883     (write _test-input-stream "}\n")
13884     # convert
13885     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13886     # registers except esp clobbered at this point
13887     # restore ed
13888     89/<- %edx 4/r32/esp
13889     (flush _test-output-buffered-file)
13890     (flush _test-error-buffered-file)
13891 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13897     # check output
13898     (check-stream-equal _test-output-stream  ""  "F - test-length-with-too-many-outputs: output should be empty")
13899     (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")
13900     # check that stop(1) was called
13901     (check-ints-equal *(edx+4) 2 "F - test-length-with-too-many-outputs: exit status")
13902     # don't restore from ebp
13903     81 0/subop/add %esp 8/imm32
13904     # . epilogue
13905     5d/pop-to-ebp
13906     c3/return
13907 
13908 test-convert-function-with-return-register-and-local:
13909     # . prologue
13910     55/push-ebp
13911     89/<- %ebp 4/r32/esp
13912     # setup
13913     (clear-stream _test-input-stream)
13914     (clear-stream $_test-input-buffered-file->buffer)
13915     (clear-stream _test-output-stream)
13916     (clear-stream $_test-output-buffered-file->buffer)
13917     #
13918     (write _test-input-stream "fn foo -> _/eax: int {\n")
13919     (write _test-input-stream "  var y/eax: int <- copy 3\n")
13920     (write _test-input-stream "  var z/ecx: int <- copy 4\n")
13921     (write _test-input-stream "  return y\n")
13922     (write _test-input-stream "}\n")
13923     # convert
13924     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
13925     (flush _test-output-buffered-file)
13926 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
13932     # check output
13933     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register-and-local/0")
13934     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register-and-local/1")
13935     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register-and-local/2")
13936     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register-and-local/3")
13937     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register-and-local/4")
13938     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register-and-local/5")
13939     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register-and-local/6")
13940     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-convert-function-with-return-register-and-local/7")
13941     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-return-register-and-local/8")
13942     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-convert-function-with-return-register-and-local/9")
13943     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-return-register-and-local/10")
13944     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-function-with-return-register-and-local/11")
13945     (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")
13946     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-register-and-local/13")
13947     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register-and-local/14")
13948     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register-and-local/15")
13949     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register-and-local/16")
13950     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register-and-local/17")
13951     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register-and-local/18")
13952     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register-and-local/19")
13953     # . epilogue
13954     89/<- %esp 5/r32/ebp
13955     5d/pop-to-ebp
13956     c3/return
13957 
13958 test-convert-function-with-return-register-and-local-2:
13959     # . prologue
13960     55/push-ebp
13961     89/<- %ebp 4/r32/esp
13962     # setup
13963     (clear-stream _test-input-stream)
13964     (clear-stream $_test-input-buffered-file->buffer)
13965     (clear-stream _test-output-stream)
13966     (clear-stream $_test-output-buffered-file->buffer)
13967     #
13968     (write _test-input-stream "fn foo -> _/eax: int {\n")
13969     (write _test-input-stream "  var y/eax: int <- copy 3\n")
13970     (write _test-input-stream "  var z/ecx: int <- copy 4\n")
13971     (write _test-input-stream "  return z\n")
13972     (write _test-input-stream "}\n")
13973     # convert
13974     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
13975     (flush _test-output-buffered-file)
13976 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
13982     # check output
13983     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register-and-local-2/0")
13984     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register-and-local-2/1")
13985     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register-and-local-2/2")
13986     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register-and-local-2/3")
13987     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register-and-local-2/4")
13988     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register-and-local-2/5")
13989     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register-and-local-2/6")
13990     (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")
13991     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-return-register-and-local-2/8")
13992     (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")
13993     (check-next-stream-line-equal _test-output-stream "    8b/-> %ecx 0x00000000/r32" "F - test-convert-function-with-return-register-and-local-2/10")
13994     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-function-with-return-register-and-local-2/11")
13995     (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")
13996     (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")
13997     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register-and-local-2/14")
13998     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register-and-local-2/15")
13999     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register-and-local-2/16")
14000     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register-and-local-2/17")
14001     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register-and-local-2/18")
14002     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register-and-local-2/19")
14003     # . epilogue
14004     89/<- %esp 5/r32/ebp
14005     5d/pop-to-ebp
14006     c3/return
14007 
14008 test-convert-function-with-return-float-register-and-local:
14009     # . prologue
14010     55/push-ebp
14011     89/<- %ebp 4/r32/esp
14012     # setup
14013     (clear-stream _test-input-stream)
14014     (clear-stream $_test-input-buffered-file->buffer)
14015     (clear-stream _test-output-stream)
14016     (clear-stream $_test-output-buffered-file->buffer)
14017     #
14018     (write _test-input-stream "fn foo -> _/xmm1: float {\n")
14019     (write _test-input-stream "  var y/eax: int <- copy 3\n")
14020     (write _test-input-stream "  var g/xmm0: float <- convert y\n")
14021     (write _test-input-stream "  var h/xmm1: float <- convert y\n")
14022     (write _test-input-stream "  return g\n")
14023     (write _test-input-stream "}\n")
14024     # convert
14025     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
14026     (flush _test-output-buffered-file)
14027 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
14033     # check output
14034     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-float-register-and-local/0")
14035     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-float-register-and-local/1")
14036     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-float-register-and-local/2")
14037     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-float-register-and-local/3")
14038     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-float-register-and-local/4")
14039     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-float-register-and-local/5")
14040     (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
14041     (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")
14042     (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
14043     (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")
14044     (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")
14045     (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
14046     (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")
14047     (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")
14048     (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
14049     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-floating-point-dereferenced/15")  # reclaim h
14050     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 0/x32"  "F - test-convert-floating-point-dereferenced/16")  # reclaim g
14051     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-floating-point-dereferenced/17")
14052     (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
14053     (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")
14054     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-float-register-and-local/20")
14055     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-float-register-and-local/21")
14056     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-float-register-and-local/22")
14057     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-float-register-and-local/23")
14058     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-float-register-and-local/24")
14059     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-float-register-and-local/25")
14060     # . epilogue
14061     89/<- %esp 5/r32/ebp
14062     5d/pop-to-ebp
14063     c3/return
14064 
14065 test-convert-function-with-return-and-local-vars:
14066     # . prologue
14067     55/push-ebp
14068     89/<- %ebp 4/r32/esp
14069     # setup
14070     (clear-stream _test-input-stream)
14071     (clear-stream $_test-input-buffered-file->buffer)
14072     (clear-stream _test-output-stream)
14073     (clear-stream $_test-output-buffered-file->buffer)
14074     #
14075     (write _test-input-stream "fn foo -> _/eax: int {\n")
14076     (write _test-input-stream "  {\n")
14077     (write _test-input-stream "    var x: int\n")
14078     (write _test-input-stream "    {\n")
14079     (write _test-input-stream "      var y: int\n")
14080     (write _test-input-stream "      return y\n")
14081     (write _test-input-stream "      increment x\n")
14082     (write _test-input-stream "    }\n")
14083     (write _test-input-stream "  }\n")
14084     (write _test-input-stream "  return 0\n")
14085     (write _test-input-stream "}\n")
14086     # convert
14087     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
14088     (flush _test-output-buffered-file)
14089 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
14095     # check output
14096     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-and-local-vars/0")
14097     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-and-local-vars/1")
14098     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-and-local-vars/2")
14099     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-and-local-vars/3")
14100     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-and-local-vars/4")
14101     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-and-local-vars/5")
14102     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-return-and-local-vars/6")
14103     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-return-and-local-vars/7")
14104     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-return-and-local-vars/8")  # var x
14105     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-return-and-local-vars/9")
14106     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-return-and-local-vars/10")
14107     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-return-and-local-vars/11")  # var y
14108     (check-next-stream-line-equal _test-output-stream "        8b/-> *(ebp+0xfffffff8) 0x00000000/r32" "F - test-convert-function-with-return-and-local-vars/12")
14109     (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")
14110     (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")
14111     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-and-local-vars/15")
14112     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-return-and-local-vars/16")
14113     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-return-and-local-vars/17")
14114     (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")
14115     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-return-and-local-vars/19")
14116     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-return-and-local-vars/20")
14117     (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")
14118     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-and-local-vars/21")
14119     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-and-local-vars/21")
14120     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-and-local-vars/22")
14121     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-and-local-vars/23")
14122     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-and-local-vars/24")
14123     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-and-local-vars/25")
14124     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-and-local-vars/26")
14125     # . epilogue
14126     89/<- %esp 5/r32/ebp
14127     5d/pop-to-ebp
14128     c3/return
14129 
14130 test-copy-object-with-no-inout:
14131     # . prologue
14132     55/push-ebp
14133     89/<- %ebp 4/r32/esp
14134     # setup
14135     (clear-stream _test-input-stream)
14136     (clear-stream $_test-input-buffered-file->buffer)
14137     (clear-stream _test-output-stream)
14138     (clear-stream $_test-output-buffered-file->buffer)
14139     (clear-stream _test-error-stream)
14140     (clear-stream $_test-error-buffered-file->buffer)
14141     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14142     68/push 0/imm32
14143     68/push 0/imm32
14144     89/<- %edx 4/r32/esp
14145     (tailor-exit-descriptor %edx 0x10)
14146     #
14147     (write _test-input-stream "fn foo {\n")
14148     (write _test-input-stream "  copy-object\n")
14149     (write _test-input-stream "}\n")
14150     # convert
14151     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14152     # registers except esp clobbered at this point
14153     # restore ed
14154     89/<- %edx 4/r32/esp
14155     (flush _test-output-buffered-file)
14156     (flush _test-error-buffered-file)
14157 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14163     # check output
14164     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-no-inout: output should be empty")
14165     (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")
14166     # check that stop(1) was called
14167     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-no-inout: exit status")
14168     # don't restore from ebp
14169     81 0/subop/add %esp 8/imm32
14170     # . epilogue
14171     5d/pop-to-ebp
14172     c3/return
14173 
14174 test-copy-object-with-no-source:
14175     # . prologue
14176     55/push-ebp
14177     89/<- %ebp 4/r32/esp
14178     # setup
14179     (clear-stream _test-input-stream)
14180     (clear-stream $_test-input-buffered-file->buffer)
14181     (clear-stream _test-output-stream)
14182     (clear-stream $_test-output-buffered-file->buffer)
14183     (clear-stream _test-error-stream)
14184     (clear-stream $_test-error-buffered-file->buffer)
14185     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14186     68/push 0/imm32
14187     68/push 0/imm32
14188     89/<- %edx 4/r32/esp
14189     (tailor-exit-descriptor %edx 0x10)
14190     #
14191     (write _test-input-stream "fn foo {\n")
14192     (write _test-input-stream "  var x: (addr int)\n")
14193     (write _test-input-stream "  copy-object x\n")
14194     (write _test-input-stream "}\n")
14195     # convert
14196     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14197     # registers except esp clobbered at this point
14198     # restore ed
14199     89/<- %edx 4/r32/esp
14200     (flush _test-output-buffered-file)
14201     (flush _test-error-buffered-file)
14202 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14208     # check output
14209     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-no-source: output should be empty")
14210     (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")
14211     # check that stop(1) was called
14212     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-no-source: exit status")
14213     # don't restore from ebp
14214     81 0/subop/add %esp 8/imm32
14215     # . epilogue
14216     5d/pop-to-ebp
14217     c3/return
14218 
14219 test-copy-object-with-too-many-inouts:
14220     # . prologue
14221     55/push-ebp
14222     89/<- %ebp 4/r32/esp
14223     # setup
14224     (clear-stream _test-input-stream)
14225     (clear-stream $_test-input-buffered-file->buffer)
14226     (clear-stream _test-output-stream)
14227     (clear-stream $_test-output-buffered-file->buffer)
14228     (clear-stream _test-error-stream)
14229     (clear-stream $_test-error-buffered-file->buffer)
14230     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14231     68/push 0/imm32
14232     68/push 0/imm32
14233     89/<- %edx 4/r32/esp
14234     (tailor-exit-descriptor %edx 0x10)
14235     #
14236     (write _test-input-stream "fn foo {\n")
14237     (write _test-input-stream "  var x: (addr boolean)\n")
14238     (write _test-input-stream "  copy-object x, x, x\n")
14239     (write _test-input-stream "}\n")
14240     # convert
14241     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14242     # registers except esp clobbered at this point
14243     # restore ed
14244     89/<- %edx 4/r32/esp
14245     (flush _test-output-buffered-file)
14246     (flush _test-error-buffered-file)
14247 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14253     # check output
14254     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-too-many-inouts: output should be empty")
14255     (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")
14256     # check that stop(1) was called
14257     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-too-many-inouts: exit status")
14258     # don't restore from ebp
14259     81 0/subop/add %esp 8/imm32
14260     # . epilogue
14261     5d/pop-to-ebp
14262     c3/return
14263 
14264 test-copy-object-with-output:
14265     # . prologue
14266     55/push-ebp
14267     89/<- %ebp 4/r32/esp
14268     # setup
14269     (clear-stream _test-input-stream)
14270     (clear-stream $_test-input-buffered-file->buffer)
14271     (clear-stream _test-output-stream)
14272     (clear-stream $_test-output-buffered-file->buffer)
14273     (clear-stream _test-error-stream)
14274     (clear-stream $_test-error-buffered-file->buffer)
14275     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14276     68/push 0/imm32
14277     68/push 0/imm32
14278     89/<- %edx 4/r32/esp
14279     (tailor-exit-descriptor %edx 0x10)
14280     #
14281     (write _test-input-stream "fn foo {\n")
14282     (write _test-input-stream "  var x/eax: (addr boolean) <- copy 0\n")
14283     (write _test-input-stream "  var y/ecx: (addr boolean) <- copy 0\n")
14284     (write _test-input-stream "  x <- copy-object x, y\n")
14285     (write _test-input-stream "}\n")
14286     # convert
14287     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14288     # registers except esp clobbered at this point
14289     # restore ed
14290     89/<- %edx 4/r32/esp
14291     (flush _test-output-buffered-file)
14292     (flush _test-error-buffered-file)
14293 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14299     # check output
14300     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-output: output should be empty")
14301     (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")
14302     # check that stop(1) was called
14303     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-output: exit status")
14304     # don't restore from ebp
14305     81 0/subop/add %esp 8/imm32
14306     # . epilogue
14307     5d/pop-to-ebp
14308     c3/return
14309 
14310 test-copy-object-deref-address:
14311     # . prologue
14312     55/push-ebp
14313     89/<- %ebp 4/r32/esp
14314     # setup
14315     (clear-stream _test-input-stream)
14316     (clear-stream $_test-input-buffered-file->buffer)
14317     (clear-stream _test-output-stream)
14318     (clear-stream $_test-output-buffered-file->buffer)
14319     #
14320     (write _test-input-stream "fn foo {\n")
14321     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
14322     (write _test-input-stream "  var y/ecx: (addr addr int) <- copy 0\n")
14323     (write _test-input-stream "  copy-object *y, x\n")
14324     (write _test-input-stream "}\n")
14325     # convert
14326     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
14327     (flush _test-output-buffered-file)
14328     # no errors
14329     # . epilogue
14330     5d/pop-to-ebp
14331     c3/return
14332 
14333 test-copy-object-non-addr:
14334     # . prologue
14335     55/push-ebp
14336     89/<- %ebp 4/r32/esp
14337     # setup
14338     (clear-stream _test-input-stream)
14339     (clear-stream $_test-input-buffered-file->buffer)
14340     (clear-stream _test-output-stream)
14341     (clear-stream $_test-output-buffered-file->buffer)
14342     (clear-stream _test-error-stream)
14343     (clear-stream $_test-error-buffered-file->buffer)
14344     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14345     68/push 0/imm32
14346     68/push 0/imm32
14347     89/<- %edx 4/r32/esp
14348     (tailor-exit-descriptor %edx 0x10)
14349     #
14350     (write _test-input-stream "fn foo {\n")
14351     (write _test-input-stream "  var x: int\n")
14352     (write _test-input-stream "  var y: int\n")
14353     (write _test-input-stream "  copy-object y, x\n")
14354     (write _test-input-stream "}\n")
14355     # convert
14356     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14357     # registers except esp clobbered at this point
14358     # restore ed
14359     89/<- %edx 4/r32/esp
14360     (flush _test-output-buffered-file)
14361     (flush _test-error-buffered-file)
14362 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14368     # check output
14369     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-non-addr: output should be empty")
14370     (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")
14371     # check that stop(1) was called
14372     (check-ints-equal *(edx+4) 2 "F - test-copy-object-non-addr: exit status")
14373     # don't restore from ebp
14374     81 0/subop/add %esp 8/imm32
14375     # . epilogue
14376     5d/pop-to-ebp
14377     c3/return
14378 
14379 test-copy-object-non-equal:
14380     # . prologue
14381     55/push-ebp
14382     89/<- %ebp 4/r32/esp
14383     # setup
14384     (clear-stream _test-input-stream)
14385     (clear-stream $_test-input-buffered-file->buffer)
14386     (clear-stream _test-output-stream)
14387     (clear-stream $_test-output-buffered-file->buffer)
14388     (clear-stream _test-error-stream)
14389     (clear-stream $_test-error-buffered-file->buffer)
14390     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14391     68/push 0/imm32
14392     68/push 0/imm32
14393     89/<- %edx 4/r32/esp
14394     (tailor-exit-descriptor %edx 0x10)
14395     #
14396     (write _test-input-stream "fn foo {\n")
14397     (write _test-input-stream "  var x: (addr int)\n")
14398     (write _test-input-stream "  var y: (addr boolean)\n")
14399     (write _test-input-stream "  copy-object y, x\n")
14400     (write _test-input-stream "}\n")
14401     # convert
14402     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14403     # registers except esp clobbered at this point
14404     # restore ed
14405     89/<- %edx 4/r32/esp
14406     (flush _test-output-buffered-file)
14407     (flush _test-error-buffered-file)
14408 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14414     # check output
14415     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-non-equal: output should be empty")
14416     (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")
14417     # check that stop(1) was called
14418     (check-ints-equal *(edx+4) 2 "F - test-copy-object-non-equal: exit status")
14419     # don't restore from ebp
14420     81 0/subop/add %esp 8/imm32
14421     # . epilogue
14422     5d/pop-to-ebp
14423     c3/return
14424 
14425 test-allocate-with-no-inout:
14426     # . prologue
14427     55/push-ebp
14428     89/<- %ebp 4/r32/esp
14429     # setup
14430     (clear-stream _test-input-stream)
14431     (clear-stream $_test-input-buffered-file->buffer)
14432     (clear-stream _test-output-stream)
14433     (clear-stream $_test-output-buffered-file->buffer)
14434     (clear-stream _test-error-stream)
14435     (clear-stream $_test-error-buffered-file->buffer)
14436     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14437     68/push 0/imm32
14438     68/push 0/imm32
14439     89/<- %edx 4/r32/esp
14440     (tailor-exit-descriptor %edx 0x10)
14441     #
14442     (write _test-input-stream "fn foo {\n")
14443     (write _test-input-stream "  allocate\n")
14444     (write _test-input-stream "}\n")
14445     # convert
14446     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14447     # registers except esp clobbered at this point
14448     # restore ed
14449     89/<- %edx 4/r32/esp
14450     (flush _test-output-buffered-file)
14451     (flush _test-error-buffered-file)
14452 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14458     # check output
14459     (check-stream-equal _test-output-stream  ""  "F - test-allocate-with-no-inout: output should be empty")
14460     (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")
14461     # check that stop(1) was called
14462     (check-ints-equal *(edx+4) 2 "F - test-allocate-with-no-inout: exit status")
14463     # don't restore from ebp
14464     81 0/subop/add %esp 8/imm32
14465     # . epilogue
14466     5d/pop-to-ebp
14467     c3/return
14468 
14469 test-allocate-with-too-many-inouts:
14470     # . prologue
14471     55/push-ebp
14472     89/<- %ebp 4/r32/esp
14473     # setup
14474     (clear-stream _test-input-stream)
14475     (clear-stream $_test-input-buffered-file->buffer)
14476     (clear-stream _test-output-stream)
14477     (clear-stream $_test-output-buffered-file->buffer)
14478     (clear-stream _test-error-stream)
14479     (clear-stream $_test-error-buffered-file->buffer)
14480     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14481     68/push 0/imm32
14482     68/push 0/imm32
14483     89/<- %edx 4/r32/esp
14484     (tailor-exit-descriptor %edx 0x10)
14485     #
14486     (write _test-input-stream "fn foo {\n")
14487     (write _test-input-stream "  var x: (addr handle int)\n")
14488     (write _test-input-stream "  allocate x, 0\n")
14489     (write _test-input-stream "}\n")
14490     # convert
14491     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14492     # registers except esp clobbered at this point
14493     # restore ed
14494     89/<- %edx 4/r32/esp
14495     (flush _test-output-buffered-file)
14496     (flush _test-error-buffered-file)
14497 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14503     # check output
14504     (check-stream-equal _test-output-stream  ""  "F - test-allocate-with-too-many-inouts: output should be empty")
14505     (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")
14506     # check that stop(1) was called
14507     (check-ints-equal *(edx+4) 2 "F - test-allocate-with-too-many-inouts: exit status")
14508     # don't restore from ebp
14509     81 0/subop/add %esp 8/imm32
14510     # . epilogue
14511     5d/pop-to-ebp
14512     c3/return
14513 
14514 test-allocate-with-output:
14515     # . prologue
14516     55/push-ebp
14517     89/<- %ebp 4/r32/esp
14518     # setup
14519     (clear-stream _test-input-stream)
14520     (clear-stream $_test-input-buffered-file->buffer)
14521     (clear-stream _test-output-stream)
14522     (clear-stream $_test-output-buffered-file->buffer)
14523     (clear-stream _test-error-stream)
14524     (clear-stream $_test-error-buffered-file->buffer)
14525     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14526     68/push 0/imm32
14527     68/push 0/imm32
14528     89/<- %edx 4/r32/esp
14529     (tailor-exit-descriptor %edx 0x10)
14530     #
14531     (write _test-input-stream "fn foo {\n")
14532     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
14533     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
14534     (write _test-input-stream "  x <- allocate y\n")
14535     (write _test-input-stream "}\n")
14536     # convert
14537     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14538     # registers except esp clobbered at this point
14539     # restore ed
14540     89/<- %edx 4/r32/esp
14541     (flush _test-output-buffered-file)
14542     (flush _test-error-buffered-file)
14543 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14549     # check output
14550     (check-stream-equal _test-output-stream  ""  "F - test-allocate-with-output: output should be empty")
14551     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'allocate' must not have any outputs"  "F - test-allocate-with-output: error message")
14552     # check that stop(1) was called
14553     (check-ints-equal *(edx+4) 2 "F - test-allocate-with-output: exit status")
14554     # don't restore from ebp
14555     81 0/subop/add %esp 8/imm32
14556     # . epilogue
14557     5d/pop-to-ebp
14558     c3/return
14559 
14560 test-allocate-non-addr:
14561     # . prologue
14562     55/push-ebp
14563     89/<- %ebp 4/r32/esp
14564     # setup
14565     (clear-stream _test-input-stream)
14566     (clear-stream $_test-input-buffered-file->buffer)
14567     (clear-stream _test-output-stream)
14568     (clear-stream $_test-output-buffered-file->buffer)
14569     (clear-stream _test-error-stream)
14570     (clear-stream $_test-error-buffered-file->buffer)
14571     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14572     68/push 0/imm32
14573     68/push 0/imm32
14574     89/<- %edx 4/r32/esp
14575     (tailor-exit-descriptor %edx 0x10)
14576     #
14577     (write _test-input-stream "fn foo {\n")
14578     (write _test-input-stream "  var y: (handle int)\n")
14579     (write _test-input-stream "  allocate y\n")
14580     (write _test-input-stream "}\n")
14581     # convert
14582     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14583     # registers except esp clobbered at this point
14584     # restore ed
14585     89/<- %edx 4/r32/esp
14586     (flush _test-output-buffered-file)
14587     (flush _test-error-buffered-file)
14588 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14594     # check output
14595     (check-stream-equal _test-output-stream  ""  "F - test-allocate-non-addr: output must be empty")
14596     (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")
14597     # check that stop(1) was called
14598     (check-ints-equal *(edx+4) 2 "F - test-allocate-non-addr: exit status")
14599     # don't restore from ebp
14600     81 0/subop/add %esp 8/imm32
14601     # . epilogue
14602     5d/pop-to-ebp
14603     c3/return
14604 
14605 test-allocate-non-addr-handle:
14606     # . prologue
14607     55/push-ebp
14608     89/<- %ebp 4/r32/esp
14609     # setup
14610     (clear-stream _test-input-stream)
14611     (clear-stream $_test-input-buffered-file->buffer)
14612     (clear-stream _test-output-stream)
14613     (clear-stream $_test-output-buffered-file->buffer)
14614     (clear-stream _test-error-stream)
14615     (clear-stream $_test-error-buffered-file->buffer)
14616     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14617     68/push 0/imm32
14618     68/push 0/imm32
14619     89/<- %edx 4/r32/esp
14620     (tailor-exit-descriptor %edx 0x10)
14621     #
14622     (write _test-input-stream "fn foo {\n")
14623     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
14624     (write _test-input-stream "  allocate y\n")
14625     (write _test-input-stream "}\n")
14626     # convert
14627     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14628     # registers except esp clobbered at this point
14629     # restore ed
14630     89/<- %edx 4/r32/esp
14631     (flush _test-output-buffered-file)
14632     (flush _test-error-buffered-file)
14633 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14639     # check output
14640     (check-stream-equal _test-output-stream  ""  "F - test-allocate-non-addr-handle: output should be empty")
14641     (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")
14642     # check that stop(1) was called
14643     (check-ints-equal *(edx+4) 2 "F - test-allocate-non-addr-handle: exit status")
14644     # don't restore from ebp
14645     81 0/subop/add %esp 8/imm32
14646     # . epilogue
14647     5d/pop-to-ebp
14648     c3/return
14649 
14650 test-allocate-deref-address:
14651     # . prologue
14652     55/push-ebp
14653     89/<- %ebp 4/r32/esp
14654     # setup
14655     (clear-stream _test-input-stream)
14656     (clear-stream $_test-input-buffered-file->buffer)
14657     (clear-stream _test-output-stream)
14658     (clear-stream $_test-output-buffered-file->buffer)
14659     #
14660     (write _test-input-stream "fn foo {\n")
14661     (write _test-input-stream "  var y/ecx: (addr addr handle int) <- copy 0\n")
14662     (write _test-input-stream "  allocate *y\n")
14663     (write _test-input-stream "}\n")
14664     # convert
14665     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
14666     (flush _test-output-buffered-file)
14667     # no errors
14668     # . epilogue
14669     5d/pop-to-ebp
14670     c3/return
14671 
14672 test-populate-with-no-inout:
14673     # . prologue
14674     55/push-ebp
14675     89/<- %ebp 4/r32/esp
14676     # setup
14677     (clear-stream _test-input-stream)
14678     (clear-stream $_test-input-buffered-file->buffer)
14679     (clear-stream _test-output-stream)
14680     (clear-stream $_test-output-buffered-file->buffer)
14681     (clear-stream _test-error-stream)
14682     (clear-stream $_test-error-buffered-file->buffer)
14683     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14684     68/push 0/imm32
14685     68/push 0/imm32
14686     89/<- %edx 4/r32/esp
14687     (tailor-exit-descriptor %edx 0x10)
14688     #
14689     (write _test-input-stream "fn foo {\n")
14690     (write _test-input-stream "  populate\n")
14691     (write _test-input-stream "}\n")
14692     # convert
14693     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14694     # registers except esp clobbered at this point
14695     # restore ed
14696     89/<- %edx 4/r32/esp
14697     (flush _test-output-buffered-file)
14698     (flush _test-error-buffered-file)
14699 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14705     # check output
14706     (check-stream-equal _test-output-stream  ""  "F - test-populate-with-no-inout: output should be empty")
14707     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate' must have two inouts"  "F - test-populate-with-no-inout: error message")
14708     # check that stop(1) was called
14709     (check-ints-equal *(edx+4) 2 "F - test-populate-with-no-inout: exit status")
14710     # don't restore from ebp
14711     81 0/subop/add %esp 8/imm32
14712     # . epilogue
14713     5d/pop-to-ebp
14714     c3/return
14715 
14716 test-populate-with-too-many-inouts:
14717     # . prologue
14718     55/push-ebp
14719     89/<- %ebp 4/r32/esp
14720     # setup
14721     (clear-stream _test-input-stream)
14722     (clear-stream $_test-input-buffered-file->buffer)
14723     (clear-stream _test-output-stream)
14724     (clear-stream $_test-output-buffered-file->buffer)
14725     (clear-stream _test-error-stream)
14726     (clear-stream $_test-error-buffered-file->buffer)
14727     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14728     68/push 0/imm32
14729     68/push 0/imm32
14730     89/<- %edx 4/r32/esp
14731     (tailor-exit-descriptor %edx 0x10)
14732     #
14733     (write _test-input-stream "fn foo {\n")
14734     (write _test-input-stream "  var x: (addr handle int)\n")
14735     (write _test-input-stream "  populate x, 3, 0\n")
14736     (write _test-input-stream "}\n")
14737     # convert
14738     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14739     # registers except esp clobbered at this point
14740     # restore ed
14741     89/<- %edx 4/r32/esp
14742     (flush _test-output-buffered-file)
14743     (flush _test-error-buffered-file)
14744 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14750     # check output
14751     (check-stream-equal _test-output-stream  ""  "F - test-populate-with-too-many-inouts: output should be empty")
14752     (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")
14753     # check that stop(1) was called
14754     (check-ints-equal *(edx+4) 2 "F - test-populate-with-too-many-inouts: exit status")
14755     # don't restore from ebp
14756     81 0/subop/add %esp 8/imm32
14757     # . epilogue
14758     5d/pop-to-ebp
14759     c3/return
14760 
14761 test-populate-with-output:
14762     # . prologue
14763     55/push-ebp
14764     89/<- %ebp 4/r32/esp
14765     # setup
14766     (clear-stream _test-input-stream)
14767     (clear-stream $_test-input-buffered-file->buffer)
14768     (clear-stream _test-output-stream)
14769     (clear-stream $_test-output-buffered-file->buffer)
14770     (clear-stream _test-error-stream)
14771     (clear-stream $_test-error-buffered-file->buffer)
14772     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14773     68/push 0/imm32
14774     68/push 0/imm32
14775     89/<- %edx 4/r32/esp
14776     (tailor-exit-descriptor %edx 0x10)
14777     #
14778     (write _test-input-stream "fn foo {\n")
14779     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
14780     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
14781     (write _test-input-stream "  x <- populate y\n")
14782     (write _test-input-stream "}\n")
14783     # convert
14784     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14785     # registers except esp clobbered at this point
14786     # restore ed
14787     89/<- %edx 4/r32/esp
14788     (flush _test-output-buffered-file)
14789     (flush _test-error-buffered-file)
14790 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14796     # check output
14797     (check-stream-equal _test-output-stream  ""  "F - test-populate-with-output: output should be empty")
14798     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate' must not have any outputs"  "F - test-populate-with-output: error message")
14799     # check that stop(1) was called
14800     (check-ints-equal *(edx+4) 2 "F - test-populate-with-output: exit status")
14801     # don't restore from ebp
14802     81 0/subop/add %esp 8/imm32
14803     # . epilogue
14804     5d/pop-to-ebp
14805     c3/return
14806 
14807 test-populate-non-addr:
14808     # . prologue
14809     55/push-ebp
14810     89/<- %ebp 4/r32/esp
14811     # setup
14812     (clear-stream _test-input-stream)
14813     (clear-stream $_test-input-buffered-file->buffer)
14814     (clear-stream _test-output-stream)
14815     (clear-stream $_test-output-buffered-file->buffer)
14816     (clear-stream _test-error-stream)
14817     (clear-stream $_test-error-buffered-file->buffer)
14818     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14819     68/push 0/imm32
14820     68/push 0/imm32
14821     89/<- %edx 4/r32/esp
14822     (tailor-exit-descriptor %edx 0x10)
14823     #
14824     (write _test-input-stream "fn foo {\n")
14825     (write _test-input-stream "  var y: (handle int)\n")
14826     (write _test-input-stream "  populate y, 3\n")
14827     (write _test-input-stream "}\n")
14828     # convert
14829     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14830     # registers except esp clobbered at this point
14831     # restore ed
14832     89/<- %edx 4/r32/esp
14833     (flush _test-output-buffered-file)
14834     (flush _test-error-buffered-file)
14835 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14841     # check output
14842     (check-stream-equal _test-output-stream  ""  "F - test-populate-non-addr: output must be empty")
14843     (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")
14844     # check that stop(1) was called
14845     (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr: exit status")
14846     # don't restore from ebp
14847     81 0/subop/add %esp 8/imm32
14848     # . epilogue
14849     5d/pop-to-ebp
14850     c3/return
14851 
14852 test-populate-non-addr-handle:
14853     # . prologue
14854     55/push-ebp
14855     89/<- %ebp 4/r32/esp
14856     # setup
14857     (clear-stream _test-input-stream)
14858     (clear-stream $_test-input-buffered-file->buffer)
14859     (clear-stream _test-output-stream)
14860     (clear-stream $_test-output-buffered-file->buffer)
14861     (clear-stream _test-error-stream)
14862     (clear-stream $_test-error-buffered-file->buffer)
14863     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14864     68/push 0/imm32
14865     68/push 0/imm32
14866     89/<- %edx 4/r32/esp
14867     (tailor-exit-descriptor %edx 0x10)
14868     #
14869     (write _test-input-stream "fn foo {\n")
14870     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
14871     (write _test-input-stream "  populate y, 3\n")
14872     (write _test-input-stream "}\n")
14873     # convert
14874     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14875     # registers except esp clobbered at this point
14876     # restore ed
14877     89/<- %edx 4/r32/esp
14878     (flush _test-output-buffered-file)
14879     (flush _test-error-buffered-file)
14880 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14886     # check output
14887     (check-stream-equal _test-output-stream  ""  "F - test-populate-non-addr-handle: output should be empty")
14888     (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")
14889     # check that stop(1) was called
14890     (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr-handle: exit status")
14891     # don't restore from ebp
14892     81 0/subop/add %esp 8/imm32
14893     # . epilogue
14894     5d/pop-to-ebp
14895     c3/return
14896 
14897 test-populate-non-addr-handle-array:
14898     # . prologue
14899     55/push-ebp
14900     89/<- %ebp 4/r32/esp
14901     # setup
14902     (clear-stream _test-input-stream)
14903     (clear-stream $_test-input-buffered-file->buffer)
14904     (clear-stream _test-output-stream)
14905     (clear-stream $_test-output-buffered-file->buffer)
14906     (clear-stream _test-error-stream)
14907     (clear-stream $_test-error-buffered-file->buffer)
14908     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14909     68/push 0/imm32
14910     68/push 0/imm32
14911     89/<- %edx 4/r32/esp
14912     (tailor-exit-descriptor %edx 0x10)
14913     #
14914     (write _test-input-stream "fn foo {\n")
14915     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
14916     (write _test-input-stream "  populate y, 3\n")
14917     (write _test-input-stream "}\n")
14918     # convert
14919     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14920     # registers except esp clobbered at this point
14921     # restore ed
14922     89/<- %edx 4/r32/esp
14923     (flush _test-output-buffered-file)
14924     (flush _test-error-buffered-file)
14925 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14931     # check output
14932     (check-stream-equal _test-output-stream  ""  "F - test-populate-non-addr-handle-array: output should be empty")
14933     (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")
14934     # check that stop(1) was called
14935     (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr-handle-array: exit status")
14936     # don't restore from ebp
14937     81 0/subop/add %esp 8/imm32
14938     # . epilogue
14939     5d/pop-to-ebp
14940     c3/return
14941 
14942 test-populate-deref-address:
14943     # . prologue
14944     55/push-ebp
14945     89/<- %ebp 4/r32/esp
14946     # setup
14947     (clear-stream _test-input-stream)
14948     (clear-stream $_test-input-buffered-file->buffer)
14949     (clear-stream _test-output-stream)
14950     (clear-stream $_test-output-buffered-file->buffer)
14951     #
14952     (write _test-input-stream "fn foo {\n")
14953     (write _test-input-stream "  var y/ecx: (addr addr handle array int) <- copy 0\n")
14954     (write _test-input-stream "  populate *y, 3\n")
14955     (write _test-input-stream "}\n")
14956     # convert
14957     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
14958     (flush _test-output-buffered-file)
14959     # no errors
14960     # . epilogue
14961     5d/pop-to-ebp
14962     c3/return
14963 
14964 test-populate-stream-with-no-inout:
14965     # . prologue
14966     55/push-ebp
14967     89/<- %ebp 4/r32/esp
14968     # setup
14969     (clear-stream _test-input-stream)
14970     (clear-stream $_test-input-buffered-file->buffer)
14971     (clear-stream _test-output-stream)
14972     (clear-stream $_test-output-buffered-file->buffer)
14973     (clear-stream _test-error-stream)
14974     (clear-stream $_test-error-buffered-file->buffer)
14975     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14976     68/push 0/imm32
14977     68/push 0/imm32
14978     89/<- %edx 4/r32/esp
14979     (tailor-exit-descriptor %edx 0x10)
14980     #
14981     (write _test-input-stream "fn foo {\n")
14982     (write _test-input-stream "  populate-stream\n")
14983     (write _test-input-stream "}\n")
14984     # convert
14985     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14986     # registers except esp clobbered at this point
14987     # restore ed
14988     89/<- %edx 4/r32/esp
14989     (flush _test-output-buffered-file)
14990     (flush _test-error-buffered-file)
14991 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14997     # check output
14998     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-with-no-inout: output should be empty")
14999     (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")
15000     # check that stop(1) was called
15001     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-no-inout: exit status")
15002     # don't restore from ebp
15003     81 0/subop/add %esp 8/imm32
15004     # . epilogue
15005     5d/pop-to-ebp
15006     c3/return
15007 
15008 test-populate-stream-with-too-many-inouts:
15009     # . prologue
15010     55/push-ebp
15011     89/<- %ebp 4/r32/esp
15012     # setup
15013     (clear-stream _test-input-stream)
15014     (clear-stream $_test-input-buffered-file->buffer)
15015     (clear-stream _test-output-stream)
15016     (clear-stream $_test-output-buffered-file->buffer)
15017     (clear-stream _test-error-stream)
15018     (clear-stream $_test-error-buffered-file->buffer)
15019     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15020     68/push 0/imm32
15021     68/push 0/imm32
15022     89/<- %edx 4/r32/esp
15023     (tailor-exit-descriptor %edx 0x10)
15024     #
15025     (write _test-input-stream "fn foo {\n")
15026     (write _test-input-stream "  var x: (addr handle int)\n")
15027     (write _test-input-stream "  populate-stream x, 3, 0\n")
15028     (write _test-input-stream "}\n")
15029     # convert
15030     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15031     # registers except esp clobbered at this point
15032     # restore ed
15033     89/<- %edx 4/r32/esp
15034     (flush _test-output-buffered-file)
15035     (flush _test-error-buffered-file)
15036 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15042     # check output
15043     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-with-too-many-inouts: output should be empty")
15044     (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")
15045     # check that stop(1) was called
15046     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-too-many-inouts: exit status")
15047     # don't restore from ebp
15048     81 0/subop/add %esp 8/imm32
15049     # . epilogue
15050     5d/pop-to-ebp
15051     c3/return
15052 
15053 test-populate-stream-with-output:
15054     # . prologue
15055     55/push-ebp
15056     89/<- %ebp 4/r32/esp
15057     # setup
15058     (clear-stream _test-input-stream)
15059     (clear-stream $_test-input-buffered-file->buffer)
15060     (clear-stream _test-output-stream)
15061     (clear-stream $_test-output-buffered-file->buffer)
15062     (clear-stream _test-error-stream)
15063     (clear-stream $_test-error-buffered-file->buffer)
15064     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15065     68/push 0/imm32
15066     68/push 0/imm32
15067     89/<- %edx 4/r32/esp
15068     (tailor-exit-descriptor %edx 0x10)
15069     #
15070     (write _test-input-stream "fn foo {\n")
15071     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
15072     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
15073     (write _test-input-stream "  x <- populate-stream y\n")
15074     (write _test-input-stream "}\n")
15075     # convert
15076     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15077     # registers except esp clobbered at this point
15078     # restore ed
15079     89/<- %edx 4/r32/esp
15080     (flush _test-output-buffered-file)
15081     (flush _test-error-buffered-file)
15082 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15088     # check output
15089     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-with-output: output should be empty")
15090     (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")
15091     # check that stop(1) was called
15092     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-output: exit status")
15093     # don't restore from ebp
15094     81 0/subop/add %esp 8/imm32
15095     # . epilogue
15096     5d/pop-to-ebp
15097     c3/return
15098 
15099 test-populate-stream-non-addr:
15100     # . prologue
15101     55/push-ebp
15102     89/<- %ebp 4/r32/esp
15103     # setup
15104     (clear-stream _test-input-stream)
15105     (clear-stream $_test-input-buffered-file->buffer)
15106     (clear-stream _test-output-stream)
15107     (clear-stream $_test-output-buffered-file->buffer)
15108     (clear-stream _test-error-stream)
15109     (clear-stream $_test-error-buffered-file->buffer)
15110     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15111     68/push 0/imm32
15112     68/push 0/imm32
15113     89/<- %edx 4/r32/esp
15114     (tailor-exit-descriptor %edx 0x10)
15115     #
15116     (write _test-input-stream "fn foo {\n")
15117     (write _test-input-stream "  var y: (handle int)\n")
15118     (write _test-input-stream "  populate-stream y, 3\n")
15119     (write _test-input-stream "}\n")
15120     # convert
15121     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15122     # registers except esp clobbered at this point
15123     # restore ed
15124     89/<- %edx 4/r32/esp
15125     (flush _test-output-buffered-file)
15126     (flush _test-error-buffered-file)
15127 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15133     # check output
15134     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-non-addr: output must be empty")
15135     (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")
15136     # check that stop(1) was called
15137     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr: exit status")
15138     # don't restore from ebp
15139     81 0/subop/add %esp 8/imm32
15140     # . epilogue
15141     5d/pop-to-ebp
15142     c3/return
15143 
15144 test-populate-stream-non-addr-handle:
15145     # . prologue
15146     55/push-ebp
15147     89/<- %ebp 4/r32/esp
15148     # setup
15149     (clear-stream _test-input-stream)
15150     (clear-stream $_test-input-buffered-file->buffer)
15151     (clear-stream _test-output-stream)
15152     (clear-stream $_test-output-buffered-file->buffer)
15153     (clear-stream _test-error-stream)
15154     (clear-stream $_test-error-buffered-file->buffer)
15155     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15156     68/push 0/imm32
15157     68/push 0/imm32
15158     89/<- %edx 4/r32/esp
15159     (tailor-exit-descriptor %edx 0x10)
15160     #
15161     (write _test-input-stream "fn foo {\n")
15162     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
15163     (write _test-input-stream "  populate-stream y, 3\n")
15164     (write _test-input-stream "}\n")
15165     # convert
15166     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15167     # registers except esp clobbered at this point
15168     # restore ed
15169     89/<- %edx 4/r32/esp
15170     (flush _test-output-buffered-file)
15171     (flush _test-error-buffered-file)
15172 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15178     # check output
15179     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-non-addr-handle: output should be empty")
15180     (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")
15181     # check that stop(1) was called
15182     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr-handle: exit status")
15183     # don't restore from ebp
15184     81 0/subop/add %esp 8/imm32
15185     # . epilogue
15186     5d/pop-to-ebp
15187     c3/return
15188 
15189 test-populate-stream-non-addr-handle-stream:
15190     # . prologue
15191     55/push-ebp
15192     89/<- %ebp 4/r32/esp
15193     # setup
15194     (clear-stream _test-input-stream)
15195     (clear-stream $_test-input-buffered-file->buffer)
15196     (clear-stream _test-output-stream)
15197     (clear-stream $_test-output-buffered-file->buffer)
15198     (clear-stream _test-error-stream)
15199     (clear-stream $_test-error-buffered-file->buffer)
15200     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15201     68/push 0/imm32
15202     68/push 0/imm32
15203     89/<- %edx 4/r32/esp
15204     (tailor-exit-descriptor %edx 0x10)
15205     #
15206     (write _test-input-stream "fn foo {\n")
15207     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
15208     (write _test-input-stream "  populate-stream y, 3\n")
15209     (write _test-input-stream "}\n")
15210     # convert
15211     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15212     # registers except esp clobbered at this point
15213     # restore ed
15214     89/<- %edx 4/r32/esp
15215     (flush _test-output-buffered-file)
15216     (flush _test-error-buffered-file)
15217 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15223     # check output
15224     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-non-addr-handle-stream: output should be empty")
15225     (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")
15226     # check that stop(1) was called
15227     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr-handle-stream: exit status")
15228     # don't restore from ebp
15229     81 0/subop/add %esp 8/imm32
15230     # . epilogue
15231     5d/pop-to-ebp
15232     c3/return
15233 
15234 test-populate-stream-deref-address:
15235     # . prologue
15236     55/push-ebp
15237     89/<- %ebp 4/r32/esp
15238     # setup
15239     (clear-stream _test-input-stream)
15240     (clear-stream $_test-input-buffered-file->buffer)
15241     (clear-stream _test-output-stream)
15242     (clear-stream $_test-output-buffered-file->buffer)
15243     #
15244     (write _test-input-stream "fn foo {\n")
15245     (write _test-input-stream "  var y/ecx: (addr addr handle stream int) <- copy 0\n")
15246     (write _test-input-stream "  populate-stream *y, 3\n")
15247     (write _test-input-stream "}\n")
15248     # convert
15249     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
15250     (flush _test-output-buffered-file)
15251     # no errors
15252     # . epilogue
15253     5d/pop-to-ebp
15254     c3/return
15255 
15256 test-convert-with-no-inout:
15257     # . prologue
15258     55/push-ebp
15259     89/<- %ebp 4/r32/esp
15260     # setup
15261     (clear-stream _test-input-stream)
15262     (clear-stream $_test-input-buffered-file->buffer)
15263     (clear-stream _test-output-stream)
15264     (clear-stream $_test-output-buffered-file->buffer)
15265     (clear-stream _test-error-stream)
15266     (clear-stream $_test-error-buffered-file->buffer)
15267     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15268     68/push 0/imm32
15269     68/push 0/imm32
15270     89/<- %edx 4/r32/esp
15271     (tailor-exit-descriptor %edx 0x10)
15272     #
15273     (write _test-input-stream "fn foo {\n")
15274     (write _test-input-stream "  var x/eax: int <- convert\n")
15275     (write _test-input-stream "}\n")
15276     # convert
15277     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15278     # registers except esp clobbered at this point
15279     # restore ed
15280     89/<- %edx 4/r32/esp
15281     (flush _test-output-buffered-file)
15282     (flush _test-error-buffered-file)
15283 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15289     # check output
15290     (check-stream-equal _test-output-stream  ""  "F - test-convert-with-no-inout: output should be empty")
15291     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'convert' expects an inout"  "F - test-convert-with-no-inout: error message")
15292     # check that stop(1) was called
15293     (check-ints-equal *(edx+4) 2 "F - test-convert-with-no-inout: exit status")
15294     # don't restore from ebp
15295     81 0/subop/add %esp 8/imm32
15296     # . epilogue
15297     5d/pop-to-ebp
15298     c3/return
15299 
15300 test-convert-with-multiple-inouts:
15301     # . prologue
15302     55/push-ebp
15303     89/<- %ebp 4/r32/esp
15304     # setup
15305     (clear-stream _test-input-stream)
15306     (clear-stream $_test-input-buffered-file->buffer)
15307     (clear-stream _test-output-stream)
15308     (clear-stream $_test-output-buffered-file->buffer)
15309     (clear-stream _test-error-stream)
15310     (clear-stream $_test-error-buffered-file->buffer)
15311     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15312     68/push 0/imm32
15313     68/push 0/imm32
15314     89/<- %edx 4/r32/esp
15315     (tailor-exit-descriptor %edx 0x10)
15316     #
15317     (write _test-input-stream "fn foo {\n")
15318     (write _test-input-stream "  var x/eax: int <- convert 0, 0\n")
15319     (write _test-input-stream "}\n")
15320     # convert
15321     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15322     # registers except esp clobbered at this point
15323     # restore ed
15324     89/<- %edx 4/r32/esp
15325     (flush _test-output-buffered-file)
15326     (flush _test-error-buffered-file)
15327 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15333     # check output
15334     (check-stream-equal _test-output-stream  ""  "F - test-convert-with-multiple-inouts: output should be empty")
15335     (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")
15336     # check that stop(1) was called
15337     (check-ints-equal *(edx+4) 2 "F - test-convert-with-multiple-inouts: exit status")
15338     # don't restore from ebp
15339     81 0/subop/add %esp 8/imm32
15340     # . epilogue
15341     5d/pop-to-ebp
15342     c3/return
15343 
15344 test-convert-with-no-output:
15345     # . prologue
15346     55/push-ebp
15347     89/<- %ebp 4/r32/esp
15348     # setup
15349     (clear-stream _test-input-stream)
15350     (clear-stream $_test-input-buffered-file->buffer)
15351     (clear-stream _test-output-stream)
15352     (clear-stream $_test-output-buffered-file->buffer)
15353     (clear-stream _test-error-stream)
15354     (clear-stream $_test-error-buffered-file->buffer)
15355     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15356     68/push 0/imm32
15357     68/push 0/imm32
15358     89/<- %edx 4/r32/esp
15359     (tailor-exit-descriptor %edx 0x10)
15360     #
15361     (write _test-input-stream "fn foo {\n")
15362     (write _test-input-stream "  convert 0\n")
15363     (write _test-input-stream "}\n")
15364     # convert
15365     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15366     # registers except esp clobbered at this point
15367     # restore ed
15368     89/<- %edx 4/r32/esp
15369     (flush _test-output-buffered-file)
15370     (flush _test-error-buffered-file)
15371 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15377     # check output
15378     (check-stream-equal _test-output-stream  ""  "F - test-convert-with-no-output: output should be empty")
15379     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'convert' expects an output"  "F - test-convert-with-no-output: error message")
15380     # check that stop(1) was called
15381     (check-ints-equal *(edx+4) 2 "F - test-convert-with-no-output: exit status")
15382     # don't restore from ebp
15383     81 0/subop/add %esp 8/imm32
15384     # . epilogue
15385     5d/pop-to-ebp
15386     c3/return
15387 
15388 test-convert-with-multiple-outputs:
15389     # . prologue
15390     55/push-ebp
15391     89/<- %ebp 4/r32/esp
15392     # setup
15393     (clear-stream _test-input-stream)
15394     (clear-stream $_test-input-buffered-file->buffer)
15395     (clear-stream _test-output-stream)
15396     (clear-stream $_test-output-buffered-file->buffer)
15397     (clear-stream _test-error-stream)
15398     (clear-stream $_test-error-buffered-file->buffer)
15399     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15400     68/push 0/imm32
15401     68/push 0/imm32
15402     89/<- %edx 4/r32/esp
15403     (tailor-exit-descriptor %edx 0x10)
15404     #
15405     (write _test-input-stream "fn foo {\n")
15406     (write _test-input-stream "  var x/eax: int <- copy 0\n")
15407     (write _test-input-stream "  var y/ecx: int <- copy 0\n")
15408     (write _test-input-stream "  x, y <- convert 0\n")
15409     (write _test-input-stream "}\n")
15410     # convert
15411     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15412     # registers except esp clobbered at this point
15413     # restore ed
15414     89/<- %edx 4/r32/esp
15415     (flush _test-output-buffered-file)
15416     (flush _test-error-buffered-file)
15417 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15423     # check output
15424     (check-stream-equal _test-output-stream  ""  "F - test-convert-with-multiple-outputs: output should be empty")
15425     (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")
15426     # check that stop(1) was called
15427     (check-ints-equal *(edx+4) 2 "F - test-convert-with-multiple-outputs: exit status")
15428     # don't restore from ebp
15429     81 0/subop/add %esp 8/imm32
15430     # . epilogue
15431     5d/pop-to-ebp
15432     c3/return
15433 
15434 test-convert-deref-address:
15435     # . prologue
15436     55/push-ebp
15437     89/<- %ebp 4/r32/esp
15438     # setup
15439     (clear-stream _test-input-stream)
15440     (clear-stream $_test-input-buffered-file->buffer)
15441     (clear-stream _test-output-stream)
15442     (clear-stream $_test-output-buffered-file->buffer)
15443     #
15444     (write _test-input-stream "fn foo {\n")
15445     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
15446     (write _test-input-stream "  var y/xmm4: float <- convert *x\n")
15447     (write _test-input-stream "}\n")
15448     # convert
15449     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
15450     (flush _test-output-buffered-file)
15451     # no errors
15452     # . epilogue
15453     5d/pop-to-ebp
15454     c3/return
15455 
15456 test-convert-to-non-register:
15457     # . prologue
15458     55/push-ebp
15459     89/<- %ebp 4/r32/esp
15460     # setup
15461     (clear-stream _test-input-stream)
15462     (clear-stream $_test-input-buffered-file->buffer)
15463     (clear-stream _test-output-stream)
15464     (clear-stream $_test-output-buffered-file->buffer)
15465     (clear-stream _test-error-stream)
15466     (clear-stream $_test-error-buffered-file->buffer)
15467     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15468     68/push 0/imm32
15469     68/push 0/imm32
15470     89/<- %edx 4/r32/esp
15471     (tailor-exit-descriptor %edx 0x10)
15472     #
15473     (write _test-input-stream "fn foo {\n")
15474     (write _test-input-stream "  var x: float\n")
15475     (write _test-input-stream "  var y: int\n")
15476     (write _test-input-stream "  x <- convert y\n")
15477     (write _test-input-stream "}\n")
15478     # convert
15479     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15480     # registers except esp clobbered at this point
15481     # restore ed
15482     89/<- %edx 4/r32/esp
15483     (flush _test-output-buffered-file)
15484     (flush _test-error-buffered-file)
15485 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15491     # check output
15492     (check-stream-equal _test-output-stream  ""  "F - test-convert-to-non-register: output should be empty")
15493     (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")
15494     # check that stop(1) was called
15495     (check-ints-equal *(edx+4) 2 "F - test-convert-to-non-register: exit status")
15496     # don't restore from ebp
15497     81 0/subop/add %esp 8/imm32
15498     # . epilogue
15499     5d/pop-to-ebp
15500     c3/return
15501 
15502 test-convert-invalid-inout-type:
15503     # . prologue
15504     55/push-ebp
15505     89/<- %ebp 4/r32/esp
15506     # setup
15507     (clear-stream _test-input-stream)
15508     (clear-stream $_test-input-buffered-file->buffer)
15509     (clear-stream _test-output-stream)
15510     (clear-stream $_test-output-buffered-file->buffer)
15511     (clear-stream _test-error-stream)
15512     (clear-stream $_test-error-buffered-file->buffer)
15513     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15514     68/push 0/imm32
15515     68/push 0/imm32
15516     89/<- %edx 4/r32/esp
15517     (tailor-exit-descriptor %edx 0x10)
15518     #
15519     (write _test-input-stream "fn foo {\n")
15520     (write _test-input-stream "  var x: boolean\n")
15521     (write _test-input-stream "  var y/xmm1: float <- convert x\n")
15522     (write _test-input-stream "}\n")
15523     # convert
15524     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15525     # registers except esp clobbered at this point
15526     # restore ed
15527     89/<- %edx 4/r32/esp
15528     (flush _test-output-buffered-file)
15529     (flush _test-error-buffered-file)
15530 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15536     # check output
15537     (check-stream-equal _test-output-stream  ""  "F - test-convert-invalid-inout-type: output should be empty")
15538     (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")
15539     # check that stop(1) was called
15540     (check-ints-equal *(edx+4) 2 "F - test-convert-invalid-inout-type: exit status")
15541     # don't restore from ebp
15542     81 0/subop/add %esp 8/imm32
15543     # . epilogue
15544     5d/pop-to-ebp
15545     c3/return
15546 
15547 test-convert-invalid-output-type:
15548     # . prologue
15549     55/push-ebp
15550     89/<- %ebp 4/r32/esp
15551     # setup
15552     (clear-stream _test-input-stream)
15553     (clear-stream $_test-input-buffered-file->buffer)
15554     (clear-stream _test-output-stream)
15555     (clear-stream $_test-output-buffered-file->buffer)
15556     (clear-stream _test-error-stream)
15557     (clear-stream $_test-error-buffered-file->buffer)
15558     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15559     68/push 0/imm32
15560     68/push 0/imm32
15561     89/<- %edx 4/r32/esp
15562     (tailor-exit-descriptor %edx 0x10)
15563     #
15564     (write _test-input-stream "fn foo {\n")
15565     (write _test-input-stream "  var x: float\n")
15566     (write _test-input-stream "  var y/eax: boolean <- convert x\n")
15567     (write _test-input-stream "}\n")
15568     # convert
15569     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15570     # registers except esp clobbered at this point
15571     # restore ed
15572     89/<- %edx 4/r32/esp
15573     (flush _test-output-buffered-file)
15574     (flush _test-error-buffered-file)
15575 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15581     # check output
15582     (check-stream-equal _test-output-stream  ""  "F - test-convert-invalid-output-type: output should be empty")
15583     (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")
15584     # check that stop(1) was called
15585     (check-ints-equal *(edx+4) 2 "F - test-convert-invalid-output-type: exit status")
15586     # don't restore from ebp
15587     81 0/subop/add %esp 8/imm32
15588     # . epilogue
15589     5d/pop-to-ebp
15590     c3/return
15591 
15592 test-convert-int-to-int:
15593     # . prologue
15594     55/push-ebp
15595     89/<- %ebp 4/r32/esp
15596     # setup
15597     (clear-stream _test-input-stream)
15598     (clear-stream $_test-input-buffered-file->buffer)
15599     (clear-stream _test-output-stream)
15600     (clear-stream $_test-output-buffered-file->buffer)
15601     (clear-stream _test-error-stream)
15602     (clear-stream $_test-error-buffered-file->buffer)
15603     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15604     68/push 0/imm32
15605     68/push 0/imm32
15606     89/<- %edx 4/r32/esp
15607     (tailor-exit-descriptor %edx 0x10)
15608     #
15609     (write _test-input-stream "fn foo {\n")
15610     (write _test-input-stream "  var x: int\n")
15611     (write _test-input-stream "  var y/eax: int <- convert x\n")
15612     (write _test-input-stream "}\n")
15613     # convert
15614     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15615     # registers except esp clobbered at this point
15616     # restore ed
15617     89/<- %edx 4/r32/esp
15618     (flush _test-output-buffered-file)
15619     (flush _test-error-buffered-file)
15620 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15626     # check output
15627     (check-stream-equal _test-output-stream  ""  "F - test-convert-int-to-int: output should be empty")
15628     (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")
15629     # check that stop(1) was called
15630     (check-ints-equal *(edx+4) 2 "F - test-convert-int-to-int: exit status")
15631     # don't restore from ebp
15632     81 0/subop/add %esp 8/imm32
15633     # . epilogue
15634     5d/pop-to-ebp
15635     c3/return
15636 
15637 test-convert-float-to-float:
15638     # . prologue
15639     55/push-ebp
15640     89/<- %ebp 4/r32/esp
15641     # setup
15642     (clear-stream _test-input-stream)
15643     (clear-stream $_test-input-buffered-file->buffer)
15644     (clear-stream _test-output-stream)
15645     (clear-stream $_test-output-buffered-file->buffer)
15646     (clear-stream _test-error-stream)
15647     (clear-stream $_test-error-buffered-file->buffer)
15648     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15649     68/push 0/imm32
15650     68/push 0/imm32
15651     89/<- %edx 4/r32/esp
15652     (tailor-exit-descriptor %edx 0x10)
15653     #
15654     (write _test-input-stream "fn foo {\n")
15655     (write _test-input-stream "  var x: float\n")
15656     (write _test-input-stream "  var y/xmm6: float <- convert x\n")
15657     (write _test-input-stream "}\n")
15658     # convert
15659     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15660     # registers except esp clobbered at this point
15661     # restore ed
15662     89/<- %edx 4/r32/esp
15663     (flush _test-output-buffered-file)
15664     (flush _test-error-buffered-file)
15665 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15671     # check output
15672     (check-stream-equal _test-output-stream  ""  "F - test-convert-float-to-float: output should be empty")
15673     (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")
15674     # check that stop(1) was called
15675     (check-ints-equal *(edx+4) 2 "F - test-convert-float-to-float: exit status")
15676     # don't restore from ebp
15677     81 0/subop/add %esp 8/imm32
15678     # . epilogue
15679     5d/pop-to-ebp
15680     c3/return
15681 
15682 #######################################################
15683 # Parsing
15684 #######################################################
15685 
15686 == data
15687 
15688 # Global state added to each var record when parsing a function
15689 Next-block-index:  # (addr int)
15690     1/imm32
15691 
15692 Curr-block-depth:  # (addr int)
15693     1/imm32
15694 
15695 == code
15696 
15697 parse-mu:  # in: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
15698     # pseudocode
15699     #   var curr-function: (addr handle function) = Program->functions
15700     #   var curr-signature: (addr handle function) = Program->signatures
15701     #   var curr-type: (addr handle typeinfo) = Program->types
15702     #   var line: (stream byte 512)
15703     #   var word-slice: slice
15704     #   while true                                  # line loop
15705     #     clear-stream(line)
15706     #     read-line-buffered(in, line)
15707     #     if (line->write == 0) break               # end of file
15708     #     word-slice = next-mu-token(line)
15709     #     if slice-empty?(word-slice)               # end of line
15710     #       continue
15711     #     else if slice-starts-with?(word-slice, "#")  # comment
15712     #       continue                                # end of line
15713     #     else if slice-equal?(word-slice, "fn")
15714     #       var new-function: (handle function) = allocate(function)
15715     #       var vars: (stack live-var 256)
15716     #       populate-mu-function-header(line, new-function, vars)
15717     #       populate-mu-function-body(in, new-function, vars)
15718     #       assert(vars->top == 0)
15719     #       *curr-function = new-function
15720     #       curr-function = &new-function->next
15721     #     else if slice-equal?(word-slice, "sig")
15722     #       var new-function: (handle function) = allocate(function)
15723     #       populate-mu-function-signature(line, new-function)
15724     #       *curr-signature = new-function
15725     #       curr-signature = &new-function->next
15726     #     else if slice-equal?(word-slice, "type")
15727     #       word-slice = next-mu-token(line)
15728     #       type-id = pos-or-insert-slice(Type-id, word-slice)
15729     #       var new-type: (handle typeinfo) = find-or-create-typeinfo(type-id)
15730     #       assert(next-word(line) == "{")
15731     #       populate-mu-type(in, new-type)
15732     #     else
15733     #       abort()
15734     #
15735     # . prologue
15736     55/push-ebp
15737     89/<- %ebp 4/r32/esp
15738     # var curr-signature: (addr handle function) at *(ebp-4)
15739     68/push _Program-signatures/imm32
15740     # . save registers
15741     50/push-eax
15742     51/push-ecx
15743     52/push-edx
15744     53/push-ebx
15745     56/push-esi
15746     57/push-edi
15747     # var line/ecx: (stream byte 512)
15748     81 5/subop/subtract %esp 0x200/imm32
15749     68/push 0x200/imm32/size
15750     68/push 0/imm32/read
15751     68/push 0/imm32/write
15752     89/<- %ecx 4/r32/esp
15753     # var word-slice/edx: slice
15754     68/push 0/imm32/end
15755     68/push 0/imm32/start
15756     89/<- %edx 4/r32/esp
15757     # var curr-function/edi: (addr handle function)
15758     bf/copy-to-edi _Program-functions/imm32
15759     # var vars/ebx: (stack live-var 256)
15760     81 5/subop/subtract %esp 0xc00/imm32
15761     68/push 0xc00/imm32/size
15762     68/push 0/imm32/top
15763     89/<- %ebx 4/r32/esp
15764     {
15765 $parse-mu:line-loop:
15766       (clear-stream %ecx)
15767       (read-line-buffered *(ebp+8) %ecx)
15768       # if (line->write == 0) break
15769       81 7/subop/compare *ecx 0/imm32
15770       0f 84/jump-if-= break/disp32
15771 +--  6 lines: #?       # dump line ------------------------------------------------------------------------------------------------------------------------------------------------------
15777       (next-mu-token %ecx %edx)
15778       # if slice-empty?(word-slice) continue
15779       (slice-empty? %edx)  # => eax
15780       3d/compare-eax-and 0/imm32/false
15781       0f 85/jump-if-!= loop/disp32
15782       # if (*word-slice->start == "#") continue
15783       # . eax = *word-slice->start
15784       8b/-> *edx 0/r32/eax
15785       8a/copy-byte *eax 0/r32/AL
15786       81 4/subop/and %eax 0xff/imm32
15787       # . if (eax == '#') continue
15788       3d/compare-eax-and 0x23/imm32/hash
15789       0f 84/jump-if-= loop/disp32
15790       # if (slice-equal?(word-slice, "fn")) parse a function
15791       {
15792 $parse-mu:fn:
15793         (slice-equal? %edx "fn")  # => eax
15794         3d/compare-eax-and 0/imm32/false
15795         0f 84/jump-if-= break/disp32
15796         # var new-function/esi: (handle function)
15797         68/push 0/imm32
15798         68/push 0/imm32
15799         89/<- %esi 4/r32/esp
15800         # populate-mu-function(line, in, vars, new-function)
15801         (allocate Heap *Function-size %esi)
15802         # var new-function-addr/eax: (addr function)
15803         (lookup *esi *(esi+4))  # => eax
15804         # initialize vars
15805         (clear-stack %ebx)
15806         #
15807         (populate-mu-function-header %ecx %eax %ebx *(ebp+0xc) *(ebp+0x10))
15808         (populate-mu-function-body *(ebp+8) %eax %ebx *(ebp+0xc) *(ebp+0x10))
15809         # *curr-function = new-function
15810         8b/-> *esi 0/r32/eax
15811         89/<- *edi 0/r32/eax
15812         8b/-> *(esi+4) 0/r32/eax
15813         89/<- *(edi+4) 0/r32/eax
15814         # curr-function = &new-function->next
15815         # . var tmp/eax: (addr function) = lookup(new-function)
15816         (lookup *esi *(esi+4))  # => eax
15817         # . curr-function = &tmp->next
15818         8d/copy-address *(eax+0x20) 7/r32/edi  # Function-next
15819         # reclaim new-function
15820         81 0/subop/add %esp 8/imm32
15821         #
15822         e9/jump $parse-mu:line-loop/disp32
15823       }
15824       # if (slice-equal?(word-slice, "sig")) parse a function signature
15825       # Function signatures are for providing types to SubX functions.
15826       {
15827 $parse-mu:sig:
15828         (slice-equal? %edx "sig")  # => eax
15829         3d/compare-eax-and 0/imm32/false
15830         0f 84/jump-if-= break/disp32
15831         # edi = curr-function
15832         57/push-edi
15833         8b/-> *(ebp-4) 7/r32/edi
15834         # var new-function/esi: (handle function)
15835         68/push 0/imm32
15836         68/push 0/imm32
15837         89/<- %esi 4/r32/esp
15838         # populate-mu-function(line, in, vars, new-function)
15839         (allocate Heap *Function-size %esi)
15840         # var new-function-addr/eax: (addr function)
15841         (lookup *esi *(esi+4))  # => eax
15842         #
15843         (populate-mu-function-signature %ecx %eax *(ebp+0xc) *(ebp+0x10))
15844         # *curr-signature = new-function
15845         8b/-> *esi 0/r32/eax
15846         89/<- *edi 0/r32/eax
15847         8b/-> *(esi+4) 0/r32/eax
15848         89/<- *(edi+4) 0/r32/eax
15849         # curr-signature = &new-function->next
15850         # . var tmp/eax: (addr function) = lookup(new-function)
15851         (lookup *esi *(esi+4))  # => eax
15852         # . curr-function = &tmp->next
15853         8d/copy-address *(eax+0x20) 7/r32/edi  # Function-next
15854         # reclaim new-function
15855         81 0/subop/add %esp 8/imm32
15856         # save curr-function
15857         89/<- *(ebp-4) 7/r32/edi
15858         # restore edi
15859         5f/pop-to-edi
15860         #
15861         e9/jump $parse-mu:line-loop/disp32
15862       }
15863       # if (slice-equal?(word-slice, "type")) parse a type (struct/record) definition
15864       {
15865 $parse-mu:type:
15866         (slice-equal? %edx "type")  # => eax
15867         3d/compare-eax-and 0/imm32
15868         0f 84/jump-if-= break/disp32
15869         (next-mu-token %ecx %edx)
15870         # var type-id/eax: int
15871         (pos-or-insert-slice Type-id %edx)  # => eax
15872         # spill
15873         51/push-ecx
15874         # var new-type/ecx: (handle typeinfo)
15875         68/push 0/imm32
15876         68/push 0/imm32
15877         89/<- %ecx 4/r32/esp
15878         (find-or-create-typeinfo %eax %ecx)
15879         #
15880         (lookup *ecx *(ecx+4))  # => eax
15881         # TODO: ensure that 'line' has nothing else but '{'
15882 #? (dump-typeinfos "=== aaa\n")
15883         (populate-mu-type *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10))  # => eax
15884 #? (dump-typeinfos "=== zzz\n")
15885         # reclaim new-type
15886         81 0/subop/add %esp 8/imm32
15887         # restore
15888         59/pop-to-ecx
15889         e9/jump $parse-mu:line-loop/disp32
15890       }
15891       # otherwise abort
15892       e9/jump $parse-mu:error1/disp32
15893     } # end line loop
15894 $parse-mu:end:
15895     # . reclaim locals
15896     81 0/subop/add %esp 0x20c/imm32  # line
15897     81 0/subop/add %esp 0xc08/imm32  # vars
15898     81 0/subop/add %esp 8/imm32
15899     # . restore registers
15900     5f/pop-to-edi
15901     5e/pop-to-esi
15902     5b/pop-to-ebx
15903     5a/pop-to-edx
15904     59/pop-to-ecx
15905     58/pop-to-eax
15906     # . reclaim local
15907     81 0/subop/add %esp 4/imm32
15908     # . epilogue
15909     89/<- %esp 5/r32/ebp
15910     5d/pop-to-ebp
15911     c3/return
15912 
15913 $parse-mu:error1:
15914     # error("unexpected top-level command: " word-slice "\n")
15915     (write-buffered *(ebp+0xc) "unexpected top-level command: ")
15916     (write-slice-buffered *(ebp+0xc) %edx)
15917     (write-buffered *(ebp+0xc) "\n")
15918     (flush *(ebp+0xc))
15919     (stop *(ebp+0x10) 1)
15920     # never gets here
15921 
15922 $parse-mu:error2:
15923     # error(vars->top " vars not reclaimed after fn '" new-function->name "'\n")
15924     (write-int32-hex-buffered *(ebp+0xc) *ebx)
15925     (write-buffered *(ebp+0xc) " vars not reclaimed after fn '")
15926     (write-slice-buffered *(ebp+0xc) *eax)  # Function-name
15927     (write-buffered *(ebp+0xc) "'\n")
15928     (flush *(ebp+0xc))
15929     (stop *(ebp+0x10) 1)
15930     # never gets here
15931 
15932 # scenarios considered:
15933 # ✗ fn foo  # no block
15934 # ✓ fn foo {
15935 # ✗ fn foo { {
15936 # ✗ fn foo { }
15937 # ✗ fn foo { } {
15938 # ✗ fn foo x {
15939 # ✗ fn foo x: {
15940 # ✓ fn foo x: int {
15941 # ✓ fn foo x: int {
15942 # ✓ fn foo x: int -> _/eax: int {
15943 # TODO:
15944 #   disallow outputs of type `(... addr ...)`
15945 #   disallow inputs of type `(... addr ... addr ...)`
15946 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)
15947     # pseudocode:
15948     #   var word-slice: slice
15949     #   next-mu-token(first-line, word-slice)
15950     #   if slice-empty?(word-slice) abort
15951     #   assert(word-slice not in '{' '}' '->')
15952     #   out->name = slice-to-string(word-slice)
15953     #   ## inouts
15954     #   while true
15955     #     word-slice = next-mu-token(first-line)
15956     #     if slice-empty?(word-slice) abort
15957     #     if (word-slice == '{') goto done
15958     #     if (word-slice == '->') break
15959     #     assert(word-slice != '}')
15960     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
15961     #     assert(v->register == null)
15962     #     # v->block-depth is implicitly 0
15963     #     out->inouts = append(v, out->inouts)
15964     #     push(vars, {v, false})
15965     #   ## outputs
15966     #   while true
15967     #     word-slice = next-mu-token(first-line)
15968     #     if slice-empty?(word-slice) abort
15969     #     if (word-slice == '{') break
15970     #     assert(word-slice not in '}' '->')
15971     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
15972     #     assert(v->register != null)
15973     #     assert(v->name == "_")
15974     #     out->outputs = append(v, out->outputs)
15975     #   done:
15976     #
15977     # . prologue
15978     55/push-ebp
15979     89/<- %ebp 4/r32/esp
15980     # . save registers
15981     50/push-eax
15982     51/push-ecx
15983     52/push-edx
15984     53/push-ebx
15985     57/push-edi
15986     # edi = out
15987     8b/-> *(ebp+0xc) 7/r32/edi
15988     # var word-slice/ecx: slice
15989     68/push 0/imm32/end
15990     68/push 0/imm32/start
15991     89/<- %ecx 4/r32/esp
15992     # var v/ebx: (handle var)
15993     68/push 0/imm32
15994     68/push 0/imm32
15995     89/<- %ebx 4/r32/esp
15996     # read function name
15997     (next-mu-token *(ebp+8) %ecx)
15998     # error checking
15999     # if slice-empty?(word-slice) abort
16000     (slice-empty? %ecx)  # => eax
16001     3d/compare-eax-and 0/imm32/false
16002     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
16003     # if (word-slice == '{') abort
16004     (slice-equal? %ecx "{")   # => eax
16005     3d/compare-eax-and 0/imm32/false
16006     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
16007     # if (word-slice == '->') abort
16008     (slice-equal? %ecx "->")   # => eax
16009     3d/compare-eax-and 0/imm32/false
16010     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
16011     # if (word-slice == '}') abort
16012     (slice-equal? %ecx "}")   # => eax
16013     3d/compare-eax-and 0/imm32/false
16014     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
16015     # if word-slice already defined, abort
16016     (function-exists? %ecx)  # => eax
16017     3d/compare-eax-and 0/imm32/false
16018     0f 85/jump-if-!= $populate-mu-function-header:error-duplicate/disp32
16019     #
16020     (slice-starts-with? %ecx "break")  # => eax
16021     3d/compare-eax-and 0/imm32/false
16022     0f 85/jump-if-!= $populate-mu-function-header:error-break/disp32
16023     (slice-starts-with? %ecx "loop")  # => eax
16024     3d/compare-eax-and 0/imm32/false
16025     0f 85/jump-if-!= $populate-mu-function-header:error-loop/disp32
16026     (slice-equal? %ecx "lookup")  # => eax
16027     3d/compare-eax-and 0/imm32/false
16028     0f 85/jump-if-!= $populate-mu-function-header:error-lookup/disp32
16029     # save function name
16030     (slice-to-string Heap %ecx %edi)  # Function-name
16031     # save function inouts
16032     {
16033 $populate-mu-function-header:check-for-inout:
16034       (next-mu-token *(ebp+8) %ecx)
16035       # if slice-empty?(word-slice) abort
16036       (slice-empty? %ecx)  # => eax
16037       3d/compare-eax-and 0/imm32/false
16038       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
16039       # if (word-slice == '{') goto done
16040       (slice-equal? %ecx "{")   # => eax
16041       3d/compare-eax-and 0/imm32/false
16042       0f 85/jump-if-!= $populate-mu-function-header:done/disp32
16043       # if (word-slice == '->') break
16044       (slice-equal? %ecx "->")   # => eax
16045       3d/compare-eax-and 0/imm32/false
16046       0f 85/jump-if-!= break/disp32
16047       # if (word-slice == '}') abort
16048       (slice-equal? %ecx "}")   # => eax
16049       3d/compare-eax-and 0/imm32/false
16050       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
16051       # v = parse-var-with-type(word-slice, first-line)
16052       (lookup *edi *(edi+4))  # Function-name Function-name => eax
16053       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x14) *(ebp+0x18))
16054       # if (v->register != null) abort
16055       # . eax: (addr var) = lookup(v)
16056       (lookup *ebx *(ebx+4))  # => eax
16057       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
16058       0f 85/jump-if-!= $populate-mu-function-header:error2/disp32
16059       # if function name is not "main"
16060       #    and v->type contains an 'addr' anywhere except the start, abort
16061       {
16062         (lookup *edi *(edi+4))  # Function-name Function-name => eax
16063         (string-equal? %eax "main")  # => eax
16064         3d/compare-eax-and 0/imm32/false
16065         75/jump-if-!= break/disp8
16066         (lookup *ebx *(ebx+4))  # => eax
16067         (addr-payload-contains-addr? %eax)  # => eax
16068         3d/compare-eax-and 0/imm32/false
16069         0f 85/jump-if-!= $populate-mu-function-header:error-nested-addr-inout/disp32
16070       }
16071       # v->block-depth is implicitly 0
16072       #
16073       # out->inouts = append(v, out->inouts)
16074       8d/copy-address *(edi+8) 0/r32/eax  # Function-inouts
16075       (append-list Heap  *ebx *(ebx+4)  *(edi+8) *(edi+0xc)  %eax)  # Function-inouts, Function-inouts
16076       # push(vars, {v, false})
16077       (push *(ebp+0x10) *ebx)
16078       (push *(ebp+0x10) *(ebx+4))
16079       (push *(ebp+0x10) 0)  # false
16080       #
16081       e9/jump loop/disp32
16082     }
16083     # save function outputs
16084     {
16085 $populate-mu-function-header:check-for-out:
16086       (next-mu-token *(ebp+8) %ecx)
16087       # if slice-empty?(word-slice) abort
16088       (slice-empty? %ecx)  # => eax
16089       3d/compare-eax-and 0/imm32/false
16090       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
16091       # if (word-slice == '{') break
16092       (slice-equal? %ecx "{")   # => eax
16093       3d/compare-eax-and 0/imm32/false
16094       0f 85/jump-if-!= break/disp32
16095       # if (word-slice == '->') abort
16096       (slice-equal? %ecx "->")   # => eax
16097       3d/compare-eax-and 0/imm32/false
16098       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
16099       # if (word-slice == '}') abort
16100       (slice-equal? %ecx "}")   # => eax
16101       3d/compare-eax-and 0/imm32/false
16102       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
16103       # v = parse-var-with-type(word-slice, first-line)
16104       (lookup *edi *(edi+4))  # Function-name Function-name => eax
16105       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x14) *(ebp+0x18))
16106       # assert(var->register != null)
16107       # . eax: (addr var) = lookup(v)
16108       (lookup *ebx *(ebx+4))  # => eax
16109       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
16110       0f 84/jump-if-= $populate-mu-function-header:error3/disp32
16111       # if (var->name != "_") abort
16112       (lookup *eax *(eax+4))  # Var-name Var-name => eax
16113       (string-equal? %eax "_")  # => eax
16114       3d/compare-eax-and 0/imm32/false
16115       0f 84/jump-if-= $populate-mu-function-header:error4/disp32
16116       # if v->type is an addr, abort
16117       (lookup *ebx *(ebx+4))  # => eax
16118       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
16119       (mu-addr-type? %eax)  # => eax
16120       3d/compare-eax-and 0/imm32/false
16121       0f 85/jump-if-!= $populate-mu-function-header:error-addr-output/disp32
16122       # out->outputs = append(v, out->outputs)
16123       8d/copy-address *(edi+0x10) 0/r32/eax  # Function-outputs
16124       (append-list Heap  *ebx *(ebx+4)  *(edi+0x10) *(edi+0x14)  %eax)  # Function-outputs, Function-outputs
16125       #
16126       e9/jump loop/disp32
16127     }
16128 $populate-mu-function-header:done:
16129     (check-no-tokens-left *(ebp+8))
16130 $populate-mu-function-header:end:
16131     # . reclaim locals
16132     81 0/subop/add %esp 0x10/imm32
16133     # . restore registers
16134     5f/pop-to-edi
16135     5b/pop-to-ebx
16136     5a/pop-to-edx
16137     59/pop-to-ecx
16138     58/pop-to-eax
16139     # . epilogue
16140     89/<- %esp 5/r32/ebp
16141     5d/pop-to-ebp
16142     c3/return
16143 
16144 $populate-mu-function-header:error1:
16145     # error("function header not in form 'fn <name> {'")
16146     (write-buffered *(ebp+0x14) "function header not in form 'fn <name> [inouts] [-> outputs] {' -- '")
16147     (flush *(ebp+0x14))
16148     (rewind-stream *(ebp+8))
16149     (write-stream-data *(ebp+0x14) *(ebp+8))
16150     (write-buffered *(ebp+0x14) "'\n")
16151     (flush *(ebp+0x14))
16152     (stop *(ebp+0x18) 1)
16153     # never gets here
16154 
16155 $populate-mu-function-header:error2:
16156     # error("fn " fn ": function inout '" var "' cannot be in a register")
16157     (write-buffered *(ebp+0x14) "fn ")
16158     50/push-eax
16159     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16160     (write-buffered *(ebp+0x14) %eax)
16161     58/pop-to-eax
16162     (write-buffered *(ebp+0x14) ": function inout '")
16163     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16164     (write-buffered *(ebp+0x14) %eax)
16165     (write-buffered *(ebp+0x14) "' cannot be in a register")
16166     (flush *(ebp+0x14))
16167     (stop *(ebp+0x18) 1)
16168     # never gets here
16169 
16170 $populate-mu-function-header:error3:
16171     # error("fn " fn ": function output '" var "' must be in a register")
16172     (write-buffered *(ebp+0x14) "fn ")
16173     50/push-eax
16174     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16175     (write-buffered *(ebp+0x14) %eax)
16176     58/pop-to-eax
16177     (write-buffered *(ebp+0x14) ": function output '")
16178     (lookup *ebx *(ebx+4))  # => eax
16179     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16180     (write-buffered *(ebp+0x14) %eax)
16181     (write-buffered *(ebp+0x14) "' must be in a register, in instruction '")
16182     (rewind-stream *(ebp+8))
16183     (write-stream-data *(ebp+0x14) *(ebp+8))
16184     (write-buffered *(ebp+0x14) "'\n")
16185     (flush *(ebp+0x14))
16186     (stop *(ebp+0x18) 1)
16187     # never gets here
16188 
16189 $populate-mu-function-header:error4:
16190     # error("fn " fn ": function outputs cannot be named; rename '" var "' in the header to '_'")
16191     (write-buffered *(ebp+0x14) "fn ")
16192     50/push-eax
16193     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16194     (write-buffered *(ebp+0x14) %eax)
16195     58/pop-to-eax
16196     (write-buffered *(ebp+0x14) ": function outputs cannot be named; rename '")
16197     (lookup *ebx *(ebx+4))  # => eax
16198     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16199     (write-buffered *(ebp+0x14) %eax)
16200     (write-buffered *(ebp+0x14) "' in the header to '_'\n")
16201     (flush *(ebp+0x14))
16202     (stop *(ebp+0x18) 1)
16203     # never gets here
16204 
16205 $populate-mu-function-header:error-duplicate:
16206     (write-buffered *(ebp+0x14) "fn ")
16207     (write-slice-buffered *(ebp+0x14) %ecx)
16208     (write-buffered *(ebp+0x14) " defined more than once\n")
16209     (flush *(ebp+0x14))
16210     (stop *(ebp+0x18) 1)
16211     # never gets here
16212 
16213 $populate-mu-function-header:error-break:
16214     (write-buffered *(ebp+0x14) "Sorry, I've reserved all function names starting with 'break' for now. Please contact mu@akkartik.com.\n")
16215     (flush *(ebp+0x14))
16216     (stop *(ebp+0x18) 1)
16217     # never gets here
16218 
16219 $populate-mu-function-header:error-loop:
16220     (write-buffered *(ebp+0x14) "Sorry, I've reserved all function names starting with 'loop' for now. Please contact mu@akkartik.com.\n")
16221     (flush *(ebp+0x14))
16222     (stop *(ebp+0x18) 1)
16223     # never gets here
16224 
16225 $populate-mu-function-header:error-lookup:
16226     (write-buffered *(ebp+0x14) "cannot define a function called 'lookup'\n")
16227     (flush *(ebp+0x14))
16228     (stop *(ebp+0x18) 1)
16229     # never gets here
16230 
16231 $populate-mu-function-header:error-addr-output:
16232     # error("fn " fn ": output cannot have an addr type; that could allow unsafe addresses to escape the function")
16233     (write-buffered *(ebp+0x14) "fn ")
16234     50/push-eax
16235     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16236     (write-buffered *(ebp+0x14) %eax)
16237     58/pop-to-eax
16238     (write-buffered *(ebp+0x14) ": output cannot have an addr type; that could allow unsafe addresses to escape the function\n")
16239     (flush *(ebp+0x14))
16240     (stop *(ebp+0x18) 1)
16241     # never gets here
16242 
16243 $populate-mu-function-header:error-nested-addr-inout:
16244     # 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")
16245     (write-buffered *(ebp+0x14) "fn ")
16246     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16247     (write-buffered *(ebp+0x14) %eax)
16248     (write-buffered *(ebp+0x14) ": inout '")
16249     (lookup *ebx *(ebx+4))  # => eax
16250     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16251     (write-buffered *(ebp+0x14) %eax)
16252     (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")
16253     (flush *(ebp+0x14))
16254     (stop *(ebp+0x18) 1)
16255     # never gets here
16256 
16257 # scenarios considered:
16258 # ✓ fn foo
16259 # ✗ fn foo {
16260 # ✓ fn foo x
16261 # ✓ fn foo x: int
16262 # ✓ fn foo x: int -> _/eax: int
16263 # TODO:
16264 #   disallow outputs of type `(... addr ...)`
16265 #   disallow inputs of type `(... addr ... addr ...)`
16266 populate-mu-function-signature:  # first-line: (addr stream byte), out: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
16267     # pseudocode:
16268     #   var word-slice: slice
16269     #   next-mu-token(first-line, word-slice)
16270     #   assert(word-slice not in '{' '}' '->')
16271     #   out->name = slice-to-string(word-slice)
16272     #   ## inouts
16273     #   while true
16274     #     word-slice = next-mu-token(first-line)
16275     #     if slice-empty?(word-slice) break
16276     #     if (word-slice == '->') break
16277     #     assert(word-slice not in '{' '}')
16278     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
16279     #     assert(v->register == null)
16280     #     # v->block-depth is implicitly 0
16281     #     out->inouts = append(v, out->inouts)
16282     #   ## outputs
16283     #   while true
16284     #     word-slice = next-mu-token(first-line)
16285     #     if slice-empty?(word-slice) break
16286     #     assert(word-slice not in '{' '}' '->')
16287     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
16288     #     assert(v->register != null)
16289     #     out->outputs = append(v, out->outputs)
16290     #
16291     # . prologue
16292     55/push-ebp
16293     89/<- %ebp 4/r32/esp
16294     # . save registers
16295     50/push-eax
16296     51/push-ecx
16297     52/push-edx
16298     53/push-ebx
16299     57/push-edi
16300     # edi = out
16301     8b/-> *(ebp+0xc) 7/r32/edi
16302     # var word-slice/ecx: slice
16303     68/push 0/imm32/end
16304     68/push 0/imm32/start
16305     89/<- %ecx 4/r32/esp
16306     # var v/ebx: (handle var)
16307     68/push 0/imm32
16308     68/push 0/imm32
16309     89/<- %ebx 4/r32/esp
16310     # read function name
16311     (next-mu-token *(ebp+8) %ecx)
16312     # error checking
16313     # if (word-slice == '{') abort
16314     (slice-equal? %ecx "{")   # => eax
16315     3d/compare-eax-and 0/imm32/false
16316     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
16317     # if (word-slice == '->') abort
16318     (slice-equal? %ecx "->")   # => eax
16319     3d/compare-eax-and 0/imm32/false
16320     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
16321     # if (word-slice == '}') abort
16322     (slice-equal? %ecx "}")   # => eax
16323     3d/compare-eax-and 0/imm32/false
16324     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
16325     # if word-slice already defined, abort
16326     (function-exists? %ecx)  # => eax
16327     3d/compare-eax-and 0/imm32/false
16328     0f 85/jump-if-!= $populate-mu-function-signature:error-duplicate/disp32
16329     #
16330     (slice-starts-with? %ecx "break")  # => eax
16331     3d/compare-eax-and 0/imm32/false
16332     0f 85/jump-if-!= $populate-mu-function-signature:error-break/disp32
16333     (slice-starts-with? %ecx "loop")  # => eax
16334     3d/compare-eax-and 0/imm32/false
16335     0f 85/jump-if-!= $populate-mu-function-signature:error-loop/disp32
16336     # save function name
16337     (slice-to-string Heap %ecx %edi)  # Function-name
16338     # save function inouts
16339     {
16340 $populate-mu-function-signature:check-for-inout:
16341       (next-mu-token *(ebp+8) %ecx)
16342       (slice-empty? %ecx)  # => eax
16343       3d/compare-eax-and 0/imm32/false
16344       0f 85/jump-if-!= break/disp32
16345       # if (word-slice == '->') break
16346       (slice-equal? %ecx "->")   # => eax
16347       3d/compare-eax-and 0/imm32/false
16348       0f 85/jump-if-!= break/disp32
16349       # if (word-slice == '{') abort
16350       (slice-equal? %ecx "{")   # => eax
16351       3d/compare-eax-and 0/imm32/false
16352       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
16353       # if (word-slice == '}') abort
16354       (slice-equal? %ecx "}")   # => eax
16355       3d/compare-eax-and 0/imm32/false
16356       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
16357       # v = parse-var-with-type(word-slice, first-line)
16358       (lookup *edi *(edi+4))  # Function-name Function-name => eax
16359       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x10) *(ebp+0x14))
16360       # if (v->register != null) abort
16361       # . eax: (addr var) = lookup(v)
16362       (lookup *ebx *(ebx+4))  # => eax
16363       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
16364       0f 85/jump-if-!= $populate-mu-function-signature:error2/disp32
16365       # if function name is not "main"
16366       #    and v->type contains an 'addr' anywhere except the start, abort
16367       {
16368         (lookup *edi *(edi+4))  # Function-name Function-name => eax
16369         (string-equal? %eax "main")  # => eax
16370         3d/compare-eax-and 0/imm32/false
16371         75/jump-if-!= break/disp8
16372         (lookup *ebx *(ebx+4))  # => eax
16373         (addr-payload-contains-addr? %eax)  # => eax
16374         3d/compare-eax-and 0/imm32/false
16375         0f 85/jump-if-!= $populate-mu-function-signature:error-nested-addr-inout/disp32
16376       }
16377       # assert(v->register == null)
16378       # . eax: (addr var) = lookup(v)
16379       (lookup *ebx *(ebx+4))  # => eax
16380       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
16381       0f 85/jump-if-!= $populate-mu-function-signature:error2/disp32
16382       # v->block-depth is implicitly 0
16383       #
16384       # out->inouts = append(v, out->inouts)
16385       8d/copy-address *(edi+8) 0/r32/eax  # Function-inouts
16386       (append-list Heap  *ebx *(ebx+4)  *(edi+8) *(edi+0xc)  %eax)  # Function-inouts, Function-inouts
16387       #
16388       e9/jump loop/disp32
16389     }
16390     # save function outputs
16391     {
16392 $populate-mu-function-signature:check-for-out:
16393       (next-mu-token *(ebp+8) %ecx)
16394       (slice-empty? %ecx)  # => eax
16395       3d/compare-eax-and 0/imm32/false
16396       0f 85/jump-if-!= break/disp32
16397       # if (word-slice == '{') abort
16398       (slice-equal? %ecx "{")   # => eax
16399       3d/compare-eax-and 0/imm32/false
16400       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
16401       # if (word-slice == '->') abort
16402       (slice-equal? %ecx "->")   # => eax
16403       3d/compare-eax-and 0/imm32/false
16404       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
16405       # if (word-slice == '}') abort
16406       (slice-equal? %ecx "}")   # => eax
16407       3d/compare-eax-and 0/imm32/false
16408       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
16409       # v = parse-var-with-type(word-slice, first-line)
16410       (lookup *edi *(edi+4))  # Function-name Function-name => eax
16411       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x10) *(ebp+0x14))
16412       # assert(var->register != null)
16413       # . eax: (addr var) = lookup(v)
16414       (lookup *ebx *(ebx+4))  # => eax
16415       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
16416       0f 84/jump-if-= $populate-mu-function-signature:error3/disp32
16417       # if (var->name != "_") abort
16418       (lookup *eax *(eax+4))  # Var-name Var-name => eax
16419       (string-equal? %eax "_")  # => eax
16420       3d/compare-eax-and 0/imm32/false
16421       0f 84/jump-if-= $populate-mu-function-signature:error4/disp32
16422       # if function name is not "lookup"
16423       #    and v->type is an addr, abort
16424       {
16425         (lookup *edi *(edi+4))  # Function-name Function-name => eax
16426         (string-equal? %eax "lookup")  # => eax
16427         3d/compare-eax-and 0/imm32/false
16428         75/jump-if-!= break/disp8
16429         (lookup *ebx *(ebx+4))  # => eax
16430         (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
16431         (mu-addr-type? %eax)  # => eax
16432         3d/compare-eax-and 0/imm32/false
16433         0f 85/jump-if-!= $populate-mu-function-signature:error-addr-output/disp32
16434       }
16435       # out->outputs = append(v, out->outputs)
16436       8d/copy-address *(edi+0x10) 0/r32/eax  # Function-outputs
16437       (append-list Heap  *ebx *(ebx+4)  *(edi+0x10) *(edi+0x14)  %eax)  # Function-outputs, Function-outputs
16438       #
16439       e9/jump loop/disp32
16440     }
16441 $populate-mu-function-signature:done:
16442     (check-no-tokens-left *(ebp+8))
16443 $populate-mu-function-signature:end:
16444     # . reclaim locals
16445     81 0/subop/add %esp 0x10/imm32
16446     # . restore registers
16447     5f/pop-to-edi
16448     5b/pop-to-ebx
16449     5a/pop-to-edx
16450     59/pop-to-ecx
16451     58/pop-to-eax
16452     # . epilogue
16453     89/<- %esp 5/r32/ebp
16454     5d/pop-to-ebp
16455     c3/return
16456 
16457 $populate-mu-function-signature:error1:
16458     # error("function signature not in form 'fn <name> {'")
16459     (write-buffered *(ebp+0x10) "function signature not in form 'fn <name> [inouts] [-> outputs] {' -- '")
16460     (flush *(ebp+0x10))
16461     (rewind-stream *(ebp+8))
16462     (write-stream-data *(ebp+0x10) *(ebp+8))
16463     (write-buffered *(ebp+0x10) "'\n")
16464     (flush *(ebp+0x10))
16465     (stop *(ebp+0x14) 1)
16466     # never gets here
16467 
16468 $populate-mu-function-signature:error2:
16469     # error("fn " fn ": function inout '" var "' cannot be in a register")
16470     (write-buffered *(ebp+0x10) "fn ")
16471     50/push-eax
16472     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16473     (write-buffered *(ebp+0x10) %eax)
16474     58/pop-to-eax
16475     (write-buffered *(ebp+0x10) ": function inout '")
16476     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16477     (write-buffered *(ebp+0x10) %eax)
16478     (write-buffered *(ebp+0x10) "' cannot be in a register")
16479     (flush *(ebp+0x10))
16480     (stop *(ebp+0x14) 1)
16481     # never gets here
16482 
16483 $populate-mu-function-signature:error3:
16484     # error("fn " fn ": function output '" var "' must be in a register")
16485     (write-buffered *(ebp+0x10) "fn ")
16486     50/push-eax
16487     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16488     (write-buffered *(ebp+0x10) %eax)
16489     58/pop-to-eax
16490     (write-buffered *(ebp+0x10) ": function output '")
16491     (lookup *ebx *(ebx+4))  # => eax
16492     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16493     (write-buffered *(ebp+0x10) %eax)
16494     (write-buffered *(ebp+0x10) "' must be in a register, in instruction '")
16495     (rewind-stream *(ebp+8))
16496     (write-stream-data *(ebp+0x10) *(ebp+8))
16497     (write-buffered *(ebp+0x10) "'\n")
16498     (flush *(ebp+0x10))
16499     (stop *(ebp+0x14) 1)
16500     # never gets here
16501 
16502 $populate-mu-function-signature:error4:
16503     # error("fn " fn ": function outputs cannot be named; rename '" var "' in the header to '_'")
16504     (write-buffered *(ebp+0x10) "fn ")
16505     50/push-eax
16506     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16507     (write-buffered *(ebp+0x10) %eax)
16508     58/pop-to-eax
16509     (write-buffered *(ebp+0x10) ": function outputs cannot be named; rename '")
16510     (lookup *ebx *(ebx+4))  # => eax
16511     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16512     (write-buffered *(ebp+0x10) %eax)
16513     (write-buffered *(ebp+0x10) "' in the header to '_'\n")
16514     (flush *(ebp+0x10))
16515     (stop *(ebp+0x14) 1)
16516     # never gets here
16517 
16518 $populate-mu-function-signature:error-duplicate:
16519     (write-buffered *(ebp+0x10) "fn ")
16520     (write-slice-buffered *(ebp+0x10) %ecx)
16521     (write-buffered *(ebp+0x10) " defined more than once\n")
16522     (flush *(ebp+0x10))
16523     (stop *(ebp+0x14) 1)
16524     # never gets here
16525 
16526 $populate-mu-function-signature:error-break:
16527     (write-buffered *(ebp+0x10) "Sorry, I've reserved all function names starting with 'break' for now. Please contact mu@akkartik.com.\n")
16528     (flush *(ebp+0x10))
16529     (stop *(ebp+0x14) 1)
16530     # never gets here
16531 
16532 $populate-mu-function-signature:error-loop:
16533     (write-buffered *(ebp+0x10) "Sorry, I've reserved all function names starting with 'loop' for now. Please contact mu@akkartik.com.\n")
16534     (flush *(ebp+0x10))
16535     (stop *(ebp+0x14) 1)
16536     # never gets here
16537 
16538 $populate-mu-function-signature:error-addr-output:
16539     # error("fn " fn ": output cannot have an addr type; that could allow unsafe addresses to escape the function")
16540     (write-buffered *(ebp+0x10) "fn ")
16541     50/push-eax
16542     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16543     (write-buffered *(ebp+0x10) %eax)
16544     58/pop-to-eax
16545     (write-buffered *(ebp+0x10) ": output cannot have an addr type; that could allow unsafe addresses to escape the function\n")
16546     (flush *(ebp+0x10))
16547     (stop *(ebp+0x14) 1)
16548     # never gets here
16549 
16550 $populate-mu-function-signature:error-nested-addr-inout:
16551     # 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")
16552     (write-buffered *(ebp+0x10) "fn ")
16553     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16554     (write-buffered *(ebp+0x10) %eax)
16555     (write-buffered *(ebp+0x10) ": inout '")
16556     (lookup *ebx *(ebx+4))  # => eax
16557     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16558     (write-buffered *(ebp+0x10) %eax)
16559     (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")
16560     (flush *(ebp+0x10))
16561     (stop *(ebp+0x14) 1)
16562     # never gets here
16563 
16564 addr-payload-contains-addr?:  # v: (addr var) -> result/eax: boolean
16565     # . prologue
16566     55/push-ebp
16567     89/<- %ebp 4/r32/esp
16568     # var t/eax: (addr type-tree) = v->type
16569     8b/-> *(ebp+8) 0/r32/eax
16570     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
16571     # if t->right contains addr, return true
16572     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
16573     (type-tree-contains? %eax 2)  # addr => eax
16574     # we don't have to look at t->left as long as it's guaranteed to be an atom
16575 $addr-payload-contains-addr?:end:
16576     # . epilogue
16577     89/<- %esp 5/r32/ebp
16578     5d/pop-to-ebp
16579     c3/return
16580 
16581 type-tree-contains?:  # t: (addr type-tree), n: type-id -> result/eax: boolean
16582     # . prologue
16583     55/push-ebp
16584     89/<- %ebp 4/r32/esp
16585     # . save registers
16586     51/push-ecx
16587     # if t is null, return false
16588     8b/-> *(ebp+8) 0/r32/eax
16589     3d/compare-eax-and 0/imm32
16590     0f 84/jump-if-= $type-tree-contains?:end/disp32  # eax changes type
16591     # if t is an atom, return (t->value == n)
16592     81 7/subop/compare *eax 0/imm32/false
16593     {
16594       74/jump-if-= break/disp8
16595       8b/-> *(ebp+0xc) 1/r32/ecx
16596       39/compare *(eax+4) 1/r32/ecx  # Type-tree-value
16597       0f 94/set-if-= %al
16598       81 4/subop/and %eax 0xff/imm32
16599       eb/jump $type-tree-contains?:end/disp8
16600     }
16601     # if t->left contains n, return true
16602     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
16603     (type-tree-contains? %eax *(ebp+0xc))  # => eax
16604     3d/compare-eax-and 0/imm32/false
16605     75/jump-if-!= $type-tree-contains?:end/disp8
16606     # otherwise return whether t->right contains n
16607     8b/-> *(ebp+8) 0/r32/eax
16608     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
16609     (type-tree-contains? %eax *(ebp+0xc))  # => eax
16610 $type-tree-contains?:end:
16611     # . restore registers
16612     59/pop-to-ecx
16613     # . epilogue
16614     89/<- %esp 5/r32/ebp
16615     5d/pop-to-ebp
16616     c3/return
16617 
16618 function-exists?:  # s: (addr slice) -> result/eax: boolean
16619     # . prologue
16620     55/push-ebp
16621     89/<- %ebp 4/r32/esp
16622     # . save registers
16623     51/push-ecx
16624     # var curr/ecx: (addr function) = functions
16625     (lookup *_Program-functions *_Program-functions->payload)  # => eax
16626     89/<- %ecx 0/r32/eax
16627     {
16628       # if (curr == null) break
16629       81 7/subop/compare %ecx 0/imm32
16630       74/jump-if-= break/disp8
16631       # if (curr->name == s) return true
16632       {
16633         (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
16634         (slice-equal? *(ebp+8) %eax)  # => eax
16635         3d/compare-eax-and 0/imm32/false
16636         74/jump-if-= break/disp8
16637         b8/copy-to-eax 1/imm32/true
16638         e9/jump $function-exists?:end/disp32
16639       }
16640       # curr = curr->next
16641       (lookup *(ecx+0x20) *(ecx+0x24))  # Function-next Function-next => eax
16642       89/<- %ecx 0/r32/eax
16643       #
16644       eb/jump loop/disp8
16645     }
16646     # var curr/ecx: (addr function) = signatures
16647     (lookup *_Program-signatures *_Program-signatures->payload)  # => eax
16648     89/<- %ecx 0/r32/eax
16649     {
16650       # if (curr == null) break
16651       81 7/subop/compare %ecx 0/imm32
16652       74/jump-if-= break/disp8
16653       # if (curr->name == s) return true
16654       {
16655         (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
16656         (slice-equal? *(ebp+8) %eax)  # => eax
16657         3d/compare-eax-and 0/imm32/false
16658         74/jump-if-= break/disp8
16659         b8/copy-to-eax 1/imm32/true
16660         eb/jump $function-exists?:end/disp8
16661       }
16662       # curr = curr->next
16663       (lookup *(ecx+0x20) *(ecx+0x24))  # Function-next Function-next => eax
16664       89/<- %ecx 0/r32/eax
16665       #
16666       eb/jump loop/disp8
16667     }
16668     # return false
16669     b8/copy-to-eax 0/imm32/false
16670 $function-exists?:end:
16671     # . restore registers
16672     59/pop-to-ecx
16673     # . epilogue
16674     89/<- %esp 5/r32/ebp
16675     5d/pop-to-ebp
16676     c3/return
16677 
16678 test-function-header-with-arg:
16679     # . prologue
16680     55/push-ebp
16681     89/<- %ebp 4/r32/esp
16682     # setup
16683     8b/-> *Primitive-type-ids 0/r32/eax
16684     89/<- *Type-id 0/r32/eax  # stream-write
16685     c7 0/subop/copy *_Program-functions 0/imm32
16686     c7 0/subop/copy *_Program-functions->payload 0/imm32
16687     c7 0/subop/copy *_Program-types 0/imm32
16688     c7 0/subop/copy *_Program-types->payload 0/imm32
16689     c7 0/subop/copy *_Program-signatures 0/imm32
16690     c7 0/subop/copy *_Program-signatures->payload 0/imm32
16691     (clear-stream _test-input-stream)
16692     (write _test-input-stream "foo n: int {\n")
16693     # var result/ecx: function
16694     2b/subtract *Function-size 4/r32/esp
16695     89/<- %ecx 4/r32/esp
16696     (zero-out %ecx *Function-size)
16697     # var vars/ebx: (stack live-var 16)
16698     81 5/subop/subtract %esp 0xc0/imm32
16699     68/push 0xc0/imm32/size
16700     68/push 0/imm32/top
16701     89/<- %ebx 4/r32/esp
16702     # convert
16703     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
16704     # check result->name
16705     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
16706     (check-strings-equal %eax "foo" "F - test-function-header-with-arg/name")
16707     # var v/edx: (addr var) = result->inouts->value
16708     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
16709     (lookup *eax *(eax+4))  # List-value List-value => eax
16710     89/<- %edx 0/r32/eax
16711     # check v->name
16712     (lookup *edx *(edx+4))  # Var-name Var-name => eax
16713     (check-strings-equal %eax "n" "F - test-function-header-with-arg/inout:0")
16714     # check v->type
16715     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
16716     (check-ints-equal *eax 1 "F - test-function-header-with-arg/inout:0/type:0")  # Type-tree-is-atom
16717     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-arg/inout:0/type:1")  # Type-tree-value
16718     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-arg/inout:0/type:2")  # Type-tree-right
16719     # . epilogue
16720     89/<- %esp 5/r32/ebp
16721     5d/pop-to-ebp
16722     c3/return
16723 
16724 test-function-header-with-multiple-args:
16725     # . prologue
16726     55/push-ebp
16727     89/<- %ebp 4/r32/esp
16728     # setup
16729     8b/-> *Primitive-type-ids 0/r32/eax
16730     89/<- *Type-id 0/r32/eax  # stream-write
16731     c7 0/subop/copy *_Program-functions 0/imm32
16732     c7 0/subop/copy *_Program-functions->payload 0/imm32
16733     c7 0/subop/copy *_Program-types 0/imm32
16734     c7 0/subop/copy *_Program-types->payload 0/imm32
16735     c7 0/subop/copy *_Program-signatures 0/imm32
16736     c7 0/subop/copy *_Program-signatures->payload 0/imm32
16737     (clear-stream _test-input-stream)
16738     (write _test-input-stream "foo a: int, b: int c: int {\n")
16739     # result/ecx: function
16740     2b/subtract *Function-size 4/r32/esp
16741     89/<- %ecx 4/r32/esp
16742     (zero-out %ecx *Function-size)
16743     # var vars/ebx: (stack live-var 16)
16744     81 5/subop/subtract %esp 0xc0/imm32
16745     68/push 0xc0/imm32/size
16746     68/push 0/imm32/top
16747     89/<- %ebx 4/r32/esp
16748     # convert
16749     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
16750     # check result->name
16751     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
16752     (check-strings-equal %eax "foo" "F - test-function-header-with-multiple-args/name")
16753     # var inouts/edx: (addr list var) = lookup(result->inouts)
16754     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
16755     89/<- %edx 0/r32/eax
16756 $test-function-header-with-multiple-args:inout0:
16757     # var v/ebx: (addr var) = lookup(inouts->value)
16758     (lookup *edx *(edx+4))  # List-value List-value => eax
16759     89/<- %ebx 0/r32/eax
16760     # check v->name
16761     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
16762     (check-strings-equal %eax "a" "F - test-function-header-with-multiple-args/inout:0")  # Var-name
16763     # check v->type
16764     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
16765     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:0/type:0")  # Type-tree-is-atom
16766     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:0/type:1")  # Type-tree-value
16767     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:0/type:2")  # Type-tree-right
16768 $test-function-header-with-multiple-args:inout1:
16769     # inouts = lookup(inouts->next)
16770     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
16771     89/<- %edx 0/r32/eax
16772     # v = lookup(inouts->value)
16773     (lookup *edx *(edx+4))  # List-value List-value => eax
16774     89/<- %ebx 0/r32/eax
16775     # check v->name
16776     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
16777     (check-strings-equal %eax "b" "F - test-function-header-with-multiple-args/inout:1")  # Var-name
16778     # check v->type
16779     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
16780     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:1/type:0")  # Type-tree-is-atom
16781     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:1/type:1")  # Type-tree-value
16782     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:1/type:2")  # Type-tree-right
16783 $test-function-header-with-multiple-args:inout2:
16784     # inouts = lookup(inouts->next)
16785     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
16786     89/<- %edx 0/r32/eax
16787     # v = lookup(inouts->value)
16788     (lookup *edx *(edx+4))  # List-value List-value => eax
16789     89/<- %ebx 0/r32/eax
16790     # check v->name
16791     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
16792     (check-strings-equal %eax "c" "F - test-function-header-with-multiple-args/inout:2")  # Var-name
16793     # check v->type
16794     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
16795     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:2/type:0")  # Type-tree-is-atom
16796     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:2/type:1")  # Type-tree-value
16797     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:2/type:2")  # Type-tree-right
16798     # . epilogue
16799     89/<- %esp 5/r32/ebp
16800     5d/pop-to-ebp
16801     c3/return
16802 
16803 test-function-header-with-multiple-args-and-outputs:
16804     # . prologue
16805     55/push-ebp
16806     89/<- %ebp 4/r32/esp
16807     # setup
16808     8b/-> *Primitive-type-ids 0/r32/eax
16809     89/<- *Type-id 0/r32/eax  # stream-write
16810     c7 0/subop/copy *_Program-functions 0/imm32
16811     c7 0/subop/copy *_Program-functions->payload 0/imm32
16812     c7 0/subop/copy *_Program-types 0/imm32
16813     c7 0/subop/copy *_Program-types->payload 0/imm32
16814     c7 0/subop/copy *_Program-signatures 0/imm32
16815     c7 0/subop/copy *_Program-signatures->payload 0/imm32
16816     (clear-stream _test-input-stream)
16817     (write _test-input-stream "foo a: int, b: int, c: int -> _/ecx: int _/edx: int {\n")
16818     # result/ecx: function
16819     2b/subtract *Function-size 4/r32/esp
16820     89/<- %ecx 4/r32/esp
16821     (zero-out %ecx *Function-size)
16822     # var vars/ebx: (stack live-var 16)
16823     81 5/subop/subtract %esp 0xc0/imm32
16824     68/push 0xc0/imm32/size
16825     68/push 0/imm32/top
16826     89/<- %ebx 4/r32/esp
16827     # convert
16828     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
16829     # check result->name
16830     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
16831     (check-strings-equal %eax "foo" "F - test-function-header-with-multiple-args-and-outputs/name")
16832     # var inouts/edx: (addr list var) = lookup(result->inouts)
16833     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
16834     89/<- %edx 0/r32/eax
16835 $test-function-header-with-multiple-args-and-outputs:inout0:
16836     # var v/ebx: (addr var) = lookup(inouts->value)
16837     (lookup *edx *(edx+4))  # List-value List-value => eax
16838     89/<- %ebx 0/r32/eax
16839     # check v->name
16840     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
16841     (check-strings-equal %eax "a" "F - test-function-header-with-multiple-args-and-outputs/inout:0")
16842     # check v->type
16843     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
16844     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:0")  # Type-tree-is-atom
16845     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:1")  # Type-tree-value
16846     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:2")  # Type-tree-right
16847 $test-function-header-with-multiple-args-and-outputs:inout1:
16848     # inouts = lookup(inouts->next)
16849     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
16850     89/<- %edx 0/r32/eax
16851     # v = lookup(inouts->value)
16852     (lookup *edx *(edx+4))  # List-value List-value => eax
16853     89/<- %ebx 0/r32/eax
16854     # check v->name
16855     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
16856     (check-strings-equal %eax "b" "F - test-function-header-with-multiple-args-and-outputs/inout:1")
16857     # check v->type
16858     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
16859     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:0")  # Type-tree-is-atom
16860     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:1")  # Type-tree-value
16861     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:2")  # Type-tree-right
16862 $test-function-header-with-multiple-args-and-outputs:inout2:
16863     # inouts = lookup(inouts->next)
16864     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
16865     89/<- %edx 0/r32/eax
16866     # v = lookup(inouts->value)
16867     (lookup *edx *(edx+4))  # List-value List-value => eax
16868     89/<- %ebx 0/r32/eax
16869     # check v->name
16870     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
16871     (check-strings-equal %eax "c" "F - test-function-header-with-multiple-args-and-outputs/inout:2")
16872     # check v->type
16873     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
16874     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:0")  # Type-tree-is-atom
16875     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:1")  # Type-tree-value
16876     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:2")  # Type-tree-right
16877 $test-function-header-with-multiple-args-and-outputs:out0:
16878     # var outputs/edx: (addr list var) = lookup(result->outputs)
16879     (lookup *(ecx+0x10) *(ecx+0x14))  # Function-outputs Function-outputs => eax
16880     89/<- %edx 0/r32/eax
16881     # v = lookup(outputs->value)
16882     (lookup *edx *(edx+4))  # List-value List-value => eax
16883     89/<- %ebx 0/r32/eax
16884     # check v->name
16885     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
16886     (check-strings-equal %eax "_" "F - test-function-header-with-multiple-args-and-outputs/output:0")
16887     # check v->register
16888     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
16889     (check-strings-equal %eax "ecx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register")
16890     # check v->type
16891     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
16892     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:0")  # Type-tree-is-atom
16893     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1")  # Type-tree-value
16894     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:2")  # Type-tree-right
16895 $test-function-header-with-multiple-args-and-outputs:out1:
16896     # outputs = lookup(outputs->next)
16897     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
16898     89/<- %edx 0/r32/eax
16899     # v = lookup(inouts->value)
16900     (lookup *edx *(edx+4))  # List-value List-value => eax
16901     89/<- %ebx 0/r32/eax
16902     # check v->name
16903     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
16904     (check-strings-equal %eax "_" "F - test-function-header-with-multiple-args-and-outputs/output:1")
16905     # check v->register
16906     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
16907     (check-strings-equal %eax "edx" "F - test-function-header-with-multiple-args-and-outputs/output:1/register")
16908     # check v->type
16909     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
16910     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:0")  # Type-tree-is-atom
16911     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1")  # Type-tree-value
16912     (check-ints-equal *(eax+0c) 0 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:2")  # Type-tree-right
16913     # . epilogue
16914     89/<- %esp 5/r32/ebp
16915     5d/pop-to-ebp
16916     c3/return
16917 
16918 # format for variables with types
16919 #   x: int
16920 #   x: int,
16921 #   x/eax: int
16922 #   x/eax: int,
16923 # ignores at most one trailing comma
16924 # does not support other, non-register metadata
16925 # WARNING: modifies name
16926 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)
16927     # pseudocode:
16928     #   var s: slice
16929     #   if (!slice-ends-with(name, ":"))
16930     #     abort
16931     #   --name->end to skip ':'
16932     #   next-token-from-slice(name->start, name->end, '/', s)
16933     #   new-var-from-slice(s, out)
16934     #   ## register
16935     #   next-token-from-slice(s->end, name->end, '/', s)
16936     #   if (!slice-empty?(s))
16937     #     out->register = slice-to-string(s)
16938     #   ## type
16939     #   var type: (handle type-tree) = parse-type(first-line)
16940     #   out->type = type
16941     #
16942     # . prologue
16943     55/push-ebp
16944     89/<- %ebp 4/r32/esp
16945     # . save registers
16946     50/push-eax
16947     51/push-ecx
16948     52/push-edx
16949     53/push-ebx
16950     56/push-esi
16951     57/push-edi
16952     # esi = name
16953     8b/-> *(ebp+8) 6/r32/esi
16954     # if (!slice-ends-with?(name, ":")) abort
16955     8b/-> *(esi+4) 1/r32/ecx  # Slice-end
16956     49/decrement-ecx
16957     8a/copy-byte *ecx 1/r32/CL
16958     81 4/subop/and %ecx 0xff/imm32
16959     81 7/subop/compare %ecx 0x3a/imm32/colon
16960     0f 85/jump-if-!= $parse-var-with-type:abort/disp32
16961     # --name->end to skip ':'
16962     ff 1/subop/decrement *(esi+4)
16963     # var s/ecx: slice
16964     68/push 0/imm32/end
16965     68/push 0/imm32/start
16966     89/<- %ecx 4/r32/esp
16967 $parse-var-with-type:parse-name:
16968     (next-token-from-slice *esi *(esi+4) 0x2f %ecx)  # Slice-start, Slice-end, '/'
16969 $parse-var-with-type:create-var:
16970     # new-var-from-slice(s, out)
16971     (new-var-from-slice Heap %ecx *(ebp+0x10))
16972     # save out->register
16973 $parse-var-with-type:save-register:
16974     # . var out-addr/edi: (addr var) = lookup(*out)
16975     8b/-> *(ebp+0x10) 7/r32/edi
16976     (lookup *edi *(edi+4))  # => eax
16977     89/<- %edi 0/r32/eax
16978     # . s = next-token(...)
16979     (next-token-from-slice *(ecx+4) *(esi+4) 0x2f %ecx)  # s->end, name->end, '/'
16980     # . if (!slice-empty?(s)) out->register = slice-to-string(s)
16981     {
16982 $parse-var-with-type:write-register:
16983       (slice-empty? %ecx)  # => eax
16984       3d/compare-eax-and 0/imm32/false
16985       75/jump-if-!= break/disp8
16986       # out->register = slice-to-string(s)
16987       8d/copy-address *(edi+0x18) 0/r32/eax  # Var-register
16988       (slice-to-string Heap %ecx %eax)
16989     }
16990 $parse-var-with-type:save-type:
16991     8d/copy-address *(edi+8) 0/r32/eax  # Var-type
16992     (parse-type Heap *(ebp+0xc) %eax *(ebp+0x18) *(ebp+0x1c))
16993 $parse-var-with-type:check-register:
16994     (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
16995     3d/compare-eax-and 0/imm32
16996     74/jump-if-= $parse-var-with-type:end/disp8
16997     (float-register? %eax)  # => eax
16998     {
16999       3d/compare-eax-and 0/imm32/false
17000       74/jump-if-= break/disp8
17001       # var is in a float register; ensure type is float
17002       (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
17003       (simple-mu-type? %eax 0xf)  # float => eax
17004       3d/compare-eax-and 0/imm32/false
17005       0f 84/jump-if-= $parse-var-with-type:error-non-float-in-floating-point-register/disp32
17006       eb/jump $parse-var-with-type:end/disp8
17007     }
17008     # var is not in a float register; ensure type is not float
17009     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
17010     (simple-mu-type? %eax 0xf)  # float => eax
17011     3d/compare-eax-and 0/imm32/false
17012     0f 85/jump-if-!= $parse-var-with-type:error-float-in-integer-register/disp32
17013 $parse-var-with-type:end:
17014     # . reclaim locals
17015     81 0/subop/add %esp 8/imm32
17016     # . restore registers
17017     5f/pop-to-edi
17018     5e/pop-to-esi
17019     5b/pop-to-ebx
17020     5a/pop-to-edx
17021     59/pop-to-ecx
17022     58/pop-to-eax
17023     # . epilogue
17024     89/<- %esp 5/r32/ebp
17025     5d/pop-to-ebp
17026     c3/return
17027 
17028 $parse-var-with-type:abort:
17029     # error("fn " fn ": var should have form 'name: type' in '" line "'\n")
17030     (write-buffered *(ebp+0x18) "fn ")
17031     (write-buffered *(ebp+0x18) *(ebp+0x14))
17032     (write-buffered *(ebp+0x18) ": var should have form 'name: type' in '")
17033     (flush *(ebp+0x18))
17034     (rewind-stream *(ebp+0xc))
17035     (write-stream-data *(ebp+0x18) *(ebp+0xc))
17036     (write-buffered *(ebp+0x18) "'\n")
17037     (flush *(ebp+0x18))
17038     (stop *(ebp+0x1c) 1)
17039     # never gets here
17040 
17041 $parse-var-with-type:error-float-in-integer-register:
17042     # error("fn " fn ": float var '" var "' should be in a floating-point register\n")
17043     (write-buffered *(ebp+0x18) "fn ")
17044     (write-buffered *(ebp+0x18) *(ebp+0x14))
17045     (write-buffered *(ebp+0x18) ": float var '")
17046     (lookup *edi *(edi+4))  # Var-name Var-name => eax
17047     (write-buffered *(ebp+0x18) %eax)
17048     (write-buffered *(ebp+0x18) "' should be in a floating-point register\n")
17049     (flush *(ebp+0x18))
17050     (stop *(ebp+0x1c) 1)
17051     # never gets here
17052 
17053 $parse-var-with-type:error-non-float-in-floating-point-register:
17054     # error("fn " fn ": non-float var '" var "' should be in an integer register\n")
17055     (write-buffered *(ebp+0x18) "fn ")
17056     (write-buffered *(ebp+0x18) *(ebp+0x14))
17057     (write-buffered *(ebp+0x18) ": non-float var '")
17058     (lookup *edi *(edi+4))  # Var-name Var-name => eax
17059     (write-buffered *(ebp+0x18) %eax)
17060     (write-buffered *(ebp+0x18) "' should be in an integer register\n")
17061     (flush *(ebp+0x18))
17062     (stop *(ebp+0x1c) 1)
17063     # never gets here
17064 
17065 float-register?:  # r: (addr array byte) -> result/eax: boolean
17066     # . prologue
17067     55/push-ebp
17068     89/<- %ebp 4/r32/esp
17069     #
17070     (get Mu-registers-unique *(ebp+8) 0xc "Mu-registers-unique")  # => eax
17071     81 7/subop/compare *eax 8/imm32/start-of-floating-point-registers
17072     0f 9d/set-if->= %al
17073     81 4/subop/and %eax 0xff/imm32
17074 $float-register?:end:
17075     # . epilogue
17076     89/<- %esp 5/r32/ebp
17077     5d/pop-to-ebp
17078     c3/return
17079 
17080 parse-type:  # ad: (addr allocation-descriptor), in: (addr stream byte), out: (addr handle type-tree), err: (addr buffered-file), ed: (addr exit-descriptor)
17081     # pseudocode:
17082     #   var s: slice = next-mu-token(in)
17083     #   assert s != ""
17084     #   assert s != "->"
17085     #   assert s != "{"
17086     #   assert s != "}"
17087     #   if s == ")"
17088     #     return
17089     #   out = allocate(Type-tree)
17090     #   if s != "("
17091     #     HACK: if s is an int, parse and return it
17092     #     out->is-atom? = true
17093     #     if (s[0] == "_")
17094     #       out->value = type-parameter
17095     #       out->parameter-name = slice-to-string(ad, s)
17096     #     else
17097     #       out->value = pos-or-insert-slice(Type-id, s)
17098     #     return
17099     #   out->left = parse-type(ad, in)
17100     #   out->right = parse-type-tree(ad, in)
17101     #
17102     # . prologue
17103     55/push-ebp
17104     89/<- %ebp 4/r32/esp
17105     # . save registers
17106     50/push-eax
17107     51/push-ecx
17108     52/push-edx
17109     # clear out
17110     (zero-out *(ebp+0x10) *Handle-size)
17111     # var s/ecx: slice
17112     68/push 0/imm32
17113     68/push 0/imm32
17114     89/<- %ecx 4/r32/esp
17115     # s = next-mu-token(in)
17116     (next-mu-token *(ebp+0xc) %ecx)
17117 #?     (write-buffered Stderr "tok: ")
17118 #?     (write-slice-buffered Stderr %ecx)
17119 #?     (write-buffered Stderr "$\n")
17120 #?     (flush Stderr)
17121     # assert s != ""
17122     (slice-equal? %ecx "")  # => eax
17123     3d/compare-eax-and 0/imm32/false
17124     0f 85/jump-if-!= $parse-type:abort/disp32
17125     # assert s != "{"
17126     (slice-equal? %ecx "{")  # => eax
17127     3d/compare-eax-and 0/imm32/false
17128     0f 85/jump-if-!= $parse-type:abort/disp32
17129     # assert s != "}"
17130     (slice-equal? %ecx "}")  # => eax
17131     3d/compare-eax-and 0/imm32/false
17132     0f 85/jump-if-!= $parse-type:abort/disp32
17133     # assert s != "->"
17134     (slice-equal? %ecx "->")  # => eax
17135     3d/compare-eax-and 0/imm32/false
17136     0f 85/jump-if-!= $parse-type:abort/disp32
17137     # if (s == ")") return
17138     (slice-equal? %ecx ")")  # => eax
17139     3d/compare-eax-and 0/imm32/false
17140     0f 85/jump-if-!= $parse-type:end/disp32
17141     # out = new tree
17142     (allocate *(ebp+8) *Type-tree-size *(ebp+0x10))
17143     # var out-addr/edx: (addr type-tree) = lookup(*out)
17144     8b/-> *(ebp+0x10) 2/r32/edx
17145     (lookup *edx *(edx+4))  # => eax
17146     89/<- %edx 0/r32/eax
17147     {
17148       # if (s != "(") break
17149       (slice-equal? %ecx "(")  # => eax
17150       3d/compare-eax-and 0/imm32/false
17151       0f 85/jump-if-!= break/disp32
17152       # if s is a number, store it in the type's size field
17153       {
17154 $parse-type:check-for-int:
17155         # var tmp/eax: byte = *s->slice
17156         8b/-> *ecx 0/r32/eax
17157         8a/copy-byte *eax 0/r32/AL
17158         81 4/subop/and %eax 0xff/imm32
17159         # TODO: raise an error on `var x: (array int a)`
17160         (decimal-digit? %eax)  # => eax
17161         3d/compare-eax-and 0/imm32/false
17162         74/jump-if-= break/disp8
17163 $parse-type:int:
17164         # strip out metadata
17165         (next-token-from-slice *ecx *(ecx+4) 0x2f %ecx)
17166         #
17167         (check-mu-hex-int %ecx *(ebp+0x14) *(ebp+0x18))
17168         (parse-hex-int-from-slice %ecx)  # => eax
17169         c7 0/subop/copy *(edx+4) 9/imm32/type-id-array-capacity  # Type-tree-value
17170         89/<- *(edx+8) 0/r32/eax  # Type-tree-value-size
17171         e9/jump $parse-type:end/disp32
17172       }
17173 $parse-type:atom:
17174       # out->is-atom? = true
17175       c7 0/subop/copy *edx 1/imm32/true  # Type-tree-is-atom
17176       {
17177 $parse-type:check-for-type-parameter:
17178         # var tmp/eax: byte = *s->slice
17179         8b/-> *ecx 0/r32/eax
17180         8a/copy-byte *eax 0/r32/AL
17181         81 4/subop/and %eax 0xff/imm32
17182         # if (tmp != '_') break
17183         3d/compare-eax-and 0x5f/imm32/_
17184         75/jump-if-!= break/disp8
17185 $parse-type:type-parameter:
17186         # out->value = type-parameter
17187         c7 0/subop/copy *(edx+4) 0xa/imm32/type-parameter  # Type-tree-value
17188         # out->parameter-name = slice-to-string(ad, s)
17189         8d/copy-address *(edx+8) 0/r32/eax  # Type-tree-parameter-name
17190         (slice-to-string *(ebp+8) %ecx %eax)
17191         e9/jump $parse-type:end/disp32
17192       }
17193 $parse-type:non-type-parameter:
17194       # out->value = pos-or-insert-slice(Type-id, s)
17195       (pos-or-insert-slice Type-id %ecx)  # => eax
17196       89/<- *(edx+4) 0/r32/eax  # Type-tree-value
17197       e9/jump $parse-type:end/disp32
17198     }
17199 $parse-type:non-atom:
17200     # otherwise s == "("
17201     # out->left = parse-type(ad, in)
17202     8d/copy-address *(edx+4) 0/r32/eax  # Type-tree-left
17203     (parse-type *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
17204     # out->right = parse-type-tree(ad, in)
17205     8d/copy-address *(edx+0xc) 0/r32/eax  # Type-tree-right
17206     (parse-type-tree *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
17207 $parse-type:end:
17208     # . reclaim locals
17209     81 0/subop/add %esp 8/imm32
17210     # . restore registers
17211     5a/pop-to-edx
17212     59/pop-to-ecx
17213     58/pop-to-eax
17214     # . epilogue
17215     89/<- %esp 5/r32/ebp
17216     5d/pop-to-ebp
17217     c3/return
17218 
17219 $parse-type:abort:
17220     # error("unexpected token when parsing type: '" s "'\n")
17221     (write-buffered *(ebp+0x14) "unexpected token when parsing type: '")
17222     (write-slice-buffered *(ebp+0x14) %ecx)
17223     (write-buffered *(ebp+0x14) "'\n")
17224     (flush *(ebp+0x14))
17225     (stop *(ebp+0x18) 1)
17226     # never gets here
17227 
17228 parse-type-tree:  # ad: (addr allocation-descriptor), in: (addr stream byte), out: (addr handle type-tree), err: (addr buffered-file), ed: (addr exit-descriptor)
17229     # pseudocode:
17230     #   var tmp: (handle type-tree) = parse-type(ad, in)
17231     #   if tmp == 0
17232     #     return 0
17233     #   out = allocate(Type-tree)
17234     #   out->left = tmp
17235     #   out->right = parse-type-tree(ad, in)
17236     #
17237     # . prologue
17238     55/push-ebp
17239     89/<- %ebp 4/r32/esp
17240     # . save registers
17241     50/push-eax
17242     51/push-ecx
17243     52/push-edx
17244     #
17245     (zero-out *(ebp+0x10) *Handle-size)
17246     # var tmp/ecx: (handle type-tree)
17247     68/push 0/imm32
17248     68/push 0/imm32
17249     89/<- %ecx 4/r32/esp
17250     # tmp = parse-type(ad, in)
17251     (parse-type *(ebp+8) *(ebp+0xc) %ecx *(ebp+0x14) *(ebp+0x18))
17252     # if (tmp == 0) return
17253     81 7/subop/compare *ecx 0/imm32
17254     74/jump-if-= $parse-type-tree:end/disp8
17255     # out = new tree
17256     (allocate *(ebp+8) *Type-tree-size *(ebp+0x10))
17257     # var out-addr/edx: (addr tree) = lookup(*out)
17258     8b/-> *(ebp+0x10) 2/r32/edx
17259     (lookup *edx *(edx+4))  # => eax
17260     89/<- %edx 0/r32/eax
17261     # out->left = tmp
17262     8b/-> *ecx 0/r32/eax
17263     89/<- *(edx+4) 0/r32/eax  # Type-tree-left
17264     8b/-> *(ecx+4) 0/r32/eax
17265     89/<- *(edx+8) 0/r32/eax  # Type-tree-left
17266     # out->right = parse-type-tree(ad, in)
17267     8d/copy-address *(edx+0xc) 0/r32/eax  # Type-tree-right
17268     (parse-type-tree *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
17269 $parse-type-tree:end:
17270     # . reclaim locals
17271     81 0/subop/add %esp 8/imm32
17272     # . restore registers
17273     5a/pop-to-edx
17274     59/pop-to-ecx
17275     58/pop-to-eax
17276     # . epilogue
17277     89/<- %esp 5/r32/ebp
17278     5d/pop-to-ebp
17279     c3/return
17280 
17281 next-mu-token:  # in: (addr stream byte), out: (addr slice)
17282     # pseudocode:
17283     # start:
17284     #   skip-chars-matching-whitespace(in)
17285     #   if in->read >= in->write              # end of in
17286     #     out = {0, 0}
17287     #     return
17288     #   out->start = &in->data[in->read]
17289     #   var curr-byte/eax: byte = in->data[in->read]
17290     #   if curr->byte == ','                  # comment token
17291     #     ++in->read
17292     #     goto start
17293     #   if curr-byte == '#'                   # comment
17294     #     goto done                             # treat as eof
17295     #   if curr-byte == '"'                   # string literal
17296     #     skip-string(in)
17297     #     goto done                           # no metadata
17298     #   if curr-byte == '('
17299     #     ++in->read
17300     #     goto done
17301     #   if curr-byte == ')'
17302     #     ++in->read
17303     #     goto done
17304     #   # read a word
17305     #   while true
17306     #     if in->read >= in->write
17307     #       break
17308     #     curr-byte = in->data[in->read]
17309     #     if curr-byte == ' '
17310     #       break
17311     #     if curr-byte == '\r'
17312     #       break
17313     #     if curr-byte == '\n'
17314     #       break
17315     #     if curr-byte == '('
17316     #       break
17317     #     if curr-byte == ')'
17318     #       break
17319     #     if curr-byte == ','
17320     #       break
17321     #     ++in->read
17322     # done:
17323     #   out->end = &in->data[in->read]
17324     #
17325     # . prologue
17326     55/push-ebp
17327     89/<- %ebp 4/r32/esp
17328     # . save registers
17329     50/push-eax
17330     51/push-ecx
17331     56/push-esi
17332     57/push-edi
17333     # esi = in
17334     8b/-> *(ebp+8) 6/r32/esi
17335     # edi = out
17336     8b/-> *(ebp+0xc) 7/r32/edi
17337 $next-mu-token:start:
17338     (skip-chars-matching-whitespace %esi)
17339 $next-mu-token:check0:
17340     # if (in->read >= in->write) return out = {0, 0}
17341     # . ecx = in->read
17342     8b/-> *(esi+4) 1/r32/ecx
17343     # . if (ecx >= in->write) return out = {0, 0}
17344     3b/compare<- *esi 1/r32/ecx
17345     c7 0/subop/copy *edi 0/imm32
17346     c7 0/subop/copy *(edi+4) 0/imm32
17347     0f 8d/jump-if->= $next-mu-token:end/disp32
17348     # out->start = &in->data[in->read]
17349     8d/copy-address *(esi+ecx+0xc) 0/r32/eax
17350     89/<- *edi 0/r32/eax
17351     # var curr-byte/eax: byte = in->data[in->read]
17352     31/xor-with %eax 0/r32/eax
17353     8a/copy-byte *(esi+ecx+0xc) 0/r32/AL
17354     {
17355 $next-mu-token:check-for-comma:
17356       # if (curr-byte != ',') break
17357       3d/compare-eax-and 0x2c/imm32/comma
17358       75/jump-if-!= break/disp8
17359       # ++in->read
17360       ff 0/subop/increment *(esi+4)
17361       # restart
17362       e9/jump $next-mu-token:start/disp32
17363     }
17364     {
17365 $next-mu-token:check-for-comment:
17366       # if (curr-byte != '#') break
17367       3d/compare-eax-and 0x23/imm32/pound
17368       75/jump-if-!= break/disp8
17369       # return eof
17370       e9/jump $next-mu-token:done/disp32
17371     }
17372     {
17373 $next-mu-token:check-for-string-literal:
17374       # if (curr-byte != '"') break
17375       3d/compare-eax-and 0x22/imm32/dquote
17376       75/jump-if-!= break/disp8
17377       (skip-string %esi)
17378       # return
17379       e9/jump $next-mu-token:done/disp32
17380     }
17381     {
17382 $next-mu-token:check-for-open-paren:
17383       # if (curr-byte != '(') break
17384       3d/compare-eax-and 0x28/imm32/open-paren
17385       75/jump-if-!= break/disp8
17386       # ++in->read
17387       ff 0/subop/increment *(esi+4)
17388       # return
17389       e9/jump $next-mu-token:done/disp32
17390     }
17391     {
17392 $next-mu-token:check-for-close-paren:
17393       # if (curr-byte != ')') break
17394       3d/compare-eax-and 0x29/imm32/close-paren
17395       75/jump-if-!= break/disp8
17396       # ++in->read
17397       ff 0/subop/increment *(esi+4)
17398       # return
17399       e9/jump $next-mu-token:done/disp32
17400     }
17401     {
17402 $next-mu-token:regular-word-without-metadata:
17403       # if (in->read >= in->write) break
17404       # . ecx = in->read
17405       8b/-> *(esi+4) 1/r32/ecx
17406       # . if (ecx >= in->write) break
17407       3b/compare<- *esi 1/r32/ecx
17408       7d/jump-if->= break/disp8
17409       # var c/eax: byte = in->data[in->read]
17410       31/xor-with %eax 0/r32/eax
17411       8a/copy-byte *(esi+ecx+0xc) 0/r32/AL
17412       # if (c == ' ') break
17413       3d/compare-eax-and 0x20/imm32/space
17414       74/jump-if-= break/disp8
17415       # if (c == '\r') break
17416       3d/compare-eax-and 0xd/imm32/carriage-return
17417       74/jump-if-= break/disp8
17418       # if (c == '\n') break
17419       3d/compare-eax-and 0xa/imm32/newline
17420       74/jump-if-= break/disp8
17421       # if (c == '(') break
17422       3d/compare-eax-and 0x28/imm32/open-paren
17423       0f 84/jump-if-= break/disp32
17424       # if (c == ')') break
17425       3d/compare-eax-and 0x29/imm32/close-paren
17426       0f 84/jump-if-= break/disp32
17427       # if (c == ',') break
17428       3d/compare-eax-and 0x2c/imm32/comma
17429       0f 84/jump-if-= break/disp32
17430       # ++in->read
17431       ff 0/subop/increment *(esi+4)
17432       #
17433       e9/jump loop/disp32
17434     }
17435 $next-mu-token:done:
17436     # out->end = &in->data[in->read]
17437     8b/-> *(esi+4) 1/r32/ecx
17438     8d/copy-address *(esi+ecx+0xc) 0/r32/eax
17439     89/<- *(edi+4) 0/r32/eax
17440 $next-mu-token:end:
17441     # . restore registers
17442     5f/pop-to-edi
17443     5e/pop-to-esi
17444     59/pop-to-ecx
17445     58/pop-to-eax
17446     # . epilogue
17447     89/<- %esp 5/r32/ebp
17448     5d/pop-to-ebp
17449     c3/return
17450 
17451 pos-or-insert-slice:  # arr: (addr stream (addr array byte)), s: (addr slice) -> index/eax: int
17452     # . prologue
17453     55/push-ebp
17454     89/<- %ebp 4/r32/esp
17455     # if (pos-slice(arr, s) != -1) return it
17456     (pos-slice *(ebp+8) *(ebp+0xc))  # => eax
17457     3d/compare-eax-and -1/imm32
17458     75/jump-if-!= $pos-or-insert-slice:end/disp8
17459 $pos-or-insert-slice:insert:
17460     # var s2/eax: (handle array byte)
17461     68/push 0/imm32
17462     68/push 0/imm32
17463     89/<- %eax 4/r32/esp
17464     (slice-to-string Heap *(ebp+0xc) %eax)
17465     # throw away alloc-id
17466     (lookup *eax *(eax+4))  # => eax
17467     (write-int *(ebp+8) %eax)
17468     (pos-slice *(ebp+8) *(ebp+0xc))  # => eax
17469 $pos-or-insert-slice:end:
17470     # . reclaim locals
17471     81 0/subop/add %esp 8/imm32
17472     # . epilogue
17473     89/<- %esp 5/r32/ebp
17474     5d/pop-to-ebp
17475     c3/return
17476 
17477 # return the index in an array of strings matching 's', -1 if not found
17478 # index is denominated in elements, not bytes
17479 pos-slice:  # arr: (addr stream (addr array byte)), s: (addr slice) -> index/eax: int
17480     # . prologue
17481     55/push-ebp
17482     89/<- %ebp 4/r32/esp
17483     # . save registers
17484     51/push-ecx
17485     52/push-edx
17486     53/push-ebx
17487     56/push-esi
17488 #?     (write-buffered Stderr "pos-slice: ")
17489 #?     (write-slice-buffered Stderr *(ebp+0xc))
17490 #?     (write-buffered Stderr "\n")
17491 #?     (flush Stderr)
17492     # esi = arr
17493     8b/-> *(ebp+8) 6/r32/esi
17494     # var index/ecx: int = 0
17495     b9/copy-to-ecx 0/imm32
17496     # var curr/edx: (addr (addr array byte)) = arr->data
17497     8d/copy-address *(esi+0xc) 2/r32/edx
17498     # var max/ebx: (addr (addr array byte)) = &arr->data[arr->write]
17499     8b/-> *esi 3/r32/ebx
17500     8d/copy-address *(esi+ebx+0xc) 3/r32/ebx
17501     {
17502 #?       (write-buffered Stderr "  ")
17503 #?       (write-int32-hex-buffered Stderr %ecx)
17504 #?       (write-buffered Stderr "\n")
17505 #?       (flush Stderr)
17506       # if (curr >= max) return -1
17507       39/compare %edx 3/r32/ebx
17508       b8/copy-to-eax -1/imm32
17509       73/jump-if-addr>= $pos-slice:end/disp8
17510       # if (slice-equal?(s, *curr)) break
17511       (slice-equal? *(ebp+0xc) *edx)  # => eax
17512       3d/compare-eax-and 0/imm32/false
17513       75/jump-if-!= break/disp8
17514       # ++index
17515       41/increment-ecx
17516       # curr += 4
17517       81 0/subop/add %edx 4/imm32
17518       #
17519       eb/jump loop/disp8
17520     }
17521     # return index
17522     89/<- %eax 1/r32/ecx
17523 $pos-slice:end:
17524 #?     (write-buffered Stderr "=> ")
17525 #?     (write-int32-hex-buffered Stderr %eax)
17526 #?     (write-buffered Stderr "\n")
17527     # . restore registers
17528     5e/pop-to-esi
17529     5b/pop-to-ebx
17530     5a/pop-to-edx
17531     59/pop-to-ecx
17532     # . epilogue
17533     89/<- %esp 5/r32/ebp
17534     5d/pop-to-ebp
17535     c3/return
17536 
17537 test-parse-var-with-type:
17538     # . prologue
17539     55/push-ebp
17540     89/<- %ebp 4/r32/esp
17541     # setup
17542     8b/-> *Primitive-type-ids 0/r32/eax
17543     89/<- *Type-id 0/r32/eax  # stream-write
17544     # (eax..ecx) = "x:"
17545     b8/copy-to-eax "x:"/imm32
17546     8b/-> *eax 1/r32/ecx
17547     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17548     05/add-to-eax 4/imm32
17549     # var slice/ecx: slice = {eax, ecx}
17550     51/push-ecx
17551     50/push-eax
17552     89/<- %ecx 4/r32/esp
17553     # _test-input-stream contains "int"
17554     (clear-stream _test-input-stream)
17555     (write _test-input-stream "int")
17556     # var v/edx: (handle var)
17557     68/push 0/imm32
17558     68/push 0/imm32
17559     89/<- %edx 4/r32/esp
17560     #
17561     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
17562     # var v-addr/edx: (addr var) = lookup(v)
17563     (lookup *edx *(edx+4))  # => eax
17564     89/<- %edx 0/r32/eax
17565     # check v-addr->name
17566     (lookup *edx *(edx+4))  # Var-name Var-name => eax
17567     (check-strings-equal %eax "x" "F - test-parse-var-with-type/name")
17568     # check v-addr->type
17569     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
17570     (check-ints-equal *eax 1 "F - test-parse-var-with-type/type:0")  # Type-tree-is-atom
17571     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-type/type:1")  # Type-tree-value
17572     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-type/type:2")  # Type-tree-right
17573     # . epilogue
17574     89/<- %esp 5/r32/ebp
17575     5d/pop-to-ebp
17576     c3/return
17577 
17578 test-parse-var-with-type-and-register:
17579     # . prologue
17580     55/push-ebp
17581     89/<- %ebp 4/r32/esp
17582     # setup
17583     8b/-> *Primitive-type-ids 0/r32/eax
17584     89/<- *Type-id 0/r32/eax  # stream-write
17585     # (eax..ecx) = "x/eax:"
17586     b8/copy-to-eax "x/eax:"/imm32
17587     8b/-> *eax 1/r32/ecx
17588     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17589     05/add-to-eax 4/imm32
17590     # var slice/ecx: slice = {eax, ecx}
17591     51/push-ecx
17592     50/push-eax
17593     89/<- %ecx 4/r32/esp
17594     # _test-input-stream contains "int"
17595     (clear-stream _test-input-stream)
17596     (write _test-input-stream "int")
17597     # var v/edx: (handle var)
17598     68/push 0/imm32
17599     68/push 0/imm32
17600     89/<- %edx 4/r32/esp
17601     #
17602     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
17603     # var v-addr/edx: (addr var) = lookup(v)
17604     (lookup *edx *(edx+4))  # => eax
17605     89/<- %edx 0/r32/eax
17606     # check v-addr->name
17607     (lookup *edx *(edx+4))  # Var-name Var-name => eax
17608     (check-strings-equal %eax "x" "F - test-parse-var-with-type-and-register/name")
17609     # check v-addr->register
17610     (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
17611     (check-strings-equal %eax "eax" "F - test-parse-var-with-type-and-register/register")
17612     # check v-addr->type
17613     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
17614     (check-ints-equal *eax 1 "F - test-parse-var-with-type-and-register/type:0")  # Type-tree-is-atom
17615     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-type-and-register/type:1")  # Type-tree-left
17616     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-type-and-register/type:2")  # Type-tree-right
17617     # . epilogue
17618     89/<- %esp 5/r32/ebp
17619     5d/pop-to-ebp
17620     c3/return
17621 
17622 test-parse-var-with-trailing-characters:
17623     # . prologue
17624     55/push-ebp
17625     89/<- %ebp 4/r32/esp
17626     # setup
17627     8b/-> *Primitive-type-ids 0/r32/eax
17628     89/<- *Type-id 0/r32/eax  # stream-write
17629     # (eax..ecx) = "x:"
17630     b8/copy-to-eax "x:"/imm32
17631     8b/-> *eax 1/r32/ecx
17632     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17633     05/add-to-eax 4/imm32
17634     # var slice/ecx: slice = {eax, ecx}
17635     51/push-ecx
17636     50/push-eax
17637     89/<- %ecx 4/r32/esp
17638     # _test-input-stream contains "int,"
17639     (clear-stream _test-input-stream)
17640     (write _test-input-stream "int,")
17641     # var v/edx: (handle var)
17642     68/push 0/imm32
17643     68/push 0/imm32
17644     89/<- %edx 4/r32/esp
17645     #
17646     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
17647     # var v-addr/edx: (addr var) = lookup(v)
17648     (lookup *edx *(edx+4))  # => eax
17649     89/<- %edx 0/r32/eax
17650     # check v-addr->name
17651     (lookup *edx *(edx+4))  # Var-name Var-name => eax
17652     (check-strings-equal %eax "x" "F - test-parse-var-with-trailing-characters/name")
17653     # check v-addr->register
17654     (check-ints-equal *(edx+0x18) 0 "F - test-parse-var-with-trailing-characters/register")  # Var-register
17655     # check v-addr->type
17656     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
17657     (check-ints-equal *eax 1 "F - test-parse-var-with-trailing-characters/type:0")  # Type-tree-is-atom
17658     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-trailing-characters/type:1")  # Type-tree-left
17659     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-trailing-characters/type:1")  # Type-tree-right
17660     # . epilogue
17661     89/<- %esp 5/r32/ebp
17662     5d/pop-to-ebp
17663     c3/return
17664 
17665 test-parse-var-with-register-and-trailing-characters:
17666     # . prologue
17667     55/push-ebp
17668     89/<- %ebp 4/r32/esp
17669     # setup
17670     8b/-> *Primitive-type-ids 0/r32/eax
17671     89/<- *Type-id 0/r32/eax  # stream-write
17672     # (eax..ecx) = "x/eax:"
17673     b8/copy-to-eax "x/eax:"/imm32
17674     8b/-> *eax 1/r32/ecx
17675     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17676     05/add-to-eax 4/imm32
17677     # var slice/ecx: slice = {eax, ecx}
17678     51/push-ecx
17679     50/push-eax
17680     89/<- %ecx 4/r32/esp
17681     # _test-input-stream contains "int,"
17682     (clear-stream _test-input-stream)
17683     (write _test-input-stream "int,")
17684     # var v/edx: (handle var)
17685     68/push 0/imm32
17686     68/push 0/imm32
17687     89/<- %edx 4/r32/esp
17688     #
17689     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
17690     # var v-addr/edx: (addr var) = lookup(v)
17691     (lookup *edx *(edx+4))  # => eax
17692     89/<- %edx 0/r32/eax
17693     # check v-addr->name
17694     (lookup *edx *(edx+4))  # Var-name Var-name => eax
17695     (check-strings-equal %eax "x" "F - test-parse-var-with-register-and-trailing-characters/name")
17696     # check v-addr->register
17697     (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
17698     (check-strings-equal %eax "eax" "F - test-parse-var-with-register-and-trailing-characters/register")
17699     # check v-addr->type
17700     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
17701     (check-ints-equal *eax 1 "F - test-parse-var-with-register-and-trailing-characters/type:0")  # Type-tree-is-atom
17702     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-register-and-trailing-characters/type:1")  # Type-tree-left
17703     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-register-and-trailing-characters/type:2")  # Type-tree-right
17704     # . epilogue
17705     89/<- %esp 5/r32/ebp
17706     5d/pop-to-ebp
17707     c3/return
17708 
17709 test-parse-var-with-compound-type:
17710     # . prologue
17711     55/push-ebp
17712     89/<- %ebp 4/r32/esp
17713     # setup
17714     8b/-> *Primitive-type-ids 0/r32/eax
17715     89/<- *Type-id 0/r32/eax  # stream-write
17716     # (eax..ecx) = "x:"
17717     b8/copy-to-eax "x:"/imm32
17718     8b/-> *eax 1/r32/ecx
17719     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17720     05/add-to-eax 4/imm32
17721     # var slice/ecx: slice = {eax, ecx}
17722     51/push-ecx
17723     50/push-eax
17724     89/<- %ecx 4/r32/esp
17725     # _test-input-stream contains "(addr int)"
17726     (clear-stream _test-input-stream)
17727     (write _test-input-stream "(addr int)")
17728     # var v/edx: (handle var)
17729     68/push 0/imm32
17730     68/push 0/imm32
17731     89/<- %edx 4/r32/esp
17732     #
17733     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
17734     # var v-addr/edx: (addr var) = lookup(v)
17735     (lookup *edx *(edx+4))  # => eax
17736     89/<- %edx 0/r32/eax
17737     # check v-addr->name
17738     (lookup *edx *(edx+4))  # Var-name Var-name => eax
17739     (check-strings-equal %eax "x" "F - test-parse-var-with-compound-type/name")
17740     # check v-addr->register
17741     (check-ints-equal *(edx+0x18) 0 "F - test-parse-var-with-compound-type/register")  # Var-register
17742     # - check v-addr->type
17743     # var type/edx: (addr type-tree) = var->type
17744     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
17745     89/<- %edx 0/r32/eax
17746     # type is a non-atom
17747     (check-ints-equal *edx 0 "F - test-parse-var-with-compound-type/type:0")  # Type-tree-is-atom
17748     # type->left == atom(addr)
17749     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
17750     (check-ints-equal *eax 1 "F - test-parse-var-with-compound-type/type:1")  # Type-tree-is-atom
17751     (check-ints-equal *(eax+4) 2 "F - test-parse-var-with-compound-type/type:2")  # Type-tree-value
17752     # type->right->left == atom(int)
17753     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
17754     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
17755     (check-ints-equal *eax 1 "F - test-parse-var-with-compound-type/type:3")  # Type-tree-is-atom
17756     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-compound-type/type:4")  # Type-tree-value
17757     # type->right->right == null
17758     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-compound-type/type:5")  # Type-tree-right
17759     # . epilogue
17760     89/<- %esp 5/r32/ebp
17761     5d/pop-to-ebp
17762     c3/return
17763 
17764 # identifier starts with a letter or '$' or '_'
17765 # no constraints at the moment on later letters
17766 # all we really want to do so far is exclude '{', '}' and '->'
17767 identifier?:  # in: (addr slice) -> result/eax: boolean
17768     # . prologue
17769     55/push-ebp
17770     89/<- %ebp 4/r32/esp
17771     # if (slice-empty?(in)) return false
17772     (slice-empty? *(ebp+8))  # => eax
17773     3d/compare-eax-and 0/imm32/false
17774     75/jump-if-!= $identifier?:false/disp8
17775     # var c/eax: byte = *in->start
17776     8b/-> *(ebp+8) 0/r32/eax
17777     8b/-> *eax 0/r32/eax
17778     8a/copy-byte *eax 0/r32/AL
17779     81 4/subop/and %eax 0xff/imm32
17780     # if (c == '$') return true
17781     3d/compare-eax-and 0x24/imm32/$
17782     74/jump-if-= $identifier?:true/disp8
17783     # if (c == '_') return true
17784     3d/compare-eax-and 0x5f/imm32/_
17785     74/jump-if-= $identifier?:true/disp8
17786     # drop case
17787     25/and-eax-with 0x5f/imm32
17788     # if (c < 'A') return false
17789     3d/compare-eax-and 0x41/imm32/A
17790     7c/jump-if-< $identifier?:false/disp8
17791     # if (c > 'Z') return false
17792     3d/compare-eax-and 0x5a/imm32/Z
17793     7f/jump-if-> $identifier?:false/disp8
17794     # otherwise return true
17795 $identifier?:true:
17796     b8/copy-to-eax 1/imm32/true
17797     eb/jump $identifier?:end/disp8
17798 $identifier?:false:
17799     b8/copy-to-eax 0/imm32/false
17800 $identifier?:end:
17801     # . epilogue
17802     89/<- %esp 5/r32/ebp
17803     5d/pop-to-ebp
17804     c3/return
17805 
17806 test-is-identifier-dollar:
17807     # . prologue
17808     55/push-ebp
17809     89/<- %ebp 4/r32/esp
17810     # (eax..ecx) = "$a"
17811     b8/copy-to-eax "$a"/imm32
17812     8b/-> *eax 1/r32/ecx
17813     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17814     05/add-to-eax 4/imm32
17815     # var slice/ecx: slice = {eax, ecx}
17816     51/push-ecx
17817     50/push-eax
17818     89/<- %ecx 4/r32/esp
17819     #
17820     (identifier? %ecx)
17821     (check-ints-equal %eax 1 "F - test-is-identifier-dollar")
17822     # . epilogue
17823     89/<- %esp 5/r32/ebp
17824     5d/pop-to-ebp
17825     c3/return
17826 
17827 test-is-identifier-underscore:
17828     # . prologue
17829     55/push-ebp
17830     89/<- %ebp 4/r32/esp
17831     # (eax..ecx) = "_a"
17832     b8/copy-to-eax "_a"/imm32
17833     8b/-> *eax 1/r32/ecx
17834     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17835     05/add-to-eax 4/imm32
17836     # var slice/ecx: slice = {eax, ecx}
17837     51/push-ecx
17838     50/push-eax
17839     89/<- %ecx 4/r32/esp
17840     #
17841     (identifier? %ecx)
17842     (check-ints-equal %eax 1 "F - test-is-identifier-underscore")
17843     # . epilogue
17844     89/<- %esp 5/r32/ebp
17845     5d/pop-to-ebp
17846     c3/return
17847 
17848 test-is-identifier-a:
17849     # . prologue
17850     55/push-ebp
17851     89/<- %ebp 4/r32/esp
17852     # (eax..ecx) = "a$"
17853     b8/copy-to-eax "a$"/imm32
17854     8b/-> *eax 1/r32/ecx
17855     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17856     05/add-to-eax 4/imm32
17857     # var slice/ecx: slice = {eax, ecx}
17858     51/push-ecx
17859     50/push-eax
17860     89/<- %ecx 4/r32/esp
17861     #
17862     (identifier? %ecx)
17863     (check-ints-equal %eax 1 "F - test-is-identifier-a")
17864     # . epilogue
17865     89/<- %esp 5/r32/ebp
17866     5d/pop-to-ebp
17867     c3/return
17868 
17869 test-is-identifier-z:
17870     # . prologue
17871     55/push-ebp
17872     89/<- %ebp 4/r32/esp
17873     # (eax..ecx) = "z$"
17874     b8/copy-to-eax "z$"/imm32
17875     8b/-> *eax 1/r32/ecx
17876     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17877     05/add-to-eax 4/imm32
17878     # var slice/ecx: slice = {eax, ecx}
17879     51/push-ecx
17880     50/push-eax
17881     89/<- %ecx 4/r32/esp
17882     #
17883     (identifier? %ecx)
17884     (check-ints-equal %eax 1 "F - test-is-identifier-z")
17885     # . epilogue
17886     89/<- %esp 5/r32/ebp
17887     5d/pop-to-ebp
17888     c3/return
17889 
17890 test-is-identifier-A:
17891     # . prologue
17892     55/push-ebp
17893     89/<- %ebp 4/r32/esp
17894     # (eax..ecx) = "A$"
17895     b8/copy-to-eax "A$"/imm32
17896     8b/-> *eax 1/r32/ecx
17897     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17898     05/add-to-eax 4/imm32
17899     # var slice/ecx: slice = {eax, ecx}
17900     51/push-ecx
17901     50/push-eax
17902     89/<- %ecx 4/r32/esp
17903     #
17904     (identifier? %ecx)
17905     (check-ints-equal %eax 1 "F - test-is-identifier-A")
17906     # . epilogue
17907     89/<- %esp 5/r32/ebp
17908     5d/pop-to-ebp
17909     c3/return
17910 
17911 test-is-identifier-Z:
17912     # . prologue
17913     55/push-ebp
17914     89/<- %ebp 4/r32/esp
17915     # (eax..ecx) = "Z$"
17916     b8/copy-to-eax "Z$"/imm32
17917     8b/-> *eax 1/r32/ecx
17918     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17919     05/add-to-eax 4/imm32
17920     # var slice/ecx: slice = {eax, ecx}
17921     51/push-ecx
17922     50/push-eax
17923     89/<- %ecx 4/r32/esp
17924     #
17925     (identifier? %ecx)
17926     (check-ints-equal %eax 1 "F - test-is-identifier-Z")
17927     # . epilogue
17928     89/<- %esp 5/r32/ebp
17929     5d/pop-to-ebp
17930     c3/return
17931 
17932 test-is-identifier-at:
17933     # character before 'A' is invalid
17934     # . prologue
17935     55/push-ebp
17936     89/<- %ebp 4/r32/esp
17937     # (eax..ecx) = "@a"
17938     b8/copy-to-eax "@a"/imm32
17939     8b/-> *eax 1/r32/ecx
17940     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17941     05/add-to-eax 4/imm32
17942     # var slice/ecx: slice = {eax, ecx}
17943     51/push-ecx
17944     50/push-eax
17945     89/<- %ecx 4/r32/esp
17946     #
17947     (identifier? %ecx)
17948     (check-ints-equal %eax 0 "F - test-is-identifier-@")
17949     # . epilogue
17950     89/<- %esp 5/r32/ebp
17951     5d/pop-to-ebp
17952     c3/return
17953 
17954 test-is-identifier-square-bracket:
17955     # character after 'Z' is invalid
17956     # . prologue
17957     55/push-ebp
17958     89/<- %ebp 4/r32/esp
17959     # (eax..ecx) = "[a"
17960     b8/copy-to-eax "[a"/imm32
17961     8b/-> *eax 1/r32/ecx
17962     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17963     05/add-to-eax 4/imm32
17964     # var slice/ecx: slice = {eax, ecx}
17965     51/push-ecx
17966     50/push-eax
17967     89/<- %ecx 4/r32/esp
17968     #
17969     (identifier? %ecx)
17970     (check-ints-equal %eax 0 "F - test-is-identifier-@")
17971     # . epilogue
17972     89/<- %esp 5/r32/ebp
17973     5d/pop-to-ebp
17974     c3/return
17975 
17976 test-is-identifier-backtick:
17977     # character before 'a' is invalid
17978     # . prologue
17979     55/push-ebp
17980     89/<- %ebp 4/r32/esp
17981     # (eax..ecx) = "`a"
17982     b8/copy-to-eax "`a"/imm32
17983     8b/-> *eax 1/r32/ecx
17984     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17985     05/add-to-eax 4/imm32
17986     # var slice/ecx: slice = {eax, ecx}
17987     51/push-ecx
17988     50/push-eax
17989     89/<- %ecx 4/r32/esp
17990     #
17991     (identifier? %ecx)
17992     (check-ints-equal %eax 0 "F - test-is-identifier-backtick")
17993     # . epilogue
17994     89/<- %esp 5/r32/ebp
17995     5d/pop-to-ebp
17996     c3/return
17997 
17998 test-is-identifier-curly-brace-open:
17999     # character after 'z' is invalid; also used for blocks
18000     # . prologue
18001     55/push-ebp
18002     89/<- %ebp 4/r32/esp
18003     # (eax..ecx) = "{a"
18004     b8/copy-to-eax "{a"/imm32
18005     8b/-> *eax 1/r32/ecx
18006     8d/copy-address *(eax+ecx+4) 1/r32/ecx
18007     05/add-to-eax 4/imm32
18008     # var slice/ecx: slice = {eax, ecx}
18009     51/push-ecx
18010     50/push-eax
18011     89/<- %ecx 4/r32/esp
18012     #
18013     (identifier? %ecx)
18014     (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-open")
18015     # . epilogue
18016     89/<- %esp 5/r32/ebp
18017     5d/pop-to-ebp
18018     c3/return
18019 
18020 test-is-identifier-curly-brace-close:
18021     # . prologue
18022     55/push-ebp
18023     89/<- %ebp 4/r32/esp
18024     # (eax..ecx) = "}a"
18025     b8/copy-to-eax "}a"/imm32
18026     8b/-> *eax 1/r32/ecx
18027     8d/copy-address *(eax+ecx+4) 1/r32/ecx
18028     05/add-to-eax 4/imm32
18029     # var slice/ecx: slice = {eax, ecx}
18030     51/push-ecx
18031     50/push-eax
18032     89/<- %ecx 4/r32/esp
18033     #
18034     (identifier? %ecx)
18035     (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-close")
18036     # . epilogue
18037     89/<- %esp 5/r32/ebp
18038     5d/pop-to-ebp
18039     c3/return
18040 
18041 test-is-identifier-hyphen:
18042     # disallow leading '-' since '->' has special meaning
18043     # . prologue
18044     55/push-ebp
18045     89/<- %ebp 4/r32/esp
18046     # (eax..ecx) = "-a"
18047     b8/copy-to-eax "-a"/imm32
18048     8b/-> *eax 1/r32/ecx
18049     8d/copy-address *(eax+ecx+4) 1/r32/ecx
18050     05/add-to-eax 4/imm32
18051     # var slice/ecx: slice = {eax, ecx}
18052     51/push-ecx
18053     50/push-eax
18054     89/<- %ecx 4/r32/esp
18055     #
18056     (identifier? %ecx)
18057     (check-ints-equal %eax 0 "F - test-is-identifier-hyphen")
18058     # . epilogue
18059     89/<- %esp 5/r32/ebp
18060     5d/pop-to-ebp
18061     c3/return
18062 
18063 populate-mu-function-body:  # in: (addr buffered-file), out: (addr function), vars: (addr stack live-var), err: (addr buffered-file), ed: (addr exit-descriptor)
18064     # . prologue
18065     55/push-ebp
18066     89/<- %ebp 4/r32/esp
18067     # . save registers
18068     50/push-eax
18069     56/push-esi
18070     57/push-edi
18071     # esi = in
18072     8b/-> *(ebp+8) 6/r32/esi
18073     # edi = out
18074     8b/-> *(ebp+0xc) 7/r32/edi
18075     # initialize some global state
18076     c7 0/subop/copy *Curr-block-depth 1/imm32
18077     # parse-mu-block(in, vars, out, out->body)
18078     8d/copy-address *(edi+0x18) 0/r32/eax  # Function-body
18079     (parse-mu-block %esi *(ebp+0x10) %edi %eax *(ebp+0x14) *(ebp+0x18))
18080 $populate-mu-function-body:end:
18081     # . restore registers
18082     5f/pop-to-edi
18083     5e/pop-to-esi
18084     58/pop-to-eax
18085     # . epilogue
18086     89/<- %esp 5/r32/ebp
18087     5d/pop-to-ebp
18088     c3/return
18089 
18090 # parses a block, assuming that the leading '{' has already been read by the caller
18091 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)
18092     # pseudocode:
18093     #   var line: (stream byte 512)
18094     #   var word-slice: slice
18095     #   allocate(Heap, Stmt-size, out)
18096     #   var out-addr: (addr block) = lookup(*out)
18097     #   out-addr->tag = 0/block
18098     #   out-addr->var = some unique name
18099     #   push(vars, {out-addr->var, false})
18100     #   while true                                  # line loop
18101     #     clear-stream(line)
18102     #     read-line-buffered(in, line)
18103     #     if (line->write == 0) break               # end of file
18104     #     word-slice = next-mu-token(line)
18105     #     if slice-empty?(word-slice)               # end of line
18106     #       continue
18107     #     else if slice-starts-with?(word-slice, "#")
18108     #       continue
18109     #     else if slice-equal?(word-slice, "{")
18110     #       assert(no-tokens-in(line))
18111     #       block = parse-mu-block(in, vars, fn)
18112     #       append-to-block(out-addr, block)
18113     #     else if slice-equal?(word-slice, "}")
18114     #       break
18115     #     else if slice-ends-with?(word-slice, ":")
18116     #       # TODO: error-check the rest of 'line'
18117     #       --word-slice->end to skip ':'
18118     #       named-block = parse-mu-named-block(word-slice, in, vars, fn)
18119     #       append-to-block(out-addr, named-block)
18120     #     else if slice-equal?(word-slice, "var")
18121     #       var-def = parse-mu-var-def(line, vars, fn)
18122     #       append-to-block(out-addr, var-def)
18123     #     else
18124     #       stmt = parse-mu-stmt(line, vars, fn)
18125     #       append-to-block(out-addr, stmt)
18126     #   pop(vars)
18127     #
18128     # . prologue
18129     55/push-ebp
18130     89/<- %ebp 4/r32/esp
18131     # . save registers
18132     50/push-eax
18133     51/push-ecx
18134     52/push-edx
18135     53/push-ebx
18136     57/push-edi
18137     # var line/ecx: (stream byte 512)
18138     81 5/subop/subtract %esp 0x200/imm32
18139     68/push 0x200/imm32/size
18140     68/push 0/imm32/read
18141     68/push 0/imm32/write
18142     89/<- %ecx 4/r32/esp
18143     # var word-slice/edx: slice
18144     68/push 0/imm32/end
18145     68/push 0/imm32/start
18146     89/<- %edx 4/r32/esp
18147     # allocate into out
18148     (allocate Heap *Stmt-size *(ebp+0x14))
18149     # var out-addr/edi: (addr block) = lookup(*out)
18150     8b/-> *(ebp+0x14) 7/r32/edi
18151     (lookup *edi *(edi+4))  # => eax
18152     89/<- %edi 0/r32/eax
18153     # out-addr->tag is 0 (block) by default
18154     # set out-addr->var
18155     8d/copy-address *(edi+0xc) 0/r32/eax  # Block-var
18156     (new-block-name *(ebp+0x10) %eax)
18157     # push(vars, out-addr->var)
18158     (push *(ebp+0xc) *(edi+0xc))  # Block-var
18159     (push *(ebp+0xc) *(edi+0x10))  # Block-var
18160     (push *(ebp+0xc) 0)  # false
18161     # increment *Curr-block-depth
18162     ff 0/subop/increment *Curr-block-depth
18163     {
18164 $parse-mu-block:line-loop:
18165       # line = read-line-buffered(in)
18166       (clear-stream %ecx)
18167       (read-line-buffered *(ebp+8) %ecx)
18168 #?       (write-buffered Stderr "line: ")
18169 #?       (write-stream-data Stderr %ecx)
18170 #? #?       (write-buffered Stderr Newline)  # line has its own newline
18171 #?       (flush Stderr)
18172 #?       (rewind-stream %ecx)
18173       # if (line->write == 0) break
18174       81 7/subop/compare *ecx 0/imm32
18175       0f 84/jump-if-= break/disp32
18176 #?       (write-buffered Stderr "vars:\n")
18177 #?       (dump-vars *(ebp+0xc))
18178       # word-slice = next-mu-token(line)
18179       (next-mu-token %ecx %edx)
18180 #?       (write-buffered Stderr "word: ")
18181 #?       (write-slice-buffered Stderr %edx)
18182 #?       (write-buffered Stderr Newline)
18183 #?       (flush Stderr)
18184       # if slice-empty?(word-slice) continue
18185       (slice-empty? %edx)
18186       3d/compare-eax-and 0/imm32/false
18187       0f 85/jump-if-!= loop/disp32
18188       # if (slice-starts-with?(word-slice, '#') continue
18189       # . eax = *word-slice->start
18190       8b/-> *edx 0/r32/eax
18191       8a/copy-byte *eax 0/r32/AL
18192       81 4/subop/and %eax 0xff/imm32
18193       # . if (eax == '#') continue
18194       3d/compare-eax-and 0x23/imm32/hash
18195       0f 84/jump-if-= loop/disp32
18196       # if slice-equal?(word-slice, "{")
18197       {
18198 $parse-mu-block:check-for-block:
18199         (slice-equal? %edx "{")
18200         3d/compare-eax-and 0/imm32/false
18201         74/jump-if-= break/disp8
18202         (check-no-tokens-left %ecx)
18203         # parse new block and append
18204         # . var tmp/eax: (handle block)
18205         68/push 0/imm32
18206         68/push 0/imm32
18207         89/<- %eax 4/r32/esp
18208         # .
18209         (parse-mu-block *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
18210         (append-to-block Heap %edi  *eax *(eax+4))
18211         # . reclaim tmp
18212         81 0/subop/add %esp 8/imm32
18213         # .
18214         e9/jump $parse-mu-block:line-loop/disp32
18215       }
18216       # if slice-equal?(word-slice, "}") break
18217 $parse-mu-block:check-for-end:
18218       (slice-equal? %edx "}")
18219       3d/compare-eax-and 0/imm32/false
18220       0f 85/jump-if-!= break/disp32
18221       # if slice-ends-with?(word-slice, ":") parse named block and append
18222       {
18223 $parse-mu-block:check-for-named-block:
18224         # . eax = *(word-slice->end-1)
18225         8b/-> *(edx+4) 0/r32/eax
18226         48/decrement-eax
18227         8a/copy-byte *eax 0/r32/AL
18228         81 4/subop/and %eax 0xff/imm32
18229         # . if (eax != ':') break
18230         3d/compare-eax-and 0x3a/imm32/colon
18231         0f 85/jump-if-!= break/disp32
18232         # TODO: error-check the rest of 'line'
18233         #
18234         # skip ':'
18235         ff 1/subop/decrement *(edx+4)  # Slice-end
18236         # var tmp/eax: (handle block)
18237         68/push 0/imm32
18238         68/push 0/imm32
18239         89/<- %eax 4/r32/esp
18240         #
18241         (parse-mu-named-block %edx *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
18242         (append-to-block Heap %edi  *eax *(eax+4))
18243         # reclaim tmp
18244         81 0/subop/add %esp 8/imm32
18245         #
18246         e9/jump $parse-mu-block:line-loop/disp32
18247       }
18248       # if slice-equal?(word-slice, "var")
18249       {
18250 $parse-mu-block:check-for-var:
18251         (slice-equal? %edx "var")
18252         3d/compare-eax-and 0/imm32/false
18253         74/jump-if-= break/disp8
18254         # var tmp/eax: (handle block)
18255         68/push 0/imm32
18256         68/push 0/imm32
18257         89/<- %eax 4/r32/esp
18258         #
18259         (parse-mu-var-def %ecx *(ebp+0xc) %eax *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
18260         (append-to-block Heap %edi  *eax *(eax+4))
18261         # reclaim tmp
18262         81 0/subop/add %esp 8/imm32
18263         #
18264         e9/jump $parse-mu-block:line-loop/disp32
18265       }
18266 $parse-mu-block:regular-stmt:
18267       # otherwise
18268       # var tmp/eax: (handle block)
18269       68/push 0/imm32
18270       68/push 0/imm32
18271       89/<- %eax 4/r32/esp
18272       #
18273       (parse-mu-stmt %ecx *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
18274       (append-to-block Heap %edi  *eax *(eax+4))
18275       # reclaim tmp
18276       81 0/subop/add %esp 8/imm32
18277       #
18278       e9/jump loop/disp32
18279     } # end line loop
18280     (clean-up-blocks *(ebp+0xc) *Curr-block-depth *(ebp+0x10))
18281     # decrement *Curr-block-depth
18282     ff 1/subop/decrement *Curr-block-depth
18283     # pop(vars)
18284     (pop *(ebp+0xc))  # => eax
18285     (pop *(ebp+0xc))  # => eax
18286     (pop *(ebp+0xc))  # => eax
18287 $parse-mu-block:end:
18288     # . reclaim locals
18289     81 0/subop/add %esp 0x214/imm32
18290     # . restore registers
18291     5f/pop-to-edi
18292     5b/pop-to-ebx
18293     5a/pop-to-edx
18294     59/pop-to-ecx
18295     58/pop-to-eax
18296     # . epilogue
18297     89/<- %esp 5/r32/ebp
18298     5d/pop-to-ebp
18299     c3/return
18300 
18301 $parse-mu-block:abort:
18302     # error("'{' or '}' should be on its own line, but got '")
18303     (write-buffered *(ebp+0x18) "'{' or '}' should be on its own line, but got '")
18304     (rewind-stream %ecx)
18305     (write-stream-data *(ebp+0x18) %ecx)
18306     (write-buffered *(ebp+0x18) "'\n")
18307     (flush *(ebp+0x18))
18308     (stop *(ebp+0x1c) 1)
18309     # never gets here
18310 
18311 new-block-name:  # fn: (addr function), out: (addr handle var)
18312     # . prologue
18313     55/push-ebp
18314     89/<- %ebp 4/r32/esp
18315     # . save registers
18316     50/push-eax
18317     51/push-ecx
18318     52/push-edx
18319     # var n/ecx: int = len(fn->name) + 10 for an int + 2 for '$:'
18320     8b/-> *(ebp+8) 0/r32/eax
18321     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18322     8b/-> *eax 0/r32/eax  # String-size
18323     05/add-to-eax 0xd/imm32  # 10 + 2 for '$:'
18324     89/<- %ecx 0/r32/eax
18325     # var name/edx: (stream byte n)
18326     29/subtract-from %esp 1/r32/ecx
18327     ff 6/subop/push %ecx
18328     68/push 0/imm32/read
18329     68/push 0/imm32/write
18330     89/<- %edx 4/r32/esp
18331     (clear-stream %edx)
18332     # eax = fn->name
18333     8b/-> *(ebp+8) 0/r32/eax
18334     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18335     # construct result using Next-block-index (and increment it)
18336     (write %edx "$")
18337     (write %edx %eax)
18338     (write %edx ":")
18339     (write-int32-hex %edx *Next-block-index)
18340     ff 0/subop/increment *Next-block-index
18341     # var s/eax: slice = {name->data, name->data + name->write}  (clobbering edx)
18342     # . eax = name->write
18343     8b/-> *edx 0/r32/eax
18344     # . edx = name->data
18345     8d/copy-address *(edx+0xc) 2/r32/edx
18346     # . eax = name->write + name->data
18347     01/add-to %eax 2/r32/edx
18348     # . push {edx, eax}
18349     ff 6/subop/push %eax
18350     ff 6/subop/push %edx
18351     89/<- %eax 4/r32/esp
18352     # out = new literal(s)
18353     (new-literal Heap %eax *(ebp+0xc))
18354 #?     8b/-> *(ebp+0xc) 0/r32/eax
18355 #?     (write-buffered Stderr "type allocid in caller after new-literal: ")
18356 #?     (write-int32-hex-buffered Stderr *(eax+8))
18357 #?     (write-buffered Stderr " for var ")
18358 #?     (write-int32-hex-buffered Stderr %eax)
18359 #?     (write-buffered Stderr Newline)
18360 #?     (flush Stderr)
18361 $new-block-name:end:
18362     # . reclaim locals
18363     81 0/subop/add %ecx 0xc/imm32  # name.{read/write/len}
18364     81 0/subop/add %ecx 8/imm32  # slice
18365     01/add-to %esp 1/r32/ecx
18366     # . restore registers
18367     5a/pop-to-edx
18368     59/pop-to-ecx
18369     58/pop-to-eax
18370     # . epilogue
18371     89/<- %esp 5/r32/ebp
18372     5d/pop-to-ebp
18373     c3/return
18374 
18375 check-no-tokens-left:  # line: (addr stream byte)
18376     # . prologue
18377     55/push-ebp
18378     89/<- %ebp 4/r32/esp
18379     # . save registers
18380     50/push-eax
18381     51/push-ecx
18382     # var s/ecx: slice
18383     68/push 0/imm32/end
18384     68/push 0/imm32/start
18385     89/<- %ecx 4/r32/esp
18386     #
18387     (next-mu-token *(ebp+8) %ecx)
18388     # if slice-empty?(s) return
18389     (slice-empty? %ecx)
18390     3d/compare-eax-and 0/imm32/false
18391     75/jump-if-!= $check-no-tokens-left:end/disp8
18392     # if (slice-starts-with?(s, '#') return
18393     # . eax = *s->start
18394     8b/-> *edx 0/r32/eax
18395     8a/copy-byte *eax 0/r32/AL
18396     81 4/subop/and %eax 0xff/imm32
18397     # . if (eax == '#') continue
18398     3d/compare-eax-and 0x23/imm32/hash
18399     74/jump-if-= $check-no-tokens-left:end/disp8
18400     # abort
18401     (write-buffered Stderr "'{' or '}' should be on its own line, but got '")
18402     (rewind-stream %ecx)
18403     (write-stream 2 %ecx)
18404     (write-buffered Stderr "'\n")
18405     (flush Stderr)
18406     # . syscall(exit, 1)
18407     bb/copy-to-ebx  1/imm32
18408     e8/call syscall_exit/disp32
18409     # never gets here
18410 $check-no-tokens-left:end:
18411     # . reclaim locals
18412     81 0/subop/add %esp 8/imm32
18413     # . restore registers
18414     59/pop-to-ecx
18415     58/pop-to-eax
18416     # . epilogue
18417     89/<- %esp 5/r32/ebp
18418     5d/pop-to-ebp
18419     c3/return
18420 
18421 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)
18422     # pseudocode:
18423     #   var v: (handle var)
18424     #   new-literal(name, v)
18425     #   push(vars, {v, false})
18426     #   parse-mu-block(in, vars, fn, out)
18427     #   pop(vars)
18428     #   out->tag = block
18429     #   out->var = v
18430     #
18431     # . prologue
18432     55/push-ebp
18433     89/<- %ebp 4/r32/esp
18434     # . save registers
18435     50/push-eax
18436     51/push-ecx
18437     57/push-edi
18438     # var v/ecx: (handle var)
18439     68/push 0/imm32
18440     68/push 0/imm32
18441     89/<- %ecx 4/r32/esp
18442     #
18443     (new-literal Heap *(ebp+8) %ecx)
18444     # push(vars, v)
18445     (push *(ebp+0x10) *ecx)
18446     (push *(ebp+0x10) *(ecx+4))
18447     (push *(ebp+0x10) 0)  # false
18448     #
18449     (parse-mu-block *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c) *(ebp+0x20))
18450     # pop v off vars
18451     (pop *(ebp+0x10))  # => eax
18452     (pop *(ebp+0x10))  # => eax
18453     (pop *(ebp+0x10))  # => eax
18454     # var out-addr/edi: (addr stmt) = lookup(*out)
18455     8b/-> *(ebp+0x18) 7/r32/edi
18456     (lookup *edi *(edi+4))  # => eax
18457     89/<- %edi 0/r32/eax
18458     # out-addr->tag = named-block
18459     c7 0/subop/copy *edi 0/imm32/block  # Stmt-tag
18460     # out-addr->var = v
18461     8b/-> *ecx 0/r32/eax
18462     89/<- *(edi+0xc) 0/r32/eax  # Block-var
18463     8b/-> *(ecx+4) 0/r32/eax
18464     89/<- *(edi+0x10) 0/r32/eax  # Block-var
18465 $parse-mu-named-block:end:
18466     # . reclaim locals
18467     81 0/subop/add %esp 8/imm32
18468     # . restore registers
18469     5f/pop-to-edi
18470     59/pop-to-ecx
18471     58/pop-to-eax
18472     # . epilogue
18473     89/<- %esp 5/r32/ebp
18474     5d/pop-to-ebp
18475     c3/return
18476 
18477 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)
18478     # . prologue
18479     55/push-ebp
18480     89/<- %ebp 4/r32/esp
18481     # . save registers
18482     50/push-eax
18483     51/push-ecx
18484     52/push-edx
18485     56/push-esi
18486     57/push-edi
18487     # edi = out
18488     8b/-> *(ebp+0x10) 7/r32/edi
18489     # var word-slice/ecx: slice
18490     68/push 0/imm32/end
18491     68/push 0/imm32/start
18492     89/<- %ecx 4/r32/esp
18493     # var v/edx: (handle var)
18494     68/push 0/imm32
18495     68/push 0/imm32
18496     89/<- %edx 4/r32/esp
18497     # v = parse-var-with-type(next-mu-token(line))
18498     (next-mu-token *(ebp+8) %ecx)
18499     {
18500       # just for tests, support null fn
18501       8b/-> *(ebp+0x14) 0/r32/eax
18502       3d/compare-eax-and 0/imm32
18503       74/jump-if-= break/disp8
18504       (lookup *eax *(eax+4))  # Var-name Var-name => eax
18505     }
18506     (parse-var-with-type %ecx *(ebp+8) %edx %eax *(ebp+0x18) *(ebp+0x1c))
18507     # var v-addr/esi: (addr var)
18508     (lookup *edx *(edx+4))  # => eax
18509     89/<- %esi 0/r32/eax
18510     # v->block-depth = *Curr-block-depth
18511     8b/-> *Curr-block-depth 0/r32/eax
18512     89/<- *(esi+0x10) 0/r32/eax  # Var-block-depth
18513     # either v has no register and there's no more to this line
18514     81 7/subop/compare *(esi+0x18) 0/imm32
18515     {
18516       75/jump-if-!= break/disp8
18517       # if v-addr->type == byte, abort
18518       (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
18519       (simple-mu-type? %eax 8)  # byte => eax
18520       3d/compare-eax-and 0/imm32/false
18521       0f 85/jump-if-!= $parse-mu-var-def:error-byte-on-stack/disp32
18522       # ensure that there's nothing else on this line
18523       (next-mu-token *(ebp+8) %ecx)
18524       (slice-empty? %ecx)  # => eax
18525       3d/compare-eax-and 0/imm32/false
18526       0f 84/jump-if-= $parse-mu-var-def:error2/disp32
18527       #
18528       (new-var-def Heap  *edx *(edx+4)  %edi)
18529       e9/jump $parse-mu-var-def:update-vars/disp32
18530     }
18531     # or v has a register and there's more to this line
18532     {
18533       0f 84/jump-if-= break/disp32
18534       # if v-addr->type == byte, check for unsupported registers
18535       {
18536         (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
18537         (simple-mu-type? %eax 8)  # byte => eax
18538         3d/compare-eax-and 0/imm32/false
18539         74/jump-if-= break/disp8
18540         (lookup *(esi+0x18) *(esi+0x1c))  # => eax
18541         (string-equal? %eax "esi")  # => eax
18542         3d/compare-eax-and 0/imm32/false
18543         0f 85/jump-if-!= $parse-mu-var-def:error-byte-registers/disp32
18544         (lookup *(esi+0x18) *(esi+0x1c))  # => eax
18545         (string-equal? %eax "edi")  # => eax
18546         3d/compare-eax-and 0/imm32/false
18547         0f 85/jump-if-!= $parse-mu-var-def:error-byte-registers/disp32
18548       }
18549       # TODO: vars of type 'byte' should only be initialized by clearing to 0
18550       # ensure that the next word is '<-'
18551       (next-mu-token *(ebp+8) %ecx)
18552       (slice-equal? %ecx "<-")  # => eax
18553       3d/compare-eax-and 0/imm32/false
18554       0f 84/jump-if-= $parse-mu-var-def:error1/disp32
18555       #
18556       (new-reg-var-def Heap  *edx *(edx+4)  %edi)
18557       (lookup *edi *(edi+4))  # => eax
18558       (add-operation-and-inputs-to-stmt %eax *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
18559     }
18560 $parse-mu-var-def:update-vars:
18561     # push 'v' at end of function
18562     (push *(ebp+0xc) *edx)
18563     (push *(ebp+0xc) *(edx+4))
18564     (push *(ebp+0xc) 0)  # Live-var-register-spilled is unused during parsing
18565 $parse-mu-var-def:end:
18566     # . reclaim locals
18567     81 0/subop/add %esp 0x10/imm32
18568     # . restore registers
18569     5f/pop-to-edi
18570     5e/pop-to-esi
18571     5a/pop-to-edx
18572     59/pop-to-ecx
18573     58/pop-to-eax
18574     # . epilogue
18575     89/<- %esp 5/r32/ebp
18576     5d/pop-to-ebp
18577     c3/return
18578 
18579 $parse-mu-var-def:error1:
18580     (rewind-stream *(ebp+8))
18581     # error("register variable requires a valid instruction to initialize but got '" line "'\n")
18582     (write-buffered *(ebp+0x18) "register variable requires a valid instruction to initialize but got '")
18583     (flush *(ebp+0x18))
18584     (write-stream-data *(ebp+0x18) *(ebp+8))
18585     (write-buffered *(ebp+0x18) "'\n")
18586     (flush *(ebp+0x18))
18587     (stop *(ebp+0x1c) 1)
18588     # never gets here
18589 
18590 $parse-mu-var-def:error2:
18591     # error("fn " fn ": var " var ": variables on the stack can't take an initializer\n")
18592     (write-buffered *(ebp+0x18) "fn ")
18593     8b/-> *(ebp+0x14) 0/r32/eax
18594     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18595     (write-buffered *(ebp+0x18) %eax)
18596     (write-buffered *(ebp+0x18) ": var ")
18597     # var v-addr/eax: (addr var) = lookup(v)
18598     (lookup *edx *(edx+4))  # => eax
18599     (lookup *eax *(eax+4))  # Var-name Var-name => eax
18600     (write-buffered *(ebp+0x18) %eax)
18601     (write-buffered *(ebp+0x18) ": variables on the stack can't take an initializer\n")
18602     (flush *(ebp+0x18))
18603     (stop *(ebp+0x1c) 1)
18604     # never gets here
18605 
18606 $parse-mu-var-def:error-byte-on-stack:
18607     # error("fn " fn ": var '" var "' of type 'byte' cannot be on the stack\n")
18608     (write-buffered *(ebp+0x18) "fn ")
18609     8b/-> *(ebp+0x14) 0/r32/eax
18610     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18611     (write-buffered *(ebp+0x18) %eax)
18612     (write-buffered *(ebp+0x18) ": var '")
18613     # var v-addr/eax: (addr var) = lookup(v)
18614     (lookup *edx *(edx+4))  # => eax
18615     (lookup *eax *(eax+4))  # Var-name Var-name => eax
18616     (write-buffered *(ebp+0x18) %eax)
18617     (write-buffered *(ebp+0x18) "' of type 'byte' cannot be on the stack\n")
18618     (flush *(ebp+0x18))
18619     (stop *(ebp+0x1c) 1)
18620     # never gets here
18621 
18622 $parse-mu-var-def:error-byte-registers:
18623     # error("fn " fn ": var '" var "' of type 'byte' cannot be in esi or edi\n")
18624     (write-buffered *(ebp+0x18) "fn ")
18625     8b/-> *(ebp+0x14) 0/r32/eax
18626     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18627     (write-buffered *(ebp+0x18) %eax)
18628     (write-buffered *(ebp+0x18) ": var '")
18629     # var v-addr/eax: (addr var) = lookup(v)
18630     (lookup *edx *(edx+4))  # => eax
18631     (lookup *eax *(eax+4))  # Var-name Var-name => eax
18632     (write-buffered *(ebp+0x18) %eax)
18633     (write-buffered *(ebp+0x18) "' of type 'byte' cannot be in esi or edi\n")
18634     (flush *(ebp+0x18))
18635     (stop *(ebp+0x1c) 1)
18636     # never gets here
18637 
18638 test-parse-mu-var-def:
18639     # 'var n: int'
18640     # . prologue
18641     55/push-ebp
18642     89/<- %ebp 4/r32/esp
18643     # setup
18644     8b/-> *Primitive-type-ids 0/r32/eax
18645     89/<- *Type-id 0/r32/eax  # stream-write
18646     (clear-stream _test-input-stream)
18647     (write _test-input-stream "n: int\n")  # caller has consumed the 'var'
18648     c7 0/subop/copy *Curr-block-depth 1/imm32
18649     # var out/esi: (handle stmt)
18650     68/push 0/imm32
18651     68/push 0/imm32
18652     89/<- %esi 4/r32/esp
18653     # var vars/ecx: (stack (addr var) 16)
18654     81 5/subop/subtract %esp 0xc0/imm32
18655     68/push 0xc0/imm32/size
18656     68/push 0/imm32/top
18657     89/<- %ecx 4/r32/esp
18658     (clear-stack %ecx)
18659     # convert
18660     (parse-mu-var-def _test-input-stream %ecx %esi 0 Stderr 0)
18661     # var out-addr/esi: (addr stmt)
18662     (lookup *esi *(esi+4))  # => eax
18663     89/<- %esi 0/r32/eax
18664     #
18665     (check-ints-equal *esi 2 "F - test-parse-mu-var-def/tag")  # Stmt-tag is var-def
18666     # var v/ecx: (addr var) = lookup(out->var)
18667     (lookup *(esi+4) *(esi+8))  # Vardef-var Vardef-var => eax
18668     89/<- %ecx 0/r32/eax
18669     # v->name
18670     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
18671     (check-strings-equal %eax "n" "F - test-parse-mu-var-def/var-name")
18672     # v->register
18673     (check-ints-equal *(ecx+0x18) 0 "F - test-parse-mu-var-def/var-register")  # Var-register
18674     # v->block-depth
18675     (check-ints-equal *(ecx+0x10) 1 "F - test-parse-mu-var-def/output-block-depth")  # Var-block-depth
18676     # v->type == int
18677     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
18678     (check-ints-equal *eax 1 "F - test-parse-mu-var-def/var-type:0")  # Type-tree-is-atom
18679     (check-ints-equal *(eax+4) 1 "F - test-parse-mu-var-def/var-type:1")  # Type-tree-value
18680     (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-var-def/var-type:2")  # Type-tree-right
18681     # . epilogue
18682     89/<- %esp 5/r32/ebp
18683     5d/pop-to-ebp
18684     c3/return
18685 
18686 test-parse-mu-reg-var-def:
18687     # 'var n/eax: int <- copy 0'
18688     # . prologue
18689     55/push-ebp
18690     89/<- %ebp 4/r32/esp
18691     # setup
18692     8b/-> *Primitive-type-ids 0/r32/eax
18693     89/<- *Type-id 0/r32/eax  # stream-write
18694     (clear-stream _test-input-stream)
18695     (write _test-input-stream "n/eax: int <- copy 0\n")  # caller has consumed the 'var'
18696     c7 0/subop/copy *Curr-block-depth 1/imm32
18697     # var out/esi: (handle stmt)
18698     68/push 0/imm32
18699     68/push 0/imm32
18700     89/<- %esi 4/r32/esp
18701     # var vars/ecx: (stack (addr var) 16)
18702     81 5/subop/subtract %esp 0xc0/imm32
18703     68/push 0xc0/imm32/size
18704     68/push 0/imm32/top
18705     89/<- %ecx 4/r32/esp
18706     (clear-stack %ecx)
18707     # convert
18708     (parse-mu-var-def _test-input-stream %ecx %esi 0 Stderr 0)
18709     # var out-addr/esi: (addr stmt)
18710     (lookup *esi *(esi+4))  # => eax
18711     89/<- %esi 0/r32/eax
18712     #
18713     (check-ints-equal *esi 3 "F - test-parse-mu-reg-var-def/tag")  # Stmt-tag is reg-var-def
18714     # var v/ecx: (addr var) = lookup(out->outputs->value)
18715     # . eax: (addr stmt-var) = lookup(out->outputs)
18716     (lookup *(esi+0x14) *(esi+0x18))  # Regvardef-outputs Regvardef-outputs => eax
18717     # .
18718     (check-ints-equal *(eax+8) 0 "F - test-parse-mu-reg-var-def/single-output")  # Stmt-var-next
18719     # . eax: (addr var) = lookup(eax->value)
18720     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
18721     # . ecx = eax
18722     89/<- %ecx 0/r32/eax
18723     # v->name
18724     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
18725     (check-strings-equal %eax "n" "F - test-parse-mu-reg-var-def/output-name")  # Var-name
18726     # v->register
18727     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
18728     (check-strings-equal %eax "eax" "F - test-parse-mu-reg-var-def/output-register")
18729     # v->block-depth
18730     (check-ints-equal *(ecx+0x10) 1 "F - test-parse-mu-reg-var-def/output-block-depth")  # Var-block-depth
18731     # v->type == int
18732     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
18733     (check-ints-equal *eax 1 "F - test-parse-mu-reg-var-def/output-type:0")  # Type-tree-is-atom
18734     (check-ints-equal *(eax+4) 1 "F - test-parse-mu-reg-var-def/output-type:1")  # Type-tree-value
18735     (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-reg-var-def/output-type:2")  # Type-tree-right
18736     # . epilogue
18737     89/<- %esp 5/r32/ebp
18738     5d/pop-to-ebp
18739     c3/return
18740 
18741 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)
18742     # pseudocode:
18743     #   var name: slice
18744     #   allocate(Heap, Stmt-size, out)
18745     #   var out-addr: (addr stmt) = lookup(*out)
18746     #   out-addr->tag = stmt
18747     #   if stmt-has-outputs?(line)
18748     #     while true
18749     #       name = next-mu-token(line)
18750     #       if (name == '<-') break
18751     #       assert(identifier?(name))
18752     #       var v: (handle var) = lookup-var(name, vars)
18753     #       out-addr->outputs = append(v, out-addr->outputs)
18754     #   add-operation-and-inputs-to-stmt(out-addr, line, vars)
18755     #
18756     # . prologue
18757     55/push-ebp
18758     89/<- %ebp 4/r32/esp
18759     # . save registers
18760     50/push-eax
18761     51/push-ecx
18762     52/push-edx
18763     53/push-ebx
18764     57/push-edi
18765     # var name/ecx: slice
18766     68/push 0/imm32/end
18767     68/push 0/imm32/start
18768     89/<- %ecx 4/r32/esp
18769     # var is-deref?/edx: boolean = false
18770     ba/copy-to-edx 0/imm32/false
18771     # var v: (handle var)
18772     68/push 0/imm32
18773     68/push 0/imm32
18774     89/<- %ebx 4/r32/esp
18775     #
18776     (allocate Heap *Stmt-size *(ebp+0x14))
18777     # var out-addr/edi: (addr stmt) = lookup(*out)
18778     8b/-> *(ebp+0x14) 7/r32/edi
18779     (lookup *edi *(edi+4))  # => eax
18780     89/<- %edi 0/r32/eax
18781     # out-addr->tag = 1/stmt
18782     c7 0/subop/copy *edi 1/imm32/stmt1  # Stmt-tag
18783     {
18784       (stmt-has-outputs? *(ebp+8))
18785       3d/compare-eax-and 0/imm32/false
18786       0f 84/jump-if-= break/disp32
18787       {
18788 $parse-mu-stmt:read-outputs:
18789         # name = next-mu-token(line)
18790         (next-mu-token *(ebp+8) %ecx)
18791         # if slice-empty?(word-slice) break
18792         (slice-empty? %ecx)  # => eax
18793         3d/compare-eax-and 0/imm32/false
18794         0f 85/jump-if-!= break/disp32
18795         # if (name == "<-") break
18796         (slice-equal? %ecx "<-")  # => eax
18797         3d/compare-eax-and 0/imm32/false
18798         0f 85/jump-if-!= break/disp32
18799         # if slice-starts-with?(name, "*") abort
18800         8b/-> *ecx 0/r32/eax  # Slice-start
18801         8a/copy-byte *eax 0/r32/AL
18802         81 4/subop/and %eax 0xff/imm32
18803         3d/compare-eax-and 0x2a/imm32/asterisk
18804         0f 84/jump-if-= $parse-mu-stmt:error-output-dereferenced/disp32
18805         # assert(identifier?(name))
18806         (identifier? %ecx)  # => eax
18807         3d/compare-eax-and 0/imm32/false
18808         0f 84/jump-if-= $parse-mu-stmt:abort/disp32
18809         #
18810         (lookup-var %ecx *(ebp+0xc) %ebx *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
18811         8d/copy-address *(edi+0x14) 0/r32/eax  # Stmt1-outputs
18812         (append-stmt-var Heap  *ebx *(ebx+4)  *(edi+0x14) *(edi+0x18)  0  %eax)  # Stmt1-outputs
18813         #
18814         e9/jump loop/disp32
18815       }
18816     }
18817     (add-operation-and-inputs-to-stmt %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
18818 $parse-mu-stmt:end:
18819     # . reclaim locals
18820     81 0/subop/add %esp 0x10/imm32
18821     # . restore registers
18822     5f/pop-to-edi
18823     5b/pop-to-ebx
18824     5a/pop-to-edx
18825     59/pop-to-ecx
18826     58/pop-to-eax
18827     # . epilogue
18828     89/<- %esp 5/r32/ebp
18829     5d/pop-to-ebp
18830     c3/return
18831 
18832 $parse-mu-stmt:abort:
18833     # error("invalid identifier '" name "'\n")
18834     (write-buffered *(ebp+0x18) "fn ")
18835     8b/-> *(ebp+0x10) 0/r32/eax
18836     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18837     (write-buffered *(ebp+0x18) %eax)
18838     (write-buffered *(ebp+0x18) ": invalid identifier '")
18839     (write-slice-buffered *(ebp+0x18) %ecx)
18840     (write-buffered *(ebp+0x18) "'\n")
18841     (flush *(ebp+0x18))
18842     (stop *(ebp+0x1c) 1)
18843     # never gets here
18844 
18845 $parse-mu-stmt:error-output-dereferenced:
18846     # error("invalid identifier '" name "'\n")
18847     (write-buffered *(ebp+0x18) "fn ")
18848     8b/-> *(ebp+0x10) 0/r32/eax
18849     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18850     (write-buffered *(ebp+0x18) %eax)
18851     (write-buffered *(ebp+0x18) ": output '")
18852     (write-slice-buffered *(ebp+0x18) %ecx)
18853     (write-buffered *(ebp+0x18) "' should write to a register, and therefore cannot be dereferenced\n")
18854     (flush *(ebp+0x18))
18855     (stop *(ebp+0x1c) 1)
18856     # never gets here
18857 
18858 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)
18859     # pseudocode:
18860     #   stmt->name = slice-to-string(next-mu-token(line))
18861     #   while true
18862     #     name = next-mu-token(line)
18863     #     v = lookup-var-or-literal(name)
18864     #     stmt->inouts = append(v, stmt->inouts)
18865     #
18866     # . prologue
18867     55/push-ebp
18868     89/<- %ebp 4/r32/esp
18869     # . save registers
18870     50/push-eax
18871     51/push-ecx
18872     52/push-edx
18873     53/push-ebx
18874     56/push-esi
18875     57/push-edi
18876     # edi = stmt
18877     8b/-> *(ebp+8) 7/r32/edi
18878     # var name/ecx: slice
18879     68/push 0/imm32/end
18880     68/push 0/imm32/start
18881     89/<- %ecx 4/r32/esp
18882     # var is-deref?/edx: boolean = false
18883     ba/copy-to-edx 0/imm32/false
18884     # var v/esi: (handle var)
18885     68/push 0/imm32
18886     68/push 0/imm32
18887     89/<- %esi 4/r32/esp
18888 $add-operation-and-inputs-to-stmt:read-operation:
18889     (next-mu-token *(ebp+0xc) %ecx)
18890     8d/copy-address *(edi+4) 0/r32/eax  # Stmt1-operation or Regvardef-operationStmt1-operation or Regvardef-operation
18891     (slice-to-string Heap %ecx %eax)
18892     # var is-get?/ebx: boolean = (name == "get")
18893     (slice-equal? %ecx "get")  # => eax
18894     89/<- %ebx 0/r32/eax
18895     {
18896 $add-operation-and-inputs-to-stmt:read-inouts:
18897       # name = next-mu-token(line)
18898       (next-mu-token *(ebp+0xc) %ecx)
18899       # if slice-empty?(word-slice) break
18900       (slice-empty? %ecx)  # => eax
18901       3d/compare-eax-and 0/imm32/false
18902       0f 85/jump-if-!= break/disp32
18903       # if (name == "<-") abort
18904       (slice-equal? %ecx "<-")
18905       3d/compare-eax-and 0/imm32/false
18906       0f 85/jump-if-!= $add-operation-and-inputs-to-stmt:abort/disp32
18907       # if (get? && second operand) lookup or create offset
18908       {
18909         81 7/subop/compare %ebx 0/imm32/false
18910         74/jump-if-= break/disp8
18911         (lookup *(edi+0xc) *(edi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
18912         3d/compare-eax-and 0/imm32
18913         74/jump-if-= break/disp8
18914         (lookup-or-create-constant %eax %ecx %esi)
18915 #?         (lookup *esi *(esi+4))
18916 #?         (write-buffered Stderr "creating new output var ")
18917 #?         (write-int32-hex-buffered Stderr %eax)
18918 #?         (write-buffered Stderr " for field called ")
18919 #?         (write-slice-buffered Stderr %ecx)
18920 #?         (write-buffered Stderr "; var name ")
18921 #?         (lookup *eax *(eax+4))  # Var-name
18922 #?         (write-buffered Stderr %eax)
18923 #?         (write-buffered Stderr Newline)
18924 #?         (flush Stderr)
18925         e9/jump $add-operation-and-inputs-to-stmt:save-var/disp32
18926       }
18927       # is-deref? = false
18928       ba/copy-to-edx 0/imm32/false
18929       # if (slice-starts-with?(name, '*')) ++name->start and set is-deref?
18930       8b/-> *ecx 0/r32/eax  # Slice-start
18931       8a/copy-byte *eax 0/r32/AL
18932       81 4/subop/and %eax 0xff/imm32
18933       3d/compare-eax-and 0x2a/imm32/asterisk
18934       {
18935         75/jump-if-!= break/disp8
18936 $add-operation-and-inputs-to-stmt:inout-is-deref:
18937         ff 0/subop/increment *ecx
18938         ba/copy-to-edx 1/imm32/true
18939       }
18940       (lookup-var-or-literal %ecx *(ebp+0x10) %esi *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
18941       # if (deref?) some additional checks
18942       81 7/subop/compare %edx 0/imm32/false
18943       {
18944         74/jump-if-= break/disp8
18945         # if var is not in register, abort
18946         (lookup *esi *(esi+4))  # => eax
18947         81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
18948         0f 84/jump-if-= $add-operation-and-inputs-to-stmt:error-deref-on-stack/disp32
18949         # if var is not an address, abort
18950         (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
18951         (mu-addr-type? %eax)  # => eax
18952         3d/compare-eax-and 0/imm32/false
18953         0f 84/jump-if-= $add-operation-and-inputs-to-stmt:error-deref-non-addr/disp32
18954       }
18955 $add-operation-and-inputs-to-stmt:save-var:
18956       8d/copy-address *(edi+0xc) 0/r32/eax
18957       (append-stmt-var Heap  *esi *(esi+4)  *(edi+0xc) *(edi+0x10)  %edx  %eax)  # Stmt1-inouts or Regvardef-inouts
18958       #
18959       e9/jump loop/disp32
18960     }
18961 $add-operation-and-inputs-to-stmt:end:
18962     # . reclaim locals
18963     81 0/subop/add %esp 0x10/imm32
18964     # . restore registers
18965     5f/pop-to-edi
18966     5e/pop-to-esi
18967     5b/pop-to-ebx
18968     5a/pop-to-edx
18969     59/pop-to-ecx
18970     58/pop-to-eax
18971     # . epilogue
18972     89/<- %esp 5/r32/ebp
18973     5d/pop-to-ebp
18974     c3/return
18975 
18976 $add-operation-and-inputs-to-stmt:abort:
18977     # error("fn ___: invalid identifier in '" line "'\n")
18978     (write-buffered *(ebp+0x18) "fn ")
18979     8b/-> *(ebp+0x14) 0/r32/eax
18980     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18981     (write-buffered *(ebp+0x18) %eax)
18982     (rewind-stream *(ebp+0xc))
18983     (write-buffered *(ebp+0x18) ": invalid identifier in '")
18984     (write-stream-data *(ebp+0x18) *(ebp+0xc))
18985     (write-buffered *(ebp+0x18) "'\n")
18986     (flush *(ebp+0x18))
18987     (stop *(ebp+0x1c) 1)
18988     # never gets here
18989 
18990 $add-operation-and-inputs-to-stmt:error-deref-on-stack:
18991     # error("fn ___: cannot dereference var ___ on stack\n")
18992     (write-buffered *(ebp+0x18) "fn ")
18993     8b/-> *(ebp+0x14) 0/r32/eax
18994     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18995     (write-buffered *(ebp+0x18) %eax)
18996     (rewind-stream *(ebp+0xc))
18997     (write-buffered *(ebp+0x18) ": cannot dereference var '")
18998     (lookup *esi *(esi+4))  # => eax
18999     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19000     (write-buffered *(ebp+0x18) %eax)
19001     (write-buffered *(ebp+0x18) "' on stack\n")
19002     (flush *(ebp+0x18))
19003     (stop *(ebp+0x1c) 1)
19004     # never gets here
19005 
19006 $add-operation-and-inputs-to-stmt:error-deref-non-addr:
19007     # error("fn ___: cannot dereference non-addr var ___\n")
19008     (write-buffered *(ebp+0x18) "fn ")
19009     8b/-> *(ebp+0x14) 0/r32/eax
19010     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19011     (write-buffered *(ebp+0x18) %eax)
19012     (rewind-stream *(ebp+0xc))
19013     (write-buffered *(ebp+0x18) ": cannot dereference non-addr var '")
19014     (lookup *esi *(esi+4))  # => eax
19015     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19016     (write-buffered *(ebp+0x18) %eax)
19017     (write-buffered *(ebp+0x18) "'\n")
19018     (flush *(ebp+0x18))
19019     (stop *(ebp+0x1c) 1)
19020     # never gets here
19021 
19022 stmt-has-outputs?:  # line: (addr stream byte) -> result/eax: boolean
19023     # . prologue
19024     55/push-ebp
19025     89/<- %ebp 4/r32/esp
19026     # . save registers
19027     51/push-ecx
19028     # var word-slice/ecx: slice
19029     68/push 0/imm32/end
19030     68/push 0/imm32/start
19031     89/<- %ecx 4/r32/esp
19032     # result = false
19033     b8/copy-to-eax 0/imm32/false
19034     (rewind-stream *(ebp+8))
19035     {
19036       (next-mu-token *(ebp+8) %ecx)
19037       # if slice-empty?(word-slice) break
19038       (slice-empty? %ecx)
19039       3d/compare-eax-and 0/imm32/false
19040       b8/copy-to-eax 0/imm32/false/result  # restore result (if we're here it's still false)
19041       0f 85/jump-if-!= break/disp32
19042       # if slice-starts-with?(word-slice, '#') break
19043       # . eax = *word-slice->start
19044       8b/-> *ecx 0/r32/eax
19045       8a/copy-byte *eax 0/r32/AL
19046       81 4/subop/and %eax 0xff/imm32
19047       # . if (eax == '#') break
19048       3d/compare-eax-and 0x23/imm32/hash
19049       b8/copy-to-eax 0/imm32/false/result  # restore result (if we're here it's still false)
19050       0f 84/jump-if-= break/disp32
19051       # if slice-equal?(word-slice, '<-') return true
19052       (slice-equal? %ecx "<-")
19053       3d/compare-eax-and 0/imm32/false
19054       74/jump-if-= loop/disp8
19055       b8/copy-to-eax 1/imm32/true
19056     }
19057 $stmt-has-outputs:end:
19058     (rewind-stream *(ebp+8))
19059     # . reclaim locals
19060     81 0/subop/add %esp 8/imm32
19061     # . restore registers
19062     59/pop-to-ecx
19063     # . epilogue
19064     89/<- %esp 5/r32/ebp
19065     5d/pop-to-ebp
19066     c3/return
19067 
19068 # if 'name' starts with a digit, create a new literal var for it
19069 # otherwise return first 'name' from the top (back) of 'vars' and abort if not found
19070 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)
19071     # . prologue
19072     55/push-ebp
19073     89/<- %ebp 4/r32/esp
19074     # . save registers
19075     50/push-eax
19076     51/push-ecx
19077     56/push-esi
19078     # esi = name
19079     8b/-> *(ebp+8) 6/r32/esi
19080     # if slice-empty?(name) abort
19081     (slice-empty? %esi)  # => eax
19082     3d/compare-eax-and 0/imm32/false
19083     0f 85/jump-if-!= $lookup-var-or-literal:abort/disp32
19084     # var c/ecx: byte = *name->start
19085     8b/-> *esi 1/r32/ecx
19086     8a/copy-byte *ecx 1/r32/CL
19087     81 4/subop/and %ecx 0xff/imm32
19088     # if (decimal-digit?(c) || c == '-') return new var(name)
19089     {
19090       81 7/subop/compare %ecx 0x2d/imm32/dash
19091       74/jump-if-= $lookup-var-or-literal:literal/disp8
19092       (decimal-digit? %ecx)  # => eax
19093       3d/compare-eax-and 0/imm32/false
19094       74/jump-if-= break/disp8
19095 $lookup-var-or-literal:literal:
19096       (new-literal-integer Heap %esi *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
19097       eb/jump $lookup-var-or-literal:end/disp8
19098     }
19099     # else if (c == '"') return new var(name)
19100     {
19101       81 7/subop/compare %ecx 0x22/imm32/dquote
19102       75/jump-if-!= break/disp8
19103 $lookup-var-or-literal:literal-string:
19104       (new-literal-string Heap %esi *(ebp+0x10))
19105       eb/jump $lookup-var-or-literal:end/disp8
19106     }
19107     # otherwise return lookup-var(name, vars)
19108     {
19109 $lookup-var-or-literal:var:
19110       (lookup-var %esi *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
19111     }
19112 $lookup-var-or-literal:end:
19113     # . restore registers
19114     5e/pop-to-esi
19115     59/pop-to-ecx
19116     58/pop-to-eax
19117     # . epilogue
19118     89/<- %esp 5/r32/ebp
19119     5d/pop-to-ebp
19120     c3/return
19121 
19122 $lookup-var-or-literal:abort:
19123     (write-buffered *(ebp+0x18) "fn ")
19124     8b/-> *(ebp+0x14) 0/r32/eax
19125     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19126     (write-buffered *(ebp+0x18) %eax)
19127     (write-buffered *(ebp+0x18) ": empty variable!")
19128     (flush *(ebp+0x18))
19129     (stop *(ebp+0x1c) 1)
19130     # never gets here
19131 
19132 # return first 'name' from the top (back) of 'vars' and abort if not found
19133 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)
19134     # . prologue
19135     55/push-ebp
19136     89/<- %ebp 4/r32/esp
19137     # . save registers
19138     50/push-eax
19139     #
19140     (lookup-var-helper *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
19141     # if (*out == 0) abort
19142     8b/-> *(ebp+0x10) 0/r32/eax
19143     81 7/subop/compare *eax 0/imm32
19144     74/jump-if-= $lookup-var:abort/disp8
19145 $lookup-var:end:
19146     # . restore registers
19147     58/pop-to-eax
19148     # . epilogue
19149     89/<- %esp 5/r32/ebp
19150     5d/pop-to-ebp
19151     c3/return
19152 
19153 $lookup-var:abort:
19154     (write-buffered *(ebp+0x18) "fn ")
19155     8b/-> *(ebp+0x14) 0/r32/eax
19156     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19157     (write-buffered *(ebp+0x18) %eax)
19158     (write-buffered *(ebp+0x18) ": unknown variable '")
19159     (write-slice-buffered *(ebp+0x18) *(ebp+8))
19160     (write-buffered *(ebp+0x18) "'\n")
19161     (flush *(ebp+0x18))
19162     (stop *(ebp+0x1c) 1)
19163     # never gets here
19164 
19165 # return first 'name' from the top (back) of 'vars', and 0/null if not found
19166 # ensure that 'name' if in a register is the topmost variable in that register
19167 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)
19168     # pseudocode:
19169     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
19170     #   var min = vars->data
19171     #   while curr >= min
19172     #     var v: (handle var) = *curr
19173     #     if v->name == name
19174     #       return
19175     #     curr -= 12
19176     #
19177     # . prologue
19178     55/push-ebp
19179     89/<- %ebp 4/r32/esp
19180     # . save registers
19181     50/push-eax
19182     51/push-ecx
19183     52/push-edx
19184     53/push-ebx
19185     56/push-esi
19186     57/push-edi
19187     # clear out
19188     (zero-out *(ebp+0x10) *Handle-size)
19189     # esi = vars
19190     8b/-> *(ebp+0xc) 6/r32/esi
19191     # ebx = vars->top
19192     8b/-> *esi 3/r32/ebx
19193     # if (vars->top > vars->size) abort
19194     3b/compare<- *(esi+4) 0/r32/eax
19195     0f 8f/jump-if-> $lookup-var-helper:error1/disp32
19196     # var min/edx: (addr handle var) = vars->data
19197     8d/copy-address *(esi+8) 2/r32/edx
19198     # var curr/ebx: (addr handle var) = &vars->data[vars->top - 12]
19199     8d/copy-address *(esi+ebx-4) 3/r32/ebx  # vars + 8 + vars->type - 12
19200     # var var-in-reg/edi: 16 addrs
19201     68/push 0/imm32
19202     68/push 0/imm32
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     89/<- %edi 4/r32/esp
19218     {
19219 $lookup-var-helper:loop:
19220       # if (curr < min) return
19221       39/compare %ebx 2/r32/edx
19222       0f 82/jump-if-addr< break/disp32
19223       # var v/ecx: (addr var) = lookup(*curr)
19224       (lookup *ebx *(ebx+4))  # => eax
19225       89/<- %ecx 0/r32/eax
19226       # var vn/eax: (addr array byte) = lookup(v->name)
19227       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
19228       # if (vn == name) return curr
19229       (slice-equal? *(ebp+8) %eax)  # => eax
19230       3d/compare-eax-and 0/imm32/false
19231       {
19232         74/jump-if-= break/disp8
19233 $lookup-var-helper:found:
19234         # var vr/eax: (addr array byte) = lookup(v->register)
19235         (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
19236         3d/compare-eax-and 0/imm32
19237         {
19238           74/jump-if-= break/disp8
19239 $lookup-var-helper:found-register:
19240           # var reg/eax: int = get(Registers, vr)
19241           (get Mu-registers-unique %eax 0xc "Mu-registers-unique")  # => eax
19242           8b/-> *eax 0/r32/eax
19243           # if (var-in-reg[reg]) error
19244           8b/-> *(edi+eax<<2) 0/r32/eax
19245           3d/compare-eax-and 0/imm32
19246           0f 85/jump-if-!= $lookup-var-helper:error2/disp32
19247         }
19248 $lookup-var-helper:return:
19249         # esi = out
19250         8b/-> *(ebp+0x10) 6/r32/esi
19251         # *out = *curr
19252         8b/-> *ebx 0/r32/eax
19253         89/<- *esi 0/r32/eax
19254         8b/-> *(ebx+4) 0/r32/eax
19255         89/<- *(esi+4) 0/r32/eax
19256         # return
19257         eb/jump $lookup-var-helper:end/disp8
19258       }
19259       # 'name' not yet found; update var-in-reg if v in register
19260       # . var vr/eax: (addr array byte) = lookup(v->register)
19261       (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
19262       # . if (vr == 0) continue
19263       3d/compare-eax-and 0/imm32
19264       74/jump-if-= $lookup-var-helper:continue/disp8
19265       # . var reg/eax: int = get(Registers, vr)
19266       (get Mu-registers-unique %eax 0xc "Mu-registers-unique")  # => eax
19267       8b/-> *eax 0/r32/eax
19268       # . var-in-reg[reg] = v
19269       89/<- *(edi+eax<<2) 1/r32/ecx
19270 $lookup-var-helper:continue:
19271       # curr -= 12
19272       81 5/subop/subtract %ebx 0xc/imm32
19273       e9/jump loop/disp32
19274     }
19275 $lookup-var-helper:end:
19276     # . reclaim locals
19277     81 0/subop/add %esp 0x40/imm32
19278     # . restore registers
19279     5f/pop-to-edi
19280     5e/pop-to-esi
19281     5b/pop-to-ebx
19282     5a/pop-to-edx
19283     59/pop-to-ecx
19284     58/pop-to-eax
19285     # . epilogue
19286     89/<- %esp 5/r32/ebp
19287     5d/pop-to-ebp
19288     c3/return
19289 
19290 $lookup-var-helper:error1:
19291     (write-buffered *(ebp+0x18) "fn ")
19292     8b/-> *(ebp+0x14) 0/r32/eax
19293     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19294     (write-buffered *(ebp+0x18) %eax)
19295     (write-buffered *(ebp+0x18) ": malformed stack when looking up '")
19296     (write-slice-buffered *(ebp+0x18) *(ebp+8))
19297     (write-buffered *(ebp+0x18) "'\n")
19298     (flush *(ebp+0x18))
19299     (stop *(ebp+0x1c) 1)
19300     # never gets here
19301 
19302 $lookup-var-helper:error2:
19303     # eax contains the conflicting var at this point
19304     (write-buffered *(ebp+0x18) "fn ")
19305     50/push-eax
19306     8b/-> *(ebp+0x14) 0/r32/eax
19307     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19308     (write-buffered *(ebp+0x18) %eax)
19309     58/pop-eax
19310     (write-buffered *(ebp+0x18) ": register ")
19311     50/push-eax
19312     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
19313     (write-buffered *(ebp+0x18) %eax)
19314     58/pop-to-eax
19315     (write-buffered *(ebp+0x18) " reads var '")
19316     (write-slice-buffered *(ebp+0x18) *(ebp+8))
19317     (write-buffered *(ebp+0x18) "' after writing var '")
19318     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19319     (write-buffered *(ebp+0x18) %eax)
19320     (write-buffered *(ebp+0x18) "'\n")
19321     (flush *(ebp+0x18))
19322     (stop *(ebp+0x1c) 1)
19323     # never gets here
19324 
19325 dump-vars:  # vars: (addr stack live-var)
19326     # pseudocode:
19327     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
19328     #   var min = vars->data
19329     #   while curr >= min
19330     #     var v: (handle var) = *curr
19331     #     print v
19332     #     curr -= 12
19333     #
19334     # . prologue
19335     55/push-ebp
19336     89/<- %ebp 4/r32/esp
19337     # . save registers
19338     52/push-edx
19339     53/push-ebx
19340     56/push-esi
19341     # esi = vars
19342     8b/-> *(ebp+8) 6/r32/esi
19343     # ebx = vars->top
19344     8b/-> *esi 3/r32/ebx
19345     # var min/edx: (addr handle var) = vars->data
19346     8d/copy-address *(esi+8) 2/r32/edx
19347     # var curr/ebx: (addr handle var) = &vars->data[vars->top - 12]
19348     8d/copy-address *(esi+ebx-4) 3/r32/ebx  # vars + 8 + vars->type - 12
19349     {
19350 $dump-vars:loop:
19351       # if (curr < min) return
19352       39/compare %ebx 2/r32/edx
19353       0f 82/jump-if-addr< break/disp32
19354       #
19355       (write-buffered Stderr "  var@")
19356       (dump-var 2 %ebx)
19357       # curr -= 12
19358       81 5/subop/subtract %ebx 0xc/imm32
19359       e9/jump loop/disp32
19360     }
19361 $dump-vars:end:
19362     # . restore registers
19363     5e/pop-to-esi
19364     5b/pop-to-ebx
19365     5a/pop-to-edx
19366     # . epilogue
19367     89/<- %esp 5/r32/ebp
19368     5d/pop-to-ebp
19369     c3/return
19370 
19371 == data
19372 # Like Registers, but no esp or ebp
19373 Mu-registers:  # (addr stream {(handle array byte), int})
19374   # a table is a stream
19375   0xa8/imm32/write
19376   0/imm32/read
19377   0xa8/imm32/length
19378   # data
19379   # general-purpose registers
19380   # it is perfectly ok to use fake alloc-ids -- as long as you never try to reclaim them
19381   0x11/imm32/alloc-id $Mu-register-eax/imm32 0/imm32
19382   0x11/imm32/alloc-id $Mu-register-ecx/imm32 1/imm32
19383   0x11/imm32/alloc-id $Mu-register-edx/imm32 2/imm32
19384   0x11/imm32/alloc-id $Mu-register-ebx/imm32 3/imm32
19385   0x11/imm32/alloc-id $Mu-register-esi/imm32 6/imm32
19386   0x11/imm32/alloc-id $Mu-register-edi/imm32 7/imm32
19387   # floating-point registers
19388   0x11/imm32/alloc-id $Mu-register-xmm0/imm32 0/imm32
19389   0x11/imm32/alloc-id $Mu-register-xmm1/imm32 1/imm32
19390   0x11/imm32/alloc-id $Mu-register-xmm2/imm32 2/imm32
19391   0x11/imm32/alloc-id $Mu-register-xmm3/imm32 3/imm32
19392   0x11/imm32/alloc-id $Mu-register-xmm4/imm32 4/imm32
19393   0x11/imm32/alloc-id $Mu-register-xmm5/imm32 5/imm32
19394   0x11/imm32/alloc-id $Mu-register-xmm6/imm32 6/imm32
19395   0x11/imm32/alloc-id $Mu-register-xmm7/imm32 7/imm32
19396 
19397 # Like Mu-registers, but with unique codes for integer and floating-point
19398 # registers.
19399 # Don't use this for code-generation, only for checking.
19400 Mu-registers-unique:  # (addr stream {(handle array byte), int})
19401   # a table is a stream
19402   0xa8/imm32/write
19403   0/imm32/read
19404   0xa8/imm32/length
19405   # data
19406   # general-purpose registers
19407   0x11/imm32/alloc-id $Mu-register-eax/imm32 0/imm32
19408   0x11/imm32/alloc-id $Mu-register-ecx/imm32 1/imm32
19409   0x11/imm32/alloc-id $Mu-register-edx/imm32 2/imm32
19410   0x11/imm32/alloc-id $Mu-register-ebx/imm32 3/imm32
19411   0x11/imm32/alloc-id $Mu-register-esi/imm32 6/imm32
19412   0x11/imm32/alloc-id $Mu-register-edi/imm32 7/imm32
19413   # floating-point registers
19414   0x11/imm32/alloc-id $Mu-register-xmm0/imm32 8/imm32
19415   0x11/imm32/alloc-id $Mu-register-xmm1/imm32 9/imm32
19416   0x11/imm32/alloc-id $Mu-register-xmm2/imm32 0xa/imm32
19417   0x11/imm32/alloc-id $Mu-register-xmm3/imm32 0xb/imm32
19418   0x11/imm32/alloc-id $Mu-register-xmm4/imm32 0xc/imm32
19419   0x11/imm32/alloc-id $Mu-register-xmm5/imm32 0xd/imm32
19420   0x11/imm32/alloc-id $Mu-register-xmm6/imm32 0xe/imm32
19421   0x11/imm32/alloc-id $Mu-register-xmm7/imm32 0xf/imm32
19422 
19423 $Mu-register-eax:
19424   0x11/imm32/alloc-id
19425   3/imm32/size
19426   0x65/e 0x61/a 0x78/x
19427 
19428 $Mu-register-ecx:
19429   0x11/imm32/alloc-id
19430   3/imm32/size
19431   0x65/e 0x63/c 0x78/x
19432 
19433 $Mu-register-edx:
19434   0x11/imm32/alloc-id
19435   3/imm32/size
19436   0x65/e 0x64/d 0x78/x
19437 
19438 $Mu-register-ebx:
19439   0x11/imm32/alloc-id
19440   3/imm32/size
19441   0x65/e 0x62/b 0x78/x
19442 
19443 $Mu-register-esi:
19444   0x11/imm32/alloc-id
19445   3/imm32/size
19446   0x65/e 0x73/s 0x69/i
19447 
19448 $Mu-register-edi:
19449   0x11/imm32/alloc-id
19450   3/imm32/size
19451   0x65/e 0x64/d 0x69/i
19452 
19453 $Mu-register-xmm0:
19454   0x11/imm32/alloc-id:fake:payload
19455   # "xmm0"
19456   0x4/imm32/size
19457   0x78/x 0x6d/m 0x6d/m 0x30/0
19458 
19459 $Mu-register-xmm1:
19460   0x11/imm32/alloc-id:fake:payload
19461   # "xmm1"
19462   0x4/imm32/size
19463   0x78/x 0x6d/m 0x6d/m 0x31/1
19464 
19465 $Mu-register-xmm2:
19466   0x11/imm32/alloc-id:fake:payload
19467   # "xmm2"
19468   0x4/imm32/size
19469   0x78/x 0x6d/m 0x6d/m 0x32/2
19470 
19471 $Mu-register-xmm3:
19472   0x11/imm32/alloc-id:fake:payload
19473   # "xmm3"
19474   0x4/imm32/size
19475   0x78/x 0x6d/m 0x6d/m 0x33/3
19476 
19477 $Mu-register-xmm4:
19478   0x11/imm32/alloc-id:fake:payload
19479   # "xmm4"
19480   0x4/imm32/size
19481   0x78/x 0x6d/m 0x6d/m 0x34/4
19482 
19483 $Mu-register-xmm5:
19484   0x11/imm32/alloc-id:fake:payload
19485   # "xmm5"
19486   0x4/imm32/size
19487   0x78/x 0x6d/m 0x6d/m 0x35/5
19488 
19489 $Mu-register-xmm6:
19490   0x11/imm32/alloc-id:fake:payload
19491   # "xmm6"
19492   0x4/imm32/size
19493   0x78/x 0x6d/m 0x6d/m 0x36/6
19494 
19495 $Mu-register-xmm7:
19496   0x11/imm32/alloc-id:fake:payload
19497   # "xmm7"
19498   0x4/imm32/size
19499   0x78/x 0x6d/m 0x6d/m 0x37/7
19500 
19501 == code
19502 
19503 # push 'out' to 'vars' if not already there; it's assumed to be a fn output
19504 maybe-define-var:  # out: (handle var), vars: (addr stack live-var)
19505     # . prologue
19506     55/push-ebp
19507     89/<- %ebp 4/r32/esp
19508     # . save registers
19509     50/push-eax
19510     # var out-addr/eax: (addr var)
19511     (lookup *(ebp+8) *(ebp+0xc))  # => eax
19512     #
19513     (binding-exists? %eax *(ebp+0x10))  # => eax
19514     3d/compare-eax-and 0/imm32/false
19515     75/jump-if-!= $maybe-define-var:end/disp8
19516     # otherwise update vars
19517     (push *(ebp+0x10) *(ebp+8))
19518     (push *(ebp+0x10) *(ebp+0xc))
19519     (push *(ebp+0x10) 0)  # 'out' is always a fn output; never spill it
19520 $maybe-define-var:end:
19521     # . restore registers
19522     58/pop-to-eax
19523     # . epilogue
19524     89/<- %esp 5/r32/ebp
19525     5d/pop-to-ebp
19526     c3/return
19527 
19528 # simpler version of lookup-var-helper
19529 binding-exists?:  # target: (addr var), vars: (addr stack live-var) -> result/eax: boolean
19530     # pseudocode:
19531     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
19532     #   var min = vars->data
19533     #   while curr >= min
19534     #     var v: (handle var) = *curr
19535     #     if v->name == target->name
19536     #       return true
19537     #     curr -= 12
19538     #   return false
19539     #
19540     # . prologue
19541     55/push-ebp
19542     89/<- %ebp 4/r32/esp
19543     # . save registers
19544     51/push-ecx
19545     52/push-edx
19546     56/push-esi
19547     # var target-name/ecx: (addr array byte) = lookup(target->name)
19548     8b/-> *(ebp+8) 0/r32/eax
19549     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19550     89/<- %ecx 0/r32/eax
19551     # esi = vars
19552     8b/-> *(ebp+0xc) 6/r32/esi
19553     # eax = vars->top
19554     8b/-> *esi 0/r32/eax
19555     # var min/edx: (addr handle var) = vars->data
19556     8d/copy-address *(esi+8) 2/r32/edx
19557     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
19558     8d/copy-address *(esi+eax-4) 6/r32/esi  # vars + 8 + vars->type - 12
19559     {
19560 $binding-exists?:loop:
19561       # if (curr < min) return
19562       39/compare %esi 2/r32/edx
19563       0f 82/jump-if-addr< break/disp32
19564       # var v/eax: (addr var) = lookup(*curr)
19565       (lookup *esi *(esi+4))  # => eax
19566       # var vn/eax: (addr array byte) = lookup(v->name)
19567       (lookup *eax *(eax+4))  # Var-name Var-name => eax
19568       # if (vn == target-name) return true
19569       (string-equal? %ecx %eax)  # => eax
19570       3d/compare-eax-and 0/imm32/false
19571       75/jump-if-!= $binding-exists?:end/disp8  # eax already contains true
19572       # curr -= 12
19573       81 5/subop/subtract %esi 0xc/imm32
19574       e9/jump loop/disp32
19575     }
19576     b8/copy-to-eax 0/imm32/false
19577 $binding-exists?:end:
19578     # . restore registers
19579     5e/pop-to-esi
19580     5a/pop-to-edx
19581     59/pop-to-ecx
19582     # . epilogue
19583     89/<- %esp 5/r32/ebp
19584     5d/pop-to-ebp
19585     c3/return
19586 
19587 test-parse-mu-stmt:
19588     # . prologue
19589     55/push-ebp
19590     89/<- %ebp 4/r32/esp
19591     # setup
19592     8b/-> *Primitive-type-ids 0/r32/eax
19593     89/<- *Type-id 0/r32/eax  # stream-write
19594     (clear-stream _test-input-stream)
19595     (write _test-input-stream "increment n\n")
19596     # var vars/ecx: (stack (addr var) 16)
19597     81 5/subop/subtract %esp 0xc0/imm32
19598     68/push 0xc0/imm32/size
19599     68/push 0/imm32/top
19600     89/<- %ecx 4/r32/esp
19601     (clear-stack %ecx)
19602     # var v/edx: (handle var)
19603     68/push 0/imm32
19604     68/push 0/imm32
19605     89/<- %edx 4/r32/esp
19606     # var s/eax: (handle array byte)
19607     68/push 0/imm32
19608     68/push 0/imm32
19609     89/<- %eax 4/r32/esp
19610     # v = new var("n")
19611     (copy-array Heap "n" %eax)
19612     (new-var Heap *eax *(eax+4) %edx)
19613     #
19614     (push %ecx *edx)
19615     (push %ecx *(edx+4))
19616     (push %ecx 0)
19617     # var out/eax: (handle stmt)
19618     68/push 0/imm32
19619     68/push 0/imm32
19620     89/<- %eax 4/r32/esp
19621     # convert
19622     (parse-mu-stmt _test-input-stream %ecx 0 %eax Stderr 0)
19623     # var out-addr/edx: (addr stmt) = lookup(*out)
19624     (lookup *eax *(eax+4))  # => eax
19625     89/<- %edx 0/r32/eax
19626     # out->tag
19627     (check-ints-equal *edx 1 "F - test-parse-mu-stmt/tag")  # Stmt-tag is Stmt1
19628     # out->operation
19629     (lookup *(edx+4) *(edx+8))  # Stmt1-operation Stmt1-operation => eax
19630     (check-strings-equal %eax "increment" "F - test-parse-mu-stmt/name")  # Stmt1-operation
19631     # out->inouts->value->name
19632     # . eax = out->inouts
19633     (lookup *(edx+0xc) *(edx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
19634     # . eax = out->inouts->value
19635     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
19636     # . eax = out->inouts->value->name
19637     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19638     # .
19639     (check-strings-equal %eax "n" "F - test-parse-mu-stmt/inout:0")
19640     # . epilogue
19641     89/<- %esp 5/r32/ebp
19642     5d/pop-to-ebp
19643     c3/return
19644 
19645 test-parse-mu-stmt-with-comma:
19646     # . prologue
19647     55/push-ebp
19648     89/<- %ebp 4/r32/esp
19649     # setup
19650     8b/-> *Primitive-type-ids 0/r32/eax
19651     89/<- *Type-id 0/r32/eax  # stream-write
19652     (clear-stream _test-input-stream)
19653     (write _test-input-stream "copy-to n, 3\n")
19654     # var vars/ecx: (stack (addr var) 16)
19655     81 5/subop/subtract %esp 0xc0/imm32
19656     68/push 0xc0/imm32/size
19657     68/push 0/imm32/top
19658     89/<- %ecx 4/r32/esp
19659     (clear-stack %ecx)
19660     # var v/edx: (handle var)
19661     68/push 0/imm32
19662     68/push 0/imm32
19663     89/<- %edx 4/r32/esp
19664     # var s/eax: (handle array byte)
19665     68/push 0/imm32
19666     68/push 0/imm32
19667     89/<- %eax 4/r32/esp
19668     # v = new var("n")
19669     (copy-array Heap "n" %eax)
19670     (new-var Heap *eax *(eax+4) %edx)
19671     #
19672     (push %ecx *edx)
19673     (push %ecx *(edx+4))
19674     (push %ecx 0)
19675     # var out/eax: (handle stmt)
19676     68/push 0/imm32
19677     68/push 0/imm32
19678     89/<- %eax 4/r32/esp
19679     # convert
19680     (parse-mu-stmt _test-input-stream %ecx 0 %eax Stderr 0)
19681     # var out-addr/edx: (addr stmt) = lookup(*out)
19682     (lookup *eax *(eax+4))  # => eax
19683     89/<- %edx 0/r32/eax
19684     # out->tag
19685     (check-ints-equal *edx 1 "F - test-parse-mu-stmt-with-comma/tag")  # Stmt-tag is Stmt1
19686     # out->operation
19687     (lookup *(edx+4) *(edx+8))  # Stmt1-operation Stmt1-operation => eax
19688     (check-strings-equal %eax "copy-to" "F - test-parse-mu-stmt-with-comma/name")  # Stmt1-operation
19689     # out->inouts->value->name
19690     # . eax = out->inouts
19691     (lookup *(edx+0xc) *(edx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
19692     # . eax = out->inouts->value
19693     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
19694     # . eax = out->inouts->value->name
19695     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19696     # .
19697     (check-strings-equal %eax "n" "F - test-parse-mu-stmt-with-comma/inout:0")
19698     # . epilogue
19699     89/<- %esp 5/r32/ebp
19700     5d/pop-to-ebp
19701     c3/return
19702 
19703 new-var:  # ad: (addr allocation-descriptor), name: (handle array byte), out: (addr handle var)
19704     # . prologue
19705     55/push-ebp
19706     89/<- %ebp 4/r32/esp
19707     # . save registers
19708     50/push-eax
19709     51/push-ecx
19710     # ecx = out
19711     8b/-> *(ebp+0x14) 1/r32/ecx
19712     #
19713     (allocate *(ebp+8) *Var-size %ecx)
19714     # var out-addr/eax: (addr var)
19715     (lookup *ecx *(ecx+4))  # => eax
19716     # out-addr->name = name
19717     8b/-> *(ebp+0xc) 1/r32/ecx
19718     89/<- *eax 1/r32/ecx  # Var-name
19719     8b/-> *(ebp+0x10) 1/r32/ecx
19720     89/<- *(eax+4) 1/r32/ecx  # Var-name
19721 #?     (write-buffered Stderr "var ")
19722 #?     (lookup *(ebp+0xc) *(ebp+0x10))
19723 #?     (write-buffered Stderr %eax)
19724 #?     (write-buffered Stderr " at ")
19725 #?     8b/-> *(ebp+0x14) 1/r32/ecx
19726 #?     (lookup *ecx *(ecx+4))  # => eax
19727 #?     (write-int32-hex-buffered Stderr %eax)
19728 #?     (write-buffered Stderr Newline)
19729 #?     (flush Stderr)
19730 $new-var:end:
19731     # . restore registers
19732     59/pop-to-ecx
19733     58/pop-to-eax
19734     # . epilogue
19735     89/<- %esp 5/r32/ebp
19736     5d/pop-to-ebp
19737     c3/return
19738 
19739 # WARNING: modifies name
19740 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)
19741     # . prologue
19742     55/push-ebp
19743     89/<- %ebp 4/r32/esp
19744     # . save registers
19745     50/push-eax
19746     51/push-ecx
19747     # first strip out metadata
19748     8b/-> *(ebp+0xc) 1/r32/ecx
19749     (next-token-from-slice *ecx *(ecx+4) 0x2f *(ebp+0xc))
19750     # if (!is-hex-int?(name)) abort
19751     (hex-int? *(ebp+0xc))  # => eax
19752     3d/compare-eax-and 0/imm32/false
19753     0f 84/jump-if-= $new-literal-integer:abort/disp32
19754     # a little more error-checking
19755     (check-mu-hex-int *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
19756     # out = new var(s)
19757     (new-var-from-slice *(ebp+8) *(ebp+0xc) *(ebp+0x10))
19758     # var out-addr/ecx: (addr var) = lookup(*out)
19759     8b/-> *(ebp+0x10) 0/r32/eax
19760     (lookup *eax *(eax+4))  # => eax
19761     89/<- %ecx 0/r32/eax
19762     # out-addr->block-depth = *Curr-block-depth
19763     8b/-> *Curr-block-depth 0/r32/eax
19764     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
19765     # out-addr->type = new tree()
19766     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
19767     (allocate *(ebp+8) *Type-tree-size %eax)
19768     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
19769     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
19770     # nothing else to do; default type is 'literal'
19771 $new-literal-integer:end:
19772     # . reclaim locals
19773     81 0/subop/add %esp 8/imm32
19774     # . restore registers
19775     59/pop-to-ecx
19776     58/pop-to-eax
19777     # . epilogue
19778     89/<- %esp 5/r32/ebp
19779     5d/pop-to-ebp
19780     c3/return
19781 
19782 $new-literal-integer:abort:
19783     (write-buffered *(ebp+0x18) "fn ")
19784     8b/-> *(ebp+0x14) 0/r32/eax
19785     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19786     (write-buffered *(ebp+0x18) %eax)
19787     (write-buffered *(ebp+0x18) ": variable '")
19788     (write-slice-buffered *(ebp+0x18) *(ebp+0xc))
19789     (write-buffered *(ebp+0x18) "' cannot begin with a digit (or do you have a typo in a number?)\n")
19790     (flush *(ebp+0x18))
19791     (stop *(ebp+0x1c) 1)
19792     # never gets here
19793 
19794 # precondition: name is a valid hex integer; require a '0x' prefix
19795 check-mu-hex-int:  # name: (addr slice), err: (addr buffered-file), ed: (addr exit-descriptor)
19796     # . prologue
19797     55/push-ebp
19798     89/<- %ebp 4/r32/esp
19799     # . save registers
19800     50/push-eax
19801     51/push-ecx
19802     52/push-edx
19803     # ecx = name
19804     8b/-> *(ebp+8) 1/r32/ecx
19805     # var start/edx: (addr byte) = name->start
19806     8b/-> *ecx 2/r32/edx
19807     # if (*start == '-') ++start
19808     b8/copy-to-eax 0/imm32
19809     8a/copy-byte *edx 0/r32/AL
19810     3d/compare-eax-and 0x2d/imm32/dash
19811     {
19812       75/jump-if-!= break/disp8
19813       42/increment-edx
19814     }
19815     # var end/ecx: (addr byte) = name->end
19816     8b/-> *(ecx+4) 1/r32/ecx
19817     # var len/eax: int = name->end - name->start
19818     89/<- %eax 1/r32/ecx
19819     29/subtract-from %eax 2/r32/edx
19820     # if (len <= 1) return
19821     3d/compare-eax-with 1/imm32
19822     0f 8e/jump-if-<= $check-mu-hex-int:end/disp32
19823 $check-mu-hex-int:length->-1:
19824     # if slice-starts-with?({start, end}, "0x") return
19825     # . var tmp = {start, end}
19826     51/push-ecx
19827     52/push-edx
19828     89/<- %eax 4/r32/esp
19829     # .
19830     (slice-starts-with? %eax "0x")  # => eax
19831     # . reclaim tmp
19832     81 0/subop/add %esp 8/imm32
19833     # .
19834     3d/compare-eax-with 0/imm32/false
19835     75/jump-if-!= $check-mu-hex-int:end/disp8
19836 $check-mu-hex-int:abort:
19837     # otherwise abort
19838     (write-buffered *(ebp+0xc) "literal integers are always hex in Mu; start '")
19839     (write-slice-buffered *(ebp+0xc) *(ebp+8))
19840     (write-buffered *(ebp+0xc) "' with a '0x' to be unambiguous, converting it to hexadecimal as necessary.\n")
19841     (flush *(ebp+0xc))
19842     (stop *(ebp+0x10) 1)
19843 $check-mu-hex-int:end:
19844     # . restore registers
19845     5a/pop-to-edx
19846     59/pop-to-ecx
19847     58/pop-to-eax
19848     # . epilogue
19849     89/<- %esp 5/r32/ebp
19850     5d/pop-to-ebp
19851     c3/return
19852 
19853 new-literal:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
19854     # . prologue
19855     55/push-ebp
19856     89/<- %ebp 4/r32/esp
19857     # . save registers
19858     50/push-eax
19859     51/push-ecx
19860     # var s/ecx: (handle array byte)
19861     68/push 0/imm32
19862     68/push 0/imm32
19863     89/<- %ecx 4/r32/esp
19864     # s = slice-to-string(name)
19865     (slice-to-string Heap *(ebp+0xc) %ecx)
19866     # allocate to out
19867     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
19868     # var out-addr/ecx: (addr var) = lookup(*out)
19869     8b/-> *(ebp+0x10) 1/r32/ecx
19870     (lookup *ecx *(ecx+4))  # => eax
19871     89/<- %ecx 0/r32/eax
19872     # out-addr->block-depth = *Curr-block-depth
19873     8b/-> *Curr-block-depth 0/r32/eax
19874     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
19875     # out-addr->type/eax = new type
19876     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
19877     (allocate *(ebp+8) *Type-tree-size %eax)
19878     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
19879     # nothing else to do; default type is 'literal'
19880     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
19881 $new-literal:end:
19882     # . reclaim locals
19883     81 0/subop/add %esp 8/imm32
19884     # . restore registers
19885     59/pop-to-ecx
19886     58/pop-to-eax
19887     # . epilogue
19888     89/<- %esp 5/r32/ebp
19889     5d/pop-to-ebp
19890     c3/return
19891 
19892 new-literal-string:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
19893     # . prologue
19894     55/push-ebp
19895     89/<- %ebp 4/r32/esp
19896     # . save registers
19897     50/push-eax
19898     51/push-ecx
19899     # var s/ecx: (handle array byte)
19900     68/push 0/imm32
19901     68/push 0/imm32
19902     89/<- %ecx 4/r32/esp
19903     # s = slice-to-string(name)
19904     (slice-to-string Heap *(ebp+0xc) %ecx)
19905     # allocate to out
19906     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
19907     # var out-addr/ecx: (addr var) = lookup(*out)
19908     8b/-> *(ebp+0x10) 1/r32/ecx
19909     (lookup *ecx *(ecx+4))  # => eax
19910     89/<- %ecx 0/r32/eax
19911     # out-addr->block-depth = *Curr-block-depth
19912     8b/-> *Curr-block-depth 0/r32/eax
19913     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
19914     # out-addr->type/eax = new type
19915     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
19916     (allocate *(ebp+8) *Type-tree-size %eax)
19917     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
19918     # out-addr->type->value = literal-string
19919     c7 0/subop/copy *(eax+4) 0x10/imm32/type-id-string-literal  # Type-tree-value
19920     # out-addr->type->is-atom? = true
19921     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
19922 $new-literal-string:end:
19923     # . reclaim locals
19924     81 0/subop/add %esp 8/imm32
19925     # . restore registers
19926     59/pop-to-ecx
19927     58/pop-to-eax
19928     # . epilogue
19929     89/<- %esp 5/r32/ebp
19930     5d/pop-to-ebp
19931     c3/return
19932 
19933 new-var-from-slice:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
19934     # . prologue
19935     55/push-ebp
19936     89/<- %ebp 4/r32/esp
19937     # . save registers
19938     51/push-ecx
19939     # var tmp/ecx: (handle array byte)
19940     68/push 0/imm32
19941     68/push 0/imm32
19942     89/<- %ecx 4/r32/esp
19943     # tmp = slice-to-string(name)
19944     (slice-to-string Heap *(ebp+0xc) %ecx)
19945     # out = new-var(tmp)
19946     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
19947 $new-var-from-slice:end:
19948     # . reclaim locals
19949     81 0/subop/add %esp 8/imm32
19950     # . restore registers
19951     59/pop-to-ecx
19952     # . epilogue
19953     89/<- %esp 5/r32/ebp
19954     5d/pop-to-ebp
19955     c3/return
19956 
19957 new-var-def:  # ad: (addr allocation-descriptor), var: (handle var), out: (addr handle stmt)
19958     # . prologue
19959     55/push-ebp
19960     89/<- %ebp 4/r32/esp
19961     # . save registers
19962     50/push-eax
19963     51/push-ecx
19964     #
19965     (allocate *(ebp+8) *Stmt-size *(ebp+0x14))
19966     # var out-addr/eax: (addr stmt) = lookup(*out)
19967     8b/-> *(ebp+0x14) 0/r32/eax
19968     (lookup *eax *(eax+4))  # => eax
19969     # out-addr->tag = stmt
19970     c7 0/subop/copy *eax 2/imm32/tag/var-on-stack  # Stmt-tag
19971     # result->var = var
19972     8b/-> *(ebp+0xc) 1/r32/ecx
19973     89/<- *(eax+4) 1/r32/ecx  # Vardef-var
19974     8b/-> *(ebp+0x10) 1/r32/ecx
19975     89/<- *(eax+8) 1/r32/ecx  # Vardef-var
19976 $new-var-def:end:
19977     # . restore registers
19978     59/pop-to-ecx
19979     58/pop-to-eax
19980     # . epilogue
19981     89/<- %esp 5/r32/ebp
19982     5d/pop-to-ebp
19983     c3/return
19984 
19985 new-reg-var-def:  # ad: (addr allocation-descriptor), var: (handle var), out: (addr handle stmt)
19986     # . prologue
19987     55/push-ebp
19988     89/<- %ebp 4/r32/esp
19989     # . save registers
19990     50/push-eax
19991     # eax = out
19992     8b/-> *(ebp+0x14) 0/r32/eax
19993     #
19994     (allocate *(ebp+8) *Stmt-size %eax)
19995     # var out-addr/eax: (addr stmt) = lookup(*out)
19996     (lookup *eax *(eax+4))  # => eax
19997     # set tag
19998     c7 0/subop/copy *eax 3/imm32/tag/var-in-register  # Stmt-tag
19999     # set output
20000     8d/copy-address *(eax+0x14) 0/r32/eax  # Regvardef-outputs
20001     (append-stmt-var Heap  *(ebp+0xc) *(ebp+0x10)  0 0  0  %eax)
20002 $new-reg-var-def:end:
20003     # . restore registers
20004     58/pop-to-eax
20005     # . epilogue
20006     89/<- %esp 5/r32/ebp
20007     5d/pop-to-ebp
20008     c3/return
20009 
20010 append-list:  # ad: (addr allocation-descriptor), value: (handle _type), list: (handle list _type), out: (addr handle list _type)
20011     # . prologue
20012     55/push-ebp
20013     89/<- %ebp 4/r32/esp
20014     # . save registers
20015     50/push-eax
20016     51/push-ecx
20017     57/push-edi
20018     # edi = out
20019     8b/-> *(ebp+0x1c) 7/r32/edi
20020     # *out = new list
20021     (allocate *(ebp+8) *List-size %edi)
20022     # var out-addr/edi: (addr list _type) = lookup(*out)
20023     (lookup *edi *(edi+4))  # => eax
20024     89/<- %edi 0/r32/eax
20025     # out-addr->value = value
20026     8b/-> *(ebp+0xc) 0/r32/eax
20027     89/<- *edi 0/r32/eax  # List-value
20028     8b/-> *(ebp+0x10) 0/r32/eax
20029     89/<- *(edi+4) 0/r32/eax  # List-value
20030     # if (list == null) return
20031     81 7/subop/compare *(ebp+0x14) 0/imm32
20032     74/jump-if-= $append-list:end/disp8
20033     # otherwise append
20034 $append-list:non-empty-list:
20035     # var curr/eax: (addr list _type) = lookup(list)
20036     (lookup *(ebp+0x14) *(ebp+0x18))  # => eax
20037     # while (curr->next != null) curr = curr->next
20038     {
20039       81 7/subop/compare *(eax+8) 0/imm32  # List-next
20040       74/jump-if-= break/disp8
20041       # curr = lookup(curr->next)
20042       (lookup *(eax+8) *(eax+0xc))  # List-next, List-next => eax
20043       #
20044       eb/jump loop/disp8
20045     }
20046     # edi = out
20047     8b/-> *(ebp+0x1c) 7/r32/edi
20048     # curr->next = out
20049     8b/-> *edi 1/r32/ecx
20050     89/<- *(eax+8) 1/r32/ecx  # List-next
20051     8b/-> *(edi+4) 1/r32/ecx
20052     89/<- *(eax+0xc) 1/r32/ecx  # List-next
20053     # out = list
20054     8b/-> *(ebp+0x14) 1/r32/ecx
20055     89/<- *edi 1/r32/ecx
20056     8b/-> *(ebp+0x18) 1/r32/ecx
20057     89/<- *(edi+4) 1/r32/ecx
20058 $append-list:end:
20059     # . restore registers
20060     5f/pop-to-edi
20061     59/pop-to-ecx
20062     58/pop-to-eax
20063     # . epilogue
20064     89/<- %esp 5/r32/ebp
20065     5d/pop-to-ebp
20066     c3/return
20067 
20068 append-stmt-var:  # ad: (addr allocation-descriptor), v: (handle var), vars: (handle stmt-var), is-deref?: boolean, out: (addr handle stmt-var)
20069     # . prologue
20070     55/push-ebp
20071     89/<- %ebp 4/r32/esp
20072     # . save registers
20073     50/push-eax
20074     51/push-ecx
20075     57/push-edi
20076     # edi = out
20077     8b/-> *(ebp+0x20) 7/r32/edi
20078     # out = new stmt-var
20079     (allocate *(ebp+8) *Stmt-var-size %edi)
20080     # var out-addr/ecx: (addr stmt-var) = lookup(*out)
20081     (lookup *edi *(edi+4))  # => eax
20082     89/<- %ecx 0/r32/eax
20083     # out-addr->value = v
20084     8b/-> *(ebp+0xc) 0/r32/eax
20085     89/<- *ecx 0/r32/eax  # Stmt-var-value
20086     8b/-> *(ebp+0x10) 0/r32/eax
20087     89/<- *(ecx+4) 0/r32/eax  # Stmt-var-value
20088     # out-addr->is-deref? = is-deref?
20089     8b/-> *(ebp+0x1c) 0/r32/eax
20090     89/<- *(ecx+0x10) 0/r32/eax  # Stmt-var-is-deref
20091     # if (vars == null) return result
20092     81 7/subop/compare *(ebp+0x14) 0/imm32/null
20093     74/jump-if-= $append-stmt-var:end/disp8
20094     # otherwise append
20095     # var curr/eax: (addr stmt-var) = lookup(vars)
20096     (lookup *(ebp+0x14) *(ebp+0x18))  # => eax
20097     # while (curr->next != null) curr = curr->next
20098     {
20099       81 7/subop/compare *(eax+8) 0/imm32  # Stmt-var-next
20100       74/jump-if-= break/disp8
20101       # curr = lookup(curr->next)
20102       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next, Stmt-var-next => eax
20103       #
20104       eb/jump loop/disp8
20105     }
20106     # curr->next = out
20107     8b/-> *edi 1/r32/ecx
20108     89/<- *(eax+8) 1/r32/ecx  # Stmt-var-next
20109     8b/-> *(edi+4) 1/r32/ecx
20110     89/<- *(eax+0xc) 1/r32/ecx  # Stmt-var-next
20111     # out = vars
20112     8b/-> *(ebp+0x14) 1/r32/ecx
20113     89/<- *edi 1/r32/ecx
20114     8b/-> *(ebp+0x18) 1/r32/ecx
20115     89/<- *(edi+4) 1/r32/ecx
20116 $append-stmt-var:end:
20117     # . restore registers
20118     5f/pop-to-edi
20119     59/pop-to-ecx
20120     58/pop-to-eax
20121     # . epilogue
20122     89/<- %esp 5/r32/ebp
20123     5d/pop-to-ebp
20124     c3/return
20125 
20126 append-to-block:  # ad: (addr allocation-descriptor), block: (addr block), x: (handle stmt)
20127     # . prologue
20128     55/push-ebp
20129     89/<- %ebp 4/r32/esp
20130     # . save registers
20131     50/push-eax
20132     56/push-esi
20133     # esi = block
20134     8b/-> *(ebp+0xc) 6/r32/esi
20135     # block->stmts = append(x, block->stmts)
20136     8d/copy-address *(esi+4) 0/r32/eax  # Block-stmts
20137     (append-list *(ebp+8)  *(ebp+0x10) *(ebp+0x14)  *(esi+4) *(esi+8)  %eax)  # ad, x, x, Block-stmts, Block-stmts
20138 $append-to-block:end:
20139     # . restore registers
20140     5e/pop-to-esi
20141     58/pop-to-eax
20142     # . epilogue
20143     89/<- %esp 5/r32/ebp
20144     5d/pop-to-ebp
20145     c3/return
20146 
20147 ## Parsing types
20148 # We need to create metadata on user-defined types, and we need to use this
20149 # metadata as we parse instructions.
20150 # However, we also want to allow types to be used before their definitions.
20151 # This means we can't ever assume any type data structures exist.
20152 
20153 lookup-or-create-constant:  # container: (addr stmt-var), field-name: (addr slice), out: (addr handle var)
20154     # . prologue
20155     55/push-ebp
20156     89/<- %ebp 4/r32/esp
20157     # . save registers
20158     50/push-eax
20159     56/push-esi
20160     # var container-type/esi: type-id
20161     (container-type *(ebp+8))  # => eax
20162     89/<- %esi 0/r32/eax
20163     # var tmp/eax: (handle typeinfo) = find-or-create-typeinfo(container-type)
20164     68/push 0/imm32
20165     68/push 0/imm32
20166     89/<- %eax 4/r32/esp
20167     (find-or-create-typeinfo %esi %eax)
20168     # var tmp-addr/eax: (addr typeinfo) = lookup(tmp)
20169     (lookup *eax *(eax+4))  # => eax
20170     # result = find-or-create-typeinfo-output-var(typeinfo, field-name)
20171 #?     (write-buffered Stderr "constant: ")
20172 #?     (write-slice-buffered Stderr *(ebp+0xc))
20173 #?     (write-buffered Stderr Newline)
20174 #?     (flush Stderr)
20175     (find-or-create-typeinfo-output-var %eax *(ebp+0xc) *(ebp+0x10))
20176 #?     8b/-> *(ebp+0x10) 0/r32/eax
20177 #?     (write-buffered Stderr "@")
20178 #?     (lookup *eax *(eax+4))
20179 #?     (write-int32-hex-buffered Stderr %eax)
20180 #?     (lookup *eax *(eax+4))
20181 #?     (write-buffered Stderr %eax)
20182 #?     (write-buffered Stderr Newline)
20183 #?     (flush Stderr)
20184 #?     (write-buffered Stderr "offset: ")
20185 #?     8b/-> *(eax+0x14) 0/r32/eax
20186 #?     (write-int32-hex-buffered Stderr %eax)
20187 #?     (write-buffered Stderr Newline)
20188 #?     (flush Stderr)
20189 $lookup-or-create-constant:end:
20190     # . reclaim locals
20191     81 0/subop/add %esp 8/imm32
20192     # . restore registers
20193     5e/pop-to-esi
20194     58/pop-to-eax
20195     # . epilogue
20196     89/<- %esp 5/r32/ebp
20197     5d/pop-to-ebp
20198     c3/return
20199 
20200 # if addr var:
20201 #   container->var->type->right->left->value
20202 # otherwise
20203 #   container->var->type->value
20204 container-type:  # container: (addr stmt-var) -> result/eax: type-id
20205     # . prologue
20206     55/push-ebp
20207     89/<- %ebp 4/r32/esp
20208     #
20209     8b/-> *(ebp+8) 0/r32/eax
20210     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
20211     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20212     {
20213       81 7/subop/compare *(eax+8) 0/imm32  # Type-tree-right
20214       74/jump-if-= break/disp8
20215       (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
20216       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20217     }
20218     8b/-> *(eax+4) 0/r32/eax  # Type-tree-value
20219 $container-type:end:
20220     # . epilogue
20221     89/<- %esp 5/r32/ebp
20222     5d/pop-to-ebp
20223     c3/return
20224 
20225 container?:  # t: type-id -> result/eax: boolean
20226     # . prologue
20227     55/push-ebp
20228     89/<- %ebp 4/r32/esp
20229     #
20230     8b/-> *(ebp+8) 0/r32/eax
20231     c1/shift 4/subop/left %eax 2/imm8
20232     3b/compare 0/r32/eax *Primitive-type-ids
20233     0f 9d/set-if->= %al
20234     81 4/subop/and %eax 0xff/imm32
20235 $container?:end:
20236     # . epilogue
20237     89/<- %esp 5/r32/ebp
20238     5d/pop-to-ebp
20239     c3/return
20240 
20241 find-or-create-typeinfo:  # t: type-id, out: (addr handle typeinfo)
20242     # . prologue
20243     55/push-ebp
20244     89/<- %ebp 4/r32/esp
20245     # . save registers
20246     50/push-eax
20247     51/push-ecx
20248     52/push-edx
20249     57/push-edi
20250     # edi = out
20251     8b/-> *(ebp+0xc) 7/r32/edi
20252     # var fields/ecx: (handle table (handle array byte) (handle typeinfo-entry))
20253     68/push 0/imm32
20254     68/push 0/imm32
20255     89/<- %ecx 4/r32/esp
20256     # find-typeinfo(t, out)
20257     (find-typeinfo *(ebp+8) %edi)
20258     {
20259       # if (*out != 0) break
20260       81 7/subop/compare *edi 0/imm32
20261       0f 85/jump-if-!= break/disp32
20262 $find-or-create-typeinfo:create:
20263       # *out = allocate
20264       (allocate Heap *Typeinfo-size %edi)
20265       # var tmp/eax: (addr typeinfo) = lookup(*out)
20266       (lookup *edi *(edi+4))  # => eax
20267 #?     (write-buffered Stderr "created typeinfo at ")
20268 #?     (write-int32-hex-buffered Stderr %eax)
20269 #?     (write-buffered Stderr " for type-id ")
20270 #?     (write-int32-hex-buffered Stderr *(ebp+8))
20271 #?     (write-buffered Stderr Newline)
20272 #?     (flush Stderr)
20273       # tmp->id = t
20274       8b/-> *(ebp+8) 2/r32/edx
20275       89/<- *eax 2/r32/edx  # Typeinfo-id
20276       # tmp->fields = new table
20277       # . fields = new table
20278       (new-stream Heap 0x40 *Typeinfo-fields-row-size %ecx)
20279       # . tmp->fields = fields
20280       8b/-> *ecx 2/r32/edx
20281       89/<- *(eax+4) 2/r32/edx  # Typeinfo-fields
20282       8b/-> *(ecx+4) 2/r32/edx
20283       89/<- *(eax+8) 2/r32/edx  # Typeinfo-fields
20284       # tmp->next = Program->types
20285       8b/-> *_Program-types 1/r32/ecx
20286       89/<- *(eax+0x10) 1/r32/ecx  # Typeinfo-next
20287       8b/-> *_Program-types->payload 1/r32/ecx
20288       89/<- *(eax+0x14) 1/r32/ecx  # Typeinfo-next
20289       # Program->types = out
20290       8b/-> *edi 1/r32/ecx
20291       89/<- *_Program-types 1/r32/ecx
20292       8b/-> *(edi+4) 1/r32/ecx
20293       89/<- *_Program-types->payload 1/r32/ecx
20294     }
20295 $find-or-create-typeinfo:end:
20296     # . reclaim locals
20297     81 0/subop/add %esp 8/imm32
20298     # . restore registers
20299     5f/pop-to-edi
20300     5a/pop-to-edx
20301     59/pop-to-ecx
20302     58/pop-to-eax
20303     # . epilogue
20304     89/<- %esp 5/r32/ebp
20305     5d/pop-to-ebp
20306     c3/return
20307 
20308 find-typeinfo:  # t: type-id, out: (addr handle typeinfo)
20309     # . prologue
20310     55/push-ebp
20311     89/<- %ebp 4/r32/esp
20312     # . save registers
20313     50/push-eax
20314     51/push-ecx
20315     52/push-edx
20316     57/push-edi
20317     # ecx = t
20318     8b/-> *(ebp+8) 1/r32/ecx
20319     # edi = out
20320     8b/-> *(ebp+0xc) 7/r32/edi
20321     # *out = Program->types
20322     8b/-> *_Program-types 0/r32/eax
20323     89/<- *edi 0/r32/eax
20324     8b/-> *_Program-types->payload 0/r32/eax
20325     89/<- *(edi+4) 0/r32/eax
20326     {
20327 $find-typeinfo:loop:
20328       # if (*out == 0) break
20329       81 7/subop/compare *edi 0/imm32
20330       74/jump-if-= break/disp8
20331 $find-typeinfo:check:
20332       # var tmp/eax: (addr typeinfo) = lookup(*out)
20333       (lookup *edi *(edi+4))  # => eax
20334       # if (tmp->id == t) break
20335       39/compare *eax 1/r32/ecx  # Typeinfo-id
20336       74/jump-if-= break/disp8
20337 $find-typeinfo:continue:
20338       # *out = tmp->next
20339       8b/-> *(eax+0x10) 2/r32/edx  # Typeinfo-next
20340       89/<- *edi 2/r32/edx
20341       8b/-> *(eax+0x14) 2/r32/edx  # Typeinfo-next
20342       89/<- *(edi+4) 2/r32/edx
20343       #
20344       eb/jump loop/disp8
20345     }
20346 $find-typeinfo:end:
20347     # . restore registers
20348     5f/pop-to-edi
20349     5a/pop-to-edx
20350     59/pop-to-ecx
20351     58/pop-to-eax
20352     # . epilogue
20353     89/<- %esp 5/r32/ebp
20354     5d/pop-to-ebp
20355     c3/return
20356 
20357 find-or-create-typeinfo-output-var:  # T: (addr typeinfo), f: (addr slice), out: (addr handle var)
20358     # . prologue
20359     55/push-ebp
20360     89/<- %ebp 4/r32/esp
20361     # . save registers
20362     50/push-eax
20363     52/push-edx
20364     57/push-edi
20365     # var dest/edi: (handle typeinfo-entry)
20366     68/push 0/imm32
20367     68/push 0/imm32
20368     89/<- %edi 4/r32/esp
20369     # find-or-create-typeinfo-fields(T, f, dest)
20370     (find-or-create-typeinfo-fields *(ebp+8) *(ebp+0xc) %edi)
20371     # var dest-addr/edi: (addr typeinfo-entry) = lookup(dest)
20372     (lookup *edi *(edi+4))  # => eax
20373     89/<- %edi 0/r32/eax
20374     # if dest-addr->output-var doesn't exist, create it
20375     {
20376       81 7/subop/compare *(edi+0xc) 0/imm32  # Typeinfo-entry-output-var
20377       0f 85/jump-if-!= break/disp32
20378       # dest-addr->output-var = new var(dummy name, type, -1 offset)
20379       # . var name/eax: (handle array byte) = "field"
20380       68/push 0/imm32
20381       68/push 0/imm32
20382       89/<- %eax 4/r32/esp
20383       (slice-to-string Heap *(ebp+0xc) %eax)
20384       # . new var
20385       8d/copy-address *(edi+0xc) 2/r32/edx
20386       (new-var Heap  *eax *(eax+4)  %edx)
20387       # . reclaim name
20388       81 0/subop/add %esp 8/imm32
20389       # var result/edx: (addr var) = lookup(dest-addr->output-var)
20390       (lookup *(edi+0xc) *(edi+0x10))  # => eax
20391       89/<- %edx 0/r32/eax
20392       # result->type = new constant type
20393       8d/copy-address *(edx+8) 0/r32/eax  # Var-type
20394       (allocate Heap *Type-tree-size %eax)
20395       (lookup *(edx+8) *(edx+0xc))  # => eax
20396       c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
20397       c7 0/subop/copy *(eax+4) 6/imm32/constant  # Type-tree-value
20398       c7 0/subop/copy *(eax+8) 0/imm32  # Type-tree-left
20399       c7 0/subop/copy *(eax+0xc) 0/imm32  # Type-tree-right
20400       c7 0/subop/copy *(eax+0x10) 0/imm32  # Type-tree-right
20401       # result->offset isn't filled out yet
20402       c7 0/subop/copy *(edx+0x14) -1/imm32/uninitialized  # Var-offset
20403     }
20404     # out = dest-addr->output-var
20405     8b/-> *(ebp+0x10) 2/r32/edx
20406     8b/-> *(edi+0xc) 0/r32/eax  # Typeinfo-entry-output-var
20407     89/<- *edx 0/r32/eax
20408     8b/-> *(edi+0x10) 0/r32/eax  # Typeinfo-entry-output-var
20409     89/<- *(edx+4) 0/r32/eax
20410 $find-or-create-typeinfo-output-var:end:
20411     # . reclaim locals
20412     81 0/subop/add %esp 8/imm32
20413     # . restore registers
20414     5f/pop-to-edi
20415     5a/pop-to-edx
20416     58/pop-to-eax
20417     # . epilogue
20418     89/<- %esp 5/r32/ebp
20419     5d/pop-to-ebp
20420     c3/return
20421 
20422 find-or-create-typeinfo-fields:  # T: (addr typeinfo), f: (addr slice), out: (addr handle typeinfo-entry)
20423     # . prologue
20424     55/push-ebp
20425     89/<- %ebp 4/r32/esp
20426     # . save registers
20427     50/push-eax
20428     56/push-esi
20429     57/push-edi
20430     # eax = lookup(T->fields)
20431     8b/-> *(ebp+8) 0/r32/eax
20432     (lookup *(eax+4) *(eax+8))  # Typeinfo-fields Typeinfo-fields => eax
20433     # edi = out
20434     8b/-> *(ebp+0x10) 7/r32/edi
20435     # var src/esi: (addr handle typeinfo-entry) = get-or-insert-slice(T->fields, f)
20436     (get-or-insert-slice %eax *(ebp+0xc) *Typeinfo-fields-row-size Heap)  # => eax
20437     89/<- %esi 0/r32/eax
20438     # if src doesn't exist, allocate it
20439     {
20440       81 7/subop/compare *esi 0/imm32
20441       75/jump-if-!= break/disp8
20442       (allocate Heap *Typeinfo-entry-size %esi)
20443 #?       (write-buffered Stderr "handle at ")
20444 #?       (write-int32-hex-buffered Stderr %esi)
20445 #?       (write-buffered Stderr ": ")
20446 #?       (write-int32-hex-buffered Stderr *esi)
20447 #?       (write-buffered Stderr " ")
20448 #?       (write-int32-hex-buffered Stderr *(esi+4))
20449 #?       (write-buffered Stderr Newline)
20450 #?       (flush Stderr)
20451 #?       (lookup *esi *(esi+4))
20452 #?       (write-buffered Stderr "created typeinfo fields at ")
20453 #?       (write-int32-hex-buffered Stderr %esi)
20454 #?       (write-buffered Stderr " for ")
20455 #?       (write-int32-hex-buffered Stderr *(ebp+8))
20456 #?       (write-buffered Stderr Newline)
20457 #?       (flush Stderr)
20458     }
20459     # *out = src
20460     # . *edi = *src
20461     8b/-> *esi 0/r32/eax
20462     89/<- *edi 0/r32/eax
20463     8b/-> *(esi+4) 0/r32/eax
20464     89/<- *(edi+4) 0/r32/eax
20465 $find-or-create-typeinfo-fields:end:
20466     # . restore registers
20467     5f/pop-to-edi
20468     5e/pop-to-esi
20469     58/pop-to-eax
20470     # . epilogue
20471     89/<- %esp 5/r32/ebp
20472     5d/pop-to-ebp
20473     c3/return
20474 
20475 populate-mu-type:  # in: (addr stream byte), t: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
20476     # pseudocode:
20477     #   var line: (stream byte 512)
20478     #   curr-index = 0
20479     #   while true
20480     #     clear-stream(line)
20481     #     read-line-buffered(in, line)
20482     #     if line->write == 0
20483     #       abort
20484     #     word-slice = next-mu-token(line)
20485     #     if slice-empty?(word-slice)               # end of line
20486     #       continue
20487     #     if slice-equal?(word-slice, "}")
20488     #       break
20489     #     var v: (handle var) = parse-var-with-type(word-slice, line)
20490     #     var r: (handle typeinfo-fields) = find-or-create-typeinfo-fields(t, word-slice/v->name)
20491     #     TODO: ensure that r->first is null
20492     #     r->index = curr-index
20493     #     curr-index++
20494     #     r->input-var = v
20495     #     if r->output-var == 0
20496     #       r->output-var = new literal
20497     #     TODO: ensure nothing else in line
20498     # t->total-size-in-bytes = -2 (not yet initialized)
20499     #
20500     # . prologue
20501     55/push-ebp
20502     89/<- %ebp 4/r32/esp
20503     # var curr-index: int at *(ebp-4)
20504     68/push 0/imm32
20505     # . save registers
20506     50/push-eax
20507     51/push-ecx
20508     52/push-edx
20509     53/push-ebx
20510     56/push-esi
20511     57/push-edi
20512     # edi = t
20513     8b/-> *(ebp+0xc) 7/r32/edi
20514     # var line/ecx: (stream byte 512)
20515     81 5/subop/subtract %esp 0x200/imm32
20516     68/push 0x200/imm32/size
20517     68/push 0/imm32/read
20518     68/push 0/imm32/write
20519     89/<- %ecx 4/r32/esp
20520     # var word-slice/edx: slice
20521     68/push 0/imm32/end
20522     68/push 0/imm32/start
20523     89/<- %edx 4/r32/esp
20524     # var v/esi: (handle var)
20525     68/push 0/imm32
20526     68/push 0/imm32
20527     89/<- %esi 4/r32/esp
20528     # var r/ebx: (handle typeinfo-entry)
20529     68/push 0/imm32
20530     68/push 0/imm32
20531     89/<- %ebx 4/r32/esp
20532     {
20533 $populate-mu-type:line-loop:
20534       (clear-stream %ecx)
20535       (read-line-buffered *(ebp+8) %ecx)
20536       # if (line->write == 0) abort
20537       81 7/subop/compare *ecx 0/imm32
20538       0f 84/jump-if-= $populate-mu-type:error1/disp32
20539 +--  6 lines: #?       # dump line ------------------------------------------------------------------------------------------------------------------------------------------------------
20545       (next-mu-token %ecx %edx)
20546       # if slice-empty?(word-slice) continue
20547       (slice-empty? %edx)  # => eax
20548       3d/compare-eax-and 0/imm32
20549       0f 85/jump-if-!= loop/disp32
20550       # if slice-equal?(word-slice, "}") break
20551       (slice-equal? %edx "}")
20552       3d/compare-eax-and 0/imm32
20553       0f 85/jump-if-!= break/disp32
20554 $populate-mu-type:parse-element:
20555       # v = parse-var-with-type(word-slice, first-line)
20556       # must do this first to strip the trailing ':' from word-slice before
20557       # using it in find-or-create-typeinfo-fields below
20558       # TODO: clean up that mutation in parse-var-with-type
20559       (type-name *edi)  # Typeinfo-id => eax
20560       (parse-var-with-type %edx %ecx %esi %eax *(ebp+0x10) *(ebp+0x14))
20561       # if v is an addr, abort
20562       (lookup *esi *(esi+4))  # => eax
20563       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20564       (mu-addr-type? %eax)  # => eax
20565       3d/compare-eax-and 0/imm32/false
20566       0f 85/jump-if-!= $populate-mu-type:error2/disp32
20567       # if v is an array, abort  (we could support it, but initialization gets complex)
20568       (lookup *esi *(esi+4))  # => eax
20569       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20570       (mu-array-type? %eax)  # => eax
20571       3d/compare-eax-and 0/imm32/false
20572       0f 85/jump-if-!= $populate-mu-type:error3/disp32
20573       # if v is a byte, abort
20574       (lookup *esi *(esi+4))  # => eax
20575       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20576       (simple-mu-type? %eax 8)  # byte => eax
20577       3d/compare-eax-and 0/imm32/false
20578       0f 85/jump-if-!= $populate-mu-type:error4/disp32
20579       # if v is a slice, abort
20580       (lookup *esi *(esi+4))  # => eax
20581       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20582       (simple-mu-type? %eax 0xc)  # slice => eax
20583       3d/compare-eax-and 0/imm32/false
20584       0f 85/jump-if-!= $populate-mu-type:error5/disp32
20585       # if v is a stream, abort  (we could support it, but initialization gets even more complex)
20586       (lookup *esi *(esi+4))  # => eax
20587       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20588       (mu-stream-type? %eax)  # => eax
20589       3d/compare-eax-and 0/imm32/false
20590       0f 85/jump-if-!= $populate-mu-type:error6/disp32
20591       # var tmp/ecx
20592       51/push-ecx
20593 $populate-mu-type:create-typeinfo-fields:
20594       # var r/ebx: (handle typeinfo-entry)
20595       (find-or-create-typeinfo-fields %edi %edx %ebx)
20596       # r->index = curr-index
20597       (lookup *ebx *(ebx+4))  # => eax
20598       8b/-> *(ebp-4) 1/r32/ecx
20599 #?       (write-buffered Stderr "saving index ")
20600 #?       (write-int32-hex-buffered Stderr %ecx)
20601 #?       (write-buffered Stderr " at ")
20602 #?       (write-int32-hex-buffered Stderr %edi)
20603 #?       (write-buffered Stderr Newline)
20604 #?       (flush Stderr)
20605       89/<- *(eax+8) 1/r32/ecx  # Typeinfo-entry-index
20606       # ++curr-index
20607       ff 0/subop/increment *(ebp-4)
20608 $populate-mu-type:set-input-type:
20609       # r->input-var = v
20610       8b/-> *esi 1/r32/ecx
20611       89/<- *eax 1/r32/ecx  # Typeinfo-entry-input-var
20612       8b/-> *(esi+4) 1/r32/ecx
20613       89/<- *(eax+4) 1/r32/ecx  # Typeinfo-entry-input-var
20614       # restore line
20615       59/pop-to-ecx
20616       {
20617 $populate-mu-type:create-output-type:
20618         # if (r->output-var == 0) create a new var with some placeholder data
20619         81 7/subop/compare *(eax+0xc) 0/imm32  # Typeinfo-entry-output-var
20620         75/jump-if-!= break/disp8
20621         8d/copy-address *(eax+0xc) 0/r32/eax  # Typeinfo-entry-output-var
20622         (new-literal Heap %edx %eax)
20623       }
20624       e9/jump loop/disp32
20625     }
20626 $populate-mu-type:invalidate-total-size-in-bytes:
20627     # Offsets and total size may not be accurate here since we may not yet
20628     # have encountered the element types.
20629     # We'll recompute them separately after parsing the entire program.
20630     c7 0/subop/copy *(edi+0xc) -2/imm32/uninitialized  # Typeinfo-total-size-in-bytes
20631 $populate-mu-type:end:
20632     # . reclaim locals
20633     81 0/subop/add %esp 0x224/imm32
20634     # . restore registers
20635     5f/pop-to-edi
20636     5e/pop-to-esi
20637     5b/pop-to-ebx
20638     5a/pop-to-edx
20639     59/pop-to-ecx
20640     58/pop-to-eax
20641     # reclaim curr-index
20642     81 0/subop/add %esp 4/imm32
20643     # . epilogue
20644     89/<- %esp 5/r32/ebp
20645     5d/pop-to-ebp
20646     c3/return
20647 
20648 $populate-mu-type:error1:
20649     # error("incomplete type definition '" t->name "'\n")
20650     (write-buffered *(ebp+0x10) "incomplete type definition '")
20651     (type-name *edi)  # Typeinfo-id => eax
20652     (write-buffered *(ebp+0x10) %eax)
20653     (write-buffered *(ebp+0x10) "\n")
20654     (flush *(ebp+0x10))
20655     (stop *(ebp+0x14) 1)
20656     # never gets here
20657 
20658 $populate-mu-type:error2:
20659     (write-buffered *(ebp+0x10) "type ")
20660     (type-name *edi)  # Typeinfo-id => eax
20661     (write-buffered *(ebp+0x10) %eax)
20662     (write-buffered *(ebp+0x10) ": 'addr' elements not allowed\n")
20663     (flush *(ebp+0x10))
20664     (stop *(ebp+0x14) 1)
20665     # never gets here
20666 
20667 $populate-mu-type:error3:
20668     (write-buffered *(ebp+0x10) "type ")
20669     (type-name *edi)  # Typeinfo-id => eax
20670     (write-buffered *(ebp+0x10) %eax)
20671     (write-buffered *(ebp+0x10) ": 'array' elements not allowed for now\n")
20672     (flush *(ebp+0x10))
20673     (stop *(ebp+0x14) 1)
20674     # never gets here
20675 
20676 $populate-mu-type:error4:
20677     (write-buffered *(ebp+0x10) "type ")
20678     (type-name *edi)  # Typeinfo-id => eax
20679     (write-buffered *(ebp+0x10) %eax)
20680     (write-buffered *(ebp+0x10) ": 'byte' elements not allowed\n")
20681     (flush *(ebp+0x10))
20682     (stop *(ebp+0x14) 1)
20683     # never gets here
20684 
20685 $populate-mu-type:error5:
20686     (write-buffered *(ebp+0x10) "type ")
20687     (type-name *edi)  # Typeinfo-id => eax
20688     (write-buffered *(ebp+0x10) %eax)
20689     (write-buffered *(ebp+0x10) ": 'slice' elements not allowed\n")
20690     (flush *(ebp+0x10))
20691     (stop *(ebp+0x14) 1)
20692     # never gets here
20693 
20694 $populate-mu-type:error6:
20695     (write-buffered *(ebp+0x10) "type ")
20696     (type-name *edi)  # Typeinfo-id => eax
20697     (write-buffered *(ebp+0x10) %eax)
20698     (write-buffered *(ebp+0x10) ": 'stream' elements not allowed for now\n")
20699     (flush *(ebp+0x10))
20700     (stop *(ebp+0x14) 1)
20701     # never gets here
20702 
20703 type-name:  # index: int -> result/eax: (addr array byte)
20704     # . prologue
20705     55/push-ebp
20706     89/<- %ebp 4/r32/esp
20707     #
20708     (index Type-id *(ebp+8))
20709 $type-name:end:
20710     # . epilogue
20711     89/<- %esp 5/r32/ebp
20712     5d/pop-to-ebp
20713     c3/return
20714 
20715 index:  # arr: (addr stream (handle array byte)), index: int -> result/eax: (addr array byte)
20716     # . prologue
20717     55/push-ebp
20718     89/<- %ebp 4/r32/esp
20719     # . save registers
20720     56/push-esi
20721     # TODO: bounds-check index
20722     # esi = arr
20723     8b/-> *(ebp+8) 6/r32/esi
20724     # eax = index
20725     8b/-> *(ebp+0xc) 0/r32/eax
20726     # eax = *(arr + 12 + index)
20727     8b/-> *(esi+eax<<2+0xc) 0/r32/eax
20728 $index:end:
20729     # . restore registers
20730     5e/pop-to-esi
20731     # . epilogue
20732     89/<- %esp 5/r32/ebp
20733     5d/pop-to-ebp
20734     c3/return
20735 
20736 #######################################################
20737 # Compute type sizes
20738 #######################################################
20739 
20740 # Compute the sizes of all user-defined types.
20741 # We'll need the sizes of their elements, which may be other user-defined
20742 # types, which we will compute as needed.
20743 
20744 # Initially, all user-defined types have their sizes set to -2 (invalid)
20745 populate-mu-type-sizes:  # err: (addr buffered-file), ed: (addr exit-descriptor)
20746     # . prologue
20747     55/push-ebp
20748     89/<- %ebp 4/r32/esp
20749 $populate-mu-type-sizes:total-sizes:
20750     # var curr/eax: (addr typeinfo) = lookup(Program->types)
20751     (lookup *_Program-types *_Program-types->payload)  # => eax
20752     {
20753       # if (curr == null) break
20754       3d/compare-eax-and 0/imm32/null
20755       74/jump-if-= break/disp8
20756       (populate-mu-type-sizes-in-type %eax *(ebp+8) *(ebp+0xc))
20757       # curr = lookup(curr->next)
20758       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
20759       eb/jump loop/disp8
20760     }
20761 $populate-mu-type-sizes:offsets:
20762     # curr = *Program->types
20763     (lookup *_Program-types *_Program-types->payload)  # => eax
20764     {
20765       # if (curr == null) break
20766       3d/compare-eax-and 0/imm32/null
20767       74/jump-if-= break/disp8
20768       (populate-mu-type-offsets %eax *(ebp+8) *(ebp+0xc))
20769       # curr = curr->next
20770       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
20771       eb/jump loop/disp8
20772     }
20773 $populate-mu-type-sizes:end:
20774     # . epilogue
20775     89/<- %esp 5/r32/ebp
20776     5d/pop-to-ebp
20777     c3/return
20778 
20779 # compute sizes of all fields, recursing as necessary
20780 # sum up all their sizes to arrive at total size
20781 # fields may be out of order, but that doesn't affect the answer
20782 populate-mu-type-sizes-in-type:  # T: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
20783     # . prologue
20784     55/push-ebp
20785     89/<- %ebp 4/r32/esp
20786     # . save registers
20787     50/push-eax
20788     51/push-ecx
20789     52/push-edx
20790     56/push-esi
20791     57/push-edi
20792     # esi = T
20793     8b/-> *(ebp+8) 6/r32/esi
20794     # if T is already computed, return
20795     81 7/subop/compare *(esi+0xc) 0/imm32  # Typeinfo-total-size-in-bytes
20796     0f 8d/jump-if->= $populate-mu-type-sizes-in-type:end/disp32
20797     # if T is being computed, abort
20798     81 7/subop/compare *(esi+0xc) -1/imm32/being-computed  # Typeinfo-total-size-in-bytes
20799     0f 84/jump-if-= $populate-mu-type-sizes-in-type:abort/disp32
20800     # tag T (-2 to -1) to avoid infinite recursion
20801     c7 0/subop/copy *(esi+0xc) -1/imm32/being-computed  # Typeinfo-total-size-in-bytes
20802     # var total-size/edi: int = 0
20803     bf/copy-to-edi 0/imm32
20804     # - for every field, if it's a user-defined type, compute its size
20805     # var table/ecx: (addr table (handle array byte) (handle typeinfo-entry)) = lookup(T->fields)
20806     (lookup *(esi+4) *(esi+8))  # Typeinfo-fields Typeinfo-fields => eax
20807     89/<- %ecx 0/r32/eax
20808     # var table-size/edx: int = table->write
20809     8b/-> *ecx 2/r32/edx  # stream-write
20810     # var curr/ecx: (addr table_row) = table->data
20811     8d/copy-address *(ecx+0xc) 1/r32/ecx
20812     # var max/edx: (addr table_row) = table->data + table->write
20813     8d/copy-address *(ecx+edx) 2/r32/edx
20814     {
20815 $populate-mu-type-sizes-in-type:loop:
20816       # if (curr >= max) break
20817       39/compare %ecx 2/r32/edx
20818       73/jump-if-addr>= break/disp8
20819       # var t/eax: (addr typeinfo-entry) = lookup(curr->value)
20820       (lookup *(ecx+8) *(ecx+0xc))  # => eax
20821       # if (t->input-var == 0) silently ignore it; we'll emit a nice error message while type-checking
20822       81 7/subop/compare *eax 0/imm32  # Typeinfo-entry-input-var
20823       74/jump-if-= $populate-mu-type-sizes-in-type:end/disp8
20824       # compute size of t->input-var
20825       (lookup *eax *(eax+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
20826       (compute-size-of-var %eax *(ebp+0xc) *(ebp+0x10))  # => eax
20827       # result += eax
20828       01/add-to %edi 0/r32/eax
20829       # curr += row-size
20830       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-fields-row-size
20831       #
20832       eb/jump loop/disp8
20833     }
20834     # - save result
20835     89/<- *(esi+0xc) 7/r32/edi  # Typeinfo-total-size-in-bytes
20836 $populate-mu-type-sizes-in-type:end:
20837     # . restore registers
20838     5f/pop-to-edi
20839     5e/pop-to-esi
20840     5a/pop-to-edx
20841     59/pop-to-ecx
20842     58/pop-to-eax
20843     # . epilogue
20844     89/<- %esp 5/r32/ebp
20845     5d/pop-to-ebp
20846     c3/return
20847 
20848 $populate-mu-type-sizes-in-type:abort:
20849     (write-buffered *(ebp+0xc) "cycle in type definitions\n")
20850     (flush *(ebp+0xc))
20851     (stop *(ebp+0x10) 1)
20852     # never gets here
20853 
20854 # Analogous to size-of, except we need to compute what size-of can just read
20855 # off the right data structures.
20856 compute-size-of-var:  # in: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
20857     # . prologue
20858     55/push-ebp
20859     89/<- %ebp 4/r32/esp
20860     # . push registers
20861     51/push-ecx
20862     # var t/ecx: (addr type-tree) = lookup(v->type)
20863     8b/-> *(ebp+8) 1/r32/ecx
20864     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
20865     89/<- %ecx 0/r32/eax
20866     # if (t->is-atom == false) t = lookup(t->left)
20867     {
20868       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
20869       75/jump-if-!= break/disp8
20870       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
20871       89/<- %ecx 0/r32/eax
20872     }
20873     # TODO: ensure t is an atom
20874     (compute-size-of-type-id *(ecx+4) *(ebp+0xc) *(ebp+0x10))  # Type-tree-value => eax
20875 $compute-size-of-var:end:
20876     # . restore registers
20877     59/pop-to-ecx
20878     # . epilogue
20879     89/<- %esp 5/r32/ebp
20880     5d/pop-to-ebp
20881     c3/return
20882 
20883 compute-size-of-type-id:  # t: type-id, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
20884     # . prologue
20885     55/push-ebp
20886     89/<- %ebp 4/r32/esp
20887     # . save registers
20888     51/push-ecx
20889     # var out/ecx: (handle typeinfo)
20890     68/push 0/imm32
20891     68/push 0/imm32
20892     89/<- %ecx 4/r32/esp
20893     # eax = t
20894     8b/-> *(ebp+8) 0/r32/eax
20895     # if t is a literal, return 0
20896     3d/compare-eax-and 0/imm32/literal
20897     0f 84/jump-if-= $compute-size-of-type-id:end/disp32  # eax changes type from type-id to int
20898     # if t is a byte, return 4 (because we don't really support non-multiples of 4)
20899     3d/compare-eax-and 8/imm32/byte
20900     {
20901       75/jump-if-!= break/disp8
20902       b8/copy-to-eax 4/imm32
20903       eb/jump $compute-size-of-type-id:end/disp8
20904     }
20905     # if t is a handle, return 8
20906     3d/compare-eax-and 4/imm32/handle
20907     {
20908       75/jump-if-!= break/disp8
20909       b8/copy-to-eax 8/imm32
20910       eb/jump $compute-size-of-type-id:end/disp8  # eax changes type from type-id to int
20911     }
20912     # if t is a slice, return 8
20913     3d/compare-eax-and 0xc/imm32/slice
20914     {
20915       75/jump-if-!= break/disp8
20916       b8/copy-to-eax 8/imm32
20917       eb/jump $compute-size-of-type-id:end/disp8  # eax changes type from type-id to int
20918     }
20919     # if t is a user-defined type, compute its size
20920     # TODO: support non-atom type
20921     (find-typeinfo %eax %ecx)
20922     {
20923       81 7/subop/compare *ecx 0/imm32
20924       74/jump-if-= break/disp8
20925 $compute-size-of-type-id:user-defined:
20926       (lookup *ecx *(ecx+4))  # => eax
20927       (populate-mu-type-sizes-in-type %eax *(ebp+0xc) *(ebp+0x10))
20928       8b/-> *(eax+0xc) 0/r32/eax  # Typeinfo-total-size-in-bytes
20929       eb/jump $compute-size-of-type-id:end/disp8
20930     }
20931     # otherwise return the word size
20932     b8/copy-to-eax 4/imm32
20933 $compute-size-of-type-id:end:
20934     # . reclaim locals
20935     81 0/subop/add %esp 8/imm32
20936     # . restore registers
20937     59/pop-to-ecx
20938     # . epilogue
20939     89/<- %esp 5/r32/ebp
20940     5d/pop-to-ebp
20941     c3/return
20942 
20943 # at this point we have total sizes for all user-defined types
20944 # compute offsets for each element
20945 # complication: fields may be out of order
20946 populate-mu-type-offsets:  # in: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
20947     # . prologue
20948     55/push-ebp
20949     89/<- %ebp 4/r32/esp
20950     # . save registers
20951     50/push-eax
20952     51/push-ecx
20953     52/push-edx
20954     53/push-ebx
20955     56/push-esi
20956     57/push-edi
20957 #?     (dump-typeinfos "aaa\n")
20958     # var curr-offset/edi: int = 0
20959     bf/copy-to-edi 0/imm32
20960     # var table/ecx: (addr table string_key (handle typeinfo-entry)) = lookup(in->fields)
20961     8b/-> *(ebp+8) 1/r32/ecx
20962     (lookup *(ecx+4) *(ecx+8))  # Typeinfo-fields Typeinfo-fields => eax
20963     89/<- %ecx 0/r32/eax
20964     # var num-elems/edx: int = table->write / Typeinfo-fields-row-size
20965     8b/-> *ecx 2/r32/edx  # stream-write
20966     c1 5/subop/shift-right-logical  %edx 4/imm8
20967     # var i/ebx: int = 0
20968     bb/copy-to-ebx 0/imm32
20969     {
20970 $populate-mu-type-offsets:loop:
20971       39/compare %ebx 2/r32/edx
20972       0f 8d/jump-if->= break/disp32
20973 #?       (write-buffered Stderr "looking up index ")
20974 #?       (write-int32-hex-buffered Stderr %ebx)
20975 #?       (write-buffered Stderr " in ")
20976 #?       (write-int32-hex-buffered Stderr *(ebp+8))
20977 #?       (write-buffered Stderr Newline)
20978 #?       (flush Stderr)
20979       # var v/esi: (addr typeinfo-entry)
20980       (locate-typeinfo-entry-with-index %ecx %ebx *(ebp+0xc) *(ebp+0x10))  # => eax
20981       89/<- %esi 0/r32/eax
20982       # if v is null, silently move on; we'll emit a nice error message while type-checking
20983       81 7/subop/compare %esi 0/imm32  # Typeinfo-entry-input-var
20984       74/jump-if-= $populate-mu-type-offsets:end/disp8
20985       # if (v->input-var == 0) silently ignore v; we'll emit a nice error message while type-checking
20986       81 7/subop/compare *esi 0/imm32  # Typeinfo-entry-input-var
20987       74/jump-if-= $populate-mu-type-offsets:end/disp8
20988       # v->output-var->offset = curr-offset
20989       # . eax: (addr var)
20990       (lookup *(esi+0xc) *(esi+0x10))  # Typeinfo-entry-output-var Typeinfo-entry-output-var => eax
20991       89/<- *(eax+0x14) 7/r32/edi  # Var-offset
20992       # curr-offset += size-of(v->input-var)
20993       (lookup *esi *(esi+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
20994       (size-of %eax)  # => eax
20995       01/add-to %edi 0/r32/eax
20996       # ++i
20997       43/increment-ebx
20998       e9/jump loop/disp32
20999     }
21000 $populate-mu-type-offsets:end:
21001     # . restore registers
21002     5f/pop-to-edi
21003     5e/pop-to-esi
21004     5b/pop-to-ebx
21005     5a/pop-to-edx
21006     59/pop-to-ecx
21007     58/pop-to-eax
21008     # . epilogue
21009     89/<- %esp 5/r32/ebp
21010     5d/pop-to-ebp
21011     c3/return
21012 
21013 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)
21014     # . prologue
21015     55/push-ebp
21016     89/<- %ebp 4/r32/esp
21017     # . save registers
21018     51/push-ecx
21019     52/push-edx
21020     53/push-ebx
21021     56/push-esi
21022     57/push-edi
21023     # esi = table
21024     8b/-> *(ebp+8) 6/r32/esi
21025     # var curr/ecx: (addr row (handle array byte) (handle typeinfo-entry)) = table->data
21026     8d/copy-address *(esi+0xc) 1/r32/ecx
21027     # var max/edx: (addr byte) = &table->data[table->write]
21028     8b/-> *esi 2/r32/edx
21029     8d/copy-address *(ecx+edx) 2/r32/edx
21030     {
21031 $locate-typeinfo-entry-with-index:loop:
21032       39/compare %ecx 2/r32/edx
21033       73/jump-if-addr>= break/disp8
21034       # var v/eax: (addr typeinfo-entry)
21035       (lookup *(ecx+8) *(ecx+0xc))  # => eax
21036       # if (v->index == idx) return v
21037       8b/-> *(eax+8) 3/r32/ebx  # Typeinfo-entry-index
21038 #?       (write-buffered Stderr "comparing ")
21039 #?       (write-int32-hex-buffered Stderr %ebx)
21040 #?       (write-buffered Stderr " and ")
21041 #?       (write-int32-hex-buffered Stderr *(ebp+0xc))
21042 #?       (write-buffered Stderr Newline)
21043 #?       (flush Stderr)
21044       39/compare *(ebp+0xc) 3/r32/ebx
21045       74/jump-if-= $locate-typeinfo-entry-with-index:end/disp8
21046       # curr += Typeinfo-entry-size
21047       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-entry-size
21048       #
21049       eb/jump loop/disp8
21050     }
21051     # return 0
21052     b8/copy-to-eax 0/imm32
21053 $locate-typeinfo-entry-with-index:end:
21054 #?     (write-buffered Stderr "returning ")
21055 #?     (write-int32-hex-buffered Stderr %eax)
21056 #?     (write-buffered Stderr Newline)
21057 #?     (flush Stderr)
21058     # . restore registers
21059     5f/pop-to-edi
21060     5e/pop-to-esi
21061     5b/pop-to-ebx
21062     5a/pop-to-edx
21063     59/pop-to-ecx
21064     # . epilogue
21065     89/<- %esp 5/r32/ebp
21066     5d/pop-to-ebp
21067     c3/return
21068 
21069 dump-typeinfos:  # hdr: (addr array byte)
21070     # . prologue
21071     55/push-ebp
21072     89/<- %ebp 4/r32/esp
21073     # . save registers
21074     50/push-eax
21075     #
21076     (write-buffered Stderr *(ebp+8))
21077     (flush Stderr)
21078     # var curr/eax: (addr typeinfo) = lookup(Program->types)
21079     (lookup *_Program-types *_Program-types->payload)  # => eax
21080     {
21081       # if (curr == null) break
21082       3d/compare-eax-and 0/imm32
21083       74/jump-if-= break/disp8
21084       (write-buffered Stderr "---\n")
21085       (flush Stderr)
21086       (dump-typeinfo %eax)
21087       # curr = lookup(curr->next)
21088       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
21089       eb/jump loop/disp8
21090     }
21091 $dump-typeinfos:end:
21092     # . restore registers
21093     58/pop-to-eax
21094     # . epilogue
21095     89/<- %esp 5/r32/ebp
21096     5d/pop-to-ebp
21097     c3/return
21098 
21099 dump-typeinfo:  # in: (addr typeinfo)
21100     # . prologue
21101     55/push-ebp
21102     89/<- %ebp 4/r32/esp
21103     # . save registers
21104     50/push-eax
21105     51/push-ecx
21106     52/push-edx
21107     53/push-ebx
21108     56/push-esi
21109     57/push-edi
21110     # esi = in
21111     8b/-> *(ebp+8) 6/r32/esi
21112     # var table/ecx: (addr table (handle array byte) (handle typeinfo-entry)) = lookup(T->fields)
21113     (lookup *(esi+4) *(esi+8))  # Typeinfo-fields Typeinfo-fields => eax
21114     89/<- %ecx 0/r32/eax
21115     (write-buffered Stderr "id:")
21116     (write-int32-hex-buffered Stderr *esi)
21117     (write-buffered Stderr "\n")
21118     (write-buffered Stderr "fields @ ")
21119     (write-int32-hex-buffered Stderr %ecx)
21120     (write-buffered Stderr Newline)
21121     (flush Stderr)
21122     (write-buffered Stderr "  write: ")
21123     (write-int32-hex-buffered Stderr *ecx)
21124     (write-buffered Stderr Newline)
21125     (flush Stderr)
21126     (write-buffered Stderr "  read: ")
21127     (write-int32-hex-buffered Stderr *(ecx+4))
21128     (write-buffered Stderr Newline)
21129     (flush Stderr)
21130     (write-buffered Stderr "  size: ")
21131     (write-int32-hex-buffered Stderr *(ecx+8))
21132     (write-buffered Stderr Newline)
21133     (flush Stderr)
21134     # var table-size/edx: int = table->write
21135     8b/-> *ecx 2/r32/edx  # stream-write
21136     # var curr/ecx: (addr table_row) = table->data
21137     8d/copy-address *(ecx+0xc) 1/r32/ecx
21138     # var max/edx: (addr table_row) = table->data + table->write
21139     8d/copy-address *(ecx+edx) 2/r32/edx
21140     {
21141 $dump-typeinfo:loop:
21142       # if (curr >= max) break
21143       39/compare %ecx 2/r32/edx
21144       0f 83/jump-if-addr>= break/disp32
21145       (write-buffered Stderr "  row:\n")
21146       (write-buffered Stderr "    key: ")
21147       (write-int32-hex-buffered Stderr *ecx)
21148       (write-buffered Stderr ",")
21149       (write-int32-hex-buffered Stderr *(ecx+4))
21150       (write-buffered Stderr " = '")
21151       (lookup *ecx *(ecx+4))
21152       (write-buffered Stderr %eax)
21153       (write-buffered Stderr "' @ ")
21154       (write-int32-hex-buffered Stderr %eax)
21155       (write-buffered Stderr Newline)
21156       (flush Stderr)
21157       (write-buffered Stderr "    value: ")
21158       (write-int32-hex-buffered Stderr *(ecx+8))
21159       (write-buffered Stderr ",")
21160       (write-int32-hex-buffered Stderr *(ecx+0xc))
21161       (write-buffered Stderr " = typeinfo-entry@")
21162       (lookup *(ecx+8) *(ecx+0xc))
21163       (write-int32-hex-buffered Stderr %eax)
21164       (write-buffered Stderr Newline)
21165       (flush Stderr)
21166       (write-buffered Stderr "        input var@")
21167       (dump-var 5 %eax)
21168       (lookup *(ecx+8) *(ecx+0xc))
21169       (write-buffered Stderr "        index: ")
21170       (write-int32-hex-buffered Stderr *(eax+8))
21171       (write-buffered Stderr Newline)
21172       (flush Stderr)
21173       (write-buffered Stderr "        output var@")
21174       8d/copy-address *(eax+0xc) 0/r32/eax  # Typeinfo-entry-output-var
21175       (dump-var 5 %eax)
21176       (flush Stderr)
21177       # curr += row-size
21178       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-fields-row-size
21179       #
21180       e9/jump loop/disp32
21181     }
21182 $dump-typeinfo:end:
21183     # . restore registers
21184     5f/pop-to-edi
21185     5e/pop-to-esi
21186     5b/pop-to-ebx
21187     5a/pop-to-edx
21188     59/pop-to-ecx
21189     58/pop-to-eax
21190     # . epilogue
21191     89/<- %esp 5/r32/ebp
21192     5d/pop-to-ebp
21193     c3/return
21194 
21195 dump-var:  # indent: int, v: (addr handle var)
21196     # . prologue
21197     55/push-ebp
21198     89/<- %ebp 4/r32/esp
21199     # . save registers
21200     50/push-eax
21201     53/push-ebx
21202     # eax = v
21203     8b/-> *(ebp+0xc) 0/r32/eax
21204     #
21205     (write-int32-hex-buffered Stderr *eax)
21206     (write-buffered Stderr ",")
21207     (write-int32-hex-buffered Stderr *(eax+4))
21208     (write-buffered Stderr "->")
21209     (lookup *eax *(eax+4))
21210     (write-int32-hex-buffered Stderr %eax)
21211     (write-buffered Stderr Newline)
21212     (flush Stderr)
21213     {
21214       3d/compare-eax-and 0/imm32
21215       0f 84/jump-if-= break/disp32
21216       (emit-indent Stderr *(ebp+8))
21217       (write-buffered Stderr "name: ")
21218       89/<- %ebx 0/r32/eax
21219       (write-int32-hex-buffered Stderr *ebx)  # Var-name
21220       (write-buffered Stderr ",")
21221       (write-int32-hex-buffered Stderr *(ebx+4))  # Var-name
21222       (write-buffered Stderr "->")
21223       (lookup *ebx *(ebx+4))  # Var-name
21224       (write-int32-hex-buffered Stderr %eax)
21225       {
21226         3d/compare-eax-and 0/imm32
21227         74/jump-if-= break/disp8
21228         (write-buffered Stderr Space)
21229         (write-buffered Stderr %eax)
21230       }
21231       (write-buffered Stderr Newline)
21232       (flush Stderr)
21233       (emit-indent Stderr *(ebp+8))
21234       (write-buffered Stderr "block depth: ")
21235       (write-int32-hex-buffered Stderr *(ebx+0x10))  # Var-block-depth
21236       (write-buffered Stderr Newline)
21237       (flush Stderr)
21238       (emit-indent Stderr *(ebp+8))
21239       (write-buffered Stderr "stack offset: ")
21240       (write-int32-hex-buffered Stderr *(ebx+0x14))  # Var-offset
21241       (write-buffered Stderr Newline)
21242       (flush Stderr)
21243       (emit-indent Stderr *(ebp+8))
21244       (write-buffered Stderr "reg: ")
21245       (write-int32-hex-buffered Stderr *(ebx+0x18))  # Var-register
21246       (write-buffered Stderr ",")
21247       (write-int32-hex-buffered Stderr *(ebx+0x1c))  # Var-register
21248       (write-buffered Stderr "->")
21249       (flush Stderr)
21250       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register
21251       (write-int32-hex-buffered Stderr %eax)
21252       {
21253         3d/compare-eax-and 0/imm32
21254         74/jump-if-= break/disp8
21255         (write-buffered Stderr Space)
21256         (write-buffered Stderr %eax)
21257       }
21258       (write-buffered Stderr Newline)
21259       (flush Stderr)
21260     }
21261 $dump-var:end:
21262     # . restore registers
21263     5b/pop-to-ebx
21264     58/pop-to-eax
21265     # . epilogue
21266     89/<- %esp 5/r32/ebp
21267     5d/pop-to-ebp
21268     c3/return
21269 
21270 #######################################################
21271 # Type-checking
21272 #######################################################
21273 
21274 check-mu-types:  # err: (addr buffered-file), ed: (addr exit-descriptor)
21275     # . prologue
21276     55/push-ebp
21277     89/<- %ebp 4/r32/esp
21278     # . save registers
21279     50/push-eax
21280     # var curr/eax: (addr function) = lookup(Program->functions)
21281     (lookup *_Program-functions *_Program-functions->payload)  # => eax
21282     {
21283 $check-mu-types:loop:
21284       # if (curr == null) break
21285       3d/compare-eax-and 0/imm32
21286       0f 84/jump-if-= break/disp32
21287 +--  8 lines: #?       # dump curr->name ------------------------------------------------------------------------------------------------------------------------------------------------
21295       (check-mu-function %eax *(ebp+8) *(ebp+0xc))
21296       # curr = lookup(curr->next)
21297       (lookup *(eax+0x20) *(eax+0x24))  # Function-next Function-next => eax
21298       e9/jump loop/disp32
21299     }
21300 $check-mu-types:end:
21301     # . restore registers
21302     58/pop-to-eax
21303     # . epilogue
21304     89/<- %esp 5/r32/ebp
21305     5d/pop-to-ebp
21306     c3/return
21307 
21308 check-mu-function:  # fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21309     # . prologue
21310     55/push-ebp
21311     89/<- %ebp 4/r32/esp
21312     # . save registers
21313     50/push-eax
21314     56/push-esi
21315     # esi = f
21316     8b/-> *(ebp+8) 6/r32/esi
21317     # outputs
21318     (lookup *(esi+0x10) *(esi+0x14))  # Function-outputs Function-outputs => eax
21319     (check-all-unique-registers %eax %esi *(ebp+0xc) *(ebp+0x10))
21320     # body
21321     (lookup *(esi+0x18) *(esi+0x1c))  # Function-body Function-body => eax
21322     (check-mu-block %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10))
21323     # if function has no outputs, we're done
21324     81 7/subop/compare *(esi+0x10) 0/imm32
21325     74/jump-if-= $check-mu-function:end/disp8
21326     # some final checks on body
21327     (check-final-stmt-is-return %eax %esi *(ebp+0xc) *(ebp+0x10))
21328     (check-no-breaks %eax %esi *(ebp+0xc) *(ebp+0x10))
21329 $check-mu-function:end:
21330     # . restore registers
21331     5e/pop-to-esi
21332     58/pop-to-eax
21333     # . epilogue
21334     89/<- %esp 5/r32/ebp
21335     5d/pop-to-ebp
21336     c3/return
21337 
21338 check-mu-block:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21339     # . prologue
21340     55/push-ebp
21341     89/<- %ebp 4/r32/esp
21342     # . save registers
21343     50/push-eax
21344     # eax = block
21345     8b/-> *(ebp+8) 0/r32/eax
21346     # var stmts/eax: (addr list stmt) = lookup(block->statements)
21347     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
21348     #
21349     {
21350 $check-mu-block:check-empty:
21351       3d/compare-eax-and 0/imm32
21352       0f 84/jump-if-= break/disp32
21353       # emit block->statements
21354       (check-mu-stmt-list %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21355     }
21356 $check-mu-block:end:
21357     # . restore registers
21358     58/pop-to-eax
21359     # . epilogue
21360     89/<- %esp 5/r32/ebp
21361     5d/pop-to-ebp
21362     c3/return
21363 
21364 check-mu-stmt-list:  # stmts: (addr list stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21365     # . prologue
21366     55/push-ebp
21367     89/<- %ebp 4/r32/esp
21368     # . save registers
21369     50/push-eax
21370     56/push-esi
21371     # esi = stmts
21372     8b/-> *(ebp+8) 6/r32/esi
21373     {
21374 $check-mu-stmt-list:loop:
21375       81 7/subop/compare %esi 0/imm32
21376       0f 84/jump-if-= break/disp32
21377       # var curr-stmt/eax: (addr stmt) = lookup(stmts->value)
21378       (lookup *esi *(esi+4))  # List-value List-value => eax
21379       {
21380 $check-mu-stmt-list:check-for-block:
21381         81 7/subop/compare *eax 0/imm32/block  # Stmt-tag
21382         75/jump-if-!= break/disp8
21383 $check-mu-stmt-list:block:
21384         (check-mu-block %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21385         eb/jump $check-mu-stmt-list:continue/disp8
21386       }
21387       {
21388 $check-mu-stmt-list:check-for-stmt1:
21389         81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
21390         0f 85/jump-if-!= break/disp32
21391 $check-mu-stmt-list:stmt1:
21392         (check-mu-stmt %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21393         eb/jump $check-mu-stmt-list:continue/disp8
21394       }
21395       {
21396 $check-mu-stmt-list:check-for-reg-var-def:
21397         81 7/subop/compare *eax 3/imm32/reg-var-def  # Stmt-tag
21398         0f 85/jump-if-!= break/disp32
21399 $check-mu-stmt-list:reg-var-def:
21400         (check-mu-stmt %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21401         eb/jump $check-mu-stmt-list:continue/disp8
21402       }
21403 $check-mu-stmt-list:continue:
21404       # TODO: raise an error on unrecognized Stmt-tag
21405       (lookup *(esi+8) *(esi+0xc))  # List-next List-next => eax
21406       89/<- %esi 0/r32/eax
21407       e9/jump loop/disp32
21408     }
21409 $check-mu-stmt-list:end:
21410     # . restore registers
21411     5e/pop-to-esi
21412     58/pop-to-eax
21413     # . epilogue
21414     89/<- %esp 5/r32/ebp
21415     5d/pop-to-ebp
21416     c3/return
21417 
21418 check-mu-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21419     # . prologue
21420     55/push-ebp
21421     89/<- %ebp 4/r32/esp
21422     # . save registers
21423     50/push-eax
21424     # - if stmt's operation matches a primitive, check against it
21425     (has-primitive-name? *(ebp+8))  # => eax
21426     3d/compare-eax-and 0/imm32/false
21427     {
21428       74/jump-if-= break/disp8
21429       (check-mu-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21430       e9/jump $check-mu-stmt:end/disp32
21431     }
21432     # - otherwise find a function to check against
21433     # var f/eax: (addr function) = lookup(*Program->functions)
21434     (lookup *_Program-functions *_Program-functions->payload)  # => eax
21435     (find-matching-function %eax *(ebp+8))  # => eax
21436     3d/compare-eax-and 0/imm32
21437     {
21438       74/jump-if-= break/disp8
21439       (check-mu-call *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21440       eb/jump $check-mu-stmt:end/disp8
21441     }
21442     # var f/eax: (addr function) = lookup(*Program->signatures)
21443     (lookup *_Program-signatures *_Program-signatures->payload)  # => eax
21444     (find-matching-function %eax *(ebp+8))  # => eax
21445     3d/compare-eax-and 0/imm32
21446     {
21447       74/jump-if-= break/disp8
21448       (check-mu-call *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21449       eb/jump $check-mu-stmt:end/disp8
21450     }
21451     # - otherwise abort
21452     e9/jump $check-mu-stmt:unknown-call/disp32
21453 $check-mu-stmt:end:
21454     # . restore registers
21455     58/pop-to-eax
21456     # . epilogue
21457     89/<- %esp 5/r32/ebp
21458     5d/pop-to-ebp
21459     c3/return
21460 
21461 $check-mu-stmt:unknown-call:
21462     (write-buffered *(ebp+0x10) "unknown function '")
21463     8b/-> *(ebp+8) 0/r32/eax
21464     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
21465     (write-buffered *(ebp+0x10) %eax)
21466     (write-buffered *(ebp+0x10) "'\n")
21467     (flush *(ebp+0x10))
21468     (stop *(ebp+0x14) 1)
21469     # never gets here
21470 
21471 has-primitive-name?:  # stmt: (addr stmt) -> result/eax: boolean
21472     # . prologue
21473     55/push-ebp
21474     89/<- %ebp 4/r32/esp
21475     # . save registers
21476     51/push-ecx
21477     56/push-esi
21478     # var name/esi: (addr array byte) = lookup(stmt->operation)
21479     8b/-> *(ebp+8) 6/r32/esi
21480     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
21481     89/<- %esi 0/r32/eax
21482     # if (name == "return") return true
21483     (string-equal? %esi "return")  # => eax
21484     3d/compare-eax-and 0/imm32/false
21485     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21486     # if (name == "get") return true
21487     (string-equal? %esi "get")  # => eax
21488     3d/compare-eax-and 0/imm32/false
21489     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21490     # if (name == "index") return true
21491     (string-equal? %esi "index")  # => eax
21492     3d/compare-eax-and 0/imm32/false
21493     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21494     # if (name == "length") return true
21495     (string-equal? %esi "length")  # => eax
21496     3d/compare-eax-and 0/imm32/false
21497     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21498     # if (name == "compute-offset") return true
21499     (string-equal? %esi "compute-offset")  # => eax
21500     3d/compare-eax-and 0/imm32/false
21501     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21502     # if (name == "copy-object") return true
21503     (string-equal? %esi "copy-object")  # => eax
21504     3d/compare-eax-and 0/imm32/false
21505     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21506     # if (name == "clear-object") return true
21507     (string-equal? %esi "clear-object")  # => eax
21508     3d/compare-eax-and 0/imm32/false
21509     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21510     # if (name == "allocate") return true
21511     (string-equal? %esi "allocate")  # => eax
21512     3d/compare-eax-and 0/imm32/false
21513     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21514     # if (name == "populate") return true
21515     (string-equal? %esi "populate")  # => eax
21516     3d/compare-eax-and 0/imm32/false
21517     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21518     # if (name == "populate-stream") return true
21519     (string-equal? %esi "populate-stream")  # => eax
21520     3d/compare-eax-and 0/imm32/false
21521     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21522     # if (name == "read-from-stream") return true
21523     (string-equal? %esi "read-from-stream")  # => eax
21524     3d/compare-eax-and 0/imm32/false
21525     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21526     # if (name == "write-to-stream") return true
21527     (string-equal? %esi "write-to-stream")  # => eax
21528     3d/compare-eax-and 0/imm32/false
21529     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21530     # var curr/ecx: (addr primitive) = Primitives
21531     b9/copy-to-ecx Primitives/imm32
21532     {
21533 $has-primitive-name?:loop:
21534       # if (curr == null) break
21535       81 7/subop/compare %ecx 0/imm32
21536       74/jump-if-= break/disp8
21537       # if (primitive->name == name) return true
21538       (lookup *ecx *(ecx+4))  # Primitive-name Primitive-name => eax
21539 #?       (write-buffered Stderr %eax)
21540 #?       (write-buffered Stderr Newline)
21541 #?       (flush Stderr)
21542       (string-equal? %esi %eax)  # => eax
21543       3d/compare-eax-and 0/imm32/false
21544       75/jump-if-!= $has-primitive-name?:end/disp8
21545 $has-primitive-name?:next-primitive:
21546       # curr = curr->next
21547       (lookup *(ecx+0x3c) *(ecx+0x40))  # Primitive-next Primitive-next => eax
21548       89/<- %ecx 0/r32/eax
21549       #
21550       e9/jump loop/disp32
21551     }
21552     # return null
21553     b8/copy-to-eax 0/imm32
21554 $has-primitive-name?:end:
21555     # . restore registers
21556     5e/pop-to-esi
21557     59/pop-to-ecx
21558     # . epilogue
21559     89/<- %esp 5/r32/ebp
21560     5d/pop-to-ebp
21561     c3/return
21562 
21563 check-mu-primitive:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21564     # . prologue
21565     55/push-ebp
21566     89/<- %ebp 4/r32/esp
21567     # . save registers
21568     50/push-eax
21569     51/push-ecx
21570     # var op/ecx: (addr array byte) = lookup(stmt->operation)
21571     8b/-> *(ebp+8) 0/r32/eax
21572     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
21573     89/<- %ecx 0/r32/eax
21574     # if (op == "copy") check-mu-copy-stmt
21575     {
21576       (string-equal? %ecx "copy")  # => eax
21577       3d/compare-eax-and 0/imm32/false
21578       74/jump-if-= break/disp8
21579       (check-mu-copy-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21580       e9/jump $check-mu-primitive:end/disp32
21581     }
21582     # if (op == "copy-to") check-mu-copy-to-stmt
21583     {
21584       (string-equal? %ecx "copy-to")  # => eax
21585       3d/compare-eax-and 0/imm32/false
21586       74/jump-if-= break/disp8
21587       (check-mu-copy-to-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21588       e9/jump $check-mu-primitive:end/disp32
21589     }
21590     # if (op == "copy-byte") check-mu-copy-byte-stmt
21591     {
21592       (string-equal? %ecx "copy-byte")  # => eax
21593       3d/compare-eax-and 0/imm32/false
21594       74/jump-if-= break/disp8
21595       (check-mu-copy-byte-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21596       e9/jump $check-mu-primitive:end/disp32
21597     }
21598     # if (op == "copy-byte-to") check-mu-copy-byte-to-stmt
21599     {
21600       (string-equal? %ecx "copy-byte-to")  # => eax
21601       3d/compare-eax-and 0/imm32/false
21602       74/jump-if-= break/disp8
21603       (check-mu-copy-byte-to-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21604       e9/jump $check-mu-primitive:end/disp32
21605     }
21606     # if (op == "compare") check-mu-compare-stmt
21607     {
21608       (string-equal? %ecx "compare")  # => eax
21609       3d/compare-eax-and 0/imm32/false
21610       74/jump-if-= break/disp8
21611       (check-mu-compare-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21612       e9/jump $check-mu-primitive:end/disp32
21613     }
21614     # if (op == "address") check-mu-address-stmt
21615     {
21616       (string-equal? %ecx "address")  # => eax
21617       3d/compare-eax-and 0/imm32/false
21618       74/jump-if-= break/disp8
21619       (check-mu-address-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21620       e9/jump $check-mu-primitive:end/disp32
21621     }
21622     # if (op == "return") check-mu-return-stmt
21623     {
21624       (string-equal? %ecx "return")  # => eax
21625       3d/compare-eax-and 0/imm32/false
21626       74/jump-if-= break/disp8
21627       (check-mu-return-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21628       e9/jump $check-mu-primitive:end/disp32
21629     }
21630     # if (op == "get") check-mu-get-stmt
21631     {
21632       (string-equal? %ecx "get")  # => eax
21633       3d/compare-eax-and 0/imm32/false
21634       74/jump-if-= break/disp8
21635       (check-mu-get-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21636       e9/jump $check-mu-primitive:end/disp32
21637     }
21638     # if (op == "index") check-mu-index-stmt
21639     {
21640       (string-equal? %ecx "index")  # => eax
21641       3d/compare-eax-and 0/imm32/false
21642       74/jump-if-= break/disp8
21643       (check-mu-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21644       e9/jump $check-mu-primitive:end/disp32
21645     }
21646     # if (op == "length") check-mu-length-stmt
21647     {
21648       (string-equal? %ecx "length")  # => eax
21649       3d/compare-eax-and 0/imm32/false
21650       74/jump-if-= break/disp8
21651       (check-mu-length-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21652       e9/jump $check-mu-primitive:end/disp32
21653     }
21654     # if (op == "compute-offset") check-mu-compute-offset-stmt
21655     {
21656       (string-equal? %ecx "compute-offset")  # => eax
21657       3d/compare-eax-and 0/imm32/false
21658       74/jump-if-= break/disp8
21659       (check-mu-compute-offset-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21660       e9/jump $check-mu-primitive:end/disp32
21661     }
21662     # if (op == "copy-object") check-mu-copy-object-stmt
21663     {
21664       (string-equal? %ecx "copy-object")  # => eax
21665       3d/compare-eax-and 0/imm32/false
21666       74/jump-if-= break/disp8
21667       (check-mu-copy-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21668       e9/jump $check-mu-primitive:end/disp32
21669     }
21670     # if (op == "clear-object") check-mu-clear-object-stmt
21671     {
21672       (string-equal? %ecx "clear-object")  # => eax
21673       3d/compare-eax-and 0/imm32/false
21674       74/jump-if-= break/disp8
21675       (check-mu-clear-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21676       e9/jump $check-mu-primitive:end/disp32
21677     }
21678     # if (op == "allocate") check-mu-allocate-stmt
21679     {
21680       (string-equal? %ecx "allocate")  # => eax
21681       3d/compare-eax-and 0/imm32/false
21682       74/jump-if-= break/disp8
21683       (check-mu-allocate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21684       e9/jump $check-mu-primitive:end/disp32
21685     }
21686     # if (op == "populate") check-mu-populate-stmt
21687     {
21688       (string-equal? %ecx "populate")  # => eax
21689       3d/compare-eax-and 0/imm32/false
21690       74/jump-if-= break/disp8
21691       (check-mu-populate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21692       e9/jump $check-mu-primitive:end/disp32
21693     }
21694     # if (op == "populate-stream") check-mu-populate-stream-stmt
21695     {
21696       (string-equal? %ecx "populate-stream")  # => eax
21697       3d/compare-eax-and 0/imm32/false
21698       74/jump-if-= break/disp8
21699       (check-mu-populate-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21700       e9/jump $check-mu-primitive:end/disp32
21701     }
21702     # if (op == "read-from-stream") check-mu-read-from-stream-stmt
21703     {
21704       (string-equal? %ecx "read-from-stream")  # => eax
21705       3d/compare-eax-and 0/imm32/false
21706       74/jump-if-= break/disp8
21707       (check-mu-read-from-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21708       e9/jump $check-mu-primitive:end/disp32
21709     }
21710     # if (op == "write-to-stream") check-mu-write-to-stream-stmt
21711     {
21712       (string-equal? %ecx "write-to-stream")  # => eax
21713       3d/compare-eax-and 0/imm32/false
21714       74/jump-if-= break/disp8
21715       (check-mu-write-to-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21716       e9/jump $check-mu-primitive:end/disp32
21717     }
21718     # if (op == "convert") check-mu-convert-stmt
21719     {
21720       (string-equal? %ecx "convert")  # => eax
21721       3d/compare-eax-and 0/imm32/false
21722       74/jump-if-= break/disp8
21723       (check-mu-convert-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21724       e9/jump $check-mu-primitive:end/disp32
21725     }
21726     # otherwise check-numberlike-stmt
21727     (check-mu-numberlike-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21728 $check-mu-primitive:end:
21729     # . restore registers
21730     59/pop-to-ecx
21731     58/pop-to-eax
21732     # . epilogue
21733     89/<- %esp 5/r32/ebp
21734     5d/pop-to-ebp
21735     c3/return
21736 
21737 # by default, Mu primitives should only operate on 'number-like' types
21738 check-mu-numberlike-primitive:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21739     # . prologue
21740     55/push-ebp
21741     89/<- %ebp 4/r32/esp
21742     # . save registers
21743     50/push-eax
21744     51/push-ecx
21745     56/push-esi
21746     # esi = stmt
21747     8b/-> *(ebp+8) 6/r32/esi
21748     # var gas/ecx: int = 2
21749     b9/copy-to-ecx 2/imm32
21750     # - check at most 1 output
21751     # var output/eax: (addr stmt-var) = stmt->outputs
21752     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
21753     {
21754       3d/compare-eax-and 0/imm32
21755       74/jump-if-= break/disp8
21756 $check-mu-numberlike-primitive:output:
21757       (check-mu-numberlike-output %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21758       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
21759       3d/compare-eax-and 0/imm32
21760       0f 85/jump-if-!= $check-mu-numberlike-primitive:error-too-many-outputs/disp32
21761       # check output is in a register
21762       # --gas
21763       49/decrement-ecx
21764     }
21765     # - check first inout
21766     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21767     {
21768       3d/compare-eax-and 0/imm32
21769       0f 84/jump-if-= $check-mu-numberlike-primitive:end/disp32
21770 $check-mu-numberlike-primitive:first-inout:
21771       (check-mu-numberlike-arg %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21772       # --gas
21773       49/decrement-ecx
21774     }
21775     # - check second inout
21776     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
21777     {
21778       3d/compare-eax-and 0/imm32
21779       74/jump-if-= $check-mu-numberlike-primitive:end/disp8
21780 $check-mu-numberlike-primitive:second-inout:
21781       # is a second inout allowed?
21782       81 7/subop/compare %ecx 0/imm32
21783       0f 84/jump-if-= $check-mu-numberlike-primitive:error-too-many-inouts/disp32
21784 $check-mu-numberlike-primitive:second-inout-permitted:
21785       (check-mu-numberlike-arg %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21786     }
21787 $check-mu-numberlike-primitive:third-inout:
21788     # if there's a third arg, raise an error
21789     81 7/subop/compare *(eax+8) 0/imm32  # Stmt-var-next
21790     0f 85/jump-if-!= $check-mu-numberlike-primitive:error-too-many-inouts/disp32
21791 $check-mu-numberlike-primitive:end:
21792     # . restore registers
21793     5e/pop-to-esi
21794     59/pop-to-ecx
21795     58/pop-to-eax
21796     # . epilogue
21797     89/<- %esp 5/r32/ebp
21798     5d/pop-to-ebp
21799     c3/return
21800 
21801 $check-mu-numberlike-primitive:error-too-many-inouts:
21802     (write-buffered *(ebp+0x10) "fn ")
21803     8b/-> *(ebp+0xc) 0/r32/eax
21804     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21805     (write-buffered *(ebp+0x10) %eax)
21806     (write-buffered *(ebp+0x10) ": stmt ")
21807     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
21808     (write-buffered *(ebp+0x10) %eax)
21809     (write-buffered *(ebp+0x10) ": too many inouts; most primitives support at most two arguments, across inouts and outputs\n")
21810     (flush *(ebp+0x10))
21811     (stop *(ebp+0x14) 1)
21812     # never gets here
21813 
21814 $check-mu-numberlike-primitive:error-too-many-outputs:
21815     (write-buffered *(ebp+0x10) "fn ")
21816     8b/-> *(ebp+0xc) 0/r32/eax
21817     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21818     (write-buffered *(ebp+0x10) %eax)
21819     (write-buffered *(ebp+0x10) ": stmt ")
21820     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
21821     (write-buffered *(ebp+0x10) %eax)
21822     (write-buffered *(ebp+0x10) ": too many outputs; most primitives support at most one output\n")
21823     (flush *(ebp+0x10))
21824     (stop *(ebp+0x14) 1)
21825     # never gets here
21826 
21827 check-mu-numberlike-arg:  # v: (addr stmt-var), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21828     # . prologue
21829     55/push-ebp
21830     89/<- %ebp 4/r32/esp
21831     # . save registers
21832     50/push-eax
21833     56/push-esi
21834     # var t/esi: (addr type-tree) = lookup(v->value->type)
21835     8b/-> *(ebp+8) 0/r32/eax
21836     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21837     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21838     89/<- %esi 0/r32/eax
21839 $check-mu-numberlike-arg:check-literal:
21840     # if t is an int, return
21841     (simple-mu-type? %esi 0)  # literal => eax
21842     3d/compare-eax-and 0/imm32/false
21843     0f 85/jump-if-!= $check-mu-numberlike-arg:end/disp32
21844 $check-mu-numberlike-arg:check-addr:
21845     # if t is an addr and v is dereferenced, return whether t->payload is an addr
21846     {
21847       (mu-addr-type? %esi)  # => eax
21848       3d/compare-eax-and 0/imm32/false
21849       74/jump-if-= break/disp8
21850       8b/-> *(ebp+8) 0/r32/eax
21851       8b/-> *(eax+0x10) 0/r32/eax  # Stmt-var-is-deref
21852       3d/compare-eax-and 0/imm32/false
21853       {
21854         74/jump-if-= break/disp8
21855         (lookup *(esi+0xc) *(esi+0x10))  # Type-tree-right Type-tree-right => eax
21856         # if t->right is null, t = t->left
21857         81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
21858         {
21859           75/jump-if-!= break/disp8
21860           (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21861         }
21862         (mu-addr-type? %eax)  # => eax
21863         3d/compare-eax-and 0/imm32/false
21864         74/jump-if-= $check-mu-numberlike-arg:end/disp8
21865       }
21866     }
21867 $check-mu-numberlike-arg:output-checks:
21868     (check-mu-numberlike-output *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18))
21869 $check-mu-numberlike-arg:end:
21870     # . restore registers
21871     5e/pop-to-esi
21872     58/pop-to-eax
21873     # . epilogue
21874     89/<- %esp 5/r32/ebp
21875     5d/pop-to-ebp
21876     c3/return
21877 
21878 check-mu-numberlike-output:  # v: (addr stmt-var), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21879     # . prologue
21880     55/push-ebp
21881     89/<- %ebp 4/r32/esp
21882     # . save registers
21883     50/push-eax
21884     #
21885     (mu-numberlike-output-var? *(ebp+8))  # => eax
21886     3d/compare-eax-and 0/imm32/false
21887     0f 84/jump-if-= $check-mu-numberlike-output:fail/disp32
21888 $check-mu-numberlike-output:end:
21889     # . restore registers
21890     58/pop-to-eax
21891     # . epilogue
21892     89/<- %esp 5/r32/ebp
21893     5d/pop-to-ebp
21894     c3/return
21895 
21896 $check-mu-numberlike-output:fail:
21897     # otherwise raise an error
21898     (write-buffered *(ebp+0x14) "fn ")
21899     8b/-> *(ebp+0x10) 0/r32/eax
21900     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21901     (write-buffered *(ebp+0x14) %eax)
21902     (write-buffered *(ebp+0x14) ": stmt ")
21903     8b/-> *(ebp+0xc) 0/r32/eax
21904     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
21905     (write-buffered *(ebp+0x14) %eax)
21906     (write-buffered *(ebp+0x14) ": '")
21907     8b/-> *(ebp+8) 0/r32/eax
21908     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21909     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21910     (write-buffered *(ebp+0x14) %eax)
21911     (write-buffered *(ebp+0x14) "' must be a non-addr non-offset scalar\n")
21912     (flush *(ebp+0x14))
21913     (stop *(ebp+0x18) 1)
21914     # never gets here
21915 
21916 mu-numberlike-output-var?:  # v: (addr stmt-var) -> result/eax: boolean
21917     # . prologue
21918     55/push-ebp
21919     89/<- %ebp 4/r32/esp
21920     #
21921     8b/-> *(ebp+8) 0/r32/eax
21922     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21923     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21924     (mu-numberlike-output? %eax)  # => eax
21925 $mu-numberlike-output-var?:end:
21926     # . epilogue
21927     89/<- %esp 5/r32/ebp
21928     5d/pop-to-ebp
21929     c3/return
21930 
21931 mu-numberlike-output?:  # v: (addr type-tree) -> result/eax: boolean
21932     # . prologue
21933     55/push-ebp
21934     89/<- %ebp 4/r32/esp
21935     # . save registers
21936     56/push-esi
21937     # var t/esi: (addr type-tree) = lookup(v->value->type)
21938     8b/-> *(ebp+8) 6/r32/esi
21939 $mu-numberlike-output?:check-int:
21940     # if t is an int, return
21941     (simple-mu-type? %esi 1)  # int => eax
21942     3d/compare-eax-and 0/imm32/false
21943     0f 85/jump-if-!= $mu-numberlike-output?:return-true/disp32
21944 $mu-numberlike-output?:check-float:
21945     # if t is a float, return
21946     (simple-mu-type? %esi 0xf)  # float => eax
21947     3d/compare-eax-and 0/imm32/false
21948     75/jump-if-!= $mu-numberlike-output?:return-true/disp8
21949 $mu-numberlike-output?:check-boolean:
21950     # if t is a boolean, return
21951     (simple-mu-type? %esi 5)  # boolean => eax
21952     3d/compare-eax-and 0/imm32/false
21953     75/jump-if-!= $mu-numberlike-output?:return-true/disp8
21954 $mu-numberlike-output?:check-byte:
21955     # if t is a byte, return
21956     (simple-mu-type? %esi 8)  # byte => eax
21957     3d/compare-eax-and 0/imm32/false
21958     75/jump-if-!= $mu-numberlike-output?:return-true/disp8
21959 $mu-numberlike-output?:check-code-point:
21960     # if t is a code-point, return
21961     (simple-mu-type? %esi 0xd)  # code-point => eax
21962     3d/compare-eax-and 0/imm32/false
21963     75/jump-if-!= $mu-numberlike-output?:return-true/disp8
21964 $mu-numberlike-output?:check-grapheme:
21965     # if t is a grapheme, return
21966     (simple-mu-type? %esi 0xe)  # grapheme => eax
21967     3d/compare-eax-and 0/imm32/false
21968     75/jump-if-!= $mu-numberlike-output?:return-true/disp8
21969 $mu-numberlike-output?:return-false:
21970     b8/copy-to-eax 0/imm32/false
21971     eb/jump $mu-numberlike-output?:end/disp8
21972 $mu-numberlike-output?:return-true:
21973     b8/copy-to-eax 1/imm32/true
21974 $mu-numberlike-output?:end:
21975     # . restore registers
21976     5e/pop-to-esi
21977     # . epilogue
21978     89/<- %esp 5/r32/ebp
21979     5d/pop-to-ebp
21980     c3/return
21981 
21982 check-mu-copy-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21983     # . prologue
21984     55/push-ebp
21985     89/<- %ebp 4/r32/esp
21986     # . save registers
21987     50/push-eax
21988     51/push-ecx
21989     52/push-edx
21990     56/push-esi
21991     57/push-edi
21992     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
21993     81 5/subop/subtract %esp 0x60/imm32
21994     68/push 0x60/imm32/size
21995     68/push 0/imm32/read
21996     68/push 0/imm32/write
21997     89/<- %edx 4/r32/esp
21998 $check-mu-copy-stmt:get-output:
21999     # esi = stmt
22000     8b/-> *(ebp+8) 6/r32/esi
22001     # var output/edi: (addr stmt-var) = stmt->outputs
22002     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22003     89/<- %edi 0/r32/eax
22004     # zero outputs
22005     3d/compare-eax-and 0/imm32
22006     0f 84/jump-if-= $check-mu-copy-stmt:error-no-output/disp32
22007     # > 1 output
22008     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
22009     3d/compare-eax-and 0/imm32
22010     0f 85/jump-if-!= $check-mu-copy-stmt:error-too-many-outputs/disp32
22011 $check-mu-copy-stmt:get-inout:
22012     # var inout/esi: (addr stmt-var) = stmt->inouts
22013     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22014     89/<- %esi 0/r32/eax
22015     # zero inouts
22016     3d/compare-eax-and 0/imm32
22017     0f 84/jump-if-= $check-mu-copy-stmt:error-no-inout/disp32
22018     # > 1 inout
22019     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
22020     3d/compare-eax-and 0/imm32
22021     0f 85/jump-if-!= $check-mu-copy-stmt:error-too-many-inouts/disp32
22022 $check-mu-copy-stmt:types:
22023     # if inout is not a scalar, abort
22024     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22025     (size-of %eax)  # => eax
22026     3d/compare-eax-and 4/imm32
22027     0f 8f/jump-if-> $check-mu-copy-stmt:error-inout-too-large/disp32
22028     # var inout-type/ecx: (addr type-tree) = inout->value->type
22029     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22030     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22031     89/<- %ecx 0/r32/eax
22032     # if (inout->is-deref?) inout-type = inout-type->payload
22033     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
22034     3d/compare-eax-and 0/imm32/false
22035     {
22036       74/jump-if-= break/disp8
22037       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
22038       # if inout-type->right is null, t = inout-type->left
22039       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
22040       {
22041         75/jump-if-!= break/disp8
22042         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22043       }
22044       89/<- %ecx 0/r32/eax
22045     }
22046     # if output not in register, abort
22047     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22048     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
22049     3d/compare-eax-and 0/imm32
22050     0f 84/jump-if-= $check-mu-copy-stmt:error-output-not-in-register/disp32
22051     # var output-type/eax: (addr type-tree) = output->value->type
22052     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22053     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22054     # if (inout-type == output-type) return
22055     (type-match? %eax %ecx %edx)  # => eax
22056     3d/compare-eax-and 0/imm32
22057     0f 85/jump-if-!= $check-mu-copy-stmt:end/disp32
22058     # if output is an addr and inout is 0, return
22059     {
22060       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22061       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22062       (mu-addr-type? %eax)  # => eax
22063       3d/compare-eax-and 0/imm32/false
22064       74/jump-if-= break/disp8
22065       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22066       (lookup *eax *(eax+4))  # Var-name Var-name => eax
22067       (string-equal? %eax "0")  # => eax
22068       3d/compare-eax-and 0/imm32/false
22069       74/jump-if-= break/disp8
22070       e9/jump $check-mu-copy-stmt:end/disp32
22071     }
22072     # if output is an offset and inout is 0, return
22073     {
22074       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22075       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22076       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
22077       75/jump-if-!= break/disp8
22078       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22079       (simple-mu-type? %eax 7)  # offset => eax
22080       3d/compare-eax-and 0/imm32/false
22081       74/jump-if-= break/disp8
22082       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22083       (lookup *eax *(eax+4))  # Var-name Var-name => eax
22084       (string-equal? %eax "0")  # => eax
22085       3d/compare-eax-and 0/imm32/false
22086       74/jump-if-= break/disp8
22087       e9/jump $check-mu-copy-stmt:end/disp32
22088     }
22089     # if output is a byte, abort if inout is not a literal. Otherwise return.
22090     {
22091       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22092       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22093       (simple-mu-type? %eax 8)  # byte => eax
22094       3d/compare-eax-and 0/imm32/false
22095       74/jump-if-= break/disp8
22096       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22097       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22098       (simple-mu-type? %eax 0)  # literal => eax
22099       3d/compare-eax-and 0/imm32/false
22100       0f 84/jump-if-= $check-mu-copy-stmt:error-non-literal-to-byte/disp32
22101       eb/jump $check-mu-copy-stmt:end/disp8
22102     }
22103     # if output is not number-like, abort
22104     (check-mu-numberlike-output %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
22105 $check-mu-copy-stmt:end:
22106     # . reclaim locals
22107     81 0/subop/add %esp 0x6c/imm32
22108     # . restore registers
22109     5f/pop-to-edi
22110     5e/pop-to-esi
22111     5a/pop-to-edx
22112     59/pop-to-ecx
22113     58/pop-to-eax
22114     # . epilogue
22115     89/<- %esp 5/r32/ebp
22116     5d/pop-to-ebp
22117     c3/return
22118 
22119 $check-mu-copy-stmt:error-no-inout:
22120     (write-buffered *(ebp+0x10) "fn ")
22121     8b/-> *(ebp+0xc) 0/r32/eax
22122     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22123     (write-buffered *(ebp+0x10) %eax)
22124     (write-buffered *(ebp+0x10) ": stmt 'copy' expects an inout\n")
22125     (flush *(ebp+0x10))
22126     (stop *(ebp+0x14) 1)
22127     # never gets here
22128 
22129 $check-mu-copy-stmt:error-too-many-inouts:
22130     (write-buffered *(ebp+0x10) "fn ")
22131     8b/-> *(ebp+0xc) 0/r32/eax
22132     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22133     (write-buffered *(ebp+0x10) %eax)
22134     (write-buffered *(ebp+0x10) ": stmt 'copy' must have just one inout\n")
22135     (flush *(ebp+0x10))
22136     (stop *(ebp+0x14) 1)
22137     # never gets here
22138 
22139 $check-mu-copy-stmt:error-no-output:
22140     (write-buffered *(ebp+0x10) "fn ")
22141     8b/-> *(ebp+0xc) 0/r32/eax
22142     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22143     (write-buffered *(ebp+0x10) %eax)
22144     (write-buffered *(ebp+0x10) ": stmt 'copy' expects an output\n")
22145     (flush *(ebp+0x10))
22146     (stop *(ebp+0x14) 1)
22147     # never gets here
22148 
22149 $check-mu-copy-stmt:error-output-not-in-register:
22150     (write-buffered *(ebp+0x10) "fn ")
22151     8b/-> *(ebp+0xc) 0/r32/eax
22152     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22153     (write-buffered *(ebp+0x10) %eax)
22154     (write-buffered *(ebp+0x10) ": stmt copy: output '")
22155     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22156     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22157     (write-buffered *(ebp+0x10) %eax)
22158     (write-buffered *(ebp+0x10) "' not in a register\n")
22159     (flush *(ebp+0x10))
22160     (stop *(ebp+0x14) 1)
22161     # never gets here
22162 
22163 $check-mu-copy-stmt:error-too-many-outputs:
22164     (write-buffered *(ebp+0x10) "fn ")
22165     8b/-> *(ebp+0xc) 0/r32/eax
22166     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22167     (write-buffered *(ebp+0x10) %eax)
22168     (write-buffered *(ebp+0x10) ": stmt 'copy' must have just one output\n")
22169     (flush *(ebp+0x10))
22170     (stop *(ebp+0x14) 1)
22171     # never gets here
22172 
22173 $check-mu-copy-stmt:error-inout-too-large:
22174     (write-buffered *(ebp+0x10) "fn ")
22175     8b/-> *(ebp+0xc) 0/r32/eax
22176     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22177     (write-buffered *(ebp+0x10) %eax)
22178     (write-buffered *(ebp+0x10) ": stmt copy: '")
22179     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22180     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22181     (write-buffered *(ebp+0x10) %eax)
22182     (write-buffered *(ebp+0x10) "' is too large to fit in a register\n")
22183     (flush *(ebp+0x10))
22184     (stop *(ebp+0x14) 1)
22185     # never gets here
22186 
22187 $check-mu-copy-stmt:error-non-literal-to-byte:
22188     (write-buffered *(ebp+0x10) "fn ")
22189     8b/-> *(ebp+0xc) 0/r32/eax
22190     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22191     (write-buffered *(ebp+0x10) %eax)
22192     (write-buffered *(ebp+0x10) ": stmt copy: cannot copy non-literal to '")
22193     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22194     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22195     (write-buffered *(ebp+0x10) %eax)
22196     (write-buffered *(ebp+0x10) "' of type byte; use copy-byte\n")
22197     (flush *(ebp+0x10))
22198     (stop *(ebp+0x14) 1)
22199     # never gets here
22200 
22201 check-mu-copy-to-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22202     # . prologue
22203     55/push-ebp
22204     89/<- %ebp 4/r32/esp
22205     # . save registers
22206     50/push-eax
22207     51/push-ecx
22208     52/push-edx
22209     53/push-ebx
22210     56/push-esi
22211     57/push-edi
22212     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
22213     81 5/subop/subtract %esp 0x60/imm32
22214     68/push 0x60/imm32/size
22215     68/push 0/imm32/read
22216     68/push 0/imm32/write
22217     89/<- %edx 4/r32/esp
22218     # esi = stmt
22219     8b/-> *(ebp+8) 6/r32/esi
22220 $check-mu-copy-to-stmt:check-for-output:
22221     # if stmt->outputs abort
22222     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22223     3d/compare-eax-and 0/imm32
22224     0f 85/jump-if-!= $check-mu-copy-to-stmt:error-too-many-outputs/disp32
22225 $check-mu-copy-to-stmt:get-dest:
22226     # var dest/edi: (addr stmt-var) = stmt->inouts
22227     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22228     89/<- %edi 0/r32/eax
22229     # zero inouts
22230     3d/compare-eax-and 0/imm32
22231     0f 84/jump-if-= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32
22232 $check-mu-copy-to-stmt:get-src:
22233     # var src/esi: (addr stmt-var) = dest->next
22234     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
22235     89/<- %esi 0/r32/eax
22236     # 1 inout
22237     3d/compare-eax-and 0/imm32
22238     0f 84/jump-if-= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32
22239     # > 2 inouts
22240     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
22241     3d/compare-eax-and 0/imm32
22242     0f 85/jump-if-!= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32
22243 $check-mu-copy-to-stmt:types:
22244     # if src is not a scalar, abort
22245     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22246     (size-of %eax)  # => eax
22247     3d/compare-eax-and 4/imm32
22248     0f 8f/jump-if-> $check-mu-copy-to-stmt:error-src-too-large/disp32
22249     # var src-type/ecx: (addr type-tree) = src->value->type
22250     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22251     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22252     89/<- %ecx 0/r32/eax
22253     # if src not in register or literal, abort
22254     # (we can't use stack-offset because it hasn't been computed yet)
22255     {
22256       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22257       (lookup *(eax+0x8) *(eax+0xc))  # Var-type Var-type => eax
22258       (simple-mu-type? %eax 0)  # => eax
22259       3d/compare-eax-and 0/imm32
22260       75/jump-if-!= break/disp8
22261       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22262       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
22263       3d/compare-eax-and 0/imm32
22264       75/jump-if-!= break/disp8
22265       e9/jump $check-mu-copy-to-stmt:error-src-not-literal-or-in-register/disp32
22266     }
22267     # var dest-type/ebx: (addr type-tree) = dest->value->type
22268     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22269     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22270     89/<- %ebx 0/r32/eax
22271     # if (dest->is-deref?) dest-type = dest-type->payload
22272 $check-mu-copy-to-stmt:check-dest-deref:
22273     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
22274     3d/compare-eax-and 0/imm32/false
22275     {
22276       74/jump-if-= break/disp8
22277       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22278 $check-mu-copy-to-stmt:dest-is-deref:
22279       # if dest-type->right is null, dest-type = dest-type->left
22280       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
22281       {
22282         75/jump-if-!= break/disp8
22283 $check-mu-copy-to-stmt:dest-is-deref2:
22284         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22285       }
22286       89/<- %ebx 0/r32/eax
22287     }
22288     # if dest is a byte and src is not a literal, abort
22289     {
22290 $check-mu-copy-to-stmt:final-check-byte:
22291       (simple-mu-type? %ebx 8)  # byte => eax
22292       3d/compare-eax-and 0/imm32/false
22293       74/jump-if-= break/disp8
22294       (simple-mu-type? %ecx 0)  # literal => eax
22295       3d/compare-eax-and 0/imm32/false
22296       0f 84/jump-if-= $check-mu-copy-to-stmt:error-non-literal-to-byte/disp32
22297     }
22298     # if (src-type == dest-type) return
22299     (type-match? %ebx %ecx %edx)  # => eax
22300     3d/compare-eax-and 0/imm32
22301     0f 85/jump-if-!= $check-mu-copy-to-stmt:end/disp32
22302     # if dest is an addr and src is 0, return
22303     {
22304 $check-mu-copy-to-stmt:final-check-addr:
22305       (mu-addr-type? %ebx)  # => eax
22306       3d/compare-eax-and 0/imm32/false
22307       74/jump-if-= break/disp8
22308       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22309       (lookup *eax *(eax+4))  # Var-name Var-name => eax
22310       (string-equal? %eax "0")  # => eax
22311       3d/compare-eax-and 0/imm32/false
22312       74/jump-if-= break/disp8
22313       e9/jump $check-mu-copy-to-stmt:end/disp32
22314     }
22315     # if dest is an offset and src is 0, return
22316     {
22317 $check-mu-copy-to-stmt:final-check-offset:
22318       81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
22319       75/jump-if-!= break/disp8
22320       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22321       (simple-mu-type? %eax 7)  # offset => eax
22322       3d/compare-eax-and 0/imm32/false
22323       74/jump-if-= break/disp8
22324       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22325       (lookup *eax *(eax+4))  # Var-name Var-name => eax
22326       (string-equal? %eax "0")  # => eax
22327       3d/compare-eax-and 0/imm32/false
22328       74/jump-if-= break/disp8
22329       e9/jump $check-mu-copy-to-stmt:end/disp32
22330     }
22331     # if dest is not number-like, abort
22332     (check-mu-numberlike-arg %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
22333 $check-mu-copy-to-stmt:end:
22334     # . reclaim locals
22335     81 0/subop/add %esp 0x6c/imm32
22336     # . restore registers
22337     5f/pop-to-edi
22338     5e/pop-to-esi
22339     5b/pop-to-ebx
22340     5a/pop-to-edx
22341     59/pop-to-ecx
22342     58/pop-to-eax
22343     # . epilogue
22344     89/<- %esp 5/r32/ebp
22345     5d/pop-to-ebp
22346     c3/return
22347 
22348 $check-mu-copy-to-stmt:error-incorrect-inouts:
22349     (write-buffered *(ebp+0x10) "fn ")
22350     8b/-> *(ebp+0xc) 0/r32/eax
22351     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22352     (write-buffered *(ebp+0x10) %eax)
22353     (write-buffered *(ebp+0x10) ": stmt 'copy-to' must have two inouts\n")
22354     (flush *(ebp+0x10))
22355     (stop *(ebp+0x14) 1)
22356     # never gets here
22357 
22358 $check-mu-copy-to-stmt:error-too-many-outputs:
22359     (write-buffered *(ebp+0x10) "fn ")
22360     8b/-> *(ebp+0xc) 0/r32/eax
22361     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22362     (write-buffered *(ebp+0x10) %eax)
22363     (write-buffered *(ebp+0x10) ": stmt 'copy-to' must not have any outputs\n")
22364     (flush *(ebp+0x10))
22365     (stop *(ebp+0x14) 1)
22366     # never gets here
22367 
22368 $check-mu-copy-to-stmt:error-src-not-literal-or-in-register:
22369     (write-buffered *(ebp+0x10) "fn ")
22370     8b/-> *(ebp+0xc) 0/r32/eax
22371     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22372     (write-buffered *(ebp+0x10) %eax)
22373     (write-buffered *(ebp+0x10) ": stmt copy-to: source (second inout) is in memory\n")
22374     (flush *(ebp+0x10))
22375     (stop *(ebp+0x14) 1)
22376     # never gets here
22377 
22378 $check-mu-copy-to-stmt:error-src-too-large:
22379     (write-buffered *(ebp+0x10) "fn ")
22380     8b/-> *(ebp+0xc) 0/r32/eax
22381     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22382     (write-buffered *(ebp+0x10) %eax)
22383     (write-buffered *(ebp+0x10) ": stmt copy-to: '")
22384     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22385     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22386     (write-buffered *(ebp+0x10) %eax)
22387     (write-buffered *(ebp+0x10) "' is too large to copy\n")
22388     (flush *(ebp+0x10))
22389     (stop *(ebp+0x14) 1)
22390     # never gets here
22391 
22392 $check-mu-copy-to-stmt:error-non-literal-to-byte:
22393     (write-buffered *(ebp+0x10) "fn ")
22394     8b/-> *(ebp+0xc) 0/r32/eax
22395     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22396     (write-buffered *(ebp+0x10) %eax)
22397     (write-buffered *(ebp+0x10) ": stmt copy-to: cannot copy non-literal to type byte; use copy-byte-to\n")
22398     (flush *(ebp+0x10))
22399     (stop *(ebp+0x14) 1)
22400     # never gets here
22401 
22402 check-mu-copy-byte-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22403     # . prologue
22404     55/push-ebp
22405     89/<- %ebp 4/r32/esp
22406     # . save registers
22407     50/push-eax
22408     51/push-ecx
22409     52/push-edx
22410     56/push-esi
22411     57/push-edi
22412     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
22413     81 5/subop/subtract %esp 0x60/imm32
22414     68/push 0x60/imm32/size
22415     68/push 0/imm32/read
22416     68/push 0/imm32/write
22417     89/<- %edx 4/r32/esp
22418 $check-mu-copy-byte-stmt:get-output:
22419     # esi = stmt
22420     8b/-> *(ebp+8) 6/r32/esi
22421     # var output/edi: (addr stmt-var) = stmt->outputs
22422     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22423     89/<- %edi 0/r32/eax
22424     # zero outputs
22425     3d/compare-eax-and 0/imm32
22426     0f 84/jump-if-= $check-mu-copy-byte-stmt:error-no-output/disp32
22427     # > 1 output
22428     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
22429     3d/compare-eax-and 0/imm32
22430     0f 85/jump-if-!= $check-mu-copy-byte-stmt:error-too-many-outputs/disp32
22431 $check-mu-copy-byte-stmt:get-inout:
22432     # var inout/esi: (addr stmt-var) = stmt->inouts
22433     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22434     89/<- %esi 0/r32/eax
22435     # zero inouts
22436     3d/compare-eax-and 0/imm32
22437     0f 84/jump-if-= $check-mu-copy-byte-stmt:error-no-inout/disp32
22438     # > 1 inout
22439     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
22440     3d/compare-eax-and 0/imm32
22441     0f 85/jump-if-!= $check-mu-copy-byte-stmt:error-too-many-inouts/disp32
22442 $check-mu-copy-byte-stmt:types:
22443     # if inout is not a scalar, abort
22444     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22445     (size-of %eax)  # => eax
22446     3d/compare-eax-and 4/imm32
22447     0f 8f/jump-if-> $check-mu-copy-byte-stmt:error-inout-too-large/disp32
22448     # var inout-type/ecx: (addr type-tree) = inout->value->type
22449     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22450     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22451     89/<- %ecx 0/r32/eax
22452 $check-mu-copy-byte-stmt:check-inout-deref:
22453     # if (inout->is-deref?) inout-type = inout-type->payload
22454     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
22455     3d/compare-eax-and 0/imm32/false
22456     {
22457       74/jump-if-= break/disp8
22458 $check-mu-copy-byte-stmt:inout-is-deref:
22459       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
22460       # if inout-type->right is null, t = inout-type->left
22461       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
22462       {
22463         75/jump-if-!= break/disp8
22464 $check-mu-copy-byte-stmt:inout-is-deref2:
22465         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22466       }
22467       89/<- %ecx 0/r32/eax
22468     }
22469     # if output not in register, abort
22470     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22471     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
22472     3d/compare-eax-and 0/imm32
22473     0f 84/jump-if-= $check-mu-copy-byte-stmt:error-output-not-in-register/disp32
22474     # var output-type/eax: (addr type-tree) = output->value->type
22475     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22476     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22477     # if output is not of type byte, abort
22478     (simple-mu-type? %eax 8)  # byte => eax
22479     3d/compare-eax-and 0/imm32
22480     0f 84/jump-if-= $check-mu-copy-byte-stmt:error-invalid-output-type/disp32
22481 $check-mu-copy-byte-stmt:end:
22482     # . reclaim locals
22483     81 0/subop/add %esp 0x6c/imm32
22484     # . restore registers
22485     5f/pop-to-edi
22486     5e/pop-to-esi
22487     5a/pop-to-edx
22488     59/pop-to-ecx
22489     58/pop-to-eax
22490     # . epilogue
22491     89/<- %esp 5/r32/ebp
22492     5d/pop-to-ebp
22493     c3/return
22494 
22495 $check-mu-copy-byte-stmt:error-no-inout:
22496     (write-buffered *(ebp+0x10) "fn ")
22497     8b/-> *(ebp+0xc) 0/r32/eax
22498     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22499     (write-buffered *(ebp+0x10) %eax)
22500     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' expects an inout\n")
22501     (flush *(ebp+0x10))
22502     (stop *(ebp+0x14) 1)
22503     # never gets here
22504 
22505 $check-mu-copy-byte-stmt:error-too-many-inouts:
22506     (write-buffered *(ebp+0x10) "fn ")
22507     8b/-> *(ebp+0xc) 0/r32/eax
22508     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22509     (write-buffered *(ebp+0x10) %eax)
22510     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' must have just one inout\n")
22511     (flush *(ebp+0x10))
22512     (stop *(ebp+0x14) 1)
22513     # never gets here
22514 
22515 $check-mu-copy-byte-stmt:error-no-output:
22516     (write-buffered *(ebp+0x10) "fn ")
22517     8b/-> *(ebp+0xc) 0/r32/eax
22518     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22519     (write-buffered *(ebp+0x10) %eax)
22520     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' expects an output\n")
22521     (flush *(ebp+0x10))
22522     (stop *(ebp+0x14) 1)
22523     # never gets here
22524 
22525 $check-mu-copy-byte-stmt:error-output-not-in-register:
22526     (write-buffered *(ebp+0x10) "fn ")
22527     8b/-> *(ebp+0xc) 0/r32/eax
22528     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22529     (write-buffered *(ebp+0x10) %eax)
22530     (write-buffered *(ebp+0x10) ": stmt copy-byte: output '")
22531     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22532     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22533     (write-buffered *(ebp+0x10) %eax)
22534     (write-buffered *(ebp+0x10) "' not in a register\n")
22535     (flush *(ebp+0x10))
22536     (stop *(ebp+0x14) 1)
22537     # never gets here
22538 
22539 $check-mu-copy-byte-stmt:error-too-many-outputs:
22540     (write-buffered *(ebp+0x10) "fn ")
22541     8b/-> *(ebp+0xc) 0/r32/eax
22542     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22543     (write-buffered *(ebp+0x10) %eax)
22544     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' must have just one output\n")
22545     (flush *(ebp+0x10))
22546     (stop *(ebp+0x14) 1)
22547     # never gets here
22548 
22549 $check-mu-copy-byte-stmt:error-invalid-output-type:
22550     (write-buffered *(ebp+0x10) "fn ")
22551     8b/-> *(ebp+0xc) 0/r32/eax
22552     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22553     (write-buffered *(ebp+0x10) %eax)
22554     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' must write to output of type byte\n")
22555     (flush *(ebp+0x10))
22556     (stop *(ebp+0x14) 1)
22557     # never gets here
22558 
22559 $check-mu-copy-byte-stmt:error-inout-too-large:
22560     (write-buffered *(ebp+0x10) "fn ")
22561     8b/-> *(ebp+0xc) 0/r32/eax
22562     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22563     (write-buffered *(ebp+0x10) %eax)
22564     (write-buffered *(ebp+0x10) ": stmt copy-byte: '")
22565     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22566     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22567     (write-buffered *(ebp+0x10) %eax)
22568     (write-buffered *(ebp+0x10) "' is too large to fit in a register\n")
22569     (flush *(ebp+0x10))
22570     (stop *(ebp+0x14) 1)
22571     # never gets here
22572 
22573 check-mu-copy-byte-to-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22574     # . prologue
22575     55/push-ebp
22576     89/<- %ebp 4/r32/esp
22577     # . save registers
22578     50/push-eax
22579     52/push-edx
22580     53/push-ebx
22581     56/push-esi
22582     57/push-edi
22583     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
22584     81 5/subop/subtract %esp 0x60/imm32
22585     68/push 0x60/imm32/size
22586     68/push 0/imm32/read
22587     68/push 0/imm32/write
22588     89/<- %edx 4/r32/esp
22589     # esi = stmt
22590     8b/-> *(ebp+8) 6/r32/esi
22591 $check-mu-copy-byte-to-stmt:check-for-output:
22592     # if stmt->outputs abort
22593     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22594     3d/compare-eax-and 0/imm32
22595     0f 85/jump-if-!= $check-mu-copy-byte-to-stmt:error-too-many-outputs/disp32
22596 $check-mu-copy-byte-to-stmt:get-dest:
22597     # var dest/edi: (addr stmt-var) = stmt->inouts
22598     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22599     89/<- %edi 0/r32/eax
22600     # zero inouts
22601     3d/compare-eax-and 0/imm32
22602     0f 84/jump-if-= $check-mu-copy-byte-to-stmt:error-incorrect-inouts/disp32
22603 $check-mu-copy-byte-to-stmt:get-src:
22604     # var src/esi: (addr stmt-var) = dest->next
22605     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
22606     89/<- %esi 0/r32/eax
22607     # 1 inout
22608     3d/compare-eax-and 0/imm32
22609     0f 84/jump-if-= $check-mu-copy-byte-to-stmt:error-incorrect-inouts/disp32
22610     # > 2 inouts
22611     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
22612     3d/compare-eax-and 0/imm32
22613     0f 85/jump-if-!= $check-mu-copy-byte-to-stmt:error-incorrect-inouts/disp32
22614 $check-mu-copy-byte-to-stmt:types:
22615     # if src is not a scalar, abort
22616     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22617     (size-of %eax)  # => eax
22618     3d/compare-eax-and 4/imm32
22619     0f 8f/jump-if-> $check-mu-copy-byte-to-stmt:error-src-too-large/disp32
22620     # if src not in register, abort
22621     {
22622       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22623       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
22624       3d/compare-eax-and 0/imm32
22625       75/jump-if-!= break/disp8
22626       e9/jump $check-mu-copy-byte-to-stmt:error-src-not-in-register/disp32
22627     }
22628     # var dest-type/ebx: (addr type-tree) = dest->value->type
22629     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22630     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22631     89/<- %ebx 0/r32/eax
22632     # if (dest->is-deref?) dest-type = dest-type->payload
22633 $check-mu-copy-byte-to-stmt:check-dest-deref:
22634     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
22635     3d/compare-eax-and 0/imm32/false
22636     {
22637       74/jump-if-= break/disp8
22638       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22639 $check-mu-copy-byte-to-stmt:dest-is-deref:
22640       # if dest-type->right is null, dest-type = dest-type->left
22641       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
22642       {
22643         75/jump-if-!= break/disp8
22644 $check-mu-copy-byte-to-stmt:dest-is-deref2:
22645         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22646       }
22647       89/<- %ebx 0/r32/eax
22648     }
22649     # if dest is not a byte, abort
22650     (simple-mu-type? %ebx 8)  # byte => eax
22651     3d/compare-eax-and 0/imm32/false
22652     0f 84/jump-if-= $check-mu-copy-byte-to-stmt:error-invalid-dest-type/disp32
22653 $check-mu-copy-byte-to-stmt:end:
22654     # . reclaim locals
22655     81 0/subop/add %esp 0x6c/imm32
22656     # . restore registers
22657     5f/pop-to-edi
22658     5e/pop-to-esi
22659     5b/pop-to-ebx
22660     5a/pop-to-edx
22661     58/pop-to-eax
22662     # . epilogue
22663     89/<- %esp 5/r32/ebp
22664     5d/pop-to-ebp
22665     c3/return
22666 
22667 $check-mu-copy-byte-to-stmt:error-incorrect-inouts:
22668     (write-buffered *(ebp+0x10) "fn ")
22669     8b/-> *(ebp+0xc) 0/r32/eax
22670     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22671     (write-buffered *(ebp+0x10) %eax)
22672     (write-buffered *(ebp+0x10) ": stmt 'copy-byte-to' must have two inouts\n")
22673     (flush *(ebp+0x10))
22674     (stop *(ebp+0x14) 1)
22675     # never gets here
22676 
22677 $check-mu-copy-byte-to-stmt:error-too-many-outputs:
22678     (write-buffered *(ebp+0x10) "fn ")
22679     8b/-> *(ebp+0xc) 0/r32/eax
22680     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22681     (write-buffered *(ebp+0x10) %eax)
22682     (write-buffered *(ebp+0x10) ": stmt 'copy-byte-to' must not have any outputs\n")
22683     (flush *(ebp+0x10))
22684     (stop *(ebp+0x14) 1)
22685     # never gets here
22686 
22687 $check-mu-copy-byte-to-stmt:error-src-not-in-register:
22688     (write-buffered *(ebp+0x10) "fn ")
22689     8b/-> *(ebp+0xc) 0/r32/eax
22690     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22691     (write-buffered *(ebp+0x10) %eax)
22692     (write-buffered *(ebp+0x10) ": stmt copy-byte-to: source (second inout) must be in a register\n")
22693     (flush *(ebp+0x10))
22694     (stop *(ebp+0x14) 1)
22695     # never gets here
22696 
22697 $check-mu-copy-byte-to-stmt:error-invalid-dest-type:
22698     (write-buffered *(ebp+0x10) "fn ")
22699     8b/-> *(ebp+0xc) 0/r32/eax
22700     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22701     (write-buffered *(ebp+0x10) %eax)
22702     (write-buffered *(ebp+0x10) ": stmt copy-byte-to: '")
22703     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22704     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22705     (write-buffered *(ebp+0x10) %eax)
22706     (write-buffered *(ebp+0x10) "' must be a byte\n")
22707     (flush *(ebp+0x10))
22708     (stop *(ebp+0x14) 1)
22709     # never gets here
22710 
22711 $check-mu-copy-byte-to-stmt:error-src-too-large:
22712     (write-buffered *(ebp+0x10) "fn ")
22713     8b/-> *(ebp+0xc) 0/r32/eax
22714     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22715     (write-buffered *(ebp+0x10) %eax)
22716     (write-buffered *(ebp+0x10) ": stmt copy-byte-to: '")
22717     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22718     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22719     (write-buffered *(ebp+0x10) %eax)
22720     (write-buffered *(ebp+0x10) "' is too large to copy\n")
22721     (flush *(ebp+0x10))
22722     (stop *(ebp+0x14) 1)
22723     # never gets here
22724 
22725 check-mu-compare-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22726     # . prologue
22727     55/push-ebp
22728     89/<- %ebp 4/r32/esp
22729     # . save registers
22730     50/push-eax
22731     51/push-ecx
22732     52/push-edx
22733     53/push-ebx
22734     56/push-esi
22735     57/push-edi
22736     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
22737     81 5/subop/subtract %esp 0x60/imm32
22738     68/push 0x60/imm32/size
22739     68/push 0/imm32/read
22740     68/push 0/imm32/write
22741     89/<- %edx 4/r32/esp
22742     # esi = stmt
22743     8b/-> *(ebp+8) 6/r32/esi
22744 $check-mu-compare-stmt:check-for-output:
22745     # if stmt->outputs abort
22746     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22747     3d/compare-eax-and 0/imm32
22748     0f 85/jump-if-!= $check-mu-compare-stmt:error-too-many-outputs/disp32
22749 $check-mu-compare-stmt:get-left:
22750     # var left/edi: (addr stmt-var) = stmt->inouts
22751     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22752     89/<- %edi 0/r32/eax
22753     # zero inouts
22754     3d/compare-eax-and 0/imm32
22755     0f 84/jump-if-= $check-mu-compare-stmt:error-incorrect-inouts/disp32
22756 $check-mu-compare-stmt:get-right:
22757     # var right/esi: (addr stmt-var) = left->next
22758     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
22759     89/<- %esi 0/r32/eax
22760     # 1 inout
22761     3d/compare-eax-and 0/imm32
22762     0f 84/jump-if-= $check-mu-compare-stmt:error-incorrect-inouts/disp32
22763     # > 2 inouts
22764     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
22765     3d/compare-eax-and 0/imm32
22766     0f 85/jump-if-!= $check-mu-compare-stmt:error-incorrect-inouts/disp32
22767     # if both inouts are in memory, abort
22768     {
22769 $check-mu-compare-stmt:both-in-mem:
22770       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22771       (lookup *(eax+0x8) *(eax+0xc))  # Var-type Var-type => eax
22772       (simple-mu-type? %eax 0)  # => eax
22773       3d/compare-eax-and 0/imm32
22774       0f 85/jump-if-!= break/disp32
22775       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22776       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
22777       3d/compare-eax-and 0/imm32
22778       75/jump-if-!= break/disp8
22779       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22780       (lookup *(eax+0x8) *(eax+0xc))  # Var-type Var-type => eax
22781       (simple-mu-type? %eax 0)  # => eax
22782       3d/compare-eax-and 0/imm32
22783       75/jump-if-!= break/disp8
22784       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22785       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
22786       3d/compare-eax-and 0/imm32
22787       75/jump-if-!= break/disp8
22788       e9/jump $check-mu-compare-stmt:error-both-in-memory/disp32
22789     }
22790 $check-mu-compare-stmt:types:
22791     # var right-type/ecx: (addr type-tree) = right->value->type
22792     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22793     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22794     89/<- %ecx 0/r32/eax
22795     # if (right->is-deref?) right-type = right-type->payload
22796     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
22797     3d/compare-eax-and 0/imm32/false
22798     {
22799       74/jump-if-= break/disp8
22800       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
22801       # if right-type->right is null, right-type = right-type->left
22802       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
22803       {
22804         75/jump-if-!= break/disp8
22805         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22806       }
22807       89/<- %ecx 0/r32/eax
22808     }
22809     # if right-type is a literal string, abort
22810     (simple-mu-type? %ecx 0x10)  # string-literal => eax
22811     3d/compare-eax-and 0/imm32/false
22812     0f 85/jump-if-!= $check-mu-compare-stmt:error-right-string-literal/disp32
22813     # if right is not a scalar, abort
22814     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22815     (size-of %eax)  # => eax
22816     3d/compare-eax-and 4/imm32
22817     0f 8f/jump-if-> $check-mu-compare-stmt:error-right-too-large/disp32
22818     # if left is not a scalar, abort
22819     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22820     (size-of %eax)  # => eax
22821     3d/compare-eax-and 4/imm32
22822     0f 8f/jump-if-> $check-mu-compare-stmt:error-left-too-large/disp32
22823     # var left-type/ebx: (addr type-tree) = left->value->type
22824     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22825     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22826     89/<- %ebx 0/r32/eax
22827     # if (left->is-deref?) left-type = left-type->payload
22828     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
22829     3d/compare-eax-and 0/imm32/false
22830     {
22831       74/jump-if-= break/disp8
22832       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22833       # if left-type->right is null, left-type = left-type->left
22834       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
22835       {
22836         75/jump-if-!= break/disp8
22837         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22838       }
22839       89/<- %ebx 0/r32/eax
22840     }
22841     # if (left-type == right-type) return
22842     (type-match? %ebx %ecx %edx)  # => eax
22843     3d/compare-eax-and 0/imm32
22844     0f 85/jump-if-!= $check-mu-compare-stmt:end/disp32
22845     # if left is an addr and right is 0, return
22846     {
22847       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22848       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22849       (mu-addr-type? %eax)  # => eax
22850       3d/compare-eax-and 0/imm32/false
22851       74/jump-if-= break/disp8
22852       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22853       (lookup *eax *(eax+4))  # Var-name Var-name => eax
22854       (string-equal? %eax "0")  # => eax
22855       3d/compare-eax-and 0/imm32/false
22856       74/jump-if-= break/disp8
22857       eb/jump $check-mu-compare-stmt:end/disp8
22858     }
22859     # if left is not number-like, abort
22860     (check-mu-numberlike-arg %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
22861 $check-mu-compare-stmt:end:
22862     # . reclaim locals
22863     81 0/subop/add %esp 0x6c/imm32
22864     # . restore registers
22865     5f/pop-to-edi
22866     5e/pop-to-esi
22867     5b/pop-to-ebx
22868     5a/pop-to-edx
22869     59/pop-to-ecx
22870     58/pop-to-eax
22871     # . epilogue
22872     89/<- %esp 5/r32/ebp
22873     5d/pop-to-ebp
22874     c3/return
22875 
22876 $check-mu-compare-stmt:error-incorrect-inouts:
22877     (write-buffered *(ebp+0x10) "fn ")
22878     8b/-> *(ebp+0xc) 0/r32/eax
22879     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22880     (write-buffered *(ebp+0x10) %eax)
22881     (write-buffered *(ebp+0x10) ": stmt 'compare' must have two inouts\n")
22882     (flush *(ebp+0x10))
22883     (stop *(ebp+0x14) 1)
22884     # never gets here
22885 
22886 $check-mu-compare-stmt:error-too-many-outputs:
22887     (write-buffered *(ebp+0x10) "fn ")
22888     8b/-> *(ebp+0xc) 0/r32/eax
22889     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22890     (write-buffered *(ebp+0x10) %eax)
22891     (write-buffered *(ebp+0x10) ": stmt 'compare' must not have any outputs\n")
22892     (flush *(ebp+0x10))
22893     (stop *(ebp+0x14) 1)
22894     # never gets here
22895 
22896 $check-mu-compare-stmt:error-both-in-memory:
22897     (write-buffered *(ebp+0x10) "fn ")
22898     8b/-> *(ebp+0xc) 0/r32/eax
22899     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22900     (write-buffered *(ebp+0x10) %eax)
22901     (write-buffered *(ebp+0x10) ": stmt compare: both inouts are in memory\n")
22902     (flush *(ebp+0x10))
22903     (stop *(ebp+0x14) 1)
22904     # never gets here
22905 
22906 $check-mu-compare-stmt:error-left-too-large:
22907     (write-buffered *(ebp+0x10) "fn ")
22908     8b/-> *(ebp+0xc) 0/r32/eax
22909     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22910     (write-buffered *(ebp+0x10) %eax)
22911     (write-buffered *(ebp+0x10) ": stmt compare: '")
22912     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22913     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22914     (write-buffered *(ebp+0x10) %eax)
22915     (write-buffered *(ebp+0x10) "' is too large to compare\n")
22916     (flush *(ebp+0x10))
22917     (stop *(ebp+0x14) 1)
22918     # never gets here
22919 
22920 $check-mu-compare-stmt:error-right-too-large:
22921     (write-buffered *(ebp+0x10) "fn ")
22922     8b/-> *(ebp+0xc) 0/r32/eax
22923     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22924     (write-buffered *(ebp+0x10) %eax)
22925     (write-buffered *(ebp+0x10) ": stmt compare: '")
22926     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22927     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22928     (write-buffered *(ebp+0x10) %eax)
22929     (write-buffered *(ebp+0x10) "' is too large to compare\n")
22930     (flush *(ebp+0x10))
22931     (stop *(ebp+0x14) 1)
22932     # never gets here
22933 
22934 $check-mu-compare-stmt:error-right-string-literal:
22935     (write-buffered *(ebp+0x10) "fn ")
22936     8b/-> *(ebp+0xc) 0/r32/eax
22937     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22938     (write-buffered *(ebp+0x10) %eax)
22939     (write-buffered *(ebp+0x10) ": stmt compare: string literal ")
22940     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22941     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22942     (write-buffered *(ebp+0x10) %eax)
22943     (write-buffered *(ebp+0x10) " is not supported; use the string-equal? function\n")
22944     (flush *(ebp+0x10))
22945     (stop *(ebp+0x14) 1)
22946     # never gets here
22947 
22948 check-mu-address-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22949     # . prologue
22950     55/push-ebp
22951     89/<- %ebp 4/r32/esp
22952     # . save registers
22953     50/push-eax
22954     51/push-ecx
22955     52/push-edx
22956     56/push-esi
22957     57/push-edi
22958 $check-mu-address-stmt:get-output:
22959     # esi = stmt
22960     8b/-> *(ebp+8) 6/r32/esi
22961     # var output/edi: (addr stmt-var) = stmt->outputs
22962     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22963     89/<- %edi 0/r32/eax
22964     # zero outputs
22965     3d/compare-eax-and 0/imm32
22966     0f 84/jump-if-= $check-mu-address-stmt:error-no-output/disp32
22967     # > 1 output
22968     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
22969     3d/compare-eax-and 0/imm32
22970     0f 85/jump-if-!= $check-mu-address-stmt:error-too-many-outputs/disp32
22971 $check-mu-address-stmt:get-inout:
22972     # var inout/esi: (addr stmt-var) = stmt->inouts
22973     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22974     89/<- %esi 0/r32/eax
22975     # zero inouts
22976     3d/compare-eax-and 0/imm32
22977     0f 84/jump-if-= $check-mu-address-stmt:error-no-inout/disp32
22978     # > 1 inout
22979     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
22980     3d/compare-eax-and 0/imm32
22981     0f 85/jump-if-!= $check-mu-address-stmt:error-too-many-inouts/disp32
22982 $check-mu-address-stmt:types:
22983     # if output not in register, abort
22984     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22985     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
22986     3d/compare-eax-and 0/imm32
22987     0f 84/jump-if-= $check-mu-address-stmt:error-output-not-in-register/disp32
22988     # var output-type/edx: (addr type-tree) = output->value->type
22989     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22990     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22991     89/<- %edx 0/r32/eax
22992     # if output-type not an addr, abort
22993     (mu-addr-type? %edx)  # => eax
22994     3d/compare-eax-and 0/imm32/false
22995     0f 84/jump-if-= $check-mu-address-stmt:error-output-not-address/disp32
22996     # output-type = output-type->right
22997     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
22998     # if output-type->right is null, output-type = output-type->left
22999     81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
23000     {
23001       75/jump-if-!= break/disp8
23002       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23003     }
23004     89/<- %edx 0/r32/eax
23005     # var inout-type/ecx: (addr type-tree) = inout->value->type
23006     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
23007     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23008     89/<- %ecx 0/r32/eax
23009     # if (inout->is-deref?) inout-type = inout-type->payload
23010     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
23011     3d/compare-eax-and 0/imm32/false
23012     {
23013       74/jump-if-= break/disp8
23014       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
23015       # if inout-type->right is null, t = inout-type->left
23016       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
23017       {
23018         75/jump-if-!= break/disp8
23019         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23020       }
23021       89/<- %ecx 0/r32/eax
23022     }
23023     # if (inout-type != output-type) abort
23024     (type-equal-ignoring-capacity? %edx %ecx)  # => eax
23025     3d/compare-eax-and 0/imm32
23026     0f 84/jump-if-= $check-mu-address-stmt:error-type-mismatch/disp32
23027 $check-mu-address-stmt:end:
23028     # . restore registers
23029     5f/pop-to-edi
23030     5e/pop-to-esi
23031     5a/pop-to-edx
23032     59/pop-to-ecx
23033     58/pop-to-eax
23034     # . epilogue
23035     89/<- %esp 5/r32/ebp
23036     5d/pop-to-ebp
23037     c3/return
23038 
23039 $check-mu-address-stmt:error-no-inout:
23040     (write-buffered *(ebp+0x10) "fn ")
23041     8b/-> *(ebp+0xc) 0/r32/eax
23042     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23043     (write-buffered *(ebp+0x10) %eax)
23044     (write-buffered *(ebp+0x10) ": stmt 'address' expects an inout\n")
23045     (flush *(ebp+0x10))
23046     (stop *(ebp+0x14) 1)
23047     # never gets here
23048 
23049 $check-mu-address-stmt:error-too-many-inouts:
23050     (write-buffered *(ebp+0x10) "fn ")
23051     8b/-> *(ebp+0xc) 0/r32/eax
23052     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23053     (write-buffered *(ebp+0x10) %eax)
23054     (write-buffered *(ebp+0x10) ": stmt 'address' must have just one inout\n")
23055     (flush *(ebp+0x10))
23056     (stop *(ebp+0x14) 1)
23057     # never gets here
23058 
23059 $check-mu-address-stmt:error-no-output:
23060     (write-buffered *(ebp+0x10) "fn ")
23061     8b/-> *(ebp+0xc) 0/r32/eax
23062     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23063     (write-buffered *(ebp+0x10) %eax)
23064     (write-buffered *(ebp+0x10) ": stmt 'address' expects an output\n")
23065     (flush *(ebp+0x10))
23066     (stop *(ebp+0x14) 1)
23067     # never gets here
23068 
23069 $check-mu-address-stmt:error-output-not-in-register:
23070     (write-buffered *(ebp+0x10) "fn ")
23071     8b/-> *(ebp+0xc) 0/r32/eax
23072     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23073     (write-buffered *(ebp+0x10) %eax)
23074     (write-buffered *(ebp+0x10) ": stmt address: output '")
23075     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23076     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23077     (write-buffered *(ebp+0x10) %eax)
23078     (write-buffered *(ebp+0x10) "' not in a register\n")
23079     (flush *(ebp+0x10))
23080     (stop *(ebp+0x14) 1)
23081     # never gets here
23082 
23083 $check-mu-address-stmt:error-too-many-outputs:
23084     (write-buffered *(ebp+0x10) "fn ")
23085     8b/-> *(ebp+0xc) 0/r32/eax
23086     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23087     (write-buffered *(ebp+0x10) %eax)
23088     (write-buffered *(ebp+0x10) ": stmt 'address' must have just one output\n")
23089     (flush *(ebp+0x10))
23090     (stop *(ebp+0x14) 1)
23091     # never gets here
23092 
23093 $check-mu-address-stmt:error-output-not-address:
23094     (write-buffered *(ebp+0x10) "fn ")
23095     8b/-> *(ebp+0xc) 0/r32/eax
23096     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23097     (write-buffered *(ebp+0x10) %eax)
23098     (write-buffered *(ebp+0x10) ": stmt address: output '")
23099     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23100     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23101     (write-buffered *(ebp+0x10) %eax)
23102     (write-buffered *(ebp+0x10) "' is not an addr\n")
23103     (flush *(ebp+0x10))
23104     (stop *(ebp+0x14) 1)
23105     # never gets here
23106 
23107 $check-mu-address-stmt:error-type-mismatch:
23108     (write-buffered *(ebp+0x10) "fn ")
23109     8b/-> *(ebp+0xc) 0/r32/eax
23110     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23111     (write-buffered *(ebp+0x10) %eax)
23112     (write-buffered *(ebp+0x10) ": stmt address: output '")
23113     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23114     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23115     (write-buffered *(ebp+0x10) %eax)
23116     (write-buffered *(ebp+0x10) "' cannot hold address of '")
23117     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
23118     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23119     (write-buffered *(ebp+0x10) %eax)
23120     (write-buffered *(ebp+0x10) "'\n")
23121     (flush *(ebp+0x10))
23122     (stop *(ebp+0x14) 1)
23123     # never gets here
23124 
23125 type-equal-ignoring-capacity?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
23126     # . prologue
23127     55/push-ebp
23128     89/<- %ebp 4/r32/esp
23129     # . save registers
23130     51/push-ecx
23131     52/push-edx
23132     53/push-ebx
23133     # var curr-a/ecx: (addr type-tree) = a
23134     8b/-> *(ebp+8) 1/r32/ecx
23135     # var curr-b/ebx: (addr type-tree) = b
23136     8b/-> *(ebp+0xc) 3/r32/ebx
23137     # if (curr-a->is-atom?) fall back to regular equality
23138     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
23139     0f 85/jump-if-!= $type-equal-ignoring-capacity?:base-case/disp32
23140     # if (curr-a->left != curr-b->left) return false
23141     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
23142     89/<- %edx 0/r32/eax
23143     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
23144     (type-equal? %edx %eax)  # => eax
23145     3d/compare-eax-and 0/imm32/false
23146     0f 84/jump-if-= $type-equal-ignoring-capacity?:end/disp32  # eax switches meaning
23147     # if (curr-a->left == "array") curr-a = curr-a->element-type
23148     {
23149       (mu-array? %edx)  # => eax
23150       3d/compare-eax-and 0/imm32/false
23151       75/jump-if-!= break/disp8
23152 $type-equal-ignoring-capacity?:array:
23153       # curr-a = curr-a->right->left
23154       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
23155       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23156       89/<- %ecx 0/r32/eax
23157       # curr-b = curr-b->right->left
23158       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23159       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23160       89/<- %ebx 0/r32/eax
23161       eb/jump $type-equal-ignoring-capacity?:base-case/disp8
23162     }
23163     # if (curr-a->left == "stream") curr-a = curr-a->element-type
23164     {
23165       (mu-stream? %edx)  # => eax
23166       3d/compare-eax-and 0/imm32/false
23167       75/jump-if-!= break/disp8
23168 $type-equal-ignoring-capacity?:stream:
23169       # curr-a = curr-a->right->left
23170       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
23171       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23172       89/<- %ecx 0/r32/eax
23173       # curr-b = curr-b->right->left
23174       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23175       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23176       89/<- %ebx 0/r32/eax
23177       eb/jump $type-equal-ignoring-capacity?:base-case/disp8
23178     }
23179 $type-equal-ignoring-capacity?:base-case:
23180     # return type-equal?(curr-a, curr-b)
23181     (type-equal? %ecx %ebx)  # => eax
23182 $type-equal-ignoring-capacity?:end:
23183     # . restore registers
23184     5b/pop-to-ebx
23185     5a/pop-to-edx
23186     59/pop-to-ecx
23187     # . epilogue
23188     89/<- %esp 5/r32/ebp
23189     5d/pop-to-ebp
23190     c3/return
23191 
23192 check-mu-return-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23193     # . prologue
23194     55/push-ebp
23195     89/<- %ebp 4/r32/esp
23196     # . save registers
23197     50/push-eax
23198     51/push-ecx
23199     52/push-edx
23200     53/push-ebx
23201     56/push-esi
23202     57/push-edi
23203     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
23204     81 5/subop/subtract %esp 0x60/imm32
23205     68/push 0x60/imm32/size
23206     68/push 0/imm32/read
23207     68/push 0/imm32/write
23208     89/<- %edx 4/r32/esp
23209     # var template/esi: (addr list var) = fn->outputs
23210     8b/-> *(ebp+0xc) 0/r32/eax
23211     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
23212     89/<- %esi 0/r32/eax
23213     # var curr-template/ebx: (addr list var) = fn->outputs
23214     89/<- %ebx 0/r32/eax
23215     # var curr/edi: (addr stmt-var) = stmt->inouts
23216     8b/-> *(ebp+8) 0/r32/eax
23217     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23218     89/<- %edi 0/r32/eax
23219     {
23220       # if template is null, break
23221       81 7/subop/compare %ebx 0/imm32
23222       0f 84/jump-if-= break/disp32
23223       # if curr is null, abort
23224       81 7/subop/compare %edi 0/imm32
23225       0f 84/jump-if-= $check-mu-return-stmt:error-too-few-inouts/disp32
23226       # var template-type/ecx: (addr type-tree) = template->value->type
23227       (lookup *ebx *(ebx+4))  # List-value List-value => eax
23228       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23229       89/<- %ecx 0/r32/eax
23230       # var curr-type/eax: (addr type-tree) = curr->value->type
23231       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23232       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23233       # if (curr->is-deref?) curr-type = payload of curr-type
23234       81 7/subop/compare *(edi+0x10) 0/imm32/false  # Stmt-var-is-deref
23235       {
23236         74/jump-if-= break/disp8
23237         (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
23238         # if t->right is null, t = t->left
23239         81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
23240         75/jump-if-!= break/disp8
23241         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23242       }
23243       # if curr-type is literal and template-type is float, abort
23244       50/push-eax
23245       {
23246         (simple-mu-type? %eax 0)  # literal => eax
23247         3d/compare-eax-and 0/imm32/false
23248         74/jump-if-= break/disp8
23249         (simple-mu-type? %ecx 0xf)  # float => eax
23250         3d/compare-eax-and 0/imm32/false
23251         0f 85/jump-if-!= $check-mu-return-stmt:error-literal-to-float/disp32
23252       }
23253       58/pop-to-eax
23254       # if (curr-type != template-type) abort
23255       (type-match? %ecx %eax %edx)  # => eax
23256       3d/compare-eax-and 0/imm32/false
23257       0f 84/jump-if-= $check-mu-return-stmt:error1/disp32
23258       # if register-within-list-with-conflict?(curr, original template, curr-template, stmt) abort
23259       (register-within-list-with-conflict? %edi %esi %ebx *(ebp+8))  # => eax
23260       3d/compare-eax-and 0/imm32/false
23261       0f 85/jump-if-!= $check-mu-return-stmt:error2/disp32
23262       # template = template->next
23263       (lookup *(ebx+8) *(ebx+0xc))  # List-next List-next => eax
23264       89/<- %ebx 0/r32/eax
23265       # curr = curr->next
23266       (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
23267       89/<- %edi 0/r32/eax
23268       #
23269       e9/jump loop/disp32
23270     }
23271     # if curr is not null, abort
23272     81 7/subop/compare %edi 0/imm32
23273     0f 85/jump-if-!= $check-mu-return-stmt:error-too-many-inouts/disp32
23274 $check-mu-return-stmt:end:
23275     # . reclaim locals
23276     81 0/subop/add %esp 0x6c/imm32
23277     # . restore registers
23278     5f/pop-to-edi
23279     5e/pop-to-esi
23280     5b/pop-to-ebx
23281     5a/pop-to-edx
23282     59/pop-to-ecx
23283     58/pop-to-eax
23284     # . epilogue
23285     89/<- %esp 5/r32/ebp
23286     5d/pop-to-ebp
23287     c3/return
23288 
23289 $check-mu-return-stmt:error1:
23290     (write-buffered *(ebp+0x10) "fn ")
23291     8b/-> *(ebp+0xc) 0/r32/eax
23292     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23293     (write-buffered *(ebp+0x10) %eax)
23294     (write-buffered *(ebp+0x10) ": return: '")
23295     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23296     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23297     (write-buffered *(ebp+0x10) %eax)
23298     (write-buffered *(ebp+0x10) "' has the wrong type\n")
23299     (flush *(ebp+0x10))
23300     (stop *(ebp+0x14) 1)
23301     # never gets here
23302 
23303 $check-mu-return-stmt:error2:
23304     (write-buffered *(ebp+0x10) "fn ")
23305     8b/-> *(ebp+0xc) 0/r32/eax
23306     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23307     (write-buffered *(ebp+0x10) %eax)
23308     (write-buffered *(ebp+0x10) ": return: '")
23309     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23310     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23311     (write-buffered *(ebp+0x10) %eax)
23312     (write-buffered *(ebp+0x10) "' is no longer available\n")
23313     (flush *(ebp+0x10))
23314     (stop *(ebp+0x14) 1)
23315     # never gets here
23316 
23317 $check-mu-return-stmt:error-literal-to-float:
23318     (write-buffered *(ebp+0x10) "fn ")
23319     8b/-> *(ebp+0xc) 0/r32/eax
23320     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23321     (write-buffered *(ebp+0x10) %eax)
23322     (write-buffered *(ebp+0x10) ": return: cannot copy literal '")
23323     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23324     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23325     (write-buffered *(ebp+0x10) %eax)
23326     (write-buffered *(ebp+0x10) "' to float\n")
23327     (flush *(ebp+0x10))
23328     (stop *(ebp+0x14) 1)
23329     # never gets here
23330 
23331 $check-mu-return-stmt:error-too-few-inouts:
23332     (write-buffered *(ebp+0x10) "fn ")
23333     8b/-> *(ebp+0xc) 0/r32/eax
23334     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23335     (write-buffered *(ebp+0x10) %eax)
23336     (write-buffered *(ebp+0x10) ": return: too few inouts\n")
23337     (flush *(ebp+0x10))
23338     (stop *(ebp+0x14) 1)
23339     # never gets here
23340 
23341 $check-mu-return-stmt:error-too-many-inouts:
23342     (write-buffered *(ebp+0x10) "fn ")
23343     8b/-> *(ebp+0xc) 0/r32/eax
23344     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23345     (write-buffered *(ebp+0x10) %eax)
23346     (write-buffered *(ebp+0x10) ": return: too many inouts\n")
23347     (flush *(ebp+0x10))
23348     (stop *(ebp+0x14) 1)
23349     # never gets here
23350 
23351 check-all-unique-registers:  # outputs: (addr list var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23352     # . prologue
23353     55/push-ebp
23354     89/<- %ebp 4/r32/esp
23355     # . save registers
23356     50/push-eax
23357     51/push-ecx
23358     56/push-esi
23359     # var table/esi: (addr table (handle array byte) int 8)
23360     81 5/subop/subtract %esp 0x60/imm32
23361     68/push 0x60/imm32/size
23362     68/push 0/imm32/read
23363     68/push 0/imm32/write
23364     89/<- %esi 4/r32/esp
23365     # var curr/ecx: (addr list var) = outputs
23366     8b/-> *(ebp+8) 1/r32/ecx
23367     {
23368       # if (curr == 0) break
23369       81 7/subop/compare %ecx 0/imm32
23370       0f 84/jump-if-= break/disp32
23371       # var reg/eax: (addr array byte) = curr->value->register  # guaranteed to exist
23372       (lookup *ecx *(ecx+4))  # List-value List-value => eax
23373       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
23374       # if reg exists in table, abort
23375       (maybe-get %esi %eax 0xc)  # => eax
23376       3d/compare-eax-and 0/imm32
23377       0f 85/jump-if-!= $check-all-unique-registers:abort/disp32
23378       # insert reg in table
23379       (lookup *ecx *(ecx+4))  # List-value List-value => eax
23380       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
23381       (get-or-insert %esi %eax 0xc Heap)
23382       # curr = curr->next
23383       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
23384       89/<- %ecx 0/r32/eax
23385       e9/jump loop/disp32
23386     }
23387 $check-all-unique-registers:end:
23388     # . reclaim locals
23389     81 0/subop/add %esp 0x6c/imm32
23390     # . restore registers
23391     5e/pop-to-esi
23392     59/pop-to-ecx
23393     58/pop-to-eax
23394     # . epilogue
23395     89/<- %esp 5/r32/ebp
23396     5d/pop-to-ebp
23397     c3/return
23398 
23399 $check-all-unique-registers:abort:
23400     (write-buffered *(ebp+0x10) "fn ")
23401     8b/-> *(ebp+0xc) 0/r32/eax
23402     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23403     (write-buffered *(ebp+0x10) %eax)
23404     (write-buffered *(ebp+0x10) ": outputs must be in unique registers\n")
23405     (flush *(ebp+0x10))
23406     (stop *(ebp+0x14) 1)
23407     # never gets here
23408 
23409 # return false if s's register is not between start (inclusive) and end (exclusive)
23410 # return false if the positionally corresponding register in stmt->inouts (where s comes from) is also s's register
23411 # otherwise return true
23412 register-within-list-with-conflict?:  # s: (addr stmt-var), start: (addr list var), end: (addr list var), stmt: (addr stmt) -> result/eax: boolean
23413     # . prologue
23414     55/push-ebp
23415     89/<- %ebp 4/r32/esp
23416     # . save registers
23417     51/push-ecx
23418     52/push-edx
23419     53/push-ebx
23420     56/push-esi
23421     57/push-edi
23422     # var target/ebx: (addr array byte) = s->value->register
23423     8b/-> *(ebp+8) 0/r32/eax
23424     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23425     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
23426 #?     (write-buffered Stderr "AA: ")
23427 #?     (write-buffered Stderr %eax)
23428 #?     (write-buffered Stderr Newline)
23429 #?     (flush Stderr)
23430     # if (var->register == 0) return false
23431     3d/compare-eax-and 0/imm32
23432     0f 84/jump-if-= $register-within-list-with-conflict?:end/disp32  # eax turns into result
23433     89/<- %ebx 0/r32/eax
23434     # var curr/ecx: (addr list var) = start
23435     8b/-> *(ebp+0xc) 1/r32/ecx
23436     # edx = end
23437     8b/-> *(ebp+0x10) 2/r32/edx
23438     {
23439       # if (curr == 0) break
23440       81 7/subop/compare %edi 0/imm32
23441       0f 84/jump-if-= break/disp32
23442       # if (curr == end) break
23443       39/compare %ecx 2/r32/edx
23444       0f 84/jump-if-= break/disp32
23445       # var curr-reg/eax: (addr array byte) = curr->value->register
23446       (lookup *ecx *(ecx+4))  # List-value List-value => eax
23447       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
23448       # if (curr-reg == 0) continue
23449       3d/compare-eax-and 0/imm32
23450       74/jump-if-= $register-within-list-with-conflict?:continue/disp8
23451       # if (curr-reg == target) check for conflict
23452       (string-equal? %eax %ebx)  # => eax
23453       3d/compare-eax-and 0/imm32/false
23454       {
23455         74/jump-if-= break/disp8
23456 #?         (write-buffered Stderr "conflict?\n")
23457 #?         (flush Stderr)
23458         # var return-inouts/eax: (addr stmt-var) = stmt->inouts
23459         8b/-> *(ebp+0x14) 0/r32/eax
23460         (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23461         (register-conflict? %ebx %eax *(ebp+0xc))  # => eax
23462         eb/jump $register-within-list-with-conflict?:end/disp8
23463       }
23464 $register-within-list-with-conflict?:continue:
23465       # curr = curr->next
23466       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
23467       89/<- %ecx 0/r32/eax
23468       e9/jump loop/disp32
23469     }
23470     # return false
23471     b8/copy-to-eax 0/imm32/false
23472 $register-within-list-with-conflict?:end:
23473     # . restore registers
23474     5f/pop-to-edi
23475     5e/pop-to-esi
23476     5b/pop-to-ebx
23477     5a/pop-to-edx
23478     59/pop-to-ecx
23479     # . epilogue
23480     89/<- %esp 5/r32/ebp
23481     5d/pop-to-ebp
23482     c3/return
23483 
23484 # At the first occurrence of register 'reg' in fn-outputs,
23485 # check if the corresponding element of return-inouts has a different register.
23486 # This hacky helper is intended to be called in one specific place. Don't
23487 # reuse it as is.
23488 register-conflict?:  # reg: (addr array byte), return-inouts: (addr stmt-var), fn-outputs: (addr list var) => result/eax: boolean
23489     # . prologue
23490     55/push-ebp
23491     89/<- %ebp 4/r32/esp
23492     # . save registers
23493     51/push-ecx
23494     52/push-edx
23495     53/push-ebx
23496     56/push-esi
23497     57/push-edi
23498 #?     (write-buffered Stderr "BB: ")
23499 #?     (write-buffered Stderr *(ebp+8))
23500 #?     (write-buffered Stderr Newline)
23501 #?     (flush Stderr)
23502     # var curr-output/edi: (addr list var) = fn-outputs
23503     8b/-> *(ebp+0x10) 7/r32/edi
23504     # var curr-inout/esi: (addr stmt-var) = return-inouts
23505     8b/-> *(ebp+0xc) 6/r32/esi
23506     {
23507       # if (curr-output == 0) abort
23508       81 7/subop/compare %edi 0/imm32
23509       0f 84/jump-if-= break/disp32
23510       # if (curr-output->value->register != reg) continue
23511       (lookup *edi *(edi+4))  # List-value List-value => eax
23512       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
23513       (string-equal? %eax *(ebp+8))  # => eax
23514       3d/compare-eax-and 0/imm32/false
23515       0f 84/jump-if= $register-conflict?:continue/disp32
23516 #?       (write-buffered Stderr "rescan\n")
23517 #?       (flush Stderr)
23518       # var curr-reg/eax: (addr array byte) = curr-inout->value->register
23519       (lookup *esi *(esi+4))  # List-value List-value => eax
23520       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
23521       # if (curr-reg == 0) return true
23522       3d/compare-eax-and 0/imm32
23523       {
23524         75/jump-if-!= break/disp8
23525 #?         (write-buffered Stderr "no register\n")
23526 #?         (flush Stderr)
23527         b8/copy-to-eax 1/imm32/true
23528         e9/jump $register-conflict?:end/disp32
23529       }
23530       # return (curr-reg != reg)
23531       (string-equal? %eax *(ebp+8))  # => eax
23532       3d/compare-eax-and 0/imm32/false
23533       0f 94/set-if-= %al
23534 #?       (write-buffered Stderr "final: ")
23535 #?       (write-int32-hex-buffered Stderr %eax)
23536 #?       (write-buffered Stderr Newline)
23537 #?       (flush Stderr)
23538       eb/jump $register-conflict?:end/disp8
23539 $register-conflict?:continue:
23540       # curr-output = curr-output->next
23541       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
23542       89/<- %edi 0/r32/eax
23543       # curr-inout = curr-inout->next
23544       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
23545       89/<- %esi 0/r32/eax
23546       e9/jump loop/disp32
23547     }
23548     # should never get here
23549     (write-buffered Stderr "register-conflict? misused\n")
23550     (flush Stderr)
23551     e8/call syscall_exit/disp32
23552 $register-conflict?:end:
23553     # . restore registers
23554     5f/pop-to-edi
23555     5e/pop-to-esi
23556     5b/pop-to-ebx
23557     5a/pop-to-edx
23558     59/pop-to-ecx
23559     # . epilogue
23560     89/<- %esp 5/r32/ebp
23561     5d/pop-to-ebp
23562     c3/return
23563 
23564 check-final-stmt-is-return:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23565     # . prologue
23566     55/push-ebp
23567     89/<- %ebp 4/r32/esp
23568     # . save registers
23569     50/push-eax
23570     51/push-ecx
23571     # var curr/ecx: (addr list stmt) = block->stmts
23572     8b/-> *(ebp+8) 0/r32/eax
23573     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
23574     3d/compare-eax-and 0/imm32
23575     74/jump-if-= $check-final-stmt-is-return:error/disp8
23576     89/<- %ecx 0/r32/eax
23577     {
23578       # if curr->next == 0, break
23579       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
23580       3d/compare-eax-and 0/imm32
23581       74/jump-if-= break/disp8
23582       # curr = curr->next
23583       89/<- %ecx 0/r32/eax
23584       e9/jump loop/disp32
23585     }
23586 $check-final-stmt-is-return:check-tag:
23587     # if curr->value->tag != Stmt1, abort
23588     (lookup *ecx *(ecx+4))  # List-value List-value => eax
23589     81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
23590     75/jump-if-!= $check-final-stmt-is-return:error/disp8
23591 $check-final-stmt-is-return:check-operation:
23592     # if curr->operation != "return", abort
23593     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
23594     (string-equal? %eax "return")
23595     3d/compare-eax-and 0/imm32/false
23596     74/jump-if-= $check-final-stmt-is-return:error/disp8
23597 $check-final-stmt-is-return:end:
23598     # . restore registers
23599     59/pop-to-ecx
23600     58/pop-to-eax
23601     # . epilogue
23602     89/<- %esp 5/r32/ebp
23603     5d/pop-to-ebp
23604     c3/return
23605 
23606 $check-final-stmt-is-return:error:
23607     (write-buffered *(ebp+0x10) "fn ")
23608     8b/-> *(ebp+0xc) 0/r32/eax
23609     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23610     (write-buffered *(ebp+0x10) %eax)
23611     (write-buffered *(ebp+0x10) ": final statement should be a 'return'\n")
23612     (flush *(ebp+0x10))
23613     (stop *(ebp+0x14) 1)
23614     # never gets here
23615 
23616 check-no-breaks:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23617     # . prologue
23618     55/push-ebp
23619     89/<- %ebp 4/r32/esp
23620     # . save registers
23621     50/push-eax
23622     51/push-ecx
23623     # var curr/ecx: (addr list stmt) = block->stmts
23624     8b/-> *(ebp+8) 0/r32/eax
23625     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
23626     3d/compare-eax-and 0/imm32
23627     0f 84/jump-if-= $check-no-breaks:end/disp32
23628     89/<- %ecx 0/r32/eax
23629     {
23630       # if curr->next == 0, break
23631       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
23632       3d/compare-eax-and 0/imm32
23633       74/jump-if-= break/disp8
23634       # if curr->value->tag != Stmt1, continue
23635       (lookup *ecx *(ecx+4))  # List-value List-value => eax
23636       81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
23637       75/jump-if-!= $check-no-breaks:continue/disp8
23638       # if curr->value->operation starts with "break", abort
23639       (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
23640       (string-starts-with? %eax "break")  # => eax
23641       3d/compare-eax-and 0/imm32/false
23642       75/jump-if-!= $check-no-breaks:error/disp8
23643 $check-no-breaks:continue:
23644       # curr = curr->next
23645       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
23646       89/<- %ecx 0/r32/eax
23647       e9/jump loop/disp32
23648     }
23649 $check-no-breaks:end:
23650     # . restore registers
23651     59/pop-to-ecx
23652     58/pop-to-eax
23653     # . epilogue
23654     89/<- %esp 5/r32/ebp
23655     5d/pop-to-ebp
23656     c3/return
23657 
23658 $check-no-breaks:error:
23659     (write-buffered *(ebp+0x10) "fn ")
23660     8b/-> *(ebp+0xc) 0/r32/eax
23661     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23662     (write-buffered *(ebp+0x10) %eax)
23663     (write-buffered *(ebp+0x10) " has outputs, so you cannot 'break' out of the outermost block. Use 'return'.\n")
23664     (flush *(ebp+0x10))
23665     (stop *(ebp+0x14) 1)
23666     # never gets here
23667 
23668 check-mu-get-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23669     # . prologue
23670     55/push-ebp
23671     89/<- %ebp 4/r32/esp
23672     # . save registers
23673     50/push-eax
23674     51/push-ecx
23675     52/push-edx
23676     53/push-ebx
23677     56/push-esi
23678     57/push-edi
23679     # esi = stmt
23680     8b/-> *(ebp+8) 6/r32/esi
23681     # - check for 0 inouts
23682     # var base/ecx: (addr var) = stmt->inouts->value
23683     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23684     3d/compare-eax-and 0/imm32/false
23685     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-inouts/disp32
23686     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23687     89/<- %ecx 0/r32/eax
23688 $check-mu-get-stmt:check-base:
23689     # - check base type
23690     # if it's an 'addr', check that it's in a register
23691     # var base-type/ebx: (addr type-tree) = lookup(base->type)
23692     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
23693     89/<- %ebx 0/r32/eax
23694     {
23695       81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
23696       0f 85/jump-if-!= break/disp32
23697 $check-mu-get-stmt:base-is-compound:
23698       # if (type->left != addr) break
23699       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
23700       (simple-mu-type? %eax 2)  # addr => eax
23701       3d/compare-eax-and 0/imm32/false
23702       74/jump-if-= break/disp8
23703 $check-mu-get-stmt:base-is-addr:
23704       # now check for register
23705       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
23706       0f 84/jump-if-= $check-mu-get-stmt:error-base-type-addr-but-not-register/disp32
23707 $check-mu-get-stmt:base-is-addr-in-register:
23708       # type->left is now an addr; skip it
23709       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23710       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
23711       0f 85/jump-if-!= $check-mu-get-stmt:error-bad-base/disp32
23712 $check-mu-get-stmt:base-is-addr-to-atom-in-register:
23713       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23714       89/<- %ebx 0/r32/eax
23715     }
23716 $check-mu-get-stmt:check-base-typeinfo:
23717     # ensure type is a container
23718     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
23719     {
23720       75/jump-if-!= break/disp8
23721       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
23722       89/<- %ebx 0/r32/eax
23723     }
23724     # var base-type-id/ebx: type-id = base-type->value
23725     8b/-> *(ebx+4) 3/r32/ebx  # Type-tree-value
23726     (container? %ebx)  # => eax
23727     3d/compare-eax-and 0/imm32/false
23728     0f 84/jump-if-= $check-mu-get-stmt:error-bad-base/disp32
23729     # var base-typeinfo/edx: (addr typeinfo) = find-typeinfo(base-type-id)
23730     # . var container/ecx: (handle typeinfo)
23731     68/push 0/imm32
23732     68/push 0/imm32
23733     89/<- %ecx 4/r32/esp
23734     # .
23735     (find-typeinfo %ebx %ecx)
23736     (lookup *ecx *(ecx+4))  # => eax
23737     # . reclaim container
23738     81 0/subop/add %esp 8/imm32
23739     # .
23740     89/<- %edx 0/r32/eax
23741     # var offset/ecx: (addr stmt-var) = stmt->inouts->next
23742     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23743     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
23744     89/<- %ecx 0/r32/eax
23745     # - check for 1 inout
23746     3d/compare-eax-and 0/imm32/false
23747     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-inouts/disp32
23748     # var offset/ecx: (addr var) = lookup(offset->value)
23749     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
23750     89/<- %ecx 0/r32/eax
23751     # - check for valid field
23752     81 7/subop/compare *(ecx+0x14) -1/imm32/uninitialized  # Var-offset
23753     0f 84/jump-if-= $check-mu-get-stmt:error-bad-field/disp32
23754     # - check for too many inouts
23755     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23756     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
23757     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
23758     3d/compare-eax-and 0/imm32/false
23759     0f 85/jump-if-!= $check-mu-get-stmt:error-too-many-inouts/disp32
23760     # var output/edi: (addr var) = stmt->outputs->value
23761     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
23762     # - check for 0 outputs
23763     3d/compare-eax-and 0/imm32/false
23764     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-outputs/disp32
23765     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23766     89/<- %edi 0/r32/eax
23767 $check-mu-get-stmt:check-output-type:
23768     # - check output type
23769     # must be in register
23770     (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
23771     3d/compare-eax-and 0/imm32
23772     0f 84/jump-if-= $check-mu-get-stmt:error-output-not-in-register/disp32
23773     # must have a non-atomic type
23774     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
23775     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
23776     0f 85/jump-if-!= $check-mu-get-stmt:error-output-type-not-address/disp32
23777     # type must start with (addr ...)
23778     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23779     (simple-mu-type? %eax 2)  # => eax
23780     3d/compare-eax-and 0/imm32/false
23781     0f 84/jump-if-= $check-mu-get-stmt:error-output-type-not-address/disp32
23782 $check-mu-get-stmt:check-output-type-match:
23783     # payload of addr type must match 'type' definition
23784     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
23785     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
23786     # if (payload->right == null) payload = payload->left
23787     81 7/subop/compare *(eax+0xc) 0/imm32/null  # Type-tree-right
23788     {
23789       75/jump-if-!= break/disp8
23790       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23791     }
23792     89/<- %edi 0/r32/eax
23793     # . var output-name/ecx: (addr array byte)
23794     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
23795     89/<- %ecx 0/r32/eax
23796     # . var base-typeinfo-entry/eax: (addr handle typeinfo-entry)
23797     (lookup *(edx+4) *(edx+8))  # Typeinfo-fields Typeinfo-fields => eax
23798     (get %eax %ecx 0x10)  # => eax
23799     # .
23800     (lookup *eax *(eax+4))  # => eax
23801     (lookup *eax *(eax+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
23802     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23803     # .
23804     (type-equal? %edi %eax)  # => eax
23805     3d/compare-eax-and 0/imm32/false
23806     0f 84/jump-if-= $check-mu-get-stmt:error-bad-output-type/disp32
23807     # - check for too many outputs
23808     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
23809     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
23810     3d/compare-eax-and 0/imm32/false
23811     0f 85/jump-if-!= $check-mu-get-stmt:error-too-many-outputs/disp32
23812 $check-mu-get-stmt:end:
23813     # . restore registers
23814     5f/pop-to-edi
23815     5e/pop-to-esi
23816     5b/pop-to-ebx
23817     5a/pop-to-edx
23818     59/pop-to-ecx
23819     58/pop-to-eax
23820     # . epilogue
23821     89/<- %esp 5/r32/ebp
23822     5d/pop-to-ebp
23823     c3/return
23824 
23825 $check-mu-get-stmt:error-too-few-inouts:
23826     (write-buffered *(ebp+0x10) "fn ")
23827     8b/-> *(ebp+0xc) 0/r32/eax
23828     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23829     (write-buffered *(ebp+0x10) %eax)
23830     (write-buffered *(ebp+0x10) ": stmt get: too few inouts (2 required)\n")
23831     (flush *(ebp+0x10))
23832     (stop *(ebp+0x14) 1)
23833     # never gets here
23834 
23835 $check-mu-get-stmt:error-too-many-inouts:
23836     (write-buffered *(ebp+0x10) "fn ")
23837     8b/-> *(ebp+0xc) 0/r32/eax
23838     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23839     (write-buffered *(ebp+0x10) %eax)
23840     (write-buffered *(ebp+0x10) ": stmt get: too many inouts (2 required)\n")
23841     (flush *(ebp+0x10))
23842     (stop *(ebp+0x14) 1)
23843     # never gets here
23844 
23845 $check-mu-get-stmt:error-too-few-outputs:
23846     (write-buffered *(ebp+0x10) "fn ")
23847     8b/-> *(ebp+0xc) 0/r32/eax
23848     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23849     (write-buffered *(ebp+0x10) %eax)
23850     (write-buffered *(ebp+0x10) ": stmt get: must have an output\n")
23851     (flush *(ebp+0x10))
23852     (stop *(ebp+0x14) 1)
23853     # never gets here
23854 
23855 $check-mu-get-stmt:error-too-many-outputs:
23856     (write-buffered *(ebp+0x10) "fn ")
23857     8b/-> *(ebp+0xc) 0/r32/eax
23858     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23859     (write-buffered *(ebp+0x10) %eax)
23860     (write-buffered *(ebp+0x10) ": stmt get: too many outputs (1 required)\n")
23861     (flush *(ebp+0x10))
23862     (stop *(ebp+0x14) 1)
23863     # never gets here
23864 
23865 $check-mu-get-stmt:error-bad-base:
23866     # error("fn " fn ": stmt get: var '" base->name "' must have a 'type' definition\n")
23867     (write-buffered *(ebp+0x10) "fn ")
23868     8b/-> *(ebp+0xc) 0/r32/eax
23869     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23870     (write-buffered *(ebp+0x10) %eax)
23871     (write-buffered *(ebp+0x10) ": stmt get: var '")
23872     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23873     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23874     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23875     (write-buffered *(ebp+0x10) %eax)
23876     (write-buffered *(ebp+0x10) "' must have a 'type' definition\n")
23877     (flush *(ebp+0x10))
23878     (stop *(ebp+0x14) 1)
23879     # never gets here
23880 
23881 $check-mu-get-stmt:error-base-type-addr-but-not-register:
23882     (write-buffered *(ebp+0x10) "fn ")
23883     8b/-> *(ebp+0xc) 0/r32/eax
23884     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23885     (write-buffered *(ebp+0x10) %eax)
23886     (write-buffered *(ebp+0x10) ": stmt get: var '")
23887     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23888     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23889     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23890     (write-buffered *(ebp+0x10) %eax)
23891     (write-buffered *(ebp+0x10) "' is an 'addr' type, and so must live in a register\n")
23892     (flush *(ebp+0x10))
23893     (stop *(ebp+0x14) 1)
23894     # never gets here
23895 
23896 $check-mu-get-stmt:error-bad-field:
23897     # error("fn " fn ": stmt get: type " type " has no member called '" curr->name "'\n")
23898     (write-buffered *(ebp+0x10) "fn ")
23899     8b/-> *(ebp+0xc) 0/r32/eax
23900     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23901     (write-buffered *(ebp+0x10) %eax)
23902     (write-buffered *(ebp+0x10) ": stmt get: type '")
23903     # . write(Type-id->data[tmp])
23904     bf/copy-to-edi Type-id/imm32
23905     8b/-> *(edi+ebx<<2+0xc) 6/r32/esi
23906     {
23907       81 7/subop/compare %esi 0/imm32
23908       74/jump-if-= break/disp8
23909       (write-buffered *(ebp+0x10) %esi)
23910     }
23911     # .
23912     (write-buffered *(ebp+0x10) "' has no member called '")
23913     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
23914     (write-buffered *(ebp+0x10) %eax)
23915     (write-buffered *(ebp+0x10) "'\n")
23916     (flush *(ebp+0x10))
23917     (stop *(ebp+0x14) 1)
23918     # never gets here
23919 
23920 $check-mu-get-stmt:error-output-not-in-register:
23921     (write-buffered *(ebp+0x10) "fn ")
23922     8b/-> *(ebp+0xc) 0/r32/eax
23923     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23924     (write-buffered *(ebp+0x10) %eax)
23925     (write-buffered *(ebp+0x10) ": stmt get: output '")
23926     (lookup *edi *(edi+4))  # Var-name Var-name => eax
23927     (write-buffered *(ebp+0x10) %eax)
23928     (write-buffered *(ebp+0x10) "' is not in a register\n")
23929     (flush *(ebp+0x10))
23930     (stop *(ebp+0x14) 1)
23931     # never gets here
23932 
23933 $check-mu-get-stmt:error-output-type-not-address:
23934     (write-buffered *(ebp+0x10) "fn ")
23935     8b/-> *(ebp+0xc) 0/r32/eax
23936     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23937     (write-buffered *(ebp+0x10) %eax)
23938     (write-buffered *(ebp+0x10) ": stmt get: output must be an addr\n")
23939     (flush *(ebp+0x10))
23940     (stop *(ebp+0x14) 1)
23941     # never gets here
23942 
23943 $check-mu-get-stmt:error-bad-output-type:
23944     (write-buffered *(ebp+0x10) "fn ")
23945     8b/-> *(ebp+0xc) 0/r32/eax
23946     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23947     (write-buffered *(ebp+0x10) %eax)
23948     (write-buffered *(ebp+0x10) ": stmt get: wrong output type for member '")
23949     (write-buffered *(ebp+0x10) %ecx)
23950     (write-buffered *(ebp+0x10) "' of type '")
23951     bf/copy-to-edi Type-id/imm32
23952     8b/-> *(edi+ebx<<2+0xc) 6/r32/esi
23953     {
23954       81 7/subop/compare %esi 0/imm32
23955       74/jump-if-= break/disp8
23956       (write-buffered *(ebp+0x10) %esi)
23957     }
23958     (write-buffered *(ebp+0x10) "'\n")
23959     (flush *(ebp+0x10))
23960     (stop *(ebp+0x14) 1)
23961     # never gets here
23962 
23963 check-mu-index-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23964     # . prologue
23965     55/push-ebp
23966     89/<- %ebp 4/r32/esp
23967     # . save registers
23968     50/push-eax
23969     51/push-ecx
23970     52/push-edx
23971     53/push-ebx
23972     56/push-esi
23973     57/push-edi
23974     # esi = stmt
23975     8b/-> *(ebp+8) 6/r32/esi
23976     # - check for 0 inouts
23977     # var base/ecx: (addr var) = stmt->inouts->value
23978     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23979 $check-mu-index-stmt:check-no-inouts:
23980     3d/compare-eax-and 0/imm32
23981     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-inouts/disp32
23982     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23983     89/<- %ecx 0/r32/eax
23984     # - check base type is either (addr array ...) in register or (array ...) on stack
23985     # var base-type/ebx: (addr type-tree) = lookup(base->type)
23986     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
23987     89/<- %ebx 0/r32/eax
23988     # if base-type is an atom, abort with a precise error
23989     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
23990     {
23991       74/jump-if-= break/disp8
23992       (simple-mu-type? %ebx 3)  # array => eax
23993       3d/compare-eax-and 0/imm32/false
23994       0f 85/jump-if-!= $check-mu-index-stmt:error-base-array-atom-type/disp32
23995       0f 84/jump-if-= $check-mu-index-stmt:error-base-non-array-type/disp32
23996     }
23997 $check-mu-index-stmt:base-is-compound:
23998     # if type->left not addr or array, abort
23999     {
24000       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24001       (simple-mu-type? %eax 2)  # addr => eax
24002       3d/compare-eax-and 0/imm32/false
24003       75/jump-if-!= break/disp8
24004       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24005       (simple-mu-type? %eax 3)  # array => eax
24006       3d/compare-eax-and 0/imm32/false
24007       75/jump-if-!= break/disp8
24008       e9/jump $check-mu-index-stmt:error-base-non-array-type/disp32
24009     }
24010     # if (type->left == addr) ensure type->right->left == array and type->register exists
24011     {
24012       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24013       (simple-mu-type? %eax 2)  # addr => eax
24014       3d/compare-eax-and 0/imm32/false
24015       74/jump-if-= break/disp8
24016 $check-mu-index-stmt:base-is-addr:
24017       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
24018       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
24019       (simple-mu-type? %eax 3)  # array => eax
24020       3d/compare-eax-and 0/imm32/false
24021       0f 84/jump-if-= $check-mu-index-stmt:error-base-non-array-type/disp32
24022 $check-mu-index-stmt:check-base-addr-is-register:
24023       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
24024       0f 84/jump-if-= $check-mu-index-stmt:error-base-address-array-type-on-stack/disp32
24025     }
24026     # if (type->left == array) ensure type->register doesn't exist
24027     {
24028       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24029       (simple-mu-type? %eax 3)  # array => eax
24030       3d/compare-eax-and 0/imm32/false
24031       74/jump-if-= break/disp8
24032 $check-mu-index-stmt:base-is-array:
24033       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
24034       0f 85/jump-if-!= $check-mu-index-stmt:error-base-array-type-in-register/disp32
24035     }
24036     # if (base-type->left == addr) base-type = base-type->right
24037     {
24038       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24039       (simple-mu-type? %eax 2)  # addr => eax
24040       3d/compare-eax-and 0/imm32/false
24041       74/jump-if-= break/disp8
24042       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
24043       89/<- %ebx 0/r32/eax
24044     }
24045     # - check for 1 inout
24046     # var index/ecx: (addr stmt-var) = stmt->inouts->next->value
24047     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24048     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24049 $check-mu-index-stmt:check-single-inout:
24050     3d/compare-eax-and 0/imm32
24051     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-inouts/disp32
24052     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24053     89/<- %ecx 0/r32/eax
24054     # - check index is either a literal or register
24055     # var index-type/edx: (addr type-tree)
24056     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
24057     89/<- %edx 0/r32/eax
24058     # if index type is an atom, it must be a literal or int
24059     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
24060     {
24061       74/jump-if-= break/disp8
24062 $check-mu-index-stmt:index-type-is-atom:
24063       (simple-mu-type? %edx 0)  # literal => eax
24064       3d/compare-eax-and 0/imm32/false
24065       75/jump-if-!= $check-mu-index-stmt:index-type-done/disp8
24066       (simple-mu-type? %edx 1)  # int => eax
24067       3d/compare-eax-and 0/imm32/false
24068       75/jump-if-!= $check-mu-index-stmt:index-type-done/disp8
24069       (simple-mu-type? %edx 7)  # offset => eax
24070       3d/compare-eax-and 0/imm32/false
24071       0f 85/jump-if-!= $check-mu-index-stmt:error-index-offset-atom-type/disp32
24072       e9/jump $check-mu-index-stmt:error-invalid-index-type/disp32
24073     }
24074     # if index type is a non-atom: it must be an offset
24075     {
24076       75/jump-if-!= break/disp8
24077 $check-mu-index-stmt:index-type-is-non-atom:
24078       (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
24079       (simple-mu-type? %eax 7)  # offset => eax
24080       3d/compare-eax-and 0/imm32/false
24081       0f 84/jump-if-= $check-mu-index-stmt:error-invalid-index-type/disp32
24082     }
24083 $check-mu-index-stmt:index-type-done:
24084     # check index is either a literal or in a register
24085     {
24086       (simple-mu-type? %edx 0)  # literal => eax
24087       3d/compare-eax-and 0/imm32/false
24088       75/jump-if-!= break/disp8
24089 $check-mu-index-stmt:check-index-in-register:
24090       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
24091       0f 84/jump-if-= $check-mu-index-stmt:error-index-on-stack/disp32
24092     }
24093     # - if index is an 'int', check that element type of base has size 1, 2, 4 or 8 bytes.
24094     {
24095       (simple-mu-type? %edx 1)  # int => eax
24096       3d/compare-eax-and 0/imm32/false
24097       74/jump-if-= break/disp8
24098 $check-mu-index-stmt:check-index-can-be-int:
24099       (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24100       (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24101       (array-element-size %eax)  # => eax
24102       3d/compare-eax-and 1/imm32
24103       74/jump-if-= break/disp8
24104       3d/compare-eax-and 2/imm32
24105       74/jump-if-= break/disp8
24106       3d/compare-eax-and 4/imm32
24107       74/jump-if-= break/disp8
24108       3d/compare-eax-and 8/imm32
24109       74/jump-if-= break/disp8
24110       e9/jump $check-mu-index-stmt:error-index-needs-offset/disp32
24111     }
24112     # - check for too many inouts
24113     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24114     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24115     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24116     3d/compare-eax-and 0/imm32/false
24117     0f 85/jump-if-!= $check-mu-index-stmt:error-too-many-inouts/disp32
24118     # - check for 0 outputs
24119     # var output/edi: (addr var) = stmt->outputs->value
24120     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24121     3d/compare-eax-and 0/imm32/false
24122     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-outputs/disp32
24123     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24124     89/<- %edi 0/r32/eax
24125     # - check output type
24126     # must have a non-atomic type
24127     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
24128     89/<- %edx 0/r32/eax
24129     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
24130     0f 85/jump-if-!= $check-mu-index-stmt:error-output-type-not-address/disp32
24131     # type must start with (addr ...)
24132     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
24133     (simple-mu-type? %eax 2)  # addr => eax
24134     3d/compare-eax-and 0/imm32/false
24135     0f 84/jump-if-= $check-mu-index-stmt:error-output-type-not-address/disp32
24136     # if tail(base-type) != tail(output-type) abort
24137     (type-tail %ebx)  # => eax
24138     89/<- %ebx 0/r32/eax
24139     (type-tail %edx)  # => eax
24140     (type-equal? %ebx %eax)  # => eax
24141     3d/compare-eax-and 0/imm32/false
24142     0f 84/jump-if-= $check-mu-index-stmt:error-bad-output-type/disp32
24143     # - check for too many outputs
24144     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24145     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24146     3d/compare-eax-and 0/imm32/false
24147     0f 85/jump-if-!= $check-mu-index-stmt:error-too-many-outputs/disp32
24148 $check-mu-index-stmt:end:
24149     # . restore registers
24150     5f/pop-to-edi
24151     5e/pop-to-esi
24152     5b/pop-to-ebx
24153     5a/pop-to-edx
24154     59/pop-to-ecx
24155     58/pop-to-eax
24156     # . epilogue
24157     89/<- %esp 5/r32/ebp
24158     5d/pop-to-ebp
24159     c3/return
24160 
24161 $check-mu-index-stmt:error-base-non-array-type:
24162     (write-buffered *(ebp+0x10) "fn ")
24163     8b/-> *(ebp+0xc) 0/r32/eax
24164     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24165     (write-buffered *(ebp+0x10) %eax)
24166     (write-buffered *(ebp+0x10) ": stmt index: var '")
24167     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24168     (write-buffered *(ebp+0x10) %eax)
24169     (write-buffered *(ebp+0x10) "' is not an array\n")
24170     (flush *(ebp+0x10))
24171     (stop *(ebp+0x14) 1)
24172     # never gets here
24173 
24174 $check-mu-index-stmt:error-base-array-atom-type:
24175     (write-buffered *(ebp+0x10) "fn ")
24176     8b/-> *(ebp+0xc) 0/r32/eax
24177     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24178     (write-buffered *(ebp+0x10) %eax)
24179     (write-buffered *(ebp+0x10) ": stmt index: array '")
24180     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24181     (write-buffered *(ebp+0x10) %eax)
24182     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
24183     (flush *(ebp+0x10))
24184     (stop *(ebp+0x14) 1)
24185     # never gets here
24186 
24187 $check-mu-index-stmt:error-base-address-array-type-on-stack:
24188     (write-buffered *(ebp+0x10) "fn ")
24189     8b/-> *(ebp+0xc) 0/r32/eax
24190     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24191     (write-buffered *(ebp+0x10) %eax)
24192     (write-buffered *(ebp+0x10) ": stmt index: var '")
24193     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24194     (write-buffered *(ebp+0x10) %eax)
24195     (write-buffered *(ebp+0x10) "' is an addr to an array, and so must live in a register\n")
24196     (flush *(ebp+0x10))
24197     (stop *(ebp+0x14) 1)
24198     # never gets here
24199 
24200 $check-mu-index-stmt:error-base-array-type-in-register:
24201     (write-buffered *(ebp+0x10) "fn ")
24202     8b/-> *(ebp+0xc) 0/r32/eax
24203     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24204     (write-buffered *(ebp+0x10) %eax)
24205     (write-buffered *(ebp+0x10) ": stmt index: var '")
24206     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24207     (write-buffered *(ebp+0x10) %eax)
24208     (write-buffered *(ebp+0x10) "' is an array, and so must live on the stack\n")
24209     (flush *(ebp+0x10))
24210     (stop *(ebp+0x14) 1)
24211     # never gets here
24212 
24213 $check-mu-index-stmt:error-too-few-inouts:
24214     (write-buffered *(ebp+0x10) "fn ")
24215     8b/-> *(ebp+0xc) 0/r32/eax
24216     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24217     (write-buffered *(ebp+0x10) %eax)
24218     (write-buffered *(ebp+0x10) ": stmt index: too few inouts (2 required)\n")
24219     (flush *(ebp+0x10))
24220     (stop *(ebp+0x14) 1)
24221     # never gets here
24222 
24223 $check-mu-index-stmt:error-invalid-index-type:
24224     (write-buffered *(ebp+0x10) "fn ")
24225     8b/-> *(ebp+0xc) 0/r32/eax
24226     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24227     (write-buffered *(ebp+0x10) %eax)
24228     (write-buffered *(ebp+0x10) ": stmt index: second argument '")
24229     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24230     (write-buffered *(ebp+0x10) %eax)
24231     (write-buffered *(ebp+0x10) "' must be an int or offset\n")
24232     (flush *(ebp+0x10))
24233     (stop *(ebp+0x14) 1)
24234     # never gets here
24235 
24236 $check-mu-index-stmt:error-index-offset-atom-type:
24237     (write-buffered *(ebp+0x10) "fn ")
24238     8b/-> *(ebp+0xc) 0/r32/eax
24239     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24240     (write-buffered *(ebp+0x10) %eax)
24241     (write-buffered *(ebp+0x10) ": stmt index: offset '")
24242     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24243     (write-buffered *(ebp+0x10) %eax)
24244     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
24245     (flush *(ebp+0x10))
24246     (stop *(ebp+0x14) 1)
24247     # never gets here
24248 
24249 $check-mu-index-stmt:error-index-on-stack:
24250     (write-buffered *(ebp+0x10) "fn ")
24251     8b/-> *(ebp+0xc) 0/r32/eax
24252     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24253     (write-buffered *(ebp+0x10) %eax)
24254     (write-buffered *(ebp+0x10) ": stmt index: second argument '")
24255     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24256     (write-buffered *(ebp+0x10) %eax)
24257     (write-buffered *(ebp+0x10) "' must be in a register\n")
24258     (flush *(ebp+0x10))
24259     (stop *(ebp+0x14) 1)
24260     # never gets here
24261 
24262 $check-mu-index-stmt:error-index-needs-offset:
24263     (write-buffered *(ebp+0x10) "fn ")
24264     8b/-> *(ebp+0xc) 0/r32/eax
24265     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24266     (write-buffered *(ebp+0x10) %eax)
24267     (write-buffered *(ebp+0x10) ": stmt index: cannot take an int for array '")
24268     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24269     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24270     (lookup *eax *(eax+4))  # Var-name Var-name => eax
24271     (write-buffered *(ebp+0x10) %eax)
24272     (write-buffered *(ebp+0x10) "'; create an offset instead. See mu.md for details.\n")
24273     (flush *(ebp+0x10))
24274     (stop *(ebp+0x14) 1)
24275     # never gets here
24276 
24277 $check-mu-index-stmt:error-too-many-inouts:
24278     (write-buffered *(ebp+0x10) "fn ")
24279     8b/-> *(ebp+0xc) 0/r32/eax
24280     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24281     (write-buffered *(ebp+0x10) %eax)
24282     (write-buffered *(ebp+0x10) ": stmt index: too many inouts (2 required)\n")
24283     (flush *(ebp+0x10))
24284     (stop *(ebp+0x14) 1)
24285     # never gets here
24286 
24287 $check-mu-index-stmt:error-too-few-outputs:
24288     (write-buffered *(ebp+0x10) "fn ")
24289     8b/-> *(ebp+0xc) 0/r32/eax
24290     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24291     (write-buffered *(ebp+0x10) %eax)
24292     (write-buffered *(ebp+0x10) ": stmt index: must have an output\n")
24293     (flush *(ebp+0x10))
24294     (stop *(ebp+0x14) 1)
24295     # never gets here
24296 
24297 $check-mu-index-stmt:error-too-many-outputs:
24298     (write-buffered *(ebp+0x10) "fn ")
24299     8b/-> *(ebp+0xc) 0/r32/eax
24300     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24301     (write-buffered *(ebp+0x10) %eax)
24302     (write-buffered *(ebp+0x10) ": stmt index: too many outputs (1 required)\n")
24303     (flush *(ebp+0x10))
24304     (stop *(ebp+0x14) 1)
24305     # never gets here
24306 
24307 $check-mu-index-stmt:error-output-not-in-register:
24308     (write-buffered *(ebp+0x10) "fn ")
24309     8b/-> *(ebp+0xc) 0/r32/eax
24310     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24311     (write-buffered *(ebp+0x10) %eax)
24312     (write-buffered *(ebp+0x10) ": stmt index: output '")
24313     (lookup *edi *(edi+4))  # Var-name Var-name => eax
24314     (write-buffered *(ebp+0x10) %eax)
24315     (write-buffered *(ebp+0x10) "' is not in a register\n")
24316     (flush *(ebp+0x10))
24317     (stop *(ebp+0x14) 1)
24318     # never gets here
24319 
24320 $check-mu-index-stmt:error-output-type-not-address:
24321     (write-buffered *(ebp+0x10) "fn ")
24322     8b/-> *(ebp+0xc) 0/r32/eax
24323     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24324     (write-buffered *(ebp+0x10) %eax)
24325     (write-buffered *(ebp+0x10) ": stmt index: output '")
24326     (lookup *edi *(edi+4))  # Var-name Var-name => eax
24327     (write-buffered *(ebp+0x10) %eax)
24328     (write-buffered *(ebp+0x10) "' must be an addr\n")
24329     (flush *(ebp+0x10))
24330     (stop *(ebp+0x14) 1)
24331     # never gets here
24332 
24333 $check-mu-index-stmt:error-bad-output-type:
24334     (write-buffered *(ebp+0x10) "fn ")
24335     8b/-> *(ebp+0xc) 0/r32/eax
24336     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24337     (write-buffered *(ebp+0x10) %eax)
24338     (write-buffered *(ebp+0x10) ": stmt index: output '")
24339     (lookup *edi *(edi+4))  # Var-name Var-name => eax
24340     (write-buffered *(ebp+0x10) %eax)
24341     (write-buffered *(ebp+0x10) "' does not have the right type\n")
24342     (flush *(ebp+0x10))
24343     (stop *(ebp+0x14) 1)
24344     # never gets here
24345 
24346 check-mu-length-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
24347     # . prologue
24348     55/push-ebp
24349     89/<- %ebp 4/r32/esp
24350     # . save registers
24351     50/push-eax
24352     51/push-ecx
24353     52/push-edx
24354     53/push-ebx
24355     56/push-esi
24356     57/push-edi
24357     # esi = stmt
24358     8b/-> *(ebp+8) 6/r32/esi
24359     # - check for 0 inouts
24360     # var base/ecx: (addr var) = stmt->inouts->value
24361     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24362 $check-mu-length-stmt:check-no-inouts:
24363     3d/compare-eax-and 0/imm32
24364     0f 84/jump-if-= $check-mu-length-stmt:error-too-few-inouts/disp32
24365     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24366     89/<- %ecx 0/r32/eax
24367     # - check base type is either (addr array ...) in register or (array ...) on stack
24368     # var base-type/ebx: (addr type-tree) = lookup(base->type)
24369     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
24370     89/<- %ebx 0/r32/eax
24371     # if base-type is an atom, abort with a precise error
24372     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
24373     {
24374       74/jump-if-= break/disp8
24375       (simple-mu-type? %ebx 3)  # array => eax
24376       3d/compare-eax-and 0/imm32/false
24377       0f 85/jump-if-!= $check-mu-length-stmt:error-base-array-atom-type/disp32
24378       0f 84/jump-if-= $check-mu-length-stmt:error-base-non-array-type/disp32
24379     }
24380 $check-mu-length-stmt:base-is-compound:
24381     # if type->left not addr or array, abort
24382     {
24383       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24384       (simple-mu-type? %eax 2)  # addr => eax
24385       3d/compare-eax-and 0/imm32/false
24386       75/jump-if-!= break/disp8
24387       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24388       (simple-mu-type? %eax 3)  # array => eax
24389       3d/compare-eax-and 0/imm32/false
24390       75/jump-if-!= break/disp8
24391       e9/jump $check-mu-length-stmt:error-base-non-array-type/disp32
24392     }
24393     # if (type->left == addr) ensure type->right->left == array and type->register exists
24394     {
24395       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24396       (simple-mu-type? %eax 2)  # addr => eax
24397       3d/compare-eax-and 0/imm32/false
24398       74/jump-if-= break/disp8
24399 $check-mu-length-stmt:base-is-addr:
24400       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
24401       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
24402       (simple-mu-type? %eax 3)  # array => eax
24403       3d/compare-eax-and 0/imm32/false
24404       0f 84/jump-if-= $check-mu-length-stmt:error-base-non-array-type/disp32
24405 $check-mu-length-stmt:check-base-addr-is-register:
24406       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
24407       0f 84/jump-if-= $check-mu-length-stmt:error-base-address-array-type-on-stack/disp32
24408     }
24409     # if (type->left == array) ensure type->register doesn't exist
24410     {
24411       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24412       (simple-mu-type? %eax 3)  # array => eax
24413       3d/compare-eax-and 0/imm32/false
24414       74/jump-if-= break/disp8
24415 $check-mu-length-stmt:base-is-array:
24416       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
24417       0f 85/jump-if-!= $check-mu-length-stmt:error-base-array-type-in-register/disp32
24418     }
24419     # if (base-type->left == addr) base-type = base-type->right
24420     {
24421       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24422       (simple-mu-type? %eax 2)  # addr => eax
24423       3d/compare-eax-and 0/imm32/false
24424       74/jump-if-= break/disp8
24425       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
24426       89/<- %ebx 0/r32/eax
24427     }
24428     # - check for too many inouts
24429     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24430     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24431     3d/compare-eax-and 0/imm32/false
24432     0f 85/jump-if-!= $check-mu-length-stmt:error-too-many-inouts/disp32
24433     # - check for 0 outputs
24434     # var output/edi: (addr var) = stmt->outputs->value
24435     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24436     3d/compare-eax-and 0/imm32/false
24437     0f 84/jump-if-= $check-mu-length-stmt:error-too-few-outputs/disp32
24438     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24439     89/<- %edi 0/r32/eax
24440     # - check output type
24441     # must have a non-atomic type
24442     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
24443     (simple-mu-type? %eax 1)  # int => eax
24444     3d/compare-eax-and 0/imm32/false
24445     0f 84/jump-if-= $check-mu-length-stmt:error-invalid-output-type/disp32
24446     # - check for too many outputs
24447     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24448     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24449     3d/compare-eax-and 0/imm32/false
24450     0f 85/jump-if-!= $check-mu-length-stmt:error-too-many-outputs/disp32
24451 $check-mu-length-stmt:end:
24452     # . restore registers
24453     5f/pop-to-edi
24454     5e/pop-to-esi
24455     5b/pop-to-ebx
24456     5a/pop-to-edx
24457     59/pop-to-ecx
24458     58/pop-to-eax
24459     # . epilogue
24460     89/<- %esp 5/r32/ebp
24461     5d/pop-to-ebp
24462     c3/return
24463 
24464 $check-mu-length-stmt:error-base-non-array-type:
24465     (write-buffered *(ebp+0x10) "fn ")
24466     8b/-> *(ebp+0xc) 0/r32/eax
24467     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24468     (write-buffered *(ebp+0x10) %eax)
24469     (write-buffered *(ebp+0x10) ": stmt length: var '")
24470     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24471     (write-buffered *(ebp+0x10) %eax)
24472     (write-buffered *(ebp+0x10) "' is not an array\n")
24473     (flush *(ebp+0x10))
24474     (stop *(ebp+0x14) 1)
24475     # never gets here
24476 
24477 $check-mu-length-stmt:error-base-array-atom-type:
24478     (write-buffered *(ebp+0x10) "fn ")
24479     8b/-> *(ebp+0xc) 0/r32/eax
24480     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24481     (write-buffered *(ebp+0x10) %eax)
24482     (write-buffered *(ebp+0x10) ": stmt length: array '")
24483     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24484     (write-buffered *(ebp+0x10) %eax)
24485     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
24486     (flush *(ebp+0x10))
24487     (stop *(ebp+0x14) 1)
24488     # never gets here
24489 
24490 $check-mu-length-stmt:error-base-address-array-type-on-stack:
24491     (write-buffered *(ebp+0x10) "fn ")
24492     8b/-> *(ebp+0xc) 0/r32/eax
24493     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24494     (write-buffered *(ebp+0x10) %eax)
24495     (write-buffered *(ebp+0x10) ": stmt length: var '")
24496     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24497     (write-buffered *(ebp+0x10) %eax)
24498     (write-buffered *(ebp+0x10) "' is an addr to an array, and so must live in a register\n")
24499     (flush *(ebp+0x10))
24500     (stop *(ebp+0x14) 1)
24501     # never gets here
24502 
24503 $check-mu-length-stmt:error-base-array-type-in-register:
24504     (write-buffered *(ebp+0x10) "fn ")
24505     8b/-> *(ebp+0xc) 0/r32/eax
24506     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24507     (write-buffered *(ebp+0x10) %eax)
24508     (write-buffered *(ebp+0x10) ": stmt length: var '")
24509     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24510     (write-buffered *(ebp+0x10) %eax)
24511     (write-buffered *(ebp+0x10) "' is an array, and so must live on the stack\n")
24512     (flush *(ebp+0x10))
24513     (stop *(ebp+0x14) 1)
24514     # never gets here
24515 
24516 $check-mu-length-stmt:error-too-few-inouts:
24517     (write-buffered *(ebp+0x10) "fn ")
24518     8b/-> *(ebp+0xc) 0/r32/eax
24519     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24520     (write-buffered *(ebp+0x10) %eax)
24521     (write-buffered *(ebp+0x10) ": stmt length: too few inouts (1 required)\n")
24522     (flush *(ebp+0x10))
24523     (stop *(ebp+0x14) 1)
24524     # never gets here
24525 
24526 $check-mu-length-stmt:error-invalid-index-type:
24527     (write-buffered *(ebp+0x10) "fn ")
24528     8b/-> *(ebp+0xc) 0/r32/eax
24529     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24530     (write-buffered *(ebp+0x10) %eax)
24531     (write-buffered *(ebp+0x10) ": stmt length: second argument '")
24532     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24533     (write-buffered *(ebp+0x10) %eax)
24534     (write-buffered *(ebp+0x10) "' must be an int or offset\n")
24535     (flush *(ebp+0x10))
24536     (stop *(ebp+0x14) 1)
24537     # never gets here
24538 
24539 $check-mu-length-stmt:error-index-offset-atom-type:
24540     (write-buffered *(ebp+0x10) "fn ")
24541     8b/-> *(ebp+0xc) 0/r32/eax
24542     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24543     (write-buffered *(ebp+0x10) %eax)
24544     (write-buffered *(ebp+0x10) ": stmt length: offset '")
24545     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24546     (write-buffered *(ebp+0x10) %eax)
24547     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
24548     (flush *(ebp+0x10))
24549     (stop *(ebp+0x14) 1)
24550     # never gets here
24551 
24552 $check-mu-length-stmt:error-index-on-stack:
24553     (write-buffered *(ebp+0x10) "fn ")
24554     8b/-> *(ebp+0xc) 0/r32/eax
24555     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24556     (write-buffered *(ebp+0x10) %eax)
24557     (write-buffered *(ebp+0x10) ": stmt length: second argument '")
24558     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24559     (write-buffered *(ebp+0x10) %eax)
24560     (write-buffered *(ebp+0x10) "' must be in a register\n")
24561     (flush *(ebp+0x10))
24562     (stop *(ebp+0x14) 1)
24563     # never gets here
24564 
24565 $check-mu-length-stmt:error-index-needs-offset:
24566     (write-buffered *(ebp+0x10) "fn ")
24567     8b/-> *(ebp+0xc) 0/r32/eax
24568     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24569     (write-buffered *(ebp+0x10) %eax)
24570     (write-buffered *(ebp+0x10) ": stmt length: cannot take an int for array '")
24571     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24572     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24573     (lookup *eax *(eax+4))  # Var-name Var-name => eax
24574     (write-buffered *(ebp+0x10) %eax)
24575     (write-buffered *(ebp+0x10) "'; create an offset instead. See mu.md for details.\n")
24576     (flush *(ebp+0x10))
24577     (stop *(ebp+0x14) 1)
24578     # never gets here
24579 
24580 $check-mu-length-stmt:error-too-many-inouts:
24581     (write-buffered *(ebp+0x10) "fn ")
24582     8b/-> *(ebp+0xc) 0/r32/eax
24583     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24584     (write-buffered *(ebp+0x10) %eax)
24585     (write-buffered *(ebp+0x10) ": stmt length: too many inouts (1 required)\n")
24586     (flush *(ebp+0x10))
24587     (stop *(ebp+0x14) 1)
24588     # never gets here
24589 
24590 $check-mu-length-stmt:error-too-few-outputs:
24591     (write-buffered *(ebp+0x10) "fn ")
24592     8b/-> *(ebp+0xc) 0/r32/eax
24593     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24594     (write-buffered *(ebp+0x10) %eax)
24595     (write-buffered *(ebp+0x10) ": stmt length: must have an output\n")
24596     (flush *(ebp+0x10))
24597     (stop *(ebp+0x14) 1)
24598     # never gets here
24599 
24600 $check-mu-length-stmt:error-too-many-outputs:
24601     (write-buffered *(ebp+0x10) "fn ")
24602     8b/-> *(ebp+0xc) 0/r32/eax
24603     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24604     (write-buffered *(ebp+0x10) %eax)
24605     (write-buffered *(ebp+0x10) ": stmt length: too many outputs (1 required)\n")
24606     (flush *(ebp+0x10))
24607     (stop *(ebp+0x14) 1)
24608     # never gets here
24609 
24610 $check-mu-length-stmt:error-output-not-in-register:
24611     (write-buffered *(ebp+0x10) "fn ")
24612     8b/-> *(ebp+0xc) 0/r32/eax
24613     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24614     (write-buffered *(ebp+0x10) %eax)
24615     (write-buffered *(ebp+0x10) ": stmt length: output '")
24616     (lookup *edi *(edi+4))  # Var-name Var-name => eax
24617     (write-buffered *(ebp+0x10) %eax)
24618     (write-buffered *(ebp+0x10) "' is not in a register\n")
24619     (flush *(ebp+0x10))
24620     (stop *(ebp+0x14) 1)
24621     # never gets here
24622 
24623 $check-mu-length-stmt:error-invalid-output-type:
24624     (write-buffered *(ebp+0x10) "fn ")
24625     8b/-> *(ebp+0xc) 0/r32/eax
24626     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24627     (write-buffered *(ebp+0x10) %eax)
24628     (write-buffered *(ebp+0x10) ": stmt length: output '")
24629     (lookup *edi *(edi+4))  # Var-name Var-name => eax
24630     (write-buffered *(ebp+0x10) %eax)
24631     (write-buffered *(ebp+0x10) "' does not have the right type\n")
24632     (flush *(ebp+0x10))
24633     (stop *(ebp+0x14) 1)
24634     # never gets here
24635 
24636 check-mu-compute-offset-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
24637     # . prologue
24638     55/push-ebp
24639     89/<- %ebp 4/r32/esp
24640     # . save registers
24641     50/push-eax
24642     51/push-ecx
24643     52/push-edx
24644     53/push-ebx
24645     56/push-esi
24646     57/push-edi
24647     # esi = stmt
24648     8b/-> *(ebp+8) 6/r32/esi
24649     # - check for 0 inouts
24650     # var base/ecx: (addr var) = stmt->inouts->value
24651     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24652 $check-mu-compute-offset-stmt:check-no-inouts:
24653     3d/compare-eax-and 0/imm32
24654     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-inouts/disp32
24655     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24656     89/<- %ecx 0/r32/eax
24657     # - check base type is either (addr array ...) in register or (array ...) on stack
24658     # var base-type/ebx: (addr type-tree) = lookup(base->type)
24659     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
24660     89/<- %ebx 0/r32/eax
24661     # if base-type is an atom, abort with a precise error
24662     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
24663     {
24664       74/jump-if-= break/disp8
24665       (simple-mu-type? %ebx 3)  # array => eax
24666       3d/compare-eax-and 0/imm32/false
24667       0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-base-array-atom-type/disp32
24668       0f 84/jump-if-= $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
24669     }
24670 $check-mu-compute-offset-stmt:base-is-compound:
24671     # if type->left not addr or array, abort
24672     {
24673       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24674       (simple-mu-type? %eax 2)  # addr => eax
24675       3d/compare-eax-and 0/imm32/false
24676       75/jump-if-!= break/disp8
24677       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24678       (simple-mu-type? %eax 3)  # array => eax
24679       3d/compare-eax-and 0/imm32/false
24680       75/jump-if-!= break/disp8
24681       e9/jump $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
24682     }
24683     # if (type->left == addr) ensure type->right->left == array and type->register exists
24684     {
24685       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24686       (simple-mu-type? %eax 2)  # addr => eax
24687       3d/compare-eax-and 0/imm32/false
24688       74/jump-if-= break/disp8
24689 $check-mu-compute-offset-stmt:base-is-addr:
24690       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
24691       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
24692       (simple-mu-type? %eax 3)  # array => eax
24693       3d/compare-eax-and 0/imm32/false
24694       0f 84/jump-if-= $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
24695     }
24696     # if (base-type->left == addr) base-type = base-type->right
24697     {
24698       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24699       (simple-mu-type? %eax 2)  # addr => eax
24700       3d/compare-eax-and 0/imm32/false
24701       74/jump-if-= break/disp8
24702       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
24703       89/<- %ebx 0/r32/eax
24704     }
24705     # - check for 1 inout
24706     # var index/ecx: (addr stmt-var) = stmt->inouts->next->value
24707     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24708     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24709 $check-mu-compute-offset-stmt:check-single-inout:
24710     3d/compare-eax-and 0/imm32
24711     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-inouts/disp32
24712     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24713     89/<- %ecx 0/r32/eax
24714     # - check index is either a literal or register
24715     # var index-type/edx: (addr type-tree)
24716     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
24717     89/<- %edx 0/r32/eax
24718     # index type must be a literal or int
24719     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
24720     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-invalid-index-type/disp32
24721     {
24722 $check-mu-compute-offset-stmt:index-type-is-atom:
24723       (simple-mu-type? %edx 0)  # literal => eax
24724       3d/compare-eax-and 0/imm32/false
24725       75/jump-if-!= break/disp8
24726       (simple-mu-type? %edx 1)  # int => eax
24727       3d/compare-eax-and 0/imm32/false
24728       75/jump-if-!= break/disp8
24729       e9/jump $check-mu-compute-offset-stmt:error-invalid-index-type/disp32
24730     }
24731     # - check for too many inouts
24732     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24733     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24734     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24735     3d/compare-eax-and 0/imm32/false
24736     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-too-many-inouts/disp32
24737     # - check for 0 outputs
24738     # var output/edi: (addr var) = stmt->outputs->value
24739     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24740     3d/compare-eax-and 0/imm32/false
24741     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-outputs/disp32
24742     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24743     89/<- %edi 0/r32/eax
24744     # - check output type
24745     # must have a non-atomic type
24746     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
24747     89/<- %edx 0/r32/eax
24748     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
24749     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-output-type-not-offset/disp32
24750     # type must start with (offset ...)
24751     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
24752     (simple-mu-type? %eax 7)  # offset => eax
24753     3d/compare-eax-and 0/imm32/false
24754     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-output-type-not-offset/disp32
24755     # if tail(base-type) != tail(output-type) abort
24756     (type-tail %ebx)  # => eax
24757     89/<- %ebx 0/r32/eax
24758     (type-tail %edx)  # => eax
24759     (type-equal? %ebx %eax)  # => eax
24760     3d/compare-eax-and 0/imm32/false
24761     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-bad-output-type/disp32
24762     # - check for too many outputs
24763     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24764     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24765     3d/compare-eax-and 0/imm32/false
24766     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-too-many-outputs/disp32
24767 $check-mu-compute-offset-stmt:end:
24768     # . restore registers
24769     5f/pop-to-edi
24770     5e/pop-to-esi
24771     5b/pop-to-ebx
24772     5a/pop-to-edx
24773     59/pop-to-ecx
24774     58/pop-to-eax
24775     # . epilogue
24776     89/<- %esp 5/r32/ebp
24777     5d/pop-to-ebp
24778     c3/return
24779 
24780 $check-mu-compute-offset-stmt:error-base-non-array-type:
24781     (write-buffered *(ebp+0x10) "fn ")
24782     8b/-> *(ebp+0xc) 0/r32/eax
24783     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24784     (write-buffered *(ebp+0x10) %eax)
24785     (write-buffered *(ebp+0x10) ": stmt compute-offset: var '")
24786     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24787     (write-buffered *(ebp+0x10) %eax)
24788     (write-buffered *(ebp+0x10) "' is not an array\n")
24789     (flush *(ebp+0x10))
24790     (stop *(ebp+0x14) 1)
24791     # never gets here
24792 
24793 $check-mu-compute-offset-stmt:error-base-array-atom-type:
24794     (write-buffered *(ebp+0x10) "fn ")
24795     8b/-> *(ebp+0xc) 0/r32/eax
24796     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24797     (write-buffered *(ebp+0x10) %eax)
24798     (write-buffered *(ebp+0x10) ": stmt compute-offset: array '")
24799     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24800     (write-buffered *(ebp+0x10) %eax)
24801     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
24802     (flush *(ebp+0x10))
24803     (stop *(ebp+0x14) 1)
24804     # never gets here
24805 
24806 $check-mu-compute-offset-stmt:error-too-few-inouts:
24807     (write-buffered *(ebp+0x10) "fn ")
24808     8b/-> *(ebp+0xc) 0/r32/eax
24809     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24810     (write-buffered *(ebp+0x10) %eax)
24811     (write-buffered *(ebp+0x10) ": stmt compute-offset: too few inouts (2 required)\n")
24812     (flush *(ebp+0x10))
24813     (stop *(ebp+0x14) 1)
24814     # never gets here
24815 
24816 $check-mu-compute-offset-stmt:error-invalid-index-type:
24817     (write-buffered *(ebp+0x10) "fn ")
24818     8b/-> *(ebp+0xc) 0/r32/eax
24819     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24820     (write-buffered *(ebp+0x10) %eax)
24821     (write-buffered *(ebp+0x10) ": stmt compute-offset: second argument '")
24822     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24823     (write-buffered *(ebp+0x10) %eax)
24824     (write-buffered *(ebp+0x10) "' must be an int\n")
24825     (flush *(ebp+0x10))
24826     (stop *(ebp+0x14) 1)
24827     # never gets here
24828 
24829 $check-mu-compute-offset-stmt:error-index-offset-atom-type:
24830     (write-buffered *(ebp+0x10) "fn ")
24831     8b/-> *(ebp+0xc) 0/r32/eax
24832     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24833     (write-buffered *(ebp+0x10) %eax)
24834     (write-buffered *(ebp+0x10) ": stmt compute-offset: offset '")
24835     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24836     (write-buffered *(ebp+0x10) %eax)
24837     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
24838     (flush *(ebp+0x10))
24839     (stop *(ebp+0x14) 1)
24840     # never gets here
24841 
24842 $check-mu-compute-offset-stmt:error-index-on-stack:
24843     (write-buffered *(ebp+0x10) "fn ")
24844     8b/-> *(ebp+0xc) 0/r32/eax
24845     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24846     (write-buffered *(ebp+0x10) %eax)
24847     (write-buffered *(ebp+0x10) ": stmt compute-offset: second argument '")
24848     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24849     (write-buffered *(ebp+0x10) %eax)
24850     (write-buffered *(ebp+0x10) "' must be in a register\n")
24851     (flush *(ebp+0x10))
24852     (stop *(ebp+0x14) 1)
24853     # never gets here
24854 
24855 $check-mu-compute-offset-stmt:error-too-many-inouts:
24856     (write-buffered *(ebp+0x10) "fn ")
24857     8b/-> *(ebp+0xc) 0/r32/eax
24858     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24859     (write-buffered *(ebp+0x10) %eax)
24860     (write-buffered *(ebp+0x10) ": stmt compute-offset: too many inouts (2 required)\n")
24861     (flush *(ebp+0x10))
24862     (stop *(ebp+0x14) 1)
24863     # never gets here
24864 
24865 $check-mu-compute-offset-stmt:error-too-few-outputs:
24866     (write-buffered *(ebp+0x10) "fn ")
24867     8b/-> *(ebp+0xc) 0/r32/eax
24868     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24869     (write-buffered *(ebp+0x10) %eax)
24870     (write-buffered *(ebp+0x10) ": stmt compute-offset: must have an output\n")
24871     (flush *(ebp+0x10))
24872     (stop *(ebp+0x14) 1)
24873     # never gets here
24874 
24875 $check-mu-compute-offset-stmt:error-too-many-outputs:
24876     (write-buffered *(ebp+0x10) "fn ")
24877     8b/-> *(ebp+0xc) 0/r32/eax
24878     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24879     (write-buffered *(ebp+0x10) %eax)
24880     (write-buffered *(ebp+0x10) ": stmt compute-offset: too many outputs (1 required)\n")
24881     (flush *(ebp+0x10))
24882     (stop *(ebp+0x14) 1)
24883     # never gets here
24884 
24885 $check-mu-compute-offset-stmt:error-output-not-in-register:
24886     (write-buffered *(ebp+0x10) "fn ")
24887     8b/-> *(ebp+0xc) 0/r32/eax
24888     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24889     (write-buffered *(ebp+0x10) %eax)
24890     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
24891     (lookup *edi *(edi+4))  # Var-name Var-name => eax
24892     (write-buffered *(ebp+0x10) %eax)
24893     (write-buffered *(ebp+0x10) "' is not in a register\n")
24894     (flush *(ebp+0x10))
24895     (stop *(ebp+0x14) 1)
24896     # never gets here
24897 
24898 $check-mu-compute-offset-stmt:error-output-type-not-offset:
24899     (write-buffered *(ebp+0x10) "fn ")
24900     8b/-> *(ebp+0xc) 0/r32/eax
24901     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24902     (write-buffered *(ebp+0x10) %eax)
24903     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
24904     (lookup *edi *(edi+4))  # Var-name Var-name => eax
24905     (write-buffered *(ebp+0x10) %eax)
24906     (write-buffered *(ebp+0x10) "' must be an offset\n")
24907     (flush *(ebp+0x10))
24908     (stop *(ebp+0x14) 1)
24909     # never gets here
24910 
24911 $check-mu-compute-offset-stmt:error-bad-output-type:
24912     (write-buffered *(ebp+0x10) "fn ")
24913     8b/-> *(ebp+0xc) 0/r32/eax
24914     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24915     (write-buffered *(ebp+0x10) %eax)
24916     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
24917     (lookup *edi *(edi+4))  # Var-name Var-name => eax
24918     (write-buffered *(ebp+0x10) %eax)
24919     (write-buffered *(ebp+0x10) "' does not have the right type\n")
24920     (flush *(ebp+0x10))
24921     (stop *(ebp+0x14) 1)
24922     # never gets here
24923 
24924 check-mu-copy-object-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
24925     # . prologue
24926     55/push-ebp
24927     89/<- %ebp 4/r32/esp
24928     # . save registers
24929     50/push-eax
24930     51/push-ecx
24931     53/push-ebx
24932     56/push-esi
24933     57/push-edi
24934     # esi = stmt
24935     8b/-> *(ebp+8) 6/r32/esi
24936 $check-mu-copy-object-stmt:check-for-output:
24937     # if stmt->outputs abort
24938     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24939     3d/compare-eax-and 0/imm32
24940     0f 85/jump-if-!= $check-mu-copy-object-stmt:error-too-many-outputs/disp32
24941 $check-mu-copy-object-stmt:get-left:
24942     # var dest/edi: (addr stmt-var) = stmt->inouts
24943     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24944     89/<- %edi 0/r32/eax
24945     # zero inouts
24946     3d/compare-eax-and 0/imm32
24947     0f 84/jump-if-= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
24948 $check-mu-copy-object-stmt:get-src:
24949     # var src/esi: (addr stmt-var) = dest->next
24950     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
24951     89/<- %esi 0/r32/eax
24952     # 1 inout
24953     3d/compare-eax-and 0/imm32
24954     0f 84/jump-if-= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
24955     # > 2 inouts
24956     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
24957     3d/compare-eax-and 0/imm32
24958     0f 85/jump-if-!= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
24959 $check-mu-copy-object-stmt:types:
24960     # var src-type/ecx: (addr type-tree) = src->value->type
24961     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
24962     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
24963     89/<- %ecx 0/r32/eax
24964     # if (src->is-deref?) src-type = src-type->payload
24965     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
24966     3d/compare-eax-and 0/imm32/false
24967     {
24968       74/jump-if-= break/disp8
24969       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
24970       # if src-type->right is null, src-type = src-type->left
24971       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
24972       {
24973         75/jump-if-!= break/disp8
24974         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
24975       }
24976       89/<- %ecx 0/r32/eax
24977     }
24978     # if src-type is not addr, abort
24979     (mu-addr-type? %ecx)  # => eax
24980     3d/compare-eax-and 0/imm32/false
24981     0f 84/jump-if-= $check-mu-copy-object-stmt:error-invalid-types/disp32
24982     # var dest-type/ebx: (addr type-tree) = dest->value->type
24983     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
24984     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
24985     89/<- %ebx 0/r32/eax
24986     # if (dest->is-deref?) dest-type = dest-type->payload
24987     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
24988     3d/compare-eax-and 0/imm32/false
24989     {
24990       74/jump-if-= break/disp8
24991       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
24992       # if dest-type->right is null, dest-type = dest-type->left
24993       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
24994       {
24995         75/jump-if-!= break/disp8
24996         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
24997       }
24998       89/<- %ebx 0/r32/eax
24999     }
25000     # if (dest-type != src-type) abort
25001     (type-equal? %ecx %ebx)  # => eax
25002     3d/compare-eax-and 0/imm32
25003     0f 84/jump-if-= $check-mu-copy-object-stmt:error-invalid-types/disp32
25004 $check-mu-copy-object-stmt:end:
25005     # . restore registers
25006     5f/pop-to-edi
25007     5e/pop-to-esi
25008     5b/pop-to-ebx
25009     59/pop-to-ecx
25010     58/pop-to-eax
25011     # . epilogue
25012     89/<- %esp 5/r32/ebp
25013     5d/pop-to-ebp
25014     c3/return
25015 
25016 $check-mu-copy-object-stmt:error-incorrect-inouts:
25017     (write-buffered *(ebp+0x10) "fn ")
25018     8b/-> *(ebp+0xc) 0/r32/eax
25019     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25020     (write-buffered *(ebp+0x10) %eax)
25021     (write-buffered *(ebp+0x10) ": stmt 'copy-object' must have two inouts\n")
25022     (flush *(ebp+0x10))
25023     (stop *(ebp+0x14) 1)
25024     # never gets here
25025 
25026 $check-mu-copy-object-stmt:error-too-many-outputs:
25027     (write-buffered *(ebp+0x10) "fn ")
25028     8b/-> *(ebp+0xc) 0/r32/eax
25029     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25030     (write-buffered *(ebp+0x10) %eax)
25031     (write-buffered *(ebp+0x10) ": stmt 'copy-object' must not have any outputs\n")
25032     (flush *(ebp+0x10))
25033     (stop *(ebp+0x14) 1)
25034     # never gets here
25035 
25036 $check-mu-copy-object-stmt:error-invalid-types:
25037     (write-buffered *(ebp+0x10) "fn ")
25038     8b/-> *(ebp+0xc) 0/r32/eax
25039     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25040     (write-buffered *(ebp+0x10) %eax)
25041     (write-buffered *(ebp+0x10) ": stmt copy-object: two inouts with identical addr types expected\n")
25042     (flush *(ebp+0x10))
25043     (stop *(ebp+0x14) 1)
25044     # never gets here
25045 
25046 check-mu-clear-object-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
25047     # . prologue
25048     55/push-ebp
25049     89/<- %ebp 4/r32/esp
25050     # . save registers
25051     50/push-eax
25052     51/push-ecx
25053     53/push-ebx
25054     56/push-esi
25055     57/push-edi
25056     # esi = stmt
25057     8b/-> *(ebp+8) 6/r32/esi
25058 $check-mu-clear-object-stmt:check-for-output:
25059     # if stmt->outputs abort
25060     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
25061     3d/compare-eax-and 0/imm32
25062     0f 85/jump-if-!= $check-mu-clear-object-stmt:error-too-many-outputs/disp32
25063 $check-mu-clear-object-stmt:get-left:
25064     # var dest/edi: (addr stmt-var) = stmt->inouts
25065     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25066     89/<- %edi 0/r32/eax
25067     # zero inouts
25068     3d/compare-eax-and 0/imm32
25069     0f 84/jump-if-= $check-mu-clear-object-stmt:error-incorrect-inouts/disp32
25070 $check-mu-clear-object-stmt:get-src:
25071     # > 1 inout
25072     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
25073     3d/compare-eax-and 0/imm32
25074     0f 85/jump-if-!= $check-mu-clear-object-stmt:error-incorrect-inouts/disp32
25075 $check-mu-clear-object-stmt:types:
25076     # var src-type/ecx: (addr type-tree) = src->value->type
25077     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25078     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25079     89/<- %ecx 0/r32/eax
25080     # if (src->is-deref?) src-type = src-type->payload
25081     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
25082     3d/compare-eax-and 0/imm32/false
25083     {
25084       74/jump-if-= break/disp8
25085       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
25086       # if src-type->right is null, src-type = src-type->left
25087       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
25088       {
25089         75/jump-if-!= break/disp8
25090         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25091       }
25092       89/<- %ecx 0/r32/eax
25093     }
25094     # if src-type is not addr, abort
25095     (mu-addr-type? %ecx)  # => eax
25096     3d/compare-eax-and 0/imm32/false
25097     0f 84/jump-if-= $check-mu-clear-object-stmt:error-invalid-type/disp32
25098 $check-mu-clear-object-stmt:end:
25099     # . restore registers
25100     5f/pop-to-edi
25101     5e/pop-to-esi
25102     5b/pop-to-ebx
25103     59/pop-to-ecx
25104     58/pop-to-eax
25105     # . epilogue
25106     89/<- %esp 5/r32/ebp
25107     5d/pop-to-ebp
25108     c3/return
25109 
25110 $check-mu-clear-object-stmt:error-incorrect-inouts:
25111     (write-buffered *(ebp+0x10) "fn ")
25112     8b/-> *(ebp+0xc) 0/r32/eax
25113     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25114     (write-buffered *(ebp+0x10) %eax)
25115     (write-buffered *(ebp+0x10) ": stmt 'clear-object' must have a single inout\n")
25116     (flush *(ebp+0x10))
25117     (stop *(ebp+0x14) 1)
25118     # never gets here
25119 
25120 $check-mu-clear-object-stmt:error-too-many-outputs:
25121     (write-buffered *(ebp+0x10) "fn ")
25122     8b/-> *(ebp+0xc) 0/r32/eax
25123     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25124     (write-buffered *(ebp+0x10) %eax)
25125     (write-buffered *(ebp+0x10) ": stmt 'clear-object' must not have any outputs\n")
25126     (flush *(ebp+0x10))
25127     (stop *(ebp+0x14) 1)
25128     # never gets here
25129 
25130 $check-mu-clear-object-stmt:error-invalid-type:
25131     (write-buffered *(ebp+0x10) "fn ")
25132     8b/-> *(ebp+0xc) 0/r32/eax
25133     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25134     (write-buffered *(ebp+0x10) %eax)
25135     (write-buffered *(ebp+0x10) ": stmt clear-object: inout must have an addr type\n")
25136     (flush *(ebp+0x10))
25137     (stop *(ebp+0x14) 1)
25138     # never gets here
25139 
25140 check-mu-allocate-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
25141     # . prologue
25142     55/push-ebp
25143     89/<- %ebp 4/r32/esp
25144     # . save registers
25145     50/push-eax
25146     53/push-ebx
25147     56/push-esi
25148     57/push-edi
25149     # esi = stmt
25150     8b/-> *(ebp+8) 6/r32/esi
25151 $check-mu-allocate-stmt:check-for-output:
25152     # if stmt->outputs abort
25153     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
25154     3d/compare-eax-and 0/imm32
25155     0f 85/jump-if-!= $check-mu-allocate-stmt:error-too-many-outputs/disp32
25156 $check-mu-allocate-stmt:get-target:
25157     # var target/edi: (addr stmt-var) = stmt->inouts
25158     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25159     89/<- %edi 0/r32/eax
25160     # zero inouts
25161     3d/compare-eax-and 0/imm32
25162     0f 84/jump-if-= $check-mu-allocate-stmt:error-incorrect-inouts/disp32
25163     # > 1 inouts
25164     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
25165     3d/compare-eax-and 0/imm32
25166     0f 85/jump-if-!= $check-mu-allocate-stmt:error-incorrect-inouts/disp32
25167 $check-mu-allocate-stmt:check-type:
25168     # var target-type/ebx: (addr type-tree) = target->value->type
25169     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25170     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25171     89/<- %ebx 0/r32/eax
25172     # if (target->is-deref?) target-type = target-type->payload
25173     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
25174     3d/compare-eax-and 0/imm32/false
25175     {
25176       74/jump-if-= break/disp8
25177       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25178       # if target-type->right is null, target-type = target-type->left
25179       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
25180       {
25181         75/jump-if-!= break/disp8
25182         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25183       }
25184       89/<- %ebx 0/r32/eax
25185     }
25186     # if target-type is not addr, abort
25187     (mu-addr-type? %ebx)  # => eax
25188     3d/compare-eax-and 0/imm32/false
25189     0f 84/jump-if-= $check-mu-allocate-stmt:error-invalid-type/disp32
25190     # if target-type->right is an atom, abort
25191     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25192     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
25193     0f 85/jump-if-!= $check-mu-allocate-stmt:error-invalid-type/disp32
25194     # if target-type->right->left is not handle, abort
25195     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25196     (simple-mu-type? %eax 4)  # handle => eax
25197     3d/compare-eax-and 0/imm32/false
25198     0f 84/jump-if-= $check-mu-allocate-stmt:error-invalid-type/disp32
25199 $check-mu-allocate-stmt:end:
25200     # . restore registers
25201     5f/pop-to-edi
25202     5e/pop-to-esi
25203     5b/pop-to-ebx
25204     58/pop-to-eax
25205     # . epilogue
25206     89/<- %esp 5/r32/ebp
25207     5d/pop-to-ebp
25208     c3/return
25209 
25210 $check-mu-allocate-stmt:error-incorrect-inouts:
25211     (write-buffered *(ebp+0x10) "fn ")
25212     8b/-> *(ebp+0xc) 0/r32/eax
25213     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25214     (write-buffered *(ebp+0x10) %eax)
25215     (write-buffered *(ebp+0x10) ": stmt 'allocate' must have a single inout\n")
25216     (flush *(ebp+0x10))
25217     (stop *(ebp+0x14) 1)
25218     # never gets here
25219 
25220 $check-mu-allocate-stmt:error-too-many-outputs:
25221     (write-buffered *(ebp+0x10) "fn ")
25222     8b/-> *(ebp+0xc) 0/r32/eax
25223     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25224     (write-buffered *(ebp+0x10) %eax)
25225     (write-buffered *(ebp+0x10) ": stmt 'allocate' must not have any outputs\n")
25226     (flush *(ebp+0x10))
25227     (stop *(ebp+0x14) 1)
25228     # never gets here
25229 
25230 $check-mu-allocate-stmt:error-invalid-type:
25231     (write-buffered *(ebp+0x10) "fn ")
25232     8b/-> *(ebp+0xc) 0/r32/eax
25233     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25234     (write-buffered *(ebp+0x10) %eax)
25235     (write-buffered *(ebp+0x10) ": stmt allocate: inout '")
25236     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25237     (lookup *eax *(eax+4))  # Var-name Var-name => eax
25238     (write-buffered *(ebp+0x10) %eax)
25239     (write-buffered *(ebp+0x10) "' must have type (addr handle ...)\n")
25240     (flush *(ebp+0x10))
25241     (stop *(ebp+0x14) 1)
25242     # never gets here
25243 
25244 check-mu-populate-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
25245     # . prologue
25246     55/push-ebp
25247     89/<- %ebp 4/r32/esp
25248     # . save registers
25249     50/push-eax
25250     53/push-ebx
25251     56/push-esi
25252     57/push-edi
25253     # esi = stmt
25254     8b/-> *(ebp+8) 6/r32/esi
25255 $check-mu-populate-stmt:check-for-output:
25256     # if stmt->outputs abort
25257     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
25258     3d/compare-eax-and 0/imm32
25259     0f 85/jump-if-!= $check-mu-populate-stmt:error-too-many-outputs/disp32
25260 $check-mu-populate-stmt:get-target:
25261     # var target/edi: (addr stmt-var) = stmt->inouts
25262     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25263     89/<- %edi 0/r32/eax
25264     # zero inouts
25265     3d/compare-eax-and 0/imm32
25266     0f 84/jump-if-= $check-mu-populate-stmt:error-incorrect-inouts/disp32
25267 $check-mu-populate-stmt:get-length:
25268     # var length/esi: (addr stmt-var) = dest->next
25269     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
25270     89/<- %esi 0/r32/eax
25271     # 1 inout
25272     3d/compare-eax-and 0/imm32
25273     0f 84/jump-if-= $check-mu-populate-stmt:error-incorrect-inouts/disp32
25274     # > 2 inouts
25275     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
25276     3d/compare-eax-and 0/imm32
25277     0f 85/jump-if-!= $check-mu-populate-stmt:error-incorrect-inouts/disp32
25278 $check-mu-populate-stmt:check-target-type:
25279     # var target-type/ebx: (addr type-tree) = target->value->type
25280     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25281     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25282     89/<- %ebx 0/r32/eax
25283 $check-mu-populate-stmt:check-target-type-deref:
25284     # if (target->is-deref?) target-type = target-type->payload
25285     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
25286     3d/compare-eax-and 0/imm32/false
25287     {
25288       74/jump-if-= break/disp8
25289       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25290       # if target-type->right is null, target-type = target-type->left
25291       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
25292       {
25293         75/jump-if-!= break/disp8
25294         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25295       }
25296       89/<- %ebx 0/r32/eax
25297     }
25298 $check-mu-populate-stmt:check-target-type-addr:
25299     # if target-type is not addr, abort
25300     (mu-addr-type? %ebx)  # => eax
25301     3d/compare-eax-and 0/imm32/false
25302     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32
25303     # if target-type->right is an atom, abort
25304     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25305     89/<- %ebx 0/r32/eax
25306     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
25307     0f 85/jump-if-!= $check-mu-populate-stmt:error-invalid-target-type/disp32
25308 $check-mu-populate-stmt:check-target-type-handle:
25309     # if target-type->right->left is not handle, abort
25310     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
25311     (simple-mu-type? %eax 4)  # handle => eax
25312     3d/compare-eax-and 0/imm32/false
25313     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32
25314     # if target-type->right->right is an atom, abort
25315     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25316     89/<- %ebx 0/r32/eax
25317     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
25318     0f 85/jump-if-!= $check-mu-populate-stmt:error-invalid-target-type/disp32
25319 $check-mu-populate-stmt:check-target-type-array:
25320     # if target-type->right->right->left is not array, abort
25321     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
25322     (simple-mu-type? %eax 3)  # array => eax
25323     3d/compare-eax-and 0/imm32/false
25324     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32
25325 $check-mu-populate-stmt:check-length-type:
25326     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
25327     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25328     89/<- %ebx 0/r32/eax
25329     (simple-mu-type? %ebx 0)  # literal => eax
25330     3d/compare-eax-and 0/imm32/false
25331     75/jump-if-!= $check-mu-populate-stmt:end/disp8
25332     (simple-mu-type? %ebx 1)  # int => eax
25333     3d/compare-eax-and 0/imm32/false
25334     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-length-type/disp32
25335 $check-mu-populate-stmt:end:
25336     # . restore registers
25337     5f/pop-to-edi
25338     5e/pop-to-esi
25339     5b/pop-to-ebx
25340     58/pop-to-eax
25341     # . epilogue
25342     89/<- %esp 5/r32/ebp
25343     5d/pop-to-ebp
25344     c3/return
25345 
25346 $check-mu-populate-stmt:error-incorrect-inouts:
25347     (write-buffered *(ebp+0x10) "fn ")
25348     8b/-> *(ebp+0xc) 0/r32/eax
25349     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25350     (write-buffered *(ebp+0x10) %eax)
25351     (write-buffered *(ebp+0x10) ": stmt 'populate' must have two inouts\n")
25352     (flush *(ebp+0x10))
25353     (stop *(ebp+0x14) 1)
25354     # never gets here
25355 
25356 $check-mu-populate-stmt:error-too-many-outputs:
25357     (write-buffered *(ebp+0x10) "fn ")
25358     8b/-> *(ebp+0xc) 0/r32/eax
25359     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25360     (write-buffered *(ebp+0x10) %eax)
25361     (write-buffered *(ebp+0x10) ": stmt 'populate' must not have any outputs\n")
25362     (flush *(ebp+0x10))
25363     (stop *(ebp+0x14) 1)
25364     # never gets here
25365 
25366 $check-mu-populate-stmt:error-invalid-target-type:
25367     (write-buffered *(ebp+0x10) "fn ")
25368     8b/-> *(ebp+0xc) 0/r32/eax
25369     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25370     (write-buffered *(ebp+0x10) %eax)
25371     (write-buffered *(ebp+0x10) ": stmt populate: first inout '")
25372     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25373     (lookup *eax *(eax+4))  # Var-name Var-name => eax
25374     (write-buffered *(ebp+0x10) %eax)
25375     (write-buffered *(ebp+0x10) "' must have type (addr handle array ...)\n")
25376     (flush *(ebp+0x10))
25377     (stop *(ebp+0x14) 1)
25378     # never gets here
25379 
25380 $check-mu-populate-stmt:error-invalid-length-type:
25381     (write-buffered *(ebp+0x10) "fn ")
25382     8b/-> *(ebp+0xc) 0/r32/eax
25383     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25384     (write-buffered *(ebp+0x10) %eax)
25385     (write-buffered *(ebp+0x10) ": stmt populate: second inout '")
25386     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
25387     (lookup *eax *(eax+4))  # Var-name Var-name => eax
25388     (write-buffered *(ebp+0x10) %eax)
25389     (write-buffered *(ebp+0x10) "' must be an int\n")
25390     (flush *(ebp+0x10))
25391     (stop *(ebp+0x14) 1)
25392     # never gets here
25393 
25394 check-mu-populate-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
25395     # . prologue
25396     55/push-ebp
25397     89/<- %ebp 4/r32/esp
25398     # . save registers
25399     50/push-eax
25400     53/push-ebx
25401     56/push-esi
25402     57/push-edi
25403     # esi = stmt
25404     8b/-> *(ebp+8) 6/r32/esi
25405 $check-mu-populate-stream-stmt:check-for-output:
25406     # if stmt->outputs abort
25407     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
25408     3d/compare-eax-and 0/imm32
25409     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-too-many-outputs/disp32
25410 $check-mu-populate-stream-stmt:get-target:
25411     # var target/edi: (addr stmt-var) = stmt->inouts
25412     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25413     89/<- %edi 0/r32/eax
25414     # zero inouts
25415     3d/compare-eax-and 0/imm32
25416     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32
25417 $check-mu-populate-stream-stmt:get-length:
25418     # var length/esi: (addr stmt-var) = dest->next
25419     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
25420     89/<- %esi 0/r32/eax
25421     # 1 inout
25422     3d/compare-eax-and 0/imm32
25423     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32
25424     # > 2 inouts
25425     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
25426     3d/compare-eax-and 0/imm32
25427     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32
25428 $check-mu-populate-stream-stmt:check-target-type:
25429     # var target-type/ebx: (addr type-tree) = target->value->type
25430     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25431     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25432     89/<- %ebx 0/r32/eax
25433 $check-mu-populate-stream-stmt:check-target-type-deref:
25434     # if (target->is-deref?) target-type = target-type->payload
25435     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
25436     3d/compare-eax-and 0/imm32/false
25437     {
25438       74/jump-if-= break/disp8
25439       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25440       # if target-type->right is null, target-type = target-type->left
25441       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
25442       {
25443         75/jump-if-!= break/disp8
25444         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25445       }
25446       89/<- %ebx 0/r32/eax
25447     }
25448 $check-mu-populate-stream-stmt:check-target-type-addr:
25449     # if target-type is not addr, abort
25450     (mu-addr-type? %ebx)  # => eax
25451     3d/compare-eax-and 0/imm32/false
25452     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
25453     # if target-type->right is an atom, abort
25454     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25455     89/<- %ebx 0/r32/eax
25456     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
25457     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
25458 $check-mu-populate-stream-stmt:check-target-type-handle:
25459     # if target-type->right->left is not handle, abort
25460     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
25461     (simple-mu-type? %eax 4)  # handle => eax
25462     3d/compare-eax-and 0/imm32/false
25463     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
25464     # if target-type->right->right is an atom, abort
25465     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25466     89/<- %ebx 0/r32/eax
25467     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
25468     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
25469 $check-mu-populate-stream-stmt:check-target-type-stream:
25470     # if target-type->right->right->left is not stream, abort
25471     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
25472     (simple-mu-type? %eax 0xb)  # stream => eax
25473     3d/compare-eax-and 0/imm32/false
25474     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
25475 $check-mu-populate-stream-stmt:check-length-type:
25476     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
25477     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25478     89/<- %ebx 0/r32/eax
25479     (simple-mu-type? %ebx 0)  # literal => eax
25480     3d/compare-eax-and 0/imm32/false
25481     75/jump-if-!= $check-mu-populate-stream-stmt:end/disp8
25482     (simple-mu-type? %ebx 1)  # int => eax
25483     3d/compare-eax-and 0/imm32/false
25484     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-length-type/disp32
25485 $check-mu-populate-stream-stmt:end:
25486     # . restore registers
25487     5f/pop-to-edi
25488     5e/pop-to-esi
25489     5b/pop-to-ebx
25490     58/pop-to-eax
25491     # . epilogue
25492     89/<- %esp 5/r32/ebp
25493     5d/pop-to-ebp
25494     c3/return
25495 
25496 $check-mu-populate-stream-stmt:error-incorrect-inouts:
25497     (write-buffered *(ebp+0x10) "fn ")
25498     8b/-> *(ebp+0xc) 0/r32/eax
25499     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25500     (write-buffered *(ebp+0x10) %eax)
25501     (write-buffered *(ebp+0x10) ": stmt 'populate-stream' must have two inouts\n")
25502     (flush *(ebp+0x10))
25503     (stop *(ebp+0x14) 1)
25504     # never gets here
25505 
25506 $check-mu-populate-stream-stmt:error-too-many-outputs:
25507     (write-buffered *(ebp+0x10) "fn ")
25508     8b/-> *(ebp+0xc) 0/r32/eax
25509     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25510     (write-buffered *(ebp+0x10) %eax)
25511     (write-buffered *(ebp+0x10) ": stmt 'populate-stream' must not have any outputs\n")
25512     (flush *(ebp+0x10))
25513     (stop *(ebp+0x14) 1)
25514     # never gets here
25515 
25516 $check-mu-populate-stream-stmt:error-invalid-target-type:
25517     (write-buffered *(ebp+0x10) "fn ")
25518     8b/-> *(ebp+0xc) 0/r32/eax
25519     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25520     (write-buffered *(ebp+0x10) %eax)
25521     (write-buffered *(ebp+0x10) ": stmt populate-stream: first inout '")
25522     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25523     (lookup *eax *(eax+4))  # Var-name Var-name => eax
25524     (write-buffered *(ebp+0x10) %eax)
25525     (write-buffered *(ebp+0x10) "' must have type (addr handle stream ...)\n")
25526     (flush *(ebp+0x10))
25527     (stop *(ebp+0x14) 1)
25528     # never gets here
25529 
25530 $check-mu-populate-stream-stmt:error-invalid-length-type:
25531     (write-buffered *(ebp+0x10) "fn ")
25532     8b/-> *(ebp+0xc) 0/r32/eax
25533     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25534     (write-buffered *(ebp+0x10) %eax)
25535     (write-buffered *(ebp+0x10) ": stmt populate-stream: second inout '")
25536     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
25537     (lookup *eax *(eax+4))  # Var-name Var-name => eax
25538     (write-buffered *(ebp+0x10) %eax)
25539     (write-buffered *(ebp+0x10) "' must be an int\n")
25540     (flush *(ebp+0x10))
25541     (stop *(ebp+0x14) 1)
25542     # never gets here
25543 
25544 check-mu-read-from-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
25545     # . prologue
25546     55/push-ebp
25547     89/<- %ebp 4/r32/esp
25548     # . save registers
25549     50/push-eax
25550     51/push-ecx
25551     52/push-edx
25552     53/push-ebx
25553     56/push-esi
25554     57/push-edi
25555     # esi = stmt
25556     8b/-> *(ebp+8) 6/r32/esi
25557     # - check for 0 inouts
25558     # var base/ecx: (addr var) = stmt->inouts->value
25559     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25560 $check-mu-read-from-stream-stmt:check-no-inouts:
25561     3d/compare-eax-and 0/imm32
25562     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-too-few-inouts/disp32
25563     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25564     89/<- %ecx 0/r32/eax
25565     # - check base type is (addr stream T)
25566     # var base-type/ebx: (addr type-tree) = lookup(base->type)
25567     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
25568     89/<- %ebx 0/r32/eax
25569 $check-mu-read-from-stream-stmt:check-base-is-compound:
25570     # if base-type is an atom, abort
25571     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
25572     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
25573 $check-mu-read-from-stream-stmt:check-base-is-addr:
25574     # if type->left not addr, abort
25575     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
25576     (simple-mu-type? %eax 2)  # addr => eax
25577     3d/compare-eax-and 0/imm32/false
25578     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
25579 $check-mu-read-from-stream-stmt:check-base-is-addr-to-stream:
25580     # base-type = base-type->right
25581     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25582     89/<- %ebx 0/r32/eax
25583     # ensure base-type->left == stream
25584     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25585     (simple-mu-type? %eax 0xb)  # stream => eax
25586     3d/compare-eax-and 0/imm32/false
25587     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
25588     # - check target type is (addr T)
25589     # var target/ecx: (addr stmt-var) = stmt->inouts->next->value
25590     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25591     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
25592 $check-mu-read-from-stream-stmt:check-single-inout:
25593     3d/compare-eax-and 0/imm32
25594     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-too-few-inouts/disp32
25595     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25596     89/<- %ecx 0/r32/eax
25597     # var target-type/edx: (addr type-tree)
25598     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
25599     89/<- %edx 0/r32/eax
25600     # if target-type is an atom, it must be a literal or int
25601 $check-mu-read-from-stream-stmt:check-target-is-compound:
25602     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
25603     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-target-type-not-address/disp32
25604 $check-mu-read-from-stream-stmt:check-target-type:
25605     # target type must start with (addr ...)
25606     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
25607     (simple-mu-type? %eax 2)  # addr => eax
25608     3d/compare-eax-and 0/imm32/false
25609     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-target-type-not-address/disp32
25610     # if tail(base-type) != tail(target-type) abort
25611     (type-tail %ebx)  # => eax
25612     89/<- %ebx 0/r32/eax
25613     (type-tail %edx)  # => eax
25614     (type-equal? %ebx %eax)  # => eax
25615     3d/compare-eax-and 0/imm32/false
25616     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-target-type/disp32
25617 $check-mu-read-from-stream-stmt:check-too-many-inouts:
25618     # - check for too many inouts
25619     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25620     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
25621     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
25622     3d/compare-eax-and 0/imm32/false
25623     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-too-many-inouts/disp32
25624 $check-mu-read-from-stream-stmt:check-unexpected-output:
25625     # - check for any output
25626     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
25627     3d/compare-eax-and 0/imm32/false
25628     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-unexpected-output/disp32
25629 $check-mu-read-from-stream-stmt:end:
25630     # . restore registers
25631     5f/pop-to-edi
25632     5e/pop-to-esi
25633     5b/pop-to-ebx
25634     5a/pop-to-edx
25635     59/pop-to-ecx
25636     58/pop-to-eax
25637     # . epilogue
25638     89/<- %esp 5/r32/ebp
25639     5d/pop-to-ebp
25640     c3/return
25641 
25642 $check-mu-read-from-stream-stmt:error-invalid-base-type:
25643     (write-buffered *(ebp+0x10) "fn ")
25644     8b/-> *(ebp+0xc) 0/r32/eax
25645     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25646     (write-buffered *(ebp+0x10) %eax)
25647     (write-buffered *(ebp+0x10) ": stmt read-from-stream: var '")
25648     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
25649     (write-buffered *(ebp+0x10) %eax)
25650     (write-buffered *(ebp+0x10) "' must be an addr to a stream\n")
25651     (flush *(ebp+0x10))
25652     (stop *(ebp+0x14) 1)
25653     # never gets here
25654 
25655 $check-mu-read-from-stream-stmt:error-too-few-inouts:
25656     (write-buffered *(ebp+0x10) "fn ")
25657     8b/-> *(ebp+0xc) 0/r32/eax
25658     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25659     (write-buffered *(ebp+0x10) %eax)
25660     (write-buffered *(ebp+0x10) ": stmt read-from-stream: too few inouts (2 required)\n")
25661     (flush *(ebp+0x10))
25662     (stop *(ebp+0x14) 1)
25663     # never gets here
25664 
25665 $check-mu-read-from-stream-stmt:error-target-type-not-address:
25666     (write-buffered *(ebp+0x10) "fn ")
25667     8b/-> *(ebp+0xc) 0/r32/eax
25668     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25669     (write-buffered *(ebp+0x10) %eax)
25670     (write-buffered *(ebp+0x10) ": stmt read-from-stream: target '")
25671     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
25672     (write-buffered *(ebp+0x10) %eax)
25673     (write-buffered *(ebp+0x10) "' must be an addr\n")
25674     (flush *(ebp+0x10))
25675     (stop *(ebp+0x14) 1)
25676     # never gets here
25677 
25678 $check-mu-read-from-stream-stmt:error-invalid-target-type:
25679     (write-buffered *(ebp+0x10) "fn ")
25680     8b/-> *(ebp+0xc) 0/r32/eax
25681     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25682     (write-buffered *(ebp+0x10) %eax)
25683     (write-buffered *(ebp+0x10) ": stmt read-from-stream: second inout '")
25684     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
25685     (write-buffered *(ebp+0x10) %eax)
25686     (write-buffered *(ebp+0x10) "' does not have the right type\n")
25687     (flush *(ebp+0x10))
25688     (stop *(ebp+0x14) 1)
25689     # never gets here
25690 
25691 $check-mu-read-from-stream-stmt:error-too-many-inouts:
25692     (write-buffered *(ebp+0x10) "fn ")
25693     8b/-> *(ebp+0xc) 0/r32/eax
25694     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25695     (write-buffered *(ebp+0x10) %eax)
25696     (write-buffered *(ebp+0x10) ": stmt read-from-stream: too many inouts (2 required)\n")
25697     (flush *(ebp+0x10))
25698     (stop *(ebp+0x14) 1)
25699     # never gets here
25700 
25701 $check-mu-read-from-stream-stmt:error-unexpected-output:
25702     (write-buffered *(ebp+0x10) "fn ")
25703     8b/-> *(ebp+0xc) 0/r32/eax
25704     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25705     (write-buffered *(ebp+0x10) %eax)
25706     (write-buffered *(ebp+0x10) ": stmt read-from-stream: unexpected output\n")
25707     (flush *(ebp+0x10))
25708     (stop *(ebp+0x14) 1)
25709     # never gets here
25710 
25711 check-mu-write-to-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
25712     # . prologue
25713     55/push-ebp
25714     89/<- %ebp 4/r32/esp
25715     # . save registers
25716     50/push-eax
25717     51/push-ecx
25718     52/push-edx
25719     53/push-ebx
25720     56/push-esi
25721     57/push-edi
25722     # esi = stmt
25723     8b/-> *(ebp+8) 6/r32/esi
25724     # - check for 0 inouts
25725     # var base/ecx: (addr var) = stmt->inouts->value
25726     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25727 $check-mu-write-to-stream-stmt:check-no-inouts:
25728     3d/compare-eax-and 0/imm32
25729     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-too-few-inouts/disp32
25730     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25731     89/<- %ecx 0/r32/eax
25732     # - check base type is (addr stream T)
25733     # var base-type/ebx: (addr type-tree) = lookup(base->type)
25734     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
25735     89/<- %ebx 0/r32/eax
25736 $check-mu-write-to-stream-stmt:check-base-is-compound:
25737     # if base-type is an atom, abort
25738     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
25739     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
25740 $check-mu-write-to-stream-stmt:check-base-is-addr:
25741     # if type->left not addr, abort
25742     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
25743     (simple-mu-type? %eax 2)  # addr => eax
25744     3d/compare-eax-and 0/imm32/false
25745     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
25746 $check-mu-write-to-stream-stmt:check-base-is-addr-to-stream:
25747     # base-type = base-type->right
25748     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25749     89/<- %ebx 0/r32/eax
25750     # ensure base-type->left == stream
25751     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25752     (simple-mu-type? %eax 0xb)  # stream => eax
25753     3d/compare-eax-and 0/imm32/false
25754     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
25755     # - check target type is (addr T)
25756     # var target/ecx: (addr stmt-var) = stmt->inouts->next->value
25757     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25758     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
25759 $check-mu-write-to-stream-stmt:check-single-inout:
25760     3d/compare-eax-and 0/imm32
25761     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-too-few-inouts/disp32
25762     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25763     89/<- %ecx 0/r32/eax
25764     # var target-type/edx: (addr type-tree)
25765     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
25766     89/<- %edx 0/r32/eax
25767     # if target-type is an atom, it must be a literal or int
25768 $check-mu-write-to-stream-stmt:check-target-is-compound:
25769     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
25770     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-target-type-not-address/disp32
25771 $check-mu-write-to-stream-stmt:check-target-type:
25772     # target type must start with (addr ...)
25773     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
25774     (simple-mu-type? %eax 2)  # addr => eax
25775     3d/compare-eax-and 0/imm32/false
25776     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-target-type-not-address/disp32
25777     # if tail(base-type) != tail(target-type) abort
25778     (type-tail %ebx)  # => eax
25779     89/<- %ebx 0/r32/eax
25780     (type-tail %edx)  # => eax
25781     (type-equal? %ebx %eax)  # => eax
25782     3d/compare-eax-and 0/imm32/false
25783     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-target-type/disp32
25784 $check-mu-write-to-stream-stmt:check-too-many-inouts:
25785     # - check for too many inouts
25786     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25787     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
25788     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
25789     3d/compare-eax-and 0/imm32/false
25790     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-too-many-inouts/disp32
25791 $check-mu-write-to-stream-stmt:check-unexpected-output:
25792     # - check for any output
25793     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
25794     3d/compare-eax-and 0/imm32/false
25795     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-unexpected-output/disp32
25796 $check-mu-write-to-stream-stmt:end:
25797     # . restore registers
25798     5f/pop-to-edi
25799     5e/pop-to-esi
25800     5b/pop-to-ebx
25801     5a/pop-to-edx
25802     59/pop-to-ecx
25803     58/pop-to-eax
25804     # . epilogue
25805     89/<- %esp 5/r32/ebp
25806     5d/pop-to-ebp
25807     c3/return
25808 
25809 $check-mu-write-to-stream-stmt:error-invalid-base-type:
25810     (write-buffered *(ebp+0x10) "fn ")
25811     8b/-> *(ebp+0xc) 0/r32/eax
25812     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25813     (write-buffered *(ebp+0x10) %eax)
25814     (write-buffered *(ebp+0x10) ": stmt write-to-stream: var '")
25815     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
25816     (write-buffered *(ebp+0x10) %eax)
25817     (write-buffered *(ebp+0x10) "' must be an addr to a stream\n")
25818     (flush *(ebp+0x10))
25819     (stop *(ebp+0x14) 1)
25820     # never gets here
25821 
25822 $check-mu-write-to-stream-stmt:error-too-few-inouts:
25823     (write-buffered *(ebp+0x10) "fn ")
25824     8b/-> *(ebp+0xc) 0/r32/eax
25825     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25826     (write-buffered *(ebp+0x10) %eax)
25827     (write-buffered *(ebp+0x10) ": stmt write-to-stream: too few inouts (2 required)\n")
25828     (flush *(ebp+0x10))
25829     (stop *(ebp+0x14) 1)
25830     # never gets here
25831 
25832 $check-mu-write-to-stream-stmt:error-target-type-not-address:
25833     (write-buffered *(ebp+0x10) "fn ")
25834     8b/-> *(ebp+0xc) 0/r32/eax
25835     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25836     (write-buffered *(ebp+0x10) %eax)
25837     (write-buffered *(ebp+0x10) ": stmt write-to-stream: target '")
25838     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
25839     (write-buffered *(ebp+0x10) %eax)
25840     (write-buffered *(ebp+0x10) "' must be an addr\n")
25841     (flush *(ebp+0x10))
25842     (stop *(ebp+0x14) 1)
25843     # never gets here
25844 
25845 $check-mu-write-to-stream-stmt:error-invalid-target-type:
25846     (write-buffered *(ebp+0x10) "fn ")
25847     8b/-> *(ebp+0xc) 0/r32/eax
25848     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25849     (write-buffered *(ebp+0x10) %eax)
25850     (write-buffered *(ebp+0x10) ": stmt write-to-stream: second inout '")
25851     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
25852     (write-buffered *(ebp+0x10) %eax)
25853     (write-buffered *(ebp+0x10) "' does not have the right type\n")
25854     (flush *(ebp+0x10))
25855     (stop *(ebp+0x14) 1)
25856     # never gets here
25857 
25858 $check-mu-write-to-stream-stmt:error-too-many-inouts:
25859     (write-buffered *(ebp+0x10) "fn ")
25860     8b/-> *(ebp+0xc) 0/r32/eax
25861     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25862     (write-buffered *(ebp+0x10) %eax)
25863     (write-buffered *(ebp+0x10) ": stmt write-to-stream: too many inouts (2 required)\n")
25864     (flush *(ebp+0x10))
25865     (stop *(ebp+0x14) 1)
25866     # never gets here
25867 
25868 $check-mu-write-to-stream-stmt:error-unexpected-output:
25869     (write-buffered *(ebp+0x10) "fn ")
25870     8b/-> *(ebp+0xc) 0/r32/eax
25871     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25872     (write-buffered *(ebp+0x10) %eax)
25873     (write-buffered *(ebp+0x10) ": stmt write-to-stream: unexpected output\n")
25874     (flush *(ebp+0x10))
25875     (stop *(ebp+0x14) 1)
25876     # never gets here
25877 
25878 check-mu-convert-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
25879     # . prologue
25880     55/push-ebp
25881     89/<- %ebp 4/r32/esp
25882     # . save registers
25883     50/push-eax
25884     51/push-ecx
25885     52/push-edx
25886     56/push-esi
25887     57/push-edi
25888 $check-mu-convert-stmt:get-output:
25889     # esi = stmt
25890     8b/-> *(ebp+8) 6/r32/esi
25891     # var output/edi: (addr stmt-var) = stmt->outputs
25892     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
25893     89/<- %edi 0/r32/eax
25894     # zero outputs
25895     3d/compare-eax-and 0/imm32
25896     0f 84/jump-if-= $check-mu-convert-stmt:error-no-output/disp32
25897     # > 1 output
25898     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
25899     3d/compare-eax-and 0/imm32
25900     0f 85/jump-if-!= $check-mu-convert-stmt:error-too-many-outputs/disp32
25901 $check-mu-convert-stmt:get-inout:
25902     # var inout/esi: (addr stmt-var) = stmt->inouts
25903     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25904     89/<- %esi 0/r32/eax
25905     # zero inouts
25906     3d/compare-eax-and 0/imm32
25907     0f 84/jump-if-= $check-mu-convert-stmt:error-no-inout/disp32
25908     # > 1 inout
25909     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
25910     3d/compare-eax-and 0/imm32
25911     0f 85/jump-if-!= $check-mu-convert-stmt:error-too-many-inouts/disp32
25912 $check-mu-convert-stmt:types:
25913     # var inout-type/ecx: (addr type-tree) = inout->value->type
25914     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
25915     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25916     89/<- %ecx 0/r32/eax
25917     # if (inout->is-deref?) inout-type = inout-type->payload
25918     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
25919     3d/compare-eax-and 0/imm32/false
25920     {
25921       74/jump-if-= break/disp8
25922       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
25923       # if inout-type->right is null, t = inout-type->left
25924       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
25925       {
25926         75/jump-if-!= break/disp8
25927         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25928       }
25929       89/<- %ecx 0/r32/eax
25930     }
25931     # if input is not int or float, abort
25932     {
25933       (simple-mu-type? %ecx 1)  # int => eax
25934       3d/compare-eax-and 0/imm32/false
25935       75/jump-if-!= break/disp8
25936       (simple-mu-type? %ecx 0xf)  # float => eax
25937       3d/compare-eax-and 0/imm32/false
25938       75/jump-if-!= break/disp8
25939       e9/jump $check-mu-convert-stmt:error-invalid-inout-type/disp32
25940     }
25941     # if output not in register, abort
25942     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25943     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
25944     3d/compare-eax-and 0/imm32
25945     0f 84/jump-if-= $check-mu-convert-stmt:error-output-not-in-register/disp32
25946     # var output-type/edx: (addr type-tree) = output->value->type
25947     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25948     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25949     89/<- %edx 0/r32/eax
25950     # if output is not int or float, abort
25951     {
25952       (simple-mu-type? %edx 1)  # int => eax
25953       3d/compare-eax-and 0/imm32/false
25954       75/jump-if-!= break/disp8
25955       (simple-mu-type? %edx 0xf)  # float => eax
25956       3d/compare-eax-and 0/imm32/false
25957       75/jump-if-!= break/disp8
25958       e9/jump $check-mu-convert-stmt:error-invalid-output-type/disp32
25959     }
25960     # if both are ints, abort
25961     {
25962       (simple-mu-type? %edx 1)  # int => eax
25963       3d/compare-eax-and 0/imm32/false
25964       74/jump-if-= break/disp8
25965       (simple-mu-type? %ecx 1)  # int => eax
25966       3d/compare-eax-and 0/imm32/false
25967       74/jump-if-= break/disp8
25968       e9/jump $check-mu-convert-stmt:error-int-to-int/disp32
25969     }
25970     # if both are floats, abort
25971     {
25972       (simple-mu-type? %edx 0xf)  # float => eax
25973       3d/compare-eax-and 0/imm32/false
25974       74/jump-if-= break/disp8
25975       (simple-mu-type? %ecx 0xf)  # float => eax
25976       3d/compare-eax-and 0/imm32/false
25977       74/jump-if-= break/disp8
25978       e9/jump $check-mu-convert-stmt:error-float-to-float/disp32
25979     }
25980 $check-mu-convert-stmt:end:
25981     # . restore registers
25982     5f/pop-to-edi
25983     5e/pop-to-esi
25984     5a/pop-to-edx
25985     59/pop-to-ecx
25986     58/pop-to-eax
25987     # . epilogue
25988     89/<- %esp 5/r32/ebp
25989     5d/pop-to-ebp
25990     c3/return
25991 
25992 $check-mu-convert-stmt:error-no-inout:
25993     (write-buffered *(ebp+0x10) "fn ")
25994     8b/-> *(ebp+0xc) 0/r32/eax
25995     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25996     (write-buffered *(ebp+0x10) %eax)
25997     (write-buffered *(ebp+0x10) ": stmt 'convert' expects an inout\n")
25998     (flush *(ebp+0x10))
25999     (stop *(ebp+0x14) 1)
26000     # never gets here
26001 
26002 $check-mu-convert-stmt:error-too-many-inouts:
26003     (write-buffered *(ebp+0x10) "fn ")
26004     8b/-> *(ebp+0xc) 0/r32/eax
26005     (lookup *eax *(eax+4))  # Function-name Function-name => eax
26006     (write-buffered *(ebp+0x10) %eax)
26007     (write-buffered *(ebp+0x10) ": stmt 'convert' must have just one inout\n")
26008     (flush *(ebp+0x10))
26009     (stop *(ebp+0x14) 1)
26010     # never gets here
26011 
26012 $check-mu-convert-stmt:error-no-output:
26013     (write-buffered *(ebp+0x10) "fn ")
26014     8b/-> *(ebp+0xc) 0/r32/eax
26015     (lookup *eax *(eax+4))  # Function-name Function-name => eax
26016     (write-buffered *(ebp+0x10) %eax)
26017     (write-buffered *(ebp+0x10) ": stmt 'convert' expects an output\n")
26018     (flush *(ebp+0x10))
26019     (stop *(ebp+0x14) 1)
26020     # never gets here
26021 
26022 $check-mu-convert-stmt:error-output-not-in-register:
26023     (write-buffered *(ebp+0x10) "fn ")
26024     8b/-> *(ebp+0xc) 0/r32/eax
26025     (lookup *eax *(eax+4))  # Function-name Function-name => eax
26026     (write-buffered *(ebp+0x10) %eax)
26027     (write-buffered *(ebp+0x10) ": stmt convert: output '")
26028     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
26029     (lookup *eax *(eax+4))  # Var-name Var-name => eax
26030     (write-buffered *(ebp+0x10) %eax)
26031     (write-buffered *(ebp+0x10) "' not in a register\n")
26032     (flush *(ebp+0x10))
26033     (stop *(ebp+0x14) 1)
26034     # never gets here
26035 
26036 $check-mu-convert-stmt:error-too-many-outputs:
26037     (write-buffered *(ebp+0x10) "fn ")
26038     8b/-> *(ebp+0xc) 0/r32/eax
26039     (lookup *eax *(eax+4))  # Function-name Function-name => eax
26040     (write-buffered *(ebp+0x10) %eax)
26041     (write-buffered *(ebp+0x10) ": stmt 'convert' must have just one output\n")
26042     (flush *(ebp+0x10))
26043     (stop *(ebp+0x14) 1)
26044     # never gets here
26045 
26046 $check-mu-convert-stmt:error-invalid-inout-type:
26047     (write-buffered *(ebp+0x10) "fn ")
26048     8b/-> *(ebp+0xc) 0/r32/eax
26049     (lookup *eax *(eax+4))  # Function-name Function-name => eax
26050     (write-buffered *(ebp+0x10) %eax)
26051     (write-buffered *(ebp+0x10) ": stmt convert: inout '")
26052     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
26053     (lookup *eax *(eax+4))  # Var-name Var-name => eax
26054     (write-buffered *(ebp+0x10) %eax)
26055     (write-buffered *(ebp+0x10) "' must be an int or float\n")
26056     (flush *(ebp+0x10))
26057     (stop *(ebp+0x14) 1)
26058     # never gets here
26059 
26060 $check-mu-convert-stmt:error-invalid-output-type:
26061     (write-buffered *(ebp+0x10) "fn ")
26062     8b/-> *(ebp+0xc) 0/r32/eax
26063     (lookup *eax *(eax+4))  # Function-name Function-name => eax
26064     (write-buffered *(ebp+0x10) %eax)
26065     (write-buffered *(ebp+0x10) ": stmt convert: output '")
26066     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
26067     (lookup *eax *(eax+4))  # Var-name Var-name => eax
26068     (write-buffered *(ebp+0x10) %eax)
26069     (write-buffered *(ebp+0x10) "' must be an int or float\n")
26070     (flush *(ebp+0x10))
26071     (stop *(ebp+0x14) 1)
26072     # never gets here
26073 
26074 $check-mu-convert-stmt:error-int-to-int:
26075     (write-buffered *(ebp+0x10) "fn ")
26076     8b/-> *(ebp+0xc) 0/r32/eax
26077     (lookup *eax *(eax+4))  # Function-name Function-name => eax
26078     (write-buffered *(ebp+0x10) %eax)
26079     (write-buffered *(ebp+0x10) ": stmt convert: no need to convert int to int\n")
26080     (flush *(ebp+0x10))
26081     (stop *(ebp+0x14) 1)
26082     # never gets here
26083 
26084 $check-mu-convert-stmt:error-float-to-float:
26085     (write-buffered *(ebp+0x10) "fn ")
26086     8b/-> *(ebp+0xc) 0/r32/eax
26087     (lookup *eax *(eax+4))  # Function-name Function-name => eax
26088     (write-buffered *(ebp+0x10) %eax)
26089     (write-buffered *(ebp+0x10) ": stmt convert: no need to convert float to float\n")
26090     (flush *(ebp+0x10))
26091     (stop *(ebp+0x14) 1)
26092     # never gets here
26093 
26094 check-mu-call:  # stmt: (addr stmt), callee: (addr function), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
26095     # . prologue
26096     55/push-ebp
26097     89/<- %ebp 4/r32/esp
26098     # var type-parameters: (addr table (handle array byte) (addr type-tree) 8)
26099     68/push 0/imm32
26100     # var type-parameters-storage: (table (handle array byte) (addr type-tree) 8)
26101     81 5/subop/subtract %esp 0x60/imm32
26102     68/push 0x60/imm32/size
26103     68/push 0/imm32/read
26104     68/push 0/imm32/write
26105     # save a pointer to type-parameters-storage at type-parameters
26106     89/<- *(ebp-4) 4/r32/esp
26107     (clear-stream *(ebp-4))
26108     # . save registers
26109     50/push-eax
26110     51/push-ecx
26111     52/push-edx
26112     53/push-ebx
26113     56/push-esi
26114     57/push-edi
26115     # esi = stmt
26116     8b/-> *(ebp+8) 6/r32/esi
26117     # edi = callee
26118     8b/-> *(ebp+0xc) 7/r32/edi
26119     # var inouts/ecx: (addr stmt-var) = lookup(stmt->inouts)
26120     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
26121     89/<- %ecx 0/r32/eax
26122     # var expected/edx: (addr list var) = lookup(f->inouts)
26123     (lookup *(edi+8) *(edi+0xc))  # Function-inouts Function-inouts => eax
26124     89/<- %edx 0/r32/eax
26125     {
26126 $check-mu-call:check-for-inouts:
26127       # if (inouts == 0) break
26128       81 7/subop/compare %ecx 0/imm32
26129       0f 84/jump-if-= break/disp32
26130       # if (expected == 0) error
26131       81 7/subop/compare %edx 0/imm32
26132       0f 84/jump-if-= break/disp32
26133 $check-mu-call:check-null-addr:
26134       # if (inouts->value->name == "0") continue
26135       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26136       (lookup *eax *(eax+4))  # Var-name Var-name => eax
26137       (string-equal? %eax "0")  # => eax
26138       3d/compare-eax-and 0/imm32/false
26139       0f 85/jump-if-!= $check-mu-call:continue-to-next-inout/disp32
26140 $check-mu-call:check-inout-type:
26141       # var t/ebx: (addr type-tree) = inouts->value->type
26142       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26143       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
26144       89/<- %ebx 0/r32/eax
26145       # if (inouts->is-deref?) t = t->right
26146       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
26147       {
26148         74/jump-if-= break/disp8
26149         (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
26150         89/<- %ebx 0/r32/eax
26151         # if t->right is null, t = t->left
26152         81 7/subop/compare *(ebx+0xc) 0/imm32  # Type-tree-right
26153         75/jump-if-!= break/disp8
26154         (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
26155         89/<- %ebx 0/r32/eax
26156       }
26157       # var v2/eax: (addr v) = lookup(expected->value)
26158       (lookup *edx *(edx+4))  # List-value List-value => eax
26159       # var t2/eax: (addr type-tree) = lookup(v2->type)
26160       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
26161       # if (t != t2) error
26162       (type-match? %eax %ebx *(ebp-4))  # => eax
26163       3d/compare-eax-and 0/imm32/false
26164       {
26165         0f 85/jump-if-!= break/disp32
26166         (write-buffered *(ebp+0x14) "fn ")
26167         8b/-> *(ebp+0x10) 0/r32/eax
26168         (lookup *eax *(eax+4))  # Function-name Function-name => eax
26169         (write-buffered *(ebp+0x14) %eax)
26170         (write-buffered *(ebp+0x14) ": call ")
26171         (lookup *edi *(edi+4))  # Function-name Function-name => eax
26172         (write-buffered *(ebp+0x14) %eax)
26173         (write-buffered *(ebp+0x14) ": type for inout '")
26174         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26175         (lookup *eax *(eax+4))  # Var-name Var-name => eax
26176         (write-buffered *(ebp+0x14) %eax)
26177         (write-buffered *(ebp+0x14) "' is not right\n")
26178         (flush *(ebp+0x14))
26179         (stop *(ebp+0x18) 1)
26180       }
26181 $check-mu-call:continue-to-next-inout:
26182       # inouts = lookup(inouts->next)
26183       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
26184       89/<- %ecx 0/r32/eax
26185       # expected = lookup(expected->next)
26186       (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
26187       89/<- %edx 0/r32/eax
26188       #
26189       e9/jump loop/disp32
26190     }
26191 $check-mu-call:check-inout-count:
26192     # if (inouts == expected) proceed
26193     39/compare %ecx 2/r32/edx
26194     {
26195       0f 84/jump-if-= break/disp32
26196       # exactly one of the two is null
26197       # if (inouts == 0) error("too many inouts")
26198       {
26199         81 7/subop/compare %ecx 0/imm32
26200         0f 84/jump-if-= break/disp32
26201         (write-buffered *(ebp+0x14) "fn ")
26202         8b/-> *(ebp+0x10) 0/r32/eax
26203         (lookup *eax *(eax+4))  # Function-name Function-name => eax
26204         (write-buffered *(ebp+0x14) %eax)
26205         (write-buffered *(ebp+0x14) ": call ")
26206         (lookup *edi *(edi+4))  # Function-name Function-name => eax
26207         (write-buffered *(ebp+0x14) %eax)
26208         (write-buffered *(ebp+0x14) ": too many inouts\n")
26209         (flush *(ebp+0x14))
26210         (stop *(ebp+0x18) 1)
26211       }
26212       # if (expected == 0) error("too few inouts")
26213       {
26214         81 7/subop/compare %edx 0/imm32
26215         0f 84/jump-if-= break/disp32
26216         (write-buffered *(ebp+0x14) "fn ")
26217         8b/-> *(ebp+0x10) 0/r32/eax
26218         (lookup *eax *(eax+4))  # Function-name Function-name => eax
26219         (write-buffered *(ebp+0x14) %eax)
26220         (write-buffered *(ebp+0x14) ": call ")
26221         (lookup *edi *(edi+4))  # Function-name Function-name => eax
26222         (write-buffered *(ebp+0x14) %eax)
26223         (write-buffered *(ebp+0x14) ": too few inouts\n")
26224         (flush *(ebp+0x14))
26225         (stop *(ebp+0x18) 1)
26226       }
26227     }
26228 $check-mu-call:check-outputs:
26229     # var outputs/ecx: (addr stmt-var) = lookup(stmt->outputs)
26230     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
26231     89/<- %ecx 0/r32/eax
26232     # var expected/edx: (addr list var) = lookup(f->outputs)
26233     (lookup *(edi+0x10) *(edi+0x14))  # Function-outputs Function-outputs => eax
26234     89/<- %edx 0/r32/eax
26235     {
26236 $check-mu-call:check-for-outputs:
26237       # if (outputs == 0) break
26238       81 7/subop/compare %ecx 0/imm32
26239       0f 84/jump-if-= break/disp32
26240       # if (expected == 0) error
26241       81 7/subop/compare %edx 0/imm32
26242       0f 84/jump-if-= break/disp32
26243 $check-mu-call:check-output-type:
26244       # var v/eax: (addr v) = lookup(outputs->value)
26245       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26246       # var t/ebx: (addr type-tree) = lookup(v->type)
26247       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
26248       89/<- %ebx 0/r32/eax
26249       # if (outputs->is-deref?) t = t->right  # TODO: check that t->left is an addr
26250       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
26251       {
26252         74/jump-if-= break/disp8
26253         (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
26254         89/<- %ebx 0/r32/eax
26255       }
26256       # var v2/eax: (addr v) = lookup(expected->value)
26257       (lookup *edx *(edx+4))  # List-value List-value => eax
26258       # var t2/eax: (addr type-tree) = lookup(v2->type)
26259       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
26260       # if (t != t2) error
26261       (type-match? %eax %ebx *(ebp-4))  # => eax
26262       3d/compare-eax-and 0/imm32/false
26263       {
26264         0f 85/jump-if-!= break/disp32
26265         (write-buffered *(ebp+0x14) "fn ")
26266         8b/-> *(ebp+0x10) 0/r32/eax
26267         (lookup *eax *(eax+4))  # Function-name Function-name => eax
26268         (write-buffered *(ebp+0x14) %eax)
26269         (write-buffered *(ebp+0x14) ": call ")
26270         (lookup *edi *(edi+4))  # Function-name Function-name => eax
26271         (write-buffered *(ebp+0x14) %eax)
26272         (write-buffered *(ebp+0x14) ": type for output '")
26273         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26274         (lookup *eax *(eax+4))  # Var-name Var-name => eax
26275         (write-buffered *(ebp+0x14) %eax)
26276         (write-buffered *(ebp+0x14) "' is not right\n")
26277         (flush *(ebp+0x14))
26278         (stop *(ebp+0x18) 1)
26279       }
26280 $check-mu-call:check-output-register:
26281       # var v/eax: (addr v) = lookup(outputs->value)
26282       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26283       # var r/ebx: (addr array byte) = lookup(v->register)
26284       (lookup *(eax+18) *(eax+0x1c))  # Var-register Var-register => eax
26285       89/<- %ebx 0/r32/eax
26286       # if (r == 0) error
26287       3d/compare-eax-and 0/imm32
26288       {
26289         0f 85/jump-if-!= break/disp32
26290         (write-buffered *(ebp+0x14) "fn ")
26291         8b/-> *(ebp+0x10) 0/r32/eax
26292         (lookup *eax *(eax+4))  # Function-name Function-name => eax
26293         (write-buffered *(ebp+0x14) %eax)
26294         (write-buffered *(ebp+0x14) ": call ")
26295         (lookup *edi *(edi+4))  # Function-name Function-name => eax
26296         (write-buffered *(ebp+0x14) %eax)
26297         (write-buffered *(ebp+0x14) ": output '")
26298         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26299         (lookup *eax *(eax+4))  # Var-name Var-name => eax
26300         (write-buffered *(ebp+0x14) %eax)
26301         (write-buffered *(ebp+0x14) "' is not in a register\n")
26302         (flush *(ebp+0x14))
26303         (stop *(ebp+0x18) 1)
26304       }
26305       # var v2/eax: (addr v) = lookup(expected->value)
26306       (lookup *edx *(edx+4))  # Stmt-var-value Stmt-var-value => eax
26307       # var r2/eax: (addr array byte) = lookup(v2->register)
26308       (lookup *(eax+18) *(eax+0x1c))  # Var-register Var-register => eax
26309       # if (r != r2) error
26310       (string-equal? %eax %ebx)  # => eax
26311       3d/compare-eax-and 0/imm32/false
26312       {
26313         0f 85/jump-if-!= break/disp32
26314         (write-buffered *(ebp+0x14) "fn ")
26315         8b/-> *(ebp+0x10) 0/r32/eax
26316         (lookup *eax *(eax+4))  # Function-name Function-name => eax
26317         (write-buffered *(ebp+0x14) %eax)
26318         (write-buffered *(ebp+0x14) ": call ")
26319         (lookup *edi *(edi+4))  # Function-name Function-name => eax
26320         (write-buffered *(ebp+0x14) %eax)
26321         (write-buffered *(ebp+0x14) ": register for output '")
26322         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26323         (lookup *eax *(eax+4))  # Var-name Var-name => eax
26324         (write-buffered *(ebp+0x14) %eax)
26325         (write-buffered *(ebp+0x14) "' is not right\n")
26326         (flush *(ebp+0x14))
26327         (stop *(ebp+0x18) 1)
26328       }
26329 $check-mu-call:continue-to-next-output:
26330       # outputs = lookup(outputs->next)
26331       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
26332       89/<- %ecx 0/r32/eax
26333       # expected = lookup(expected->next)
26334       (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
26335       89/<- %edx 0/r32/eax
26336       #
26337       e9/jump loop/disp32
26338     }
26339 $check-mu-call:check-output-count:
26340     # if (outputs == expected) proceed
26341     39/compare %ecx 2/r32/edx
26342     {
26343       0f 84/jump-if-= break/disp32
26344       # exactly one of the two is null
26345       # if (outputs == 0) error("too many outputs")
26346       {
26347         81 7/subop/compare %ecx 0/imm32
26348         0f 84/jump-if-= break/disp32
26349         (write-buffered *(ebp+0x14) "fn ")
26350         8b/-> *(ebp+0x10) 0/r32/eax
26351         (lookup *eax *(eax+4))  # Function-name Function-name => eax
26352         (write-buffered *(ebp+0x14) %eax)
26353         (write-buffered *(ebp+0x14) ": call ")
26354         (lookup *edi *(edi+4))  # Function-name Function-name => eax
26355         (write-buffered *(ebp+0x14) %eax)
26356         (write-buffered *(ebp+0x14) ": too many outputs\n")
26357         (flush *(ebp+0x14))
26358         (stop *(ebp+0x18) 1)
26359       }
26360       # if (expected == 0) error("too few outputs")
26361       {
26362         81 7/subop/compare %edx 0/imm32
26363         0f 84/jump-if-= break/disp32
26364         (write-buffered *(ebp+0x14) "fn ")
26365         8b/-> *(ebp+0x10) 0/r32/eax
26366         (lookup *eax *(eax+4))  # Function-name Function-name => eax
26367         (write-buffered *(ebp+0x14) %eax)
26368         (write-buffered *(ebp+0x14) ": call ")
26369         (lookup *edi *(edi+4))  # Function-name Function-name => eax
26370         (write-buffered *(ebp+0x14) %eax)
26371         (write-buffered *(ebp+0x14) ": too few outputs\n")
26372         (flush *(ebp+0x14))
26373         (stop *(ebp+0x18) 1)
26374       }
26375     }
26376 $check-mu-call:end:
26377     # . restore registers
26378     5f/pop-to-edi
26379     5e/pop-to-esi
26380     5b/pop-to-ebx
26381     5a/pop-to-edx
26382     59/pop-to-ecx
26383     58/pop-to-eax
26384     # . reclaim locals exclusively on the stack
26385     81 0/subop/add %esp 0x70/imm32
26386     # . epilogue
26387     89/<- %esp 5/r32/ebp
26388     5d/pop-to-ebp
26389     c3/return
26390 
26391 # like type-equal? but takes literals type parameters into account
26392 type-match?:  # def: (addr type-tree), call: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean
26393     # . prologue
26394     55/push-ebp
26395     89/<- %ebp 4/r32/esp
26396     # if (call is literal and def is numberlike) return true
26397     {
26398 $type-match?:check-literal-int:
26399       (simple-mu-type? *(ebp+0xc) 0)  # literal => eax
26400       3d/compare-eax-and 0/imm32/false
26401       74/jump-if-= break/disp8
26402       (mu-numberlike-output? *(ebp+8))  # => eax
26403       3d/compare-eax-and 0/imm32/false
26404       74/jump-if-= break/disp8
26405       b8/copy-to-eax 1/imm32/true
26406       e9/jump $type-match?:end/disp32
26407     }
26408     # if (call is literal-string and def is string) return true
26409     {
26410 $type-match?:check-literal-string:
26411       (simple-mu-type? *(ebp+0xc) 0x10)  # literal-string => eax
26412       3d/compare-eax-and 0/imm32/false
26413       74/jump-if-= break/disp8
26414       (mu-string-type? *(ebp+8))  # => eax
26415       3d/compare-eax-and 0/imm32/false
26416       74/jump-if-= break/disp8
26417       b8/copy-to-eax 1/imm32/true
26418       e9/jump $type-match?:end/disp32
26419     }
26420 $type-match?:baseline:
26421     # otherwise fall back
26422     (type-component-match? *(ebp+8) *(ebp+0xc) *(ebp+0x10))  # => eax
26423 $type-match?:end:
26424     # . epilogue
26425     89/<- %esp 5/r32/ebp
26426     5d/pop-to-ebp
26427     c3/return
26428 
26429 type-component-match?:  # def: (addr type-tree), call: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean
26430     # . prologue
26431     55/push-ebp
26432     89/<- %ebp 4/r32/esp
26433     # . save registers
26434     51/push-ecx
26435     52/push-edx
26436     53/push-ebx
26437     # ecx = def
26438     8b/-> *(ebp+8) 1/r32/ecx
26439     # edx = call
26440     8b/-> *(ebp+0xc) 2/r32/edx
26441 $type-component-match?:compare-addr:
26442     # if (def == call) return true
26443     8b/-> %ecx 0/r32/eax  # Var-type
26444     39/compare %edx 0/r32/eax  # Var-type
26445     b8/copy-to-eax 1/imm32/true
26446     0f 84/jump-if-= $type-component-match?:end/disp32
26447     # if (def == 0) return false
26448     b8/copy-to-eax 0/imm32/false
26449     81 7/subop/compare %ecx 0/imm32  # Type-tree-is-atom
26450     0f 84/jump-if-= $type-component-match?:end/disp32
26451     # if (call == 0) return false
26452     81 7/subop/compare %edx 0/imm32  # Type-tree-is-atom
26453     0f 84/jump-if-= $type-component-match?:end/disp32
26454     # if def is a type parameter, just check in type-parameters
26455     {
26456 $type-component-match?:check-type-parameter:
26457       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
26458       74/jump-if-= break/disp8
26459       81 7/subop/compare *(ecx+4) 0xa/imm32/type-parameter  # Type-tree-value
26460       75/jump-if-!= break/disp8
26461 $type-component-match?:type-parameter:
26462       (type-parameter-match? *(ecx+8) *(ecx+0xc)  %edx  *(ebp+0x10))  # => eax
26463       e9/jump $type-component-match?:end/disp32
26464     }
26465     # if def is a list containing just a type parameter, just check in type-parameters
26466     {
26467 $type-component-match?:check-list-type-parameter:
26468       # if def is a list..
26469       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
26470       75/jump-if-!= break/disp8
26471       #   ..that's a singleton
26472       81 7/subop/compare *(ecx+0xc) 0/imm32  # Type-tree-left
26473       75/jump-if-!= break/disp8
26474       #   ..and whose head is a type parameter
26475       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26476       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
26477       74/jump-if-= break/disp8
26478       81 7/subop/compare *(eax+4) 0xa/imm32/type-parameter  # Type-tree-value
26479       75/jump-if-!= break/disp8
26480 $type-component-match?:list-type-parameter:
26481       (type-parameter-match? *(eax+8) *(eax+0xc)  %edx  *(ebp+0x10))  # => eax
26482       e9/jump $type-component-match?:end/disp32
26483     }
26484 $type-component-match?:compare-atom-state:
26485     # if (def->is-atom? != call->is-atom?) return false
26486     8b/-> *ecx 3/r32/ebx  # Type-tree-is-atom
26487     39/compare *edx 3/r32/ebx  # Type-tree-is-atom
26488     b8/copy-to-eax 0/imm32/false
26489     0f 85/jump-if-!= $type-component-match?:end/disp32
26490     # if def->is-atom? return (def->value == call->value)
26491     {
26492 $type-component-match?:check-atom:
26493       81 7/subop/compare %ebx 0/imm32/false
26494       74/jump-if-= break/disp8
26495 $type-component-match?:is-atom:
26496       8b/-> *(ecx+4) 0/r32/eax  # Type-tree-value
26497       39/compare *(edx+4) 0/r32/eax  # Type-tree-value
26498       0f 94/set-if-= %al
26499       81 4/subop/and %eax 0xff/imm32
26500       e9/jump $type-component-match?:end/disp32
26501     }
26502 $type-component-match?:check-left:
26503     # if (!type-component-match?(def->left, call->left)) return false
26504     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26505     89/<- %ebx 0/r32/eax
26506     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
26507     (type-component-match? %ebx %eax *(ebp+0x10))  # => eax
26508     3d/compare-eax-and 0/imm32/false
26509     74/jump-if-= $type-component-match?:end/disp8
26510 $type-component-match?:check-right:
26511     # return type-component-match?(def->right, call->right)
26512     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
26513     89/<- %ebx 0/r32/eax
26514     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
26515     (type-component-match? %ebx %eax *(ebp+0x10))  # => eax
26516 $type-component-match?:end:
26517     # . restore registers
26518     5b/pop-to-ebx
26519     5a/pop-to-edx
26520     59/pop-to-ecx
26521     # . epilogue
26522     89/<- %esp 5/r32/ebp
26523     5d/pop-to-ebp
26524     c3/return
26525 
26526 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
26527     # . prologue
26528     55/push-ebp
26529     89/<- %ebp 4/r32/esp
26530     # . save registers
26531     51/push-ecx
26532     #
26533     (get-or-insert-handle *(ebp+0x14)  *(ebp+8) *(ebp+0xc)  0xc)  # => eax
26534     # if parameter wasn't saved, save it
26535     {
26536       81 7/subop/compare *eax 0/imm32
26537       75/jump-if-!= break/disp8
26538       8b/-> *(ebp+0x10) 1/r32/ecx
26539       89/<- *eax 1/r32/ecx
26540     }
26541     #
26542     (type-equal? *(ebp+0x10) *eax)  # => eax
26543 $type-parameter-match?:end:
26544     # . restore registers
26545     59/pop-to-ecx
26546     # . epilogue
26547     89/<- %esp 5/r32/ebp
26548     5d/pop-to-ebp
26549     c3/return
26550 
26551 size-of:  # v: (addr var) -> result/eax: int
26552     # . prologue
26553     55/push-ebp
26554     89/<- %ebp 4/r32/esp
26555     # . save registers
26556     51/push-ecx
26557     # var t/ecx: (addr type-tree) = lookup(v->type)
26558     8b/-> *(ebp+8) 1/r32/ecx
26559 #?     (write-buffered Stderr "size-of ")
26560 #?     (write-int32-hex-buffered Stderr %ecx)
26561 #?     (write-buffered Stderr Newline)
26562 #?     (write-buffered Stderr "type allocid: ")
26563 #?     (write-int32-hex-buffered Stderr *(ecx+8))
26564 #?     (write-buffered Stderr Newline)
26565 #?     (flush Stderr)
26566     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
26567     89/<- %ecx 0/r32/eax
26568     # if mu-array?(t) return size-of-array(t)
26569     {
26570       (mu-array? %ecx)  # => eax
26571       3d/compare-eax-and 0/imm32/false
26572       74/jump-if-= break/disp8
26573       (size-of-array %ecx)  # => eax
26574       eb/jump $size-of:end/disp8
26575     }
26576     # if mu-stream?(t) return size-of-stream(t)
26577     {
26578       (mu-stream? %ecx)  # => eax
26579       3d/compare-eax-and 0/imm32/false
26580       74/jump-if-= break/disp8
26581       (size-of-stream %ecx)  # => eax
26582       eb/jump $size-of:end/disp8
26583     }
26584     # if (!t->is-atom?) t = lookup(t->left)
26585     {
26586       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
26587       75/jump-if-!= break/disp8
26588       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26589       89/<- %ecx 0/r32/eax
26590     }
26591     # TODO: assert t->is-atom?
26592     (size-of-type-id *(ecx+4))  # Type-tree-value => eax
26593 $size-of:end:
26594     # . restore registers
26595     59/pop-to-ecx
26596     # . epilogue
26597     89/<- %esp 5/r32/ebp
26598     5d/pop-to-ebp
26599     c3/return
26600 
26601 size-of-deref:  # v: (addr var) -> result/eax: int
26602     # . prologue
26603     55/push-ebp
26604     89/<- %ebp 4/r32/esp
26605     # . save registers
26606     51/push-ecx
26607     # var t/ecx: (addr type-tree) = lookup(v->type)
26608     8b/-> *(ebp+8) 1/r32/ecx
26609     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
26610     89/<- %ecx 0/r32/eax
26611     # TODO: assert(t is an addr)
26612     # t = lookup(t->right)
26613     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
26614     89/<- %ecx 0/r32/eax
26615     # if mu-array?(t) return size-of-array(t)
26616     {
26617       (mu-array? %ecx)  # => eax
26618       3d/compare-eax-and 0/imm32/false
26619       74/jump-if-= break/disp8
26620       (size-of-array %ecx)  # => eax
26621       eb/jump $size-of-deref:end/disp8
26622     }
26623     # if mu-stream?(t) return size-of-stream(t)
26624     {
26625       (mu-stream? %ecx)  # => eax
26626       3d/compare-eax-and 0/imm32/false
26627       74/jump-if-= break/disp8
26628       (size-of-stream %ecx)  # => eax
26629       eb/jump $size-of-deref:end/disp8
26630     }
26631     # if (!t->is-atom?) t = lookup(t->left)
26632     {
26633       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
26634       75/jump-if-!= break/disp8
26635       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26636       89/<- %ecx 0/r32/eax
26637     }
26638     # TODO: assert t->is-atom?
26639     (size-of-type-id *(ecx+4))  # Type-tree-value => eax
26640 $size-of-deref:end:
26641     # . restore registers
26642     59/pop-to-ecx
26643     # . epilogue
26644     89/<- %esp 5/r32/ebp
26645     5d/pop-to-ebp
26646     c3/return
26647 
26648 mu-array?:  # t: (addr type-tree) -> result/eax: boolean
26649     # . prologue
26650     55/push-ebp
26651     89/<- %ebp 4/r32/esp
26652     # . save registers
26653     51/push-ecx
26654     # ecx = t
26655     8b/-> *(ebp+8) 1/r32/ecx
26656     # if t->is-atom?, return false
26657     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
26658     75/jump-if-!= $mu-array?:return-false/disp8
26659     # if !t->left->is-atom?, return false
26660     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26661     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
26662     74/jump-if-= $mu-array?:return-false/disp8
26663     # return t->left->value == array
26664     81 7/subop/compare *(eax+4) 3/imm32/array-type-id  # Type-tree-value
26665     0f 94/set-if-= %al
26666     81 4/subop/and %eax 0xff/imm32
26667     eb/jump $mu-array?:end/disp8
26668 $mu-array?:return-false:
26669     b8/copy-to-eax 0/imm32/false
26670 $mu-array?:end:
26671     # . restore registers
26672     59/pop-to-ecx
26673     # . epilogue
26674     89/<- %esp 5/r32/ebp
26675     5d/pop-to-ebp
26676     c3/return
26677 
26678 # size of a statically allocated array where the size is part of the type expression
26679 size-of-array:  # a: (addr type-tree) -> result/eax: int
26680     # . prologue
26681     55/push-ebp
26682     89/<- %ebp 4/r32/esp
26683     # . save registers
26684     51/push-ecx
26685     52/push-edx
26686     #
26687     8b/-> *(ebp+8) 1/r32/ecx
26688     # TODO: assert that a->left is 'array'
26689     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
26690     89/<- %ecx 0/r32/eax
26691     # var elem-type/edx: type-id = a->right->left->value
26692     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26693     8b/-> *(eax+4) 2/r32/edx  # Type-tree-value
26694     # TODO: assert that a->right->right->left->value == size
26695     # var array-size/ecx: int = a->right->right->left->value-size
26696     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
26697     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
26698     8b/-> *(eax+8) 1/r32/ecx  # Type-tree-value-size
26699     # return 4 + array-size * size-of(elem-type)
26700     (size-of-type-id-as-array-element %edx)  # => eax
26701     f7 4/subop/multiply-into-edx-eax %ecx
26702     05/add-to-eax 4/imm32  # for array size
26703     # TODO: check edx for overflow
26704 $size-of-array:end:
26705     # . restore registers
26706     5a/pop-to-edx
26707     59/pop-to-ecx
26708     # . epilogue
26709     89/<- %esp 5/r32/ebp
26710     5d/pop-to-ebp
26711     c3/return
26712 
26713 mu-stream?:  # t: (addr type-tree) -> result/eax: boolean
26714     # . prologue
26715     55/push-ebp
26716     89/<- %ebp 4/r32/esp
26717     # . save registers
26718     51/push-ecx
26719     # ecx = t
26720     8b/-> *(ebp+8) 1/r32/ecx
26721     # if t->is-atom?, return false
26722     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
26723     75/jump-if-!= $mu-stream?:return-false/disp8
26724     # if !t->left->is-atom?, return false
26725     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26726     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
26727     74/jump-if-= $mu-stream?:return-false/disp8
26728     # return t->left->value == stream
26729     81 7/subop/compare *(eax+4) 0xb/imm32/stream-type-id  # Type-tree-value
26730     0f 94/set-if-= %al
26731     81 4/subop/and %eax 0xff/imm32
26732     eb/jump $mu-stream?:end/disp8
26733 $mu-stream?:return-false:
26734     b8/copy-to-eax 0/imm32/false
26735 $mu-stream?:end:
26736     # . restore registers
26737     59/pop-to-ecx
26738     # . epilogue
26739     89/<- %esp 5/r32/ebp
26740     5d/pop-to-ebp
26741     c3/return
26742 
26743 # size of a statically allocated stream where the size is part of the type expression
26744 size-of-stream:  # a: (addr type-tree) -> result/eax: int
26745     # . prologue
26746     55/push-ebp
26747     89/<- %ebp 4/r32/esp
26748     #
26749     (size-of-array *(ebp+8))  # assumes we ignore the actual type name 'array' in the type
26750     05/add-to-eax 8/imm32  # for read/write pointers
26751 $size-of-stream:end:
26752     # . epilogue
26753     89/<- %esp 5/r32/ebp
26754     5d/pop-to-ebp
26755     c3/return
26756 
26757 size-of-type-id:  # t: type-id -> result/eax: int
26758     # . prologue
26759     55/push-ebp
26760     89/<- %ebp 4/r32/esp
26761     # . save registers
26762     51/push-ecx
26763     # var out/ecx: (handle typeinfo)
26764     68/push 0/imm32
26765     68/push 0/imm32
26766     89/<- %ecx 4/r32/esp
26767     # eax = t
26768     8b/-> *(ebp+8) 0/r32/eax
26769     # if t is a literal, return 0
26770     3d/compare-eax-and 0/imm32
26771     0f 84/jump-if-= $size-of-type-id:end/disp32  # eax changes type from type-id to int
26772     # if t is a byte, return 4 (because we don't really support non-multiples of 4)
26773     3d/compare-eax-and 8/imm32/byte
26774     {
26775       75/jump-if-!= break/disp8
26776       b8/copy-to-eax 4/imm32
26777       eb/jump $size-of-type-id:end/disp8
26778     }
26779     # if t is a handle, return 8
26780     3d/compare-eax-and 4/imm32/handle
26781     {
26782       75/jump-if-!= break/disp8
26783       b8/copy-to-eax 8/imm32
26784       eb/jump $size-of-type-id:end/disp8  # eax changes type from type-id to int
26785     }
26786     # if t is a slice, return 8
26787     3d/compare-eax-and 0xc/imm32/slice
26788     {
26789       75/jump-if-!= break/disp8
26790       b8/copy-to-eax 8/imm32
26791       eb/jump $size-of-type-id:end/disp8  # eax changes type from type-id to int
26792     }
26793     # if t is a user-defined type, return its size
26794     # TODO: support non-atom type
26795     (find-typeinfo %eax %ecx)
26796     {
26797       81 7/subop/compare *ecx 0/imm32
26798       74/jump-if-= break/disp8
26799 $size-of-type-id:user-defined:
26800       (lookup *ecx *(ecx+4))  # => eax
26801       8b/-> *(eax+0xc) 0/r32/eax  # Typeinfo-total-size-in-bytes
26802       eb/jump $size-of-type-id:end/disp8
26803     }
26804     # otherwise return the word size
26805     b8/copy-to-eax 4/imm32
26806 $size-of-type-id:end:
26807     # . reclaim locals
26808     81 0/subop/add %esp 8/imm32
26809     # . restore registers
26810     59/pop-to-ecx
26811     # . epilogue
26812     89/<- %esp 5/r32/ebp
26813     5d/pop-to-ebp
26814     c3/return
26815 
26816 # Minor violation of our type system since it returns an addr. But we could
26817 # replace it with a handle some time.
26818 # Returns null if t is an atom.
26819 type-tail:  # t: (addr type-tree) -> out/eax: (addr type-tree)
26820     # . prologue
26821     55/push-ebp
26822     89/<- %ebp 4/r32/esp
26823     # . save registers
26824     51/push-ecx
26825     # eax = 0
26826     b8/copy-to-eax 0/imm32
26827     # ecx = t
26828     8b/-> *(ebp+8) 1/r32/ecx
26829 $type-tail:check-atom:
26830     # if t->is-atom? return 0
26831     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
26832     0f 85/jump-if-!= $type-tail:end/disp32
26833     # var tail = t->right
26834     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
26835     89/<- %ecx 0/r32/eax
26836 $type-tail:check-singleton:
26837     # if (tail->right == 0) return tail->left
26838     {
26839       81 7/subop/compare *(ecx+0xc) 0/imm32  # Type-tree-right
26840       75/jump-if-!= break/disp8
26841       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26842       e9/jump $type-tail:end/disp32
26843     }
26844     # if tail->right->left is an array-capacity, return tail->left
26845     {
26846 $type-tail:check-array-capacity:
26847       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
26848       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
26849       75/jump-if-!= break/disp8
26850 $type-tail:check-array-capacity-1:
26851       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
26852       3d/compare-eax-and 0/imm32
26853       74/jump-if-= break/disp8
26854 $type-tail:check-array-capacity-2:
26855       (simple-mu-type? %eax 9)  # array-capacity => eax
26856       3d/compare-eax-and 0/imm32/false
26857       74/jump-if-= break/disp8
26858 $type-tail:array-capacity:
26859       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26860       eb/jump $type-tail:end/disp8
26861     }
26862 $type-tail:check-compound-left:
26863     # if !tail->left->is-atom? return tail->left
26864     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26865     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
26866     74/jump-if-= $type-tail:end/disp8
26867 $type-tail:return-tail:
26868     # return tail
26869     89/<- %eax 1/r32/ecx
26870 $type-tail:end:
26871     # . restore registers
26872     59/pop-to-ecx
26873     # . epilogue
26874     89/<- %esp 5/r32/ebp
26875     5d/pop-to-ebp
26876     c3/return
26877 
26878 type-equal?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
26879     # . prologue
26880     55/push-ebp
26881     89/<- %ebp 4/r32/esp
26882     # . save registers
26883     51/push-ecx
26884     52/push-edx
26885     53/push-ebx
26886     # ecx = a
26887     8b/-> *(ebp+8) 1/r32/ecx
26888     # edx = b
26889     8b/-> *(ebp+0xc) 2/r32/edx
26890 $type-equal?:compare-addr:
26891     # if (a == b) return true
26892     8b/-> %ecx 0/r32/eax  # Var-type
26893     39/compare %edx 0/r32/eax  # Var-type
26894     b8/copy-to-eax 1/imm32/true
26895     0f 84/jump-if-= $type-equal?:end/disp32
26896 $type-equal?:compare-null-a:
26897     # if (a == 0) return false
26898     b8/copy-to-eax 0/imm32/false
26899     81 7/subop/compare %ecx 0/imm32
26900     0f 84/jump-if-= $type-equal?:end/disp32
26901 $type-equal?:compare-null-b:
26902     # if (b == 0) return false
26903     81 7/subop/compare %edx 0/imm32
26904     0f 84/jump-if-= $type-equal?:end/disp32
26905 $type-equal?:compare-atom-state:
26906     # if (a->is-atom? != b->is-atom?) return false
26907     8b/-> *ecx 3/r32/ebx  # Type-tree-is-atom
26908     39/compare *edx 3/r32/ebx  # Type-tree-is-atom
26909     b8/copy-to-eax 0/imm32/false
26910     0f 85/jump-if-!= $type-equal?:end/disp32
26911     # if a->is-atom? return (a->value == b->value)
26912     {
26913 $type-equal?:check-atom:
26914       81 7/subop/compare %ebx 0/imm32/false
26915       74/jump-if-= break/disp8
26916 $type-equal?:is-atom:
26917       8b/-> *(ecx+4) 0/r32/eax  # Type-tree-value
26918       39/compare *(edx+4) 0/r32/eax  # Type-tree-value
26919       0f 94/set-if-= %al
26920       81 4/subop/and %eax 0xff/imm32
26921       e9/jump $type-equal?:end/disp32
26922     }
26923 $type-equal?:check-left:
26924     # if (!type-equal?(a->left, b->left)) return false
26925     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26926     89/<- %ebx 0/r32/eax
26927     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
26928     (type-equal? %eax %ebx)  # => eax
26929     3d/compare-eax-and 0/imm32/false
26930     74/jump-if-= $type-equal?:end/disp8
26931 $type-equal?:check-right:
26932     # return type-equal?(a->right, b->right)
26933     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
26934     89/<- %ebx 0/r32/eax
26935     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
26936     (type-equal? %eax %ebx)  # => eax
26937 $type-equal?:end:
26938     # . restore registers
26939     5b/pop-to-ebx
26940     5a/pop-to-edx
26941     59/pop-to-ecx
26942     # . epilogue
26943     89/<- %esp 5/r32/ebp
26944     5d/pop-to-ebp
26945     c3/return
26946 
26947 #######################################################
26948 # Code-generation
26949 #######################################################
26950 
26951 == data
26952 
26953 # Global state added to each var record when performing code-generation.
26954 Curr-local-stack-offset:  # (addr int)
26955     0/imm32
26956 
26957 == code
26958 
26959 # We may not need to pass err/ed everywhere here. I think they're relics of Mu
26960 # getting type checks later in life.
26961 # But we do need them for runtime checks, particularly array index bounds checks.
26962 # So perhaps it's not worth taking them out. They're a safety net.
26963 
26964 emit-subx:  # out: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
26965     # . prologue
26966     55/push-ebp
26967     89/<- %ebp 4/r32/esp
26968     # . save registers
26969     50/push-eax
26970     # var curr/eax: (addr function) = *Program->functions
26971     (lookup *_Program-functions *_Program-functions->payload)  # => eax
26972     {
26973       # if (curr == null) break
26974       3d/compare-eax-and 0/imm32
26975       0f 84/jump-if-= break/disp32
26976       (emit-subx-function *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10))
26977       # curr = lookup(curr->next)
26978       (lookup *(eax+0x20) *(eax+0x24))  # Function-next Function-next => eax
26979       e9/jump loop/disp32
26980     }
26981 $emit-subx:end:
26982     # . restore registers
26983     58/pop-to-eax
26984     # . epilogue
26985     89/<- %esp 5/r32/ebp
26986     5d/pop-to-ebp
26987     c3/return
26988 
26989 emit-subx-function:  # out: (addr buffered-file), f: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
26990     # . prologue
26991     55/push-ebp
26992     89/<- %ebp 4/r32/esp
26993     # some preprocessing
26994     (populate-mu-type-offsets-in-inouts *(ebp+0xc))
26995     # . save registers
26996     50/push-eax
26997     51/push-ecx
26998     52/push-edx
26999     # initialize some global state
27000     c7 0/subop/copy *Curr-block-depth 1/imm32  # Important: keep this in sync with the parse phase
27001     c7 0/subop/copy *Curr-local-stack-offset 0/imm32
27002     # ecx = f
27003     8b/-> *(ebp+0xc) 1/r32/ecx
27004     # var vars/edx: (stack (addr var) 256)
27005     81 5/subop/subtract %esp 0xc00/imm32
27006     68/push 0xc00/imm32/size
27007     68/push 0/imm32/top
27008     89/<- %edx 4/r32/esp
27009     # var name/eax: (addr array byte) = lookup(f->name)
27010     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
27011     #
27012     (write-buffered *(ebp+8) %eax)
27013     (write-buffered *(ebp+8) ":\n")
27014     (emit-subx-prologue *(ebp+8))
27015     # var body/eax: (addr block) = lookup(f->body)
27016     (lookup *(ecx+0x18) *(ecx+0x1c))  # Function-body Function-body => eax
27017     #
27018     (emit-subx-block *(ebp+8) %eax %edx *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
27019     (emit-subx-epilogue *(ebp+8))
27020     # TODO: validate that *Curr-block-depth and *Curr-local-stack-offset have
27021     # been cleaned up
27022 $emit-subx-function:end:
27023     # . reclaim locals
27024     81 0/subop/add %esp 0xc08/imm32
27025     # . restore registers
27026     5a/pop-to-edx
27027     59/pop-to-ecx
27028     58/pop-to-eax
27029     # . epilogue
27030     89/<- %esp 5/r32/ebp
27031     5d/pop-to-ebp
27032     c3/return
27033 
27034 populate-mu-type-offsets-in-inouts:  # f: (addr function)
27035     # . prologue
27036     55/push-ebp
27037     89/<- %ebp 4/r32/esp
27038     # . save registers
27039     50/push-eax
27040     51/push-ecx
27041     52/push-edx
27042     53/push-ebx
27043     57/push-edi
27044     # var next-offset/edx: int = 8
27045     ba/copy-to-edx 8/imm32
27046     # var curr/ecx: (addr list var) = lookup(f->inouts)
27047     8b/-> *(ebp+8) 1/r32/ecx
27048     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
27049     89/<- %ecx 0/r32/eax
27050     {
27051 $populate-mu-type-offsets-in-inouts:loop:
27052       81 7/subop/compare %ecx 0/imm32
27053       74/jump-if-= break/disp8
27054       # var v/ebx: (addr var) = lookup(curr->value)
27055       (lookup *ecx *(ecx+4))  # List-value List-value => eax
27056       89/<- %ebx 0/r32/eax
27057 #?       (lookup *ebx *(ebx+4))
27058 #?       (write-buffered Stderr "setting offset of fn inout ")
27059 #?       (write-buffered Stderr %eax)
27060 #?       (write-buffered Stderr "@")
27061 #?       (write-int32-hex-buffered Stderr %ebx)
27062 #?       (write-buffered Stderr " to ")
27063 #?       (write-int32-hex-buffered Stderr %edx)
27064 #?       (write-buffered Stderr Newline)
27065 #?       (flush Stderr)
27066       # v->offset = next-offset
27067       89/<- *(ebx+0x14) 2/r32/edx  # Var-offset
27068       # next-offset += size-of(v)
27069       (size-of %ebx)  # => eax
27070       01/add-to %edx 0/r32/eax
27071       # curr = lookup(curr->next)
27072       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
27073       89/<- %ecx 0/r32/eax
27074       #
27075       eb/jump loop/disp8
27076     }
27077 $populate-mu-type-offsets-in-inouts:end:
27078     # . restore registers
27079     5f/pop-to-edi
27080     5b/pop-to-ebx
27081     5a/pop-to-edx
27082     59/pop-to-ecx
27083     58/pop-to-eax
27084     # . epilogue
27085     89/<- %esp 5/r32/ebp
27086     5d/pop-to-ebp
27087     c3/return
27088 
27089 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)
27090     # . prologue
27091     55/push-ebp
27092     89/<- %ebp 4/r32/esp
27093     # . save registers
27094     50/push-eax
27095     51/push-ecx
27096     53/push-ebx
27097     56/push-esi
27098     # esi = stmts
27099     8b/-> *(ebp+0xc) 6/r32/esi
27100     #
27101     {
27102 $emit-subx-stmt-list:loop:
27103       81 7/subop/compare %esi 0/imm32
27104       0f 84/jump-if-= break/disp32
27105       # var curr-stmt/ecx: (addr stmt) = lookup(stmts->value)
27106       (lookup *esi *(esi+4))  # List-value List-value => eax
27107       89/<- %ecx 0/r32/eax
27108       {
27109 $emit-subx-stmt-list:check-for-block:
27110         81 7/subop/compare *ecx 0/imm32/block  # Stmt-tag
27111         75/jump-if-!= break/disp8
27112 $emit-subx-stmt-list:block:
27113         (emit-subx-block *(ebp+8) %ecx *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
27114       }
27115       {
27116 $emit-subx-stmt-list:check-for-stmt:
27117         81 7/subop/compare *ecx 1/imm32/stmt1  # Stmt-tag
27118         0f 85/jump-if-!= break/disp32
27119 $emit-subx-stmt-list:stmt1:
27120         {
27121           (mu-branch? %ecx)  # => eax
27122           3d/compare-eax-and 0/imm32/false
27123           0f 84/jump-if-= break/disp32
27124 $emit-subx-stmt-list:branch-stmt:
27125 +-- 25 lines: # unconditional return ----------------------------------------------------------------------------------------------------------------------------------------------------
27150 +-- 27 lines: # unconditional loops -----------------------------------------------------------------------------------------------------------------------------------------------------
27177 +-- 16 lines: # unconditional breaks ----------------------------------------------------------------------------------------------------------------------------------------------------
27193 +-- 38 lines: # simple conditional branches without a target ----------------------------------------------------------------------------------------------------------------------------
27231 +-- 19 lines: # conditional branches with an explicit target ----------------------------------------------------------------------------------------------------------------------------
27250         }
27251 $emit-subx-stmt-list:1-to-1:
27252         (emit-subx-stmt *(ebp+8) %ecx Primitives *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
27253         e9/jump $emit-subx-stmt-list:continue/disp32
27254       }
27255       {
27256 $emit-subx-stmt-list:check-for-var-def:
27257         81 7/subop/compare *ecx 2/imm32/var-def  # Stmt-tag
27258         75/jump-if-!= break/disp8
27259 $emit-subx-stmt-list:var-def:
27260         (emit-subx-var-def *(ebp+8) %ecx)
27261         (push *(ebp+0x10) *(ecx+4))  # Vardef-var
27262         (push *(ebp+0x10) *(ecx+8))  # Vardef-var
27263         (push *(ebp+0x10) 0)  # Live-var-register-spilled = 0 for vars on the stack
27264         #
27265         eb/jump $emit-subx-stmt-list:continue/disp8
27266       }
27267       {
27268 $emit-subx-stmt-list:check-for-reg-var-def:
27269         81 7/subop/compare *ecx 3/imm32/reg-var-def  # Stmt-tag
27270         0f 85/jump-if-!= break/disp32
27271 $emit-subx-stmt-list:reg-var-def:
27272         # TODO: ensure that there's exactly one output
27273         (push-output-and-maybe-emit-spill *(ebp+8) %ecx *(ebp+0x10) %esi *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
27274         # emit the instruction as usual
27275         (emit-subx-stmt *(ebp+8) %ecx Primitives *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
27276         #
27277         eb/jump $emit-subx-stmt-list:continue/disp8
27278       }
27279 $emit-subx-stmt-list:continue:
27280       # TODO: raise an error on unrecognized Stmt-tag
27281       (lookup *(esi+8) *(esi+0xc))  # List-next List-next => eax
27282       89/<- %esi 0/r32/eax
27283       e9/jump loop/disp32
27284     }
27285 $emit-subx-stmt-list:emit-cleanup:
27286     (emit-cleanup-code-until-depth *(ebp+8) *(ebp+0x10) *Curr-block-depth)
27287 $emit-subx-stmt-list:clean-up:
27288     (clean-up-stack-offset-state *(ebp+0x10) *Curr-block-depth)
27289     (clean-up-blocks *(ebp+0x10) *Curr-block-depth *(ebp+0x14))
27290 $emit-subx-stmt-list:end:
27291     # . restore registers
27292     5e/pop-to-esi
27293     5b/pop-to-ebx
27294     59/pop-to-ecx
27295     58/pop-to-eax
27296     # . epilogue
27297     89/<- %esp 5/r32/ebp
27298     5d/pop-to-ebp
27299     c3/return
27300 
27301 # 'later-stmts' includes 'stmt', but will behave the same even without it; reg-var-def stmts are guaranteed not to write to function outputs.
27302 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)
27303     # . prologue
27304     55/push-ebp
27305     89/<- %ebp 4/r32/esp
27306     # . save registers
27307     50/push-eax
27308     51/push-ecx
27309     52/push-edx
27310     # ecx = stmt
27311     8b/-> *(ebp+0xc) 1/r32/ecx
27312     # var sv/eax: (addr stmt-var) = lookup(curr-stmt->outputs)
27313     (lookup *(ecx+0x14) *(ecx+0x18))  # Regvardef-outputs Regvardef-outputs => eax
27314     # TODO: assert !sv->is-deref?
27315     # var v/ecx: (addr var) = lookup(sv->value)
27316     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27317     89/<- %ecx 0/r32/eax
27318     # v->block-depth = *Curr-block-depth
27319     8b/-> *Curr-block-depth 0/r32/eax
27320     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
27321 #?     (write-buffered Stderr "var ")
27322 #?     (lookup *ecx *(ecx+4))
27323 #?     (write-buffered Stderr %eax)
27324 #?     (write-buffered Stderr " at depth ")
27325 #?     (write-int32-hex-buffered Stderr *(ecx+0x10))
27326 #?     (write-buffered Stderr Newline)
27327 #?     (flush Stderr)
27328     # ensure that v is in a register
27329     81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
27330     0f 84/jump-if-= $push-output-and-maybe-emit-spill:abort/disp32
27331     # var emit-spill?/edx: boolean = not-yet-spilled-this-block? && will-not-write-some-register?(fn)
27332     (not-yet-spilled-this-block? %ecx *(ebp+0x10))  # => eax
27333     89/<- %edx 0/r32/eax
27334     3d/compare-eax-and 0/imm32/false
27335     0f 84/jump-if-= $push-output-and-maybe-emit-spill:push/disp32
27336     (will-not-write-some-register? %ecx *(ebp+0x14) *(ebp+0x18))  # => eax
27337     89/<- %edx 0/r32/eax
27338     # check emit-spill?
27339     3d/compare-eax-and 0/imm32/false
27340     0f 84/jump-if-= $push-output-and-maybe-emit-spill:push/disp32
27341     # TODO: assert(size-of(output) == 4)
27342     # *Curr-local-stack-offset -= 4
27343     81 5/subop/subtract *Curr-local-stack-offset 4/imm32
27344     # emit spill
27345     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
27346     (emit-push-register *(ebp+8) %eax)
27347 $push-output-and-maybe-emit-spill:push:
27348     8b/-> *(ebp+0xc) 1/r32/ecx
27349     (lookup *(ecx+0x14) *(ecx+0x18))  # Regvardef-outputs Regvardef-outputs => eax
27350     # push(vars, {sv->value, emit-spill?})
27351     (push *(ebp+0x10) *eax)  # Stmt-var-value
27352     (push *(ebp+0x10) *(eax+4))  # Stmt-var-value
27353     (push *(ebp+0x10) %edx)
27354 $push-output-and-maybe-emit-spill:end:
27355     # . restore registers
27356     5a/pop-to-edx
27357     59/pop-to-ecx
27358     58/pop-to-eax
27359     # . epilogue
27360     89/<- %esp 5/r32/ebp
27361     5d/pop-to-ebp
27362     c3/return
27363 
27364 $push-output-and-maybe-emit-spill:abort:
27365     # error("var '" var->name "' initialized from an instruction must live in a register\n")
27366     (write-buffered *(ebp+0x1c) "var '")
27367     (write-buffered *(ebp+0x1c) *eax)  # Var-name
27368     (write-buffered *(ebp+0x1c) "' initialized from an instruction must live in a register\n")
27369     (flush *(ebp+0x1c))
27370     (stop *(ebp+0x20) 1)
27371     # never gets here
27372 
27373 emit-subx-cleanup-and-unconditional-nonlocal-branch:  # out: (addr buffered-file), stmt: (addr stmt1), vars: (addr stack live-var)
27374     # . prologue
27375     55/push-ebp
27376     89/<- %ebp 4/r32/esp
27377     # . save registers
27378     50/push-eax
27379     51/push-ecx
27380     # ecx = stmt
27381     8b/-> *(ebp+0xc) 1/r32/ecx
27382     # var target/eax: (addr array byte) = curr-stmt->inouts->value->name
27383     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27384     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27385     (lookup *eax *(eax+4))  # Var-name Var-name => eax
27386     # clean up until target block
27387     (emit-cleanup-code-until-target *(ebp+8) *(ebp+0x10) %eax)
27388     # emit jump to target block
27389     (emit-indent *(ebp+8) *Curr-block-depth)
27390     (write-buffered *(ebp+8) "e9/jump ")
27391     (write-buffered *(ebp+8) %eax)
27392     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
27393     (string-starts-with? %eax "break")
27394     3d/compare-eax-and 0/imm32/false
27395     {
27396       74/jump-if-= break/disp8
27397       (write-buffered *(ebp+8) ":break/disp32\n")
27398       eb/jump $emit-subx-cleanup-and-unconditional-nonlocal-branch:end/disp8
27399     }
27400     (write-buffered *(ebp+8) ":loop/disp32\n")
27401 $emit-subx-cleanup-and-unconditional-nonlocal-branch:end:
27402     # . restore registers
27403     59/pop-to-ecx
27404     58/pop-to-eax
27405     # . epilogue
27406     89/<- %esp 5/r32/ebp
27407     5d/pop-to-ebp
27408     c3/return
27409 
27410 emit-outputs:  # out: (addr buffered-file), return-stmt: (addr stmt1), fn: (addr function)
27411     # . prologue
27412     55/push-ebp
27413     89/<- %ebp 4/r32/esp
27414     # . save registers
27415     50/push-eax
27416     51/push-ecx
27417     56/push-esi
27418     57/push-edi
27419     # var curr-inout/esi: (addr stmt-var) = return-stmt->inouts
27420     8b/-> *(ebp+0xc) 0/r32/eax
27421     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27422     89/<- %esi 0/r32/eax
27423     # var curr-output/edi: (addr list var) = fn->outputs
27424     8b/-> *(ebp+0x10) 0/r32/eax
27425     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
27426     89/<- %edi 0/r32/eax
27427     {
27428 $emit-outputs:loop:
27429       81 7/subop/compare %esi 0/imm32
27430       0f 84/jump-if-= break/disp32
27431       # emit copy to output register
27432       # var curr-output-register/ecx: (addr array byte) = curr-output->value->register
27433       (lookup *edi *(edi+4))  # List-value List-value => eax
27434       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
27435       89/<- %ecx 0/r32/eax
27436       # if curr-output-register starts with "x", emit a floating-point copy
27437       8a/copy-byte *(ecx+4) 0/r32/AL
27438       81 4/subop/and %eax 0xff/imm32
27439       3d/compare-eax-and 0x78/imm32/x
27440       {
27441         75/jump-if-!= break/disp8
27442         (emit-float-output *(ebp+8) %esi %ecx)
27443         eb/jump $emit-outputs:continue/disp8
27444       }
27445       # otherwise emit an int copy
27446       (emit-int-output *(ebp+8) %esi %ecx)
27447 $emit-outputs:continue:
27448       # curr-inout = curr-inout->next
27449       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
27450       89/<- %esi 0/r32/eax
27451       # curr-output = curr-output->next
27452       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
27453       89/<- %edi 0/r32/eax
27454       #
27455       e9/jump loop/disp32
27456     }
27457 $emit-outputs:end:
27458     # . restore registers
27459     5f/pop-to-edi
27460     5e/pop-to-esi
27461     59/pop-to-ecx
27462     58/pop-to-eax
27463     # . epilogue
27464     89/<- %esp 5/r32/ebp
27465     5d/pop-to-ebp
27466     c3/return
27467 
27468 emit-int-output:  # out: (addr buffered-file), return-var: (addr stmt-var), dest-reg: (addr array byte)
27469     # . prologue
27470     55/push-ebp
27471     89/<- %ebp 4/r32/esp
27472     # . save registers
27473     50/push-eax
27474     51/push-ecx
27475     # ecx = return-var->value
27476     8b/-> *(ebp+0xc) 0/r32/eax
27477     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27478     89/<- %ecx 0/r32/eax
27479     # if curr-var is a literal, emit copy of a literal to the output
27480     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
27481     (simple-mu-type? %eax 0)  # literal => eax
27482     {
27483       3d/compare-eax-and 0/imm32/false
27484       0f 84/jump-if-= break/disp32
27485       (emit-indent *(ebp+8) *Curr-block-depth)
27486       (write-buffered *(ebp+8) "c7 0/subop/copy %")
27487       (write-buffered *(ebp+8) *(ebp+0x10))
27488       (write-buffered *(ebp+8) " ")
27489       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
27490       (write-buffered *(ebp+8) %eax)
27491       (write-buffered *(ebp+8) "/imm32\n")
27492       e9/jump $emit-int-output:end/disp32
27493     }
27494     # otherwise emit an integer copy
27495     (emit-indent *(ebp+8) *Curr-block-depth)
27496     (write-buffered *(ebp+8) "8b/->")
27497     (emit-subx-var-as-rm32 *(ebp+8) *(ebp+0xc))
27498     (write-buffered *(ebp+8) " ")
27499     (get Mu-registers *(ebp+0x10) 0xc "Mu-registers")  # => eax
27500     (write-int32-hex-buffered *(ebp+8) *eax)
27501     (write-buffered *(ebp+8) "/r32\n")
27502 $emit-int-output:end:
27503     # . restore registers
27504     59/pop-to-ecx
27505     58/pop-to-eax
27506     # . epilogue
27507     89/<- %esp 5/r32/ebp
27508     5d/pop-to-ebp
27509     c3/return
27510 
27511 emit-float-output:  # out: (addr buffered-file), return-var: (addr stmt-var), dest-reg: (addr array byte)
27512     # . prologue
27513     55/push-ebp
27514     89/<- %ebp 4/r32/esp
27515     # . save registers
27516     50/push-eax
27517     #
27518     (emit-indent *(ebp+8) *Curr-block-depth)
27519     (write-buffered *(ebp+8) "f3 0f 10/->")
27520     (emit-subx-var-as-rm32 *(ebp+8) *(ebp+0xc))
27521     (write-buffered *(ebp+8) " ")
27522     (get Mu-registers *(ebp+0x10) 0xc "Mu-registers")  # => eax
27523     (write-int32-hex-buffered *(ebp+8) *eax)
27524     (write-buffered *(ebp+8) "/x32\n")
27525 $emit-float-output:end:
27526     # . restore registers
27527     58/pop-to-eax
27528     # . epilogue
27529     89/<- %esp 5/r32/ebp
27530     5d/pop-to-ebp
27531     c3/return
27532 
27533 mu-branch?:  # stmt: (addr stmt1) -> result/eax: boolean
27534     # . prologue
27535     55/push-ebp
27536     89/<- %ebp 4/r32/esp
27537     # . save registers
27538     51/push-ecx
27539     # ecx = lookup(stmt->operation)
27540     8b/-> *(ebp+8) 1/r32/ecx
27541     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
27542     89/<- %ecx 0/r32/eax
27543     # if (stmt->operation starts with "loop") return true
27544     (string-starts-with? %ecx "loop")  # => eax
27545     3d/compare-eax-and 0/imm32/false
27546     75/jump-if-not-equal $mu-branch?:end/disp8
27547     # if (stmt->operation starts with "break") return true
27548     (string-starts-with? %ecx "break")  # => eax
27549     3d/compare-eax-and 0/imm32/false
27550     75/jump-if-not-equal $mu-branch?:end/disp8
27551     # otherwise return (stmt->operation starts with "return")
27552     (string-starts-with? %ecx "return")  # => eax
27553 $mu-branch?:end:
27554     # . restore registers
27555     59/pop-to-ecx
27556     # . epilogue
27557     89/<- %esp 5/r32/ebp
27558     5d/pop-to-ebp
27559     c3/return
27560 
27561 emit-reverse-break:  # out: (addr buffered-file), stmt: (addr stmt1)
27562     # . prologue
27563     55/push-ebp
27564     89/<- %ebp 4/r32/esp
27565     # . save registers
27566     50/push-eax
27567     # eax = stmt
27568     8b/-> *(ebp+0xc) 0/r32/eax
27569     #
27570     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
27571     (get Reverse-branch %eax 0x10 "reverse-branch: ")  # => eax: (addr handle array byte)
27572     (emit-indent *(ebp+8) *Curr-block-depth)
27573     (lookup *eax *(eax+4))  # => eax
27574     (write-buffered *(ebp+8) %eax)
27575     (write-buffered *(ebp+8) " break/disp32\n")
27576 $emit-reverse-break:end:
27577     # . restore registers
27578     58/pop-to-eax
27579     # . epilogue
27580     89/<- %esp 5/r32/ebp
27581     5d/pop-to-ebp
27582     c3/return
27583 
27584 == data
27585 
27586 # Table from Mu branch instructions to the reverse SubX opcodes for them.
27587 Reverse-branch:  # (table (handle array byte) (handle array byte))
27588   # a table is a stream
27589   0x1c0/imm32/write
27590   0/imm32/read
27591   0x1c0/imm32/size
27592   # data
27593   0x11/imm32/alloc-id   _string-break-if-=/imm32                0x11/imm32/alloc-id   _string_0f_85_jump_label/imm32
27594   0x11/imm32/alloc-id   _string-loop-if-=/imm32                 0x11/imm32/alloc-id   _string_0f_85_jump_label/imm32
27595   0x11/imm32/alloc-id   _string-break-if-!=/imm32               0x11/imm32/alloc-id   _string_0f_84_jump_label/imm32
27596   0x11/imm32/alloc-id   _string-loop-if-!=/imm32                0x11/imm32/alloc-id   _string_0f_84_jump_label/imm32
27597   0x11/imm32/alloc-id   _string-break-if-</imm32                0x11/imm32/alloc-id   _string_0f_8d_jump_label/imm32
27598   0x11/imm32/alloc-id   _string-loop-if-</imm32                 0x11/imm32/alloc-id   _string_0f_8d_jump_label/imm32
27599   0x11/imm32/alloc-id   _string-break-if->/imm32                0x11/imm32/alloc-id   _string_0f_8e_jump_label/imm32
27600   0x11/imm32/alloc-id   _string-loop-if->/imm32                 0x11/imm32/alloc-id   _string_0f_8e_jump_label/imm32
27601   0x11/imm32/alloc-id   _string-break-if-<=/imm32               0x11/imm32/alloc-id   _string_0f_8f_jump_label/imm32
27602   0x11/imm32/alloc-id   _string-loop-if-<=/imm32                0x11/imm32/alloc-id   _string_0f_8f_jump_label/imm32
27603   0x11/imm32/alloc-id   _string-break-if->=/imm32               0x11/imm32/alloc-id   _string_0f_8c_jump_label/imm32
27604   0x11/imm32/alloc-id   _string-loop-if->=/imm32                0x11/imm32/alloc-id   _string_0f_8c_jump_label/imm32
27605   0x11/imm32/alloc-id   _string-break-if-addr</imm32            0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
27606   0x11/imm32/alloc-id   _string-loop-if-addr</imm32             0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
27607   0x11/imm32/alloc-id   _string-break-if-addr>/imm32            0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
27608   0x11/imm32/alloc-id   _string-loop-if-addr>/imm32             0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
27609   0x11/imm32/alloc-id   _string-break-if-addr<=/imm32           0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
27610   0x11/imm32/alloc-id   _string-loop-if-addr<=/imm32            0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
27611   0x11/imm32/alloc-id   _string-break-if-addr>=/imm32           0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
27612   0x11/imm32/alloc-id   _string-loop-if-addr>=/imm32            0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
27613   0x11/imm32/alloc-id   _string-break-if-float</imm32           0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
27614   0x11/imm32/alloc-id   _string-loop-if-float</imm32            0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
27615   0x11/imm32/alloc-id   _string-break-if-float>/imm32           0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
27616   0x11/imm32/alloc-id   _string-loop-if-float>/imm32            0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
27617   0x11/imm32/alloc-id   _string-break-if-float<=/imm32          0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
27618   0x11/imm32/alloc-id   _string-loop-if-float<=/imm32           0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
27619   0x11/imm32/alloc-id   _string-break-if-float>=/imm32          0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
27620   0x11/imm32/alloc-id   _string-loop-if-float>=/imm32           0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
27621 
27622 == code
27623 
27624 emit-unconditional-jump-to-depth:  # out: (addr buffered-file), vars: (addr stack live-var), depth: int, label-suffix: (addr array byte)
27625     # . prologue
27626     55/push-ebp
27627     89/<- %ebp 4/r32/esp
27628     # . save registers
27629     50/push-eax
27630     51/push-ecx
27631     52/push-edx
27632     53/push-ebx
27633     56/push-esi
27634     # ecx = vars
27635     8b/-> *(ebp+0xc) 1/r32/ecx
27636     # var eax: int = vars->top
27637     8b/-> *ecx 0/r32/eax
27638     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
27639     8d/copy-address *(ecx+eax-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
27640     # var min/ecx: (addr handle var) = vars->data
27641     8d/copy-address *(ecx+8) 1/r32/ecx
27642     # edx = depth
27643     8b/-> *(ebp+0x10) 2/r32/edx
27644     {
27645 $emit-unconditional-jump-to-depth:loop:
27646       # if (curr < min) break
27647       39/compare %esi 1/r32/ecx
27648       0f 82/jump-if-addr< break/disp32
27649       # var v/ebx: (addr var) = lookup(*curr)
27650       (lookup *esi *(esi+4))  # => eax
27651       89/<- %ebx 0/r32/eax
27652       # if (v->block-depth < until-block-depth) break
27653       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
27654       0f 8c/jump-if-< break/disp32
27655       {
27656 $emit-unconditional-jump-to-depth:check:
27657         # if v->block-depth != until-block-depth, continue
27658         39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
27659         0f 85/jump-if-!= break/disp32
27660 $emit-unconditional-jump-to-depth:depth-found:
27661         # if v is not a literal, continue
27662         (size-of %ebx)  # => eax
27663         3d/compare-eax-and 0/imm32
27664         0f 85/jump-if-!= break/disp32
27665 $emit-unconditional-jump-to-depth:label-found:
27666         # emit unconditional jump, then return
27667         (emit-indent *(ebp+8) *Curr-block-depth)
27668         (write-buffered *(ebp+8) "e9/jump ")
27669         (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
27670         (write-buffered *(ebp+8) %eax)
27671         (write-buffered *(ebp+8) ":")
27672         (write-buffered *(ebp+8) *(ebp+0x14))
27673         (write-buffered *(ebp+8) "/disp32\n")
27674         eb/jump $emit-unconditional-jump-to-depth:end/disp8
27675       }
27676       # curr -= 12
27677       81 5/subop/subtract %esi 0xc/imm32
27678       e9/jump loop/disp32
27679     }
27680     # TODO: error if no label at 'depth' was found
27681 $emit-unconditional-jump-to-depth:end:
27682     # . restore registers
27683     5e/pop-to-esi
27684     5b/pop-to-ebx
27685     5a/pop-to-edx
27686     59/pop-to-ecx
27687     58/pop-to-eax
27688     # . epilogue
27689     89/<- %esp 5/r32/ebp
27690     5d/pop-to-ebp
27691     c3/return
27692 
27693 # emit clean-up code for 'vars' until some block depth
27694 # doesn't actually modify 'vars' so we need traverse manually inside the stack
27695 emit-cleanup-code-until-depth:  # out: (addr buffered-file), vars: (addr stack live-var), until-block-depth: int
27696     # . prologue
27697     55/push-ebp
27698     89/<- %ebp 4/r32/esp
27699     # . save registers
27700     50/push-eax
27701     51/push-ecx
27702     52/push-edx
27703     53/push-ebx
27704     56/push-esi
27705 #?     (write-buffered Stderr "--- cleanup\n")
27706 #?     (flush Stderr)
27707     # ecx = vars
27708     8b/-> *(ebp+0xc) 1/r32/ecx
27709     # var esi: int = vars->top
27710     8b/-> *ecx 6/r32/esi
27711     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
27712     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
27713     # var min/ecx: (addr handle var) = vars->data
27714     81 0/subop/add %ecx 8/imm32
27715     # edx = until-block-depth
27716     8b/-> *(ebp+0x10) 2/r32/edx
27717     {
27718 $emit-cleanup-code-until-depth:loop:
27719       # if (curr < min) break
27720       39/compare %esi 1/r32/ecx
27721       0f 82/jump-if-addr< break/disp32
27722       # var v/ebx: (addr var) = lookup(*curr)
27723       (lookup *esi *(esi+4))  # => eax
27724       89/<- %ebx 0/r32/eax
27725 #?       (lookup *ebx *(ebx+4))  # Var-name
27726 #?       (write-buffered Stderr "var ")
27727 #?       (write-buffered Stderr %eax)
27728 #?       (write-buffered Stderr Newline)
27729 #?       (flush Stderr)
27730       # if (v->block-depth < until-block-depth) break
27731       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
27732       0f 8c/jump-if-< break/disp32
27733       # if v is in a register
27734       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
27735       {
27736         0f 84/jump-if-= break/disp32
27737         {
27738 $emit-cleanup-code-until-depth:check-for-previous-spill:
27739           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
27740           3d/compare-eax-and 0/imm32/false
27741           74/jump-if-= break/disp8
27742 $emit-cleanup-code-until-depth:reclaim-var-in-register:
27743           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
27744           (emit-pop-register *(ebp+8) %eax)
27745         }
27746         eb/jump $emit-cleanup-code-until-depth:continue/disp8
27747       }
27748       # otherwise v is on the stack
27749       {
27750         75/jump-if-!= break/disp8
27751 $emit-cleanup-code-until-depth:var-on-stack:
27752         (size-of %ebx)  # => eax
27753         # don't emit code for labels
27754         3d/compare-eax-and 0/imm32
27755         74/jump-if-= break/disp8
27756 $emit-cleanup-code-until-depth:reclaim-var-on-stack:
27757         (emit-indent *(ebp+8) *Curr-block-depth)
27758         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
27759         (write-int32-hex-buffered *(ebp+8) %eax)
27760         (write-buffered *(ebp+8) "/imm32\n")
27761       }
27762 $emit-cleanup-code-until-depth:continue:
27763       # curr -= 12
27764       81 5/subop/subtract %esi 0xc/imm32
27765       e9/jump loop/disp32
27766     }
27767 $emit-cleanup-code-until-depth:end:
27768     # . restore registers
27769     5e/pop-to-esi
27770     5b/pop-to-ebx
27771     5a/pop-to-edx
27772     59/pop-to-ecx
27773     58/pop-to-eax
27774     # . epilogue
27775     89/<- %esp 5/r32/ebp
27776     5d/pop-to-ebp
27777     c3/return
27778 
27779 # emit clean-up code for 'vars' that don't conflict with output registers
27780 # doesn't actually modify 'vars' so we need traverse manually inside the stack
27781 emit-cleanup-code-for-non-outputs:  # out: (addr buffered-file), vars: (addr stack live-var), fn: (addr function)
27782     # . prologue
27783     55/push-ebp
27784     89/<- %ebp 4/r32/esp
27785     # . save registers
27786     50/push-eax
27787     51/push-ecx
27788     52/push-edx
27789     53/push-ebx
27790     56/push-esi
27791     57/push-edi
27792     # ecx = vars
27793     8b/-> *(ebp+0xc) 1/r32/ecx
27794     # var esi: int = vars->top
27795     8b/-> *ecx 6/r32/esi
27796     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
27797     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
27798     # var min/ecx: (addr handle var) = vars->data
27799     81 0/subop/add %ecx 8/imm32
27800     {
27801 $emit-cleanup-code-for-non-outputs:loop:
27802       # if (curr < min) break
27803       39/compare %esi 1/r32/ecx
27804       0f 82/jump-if-addr< break/disp32
27805       # var v/ebx: (addr var) = lookup(*curr)
27806       (lookup *esi *(esi+4))  # => eax
27807       89/<- %ebx 0/r32/eax
27808       # if v is in a register
27809       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
27810       {
27811         0f 84/jump-if-= break/disp32
27812         {
27813 $emit-cleanup-code-for-non-outputs:check-for-previous-spill:
27814           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
27815           3d/compare-eax-and 0/imm32/false
27816           0f 84/jump-if-= break/disp32
27817 $emit-cleanup-code-for-non-outputs:reclaim-var-in-register:
27818           # var reg/edi: (addr array name) = v->register
27819           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
27820           89/<- %edi 0/r32/eax
27821           # if reg is not in function outputs, emit a pop
27822           (reg-in-function-outputs? *(ebp+0x10) %edi)  # => eax
27823           3d/compare-eax-and 0/imm32/false
27824           {
27825             75/jump-if-!= break/disp8
27826             (emit-pop-register *(ebp+8) %edi)
27827             eb/jump $emit-cleanup-code-for-non-outputs:reclaim-var-in-register-done/disp8
27828           }
27829           # otherwise just drop it from the stack
27830           (emit-indent *(ebp+8) *Curr-block-depth)
27831           (write-buffered *(ebp+8) "81 0/subop/add %esp 4/imm32\n")
27832         }
27833 $emit-cleanup-code-for-non-outputs:reclaim-var-in-register-done:
27834         eb/jump $emit-cleanup-code-for-non-outputs:continue/disp8
27835       }
27836       # otherwise v is on the stack
27837       {
27838         75/jump-if-!= break/disp8
27839 $emit-cleanup-code-for-non-outputs:var-on-stack:
27840         (size-of %ebx)  # => eax
27841         # don't emit code for labels
27842         3d/compare-eax-and 0/imm32
27843         74/jump-if-= break/disp8
27844 $emit-cleanup-code-for-non-outputs:reclaim-var-on-stack:
27845         (emit-indent *(ebp+8) *Curr-block-depth)
27846         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
27847         (write-int32-hex-buffered *(ebp+8) %eax)
27848         (write-buffered *(ebp+8) "/imm32\n")
27849       }
27850 $emit-cleanup-code-for-non-outputs:continue:
27851       # curr -= 12
27852       81 5/subop/subtract %esi 0xc/imm32
27853       e9/jump loop/disp32
27854     }
27855 $emit-cleanup-code-for-non-outputs:end:
27856     # . restore registers
27857     5f/pop-to-edi
27858     5e/pop-to-esi
27859     5b/pop-to-ebx
27860     5a/pop-to-edx
27861     59/pop-to-ecx
27862     58/pop-to-eax
27863     # . epilogue
27864     89/<- %esp 5/r32/ebp
27865     5d/pop-to-ebp
27866     c3/return
27867 
27868 emit-push-register:  # out: (addr buffered-file), reg: (addr array byte)
27869     # . prologue
27870     55/push-ebp
27871     89/<- %ebp 4/r32/esp
27872     # eax = reg
27873     8b/-> *(ebp+0xc) 0/r32/eax
27874     # var prefix/eax: byte = reg->data[0]
27875     8a/copy-byte *(eax+4) 0/r32/AL
27876     81 4/subop/and %eax 0xff/imm32
27877     # if (prefix == 'x') push xmm register
27878     {
27879       3d/compare-eax-and 0x78/imm32/x
27880       0f 85/jump-if-!= break/disp32
27881       # TODO validate register
27882       (emit-indent *(ebp+8) *Curr-block-depth)
27883       (write-buffered *(ebp+8) "81 5/subop/subtract %esp 4/imm32\n")
27884       (emit-indent *(ebp+8) *Curr-block-depth)
27885       (write-buffered *(ebp+8) "f3 0f 11/<- *esp ")
27886       # var prefix/eax: byte = reg->data[3]
27887       8b/-> *(ebp+0xc) 0/r32/eax
27888       8a/copy-byte *(eax+7) 0/r32/AL
27889       81 4/subop/and %eax 0xff/imm32
27890       (write-byte-buffered *(ebp+8) %eax)
27891       (write-buffered *(ebp+8) "/x32\n")
27892       e9/jump $emit-push-register:end/disp32
27893     }
27894     # otherwise push gp register
27895     (emit-indent *(ebp+8) *Curr-block-depth)
27896     (write-buffered *(ebp+8) "ff 6/subop/push %")
27897     (write-buffered *(ebp+8) *(ebp+0xc))
27898     (write-buffered *(ebp+8) Newline)
27899 $emit-push-register:end:
27900     # . epilogue
27901     89/<- %esp 5/r32/ebp
27902     5d/pop-to-ebp
27903     c3/return
27904 
27905 emit-pop-register:  # out: (addr buffered-file), reg: (addr array byte)
27906     # . prologue
27907     55/push-ebp
27908     89/<- %ebp 4/r32/esp
27909     # . save registers
27910     50/push-eax
27911     # eax = reg
27912     8b/-> *(ebp+0xc) 0/r32/eax
27913     # var prefix/eax: byte = reg->data[0]
27914     8a/copy-byte *(eax+4) 0/r32/AL
27915     81 4/subop/and %eax 0xff/imm32
27916     # if (prefix == 'x') pop to xmm register
27917     {
27918       3d/compare-eax-and 0x78/imm32/x
27919       0f 85/jump-if-!= break/disp32
27920       # TODO validate register
27921       (emit-indent *(ebp+8) *Curr-block-depth)
27922       (write-buffered *(ebp+8) "f3 0f 10/-> *esp ")
27923       # var prefix/eax: byte = reg->data[3]
27924       8b/-> *(ebp+0xc) 0/r32/eax
27925       8a/copy-byte *(eax+7) 0/r32/AL
27926       81 4/subop/and %eax 0xff/imm32
27927       (write-byte-buffered *(ebp+8) %eax)
27928       (write-buffered *(ebp+8) "/x32\n")
27929       (emit-indent *(ebp+8) *Curr-block-depth)
27930       (write-buffered *(ebp+8) "81 0/subop/add %esp 4/imm32\n")
27931       e9/jump $emit-pop-register:end/disp32
27932     }
27933     # otherwise pop to gp register
27934     (emit-indent *(ebp+8) *Curr-block-depth)
27935     (write-buffered *(ebp+8) "8f 0/subop/pop %")
27936     (write-buffered *(ebp+8) *(ebp+0xc))
27937     (write-buffered *(ebp+8) Newline)
27938 $emit-pop-register:end:
27939     # . restore registers
27940     58/pop-to-eax
27941     # . epilogue
27942     89/<- %esp 5/r32/ebp
27943     5d/pop-to-ebp
27944     c3/return
27945 
27946 # emit clean-up code for 'vars' until a given label is encountered
27947 # doesn't actually modify 'vars' so we need traverse manually inside the stack
27948 emit-cleanup-code-until-target:  # out: (addr buffered-file), vars: (addr stack live-var), until-block-label: (addr array byte)
27949     # . prologue
27950     55/push-ebp
27951     89/<- %ebp 4/r32/esp
27952     # . save registers
27953     50/push-eax
27954     51/push-ecx
27955     52/push-edx
27956     53/push-ebx
27957     # ecx = vars
27958     8b/-> *(ebp+0xc) 1/r32/ecx
27959     # var eax: int = vars->top
27960     8b/-> *ecx 0/r32/eax
27961     # var curr/edx: (addr handle var) = &vars->data[vars->top - 12]
27962     8d/copy-address *(ecx+eax-4) 2/r32/edx  # vars + 8 + vars->top - 12/Live-var-size
27963     # var min/ecx: (addr handle var) = vars->data
27964     81 0/subop/add %ecx 8/imm32
27965     {
27966 $emit-cleanup-code-until-target:loop:
27967       # if (curr < min) break
27968       39/compare %edx 1/r32/ecx
27969       0f 82/jump-if-addr< break/disp32
27970       # var v/ebx: (handle var) = lookup(*curr)
27971       (lookup *edx *(edx+4))  # => eax
27972       89/<- %ebx 0/r32/eax
27973       # if (v->name == until-block-label) break
27974       (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
27975       (string-equal? %eax *(ebp+0x10))  # => eax
27976       3d/compare-eax-and 0/imm32/false
27977       0f 85/jump-if-!= break/disp32
27978       # if v is in a register
27979       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
27980       {
27981         0f 84/jump-if-= break/disp32
27982         {
27983 $emit-cleanup-code-until-target:check-for-previous-spill:
27984           8b/-> *(edx+8) 0/r32/eax  # Live-var-register-spilled
27985           3d/compare-eax-and 0/imm32/false
27986           74/jump-if-= break/disp8
27987 $emit-cleanup-code-until-target:reclaim-var-in-register:
27988           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
27989           (emit-pop-register *(ebp+8) %eax)
27990         }
27991         eb/jump $emit-cleanup-code-until-target:continue/disp8
27992       }
27993       # otherwise v is on the stack
27994       {
27995         75/jump-if-!= break/disp8
27996 $emit-cleanup-code-until-target:reclaim-var-on-stack:
27997         (size-of %ebx)  # => eax
27998         # don't emit code for labels
27999         3d/compare-eax-and 0/imm32
28000         74/jump-if-= break/disp8
28001         #
28002         (emit-indent *(ebp+8) *Curr-block-depth)
28003         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
28004         (write-int32-hex-buffered *(ebp+8) %eax)
28005         (write-buffered *(ebp+8) "/imm32\n")
28006       }
28007 $emit-cleanup-code-until-target:continue:
28008       # curr -= 12
28009       81 5/subop/subtract %edx 0xc/imm32
28010       e9/jump loop/disp32
28011     }
28012 $emit-cleanup-code-until-target:end:
28013     # . restore registers
28014     5b/pop-to-ebx
28015     5a/pop-to-edx
28016     59/pop-to-ecx
28017     58/pop-to-eax
28018     # . epilogue
28019     89/<- %esp 5/r32/ebp
28020     5d/pop-to-ebp
28021     c3/return
28022 
28023 # update Curr-local-stack-offset assuming vars until some block depth are popped
28024 # doesn't actually modify 'vars', so we need traverse manually inside the stack
28025 clean-up-stack-offset-state:  # vars: (addr stack live-var), until-block-depth: int
28026     # . prologue
28027     55/push-ebp
28028     89/<- %ebp 4/r32/esp
28029     # . save registers
28030     50/push-eax
28031     51/push-ecx
28032     52/push-edx
28033     53/push-ebx
28034     56/push-esi
28035     # ecx = vars
28036     8b/-> *(ebp+8) 1/r32/ecx
28037     # var esi: int = vars->top
28038     8b/-> *ecx 6/r32/esi
28039     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
28040     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
28041     # var min/ecx: (addr handle var) = vars->data
28042     81 0/subop/add %ecx 8/imm32
28043     # edx = until-block-depth
28044     8b/-> *(ebp+0xc) 2/r32/edx
28045     {
28046 $clean-up-stack-offset-state:loop:
28047       # if (curr < min) break
28048       39/compare %esi 1/r32/ecx
28049       0f 82/jump-if-addr< break/disp32
28050       # var v/ebx: (addr var) = lookup(*curr)
28051       (lookup *esi *(esi+4))  # => eax
28052       89/<- %ebx 0/r32/eax
28053       # if (v->block-depth < until-block-depth) break
28054       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
28055       0f 8c/jump-if-< break/disp32
28056       # if v is in a register
28057       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
28058       {
28059         0f 84/jump-if-= break/disp32
28060         {
28061 $clean-up-stack-offset-state:check-for-previous-spill:
28062           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
28063           3d/compare-eax-and 0/imm32/false
28064           74/jump-if-= break/disp8
28065 $clean-up-stack-offset-state:reclaim-var-in-register:
28066           81 0/subop/add *Curr-local-stack-offset 4/imm32
28067         }
28068         eb/jump $clean-up-stack-offset-state:continue/disp8
28069       }
28070       # otherwise v is on the stack
28071       {
28072         75/jump-if-!= break/disp8
28073 $clean-up-stack-offset-state:var-on-stack:
28074         (size-of %ebx)  # => eax
28075         01/add-to *Curr-local-stack-offset 0/r32/eax
28076       }
28077 $clean-up-stack-offset-state:continue:
28078       # curr -= 12
28079       81 5/subop/subtract %esi 0xc/imm32
28080       e9/jump loop/disp32
28081     }
28082 $clean-up-stack-offset-state:end:
28083     # . restore registers
28084     5e/pop-to-esi
28085     5b/pop-to-ebx
28086     5a/pop-to-edx
28087     59/pop-to-ecx
28088     58/pop-to-eax
28089     # . epilogue
28090     89/<- %esp 5/r32/ebp
28091     5d/pop-to-ebp
28092     c3/return
28093 
28094 # Return true if there isn't a variable in 'vars' with the same block-depth
28095 # and register as 'v'.
28096 # 'v' is guaranteed not to be within 'vars'.
28097 not-yet-spilled-this-block?:  # v: (addr var), vars: (addr stack live-var) -> result/eax: boolean
28098     # . prologue
28099     55/push-ebp
28100     89/<- %ebp 4/r32/esp
28101     # . save registers
28102     51/push-ecx
28103     52/push-edx
28104     53/push-ebx
28105     56/push-esi
28106     57/push-edi
28107     # ecx = vars
28108     8b/-> *(ebp+0xc) 1/r32/ecx
28109     # var eax: int = vars->top
28110     8b/-> *ecx 0/r32/eax
28111     # var curr/edx: (addr handle var) = &vars->data[vars->top - 12]
28112     8d/copy-address *(ecx+eax-4) 2/r32/edx  # vars + 8 + vars->top - 12/Live-var-size
28113     # var min/ecx: (addr handle var) = vars->data
28114     8d/copy-address *(ecx+8) 1/r32/ecx
28115     # var depth/ebx: int = v->block-depth
28116     8b/-> *(ebp+8) 3/r32/ebx
28117     8b/-> *(ebx+0x10) 3/r32/ebx  # Var-block-depth
28118     # var needle/esi: (addr array byte) = v->register
28119     8b/-> *(ebp+8) 6/r32/esi
28120     (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
28121     89/<- %esi 0/r32/eax
28122     {
28123 $not-yet-spilled-this-block?:loop:
28124       # if (curr < min) break
28125       39/compare %edx 1/r32/ecx
28126       0f 82/jump-if-addr< break/disp32
28127       # var cand/edi: (addr var) = lookup(*curr)
28128       (lookup *edx *(edx+4))  # => eax
28129       89/<- %edi 0/r32/eax
28130       # if (cand->block-depth < depth) break
28131       39/compare *(edi+0x10) 3/r32/ebx  # Var-block-depth
28132       0f 8c/jump-if-< break/disp32
28133       # var cand-reg/edi: (array array byte) = cand->reg
28134       (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
28135       89/<- %edi 0/r32/eax
28136       # if (cand-reg == null) continue
28137       {
28138 $not-yet-spilled-this-block?:check-reg:
28139         81 7/subop/compare %edi 0/imm32
28140         0f 84/jump-if-= break/disp32
28141         # if (cand-reg == needle) return true
28142         (string-equal? %esi %edi)  # => eax
28143         3d/compare-eax-and 0/imm32/false
28144         74/jump-if-= break/disp8
28145 $not-yet-spilled-this-block?:return-false:
28146         b8/copy-to-eax 0/imm32/false
28147         eb/jump $not-yet-spilled-this-block?:end/disp8
28148       }
28149 $not-yet-spilled-this-block?:continue:
28150       # curr -= 12
28151       81 5/subop/subtract %edx 0xc/imm32
28152       e9/jump loop/disp32
28153     }
28154 $not-yet-spilled-this-block?:return-true:
28155     # return true
28156     b8/copy-to-eax 1/imm32/true
28157 $not-yet-spilled-this-block?:end:
28158     # . restore registers
28159     5f/pop-to-edi
28160     5e/pop-to-esi
28161     5b/pop-to-ebx
28162     5a/pop-to-edx
28163     59/pop-to-ecx
28164     # . epilogue
28165     89/<- %esp 5/r32/ebp
28166     5d/pop-to-ebp
28167     c3/return
28168 
28169 # could the register of 'v' ever be written to by one of the vars in fn-outputs?
28170 will-not-write-some-register?:  # v: (addr var), stmts: (addr list stmt), fn: (addr function) -> result/eax: boolean
28171     # . prologue
28172     55/push-ebp
28173     89/<- %ebp 4/r32/esp
28174     # eax = v
28175     8b/-> *(ebp+8) 0/r32/eax
28176     # var reg/eax: (addr array byte) = lookup(v->register)
28177     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
28178     # var target/eax: (addr var) = find-register(fn-outputs, reg)
28179     (find-register *(ebp+0x10) %eax)  # => eax
28180     # if (target == 0) return true
28181     {
28182       3d/compare-eax-and 0/imm32
28183       75/jump-if-!= break/disp8
28184       b8/copy-to-eax 1/imm32/true
28185       eb/jump $will-not-write-some-register?:end/disp8
28186     }
28187     # return !assigns-in-stmts?(stmts, target)
28188     (assigns-in-stmts? *(ebp+0xc) %eax)  # => eax
28189     3d/compare-eax-and 0/imm32/false
28190     # assume: true = 1, so no need to mask with 0x000000ff
28191     0f 94/set-if-= %al
28192 $will-not-write-some-register?:end:
28193     # . epilogue
28194     89/<- %esp 5/r32/ebp
28195     5d/pop-to-ebp
28196     c3/return
28197 
28198 # return fn output with matching register
28199 # always returns false if 'reg' is null
28200 find-register:  # fn: (addr function), reg: (addr array byte) -> result/eax: (addr var)
28201     # . prologue
28202     55/push-ebp
28203     89/<- %ebp 4/r32/esp
28204     # . save registers
28205     51/push-ecx
28206     # var curr/ecx: (addr list var) = lookup(fn->outputs)
28207     8b/-> *(ebp+8) 1/r32/ecx
28208     (lookup *(ecx+0x10) *(ecx+0x14))  # Function-outputs Function-outputs => eax
28209     89/<- %ecx 0/r32/eax
28210     {
28211 $find-register:loop:
28212       # if (curr == 0) break
28213       81 7/subop/compare %ecx 0/imm32
28214       74/jump-if-= break/disp8
28215       # eax = curr->value->register
28216       (lookup *ecx *(ecx+4))  # List-value List-value => eax
28217       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
28218       # if (eax == reg) return curr->value
28219 $find-register:compare:
28220       (string-equal? *(ebp+0xc) %eax)  # => eax
28221       {
28222         3d/compare-eax-and 0/imm32/false
28223         74/jump-if-= break/disp8
28224 $find-register:found:
28225         (lookup *ecx *(ecx+4))  # List-value List-value => eax
28226         eb/jump $find-register:end/disp8
28227       }
28228       # curr = lookup(curr->next)
28229       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
28230       89/<- %ecx 0/r32/eax
28231       #
28232       eb/jump loop/disp8
28233     }
28234 $find-register:end:
28235     # . restore registers
28236     59/pop-to-ecx
28237     # . epilogue
28238     89/<- %esp 5/r32/ebp
28239     5d/pop-to-ebp
28240     c3/return
28241 
28242 assigns-in-stmts?:  # stmts: (addr list stmt), v: (addr var) -> result/eax: boolean
28243     # . prologue
28244     55/push-ebp
28245     89/<- %ebp 4/r32/esp
28246     # . save registers
28247     51/push-ecx
28248     # var curr/ecx: (addr list stmt) = stmts
28249     8b/-> *(ebp+8) 1/r32/ecx
28250     {
28251       # if (curr == 0) break
28252       81 7/subop/compare %ecx 0/imm32
28253       74/jump-if-= break/disp8
28254       # if assigns-in-stmt?(curr->value, v) return true
28255       (lookup *ecx *(ecx+4))  # List-value List-value => eax
28256       (assigns-in-stmt? %eax *(ebp+0xc))  # => eax
28257       3d/compare-eax-and 0/imm32/false
28258       75/jump-if-!= break/disp8
28259       # curr = lookup(curr->next)
28260       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
28261       89/<- %ecx 0/r32/eax
28262       #
28263       eb/jump loop/disp8
28264     }
28265 $assigns-in-stmts?:end:
28266     # . restore registers
28267     59/pop-to-ecx
28268     # . epilogue
28269     89/<- %esp 5/r32/ebp
28270     5d/pop-to-ebp
28271     c3/return
28272 
28273 assigns-in-stmt?:  # stmt: (addr stmt), v: (addr var) -> result/eax: boolean
28274     # . prologue
28275     55/push-ebp
28276     89/<- %ebp 4/r32/esp
28277     # . save registers
28278     51/push-ecx
28279     # ecx = stmt
28280     8b/-> *(ebp+8) 1/r32/ecx
28281     # if stmt is a stmt1, return assigns-in-stmt-vars?(stmt->outputs, v)
28282     {
28283       81 7/subop/compare *ecx 1/imm32/stmt1  # Stmt-tag
28284       75/jump-if-!= break/disp8
28285       (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
28286       (assigns-in-stmt-vars? %eax *(ebp+0xc))  # => eax
28287       eb/jump $assigns-in-stmt?:end/disp8
28288     }
28289     # if stmt is a block, return assigns-in-stmts?(stmt->stmts, v)
28290     {
28291       81 7/subop/compare *ecx 0/imm32/block  # Stmt-tag
28292       75/jump-if-!= break/disp8
28293       (lookup *(ecx+4) *(ecx+8))  # Block-stmts Block-stmts => eax
28294       (assigns-in-stmts? %eax *(ebp+0xc))  # => eax
28295       eb/jump $assigns-in-stmt?:end/disp8
28296     }
28297     # otherwise return false
28298     b8/copy 0/imm32/false
28299 $assigns-in-stmt?:end:
28300     # . restore registers
28301     59/pop-to-ecx
28302     # . epilogue
28303     89/<- %esp 5/r32/ebp
28304     5d/pop-to-ebp
28305     c3/return
28306 
28307 assigns-in-stmt-vars?:  # stmt-var: (addr stmt-var), v: (addr var) -> result/eax: boolean
28308     # . prologue
28309     55/push-ebp
28310     89/<- %ebp 4/r32/esp
28311     # . save registers
28312     51/push-ecx
28313     # var curr/ecx: (addr stmt-var) = stmt-var
28314     8b/-> *(ebp+8) 1/r32/ecx
28315     {
28316       # if (curr == 0) break
28317       81 7/subop/compare %ecx 0/imm32
28318       74/jump-if-= break/disp8
28319       # eax = lookup(curr->value)
28320       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
28321       # if (eax == v  &&  curr->is-deref? == false) return true
28322       {
28323         39/compare *(ebp+0xc) 0/r32/eax
28324         75/jump-if-!= break/disp8
28325         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
28326         75/jump-if-!= break/disp8
28327         b8/copy-to-eax 1/imm32/true
28328         eb/jump $assigns-in-stmt-vars?:end/disp8
28329       }
28330       # curr = lookup(curr->next)
28331       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
28332       89/<- %ecx 0/r32/eax
28333       #
28334       eb/jump loop/disp8
28335     }
28336 $assigns-in-stmt-vars?:end:
28337     # . restore registers
28338     59/pop-to-ecx
28339     # . epilogue
28340     89/<- %esp 5/r32/ebp
28341     5d/pop-to-ebp
28342     c3/return
28343 
28344 # is there a var before 'v' with the same block-depth and register on the 'vars' stack?
28345 # v is guaranteed to be within vars
28346 # 'start' is provided as an optimization, a pointer within vars
28347 # *start == v
28348 same-register-spilled-before?:  # v: (addr var), vars: (addr stack (handle var)), start: (addr var) -> result/eax: boolean
28349     # . prologue
28350     55/push-ebp
28351     89/<- %ebp 4/r32/esp
28352     # . save registers
28353     51/push-ecx
28354     52/push-edx
28355     53/push-ebx
28356     56/push-esi
28357     57/push-edi
28358     # ecx = v
28359     8b/-> *(ebp+8) 1/r32/ecx
28360     # var reg/edx: (addr array byte) = lookup(v->register)
28361     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
28362     89/<- %edx 0/r32/eax
28363     # var depth/ebx: int = v->block-depth
28364     8b/-> *(ecx+0x10) 3/r32/ebx  # Var-block-depth
28365     # var min/ecx: (addr handle var) = vars->data
28366     8b/-> *(ebp+0xc) 1/r32/ecx
28367     81 0/subop/add %ecx 8/imm32
28368     # TODO: check that start >= min and start < &vars->data[top]
28369     # TODO: check that *start == v
28370     # var curr/esi: (addr handle var) = start
28371     8b/-> *(ebp+0x10) 6/r32/esi
28372     # curr -= 8
28373     81 5/subop/subtract %esi 8/imm32
28374     {
28375 $same-register-spilled-before?:loop:
28376       # if (curr < min) break
28377       39/compare %esi 1/r32/ecx
28378       0f 82/jump-if-addr< break/disp32
28379       # var x/eax: (addr var) = lookup(*curr)
28380       (lookup *esi *(esi+4))  # => eax
28381       # if (x->block-depth < depth) break
28382       39/compare *(eax+0x10) 3/r32/ebx  # Var-block-depth
28383       0f 8c/jump-if-< break/disp32
28384       # if (x->register == 0) continue
28385       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
28386       74/jump-if-= $same-register-spilled-before?:continue/disp8
28387       # if (x->register == reg) return true
28388       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
28389       (string-equal? %eax %edx)  # => eax
28390       3d/compare-eax-and 0/imm32/false
28391       b8/copy-to-eax 1/imm32/true
28392       75/jump-if-!= $same-register-spilled-before?:end/disp8
28393 $same-register-spilled-before?:continue:
28394       # curr -= 8
28395       81 5/subop/subtract %esi 8/imm32
28396       e9/jump loop/disp32
28397     }
28398 $same-register-spilled-before?:false:
28399     b8/copy-to-eax 0/imm32/false
28400 $same-register-spilled-before?:end:
28401     # . restore registers
28402     5f/pop-to-edi
28403     5e/pop-to-esi
28404     5b/pop-to-ebx
28405     5a/pop-to-edx
28406     59/pop-to-ecx
28407     # . epilogue
28408     89/<- %esp 5/r32/ebp
28409     5d/pop-to-ebp
28410     c3/return
28411 
28412 # clean up global state for 'vars' until some block depth (inclusive)
28413 clean-up-blocks:  # vars: (addr stack live-var), until-block-depth: int, fn: (addr function)
28414     # . prologue
28415     55/push-ebp
28416     89/<- %ebp 4/r32/esp
28417     # . save registers
28418     50/push-eax
28419     51/push-ecx
28420     56/push-esi
28421     # esi = vars
28422     8b/-> *(ebp+8) 6/r32/esi
28423     # ecx = until-block-depth
28424     8b/-> *(ebp+0xc) 1/r32/ecx
28425     {
28426 $clean-up-blocks:reclaim-loop:
28427       # if (vars->top <= 0) break
28428       8b/-> *esi 0/r32/eax  # Stack-top
28429       3d/compare-eax-and 0/imm32
28430       0f 8e/jump-if-<= break/disp32
28431       # var v/eax: (addr var) = lookup(vars[vars->top-12])
28432       (lookup *(esi+eax-4) *(esi+eax))  # vars + 8 + vars->top - 12 => eax
28433       # if (v->block-depth < until-block-depth) break
28434       39/compare *(eax+0x10) 1/r32/ecx  # Var-block-depth
28435       0f 8c/jump-if-< break/disp32
28436       (pop %esi)  # => eax
28437       (pop %esi)  # => eax
28438       (pop %esi)  # => eax
28439       e9/jump loop/disp32
28440     }
28441 $clean-up-blocks:end:
28442     # . restore registers
28443     5e/pop-to-esi
28444     59/pop-to-ecx
28445     58/pop-to-eax
28446     # . epilogue
28447     89/<- %esp 5/r32/ebp
28448     5d/pop-to-ebp
28449     c3/return
28450 
28451 reg-in-function-outputs?:  # fn: (addr function), target: (addr array byte) -> result/eax: boolean
28452     # . prologue
28453     55/push-ebp
28454     89/<- %ebp 4/r32/esp
28455     # . save registers
28456     51/push-ecx
28457     # var curr/ecx: (addr list var) = lookup(fn->outputs)
28458     8b/-> *(ebp+8) 0/r32/eax
28459     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
28460     89/<- %ecx 0/r32/eax
28461     # while curr != null
28462     {
28463       81 7/subop/compare %ecx 0/imm32
28464       74/jump-if-= break/disp8
28465       # var v/eax: (addr var) = lookup(curr->value)
28466       (lookup *ecx *(ecx+4))  # List-value List-value => eax
28467       # var reg/eax: (addr array byte) = lookup(v->register)
28468       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
28469       # if (reg == target) return true
28470       (string-equal? %eax *(ebp+0xc))  # => eax
28471       3d/compare-eax-and 0/imm32/false
28472       75/jump-if-!= $reg-in-function-outputs?:end/disp8
28473       # curr = curr->next
28474       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
28475       89/<- %ecx 0/r32/eax
28476       #
28477       eb/jump loop/disp8
28478     }
28479     # return false
28480     b8/copy-to-eax 0/imm32
28481 $reg-in-function-outputs?:end:
28482     # . restore registers
28483     59/pop-to-ecx
28484     # . epilogue
28485     89/<- %esp 5/r32/ebp
28486     5d/pop-to-ebp
28487     c3/return
28488 
28489 emit-subx-var-def:  # out: (addr buffered-file), stmt: (addr stmt)
28490     # . prologue
28491     55/push-ebp
28492     89/<- %ebp 4/r32/esp
28493     # . save registers
28494     50/push-eax
28495     51/push-ecx
28496     52/push-edx
28497     # eax = stmt
28498     8b/-> *(ebp+0xc) 0/r32/eax
28499     # var v/ecx: (addr var)
28500     (lookup *(eax+4) *(eax+8))  # Vardef-var Vardef-var => eax
28501     89/<- %ecx 0/r32/eax
28502     # v->block-depth = *Curr-block-depth
28503     8b/-> *Curr-block-depth 0/r32/eax
28504     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
28505     # var n/edx: int = size-of(stmt->var)
28506     (size-of %ecx)  # => eax
28507     89/<- %edx 0/r32/eax
28508     # *Curr-local-stack-offset -= n
28509     29/subtract-from *Curr-local-stack-offset 2/r32/edx
28510     # v->offset = *Curr-local-stack-offset
28511     8b/-> *Curr-local-stack-offset 0/r32/eax
28512     89/<- *(ecx+0x14) 0/r32/eax  # Var-offset
28513     # if v is an array, do something special to initialize it
28514     {
28515       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
28516       (mu-array? %eax)  # => eax
28517       3d/compare-eax-and 0/imm32/false
28518       0f 84/jump-if-= break/disp32
28519       # var array-size-without-size/edx: int = n-4
28520       81 5/subop/subtract %edx 4/imm32
28521       #
28522       (emit-array-data-initialization *(ebp+8) %edx)
28523       e9/jump $emit-subx-var-def:end/disp32
28524     }
28525     # another special-case for initializing streams
28526     # a stream is an array with 2 extra pointers
28527     {
28528       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
28529       (mu-stream? %eax)  # => eax
28530       3d/compare-eax-and 0/imm32/false
28531       0f 84/jump-if-= break/disp32
28532       # var array-size-without-size/edx: int = n-12
28533       81 5/subop/subtract %edx 0xc/imm32
28534       (emit-array-data-initialization *(ebp+8) %edx)
28535       # emit read and write pointers
28536       (emit-indent *(ebp+8) *Curr-block-depth)
28537       (write-buffered *(ebp+8) "68/push 0/imm32\n")
28538       (emit-indent *(ebp+8) *Curr-block-depth)
28539       (write-buffered *(ebp+8) "68/push 0/imm32\n")
28540       #
28541       eb/jump $emit-subx-var-def:end/disp8
28542     }
28543     # while n > 0
28544     {
28545       81 7/subop/compare %edx 0/imm32
28546       7e/jump-if-<= break/disp8
28547       (emit-indent *(ebp+8) *Curr-block-depth)
28548       (write-buffered *(ebp+8) "68/push 0/imm32\n")
28549       # n -= 4
28550       81 5/subop/subtract %edx 4/imm32
28551       #
28552       eb/jump loop/disp8
28553     }
28554 $emit-subx-var-def:end:
28555     # . restore registers
28556     5a/pop-to-edx
28557     59/pop-to-ecx
28558     58/pop-to-eax
28559     # . epilogue
28560     89/<- %esp 5/r32/ebp
28561     5d/pop-to-ebp
28562     c3/return
28563 
28564 emit-array-data-initialization:  # out: (addr buffered-file), n: int
28565     # . prologue
28566     55/push-ebp
28567     89/<- %ebp 4/r32/esp
28568     #
28569     (emit-indent *(ebp+8) *Curr-block-depth)
28570     (write-buffered *(ebp+8) "(push-n-zero-bytes ")
28571     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
28572     (write-buffered *(ebp+8) ")\n")
28573     (emit-indent *(ebp+8) *Curr-block-depth)
28574     (write-buffered *(ebp+8) "68/push ")
28575     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
28576     (write-buffered *(ebp+8) "/imm32\n")
28577 $emit-array-data-initialization:end:
28578     # . epilogue
28579     89/<- %esp 5/r32/ebp
28580     5d/pop-to-ebp
28581     c3/return
28582 
28583 emit-subx-stmt:  # out: (addr buffered-file), stmt: (addr stmt), primitives: (addr primitive), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
28584     # . prologue
28585     55/push-ebp
28586     89/<- %ebp 4/r32/esp
28587     # . save registers
28588     50/push-eax
28589     51/push-ecx
28590     # - some special-case primitives that don't actually use the 'primitives' data structure
28591     # var op/ecx: (addr array byte) = lookup(stmt->operation)
28592     8b/-> *(ebp+0xc) 1/r32/ecx
28593     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
28594     89/<- %ecx 0/r32/eax
28595     # copy byte (can be a primitive except we need to emit a second instruction)
28596     {
28597       # if (!string-equal?(stmt->operation, "copy-byte")) break
28598       (string-equal? %ecx "copy-byte")  # => eax
28599       3d/compare-eax-and 0/imm32/false
28600       0f 84/jump-if-= break/disp32
28601       (translate-mu-copy-byte-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28602       e9/jump $emit-subx-stmt:end/disp32
28603     }
28604     # copy-byte-to can be a primitive; writes to memory don't need to clear surrounding bytes
28605     # array size
28606     {
28607       # if (!string-equal?(stmt->operation, "length")) break
28608       (string-equal? %ecx "length")  # => eax
28609       3d/compare-eax-and 0/imm32/false
28610       0f 84/jump-if-= break/disp32
28611       (translate-mu-length-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28612       e9/jump $emit-subx-stmt:end/disp32
28613     }
28614     # index into array
28615     {
28616       # if (!string-equal?(stmt->operation, "index")) break
28617       (string-equal? %ecx "index")  # => eax
28618       3d/compare-eax-and 0/imm32/false
28619       0f 84/jump-if-= break/disp32
28620       (translate-mu-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
28621       e9/jump $emit-subx-stmt:end/disp32
28622     }
28623     # compute-offset for index into array
28624     {
28625       # if (!string-equal?(stmt->operation, "compute-offset")) break
28626       (string-equal? %ecx "compute-offset")  # => eax
28627       3d/compare-eax-and 0/imm32/false
28628       0f 84/jump-if-= break/disp32
28629       (translate-mu-compute-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28630       e9/jump $emit-subx-stmt:end/disp32
28631     }
28632     # get field from record
28633     {
28634       # if (!string-equal?(stmt->operation, "get")) break
28635       (string-equal? %ecx "get")  # => eax
28636       3d/compare-eax-and 0/imm32/false
28637       0f 84/jump-if-= break/disp32
28638       (translate-mu-get-stmt *(ebp+8) *(ebp+0xc))
28639       e9/jump $emit-subx-stmt:end/disp32
28640     }
28641     # allocate scalar
28642     {
28643       # if (!string-equal?(stmt->operation, "allocate")) break
28644       (string-equal? %ecx "allocate")  # => eax
28645       3d/compare-eax-and 0/imm32/false
28646       0f 84/jump-if-= break/disp32
28647       (translate-mu-allocate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28648       e9/jump $emit-subx-stmt:end/disp32
28649     }
28650     # copy-object
28651     {
28652       # if (!string-equal?(stmt->operation, "copy-object")) break
28653       (string-equal? %ecx "copy-object")  # => eax
28654       3d/compare-eax-and 0/imm32/false
28655       0f 84/jump-if-= break/disp32
28656       (translate-mu-copy-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28657       e9/jump $emit-subx-stmt:end/disp32
28658     }
28659     # clear-object
28660     {
28661       # if (!string-equal?(stmt->operation, "clear-object")) break
28662       (string-equal? %ecx "clear-object")  # => eax
28663       3d/compare-eax-and 0/imm32/false
28664       0f 84/jump-if-= break/disp32
28665       (translate-mu-clear-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28666       e9/jump $emit-subx-stmt:end/disp32
28667     }
28668     # allocate array
28669     {
28670       # if (!string-equal?(stmt->operation, "populate")) break
28671       (string-equal? %ecx "populate")  # => eax
28672       3d/compare-eax-and 0/imm32/false
28673       0f 84/jump-if-= break/disp32
28674       (translate-mu-populate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28675       e9/jump $emit-subx-stmt:end/disp32
28676     }
28677     # allocate stream
28678     {
28679       # if (!string-equal?(stmt->operation, "populate-stream")) break
28680       (string-equal? %ecx "populate-stream")  # => eax
28681       3d/compare-eax-and 0/imm32/false
28682       0f 84/jump-if-= break/disp32
28683       (translate-mu-populate-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28684       e9/jump $emit-subx-stmt:end/disp32
28685     }
28686     # read from stream
28687     {
28688       # if (!string-equal?(stmt->operation, "read-from-stream")) break
28689       (string-equal? %ecx "read-from-stream")  # => eax
28690       3d/compare-eax-and 0/imm32/false
28691       0f 84/jump-if-= break/disp32
28692       (translate-mu-read-from-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28693       e9/jump $emit-subx-stmt:end/disp32
28694     }
28695     # write to stream
28696     {
28697       # if (!string-equal?(stmt->operation, "write-to-stream")) break
28698       (string-equal? %ecx "write-to-stream")  # => eax
28699       3d/compare-eax-and 0/imm32/false
28700       0f 84/jump-if-= break/disp32
28701       (translate-mu-write-to-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28702       e9/jump $emit-subx-stmt:end/disp32
28703     }
28704     # - optimizations
28705     # if copy instruction has same register in source and destination, emit nothing
28706     (redundant-copy? *(ebp+0xc))  # => eax
28707     3d/compare-eax-and 0/imm32/false
28708     75/jump-if-!= $emit-subx-stmt:end/disp8
28709     # - if stmt matches a primitive, emit it
28710     {
28711 $emit-subx-stmt:check-for-primitive:
28712       # var curr/eax: (addr primitive)
28713       (find-matching-primitive *(ebp+0x10) *(ebp+0xc))  # primitives, stmt => eax
28714       3d/compare-eax-and 0/imm32
28715       74/jump-if-= break/disp8
28716 $emit-subx-stmt:primitive:
28717       (emit-subx-primitive *(ebp+8) *(ebp+0xc) %eax)  # out, stmt, curr
28718       e9/jump $emit-subx-stmt:end/disp32
28719     }
28720     # - otherwise emit a call
28721     # TODO: type-checking
28722 $emit-subx-stmt:call:
28723     (emit-call *(ebp+8) *(ebp+0xc))
28724 $emit-subx-stmt:end:
28725     # . restore registers
28726     59/pop-to-ecx
28727     58/pop-to-eax
28728     # . epilogue
28729     89/<- %esp 5/r32/ebp
28730     5d/pop-to-ebp
28731     c3/return
28732 
28733 redundant-copy?:  # stmt: (addr stmt) -> result/eax: boolean
28734     # . prologue
28735     55/push-ebp
28736     89/<- %ebp 4/r32/esp
28737     # . save registers
28738     56/push-esi
28739     57/push-edi
28740     # esi = stmt
28741     8b/-> *(ebp+8) 6/r32/esi
28742     # if stmt->operation != "copy" return false
28743     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
28744     (string-equal? %eax "copy")  # => eax
28745     3d/compare-eax-and 0/imm32/false
28746     0f 84/jump-if-= $redundant-copy?:end/disp32
28747     # var output-reg/edi: (addr stmt-var) = stmt->outputs->value->register
28748     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
28749     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
28750     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
28751     # . if output-reg == null, return false
28752     3d/compare-eax-and 0/imm32
28753     74/jump-if-= $redundant-copy?:end/disp8
28754     89/<- %edi 0/r32/eax
28755     # return (inout->value->register == output->value->register)
28756     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
28757     # . if inout->is-deref return false
28758     81 7/subop/compare *(eax+0x10) 0/imm32/false  # Stmt-var-is-deref
28759     {
28760       74/jump-if-= break/disp8
28761       b8/copy-to-eax 0/imm32/false
28762       e9/jump $redundant-copy?:end/disp32
28763     }
28764     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
28765     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
28766     # . if inout-reg == null, return false
28767     3d/compare-eax-and 0/imm32
28768     74/jump-if-= $redundant-copy?:end/disp8
28769     (string-equal? %eax %edi)  # => eax
28770 $redundant-copy?:end:
28771     # . restore registers
28772     5f/pop-to-edi
28773     5e/pop-to-esi
28774     # . epilogue
28775     89/<- %esp 5/r32/ebp
28776     5d/pop-to-ebp
28777     c3/return
28778 
28779 translate-mu-length-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
28780     # . prologue
28781     55/push-ebp
28782     89/<- %ebp 4/r32/esp
28783     # . save registers
28784     50/push-eax
28785     51/push-ecx
28786     52/push-edx
28787     53/push-ebx
28788     56/push-esi
28789     # esi = stmt
28790     8b/-> *(ebp+0xc) 6/r32/esi
28791     # var base/ebx: (addr var) = stmt->inouts[0]->value
28792     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
28793     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
28794     89/<- %ebx 0/r32/eax
28795     # var elemsize/ecx: int = array-element-size(base)
28796     (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
28797     89/<- %ecx 0/r32/eax
28798     # var outreg/edx: (addr array byte) = stmt->outputs[0]->value->register
28799     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
28800     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
28801     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
28802     89/<- %edx 0/r32/eax
28803     # if elemsize == 1
28804     {
28805       81 7/subop/compare %ecx 1/imm32
28806       75/jump-if-!= break/disp8
28807 $translate-mu-length-stmt:size-1:
28808       (emit-save-size-to *(ebp+8) %ebx %edx)
28809       e9/jump $translate-mu-length-stmt:end/disp32
28810     }
28811     # if elemsize is a power of 2 less than 256
28812     {
28813       (power-of-2? %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
28814       3d/compare-eax-and 0/imm32/false
28815       74/jump-if-= break/disp8
28816       81 7/subop/compare %ecx 0xff/imm32
28817       7f/jump-if-> break/disp8
28818 $translate-mu-length-stmt:size-power-of-2:
28819       (emit-save-size-to *(ebp+8) %ebx %edx)
28820       (emit-divide-by-shift-right *(ebp+8) %edx %ecx)
28821       e9/jump $translate-mu-length-stmt:end/disp32
28822     }
28823     # otherwise, the complex case
28824     # . emit register spills
28825     {
28826 $translate-mu-length-stmt:complex:
28827       (string-equal? %edx "eax")  # => eax
28828       3d/compare-eax-and 0/imm32/false
28829       75/break-if-!= break/disp8
28830       (emit-indent *(ebp+8) *Curr-block-depth)
28831       (write-buffered *(ebp+8) "50/push-eax\n")
28832     }
28833     {
28834       (string-equal? %edx "ecx")  # => eax
28835       3d/compare-eax-and 0/imm32/false
28836       75/break-if-!= break/disp8
28837       (emit-indent *(ebp+8) *Curr-block-depth)
28838       (write-buffered *(ebp+8) "51/push-ecx\n")
28839     }
28840     {
28841       (string-equal? %edx "edx")  # => eax
28842       3d/compare-eax-and 0/imm32/false
28843       75/break-if-!= break/disp8
28844       (emit-indent *(ebp+8) *Curr-block-depth)
28845       (write-buffered *(ebp+8) "52/push-edx\n")
28846     }
28847     # .
28848     (emit-save-size-to *(ebp+8) %ebx "eax")
28849     (emit-indent *(ebp+8) *Curr-block-depth)
28850     (write-buffered *(ebp+8) "31/xor %edx 2/r32/edx\n")
28851     (emit-indent *(ebp+8) *Curr-block-depth)
28852     (write-buffered *(ebp+8) "b9/copy-to-ecx ")
28853     (write-int32-hex-buffered *(ebp+8) %ecx)
28854     (write-buffered *(ebp+8) "/imm32\n")
28855     (emit-indent *(ebp+8) *Curr-block-depth)
28856     (write-buffered *(ebp+8) "f7 7/subop/idiv-eax-edx-by %ecx\n")
28857     {
28858       (string-equal? %edx "eax")  # => eax
28859       3d/compare-eax-and 0/imm32/false
28860       75/break-if-!= break/disp8
28861       (emit-indent *(ebp+8) *Curr-block-depth)
28862       (write-buffered *(ebp+8) "89/<- %")
28863       (write-buffered *(ebp+8) %edx)
28864       (write-buffered *(ebp+8) " 0/r32/eax\n")
28865     }
28866     # . emit register restores
28867     {
28868       (string-equal? %edx "edx")  # => eax
28869       3d/compare-eax-and 0/imm32/false
28870       75/break-if-!= break/disp8
28871       (emit-indent *(ebp+8) *Curr-block-depth)
28872       (write-buffered *(ebp+8) "5a/pop-to-edx\n")
28873     }
28874     {
28875       (string-equal? %edx "ecx")  # => eax
28876       3d/compare-eax-and 0/imm32/false
28877       75/break-if-!= break/disp8
28878       (emit-indent *(ebp+8) *Curr-block-depth)
28879       (write-buffered *(ebp+8) "59/pop-to-ecx\n")
28880     }
28881     {
28882       (string-equal? %edx "eax")  # => eax
28883       3d/compare-eax-and 0/imm32/false
28884       75/break-if-!= break/disp8
28885       (emit-indent *(ebp+8) *Curr-block-depth)
28886       (write-buffered *(ebp+8) "58/pop-to-eax\n")
28887     }
28888 $translate-mu-length-stmt:end:
28889     # . restore registers
28890     5e/pop-to-esi
28891     5b/pop-to-ebx
28892     5a/pop-to-edx
28893     59/pop-to-ecx
28894     58/pop-to-eax
28895     # . epilogue
28896     89/<- %esp 5/r32/ebp
28897     5d/pop-to-ebp
28898     c3/return
28899 
28900 array-element-size:  # arr: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
28901     # . prologue
28902     55/push-ebp
28903     89/<- %ebp 4/r32/esp
28904     #
28905     (array-element-type-id *(ebp+8) *(ebp+0xc) *(ebp+0x10))  # => eax
28906     (size-of-type-id-as-array-element %eax)  # => eax
28907 $array-element-size:end:
28908     # . epilogue
28909     89/<- %esp 5/r32/ebp
28910     5d/pop-to-ebp
28911     c3/return
28912 
28913 array-element-type-id:  # v: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: type-id
28914     # precondition: n is positive
28915     # . prologue
28916     55/push-ebp
28917     89/<- %ebp 4/r32/esp
28918     #
28919     8b/-> *(ebp+8) 0/r32/eax
28920     # var t/eax: (addr type-tree)
28921     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
28922     # if t == 0 abort
28923     3d/compare-eax-with 0/imm32
28924     0f 84/jump-if-== $array-element-type-id:error0/disp32
28925     # if t->is-atom? abort
28926     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
28927     0f 85/jump-if-!= $array-element-type-id:error1/disp32
28928     # if (t->left == addr) t = t->right
28929     {
28930       50/push-eax
28931       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
28932       (simple-mu-type? %eax 2)  # addr => eax
28933       3d/compare-eax-with 0/imm32/false
28934       58/pop-to-eax
28935       74/jump-if-= break/disp8
28936 $array-element-type-id:skip-addr:
28937       (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
28938     }
28939     # if t == 0 abort
28940     3d/compare-eax-with 0/imm32
28941     0f 84/jump-if-= $array-element-type-id:error2/disp32
28942     # if t->is-atom? abort
28943     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
28944     0f 85/jump-if-!= $array-element-type-id:error2/disp32
28945     # if t->left != array abort
28946     {
28947       50/push-eax
28948       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
28949       (simple-mu-type? %eax 3)  # array => eax
28950       3d/compare-eax-with 0/imm32/false
28951       58/pop-to-eax
28952 $array-element-type-id:no-array:
28953       0f 84/jump-if-= $array-element-type-id:error2/disp32
28954     }
28955 $array-element-type-id:skip-array:
28956     # t = t->right
28957     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
28958     # if t == 0 abort
28959     3d/compare-eax-with 0/imm32
28960     0f 84/jump-if-= $array-element-type-id:error2/disp32
28961     # if t->is-atom? abort
28962     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
28963     0f 85/jump-if-!= $array-element-type-id:error2/disp32
28964     # t = t->left
28965     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
28966     # if (!t->is-atom?) t = t->left     # TODO: assumes array element size can be determined from just first word of array element type
28967     # if (t->is-atom == false) t = lookup(t->left)
28968     {
28969       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
28970       75/jump-if-!= break/disp8
28971       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
28972     }
28973     # return t->value
28974     8b/-> *(eax+4) 0/r32/eax  # Type-tree-value
28975 $array-element-type-id:end:
28976     # . epilogue
28977     89/<- %esp 5/r32/ebp
28978     5d/pop-to-ebp
28979     c3/return
28980 
28981 $array-element-type-id:error0:
28982     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
28983     50/push-eax
28984     8b/-> *(ebp+8) 0/r32/eax
28985     (lookup *eax *(eax+4))  # Var-name Var-name => eax
28986     (write-buffered *(ebp+0xc) %eax)
28987     58/pop-to-eax
28988     (write-buffered *(ebp+0xc) "' has no type\n")
28989     (flush *(ebp+0xc))
28990     (stop *(ebp+0x10) 1)
28991     # never gets here
28992 
28993 $array-element-type-id:error1:
28994     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
28995     50/push-eax
28996     8b/-> *(ebp+8) 0/r32/eax
28997     (lookup *eax *(eax+4))  # Var-name Var-name => eax
28998     (write-buffered *(ebp+0xc) %eax)
28999     58/pop-to-eax
29000     (write-buffered *(ebp+0xc) "' has atomic type ")
29001     (write-int32-hex-buffered *(ebp+0xc) *(eax+4))  # Type-tree-value
29002     (write-buffered *(ebp+0xc) Newline)
29003     (flush *(ebp+0xc))
29004     (stop *(ebp+0x10) 1)
29005     # never gets here
29006 
29007 $array-element-type-id:error2:
29008     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
29009     50/push-eax
29010     8b/-> *(ebp+8) 0/r32/eax
29011     (lookup *eax *(eax+4))  # Var-name Var-name => eax
29012     (write-buffered *(ebp+0xc) %eax)
29013     58/pop-to-eax
29014     (write-buffered *(ebp+0xc) "' has non-array type\n")
29015     (flush *(ebp+0xc))
29016     (stop *(ebp+0x10) 1)
29017     # never gets here
29018 
29019 size-of-type-id-as-array-element:  # t: type-id -> result/eax: int
29020     # . prologue
29021     55/push-ebp
29022     89/<- %ebp 4/r32/esp
29023     # eax = t
29024     8b/-> *(ebp+8) 0/r32/eax
29025     # if t is 'byte', size is 1
29026     3d/compare-eax-and 8/imm32/byte
29027     {
29028       75/jump-if-!= break/disp8
29029       b8/copy-to-eax 1/imm32
29030       eb/jump $size-of-type-id-as-array-element:end/disp8
29031     }
29032     # otherwise proceed as usual
29033     (size-of-type-id %eax)  # => eax
29034 $size-of-type-id-as-array-element:end:
29035     # . epilogue
29036     89/<- %esp 5/r32/ebp
29037     5d/pop-to-ebp
29038     c3/return
29039 
29040 emit-save-size-to:  # out: (addr buffered-file), base: (addr var), outreg: (addr array byte)
29041     # . prologue
29042     55/push-ebp
29043     89/<- %ebp 4/r32/esp
29044     # . save registers
29045     50/push-eax
29046     53/push-ebx
29047     # ebx = base
29048     8b/-> *(ebp+0xc) 3/r32/ebx
29049     (emit-indent *(ebp+8) *Curr-block-depth)
29050     (write-buffered *(ebp+8) "8b/-> *")
29051     # if base is an (addr array ...) in a register
29052     {
29053       81 7/subop/compare *(ebx+0x18)) 0/imm32  # Var-register
29054       74/jump-if-= break/disp8
29055 $emit-save-size-to:emit-base-from-register:
29056       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
29057       (write-buffered *(ebp+8) %eax)
29058       eb/jump $emit-save-size-to:emit-output/disp8
29059     }
29060     # otherwise if base is an (array ...) on the stack
29061     {
29062       81 7/subop/compare *(ebx+0x14)) 0/imm32  # Var-offset
29063       74/jump-if-= break/disp8
29064 $emit-save-size-to:emit-base-from-stack:
29065       (write-buffered *(ebp+8) "(ebp+")
29066       (write-int32-hex-buffered *(ebp+8) *(ebx+0x14))  # Var-offset
29067       (write-buffered *(ebp+8) ")")
29068     }
29069 $emit-save-size-to:emit-output:
29070     (write-buffered *(ebp+8) " ")
29071     (get Mu-registers *(ebp+0x10) 0xc "Mu-registers")  # => eax
29072     (write-int32-hex-buffered *(ebp+8) *eax)
29073     (write-buffered *(ebp+8) "/r32\n")
29074 $emit-save-size-to:end:
29075     # . restore registers
29076     5b/pop-to-ebx
29077     58/pop-to-eax
29078     # . epilogue
29079     89/<- %esp 5/r32/ebp
29080     5d/pop-to-ebp
29081     c3/return
29082 
29083 emit-divide-by-shift-right:  # out: (addr buffered-file), reg: (addr array byte), size: int
29084     # . prologue
29085     55/push-ebp
29086     89/<- %ebp 4/r32/esp
29087     # . save registers
29088     50/push-eax
29089     #
29090     (emit-indent *(ebp+8) *Curr-block-depth)
29091     (write-buffered *(ebp+8) "c1/shift 5/subop/>> %")
29092     (write-buffered *(ebp+8) *(ebp+0xc))
29093     (write-buffered *(ebp+8) Space)
29094     (num-shift-rights *(ebp+0x10))  # => eax
29095     (write-int32-hex-buffered *(ebp+8) %eax)
29096     (write-buffered *(ebp+8) "/imm8\n")
29097 $emit-divide-by-shift-right:end:
29098     # . restore registers
29099     58/pop-to-eax
29100     # . epilogue
29101     89/<- %esp 5/r32/ebp
29102     5d/pop-to-ebp
29103     c3/return
29104 
29105 translate-mu-copy-byte-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29106     # . prologue
29107     55/push-ebp
29108     89/<- %ebp 4/r32/esp
29109     # . save registers
29110     50/push-eax
29111     56/push-esi
29112     # esi = stmt
29113     8b/-> *(ebp+0xc) 6/r32/esi
29114     #
29115     (emit-indent *(ebp+8) *Curr-block-depth)
29116     (write-buffered *(ebp+8) "8a/byte->")
29117     # emit stmt->inouts[0]
29118     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29119     (emit-subx-var-as-rm32 *(ebp+8) %eax)
29120     # emit /r32 for stmt->outputs[0]->register
29121     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
29122     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29123     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
29124     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
29125     (write-buffered *(ebp+8) Space)
29126     (write-int32-hex-buffered *(ebp+8) *eax)
29127     (write-buffered *(ebp+8) "/r32\n")
29128     # clear rest of register
29129     (emit-indent *(ebp+8) *Curr-block-depth)
29130     (write-buffered *(ebp+8) "81 4/subop/and %")
29131     8b/-> *(ebp+0xc) 0/r32/eax
29132     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
29133     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29134     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
29135     (write-buffered *(ebp+8) %eax)
29136     (write-buffered *(ebp+8) " 0xff/imm32\n")
29137 $translate-mu-copy-byte-stmt:end:
29138     # . restore registers
29139     5e/pop-to-esi
29140     58/pop-to-eax
29141     # . epilogue
29142     89/<- %esp 5/r32/ebp
29143     5d/pop-to-ebp
29144     c3/return
29145 
29146 # a little different from other translate- functions; notice the extra 'fn' argument
29147 translate-mu-index-stmt:  # out: (addr buffered-file), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
29148     # . prologue
29149     55/push-ebp
29150     89/<- %ebp 4/r32/esp
29151     # . save registers
29152     53/push-ebx
29153     # ebx = stmt
29154     8b/-> *(ebp+0xc) 3/r32/ebx
29155     # var base/ebx: (addr var) = stmt->inouts[0]
29156     (lookup *(ebx+0xc) *(ebx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29157     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29158     89/<- %ebx 0/r32/eax
29159     # emit bounds-check
29160     (emit-mu-index-bounds-check *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18))
29161     # if (var->register) do one thing
29162     {
29163       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
29164       74/jump-if-= break/disp8
29165       # TODO: ensure there's no dereference
29166       (translate-mu-index-stmt-with-array-in-register *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
29167       eb/jump $translate-mu-index-stmt:end/disp8
29168     }
29169     # if (var->offset) do a different thing
29170     {
29171       81 7/subop/compare *(ebx+0x14) 0/imm32  # Var-offset
29172       74/jump-if-= break/disp8
29173       # TODO: ensure there's no dereference
29174       (translate-mu-index-stmt-with-array-on-stack *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
29175       eb/jump $translate-mu-index-stmt:end/disp8
29176     }
29177 $translate-mu-index-stmt:end:
29178     # . restore registers
29179     5b/pop-to-ebx
29180     # . epilogue
29181     89/<- %esp 5/r32/ebp
29182     5d/pop-to-ebp
29183     c3/return
29184 
29185 $translate-mu-index-stmt:error1:
29186     (write-buffered *(ebp+0x14) "couldn't translate an index instruction. second (index) input must either lie in a register or be a literal\n")
29187     (flush *(ebp+0x14))
29188     (stop *(ebp+0x18) 1)
29189     # never gets here
29190 
29191 $translate-mu-index-stmt:error2:
29192     (write-buffered *(ebp+0x14) "couldn't translate an index instruction. second (index) input when in a register must be an int or offset\n")
29193     (flush *(ebp+0x14))
29194     (stop *(ebp+0x18) 1)
29195     # never gets here
29196 
29197 emit-mu-index-bounds-check:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29198     # . prologue
29199     55/push-ebp
29200     89/<- %ebp 4/r32/esp
29201     # . save registers
29202     50/push-eax
29203     51/push-ecx
29204     52/push-edx
29205     53/push-ebx
29206     # ecx = stmt
29207     8b/-> *(ebp+0xc) 1/r32/ecx
29208     #
29209     (emit-indent *(ebp+8) *Curr-block-depth)
29210     (write-buffered *(ebp+8) "(__check-mu-array-bounds ")
29211 $emit-mu-index-bounds-check:compute-base:
29212     # var base/ebx: (addr var) = inouts[0]
29213     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29214     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29215     89/<- %ebx 0/r32/eax
29216 $emit-mu-index-bounds-check:emit-index:
29217     # var index/edx: (addr var) = inouts[1]
29218     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29219     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
29220     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29221     89/<- %edx 0/r32/eax
29222     # if index->register, print its code
29223     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
29224     {
29225       0f 84/jump-if-= break/disp32
29226 $emit-mu-index-bounds-check:emit-register-index:
29227       (write-buffered *(ebp+8) "%")
29228       (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
29229       (write-buffered *(ebp+8) %eax)
29230       eb/jump $emit-mu-index-bounds-check:index-done/disp8
29231     }
29232     # otherwise if index is a literal, print it
29233 $emit-mu-index-bounds-check:emit-literal-index:
29234     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29235     (simple-mu-type? %eax 0)  # => eax
29236     3d/compare-eax-and 0/imm32/false
29237     {
29238       0f 84/jump-if-= break/disp32
29239       (lookup *edx *(edx+4))  # Var-name Var-name => eax
29240       (write-buffered *(ebp+8) %eax)
29241     }
29242 $emit-mu-index-bounds-check:index-done:
29243     (write-buffered *(ebp+8) " ")
29244 $emit-mu-index-bounds-check:emit-element-size:
29245     # if index is a literal or int, print size of array element
29246     {
29247       {
29248         (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29249         (simple-mu-type? %eax 0)  # literal => eax
29250         3d/compare-eax-and 0/imm32/false
29251         75/jump-if-!= break/disp8
29252         (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29253         (simple-mu-type? %eax 1)  # int => eax
29254         3d/compare-eax-and 0/imm32/false
29255         75/jump-if-!= break/disp8
29256         eb/jump $emit-mu-index-bounds-check:emit-element-size-offset/disp8
29257       }
29258 $emit-mu-index-bounds-check:emit-int-register-index:
29259       (array-element-size %ebx *(ebp+0x14) *(ebp+0x18))  # => eax
29260       (write-int32-hex-buffered *(ebp+8) %eax)
29261       e9/jump $emit-mu-index-bounds-check:emit-base/disp32
29262     }
29263 $emit-mu-index-bounds-check:emit-element-size-offset:
29264     # if index has type (offset ...), print "1"
29265     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29266     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
29267     {
29268       75/jump-if-!= break/disp8
29269       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29270       (simple-mu-type? %eax 7)  # => eax
29271       3d/compare-eax-and 0/imm32/false
29272       {
29273         0f 84/jump-if-= break/disp32
29274 $emit-mu-index-bounds-check:emit-offset-register-index:
29275         (write-buffered *(ebp+8) "1")
29276       }
29277     }
29278 $emit-mu-index-bounds-check:emit-base:
29279     # if base is in a register, print " *" base->register
29280     81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
29281     {
29282       74/jump-if-= break/disp8
29283       (write-buffered *(ebp+8) " *")
29284       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
29285       (write-buffered *(ebp+8) %eax)
29286       e9/jump $emit-mu-index-bounds-check:emit-function-name/disp32
29287     }
29288     # otherwise print " *(ebp+" base->offset ")"
29289     (write-buffered *(ebp+8) " *(ebp+")
29290     (write-int32-hex-buffered *(ebp+8) *(ebx+0x14))  # Var-offset
29291     (write-buffered *(ebp+8) ")")
29292 $emit-mu-index-bounds-check:emit-function-name:
29293     # " \"" function-name "\""
29294     (write-buffered *(ebp+8) " \"")
29295     8b/-> *(ebp+0x10) 1/r32/ecx
29296     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
29297     (write-buffered *(ebp+8) %eax)
29298     (write-buffered *(ebp+8) "\"")
29299 $emit-mu-index-bounds-check:emit-array-name:
29300     # " \"" base->name "\""
29301     (write-buffered *(ebp+8) " \"")
29302     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
29303     (write-buffered *(ebp+8) %eax)
29304     (write-buffered *(ebp+8) "\")\n")
29305 $emit-mu-index-bounds-check:end:
29306     # . restore registers
29307     5b/pop-to-ebx
29308     5a/pop-to-edx
29309     59/pop-to-ecx
29310     58/pop-to-eax
29311     # . epilogue
29312     89/<- %esp 5/r32/ebp
29313     5d/pop-to-ebp
29314     c3/return
29315 
29316 translate-mu-index-stmt-with-array-in-register:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29317     # . prologue
29318     55/push-ebp
29319     89/<- %ebp 4/r32/esp
29320     # . save registers
29321     50/push-eax
29322     51/push-ecx
29323     52/push-edx
29324     53/push-ebx
29325     #
29326     (emit-indent *(ebp+8) *Curr-block-depth)
29327     (write-buffered *(ebp+8) "8d/copy-address *(")
29328     # TODO: ensure inouts[0] is in a register and not dereferenced
29329 $translate-mu-index-stmt-with-array-in-register:emit-base:
29330     # ecx = stmt
29331     8b/-> *(ebp+0xc) 1/r32/ecx
29332     # var base/ebx: (addr var) = inouts[0]
29333     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29334     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29335     89/<- %ebx 0/r32/eax
29336     # print base->register " + "
29337     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
29338     (write-buffered *(ebp+8) %eax)
29339     (write-buffered *(ebp+8) " + ")
29340     # var index/edx: (addr var) = inouts[1]
29341     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29342     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
29343     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29344     89/<- %edx 0/r32/eax
29345     # if index->register
29346     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
29347     {
29348       0f 84/jump-if-= break/disp32
29349 $translate-mu-index-stmt-with-array-in-register:emit-register-index:
29350       # if index is an int
29351       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29352       (simple-mu-type? %eax 1)  # int => eax
29353       3d/compare-eax-and 0/imm32/false
29354       {
29355         0f 84/jump-if-= break/disp32
29356 $translate-mu-index-stmt-with-array-in-register:emit-int-register-index:
29357         # print index->register "<<" log2(array-element-size(base)) " + 4) "
29358         # . index->register "<<"
29359         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
29360         (write-buffered *(ebp+8) %eax)
29361         (write-buffered *(ebp+8) "<<")
29362         # . log2(array-element-size(base->type))
29363         # we know size is a power of 2
29364         (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
29365         (num-shift-rights %eax)  # => eax
29366         (write-int32-hex-buffered *(ebp+8) %eax)
29367         e9/jump $translate-mu-index-stmt-with-array-in-register:emit-register-index-done/disp32
29368       }
29369       # if index->type is any other atom, abort
29370       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29371       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
29372       0f 85/jump-if-!= $translate-mu-index-stmt:error2/disp32
29373       # if index has type (offset ...)
29374       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29375       (simple-mu-type? %eax 7)  # => eax
29376       3d/compare-eax-and 0/imm32/false
29377       {
29378         0f 84/jump-if-= break/disp32
29379         # print index->register
29380 $translate-mu-index-stmt-with-array-in-register:emit-offset-register-index:
29381         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
29382         (write-buffered *(ebp+8) %eax)
29383       }
29384 $translate-mu-index-stmt-with-array-in-register:emit-register-index-done:
29385       (write-buffered *(ebp+8) " + 4) ")
29386       e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32
29387     }
29388     # otherwise if index is a literal
29389     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29390     (simple-mu-type? %eax 0)  # => eax
29391     3d/compare-eax-and 0/imm32/false
29392     {
29393       0f 84/jump-if-= break/disp32
29394 $translate-mu-index-stmt-with-array-in-register:emit-literal-index:
29395       # var index-value/edx: int = parse-hex-int(index->name)
29396       (lookup *edx *(edx+4))  # Var-name Var-name => eax
29397       (parse-hex-int %eax)  # => eax
29398       89/<- %edx 0/r32/eax
29399       # offset = idx-value * array-element-size(base->type)
29400       (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
29401       f7 4/subop/multiply-into-edx-eax %edx  # clobbers edx
29402       # offset += 4 for array size
29403       05/add-to-eax 4/imm32
29404       # TODO: check edx for overflow
29405       # print offset
29406       (write-int32-hex-buffered *(ebp+8) %eax)
29407       (write-buffered *(ebp+8) ") ")
29408       e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32
29409     }
29410     # otherwise abort
29411     e9/jump $translate-mu-index-stmt:error1/disp32
29412 $translate-mu-index-stmt-with-array-in-register:emit-output:
29413     # outputs[0] "/r32"
29414     8b/-> *(ebp+0xc) 1/r32/ecx
29415     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
29416     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29417     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
29418     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
29419     (write-int32-hex-buffered *(ebp+8) *eax)
29420     (write-buffered *(ebp+8) "/r32\n")
29421 $translate-mu-index-stmt-with-array-in-register:end:
29422     # . restore registers
29423     5b/pop-to-ebx
29424     5a/pop-to-edx
29425     59/pop-to-ecx
29426     58/pop-to-eax
29427     # . epilogue
29428     89/<- %esp 5/r32/ebp
29429     5d/pop-to-ebp
29430     c3/return
29431 
29432 translate-mu-index-stmt-with-array-on-stack:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29433     # . prologue
29434     55/push-ebp
29435     89/<- %ebp 4/r32/esp
29436     # . save registers
29437     50/push-eax
29438     51/push-ecx
29439     52/push-edx
29440     53/push-ebx
29441     #
29442     (emit-indent *(ebp+8) *Curr-block-depth)
29443     (write-buffered *(ebp+8) "8d/copy-address *(ebp + ")
29444     # var curr/edx: (addr stmt-var) = lookup(stmt->inouts)
29445     8b/-> *(ebp+0xc) 0/r32/eax
29446     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29447     89/<- %edx 0/r32/eax
29448     # var base/ecx: (addr var) = lookup(curr->value)
29449     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29450     89/<- %ecx 0/r32/eax
29451     # var curr2/eax: (addr stmt-var) = lookup(curr->next)
29452     (lookup *(edx+8) *(edx+0xc))  # Stmt-var-next Stmt-var-next => eax
29453     # var index/edx: (handle var) = curr2->value
29454     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29455     89/<- %edx 0/r32/eax
29456     # if index->register
29457     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
29458     {
29459       0f 84/jump-if-= break/disp32
29460 $translate-mu-index-stmt-with-array-on-stack:emit-register-index:
29461       # if index is an int
29462       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29463       (simple-mu-type? %eax 1)  # int => eax
29464       3d/compare-eax-and 0/imm32/false
29465       {
29466         0f 84/jump-if-= break/disp32
29467 $translate-mu-index-stmt-with-array-on-stack:emit-int-register-index:
29468         # print index->register "<<" log2(array-element-size(base)) " + " base->offset+4
29469         # . inouts[1]->register "<<"
29470         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
29471         (write-buffered *(ebp+8) %eax)
29472         (write-buffered *(ebp+8) "<<")
29473         # . log2(array-element-size(base))
29474         # TODO: ensure size is a power of 2
29475         (array-element-size %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
29476         (num-shift-rights %eax)  # => eax
29477         (write-int32-hex-buffered *(ebp+8) %eax)
29478         #
29479         (write-buffered *(ebp+8) " + ")
29480         #
29481         8b/-> *(ecx+0x14) 0/r32/eax  # Var-offset
29482         05/add-to-eax 4/imm32  # for array length
29483         (write-int32-hex-buffered *(ebp+8) %eax)
29484         e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done/disp32
29485       }
29486       # if index->type is any other atom, abort
29487       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29488       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
29489       0f 85/jump-if-!= $translate-mu-index-stmt:error2/disp32
29490       # if index has type (offset ...)
29491       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29492       (simple-mu-type? %eax 7)  # => eax
29493       3d/compare-eax-and 0/imm32/false
29494       {
29495         0f 84/jump-if-= break/disp32
29496         # print index->register
29497 $translate-mu-index-stmt-with-array-on-stack:emit-offset-register-index:
29498         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
29499         (write-buffered *(ebp+8) %eax)
29500       }
29501 $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done:
29502       (write-buffered *(ebp+8) ") ")
29503       e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32
29504     }
29505     # otherwise if index is a literal
29506     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29507     (simple-mu-type? %eax 0)  # => eax
29508     3d/compare-eax-and 0/imm32/false
29509     {
29510       0f 84/jump-if-= break/disp32
29511 $translate-mu-index-stmt-with-array-on-stack:emit-literal-index:
29512       # var idx-value/edx: int = parse-hex-int(index->name)
29513       (lookup *edx *(edx+4))  # Var-name Var-name => eax
29514       (parse-hex-int %eax)  # Var-name => eax
29515       89/<- %edx 0/r32/eax
29516       # offset = idx-value * array-element-size(base)
29517       (array-element-size %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
29518       f7 4/subop/multiply-into-edx-eax %edx  # clobbers edx
29519       # offset += base->offset
29520       03/add *(ecx+0x14) 0/r32/eax  # Var-offset
29521       # offset += 4 for array size
29522       05/add-to-eax 4/imm32
29523       # TODO: check edx for overflow
29524       # print offset
29525       (write-int32-hex-buffered *(ebp+8) %eax)
29526       (write-buffered *(ebp+8) ") ")
29527       e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32
29528     }
29529     # otherwise abort
29530     e9/jump $translate-mu-index-stmt:error1/disp32
29531 $translate-mu-index-stmt-with-array-on-stack:emit-output:
29532     # outputs[0] "/r32"
29533     8b/-> *(ebp+0xc) 0/r32/eax
29534     (lookup *(eax+0x14) *(eax+0x18))  # Stmt1-outputs Stmt1-outputs => eax
29535     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29536     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
29537     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
29538     (write-int32-hex-buffered *(ebp+8) *eax)
29539     (write-buffered *(ebp+8) "/r32\n")
29540 $translate-mu-index-stmt-with-array-on-stack:end:
29541     # . restore registers
29542     5b/pop-to-ebx
29543     5a/pop-to-edx
29544     59/pop-to-ecx
29545     58/pop-to-eax
29546     # . epilogue
29547     89/<- %esp 5/r32/ebp
29548     5d/pop-to-ebp
29549     c3/return
29550 
29551 translate-mu-compute-index-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29552     # . prologue
29553     55/push-ebp
29554     89/<- %ebp 4/r32/esp
29555     # . save registers
29556     50/push-eax
29557     51/push-ecx
29558     52/push-edx
29559     53/push-ebx
29560     #
29561     (emit-indent *(ebp+8) *Curr-block-depth)
29562     (write-buffered *(ebp+8) "69/multiply")
29563     # ecx = stmt
29564     8b/-> *(ebp+0xc) 1/r32/ecx
29565     # var first-inout/ebx: (addr stmt-var) = stmt->inouts[0]
29566     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29567     89/<- %ebx 0/r32/eax
29568 $translate-mu-compute-index-stmt:emit-index:
29569     (lookup *(ebx+8) *(ebx+0xc))  # Stmt-var-next Stmt-var-next => eax
29570     (emit-subx-var-as-rm32 *(ebp+8) %eax)
29571     (write-buffered *(ebp+8) Space)
29572 $translate-mu-compute-index-stmt:emit-elem-size:
29573     # var base/ebx: (addr var)
29574     (lookup *ebx *(ebx+4))  # Stmt-var-value Stmt-var-value => eax
29575     89/<- %ebx 0/r32/eax
29576     # print array-element-size(base)
29577     (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
29578     (write-int32-hex-buffered *(ebp+8) %eax)
29579     (write-buffered *(ebp+8) "/imm32 ")
29580 $translate-mu-compute-index-stmt:emit-output:
29581     # outputs[0] "/r32"
29582     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
29583     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29584     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
29585     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
29586     (write-int32-hex-buffered *(ebp+8) *eax)
29587     (write-buffered *(ebp+8) "/r32\n")
29588 $translate-mu-compute-index-stmt:end:
29589     # . restore registers
29590     5b/pop-to-ebx
29591     5a/pop-to-edx
29592     59/pop-to-ecx
29593     58/pop-to-eax
29594     # . epilogue
29595     89/<- %esp 5/r32/ebp
29596     5d/pop-to-ebp
29597     c3/return
29598 
29599 translate-mu-get-stmt:  # out: (addr buffered-file), stmt: (addr stmt)
29600     # . prologue
29601     55/push-ebp
29602     89/<- %ebp 4/r32/esp
29603     # . save registers
29604     50/push-eax
29605     51/push-ecx
29606     52/push-edx
29607     #
29608     (emit-indent *(ebp+8) *Curr-block-depth)
29609     (write-buffered *(ebp+8) "8d/copy-address ")
29610     # ecx = stmt
29611     8b/-> *(ebp+0xc) 1/r32/ecx
29612     # var offset/edx: int = get offset of stmt
29613     (mu-get-offset %ecx)  # => eax
29614     89/<- %edx 0/r32/eax
29615     # var base/eax: (addr var) = stmt->inouts->value
29616     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29617     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29618     # if base is in a register
29619     81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
29620     {
29621       0f 84/jump-if-= break/disp32
29622 $translate-mu-get-stmt:emit-register-input:
29623       # emit "*(" base->register " + " offset ") "
29624       (write-buffered *(ebp+8) "*(")
29625       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
29626       (write-buffered *(ebp+8) %eax)
29627       (write-buffered *(ebp+8) " + ")
29628       (write-int32-hex-buffered *(ebp+8) %edx)
29629       (write-buffered *(ebp+8) ") ")
29630       e9/jump $translate-mu-get-stmt:emit-output/disp32
29631     }
29632     # otherwise base is on the stack
29633     {
29634 $translate-mu-get-stmt:emit-stack-input:
29635       # emit "*(ebp + " inouts[0]->stack-offset + offset ") "
29636       (write-buffered *(ebp+8) "*(ebp+")
29637       03/add *(eax+0x14) 2/r32/edx  # Var-offset
29638       (write-int32-hex-buffered *(ebp+8) %edx)
29639       (write-buffered *(ebp+8) ") ")
29640       eb/jump $translate-mu-get-stmt:emit-output/disp8
29641     }
29642 $translate-mu-get-stmt:emit-output:
29643     # var output/eax: (addr var) = stmt->outputs->value
29644     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
29645     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29646     # emit offset->register "/r32"
29647     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
29648     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
29649     (write-int32-hex-buffered *(ebp+8) *eax)
29650     (write-buffered *(ebp+8) "/r32\n")
29651 $translate-mu-get-stmt:end:
29652     # . restore registers
29653     5a/pop-to-edx
29654     59/pop-to-ecx
29655     58/pop-to-eax
29656     # . epilogue
29657     89/<- %esp 5/r32/ebp
29658     5d/pop-to-ebp
29659     c3/return
29660 
29661 translate-mu-copy-object-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29662     # . prologue
29663     55/push-ebp
29664     89/<- %ebp 4/r32/esp
29665     # . save registers
29666     50/push-eax
29667     #
29668     (emit-indent *(ebp+8) *Curr-block-depth)
29669     (write-buffered *(ebp+8) "(copy-bytes")
29670     # eax = stmt
29671     8b/-> *(ebp+0xc) 0/r32/eax
29672     # var first-inout/eax: (addr stmt-var) = stmt->inouts[0]
29673     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29674     (emit-subx-call-operand *(ebp+8) %eax)
29675     # var second-inout/eax: (addr stmt-var) = stmt->inouts[1]
29676     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
29677     (emit-subx-call-operand *(ebp+8) %eax)
29678     # emit size of inouts
29679     (write-buffered *(ebp+8) Space)
29680     (addr-payload-size %eax *(ebp+0x10) *(ebp+0x14))  # => eax
29681     (write-int32-hex-buffered *(ebp+8) %eax)
29682     (write-buffered *(ebp+8) ")\n")
29683 $translate-mu-copy-object-stmt:end:
29684     # . restore registers
29685     58/pop-to-eax
29686     # . epilogue
29687     89/<- %esp 5/r32/ebp
29688     5d/pop-to-ebp
29689     c3/return
29690 
29691 translate-mu-clear-object-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29692     # . prologue
29693     55/push-ebp
29694     89/<- %ebp 4/r32/esp
29695     # . save registers
29696     50/push-eax
29697     #
29698     (emit-indent *(ebp+8) *Curr-block-depth)
29699     (write-buffered *(ebp+8) "(zero-out")
29700     # eax = stmt
29701     8b/-> *(ebp+0xc) 0/r32/eax
29702     # var dest/eax: (addr stmt-var) = stmt->inouts[0]
29703     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29704     #
29705     (emit-subx-call-operand *(ebp+8) %eax)
29706     (write-buffered *(ebp+8) Space)
29707     (addr-payload-size %eax *(ebp+0x10) *(ebp+0x14))  # => eax
29708     (write-int32-hex-buffered *(ebp+8) %eax)
29709     (write-buffered *(ebp+8) ")\n")
29710 $translate-mu-clear-object-stmt:end:
29711     # . restore registers
29712     58/pop-to-eax
29713     # . epilogue
29714     89/<- %esp 5/r32/ebp
29715     5d/pop-to-ebp
29716     c3/return
29717 
29718 translate-mu-allocate-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29719     # . prologue
29720     55/push-ebp
29721     89/<- %ebp 4/r32/esp
29722     # . save registers
29723     50/push-eax
29724     56/push-esi
29725     57/push-edi
29726     # esi = stmt
29727     8b/-> *(ebp+0xc) 6/r32/esi
29728     # var target/edi: (addr stmt-var) = stmt->inouts[0]
29729     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29730     89/<- %edi 0/r32/eax
29731     #
29732     (emit-indent *(ebp+8) *Curr-block-depth)
29733     (write-buffered *(ebp+8) "(allocate Heap ")
29734     (addr-handle-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
29735     (write-int32-hex-buffered *(ebp+8) %eax)
29736     (emit-subx-call-operand *(ebp+8) %edi)
29737     (write-buffered *(ebp+8) ")\n")
29738 $translate-mu-allocate-stmt:end:
29739     # . restore registers
29740     5f/pop-to-edi
29741     5e/pop-to-esi
29742     58/pop-to-eax
29743     # . epilogue
29744     89/<- %esp 5/r32/ebp
29745     5d/pop-to-ebp
29746     c3/return
29747 
29748 addr-handle-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
29749     # . prologue
29750     55/push-ebp
29751     89/<- %ebp 4/r32/esp
29752     # var t/eax: (addr type-tree) = s->value->type
29753     8b/-> *(ebp+8) 0/r32/eax
29754     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29755     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
29756     # TODO: check eax != 0
29757     # TODO: check !t->is-atom?
29758     # TODO: check t->left == addr
29759     # t = t->right
29760 $addr-handle-payload-size:skip-addr:
29761     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
29762     # TODO: check eax != 0
29763     # TODO: check !t->is-atom?
29764     # TODO: check t->left == handle
29765     # t = t->right
29766 $addr-handle-payload-size:skip-handle:
29767     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
29768     # TODO: check eax != 0
29769     # if !t->is-atom? t = t->left
29770     81 7/subop/compare *eax 0/imm32/false
29771     {
29772       75/jump-if-!= break/disp8
29773       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29774     }
29775     # TODO: check t->is-atom?
29776     # return size(t->value)
29777     (size-of-type-id *(eax+4))  # Type-tree-value => eax
29778 $addr-handle-payload-size:end:
29779     # . epilogue
29780     89/<- %esp 5/r32/ebp
29781     5d/pop-to-ebp
29782     c3/return
29783 
29784 addr-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
29785     # . prologue
29786     55/push-ebp
29787     89/<- %ebp 4/r32/esp
29788     # var t/eax: (addr type-tree) = s->value->type
29789     8b/-> *(ebp+8) 0/r32/eax
29790     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29791     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
29792     # TODO: check eax != 0
29793     # TODO: check !t->is-atom?
29794     # TODO: check t->left == addr
29795     # t = t->right
29796 $addr-payload-size:skip-addr:
29797     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
29798     # TODO: check eax != 0
29799     # if !t->is-atom? t = t->left
29800     81 7/subop/compare *eax 0/imm32/false
29801     {
29802       75/jump-if-!= break/disp8
29803       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29804     }
29805     # TODO: check t->is-atom?
29806     # return size(t->value)
29807     (size-of-type-id *(eax+4))  # Type-tree-value => eax
29808 $addr-payload-size:end:
29809     # . epilogue
29810     89/<- %esp 5/r32/ebp
29811     5d/pop-to-ebp
29812     c3/return
29813 
29814 translate-mu-populate-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29815     # . prologue
29816     55/push-ebp
29817     89/<- %ebp 4/r32/esp
29818     # . save registers
29819     50/push-eax
29820     51/push-ecx
29821     56/push-esi
29822     57/push-edi
29823     # esi = stmt
29824     8b/-> *(ebp+0xc) 6/r32/esi
29825     # var target/edi: (addr stmt-var) = stmt->inouts[0]
29826     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29827     89/<- %edi 0/r32/eax
29828     # var len/ecx: (addr stmt-var) = stmt->inouts[1]
29829     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
29830     89/<- %ecx 0/r32/eax
29831     #
29832     (emit-indent *(ebp+8) *Curr-block-depth)
29833     (write-buffered *(ebp+8) "(allocate-array2 Heap ")
29834     (addr-handle-array-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
29835     (write-int32-hex-buffered *(ebp+8) %eax)
29836     (emit-subx-call-operand *(ebp+8) %ecx)
29837     (emit-subx-call-operand *(ebp+8) %edi)
29838     (write-buffered *(ebp+8) ")\n")
29839 $translate-mu-populate-stmt:end:
29840     # . restore registers
29841     5f/pop-to-edi
29842     5e/pop-to-esi
29843     59/pop-to-ecx
29844     58/pop-to-eax
29845     # . epilogue
29846     89/<- %esp 5/r32/ebp
29847     5d/pop-to-ebp
29848     c3/return
29849 
29850 translate-mu-populate-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29851     # . prologue
29852     55/push-ebp
29853     89/<- %ebp 4/r32/esp
29854     # . save registers
29855     50/push-eax
29856     51/push-ecx
29857     56/push-esi
29858     57/push-edi
29859     # esi = stmt
29860     8b/-> *(ebp+0xc) 6/r32/esi
29861     # var target/edi: (addr stmt-var) = stmt->inouts[0]
29862     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29863     89/<- %edi 0/r32/eax
29864     # var len/ecx: (addr stmt-var) = stmt->inouts[1]
29865     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
29866     89/<- %ecx 0/r32/eax
29867     #
29868     (emit-indent *(ebp+8) *Curr-block-depth)
29869     (write-buffered *(ebp+8) "(new-stream Heap ")
29870     (addr-handle-stream-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
29871     (write-int32-hex-buffered *(ebp+8) %eax)
29872     (emit-subx-call-operand *(ebp+8) %ecx)
29873     (emit-subx-call-operand *(ebp+8) %edi)
29874     (write-buffered *(ebp+8) ")\n")
29875 $translate-mu-populate-stream-stmt:end:
29876     # . restore registers
29877     5f/pop-to-edi
29878     5e/pop-to-esi
29879     59/pop-to-ecx
29880     58/pop-to-eax
29881     # . epilogue
29882     89/<- %esp 5/r32/ebp
29883     5d/pop-to-ebp
29884     c3/return
29885 
29886 translate-mu-read-from-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29887     # . prologue
29888     55/push-ebp
29889     89/<- %ebp 4/r32/esp
29890     # . save registers
29891     50/push-eax
29892     51/push-ecx
29893     56/push-esi
29894     57/push-edi
29895     # esi = stmt
29896     8b/-> *(ebp+0xc) 6/r32/esi
29897     # var stream/ecx: (addr stmt-var) = stmt->inouts[0]
29898     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29899     89/<- %ecx 0/r32/eax
29900     # var target/edi: (addr stmt-var) = stmt->inouts[1]
29901     (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
29902     89/<- %edi 0/r32/eax
29903     #
29904     (emit-indent *(ebp+8) *Curr-block-depth)
29905     (write-buffered *(ebp+8) "(read-from-stream")
29906     (emit-subx-call-operand *(ebp+8) %ecx)
29907     (emit-subx-call-operand *(ebp+8) %edi)
29908     (write-buffered *(ebp+8) Space)
29909     (addr-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
29910     (write-int32-hex-buffered *(ebp+8) %eax)
29911     (write-buffered *(ebp+8) ")\n")
29912 $translate-mu-read-from-stream-stmt:end:
29913     # . restore registers
29914     5f/pop-to-edi
29915     5e/pop-to-esi
29916     59/pop-to-ecx
29917     58/pop-to-eax
29918     # . epilogue
29919     89/<- %esp 5/r32/ebp
29920     5d/pop-to-ebp
29921     c3/return
29922 
29923 translate-mu-write-to-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29924     # . prologue
29925     55/push-ebp
29926     89/<- %ebp 4/r32/esp
29927     # . save registers
29928     50/push-eax
29929     51/push-ecx
29930     56/push-esi
29931     57/push-edi
29932     # esi = stmt
29933     8b/-> *(ebp+0xc) 6/r32/esi
29934     # var stream/ecx: (addr stmt-var) = stmt->inouts[0]
29935     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29936     89/<- %ecx 0/r32/eax
29937     # var target/edi: (addr stmt-var) = stmt->inouts[1]
29938     (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
29939     89/<- %edi 0/r32/eax
29940     #
29941     (emit-indent *(ebp+8) *Curr-block-depth)
29942     (write-buffered *(ebp+8) "(write-to-stream")
29943     (emit-subx-call-operand *(ebp+8) %ecx)
29944     (flush *(ebp+8))
29945     (emit-subx-call-operand *(ebp+8) %edi)
29946     (flush *(ebp+8))
29947     (write-buffered *(ebp+8) Space)
29948     (flush *(ebp+8))
29949     (addr-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
29950     (write-int32-hex-buffered *(ebp+8) %eax)
29951     (write-buffered *(ebp+8) ")\n")
29952 $translate-mu-write-to-stream-stmt:end:
29953     # . restore registers
29954     5f/pop-to-edi
29955     5e/pop-to-esi
29956     59/pop-to-ecx
29957     58/pop-to-eax
29958     # . epilogue
29959     89/<- %esp 5/r32/ebp
29960     5d/pop-to-ebp
29961     c3/return
29962 
29963 addr-handle-array-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
29964     # . prologue
29965     55/push-ebp
29966     89/<- %ebp 4/r32/esp
29967     # var t/eax: (addr type-tree) = s->value->type
29968     8b/-> *(ebp+8) 0/r32/eax
29969     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29970     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
29971     # TODO: check eax != 0
29972     # TODO: check !t->is-atom?
29973     # TODO: check t->left == addr
29974     # t = t->right
29975 $addr-handle-array-payload-size:skip-addr:
29976     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
29977     # TODO: check eax != 0
29978     # TODO: check !t->is-atom?
29979     # TODO: check t->left == handle
29980     # t = t->right
29981 $addr-handle-array-payload-size:skip-handle:
29982     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
29983     # TODO: check eax != 0
29984     # TODO: check !t->is-atom?
29985     # TODO: check t->left == array
29986     # t = t->right
29987 $addr-handle-array-payload-size:skip-array:
29988     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
29989     # TODO: check eax != 0
29990     # if !t->is-atom? t = t->left
29991     81 7/subop/compare *eax 0/imm32/false
29992     {
29993       75/jump-if-!= break/disp8
29994       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29995     }
29996 $addr-handle-array-payload-size:compute-size:
29997     # TODO: check t->is-atom?
29998     # return size(t->value)
29999     (size-of-type-id-as-array-element *(eax+4))  # Type-tree-value => eax
30000 $addr-handle-array-payload-size:end:
30001     # . epilogue
30002     89/<- %esp 5/r32/ebp
30003     5d/pop-to-ebp
30004     c3/return
30005 
30006 addr-handle-stream-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
30007     # . prologue
30008     55/push-ebp
30009     89/<- %ebp 4/r32/esp
30010     # var t/eax: (addr type-tree) = s->value->type
30011     8b/-> *(ebp+8) 0/r32/eax
30012     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
30013     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
30014     # TODO: check eax != 0
30015     # TODO: check !t->is-atom?
30016     # TODO: check t->left == addr
30017     # t = t->right
30018 $addr-handle-stream-payload-size:skip-addr:
30019     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
30020     # TODO: check eax != 0
30021     # TODO: check !t->is-atom?
30022     # TODO: check t->left == handle
30023     # t = t->right
30024 $addr-handle-stream-payload-size:skip-handle:
30025     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
30026     # TODO: check eax != 0
30027     # TODO: check !t->is-atom?
30028     # TODO: check t->left == stream
30029     # t = t->right
30030 $addr-handle-stream-payload-size:skip-stream:
30031     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
30032     # TODO: check eax != 0
30033     # if !t->is-atom? t = t->left
30034     81 7/subop/compare *eax 0/imm32/false
30035     {
30036       75/jump-if-!= break/disp8
30037       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
30038     }
30039 $addr-handle-stream-payload-size:compute-size:
30040     # TODO: check t->is-atom?
30041     # return size(t->value)
30042     (size-of-type-id-as-array-element *(eax+4))  # Type-tree-value => eax
30043 $addr-handle-stream-payload-size:end:
30044     # . epilogue
30045     89/<- %esp 5/r32/ebp
30046     5d/pop-to-ebp
30047     c3/return
30048 
30049 power-of-2?:  # n: int, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: boolean
30050     # precondition: n is positive
30051     # . prologue
30052     55/push-ebp
30053     89/<- %ebp 4/r32/esp
30054     # eax = n
30055     8b/-> *(ebp+8) 0/r32/eax
30056     # if (n < 0) abort
30057     3d/compare-eax-with 0/imm32
30058     0f 8c/jump-if-< $power-of-2?:abort/disp32
30059     # var tmp/eax: int = n-1
30060     48/decrement-eax
30061     # var tmp2/eax: int = n & tmp
30062     23/and-> *(ebp+8) 0/r32/eax
30063     # return (tmp2 == 0)
30064     3d/compare-eax-and 0/imm32
30065     0f 94/set-byte-if-= %al
30066     81 4/subop/and %eax 0xff/imm32
30067 $power-of-2?:end:
30068     # . epilogue
30069     89/<- %esp 5/r32/ebp
30070     5d/pop-to-ebp
30071     c3/return
30072 
30073 $power-of-2?:abort:
30074     (write-buffered *(ebp+0xc) "power-of-2?: negative number\n")
30075     (flush *(ebp+0xc))
30076     (stop *(ebp+0x10) 1)
30077     # never gets here
30078 
30079 num-shift-rights:  # n: int -> result/eax: int
30080     # precondition: n is a positive power of 2
30081     # . prologue
30082     55/push-ebp
30083     89/<- %ebp 4/r32/esp
30084     # . save registers
30085     51/push-ecx
30086     # var curr/ecx: int = n
30087     8b/-> *(ebp+8) 1/r32/ecx
30088     # result = 0
30089     b8/copy-to-eax 0/imm32
30090     {
30091       # if (curr <= 1) break
30092       81 7/subop/compare %ecx 1/imm32
30093       7e/jump-if-<= break/disp8
30094       40/increment-eax
30095       c1/shift 5/subop/arithmetic-right %ecx 1/imm8
30096       eb/jump loop/disp8
30097     }
30098 $num-shift-rights:end:
30099     # . restore registers
30100     59/pop-to-ecx
30101     # . epilogue
30102     89/<- %esp 5/r32/ebp
30103     5d/pop-to-ebp
30104     c3/return
30105 
30106 mu-get-offset:  # stmt: (addr stmt) -> result/eax: int
30107     # . prologue
30108     55/push-ebp
30109     89/<- %ebp 4/r32/esp
30110     # var second-inout/eax: (addr stmt-var) = stmt->inouts->next
30111     8b/-> *(ebp+8) 0/r32/eax
30112     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
30113     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
30114     # var output-var/eax: (addr var) = second-inout->value
30115     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
30116 #?     (write-buffered Stderr "mu-get-offset: ")
30117 #?     (write-int32-hex-buffered Stderr %eax)
30118 #?     (write-buffered Stderr " name: ")
30119 #?     50/push-eax
30120 #?     (lookup *eax *(eax+4))  # Var-name
30121 #?     (write-buffered Stderr %eax)
30122 #?     58/pop-to-eax
30123 #?     (write-buffered Stderr Newline)
30124 #?     (flush Stderr)
30125     # return output-var->stack-offset
30126     8b/-> *(eax+0x14) 0/r32/eax  # Var-offset
30127 #?     (write-buffered Stderr "=> ")
30128 #?     (write-int32-hex-buffered Stderr %eax)
30129 #?     (write-buffered Stderr Newline)
30130 #?     (flush Stderr)
30131 $emit-get-offset:end:
30132     # . epilogue
30133     89/<- %esp 5/r32/ebp
30134     5d/pop-to-ebp
30135     c3/return
30136 
30137 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)
30138     # . prologue
30139     55/push-ebp
30140     89/<- %ebp 4/r32/esp
30141     # . save registers
30142     50/push-eax
30143     51/push-ecx
30144     56/push-esi
30145     # esi = block
30146     8b/-> *(ebp+0xc) 6/r32/esi
30147     # block->var->block-depth = *Curr-block-depth
30148     (lookup *(esi+0xc) *(esi+0x10))  # Block-var Block-var => eax
30149     8b/-> *Curr-block-depth 1/r32/ecx
30150     89/<- *(eax+0x10) 1/r32/ecx  # Var-block-depth
30151     # var stmts/eax: (addr list stmt) = lookup(block->statements)
30152     (lookup *(esi+4) *(esi+8))  # Block-stmts Block-stmts => eax
30153     #
30154     {
30155 $emit-subx-block:check-empty:
30156       3d/compare-eax-and 0/imm32
30157       0f 84/jump-if-= break/disp32
30158       (emit-indent *(ebp+8) *Curr-block-depth)
30159       (write-buffered *(ebp+8) "{\n")
30160       # var v/ecx: (addr var) = lookup(block->var)
30161       (lookup *(esi+0xc) *(esi+0x10))  # Block-var Block-var => eax
30162       89/<- %ecx 0/r32/eax
30163       #
30164       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
30165       (write-buffered *(ebp+8) %eax)
30166       (write-buffered *(ebp+8) ":loop:\n")
30167       ff 0/subop/increment *Curr-block-depth
30168       (push *(ebp+0x10) *(esi+0xc))  # Block-var
30169       (push *(ebp+0x10) *(esi+0x10))  # Block-var
30170       (push *(ebp+0x10) 0)  # false
30171       # emit block->statements
30172       (lookup *(esi+4) *(esi+8))  # Block-stmts Block-stmts => eax
30173       (emit-subx-stmt-list *(ebp+8) %eax *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
30174       (pop *(ebp+0x10))  # => eax
30175       (pop *(ebp+0x10))  # => eax
30176       (pop *(ebp+0x10))  # => eax
30177       ff 1/subop/decrement *Curr-block-depth
30178       (emit-indent *(ebp+8) *Curr-block-depth)
30179       (write-buffered *(ebp+8) "}\n")
30180       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
30181       (write-buffered *(ebp+8) %eax)
30182       (write-buffered *(ebp+8) ":break:\n")
30183     }
30184 $emit-subx-block:end:
30185     # . restore registers
30186     5e/pop-to-esi
30187     59/pop-to-ecx
30188     58/pop-to-eax
30189     # . epilogue
30190     89/<- %esp 5/r32/ebp
30191     5d/pop-to-ebp
30192     c3/return
30193 
30194 # Primitives supported
30195 # See mu_instructions for a summary of this linked-list data structure.
30196 #
30197 # For each operation, put variants with hard-coded registers before flexible ones.
30198 #
30199 # Unfortunately, our restrictions on addresses require that various fields in
30200 # primitives be handles, which complicates these definitions.
30201 #   - we need to insert dummy fields all over the place for fake alloc-ids
30202 #   - we can't use our syntax sugar of quoted literals for string fields
30203 #
30204 # Fake alloc-ids are needed because our type definitions up top require
30205 # handles but it's clearer to statically allocate these long-lived objects.
30206 # Fake alloc-ids are perfectly safe, but they can't be reclaimed.
30207 #
30208 # Every 'object' below starts with a fake alloc-id. It may also contain other
30209 # fake alloc-ids for various handle fields.
30210 #
30211 # I think of objects starting with a fake alloc-id as having type 'payload'.
30212 # It's not really intended to be created dynamically; for that use `allocate`
30213 # as usual.
30214 #
30215 # Idea for a notation to simplify such definitions:
30216 #   _Primitive-increment-eax:  # (payload primitive)
30217 #     0x11/alloc-id:fake:payload
30218 #     0x11 @(0x11 "increment")  # name
30219 #     0 0                       # inouts
30220 #     0x11 @(0x11/payload
30221 #            0x11 @(0x11/payload  # List-value
30222 #                   0 0             # Var-name
30223 #                   0x11 @(0x11     # Var-type
30224 #                          1/is-atom
30225 #                          1/value 0/unused   # Type-tree-left
30226 #                          0 0                # Type-tree-right
30227 #                         )
30228 #                   1               # block-depth
30229 #                   0               # stack-offset
30230 #                   0x11 @(0x11 "eax")  # Var-register
30231 #                  )
30232 #            0 0)                 # List-next
30233 #     ...
30234 #     _Primitive-increment-ecx/imm32/next
30235 #   ...
30236 # Awfully complex and non-obvious. But also clearly signals there's something
30237 # to learn here, so may be worth trying.
30238 #
30239 # '@' is just an initial thought. Punctuation used so far in Mu: () * % # / "
30240 #
30241 # For now we'll continue to just use comments and manually ensure they stay up
30242 # to date.
30243 == data
30244 Primitives:  # (addr primitive)
30245 # - increment/decrement
30246 _Primitive-increment-eax:  # (addr primitive)
30247     # var/eax <- increment => 40/increment-eax
30248     0x11/imm32/alloc-id:fake
30249     _string-increment/imm32/name
30250     0/imm32/no-inouts
30251     0/imm32/no-inouts
30252     0x11/imm32/alloc-id:fake
30253     Single-int-var-in-eax/imm32/outputs
30254     0x11/imm32/alloc-id:fake
30255     _string_40_increment_eax/imm32/subx-name
30256     0/imm32/no-rm32
30257     0/imm32/no-r32
30258     0/imm32/no-imm32
30259     0/imm32/no-imm8
30260     0/imm32/no-disp32
30261     0/imm32/no-xm32
30262     0/imm32/no-x32
30263     0x11/imm32/alloc-id:fake
30264     _Primitive-increment-ecx/imm32/next
30265 _Primitive-increment-ecx:  # (payload primitive)
30266     0x11/imm32/alloc-id:fake:payload
30267     # var/ecx <- increment => 41/increment-ecx
30268     0x11/imm32/alloc-id:fake
30269     _string-increment/imm32/name
30270     0/imm32/no-inouts
30271     0/imm32/no-inouts
30272     0x11/imm32/alloc-id:fake
30273     Single-int-var-in-ecx/imm32/outputs
30274     0x11/imm32/alloc-id:fake
30275     _string_41_increment_ecx/imm32/subx-name
30276     0/imm32/no-rm32
30277     0/imm32/no-r32
30278     0/imm32/no-imm32
30279     0/imm32/no-imm8
30280     0/imm32/no-disp32
30281     0/imm32/no-xm32
30282     0/imm32/no-x32
30283     0x11/imm32/alloc-id:fake
30284     _Primitive-increment-edx/imm32/next
30285 _Primitive-increment-edx:  # (payload primitive)
30286     0x11/imm32/alloc-id:fake:payload
30287     # var/edx <- increment => 42/increment-edx
30288     0x11/imm32/alloc-id:fake
30289     _string-increment/imm32/name
30290     0/imm32/no-inouts
30291     0/imm32/no-inouts
30292     0x11/imm32/alloc-id:fake
30293     Single-int-var-in-edx/imm32/outputs
30294     0x11/imm32/alloc-id:fake
30295     _string_42_increment_edx/imm32/subx-name
30296     0/imm32/no-rm32
30297     0/imm32/no-r32
30298     0/imm32/no-imm32
30299     0/imm32/no-imm8
30300     0/imm32/no-disp32
30301     0/imm32/no-xm32
30302     0/imm32/no-x32
30303     0x11/imm32/alloc-id:fake
30304     _Primitive-increment-ebx/imm32/next
30305 _Primitive-increment-ebx:  # (payload primitive)
30306     0x11/imm32/alloc-id:fake:payload
30307     # var/ebx <- increment => 43/increment-ebx
30308     0x11/imm32/alloc-id:fake
30309     _string-increment/imm32/name
30310     0/imm32/no-inouts
30311     0/imm32/no-inouts
30312     0x11/imm32/alloc-id:fake
30313     Single-int-var-in-ebx/imm32/outputs
30314     0x11/imm32/alloc-id:fake
30315     _string_43_increment_ebx/imm32/subx-name
30316     0/imm32/no-rm32
30317     0/imm32/no-r32
30318     0/imm32/no-imm32
30319     0/imm32/no-imm8
30320     0/imm32/no-disp32
30321     0/imm32/no-xm32
30322     0/imm32/no-x32
30323     0x11/imm32/alloc-id:fake
30324     _Primitive-increment-esi/imm32/next
30325 _Primitive-increment-esi:  # (payload primitive)
30326     0x11/imm32/alloc-id:fake:payload
30327     # var/esi <- increment => 46/increment-esi
30328     0x11/imm32/alloc-id:fake
30329     _string-increment/imm32/name
30330     0/imm32/no-inouts
30331     0/imm32/no-inouts
30332     0x11/imm32/alloc-id:fake
30333     Single-int-var-in-esi/imm32/outputs
30334     0x11/imm32/alloc-id:fake
30335     _string_46_increment_esi/imm32/subx-name
30336     0/imm32/no-rm32
30337     0/imm32/no-r32
30338     0/imm32/no-imm32
30339     0/imm32/no-imm8
30340     0/imm32/no-disp32
30341     0/imm32/no-xm32
30342     0/imm32/no-x32
30343     0x11/imm32/alloc-id:fake
30344     _Primitive-increment-edi/imm32/next
30345 _Primitive-increment-edi:  # (payload primitive)
30346     0x11/imm32/alloc-id:fake:payload
30347     # var/edi <- increment => 47/increment-edi
30348     0x11/imm32/alloc-id:fake
30349     _string-increment/imm32/name
30350     0/imm32/no-inouts
30351     0/imm32/no-inouts
30352     0x11/imm32/alloc-id:fake
30353     Single-int-var-in-edi/imm32/outputs
30354     0x11/imm32/alloc-id:fake
30355     _string_47_increment_edi/imm32/subx-name
30356     0/imm32/no-rm32
30357     0/imm32/no-r32
30358     0/imm32/no-imm32
30359     0/imm32/no-imm8
30360     0/imm32/no-disp32
30361     0/imm32/no-xm32
30362     0/imm32/no-x32
30363     0x11/imm32/alloc-id:fake
30364     _Primitive-decrement-eax/imm32/next
30365 _Primitive-decrement-eax:  # (payload primitive)
30366     0x11/imm32/alloc-id:fake:payload
30367     # var/eax <- decrement => 48/decrement-eax
30368     0x11/imm32/alloc-id:fake
30369     _string-decrement/imm32/name
30370     0/imm32/no-inouts
30371     0/imm32/no-inouts
30372     0x11/imm32/alloc-id:fake
30373     Single-int-var-in-eax/imm32/outputs
30374     0x11/imm32/alloc-id:fake
30375     _string_48_decrement_eax/imm32/subx-name
30376     0/imm32/no-rm32
30377     0/imm32/no-r32
30378     0/imm32/no-imm32
30379     0/imm32/no-imm8
30380     0/imm32/no-disp32
30381     0/imm32/no-xm32
30382     0/imm32/no-x32
30383     0x11/imm32/alloc-id:fake
30384     _Primitive-decrement-ecx/imm32/next
30385 _Primitive-decrement-ecx:  # (payload primitive)
30386     0x11/imm32/alloc-id:fake:payload
30387     # var/ecx <- decrement => 49/decrement-ecx
30388     0x11/imm32/alloc-id:fake
30389     _string-decrement/imm32/name
30390     0/imm32/no-inouts
30391     0/imm32/no-inouts
30392     0x11/imm32/alloc-id:fake
30393     Single-int-var-in-ecx/imm32/outputs
30394     0x11/imm32/alloc-id:fake
30395     _string_49_decrement_ecx/imm32/subx-name
30396     0/imm32/no-rm32
30397     0/imm32/no-r32
30398     0/imm32/no-imm32
30399     0/imm32/no-imm8
30400     0/imm32/no-disp32
30401     0/imm32/no-xm32
30402     0/imm32/no-x32
30403     0x11/imm32/alloc-id:fake
30404     _Primitive-decrement-edx/imm32/next
30405 _Primitive-decrement-edx:  # (payload primitive)
30406     0x11/imm32/alloc-id:fake:payload
30407     # var/edx <- decrement => 4a/decrement-edx
30408     0x11/imm32/alloc-id:fake
30409     _string-decrement/imm32/name
30410     0/imm32/no-inouts
30411     0/imm32/no-inouts
30412     0x11/imm32/alloc-id:fake
30413     Single-int-var-in-edx/imm32/outputs
30414     0x11/imm32/alloc-id:fake
30415     _string_4a_decrement_edx/imm32/subx-name
30416     0/imm32/no-rm32
30417     0/imm32/no-r32
30418     0/imm32/no-imm32
30419     0/imm32/no-imm8
30420     0/imm32/no-disp32
30421     0/imm32/no-xm32
30422     0/imm32/no-x32
30423     0x11/imm32/alloc-id:fake
30424     _Primitive-decrement-ebx/imm32/next
30425 _Primitive-decrement-ebx:  # (payload primitive)
30426     0x11/imm32/alloc-id:fake:payload
30427     # var/ebx <- decrement => 4b/decrement-ebx
30428     0x11/imm32/alloc-id:fake
30429     _string-decrement/imm32/name
30430     0/imm32/no-inouts
30431     0/imm32/no-inouts
30432     0x11/imm32/alloc-id:fake
30433     Single-int-var-in-ebx/imm32/outputs
30434     0x11/imm32/alloc-id:fake
30435     _string_4b_decrement_ebx/imm32/subx-name
30436     0/imm32/no-rm32
30437     0/imm32/no-r32
30438     0/imm32/no-imm32
30439     0/imm32/no-imm8
30440     0/imm32/no-disp32
30441     0/imm32/no-xm32
30442     0/imm32/no-x32
30443     0x11/imm32/alloc-id:fake
30444     _Primitive-decrement-esi/imm32/next
30445 _Primitive-decrement-esi:  # (payload primitive)
30446     0x11/imm32/alloc-id:fake:payload
30447     # var/esi <- decrement => 4e/decrement-esi
30448     0x11/imm32/alloc-id:fake
30449     _string-decrement/imm32/name
30450     0/imm32/no-inouts
30451     0/imm32/no-inouts
30452     0x11/imm32/alloc-id:fake
30453     Single-int-var-in-esi/imm32/outputs
30454     0x11/imm32/alloc-id:fake
30455     _string_4e_decrement_esi/imm32/subx-name
30456     0/imm32/no-rm32
30457     0/imm32/no-r32
30458     0/imm32/no-imm32
30459     0/imm32/no-imm8
30460     0/imm32/no-disp32
30461     0/imm32/no-xm32
30462     0/imm32/no-x32
30463     0x11/imm32/alloc-id:fake
30464     _Primitive-decrement-edi/imm32/next
30465 _Primitive-decrement-edi:  # (payload primitive)
30466     0x11/imm32/alloc-id:fake:payload
30467     # var/edi <- decrement => 4f/decrement-edi
30468     0x11/imm32/alloc-id:fake
30469     _string-decrement/imm32/name
30470     0/imm32/no-inouts
30471     0/imm32/no-inouts
30472     0x11/imm32/alloc-id:fake
30473     Single-int-var-in-edi/imm32/outputs
30474     0x11/imm32/alloc-id:fake
30475     _string_4f_decrement_edi/imm32/subx-name
30476     0/imm32/no-rm32
30477     0/imm32/no-r32
30478     0/imm32/no-imm32
30479     0/imm32/no-imm8
30480     0/imm32/no-disp32
30481     0/imm32/no-xm32
30482     0/imm32/no-x32
30483     0x11/imm32/alloc-id:fake
30484     _Primitive-increment-mem/imm32/next
30485 _Primitive-increment-mem:  # (payload primitive)
30486     0x11/imm32/alloc-id:fake:payload
30487     # increment var => ff 0/subop/increment *(ebp+__)
30488     0x11/imm32/alloc-id:fake
30489     _string-increment/imm32/name
30490     0x11/imm32/alloc-id:fake
30491     Single-int-var-in-mem/imm32/inouts
30492     0/imm32/no-outputs
30493     0/imm32/no-outputs
30494     0x11/imm32/alloc-id:fake
30495     _string_ff_subop_increment/imm32/subx-name
30496     1/imm32/rm32-is-first-inout
30497     0/imm32/no-r32
30498     0/imm32/no-imm32
30499     0/imm32/no-imm8
30500     0/imm32/no-disp32
30501     0/imm32/no-xm32
30502     0/imm32/no-x32
30503     0x11/imm32/alloc-id:fake
30504     _Primitive-increment-reg/imm32/next
30505 _Primitive-increment-reg:  # (payload primitive)
30506     0x11/imm32/alloc-id:fake:payload
30507     # var/reg <- increment => ff 0/subop/increment %__
30508     0x11/imm32/alloc-id:fake
30509     _string-increment/imm32/name
30510     0/imm32/no-inouts
30511     0/imm32/no-inouts
30512     0x11/imm32/alloc-id:fake
30513     Single-int-var-in-some-register/imm32/outputs
30514     0x11/imm32/alloc-id:fake
30515     _string_ff_subop_increment/imm32/subx-name
30516     3/imm32/rm32-is-first-output
30517     0/imm32/no-r32
30518     0/imm32/no-imm32
30519     0/imm32/no-imm8
30520     0/imm32/no-disp32
30521     0/imm32/no-xm32
30522     0/imm32/no-x32
30523     0x11/imm32/alloc-id:fake
30524     _Primitive-decrement-mem/imm32/next
30525 _Primitive-decrement-mem:  # (payload primitive)
30526     0x11/imm32/alloc-id:fake:payload
30527     # decrement var => ff 1/subop/decrement *(ebp+__)
30528     0x11/imm32/alloc-id:fake
30529     _string-decrement/imm32/name
30530     0x11/imm32/alloc-id:fake
30531     Single-int-var-in-mem/imm32/inouts
30532     0/imm32/no-outputs
30533     0/imm32/no-outputs
30534     0x11/imm32/alloc-id:fake
30535     _string_ff_subop_decrement/imm32/subx-name
30536     1/imm32/rm32-is-first-inout
30537     0/imm32/no-r32
30538     0/imm32/no-imm32
30539     0/imm32/no-imm8
30540     0/imm32/no-disp32
30541     0/imm32/no-xm32
30542     0/imm32/no-x32
30543     0x11/imm32/alloc-id:fake
30544     _Primitive-decrement-reg/imm32/next
30545 _Primitive-decrement-reg:  # (payload primitive)
30546     0x11/imm32/alloc-id:fake:payload
30547     # var/reg <- decrement => ff 1/subop/decrement %__
30548     0x11/imm32/alloc-id:fake
30549     _string-decrement/imm32/name
30550     0/imm32/no-inouts
30551     0/imm32/no-inouts
30552     0x11/imm32/alloc-id:fake
30553     Single-int-var-in-some-register/imm32/outputs
30554     0x11/imm32/alloc-id:fake
30555     _string_ff_subop_decrement/imm32/subx-name
30556     3/imm32/rm32-is-first-output
30557     0/imm32/no-r32
30558     0/imm32/no-imm32
30559     0/imm32/no-imm8
30560     0/imm32/no-disp32
30561     0/imm32/no-xm32
30562     0/imm32/no-x32
30563     0x11/imm32/alloc-id:fake
30564     _Primitive-add-to-eax/imm32/next
30565 # - add
30566 _Primitive-add-to-eax:  # (payload primitive)
30567     0x11/imm32/alloc-id:fake:payload
30568     # var/eax <- add lit => 05/add-to-eax lit/imm32
30569     0x11/imm32/alloc-id:fake
30570     _string-add/imm32/name
30571     0x11/imm32/alloc-id:fake
30572     Single-lit-var/imm32/inouts
30573     0x11/imm32/alloc-id:fake
30574     Single-int-var-in-eax/imm32/outputs
30575     0x11/imm32/alloc-id:fake
30576     _string_05_add_to_eax/imm32/subx-name
30577     0/imm32/no-rm32
30578     0/imm32/no-r32
30579     1/imm32/imm32-is-first-inout
30580     0/imm32/no-imm8
30581     0/imm32/no-disp32
30582     0/imm32/no-xm32
30583     0/imm32/no-x32
30584     0x11/imm32/alloc-id:fake
30585     _Primitive-add-reg-to-reg/imm32/next
30586 _Primitive-add-reg-to-reg:  # (payload primitive)
30587     0x11/imm32/alloc-id:fake:payload
30588     # var1/reg <- add var2/reg => 01/add-to var1/rm32 var2/r32
30589     0x11/imm32/alloc-id:fake
30590     _string-add/imm32/name
30591     0x11/imm32/alloc-id:fake
30592     Single-int-var-in-some-register/imm32/inouts
30593     0x11/imm32/alloc-id:fake
30594     Single-int-var-in-some-register/imm32/outputs
30595     0x11/imm32/alloc-id:fake
30596     _string_01_add_to/imm32/subx-name
30597     3/imm32/rm32-is-first-output
30598     1/imm32/r32-is-first-inout
30599     0/imm32/no-imm32
30600     0/imm32/no-imm8
30601     0/imm32/no-disp32
30602     0/imm32/no-xm32
30603     0/imm32/no-x32
30604     0x11/imm32/alloc-id:fake
30605     _Primitive-add-reg-to-mem/imm32/next
30606 _Primitive-add-reg-to-mem:  # (payload primitive)
30607     0x11/imm32/alloc-id:fake:payload
30608     # add-to var1 var2/reg => 01/add-to var1 var2/r32
30609     0x11/imm32/alloc-id:fake
30610     _string-add-to/imm32/name
30611     0x11/imm32/alloc-id:fake
30612     Two-args-int-stack-int-reg/imm32/inouts
30613     0/imm32/no-outputs
30614     0/imm32/no-outputs
30615     0x11/imm32/alloc-id:fake
30616     _string_01_add_to/imm32/subx-name
30617     1/imm32/rm32-is-first-inout
30618     2/imm32/r32-is-second-inout
30619     0/imm32/no-imm32
30620     0/imm32/no-imm8
30621     0/imm32/no-disp32
30622     0/imm32/no-xm32
30623     0/imm32/no-x32
30624     0x11/imm32/alloc-id:fake
30625     _Primitive-add-mem-to-reg/imm32/next
30626 _Primitive-add-mem-to-reg:  # (payload primitive)
30627     0x11/imm32/alloc-id:fake:payload
30628     # var1/reg <- add var2 => 03/add var2/rm32 var1/r32
30629     0x11/imm32/alloc-id:fake
30630     _string-add/imm32/name
30631     0x11/imm32/alloc-id:fake
30632     Single-int-var-in-mem/imm32/inouts
30633     0x11/imm32/alloc-id:fake
30634     Single-int-var-in-some-register/imm32/outputs
30635     0x11/imm32/alloc-id:fake
30636     _string_03_add/imm32/subx-name
30637     1/imm32/rm32-is-first-inout
30638     3/imm32/r32-is-first-output
30639     0/imm32/no-imm32
30640     0/imm32/no-imm8
30641     0/imm32/no-disp32
30642     0/imm32/no-xm32
30643     0/imm32/no-x32
30644     0x11/imm32/alloc-id:fake
30645     _Primitive-add-lit-to-reg/imm32/next
30646 _Primitive-add-lit-to-reg:  # (payload primitive)
30647     0x11/imm32/alloc-id:fake:payload
30648     # var1/reg <- add lit => 81 0/subop/add var1/rm32 lit/imm32
30649     0x11/imm32/alloc-id:fake
30650     _string-add/imm32/name
30651     0x11/imm32/alloc-id:fake
30652     Single-lit-var/imm32/inouts
30653     0x11/imm32/alloc-id:fake
30654     Single-int-var-in-some-register/imm32/outputs
30655     0x11/imm32/alloc-id:fake
30656     _string_81_subop_add/imm32/subx-name
30657     3/imm32/rm32-is-first-output
30658     0/imm32/no-r32
30659     1/imm32/imm32-is-first-inout
30660     0/imm32/no-imm8
30661     0/imm32/no-disp32
30662     0/imm32/no-xm32
30663     0/imm32/no-x32
30664     0x11/imm32/alloc-id:fake
30665     _Primitive-add-lit-to-mem/imm32/next
30666 _Primitive-add-lit-to-mem:  # (payload primitive)
30667     0x11/imm32/alloc-id:fake:payload
30668     # add-to var1, lit => 81 0/subop/add var1/rm32 lit/imm32
30669     0x11/imm32/alloc-id:fake
30670     _string-add-to/imm32/name
30671     0x11/imm32/alloc-id:fake
30672     Int-var-and-literal/imm32/inouts
30673     0/imm32/no-outputs
30674     0/imm32/no-outputs
30675     0x11/imm32/alloc-id:fake
30676     _string_81_subop_add/imm32/subx-name
30677     1/imm32/rm32-is-first-inout
30678     0/imm32/no-r32
30679     2/imm32/imm32-is-second-inout
30680     0/imm32/no-imm8
30681     0/imm32/no-disp32
30682     0/imm32/no-xm32
30683     0/imm32/no-x32
30684     0x11/imm32/alloc-id:fake
30685     _Primitive-subtract-from-eax/imm32/next
30686 # - subtract
30687 _Primitive-subtract-from-eax:  # (payload primitive)
30688     0x11/imm32/alloc-id:fake:payload
30689     # var/eax <- subtract lit => 2d/subtract-from-eax lit/imm32
30690     0x11/imm32/alloc-id:fake
30691     _string-subtract/imm32/name
30692     0x11/imm32/alloc-id:fake
30693     Single-lit-var/imm32/inouts
30694     0x11/imm32/alloc-id:fake
30695     Single-int-var-in-eax/imm32/outputs
30696     0x11/imm32/alloc-id:fake
30697     _string_2d_subtract_from_eax/imm32/subx-name
30698     0/imm32/no-rm32
30699     0/imm32/no-r32
30700     1/imm32/imm32-is-first-inout
30701     0/imm32/no-imm8
30702     0/imm32/no-disp32
30703     0/imm32/no-xm32
30704     0/imm32/no-x32
30705     0x11/imm32/alloc-id:fake
30706     _Primitive-subtract-reg-from-reg/imm32/next
30707 _Primitive-subtract-reg-from-reg:  # (payload primitive)
30708     0x11/imm32/alloc-id:fake:payload
30709     # var1/reg <- subtract var2/reg => 29/subtract-from var1/rm32 var2/r32
30710     0x11/imm32/alloc-id:fake
30711     _string-subtract/imm32/name
30712     0x11/imm32/alloc-id:fake
30713     Single-int-var-in-some-register/imm32/inouts
30714     0x11/imm32/alloc-id:fake
30715     Single-int-var-in-some-register/imm32/outputs
30716     0x11/imm32/alloc-id:fake
30717     _string_29_subtract_from/imm32/subx-name
30718     3/imm32/rm32-is-first-output
30719     1/imm32/r32-is-first-inout
30720     0/imm32/no-imm32
30721     0/imm32/no-imm8
30722     0/imm32/no-disp32
30723     0/imm32/no-xm32
30724     0/imm32/no-x32
30725     0x11/imm32/alloc-id:fake
30726     _Primitive-subtract-reg-from-mem/imm32/next
30727 _Primitive-subtract-reg-from-mem:  # (payload primitive)
30728     0x11/imm32/alloc-id:fake:payload
30729     # subtract-from var1 var2/reg => 29/subtract-from var1 var2/r32
30730     0x11/imm32/alloc-id:fake
30731     _string-subtract-from/imm32/name
30732     0x11/imm32/alloc-id:fake
30733     Two-args-int-stack-int-reg/imm32/inouts
30734     0/imm32/no-outputs
30735     0/imm32/no-outputs
30736     0x11/imm32/alloc-id:fake
30737     _string_29_subtract_from/imm32/subx-name
30738     1/imm32/rm32-is-first-inout
30739     2/imm32/r32-is-second-inout
30740     0/imm32/no-imm32
30741     0/imm32/no-imm8
30742     0/imm32/no-disp32
30743     0/imm32/no-xm32
30744     0/imm32/no-x32
30745     0x11/imm32/alloc-id:fake
30746     _Primitive-subtract-mem-from-reg/imm32/next
30747 _Primitive-subtract-mem-from-reg:  # (payload primitive)
30748     0x11/imm32/alloc-id:fake:payload
30749     # var1/reg <- subtract var2 => 2b/subtract var2/rm32 var1/r32
30750     0x11/imm32/alloc-id:fake
30751     _string-subtract/imm32/name
30752     0x11/imm32/alloc-id:fake
30753     Single-int-var-in-mem/imm32/inouts
30754     0x11/imm32/alloc-id:fake
30755     Single-int-var-in-some-register/imm32/outputs
30756     0x11/imm32/alloc-id:fake
30757     _string_2b_subtract/imm32/subx-name
30758     1/imm32/rm32-is-first-inout
30759     3/imm32/r32-is-first-output
30760     0/imm32/no-imm32
30761     0/imm32/no-imm8
30762     0/imm32/no-disp32
30763     0/imm32/no-xm32
30764     0/imm32/no-x32
30765     0x11/imm32/alloc-id:fake
30766     _Primitive-subtract-lit-from-reg/imm32/next
30767 _Primitive-subtract-lit-from-reg:  # (payload primitive)
30768     0x11/imm32/alloc-id:fake:payload
30769     # var1/reg <- subtract lit => 81 5/subop/subtract var1/rm32 lit/imm32
30770     0x11/imm32/alloc-id:fake
30771     _string-subtract/imm32/name
30772     0x11/imm32/alloc-id:fake
30773     Single-lit-var/imm32/inouts
30774     0x11/imm32/alloc-id:fake
30775     Single-int-var-in-some-register/imm32/outputs
30776     0x11/imm32/alloc-id:fake
30777     _string_81_subop_subtract/imm32/subx-name
30778     3/imm32/rm32-is-first-output
30779     0/imm32/no-r32
30780     1/imm32/imm32-is-first-inout
30781     0/imm32/no-imm8
30782     0/imm32/no-disp32
30783     0/imm32/no-xm32
30784     0/imm32/no-x32
30785     0x11/imm32/alloc-id:fake
30786     _Primitive-subtract-lit-from-mem/imm32/next
30787 _Primitive-subtract-lit-from-mem:  # (payload primitive)
30788     0x11/imm32/alloc-id:fake:payload
30789     # subtract-from var1, lit => 81 5/subop/subtract var1/rm32 lit/imm32
30790     0x11/imm32/alloc-id:fake
30791     _string-subtract-from/imm32/name
30792     0x11/imm32/alloc-id:fake
30793     Int-var-and-literal/imm32/inouts
30794     0/imm32/no-outputs
30795     0/imm32/no-outputs
30796     0x11/imm32/alloc-id:fake
30797     _string_81_subop_subtract/imm32/subx-name
30798     1/imm32/rm32-is-first-inout
30799     0/imm32/no-r32
30800     2/imm32/imm32-is-second-inout
30801     0/imm32/no-imm8
30802     0/imm32/no-disp32
30803     0/imm32/no-xm32
30804     0/imm32/no-x32
30805     0x11/imm32/alloc-id:fake
30806     _Primitive-and-with-eax/imm32/next
30807 # - and
30808 _Primitive-and-with-eax:  # (payload primitive)
30809     0x11/imm32/alloc-id:fake:payload
30810     # var/eax <- and lit => 25/and-with-eax lit/imm32
30811     0x11/imm32/alloc-id:fake
30812     _string-and/imm32/name
30813     0x11/imm32/alloc-id:fake
30814     Single-lit-var/imm32/inouts
30815     0x11/imm32/alloc-id:fake
30816     Single-int-var-in-eax/imm32/outputs
30817     0x11/imm32/alloc-id:fake
30818     _string_25_and_with_eax/imm32/subx-name
30819     0/imm32/no-rm32
30820     0/imm32/no-r32
30821     1/imm32/imm32-is-first-inout
30822     0/imm32/no-imm8
30823     0/imm32/no-disp32
30824     0/imm32/no-xm32
30825     0/imm32/no-x32
30826     0x11/imm32/alloc-id:fake
30827     _Primitive-and-reg-with-reg/imm32/next
30828 _Primitive-and-reg-with-reg:  # (payload primitive)
30829     0x11/imm32/alloc-id:fake:payload
30830     # var1/reg <- and var2/reg => 21/and-with var1/rm32 var2/r32
30831     0x11/imm32/alloc-id:fake
30832     _string-and/imm32/name
30833     0x11/imm32/alloc-id:fake
30834     Single-int-var-in-some-register/imm32/inouts
30835     0x11/imm32/alloc-id:fake
30836     Single-int-var-in-some-register/imm32/outputs
30837     0x11/imm32/alloc-id:fake
30838     _string_21_and_with/imm32/subx-name
30839     3/imm32/rm32-is-first-output
30840     1/imm32/r32-is-first-inout
30841     0/imm32/no-imm32
30842     0/imm32/no-imm8
30843     0/imm32/no-disp32
30844     0/imm32/no-xm32
30845     0/imm32/no-x32
30846     0x11/imm32/alloc-id:fake
30847     _Primitive-and-reg-with-mem/imm32/next
30848 _Primitive-and-reg-with-mem:  # (payload primitive)
30849     0x11/imm32/alloc-id:fake:payload
30850     # and-with var1 var2/reg => 21/and-with var1 var2/r32
30851     0x11/imm32/alloc-id:fake
30852     _string-and-with/imm32/name
30853     0x11/imm32/alloc-id:fake
30854     Two-args-int-stack-int-reg/imm32/inouts
30855     0/imm32/no-outputs
30856     0/imm32/no-outputs
30857     0x11/imm32/alloc-id:fake
30858     _string_21_and_with/imm32/subx-name
30859     1/imm32/rm32-is-first-inout
30860     2/imm32/r32-is-second-inout
30861     0/imm32/no-imm32
30862     0/imm32/no-imm8
30863     0/imm32/no-disp32
30864     0/imm32/no-xm32
30865     0/imm32/no-x32
30866     0x11/imm32/alloc-id:fake
30867     _Primitive-and-mem-with-reg/imm32/next
30868 _Primitive-and-mem-with-reg:  # (payload primitive)
30869     0x11/imm32/alloc-id:fake:payload
30870     # var1/reg <- and var2 => 23/and var2/rm32 var1/r32
30871     0x11/imm32/alloc-id:fake
30872     _string-and/imm32/name
30873     0x11/imm32/alloc-id:fake
30874     Single-int-var-in-mem/imm32/inouts
30875     0x11/imm32/alloc-id:fake
30876     Single-int-var-in-some-register/imm32/outputs
30877     0x11/imm32/alloc-id:fake
30878     _string_23_and/imm32/subx-name
30879     1/imm32/rm32-is-first-inout
30880     3/imm32/r32-is-first-output
30881     0/imm32/no-imm32
30882     0/imm32/no-imm8
30883     0/imm32/no-disp32
30884     0/imm32/no-xm32
30885     0/imm32/no-x32
30886     0x11/imm32/alloc-id:fake
30887     _Primitive-and-lit-with-reg/imm32/next
30888 _Primitive-and-lit-with-reg:  # (payload primitive)
30889     0x11/imm32/alloc-id:fake:payload
30890     # var1/reg <- and lit => 81 4/subop/and var1/rm32 lit/imm32
30891     0x11/imm32/alloc-id:fake
30892     _string-and/imm32/name
30893     0x11/imm32/alloc-id:fake
30894     Single-lit-var/imm32/inouts
30895     0x11/imm32/alloc-id:fake
30896     Single-int-var-in-some-register/imm32/outputs
30897     0x11/imm32/alloc-id:fake
30898     _string_81_subop_and/imm32/subx-name
30899     3/imm32/rm32-is-first-output
30900     0/imm32/no-r32
30901     1/imm32/imm32-is-first-inout
30902     0/imm32/no-imm8
30903     0/imm32/no-disp32
30904     0/imm32/no-xm32
30905     0/imm32/no-x32
30906     0x11/imm32/alloc-id:fake
30907     _Primitive-and-lit-with-mem/imm32/next
30908 _Primitive-and-lit-with-mem:  # (payload primitive)
30909     0x11/imm32/alloc-id:fake:payload
30910     # and-with var1, lit => 81 4/subop/and var1/rm32 lit/imm32
30911     0x11/imm32/alloc-id:fake
30912     _string-and-with/imm32/name
30913     0x11/imm32/alloc-id:fake
30914     Int-var-and-literal/imm32/inouts
30915     0/imm32/no-outputs
30916     0/imm32/no-outputs
30917     0x11/imm32/alloc-id:fake
30918     _string_81_subop_and/imm32/subx-name
30919     1/imm32/rm32-is-first-inout
30920     0/imm32/no-r32
30921     2/imm32/imm32-is-second-inout
30922     0/imm32/no-imm8
30923     0/imm32/no-disp32
30924     0/imm32/no-xm32
30925     0/imm32/no-x32
30926     0x11/imm32/alloc-id:fake
30927     _Primitive-or-with-eax/imm32/next
30928 # - or
30929 _Primitive-or-with-eax:  # (payload primitive)
30930     0x11/imm32/alloc-id:fake:payload
30931     # var/eax <- or lit => 0d/or-with-eax lit/imm32
30932     0x11/imm32/alloc-id:fake
30933     _string-or/imm32/name
30934     0x11/imm32/alloc-id:fake
30935     Single-lit-var/imm32/inouts
30936     0x11/imm32/alloc-id:fake
30937     Single-int-var-in-eax/imm32/outputs
30938     0x11/imm32/alloc-id:fake
30939     _string_0d_or_with_eax/imm32/subx-name
30940     0/imm32/no-rm32
30941     0/imm32/no-r32
30942     1/imm32/imm32-is-first-inout
30943     0/imm32/no-imm8
30944     0/imm32/no-disp32
30945     0/imm32/no-xm32
30946     0/imm32/no-x32
30947     0x11/imm32/alloc-id:fake
30948     _Primitive-or-reg-with-reg/imm32/next
30949 _Primitive-or-reg-with-reg:  # (payload primitive)
30950     0x11/imm32/alloc-id:fake:payload
30951     # var1/reg <- or var2/reg => 09/or-with var1/rm32 var2/r32
30952     0x11/imm32/alloc-id:fake
30953     _string-or/imm32/name
30954     0x11/imm32/alloc-id:fake
30955     Single-int-var-in-some-register/imm32/inouts
30956     0x11/imm32/alloc-id:fake
30957     Single-int-var-in-some-register/imm32/outputs
30958     0x11/imm32/alloc-id:fake
30959     _string_09_or_with/imm32/subx-name
30960     3/imm32/rm32-is-first-output
30961     1/imm32/r32-is-first-inout
30962     0/imm32/no-imm32
30963     0/imm32/no-imm8
30964     0/imm32/no-disp32
30965     0/imm32/no-xm32
30966     0/imm32/no-x32
30967     0x11/imm32/alloc-id:fake
30968     _Primitive-or-reg-with-mem/imm32/next
30969 _Primitive-or-reg-with-mem:  # (payload primitive)
30970     0x11/imm32/alloc-id:fake:payload
30971     # or-with var1 var2/reg => 09/or-with var1 var2/r32
30972     0x11/imm32/alloc-id:fake
30973     _string-or-with/imm32/name
30974     0x11/imm32/alloc-id:fake
30975     Two-args-int-stack-int-reg/imm32/inouts
30976     0/imm32/no-outputs
30977     0/imm32/no-outputs
30978     0x11/imm32/alloc-id:fake
30979     _string_09_or_with/imm32/subx-name
30980     1/imm32/rm32-is-first-inout
30981     2/imm32/r32-is-second-inout
30982     0/imm32/no-imm32
30983     0/imm32/no-imm8
30984     0/imm32/no-disp32
30985     0/imm32/no-xm32
30986     0/imm32/no-x32
30987     0x11/imm32/alloc-id:fake
30988     _Primitive-or-mem-with-reg/imm32/next
30989 _Primitive-or-mem-with-reg:  # (payload primitive)
30990     0x11/imm32/alloc-id:fake:payload
30991     # var1/reg <- or var2 => 0b/or var2/rm32 var1/r32
30992     0x11/imm32/alloc-id:fake
30993     _string-or/imm32/name
30994     0x11/imm32/alloc-id:fake
30995     Single-int-var-in-mem/imm32/inouts
30996     0x11/imm32/alloc-id:fake
30997     Single-int-var-in-some-register/imm32/outputs
30998     0x11/imm32/alloc-id:fake
30999     _string_0b_or/imm32/subx-name
31000     1/imm32/rm32-is-first-inout
31001     3/imm32/r32-is-first-output
31002     0/imm32/no-imm32
31003     0/imm32/no-imm8
31004     0/imm32/no-disp32
31005     0/imm32/no-xm32
31006     0/imm32/no-x32
31007     0x11/imm32/alloc-id:fake
31008     _Primitive-or-lit-with-reg/imm32/next
31009 _Primitive-or-lit-with-reg:  # (payload primitive)
31010     0x11/imm32/alloc-id:fake:payload
31011     # var1/reg <- or lit => 81 1/subop/or var1/rm32 lit/imm32
31012     0x11/imm32/alloc-id:fake
31013     _string-or/imm32/name
31014     0x11/imm32/alloc-id:fake
31015     Single-lit-var/imm32/inouts
31016     0x11/imm32/alloc-id:fake
31017     Single-int-var-in-some-register/imm32/outputs
31018     0x11/imm32/alloc-id:fake
31019     _string_81_subop_or/imm32/subx-name
31020     3/imm32/rm32-is-first-output
31021     0/imm32/no-r32
31022     1/imm32/imm32-is-first-inout
31023     0/imm32/no-imm8
31024     0/imm32/no-disp32
31025     0/imm32/no-xm32
31026     0/imm32/no-x32
31027     0x11/imm32/alloc-id:fake
31028     _Primitive-or-lit-with-mem/imm32/next
31029 _Primitive-or-lit-with-mem:  # (payload primitive)
31030     0x11/imm32/alloc-id:fake:payload
31031     # or-with var1, lit => 81 1/subop/or var1/rm32 lit/imm32
31032     0x11/imm32/alloc-id:fake
31033     _string-or-with/imm32/name
31034     0x11/imm32/alloc-id:fake
31035     Int-var-and-literal/imm32/inouts
31036     0/imm32/no-outputs
31037     0/imm32/no-outputs
31038     0x11/imm32/alloc-id:fake
31039     _string_81_subop_or/imm32/subx-name
31040     1/imm32/rm32-is-first-inout
31041     0/imm32/no-r32
31042     2/imm32/imm32-is-second-inout
31043     0/imm32/no-imm8
31044     0/imm32/no-disp32
31045     0/imm32/no-xm32
31046     0/imm32/no-x32
31047     0x11/imm32/alloc-id:fake
31048     _Primitive-xor-with-eax/imm32/next
31049 # - xor
31050 _Primitive-xor-with-eax:  # (payload primitive)
31051     0x11/imm32/alloc-id:fake:payload
31052     # var/eax <- xor lit => 35/xor-with-eax lit/imm32
31053     0x11/imm32/alloc-id:fake
31054     _string-xor/imm32/name
31055     0x11/imm32/alloc-id:fake
31056     Single-lit-var/imm32/inouts
31057     0x11/imm32/alloc-id:fake
31058     Single-int-var-in-eax/imm32/outputs
31059     0x11/imm32/alloc-id:fake
31060     _string_35_xor_with_eax/imm32/subx-name
31061     0/imm32/no-rm32
31062     0/imm32/no-r32
31063     1/imm32/imm32-is-first-inout
31064     0/imm32/no-imm8
31065     0/imm32/no-disp32
31066     0/imm32/no-xm32
31067     0/imm32/no-x32
31068     0x11/imm32/alloc-id:fake
31069     _Primitive-xor-reg-with-reg/imm32/next
31070 _Primitive-xor-reg-with-reg:  # (payload primitive)
31071     0x11/imm32/alloc-id:fake:payload
31072     # var1/reg <- xor var2/reg => 31/xor-with var1/rm32 var2/r32
31073     0x11/imm32/alloc-id:fake
31074     _string-xor/imm32/name
31075     0x11/imm32/alloc-id:fake
31076     Single-int-var-in-some-register/imm32/inouts
31077     0x11/imm32/alloc-id:fake
31078     Single-int-var-in-some-register/imm32/outputs
31079     0x11/imm32/alloc-id:fake
31080     _string_31_xor_with/imm32/subx-name
31081     3/imm32/rm32-is-first-output
31082     1/imm32/r32-is-first-inout
31083     0/imm32/no-imm32
31084     0/imm32/no-imm8
31085     0/imm32/no-disp32
31086     0/imm32/no-xm32
31087     0/imm32/no-x32
31088     0x11/imm32/alloc-id:fake
31089     _Primitive-xor-reg-with-mem/imm32/next
31090 _Primitive-xor-reg-with-mem:  # (payload primitive)
31091     0x11/imm32/alloc-id:fake:payload
31092     # xor-with var1 var2/reg => 31/xor-with var1 var2/r32
31093     0x11/imm32/alloc-id:fake
31094     _string-xor-with/imm32/name
31095     0x11/imm32/alloc-id:fake
31096     Two-args-int-stack-int-reg/imm32/inouts
31097     0/imm32/no-outputs
31098     0/imm32/no-outputs
31099     0x11/imm32/alloc-id:fake
31100     _string_31_xor_with/imm32/subx-name
31101     1/imm32/rm32-is-first-inout
31102     2/imm32/r32-is-second-inout
31103     0/imm32/no-imm32
31104     0/imm32/no-imm8
31105     0/imm32/no-disp32
31106     0/imm32/no-xm32
31107     0/imm32/no-x32
31108     0x11/imm32/alloc-id:fake
31109     _Primitive-xor-mem-with-reg/imm32/next
31110 _Primitive-xor-mem-with-reg:  # (payload primitive)
31111     0x11/imm32/alloc-id:fake:payload
31112     # var1/reg <- xor var2 => 33/xor var2/rm32 var1/r32
31113     0x11/imm32/alloc-id:fake
31114     _string-xor/imm32/name
31115     0x11/imm32/alloc-id:fake
31116     Single-int-var-in-mem/imm32/inouts
31117     0x11/imm32/alloc-id:fake
31118     Single-int-var-in-some-register/imm32/outputs
31119     0x11/imm32/alloc-id:fake
31120     _string_33_xor/imm32/subx-name
31121     1/imm32/rm32-is-first-inout
31122     3/imm32/r32-is-first-output
31123     0/imm32/no-imm32
31124     0/imm32/no-imm8
31125     0/imm32/no-disp32
31126     0/imm32/no-xm32
31127     0/imm32/no-x32
31128     0x11/imm32/alloc-id:fake
31129     _Primitive-xor-lit-with-reg/imm32/next
31130 _Primitive-xor-lit-with-reg:  # (payload primitive)
31131     0x11/imm32/alloc-id:fake:payload
31132     # var1/reg <- xor lit => 81 6/subop/xor var1/rm32 lit/imm32
31133     0x11/imm32/alloc-id:fake
31134     _string-xor/imm32/name
31135     0x11/imm32/alloc-id:fake
31136     Single-lit-var/imm32/inouts
31137     0x11/imm32/alloc-id:fake
31138     Single-int-var-in-some-register/imm32/outputs
31139     0x11/imm32/alloc-id:fake
31140     _string_81_subop_xor/imm32/subx-name
31141     3/imm32/rm32-is-first-output
31142     0/imm32/no-r32
31143     1/imm32/imm32-is-first-inout
31144     0/imm32/no-imm8
31145     0/imm32/no-disp32
31146     0/imm32/no-xm32
31147     0/imm32/no-x32
31148     0x11/imm32/alloc-id:fake
31149     _Primitive-xor-lit-with-mem/imm32/next
31150 _Primitive-xor-lit-with-mem:  # (payload primitive)
31151     0x11/imm32/alloc-id:fake:payload
31152     # xor-with var1, lit => 81 6/subop/xor var1/rm32 lit/imm32
31153     0x11/imm32/alloc-id:fake
31154     _string-xor-with/imm32/name
31155     0x11/imm32/alloc-id:fake
31156     Int-var-and-literal/imm32/inouts
31157     0/imm32/no-outputs
31158     0/imm32/no-outputs
31159     0x11/imm32/alloc-id:fake
31160     _string_81_subop_xor/imm32/subx-name
31161     1/imm32/rm32-is-first-inout
31162     0/imm32/no-r32
31163     2/imm32/imm32-is-second-inout
31164     0/imm32/no-imm8
31165     0/imm32/no-disp32
31166     0/imm32/no-xm32
31167     0/imm32/no-x32
31168     0x11/imm32/alloc-id:fake
31169     _Primitive-shift-reg-left-by-lit/imm32/next
31170 _Primitive-shift-reg-left-by-lit:  # (payload primitive)
31171     0x11/imm32/alloc-id:fake:payload
31172     # var1/reg <- shift-left lit => c1/shift 4/subop/left var1/rm32 lit/imm32
31173     0x11/imm32/alloc-id:fake
31174     _string-shift-left/imm32/name
31175     0x11/imm32/alloc-id:fake
31176     Single-lit-var/imm32/inouts
31177     0x11/imm32/alloc-id:fake
31178     Single-int-var-in-some-register/imm32/outputs
31179     0x11/imm32/alloc-id:fake
31180     _string_c1_subop_shift_left/imm32/subx-name
31181     3/imm32/rm32-is-first-output
31182     0/imm32/no-r32
31183     0/imm32/no-imm32
31184     1/imm32/imm8-is-first-inout
31185     0/imm32/no-disp32
31186     0/imm32/no-xm32
31187     0/imm32/no-x32
31188     0x11/imm32/alloc-id:fake
31189     _Primitive-shift-reg-right-by-lit/imm32/next
31190 _Primitive-shift-reg-right-by-lit:  # (payload primitive)
31191     0x11/imm32/alloc-id:fake:payload
31192     # var1/reg <- shift-right lit => c1/shift 5/subop/right var1/rm32 lit/imm32
31193     0x11/imm32/alloc-id:fake
31194     _string-shift-right/imm32/name
31195     0x11/imm32/alloc-id:fake
31196     Single-lit-var/imm32/inouts
31197     0x11/imm32/alloc-id:fake
31198     Single-int-var-in-some-register/imm32/outputs
31199     0x11/imm32/alloc-id:fake
31200     _string_c1_subop_shift_right_padding_zeroes/imm32/subx-name
31201     3/imm32/rm32-is-first-output
31202     0/imm32/no-r32
31203     0/imm32/no-imm32
31204     1/imm32/imm8-is-first-inout
31205     0/imm32/no-disp32
31206     0/imm32/no-xm32
31207     0/imm32/no-x32
31208     0x11/imm32/alloc-id:fake
31209     _Primitive-shift-reg-right-signed-by-lit/imm32/next
31210 _Primitive-shift-reg-right-signed-by-lit:  # (payload primitive)
31211     0x11/imm32/alloc-id:fake:payload
31212     # var1/reg <- shift-right-signed lit => c1/shift 7/subop/right-preserving-sign var1/rm32 lit/imm32
31213     0x11/imm32/alloc-id:fake
31214     _string-shift-right-signed/imm32/name
31215     0x11/imm32/alloc-id:fake
31216     Single-lit-var/imm32/inouts
31217     0x11/imm32/alloc-id:fake
31218     Single-int-var-in-some-register/imm32/outputs
31219     0x11/imm32/alloc-id:fake
31220     _string_c1_subop_shift_right_preserving_sign/imm32/subx-name
31221     3/imm32/rm32-is-first-output
31222     0/imm32/no-r32
31223     0/imm32/no-imm32
31224     1/imm32/imm8-is-first-inout
31225     0/imm32/no-disp32
31226     0/imm32/no-xm32
31227     0/imm32/no-x32
31228     0x11/imm32/alloc-id:fake
31229     _Primitive-shift-mem-left-by-lit/imm32/next
31230 _Primitive-shift-mem-left-by-lit:  # (payload primitive)
31231     0x11/imm32/alloc-id:fake:payload
31232     # shift-left var1, lit => c1/shift 4/subop/left var1/rm32 lit/imm32
31233     0x11/imm32/alloc-id:fake
31234     _string-shift-left/imm32/name
31235     0x11/imm32/alloc-id:fake
31236     Int-var-and-literal/imm32/inouts
31237     0/imm32/no-outputs
31238     0/imm32/no-outputs
31239     0x11/imm32/alloc-id:fake
31240     _string_c1_subop_shift_left/imm32/subx-name
31241     1/imm32/rm32-is-first-inout
31242     0/imm32/no-r32
31243     0/imm32/no-imm32
31244     2/imm32/imm8-is-second-inout
31245     0/imm32/no-disp32
31246     0/imm32/no-xm32
31247     0/imm32/no-x32
31248     0x11/imm32/alloc-id:fake
31249     _Primitive-shift-mem-right-by-lit/imm32/next
31250 _Primitive-shift-mem-right-by-lit:  # (payload primitive)
31251     0x11/imm32/alloc-id:fake:payload
31252     # shift-right var1, lit => c1/shift 5/subop/right var1/rm32 lit/imm32
31253     0x11/imm32/alloc-id:fake
31254     _string-shift-right/imm32/name
31255     0x11/imm32/alloc-id:fake
31256     Int-var-and-literal/imm32/inouts
31257     0/imm32/no-outputs
31258     0/imm32/no-outputs
31259     0x11/imm32/alloc-id:fake
31260     _string_c1_subop_shift_right_padding_zeroes/imm32/subx-name
31261     1/imm32/rm32-is-first-inout
31262     0/imm32/no-r32
31263     0/imm32/no-imm32
31264     2/imm32/imm8-is-second-inout
31265     0/imm32/no-disp32
31266     0/imm32/no-xm32
31267     0/imm32/no-x32
31268     0x11/imm32/alloc-id:fake
31269     _Primitive-shift-mem-right-signed-by-lit/imm32/next
31270 _Primitive-shift-mem-right-signed-by-lit:  # (payload primitive)
31271     0x11/imm32/alloc-id:fake:payload
31272     # shift-right-signed var1, lit => c1/shift 7/subop/right-preserving-sign var1/rm32 lit/imm32
31273     0x11/imm32/alloc-id:fake
31274     _string-shift-right-signed/imm32/name
31275     0x11/imm32/alloc-id:fake
31276     Int-var-and-literal/imm32/inouts
31277     0/imm32/no-outputs
31278     0/imm32/no-outputs
31279     0x11/imm32/alloc-id:fake
31280     _string_c1_subop_shift_right_preserving_sign/imm32/subx-name
31281     1/imm32/rm32-is-first-inout
31282     0/imm32/no-r32
31283     0/imm32/no-imm32
31284     2/imm32/imm8-is-second-inout
31285     0/imm32/no-disp32
31286     0/imm32/no-xm32
31287     0/imm32/no-x32
31288     0x11/imm32/alloc-id:fake
31289     _Primitive-copy-to-eax/imm32/next
31290 # - copy
31291 _Primitive-copy-to-eax:  # (payload primitive)
31292     0x11/imm32/alloc-id:fake:payload
31293     # var/eax <- copy lit => b8/copy-to-eax lit/imm32
31294     0x11/imm32/alloc-id:fake
31295     _string-copy/imm32/name
31296     0x11/imm32/alloc-id:fake
31297     Single-lit-var/imm32/inouts
31298     0x11/imm32/alloc-id:fake
31299     Single-int-var-in-eax/imm32/outputs
31300     0x11/imm32/alloc-id:fake
31301     _string_b8_copy_to_eax/imm32/subx-name
31302     0/imm32/no-rm32
31303     0/imm32/no-r32
31304     1/imm32/imm32-is-first-inout
31305     0/imm32/no-imm8
31306     0/imm32/no-disp32
31307     0/imm32/no-xm32
31308     0/imm32/no-x32
31309     0x11/imm32/alloc-id:fake
31310     _Primitive-copy-to-ecx/imm32/next
31311 _Primitive-copy-to-ecx:  # (payload primitive)
31312     0x11/imm32/alloc-id:fake:payload
31313     # var/ecx <- copy lit => b9/copy-to-ecx lit/imm32
31314     0x11/imm32/alloc-id:fake
31315     _string-copy/imm32/name
31316     0x11/imm32/alloc-id:fake
31317     Single-lit-var/imm32/inouts
31318     0x11/imm32/alloc-id:fake
31319     Single-int-var-in-ecx/imm32/outputs
31320     0x11/imm32/alloc-id:fake
31321     _string_b9_copy_to_ecx/imm32/subx-name
31322     0/imm32/no-rm32
31323     0/imm32/no-r32
31324     1/imm32/imm32-is-first-inout
31325     0/imm32/no-imm8
31326     0/imm32/no-disp32
31327     0/imm32/no-xm32
31328     0/imm32/no-x32
31329     0x11/imm32/alloc-id:fake
31330     _Primitive-copy-to-edx/imm32/next
31331 _Primitive-copy-to-edx:  # (payload primitive)
31332     0x11/imm32/alloc-id:fake:payload
31333     # var/edx <- copy lit => ba/copy-to-edx lit/imm32
31334     0x11/imm32/alloc-id:fake
31335     _string-copy/imm32/name
31336     0x11/imm32/alloc-id:fake
31337     Single-lit-var/imm32/inouts
31338     0x11/imm32/alloc-id:fake
31339     Single-int-var-in-edx/imm32/outputs
31340     0x11/imm32/alloc-id:fake
31341     _string_ba_copy_to_edx/imm32/subx-name
31342     0/imm32/no-rm32
31343     0/imm32/no-r32
31344     1/imm32/imm32-is-first-inout
31345     0/imm32/no-imm8
31346     0/imm32/no-disp32
31347     0/imm32/no-xm32
31348     0/imm32/no-x32
31349     0x11/imm32/alloc-id:fake
31350     _Primitive-copy-to-ebx/imm32/next
31351 _Primitive-copy-to-ebx:  # (payload primitive)
31352     0x11/imm32/alloc-id:fake:payload
31353     # var/ebx <- copy lit => bb/copy-to-ebx lit/imm32
31354     0x11/imm32/alloc-id:fake
31355     _string-copy/imm32/name
31356     0x11/imm32/alloc-id:fake
31357     Single-lit-var/imm32/inouts
31358     0x11/imm32/alloc-id:fake
31359     Single-int-var-in-ebx/imm32/outputs
31360     0x11/imm32/alloc-id:fake
31361     _string_bb_copy_to_ebx/imm32/subx-name
31362     0/imm32/no-rm32
31363     0/imm32/no-r32
31364     1/imm32/imm32-is-first-inout
31365     0/imm32/no-imm8
31366     0/imm32/no-disp32
31367     0/imm32/no-xm32
31368     0/imm32/no-x32
31369     0x11/imm32/alloc-id:fake
31370     _Primitive-copy-to-esi/imm32/next
31371 _Primitive-copy-to-esi:  # (payload primitive)
31372     0x11/imm32/alloc-id:fake:payload
31373     # var/esi <- copy lit => be/copy-to-esi lit/imm32
31374     0x11/imm32/alloc-id:fake
31375     _string-copy/imm32/name
31376     0x11/imm32/alloc-id:fake
31377     Single-lit-var/imm32/inouts
31378     0x11/imm32/alloc-id:fake
31379     Single-int-var-in-esi/imm32/outputs
31380     0x11/imm32/alloc-id:fake
31381     _string_be_copy_to_esi/imm32/subx-name
31382     0/imm32/no-rm32
31383     0/imm32/no-r32
31384     1/imm32/imm32-is-first-inout
31385     0/imm32/no-imm8
31386     0/imm32/no-disp32
31387     0/imm32/no-xm32
31388     0/imm32/no-x32
31389     0x11/imm32/alloc-id:fake
31390     _Primitive-copy-to-edi/imm32/next
31391 _Primitive-copy-to-edi:  # (payload primitive)
31392     0x11/imm32/alloc-id:fake:payload
31393     # var/edi <- copy lit => bf/copy-to-edi lit/imm32
31394     0x11/imm32/alloc-id:fake
31395     _string-copy/imm32/name
31396     0x11/imm32/alloc-id:fake
31397     Single-lit-var/imm32/inouts
31398     0x11/imm32/alloc-id:fake
31399     Single-int-var-in-edi/imm32/outputs
31400     0x11/imm32/alloc-id:fake
31401     _string_bf_copy_to_edi/imm32/subx-name
31402     0/imm32/no-rm32
31403     0/imm32/no-r32
31404     1/imm32/imm32-is-first-inout
31405     0/imm32/no-imm8
31406     0/imm32/no-disp32
31407     0/imm32/no-xm32
31408     0/imm32/no-x32
31409     0x11/imm32/alloc-id:fake
31410     _Primitive-copy-reg-to-reg/imm32/next
31411 _Primitive-copy-reg-to-reg:  # (payload primitive)
31412     0x11/imm32/alloc-id:fake:payload
31413     # var1/reg <- copy var2/reg => 89/<- var1/rm32 var2/r32
31414     0x11/imm32/alloc-id:fake
31415     _string-copy/imm32/name
31416     0x11/imm32/alloc-id:fake
31417     Single-int-var-in-some-register/imm32/inouts
31418     0x11/imm32/alloc-id:fake
31419     Single-int-var-in-some-register/imm32/outputs
31420     0x11/imm32/alloc-id:fake
31421     _string_89_<-/imm32/subx-name
31422     3/imm32/rm32-is-first-output
31423     1/imm32/r32-is-first-inout
31424     0/imm32/no-imm32
31425     0/imm32/no-imm8
31426     0/imm32/no-disp32
31427     0/imm32/no-xm32
31428     0/imm32/no-x32
31429     0x11/imm32/alloc-id:fake
31430     _Primitive-copy-reg-to-mem/imm32/next
31431 _Primitive-copy-reg-to-mem:  # (payload primitive)
31432     0x11/imm32/alloc-id:fake:payload
31433     # copy-to var1 var2/reg => 89/<- var1 var2/r32
31434     0x11/imm32/alloc-id:fake
31435     _string-copy-to/imm32/name
31436     0x11/imm32/alloc-id:fake
31437     Two-args-int-stack-int-reg/imm32/inouts
31438     0/imm32/no-outputs
31439     0/imm32/no-outputs
31440     0x11/imm32/alloc-id:fake
31441     _string_89_<-/imm32/subx-name
31442     1/imm32/rm32-is-first-inout
31443     2/imm32/r32-is-second-inout
31444     0/imm32/no-imm32
31445     0/imm32/no-imm8
31446     0/imm32/no-disp32
31447     0/imm32/no-xm32
31448     0/imm32/no-x32
31449     0x11/imm32/alloc-id:fake
31450     _Primitive-copy-mem-to-reg/imm32/next
31451 _Primitive-copy-mem-to-reg:  # (payload primitive)
31452     0x11/imm32/alloc-id:fake:payload
31453     # var1/reg <- copy var2 => 8b/-> var2/rm32 var1/r32
31454     0x11/imm32/alloc-id:fake
31455     _string-copy/imm32/name
31456     0x11/imm32/alloc-id:fake
31457     Single-int-var-in-mem/imm32/inouts
31458     0x11/imm32/alloc-id:fake
31459     Single-int-var-in-some-register/imm32/outputs
31460     0x11/imm32/alloc-id:fake
31461     _string_8b_->/imm32/subx-name
31462     1/imm32/rm32-is-first-inout
31463     3/imm32/r32-is-first-output
31464     0/imm32/no-imm32
31465     0/imm32/no-imm8
31466     0/imm32/no-disp32
31467     0/imm32/no-xm32
31468     0/imm32/no-x32
31469     0x11/imm32/alloc-id:fake
31470     _Primitive-copy-lit-to-reg/imm32/next
31471 _Primitive-copy-lit-to-reg:  # (payload primitive)
31472     0x11/imm32/alloc-id:fake:payload
31473     # var1/reg <- copy lit => c7 0/subop/copy var1/rm32 lit/imm32
31474     0x11/imm32/alloc-id:fake
31475     _string-copy/imm32/name
31476     0x11/imm32/alloc-id:fake
31477     Single-lit-var/imm32/inouts
31478     0x11/imm32/alloc-id:fake
31479     Single-int-var-in-some-register/imm32/outputs
31480     0x11/imm32/alloc-id:fake
31481     _string_c7_subop_copy/imm32/subx-name
31482     3/imm32/rm32-is-first-output
31483     0/imm32/no-r32
31484     1/imm32/imm32-is-first-inout
31485     0/imm32/no-imm8
31486     0/imm32/no-disp32
31487     0/imm32/no-xm32
31488     0/imm32/no-x32
31489     0x11/imm32/alloc-id:fake
31490     _Primitive-copy-lit-to-mem/imm32/next
31491 _Primitive-copy-lit-to-mem:  # (payload primitive)
31492     0x11/imm32/alloc-id:fake:payload
31493     # copy-to var1, lit => c7 0/subop/copy var1/rm32 lit/imm32
31494     0x11/imm32/alloc-id:fake
31495     _string-copy-to/imm32/name
31496     0x11/imm32/alloc-id:fake
31497     Int-var-and-literal/imm32/inouts
31498     0/imm32/no-outputs
31499     0/imm32/no-outputs
31500     0x11/imm32/alloc-id:fake
31501     _string_c7_subop_copy/imm32/subx-name
31502     1/imm32/rm32-is-first-inout
31503     0/imm32/no-r32
31504     2/imm32/imm32-is-second-inout
31505     0/imm32/no-imm8
31506     0/imm32/no-disp32
31507     0/imm32/no-xm32
31508     0/imm32/no-x32
31509     0x11/imm32/alloc-id:fake
31510     _Primitive-copy-byte-from-reg/imm32/next
31511 # - copy byte
31512 _Primitive-copy-byte-from-reg:
31513     0x11/imm32/alloc-id:fake:payload
31514     # var/reg <- copy-byte var2/reg2 => 8a/byte-> %var2 var/r32
31515     0x11/imm32/alloc-id:fake
31516     _string-copy-byte/imm32/name
31517     0x11/imm32/alloc-id:fake
31518     Single-byte-var-in-some-register/imm32/inouts
31519     0x11/imm32/alloc-id:fake
31520     Single-byte-var-in-some-register/imm32/outputs
31521     0x11/imm32/alloc-id:fake
31522     _string_8a_copy_byte/imm32/subx-name
31523     1/imm32/rm32-is-first-inout
31524     3/imm32/r32-is-first-output
31525     0/imm32/no-imm32
31526     0/imm32/no-imm8
31527     0/imm32/no-disp32
31528     0/imm32/no-xm32
31529     0/imm32/no-x32
31530     0x11/imm32/alloc-id:fake
31531     _Primitive-copy-byte-from-mem/imm32/next
31532 _Primitive-copy-byte-from-mem:
31533     0x11/imm32/alloc-id:fake:payload
31534     # var/reg <- copy-byte *var2/reg2 => 8a/byte-> *var2 var/r32
31535     0x11/imm32/alloc-id:fake
31536     _string-copy-byte/imm32/name
31537     0x11/imm32/alloc-id:fake
31538     Single-byte-var-in-mem/imm32/inouts
31539     0x11/imm32/alloc-id:fake
31540     Single-byte-var-in-some-register/imm32/outputs
31541     0x11/imm32/alloc-id:fake
31542     _string_8a_copy_byte/imm32/subx-name
31543     1/imm32/rm32-is-first-inout
31544     3/imm32/r32-is-first-output
31545     0/imm32/no-imm32
31546     0/imm32/no-imm8
31547     0/imm32/no-disp32
31548     0/imm32/no-xm32
31549     0/imm32/no-x32
31550     0x11/imm32/alloc-id:fake
31551     _Primitive-copy-byte-to-mem/imm32/next
31552 _Primitive-copy-byte-to-mem:
31553     0x11/imm32/alloc-id:fake:payload
31554     # copy-byte-to *var1/reg1, var2/reg2 => 88/byte<- *reg1 reg2/r32
31555     0x11/imm32/alloc-id:fake
31556     _string-copy-byte-to/imm32/name
31557     0x11/imm32/alloc-id:fake
31558     Two-args-byte-stack-byte-reg/imm32/inouts
31559     0/imm32/no-outputs
31560     0/imm32/no-outputs
31561     0x11/imm32/alloc-id:fake
31562     _string_88_copy_byte/imm32/subx-name
31563     1/imm32/rm32-is-first-inout
31564     2/imm32/r32-is-second-inout
31565     0/imm32/no-imm32
31566     0/imm32/no-imm8
31567     0/imm32/no-disp32
31568     0/imm32/no-xm32
31569     0/imm32/no-x32
31570     0x11/imm32/alloc-id:fake
31571     _Primitive-address/imm32/next
31572 # - address
31573 _Primitive-address:  # (payload primitive)
31574     0x11/imm32/alloc-id:fake:payload
31575     # var1/reg <- address var2 => 8d/copy-address var2/rm32 var1/r32
31576     0x11/imm32/alloc-id:fake
31577     _string-address/imm32/name
31578     0x11/imm32/alloc-id:fake
31579     Single-int-var-in-mem/imm32/inouts
31580     0x11/imm32/alloc-id:fake
31581     Single-addr-var-in-some-register/imm32/outputs
31582     0x11/imm32/alloc-id:fake
31583     _string_8d_copy_address/imm32/subx-name
31584     1/imm32/rm32-is-first-inout
31585     3/imm32/r32-is-first-output
31586     0/imm32/no-imm32
31587     0/imm32/no-imm8
31588     0/imm32/no-disp32
31589     0/imm32/no-xm32
31590     0/imm32/no-x32
31591     0x11/imm32/alloc-id:fake
31592     _Primitive-compare-reg-with-reg/imm32/next
31593 # - compare
31594 _Primitive-compare-reg-with-reg:  # (payload primitive)
31595     0x11/imm32/alloc-id:fake:payload
31596     # compare var1/reg1 var2/reg2 => 39/compare var1/rm32 var2/r32
31597     0x11/imm32/alloc-id:fake
31598     _string-compare/imm32/name
31599     0x11/imm32/alloc-id:fake
31600     Two-int-args-in-regs/imm32/inouts
31601     0/imm32/no-outputs
31602     0/imm32/no-outputs
31603     0x11/imm32/alloc-id:fake
31604     _string_39_compare->/imm32/subx-name
31605     1/imm32/rm32-is-first-inout
31606     2/imm32/r32-is-second-inout
31607     0/imm32/no-imm32
31608     0/imm32/no-imm8
31609     0/imm32/no-disp32
31610     0/imm32/no-xm32
31611     0/imm32/no-x32
31612     0x11/imm32/alloc-id:fake
31613     _Primitive-compare-mem-with-reg/imm32/next
31614 _Primitive-compare-mem-with-reg:  # (payload primitive)
31615     0x11/imm32/alloc-id:fake:payload
31616     # compare var1 var2/reg => 39/compare var1/rm32 var2/r32
31617     0x11/imm32/alloc-id:fake
31618     _string-compare/imm32/name
31619     0x11/imm32/alloc-id:fake
31620     Two-args-int-stack-int-reg/imm32/inouts
31621     0/imm32/no-outputs
31622     0/imm32/no-outputs
31623     0x11/imm32/alloc-id:fake
31624     _string_39_compare->/imm32/subx-name
31625     1/imm32/rm32-is-first-inout
31626     2/imm32/r32-is-second-inout
31627     0/imm32/no-imm32
31628     0/imm32/no-imm8
31629     0/imm32/no-disp32
31630     0/imm32/no-xm32
31631     0/imm32/no-x32
31632     0x11/imm32/alloc-id:fake
31633     _Primitive-compare-reg-with-mem/imm32/next
31634 _Primitive-compare-reg-with-mem:  # (payload primitive)
31635     0x11/imm32/alloc-id:fake:payload
31636     # compare var1/reg var2 => 3b/compare<- var2/rm32 var1/r32
31637     0x11/imm32/alloc-id:fake
31638     _string-compare/imm32/name
31639     0x11/imm32/alloc-id:fake
31640     Two-args-int-reg-int-stack/imm32/inouts
31641     0/imm32/no-outputs
31642     0/imm32/no-outputs
31643     0x11/imm32/alloc-id:fake
31644     _string_3b_compare<-/imm32/subx-name
31645     2/imm32/rm32-is-second-inout
31646     1/imm32/r32-is-first-inout
31647     0/imm32/no-imm32
31648     0/imm32/no-imm8
31649     0/imm32/no-disp32
31650     0/imm32/no-xm32
31651     0/imm32/no-x32
31652     0x11/imm32/alloc-id:fake
31653     _Primitive-compare-eax-with-literal/imm32/next
31654 _Primitive-compare-eax-with-literal:  # (payload primitive)
31655     0x11/imm32/alloc-id:fake:payload
31656     # compare var1/eax n => 3d/compare-eax-with n/imm32
31657     0x11/imm32/alloc-id:fake
31658     _string-compare/imm32/name
31659     0x11/imm32/alloc-id:fake
31660     Two-args-int-eax-int-literal/imm32/inouts
31661     0/imm32/no-outputs
31662     0/imm32/no-outputs
31663     0x11/imm32/alloc-id:fake
31664     _string_3d_compare_eax_with/imm32/subx-name
31665     0/imm32/no-rm32
31666     0/imm32/no-r32
31667     2/imm32/imm32-is-second-inout
31668     0/imm32/no-imm8
31669     0/imm32/no-disp32
31670     0/imm32/no-xm32
31671     0/imm32/no-x32
31672     0x11/imm32/alloc-id:fake
31673     _Primitive-compare-reg-with-literal/imm32/next
31674 _Primitive-compare-reg-with-literal:  # (payload primitive)
31675     0x11/imm32/alloc-id:fake:payload
31676     # compare var1/reg n => 81 7/subop/compare %reg n/imm32
31677     0x11/imm32/alloc-id:fake
31678     _string-compare/imm32/name
31679     0x11/imm32/alloc-id:fake
31680     Int-var-in-register-and-literal/imm32/inouts
31681     0/imm32/no-outputs
31682     0/imm32/no-outputs
31683     0x11/imm32/alloc-id:fake
31684     _string_81_subop_compare/imm32/subx-name
31685     1/imm32/rm32-is-first-inout
31686     0/imm32/no-r32
31687     2/imm32/imm32-is-second-inout
31688     0/imm32/no-imm8
31689     0/imm32/no-disp32
31690     0/imm32/no-xm32
31691     0/imm32/no-x32
31692     0x11/imm32/alloc-id:fake
31693     _Primitive-compare-mem-with-literal/imm32/next
31694 _Primitive-compare-mem-with-literal:  # (payload primitive)
31695     0x11/imm32/alloc-id:fake:payload
31696     # compare var1 n => 81 7/subop/compare *(ebp+___) n/imm32
31697     0x11/imm32/alloc-id:fake
31698     _string-compare/imm32/name
31699     0x11/imm32/alloc-id:fake
31700     Int-var-and-literal/imm32/inouts
31701     0/imm32/no-outputs
31702     0/imm32/no-outputs
31703     0x11/imm32/alloc-id:fake
31704     _string_81_subop_compare/imm32/subx-name
31705     1/imm32/rm32-is-first-inout
31706     0/imm32/no-r32
31707     2/imm32/imm32-is-second-inout
31708     0/imm32/no-imm8
31709     0/imm32/no-disp32
31710     0/imm32/no-xm32
31711     0/imm32/no-x32
31712     0x11/imm32/alloc-id:fake
31713     _Primitive-negate-reg/imm32/next
31714 # - negate
31715 _Primitive-negate-reg:  # (payload primitive)
31716     0x11/imm32/alloc-id:fake:payload
31717     # var1/reg <- negate => f7 3/subop/negate var1/rm32
31718     0x11/imm32/alloc-id:fake
31719     _string-negate/imm32/name
31720     0/imm32/no-inouts
31721     0/imm32/no-inouts
31722     0x11/imm32/alloc-id:fake
31723     Single-int-var-in-some-register/imm32/outputs
31724     0x11/imm32/alloc-id:fake
31725     _string_f7_subop_negate/imm32/subx-name
31726     3/imm32/rm32-is-first-output
31727     0/imm32/no-r32
31728     0/imm32/no-imm32
31729     0/imm32/no-imm8
31730     0/imm32/no-disp32
31731     0/imm32/no-xm32
31732     0/imm32/no-x32
31733     0x11/imm32/alloc-id:fake
31734     _Primitive-negate-mem/imm32/next
31735 _Primitive-negate-mem:  # (payload primitive)
31736     0x11/imm32/alloc-id:fake:payload
31737     # negate var1 => f7 3/subop/negate var1/rm32
31738     0x11/imm32/alloc-id:fake
31739     _string-negate/imm32/name
31740     0x11/imm32/alloc-id:fake
31741     Single-int-var-in-mem/imm32/inouts
31742     0/imm32/no-outputs
31743     0/imm32/no-outputs
31744     0x11/imm32/alloc-id:fake
31745     _string_f7_subop_negate/imm32/subx-name
31746     1/imm32/rm32-is-first-inout
31747     0/imm32/no-r32
31748     0/imm32/no-imm32
31749     0/imm32/no-imm8
31750     0/imm32/no-disp32
31751     0/imm32/no-xm32
31752     0/imm32/no-x32
31753     0x11/imm32/alloc-id:fake
31754     _Primitive-multiply-reg-by-reg/imm32/next
31755 # - multiply
31756 _Primitive-multiply-reg-by-reg:  # (payload primitive)
31757     0x11/imm32/alloc-id:fake:payload
31758     # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32
31759     0x11/imm32/alloc-id:fake
31760     _string-multiply/imm32/name
31761     0x11/imm32/alloc-id:fake
31762     Single-int-var-in-some-register/imm32/inouts
31763     0x11/imm32/alloc-id:fake
31764     Single-int-var-in-some-register/imm32/outputs
31765     0x11/imm32/alloc-id:fake
31766     _string_0f_af_multiply/imm32/subx-name
31767     1/imm32/rm32-is-first-inout
31768     3/imm32/r32-is-first-output
31769     0/imm32/no-imm32
31770     0/imm32/no-imm8
31771     0/imm32/no-disp32
31772     0/imm32/no-xm32
31773     0/imm32/no-x32
31774     0x11/imm32/alloc-id:fake
31775     _Primitive-multiply-reg-by-mem/imm32/next
31776 _Primitive-multiply-reg-by-mem:  # (payload primitive)
31777     0x11/imm32/alloc-id:fake:payload
31778     # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32
31779     0x11/imm32/alloc-id:fake
31780     _string-multiply/imm32/name
31781     0x11/imm32/alloc-id:fake
31782     Single-int-var-in-mem/imm32/inouts
31783     0x11/imm32/alloc-id:fake
31784     Single-int-var-in-some-register/imm32/outputs
31785     0x11/imm32/alloc-id:fake
31786     _string_0f_af_multiply/imm32/subx-name
31787     1/imm32/rm32-is-first-inout
31788     3/imm32/r32-is-first-output
31789     0/imm32/no-imm32
31790     0/imm32/no-imm8
31791     0/imm32/no-disp32
31792     0/imm32/no-xm32
31793     0/imm32/no-x32
31794     0x11/imm32/alloc-id:fake
31795     _Primitive-convert-mem-to-xreg/imm32/next
31796 # - convert int to floating point
31797 _Primitive-convert-mem-to-xreg:  # (payload primitive)
31798     0x11/imm32/alloc-id:fake:payload
31799     # var1/xreg <- convert var2 => f3 0f 2a/convert-to-float var2/rm32 var1/x32
31800     0x11/imm32/alloc-id:fake
31801     _string-convert/imm32/name
31802     0x11/imm32/alloc-id:fake
31803     Single-int-var-in-mem/imm32/inouts
31804     0x11/imm32/alloc-id:fake
31805     Single-float-var-in-some-register/imm32/outputs
31806     0x11/imm32/alloc-id:fake
31807     _string_f3_0f_2a_convert_to_float/imm32/subx-name
31808     1/imm32/rm32-is-first-inout
31809     0/imm32/no-r32
31810     0/imm32/no-imm32
31811     0/imm32/no-imm8
31812     0/imm32/no-disp32
31813     0/imm32/no-xm32
31814     3/imm32/x32-is-first-output
31815     0x11/imm32/alloc-id:fake
31816     _Primitive-convert-reg-to-xreg/imm32/next
31817 _Primitive-convert-reg-to-xreg:  # (payload primitive)
31818     0x11/imm32/alloc-id:fake:payload
31819     # var1/xreg <- convert var2/reg => f3 0f 2a/convert-to-float var2/rm32 var1/x32
31820     0x11/imm32/alloc-id:fake
31821     _string-convert/imm32/name
31822     0x11/imm32/alloc-id:fake
31823     Single-int-var-in-some-register/imm32/inouts
31824     0x11/imm32/alloc-id:fake
31825     Single-float-var-in-some-register/imm32/outputs
31826     0x11/imm32/alloc-id:fake
31827     _string_f3_0f_2a_convert_to_float/imm32/subx-name
31828     1/imm32/rm32-is-first-inout
31829     0/imm32/no-r32
31830     0/imm32/no-imm32
31831     0/imm32/no-imm8
31832     0/imm32/no-disp32
31833     0/imm32/no-xm32
31834     3/imm32/x32-is-first-output
31835     0x11/imm32/alloc-id:fake
31836     _Primitive-convert-xmem-to-reg/imm32/next
31837 # - convert floating point to int
31838 _Primitive-convert-xmem-to-reg:  # (payload primitive)
31839     0x11/imm32/alloc-id:fake:payload
31840     # var1/reg <- convert var2 => f3 0f 2d/convert-to-int var2/xm32 var1/r32
31841     0x11/imm32/alloc-id:fake
31842     _string-convert/imm32/name
31843     0x11/imm32/alloc-id:fake
31844     Single-float-var-in-mem/imm32/inouts
31845     0x11/imm32/alloc-id:fake
31846     Single-int-var-in-some-register/imm32/outputs
31847     0x11/imm32/alloc-id:fake
31848     _string_f3_0f_2d_convert_to_int/imm32/subx-name
31849     0/imm32/no-rm32
31850     3/imm32/r32-is-first-output
31851     0/imm32/no-imm32
31852     0/imm32/no-imm8
31853     0/imm32/no-disp32
31854     1/imm32/xm32-is-first-inout
31855     0/imm32/no-x32
31856     0x11/imm32/alloc-id:fake
31857     _Primitive-convert-xreg-to-reg/imm32/next
31858 _Primitive-convert-xreg-to-reg:  # (payload primitive)
31859     0x11/imm32/alloc-id:fake:payload
31860     # var1/reg <- convert var2/xreg => f3 0f 2d/convert-to-int var2/xm32 var1/r32
31861     0x11/imm32/alloc-id:fake
31862     _string-convert/imm32/name
31863     0x11/imm32/alloc-id:fake
31864     Single-float-var-in-some-register/imm32/inouts
31865     0x11/imm32/alloc-id:fake
31866     Single-int-var-in-some-register/imm32/outputs
31867     0x11/imm32/alloc-id:fake
31868     _string_f3_0f_2d_convert_to_int/imm32/subx-name
31869     0/imm32/no-rm32
31870     3/imm32/r32-is-first-output
31871     0/imm32/no-imm32
31872     0/imm32/no-imm8
31873     0/imm32/no-disp32
31874     1/imm32/xm32-is-first-inout
31875     0/imm32/no-x32
31876     0x11/imm32/alloc-id:fake
31877     _Primitive-truncate-xmem-to-reg/imm32/next
31878 _Primitive-truncate-xmem-to-reg:  # (payload primitive)
31879     0x11/imm32/alloc-id:fake:payload
31880     # var1/reg <- truncate var2 => f3 0f 2c/truncate-to-int var2/xm32 var1/r32
31881     0x11/imm32/alloc-id:fake
31882     _string-truncate/imm32/name
31883     0x11/imm32/alloc-id:fake
31884     Single-float-var-in-mem/imm32/inouts
31885     0x11/imm32/alloc-id:fake
31886     Single-int-var-in-some-register/imm32/outputs
31887     0x11/imm32/alloc-id:fake
31888     _string_f3_0f_2c_truncate_to_int/imm32/subx-name
31889     0/imm32/no-rm32
31890     3/imm32/r32-is-first-output
31891     0/imm32/no-imm32
31892     0/imm32/no-imm8
31893     0/imm32/no-disp32
31894     1/imm32/xm32-is-first-inout
31895     0/imm32/no-x32
31896     0x11/imm32/alloc-id:fake
31897     _Primitive-truncate-xreg-to-reg/imm32/next
31898 _Primitive-truncate-xreg-to-reg:  # (payload primitive)
31899     0x11/imm32/alloc-id:fake:payload
31900     # var1/reg <- truncate var2/xreg => f3 0f 2c/truncate-to-int var2/xm32 var1/r32
31901     0x11/imm32/alloc-id:fake
31902     _string-truncate/imm32/name
31903     0x11/imm32/alloc-id:fake
31904     Single-float-var-in-some-register/imm32/inouts
31905     0x11/imm32/alloc-id:fake
31906     Single-int-var-in-some-register/imm32/outputs
31907     0x11/imm32/alloc-id:fake
31908     _string_f3_0f_2c_truncate_to_int/imm32/subx-name
31909     0/imm32/no-rm32
31910     3/imm32/r32-is-first-output
31911     0/imm32/no-imm32
31912     0/imm32/no-imm8
31913     0/imm32/no-disp32
31914     1/imm32/xm32-is-first-inout
31915     0/imm32/no-x32
31916     0x11/imm32/alloc-id:fake
31917     _Primitive-reinterpret-xmem-as-reg/imm32/next
31918 # - reinterpret bytes (just for debugging)
31919 _Primitive-reinterpret-xmem-as-reg:  # (payload primitive)
31920     0x11/imm32/alloc-id:fake:payload
31921     # var1/reg <- reinterpret var2 => 8b/-> var2/xm32 var1/r32
31922     0x11/imm32/alloc-id:fake
31923     _string-reinterpret/imm32/name
31924     0x11/imm32/alloc-id:fake
31925     Single-float-var-in-mem/imm32/inouts
31926     0x11/imm32/alloc-id:fake
31927     Single-int-var-in-some-register/imm32/outputs
31928     0x11/imm32/alloc-id:fake
31929     _string_8b_->/imm32/subx-name
31930     0/imm32/no-rm32
31931     3/imm32/r32-is-first-output
31932     0/imm32/no-imm32
31933     0/imm32/no-imm8
31934     0/imm32/no-disp32
31935     1/imm32/xm32-is-first-inout
31936     0/imm32/no-x32
31937     0x11/imm32/alloc-id:fake
31938     _Primitive-reinterpret-mem-as-xreg/imm32/next
31939 _Primitive-reinterpret-mem-as-xreg:  # (payload primitive)
31940     0x11/imm32/alloc-id:fake:payload
31941     # var1/xreg <- reinterpret var2 => f3 0f 10/-> var2/rm32 var1/x32
31942     0x11/imm32/alloc-id:fake
31943     _string-reinterpret/imm32/name
31944     0x11/imm32/alloc-id:fake
31945     Single-int-var-in-mem/imm32/inouts
31946     0x11/imm32/alloc-id:fake
31947     Single-float-var-in-some-register/imm32/outputs
31948     0x11/imm32/alloc-id:fake
31949     _string_f3_0f_10_copy/imm32/subx-name
31950     1/imm32/rm32-is-first-inout
31951     0/imm32/no-r32
31952     0/imm32/no-imm32
31953     0/imm32/no-imm8
31954     0/imm32/no-disp32
31955     0/imm32/no-xm32
31956     3/imm32/x32-is-first-output
31957     0x11/imm32/alloc-id:fake
31958     _Primitive-copy-xreg-to-xreg/imm32/next
31959 # - floating-point copy
31960 _Primitive-copy-xreg-to-xreg:  # (payload primitive)
31961     0x11/imm32/alloc-id:fake:payload
31962     # var1/xreg <- copy var2/xreg => f3 0f 11/<- var1/xm32 var2/x32
31963     0x11/imm32/alloc-id:fake
31964     _string-copy/imm32/name
31965     0x11/imm32/alloc-id:fake
31966     Single-float-var-in-some-register/imm32/inouts
31967     0x11/imm32/alloc-id:fake
31968     Single-float-var-in-some-register/imm32/outputs
31969     0x11/imm32/alloc-id:fake
31970     _string_f3_0f_11_copy/imm32/subx-name
31971     0/imm32/no-rm32
31972     0/imm32/no-r32
31973     0/imm32/no-imm32
31974     0/imm32/no-imm8
31975     0/imm32/no-disp32
31976     3/imm32/xm32-is-first-output
31977     1/imm32/x32-is-first-inout
31978     0x11/imm32/alloc-id:fake
31979     _Primitive-copy-xreg-to-mem/imm32/next
31980 _Primitive-copy-xreg-to-mem:  # (payload primitive)
31981     0x11/imm32/alloc-id:fake:payload
31982     # copy-to var1 var2/xreg => f3 0f 11/<- var1 var2/x32
31983     0x11/imm32/alloc-id:fake
31984     _string-copy-to/imm32/name
31985     0x11/imm32/alloc-id:fake
31986     Two-args-float-stack-float-reg/imm32/inouts
31987     0/imm32/no-outputs
31988     0/imm32/no-outputs
31989     0x11/imm32/alloc-id:fake
31990     _string_f3_0f_11_copy/imm32/subx-name
31991     0/imm32/no-rm32
31992     0/imm32/no-r32
31993     0/imm32/no-imm32
31994     0/imm32/no-imm8
31995     0/imm32/no-disp32
31996     1/imm32/xm32-is-first-inout
31997     2/imm32/x32-is-second-inout
31998     0x11/imm32/alloc-id:fake
31999     _Primitive-copy-mem-to-xreg/imm32/next
32000 _Primitive-copy-mem-to-xreg:  # (payload primitive)
32001     0x11/imm32/alloc-id:fake:payload
32002     # var1/xreg <- copy var2 => f3 0f 10/-> var2/rm32 var1/x32
32003     0x11/imm32/alloc-id:fake
32004     _string-copy/imm32/name
32005     0x11/imm32/alloc-id:fake
32006     Single-float-var-in-mem/imm32/inouts
32007     0x11/imm32/alloc-id:fake
32008     Single-float-var-in-some-register/imm32/outputs
32009     0x11/imm32/alloc-id:fake
32010     _string_f3_0f_10_copy/imm32/subx-name
32011     0/imm32/no-rm32
32012     0/imm32/no-r32
32013     0/imm32/no-imm32
32014     0/imm32/no-imm8
32015     0/imm32/no-disp32
32016     1/imm32/xm32-is-first-inout
32017     3/imm32/x32-is-first-output
32018     0x11/imm32/alloc-id:fake
32019     _Primitive-address-of-xmem/imm32/next
32020 # - floating-point-address
32021 _Primitive-address-of-xmem:  # (payload primitive)
32022     0x11/imm32/alloc-id:fake:payload
32023     # var1/reg <- address var2 => 8d/copy-address var2/rm32 var1/r32
32024     0x11/imm32/alloc-id:fake
32025     _string-address/imm32/name
32026     0x11/imm32/alloc-id:fake
32027     Single-float-var-in-mem/imm32/inouts
32028     0x11/imm32/alloc-id:fake
32029     Single-addr-var-in-some-register/imm32/outputs
32030     0x11/imm32/alloc-id:fake
32031     _string_8d_copy_address/imm32/subx-name
32032     1/imm32/rm32-is-first-inout
32033     3/imm32/r32-is-first-output
32034     0/imm32/no-imm32
32035     0/imm32/no-imm8
32036     0/imm32/no-disp32
32037     0/imm32/no-xm32
32038     0/imm32/no-x32
32039     0x11/imm32/alloc-id:fake
32040     _Primitive-add-xreg-to-xreg/imm32/next
32041 # - floating-point add
32042 _Primitive-add-xreg-to-xreg:  # (payload primitive)
32043     0x11/imm32/alloc-id:fake:payload
32044     # var1/xreg <- add var2/xreg => f3 0f 58/add var1/xm32 var2/x32
32045     0x11/imm32/alloc-id:fake
32046     _string-add/imm32/name
32047     0x11/imm32/alloc-id:fake
32048     Single-float-var-in-some-register/imm32/inouts
32049     0x11/imm32/alloc-id:fake
32050     Single-float-var-in-some-register/imm32/outputs
32051     0x11/imm32/alloc-id:fake
32052     _string_f3_0f_58_add/imm32/subx-name
32053     0/imm32/no-rm32
32054     0/imm32/no-r32
32055     0/imm32/no-imm32
32056     0/imm32/no-imm8
32057     0/imm32/no-disp32
32058     1/imm32/xm32-is-first-inout
32059     3/imm32/x32-is-first-output
32060     0x11/imm32/alloc-id:fake
32061     _Primitive-add-mem-to-xreg/imm32/next
32062 _Primitive-add-mem-to-xreg:  # (payload primitive)
32063     0x11/imm32/alloc-id:fake:payload
32064     # var1/xreg <- add var2 => f3 0f 58/add var2/xm32 var1/x32
32065     0x11/imm32/alloc-id:fake
32066     _string-add/imm32/name
32067     0x11/imm32/alloc-id:fake
32068     Single-float-var-in-mem/imm32/inouts
32069     0x11/imm32/alloc-id:fake
32070     Single-float-var-in-some-register/imm32/outputs
32071     0x11/imm32/alloc-id:fake
32072     _string_f3_0f_58_add/imm32/subx-name
32073     0/imm32/no-rm32
32074     0/imm32/no-r32
32075     0/imm32/no-imm32
32076     0/imm32/no-imm8
32077     0/imm32/no-disp32
32078     1/imm32/xm32-is-first-inout
32079     3/imm32/x32-is-first-output
32080     0x11/imm32/alloc-id:fake
32081     _Primitive-subtract-xreg-from-xreg/imm32/next
32082 # - floating-point subtract
32083 _Primitive-subtract-xreg-from-xreg:  # (payload primitive)
32084     0x11/imm32/alloc-id:fake:payload
32085     # var1/xreg <- subtract var2/xreg => f3 0f 5c/subtract var1/xm32 var2/x32
32086     0x11/imm32/alloc-id:fake
32087     _string-subtract/imm32/name
32088     0x11/imm32/alloc-id:fake
32089     Single-float-var-in-some-register/imm32/inouts
32090     0x11/imm32/alloc-id:fake
32091     Single-float-var-in-some-register/imm32/outputs
32092     0x11/imm32/alloc-id:fake
32093     _string_f3_0f_5c_subtract/imm32/subx-name
32094     0/imm32/no-rm32
32095     0/imm32/no-r32
32096     0/imm32/no-imm32
32097     0/imm32/no-imm8
32098     0/imm32/no-disp32
32099     1/imm32/xm32-is-first-inout
32100     3/imm32/x32-is-first-output
32101     0x11/imm32/alloc-id:fake
32102     _Primitive-subtract-mem-from-xreg/imm32/next
32103 _Primitive-subtract-mem-from-xreg:  # (payload primitive)
32104     0x11/imm32/alloc-id:fake:payload
32105     # var1/xreg <- subtract var2 => f3 0f 5c/subtract var2/xm32 var1/x32
32106     0x11/imm32/alloc-id:fake
32107     _string-subtract/imm32/name
32108     0x11/imm32/alloc-id:fake
32109     Single-float-var-in-mem/imm32/inouts
32110     0x11/imm32/alloc-id:fake
32111     Single-float-var-in-some-register/imm32/outputs
32112     0x11/imm32/alloc-id:fake
32113     _string_f3_0f_5c_subtract/imm32/subx-name
32114     0/imm32/no-rm32
32115     0/imm32/no-r32
32116     0/imm32/no-imm32
32117     0/imm32/no-imm8
32118     0/imm32/no-disp32
32119     1/imm32/xm32-is-first-inout
32120     3/imm32/x32-is-first-output
32121     0x11/imm32/alloc-id:fake
32122     _Primitive-multiply-xreg-by-xreg/imm32/next
32123 # - floating-point multiply
32124 _Primitive-multiply-xreg-by-xreg:  # (payload primitive)
32125     0x11/imm32/alloc-id:fake:payload
32126     # var1/xreg <- multiply var2 => f3 0f 59/multiply var2/xm32 var1/x32
32127     0x11/imm32/alloc-id:fake
32128     _string-multiply/imm32/name
32129     0x11/imm32/alloc-id:fake
32130     Single-float-var-in-some-register/imm32/inouts
32131     0x11/imm32/alloc-id:fake
32132     Single-float-var-in-some-register/imm32/outputs
32133     0x11/imm32/alloc-id:fake
32134     _string_f3_0f_59_multiply/imm32/subx-name
32135     0/imm32/no-rm32
32136     0/imm32/no-r32
32137     0/imm32/no-imm32
32138     0/imm32/no-imm8
32139     0/imm32/no-disp32
32140     1/imm32/xm32-is-first-inout
32141     3/imm32/x32-is-first-output
32142     0x11/imm32/alloc-id:fake
32143     _Primitive-multiply-xreg-by-mem/imm32/next
32144 _Primitive-multiply-xreg-by-mem:  # (payload primitive)
32145     0x11/imm32/alloc-id:fake:payload
32146     # var1/xreg <- multiply var2 => 53 0f 59/multiply var2/xm32 var1/x32
32147     0x11/imm32/alloc-id:fake
32148     _string-multiply/imm32/name
32149     0x11/imm32/alloc-id:fake
32150     Single-float-var-in-mem/imm32/inouts
32151     0x11/imm32/alloc-id:fake
32152     Single-float-var-in-some-register/imm32/outputs
32153     0x11/imm32/alloc-id:fake
32154     _string_f3_0f_59_multiply/imm32/subx-name
32155     0/imm32/no-rm32
32156     0/imm32/no-r32
32157     0/imm32/no-imm32
32158     0/imm32/no-imm8
32159     0/imm32/no-disp32
32160     1/imm32/xm32-is-first-inout
32161     3/imm32/x32-is-first-output
32162     0x11/imm32/alloc-id:fake
32163     _Primitive-divide-xreg-by-xreg/imm32/next
32164 # - floating-point divide
32165 _Primitive-divide-xreg-by-xreg:  # (payload primitive)
32166     0x11/imm32/alloc-id:fake:payload
32167     # var1/xreg <- divide var2 => f3 0f 5e/divide var2/xm32 var1/x32
32168     0x11/imm32/alloc-id:fake
32169     _string-divide/imm32/name
32170     0x11/imm32/alloc-id:fake
32171     Single-float-var-in-some-register/imm32/inouts
32172     0x11/imm32/alloc-id:fake
32173     Single-float-var-in-some-register/imm32/outputs
32174     0x11/imm32/alloc-id:fake
32175     _string_f3_0f_5e_divide/imm32/subx-name
32176     0/imm32/no-rm32
32177     0/imm32/no-r32
32178     0/imm32/no-imm32
32179     0/imm32/no-imm8
32180     0/imm32/no-disp32
32181     1/imm32/xm32-is-first-inout
32182     3/imm32/x32-is-first-output
32183     0x11/imm32/alloc-id:fake
32184     _Primitive-divide-xreg-by-mem/imm32/next
32185 _Primitive-divide-xreg-by-mem:  # (payload primitive)
32186     0x11/imm32/alloc-id:fake:payload
32187     # var1/xreg <- divide var2 => f3 0f 5e/divide var2/xm32 var1/x32
32188     0x11/imm32/alloc-id:fake
32189     _string-divide/imm32/name
32190     0x11/imm32/alloc-id:fake
32191     Single-float-var-in-mem/imm32/inouts
32192     0x11/imm32/alloc-id:fake
32193     Single-float-var-in-some-register/imm32/outputs
32194     0x11/imm32/alloc-id:fake
32195     _string_f3_0f_5e_divide/imm32/subx-name
32196     0/imm32/no-rm32
32197     0/imm32/no-r32
32198     0/imm32/no-imm32
32199     0/imm32/no-imm8
32200     0/imm32/no-disp32
32201     1/imm32/xm32-is-first-inout
32202     3/imm32/x32-is-first-output
32203     0x11/imm32/alloc-id:fake
32204     _Primitive-max-xreg-with-xreg/imm32/next
32205 # - floating-point maximum
32206 _Primitive-max-xreg-with-xreg:  # (payload primitive)
32207     0x11/imm32/alloc-id:fake:payload
32208     # var1/xreg <- max var2 => f3 0f 5f/max var2/xm32 var1/x32
32209     0x11/imm32/alloc-id:fake
32210     _string-max/imm32/name
32211     0x11/imm32/alloc-id:fake
32212     Single-float-var-in-some-register/imm32/inouts
32213     0x11/imm32/alloc-id:fake
32214     Single-float-var-in-some-register/imm32/outputs
32215     0x11/imm32/alloc-id:fake
32216     _string_f3_0f_5f_max/imm32/subx-name
32217     0/imm32/no-rm32
32218     0/imm32/no-r32
32219     0/imm32/no-imm32
32220     0/imm32/no-imm8
32221     0/imm32/no-disp32
32222     1/imm32/xm32-is-first-inout
32223     3/imm32/x32-is-first-output
32224     0x11/imm32/alloc-id:fake
32225     _Primitive-max-xreg-with-mem/imm32/next
32226 _Primitive-max-xreg-with-mem:  # (payload primitive)
32227     0x11/imm32/alloc-id:fake:payload
32228     # var1/xreg <- divide var2 => f3 0f 5f/max var2/xm32 var1/x32
32229     0x11/imm32/alloc-id:fake
32230     _string-max/imm32/name
32231     0x11/imm32/alloc-id:fake
32232     Single-float-var-in-mem/imm32/inouts
32233     0x11/imm32/alloc-id:fake
32234     Single-float-var-in-some-register/imm32/outputs
32235     0x11/imm32/alloc-id:fake
32236     _string_f3_0f_5f_max/imm32/subx-name
32237     0/imm32/no-rm32
32238     0/imm32/no-r32
32239     0/imm32/no-imm32
32240     0/imm32/no-imm8
32241     0/imm32/no-disp32
32242     1/imm32/xm32-is-first-inout
32243     3/imm32/x32-is-first-output
32244     0x11/imm32/alloc-id:fake
32245     _Primitive-min-xreg-with-xreg/imm32/next
32246 # - floating-point minimum
32247 _Primitive-min-xreg-with-xreg:  # (payload primitive)
32248     0x11/imm32/alloc-id:fake:payload
32249     # var1/xreg <- divide var2 => f3 0f 5d/min var2/xm32 var1/x32
32250     0x11/imm32/alloc-id:fake
32251     _string-min/imm32/name
32252     0x11/imm32/alloc-id:fake
32253     Single-float-var-in-some-register/imm32/inouts
32254     0x11/imm32/alloc-id:fake
32255     Single-float-var-in-some-register/imm32/outputs
32256     0x11/imm32/alloc-id:fake
32257     _string_f3_0f_5d_min/imm32/subx-name
32258     0/imm32/no-rm32
32259     0/imm32/no-r32
32260     0/imm32/no-imm32
32261     0/imm32/no-imm8
32262     0/imm32/no-disp32
32263     1/imm32/xm32-is-first-inout
32264     3/imm32/x32-is-first-output
32265     0x11/imm32/alloc-id:fake
32266     _Primitive-min-xreg-with-mem/imm32/next
32267 _Primitive-min-xreg-with-mem:  # (payload primitive)
32268     0x11/imm32/alloc-id:fake:payload
32269     # var1/xreg <- divide var2 => f3 0f 5d/min var2/xm32 var1/x32
32270     0x11/imm32/alloc-id:fake
32271     _string-min/imm32/name
32272     0x11/imm32/alloc-id:fake
32273     Single-float-var-in-mem/imm32/inouts
32274     0x11/imm32/alloc-id:fake
32275     Single-float-var-in-some-register/imm32/outputs
32276     0x11/imm32/alloc-id:fake
32277     _string_f3_0f_5d_min/imm32/subx-name
32278     0/imm32/no-rm32
32279     0/imm32/no-r32
32280     0/imm32/no-imm32
32281     0/imm32/no-imm8
32282     0/imm32/no-disp32
32283     1/imm32/xm32-is-first-inout
32284     3/imm32/x32-is-first-output
32285     0x11/imm32/alloc-id:fake
32286     _Primitive-reciprocal-xreg-to-xreg/imm32/next
32287 # - floating-point reciprocal
32288 _Primitive-reciprocal-xreg-to-xreg:  # (payload primitive)
32289     0x11/imm32/alloc-id:fake:payload
32290     # var1/xreg <- reciprocal var2 => f3 0f 53/reciprocal var2/xm32 var1/x32
32291     0x11/imm32/alloc-id:fake
32292     _string-reciprocal/imm32/name
32293     0x11/imm32/alloc-id:fake
32294     Single-float-var-in-some-register/imm32/inouts
32295     0x11/imm32/alloc-id:fake
32296     Single-float-var-in-some-register/imm32/outputs
32297     0x11/imm32/alloc-id:fake
32298     _string_f3_0f_53_reciprocal/imm32/subx-name
32299     0/imm32/no-rm32
32300     0/imm32/no-r32
32301     0/imm32/no-imm32
32302     0/imm32/no-imm8
32303     0/imm32/no-disp32
32304     1/imm32/xm32-is-first-inout
32305     3/imm32/x32-is-first-output
32306     0x11/imm32/alloc-id:fake
32307     _Primitive-reciprocal-mem-to-xreg/imm32/next
32308 _Primitive-reciprocal-mem-to-xreg:  # (payload primitive)
32309     0x11/imm32/alloc-id:fake:payload
32310     # var1/xreg <- divide var2 => f3 0f 53/reciprocal var2/xm32 var1/x32
32311     0x11/imm32/alloc-id:fake
32312     _string-reciprocal/imm32/name
32313     0x11/imm32/alloc-id:fake
32314     Single-float-var-in-mem/imm32/inouts
32315     0x11/imm32/alloc-id:fake
32316     Single-float-var-in-some-register/imm32/outputs
32317     0x11/imm32/alloc-id:fake
32318     _string_f3_0f_53_reciprocal/imm32/subx-name
32319     0/imm32/no-rm32
32320     0/imm32/no-r32
32321     0/imm32/no-imm32
32322     0/imm32/no-imm8
32323     0/imm32/no-disp32
32324     1/imm32/xm32-is-first-inout
32325     3/imm32/x32-is-first-output
32326     0x11/imm32/alloc-id:fake
32327     _Primitive-square-root-xreg-to-xreg/imm32/next
32328 # - floating-point square root
32329 _Primitive-square-root-xreg-to-xreg:  # (payload primitive)
32330     0x11/imm32/alloc-id:fake:payload
32331     # var1/xreg <- square-root var2 => f3 0f 51/square-root var2/xm32 var1/x32
32332     0x11/imm32/alloc-id:fake
32333     _string-square-root/imm32/name
32334     0x11/imm32/alloc-id:fake
32335     Single-float-var-in-some-register/imm32/inouts
32336     0x11/imm32/alloc-id:fake
32337     Single-float-var-in-some-register/imm32/outputs
32338     0x11/imm32/alloc-id:fake
32339     _string_f3_0f_51_square_root/imm32/subx-name
32340     0/imm32/no-rm32
32341     0/imm32/no-r32
32342     0/imm32/no-imm32
32343     0/imm32/no-imm8
32344     0/imm32/no-disp32
32345     1/imm32/xm32-is-first-inout
32346     3/imm32/x32-is-first-output
32347     0x11/imm32/alloc-id:fake
32348     _Primitive-square-root-mem-to-xreg/imm32/next
32349 _Primitive-square-root-mem-to-xreg:  # (payload primitive)
32350     0x11/imm32/alloc-id:fake:payload
32351     # var1/xreg <- divide var2 => f3 0f 51/square-root var2/xm32 var1/x32
32352     0x11/imm32/alloc-id:fake
32353     _string-square-root/imm32/name
32354     0x11/imm32/alloc-id:fake
32355     Single-float-var-in-mem/imm32/inouts
32356     0x11/imm32/alloc-id:fake
32357     Single-float-var-in-some-register/imm32/outputs
32358     0x11/imm32/alloc-id:fake
32359     _string_f3_0f_51_square_root/imm32/subx-name
32360     0/imm32/no-rm32
32361     0/imm32/no-r32
32362     0/imm32/no-imm32
32363     0/imm32/no-imm8
32364     0/imm32/no-disp32
32365     1/imm32/xm32-is-first-inout
32366     3/imm32/x32-is-first-output
32367     0x11/imm32/alloc-id:fake
32368     _Primitive-inverse-square-root-xreg-to-xreg/imm32/next
32369 # - floating-point inverse square root 1/sqrt(x)
32370 _Primitive-inverse-square-root-xreg-to-xreg:  # (payload primitive)
32371     0x11/imm32/alloc-id:fake:payload
32372     # var1/xreg <- reciprocal var2 => f3 0f 52/inverse-square-root var2/xm32 var1/x32
32373     0x11/imm32/alloc-id:fake
32374     _string-inverse-square-root/imm32/name
32375     0x11/imm32/alloc-id:fake
32376     Single-float-var-in-some-register/imm32/inouts
32377     0x11/imm32/alloc-id:fake
32378     Single-float-var-in-some-register/imm32/outputs
32379     0x11/imm32/alloc-id:fake
32380     _string_f3_0f_52_inverse_square_root/imm32/subx-name
32381     0/imm32/no-rm32
32382     0/imm32/no-r32
32383     0/imm32/no-imm32
32384     0/imm32/no-imm8
32385     0/imm32/no-disp32
32386     1/imm32/xm32-is-first-inout
32387     3/imm32/x32-is-first-output
32388     0x11/imm32/alloc-id:fake
32389     _Primitive-inverse-square-root-mem-to-xreg/imm32/next
32390 _Primitive-inverse-square-root-mem-to-xreg:  # (payload primitive)
32391     0x11/imm32/alloc-id:fake:payload
32392     # var1/xreg <- divide var2 => f3 0f 52/inverse-square-root var2/xm32 var1/x32
32393     0x11/imm32/alloc-id:fake
32394     _string-inverse-square-root/imm32/name
32395     0x11/imm32/alloc-id:fake
32396     Single-float-var-in-mem/imm32/inouts
32397     0x11/imm32/alloc-id:fake
32398     Single-float-var-in-some-register/imm32/outputs
32399     0x11/imm32/alloc-id:fake
32400     _string_f3_0f_52_inverse_square_root/imm32/subx-name
32401     0/imm32/no-rm32
32402     0/imm32/no-r32
32403     0/imm32/no-imm32
32404     0/imm32/no-imm8
32405     0/imm32/no-disp32
32406     1/imm32/xm32-is-first-inout
32407     3/imm32/x32-is-first-output
32408     0x11/imm32/alloc-id:fake
32409     _Primitive-compare-xreg-with-xreg/imm32/next
32410 # - floating-point compare
32411 _Primitive-compare-xreg-with-xreg:  # (payload primitive)
32412     0x11/imm32/alloc-id:fake:payload
32413     # compare var1/reg1 var2/reg2 => 0f 2f/compare var2/x32 var1/xm32
32414     0x11/imm32/alloc-id:fake
32415     _string-compare/imm32/name
32416     0x11/imm32/alloc-id:fake
32417     Two-float-args-in-regs/imm32/inouts
32418     0/imm32/no-outputs
32419     0/imm32/no-outputs
32420     0x11/imm32/alloc-id:fake
32421     _string_0f_2f_compare/imm32/subx-name
32422     0/imm32/no-rm32
32423     0/imm32/no-r32
32424     0/imm32/no-imm32
32425     0/imm32/no-imm8
32426     0/imm32/no-disp32
32427     2/imm32/xm32-is-second-inout
32428     1/imm32/x32-is-first-inout
32429     0x11/imm32/alloc-id:fake
32430     _Primitive-compare-xreg-with-mem/imm32/next
32431 _Primitive-compare-xreg-with-mem:  # (payload primitive)
32432     0x11/imm32/alloc-id:fake:payload
32433     # compare var1/xreg var2 => 0f 2f/compare var1/x32 var2/xm32
32434     0x11/imm32/alloc-id:fake
32435     _string-compare/imm32/name
32436     0x11/imm32/alloc-id:fake
32437     Two-args-float-reg-float-stack/imm32/inouts
32438     0/imm32/no-outputs
32439     0/imm32/no-outputs
32440     0x11/imm32/alloc-id:fake
32441     _string_0f_2f_compare/imm32/subx-name
32442     0/imm32/no-rm32
32443     0/imm32/no-r32
32444     0/imm32/no-imm32
32445     0/imm32/no-imm8
32446     0/imm32/no-disp32
32447     2/imm32/xm32-is-second-inout
32448     1/imm32/x32-is-first-inout
32449     0x11/imm32/alloc-id:fake
32450     _Primitive-break-if-addr</imm32/next
32451 # - branches
32452 _Primitive-break-if-addr<:  # (payload primitive)
32453     0x11/imm32/alloc-id:fake:payload
32454     0x11/imm32/alloc-id:fake
32455     _string-break-if-addr</imm32/name
32456     0/imm32/no-inouts
32457     0/imm32/no-inouts
32458     0/imm32/no-outputs
32459     0/imm32/no-outputs
32460     0x11/imm32/alloc-id:fake
32461     _string_0f_82_jump_break/imm32/subx-name
32462     0/imm32/no-rm32
32463     0/imm32/no-r32
32464     0/imm32/no-imm32
32465     0/imm32/no-imm8
32466     0/imm32/no-disp32
32467     0/imm32/no-xm32
32468     0/imm32/no-x32
32469     0x11/imm32/alloc-id:fake
32470     _Primitive-break-if-addr>=/imm32/next
32471 _Primitive-break-if-addr>=:  # (payload primitive)
32472     0x11/imm32/alloc-id:fake:payload
32473     0x11/imm32/alloc-id:fake
32474     _string-break-if-addr>=/imm32/name
32475     0/imm32/no-inouts
32476     0/imm32/no-inouts
32477     0/imm32/no-outputs
32478     0/imm32/no-outputs
32479     0x11/imm32/alloc-id:fake
32480     _string_0f_83_jump_break/imm32/subx-name
32481     0/imm32/no-rm32
32482     0/imm32/no-r32
32483     0/imm32/no-imm32
32484     0/imm32/no-imm8
32485     0/imm32/no-disp32
32486     0/imm32/no-xm32
32487     0/imm32/no-x32
32488     0x11/imm32/alloc-id:fake
32489     _Primitive-break-if-=/imm32/next
32490 _Primitive-break-if-=:  # (payload primitive)
32491     0x11/imm32/alloc-id:fake:payload
32492     0x11/imm32/alloc-id:fake
32493     _string-break-if-=/imm32/name
32494     0/imm32/no-inouts
32495     0/imm32/no-inouts
32496     0/imm32/no-outputs
32497     0/imm32/no-outputs
32498     0x11/imm32/alloc-id:fake
32499     _string_0f_84_jump_break/imm32/subx-name
32500     0/imm32/no-rm32
32501     0/imm32/no-r32
32502     0/imm32/no-imm32
32503     0/imm32/no-imm8
32504     0/imm32/no-disp32
32505     0/imm32/no-xm32
32506     0/imm32/no-x32
32507     0x11/imm32/alloc-id:fake
32508     _Primitive-break-if-!=/imm32/next
32509 _Primitive-break-if-!=:  # (payload primitive)
32510     0x11/imm32/alloc-id:fake:payload
32511     0x11/imm32/alloc-id:fake
32512     _string-break-if-!=/imm32/name
32513     0/imm32/no-inouts
32514     0/imm32/no-inouts
32515     0/imm32/no-outputs
32516     0/imm32/no-outputs
32517     0x11/imm32/alloc-id:fake
32518     _string_0f_85_jump_break/imm32/subx-name
32519     0/imm32/no-rm32
32520     0/imm32/no-r32
32521     0/imm32/no-imm32
32522     0/imm32/no-imm8
32523     0/imm32/no-disp32
32524     0/imm32/no-xm32
32525     0/imm32/no-x32
32526     0x11/imm32/alloc-id:fake
32527     _Primitive-break-if-addr<=/imm32/next
32528 _Primitive-break-if-addr<=:  # (payload primitive)
32529     0x11/imm32/alloc-id:fake:payload
32530     0x11/imm32/alloc-id:fake
32531     _string-break-if-addr<=/imm32/name
32532     0/imm32/no-inouts
32533     0/imm32/no-inouts
32534     0/imm32/no-outputs
32535     0/imm32/no-outputs
32536     0x11/imm32/alloc-id:fake
32537     _string_0f_86_jump_break/imm32/subx-name
32538     0/imm32/no-rm32
32539     0/imm32/no-r32
32540     0/imm32/no-imm32
32541     0/imm32/no-imm8
32542     0/imm32/no-disp32
32543     0/imm32/no-xm32
32544     0/imm32/no-x32
32545     0x11/imm32/alloc-id:fake
32546     _Primitive-break-if-addr>/imm32/next
32547 _Primitive-break-if-addr>:  # (payload primitive)
32548     0x11/imm32/alloc-id:fake:payload
32549     0x11/imm32/alloc-id:fake
32550     _string-break-if-addr>/imm32/name
32551     0/imm32/no-inouts
32552     0/imm32/no-inouts
32553     0/imm32/no-outputs
32554     0/imm32/no-outputs
32555     0x11/imm32/alloc-id:fake
32556     _string_0f_87_jump_break/imm32/subx-name
32557     0/imm32/no-rm32
32558     0/imm32/no-r32
32559     0/imm32/no-imm32
32560     0/imm32/no-imm8
32561     0/imm32/no-disp32
32562     0/imm32/no-xm32
32563     0/imm32/no-x32
32564     0x11/imm32/alloc-id:fake
32565     _Primitive-break-if-</imm32/next
32566 _Primitive-break-if-<:  # (payload primitive)
32567     0x11/imm32/alloc-id:fake:payload
32568     0x11/imm32/alloc-id:fake
32569     _string-break-if-</imm32/name
32570     0/imm32/no-inouts
32571     0/imm32/no-inouts
32572     0/imm32/no-outputs
32573     0/imm32/no-outputs
32574     0x11/imm32/alloc-id:fake
32575     _string_0f_8c_jump_break/imm32/subx-name
32576     0/imm32/no-rm32
32577     0/imm32/no-r32
32578     0/imm32/no-imm32
32579     0/imm32/no-imm8
32580     0/imm32/no-disp32
32581     0/imm32/no-xm32
32582     0/imm32/no-x32
32583     0x11/imm32/alloc-id:fake
32584     _Primitive-break-if->=/imm32/next
32585 _Primitive-break-if->=:  # (payload primitive)
32586     0x11/imm32/alloc-id:fake:payload
32587     0x11/imm32/alloc-id:fake
32588     _string-break-if->=/imm32/name
32589     0/imm32/no-inouts
32590     0/imm32/no-inouts
32591     0/imm32/no-outputs
32592     0/imm32/no-outputs
32593     0x11/imm32/alloc-id:fake
32594     _string_0f_8d_jump_break/imm32/subx-name
32595     0/imm32/no-rm32
32596     0/imm32/no-r32
32597     0/imm32/no-imm32
32598     0/imm32/no-imm8
32599     0/imm32/no-disp32
32600     0/imm32/no-xm32
32601     0/imm32/no-x32
32602     0x11/imm32/alloc-id:fake
32603     _Primitive-break-if-<=/imm32/next
32604 _Primitive-break-if-<=:  # (payload primitive)
32605     0x11/imm32/alloc-id:fake:payload
32606     0x11/imm32/alloc-id:fake
32607     _string-break-if-<=/imm32/name
32608     0/imm32/no-inouts
32609     0/imm32/no-inouts
32610     0/imm32/no-outputs
32611     0/imm32/no-outputs
32612     0x11/imm32/alloc-id:fake
32613     _string_0f_8e_jump_break/imm32/subx-name
32614     0/imm32/no-rm32
32615     0/imm32/no-r32
32616     0/imm32/no-imm32
32617     0/imm32/no-imm8
32618     0/imm32/no-disp32
32619     0/imm32/no-xm32
32620     0/imm32/no-x32
32621     0x11/imm32/alloc-id:fake
32622     _Primitive-break-if->/imm32/next
32623 _Primitive-break-if->:  # (payload primitive)
32624     0x11/imm32/alloc-id:fake:payload
32625     0x11/imm32/alloc-id:fake
32626     _string-break-if->/imm32/name
32627     0/imm32/no-inouts
32628     0/imm32/no-inouts
32629     0/imm32/no-outputs
32630     0/imm32/no-outputs
32631     0x11/imm32/alloc-id:fake
32632     _string_0f_8f_jump_break/imm32/subx-name
32633     0/imm32/no-rm32
32634     0/imm32/no-r32
32635     0/imm32/no-imm32
32636     0/imm32/no-imm8
32637     0/imm32/no-disp32
32638     0/imm32/no-xm32
32639     0/imm32/no-x32
32640     0x11/imm32/alloc-id:fake
32641     _Primitive-break/imm32/next
32642 _Primitive-break:  # (payload primitive)
32643     0x11/imm32/alloc-id:fake:payload
32644     0x11/imm32/alloc-id:fake
32645     _string-break/imm32/name
32646     0/imm32/no-inouts
32647     0/imm32/no-inouts
32648     0/imm32/no-outputs
32649     0/imm32/no-outputs
32650     0x11/imm32/alloc-id:fake
32651     _string_e9_jump_break/imm32/subx-name
32652     0/imm32/no-rm32
32653     0/imm32/no-r32
32654     0/imm32/no-imm32
32655     0/imm32/no-imm8
32656     0/imm32/no-disp32
32657     0/imm32/no-xm32
32658     0/imm32/no-x32
32659     0x11/imm32/alloc-id:fake
32660     _Primitive-loop-if-addr</imm32/next
32661 _Primitive-loop-if-addr<:  # (payload primitive)
32662     0x11/imm32/alloc-id:fake:payload
32663     0x11/imm32/alloc-id:fake
32664     _string-loop-if-addr</imm32/name
32665     0/imm32/no-inouts
32666     0/imm32/no-inouts
32667     0/imm32/no-outputs
32668     0/imm32/no-outputs
32669     0x11/imm32/alloc-id:fake
32670     _string_0f_82_jump_loop/imm32/subx-name
32671     0/imm32/no-rm32
32672     0/imm32/no-r32
32673     0/imm32/no-imm32
32674     0/imm32/no-imm8
32675     0/imm32/no-disp32
32676     0/imm32/no-xm32
32677     0/imm32/no-x32
32678     0x11/imm32/alloc-id:fake
32679     _Primitive-loop-if-addr>=/imm32/next
32680 _Primitive-loop-if-addr>=:  # (payload primitive)
32681     0x11/imm32/alloc-id:fake:payload
32682     0x11/imm32/alloc-id:fake
32683     _string-loop-if-addr>=/imm32/name
32684     0/imm32/no-inouts
32685     0/imm32/no-inouts
32686     0/imm32/no-outputs
32687     0/imm32/no-outputs
32688     0x11/imm32/alloc-id:fake
32689     _string_0f_83_jump_loop/imm32/subx-name
32690     0/imm32/no-rm32
32691     0/imm32/no-r32
32692     0/imm32/no-imm32
32693     0/imm32/no-imm8
32694     0/imm32/no-disp32
32695     0/imm32/no-xm32
32696     0/imm32/no-x32
32697     0x11/imm32/alloc-id:fake
32698     _Primitive-loop-if-=/imm32/next
32699 _Primitive-loop-if-=:  # (payload primitive)
32700     0x11/imm32/alloc-id:fake:payload
32701     0x11/imm32/alloc-id:fake
32702     _string-loop-if-=/imm32/name
32703     0/imm32/no-inouts
32704     0/imm32/no-inouts
32705     0/imm32/no-outputs
32706     0/imm32/no-outputs
32707     0x11/imm32/alloc-id:fake
32708     _string_0f_84_jump_loop/imm32/subx-name
32709     0/imm32/no-rm32
32710     0/imm32/no-r32
32711     0/imm32/no-imm32
32712     0/imm32/no-imm8
32713     0/imm32/no-disp32
32714     0/imm32/no-xm32
32715     0/imm32/no-x32
32716     0x11/imm32/alloc-id:fake
32717     _Primitive-loop-if-!=/imm32/next
32718 _Primitive-loop-if-!=:  # (payload primitive)
32719     0x11/imm32/alloc-id:fake:payload
32720     0x11/imm32/alloc-id:fake
32721     _string-loop-if-!=/imm32/name
32722     0/imm32/no-inouts
32723     0/imm32/no-inouts
32724     0/imm32/no-outputs
32725     0/imm32/no-outputs
32726     0x11/imm32/alloc-id:fake
32727     _string_0f_85_jump_loop/imm32/subx-name
32728     0/imm32/no-rm32
32729     0/imm32/no-r32
32730     0/imm32/no-imm32
32731     0/imm32/no-imm8
32732     0/imm32/no-disp32
32733     0/imm32/no-xm32
32734     0/imm32/no-x32
32735     0x11/imm32/alloc-id:fake
32736     _Primitive-loop-if-addr<=/imm32/next
32737 _Primitive-loop-if-addr<=:  # (payload primitive)
32738     0x11/imm32/alloc-id:fake:payload
32739     0x11/imm32/alloc-id:fake
32740     _string-loop-if-addr<=/imm32/name
32741     0/imm32/no-inouts
32742     0/imm32/no-inouts
32743     0/imm32/no-outputs
32744     0/imm32/no-outputs
32745     0x11/imm32/alloc-id:fake
32746     _string_0f_86_jump_loop/imm32/subx-name
32747     0/imm32/no-rm32
32748     0/imm32/no-r32
32749     0/imm32/no-imm32
32750     0/imm32/no-imm8
32751     0/imm32/no-disp32
32752     0/imm32/no-xm32
32753     0/imm32/no-x32
32754     0x11/imm32/alloc-id:fake
32755     _Primitive-loop-if-addr>/imm32/next
32756 _Primitive-loop-if-addr>:  # (payload primitive)
32757     0x11/imm32/alloc-id:fake:payload
32758     0x11/imm32/alloc-id:fake
32759     _string-loop-if-addr>/imm32/name
32760     0/imm32/no-inouts
32761     0/imm32/no-inouts
32762     0/imm32/no-outputs
32763     0/imm32/no-outputs
32764     0x11/imm32/alloc-id:fake
32765     _string_0f_87_jump_loop/imm32/subx-name
32766     0/imm32/no-rm32
32767     0/imm32/no-r32
32768     0/imm32/no-imm32
32769     0/imm32/no-imm8
32770     0/imm32/no-disp32
32771     0/imm32/no-xm32
32772     0/imm32/no-x32
32773     0x11/imm32/alloc-id:fake
32774     _Primitive-loop-if-</imm32/next
32775 _Primitive-loop-if-<:  # (payload primitive)
32776     0x11/imm32/alloc-id:fake:payload
32777     0x11/imm32/alloc-id:fake
32778     _string-loop-if-</imm32/name
32779     0/imm32/no-inouts
32780     0/imm32/no-inouts
32781     0/imm32/no-outputs
32782     0/imm32/no-outputs
32783     0x11/imm32/alloc-id:fake
32784     _string_0f_8c_jump_loop/imm32/subx-name
32785     0/imm32/no-rm32
32786     0/imm32/no-r32
32787     0/imm32/no-imm32
32788     0/imm32/no-imm8
32789     0/imm32/no-disp32
32790     0/imm32/no-xm32
32791     0/imm32/no-x32
32792     0x11/imm32/alloc-id:fake
32793     _Primitive-loop-if->=/imm32/next
32794 _Primitive-loop-if->=:  # (payload primitive)
32795     0x11/imm32/alloc-id:fake:payload
32796     0x11/imm32/alloc-id:fake
32797     _string-loop-if->=/imm32/name
32798     0/imm32/no-inouts
32799     0/imm32/no-inouts
32800     0/imm32/no-outputs
32801     0/imm32/no-outputs
32802     0x11/imm32/alloc-id:fake
32803     _string_0f_8d_jump_loop/imm32/subx-name
32804     0/imm32/no-rm32
32805     0/imm32/no-r32
32806     0/imm32/no-imm32
32807     0/imm32/no-imm8
32808     0/imm32/no-disp32
32809     0/imm32/no-xm32
32810     0/imm32/no-x32
32811     0x11/imm32/alloc-id:fake
32812     _Primitive-loop-if-<=/imm32/next
32813 _Primitive-loop-if-<=:  # (payload primitive)
32814     0x11/imm32/alloc-id:fake:payload
32815     0x11/imm32/alloc-id:fake
32816     _string-loop-if-<=/imm32/name
32817     0/imm32/no-inouts
32818     0/imm32/no-inouts
32819     0/imm32/no-outputs
32820     0/imm32/no-outputs
32821     0x11/imm32/alloc-id:fake
32822     _string_0f_8e_jump_loop/imm32/subx-name
32823     0/imm32/no-rm32
32824     0/imm32/no-r32
32825     0/imm32/no-imm32
32826     0/imm32/no-imm8
32827     0/imm32/no-disp32
32828     0/imm32/no-xm32
32829     0/imm32/no-x32
32830     0x11/imm32/alloc-id:fake
32831     _Primitive-loop-if->/imm32/next
32832 _Primitive-loop-if->:  # (payload primitive)
32833     0x11/imm32/alloc-id:fake:payload
32834     0x11/imm32/alloc-id:fake
32835     _string-loop-if->/imm32/name
32836     0/imm32/no-inouts
32837     0/imm32/no-inouts
32838     0/imm32/no-outputs
32839     0/imm32/no-outputs
32840     0x11/imm32/alloc-id:fake
32841     _string_0f_8f_jump_loop/imm32/subx-name
32842     0/imm32/no-rm32
32843     0/imm32/no-r32
32844     0/imm32/no-imm32
32845     0/imm32/no-imm8
32846     0/imm32/no-disp32
32847     0/imm32/no-xm32
32848     0/imm32/no-x32
32849     0x11/imm32/alloc-id:fake
32850     _Primitive-loop/imm32/next  # we probably don't need an unconditional break
32851 _Primitive-loop:  # (payload primitive)
32852     0x11/imm32/alloc-id:fake:payload
32853     0x11/imm32/alloc-id:fake
32854     _string-loop/imm32/name
32855     0/imm32/no-inouts
32856     0/imm32/no-inouts
32857     0/imm32/no-outputs
32858     0/imm32/no-outputs
32859     0x11/imm32/alloc-id:fake
32860     _string_e9_jump_loop/imm32/subx-name
32861     0/imm32/no-rm32
32862     0/imm32/no-r32
32863     0/imm32/no-imm32
32864     0/imm32/no-imm8
32865     0/imm32/no-disp32
32866     0/imm32/no-xm32
32867     0/imm32/no-x32
32868     0x11/imm32/alloc-id:fake
32869     _Primitive-break-if-addr<-named/imm32/next
32870 # - branches to named blocks
32871 _Primitive-break-if-addr<-named:  # (payload primitive)
32872     0x11/imm32/alloc-id:fake:payload
32873     0x11/imm32/alloc-id:fake
32874     _string-break-if-addr</imm32/name
32875     0x11/imm32/alloc-id:fake
32876     Single-lit-var/imm32/inouts
32877     0/imm32/no-outputs
32878     0/imm32/no-outputs
32879     0x11/imm32/alloc-id:fake
32880     _string_0f_82_jump_label/imm32/subx-name
32881     0/imm32/no-rm32
32882     0/imm32/no-r32
32883     0/imm32/no-imm32
32884     0/imm32/no-imm8
32885     1/imm32/disp32-is-first-inout
32886     0/imm32/no-xm32
32887     0/imm32/no-x32
32888     0x11/imm32/alloc-id:fake
32889     _Primitive-break-if-addr>=-named/imm32/next
32890 _Primitive-break-if-addr>=-named:  # (payload primitive)
32891     0x11/imm32/alloc-id:fake:payload
32892     0x11/imm32/alloc-id:fake
32893     _string-break-if-addr>=/imm32/name
32894     0x11/imm32/alloc-id:fake
32895     Single-lit-var/imm32/inouts
32896     0/imm32/no-outputs
32897     0/imm32/no-outputs
32898     0x11/imm32/alloc-id:fake
32899     _string_0f_83_jump_label/imm32/subx-name
32900     0/imm32/no-rm32
32901     0/imm32/no-r32
32902     0/imm32/no-imm32
32903     0/imm32/no-imm8
32904     1/imm32/disp32-is-first-inout
32905     0/imm32/no-xm32
32906     0/imm32/no-x32
32907     0x11/imm32/alloc-id:fake
32908     _Primitive-break-if-=-named/imm32/next
32909 _Primitive-break-if-=-named:  # (payload primitive)
32910     0x11/imm32/alloc-id:fake:payload
32911     0x11/imm32/alloc-id:fake
32912     _string-break-if-=/imm32/name
32913     0x11/imm32/alloc-id:fake
32914     Single-lit-var/imm32/inouts
32915     0/imm32/no-outputs
32916     0/imm32/no-outputs
32917     0x11/imm32/alloc-id:fake
32918     _string_0f_84_jump_label/imm32/subx-name
32919     0/imm32/no-rm32
32920     0/imm32/no-r32
32921     0/imm32/no-imm32
32922     0/imm32/no-imm8
32923     1/imm32/disp32-is-first-inout
32924     0/imm32/no-xm32
32925     0/imm32/no-x32
32926     0x11/imm32/alloc-id:fake
32927     _Primitive-break-if-!=-named/imm32/next
32928 _Primitive-break-if-!=-named:  # (payload primitive)
32929     0x11/imm32/alloc-id:fake:payload
32930     0x11/imm32/alloc-id:fake
32931     _string-break-if-!=/imm32/name
32932     0x11/imm32/alloc-id:fake
32933     Single-lit-var/imm32/inouts
32934     0/imm32/no-outputs
32935     0/imm32/no-outputs
32936     0x11/imm32/alloc-id:fake
32937     _string_0f_85_jump_label/imm32/subx-name
32938     0/imm32/no-rm32
32939     0/imm32/no-r32
32940     0/imm32/no-imm32
32941     0/imm32/no-imm8
32942     1/imm32/disp32-is-first-inout
32943     0/imm32/no-xm32
32944     0/imm32/no-x32
32945     0x11/imm32/alloc-id:fake
32946     _Primitive-break-if-addr<=-named/imm32/next
32947 _Primitive-break-if-addr<=-named:  # (payload primitive)
32948     0x11/imm32/alloc-id:fake:payload
32949     0x11/imm32/alloc-id:fake
32950     _string-break-if-addr<=/imm32/name
32951     0x11/imm32/alloc-id:fake
32952     Single-lit-var/imm32/inouts
32953     0/imm32/no-outputs
32954     0/imm32/no-outputs
32955     0x11/imm32/alloc-id:fake
32956     _string_0f_86_jump_label/imm32/subx-name
32957     0/imm32/no-rm32
32958     0/imm32/no-r32
32959     0/imm32/no-imm32
32960     0/imm32/no-imm8
32961     1/imm32/disp32-is-first-inout
32962     0/imm32/no-xm32
32963     0/imm32/no-x32
32964     0x11/imm32/alloc-id:fake
32965     _Primitive-break-if-addr>-named/imm32/next
32966 _Primitive-break-if-addr>-named:  # (payload primitive)
32967     0x11/imm32/alloc-id:fake:payload
32968     0x11/imm32/alloc-id:fake
32969     _string-break-if-addr>/imm32/name
32970     0x11/imm32/alloc-id:fake
32971     Single-lit-var/imm32/inouts
32972     0/imm32/no-outputs
32973     0/imm32/no-outputs
32974     0x11/imm32/alloc-id:fake
32975     _string_0f_87_jump_label/imm32/subx-name
32976     0/imm32/no-rm32
32977     0/imm32/no-r32
32978     0/imm32/no-imm32
32979     0/imm32/no-imm8
32980     1/imm32/disp32-is-first-inout
32981     0/imm32/no-xm32
32982     0/imm32/no-x32
32983     0x11/imm32/alloc-id:fake
32984     _Primitive-break-if-<-named/imm32/next
32985 _Primitive-break-if-<-named:  # (payload primitive)
32986     0x11/imm32/alloc-id:fake:payload
32987     0x11/imm32/alloc-id:fake
32988     _string-break-if-</imm32/name
32989     0x11/imm32/alloc-id:fake
32990     Single-lit-var/imm32/inouts
32991     0/imm32/no-outputs
32992     0/imm32/no-outputs
32993     0x11/imm32/alloc-id:fake
32994     _string_0f_8c_jump_label/imm32/subx-name
32995     0/imm32/no-rm32
32996     0/imm32/no-r32
32997     0/imm32/no-imm32
32998     0/imm32/no-imm8
32999     1/imm32/disp32-is-first-inout
33000     0/imm32/no-xm32
33001     0/imm32/no-x32
33002     0x11/imm32/alloc-id:fake
33003     _Primitive-break-if->=-named/imm32/next
33004 _Primitive-break-if->=-named:  # (payload primitive)
33005     0x11/imm32/alloc-id:fake:payload
33006     0x11/imm32/alloc-id:fake
33007     _string-break-if->=/imm32/name
33008     0x11/imm32/alloc-id:fake
33009     Single-lit-var/imm32/inouts
33010     0/imm32/no-outputs
33011     0/imm32/no-outputs
33012     0x11/imm32/alloc-id:fake
33013     _string_0f_8d_jump_label/imm32/subx-name
33014     0/imm32/no-rm32
33015     0/imm32/no-r32
33016     0/imm32/no-imm32
33017     0/imm32/no-imm8
33018     1/imm32/disp32-is-first-inout
33019     0/imm32/no-xm32
33020     0/imm32/no-x32
33021     0x11/imm32/alloc-id:fake
33022     _Primitive-break-if-<=-named/imm32/next
33023 _Primitive-break-if-<=-named:  # (payload primitive)
33024     0x11/imm32/alloc-id:fake:payload
33025     0x11/imm32/alloc-id:fake
33026     _string-break-if-<=/imm32/name
33027     0x11/imm32/alloc-id:fake
33028     Single-lit-var/imm32/inouts
33029     0/imm32/no-outputs
33030     0/imm32/no-outputs
33031     0x11/imm32/alloc-id:fake
33032     _string_0f_8e_jump_label/imm32/subx-name
33033     0/imm32/no-rm32
33034     0/imm32/no-r32
33035     0/imm32/no-imm32
33036     0/imm32/no-imm8
33037     1/imm32/disp32-is-first-inout
33038     0/imm32/no-xm32
33039     0/imm32/no-x32
33040     0x11/imm32/alloc-id:fake
33041     _Primitive-break-if->-named/imm32/next
33042 _Primitive-break-if->-named:  # (payload primitive)
33043     0x11/imm32/alloc-id:fake:payload
33044     0x11/imm32/alloc-id:fake
33045     _string-break-if->/imm32/name
33046     0x11/imm32/alloc-id:fake
33047     Single-lit-var/imm32/inouts
33048     0/imm32/no-outputs
33049     0/imm32/no-outputs
33050     0x11/imm32/alloc-id:fake
33051     _string_0f_8f_jump_label/imm32/subx-name
33052     0/imm32/no-rm32
33053     0/imm32/no-r32
33054     0/imm32/no-imm32
33055     0/imm32/no-imm8
33056     1/imm32/disp32-is-first-inout
33057     0/imm32/no-xm32
33058     0/imm32/no-x32
33059     0x11/imm32/alloc-id:fake
33060     _Primitive-break-named/imm32/next
33061 _Primitive-break-named:  # (payload primitive)
33062     0x11/imm32/alloc-id:fake:payload
33063     0x11/imm32/alloc-id:fake
33064     _string-break/imm32/name
33065     0x11/imm32/alloc-id:fake
33066     Single-lit-var/imm32/inouts
33067     0/imm32/no-outputs
33068     0/imm32/no-outputs
33069     0x11/imm32/alloc-id:fake
33070     _string_e9_jump_label/imm32/subx-name
33071     0/imm32/no-rm32
33072     0/imm32/no-r32
33073     0/imm32/no-imm32
33074     0/imm32/no-imm8
33075     1/imm32/disp32-is-first-inout
33076     0/imm32/no-xm32
33077     0/imm32/no-x32
33078     0x11/imm32/alloc-id:fake
33079     _Primitive-loop-if-addr<-named/imm32/next
33080 _Primitive-loop-if-addr<-named:  # (payload primitive)
33081     0x11/imm32/alloc-id:fake:payload
33082     0x11/imm32/alloc-id:fake
33083     _string-loop-if-addr</imm32/name
33084     0x11/imm32/alloc-id:fake
33085     Single-lit-var/imm32/inouts
33086     0/imm32/no-outputs
33087     0/imm32/no-outputs
33088     0x11/imm32/alloc-id:fake
33089     _string_0f_82_jump_label/imm32/subx-name
33090     0/imm32/no-rm32
33091     0/imm32/no-r32
33092     0/imm32/no-imm32
33093     0/imm32/no-imm8
33094     1/imm32/disp32-is-first-inout
33095     0/imm32/no-xm32
33096     0/imm32/no-x32
33097     0x11/imm32/alloc-id:fake
33098     _Primitive-loop-if-addr>=-named/imm32/next
33099 _Primitive-loop-if-addr>=-named:  # (payload primitive)
33100     0x11/imm32/alloc-id:fake:payload
33101     0x11/imm32/alloc-id:fake
33102     _string-loop-if-addr>=/imm32/name
33103     0x11/imm32/alloc-id:fake
33104     Single-lit-var/imm32/inouts
33105     0/imm32/no-outputs
33106     0/imm32/no-outputs
33107     0x11/imm32/alloc-id:fake
33108     _string_0f_83_jump_label/imm32/subx-name
33109     0/imm32/no-rm32
33110     0/imm32/no-r32
33111     0/imm32/no-imm32
33112     0/imm32/no-imm8
33113     1/imm32/disp32-is-first-inout
33114     0/imm32/no-xm32
33115     0/imm32/no-x32
33116     0x11/imm32/alloc-id:fake
33117     _Primitive-loop-if-=-named/imm32/next
33118 _Primitive-loop-if-=-named:  # (payload primitive)
33119     0x11/imm32/alloc-id:fake:payload
33120     0x11/imm32/alloc-id:fake
33121     _string-loop-if-=/imm32/name
33122     0x11/imm32/alloc-id:fake
33123     Single-lit-var/imm32/inouts
33124     0/imm32/no-outputs
33125     0/imm32/no-outputs
33126     0x11/imm32/alloc-id:fake
33127     _string_0f_84_jump_label/imm32/subx-name
33128     0/imm32/no-rm32
33129     0/imm32/no-r32
33130     0/imm32/no-imm32
33131     0/imm32/no-imm8
33132     1/imm32/disp32-is-first-inout
33133     0/imm32/no-xm32
33134     0/imm32/no-x32
33135     0x11/imm32/alloc-id:fake
33136     _Primitive-loop-if-!=-named/imm32/next
33137 _Primitive-loop-if-!=-named:  # (payload primitive)
33138     0x11/imm32/alloc-id:fake:payload
33139     0x11/imm32/alloc-id:fake
33140     _string-loop-if-!=/imm32/name
33141     0x11/imm32/alloc-id:fake
33142     Single-lit-var/imm32/inouts
33143     0/imm32/no-outputs
33144     0/imm32/no-outputs
33145     0x11/imm32/alloc-id:fake
33146     _string_0f_85_jump_label/imm32/subx-name
33147     0/imm32/no-rm32
33148     0/imm32/no-r32
33149     0/imm32/no-imm32
33150     0/imm32/no-imm8
33151     1/imm32/disp32-is-first-inout
33152     0/imm32/no-xm32
33153     0/imm32/no-x32
33154     0x11/imm32/alloc-id:fake
33155     _Primitive-loop-if-addr<=-named/imm32/next
33156 _Primitive-loop-if-addr<=-named:  # (payload primitive)
33157     0x11/imm32/alloc-id:fake:payload
33158     0x11/imm32/alloc-id:fake
33159     _string-loop-if-addr<=/imm32/name
33160     0x11/imm32/alloc-id:fake
33161     Single-lit-var/imm32/inouts
33162     0/imm32/no-outputs
33163     0/imm32/no-outputs
33164     0x11/imm32/alloc-id:fake
33165     _string_0f_86_jump_label/imm32/subx-name
33166     0/imm32/no-rm32
33167     0/imm32/no-r32
33168     0/imm32/no-imm32
33169     0/imm32/no-imm8
33170     1/imm32/disp32-is-first-inout
33171     0/imm32/no-xm32
33172     0/imm32/no-x32
33173     0x11/imm32/alloc-id:fake
33174     _Primitive-loop-if-addr>-named/imm32/next
33175 _Primitive-loop-if-addr>-named:  # (payload primitive)
33176     0x11/imm32/alloc-id:fake:payload
33177     0x11/imm32/alloc-id:fake
33178     _string-loop-if-addr>/imm32/name
33179     0x11/imm32/alloc-id:fake
33180     Single-lit-var/imm32/inouts
33181     0/imm32/no-outputs
33182     0/imm32/no-outputs
33183     0x11/imm32/alloc-id:fake
33184     _string_0f_87_jump_label/imm32/subx-name
33185     0/imm32/no-rm32
33186     0/imm32/no-r32
33187     0/imm32/no-imm32
33188     0/imm32/no-imm8
33189     1/imm32/disp32-is-first-inout
33190     0/imm32/no-xm32
33191     0/imm32/no-x32
33192     0x11/imm32/alloc-id:fake
33193     _Primitive-loop-if-<-named/imm32/next
33194 _Primitive-loop-if-<-named:  # (payload primitive)
33195     0x11/imm32/alloc-id:fake:payload
33196     0x11/imm32/alloc-id:fake
33197     _string-loop-if-</imm32/name
33198     0x11/imm32/alloc-id:fake
33199     Single-lit-var/imm32/inouts
33200     0/imm32/no-outputs
33201     0/imm32/no-outputs
33202     0x11/imm32/alloc-id:fake
33203     _string_0f_8c_jump_label/imm32/subx-name
33204     0/imm32/no-rm32
33205     0/imm32/no-r32
33206     0/imm32/no-imm32
33207     0/imm32/no-imm8
33208     1/imm32/disp32-is-first-inout
33209     0/imm32/no-xm32
33210     0/imm32/no-x32
33211     0x11/imm32/alloc-id:fake
33212     _Primitive-loop-if->=-named/imm32/next
33213 _Primitive-loop-if->=-named:  # (payload primitive)
33214     0x11/imm32/alloc-id:fake:payload
33215     0x11/imm32/alloc-id:fake
33216     _string-loop-if->=/imm32/name
33217     0x11/imm32/alloc-id:fake
33218     Single-lit-var/imm32/inouts
33219     0/imm32/no-outputs
33220     0/imm32/no-outputs
33221     0x11/imm32/alloc-id:fake
33222     _string_0f_8d_jump_label/imm32/subx-name
33223     0/imm32/no-rm32
33224     0/imm32/no-r32
33225     0/imm32/no-imm32
33226     0/imm32/no-imm8
33227     1/imm32/disp32-is-first-inout
33228     0/imm32/no-xm32
33229     0/imm32/no-x32
33230     0x11/imm32/alloc-id:fake
33231     _Primitive-loop-if-<=-named/imm32/next
33232 _Primitive-loop-if-<=-named:  # (payload primitive)
33233     0x11/imm32/alloc-id:fake:payload
33234     0x11/imm32/alloc-id:fake
33235     _string-loop-if-<=/imm32/name
33236     0x11/imm32/alloc-id:fake
33237     Single-lit-var/imm32/inouts
33238     0/imm32/no-outputs
33239     0/imm32/no-outputs
33240     0x11/imm32/alloc-id:fake
33241     _string_0f_8e_jump_label/imm32/subx-name
33242     0/imm32/no-rm32
33243     0/imm32/no-r32
33244     0/imm32/no-imm32
33245     0/imm32/no-imm8
33246     1/imm32/disp32-is-first-inout
33247     0/imm32/no-xm32
33248     0/imm32/no-x32
33249     0x11/imm32/alloc-id:fake
33250     _Primitive-loop-if->-named/imm32/next
33251 _Primitive-loop-if->-named:  # (payload primitive)
33252     0x11/imm32/alloc-id:fake:payload
33253     0x11/imm32/alloc-id:fake
33254     _string-loop-if->/imm32/name
33255     0x11/imm32/alloc-id:fake
33256     Single-lit-var/imm32/inouts
33257     0/imm32/no-outputs
33258     0/imm32/no-outputs
33259     0x11/imm32/alloc-id:fake
33260     _string_0f_8f_jump_label/imm32/subx-name
33261     0/imm32/no-rm32
33262     0/imm32/no-r32
33263     0/imm32/no-imm32
33264     0/imm32/no-imm8
33265     1/imm32/disp32-is-first-inout
33266     0/imm32/no-xm32
33267     0/imm32/no-x32
33268     0x11/imm32/alloc-id:fake
33269     _Primitive-loop-named/imm32/next  # we probably don't need an unconditional break
33270 _Primitive-loop-named:  # (payload primitive)
33271     0x11/imm32/alloc-id:fake:payload
33272     0x11/imm32/alloc-id:fake
33273     _string-loop/imm32/name
33274     0x11/imm32/alloc-id:fake
33275     Single-lit-var/imm32/inouts
33276     0/imm32/no-outputs
33277     0/imm32/no-outputs
33278     0x11/imm32/alloc-id:fake
33279     _string_e9_jump_label/imm32/subx-name
33280     0/imm32/no-rm32
33281     0/imm32/no-r32
33282     0/imm32/no-imm32
33283     0/imm32/no-imm8
33284     1/imm32/disp32-is-first-inout
33285     0/imm32/no-xm32
33286     0/imm32/no-x32
33287     0x11/imm32/alloc-id:fake
33288     _Primitive-break-if-float</imm32/next
33289 # - branches based on floating-point comparisons
33290 _Primitive-break-if-float<:  # (payload primitive)
33291     0x11/imm32/alloc-id:fake:payload
33292     0x11/imm32/alloc-id:fake
33293     _string-break-if-float</imm32/name
33294     0/imm32/no-inouts
33295     0/imm32/no-inouts
33296     0/imm32/no-outputs
33297     0/imm32/no-outputs
33298     0x11/imm32/alloc-id:fake
33299     _string_0f_82_jump_break/imm32/subx-name
33300     0/imm32/no-rm32
33301     0/imm32/no-r32
33302     0/imm32/no-imm32
33303     0/imm32/no-imm8
33304     0/imm32/no-disp32
33305     0/imm32/no-xm32
33306     0/imm32/no-x32
33307     0x11/imm32/alloc-id:fake
33308     _Primitive-break-if-float>=/imm32/next
33309 _Primitive-break-if-float>=:  # (payload primitive)
33310     0x11/imm32/alloc-id:fake:payload
33311     0x11/imm32/alloc-id:fake
33312     _string-break-if-float>=/imm32/name
33313     0/imm32/no-inouts
33314     0/imm32/no-inouts
33315     0/imm32/no-outputs
33316     0/imm32/no-outputs
33317     0x11/imm32/alloc-id:fake
33318     _string_0f_83_jump_break/imm32/subx-name
33319     0/imm32/no-rm32
33320     0/imm32/no-r32
33321     0/imm32/no-imm32
33322     0/imm32/no-imm8
33323     0/imm32/no-disp32
33324     0/imm32/no-xm32
33325     0/imm32/no-x32
33326     0x11/imm32/alloc-id:fake
33327     _Primitive-break-if-float<=/imm32/next
33328 _Primitive-break-if-float<=:  # (payload primitive)
33329     0x11/imm32/alloc-id:fake:payload
33330     0x11/imm32/alloc-id:fake
33331     _string-break-if-float<=/imm32/name
33332     0/imm32/no-inouts
33333     0/imm32/no-inouts
33334     0/imm32/no-outputs
33335     0/imm32/no-outputs
33336     0x11/imm32/alloc-id:fake
33337     _string_0f_86_jump_break/imm32/subx-name
33338     0/imm32/no-rm32
33339     0/imm32/no-r32
33340     0/imm32/no-imm32
33341     0/imm32/no-imm8
33342     0/imm32/no-disp32
33343     0/imm32/no-xm32
33344     0/imm32/no-x32
33345     0x11/imm32/alloc-id:fake
33346     _Primitive-break-if-float>/imm32/next
33347 _Primitive-break-if-float>:  # (payload primitive)
33348     0x11/imm32/alloc-id:fake:payload
33349     0x11/imm32/alloc-id:fake
33350     _string-break-if-float>/imm32/name
33351     0/imm32/no-inouts
33352     0/imm32/no-inouts
33353     0/imm32/no-outputs
33354     0/imm32/no-outputs
33355     0x11/imm32/alloc-id:fake
33356     _string_0f_87_jump_break/imm32/subx-name
33357     0/imm32/no-rm32
33358     0/imm32/no-r32
33359     0/imm32/no-imm32
33360     0/imm32/no-imm8
33361     0/imm32/no-disp32
33362     0/imm32/no-xm32
33363     0/imm32/no-x32
33364     0x11/imm32/alloc-id:fake
33365     _Primitive-loop-if-float</imm32/next
33366 _Primitive-loop-if-float<:  # (payload primitive)
33367     0x11/imm32/alloc-id:fake:payload
33368     0x11/imm32/alloc-id:fake
33369     _string-loop-if-float</imm32/name
33370     0/imm32/no-inouts
33371     0/imm32/no-inouts
33372     0/imm32/no-outputs
33373     0/imm32/no-outputs
33374     0x11/imm32/alloc-id:fake
33375     _string_0f_82_jump_loop/imm32/subx-name
33376     0/imm32/no-rm32
33377     0/imm32/no-r32
33378     0/imm32/no-imm32
33379     0/imm32/no-imm8
33380     0/imm32/no-disp32
33381     0/imm32/no-xm32
33382     0/imm32/no-x32
33383     0x11/imm32/alloc-id:fake
33384     _Primitive-loop-if-float>=/imm32/next
33385 _Primitive-loop-if-float>=:  # (payload primitive)
33386     0x11/imm32/alloc-id:fake:payload
33387     0x11/imm32/alloc-id:fake
33388     _string-loop-if-float>=/imm32/name
33389     0/imm32/no-inouts
33390     0/imm32/no-inouts
33391     0/imm32/no-outputs
33392     0/imm32/no-outputs
33393     0x11/imm32/alloc-id:fake
33394     _string_0f_83_jump_loop/imm32/subx-name
33395     0/imm32/no-rm32
33396     0/imm32/no-r32
33397     0/imm32/no-imm32
33398     0/imm32/no-imm8
33399     0/imm32/no-disp32
33400     0/imm32/no-xm32
33401     0/imm32/no-x32
33402     0x11/imm32/alloc-id:fake
33403     _Primitive-loop-if-float<=/imm32/next
33404 _Primitive-loop-if-float<=:  # (payload primitive)
33405     0x11/imm32/alloc-id:fake:payload
33406     0x11/imm32/alloc-id:fake
33407     _string-loop-if-float<=/imm32/name
33408     0/imm32/no-inouts
33409     0/imm32/no-inouts
33410     0/imm32/no-outputs
33411     0/imm32/no-outputs
33412     0x11/imm32/alloc-id:fake
33413     _string_0f_86_jump_loop/imm32/subx-name
33414     0/imm32/no-rm32
33415     0/imm32/no-r32
33416     0/imm32/no-imm32
33417     0/imm32/no-imm8
33418     0/imm32/no-disp32
33419     0/imm32/no-xm32
33420     0/imm32/no-x32
33421     0x11/imm32/alloc-id:fake
33422     _Primitive-loop-if-float>/imm32/next
33423 _Primitive-loop-if-float>:  # (payload primitive)
33424     0x11/imm32/alloc-id:fake:payload
33425     0x11/imm32/alloc-id:fake
33426     _string-loop-if-float>/imm32/name
33427     0/imm32/no-inouts
33428     0/imm32/no-inouts
33429     0/imm32/no-outputs
33430     0/imm32/no-outputs
33431     0x11/imm32/alloc-id:fake
33432     _string_0f_87_jump_loop/imm32/subx-name
33433     0/imm32/no-rm32
33434     0/imm32/no-r32
33435     0/imm32/no-imm32
33436     0/imm32/no-imm8
33437     0/imm32/no-disp32
33438     0/imm32/no-xm32
33439     0/imm32/no-x32
33440     0x11/imm32/alloc-id:fake
33441     _Primitive-break-if-float<-named/imm32/next
33442 _Primitive-break-if-float<-named:  # (payload primitive)
33443     0x11/imm32/alloc-id:fake:payload
33444     0x11/imm32/alloc-id:fake
33445     _string-break-if-float</imm32/name
33446     0x11/imm32/alloc-id:fake
33447     Single-lit-var/imm32/inouts
33448     0/imm32/no-outputs
33449     0/imm32/no-outputs
33450     0x11/imm32/alloc-id:fake
33451     _string_0f_82_jump_label/imm32/subx-name
33452     0/imm32/no-rm32
33453     0/imm32/no-r32
33454     0/imm32/no-imm32
33455     0/imm32/no-imm8
33456     1/imm32/disp32-is-first-inout
33457     0/imm32/no-xm32
33458     0/imm32/no-x32
33459     0x11/imm32/alloc-id:fake
33460     _Primitive-break-if-float>=-named/imm32/next
33461 _Primitive-break-if-float>=-named:  # (payload primitive)
33462     0x11/imm32/alloc-id:fake:payload
33463     0x11/imm32/alloc-id:fake
33464     _string-break-if-float>=/imm32/name
33465     0x11/imm32/alloc-id:fake
33466     Single-lit-var/imm32/inouts
33467     0/imm32/no-outputs
33468     0/imm32/no-outputs
33469     0x11/imm32/alloc-id:fake
33470     _string_0f_83_jump_label/imm32/subx-name
33471     0/imm32/no-rm32
33472     0/imm32/no-r32
33473     0/imm32/no-imm32
33474     0/imm32/no-imm8
33475     1/imm32/disp32-is-first-inout
33476     0/imm32/no-xm32
33477     0/imm32/no-x32
33478     0x11/imm32/alloc-id:fake
33479     _Primitive-break-if-float<=-named/imm32/next
33480 _Primitive-break-if-float<=-named:  # (payload primitive)
33481     0x11/imm32/alloc-id:fake:payload
33482     0x11/imm32/alloc-id:fake
33483     _string-break-if-float<=/imm32/name
33484     0x11/imm32/alloc-id:fake
33485     Single-lit-var/imm32/inouts
33486     0/imm32/no-outputs
33487     0/imm32/no-outputs
33488     0x11/imm32/alloc-id:fake
33489     _string_0f_86_jump_label/imm32/subx-name
33490     0/imm32/no-rm32
33491     0/imm32/no-r32
33492     0/imm32/no-imm32
33493     0/imm32/no-imm8
33494     1/imm32/disp32-is-first-inout
33495     0/imm32/no-xm32
33496     0/imm32/no-x32
33497     0x11/imm32/alloc-id:fake
33498     _Primitive-break-if-float>-named/imm32/next
33499 _Primitive-break-if-float>-named:  # (payload primitive)
33500     0x11/imm32/alloc-id:fake:payload
33501     0x11/imm32/alloc-id:fake
33502     _string-break-if-float>/imm32/name
33503     0x11/imm32/alloc-id:fake
33504     Single-lit-var/imm32/inouts
33505     0/imm32/no-outputs
33506     0/imm32/no-outputs
33507     0x11/imm32/alloc-id:fake
33508     _string_0f_87_jump_label/imm32/subx-name
33509     0/imm32/no-rm32
33510     0/imm32/no-r32
33511     0/imm32/no-imm32
33512     0/imm32/no-imm8
33513     1/imm32/disp32-is-first-inout
33514     0/imm32/no-xm32
33515     0/imm32/no-x32
33516     0x11/imm32/alloc-id:fake
33517     _Primitive-loop-if-float<-named/imm32/next
33518 _Primitive-loop-if-float<-named:  # (payload primitive)
33519     0x11/imm32/alloc-id:fake:payload
33520     0x11/imm32/alloc-id:fake
33521     _string-loop-if-float</imm32/name
33522     0x11/imm32/alloc-id:fake
33523     Single-lit-var/imm32/inouts
33524     0/imm32/no-outputs
33525     0/imm32/no-outputs
33526     0x11/imm32/alloc-id:fake
33527     _string_0f_82_jump_label/imm32/subx-name
33528     0/imm32/no-rm32
33529     0/imm32/no-r32
33530     0/imm32/no-imm32
33531     0/imm32/no-imm8
33532     1/imm32/disp32-is-first-inout
33533     0/imm32/no-xm32
33534     0/imm32/no-x32
33535     0x11/imm32/alloc-id:fake
33536     _Primitive-loop-if-float>=-named/imm32/next
33537 _Primitive-loop-if-float>=-named:  # (payload primitive)
33538     0x11/imm32/alloc-id:fake:payload
33539     0x11/imm32/alloc-id:fake
33540     _string-loop-if-float>=/imm32/name
33541     0x11/imm32/alloc-id:fake
33542     Single-lit-var/imm32/inouts
33543     0/imm32/no-outputs
33544     0/imm32/no-outputs
33545     0x11/imm32/alloc-id:fake
33546     _string_0f_83_jump_label/imm32/subx-name
33547     0/imm32/no-rm32
33548     0/imm32/no-r32
33549     0/imm32/no-imm32
33550     0/imm32/no-imm8
33551     1/imm32/disp32-is-first-inout
33552     0/imm32/no-xm32
33553     0/imm32/no-x32
33554     0x11/imm32/alloc-id:fake
33555     _Primitive-loop-if-float<=-named/imm32/next
33556 _Primitive-loop-if-float<=-named:  # (payload primitive)
33557     0x11/imm32/alloc-id:fake:payload
33558     0x11/imm32/alloc-id:fake
33559     _string-loop-if-float<=/imm32/name
33560     0x11/imm32/alloc-id:fake
33561     Single-lit-var/imm32/inouts
33562     0/imm32/no-outputs
33563     0/imm32/no-outputs
33564     0x11/imm32/alloc-id:fake
33565     _string_0f_86_jump_label/imm32/subx-name
33566     0/imm32/no-rm32
33567     0/imm32/no-r32
33568     0/imm32/no-imm32
33569     0/imm32/no-imm8
33570     1/imm32/disp32-is-first-inout
33571     0/imm32/no-xm32
33572     0/imm32/no-x32
33573     0x11/imm32/alloc-id:fake
33574     _Primitive-loop-if-float>-named/imm32/next
33575 _Primitive-loop-if-float>-named:  # (payload primitive)
33576     0x11/imm32/alloc-id:fake:payload
33577     0x11/imm32/alloc-id:fake
33578     _string-loop-if-float>/imm32/name
33579     0x11/imm32/alloc-id:fake
33580     Single-lit-var/imm32/inouts
33581     0/imm32/no-outputs
33582     0/imm32/no-outputs
33583     0x11/imm32/alloc-id:fake
33584     _string_0f_87_jump_label/imm32/subx-name
33585     0/imm32/no-rm32
33586     0/imm32/no-r32
33587     0/imm32/no-imm32
33588     0/imm32/no-imm8
33589     1/imm32/disp32-is-first-inout
33590     0/imm32/no-xm32
33591     0/imm32/no-x32
33592     0/imm32/next
33593     0/imm32/next
33594 
33595 # string literals for Mu instructions
33596 _string-add:  # (payload array byte)
33597     0x11/imm32/alloc-id:fake:payload
33598     # "add"
33599     0x3/imm32/size
33600     0x61/a 0x64/d 0x64/d
33601 _string-address:  # (payload array byte)
33602     0x11/imm32/alloc-id:fake:payload
33603     # "address"
33604     0x7/imm32/size
33605     0x61/a 0x64/d 0x64/d 0x72/r 0x65/e 0x73/s 0x73/s
33606 _string-add-to:  # (payload array byte)
33607     0x11/imm32/alloc-id:fake:payload
33608     # "add-to"
33609     0x6/imm32/size
33610     0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o
33611 _string-and:  # (payload array byte)
33612     0x11/imm32/alloc-id:fake:payload
33613     # "and"
33614     0x3/imm32/size
33615     0x61/a 0x6e/n 0x64/d
33616 _string-and-with:  # (payload array byte)
33617     0x11/imm32/alloc-id:fake:payload
33618     # "and-with"
33619     0x8/imm32/size
33620     0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
33621 _string-break:  # (payload array byte)
33622     0x11/imm32/alloc-id:fake:payload
33623     # "break"
33624     0x5/imm32/size
33625     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k
33626 _string-break-if-<:  # (payload array byte)
33627     0x11/imm32/alloc-id:fake:payload
33628     # "break-if-<"
33629     0xa/imm32/size
33630     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/<
33631 _string-break-if-<=:  # (payload array byte)
33632     0x11/imm32/alloc-id:fake:payload
33633     # "break-if-<="
33634     0xb/imm32/size
33635     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/=
33636 _string-break-if-=:  # (payload array byte)
33637     0x11/imm32/alloc-id:fake:payload
33638     # "break-if-="
33639     0xa/imm32/size
33640     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/=
33641 _string-break-if->:  # (payload array byte)
33642     0x11/imm32/alloc-id:fake:payload
33643     # "break-if->"
33644     0xa/imm32/size
33645     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/>
33646 _string-break-if->=:  # (payload array byte)
33647     0x11/imm32/alloc-id:fake:payload
33648     # "break-if->="
33649     0xb/imm32/size
33650     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/=
33651 _string-break-if-!=:  # (payload array byte)
33652     0x11/imm32/alloc-id:fake:payload
33653     # "break-if-!="
33654     0xb/imm32/size
33655     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/=
33656 _string-break-if-addr<:  # (payload array byte)
33657     0x11/imm32/alloc-id:fake:payload
33658     # "break-if-addr<"
33659     0xe/imm32/size
33660     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/<
33661 _string-break-if-addr<=:  # (payload array byte)
33662     0x11/imm32/alloc-id:fake:payload
33663     # "break-if-addr<="
33664     0xf/imm32/size
33665     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/=
33666 _string-break-if-addr>:  # (payload array byte)
33667     0x11/imm32/alloc-id:fake:payload
33668     # "break-if-addr>"
33669     0xe/imm32/size
33670     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/>
33671 _string-break-if-addr>=:  # (payload array byte)
33672     0x11/imm32/alloc-id:fake:payload
33673     # "break-if-addr>="
33674     0xf/imm32/size
33675     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/=
33676 _string-break-if-float<:  # (payload array byte)
33677     0x11/imm32/alloc-id:fake:payload
33678     # "break-if-float<"
33679     0xf/imm32/size
33680     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/<
33681 _string-break-if-float<=:  # (payload array byte)
33682     0x11/imm32/alloc-id:fake:payload
33683     # "break-if-float<="
33684     0x10/imm32/size
33685     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/=
33686 _string-break-if-float>:  # (payload array byte)
33687     0x11/imm32/alloc-id:fake:payload
33688     # "break-if-float>"
33689     0xf/imm32/size
33690     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/>
33691 _string-break-if-float>=:  # (payload array byte)
33692     0x11/imm32/alloc-id:fake:payload
33693     # "break-if-float>="
33694     0x10/imm32/size
33695     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/=
33696 _string-compare:  # (payload array byte)
33697     0x11/imm32/alloc-id:fake:payload
33698     # "compare"
33699     0x7/imm32/size
33700     0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e
33701 _string-copy:  # (payload array byte)
33702     0x11/imm32/alloc-id:fake:payload
33703     # "copy"
33704     0x4/imm32/size
33705     0x63/c 0x6f/o 0x70/p 0x79/y
33706 _string-copy-to:  # (payload array byte)
33707     0x11/imm32/alloc-id:fake:payload
33708     # "copy-to"
33709     0x7/imm32/size
33710     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o
33711 _string-copy-byte:
33712     0x11/imm32/alloc-id:fake:payload
33713     # "copy-byte"
33714     0x9/imm32/size
33715     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/- 0x62/b 0x79/y 0x74/t 0x65/e
33716 _string-copy-byte-to:
33717     0x11/imm32/alloc-id:fake:payload
33718     # "copy-byte-to"
33719     0xc/imm32/size
33720     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/- 0x62/b 0x79/y 0x74/t 0x65/e 0x2d/- 0x74/t 0x6f/o
33721 _string-decrement:  # (payload array byte)
33722     0x11/imm32/alloc-id:fake:payload
33723     # "decrement"
33724     0x9/imm32/size
33725     0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t
33726 _string-increment:  # (payload array byte)
33727     0x11/imm32/alloc-id:fake:payload
33728     # "increment"
33729     0x9/imm32/size
33730     0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t
33731 _string-loop:  # (payload array byte)
33732     0x11/imm32/alloc-id:fake:payload
33733     # "loop"
33734     0x4/imm32/size
33735     0x6c/l 0x6f/o 0x6f/o 0x70/p
33736 _string-loop-if-<:  # (payload array byte)
33737     0x11/imm32/alloc-id:fake:payload
33738     # "loop-if-<"
33739     0x9/imm32/size
33740     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/<
33741 _string-loop-if-<=:  # (payload array byte)
33742     0x11/imm32/alloc-id:fake:payload
33743     # "loop-if-<="
33744     0xa/imm32/size
33745     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/=
33746 _string-loop-if-=:  # (payload array byte)
33747     0x11/imm32/alloc-id:fake:payload
33748     # "loop-if-="
33749     0x9/imm32/size
33750     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/=
33751 _string-loop-if->:  # (payload array byte)
33752     0x11/imm32/alloc-id:fake:payload
33753     # "loop-if->"
33754     0x9/imm32/size
33755     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/>
33756 _string-loop-if->=:  # (payload array byte)
33757     0x11/imm32/alloc-id:fake:payload
33758     # "loop-if->="
33759     0xa/imm32/size
33760     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/=
33761 _string-loop-if-!=:  # (payload array byte)
33762     0x11/imm32/alloc-id:fake:payload
33763     # "loop-if-!="
33764     0xa/imm32/size
33765     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/=
33766 _string-loop-if-addr<:  # (payload array byte)
33767     0x11/imm32/alloc-id:fake:payload
33768     # "loop-if-addr<"
33769     0xd/imm32/size
33770     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/<
33771 _string-loop-if-addr<=:  # (payload array byte)
33772     0x11/imm32/alloc-id:fake:payload
33773     # "loop-if-addr<="
33774     0xe/imm32/size
33775     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/=
33776 _string-loop-if-addr>:  # (payload array byte)
33777     0x11/imm32/alloc-id:fake:payload
33778     # "loop-if-addr>"
33779     0xd/imm32/size
33780     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/>
33781 _string-loop-if-addr>=:  # (payload array byte)
33782     0x11/imm32/alloc-id:fake:payload
33783     # "loop-if-addr>="
33784     0xe/imm32/size
33785     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/=
33786 _string-loop-if-float<:  # (payload array byte)
33787     0x11/imm32/alloc-id:fake:payload
33788     # "loop-if-float<"
33789     0xe/imm32/size
33790     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/<
33791 _string-loop-if-float<=:  # (payload array byte)
33792     0x11/imm32/alloc-id:fake:payload
33793     # "loop-if-float<="
33794     0xf/imm32/size
33795     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/=
33796 _string-loop-if-float>:  # (payload array byte)
33797     0x11/imm32/alloc-id:fake:payload
33798     # "loop-if-float>"
33799     0xe/imm32/size
33800     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/>
33801 _string-loop-if-float>=:  # (payload array byte)
33802     0x11/imm32/alloc-id:fake:payload
33803     # "loop-if-float>="
33804     0xf/imm32/size
33805     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/=
33806 _string-multiply:  # (payload array byte)
33807     0x11/imm32/alloc-id:fake:payload
33808     # "multiply"
33809     0x8/imm32/size
33810     0x6d/m 0x75/u 0x6c/l 0x74/t 0x69/i 0x70/p 0x6c/l 0x79/y
33811 _string-convert:  # (payload array byte)
33812     0x11/imm32/alloc-id:fake:payload
33813     # "convert"
33814     0x7/imm32/size
33815     0x63/c 0x6f/o 0x6e/n 0x76/v 0x65/e 0x72/r 0x74/t
33816 _string-truncate:  # (payload array byte)
33817     0x11/imm32/alloc-id:fake:payload
33818     # "truncate"
33819     0x8/imm32/size
33820     0x74/t 0x72/r 0x75/u 0x6e/n 0x63/c 0x61/a 0x74/t 0x65/e
33821 _string-reinterpret:  # (payload array byte)
33822     0x11/imm32/alloc-id:fake:payload
33823     # "reinterpret"
33824     0xb/imm32/size
33825     0x72/r 0x65/e 0x69/i 0x6e/n 0x74/t 0x65/e 0x72/r 0x70/p 0x72/r 0x65/e 0x74/t
33826 _string-divide:
33827     0x11/imm32/alloc-id:fake:payload
33828     # "divide"
33829     0x6/imm32/size
33830     0x64/d 0x69/i 0x76/v 0x69/i 0x64/d 0x65/e
33831 _string-max:
33832     0x11/imm32/alloc-id:fake:payload
33833     # "max"
33834     0x3/imm32/size
33835     0x6d/m 0x61/a 0x78/x
33836 _string-min:
33837     0x11/imm32/alloc-id:fake:payload
33838     # "min"
33839     0x3/imm32/size
33840     0x6d/m 0x69/i 0x6e/n
33841 _string-reciprocal:
33842     0x11/imm32/alloc-id:fake:payload
33843     # "reciprocal"
33844     0xa/imm32/size
33845     0x72/r 0x65/e 0x63/c 0x69/i 0x70/p 0x72/r 0x6f/o 0x63/c 0x61/a 0x6c/l
33846 _string-square-root:
33847     0x11/imm32/alloc-id:fake:payload
33848     # "square-root"
33849     0xb/imm32/size
33850     0x73/s 0x71/q 0x75/u 0x61/a 0x72/r 0x65/e 0x2d/- 0x72/r 0x6f/o 0x6f/o 0x74/t
33851 _string-inverse-square-root:
33852     0x11/imm32/alloc-id:fake:payload
33853     # "inverse-square-root"
33854     0x13/imm32/size
33855     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
33856 _string-negate:  # (payload array byte)
33857     0x11/imm32/alloc-id:fake:payload
33858     # "negate"
33859     0x6/imm32/size
33860     0x6e/n 0x65/e 0x67/g 0x61/a 0x74/t 0x65/e
33861 _string-or:  # (payload array byte)
33862     0x11/imm32/alloc-id:fake:payload
33863     # "or"
33864     0x2/imm32/size
33865     0x6f/o 0x72/r
33866 _string-or-with:  # (payload array byte)
33867     0x11/imm32/alloc-id:fake:payload
33868     # "or-with"
33869     0x7/imm32/size
33870     0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
33871 _string-subtract:  # (payload array byte)
33872     0x11/imm32/alloc-id:fake:payload
33873     # "subtract"
33874     0x8/imm32/size
33875     0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t
33876 _string-subtract-from:  # (payload array byte)
33877     0x11/imm32/alloc-id:fake:payload
33878     # "subtract-from"
33879     0xd/imm32/size
33880     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
33881 _string-xor:  # (payload array byte)
33882     0x11/imm32/alloc-id:fake:payload
33883     # "xor"
33884     0x3/imm32/size
33885     0x78/x 0x6f/o 0x72/r
33886 _string-xor-with:  # (payload array byte)
33887     0x11/imm32/alloc-id:fake:payload
33888     # "xor-with"
33889     0x8/imm32/size
33890     0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
33891 _string-shift-left:  # (payload array byte)
33892     0x11/imm32/alloc-id:fake:payload
33893     # "shift-left"
33894     0xa/imm32/size
33895     0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x6c/l 0x65/e 0x66/f 0x74/t
33896 _string-shift-right:  # (payload array byte)
33897     0x11/imm32/alloc-id:fake:payload
33898     # "shift-right"
33899     0xb/imm32/size
33900     0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x72/r 0x69/i 0x67/g 0x68/h 0x74/t
33901 _string-shift-right-signed:  # (payload array byte)
33902     0x11/imm32/alloc-id:fake:payload
33903     # "shift-right-signed"
33904     0x12/imm32/size
33905     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
33906 
33907 # string literals for SubX instructions
33908 _string_01_add_to:  # (payload array byte)
33909     0x11/imm32/alloc-id:fake:payload
33910     # "01/add-to"
33911     0x9/imm32/size
33912     0x30/0 0x31/1 0x2f/slash 0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o
33913 _string_03_add:  # (payload array byte)
33914     0x11/imm32/alloc-id:fake:payload
33915     # "03/add"
33916     0x6/imm32/size
33917     0x30/0 0x33/3 0x2f/slash 0x61/a 0x64/d 0x64/d
33918 _string_05_add_to_eax:  # (payload array byte)
33919     0x11/imm32/alloc-id:fake:payload
33920     # "05/add-to-eax"
33921     0xd/imm32/size
33922     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
33923 _string_09_or_with:  # (payload array byte)
33924     0x11/imm32/alloc-id:fake:payload
33925     # "09/or-with"
33926     0xa/imm32/size
33927     0x30/0 0x39/9 0x2f/slash 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
33928 _string_0b_or:  # (payload array byte)
33929     0x11/imm32/alloc-id:fake:payload
33930     # "0b/or"
33931     0x5/imm32/size
33932     0x30/0 0x62/b 0x2f/slash 0x6f/o 0x72/r
33933 _string_0d_or_with_eax:  # (payload array byte)
33934     0x11/imm32/alloc-id:fake:payload
33935     # "0d/or-with-eax"
33936     0xe/imm32/size
33937     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
33938 _string_0f_82_jump_label:  # (payload array byte)
33939     0x11/imm32/alloc-id:fake:payload
33940     # "0f 82/jump-if-addr<"
33941     0x13/imm32/size
33942     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/<
33943 _string_0f_82_jump_break:  # (payload array byte)
33944     0x11/imm32/alloc-id:fake:payload
33945     # "0f 82/jump-if-addr< break/disp32"
33946     0x20/imm32/size
33947     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
33948 _string_0f_82_jump_loop:  # (payload array byte)
33949     0x11/imm32/alloc-id:fake:payload
33950     # "0f 82/jump-if-addr< loop/disp32"
33951     0x1f/imm32/size
33952     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
33953 _string_0f_83_jump_label:  # (payload array byte)
33954     0x11/imm32/alloc-id:fake:payload
33955     # "0f 83/jump-if-addr>="
33956     0x14/imm32/size
33957     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/=
33958 _string_0f_83_jump_break:  # (payload array byte)
33959     0x11/imm32/alloc-id:fake:payload
33960     # "0f 83/jump-if-addr>= break/disp32"
33961     0x21/imm32/size
33962     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
33963 _string_0f_83_jump_loop:  # (payload array byte)
33964     0x11/imm32/alloc-id:fake:payload
33965     # "0f 83/jump-if-addr>= loop/disp32"
33966     0x20/imm32/size
33967     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
33968 _string_0f_84_jump_label:  # (payload array byte)
33969     0x11/imm32/alloc-id:fake:payload
33970     # "0f 84/jump-if-="
33971     0xf/imm32/size
33972     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/=
33973 _string_0f_84_jump_break:  # (payload array byte)
33974     0x11/imm32/alloc-id:fake:payload
33975     # "0f 84/jump-if-= break/disp32"
33976     0x1c/imm32/size
33977     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
33978 _string_0f_84_jump_loop:  # (payload array byte)
33979     0x11/imm32/alloc-id:fake:payload
33980     # "0f 84/jump-if-= loop/disp32"
33981     0x1b/imm32/size
33982     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
33983 _string_0f_85_jump_label:  # (payload array byte)
33984     0x11/imm32/alloc-id:fake:payload
33985     # "0f 85/jump-if-!="
33986     0x10/imm32/size
33987     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/=
33988 _string_0f_85_jump_break:  # (payload array byte)
33989     0x11/imm32/alloc-id:fake:payload
33990     # "0f 85/jump-if-!= break/disp32"
33991     0x1d/imm32/size
33992     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
33993 _string_0f_85_jump_loop:  # (payload array byte)
33994     0x11/imm32/alloc-id:fake:payload
33995     # "0f 85/jump-if-!= loop/disp32"
33996     0x1c/imm32/size
33997     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
33998 _string_0f_86_jump_label:  # (payload array byte)
33999     0x11/imm32/alloc-id:fake:payload
34000     # "0f 86/jump-if-addr<="
34001     0x14/imm32/size
34002     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/=
34003 _string_0f_86_jump_break:  # (payload array byte)
34004     0x11/imm32/alloc-id:fake:payload
34005     # "0f 86/jump-if-addr<= break/disp32"
34006     0x21/imm32/size
34007     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
34008 _string_0f_86_jump_loop:  # (payload array byte)
34009     0x11/imm32/alloc-id:fake:payload
34010     # "0f 86/jump-if-addr<= loop/disp32"
34011     0x20/imm32/size
34012     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
34013 _string_0f_87_jump_label:  # (payload array byte)
34014     0x11/imm32/alloc-id:fake:payload
34015     # "0f 87/jump-if-addr>"
34016     0x13/imm32/size
34017     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/>
34018 _string_0f_87_jump_break:  # (payload array byte)
34019     0x11/imm32/alloc-id:fake:payload
34020     # "0f 87/jump-if-addr> break/disp32"
34021     0x20/imm32/size
34022     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
34023 _string_0f_87_jump_loop:  # (payload array byte)
34024     0x11/imm32/alloc-id:fake:payload
34025     # "0f 87/jump-if-addr> loop/disp32"
34026     0x1f/imm32/size
34027     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
34028 _string_0f_8c_jump_label:  # (payload array byte)
34029     0x11/imm32/alloc-id:fake:payload
34030     # "0f 8c/jump-if-<"
34031     0xf/imm32/size
34032     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/<
34033 _string_0f_8c_jump_break:  # (payload array byte)
34034     0x11/imm32/alloc-id:fake:payload
34035     # "0f 8c/jump-if-< break/disp32"
34036     0x1c/imm32/size
34037     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
34038 _string_0f_8c_jump_loop:  # (payload array byte)
34039     0x11/imm32/alloc-id:fake:payload
34040     # "0f 8c/jump-if-< loop/disp32"
34041     0x1b/imm32/size
34042     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
34043 _string_0f_8d_jump_label:  # (payload array byte)
34044     0x11/imm32/alloc-id:fake:payload
34045     # "0f 8d/jump-if->="
34046     0x10/imm32/size
34047     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/=
34048 _string_0f_8d_jump_break:  # (payload array byte)
34049     0x11/imm32/alloc-id:fake:payload
34050     # "0f 8d/jump-if->= break/disp32"
34051     0x1d/imm32/size
34052     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
34053 _string_0f_8d_jump_loop:  # (payload array byte)
34054     0x11/imm32/alloc-id:fake:payload
34055     # "0f 8d/jump-if->= loop/disp32"
34056     0x1c/imm32/size
34057     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
34058 _string_0f_8e_jump_label:  # (payload array byte)
34059     0x11/imm32/alloc-id:fake:payload
34060     # "0f 8e/jump-if-<="
34061     0x10/imm32/size
34062     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/=
34063 _string_0f_8e_jump_break:  # (payload array byte)
34064     0x11/imm32/alloc-id:fake:payload
34065     # "0f 8e/jump-if-<= break/disp32"
34066     0x1d/imm32/size
34067     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
34068 _string_0f_8e_jump_loop:  # (payload array byte)
34069     0x11/imm32/alloc-id:fake:payload
34070     # "0f 8e/jump-if-<= loop/disp32"
34071     0x1c/imm32/size
34072     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
34073 _string_0f_8f_jump_label:  # (payload array byte)
34074     0x11/imm32/alloc-id:fake:payload
34075     # "0f 8f/jump-if->"
34076     0xf/imm32/size
34077     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/>
34078 _string_0f_8f_jump_break:  # (payload array byte)
34079     0x11/imm32/alloc-id:fake:payload
34080     # "0f 8f/jump-if-> break/disp32"
34081     0x1c/imm32/size
34082     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
34083 _string_0f_8f_jump_loop:  # (payload array byte)
34084     0x11/imm32/alloc-id:fake:payload
34085     # "0f 8f/jump-if-> loop/disp32"
34086     0x1b/imm32/size
34087     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
34088 _string_0f_af_multiply:  # (payload array byte)
34089     0x11/imm32/alloc-id:fake:payload
34090     # "0f af/multiply"
34091     0xe/imm32/size
34092     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
34093 _string_f3_0f_2a_convert_to_float:
34094     0x11/imm32/alloc-id:fake:payload
34095     # "f3 0f 2a/convert-to-float"
34096     0x19/imm32/size
34097     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
34098 _string_f3_0f_2d_convert_to_int:
34099     0x11/imm32/alloc-id:fake:payload
34100     # "f3 0f 2d/convert-to-int"
34101     0x17/imm32/size
34102     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
34103 _string_f3_0f_2c_truncate_to_int:
34104     0x11/imm32/alloc-id:fake:payload
34105     # "f3 0f 2c/truncate-to-int"
34106     0x18/imm32/size
34107     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
34108 _string_f3_0f_58_add:
34109     0x11/imm32/alloc-id:fake:payload
34110     # "f3 0f 58/add"
34111     0xc/imm32/size
34112     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x38/8 0x2f/slash 0x61/a 0x64/d 0x64/d
34113 _string_f3_0f_5c_subtract:
34114     0x11/imm32/alloc-id:fake:payload
34115     # "f3 0f 5c/subtract"
34116     0x11/imm32/size
34117     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
34118 _string_f3_0f_59_multiply:
34119     0x11/imm32/alloc-id:fake:payload
34120     # "f3 0f 59/multiply"
34121     0x11/imm32/size
34122     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
34123 _string_f3_0f_5e_divide:
34124     0x11/imm32/alloc-id:fake:payload
34125     # "f3 0f 5e/divide"
34126     0xf/imm32/size
34127     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
34128 _string_f3_0f_53_reciprocal:
34129     0x11/imm32/alloc-id:fake:payload
34130     # "f3 0f 53/reciprocal"
34131     0x13/imm32/size
34132     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
34133 _string_f3_0f_51_square_root:
34134     0x11/imm32/alloc-id:fake:payload
34135     # "f3 0f 51/square-root"
34136     0x14/imm32/size
34137     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
34138 _string_f3_0f_52_inverse_square_root:
34139     0x11/imm32/alloc-id:fake:payload
34140     # "f3 0f 52/inverse-square-root"
34141     0x1c/imm32/size
34142     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
34143 _string_f3_0f_5d_min:
34144     0x11/imm32/alloc-id:fake:payload
34145     # "f3 0f 5d/min"
34146     0xc/imm32/size
34147     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x64/d 0x2f/slash 0x6d/m 0x69/i 0x6e/n
34148 _string_f3_0f_5f_max:
34149     0x11/imm32/alloc-id:fake:payload
34150     # "f3 0f 5f/max"
34151     0xc/imm32/size
34152     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x66/f 0x2f/slash 0x6d/m 0x61/a 0x78/x
34153 _string_f3_0f_10_copy:
34154     0x11/imm32/alloc-id:fake:payload
34155     # "f3 0f 10/copy"
34156     0xd/imm32/size
34157     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
34158 _string_f3_0f_11_copy:
34159     0x11/imm32/alloc-id:fake:payload
34160     # "f3 0f 11/copy"
34161     0xd/imm32/size
34162     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
34163 _string_0f_2f_compare:
34164     0x11/imm32/alloc-id:fake:payload
34165     # "0f 2f/compare"
34166     0xd/imm32/size
34167     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
34168 _string_21_and_with:  # (payload array byte)
34169     0x11/imm32/alloc-id:fake:payload
34170     # "21/and-with"
34171     0xb/imm32/size
34172     0x32/2 0x31/1 0x2f/slash 0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
34173 _string_23_and:  # (payload array byte)
34174     0x11/imm32/alloc-id:fake:payload
34175     # "23/and"
34176     0x6/imm32/size
34177     0x32/2 0x33/3 0x2f/slash 0x61/a 0x6e/n 0x64/d
34178 _string_25_and_with_eax:  # (payload array byte)
34179     0x11/imm32/alloc-id:fake:payload
34180     # "25/and-with-eax"
34181     0xf/imm32/size
34182     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
34183 _string_29_subtract_from:  # (payload array byte)
34184     0x11/imm32/alloc-id:fake:payload
34185     # "29/subtract-from"
34186     0x10/imm32/size
34187     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
34188 _string_2b_subtract:  # (payload array byte)
34189     0x11/imm32/alloc-id:fake:payload
34190     # "2b/subtract"
34191     0xb/imm32/size
34192     0x32/2 0x62/b 0x2f/slash 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t
34193 _string_2d_subtract_from_eax:  # (payload array byte)
34194     0x11/imm32/alloc-id:fake:payload
34195     # "2d/subtract-from-eax"
34196     0x14/imm32/size
34197     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
34198 _string_31_xor_with:  # (payload array byte)
34199     0x11/imm32/alloc-id:fake:payload
34200     # "31/xor-with"
34201     0xb/imm32/size
34202     0x33/3 0x31/1 0x2f/slash 0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
34203 _string_33_xor:  # (payload array byte)
34204     0x11/imm32/alloc-id:fake:payload
34205     # "33/xor"
34206     0x6/imm32/size
34207     0x33/3 0x33/3 0x2f/slash 0x78/x 0x6f/o 0x72/r
34208 _string_35_xor_with_eax:  # (payload array byte)
34209     0x11/imm32/alloc-id:fake:payload
34210     # "35/xor-with-eax"
34211     0xf/imm32/size
34212     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
34213 _string_39_compare->:  # (payload array byte)
34214     0x11/imm32/alloc-id:fake:payload
34215     # "39/compare->"
34216     0xc/imm32/size
34217     0x33/3 0x39/9 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x2d/dash 0x3e/>
34218 _string_3b_compare<-:  # (payload array byte)
34219     0x11/imm32/alloc-id:fake:payload
34220     # "3b/compare<-"
34221     0xc/imm32/size
34222     0x33/3 0x62/b 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x3c/< 0x2d/dash
34223 _string_3d_compare_eax_with:  # (payload array byte)
34224     0x11/imm32/alloc-id:fake:payload
34225     # "3d/compare-eax-with"
34226     0x13/imm32/size
34227     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
34228 _string_40_increment_eax:  # (payload array byte)
34229     0x11/imm32/alloc-id:fake:payload
34230     # "40/increment-eax"
34231     0x10/imm32/size
34232     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
34233 _string_41_increment_ecx:  # (payload array byte)
34234     0x11/imm32/alloc-id:fake:payload
34235     # "41/increment-ecx"
34236     0x10/imm32/size
34237     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
34238 _string_42_increment_edx:  # (payload array byte)
34239     0x11/imm32/alloc-id:fake:payload
34240     # "42/increment-edx"
34241     0x10/imm32/size
34242     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
34243 _string_43_increment_ebx:  # (payload array byte)
34244     0x11/imm32/alloc-id:fake:payload
34245     # "43/increment-ebx"
34246     0x10/imm32/size
34247     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
34248 _string_46_increment_esi:  # (payload array byte)
34249     0x11/imm32/alloc-id:fake:payload
34250     # "46/increment-esi"
34251     0x10/imm32/size
34252     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
34253 _string_47_increment_edi:  # (payload array byte)
34254     0x11/imm32/alloc-id:fake:payload
34255     # "47/increment-edi"
34256     0x10/imm32/size
34257     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
34258 _string_48_decrement_eax:  # (payload array byte)
34259     0x11/imm32/alloc-id:fake:payload
34260     # "48/decrement-eax"
34261     0x10/imm32/size
34262     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
34263 _string_49_decrement_ecx:  # (payload array byte)
34264     0x11/imm32/alloc-id:fake:payload
34265     # "49/decrement-ecx"
34266     0x10/imm32/size
34267     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
34268 _string_4a_decrement_edx:  # (payload array byte)
34269     0x11/imm32/alloc-id:fake:payload
34270     # "4a/decrement-edx"
34271     0x10/imm32/size
34272     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
34273 _string_4b_decrement_ebx:  # (payload array byte)
34274     0x11/imm32/alloc-id:fake:payload
34275     # "4b/decrement-ebx"
34276     0x10/imm32/size
34277     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
34278 _string_4e_decrement_esi:  # (payload array byte)
34279     0x11/imm32/alloc-id:fake:payload
34280     # "4e/decrement-esi"
34281     0x10/imm32/size
34282     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
34283 _string_4f_decrement_edi:  # (payload array byte)
34284     0x11/imm32/alloc-id:fake:payload
34285     # "4f/decrement-edi"
34286     0x10/imm32/size
34287     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
34288 _string_81_subop_add:  # (payload array byte)
34289     0x11/imm32/alloc-id:fake:payload
34290     # "81 0/subop/add"
34291     0xe/imm32/size
34292     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
34293 _string_81_subop_or:  # (payload array byte)
34294     0x11/imm32/alloc-id:fake:payload
34295     # "81 1/subop/or"
34296     0xd/imm32/size
34297     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
34298 _string_81_subop_and:  # (payload array byte)
34299     0x11/imm32/alloc-id:fake:payload
34300     # "81 4/subop/and"
34301     0xe/imm32/size
34302     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
34303 _string_81_subop_subtract:  # (payload array byte)
34304     0x11/imm32/alloc-id:fake:payload
34305     # "81 5/subop/subtract"
34306     0x13/imm32/size
34307     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
34308 _string_81_subop_xor:  # (payload array byte)
34309     0x11/imm32/alloc-id:fake:payload
34310     # "81 6/subop/xor"
34311     0xe/imm32/size
34312     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
34313 _string_81_subop_compare:  # (payload array byte)
34314     0x11/imm32/alloc-id:fake:payload
34315     # "81 7/subop/compare"
34316     0x12/imm32/size
34317     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
34318 _string_89_<-:  # (payload array byte)
34319     0x11/imm32/alloc-id:fake:payload
34320     # "89/<-"
34321     0x5/imm32/size
34322     0x38/8 0x39/9 0x2f/slash 0x3c/< 0x2d/dash
34323 _string_8b_->:  # (payload array byte)
34324     0x11/imm32/alloc-id:fake:payload
34325     # "8b/->"
34326     0x5/imm32/size
34327     0x38/8 0x62/b 0x2f/slash 0x2d/dash 0x3e/>
34328 _string_8a_copy_byte:
34329     0x11/imm32/alloc-id:fake:payload
34330     # "8a/byte->"
34331     0x9/imm32/size
34332     0x38/8 0x61/a 0x2f// 0x62/b 0x79/y 0x74/t 0x65/e 0x2d/- 0x3e/>
34333 _string_88_copy_byte:
34334     0x11/imm32/alloc-id:fake:payload
34335     # "88/byte<-"
34336     0x9/imm32/size
34337     0x38/8 0x38/8 0x2f// 0x62/b 0x79/y 0x74/t 0x65/e 0x3c/< 0x2d/-
34338 _string_8d_copy_address:  # (payload array byte)
34339     0x11/imm32/alloc-id:fake:payload
34340     # "8d/copy-address"
34341     0xf/imm32/size
34342     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
34343 _string_b8_copy_to_eax:  # (payload array byte)
34344     0x11/imm32/alloc-id:fake:payload
34345     # "b8/copy-to-eax"
34346     0xe/imm32/size
34347     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
34348 _string_b9_copy_to_ecx:  # (payload array byte)
34349     0x11/imm32/alloc-id:fake:payload
34350     # "b9/copy-to-ecx"
34351     0xe/imm32/size
34352     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
34353 _string_ba_copy_to_edx:  # (payload array byte)
34354     0x11/imm32/alloc-id:fake:payload
34355     # "ba/copy-to-edx"
34356     0xe/imm32/size
34357     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
34358 _string_bb_copy_to_ebx:  # (payload array byte)
34359     0x11/imm32/alloc-id:fake:payload
34360     # "bb/copy-to-ebx"
34361     0xe/imm32/size
34362     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
34363 _string_be_copy_to_esi:  # (payload array byte)
34364     0x11/imm32/alloc-id:fake:payload
34365     # "be/copy-to-esi"
34366     0xe/imm32/size
34367     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
34368 _string_bf_copy_to_edi:  # (payload array byte)
34369     0x11/imm32/alloc-id:fake:payload
34370     # "bf/copy-to-edi"
34371     0xe/imm32/size
34372     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
34373 _string_c7_subop_copy:  # (payload array byte)
34374     0x11/imm32/alloc-id:fake:payload
34375     # "c7 0/subop/copy"
34376     0xf/imm32/size
34377     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
34378 _string_e9_jump_label:  # (payload array byte)
34379     0x11/imm32/alloc-id:fake:payload
34380     # "e9/jump"
34381     0x7/imm32/size
34382     0x65/e 0x39/9 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p
34383 _string_e9_jump_break:  # (payload array byte)
34384     0x11/imm32/alloc-id:fake:payload
34385     # "e9/jump break/disp32"
34386     0x14/imm32/size
34387     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
34388 _string_e9_jump_loop:  # (payload array byte)
34389     0x11/imm32/alloc-id:fake:payload
34390     # "e9/jump loop/disp32"
34391     0x13/imm32/size
34392     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
34393 _string_f7_subop_negate:
34394     0x11/imm32/alloc-id:fake:payload
34395     # "f7 3/subop/negate"
34396     0x11/imm32/size
34397     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
34398 _string_ff_subop_increment:  # (payload array byte)
34399     0x11/imm32/alloc-id:fake:payload
34400     # "ff 0/subop/increment"
34401     0x14/imm32/size
34402     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
34403 _string_ff_subop_decrement:  # (payload array byte)
34404     0x11/imm32/alloc-id:fake:payload
34405     # "ff 1/subop/decrement"
34406     0x14/imm32/size
34407     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
34408 _string_c1_subop_shift_left:  # (payload array byte)
34409     0x11/imm32/alloc-id:fake:payload
34410     # "c1/shift 4/subop/left"
34411     0x15/imm32/size
34412     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
34413 _string_c1_subop_shift_right_padding_zeroes:  # (payload array byte)
34414     0x11/imm32/alloc-id:fake:payload
34415     # "c1/shift 5/subop/right-padding-zeroes"
34416     0x25/imm32/size
34417     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
34418 _string_c1_subop_shift_right_preserving_sign:  # (payload array byte)
34419     0x11/imm32/alloc-id:fake:payload
34420     # "c1/shift 7/subop/right-preserving-sign"
34421     0x26/imm32/size
34422     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
34423 
34424 Single-int-var-in-mem:  # (payload list var)
34425     0x11/imm32/alloc-id:fake:payload
34426     0x11/imm32/alloc-id:fake
34427     Int-var-in-mem/imm32
34428     0/imm32/next
34429     0/imm32/next
34430 
34431 Int-var-in-mem:  # (payload var)
34432     0x11/imm32/alloc-id:fake:payload
34433     0/imm32/name
34434     0/imm32/name
34435     0x11/imm32/alloc-id:fake
34436     Type-int/imm32
34437     1/imm32/some-block-depth
34438     1/imm32/some-stack-offset
34439     0/imm32/no-register
34440     0/imm32/no-register
34441 
34442 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
34443 Single-byte-var-in-mem:  # (payload list var)
34444     0x11/imm32/alloc-id:fake:payload
34445     0x11/imm32/alloc-id:fake
34446     Byte-var-in-mem/imm32
34447     0/imm32/next
34448     0/imm32/next
34449 
34450 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
34451 Byte-var-in-mem:  # (payload var)
34452     0x11/imm32/alloc-id:fake:payload
34453     0/imm32/name
34454     0/imm32/name
34455     0x11/imm32/alloc-id:fake
34456     Type-byte/imm32
34457     1/imm32/some-block-depth
34458     1/imm32/some-stack-offset
34459     0/imm32/no-register
34460     0/imm32/no-register
34461 
34462 Two-args-int-stack-int-reg:  # (payload list var)
34463     0x11/imm32/alloc-id:fake:payload
34464     0x11/imm32/alloc-id:fake
34465     Int-var-in-mem/imm32
34466     0x11/imm32/alloc-id:fake
34467     Single-int-var-in-some-register/imm32/next
34468 
34469 Two-int-args-in-regs:  # (payload list var)
34470     0x11/imm32/alloc-id:fake:payload
34471     0x11/imm32/alloc-id:fake
34472     Int-var-in-some-register/imm32
34473     0x11/imm32/alloc-id:fake
34474     Single-int-var-in-some-register/imm32/next
34475 
34476 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
34477 Two-args-byte-stack-byte-reg:  # (payload list var)
34478     0x11/imm32/alloc-id:fake:payload
34479     0x11/imm32/alloc-id:fake
34480     Byte-var-in-mem/imm32
34481     0x11/imm32/alloc-id:fake
34482     Single-byte-var-in-some-register/imm32/next
34483 
34484 Two-args-int-reg-int-stack:  # (payload list var)
34485     0x11/imm32/alloc-id:fake:payload
34486     0x11/imm32/alloc-id:fake
34487     Int-var-in-some-register/imm32
34488     0x11/imm32/alloc-id:fake
34489     Single-int-var-in-mem/imm32/next
34490 
34491 Two-args-int-eax-int-literal:  # (payload list var)
34492     0x11/imm32/alloc-id:fake:payload
34493     0x11/imm32/alloc-id:fake
34494     Int-var-in-eax/imm32
34495     0x11/imm32/alloc-id:fake
34496     Single-lit-var/imm32/next
34497 
34498 Int-var-and-literal:  # (payload list var)
34499     0x11/imm32/alloc-id:fake:payload
34500     0x11/imm32/alloc-id:fake
34501     Int-var-in-mem/imm32
34502     0x11/imm32/alloc-id:fake
34503     Single-lit-var/imm32/next
34504 
34505 Int-var-in-register-and-literal:  # (payload list var)
34506     0x11/imm32/alloc-id:fake:payload
34507     0x11/imm32/alloc-id:fake
34508     Int-var-in-some-register/imm32
34509     0x11/imm32/alloc-id:fake
34510     Single-lit-var/imm32/next
34511 
34512 Two-float-args-in-regs:  # (payload list var)
34513     0x11/imm32/alloc-id:fake:payload
34514     0x11/imm32/alloc-id:fake
34515     Float-var-in-some-register/imm32
34516     0x11/imm32/alloc-id:fake
34517     Single-float-var-in-some-register/imm32/next
34518 
34519 Two-args-float-reg-float-stack:  # (payload list var)
34520     0x11/imm32/alloc-id:fake:payload
34521     0x11/imm32/alloc-id:fake
34522     Float-var-in-some-register/imm32
34523     0x11/imm32/alloc-id:fake
34524     Single-float-var-in-mem/imm32/next
34525 
34526 Two-args-float-stack-float-reg:  # (payload list var)
34527     0x11/imm32/alloc-id:fake:payload
34528     0x11/imm32/alloc-id:fake
34529     Float-var-in-mem/imm32
34530     0x11/imm32/alloc-id:fake
34531     Single-float-var-in-some-register/imm32/next
34532 
34533 Single-int-var-in-some-register:  # (payload list var)
34534     0x11/imm32/alloc-id:fake:payload
34535     0x11/imm32/alloc-id:fake
34536     Int-var-in-some-register/imm32
34537     0/imm32/next
34538     0/imm32/next
34539 
34540 Single-addr-var-in-some-register:  # (payload list var)
34541     0x11/imm32/alloc-id:fake:payload
34542     0x11/imm32/alloc-id:fake
34543     Addr-var-in-some-register/imm32
34544     0/imm32/next
34545     0/imm32/next
34546 
34547 Single-byte-var-in-some-register:  # (payload list var)
34548     0x11/imm32/alloc-id:fake:payload
34549     0x11/imm32/alloc-id:fake
34550     Byte-var-in-some-register/imm32
34551     0/imm32/next
34552     0/imm32/next
34553 
34554 Int-var-in-some-register:  # (payload var)
34555     0x11/imm32/alloc-id:fake:payload
34556     0/imm32/name
34557     0/imm32/name
34558     0x11/imm32/alloc-id:fake
34559     Type-int/imm32
34560     1/imm32/some-block-depth
34561     0/imm32/no-stack-offset
34562     0x11/imm32/alloc-id:fake
34563     Any-register/imm32
34564 
34565 Any-register:  # (payload array byte)
34566     0x11/imm32/alloc-id:fake:payload
34567     1/imm32/size
34568     # data
34569     2a/asterisk
34570 
34571 Addr-var-in-some-register:  # (payload var)
34572     0x11/imm32/alloc-id:fake:payload
34573     0/imm32/name
34574     0/imm32/name
34575     0x11/imm32/alloc-id:fake
34576     Type-addr/imm32
34577     1/imm32/some-block-depth
34578     0/imm32/no-stack-offset
34579     0x11/imm32/alloc-id:fake
34580     Any-register/imm32
34581 
34582 Byte-var-in-some-register:  # (payload var)
34583     0x11/imm32/alloc-id:fake:payload
34584     0/imm32/name
34585     0/imm32/name
34586     0x11/imm32/alloc-id:fake
34587     Type-byte/imm32
34588     1/imm32/some-block-depth
34589     0/imm32/no-stack-offset
34590     0x11/imm32/alloc-id:fake
34591     Any-register/imm32
34592 
34593 Single-int-var-in-eax:  # (payload list var)
34594     0x11/imm32/alloc-id:fake:payload
34595     0x11/imm32/alloc-id:fake
34596     Int-var-in-eax/imm32
34597     0/imm32/next
34598     0/imm32/next
34599 
34600 Int-var-in-eax:
34601     0x11/imm32/alloc-id:fake:payload
34602     0/imm32/name
34603     0/imm32/name
34604     0x11/imm32/alloc-id:fake
34605     Type-int/imm32
34606     1/imm32/some-block-depth
34607     0/imm32/no-stack-offset
34608     0x11/imm32/alloc-id:fake
34609     $Mu-register-eax/imm32  # can't use Register-eax only to keep our buggy tools/treeshake.cc happy (TODO)
34610 
34611 Single-int-var-in-ecx:  # (payload list var)
34612     0x11/imm32/alloc-id:fake:payload
34613     0x11/imm32/alloc-id:fake
34614     Int-var-in-ecx/imm32
34615     0/imm32/next
34616     0/imm32/next
34617 
34618 Int-var-in-ecx:
34619     0x11/imm32/alloc-id:fake:payload
34620     0/imm32/name
34621     0/imm32/name
34622     0x11/imm32/alloc-id:fake
34623     Type-int/imm32
34624     1/imm32/some-block-depth
34625     0/imm32/no-stack-offset
34626     0x11/imm32/alloc-id:fake
34627     $Register-ecx/imm32/register
34628 
34629 Single-int-var-in-edx:  # (payload list var)
34630     0x11/imm32/alloc-id:fake:payload
34631     0x11/imm32/alloc-id:fake
34632     Int-var-in-edx/imm32
34633     0/imm32/next
34634     0/imm32/next
34635 
34636 Int-var-in-edx:  # (payload list var)
34637     0x11/imm32/alloc-id:fake:payload
34638     0/imm32/name
34639     0/imm32/name
34640     0x11/imm32/alloc-id:fake
34641     Type-int/imm32
34642     1/imm32/some-block-depth
34643     0/imm32/no-stack-offset
34644     0x11/imm32/alloc-id:fake
34645     $Register-edx/imm32/register
34646 
34647 Single-int-var-in-ebx:  # (payload list var)
34648     0x11/imm32/alloc-id:fake:payload
34649     0x11/imm32/alloc-id:fake
34650     Int-var-in-ebx/imm32
34651     0/imm32/next
34652     0/imm32/next
34653 
34654 Int-var-in-ebx:  # (payload list var)
34655     0x11/imm32/alloc-id:fake:payload
34656     0/imm32/name
34657     0/imm32/name
34658     0x11/imm32/alloc-id:fake
34659     Type-int/imm32
34660     1/imm32/some-block-depth
34661     0/imm32/no-stack-offset
34662     0x11/imm32/alloc-id:fake
34663     $Register-ebx/imm32/register
34664 
34665 Single-int-var-in-esi:  # (payload list var)
34666     0x11/imm32/alloc-id:fake:payload
34667     0x11/imm32/alloc-id:fake
34668     Int-var-in-esi/imm32
34669     0/imm32/next
34670     0/imm32/next
34671 
34672 Int-var-in-esi:  # (payload list var)
34673     0x11/imm32/alloc-id:fake:payload
34674     0/imm32/name
34675     0/imm32/name
34676     0x11/imm32/alloc-id:fake
34677     Type-int/imm32
34678     1/imm32/some-block-depth
34679     0/imm32/no-stack-offset
34680     0x11/imm32/alloc-id:fake
34681     $Register-esi/imm32/register
34682 
34683 Single-int-var-in-edi:  # (payload list var)
34684     0x11/imm32/alloc-id:fake:payload
34685     0x11/imm32/alloc-id:fake
34686     Int-var-in-edi/imm32
34687     0/imm32/next
34688     0/imm32/next
34689 
34690 Int-var-in-edi:  # (payload list var)
34691     0x11/imm32/alloc-id:fake:payload
34692     0/imm32/name
34693     0/imm32/name
34694     0x11/imm32/alloc-id:fake
34695     Type-int/imm32
34696     1/imm32/some-block-depth
34697     0/imm32/no-stack-offset
34698     0x11/imm32/alloc-id:fake
34699     $Register-edi/imm32/register
34700 
34701 Single-lit-var:  # (payload list var)
34702     0x11/imm32/alloc-id:fake:payload
34703     0x11/imm32/alloc-id:fake
34704     Lit-var/imm32
34705     0/imm32/next
34706     0/imm32/next
34707 
34708 Lit-var:  # (payload var)
34709     0x11/imm32/alloc-id:fake:payload
34710     0/imm32/name
34711     0/imm32/name
34712     0x11/imm32/alloc-id:fake
34713     Type-literal/imm32
34714     1/imm32/some-block-depth
34715     0/imm32/no-stack-offset
34716     0/imm32/no-register
34717     0/imm32/no-register
34718 
34719 Single-float-var-in-mem:  # (payload list var)
34720     0x11/imm32/alloc-id:fake:payload
34721     0x11/imm32/alloc-id:fake
34722     Float-var-in-mem/imm32
34723     0/imm32/next
34724     0/imm32/next
34725 
34726 Float-var-in-mem:  # (payload var)
34727     0x11/imm32/alloc-id:fake:payload
34728     0/imm32/name
34729     0/imm32/name
34730     0x11/imm32/alloc-id:fake
34731     Type-float/imm32
34732     1/imm32/some-block-depth
34733     1/imm32/some-stack-offset
34734     0/imm32/no-register
34735     0/imm32/no-register
34736 
34737 Single-float-var-in-some-register:  # (payload list var)
34738     0x11/imm32/alloc-id:fake:payload
34739     0x11/imm32/alloc-id:fake
34740     Float-var-in-some-register/imm32
34741     0/imm32/next
34742     0/imm32/next
34743 
34744 Float-var-in-some-register:  # (payload var)
34745     0x11/imm32/alloc-id:fake:payload
34746     0/imm32/name
34747     0/imm32/name
34748     0x11/imm32/alloc-id:fake
34749     Type-float/imm32
34750     1/imm32/some-block-depth
34751     0/imm32/no-stack-offset
34752     0x11/imm32/alloc-id:fake
34753     Any-register/imm32
34754 
34755 Type-int:  # (payload type-tree)
34756     0x11/imm32/alloc-id:fake:payload
34757     1/imm32/is-atom
34758     1/imm32/value:int
34759     0/imm32/left:unused
34760     0/imm32/right:null
34761     0/imm32/right:null
34762 
34763 Type-literal:  # (payload type-tree)
34764     0x11/imm32/alloc-id:fake:payload
34765     1/imm32/is-atom
34766     0/imm32/value:literal
34767     0/imm32/left:unused
34768     0/imm32/right:null
34769     0/imm32/right:null
34770 
34771 Type-addr:  # (payload type-tree)
34772     0x11/imm32/alloc-id:fake:payload
34773     1/imm32/is-atom
34774     2/imm32/value:addr
34775     0/imm32/left:unused
34776     0/imm32/right:null
34777     0/imm32/right:null
34778 
34779 Type-byte:  # (payload type-tree)
34780     0x11/imm32/alloc-id:fake:payload
34781     1/imm32/is-atom
34782     8/imm32/value:byte
34783     0/imm32/left:unused
34784     0/imm32/right:null
34785     0/imm32/right:null
34786 
34787 Type-float:  # (payload type-tree)
34788     0x11/imm32/alloc-id:fake:payload
34789     1/imm32/is-atom
34790     0xf/imm32/value:float
34791     0/imm32/left:unused
34792     0/imm32/right:null
34793     0/imm32/right:null
34794 
34795 == code
34796 emit-subx-primitive:  # out: (addr buffered-file), stmt: (addr stmt), primitive: (addr primitive), err: (addr buffered-file), ed: (addr exit-descriptor)
34797     # . prologue
34798     55/push-ebp
34799     89/<- %ebp 4/r32/esp
34800     # . save registers
34801     50/push-eax
34802     51/push-ecx
34803     # ecx = primitive
34804     8b/-> *(ebp+0x10) 1/r32/ecx
34805     # emit primitive name
34806     (emit-indent *(ebp+8) *Curr-block-depth)
34807     (lookup *(ecx+0x18) *(ecx+0x1c))  # Primitive-subx-name Primitive-subx-name => eax
34808     (write-buffered *(ebp+8) %eax)
34809     # emit rm32 if necessary
34810     (emit-subx-rm32 *(ebp+8) *(ecx+0x20) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-rm32
34811     # emit xm32 if necessary
34812     (emit-subx-rm32 *(ebp+8) *(ecx+0x34) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-xm32
34813     # emit r32 if necessary
34814     (emit-subx-r32 *(ebp+8) *(ecx+0x24) *(ebp+0xc))  # Primitive-subx-r32
34815     # emit x32 if necessary
34816     (emit-subx-x32 *(ebp+8) *(ecx+0x38) *(ebp+0xc))  # Primitive-subx-x32
34817     # emit imm32 if necessary
34818     (emit-subx-imm32 *(ebp+8) *(ecx+0x28) *(ebp+0xc))  # Primitive-subx-imm32
34819     # emit imm8 if necessary
34820     (emit-subx-imm8 *(ebp+8) *(ecx+0x2c) *(ebp+0xc))  # Primitive-subx-imm8
34821     # emit disp32 if necessary
34822     (emit-subx-disp32 *(ebp+8) *(ecx+0x30) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-disp32
34823     (write-buffered *(ebp+8) Newline)
34824 $emit-subx-primitive:end:
34825     # . restore registers
34826     59/pop-to-ecx
34827     58/pop-to-eax
34828     # . epilogue
34829     89/<- %esp 5/r32/ebp
34830     5d/pop-to-ebp
34831     c3/return
34832 
34833 emit-subx-rm32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
34834     # . prologue
34835     55/push-ebp
34836     89/<- %ebp 4/r32/esp
34837     # . save registers
34838     50/push-eax
34839     # if (l == 0) return
34840     81 7/subop/compare *(ebp+0xc) 0/imm32
34841     74/jump-if-= $emit-subx-rm32:end/disp8
34842     # var v/eax: (addr stmt-var)
34843     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # => eax
34844     (emit-subx-var-as-rm32 *(ebp+8) %eax)
34845 $emit-subx-rm32:end:
34846     # . restore registers
34847     58/pop-to-eax
34848     # . epilogue
34849     89/<- %esp 5/r32/ebp
34850     5d/pop-to-ebp
34851     c3/return
34852 
34853 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)
34854     # . prologue
34855     55/push-ebp
34856     89/<- %ebp 4/r32/esp
34857     # . save registers
34858     51/push-ecx
34859     # eax = l
34860     8b/-> *(ebp+0xc) 0/r32/eax
34861     # ecx = stmt
34862     8b/-> *(ebp+8) 1/r32/ecx
34863     # if (l == 1) return stmt->inouts
34864     {
34865       3d/compare-eax-and 1/imm32
34866       75/jump-if-!= break/disp8
34867 $get-stmt-operand-from-arg-location:1:
34868       (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
34869       eb/jump $get-stmt-operand-from-arg-location:end/disp8
34870     }
34871     # if (l == 2) return stmt->inouts->next
34872     {
34873       3d/compare-eax-and 2/imm32
34874       75/jump-if-!= break/disp8
34875 $get-stmt-operand-from-arg-location:2:
34876       (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
34877       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
34878       eb/jump $get-stmt-operand-from-arg-location:end/disp8
34879     }
34880     # if (l == 3) return stmt->outputs
34881     {
34882       3d/compare-eax-and 3/imm32
34883       75/jump-if-!= break/disp8
34884 $get-stmt-operand-from-arg-location:3:
34885       (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
34886       eb/jump $get-stmt-operand-from-arg-location:end/disp8
34887     }
34888     # abort
34889     e9/jump $get-stmt-operand-from-arg-location:abort/disp32
34890 $get-stmt-operand-from-arg-location:end:
34891     # . restore registers
34892     59/pop-to-ecx
34893     # . epilogue
34894     89/<- %esp 5/r32/ebp
34895     5d/pop-to-ebp
34896     c3/return
34897 
34898 $get-stmt-operand-from-arg-location:abort:
34899     # error("invalid arg-location " eax)
34900     (write-buffered *(ebp+0x10) "invalid arg-location ")
34901     (write-int32-hex-buffered *(ebp+0x10) %eax)
34902     (write-buffered *(ebp+0x10) Newline)
34903     (flush *(ebp+0x10))
34904     (stop *(ebp+0x14) 1)
34905     # never gets here
34906 
34907 emit-subx-r32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
34908     # . prologue
34909     55/push-ebp
34910     89/<- %ebp 4/r32/esp
34911     # . save registers
34912     50/push-eax
34913     51/push-ecx
34914     # if (l == 0) return
34915     81 7/subop/compare *(ebp+0xc) 0/imm32
34916     0f 84/jump-if-= $emit-subx-r32:end/disp32
34917     # var v/eax: (addr stmt-var)
34918     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
34919     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
34920     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
34921 #?     (write-buffered Stderr "looking up ")
34922 #?     (write-buffered Stderr %eax)
34923 #?     (write-buffered Stderr Newline)
34924 #?     (flush Stderr)
34925     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
34926     (write-buffered *(ebp+8) Space)
34927     (write-int32-hex-buffered *(ebp+8) *eax)
34928     (write-buffered *(ebp+8) "/r32")
34929 $emit-subx-r32:end:
34930     # . restore registers
34931     59/pop-to-ecx
34932     58/pop-to-eax
34933     # . epilogue
34934     89/<- %esp 5/r32/ebp
34935     5d/pop-to-ebp
34936     c3/return
34937 
34938 emit-subx-x32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
34939     # . prologue
34940     55/push-ebp
34941     89/<- %ebp 4/r32/esp
34942     # . save registers
34943     50/push-eax
34944     51/push-ecx
34945     # if (l == 0) return
34946     81 7/subop/compare *(ebp+0xc) 0/imm32
34947     0f 84/jump-if-= $emit-subx-x32:end/disp32
34948     # var v/eax: (addr stmt-var)
34949     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
34950     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
34951     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
34952 #?     (write-buffered Stderr "looking up ")
34953 #?     (write-buffered Stderr %eax)
34954 #?     (write-buffered Stderr Newline)
34955 #?     (flush Stderr)
34956     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
34957     (write-buffered *(ebp+8) Space)
34958     (write-int32-hex-buffered *(ebp+8) *eax)
34959     (write-buffered *(ebp+8) "/x32")
34960 $emit-subx-x32:end:
34961     # . restore registers
34962     59/pop-to-ecx
34963     58/pop-to-eax
34964     # . epilogue
34965     89/<- %esp 5/r32/ebp
34966     5d/pop-to-ebp
34967     c3/return
34968 
34969 emit-subx-imm32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
34970     # . prologue
34971     55/push-ebp
34972     89/<- %ebp 4/r32/esp
34973     # . save registers
34974     50/push-eax
34975     51/push-ecx
34976     # if (l == 0) return
34977     81 7/subop/compare *(ebp+0xc) 0/imm32
34978     0f 84/jump-if-= $emit-subx-imm32:end/disp32
34979     # var v/eax: (handle var)
34980     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
34981     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
34982     (lookup *eax *(eax+4))  # Var-name Var-name => eax
34983     (write-buffered *(ebp+8) Space)
34984     (write-buffered *(ebp+8) %eax)
34985     (write-buffered *(ebp+8) "/imm32")
34986 $emit-subx-imm32:end:
34987     # . restore registers
34988     59/pop-to-ecx
34989     58/pop-to-eax
34990     # . epilogue
34991     89/<- %esp 5/r32/ebp
34992     5d/pop-to-ebp
34993     c3/return
34994 
34995 emit-subx-imm8:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
34996     # . prologue
34997     55/push-ebp
34998     89/<- %ebp 4/r32/esp
34999     # . save registers
35000     50/push-eax
35001     51/push-ecx
35002     # if (l == 0) return
35003     81 7/subop/compare *(ebp+0xc) 0/imm32
35004     0f 84/jump-if-= $emit-subx-imm32:end/disp32
35005     # var v/eax: (handle var)
35006     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
35007     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
35008     (lookup *eax *(eax+4))  # Var-name Var-name => eax
35009     (write-buffered *(ebp+8) Space)
35010     (write-buffered *(ebp+8) %eax)
35011     (write-buffered *(ebp+8) "/imm8")
35012 $emit-subx-imm8:end:
35013     # . restore registers
35014     59/pop-to-ecx
35015     58/pop-to-eax
35016     # . epilogue
35017     89/<- %esp 5/r32/ebp
35018     5d/pop-to-ebp
35019     c3/return
35020 
35021 emit-subx-disp32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
35022     # . prologue
35023     55/push-ebp
35024     89/<- %ebp 4/r32/esp
35025     # . save registers
35026     50/push-eax
35027     51/push-ecx
35028     # if (location == 0) return
35029     81 7/subop/compare *(ebp+0xc) 0/imm32
35030     0f 84/jump-if-= $emit-subx-disp32:end/disp32
35031     # var v/eax: (addr stmt-var)
35032     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # => eax
35033     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
35034     (lookup *eax *(eax+4))  # Var-name Var-name => eax
35035     (write-buffered *(ebp+8) Space)
35036     (write-buffered *(ebp+8) %eax)
35037     # hack: if instruction operation starts with "break", emit ":break"
35038     # var name/ecx: (addr array byte) = lookup(stmt->operation)
35039     8b/-> *(ebp+0x10) 0/r32/eax
35040     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
35041     89/<- %ecx 0/r32/eax
35042     {
35043       (string-starts-with? %ecx "break")  # => eax
35044       3d/compare-eax-and 0/imm32/false
35045       74/jump-if-= break/disp8
35046       (write-buffered *(ebp+8) ":break")
35047     }
35048     # hack: if instruction operation starts with "loop", emit ":loop"
35049     {
35050       (string-starts-with? %ecx "loop")  # => eax
35051       3d/compare-eax-and 0/imm32/false
35052       74/jump-if-= break/disp8
35053       (write-buffered *(ebp+8) ":loop")
35054     }
35055     (write-buffered *(ebp+8) "/disp32")
35056 $emit-subx-disp32:end:
35057     # . restore registers
35058     59/pop-to-ecx
35059     58/pop-to-eax
35060     # . epilogue
35061     89/<- %esp 5/r32/ebp
35062     5d/pop-to-ebp
35063     c3/return
35064 
35065 emit-call:  # out: (addr buffered-file), stmt: (addr stmt)
35066     # . prologue
35067     55/push-ebp
35068     89/<- %ebp 4/r32/esp
35069     # . save registers
35070     50/push-eax
35071     51/push-ecx
35072     #
35073     (emit-indent *(ebp+8) *Curr-block-depth)
35074     (write-buffered *(ebp+8) "(")
35075     # ecx = stmt
35076     8b/-> *(ebp+0xc) 1/r32/ecx
35077     # - emit function name
35078     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
35079     (write-buffered *(ebp+8) %eax)
35080     # - emit arguments
35081     # var curr/eax: (addr stmt-var) = lookup(stmt->inouts)
35082     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
35083     {
35084       # if (curr == null) break
35085       3d/compare-eax-and 0/imm32
35086       74/jump-if-= break/disp8
35087       #
35088       (emit-subx-call-operand *(ebp+8) %eax)
35089       # curr = lookup(curr->next)
35090       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
35091       eb/jump loop/disp8
35092     }
35093     #
35094     (write-buffered *(ebp+8) ")\n")
35095 $emit-call:end:
35096     # . restore registers
35097     59/pop-to-ecx
35098     58/pop-to-eax
35099     # . epilogue
35100     89/<- %esp 5/r32/ebp
35101     5d/pop-to-ebp
35102     c3/return
35103 
35104 emit-subx-call-operand:  # out: (addr buffered-file), s: (addr stmt-var)
35105     # shares code with emit-subx-var-as-rm32
35106     # . prologue
35107     55/push-ebp
35108     89/<- %ebp 4/r32/esp
35109     # . save registers
35110     50/push-eax
35111     51/push-ecx
35112     56/push-esi
35113     # ecx = s
35114     8b/-> *(ebp+0xc) 1/r32/ecx
35115     # var operand/esi: (addr var) = lookup(s->value)
35116     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
35117     89/<- %esi 0/r32/eax
35118     # if (operand->register && !s->is-deref?) emit "%__"
35119     {
35120 $emit-subx-call-operand:check-for-register-direct:
35121       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
35122       74/jump-if-= break/disp8
35123       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
35124       75/jump-if-!= break/disp8
35125 $emit-subx-call-operand:register-direct:
35126       (write-buffered *(ebp+8) " %")
35127       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
35128       (write-buffered *(ebp+8) %eax)
35129       e9/jump $emit-subx-call-operand:end/disp32
35130     }
35131     # else if (operand->register && s->is-deref?) emit "*__"
35132     {
35133 $emit-subx-call-operand:check-for-register-indirect:
35134       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
35135       74/jump-if-= break/disp8
35136       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
35137       74/jump-if-= break/disp8
35138 $emit-subx-call-operand:register-indirect:
35139       (emit-subx-call-operand-register-indirect *(ebp+8) %esi)
35140       e9/jump $emit-subx-call-operand:end/disp32
35141     }
35142     # else if (operand->stack-offset) emit "*(ebp+__)"
35143     {
35144       81 7/subop/compare *(esi+0x14) 0/imm32  # Var-offset
35145       74/jump-if-= break/disp8
35146 $emit-subx-call-operand:stack:
35147       (emit-subx-call-operand-stack *(ebp+8) %esi)
35148       e9/jump $emit-subx-call-operand:end/disp32
35149     }
35150     # else if (operand->type == literal) emit "__"
35151     {
35152       (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
35153       81 7/subop/compare *(eax+4) 0/imm32  # Type-tree-value
35154       75/jump-if-!= break/disp8
35155 $emit-subx-call-operand:literal:
35156       (write-buffered *(ebp+8) Space)
35157       (lookup *esi *(esi+4))  # Var-name Var-name => eax
35158       (write-buffered *(ebp+8) %eax)
35159       e9/jump $emit-subx-call-operand:end/disp32
35160     }
35161     # else if (operand->type == literal-string) emit "__"
35162     {
35163       (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
35164       81 7/subop/compare *(eax+4) 0x10/imm32  # Type-tree-value
35165       75/jump-if-!= break/disp8
35166 $emit-subx-call-operand:literal-string:
35167       (write-buffered *(ebp+8) Space)
35168       (lookup *esi *(esi+4))  # Var-name Var-name => eax
35169       (write-buffered *(ebp+8) %eax)
35170     }
35171 $emit-subx-call-operand:end:
35172     # . restore registers
35173     5e/pop-to-esi
35174     59/pop-to-ecx
35175     58/pop-to-eax
35176     # . epilogue
35177     89/<- %esp 5/r32/ebp
35178     5d/pop-to-ebp
35179     c3/return
35180 
35181 emit-subx-call-operand-register-indirect:  # out: (addr buffered-file), v: (addr var)
35182     # . prologue
35183     55/push-ebp
35184     89/<- %ebp 4/r32/esp
35185     # . save registers
35186     50/push-eax
35187     51/push-ecx
35188     56/push-esi
35189     # esi = v
35190     8b/-> *(ebp+0xc) 6/r32/esi
35191     # var size/ecx: int = size-of-deref(v)
35192     (size-of-deref %esi)  # => eax
35193     89/<- %ecx 0/r32/eax
35194     # var reg-name/esi: (addr array byte) = lookup(v->register)
35195     (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
35196     89/<- %esi 0/r32/eax
35197     # TODO: assert size is a multiple of 4
35198     # var i/eax: int = 0
35199     b8/copy-to-eax 0/imm32
35200     {
35201 $emit-subx-call-operand-register-indirect:loop:
35202       # if (i >= size) break
35203       39/compare %eax 1/r32/ecx
35204       7d/jump-if->= break/disp8
35205       # emit " *(" v->register "+" i ")"
35206       (write-buffered *(ebp+8) " *(")
35207       (write-buffered *(ebp+8) %esi)
35208       (write-buffered *(ebp+8) "+")
35209       (write-int32-hex-buffered *(ebp+8) %eax)
35210       (write-buffered *(ebp+8) ")")
35211       # i += 4
35212       05/add-to-eax 4/imm32
35213       #
35214       eb/jump loop/disp8
35215     }
35216 $emit-subx-call-operand-register-indirect:end:
35217     # . restore registers
35218     5e/pop-to-esi
35219     59/pop-to-ecx
35220     58/pop-to-eax
35221     # . epilogue
35222     89/<- %esp 5/r32/ebp
35223     5d/pop-to-ebp
35224     c3/return
35225 
35226 emit-subx-call-operand-stack:  # out: (addr buffered-file), v: (addr var)
35227     # . prologue
35228     55/push-ebp
35229     89/<- %ebp 4/r32/esp
35230     # . save registers
35231     50/push-eax
35232     51/push-ecx
35233     56/push-esi
35234     # esi = v
35235     8b/-> *(ebp+0xc) 6/r32/esi
35236     # var curr/ecx: int = v->offset
35237     8b/-> *(esi+0x14) 1/r32/ecx  # Var-offset
35238     # var max/eax: int = v->offset + size-of(v)
35239     (size-of %esi)  # => eax
35240     # TODO: assert size is a multiple of 4
35241     01/add-to %eax 1/r32/ecx
35242     {
35243 $emit-subx-call-operand-stack:loop:
35244       # if (curr >= max) break
35245       39/compare %ecx 0/r32/eax
35246       7d/jump-if->= break/disp8
35247       # emit " *(ebp+" curr ")"
35248       (write-buffered *(ebp+8) " *(ebp+")
35249       (write-int32-hex-buffered *(ebp+8) %ecx)
35250       (write-buffered *(ebp+8) ")")
35251       # i += 4
35252       81 0/subop/add %ecx 4/imm32
35253       #
35254       eb/jump loop/disp8
35255     }
35256 $emit-subx-call-operand-stack:end:
35257     # . restore registers
35258     5e/pop-to-esi
35259     59/pop-to-ecx
35260     58/pop-to-eax
35261     # . epilogue
35262     89/<- %esp 5/r32/ebp
35263     5d/pop-to-ebp
35264     c3/return
35265 
35266 emit-subx-var-as-rm32:  # out: (addr buffered-file), s: (addr stmt-var)
35267     # . prologue
35268     55/push-ebp
35269     89/<- %ebp 4/r32/esp
35270     # . save registers
35271     50/push-eax
35272     51/push-ecx
35273     56/push-esi
35274     # ecx = s
35275     8b/-> *(ebp+0xc) 1/r32/ecx
35276     # var operand/esi: (addr var) = lookup(s->value)
35277     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
35278     89/<- %esi 0/r32/eax
35279     # if (operand->register && s->is-deref?) emit "*__"
35280     {
35281 $emit-subx-var-as-rm32:check-for-register-indirect:
35282       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
35283       74/jump-if-= break/disp8
35284       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
35285       74/jump-if-= break/disp8
35286 $emit-subx-var-as-rm32:register-indirect:
35287       (write-buffered *(ebp+8) " *")
35288       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
35289       (write-buffered *(ebp+8) %eax)
35290       e9/jump $emit-subx-var-as-rm32:end/disp32
35291     }
35292     # if (operand->register && !s->is-deref?) emit "%__"
35293     {
35294 $emit-subx-var-as-rm32:check-for-register-direct:
35295       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
35296       74/jump-if-= break/disp8
35297       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
35298       75/jump-if-!= break/disp8
35299 $emit-subx-var-as-rm32:register-direct:
35300       (write-buffered *(ebp+8) " %")
35301       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
35302       (write-buffered *(ebp+8) %eax)
35303       e9/jump $emit-subx-var-as-rm32:end/disp32
35304     }
35305     # else if (operand->stack-offset) emit "*(ebp+__)"
35306     {
35307       81 7/subop/compare *(esi+0x14) 0/imm32  # Var-offset
35308       74/jump-if-= break/disp8
35309 $emit-subx-var-as-rm32:stack:
35310       (write-buffered *(ebp+8) Space)
35311       (write-buffered *(ebp+8) "*(ebp+")
35312       (write-int32-hex-buffered *(ebp+8) *(esi+0x14))  # Var-offset
35313       (write-buffered *(ebp+8) ")")
35314     }
35315 $emit-subx-var-as-rm32:end:
35316     # . restore registers
35317     5e/pop-to-esi
35318     59/pop-to-ecx
35319     58/pop-to-eax
35320     # . epilogue
35321     89/<- %esp 5/r32/ebp
35322     5d/pop-to-ebp
35323     c3/return
35324 
35325 find-matching-primitive:  # primitives: (addr primitive), stmt: (addr stmt) -> result/eax: (addr primitive)
35326     # . prologue
35327     55/push-ebp
35328     89/<- %ebp 4/r32/esp
35329     # . save registers
35330     51/push-ecx
35331     # var curr/ecx: (addr primitive) = primitives
35332     8b/-> *(ebp+8) 1/r32/ecx
35333     {
35334 $find-matching-primitive:loop:
35335       # if (curr == null) break
35336       81 7/subop/compare %ecx 0/imm32
35337       74/jump-if-= break/disp8
35338       # if match(curr, stmt) return curr
35339       {
35340         (mu-stmt-matches-primitive? *(ebp+0xc) %ecx)  # => eax
35341         3d/compare-eax-and 0/imm32/false
35342         74/jump-if-= break/disp8
35343         89/<- %eax 1/r32/ecx
35344         eb/jump $find-matching-primitive:end/disp8
35345       }
35346 $find-matching-primitive:next-primitive:
35347       # curr = curr->next
35348       (lookup *(ecx+0x3c) *(ecx+0x40))  # Primitive-next Primitive-next => eax
35349       89/<- %ecx 0/r32/eax
35350       #
35351       e9/jump loop/disp32
35352     }
35353     # return null
35354     b8/copy-to-eax 0/imm32
35355 $find-matching-primitive:end:
35356     # . restore registers
35357     59/pop-to-ecx
35358     # . epilogue
35359     89/<- %esp 5/r32/ebp
35360     5d/pop-to-ebp
35361     c3/return
35362 
35363 mu-stmt-matches-primitive?:  # stmt: (addr stmt), primitive: (addr primitive) -> result/eax: boolean
35364     # A mu stmt matches a primitive if the name matches, all the inout vars
35365     # match, and all the output vars match.
35366     # Vars match if types match and registers match.
35367     # In addition, a stmt output matches a primitive's output if types match
35368     # and the primitive has a wildcard register.
35369     # . prologue
35370     55/push-ebp
35371     89/<- %ebp 4/r32/esp
35372     # . save registers
35373     51/push-ecx
35374     52/push-edx
35375     53/push-ebx
35376     56/push-esi
35377     57/push-edi
35378     # ecx = stmt
35379     8b/-> *(ebp+8) 1/r32/ecx
35380     # edx = primitive
35381     8b/-> *(ebp+0xc) 2/r32/edx
35382     {
35383 $mu-stmt-matches-primitive?:check-name:
35384       # if (primitive->name != stmt->operation) return false
35385       # . var esi: (addr array byte) = lookup(stmt->operation)
35386       (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
35387       89/<- %esi 0/r32/eax
35388       # . var edi: (addr array byte) = lookup(primitive->name)
35389       (lookup *edx *(edx+4))  # Primitive-name Primitive-name => eax
35390 #?       (write-buffered Stderr %eax)
35391 #?       (write-buffered Stderr Newline)
35392 #?       (flush Stderr)
35393       89/<- %edi 0/r32/eax
35394       (string-equal? %esi %edi)  # => eax
35395       3d/compare-eax-and 0/imm32/false
35396       75/jump-if-!= break/disp8
35397       b8/copy-to-eax 0/imm32
35398       e9/jump $mu-stmt-matches-primitive?:end/disp32
35399     }
35400     # var curr/esi: (addr stmt-var) = lookup(stmt->inouts)
35401     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
35402     89/<- %esi 0/r32/eax
35403     # var curr2/edi: (addr list var) = lookup(primitive->inouts)
35404     (lookup *(edx+8) *(edx+0xc))  # Primitive-inouts Primitive-inouts => eax
35405     89/<- %edi 0/r32/eax
35406     {
35407 $mu-stmt-matches-primitive?:inouts-loop:
35408       # if (curr == 0 && curr2 == 0) move on to check outputs
35409       {
35410 $mu-stmt-matches-primitive?:check-both-inouts-null:
35411         81 7/subop/compare %esi 0/imm32
35412         75/jump-if-!= break/disp8
35413 $mu-stmt-matches-primitive?:stmt-inout-null:
35414         81 7/subop/compare %edi 0/imm32
35415         0f 84/jump-if-= $mu-stmt-matches-primitive?:check-outputs/disp32
35416 $mu-stmt-matches-primitive?:stmt-inout-null-and-prim-inout-not-null:
35417         # return false
35418         b8/copy-to-eax 0/imm32/false
35419         e9/jump $mu-stmt-matches-primitive?:end/disp32
35420       }
35421       # if (curr2 == 0) return false
35422       {
35423 $mu-stmt-matches-primitive?:check-prim-inout-null:
35424         81 7/subop/compare %edi 0/imm32
35425         75/jump-if-!= break/disp8
35426 $mu-stmt-matches-primitive?:prim-inout-null:
35427         b8/copy-to-eax 0/imm32/false
35428         e9/jump $mu-stmt-matches-primitive?:end/disp32
35429       }
35430       # if (curr != curr2) return false
35431       {
35432 $mu-stmt-matches-primitive?:check-inouts-match:
35433         (lookup *edi *(edi+4))  # List-value List-value => eax
35434         (operand-matches-primitive? %esi %eax)  # => eax
35435         3d/compare-eax-and 0/imm32/false
35436         75/jump-if-!= break/disp8
35437 $mu-stmt-matches-primitive?:inouts-match:
35438         b8/copy-to-eax 0/imm32/false
35439         e9/jump $mu-stmt-matches-primitive?:end/disp32
35440       }
35441 $mu-stmt-matches-primitive?:next-inout:
35442       # curr = lookup(curr->next)
35443       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
35444       89/<- %esi 0/r32/eax
35445       # curr2 = lookup(curr2->next)
35446       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
35447       89/<- %edi 0/r32/eax
35448       #
35449       e9/jump loop/disp32
35450     }
35451 $mu-stmt-matches-primitive?:check-outputs:
35452     # var curr/esi: (addr stmt-var) = lookup(stmt->outputs)
35453     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
35454     89/<- %esi 0/r32/eax
35455     # var curr2/edi: (addr list var) = lookup(primitive->outputs)
35456     (lookup *(edx+0x10) *(edx+0x14))  # Primitive-outputs Primitive-outputs => eax
35457     89/<- %edi 0/r32/eax
35458     {
35459 $mu-stmt-matches-primitive?:outputs-loop:
35460       # if (curr == 0) return (curr2 == 0)
35461       {
35462 $mu-stmt-matches-primitive?:check-both-outputs-null:
35463         81 7/subop/compare %esi 0/imm32
35464         75/jump-if-!= break/disp8
35465         {
35466 $mu-stmt-matches-primitive?:stmt-output-null:
35467           81 7/subop/compare %edi 0/imm32
35468           75/jump-if-!= break/disp8
35469 $mu-stmt-matches-primitive?:both-outputs-null:
35470           # return true
35471           b8/copy-to-eax 1/imm32
35472           e9/jump $mu-stmt-matches-primitive?:end/disp32
35473         }
35474 $mu-stmt-matches-primitive?:stmt-output-null-and-prim-output-not-null:
35475         # return false
35476         b8/copy-to-eax 0/imm32
35477         e9/jump $mu-stmt-matches-primitive?:end/disp32
35478       }
35479       # if (curr2 == 0) return false
35480       {
35481 $mu-stmt-matches-primitive?:check-prim-output-null:
35482         81 7/subop/compare %edi 0/imm32
35483         75/jump-if-!= break/disp8
35484 $mu-stmt-matches-primitive?:prim-output-is-null:
35485         b8/copy-to-eax 0/imm32
35486         e9/jump $mu-stmt-matches-primitive?:end/disp32
35487       }
35488       # if (curr != curr2) return false
35489       {
35490 $mu-stmt-matches-primitive?:check-outputs-match:
35491         (lookup *edi *(edi+4))  # List-value List-value => eax
35492         (operand-matches-primitive? %esi %eax)  # => eax
35493         3d/compare-eax-and 0/imm32/false
35494         75/jump-if-!= break/disp8
35495 $mu-stmt-matches-primitive?:outputs-match:
35496         b8/copy-to-eax 0/imm32
35497         e9/jump $mu-stmt-matches-primitive?:end/disp32
35498       }
35499 $mu-stmt-matches-primitive?:next-output:
35500       # curr = lookup(curr->next)
35501       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
35502       89/<- %esi 0/r32/eax
35503       # curr2 = lookup(curr2->next)
35504       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
35505       89/<- %edi 0/r32/eax
35506       #
35507       e9/jump loop/disp32
35508     }
35509 $mu-stmt-matches-primitive?:return-true:
35510     b8/copy-to-eax 1/imm32
35511 $mu-stmt-matches-primitive?:end:
35512     # . restore registers
35513     5f/pop-to-edi
35514     5e/pop-to-esi
35515     5b/pop-to-ebx
35516     5a/pop-to-edx
35517     59/pop-to-ecx
35518     # . epilogue
35519     89/<- %esp 5/r32/ebp
35520     5d/pop-to-ebp
35521     c3/return
35522 
35523 operand-matches-primitive?:  # s: (addr stmt-var), prim-var: (addr var) -> result/eax: boolean
35524     # . prologue
35525     55/push-ebp
35526     89/<- %ebp 4/r32/esp
35527     # . save registers
35528     51/push-ecx
35529     52/push-edx
35530     53/push-ebx
35531     56/push-esi
35532     57/push-edi
35533     # ecx = s
35534     8b/-> *(ebp+8) 1/r32/ecx
35535     # var var/esi: (addr var) = lookup(s->value)
35536     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
35537     89/<- %esi 0/r32/eax
35538     # edi = prim-var
35539     8b/-> *(ebp+0xc) 7/r32/edi
35540 $operand-matches-primitive?:check-type:
35541     # if !category-match?(var->type, prim-var->type) return false
35542     # . var vtype/ebx: (addr type-tree) = lookup(var->type)
35543     (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
35544     89/<- %ebx 0/r32/eax
35545     # . if s is deref, vtype = vtype->right
35546     {
35547       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
35548       74/jump-if-= break/disp8
35549 $operand-matches-primitive?:is-deref:
35550       # . var t/eax: (addr type)
35551       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
35552       # . if !t->is-atom? t = t->left
35553       81 7/subop/compare *eax 0/imm32/false
35554       {
35555         75/jump-if-!= break/disp8
35556         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
35557       }
35558       # .
35559       89/<- %ebx 0/r32/eax
35560     }
35561     # . var ptype/eax: (addr type-tree) = lookup(prim-var->type)
35562     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
35563     (subx-type-category-match? %ebx %eax)  # => eax
35564     3d/compare-eax-and 0/imm32/false
35565     0f 84/jump-if-= $operand-matches-primitive?:return-false/disp32
35566     {
35567 $operand-matches-primitive?:check-register:
35568       # if prim-var is in memory and var is in register but dereference, match
35569       {
35570         81 7/subop/compare *(edi+0x18) 0/imm32  # Var-register
35571         0f 85/jump-if-!= break/disp32
35572         81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
35573         74/jump-if-= break/disp8
35574         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
35575         74/jump-if-= break/disp8
35576 $operand-matches-primitive?:var-deref-match:
35577         e9/jump $operand-matches-primitive?:return-true/disp32
35578       }
35579       # if prim-var is in register and var is in register but dereference, no match
35580       {
35581         81 7/subop/compare *(edi+0x18) 0/imm32  # Var-register
35582         0f 84/jump-if-= break/disp32
35583         81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
35584         0f 84/jump-if-= break/disp32
35585         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
35586         74/jump-if-= break/disp8
35587 $operand-matches-primitive?:var-deref-no-match:
35588         e9/jump $operand-matches-primitive?:return-false/disp32
35589       }
35590       # return false if var->register doesn't match prim-var->register
35591       {
35592         # if register addresses are equal, it's a match
35593         # var vreg/ebx: (addr array byte) = lookup(var->register)
35594         (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
35595         89/<- %ebx 0/r32/eax
35596         # var preg/ecx: (addr array byte) = lookup(prim-var->register)
35597         (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
35598         89/<- %ecx 0/r32/eax
35599         # if (vreg == preg) break
35600         39/compare %ecx 3/r32/ebx
35601         74/jump-if-= break/disp8
35602 $operand-matches-primitive?:var-register-no-match:
35603         # if either address is 0, return false
35604         81 7/subop/compare %ebx 0/imm32
35605         74/jump-if-=  $operand-matches-primitive?:return-false/disp8
35606         81 7/subop/compare %ecx 0/imm32
35607         74/jump-if-=  $operand-matches-primitive?:return-false/disp8
35608         # if prim-var->register is wildcard, it's a match
35609         (string-equal? %ecx "*")  # Any-register => eax
35610         3d/compare-eax-and 0/imm32/false
35611         75/jump-if-!= break/disp8
35612 $operand-matches-primitive?:wildcard-no-match:
35613         # if string contents aren't equal, return false
35614         (string-equal? %ecx %ebx)  # => eax
35615         3d/compare-eax-and 0/imm32/false
35616         74/jump-if-= $operand-matches-primitive?:return-false/disp8
35617       }
35618     }
35619 $operand-matches-primitive?:return-true:
35620     b8/copy-to-eax 1/imm32/true
35621     eb/jump $operand-matches-primitive?:end/disp8
35622 $operand-matches-primitive?:return-false:
35623     b8/copy-to-eax 0/imm32/false
35624 $operand-matches-primitive?:end:
35625     # . restore registers
35626     5f/pop-to-edi
35627     5e/pop-to-esi
35628     5b/pop-to-ebx
35629     5a/pop-to-edx
35630     59/pop-to-ecx
35631     # . epilogue
35632     89/<- %esp 5/r32/ebp
35633     5d/pop-to-ebp
35634     c3/return
35635 
35636 find-matching-function:  # functions: (addr function), stmt: (addr stmt) -> result/eax: (addr function)
35637     # . prologue
35638     55/push-ebp
35639     89/<- %ebp 4/r32/esp
35640     # . save registers
35641     51/push-ecx
35642     # var curr/ecx: (handle function) = functions
35643     8b/-> *(ebp+8) 1/r32/ecx
35644     {
35645       # if (curr == null) break
35646       81 7/subop/compare %ecx 0/imm32
35647       74/jump-if-= break/disp8
35648 #?       (write-buffered Stderr "iter\n")
35649 #?       (flush Stderr)
35650       # if match(stmt, curr) return curr
35651       {
35652         (mu-stmt-matches-function? *(ebp+0xc) %ecx)  # => eax
35653         3d/compare-eax-and 0/imm32/false
35654         74/jump-if-= break/disp8
35655         89/<- %eax 1/r32/ecx
35656         eb/jump $find-matching-function:end/disp8
35657       }
35658       # curr = curr->next
35659       (lookup *(ecx+0x20) *(ecx+0x24))  # Function-next Function-next => eax
35660       89/<- %ecx 0/r32/eax
35661       #
35662       eb/jump loop/disp8
35663     }
35664     # return null
35665     b8/copy-to-eax 0/imm32
35666 $find-matching-function:end:
35667     # . restore registers
35668     59/pop-to-ecx
35669     # . epilogue
35670     89/<- %esp 5/r32/ebp
35671     5d/pop-to-ebp
35672     c3/return
35673 
35674 # Just compare names; user-defined functions don't support overloading yet.
35675 mu-stmt-matches-function?:  # stmt: (addr stmt1), function: (addr function) -> result/eax: boolean
35676     # . prologue
35677     55/push-ebp
35678     89/<- %ebp 4/r32/esp
35679     # . save registers
35680     51/push-ecx
35681     # return function->name == stmt->operation
35682     # ecx = lookup(stmt->operation)
35683     8b/-> *(ebp+8) 0/r32/eax
35684     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
35685     89/<- %ecx 0/r32/eax
35686     # eax = lookup(function->name)
35687     8b/-> *(ebp+0xc) 0/r32/eax
35688     (lookup *eax *(eax+4))  # Function-name Function-name => eax
35689     (string-equal? %eax %ecx)  # => eax
35690 $mu-stmt-matches-function?:end:
35691     # . restore registers
35692     59/pop-to-ecx
35693     # . epilogue
35694     89/<- %esp 5/r32/ebp
35695     5d/pop-to-ebp
35696     c3/return
35697 
35698 # Type-checking happens elsewhere. This method is for selecting between
35699 # primitives.
35700 subx-type-category-match?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
35701     # . prologue
35702     55/push-ebp
35703     89/<- %ebp 4/r32/esp
35704     # . save registers
35705     51/push-ecx
35706     # var cata/ecx: int = type-category(a)
35707     (type-category *(ebp+8))  # => eax
35708     89/<- %ecx 0/r32/eax
35709     # var catb/eax: int = type-category(b)
35710     (type-category *(ebp+0xc))  # => eax
35711     # return cata == catb
35712     39/compare %eax 1/r32/ecx
35713     0f 94/set-byte-if-= %al
35714     81 4/subop/and %eax 0xff/imm32
35715 $subx-type-category-match?:end:
35716     # . restore registers
35717     59/pop-to-ecx
35718     # . epilogue
35719     89/<- %esp 5/r32/ebp
35720     5d/pop-to-ebp
35721     c3/return
35722 
35723 type-category:  # a: (addr type-tree) -> result/eax: int
35724     # . prologue
35725     55/push-ebp
35726     89/<- %ebp 4/r32/esp
35727     # . save registers
35728     51/push-ecx
35729     # var lit?/ecx: boolean = literal-type?(a)
35730     (simple-mu-type? *(ebp+8) 0)  # literal => eax
35731     89/<- %ecx 0/r32/eax
35732     # var float?/eax: int = float?(a)
35733     (simple-mu-type? *(ebp+8) 0xf)  # => eax
35734     # set bits for lit? and float?
35735     c1/shift 4/subop/left %ecx 1/imm8
35736     09/or %eax 1/r32/ecx
35737 $type-category:end:
35738     # . restore registers
35739     59/pop-to-ecx
35740     # . epilogue
35741     89/<- %esp 5/r32/ebp
35742     5d/pop-to-ebp
35743     c3/return
35744 
35745 simple-mu-type?:  # a: (addr type-tree), n: type-id -> result/eax: boolean
35746     # . prologue
35747     55/push-ebp
35748     89/<- %ebp 4/r32/esp
35749     # . save registers
35750     51/push-ecx
35751     # ecx = n
35752     8b/-> *(ebp+0xc) 1/r32/ecx
35753     # return (a->value == n)
35754     8b/-> *(ebp+8) 0/r32/eax
35755     39/compare *(eax+4) 1/r32/ecx  # Type-tree-value
35756     0f 94/set-byte-if-= %al
35757     81 4/subop/and %eax 0xff/imm32
35758 $simple-mu-type?:end:
35759     # . restore registers
35760     59/pop-to-ecx
35761     # . epilogue
35762     89/<- %esp 5/r32/ebp
35763     5d/pop-to-ebp
35764     c3/return
35765 
35766 mu-addr-type?:  # a: (addr type-tree) -> result/eax: boolean
35767     # . prologue
35768     55/push-ebp
35769     89/<- %ebp 4/r32/esp
35770     # eax = a
35771     8b/-> *(ebp+8) 0/r32/eax
35772     # if (!a->is-atom?) a = a->left
35773     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
35774     {
35775       75/jump-if-!= break/disp8
35776       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
35777     }
35778     # return (a->value == addr)
35779     81 7/subop/compare *(eax+4) 2/imm32/addr  # Type-tree-value
35780     0f 94/set-byte-if-= %al
35781     81 4/subop/and %eax 0xff/imm32
35782 $mu-addr-type?:end:
35783     # . epilogue
35784     89/<- %esp 5/r32/ebp
35785     5d/pop-to-ebp
35786     c3/return
35787 
35788 mu-array-type?:  # a: (addr type-tree) -> result/eax: boolean
35789     # . prologue
35790     55/push-ebp
35791     89/<- %ebp 4/r32/esp
35792     # eax = a
35793     8b/-> *(ebp+8) 0/r32/eax
35794     # if (!a->is-atom?) a = a->left
35795     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
35796     {
35797       75/jump-if-!= break/disp8
35798       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
35799     }
35800     # return (a->value == array)
35801     81 7/subop/compare *(eax+4) 3/imm32/array  # Type-tree-value
35802     0f 94/set-byte-if-= %al
35803     81 4/subop/and %eax 0xff/imm32
35804 $mu-array-type?:end:
35805     # . epilogue
35806     89/<- %esp 5/r32/ebp
35807     5d/pop-to-ebp
35808     c3/return
35809 
35810 mu-string-type?:  # a: (addr type-tree) -> result/eax: boolean
35811     # . prologue
35812     55/push-ebp
35813     89/<- %ebp 4/r32/esp
35814     # . save registers
35815     56/push-esi
35816     # esi = a
35817     8b/-> *(ebp+8) 6/r32/esi
35818     # if (a->is-atom?) return false
35819     81 7/subop/compare *esi 0/imm32/false  # Type-tree-is-atom
35820     0f 85/jump-if-!= $mu-string-type?:return-false/disp32
35821     # if a is not an addr, return false
35822     (mu-addr-type? %esi)  # => eax
35823     3d/compare-eax-with 0/imm32/false
35824     0f 84/jump-if-= $mu-string-type?:end/disp32  # eax changes var
35825     # if a is not an array, return false
35826     (lookup *(esi+0xc) *(esi+0x10))  # Type-tree-right Type-tree-right => eax
35827     (mu-array-type? %eax)  # => eax
35828     3d/compare-eax-with 0/imm32/false
35829     74/jump-if-= $mu-string-type?:end/disp8  # eax changes var
35830     # var p/eax: (addr type-tree) = payload of a
35831     (lookup *(esi+0xc) *(esi+0x10))  # Type-tree-right Type-tree-right => eax
35832     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
35833     # if p is an atom, return false
35834     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
35835     75/jump-if-!= $mu-string-type?:return-false/disp8
35836     # return (p == byte)
35837     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
35838     (simple-mu-type? %eax 8)  # byte => eax
35839     eb/jump $mu-string-type?:end/disp8
35840 $mu-string-type?:return-false:
35841     b8/copy-to-eax 0/imm32/false
35842 $mu-string-type?:end:
35843     # . restore registers
35844     5e/pop-to-esi
35845     # . epilogue
35846     89/<- %esp 5/r32/ebp
35847     5d/pop-to-ebp
35848     c3/return
35849 
35850 mu-stream-type?:  # a: (addr type-tree) -> result/eax: boolean
35851     # . prologue
35852     55/push-ebp
35853     89/<- %ebp 4/r32/esp
35854     # eax = a
35855     8b/-> *(ebp+8) 0/r32/eax
35856     # if (!a->is-atom?) a = a->left
35857     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
35858     {
35859       75/jump-if-!= break/disp8
35860       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
35861     }
35862     # return (a->value == stream)
35863     81 7/subop/compare *(eax+4) 0xb/imm32/stream  # Type-tree-value
35864     0f 94/set-byte-if-= %al
35865     81 4/subop/and %eax 0xff/imm32
35866 $mu-stream-type?:end:
35867     # . epilogue
35868     89/<- %esp 5/r32/ebp
35869     5d/pop-to-ebp
35870     c3/return
35871 
35872 test-emit-subx-stmt-primitive:
35873     # Primitive operation on a variable on the stack.
35874     #   increment foo
35875     # =>
35876     #   ff 0/subop/increment *(ebp-8)
35877     #
35878     # There's a variable on the var stack as follows:
35879     #   name: 'foo'
35880     #   type: int
35881     #   stack-offset: -8
35882     #
35883     # There's a primitive with this info:
35884     #   name: 'increment'
35885     #   inouts: int/mem
35886     #   value: 'ff 0/subop/increment'
35887     #
35888     # . prologue
35889     55/push-ebp
35890     89/<- %ebp 4/r32/esp
35891     # setup
35892     (clear-stream _test-output-stream)
35893     (clear-stream $_test-output-buffered-file->buffer)
35894     # simulate allocated payloads starting with an initial fake alloc-id (0x11)
35895 $test-emit-subx-stmt-primitive:initialize-type:
35896     # var type/ecx: (payload type-tree) = int
35897     68/push 0/imm32/right:null
35898     68/push 0/imm32/right:null
35899     68/push 0/imm32/left:unused
35900     68/push 1/imm32/value:int
35901     68/push 1/imm32/is-atom?:true
35902     68/push 0x11/imm32/alloc-id:fake:payload
35903     89/<- %ecx 4/r32/esp
35904 $test-emit-subx-stmt-primitive:initialize-var:
35905     # var var-foo/ecx: (payload var) = var(type)
35906     68/push 0/imm32/no-register
35907     68/push 0/imm32/no-register
35908     68/push -8/imm32/stack-offset
35909     68/push 1/imm32/block-depth
35910     51/push-ecx/type
35911     68/push 0x11/imm32/alloc-id:fake
35912     68/push 0/imm32/name
35913     68/push 0/imm32/name
35914     68/push 0x11/imm32/alloc-id:fake:payload
35915     89/<- %ecx 4/r32/esp
35916 $test-emit-subx-stmt-primitive:initialize-var-name:
35917     # var-foo->name = "foo"
35918     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
35919     (copy-array Heap "foo" %eax)
35920 $test-emit-subx-stmt-primitive:initialize-stmt-var:
35921     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
35922     68/push 0/imm32/is-deref:false
35923     68/push 0/imm32/next
35924     68/push 0/imm32/next
35925     51/push-ecx/var-foo
35926     68/push 0x11/imm32/alloc-id:fake
35927     68/push 0x11/imm32/alloc-id:fake:payload
35928     89/<- %ebx 4/r32/esp
35929 $test-emit-subx-stmt-primitive:initialize-stmt:
35930     # var stmt/esi: (addr statement)
35931     68/push 0/imm32/no-outputs
35932     68/push 0/imm32/no-outputs
35933     53/push-ebx/inouts
35934     68/push 0x11/imm32/alloc-id:fake
35935     68/push 0/imm32/operation
35936     68/push 0/imm32/operation
35937     68/push 1/imm32/tag
35938     89/<- %esi 4/r32/esp
35939 $test-emit-subx-stmt-primitive:initialize-stmt-operation:
35940     # stmt->operation = "increment"
35941     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
35942     (copy-array Heap "increment" %eax)
35943 $test-emit-subx-stmt-primitive:initialize-primitive:
35944     # var primitives/ebx: (addr primitive)
35945     68/push 0/imm32/next
35946     68/push 0/imm32/next
35947     68/push 0/imm32/no-x32
35948     68/push 0/imm32/no-xm32
35949     68/push 0/imm32/no-disp32
35950     68/push 0/imm32/no-imm8
35951     68/push 0/imm32/no-imm32
35952     68/push 0/imm32/no-r32
35953     68/push 1/imm32/rm32-is-first-inout
35954     68/push 0/imm32/subx-name
35955     68/push 0/imm32/subx-name
35956     68/push 0/imm32/no-outputs
35957     68/push 0/imm32/no-outputs
35958     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
35959     68/push 0x11/imm32/alloc-id:fake
35960     68/push 0/imm32/name
35961     68/push 0/imm32/name
35962     89/<- %ebx 4/r32/esp
35963 $test-emit-subx-stmt-primitive:initialize-primitive-name:
35964     # primitives->name = "increment"
35965     (copy-array Heap "increment" %ebx)  # Primitive-name
35966 $test-emit-subx-stmt-primitive:initialize-primitive-subx-name:
35967     # primitives->subx-name = "ff 0/subop/increment"
35968     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
35969     (copy-array Heap "ff 0/subop/increment" %eax)
35970     # convert
35971     c7 0/subop/copy *Curr-block-depth 0/imm32
35972     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
35973     (flush _test-output-buffered-file)
35974 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
35980     # check output
35981     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-stmt-primitive")
35982     # . epilogue
35983     89/<- %esp 5/r32/ebp
35984     5d/pop-to-ebp
35985     c3/return
35986 
35987 test-emit-subx-stmt-primitive-register:
35988     # Primitive operation on a variable in a register.
35989     #   foo <- increment
35990     # =>
35991     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
35992     #
35993     # There's a variable on the var stack as follows:
35994     #   name: 'foo'
35995     #   type: int
35996     #   register: 'eax'
35997     #
35998     # There's a primitive with this info:
35999     #   name: 'increment'
36000     #   out: int/reg
36001     #   value: 'ff 0/subop/increment'
36002     #
36003     # . prologue
36004     55/push-ebp
36005     89/<- %ebp 4/r32/esp
36006     # setup
36007     (clear-stream _test-output-stream)
36008     (clear-stream $_test-output-buffered-file->buffer)
36009 $test-emit-subx-stmt-primitive-register:initialize-type:
36010     # var type/ecx: (payload type-tree) = int
36011     68/push 0/imm32/right:null
36012     68/push 0/imm32/right:null
36013     68/push 0/imm32/left:unused
36014     68/push 1/imm32/value:int
36015     68/push 1/imm32/is-atom?:true
36016     68/push 0x11/imm32/alloc-id:fake:payload
36017     89/<- %ecx 4/r32/esp
36018 $test-emit-subx-stmt-primitive-register:initialize-var:
36019     # var var-foo/ecx: (payload var)
36020     68/push 0/imm32/register
36021     68/push 0/imm32/register
36022     68/push 0/imm32/no-stack-offset
36023     68/push 1/imm32/block-depth
36024     51/push-ecx
36025     68/push 0x11/imm32/alloc-id:fake
36026     68/push 0/imm32/name
36027     68/push 0/imm32/name
36028     68/push 0x11/imm32/alloc-id:fake:payload
36029     89/<- %ecx 4/r32/esp
36030 $test-emit-subx-stmt-primitive-register:initialize-var-name:
36031     # var-foo->name = "foo"
36032     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
36033     (copy-array Heap "foo" %eax)
36034 $test-emit-subx-stmt-primitive-register:initialize-var-register:
36035     # var-foo->register = "eax"
36036     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
36037     (copy-array Heap "eax" %eax)
36038 $test-emit-subx-stmt-primitive-register:initialize-stmt-var:
36039     # var operand/ebx: (payload stmt-var)
36040     68/push 0/imm32/is-deref:false
36041     68/push 0/imm32/next
36042     68/push 0/imm32/next
36043     51/push-ecx/var-foo
36044     68/push 0x11/imm32/alloc-id:fake
36045     68/push 0x11/imm32/alloc-id:fake:payload
36046     89/<- %ebx 4/r32/esp
36047 $test-emit-subx-stmt-primitive-register:initialize-stmt:
36048     # var stmt/esi: (addr statement)
36049     53/push-ebx/outputs
36050     68/push 0x11/imm32/alloc-id:fake
36051     68/push 0/imm32/no-inouts
36052     68/push 0/imm32/no-inouts
36053     68/push 0/imm32/operation
36054     68/push 0/imm32/operation
36055     68/push 1/imm32
36056     89/<- %esi 4/r32/esp
36057 $test-emit-subx-stmt-primitive-register:initialize-stmt-operation:
36058     # stmt->operation = "increment"
36059     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
36060     (copy-array Heap "increment" %eax)
36061 $test-emit-subx-stmt-primitive-register:initialize-formal-var:
36062     # var formal-var/ebx: (payload var)
36063     68/push 0/imm32/register
36064     68/push 0/imm32/register
36065     68/push 0/imm32/no-stack-offset
36066     68/push 1/imm32/block-depth
36067     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
36068     68/push 0x11/imm32/alloc-id:fake
36069     68/push 0/imm32/name
36070     68/push 0/imm32/name
36071     68/push 0x11/imm32/alloc-id:fake:payload
36072     89/<- %ebx 4/r32/esp
36073 $test-emit-subx-stmt-primitive-register:initialize-formal-var-name:
36074     # formal-var->name = "dummy"
36075     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
36076     (copy-array Heap "dummy" %eax)
36077 $test-emit-subx-stmt-primitive-register:initialize-formal-register:
36078     # formal-var->register = "*"
36079     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
36080     (copy-array Heap "*" %eax)  # Any-register
36081 $test-emit-subx-stmt-primitive-register:initialize-var-list:
36082     # var formal-outputs/ebx: (payload list var)
36083     68/push 0/imm32/next
36084     68/push 0/imm32/next
36085     53/push-ebx/formal-var
36086     68/push 0x11/imm32/alloc-id:fake
36087     68/push 0x11/imm32/alloc-id:fake:payload
36088     89/<- %ebx 4/r32/esp
36089 $test-emit-subx-stmt-primitive-register:initialize-primitive:
36090     # var primitives/ebx: (addr primitive)
36091     68/push 0/imm32/next
36092     68/push 0/imm32/next
36093     68/push 0/imm32/no-x32
36094     68/push 0/imm32/no-xm32
36095     68/push 0/imm32/no-disp32
36096     68/push 0/imm32/no-imm8
36097     68/push 0/imm32/no-imm32
36098     68/push 0/imm32/no-r32
36099     68/push 3/imm32/rm32-is-first-output
36100     68/push 0/imm32/subx-name
36101     68/push 0/imm32/subx-name
36102     53/push-ebx/outputs
36103     68/push 0x11/imm32/alloc-id:fake
36104     68/push 0/imm32/no-inouts
36105     68/push 0/imm32/no-inouts
36106     68/push 0/imm32/name
36107     68/push 0/imm32/name
36108     89/<- %ebx 4/r32/esp
36109 $test-emit-subx-stmt-primitive-register:initialize-primitive-name:
36110     # primitives->name = "increment"
36111     (copy-array Heap "increment" %ebx)  # Primitive-name
36112 $test-emit-subx-stmt-primitive-register:initialize-primitive-subx-name:
36113     # primitives->subx-name = "ff 0/subop/increment"
36114     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
36115     (copy-array Heap "ff 0/subop/increment" %eax)
36116     # convert
36117     c7 0/subop/copy *Curr-block-depth 0/imm32
36118     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
36119     (flush _test-output-buffered-file)
36120 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
36126     # check output
36127     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-primitive-register")
36128     # . epilogue
36129     89/<- %esp 5/r32/ebp
36130     5d/pop-to-ebp
36131     c3/return
36132 
36133 test-emit-subx-stmt-select-primitive:
36134     # Select the right primitive between overloads.
36135     #   foo <- increment
36136     # =>
36137     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
36138     #
36139     # There's a variable on the var stack as follows:
36140     #   name: 'foo'
36141     #   type: int
36142     #   register: 'eax'
36143     #
36144     # There's two primitives, as follows:
36145     #   - name: 'increment'
36146     #     out: int/reg
36147     #     value: 'ff 0/subop/increment'
36148     #   - name: 'increment'
36149     #     inout: int/mem
36150     #     value: 'ff 0/subop/increment'
36151     #
36152     # . prologue
36153     55/push-ebp
36154     89/<- %ebp 4/r32/esp
36155     # setup
36156     (clear-stream _test-output-stream)
36157     (clear-stream $_test-output-buffered-file->buffer)
36158 $test-emit-subx-stmt-select-primitive:initialize-type:
36159     # var type/ecx: (payload type-tree) = int
36160     68/push 0/imm32/right:null
36161     68/push 0/imm32/right:null
36162     68/push 0/imm32/left:unused
36163     68/push 1/imm32/value:int
36164     68/push 1/imm32/is-atom?:true
36165     68/push 0x11/imm32/alloc-id:fake:payload
36166     89/<- %ecx 4/r32/esp
36167 $test-emit-subx-stmt-select-primitive:initialize-var:
36168     # var var-foo/ecx: (payload var)
36169     68/push 0/imm32/register
36170     68/push 0/imm32/register
36171     68/push 0/imm32/no-stack-offset
36172     68/push 1/imm32/block-depth
36173     51/push-ecx
36174     68/push 0x11/imm32/alloc-id:fake
36175     68/push 0/imm32/name
36176     68/push 0/imm32/name
36177     68/push 0x11/imm32/alloc-id:fake:payload
36178     89/<- %ecx 4/r32/esp
36179 $test-emit-subx-stmt-select-primitive:initialize-var-name:
36180     # var-foo->name = "foo"
36181     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
36182     (copy-array Heap "foo" %eax)
36183 $test-emit-subx-stmt-select-primitive:initialize-var-register:
36184     # var-foo->register = "eax"
36185     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
36186     (copy-array Heap "eax" %eax)
36187 $test-emit-subx-stmt-select-primitive:initialize-stmt-var:
36188     # var operand/ebx: (payload stmt-var)
36189     68/push 0/imm32/is-deref:false
36190     68/push 0/imm32/next
36191     68/push 0/imm32/next
36192     51/push-ecx/var-foo
36193     68/push 0x11/imm32/alloc-id:fake
36194     68/push 0x11/imm32/alloc-id:fake:payload
36195     89/<- %ebx 4/r32/esp
36196 $test-emit-subx-stmt-select-primitive:initialize-stmt:
36197     # var stmt/esi: (addr statement)
36198     53/push-ebx/outputs
36199     68/push 0x11/imm32/alloc-id:fake
36200     68/push 0/imm32/no-inouts
36201     68/push 0/imm32/no-inouts
36202     68/push 0/imm32/operation
36203     68/push 0/imm32/operation
36204     68/push 1/imm32
36205     89/<- %esi 4/r32/esp
36206 $test-emit-subx-stmt-select-primitive:initialize-stmt-operation:
36207     # stmt->operation = "increment"
36208     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
36209     (copy-array Heap "increment" %eax)
36210 $test-emit-subx-stmt-select-primitive:initialize-formal-var:
36211     # var formal-var/ebx: (payload var)
36212     68/push 0/imm32/register
36213     68/push 0/imm32/register
36214     68/push 0/imm32/no-stack-offset
36215     68/push 1/imm32/block-depth
36216     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
36217     68/push 0x11/imm32/alloc-id:fake
36218     68/push 0/imm32/name
36219     68/push 0/imm32/name
36220     68/push 0x11/imm32/alloc-id:fake:payload
36221     89/<- %ebx 4/r32/esp
36222 $test-emit-subx-stmt-select-primitive:initialize-formal-var-name:
36223     # formal-var->name = "dummy"
36224     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
36225     (copy-array Heap "dummy" %eax)
36226 $test-emit-subx-stmt-select-primitive:initialize-formal-register:
36227     # formal-var->register = "*"
36228     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
36229     (copy-array Heap "*" %eax)  # Any-register
36230 $test-emit-subx-stmt-select-primitive:initialize-var-list:
36231     # var formal-outputs/ebx: (payload list var)
36232     68/push 0/imm32/next
36233     68/push 0/imm32/next
36234     53/push-ebx/formal-var
36235     68/push 0x11/imm32/alloc-id:fake
36236     68/push 0x11/imm32/alloc-id:fake:payload
36237     89/<- %ebx 4/r32/esp
36238 $test-emit-subx-stmt-select-primitive:initialize-primitive2:
36239     # var primitive2/edi: (payload primitive)
36240     68/push 0/imm32/next
36241     68/push 0/imm32/next
36242     68/push 0/imm32/no-x32
36243     68/push 0/imm32/no-xm32
36244     68/push 0/imm32/no-disp32
36245     68/push 0/imm32/no-imm8
36246     68/push 0/imm32/no-imm32
36247     68/push 0/imm32/no-r32
36248     68/push 3/imm32/rm32-is-first-output
36249     68/push 0/imm32/subx-name
36250     68/push 0/imm32/subx-name
36251     53/push-ebx/outputs
36252     68/push 0x11/imm32/alloc-id:fake
36253     68/push 0/imm32/no-inouts
36254     68/push 0/imm32/no-inouts
36255     68/push 0/imm32/name
36256     68/push 0/imm32/name
36257     68/push 0x11/imm32/alloc-id:fake:payload
36258     89/<- %edi 4/r32/esp
36259 $test-emit-subx-stmt-select-primitive:initialize-primitive2-name:
36260     # primitives->name = "increment"
36261     8d/copy-address *(edi+4) 0/r32/eax  # Primitive-name + 4
36262     (copy-array Heap "increment" %eax)
36263 $test-emit-subx-stmt-select-primitive:initialize-primitive2-subx-name:
36264     # primitives->subx-name = "ff 0/subop/increment"
36265     8d/copy-address *(edi+0x1c) 0/r32/eax  # Primitive-subx-name + 4
36266     (copy-array Heap "ff 0/subop/increment" %eax)
36267 $test-emit-subx-stmt-select-primitive:initialize-primitive:
36268     # var primitives/ebx: (addr primitive)
36269     57/push-edi
36270     68/push 0x11/imm32/alloc-id:fake
36271     68/push 0/imm32/no-x32
36272     68/push 0/imm32/no-xm32
36273     68/push 0/imm32/no-disp32
36274     68/push 0/imm32/no-imm8
36275     68/push 0/imm32/no-imm32
36276     68/push 0/imm32/no-r32
36277     68/push 1/imm32/rm32-is-first-inout
36278     68/push 0/imm32/subx-name
36279     68/push 0/imm32/subx-name
36280     68/push 0/imm32/no-outputs
36281     68/push 0/imm32/no-outputs
36282     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
36283     68/push 0x11/imm32/alloc-id:fake
36284     68/push 0/imm32/name
36285     68/push 0/imm32/name
36286     89/<- %ebx 4/r32/esp
36287 $test-emit-subx-stmt-select-primitive:initialize-primitive-name:
36288     # primitives->name = "increment"
36289     (copy-array Heap "increment" %ebx)  # Primitive-name
36290 $test-emit-subx-stmt-select-primitive:initialize-primitive-subx-name:
36291     # primitives->subx-name = "ff 0/subop/increment"
36292     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
36293     (copy-array Heap "ff 0/subop/increment" %eax)
36294     # convert
36295     c7 0/subop/copy *Curr-block-depth 0/imm32
36296     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
36297     (flush _test-output-buffered-file)
36298 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
36304     # check output
36305     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive")
36306     # . epilogue
36307     89/<- %esp 5/r32/ebp
36308     5d/pop-to-ebp
36309     c3/return
36310 
36311 test-emit-subx-stmt-select-primitive-2:
36312     # Select the right primitive between overloads.
36313     #   increment foo
36314     # =>
36315     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
36316     #
36317     # There's a variable on the var stack as follows:
36318     #   name: 'foo'
36319     #   type: int
36320     #   register: 'eax'
36321     #
36322     # There's two primitives, as follows:
36323     #   - name: 'increment'
36324     #     out: int/reg
36325     #     value: 'ff 0/subop/increment'
36326     #   - name: 'increment'
36327     #     inout: int/mem
36328     #     value: 'ff 0/subop/increment'
36329     #
36330     # . prologue
36331     55/push-ebp
36332     89/<- %ebp 4/r32/esp
36333     # setup
36334     (clear-stream _test-output-stream)
36335     (clear-stream $_test-output-buffered-file->buffer)
36336 $test-emit-subx-stmt-select-primitive-2:initialize-type:
36337     # var type/ecx: (payload type-tree) = int
36338     68/push 0/imm32/right:null
36339     68/push 0/imm32/right:null
36340     68/push 0/imm32/left:unused
36341     68/push 1/imm32/value:int
36342     68/push 1/imm32/is-atom?:true
36343     68/push 0x11/imm32/alloc-id:fake:payload
36344     89/<- %ecx 4/r32/esp
36345 $test-emit-subx-stmt-select-primitive-2:initialize-var:
36346     # var var-foo/ecx: (payload var)
36347     68/push 0/imm32/register
36348     68/push 0/imm32/register
36349     68/push 0/imm32/no-stack-offset
36350     68/push 1/imm32/block-depth
36351     51/push-ecx
36352     68/push 0x11/imm32/alloc-id:fake
36353     68/push 0/imm32/name
36354     68/push 0/imm32/name
36355     68/push 0x11/imm32/alloc-id:fake:payload
36356     89/<- %ecx 4/r32/esp
36357 $test-emit-subx-stmt-select-primitive-2:initialize-var-name:
36358     # var-foo->name = "foo"
36359     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
36360     (copy-array Heap "foo" %eax)
36361 $test-emit-subx-stmt-select-primitive-2:initialize-var-register:
36362     # var-foo->register = "eax"
36363     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
36364     (copy-array Heap "eax" %eax)
36365 $test-emit-subx-stmt-select-primitive-2:initialize-stmt-var:
36366     # var operand/ebx: (payload stmt-var)
36367     68/push 0/imm32/is-deref:false
36368     68/push 0/imm32/next
36369     68/push 0/imm32/next
36370     51/push-ecx/var-foo
36371     68/push 0x11/imm32/alloc-id:fake
36372     68/push 0x11/imm32/alloc-id:fake:payload
36373     89/<- %ebx 4/r32/esp
36374 $test-emit-subx-stmt-select-primitive-2:initialize-stmt:
36375     # var stmt/esi: (addr statement)
36376     68/push 0/imm32/no-outputs
36377     68/push 0/imm32/no-outputs
36378     53/push-ebx/inouts
36379     68/push 0x11/imm32/alloc-id:fake
36380     68/push 0/imm32/operation
36381     68/push 0/imm32/operation
36382     68/push 1/imm32
36383     89/<- %esi 4/r32/esp
36384 $test-emit-subx-stmt-select-primitive-2:initialize-stmt-operation:
36385     # stmt->operation = "increment"
36386     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
36387     (copy-array Heap "increment" %eax)
36388 $test-emit-subx-stmt-select-primitive-2:initialize-formal-var:
36389     # var formal-var/ebx: (payload var)
36390     68/push 0/imm32/register
36391     68/push 0/imm32/register
36392     68/push 0/imm32/no-stack-offset
36393     68/push 1/imm32/block-depth
36394     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
36395     68/push 0x11/imm32/alloc-id:fake
36396     68/push 0/imm32/name
36397     68/push 0/imm32/name
36398     68/push 0x11/imm32/alloc-id:fake:payload
36399     89/<- %ebx 4/r32/esp
36400 $test-emit-subx-stmt-select-primitive-2:initialize-formal-var-name:
36401     # formal-var->name = "dummy"
36402     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
36403     (copy-array Heap "dummy" %eax)
36404 $test-emit-subx-stmt-select-primitive-2:initialize-formal-register:
36405     # formal-var->register = "*"
36406     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
36407     (copy-array Heap "*" %eax)  # Any-register
36408 $test-emit-subx-stmt-select-primitive-2:initialize-var-list:
36409     # var formal-outputs/ebx: (payload list stmt-var)
36410     68/push 0/imm32/next
36411     68/push 0/imm32/next
36412     53/push-ebx/formal-var
36413     68/push 0x11/imm32/alloc-id:fake
36414     68/push 0x11/imm32/alloc-id:fake:payload
36415     89/<- %ebx 4/r32/esp
36416 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2:
36417     # var primitive2/edi: (payload primitive)
36418     68/push 0/imm32/next
36419     68/push 0/imm32/next
36420     68/push 0/imm32/no-x32
36421     68/push 0/imm32/no-xm32
36422     68/push 0/imm32/no-disp32
36423     68/push 0/imm32/no-imm8
36424     68/push 0/imm32/no-imm32
36425     68/push 0/imm32/no-r32
36426     68/push 3/imm32/rm32-is-first-output
36427     68/push 0/imm32/subx-name
36428     68/push 0/imm32/subx-name
36429     53/push-ebx/outputs
36430     68/push 0x11/imm32/alloc-id:fake
36431     68/push 0/imm32/no-inouts
36432     68/push 0/imm32/no-inouts
36433     68/push 0/imm32/name
36434     68/push 0/imm32/name
36435     68/push 0x11/imm32/alloc-id:fake:payload
36436     89/<- %edi 4/r32/esp
36437 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2-name:
36438     # primitives->name = "increment"
36439     8d/copy-address *(edi+4) 0/r32/eax  # Primitive-name + 4
36440     (copy-array Heap "increment" %eax)
36441 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2-subx-name:
36442     # primitives->subx-name = "ff 0/subop/increment"
36443     8d/copy-address *(edi+0x1c) 0/r32/eax  # Primitive-subx-name + 4
36444     (copy-array Heap "ff 0/subop/increment" %eax)
36445 $test-emit-subx-stmt-select-primitive-2:initialize-primitive:
36446     # var primitives/ebx: (addr primitive)
36447     57/push-edi
36448     68/push 0x11/imm32/alloc-id:fake
36449     68/push 0/imm32/no-x32
36450     68/push 0/imm32/no-xm32
36451     68/push 0/imm32/no-disp32
36452     68/push 0/imm32/no-imm8
36453     68/push 0/imm32/no-imm32
36454     68/push 0/imm32/no-r32
36455     68/push 1/imm32/rm32-is-first-inout
36456     68/push 0/imm32/subx-name
36457     68/push 0/imm32/subx-name
36458     68/push 0/imm32/no-outputs
36459     68/push 0/imm32/no-outputs
36460     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
36461     68/push 0x11/imm32/alloc-id:fake
36462     68/push 0/imm32/name
36463     68/push 0/imm32/name
36464     89/<- %ebx 4/r32/esp
36465 $test-emit-subx-stmt-select-primitive-2:initialize-primitive-name:
36466     # primitives->name = "increment"
36467     (copy-array Heap "increment" %ebx)  # Primitive-name
36468 $test-emit-subx-stmt-select-primitive-2:initialize-primitive-subx-name:
36469     # primitives->subx-name = "ff 0/subop/increment"
36470     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
36471     (copy-array Heap "ff 0/subop/increment" %eax)
36472     # convert
36473     c7 0/subop/copy *Curr-block-depth 0/imm32
36474     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
36475     (flush _test-output-buffered-file)
36476 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
36482     # check output
36483     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive-2")
36484     # . epilogue
36485     89/<- %esp 5/r32/ebp
36486     5d/pop-to-ebp
36487     c3/return
36488 
36489 test-increment-register:
36490     # Select the right register between overloads.
36491     #   foo <- increment
36492     # =>
36493     #   50/increment-eax
36494     #
36495     # There's a variable on the var stack as follows:
36496     #   name: 'foo'
36497     #   type: int
36498     #   register: 'eax'
36499     #
36500     # Primitives are the global definitions.
36501     #
36502     # . prologue
36503     55/push-ebp
36504     89/<- %ebp 4/r32/esp
36505     # setup
36506     (clear-stream _test-output-stream)
36507     (clear-stream $_test-output-buffered-file->buffer)
36508 $test-increment-register:initialize-type:
36509     # var type/ecx: (payload type-tree) = int
36510     68/push 0/imm32/right:null
36511     68/push 0/imm32/right:null
36512     68/push 0/imm32/left:unused
36513     68/push 1/imm32/value:int
36514     68/push 1/imm32/is-atom?:true
36515     68/push 0x11/imm32/alloc-id:fake:payload
36516     89/<- %ecx 4/r32/esp
36517 $test-increment-register:initialize-var:
36518     # var var-foo/ecx: (payload var)
36519     68/push 0/imm32/register
36520     68/push 0/imm32/register
36521     68/push 0/imm32/no-stack-offset
36522     68/push 1/imm32/block-depth
36523     51/push-ecx
36524     68/push 0x11/imm32/alloc-id:fake
36525     68/push 0/imm32/name
36526     68/push 0/imm32/name
36527     68/push 0x11/imm32/alloc-id:fake:payload
36528     89/<- %ecx 4/r32/esp
36529 $test-increment-register:initialize-var-name:
36530     # var-foo->name = "foo"
36531     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
36532     (copy-array Heap "foo" %eax)
36533 $test-increment-register:initialize-var-register:
36534     # var-foo->register = "eax"
36535     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
36536     (copy-array Heap "eax" %eax)
36537 $test-increment-register:initialize-stmt-var:
36538     # var operand/ebx: (payload stmt-var)
36539     68/push 0/imm32/is-deref:false
36540     68/push 0/imm32/next
36541     68/push 0/imm32/next
36542     51/push-ecx/var-foo
36543     68/push 0x11/imm32/alloc-id:fake
36544     68/push 0x11/imm32/alloc-id:fake:payload
36545     89/<- %ebx 4/r32/esp
36546 $test-increment-register:initialize-stmt:
36547     # var stmt/esi: (addr statement)
36548     53/push-ebx/outputs
36549     68/push 0x11/imm32/alloc-id:fake
36550     68/push 0/imm32/no-inouts
36551     68/push 0/imm32/no-inouts
36552     68/push 0/imm32/operation
36553     68/push 0/imm32/operation
36554     68/push 1/imm32
36555     89/<- %esi 4/r32/esp
36556 $test-increment-register:initialize-stmt-operation:
36557     # stmt->operation = "increment"
36558     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
36559     (copy-array Heap "increment" %eax)
36560     # convert
36561     c7 0/subop/copy *Curr-block-depth 0/imm32
36562     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
36563     (flush _test-output-buffered-file)
36564 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
36570     # check output
36571     (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-register")
36572     # . epilogue
36573     89/<- %esp 5/r32/ebp
36574     5d/pop-to-ebp
36575     c3/return
36576 
36577 test-add-reg-to-reg:
36578     #   var1/reg <- add var2/reg
36579     # =>
36580     #   01/add-to %var1 var2
36581     #
36582     # . prologue
36583     55/push-ebp
36584     89/<- %ebp 4/r32/esp
36585     # setup
36586     (clear-stream _test-output-stream)
36587     (clear-stream $_test-output-buffered-file->buffer)
36588 $test-add-reg-to-reg:initialize-type:
36589     # var type/ecx: (payload type-tree) = int
36590     68/push 0/imm32/right:null
36591     68/push 0/imm32/right:null
36592     68/push 0/imm32/left:unused
36593     68/push 1/imm32/value:int
36594     68/push 1/imm32/is-atom?:true
36595     68/push 0x11/imm32/alloc-id:fake:payload
36596     89/<- %ecx 4/r32/esp
36597 $test-add-reg-to-reg:initialize-var1:
36598     # var var1/ecx: (payload var)
36599     68/push 0/imm32/register
36600     68/push 0/imm32/register
36601     68/push 0/imm32/no-stack-offset
36602     68/push 1/imm32/block-depth
36603     51/push-ecx
36604     68/push 0x11/imm32/alloc-id:fake
36605     68/push 0/imm32/name
36606     68/push 0/imm32/name
36607     68/push 0x11/imm32/alloc-id:fake:payload
36608     89/<- %ecx 4/r32/esp
36609 $test-add-reg-to-reg:initialize-var1-name:
36610     # var1->name = "var1"
36611     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
36612     (copy-array Heap "var1" %eax)
36613 $test-add-reg-to-reg:initialize-var1-register:
36614     # var1->register = "eax"
36615     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
36616     (copy-array Heap "eax" %eax)
36617 $test-add-reg-to-reg:initialize-var2:
36618     # var var2/edx: (payload var)
36619     68/push 0/imm32/register
36620     68/push 0/imm32/register
36621     68/push 0/imm32/no-stack-offset
36622     68/push 1/imm32/block-depth
36623     ff 6/subop/push *(ecx+0x10)
36624     68/push 0x11/imm32/alloc-id:fake
36625     68/push 0/imm32/name
36626     68/push 0/imm32/name
36627     68/push 0x11/imm32/alloc-id:fake:payload
36628     89/<- %edx 4/r32/esp
36629 $test-add-reg-to-reg:initialize-var2-name:
36630     # var2->name = "var2"
36631     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
36632     (copy-array Heap "var2" %eax)
36633 $test-add-reg-to-reg:initialize-var2-register:
36634     # var2->register = "ecx"
36635     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
36636     (copy-array Heap "ecx" %eax)
36637 $test-add-reg-to-reg:initialize-inouts:
36638     # var inouts/esi: (payload stmt-var) = [var2]
36639     68/push 0/imm32/is-deref:false
36640     68/push 0/imm32/next
36641     68/push 0/imm32/next
36642     52/push-edx/var2
36643     68/push 0x11/imm32/alloc-id:fake
36644     68/push 0x11/imm32/alloc-id:fake:payload
36645     89/<- %esi 4/r32/esp
36646 $test-add-reg-to-reg:initialize-outputs:
36647     # var outputs/edi: (payload stmt-var) = [var1]
36648     68/push 0/imm32/is-deref:false
36649     68/push 0/imm32/next
36650     68/push 0/imm32/next
36651     51/push-ecx/var1
36652     68/push 0x11/imm32/alloc-id:fake
36653     68/push 0x11/imm32/alloc-id:fake:payload
36654     89/<- %edi 4/r32/esp
36655 $test-add-reg-to-reg:initialize-stmt:
36656     # var stmt/esi: (addr statement)
36657     68/push 0/imm32/next
36658     68/push 0/imm32/next
36659     57/push-edi/outputs
36660     68/push 0x11/imm32/alloc-id:fake
36661     56/push-esi/inouts
36662     68/push 0x11/imm32/alloc-id:fake
36663     68/push 0/imm32/operation
36664     68/push 0/imm32/operation
36665     68/push 1/imm32/tag:stmt1
36666     89/<- %esi 4/r32/esp
36667 $test-add-reg-to-reg:initialize-stmt-operation:
36668     # stmt->operation = "add"
36669     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
36670     (copy-array Heap "add" %eax)
36671     # convert
36672     c7 0/subop/copy *Curr-block-depth 0/imm32
36673     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
36674     (flush _test-output-buffered-file)
36675 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
36681     # check output
36682     (check-next-stream-line-equal _test-output-stream "01/add-to %eax 0x00000001/r32" "F - test-add-reg-to-reg")
36683     # . epilogue
36684     89/<- %esp 5/r32/ebp
36685     5d/pop-to-ebp
36686     c3/return
36687 
36688 test-add-reg-to-mem:
36689     #   add-to var1 var2/reg
36690     # =>
36691     #   01/add-to *(ebp+__) var2
36692     #
36693     # . prologue
36694     55/push-ebp
36695     89/<- %ebp 4/r32/esp
36696     # setup
36697     (clear-stream _test-output-stream)
36698     (clear-stream $_test-output-buffered-file->buffer)
36699 $test-add-reg-to-mem:initialize-type:
36700     # var type/ecx: (payload type-tree) = int
36701     68/push 0/imm32/right:null
36702     68/push 0/imm32/right:null
36703     68/push 0/imm32/left:unused
36704     68/push 1/imm32/value:int
36705     68/push 1/imm32/is-atom?:true
36706     68/push 0x11/imm32/alloc-id:fake:payload
36707     89/<- %ecx 4/r32/esp
36708 $test-add-reg-to-mem:initialize-var1:
36709     # var var1/ecx: (payload var)
36710     68/push 0/imm32/register
36711     68/push 0/imm32/register
36712     68/push 8/imm32/stack-offset
36713     68/push 1/imm32/block-depth
36714     51/push-ecx
36715     68/push 0x11/imm32/alloc-id:fake
36716     68/push 0/imm32/name
36717     68/push 0/imm32/name
36718     68/push 0x11/imm32/alloc-id:fake:payload
36719     89/<- %ecx 4/r32/esp
36720 $test-add-reg-to-mem:initialize-var1-name:
36721     # var1->name = "var1"
36722     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
36723     (copy-array Heap "var1" %eax)
36724 $test-add-reg-to-mem:initialize-var2:
36725     # var var2/edx: (payload var)
36726     68/push 0/imm32/register
36727     68/push 0/imm32/register
36728     68/push 0/imm32/no-stack-offset
36729     68/push 1/imm32/block-depth
36730     ff 6/subop/push *(ecx+0x10)
36731     68/push 0x11/imm32/alloc-id:fake
36732     68/push 0/imm32/name
36733     68/push 0/imm32/name
36734     68/push 0x11/imm32/alloc-id:fake:payload
36735     89/<- %edx 4/r32/esp
36736 $test-add-reg-to-mem:initialize-var2-name:
36737     # var2->name = "var2"
36738     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
36739     (copy-array Heap "var2" %eax)
36740 $test-add-reg-to-mem:initialize-var2-register:
36741     # var2->register = "ecx"
36742     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
36743     (copy-array Heap "ecx" %eax)
36744 $test-add-reg-to-mem:initialize-inouts:
36745     # var inouts/esi: (payload stmt-var) = [var2]
36746     68/push 0/imm32/is-deref:false
36747     68/push 0/imm32/next
36748     68/push 0/imm32/next
36749     52/push-edx/var2
36750     68/push 0x11/imm32/alloc-id:fake
36751     68/push 0x11/imm32/alloc-id:fake:payload
36752     89/<- %esi 4/r32/esp
36753     # inouts = [var1, var2]
36754     68/push 0/imm32/is-deref:false
36755     56/push-esi/next
36756     68/push 0x11/imm32/alloc-id:fake
36757     51/push-ecx/var1
36758     68/push 0x11/imm32/alloc-id:fake
36759     68/push 0x11/imm32/alloc-id:fake:payload
36760     89/<- %esi 4/r32/esp
36761 $test-add-reg-to-mem:initialize-stmt:
36762     # var stmt/esi: (addr statement)
36763     68/push 0/imm32/next
36764     68/push 0/imm32/next
36765     68/push 0/imm32/outputs
36766     68/push 0/imm32/outputs
36767     56/push-esi/inouts
36768     68/push 0x11/imm32/alloc-id:fake
36769     68/push 0/imm32/operation
36770     68/push 0/imm32/operation
36771     68/push 1/imm32/tag:stmt1
36772     89/<- %esi 4/r32/esp
36773 $test-add-reg-to-mem:initialize-stmt-operation:
36774     # stmt->operation = "add-to"
36775     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
36776     (copy-array Heap "add-to" %eax)
36777     # convert
36778     c7 0/subop/copy *Curr-block-depth 0/imm32
36779     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
36780     (flush _test-output-buffered-file)
36781 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
36787     # check output
36788     (check-next-stream-line-equal _test-output-stream "01/add-to *(ebp+0x00000008) 0x00000001/r32" "F - test-add-reg-to-mem")
36789     # . epilogue
36790     89/<- %esp 5/r32/ebp
36791     5d/pop-to-ebp
36792     c3/return
36793 
36794 test-add-mem-to-reg:
36795     #   var1/reg <- add var2
36796     # =>
36797     #   03/add *(ebp+__) var1
36798     #
36799     # . prologue
36800     55/push-ebp
36801     89/<- %ebp 4/r32/esp
36802     # setup
36803     (clear-stream _test-output-stream)
36804     (clear-stream $_test-output-buffered-file->buffer)
36805 $test-add-mem-to-reg:initialize-type:
36806     # var type/ecx: (payload type-tree) = int
36807     68/push 0/imm32/right:null
36808     68/push 0/imm32/right:null
36809     68/push 0/imm32/left:unused
36810     68/push 1/imm32/value:int
36811     68/push 1/imm32/is-atom?:true
36812     68/push 0x11/imm32/alloc-id:fake:payload
36813     89/<- %ecx 4/r32/esp
36814 $test-add-mem-to-reg:initialize-var:
36815     # var var1/ecx: (payload var)
36816     68/push 0/imm32/register
36817     68/push 0/imm32/register
36818     68/push 0/imm32/no-stack-offset
36819     68/push 1/imm32/block-depth
36820     51/push-ecx
36821     68/push 0x11/imm32/alloc-id:fake
36822     68/push 0/imm32/name
36823     68/push 0/imm32/name
36824     68/push 0x11/imm32/alloc-id:fake:payload
36825     89/<- %ecx 4/r32/esp
36826 $test-add-mem-to-reg:initialize-var-name:
36827     # var1->name = "foo"
36828     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
36829     (copy-array Heap "var1" %eax)
36830 $test-add-mem-to-reg:initialize-var-register:
36831     # var1->register = "eax"
36832     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
36833     (copy-array Heap "eax" %eax)
36834 $test-add-mem-to-reg:initialize-var2:
36835     # var var2/edx: (payload var)
36836     68/push 0/imm32/register
36837     68/push 0/imm32/register
36838     68/push 8/imm32/stack-offset
36839     68/push 1/imm32/block-depth
36840     ff 6/subop/push *(ecx+0x10)
36841     68/push 0x11/imm32/alloc-id:fake
36842     68/push 0/imm32/name
36843     68/push 0/imm32/name
36844     68/push 0x11/imm32/alloc-id:fake:payload
36845     89/<- %edx 4/r32/esp
36846 $test-add-mem-to-reg:initialize-var2-name:
36847     # var2->name = "var2"
36848     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
36849     (copy-array Heap "var2" %eax)
36850 $test-add-mem-to-reg:initialize-inouts:
36851     # var inouts/esi: (payload stmt-var) = [var2]
36852     68/push 0/imm32/is-deref:false
36853     68/push 0/imm32/next
36854     68/push 0/imm32/next
36855     52/push-edx/var2
36856     68/push 0x11/imm32/alloc-id:fake
36857     68/push 0x11/imm32/alloc-id:fake:payload
36858     89/<- %esi 4/r32/esp
36859 $test-add-mem-to-reg:initialize-outputs:
36860     # var outputs/edi: (payload stmt-var) = [var1]
36861     68/push 0/imm32/is-deref:false
36862     68/push 0/imm32/next
36863     68/push 0/imm32/next
36864     51/push-ecx/var1
36865     68/push 0x11/imm32/alloc-id:fake
36866     68/push 0x11/imm32/alloc-id:fake:payload
36867     89/<- %edi 4/r32/esp
36868 $test-add-mem-to-reg:initialize-stmt:
36869     # var stmt/esi: (addr statement)
36870     68/push 0/imm32/next
36871     68/push 0/imm32/next
36872     57/push-edi/outputs
36873     68/push 0x11/imm32/alloc-id:fake
36874     56/push-esi/inouts
36875     68/push 0x11/imm32/alloc-id:fake
36876     68/push 0/imm32/operation
36877     68/push 0/imm32/operation
36878     68/push 1/imm32/tag:stmt1
36879     89/<- %esi 4/r32/esp
36880 $test-add-mem-to-reg:initialize-stmt-operation:
36881     # stmt->operation = "add"
36882     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
36883     (copy-array Heap "add" %eax)
36884     # convert
36885     c7 0/subop/copy *Curr-block-depth 0/imm32
36886     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
36887     (flush _test-output-buffered-file)
36888 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
36894     # check output
36895     (check-next-stream-line-equal _test-output-stream "03/add *(ebp+0x00000008) 0x00000000/r32" "F - test-add-mem-to-reg")
36896     # . epilogue
36897     89/<- %esp 5/r32/ebp
36898     5d/pop-to-ebp
36899     c3/return
36900 
36901 test-add-literal-to-eax:
36902     #   var1/eax <- add 0x34
36903     # =>
36904     #   05/add-to-eax 0x34/imm32
36905     #
36906     # . prologue
36907     55/push-ebp
36908     89/<- %ebp 4/r32/esp
36909     # setup
36910     (clear-stream _test-output-stream)
36911     (clear-stream $_test-output-buffered-file->buffer)
36912 $test-add-literal-to-eax:initialize-var-type:
36913     # var type/ecx: (payload type-tree) = int
36914     68/push 0/imm32/right:null
36915     68/push 0/imm32/right:null
36916     68/push 0/imm32/left:unused
36917     68/push 1/imm32/value:int
36918     68/push 1/imm32/is-atom?:true
36919     68/push 0x11/imm32/alloc-id:fake:payload
36920     89/<- %ecx 4/r32/esp
36921 $test-add-literal-to-eax:initialize-var:
36922     # var v/ecx: (payload var)
36923     68/push 0/imm32/register
36924     68/push 0/imm32/register
36925     68/push 0/imm32/no-stack-offset
36926     68/push 1/imm32/block-depth
36927     51/push-ecx
36928     68/push 0x11/imm32/alloc-id:fake
36929     68/push 0/imm32/name
36930     68/push 0/imm32/name
36931     68/push 0x11/imm32/alloc-id:fake:payload
36932     89/<- %ecx 4/r32/esp
36933 $test-add-literal-to-eax:initialize-var-name:
36934     # v->name = "v"
36935     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
36936     (copy-array Heap "v" %eax)
36937 $test-add-literal-to-eax:initialize-var-register:
36938     # v->register = "eax"
36939     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
36940     (copy-array Heap "eax" %eax)
36941 $test-add-literal-to-eax:initialize-literal-type:
36942     # var type/edx: (payload type-tree) = literal
36943     68/push 0/imm32/right:null
36944     68/push 0/imm32/right:null
36945     68/push 0/imm32/left:unused
36946     68/push 0/imm32/value:literal
36947     68/push 1/imm32/is-atom?:true
36948     68/push 0x11/imm32/alloc-id:fake:payload
36949     89/<- %edx 4/r32/esp
36950 $test-add-literal-to-eax:initialize-literal:
36951     # var l/edx: (payload var)
36952     68/push 0/imm32/register
36953     68/push 0/imm32/register
36954     68/push 0/imm32/no-stack-offset
36955     68/push 1/imm32/block-depth
36956     52/push-edx
36957     68/push 0x11/imm32/alloc-id:fake
36958     68/push 0/imm32/name
36959     68/push 0/imm32/name
36960     68/push 0x11/imm32/alloc-id:fake:payload
36961     89/<- %edx 4/r32/esp
36962 $test-add-literal-to-eax:initialize-literal-value:
36963     # l->name = "0x34"
36964     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
36965     (copy-array Heap "0x34" %eax)
36966 $test-add-literal-to-eax:initialize-inouts:
36967     # var inouts/esi: (payload stmt-var) = [l]
36968     68/push 0/imm32/is-deref:false
36969     68/push 0/imm32/next
36970     68/push 0/imm32/next
36971     52/push-edx/l
36972     68/push 0x11/imm32/alloc-id:fake
36973     68/push 0x11/imm32/alloc-id:fake:payload
36974     89/<- %esi 4/r32/esp
36975 $test-add-literal-to-eax:initialize-outputs:
36976     # var outputs/edi: (payload stmt-var) = [v]
36977     68/push 0/imm32/is-deref:false
36978     68/push 0/imm32/next
36979     68/push 0/imm32/next
36980     51/push-ecx/v
36981     68/push 0x11/imm32/alloc-id:fake
36982     68/push 0x11/imm32/alloc-id:fake:payload
36983     89/<- %edi 4/r32/esp
36984 $test-add-literal-to-eax:initialize-stmt:
36985     # var stmt/esi: (addr statement)
36986     68/push 0/imm32/next
36987     68/push 0/imm32/next
36988     57/push-edi/outputs
36989     68/push 0x11/imm32/alloc-id:fake
36990     56/push-esi/inouts
36991     68/push 0x11/imm32/alloc-id:fake
36992     68/push 0/imm32/operation
36993     68/push 0/imm32/operation
36994     68/push 1/imm32/tag:stmt1
36995     89/<- %esi 4/r32/esp
36996 $test-add-literal-to-eax:initialize-stmt-operation:
36997     # stmt->operation = "add"
36998     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
36999     (copy-array Heap "add" %eax)
37000     # convert
37001     c7 0/subop/copy *Curr-block-depth 0/imm32
37002     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37003     (flush _test-output-buffered-file)
37004 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37010     # check output
37011     (check-next-stream-line-equal _test-output-stream "05/add-to-eax 0x34/imm32" "F - test-add-literal-to-eax")
37012     # . epilogue
37013     89/<- %esp 5/r32/ebp
37014     5d/pop-to-ebp
37015     c3/return
37016 
37017 test-add-literal-to-reg:
37018     #   var1/ecx <- add 0x34
37019     # =>
37020     #   81 0/subop/add %ecx 0x34/imm32
37021     #
37022     # . prologue
37023     55/push-ebp
37024     89/<- %ebp 4/r32/esp
37025     # setup
37026     (clear-stream _test-output-stream)
37027     (clear-stream $_test-output-buffered-file->buffer)
37028 $test-add-literal-to-reg:initialize-var-type:
37029     # var type/ecx: (payload type-tree) = int
37030     68/push 0/imm32/right:null
37031     68/push 0/imm32/right:null
37032     68/push 0/imm32/left:unused
37033     68/push 1/imm32/value:int
37034     68/push 1/imm32/is-atom?:true
37035     68/push 0x11/imm32/alloc-id:fake:payload
37036     89/<- %ecx 4/r32/esp
37037 $test-add-literal-to-reg:initialize-var:
37038     # var v/ecx: (payload var)
37039     68/push 0/imm32/register
37040     68/push 0/imm32/register
37041     68/push 0/imm32/no-stack-offset
37042     68/push 1/imm32/block-depth
37043     51/push-ecx
37044     68/push 0x11/imm32/alloc-id:fake
37045     68/push 0/imm32/name
37046     68/push 0/imm32/name
37047     68/push 0x11/imm32/alloc-id:fake:payload
37048     89/<- %ecx 4/r32/esp
37049 $test-add-literal-to-reg:initialize-var-name:
37050     # v->name = "v"
37051     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37052     (copy-array Heap "v" %eax)
37053 $test-add-literal-to-reg:initialize-var-register:
37054     # v->register = "ecx"
37055     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
37056     (copy-array Heap "ecx" %eax)
37057 $test-add-literal-to-reg:initialize-literal-type:
37058     # var type/edx: (payload type-tree) = literal
37059     68/push 0/imm32/right:null
37060     68/push 0/imm32/right:null
37061     68/push 0/imm32/left:unused
37062     68/push 0/imm32/value:literal
37063     68/push 1/imm32/is-atom?:true
37064     68/push 0x11/imm32/alloc-id:fake:payload
37065     89/<- %edx 4/r32/esp
37066 $test-add-literal-to-reg:initialize-literal:
37067     # var l/edx: (payload var)
37068     68/push 0/imm32/register
37069     68/push 0/imm32/register
37070     68/push 0/imm32/no-stack-offset
37071     68/push 1/imm32/block-depth
37072     52/push-edx
37073     68/push 0x11/imm32/alloc-id:fake
37074     68/push 0/imm32/name
37075     68/push 0/imm32/name
37076     68/push 0x11/imm32/alloc-id:fake:payload
37077     89/<- %edx 4/r32/esp
37078 $test-add-literal-to-reg:initialize-literal-value:
37079     # l->name = "0x34"
37080     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
37081     (copy-array Heap "0x34" %eax)
37082 $test-add-literal-to-reg:initialize-inouts:
37083     # var inouts/esi: (payload stmt-var) = [l]
37084     68/push 0/imm32/is-deref:false
37085     68/push 0/imm32/next
37086     68/push 0/imm32/next
37087     52/push-edx/l
37088     68/push 0x11/imm32/alloc-id:fake
37089     68/push 0x11/imm32/alloc-id:fake:payload
37090     89/<- %esi 4/r32/esp
37091 $test-add-literal-to-reg:initialize-outputs:
37092     # var outputs/edi: (payload stmt-var) = [v]
37093     68/push 0/imm32/is-deref:false
37094     68/push 0/imm32/next
37095     68/push 0/imm32/next
37096     51/push-ecx/v
37097     68/push 0x11/imm32/alloc-id:fake
37098     68/push 0x11/imm32/alloc-id:fake:payload
37099     89/<- %edi 4/r32/esp
37100 $test-add-literal-to-reg:initialize-stmt:
37101     # var stmt/esi: (addr statement)
37102     68/push 0/imm32/next
37103     68/push 0/imm32/next
37104     57/push-edi/outputs
37105     68/push 0x11/imm32/alloc-id:fake
37106     56/push-esi/inouts
37107     68/push 0x11/imm32/alloc-id:fake
37108     68/push 0/imm32/operation
37109     68/push 0/imm32/operation
37110     68/push 1/imm32/tag:stmt1
37111     89/<- %esi 4/r32/esp
37112 $test-add-literal-to-reg:initialize-stmt-operation:
37113     # stmt->operation = "add"
37114     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37115     (copy-array Heap "add" %eax)
37116     # convert
37117     c7 0/subop/copy *Curr-block-depth 0/imm32
37118     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37119     (flush _test-output-buffered-file)
37120 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37126     # check output
37127     (check-next-stream-line-equal _test-output-stream "81 0/subop/add %ecx 0x34/imm32" "F - test-add-literal-to-reg")
37128     # . epilogue
37129     89/<- %esp 5/r32/ebp
37130     5d/pop-to-ebp
37131     c3/return
37132 
37133 test-add-literal-to-mem:
37134     #   add-to var1, 0x34
37135     # =>
37136     #   81 0/subop/add %eax 0x34/imm32
37137     #
37138     # . prologue
37139     55/push-ebp
37140     89/<- %ebp 4/r32/esp
37141     # setup
37142     (clear-stream _test-output-stream)
37143     (clear-stream $_test-output-buffered-file->buffer)
37144 $test-add-literal-to-mem:initialize-type:
37145     # var type/ecx: (payload type-tree) = int
37146     68/push 0/imm32/right:null
37147     68/push 0/imm32/right:null
37148     68/push 0/imm32/left:unused
37149     68/push 1/imm32/value:int
37150     68/push 1/imm32/is-atom?:true
37151     68/push 0x11/imm32/alloc-id:fake:payload
37152     89/<- %ecx 4/r32/esp
37153 $test-add-literal-to-mem:initialize-var1:
37154     # var var1/ecx: (payload var)
37155     68/push 0/imm32/register
37156     68/push 0/imm32/register
37157     68/push 8/imm32/stack-offset
37158     68/push 1/imm32/block-depth
37159     51/push-ecx
37160     68/push 0x11/imm32/alloc-id:fake
37161     68/push 0/imm32/name
37162     68/push 0/imm32/name
37163     68/push 0x11/imm32/alloc-id:fake:payload
37164     89/<- %ecx 4/r32/esp
37165 $test-add-literal-to-mem:initialize-var1-name:
37166     # var1->name = "var1"
37167     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37168     (copy-array Heap "var1" %eax)
37169 $test-add-literal-to-mem:initialize-literal-type:
37170     # var type/edx: (payload type-tree) = literal
37171     68/push 0/imm32/right:null
37172     68/push 0/imm32/right:null
37173     68/push 0/imm32/left:unused
37174     68/push 0/imm32/value:literal
37175     68/push 1/imm32/is-atom?:true
37176     68/push 0x11/imm32/alloc-id:fake:payload
37177     89/<- %edx 4/r32/esp
37178 $test-add-literal-to-mem:initialize-literal:
37179     # var l/edx: (payload var)
37180     68/push 0/imm32/register
37181     68/push 0/imm32/register
37182     68/push 0/imm32/no-stack-offset
37183     68/push 1/imm32/block-depth
37184     52/push-edx
37185     68/push 0x11/imm32/alloc-id:fake
37186     68/push 0/imm32/name
37187     68/push 0/imm32/name
37188     68/push 0x11/imm32/alloc-id:fake:payload
37189     89/<- %edx 4/r32/esp
37190 $test-add-literal-to-mem:initialize-literal-value:
37191     # l->name = "0x34"
37192     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
37193     (copy-array Heap "0x34" %eax)
37194 $test-add-literal-to-mem:initialize-inouts:
37195     # var inouts/esi: (payload stmt-var) = [l]
37196     68/push 0/imm32/is-deref:false
37197     68/push 0/imm32/next
37198     68/push 0/imm32/next
37199     52/push-edx/l
37200     68/push 0x11/imm32/alloc-id:fake
37201     68/push 0x11/imm32/alloc-id:fake:payload
37202     89/<- %esi 4/r32/esp
37203     # var inouts = (handle stmt-var) = [var1, var2]
37204     68/push 0/imm32/is-deref:false
37205     56/push-esi/next
37206     68/push 0x11/imm32/alloc-id:fake
37207     51/push-ecx/var1
37208     68/push 0x11/imm32/alloc-id:fake
37209     68/push 0x11/imm32/alloc-id:fake:payload
37210     89/<- %esi 4/r32/esp
37211 $test-add-literal-to-mem:initialize-stmt:
37212     # var stmt/esi: (addr statement)
37213     68/push 0/imm32/next
37214     68/push 0/imm32/next
37215     68/push 0/imm32/outputs
37216     68/push 0/imm32/outputs
37217     56/push-esi/inouts
37218     68/push 0x11/imm32/alloc-id:fake
37219     68/push 0/imm32/operation
37220     68/push 0/imm32/operation
37221     68/push 1/imm32/tag:stmt1
37222     89/<- %esi 4/r32/esp
37223 $test-add-literal-to-mem:initialize-stmt-operation:
37224     # stmt->operation = "add-to"
37225     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37226     (copy-array Heap "add-to" %eax)
37227     # convert
37228     c7 0/subop/copy *Curr-block-depth 0/imm32
37229     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37230     (flush _test-output-buffered-file)
37231 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37237     # check output
37238     (check-next-stream-line-equal _test-output-stream "81 0/subop/add *(ebp+0x00000008) 0x34/imm32" "F - test-add-literal-to-mem")
37239     # . epilogue
37240     89/<- %esp 5/r32/ebp
37241     5d/pop-to-ebp
37242     c3/return
37243 
37244 test-shift-reg-by-literal:
37245     #   var1/ecx <- shift-left 2
37246     # =>
37247     #   c1/shift 4/subop/left %ecx 2/imm8
37248     #
37249     # . prologue
37250     55/push-ebp
37251     89/<- %ebp 4/r32/esp
37252     # setup
37253     (clear-stream _test-output-stream)
37254     (clear-stream $_test-output-buffered-file->buffer)
37255 $test-shift-reg-by-literal:initialize-var-type:
37256     # var type/ecx: (payload type-tree) = int
37257     68/push 0/imm32/right:null
37258     68/push 0/imm32/right:null
37259     68/push 0/imm32/left:unused
37260     68/push 1/imm32/value:int
37261     68/push 1/imm32/is-atom?:true
37262     68/push 0x11/imm32/alloc-id:fake:payload
37263     89/<- %ecx 4/r32/esp
37264 $test-shift-reg-by-literal:initialize-var:
37265     # var v/ecx: (payload var)
37266     68/push 0/imm32/register
37267     68/push 0/imm32/register
37268     68/push 0/imm32/no-stack-offset
37269     68/push 1/imm32/block-depth
37270     51/push-ecx
37271     68/push 0x11/imm32/alloc-id:fake
37272     68/push 0/imm32/name
37273     68/push 0/imm32/name
37274     68/push 0x11/imm32/alloc-id:fake:payload
37275     89/<- %ecx 4/r32/esp
37276 $test-shift-reg-by-literal:initialize-var-name:
37277     # v->name = "v"
37278     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37279     (copy-array Heap "v" %eax)
37280 $test-shift-reg-by-literal:initialize-var-register:
37281     # v->register = "ecx"
37282     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
37283     (copy-array Heap "ecx" %eax)
37284 $test-shift-reg-by-literal:initialize-literal-type:
37285     # var type/edx: (payload type-tree) = literal
37286     68/push 0/imm32/right:null
37287     68/push 0/imm32/right:null
37288     68/push 0/imm32/left:unused
37289     68/push 0/imm32/value:literal
37290     68/push 1/imm32/is-atom?:true
37291     68/push 0x11/imm32/alloc-id:fake:payload
37292     89/<- %edx 4/r32/esp
37293 $test-shift-reg-by-literal:initialize-literal:
37294     # var l/edx: (payload var)
37295     68/push 0/imm32/register
37296     68/push 0/imm32/register
37297     68/push 0/imm32/no-stack-offset
37298     68/push 1/imm32/block-depth
37299     52/push-edx
37300     68/push 0x11/imm32/alloc-id:fake
37301     68/push 0/imm32/name
37302     68/push 0/imm32/name
37303     68/push 0x11/imm32/alloc-id:fake:payload
37304     89/<- %edx 4/r32/esp
37305 $test-shift-reg-by-literal:initialize-literal-value:
37306     # l->name = "2"
37307     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
37308     (copy-array Heap "2" %eax)
37309 $test-shift-reg-by-literal:initialize-inouts:
37310     # var inouts/esi: (payload stmt-var) = [l]
37311     68/push 0/imm32/is-deref:false
37312     68/push 0/imm32/next
37313     68/push 0/imm32/next
37314     52/push-edx/l
37315     68/push 0x11/imm32/alloc-id:fake
37316     68/push 0x11/imm32/alloc-id:fake:payload
37317     89/<- %esi 4/r32/esp
37318 $test-shift-reg-by-literal:initialize-outputs:
37319     # var outputs/edi: (payload stmt-var) = [v]
37320     68/push 0/imm32/is-deref:false
37321     68/push 0/imm32/next
37322     68/push 0/imm32/next
37323     51/push-ecx/v
37324     68/push 0x11/imm32/alloc-id:fake
37325     68/push 0x11/imm32/alloc-id:fake:payload
37326     89/<- %edi 4/r32/esp
37327 $test-shift-reg-by-literal:initialize-stmt:
37328     # var stmt/esi: (addr statement)
37329     68/push 0/imm32/next
37330     68/push 0/imm32/next
37331     57/push-edi/outputs
37332     68/push 0x11/imm32/alloc-id:fake
37333     56/push-esi/inouts
37334     68/push 0x11/imm32/alloc-id:fake
37335     68/push 0/imm32/operation
37336     68/push 0/imm32/operation
37337     68/push 1/imm32/tag:stmt1
37338     89/<- %esi 4/r32/esp
37339 $test-shift-reg-by-literal:initialize-stmt-operation:
37340     # stmt->operation = "shift-left"
37341     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37342     (copy-array Heap "shift-left" %eax)
37343     # convert
37344     c7 0/subop/copy *Curr-block-depth 0/imm32
37345     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37346     (flush _test-output-buffered-file)
37347 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37353     # check output
37354     (check-next-stream-line-equal _test-output-stream "c1/shift 4/subop/left %ecx 2/imm8" "F - test-shift-reg-by-literal")
37355     # . epilogue
37356     89/<- %esp 5/r32/ebp
37357     5d/pop-to-ebp
37358     c3/return
37359 
37360 test-shift-mem-by-literal:
37361     #   shift-left var 3
37362     # =>
37363     #   c1/shift 4/subop/left *(ebp+8) 3/imm8
37364     #
37365     # . prologue
37366     55/push-ebp
37367     89/<- %ebp 4/r32/esp
37368     # setup
37369     (clear-stream _test-output-stream)
37370     (clear-stream $_test-output-buffered-file->buffer)
37371 $test-shift-mem-by-literal:initialize-type:
37372     # var type/ecx: (payload type-tree) = int
37373     68/push 0/imm32/right:null
37374     68/push 0/imm32/right:null
37375     68/push 0/imm32/left:unused
37376     68/push 1/imm32/value:int
37377     68/push 1/imm32/is-atom?:true
37378     68/push 0x11/imm32/alloc-id:fake:payload
37379     89/<- %ecx 4/r32/esp
37380 $test-shift-mem-by-literal:initialize-var1:
37381     # var var1/ecx: (payload var)
37382     68/push 0/imm32/register
37383     68/push 0/imm32/register
37384     68/push 8/imm32/stack-offset
37385     68/push 1/imm32/block-depth
37386     51/push-ecx
37387     68/push 0x11/imm32/alloc-id:fake
37388     68/push 0/imm32/name
37389     68/push 0/imm32/name
37390     68/push 0x11/imm32/alloc-id:fake:payload
37391     89/<- %ecx 4/r32/esp
37392 $test-shift-mem-by-literal:initialize-var1-name:
37393     # var1->name = "var1"
37394     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37395     (copy-array Heap "var1" %eax)
37396 $test-shift-mem-by-literal:initialize-literal-type:
37397     # var type/edx: (payload type-tree) = literal
37398     68/push 0/imm32/right:null
37399     68/push 0/imm32/right:null
37400     68/push 0/imm32/left:unused
37401     68/push 0/imm32/value:literal
37402     68/push 1/imm32/is-atom?:true
37403     68/push 0x11/imm32/alloc-id:fake:payload
37404     89/<- %edx 4/r32/esp
37405 $test-shift-mem-by-literal:initialize-literal:
37406     # var l/edx: (payload var)
37407     68/push 0/imm32/register
37408     68/push 0/imm32/register
37409     68/push 0/imm32/no-stack-offset
37410     68/push 1/imm32/block-depth
37411     52/push-edx
37412     68/push 0x11/imm32/alloc-id:fake
37413     68/push 0/imm32/name
37414     68/push 0/imm32/name
37415     68/push 0x11/imm32/alloc-id:fake:payload
37416     89/<- %edx 4/r32/esp
37417 $test-shift-mem-by-literal:initialize-literal-value:
37418     # l->name = "3"
37419     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
37420     (copy-array Heap "3" %eax)
37421 $test-shift-mem-by-literal:initialize-inouts:
37422     # var inouts/esi: (payload stmt-var) = [l]
37423     68/push 0/imm32/is-deref:false
37424     68/push 0/imm32/next
37425     68/push 0/imm32/next
37426     52/push-edx/l
37427     68/push 0x11/imm32/alloc-id:fake
37428     68/push 0x11/imm32/alloc-id:fake:payload
37429     89/<- %esi 4/r32/esp
37430     # var inouts = (handle stmt-var) = [var1, var2]
37431     68/push 0/imm32/is-deref:false
37432     56/push-esi/next
37433     68/push 0x11/imm32/alloc-id:fake
37434     51/push-ecx/var1
37435     68/push 0x11/imm32/alloc-id:fake
37436     68/push 0x11/imm32/alloc-id:fake:payload
37437     89/<- %esi 4/r32/esp
37438 $test-shift-mem-by-literal:initialize-stmt:
37439     # var stmt/esi: (addr statement)
37440     68/push 0/imm32/next
37441     68/push 0/imm32/next
37442     68/push 0/imm32/outputs
37443     68/push 0/imm32/outputs
37444     56/push-esi/inouts
37445     68/push 0x11/imm32/alloc-id:fake
37446     68/push 0/imm32/operation
37447     68/push 0/imm32/operation
37448     68/push 1/imm32/tag:stmt1
37449     89/<- %esi 4/r32/esp
37450 $test-shift-mem-by-literal:initialize-stmt-operation:
37451     # stmt->operation = "shift-left"
37452     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37453     (copy-array Heap "shift-left" %eax)
37454     # convert
37455     c7 0/subop/copy *Curr-block-depth 0/imm32
37456     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37457     (flush _test-output-buffered-file)
37458 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37464     # check output
37465     (check-next-stream-line-equal _test-output-stream "c1/shift 4/subop/left *(ebp+0x00000008) 3/imm8" "F - test-shift-mem-by-literal")
37466     # . epilogue
37467     89/<- %esp 5/r32/ebp
37468     5d/pop-to-ebp
37469     c3/return
37470 
37471 test-compare-reg-with-reg:
37472     #   compare var1/ecx, var2/eax
37473     # =>
37474     #   39/compare %ecx 0/r32/eax
37475     #
37476     # . prologue
37477     55/push-ebp
37478     89/<- %ebp 4/r32/esp
37479     # setup
37480     (clear-stream _test-output-stream)
37481     (clear-stream $_test-output-buffered-file->buffer)
37482 $test-compare-reg-with-reg:initialize-type:
37483     # var type/ecx: (payload type-tree) = int
37484     68/push 0/imm32/right:null
37485     68/push 0/imm32/right:null
37486     68/push 0/imm32/left:unused
37487     68/push 1/imm32/value:int
37488     68/push 1/imm32/is-atom?:true
37489     68/push 0x11/imm32/alloc-id:fake:payload
37490     89/<- %ecx 4/r32/esp
37491 $test-compare-reg-with-reg:initialize-var1:
37492     # var var1/ecx: (payload var)
37493     68/push 0/imm32/register
37494     68/push 0/imm32/register
37495     68/push 0/imm32/no-stack-offset
37496     68/push 1/imm32/block-depth
37497     51/push-ecx
37498     68/push 0x11/imm32/alloc-id:fake
37499     68/push 0/imm32/name
37500     68/push 0/imm32/name
37501     68/push 0x11/imm32/alloc-id:fake:payload
37502     89/<- %ecx 4/r32/esp
37503 $test-compare-reg-with-reg:initialize-var1-name:
37504     # var1->name = "var1"
37505     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37506     (copy-array Heap "var1" %eax)
37507 $test-compare-reg-with-reg:initialize-var1-register:
37508     # var1->register = "ecx"
37509     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
37510     (copy-array Heap "ecx" %eax)
37511 $test-compare-reg-with-reg:initialize-var2:
37512     # var var2/edx: (payload var)
37513     68/push 0/imm32/register
37514     68/push 0/imm32/register
37515     68/push 0/imm32/no-stack-offset
37516     68/push 1/imm32/block-depth
37517     ff 6/subop/push *(ecx+0x10)
37518     68/push 0x11/imm32/alloc-id:fake
37519     68/push 0/imm32/name
37520     68/push 0/imm32/name
37521     68/push 0x11/imm32/alloc-id:fake:payload
37522     89/<- %edx 4/r32/esp
37523 $test-compare-reg-with-reg:initialize-var2-name:
37524     # var2->name = "var2"
37525     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
37526     (copy-array Heap "var2" %eax)
37527 $test-compare-reg-with-reg:initialize-var2-register:
37528     # var2->register = "eax"
37529     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
37530     (copy-array Heap "eax" %eax)
37531 $test-compare-reg-with-reg:initialize-inouts:
37532     # var inouts/esi: (payload stmt-var) = [var2]
37533     68/push 0/imm32/is-deref:false
37534     68/push 0/imm32/next
37535     68/push 0/imm32/next
37536     52/push-edx/var2
37537     68/push 0x11/imm32/alloc-id:fake
37538     68/push 0x11/imm32/alloc-id:fake:payload
37539     89/<- %esi 4/r32/esp
37540     # inouts = [var1, var2]
37541     68/push 0/imm32/is-deref:false
37542     56/push-esi/next
37543     68/push 0x11/imm32/alloc-id:fake
37544     51/push-ecx/var1
37545     68/push 0x11/imm32/alloc-id:fake
37546     68/push 0x11/imm32/alloc-id:fake:payload
37547     89/<- %esi 4/r32/esp
37548 $test-compare-reg-with-reg:initialize-stmt:
37549     # var stmt/esi: (addr statement)
37550     68/push 0/imm32/next
37551     68/push 0/imm32/next
37552     68/push 0/imm32/outputs
37553     68/push 0/imm32/outputs
37554     56/push-esi/inouts
37555     68/push 0x11/imm32/alloc-id:fake
37556     68/push 0/imm32/operation
37557     68/push 0/imm32/operation
37558     68/push 1/imm32/tag:stmt1
37559     89/<- %esi 4/r32/esp
37560 $test-compare-reg-with-reg:initialize-stmt-operation:
37561     # stmt->operation = "compare"
37562     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37563     (copy-array Heap "compare" %eax)
37564     # convert
37565     c7 0/subop/copy *Curr-block-depth 0/imm32
37566     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37567     (flush _test-output-buffered-file)
37568 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37574     # check output
37575     (check-next-stream-line-equal _test-output-stream "39/compare-> %ecx 0x00000000/r32" "F - test-compare-reg-with-reg")
37576     # . epilogue
37577     89/<- %esp 5/r32/ebp
37578     5d/pop-to-ebp
37579     c3/return
37580 
37581 test-compare-mem-with-reg:
37582     #   compare var1, var2/eax
37583     # =>
37584     #   39/compare *(ebp+___) 0/r32/eax
37585     #
37586     # . prologue
37587     55/push-ebp
37588     89/<- %ebp 4/r32/esp
37589     # setup
37590     (clear-stream _test-output-stream)
37591     (clear-stream $_test-output-buffered-file->buffer)
37592 $test-compare-mem-with-reg:initialize-type:
37593     # var type/ecx: (payload type-tree) = int
37594     68/push 0/imm32/right:null
37595     68/push 0/imm32/right:null
37596     68/push 0/imm32/left:unused
37597     68/push 1/imm32/value:int
37598     68/push 1/imm32/is-atom?:true
37599     68/push 0x11/imm32/alloc-id:fake:payload
37600     89/<- %ecx 4/r32/esp
37601 $test-compare-mem-with-reg:initialize-var1:
37602     # var var1/ecx: (payload var)
37603     68/push 0/imm32/register
37604     68/push 0/imm32/register
37605     68/push 8/imm32/stack-offset
37606     68/push 1/imm32/block-depth
37607     51/push-ecx
37608     68/push 0x11/imm32/alloc-id:fake
37609     68/push 0/imm32/name
37610     68/push 0/imm32/name
37611     68/push 0x11/imm32/alloc-id:fake:payload
37612     89/<- %ecx 4/r32/esp
37613 $test-compare-mem-with-reg:initialize-var1-name:
37614     # var1->name = "var1"
37615     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37616     (copy-array Heap "var1" %eax)
37617 $test-compare-mem-with-reg:initialize-var2:
37618     # var var2/edx: (payload var)
37619     68/push 0/imm32/register
37620     68/push 0/imm32/register
37621     68/push 0/imm32/no-stack-offset
37622     68/push 1/imm32/block-depth
37623     ff 6/subop/push *(ecx+0x10)
37624     68/push 0x11/imm32/alloc-id:fake
37625     68/push 0/imm32/name
37626     68/push 0/imm32/name
37627     68/push 0x11/imm32/alloc-id:fake:payload
37628     89/<- %edx 4/r32/esp
37629 $test-compare-mem-with-reg:initialize-var2-name:
37630     # var2->name = "var2"
37631     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
37632     (copy-array Heap "var2" %eax)
37633 $test-compare-mem-with-reg:initialize-var2-register:
37634     # var2->register = "eax"
37635     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
37636     (copy-array Heap "eax" %eax)
37637 $test-compare-mem-with-reg:initialize-inouts:
37638     # var inouts/esi: (payload stmt-var) = [var2]
37639     68/push 0/imm32/is-deref:false
37640     68/push 0/imm32/next
37641     68/push 0/imm32/next
37642     52/push-edx/var2
37643     68/push 0x11/imm32/alloc-id:fake
37644     68/push 0x11/imm32/alloc-id:fake:payload
37645     89/<- %esi 4/r32/esp
37646     # inouts = [var1, var2]
37647     68/push 0/imm32/is-deref:false
37648     56/push-esi/next
37649     68/push 0x11/imm32/alloc-id:fake
37650     51/push-ecx/var1
37651     68/push 0x11/imm32/alloc-id:fake
37652     68/push 0x11/imm32/alloc-id:fake:payload
37653     89/<- %esi 4/r32/esp
37654 $test-compare-mem-with-reg:initialize-stmt:
37655     # var stmt/esi: (addr statement)
37656     68/push 0/imm32/next
37657     68/push 0/imm32/next
37658     68/push 0/imm32/outputs
37659     68/push 0/imm32/outputs
37660     56/push-esi/inouts
37661     68/push 0x11/imm32/alloc-id:fake
37662     68/push 0/imm32/operation
37663     68/push 0/imm32/operation
37664     68/push 1/imm32/tag:stmt1
37665     89/<- %esi 4/r32/esp
37666 $test-compare-mem-with-reg:initialize-stmt-operation:
37667     # stmt->operation = "compare"
37668     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37669     (copy-array Heap "compare" %eax)
37670     # convert
37671     c7 0/subop/copy *Curr-block-depth 0/imm32
37672     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37673     (flush _test-output-buffered-file)
37674 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37680     # check output
37681     (check-next-stream-line-equal _test-output-stream "39/compare-> *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-mem-with-reg")
37682     # . epilogue
37683     89/<- %esp 5/r32/ebp
37684     5d/pop-to-ebp
37685     c3/return
37686 
37687 test-compare-reg-with-mem:
37688     #   compare var1/eax, var2
37689     # =>
37690     #   3b/compare<- *(ebp+___) 0/r32/eax
37691     #
37692     # . prologue
37693     55/push-ebp
37694     89/<- %ebp 4/r32/esp
37695     # setup
37696     (clear-stream _test-output-stream)
37697     (clear-stream $_test-output-buffered-file->buffer)
37698 $test-compare-reg-with-mem:initialize-type:
37699     # var type/ecx: (payload type-tree) = int
37700     68/push 0/imm32/right:null
37701     68/push 0/imm32/right:null
37702     68/push 0/imm32/left:unused
37703     68/push 1/imm32/value:int
37704     68/push 1/imm32/is-atom?:true
37705     68/push 0x11/imm32/alloc-id:fake:payload
37706     89/<- %ecx 4/r32/esp
37707 $test-compare-reg-with-mem:initialize-var1:
37708     # var var1/ecx: (payload var)
37709     68/push 0/imm32/register
37710     68/push 0/imm32/register
37711     68/push 0/imm32/no-stack-offset
37712     68/push 1/imm32/block-depth
37713     51/push-ecx
37714     68/push 0x11/imm32/alloc-id:fake
37715     68/push 0/imm32/name
37716     68/push 0/imm32/name
37717     68/push 0x11/imm32/alloc-id:fake:payload
37718     89/<- %ecx 4/r32/esp
37719 $test-compare-reg-with-mem:initialize-var1-name:
37720     # var1->name = "var1"
37721     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37722     (copy-array Heap "var1" %eax)
37723 $test-compare-reg-with-mem:initialize-var1-register:
37724     # var1->register = "eax"
37725     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
37726     (copy-array Heap "eax" %eax)
37727 $test-compare-reg-with-mem:initialize-var2:
37728     # var var2/edx: (payload var)
37729     68/push 0/imm32/register
37730     68/push 0/imm32/register
37731     68/push 8/imm32/stack-offset
37732     68/push 1/imm32/block-depth
37733     ff 6/subop/push *(ecx+0x10)
37734     68/push 0x11/imm32/alloc-id:fake
37735     68/push 0/imm32/name
37736     68/push 0/imm32/name
37737     68/push 0x11/imm32/alloc-id:fake:payload
37738     89/<- %edx 4/r32/esp
37739 $test-compare-reg-with-mem:initialize-var2-name:
37740     # var2->name = "var2"
37741     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
37742     (copy-array Heap "var2" %eax)
37743 $test-compare-reg-with-mem:initialize-inouts:
37744     # var inouts/esi: (payload stmt-var) = [var2]
37745     68/push 0/imm32/is-deref:false
37746     68/push 0/imm32/next
37747     68/push 0/imm32/next
37748     52/push-edx/var2
37749     68/push 0x11/imm32/alloc-id:fake
37750     68/push 0x11/imm32/alloc-id:fake:payload
37751     89/<- %esi 4/r32/esp
37752     # inouts = [var1, var2]
37753     68/push 0/imm32/is-deref:false
37754     56/push-esi/next
37755     68/push 0x11/imm32/alloc-id:fake
37756     51/push-ecx/var1
37757     68/push 0x11/imm32/alloc-id:fake
37758     68/push 0x11/imm32/alloc-id:fake:payload
37759     89/<- %esi 4/r32/esp
37760 $test-compare-reg-with-mem:initialize-stmt:
37761     # var stmt/esi: (addr statement)
37762     68/push 0/imm32/next
37763     68/push 0/imm32/next
37764     68/push 0/imm32/outputs
37765     68/push 0/imm32/outputs
37766     56/push-esi/inouts
37767     68/push 0x11/imm32/alloc-id:fake
37768     68/push 0/imm32/operation
37769     68/push 0/imm32/operation
37770     68/push 1/imm32/tag:stmt1
37771     89/<- %esi 4/r32/esp
37772 $test-compare-reg-with-mem:initialize-stmt-operation:
37773     # stmt->operation = "compare"
37774     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37775     (copy-array Heap "compare" %eax)
37776     # convert
37777     c7 0/subop/copy *Curr-block-depth 0/imm32
37778     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37779     (flush _test-output-buffered-file)
37780 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37786     # check output
37787     (check-next-stream-line-equal _test-output-stream "3b/compare<- *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-reg-with-mem")
37788     # . epilogue
37789     89/<- %esp 5/r32/ebp
37790     5d/pop-to-ebp
37791     c3/return
37792 
37793 test-compare-mem-with-literal:
37794     #   compare var1, 0x34
37795     # =>
37796     #   81 7/subop/compare *(ebp+___) 0x34/imm32
37797     #
37798     # . prologue
37799     55/push-ebp
37800     89/<- %ebp 4/r32/esp
37801     # setup
37802     (clear-stream _test-output-stream)
37803     (clear-stream $_test-output-buffered-file->buffer)
37804 $test-compare-mem-with-literal:initialize-type:
37805     # var type/ecx: (payload type-tree) = int
37806     68/push 0/imm32/right:null
37807     68/push 0/imm32/right:null
37808     68/push 0/imm32/left:unused
37809     68/push 1/imm32/value:int
37810     68/push 1/imm32/is-atom?:true
37811     68/push 0x11/imm32/alloc-id:fake:payload
37812     89/<- %ecx 4/r32/esp
37813 $test-compare-mem-with-literal:initialize-var1:
37814     # var var1/ecx: (payload var)
37815     68/push 0/imm32/register
37816     68/push 0/imm32/register
37817     68/push 8/imm32/stack-offset
37818     68/push 1/imm32/block-depth
37819     51/push-ecx
37820     68/push 0x11/imm32/alloc-id:fake
37821     68/push 0/imm32/name
37822     68/push 0/imm32/name
37823     68/push 0x11/imm32/alloc-id:fake:payload
37824     89/<- %ecx 4/r32/esp
37825 $test-compare-mem-with-literal:initialize-var1-name:
37826     # var1->name = "var1"
37827     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37828     (copy-array Heap "var1" %eax)
37829 $test-compare-mem-with-literal:initialize-literal-type:
37830     # var type/edx: (payload type-tree) = literal
37831     68/push 0/imm32/right:null
37832     68/push 0/imm32/right:null
37833     68/push 0/imm32/left:unused
37834     68/push 0/imm32/value:literal
37835     68/push 1/imm32/is-atom?:true
37836     68/push 0x11/imm32/alloc-id:fake:payload
37837     89/<- %edx 4/r32/esp
37838 $test-compare-mem-with-literal:initialize-literal:
37839     # var l/edx: (payload var)
37840     68/push 0/imm32/register
37841     68/push 0/imm32/register
37842     68/push 0/imm32/no-stack-offset
37843     68/push 1/imm32/block-depth
37844     52/push-edx
37845     68/push 0x11/imm32/alloc-id:fake
37846     68/push 0/imm32/name
37847     68/push 0/imm32/name
37848     68/push 0x11/imm32/alloc-id:fake:payload
37849     89/<- %edx 4/r32/esp
37850 $test-compare-mem-with-literal:initialize-literal-value:
37851     # l->name = "0x34"
37852     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
37853     (copy-array Heap "0x34" %eax)
37854 $test-compare-mem-with-literal:initialize-inouts:
37855     # var inouts/esi: (payload stmt-var) = [l]
37856     68/push 0/imm32/is-deref:false
37857     68/push 0/imm32/next
37858     68/push 0/imm32/next
37859     52/push-edx/l
37860     68/push 0x11/imm32/alloc-id:fake
37861     68/push 0x11/imm32/alloc-id:fake:payload
37862     89/<- %esi 4/r32/esp
37863     # var inouts = (handle stmt-var) = [var1, var2]
37864     68/push 0/imm32/is-deref:false
37865     56/push-esi/next
37866     68/push 0x11/imm32/alloc-id:fake
37867     51/push-ecx/var1
37868     68/push 0x11/imm32/alloc-id:fake
37869     68/push 0x11/imm32/alloc-id:fake:payload
37870     89/<- %esi 4/r32/esp
37871 $test-compare-mem-with-literal:initialize-stmt:
37872     # var stmt/esi: (addr statement)
37873     68/push 0/imm32/next
37874     68/push 0/imm32/next
37875     68/push 0/imm32/outputs
37876     68/push 0/imm32/outputs
37877     56/push-esi/inouts
37878     68/push 0x11/imm32/alloc-id:fake
37879     68/push 0/imm32/operation
37880     68/push 0/imm32/operation
37881     68/push 1/imm32/tag:stmt1
37882     89/<- %esi 4/r32/esp
37883 $test-compare-mem-with-literal:initialize-stmt-operation:
37884     # stmt->operation = "compare"
37885     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37886     (copy-array Heap "compare" %eax)
37887     # convert
37888     c7 0/subop/copy *Curr-block-depth 0/imm32
37889     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37890     (flush _test-output-buffered-file)
37891 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37897     # check output
37898     (check-next-stream-line-equal _test-output-stream "81 7/subop/compare *(ebp+0x00000008) 0x34/imm32" "F - test-compare-mem-with-literal")
37899     # . epilogue
37900     89/<- %esp 5/r32/ebp
37901     5d/pop-to-ebp
37902     c3/return
37903 
37904 test-compare-eax-with-literal:
37905     #   compare var1/eax 0x34
37906     # =>
37907     #   3d/compare-eax-with 0x34/imm32
37908     #
37909     # . prologue
37910     55/push-ebp
37911     89/<- %ebp 4/r32/esp
37912     # setup
37913     (clear-stream _test-output-stream)
37914     (clear-stream $_test-output-buffered-file->buffer)
37915 $test-compare-eax-with-literal:initialize-type:
37916     # var type/ecx: (payload type-tree) = int
37917     68/push 0/imm32/right:null
37918     68/push 0/imm32/right:null
37919     68/push 0/imm32/left:unused
37920     68/push 1/imm32/value:int
37921     68/push 1/imm32/is-atom?:true
37922     68/push 0x11/imm32/alloc-id:fake:payload
37923     89/<- %ecx 4/r32/esp
37924 $test-compare-eax-with-literal:initialize-var1:
37925     # var var1/ecx: (payload var)
37926     68/push 0/imm32/register
37927     68/push 0/imm32/register
37928     68/push 0/imm32/no-stack-offset
37929     68/push 1/imm32/block-depth
37930     51/push-ecx
37931     68/push 0x11/imm32/alloc-id:fake
37932     68/push 0/imm32/name
37933     68/push 0/imm32/name
37934     68/push 0x11/imm32/alloc-id:fake:payload
37935     89/<- %ecx 4/r32/esp
37936 $test-compare-eax-with-literal:initialize-var1-name:
37937     # var1->name = "var1"
37938     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37939     (copy-array Heap "var1" %eax)
37940 $test-compare-eax-with-literal:initialize-var1-register:
37941     # v->register = "eax"
37942     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
37943     (copy-array Heap "eax" %eax)
37944 $test-compare-eax-with-literal:initialize-literal-type:
37945     # var type/edx: (payload type-tree) = literal
37946     68/push 0/imm32/right:null
37947     68/push 0/imm32/right:null
37948     68/push 0/imm32/left:unused
37949     68/push 0/imm32/value:literal
37950     68/push 1/imm32/is-atom?:true
37951     68/push 0x11/imm32/alloc-id:fake:payload
37952     89/<- %edx 4/r32/esp
37953 $test-compare-eax-with-literal:initialize-literal:
37954     # var l/edx: (payload var)
37955     68/push 0/imm32/register
37956     68/push 0/imm32/register
37957     68/push 0/imm32/no-stack-offset
37958     68/push 1/imm32/block-depth
37959     52/push-edx
37960     68/push 0x11/imm32/alloc-id:fake
37961     68/push 0/imm32/name
37962     68/push 0/imm32/name
37963     68/push 0x11/imm32/alloc-id:fake:payload
37964     89/<- %edx 4/r32/esp
37965 $test-compare-eax-with-literal:initialize-literal-value:
37966     # l->name = "0x34"
37967     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
37968     (copy-array Heap "0x34" %eax)
37969 $test-compare-eax-with-literal:initialize-inouts:
37970     # var inouts/esi: (payload stmt-var) = [l]
37971     68/push 0/imm32/is-deref:false
37972     68/push 0/imm32/next
37973     68/push 0/imm32/next
37974     52/push-edx/l
37975     68/push 0x11/imm32/alloc-id:fake
37976     68/push 0x11/imm32/alloc-id:fake:payload
37977     89/<- %esi 4/r32/esp
37978     # var inouts = (handle stmt-var) = [var1, var2]
37979     68/push 0/imm32/is-deref:false
37980     56/push-esi/next
37981     68/push 0x11/imm32/alloc-id:fake
37982     51/push-ecx/var1
37983     68/push 0x11/imm32/alloc-id:fake
37984     68/push 0x11/imm32/alloc-id:fake:payload
37985     89/<- %esi 4/r32/esp
37986 $test-compare-eax-with-literal:initialize-stmt:
37987     # var stmt/esi: (addr statement)
37988     68/push 0/imm32/next
37989     68/push 0/imm32/next
37990     68/push 0/imm32/outputs
37991     68/push 0/imm32/outputs
37992     56/push-esi/inouts
37993     68/push 0x11/imm32/alloc-id:fake
37994     68/push 0/imm32/operation
37995     68/push 0/imm32/operation
37996     68/push 1/imm32/tag:stmt1
37997     89/<- %esi 4/r32/esp
37998 $test-compare-eax-with-literal:initialize-stmt-operation:
37999     # stmt->operation = "compare"
38000     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
38001     (copy-array Heap "compare" %eax)
38002     # convert
38003     c7 0/subop/copy *Curr-block-depth 0/imm32
38004     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
38005     (flush _test-output-buffered-file)
38006 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
38012     # check output
38013     (check-next-stream-line-equal _test-output-stream "3d/compare-eax-with 0x34/imm32" "F - test-compare-eax-with-literal")
38014     # . epilogue
38015     89/<- %esp 5/r32/ebp
38016     5d/pop-to-ebp
38017     c3/return
38018 
38019 test-compare-reg-with-literal:
38020     #   compare var1/ecx 0x34
38021     # =>
38022     #   81 7/subop/compare %ecx 0x34/imm32
38023     #
38024     # . prologue
38025     55/push-ebp
38026     89/<- %ebp 4/r32/esp
38027     # setup
38028     (clear-stream _test-output-stream)
38029     (clear-stream $_test-output-buffered-file->buffer)
38030 $test-compare-reg-with-literal:initialize-type:
38031     # var type/ecx: (payload type-tree) = int
38032     68/push 0/imm32/right:null
38033     68/push 0/imm32/right:null
38034     68/push 0/imm32/left:unused
38035     68/push 1/imm32/value:int
38036     68/push 1/imm32/is-atom?:true
38037     68/push 0x11/imm32/alloc-id:fake:payload
38038     89/<- %ecx 4/r32/esp
38039 $test-compare-reg-with-literal:initialize-var1:
38040     # var var1/ecx: (payload var)
38041     68/push 0/imm32/register
38042     68/push 0/imm32/register
38043     68/push 0/imm32/no-stack-offset
38044     68/push 1/imm32/block-depth
38045     51/push-ecx
38046     68/push 0x11/imm32/alloc-id:fake
38047     68/push 0/imm32/name
38048     68/push 0/imm32/name
38049     68/push 0x11/imm32/alloc-id:fake:payload
38050     89/<- %ecx 4/r32/esp
38051 $test-compare-reg-with-literal:initialize-var1-name:
38052     # var1->name = "var1"
38053     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
38054     (copy-array Heap "var1" %eax)
38055 $test-compare-reg-with-literal:initialize-var1-register:
38056     # v->register = "ecx"
38057     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
38058     (copy-array Heap "ecx" %eax)
38059 $test-compare-reg-with-literal:initialize-literal-type:
38060     # var type/edx: (payload type-tree) = literal
38061     68/push 0/imm32/right:null
38062     68/push 0/imm32/right:null
38063     68/push 0/imm32/left:unused
38064     68/push 0/imm32/value:literal
38065     68/push 1/imm32/is-atom?:true
38066     68/push 0x11/imm32/alloc-id:fake:payload
38067     89/<- %edx 4/r32/esp
38068 $test-compare-reg-with-literal:initialize-literal:
38069     # var l/edx: (payload var)
38070     68/push 0/imm32/register
38071     68/push 0/imm32/register
38072     68/push 0/imm32/no-stack-offset
38073     68/push 1/imm32/block-depth
38074     52/push-edx
38075     68/push 0x11/imm32/alloc-id:fake
38076     68/push 0/imm32/name
38077     68/push 0/imm32/name
38078     68/push 0x11/imm32/alloc-id:fake:payload
38079     89/<- %edx 4/r32/esp
38080 $test-compare-reg-with-literal:initialize-literal-value:
38081     # l->name = "0x34"
38082     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
38083     (copy-array Heap "0x34" %eax)
38084 $test-compare-reg-with-literal:initialize-inouts:
38085     # var inouts/esi: (payload stmt-var) = [l]
38086     68/push 0/imm32/is-deref:false
38087     68/push 0/imm32/next
38088     68/push 0/imm32/next
38089     52/push-edx/l
38090     68/push 0x11/imm32/alloc-id:fake
38091     68/push 0x11/imm32/alloc-id:fake:payload
38092     89/<- %esi 4/r32/esp
38093     # var inouts = (handle stmt-var) = [var1, var2]
38094     68/push 0/imm32/is-deref:false
38095     56/push-esi/next
38096     68/push 0x11/imm32/alloc-id:fake
38097     51/push-ecx/var1
38098     68/push 0x11/imm32/alloc-id:fake
38099     68/push 0x11/imm32/alloc-id:fake:payload
38100     89/<- %esi 4/r32/esp
38101 $test-compare-reg-with-literal:initialize-stmt:
38102     # var stmt/esi: (addr statement)
38103     68/push 0/imm32/next
38104     68/push 0/imm32/next
38105     68/push 0/imm32/outputs
38106     68/push 0/imm32/outputs
38107     56/push-esi/inouts
38108     68/push 0x11/imm32/alloc-id:fake
38109     68/push 0/imm32/operation
38110     68/push 0/imm32/operation
38111     68/push 1/imm32/tag:stmt1
38112     89/<- %esi 4/r32/esp
38113 $test-compare-reg-with-literal:initialize-stmt-operation:
38114     # stmt->operation = "compare"
38115     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
38116     (copy-array Heap "compare" %eax)
38117     # convert
38118     c7 0/subop/copy *Curr-block-depth 0/imm32
38119     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
38120     (flush _test-output-buffered-file)
38121 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
38127     # check output
38128     (check-next-stream-line-equal _test-output-stream "81 7/subop/compare %ecx 0x34/imm32" "F - test-compare-reg-with-literal")
38129     # . epilogue
38130     89/<- %esp 5/r32/ebp
38131     5d/pop-to-ebp
38132     c3/return
38133 
38134 test-emit-subx-stmt-function-call:
38135     # Call a function on a variable on the stack.
38136     #   f foo
38137     # =>
38138     #   (f *(ebp-8))
38139     # (Changing the function name supports overloading in general, but here it
38140     # just serves to help disambiguate things.)
38141     #
38142     # There's a variable on the var stack as follows:
38143     #   name: 'foo'
38144     #   type: int
38145     #   stack-offset: -8
38146     #
38147     # There's nothing in primitives.
38148     #
38149     # We don't perform any checking here on the type of 'f'.
38150     #
38151     # . prologue
38152     55/push-ebp
38153     89/<- %ebp 4/r32/esp
38154     # setup
38155     (clear-stream _test-output-stream)
38156     (clear-stream $_test-output-buffered-file->buffer)
38157 $test-emit-subx-function-call:initialize-type:
38158     # var type/ecx: (payload type-tree) = int
38159     68/push 0/imm32/right:null
38160     68/push 0/imm32/right:null
38161     68/push 0/imm32/left:unused
38162     68/push 1/imm32/value:int
38163     68/push 1/imm32/is-atom?:true
38164     68/push 0x11/imm32/alloc-id:fake:payload
38165     89/<- %ecx 4/r32/esp
38166 $test-emit-subx-function-call:initialize-var:
38167     # var var-foo/ecx: (payload var) = var(type)
38168     68/push 0/imm32/no-register
38169     68/push 0/imm32/no-register
38170     68/push -8/imm32/stack-offset
38171     68/push 1/imm32/block-depth
38172     51/push-ecx/type
38173     68/push 0x11/imm32/alloc-id:fake
38174     68/push 0/imm32/name
38175     68/push 0/imm32/name
38176     68/push 0x11/imm32/alloc-id:fake:payload
38177     89/<- %ecx 4/r32/esp
38178 $test-emit-subx-function-call:initialize-var-name:
38179     # var-foo->name = "foo"
38180     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
38181     (copy-array Heap "foo" %eax)
38182 $test-emit-subx-function-call:initialize-stmt-var:
38183     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
38184     68/push 0/imm32/is-deref:false
38185     68/push 0/imm32/next
38186     68/push 0/imm32/next
38187     51/push-ecx/var-foo
38188     68/push 0x11/imm32/alloc-id:fake
38189     68/push 0x11/imm32/alloc-id:fake:payload
38190     89/<- %ebx 4/r32/esp
38191 $test-emit-subx-function-call:initialize-stmt:
38192     # var stmt/esi: (addr statement)
38193     68/push 0/imm32/no-outputs
38194     68/push 0/imm32/no-outputs
38195     53/push-ebx/inouts
38196     68/push 0x11/imm32/alloc-id:fake
38197     68/push 0/imm32/operation
38198     68/push 0/imm32/operation
38199     68/push 1/imm32/tag
38200     89/<- %esi 4/r32/esp
38201 $test-emit-subx-function-call:initialize-stmt-operation:
38202     # stmt->operation = "f"
38203     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
38204     (copy-array Heap "f" %eax)
38205     # convert
38206     c7 0/subop/copy *Curr-block-depth 0/imm32
38207     (emit-subx-stmt _test-output-buffered-file %esi 0 0 Stderr 0)
38208     (flush _test-output-buffered-file)
38209 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
38215     # check output
38216     (check-next-stream-line-equal _test-output-stream "(f *(ebp+0xfffffff8))" "F - test-emit-subx-stmt-function-call")
38217     # . epilogue
38218     89/<- %esp 5/r32/ebp
38219     5d/pop-to-ebp
38220     c3/return
38221 
38222 test-emit-subx-stmt-function-call-with-literal-arg:
38223     # Call a function on a literal.
38224     #   f 0x34
38225     # =>
38226     #   (f2 0x34)
38227     #
38228     # . prologue
38229     55/push-ebp
38230     89/<- %ebp 4/r32/esp
38231     # setup
38232     (clear-stream _test-output-stream)
38233     (clear-stream $_test-output-buffered-file->buffer)
38234 $test-emit-subx-function-call-with-literal-arg:initialize-type:
38235     # var type/ecx: (payload type-tree) = int
38236     68/push 0/imm32/right:null
38237     68/push 0/imm32/right:null
38238     68/push 0/imm32/left:unused
38239     68/push 0/imm32/value:literal
38240     68/push 1/imm32/is-atom?:true
38241     68/push 0x11/imm32/alloc-id:fake:payload
38242     89/<- %ecx 4/r32/esp
38243 $test-emit-subx-function-call-with-literal-arg:initialize-var:
38244     # var var-foo/ecx: (payload var) = var(lit)
38245     68/push 0/imm32/no-register
38246     68/push 0/imm32/no-register
38247     68/push 0/imm32/no-stack-offset
38248     68/push 1/imm32/block-depth
38249     51/push-ecx/type
38250     68/push 0x11/imm32/alloc-id:fake
38251     68/push 0/imm32/name
38252     68/push 0/imm32/name
38253     68/push 0x11/imm32/alloc-id:fake:payload
38254     89/<- %ecx 4/r32/esp
38255 $test-emit-subx-function-call-with-literal-arg:initialize-var-name:
38256     # var-foo->name = "0x34"
38257     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
38258     (copy-array Heap "0x34" %eax)
38259 $test-emit-subx-function-call-with-literal-arg:initialize-stmt-var:
38260     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
38261     68/push 0/imm32/is-deref:false
38262     68/push 0/imm32/next
38263     68/push 0/imm32/next
38264     51/push-ecx/var-foo
38265     68/push 0x11/imm32/alloc-id:fake
38266     68/push 0x11/imm32/alloc-id:fake:payload
38267     89/<- %ebx 4/r32/esp
38268 $test-emit-subx-function-call-with-literal-arg:initialize-stmt:
38269     # var stmt/esi: (addr statement)
38270     68/push 0/imm32/no-outputs
38271     68/push 0/imm32/no-outputs
38272     53/push-ebx/inouts
38273     68/push 0x11/imm32/alloc-id:fake
38274     68/push 0/imm32/operation
38275     68/push 0/imm32/operation
38276     68/push 1/imm32/tag
38277     89/<- %esi 4/r32/esp
38278 $test-emit-subx-function-call-with-literal-arg:initialize-stmt-operation:
38279     # stmt->operation = "f"
38280     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
38281     (copy-array Heap "f" %eax)
38282     # convert
38283     c7 0/subop/copy *Curr-block-depth 0/imm32
38284     (emit-subx-stmt _test-output-buffered-file %esi 0 %ebx 0 Stderr 0)
38285     (flush _test-output-buffered-file)
38286 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
38292     # check output
38293     (check-next-stream-line-equal _test-output-stream "(f 0x34)" "F - test-emit-subx-stmt-function-call-with-literal-arg")
38294     # . epilogue
38295     89/<- %esp 5/r32/ebp
38296     5d/pop-to-ebp
38297     c3/return
38298 
38299 emit-indent:  # out: (addr buffered-file), n: int
38300     # . prologue
38301     55/push-ebp
38302     89/<- %ebp 4/r32/esp
38303     # . save registers
38304     50/push-eax
38305     # var i/eax: int = n
38306     8b/-> *(ebp+0xc) 0/r32/eax
38307     {
38308       # if (i <= 0) break
38309       3d/compare-eax-with 0/imm32
38310       7e/jump-if-<= break/disp8
38311       (write-buffered *(ebp+8) "  ")
38312       48/decrement-eax
38313       eb/jump loop/disp8
38314     }
38315 $emit-indent:end:
38316     # . restore registers
38317     58/pop-to-eax
38318     # . epilogue
38319     89/<- %esp 5/r32/ebp
38320     5d/pop-to-ebp
38321     c3/return
38322 
38323 emit-subx-prologue:  # out: (addr buffered-file)
38324     # . prologue
38325     55/push-ebp
38326     89/<- %ebp 4/r32/esp
38327     #
38328     (write-buffered *(ebp+8) "  # . prologue\n")
38329     (write-buffered *(ebp+8) "  55/push-ebp\n")
38330     (write-buffered *(ebp+8) "  89/<- %ebp 4/r32/esp\n")
38331 $emit-subx-prologue:end:
38332     # . epilogue
38333     89/<- %esp 5/r32/ebp
38334     5d/pop-to-ebp
38335     c3/return
38336 
38337 emit-subx-epilogue:  # out: (addr buffered-file)
38338     # . prologue
38339     55/push-ebp
38340     89/<- %ebp 4/r32/esp
38341     #
38342     (write-buffered *(ebp+8) "  # . epilogue\n")
38343     (write-buffered *(ebp+8) "  89/<- %esp 5/r32/ebp\n")
38344     (write-buffered *(ebp+8) "  5d/pop-to-ebp\n")
38345     (write-buffered *(ebp+8) "  c3/return\n")
38346 $emit-subx-epilogue:end:
38347     # . epilogue
38348     89/<- %esp 5/r32/ebp
38349     5d/pop-to-ebp
38350     c3/return