https://github.com/akkartik/mu/blob/master/apps/mu.subx
    1 # The Mu computer's level-2 language, also called Mu.
    2 # http://akkartik.name/post/mu-2019-2
    3 #
    4 # To run:
    5 #   $ ./translate_subx init.linux [0-9]*.subx apps/mu.subx
    6 #   $ ./a.elf < prog.mu > prog.elf
    7 
    8 # == Goals
    9 # 1. Be memory safe. It should be impossible to corrupt the heap, or to create
   10 # a bad pointer. (Requires strong type safety.)
   11 # 2. Do as little as possible to achieve goal 1. The translator should be
   12 # implementable in machine code.
   13 #   - minimize impedance mismatch between source language and SubX target
   14 #     (e.g. programmer manages registers manually)
   15 #   - checks over syntax
   16 #     (e.g. programmer's register allocation is checked)
   17 #   - runtime checks to avoid complex static analysis
   18 #     (e.g. array indexing always checks bounds)
   19 
   20 # == Language description
   21 # A program is a sequence of function and type definitions.
   22 #
   23 # Function example:
   24 #   fn foo n: int -> _/eax: int {
   25 #     ...
   26 #   }
   27 #
   28 # Functions consist of a name, optional inputs, optional outputs and a block.
   29 #
   30 # Function inputs and outputs are variables. All variables have a type and
   31 # storage specifier. They can be placed either in memory (on the stack) or in
   32 # one of 6 named registers.
   33 #   eax ecx edx ebx esi edi
   34 # Variables in registers must be primitive 32-bit types.
   35 # Variables not explicitly placed in a register are on the stack.
   36 #
   37 # Function inputs are always passed in memory (on the stack), while outputs
   38 # are always returned in registers. Outputs can't be named; they use the
   39 # dummy value '_'.
   40 #
   41 # Blocks mostly consist of statements.
   42 #
   43 # Statements mostly consist of a name, optional inputs and optional outputs.
   44 #
   45 # Statement inputs are variables or literals. Variables need to specify type
   46 # (and storage) the first time they're mentioned but not later.
   47 #
   48 # Statement outputs, like function outputs, must be variables in registers.
   49 #
   50 # Statement names must be either primitives or user-defined functions.
   51 #
   52 # Primitives can write to any register.
   53 # User-defined functions only write to hard-coded registers. Outputs of each
   54 # call must have the same registers as in the function definition.
   55 #
   56 # There are some other statement types:
   57 #   - blocks. Multiple statements surrounded by '{...}' and optionally
   58 #     prefixed with a label name and ':'
   59 #       - {
   60 #           ...
   61 #         }
   62 #       - foo: {
   63 #           ...
   64 #         }
   65 #
   66 #   - variable definitions on the stack. E.g.:
   67 #       - var foo: int
   68 #       - var bar: (array int 3)
   69 #     There's no initializer; variables are automatically initialized.
   70 #     The type of a local variable is either word-length (4 bytes) or starts with 'ref'.
   71 #
   72 #   - variables definitions in a register. E.g.:
   73 #       - var foo/eax: int <- add bar 1
   74 #     The initializer is mandatory and must be a valid instruction that writes
   75 #     a single output to the right register. In practice registers will
   76 #     usually be either initialized by primitives or copied from eax.
   77 #       - var eax: int <- foo bar quux
   78 #         var floo/ecx: int <- copy eax
   79 #
   80 # Still todo:
   81 #   global variables
   82 #   union types
   83 #
   84 # Formal types:
   85 #   A program is a linked list of functions
   86 #   A function contains:
   87 #     name: (handle array byte)
   88 #     inouts: linked list of vars  <-- 'inouts' is more precise than 'inputs'
   89 #       data: (handle var)
   90 #       next: (handle list)
   91 #     outputs: linked list of vars
   92 #       data: (handle var)
   93 #       next: (handle list)
   94 #     body: (handle block)
   95 #   A var-type contains:
   96 #     name: (handle array byte)
   97 #     type: (handle type-tree)
   98 #
   99 #   A statement can be:
  100 #     tag 0: a block
  101 #     tag 1: a simple statement (stmt1)
  102 #     tag 2: a variable defined on the stack
  103 #     tag 3: a variable defined in a register
  104 #
  105 #   A block contains:
  106 #     tag: 0
  107 #     statements: (handle list stmt)
  108 #     name: (handle array byte) -- starting with '$'
  109 #
  110 #   A regular statement contains:
  111 #     tag: 1
  112 #     operation: (handle array byte)
  113 #     inouts: (handle list operand)
  114 #     outputs: (handle list var)
  115 #
  116 #   A variable defined on the stack contains:
  117 #     tag: 2
  118 #     name: (handle array byte)
  119 #     type: (handle type-tree)
  120 #
  121 #   A variable defined in a register contains:
  122 #     tag: 3
  123 #     name: (handle array byte)
  124 #     type: (handle type-tree)
  125 #     reg: (handle array byte)
  126 
  127 # == Translation: managing the stack
  128 # Now that we know what the language looks like in the large, let's think
  129 # about how translation happens from the bottom up. One crucial piece of the
  130 # puzzle is how Mu will clean up variables defined on the stack for you.
  131 #
  132 # Assume that we maintain a 'functions' list while parsing source code. And a
  133 # 'primitives' list is a global constant. Both these contain enough information
  134 # to perform type-checking on function calls or primitive statements, respectively.
  135 #
  136 # Defining variables pushes them on a stack with the current block depth and
  137 # enough information about their location (stack offset or register).
  138 # Starting a block increments the current block id.
  139 # Each statement now has enough information to emit code for it.
  140 # Ending a block is where the magic happens:
  141 #   pop all variables at the current block depth
  142 #   emit code to restore all register variables introduced at the current depth
  143 #   emit code to clean up all stack variables at the current depth (just increment esp)
  144 #   decrement the current block depth
  145 #
  146 # Formal types:
  147 #   live-vars: stack of vars
  148 #   var:
  149 #     name: (handle array byte)
  150 #     type: (handle type-tree)
  151 #     block: int
  152 #     stack-offset: int  (added to ebp)
  153 #     register: (handle array byte)
  154 #       either usual register names
  155 #       or '*' to indicate any register
  156 #   At most one of stack-offset or register-index must be non-zero.
  157 #   A register of '*' designates a variable _template_. Only legal in formal
  158 #   parameters for primitives.
  159 
  160 # == Translating a single function call
  161 # This one's easy. Assuming we've already checked things, we just drop the
  162 # outputs (which use hard-coded registers) and emit inputs in a standard format.
  163 #
  164 # out1, out2, out3, ... <- name inout1, inout2, inout3, ...
  165 # =>
  166 # (name inout1 inout2 inout3)
  167 #
  168 # Formal types:
  169 #   functions: linked list of info
  170 #     name: (handle array byte)
  171 #     inouts: linked list of vars
  172 #     outputs: linked list of vars
  173 #     body: block (linked list of statements)
  174 
  175 # == Translating a single primitive instruction
  176 # A second crucial piece of the puzzle is how Mu converts fairly regular
  177 # primitives with their uniform syntax to SubX instructions with their gnarly
  178 # x86 details.
  179 #
  180 # Mu instructions have inputs and outputs. Primitives can have up to 2 of
  181 # them.
  182 # SubX instructions have rm32 and r32 operands.
  183 # The translation between them covers almost all the possibilities.
  184 #   Instructions with 1 inout may turn into ones with 1 rm32
  185 #     (e.g. incrementing a var on the stack)
  186 #   Instructions with 1 output may turn into ones with 1 rm32
  187 #     (e.g. incrementing a var in a register)
  188 #   1 inout and 1 output may turn into 1 rm32 and 1 r32
  189 #     (e.g. adding a var to a reg)
  190 #   2 inouts may turn into 1 rm32 and 1 r32
  191 #     (e.g. adding a reg to a var)
  192 #   1 inout and 1 literal may turn into 1 rm32 and 1 imm32
  193 #     (e.g. adding a constant to a var)
  194 #   1 output and 1 literal may turn into 1 rm32 and 1 imm32
  195 #     (e.g. adding a constant to a reg)
  196 #   2 outputs to hardcoded registers and 1 inout may turn into 1 rm32
  197 #     (special-case: divide edx:eax by a var or reg)
  198 # Observations:
  199 #   We always emit rm32. It may be the first inout or the first output.
  200 #   We may emit r32 or imm32 or neither.
  201 #   When we emit r32 it may come from first inout or second inout or first output.
  202 #
  203 # Accordingly, the formal data structure for a primitive looks like this:
  204 #   primitives: linked list of info
  205 #     name: (handle array byte)
  206 #     mu-inouts: linked list of vars to check
  207 #     mu-outputs: linked list of vars to check; at most a singleton
  208 #     subx-name: (handle array byte)
  209 #     subx-rm32: enum arg-location
  210 #     subx-r32: enum arg-location
  211 #     subx-imm32: enum arg-location
  212 #     subx-imm8: enum arg-location
  213 #     subx-disp32: enum arg-location
  214 #     subx-xm32: enum arg-location
  215 #     subx-x32: enum arg-location
  216 #   arg-location: enum
  217 #     0 means none
  218 #     1 means first inout
  219 #     2 means second inout
  220 #     3 means first output
  221 
  222 # == Translating a block
  223 # Emit block name if necessary
  224 # Emit '{'
  225 # When you encounter a statement, emit it as above
  226 # When you encounter a variable declaration
  227 #   emit any code needed for it (bzeros)
  228 #   push it on the var stack
  229 #   update register dict if necessary
  230 # When you encounter '}'
  231 #   While popping variables off the var stack until block id changes
  232 #     Emit code needed to clean up the stack
  233 #       either increment esp
  234 #       or pop into appropriate register
  235 
  236 # The rest is straightforward.
  237 
  238 == data
  239 
  240 Program:
  241 _Program-functions:  # (handle function)
  242   0/imm32
  243 _Program-functions->payload:
  244   0/imm32
  245 _Program-types:  # (handle typeinfo)
  246   0/imm32
  247 _Program-types->payload:
  248   0/imm32
  249 _Program-signatures:  # (handle function)
  250   0/imm32
  251 _Program-signatures->payload:
  252   0/imm32
  253 
  254 # Some constants for simulating the data structures described above.
  255 # Many constants here come with a type in a comment.
  256 #
  257 # Sometimes the type is of the value at that offset for the given type. For
  258 # example, if you start at a function record and move forward Function-inouts
  259 # bytes, you'll find a (handle list var).
  260 #
  261 # At other times, the type is of the constant itself. For example, the type of
  262 # the constant Function-size is (addr int). To get the size of a function,
  263 # look in *Function-size.
  264 
  265 Function-name:  # (handle array byte)
  266   0/imm32
  267 Function-inouts:  # (handle list var)
  268   8/imm32
  269 Function-outputs:  # (handle list var)
  270   0x10/imm32
  271 Function-body:  # (handle block)
  272   0x18/imm32
  273 Function-next:  # (handle function)
  274   0x20/imm32
  275 Function-size:  # (addr int)
  276   0x28/imm32/40
  277 
  278 Primitive-name:  # (handle array byte)
  279   0/imm32
  280 Primitive-inouts:  # (handle list var)
  281   8/imm32
  282 Primitive-outputs:  # (handle list var)
  283   0x10/imm32
  284 Primitive-subx-name:  # (handle array byte)
  285   0x18/imm32
  286 Primitive-subx-rm32:  # enum arg-location
  287   0x20/imm32
  288 Primitive-subx-r32:  # enum arg-location
  289   0x24/imm32
  290 Primitive-subx-imm32:  # enum arg-location
  291   0x28/imm32
  292 Primitive-subx-imm8:  # enum arg-location  -- only for bit shifts
  293   0x2c/imm32
  294 Primitive-subx-disp32:  # enum arg-location  -- only for branches
  295   0x30/imm32
  296 Primitive-subx-xm32:  # enum arg-location
  297   0x34/imm32
  298 Primitive-subx-x32:  # enum arg-location
  299   0x38/imm32
  300 Primitive-next:  # (handle function)
  301   0x3c/imm32
  302 Primitive-size:  # (addr int)
  303   0x44/imm32/68
  304 
  305 Stmt-tag:  # int
  306   0/imm32
  307 
  308 Block-stmts:  # (handle list stmt)
  309   4/imm32
  310 Block-var:  # (handle var)
  311   0xc/imm32
  312 
  313 Stmt1-operation:  # (handle array byte)
  314   4/imm32
  315 Stmt1-inouts:  # (handle stmt-var)
  316   0xc/imm32
  317 Stmt1-outputs:  # (handle stmt-var)
  318   0x14/imm32
  319 
  320 Vardef-var:  # (handle var)
  321   4/imm32
  322 
  323 Regvardef-operation:  # (handle array byte)
  324   4/imm32
  325 Regvardef-inouts:  # (handle stmt-var)
  326   0xc/imm32
  327 Regvardef-outputs:  # (handle stmt-var)  # will have exactly one element
  328   0x14/imm32
  329 
  330 Stmt-size:  # (addr int)
  331   0x1c/imm32
  332 
  333 Var-name:  # (handle array byte)
  334   0/imm32
  335 Var-type:  # (handle type-tree)
  336   8/imm32
  337 Var-block-depth:  # int -- not available until code-generation time
  338   0x10/imm32
  339 Var-offset:  # int -- not available until code-generation time
  340   0x14/imm32
  341 Var-register:  # (handle array byte) -- name of a register
  342   0x18/imm32
  343 Var-size:  # (addr int)
  344   0x20/imm32
  345 
  346 List-value:  # (handle _)
  347   0/imm32
  348 List-next:  # (handle list _)
  349   8/imm32
  350 List-size:  # (addr int)
  351   0x10/imm32
  352 
  353 # A stmt-var is like a list of vars with call-site specific metadata
  354 Stmt-var-value:  # (handle var)
  355   0/imm32
  356 Stmt-var-next:  # (handle stmt-var)
  357   8/imm32
  358 Stmt-var-is-deref:  # boolean
  359   0x10/imm32
  360 Stmt-var-size:  # (addr int)
  361   0x14/imm32
  362 
  363 # A live-var is a var augmented with information needed for tracking live
  364 # variables.
  365 Live-var-value:  # (handle var)
  366   0/imm32
  367 Live-var-register-spilled:  # boolean; only used if value is in a register, and only during code-gen
  368   8/imm32
  369 Live-var-size:  # (addr int)
  370   0xc/imm32
  371 
  372 # Types are expressed as trees (s-expressions) of type-ids (ints).
  373 
  374 Type-tree-is-atom:  # boolean
  375   0/imm32
  376 # if is-atom?
  377 Type-tree-value:  # type-id
  378   4/imm32
  379 Type-tree-value-size:  # int (for static data structure sizes)
  380   8/imm32
  381 Type-tree-parameter-name:  # (handle array byte) for type parameters
  382   8/imm32
  383 # unless is-atom?
  384 Type-tree-left:  # (addr type-tree)
  385   4/imm32
  386 Type-tree-right:  # (addr type-tree)
  387   0xc/imm32
  388 #
  389 Type-tree-size:  # (addr int)
  390   0x14/imm32
  391 
  392 # Types
  393 
  394 # TODO: Turn this data structure into valid Mu, with (fake) handles rather than addrs.
  395 Type-id:  # (stream (addr array byte))
  396   0/imm32/write  # initialized later from Primitive-type-ids
  397   0/imm32/read
  398   0x100/imm32/size
  399   # data
  400   0/imm32  # 0 reserved for literals; value is just the name
  401            # Not to be used directly, so we don't include a name here.
  402   "int"/imm32  # 1
  403   "addr"/imm32  # 2
  404   "array"/imm32  # 3
  405   "handle"/imm32  # 4
  406   "boolean"/imm32  # 5
  407   0/imm32  # 6 reserved for constants; they're like literals, but value is an int in Var-offset
  408            # Not to be used directly, so we don't include a name here.
  409   "offset"/imm32  # 7: (offset T) is guaranteed to be a 32-bit multiple of size-of(T)
  410   # 0x20
  411   "byte"/imm32  # 8
  412   0/imm32  # 9 reserved for array-capacity; value is in Type-tree-size.
  413            # Not to be used directly, so we don't include a name here.
  414   0/imm32  # 10 reserved for type parameters; value is (address array byte) in Type-tree-value2.
  415            # Not to be used directly, so we don't include a name here.
  416   "stream"/imm32  # 11
  417   "slice"/imm32  # 12
  418   "code-point"/imm32  # 13; smallest scannable unit from a text stream
  419   "grapheme"/imm32  # 14; smallest printable unit; will eventually be composed of multiple code-points, but currently corresponds 1:1
  420                     # only 4-byte graphemes in utf-8 are currently supported;
  421                     # unclear how we should deal with larger clusters.
  422   "float"/imm32     # 15
  423   # 0x40
  424   0/imm32  # 16 reserved for literal strings; value is just the name
  425            # Not to be used directly, so we don't include a name here.
  426            # TODO: move this up next to literal ints
  427   # Keep Primitive-type-ids in sync if you add types here.
  428           0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  429   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  430   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  431   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  432   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  433   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  434 
  435 Primitive-type-ids:  # (addr int)
  436   0x44
  437 
  438 # == Type definitions
  439 # Program->types contains some typeinfo for each type definition.
  440 # Types contain vars with types, but can't specify registers.
  441 Typeinfo-id:  # type-id
  442   0/imm32
  443 Typeinfo-fields:  # (handle table (handle array byte) (handle typeinfo-entry))
  444   4/imm32
  445 # Total size must be >= 0
  446 # During parsing it may take on two additional values:
  447 #   -2: not yet initialized
  448 #   -1: in process of being computed
  449 # See populate-mu-type-sizes for details.
  450 Typeinfo-total-size-in-bytes:  # int
  451   0xc/imm32
  452 Typeinfo-next:  # (handle typeinfo)
  453   0x10/imm32
  454 Typeinfo-size:  # (addr int)
  455   0x18/imm32
  456 
  457 # Each entry in the typeinfo->fields table has a pointer to a string and a
  458 # pointer to a typeinfo-entry.
  459 Typeinfo-fields-row-size:  # (addr int)
  460   0x10/imm32
  461 
  462 # typeinfo-entry objects have information about a field in a single record type
  463 #
  464 # each field of a type is represented using two var's:
  465 #   1. the input var: expected type of the field; convenient for creating using parse-var-with-type
  466 #   2. the output var: a constant containing the byte offset; convenient for code-generation
  467 # computing the output happens after parsing; in the meantime we preserve the
  468 # order of fields in the 'index' field.
  469 Typeinfo-entry-input-var:  # (handle var)
  470   0/imm32
  471 Typeinfo-entry-index:  # int
  472   8/imm32
  473 Typeinfo-entry-output-var:  # (handle var)
  474   0xc/imm32
  475 Typeinfo-entry-size:  # (addr int)
  476   0x14/imm32
  477 
  478 == code
  479 
  480 Entry:
  481     # . prologue
  482     89/<- %ebp 4/r32/esp
  483     (new-segment *Heap-size Heap)
  484     # if (argv[1] == "test') run-tests()
  485     {
  486       # if (argc <= 1) break
  487       81 7/subop/compare *ebp 1/imm32
  488       7e/jump-if-<= break/disp8
  489       # if (argv[1] != "test") break
  490       (kernel-string-equal? *(ebp+8) "test")  # => eax
  491       3d/compare-eax-and 0/imm32/false
  492       74/jump-if-= break/disp8
  493       #
  494       (run-tests)
  495       # syscall(exit, *Num-test-failures)
  496       8b/-> *Num-test-failures 3/r32/ebx
  497       eb/jump $mu-main:end/disp8
  498     }
  499     # otherwise convert Stdin
  500     (convert-mu Stdin Stdout Stderr 0)
  501     (flush Stdout)
  502     # syscall(exit, 0)
  503     bb/copy-to-ebx 0/imm32
  504 $mu-main:end:
  505     e8/call syscall_exit/disp32
  506 
  507 convert-mu:  # in: (addr buffered-file), out: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
  508     # . prologue
  509     55/push-ebp
  510     89/<- %ebp 4/r32/esp
  511     # . save registers
  512     50/push-eax
  513     # initialize global data structures
  514     c7 0/subop/copy *Next-block-index 1/imm32
  515     8b/-> *Primitive-type-ids 0/r32/eax
  516     89/<- *Type-id 0/r32/eax  # stream-write
  517     c7 0/subop/copy *_Program-functions 0/imm32
  518     c7 0/subop/copy *_Program-functions->payload 0/imm32
  519     c7 0/subop/copy *_Program-types 0/imm32
  520     c7 0/subop/copy *_Program-types->payload 0/imm32
  521     c7 0/subop/copy *_Program-signatures 0/imm32
  522     c7 0/subop/copy *_Program-signatures->payload 0/imm32
  523     #
  524     (parse-mu *(ebp+8) *(ebp+0x10) *(ebp+0x14))
  525     (populate-mu-type-sizes *(ebp+0x10) *(ebp+0x14))
  526 #?     (dump-typeinfos "=== typeinfos\n")
  527     (check-mu-types *(ebp+0x10) *(ebp+0x14))
  528     (emit-subx *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
  529 $convert-mu:end:
  530     # . restore registers
  531     58/pop-to-eax
  532     # . epilogue
  533     89/<- %esp 5/r32/ebp
  534     5d/pop-to-ebp
  535     c3/return
  536 
  537 test-convert-empty-input:
  538     # empty input => empty output
  539     # . prologue
  540     55/push-ebp
  541     89/<- %ebp 4/r32/esp
  542     # setup
  543     (clear-stream _test-input-stream)
  544     (clear-stream $_test-input-buffered-file->buffer)
  545     (clear-stream _test-output-stream)
  546     (clear-stream $_test-output-buffered-file->buffer)
  547     #
  548     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  549     (flush _test-output-buffered-file)
  550     (check-stream-equal _test-output-stream "" "F - test-convert-empty-input")
  551     # . epilogue
  552     89/<- %esp 5/r32/ebp
  553     5d/pop-to-ebp
  554     c3/return
  555 
  556 test-convert-function-skeleton:
  557     # . prologue
  558     55/push-ebp
  559     89/<- %ebp 4/r32/esp
  560     # setup
  561     (clear-stream _test-input-stream)
  562     (clear-stream $_test-input-buffered-file->buffer)
  563     (clear-stream _test-output-stream)
  564     (clear-stream $_test-output-buffered-file->buffer)
  565     #
  566     (write _test-input-stream "fn foo {\n")
  567     (write _test-input-stream "}\n")
  568     # convert
  569     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  570     (flush _test-output-buffered-file)
  571 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
  577     # check output
  578     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-skeleton/0")
  579     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-skeleton/1")
  580     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-skeleton/2")
  581     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-skeleton/3")
  582     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-skeleton/4")
  583     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-skeleton/5")
  584     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-skeleton/6")
  585     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-skeleton/7")
  586     # . epilogue
  587     89/<- %esp 5/r32/ebp
  588     5d/pop-to-ebp
  589     c3/return
  590 
  591 test-convert-multiple-function-skeletons:
  592     # . prologue
  593     55/push-ebp
  594     89/<- %ebp 4/r32/esp
  595     # setup
  596     (clear-stream _test-input-stream)
  597     (clear-stream $_test-input-buffered-file->buffer)
  598     (clear-stream _test-output-stream)
  599     (clear-stream $_test-output-buffered-file->buffer)
  600     #
  601     (write _test-input-stream "fn foo {\n")
  602     (write _test-input-stream "}\n")
  603     (write _test-input-stream "fn bar {\n")
  604     (write _test-input-stream "}\n")
  605     # convert
  606     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  607     (flush _test-output-buffered-file)
  608 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
  614     # check first function
  615     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-multiple-function-skeletons/0")
  616     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-multiple-function-skeletons/1")
  617     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-multiple-function-skeletons/2")
  618     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-multiple-function-skeletons/3")
  619     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-multiple-function-skeletons/4")
  620     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-multiple-function-skeletons/5")
  621     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-multiple-function-skeletons/6")
  622     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-multiple-function-skeletons/7")
  623     # check second function
  624     (check-next-stream-line-equal _test-output-stream "bar:"                    "F - test-convert-multiple-function-skeletons/10")
  625     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-multiple-function-skeletons/11")
  626     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-multiple-function-skeletons/12")
  627     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-multiple-function-skeletons/13")
  628     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-multiple-function-skeletons/14")
  629     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-multiple-function-skeletons/15")
  630     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-multiple-function-skeletons/16")
  631     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-multiple-function-skeletons/17")
  632     # . epilogue
  633     89/<- %esp 5/r32/ebp
  634     5d/pop-to-ebp
  635     c3/return
  636 
  637 test-convert-function-with-arg:
  638     # . prologue
  639     55/push-ebp
  640     89/<- %ebp 4/r32/esp
  641     # setup
  642     (clear-stream _test-input-stream)
  643     (clear-stream $_test-input-buffered-file->buffer)
  644     (clear-stream _test-output-stream)
  645     (clear-stream $_test-output-buffered-file->buffer)
  646     #
  647     (write _test-input-stream "fn foo n: int {\n")
  648     (write _test-input-stream "}\n")
  649     # convert
  650     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  651     (flush _test-output-buffered-file)
  652 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
  658     # check output
  659     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-arg/0")
  660     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-arg/1")
  661     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-arg/2")
  662     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-arg/3")
  663     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-arg/4")
  664     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-arg/5")
  665     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-arg/6")
  666     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-arg/7")
  667     # . epilogue
  668     89/<- %esp 5/r32/ebp
  669     5d/pop-to-ebp
  670     c3/return
  671 
  672 test-function-with-redefined-name:
  673     # . prologue
  674     55/push-ebp
  675     89/<- %ebp 4/r32/esp
  676     # setup
  677     (clear-stream _test-input-stream)
  678     (clear-stream $_test-input-buffered-file->buffer)
  679     (clear-stream _test-output-stream)
  680     (clear-stream $_test-output-buffered-file->buffer)
  681     (clear-stream _test-error-stream)
  682     (clear-stream $_test-error-buffered-file->buffer)
  683     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  684     68/push 0/imm32
  685     68/push 0/imm32
  686     89/<- %edx 4/r32/esp
  687     (tailor-exit-descriptor %edx 0x10)
  688     #
  689     (write _test-input-stream "fn foo {\n")
  690     (write _test-input-stream "}\n")
  691     (write _test-input-stream "fn foo {\n")
  692     (write _test-input-stream "}\n")
  693     # convert
  694     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  695     # registers except esp clobbered at this point
  696     # restore ed
  697     89/<- %edx 4/r32/esp
  698     (flush _test-output-buffered-file)
  699     (flush _test-error-buffered-file)
  700 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
  706     # check output
  707     (check-stream-equal _test-output-stream  ""  "F - test-function-with-redefined-name: output should be empty")
  708     (check-next-stream-line-equal _test-error-stream  "fn foo defined more than once"  "F - test-function-with-redefined-name: error message")
  709     # check that stop(1) was called
  710     (check-ints-equal *(edx+4) 2 "F - test-function-with-redefined-name: exit status")
  711     # don't restore from ebp
  712     81 0/subop/add %esp 8/imm32
  713     # . epilogue
  714     5d/pop-to-ebp
  715     c3/return
  716 
  717 test-function-with-redefined-name-2:
  718     # . prologue
  719     55/push-ebp
  720     89/<- %ebp 4/r32/esp
  721     # setup
  722     (clear-stream _test-input-stream)
  723     (clear-stream $_test-input-buffered-file->buffer)
  724     (clear-stream _test-output-stream)
  725     (clear-stream $_test-output-buffered-file->buffer)
  726     (clear-stream _test-error-stream)
  727     (clear-stream $_test-error-buffered-file->buffer)
  728     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  729     68/push 0/imm32
  730     68/push 0/imm32
  731     89/<- %edx 4/r32/esp
  732     (tailor-exit-descriptor %edx 0x10)
  733     #
  734     (write _test-input-stream "fn foo {\n")
  735     (write _test-input-stream "}\n")
  736     (write _test-input-stream "sig foo\n")
  737     # convert
  738     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  739     # registers except esp clobbered at this point
  740     # restore ed
  741     89/<- %edx 4/r32/esp
  742     (flush _test-output-buffered-file)
  743     (flush _test-error-buffered-file)
  744 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
  750     # check output
  751     (check-stream-equal _test-output-stream  ""  "F - test-function-with-redefined-name-2: output should be empty")
  752     (check-next-stream-line-equal _test-error-stream  "fn foo defined more than once"  "F - test-function-with-redefined-name-2: error message")
  753     # check that stop(1) was called
  754     (check-ints-equal *(edx+4) 2 "F - test-function-with-redefined-name-2: exit status")
  755     # don't restore from ebp
  756     81 0/subop/add %esp 8/imm32
  757     # . epilogue
  758     5d/pop-to-ebp
  759     c3/return
  760 
  761 test-function-with-redefined-name-3:
  762     # . prologue
  763     55/push-ebp
  764     89/<- %ebp 4/r32/esp
  765     # setup
  766     (clear-stream _test-input-stream)
  767     (clear-stream $_test-input-buffered-file->buffer)
  768     (clear-stream _test-output-stream)
  769     (clear-stream $_test-output-buffered-file->buffer)
  770     (clear-stream _test-error-stream)
  771     (clear-stream $_test-error-buffered-file->buffer)
  772     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  773     68/push 0/imm32
  774     68/push 0/imm32
  775     89/<- %edx 4/r32/esp
  776     (tailor-exit-descriptor %edx 0x10)
  777     #
  778     (write _test-input-stream "sig foo\n")
  779     (write _test-input-stream "fn foo {\n")
  780     (write _test-input-stream "}\n")
  781     # convert
  782     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  783     # registers except esp clobbered at this point
  784     # restore ed
  785     89/<- %edx 4/r32/esp
  786     (flush _test-output-buffered-file)
  787     (flush _test-error-buffered-file)
  788 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
  794     # check output
  795     (check-stream-equal _test-output-stream  ""  "F - test-function-with-redefined-name-3: output should be empty")
  796     (check-next-stream-line-equal _test-error-stream  "fn foo defined more than once"  "F - test-function-with-redefined-name-3: error message")
  797     # check that stop(1) was called
  798     (check-ints-equal *(edx+4) 2 "F - test-function-with-redefined-name-3: exit status")
  799     # don't restore from ebp
  800     81 0/subop/add %esp 8/imm32
  801     # . epilogue
  802     5d/pop-to-ebp
  803     c3/return
  804 
  805 test-function-with-inout-in-register:
  806     # . prologue
  807     55/push-ebp
  808     89/<- %ebp 4/r32/esp
  809     # setup
  810     (clear-stream _test-input-stream)
  811     (clear-stream $_test-input-buffered-file->buffer)
  812     (clear-stream _test-output-stream)
  813     (clear-stream $_test-output-buffered-file->buffer)
  814     (clear-stream _test-error-stream)
  815     (clear-stream $_test-error-buffered-file->buffer)
  816     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  817     68/push 0/imm32
  818     68/push 0/imm32
  819     89/<- %edx 4/r32/esp
  820     (tailor-exit-descriptor %edx 0x10)
  821     #
  822     (write _test-input-stream "fn foo x/eax: int {\n")
  823     (write _test-input-stream "}\n")
  824     # convert
  825     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  826     # registers except esp clobbered at this point
  827     # restore ed
  828     89/<- %edx 4/r32/esp
  829     (flush _test-output-buffered-file)
  830     (flush _test-error-buffered-file)
  831 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
  837     # check output
  838     (check-stream-equal _test-output-stream  ""  "F - test-function-with-inout-in-register: output should be empty")
  839     (check-next-stream-line-equal _test-error-stream  "fn foo: function inout 'x' cannot be in a register"  "F - test-function-with-inout-in-register: error message")
  840     # check that stop(1) was called
  841     (check-ints-equal *(edx+4) 2 "F - test-function-with-inout-in-register: exit status")
  842     # don't restore from ebp
  843     81 0/subop/add %esp 8/imm32
  844     # . epilogue
  845     5d/pop-to-ebp
  846     c3/return
  847 
  848 test-function-with-addr-output:
  849     # . prologue
  850     55/push-ebp
  851     89/<- %ebp 4/r32/esp
  852     # setup
  853     (clear-stream _test-input-stream)
  854     (clear-stream $_test-input-buffered-file->buffer)
  855     (clear-stream _test-output-stream)
  856     (clear-stream $_test-output-buffered-file->buffer)
  857     (clear-stream _test-error-stream)
  858     (clear-stream $_test-error-buffered-file->buffer)
  859     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  860     68/push 0/imm32
  861     68/push 0/imm32
  862     89/<- %edx 4/r32/esp
  863     (tailor-exit-descriptor %edx 0x10)
  864     #
  865     (write _test-input-stream "fn foo -> _/eax: (addr int) {\n")
  866     (write _test-input-stream "}\n")
  867     # convert
  868     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  869     # registers except esp clobbered at this point
  870     # restore ed
  871     89/<- %edx 4/r32/esp
  872     (flush _test-output-buffered-file)
  873     (flush _test-error-buffered-file)
  874 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
  880     # check output
  881     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-output: output should be empty")
  882     (check-next-stream-line-equal _test-error-stream  "fn foo: output cannot have an addr type; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-output: error message")
  883     # check that stop(1) was called
  884     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-output: exit status")
  885     # don't restore from ebp
  886     81 0/subop/add %esp 8/imm32
  887     # . epilogue
  888     5d/pop-to-ebp
  889     c3/return
  890 
  891 test-function-with-addr-inout:
  892     # . prologue
  893     55/push-ebp
  894     89/<- %ebp 4/r32/esp
  895     # setup
  896     (clear-stream _test-input-stream)
  897     (clear-stream $_test-input-buffered-file->buffer)
  898     (clear-stream _test-output-stream)
  899     (clear-stream $_test-output-buffered-file->buffer)
  900     (clear-stream _test-error-stream)
  901     (clear-stream $_test-error-buffered-file->buffer)
  902     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  903     68/push 0/imm32
  904     68/push 0/imm32
  905     89/<- %edx 4/r32/esp
  906     (tailor-exit-descriptor %edx 0x10)
  907     #
  908     (write _test-input-stream "fn foo a: (addr addr int) {\n")
  909     (write _test-input-stream "}\n")
  910     # convert
  911     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  912     # registers except esp clobbered at this point
  913     # restore ed
  914     89/<- %edx 4/r32/esp
  915     (flush _test-output-buffered-file)
  916     (flush _test-error-buffered-file)
  917 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
  923     # check output
  924     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout: output should be empty")
  925     (check-next-stream-line-equal _test-error-stream  "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-inout: error message")
  926     # check that stop(1) was called
  927     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout: exit status")
  928     # don't restore from ebp
  929     81 0/subop/add %esp 8/imm32
  930     # . epilogue
  931     5d/pop-to-ebp
  932     c3/return
  933 
  934 test-function-with-addr-inout-2:
  935     # . prologue
  936     55/push-ebp
  937     89/<- %ebp 4/r32/esp
  938     # setup
  939     (clear-stream _test-input-stream)
  940     (clear-stream $_test-input-buffered-file->buffer)
  941     (clear-stream _test-output-stream)
  942     (clear-stream $_test-output-buffered-file->buffer)
  943     (clear-stream _test-error-stream)
  944     (clear-stream $_test-error-buffered-file->buffer)
  945     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  946     68/push 0/imm32
  947     68/push 0/imm32
  948     89/<- %edx 4/r32/esp
  949     (tailor-exit-descriptor %edx 0x10)
  950     #
  951     (write _test-input-stream "fn foo a: (addr array addr int) {\n")
  952     (write _test-input-stream "}\n")
  953     # convert
  954     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  955     # registers except esp clobbered at this point
  956     # restore ed
  957     89/<- %edx 4/r32/esp
  958     (flush _test-output-buffered-file)
  959     (flush _test-error-buffered-file)
  960 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
  966     # check output
  967     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout-2: output should be empty")
  968     (check-next-stream-line-equal _test-error-stream  "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-inout-2: error message")
  969     # check that stop(1) was called
  970     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout-2: exit status")
  971     # don't restore from ebp
  972     81 0/subop/add %esp 8/imm32
  973     # . epilogue
  974     5d/pop-to-ebp
  975     c3/return
  976 
  977 test-function-with-addr-inout-3:
  978     # . prologue
  979     55/push-ebp
  980     89/<- %ebp 4/r32/esp
  981     # setup
  982     (clear-stream _test-input-stream)
  983     (clear-stream $_test-input-buffered-file->buffer)
  984     (clear-stream _test-output-stream)
  985     (clear-stream $_test-output-buffered-file->buffer)
  986     (clear-stream _test-error-stream)
  987     (clear-stream $_test-error-buffered-file->buffer)
  988     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  989     68/push 0/imm32
  990     68/push 0/imm32
  991     89/<- %edx 4/r32/esp
  992     (tailor-exit-descriptor %edx 0x10)
  993     #
  994     (write _test-input-stream "fn foo a: (addr array (addr int) 3) {\n")
  995     (write _test-input-stream "}\n")
  996     # convert
  997     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  998     # registers except esp clobbered at this point
  999     # restore ed
 1000     89/<- %edx 4/r32/esp
 1001     (flush _test-output-buffered-file)
 1002     (flush _test-error-buffered-file)
 1003 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 1009     # check output
 1010     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout-3: output should be empty")
 1011     (check-next-stream-line-equal _test-error-stream  "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-inout-3: error message")
 1012     # check that stop(1) was called
 1013     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout-3: exit status")
 1014     # don't restore from ebp
 1015     81 0/subop/add %esp 8/imm32
 1016     # . epilogue
 1017     5d/pop-to-ebp
 1018     c3/return
 1019 
 1020 test-function-with-addr-inout-4:
 1021     # . prologue
 1022     55/push-ebp
 1023     89/<- %ebp 4/r32/esp
 1024     # setup
 1025     (clear-stream _test-input-stream)
 1026     (clear-stream $_test-input-buffered-file->buffer)
 1027     (clear-stream _test-output-stream)
 1028     (clear-stream $_test-output-buffered-file->buffer)
 1029     (clear-stream _test-error-stream)
 1030     (clear-stream $_test-error-buffered-file->buffer)
 1031     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1032     68/push 0/imm32
 1033     68/push 0/imm32
 1034     89/<- %edx 4/r32/esp
 1035     (tailor-exit-descriptor %edx 0x10)
 1036     #
 1037     (write _test-input-stream "fn foo a: (array (addr int) 3) {\n")
 1038     (write _test-input-stream "}\n")
 1039     # convert
 1040     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1041     # registers except esp clobbered at this point
 1042     # restore ed
 1043     89/<- %edx 4/r32/esp
 1044     (flush _test-output-buffered-file)
 1045     (flush _test-error-buffered-file)
 1046 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 1052     # check output
 1053     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout-4: output should be empty")
 1054     (check-next-stream-line-equal _test-error-stream  "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-inout-4: error message")
 1055     # check that stop(1) was called
 1056     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout-4: exit status")
 1057     # don't restore from ebp
 1058     81 0/subop/add %esp 8/imm32
 1059     # . epilogue
 1060     5d/pop-to-ebp
 1061     c3/return
 1062 
 1063 # 'main' is an exception
 1064 test-function-main-with-addr-inout:
 1065     # . prologue
 1066     55/push-ebp
 1067     89/<- %ebp 4/r32/esp
 1068     # setup
 1069     (clear-stream _test-input-stream)
 1070     (clear-stream $_test-input-buffered-file->buffer)
 1071     (clear-stream _test-output-stream)
 1072     (clear-stream $_test-output-buffered-file->buffer)
 1073     #
 1074     (write _test-input-stream "fn main a: (addr addr int) {\n")
 1075     (write _test-input-stream "}\n")
 1076     # convert
 1077     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1078     (flush _test-output-buffered-file)
 1079     # no errors
 1080     # . epilogue
 1081     89/<- %esp 5/r32/ebp
 1082     5d/pop-to-ebp
 1083     c3/return
 1084 
 1085 # 'lookup' is an exception, but only in signatures
 1086 test-signature-lookup-with-addr-inout:
 1087     # . prologue
 1088     55/push-ebp
 1089     89/<- %ebp 4/r32/esp
 1090     # setup
 1091     (clear-stream _test-input-stream)
 1092     (clear-stream $_test-input-buffered-file->buffer)
 1093     (clear-stream _test-output-stream)
 1094     (clear-stream $_test-output-buffered-file->buffer)
 1095     #
 1096     (write _test-input-stream "sig lookup h: (handle _T) -> _/eax: (addr _T)\n")
 1097     # convert
 1098     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1099     (flush _test-output-buffered-file)
 1100     # no errors
 1101     # . epilogue
 1102     89/<- %esp 5/r32/ebp
 1103     5d/pop-to-ebp
 1104     c3/return
 1105 
 1106 test-convert-function-with-arg-and-body:
 1107     # . prologue
 1108     55/push-ebp
 1109     89/<- %ebp 4/r32/esp
 1110     # setup
 1111     (clear-stream _test-input-stream)
 1112     (clear-stream $_test-input-buffered-file->buffer)
 1113     (clear-stream _test-output-stream)
 1114     (clear-stream $_test-output-buffered-file->buffer)
 1115     #
 1116     (write _test-input-stream "fn foo n: int {\n")
 1117     (write _test-input-stream "  increment n\n")
 1118     (write _test-input-stream "}\n")
 1119     # convert
 1120     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1121     (flush _test-output-buffered-file)
 1122 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 1128     # check output
 1129     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-arg-and-body/0")
 1130     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-arg-and-body/1")
 1131     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-arg-and-body/2")
 1132     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-arg-and-body/3")
 1133     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-arg-and-body/4")
 1134     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-arg-and-body/5")
 1135     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-arg-and-body/6")
 1136     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-arg-and-body/7")
 1137     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-arg-and-body/8")
 1138     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-arg-and-body/9")
 1139     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-arg-and-body/10")
 1140     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-arg-and-body/11")
 1141     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-arg-and-body/12")
 1142     # . epilogue
 1143     89/<- %esp 5/r32/ebp
 1144     5d/pop-to-ebp
 1145     c3/return
 1146 
 1147 test-convert-function-distinguishes-args:
 1148     # . prologue
 1149     55/push-ebp
 1150     89/<- %ebp 4/r32/esp
 1151     # setup
 1152     (clear-stream _test-input-stream)
 1153     (clear-stream $_test-input-buffered-file->buffer)
 1154     (clear-stream _test-output-stream)
 1155     (clear-stream $_test-output-buffered-file->buffer)
 1156     #
 1157     (write _test-input-stream "fn foo a: int, b: int {\n")
 1158     (write _test-input-stream "  increment b\n")
 1159     (write _test-input-stream "}\n")
 1160     # convert
 1161     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1162     (flush _test-output-buffered-file)
 1163 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 1169     # check output
 1170     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-distinguishes-args/0")
 1171     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-distinguishes-args/1")
 1172     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-distinguishes-args/2")
 1173     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-distinguishes-args/3")
 1174     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-distinguishes-args/4")
 1175     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-distinguishes-args/5")
 1176     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0x0000000c)"  "F - test-convert-function-distinguishes-args/6")
 1177     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-distinguishes-args/7")
 1178     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-distinguishes-args/8")
 1179     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-distinguishes-args/9")
 1180     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-distinguishes-args/10")
 1181     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-distinguishes-args/11")
 1182     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-distinguishes-args/12")
 1183     # . epilogue
 1184     89/<- %esp 5/r32/ebp
 1185     5d/pop-to-ebp
 1186     c3/return
 1187 
 1188 test-convert-function-with-return-literal:
 1189     # . prologue
 1190     55/push-ebp
 1191     89/<- %ebp 4/r32/esp
 1192     # setup
 1193     (clear-stream _test-input-stream)
 1194     (clear-stream $_test-input-buffered-file->buffer)
 1195     (clear-stream _test-output-stream)
 1196     (clear-stream $_test-output-buffered-file->buffer)
 1197     #
 1198     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1199     (write _test-input-stream "  return 0\n")
 1200     (write _test-input-stream "}\n")
 1201     # convert
 1202     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1203     (flush _test-output-buffered-file)
 1204 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 1210     # check output
 1211     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-literal/0")
 1212     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-literal/1")
 1213     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-literal/2")
 1214     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-literal/3")
 1215     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-literal/4")
 1216     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-literal/5")
 1217     (check-next-stream-line-equal _test-output-stream "    c7 0/subop/copy %eax 0/imm32"  "F - test-convert-function-with-return-literal/6")
 1218     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-literal/7")
 1219     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-literal/8")
 1220     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-literal/9")
 1221     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-literal/10")
 1222     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-literal/11")
 1223     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-literal/12")
 1224     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-literal/13")
 1225     # . epilogue
 1226     89/<- %esp 5/r32/ebp
 1227     5d/pop-to-ebp
 1228     c3/return
 1229 
 1230 test-convert-function-with-return:
 1231     # . prologue
 1232     55/push-ebp
 1233     89/<- %ebp 4/r32/esp
 1234     # setup
 1235     (clear-stream _test-input-stream)
 1236     (clear-stream $_test-input-buffered-file->buffer)
 1237     (clear-stream _test-output-stream)
 1238     (clear-stream $_test-output-buffered-file->buffer)
 1239     #
 1240     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1241     (write _test-input-stream "  var y: int\n")
 1242     (write _test-input-stream "  return y\n")
 1243     (write _test-input-stream "}\n")
 1244     # convert
 1245     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1246     (flush _test-output-buffered-file)
 1247 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 1253     # check output
 1254     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return/0")
 1255     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return/1")
 1256     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return/2")
 1257     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return/3")
 1258     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return/4")
 1259     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return/5")
 1260     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-return/6")  # y
 1261     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0xfffffffc) 0x00000000/r32" "F - test-convert-function-with-return/7")
 1262     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-return/8")
 1263     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return/9")
 1264     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return/10")
 1265     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return/11")
 1266     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return/12")
 1267     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return/13")
 1268     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return/14")
 1269     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return/15")
 1270     # . epilogue
 1271     89/<- %esp 5/r32/ebp
 1272     5d/pop-to-ebp
 1273     c3/return
 1274 
 1275 test-convert-function-with-return-register:
 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 -> _/eax: int {\n")
 1286     (write _test-input-stream "  var y/eax: int <- copy 3\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-register/0")
 1300     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register/1")
 1301     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register/2")
 1302     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register/3")
 1303     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register/4")
 1304     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register/5")
 1305     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register/6")
 1306     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-convert-function-with-return-register/7")
 1307     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-return-register/8")
 1308     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-return-register/9")
 1309     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-register/10")
 1310     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register/11")
 1311     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register/12")
 1312     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register/13")
 1313     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register/14")
 1314     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register/15")
 1315     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register/16")
 1316     # . epilogue
 1317     89/<- %esp 5/r32/ebp
 1318     5d/pop-to-ebp
 1319     c3/return
 1320 
 1321 test-function-with-output-without-register:
 1322     # . prologue
 1323     55/push-ebp
 1324     89/<- %ebp 4/r32/esp
 1325     # setup
 1326     (clear-stream _test-input-stream)
 1327     (clear-stream $_test-input-buffered-file->buffer)
 1328     (clear-stream _test-output-stream)
 1329     (clear-stream $_test-output-buffered-file->buffer)
 1330     (clear-stream _test-error-stream)
 1331     (clear-stream $_test-error-buffered-file->buffer)
 1332     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1333     68/push 0/imm32
 1334     68/push 0/imm32
 1335     89/<- %edx 4/r32/esp
 1336     (tailor-exit-descriptor %edx 0x10)
 1337     #
 1338     (write _test-input-stream "fn foo -> _: int {\n")
 1339     (write _test-input-stream "}\n")
 1340     # convert
 1341     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1342     # registers except esp clobbered at this point
 1343     # restore ed
 1344     89/<- %edx 4/r32/esp
 1345     (flush _test-output-buffered-file)
 1346     (flush _test-error-buffered-file)
 1347 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 1353     # check output
 1354     (check-stream-equal _test-output-stream  ""  "F - test-function-with-output-without-register: output should be empty")
 1355     (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")
 1356     # check that stop(1) was called
 1357     (check-ints-equal *(edx+4) 2 "F - test-function-with-output-without-register: exit status")
 1358     # don't restore from ebp
 1359     81 0/subop/add %esp 8/imm32
 1360     # . epilogue
 1361     5d/pop-to-ebp
 1362     c3/return
 1363 
 1364 test-function-with-outputs-in-conflicting-registers:
 1365     # . prologue
 1366     55/push-ebp
 1367     89/<- %ebp 4/r32/esp
 1368     # setup
 1369     (clear-stream _test-input-stream)
 1370     (clear-stream $_test-input-buffered-file->buffer)
 1371     (clear-stream _test-output-stream)
 1372     (clear-stream $_test-output-buffered-file->buffer)
 1373     (clear-stream _test-error-stream)
 1374     (clear-stream $_test-error-buffered-file->buffer)
 1375     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1376     68/push 0/imm32
 1377     68/push 0/imm32
 1378     89/<- %edx 4/r32/esp
 1379     (tailor-exit-descriptor %edx 0x10)
 1380     #
 1381     (write _test-input-stream "fn foo -> _/eax: int, _/eax: int {\n")
 1382     (write _test-input-stream "}\n")
 1383     # convert
 1384     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1385     # registers except esp clobbered at this point
 1386     # restore ed
 1387     89/<- %edx 4/r32/esp
 1388     (flush _test-output-buffered-file)
 1389     (flush _test-error-buffered-file)
 1390 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 1396     # check output
 1397     (check-stream-equal _test-output-stream  ""  "F - test-function-with-outputs-in-conflicting-registers: output should be empty")
 1398     (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")
 1399     # check that stop(1) was called
 1400     (check-ints-equal *(edx+4) 2 "F - test-function-with-outputs-in-conflicting-registers: exit status")
 1401     # don't restore from ebp
 1402     81 0/subop/add %esp 8/imm32
 1403     # . epilogue
 1404     5d/pop-to-ebp
 1405     c3/return
 1406 
 1407 test-function-with-named-output:
 1408     # . prologue
 1409     55/push-ebp
 1410     89/<- %ebp 4/r32/esp
 1411     # setup
 1412     (clear-stream _test-input-stream)
 1413     (clear-stream $_test-input-buffered-file->buffer)
 1414     (clear-stream _test-output-stream)
 1415     (clear-stream $_test-output-buffered-file->buffer)
 1416     (clear-stream _test-error-stream)
 1417     (clear-stream $_test-error-buffered-file->buffer)
 1418     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1419     68/push 0/imm32
 1420     68/push 0/imm32
 1421     89/<- %edx 4/r32/esp
 1422     (tailor-exit-descriptor %edx 0x10)
 1423     #
 1424     (write _test-input-stream "fn foo -> x/eax: int {\n")
 1425     (write _test-input-stream "  return 0\n")
 1426     (write _test-input-stream "}\n")
 1427     # convert
 1428     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1429     # registers except esp clobbered at this point
 1430     # restore ed
 1431     89/<- %edx 4/r32/esp
 1432     (flush _test-output-buffered-file)
 1433     (flush _test-error-buffered-file)
 1434 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 1440     # check output
 1441     (check-stream-equal _test-output-stream  ""  "F - test-function-with-named-output: output should be empty")
 1442     (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")
 1443     # check that stop(1) was called
 1444     (check-ints-equal *(edx+4) 2 "F - test-function-with-named-output: exit status")
 1445     # don't restore from ebp
 1446     81 0/subop/add %esp 8/imm32
 1447     # . epilogue
 1448     5d/pop-to-ebp
 1449     c3/return
 1450 
 1451 test-return-with-wrong-type:
 1452     # . prologue
 1453     55/push-ebp
 1454     89/<- %ebp 4/r32/esp
 1455     # setup
 1456     (clear-stream _test-input-stream)
 1457     (clear-stream $_test-input-buffered-file->buffer)
 1458     (clear-stream _test-output-stream)
 1459     (clear-stream $_test-output-buffered-file->buffer)
 1460     (clear-stream _test-error-stream)
 1461     (clear-stream $_test-error-buffered-file->buffer)
 1462     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1463     68/push 0/imm32
 1464     68/push 0/imm32
 1465     89/<- %edx 4/r32/esp
 1466     (tailor-exit-descriptor %edx 0x10)
 1467     #
 1468     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1469     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 1470     (write _test-input-stream "  return x\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-return-with-wrong-type: output should be empty")
 1487     (check-next-stream-line-equal _test-error-stream  "fn foo: return: 'x' has the wrong type"  "F - test-return-with-wrong-type: error message")
 1488     # check that stop(1) was called
 1489     (check-ints-equal *(edx+4) 2 "F - test-return-with-wrong-type: 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-missing-return:
 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 "}\n")
 1516     # convert
 1517     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1518     # registers except esp clobbered at this point
 1519     # restore ed
 1520     89/<- %edx 4/r32/esp
 1521     (flush _test-output-buffered-file)
 1522     (flush _test-error-buffered-file)
 1523 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 1529     # check output
 1530     (check-stream-equal _test-output-stream  ""  "F - test-missing-return: output should be empty")
 1531     (check-next-stream-line-equal _test-error-stream  "fn foo: final statement should be a 'return'"  "F - test-missing-return: error message")
 1532     # check that stop(1) was called
 1533     (check-ints-equal *(edx+4) 2 "F - test-missing-return: exit status")
 1534     # don't restore from ebp
 1535     81 0/subop/add %esp 8/imm32
 1536     # . epilogue
 1537     5d/pop-to-ebp
 1538     c3/return
 1539 
 1540 test-early-exit-without-return:
 1541     # . prologue
 1542     55/push-ebp
 1543     89/<- %ebp 4/r32/esp
 1544     # setup
 1545     (clear-stream _test-input-stream)
 1546     (clear-stream $_test-input-buffered-file->buffer)
 1547     (clear-stream _test-output-stream)
 1548     (clear-stream $_test-output-buffered-file->buffer)
 1549     (clear-stream _test-error-stream)
 1550     (clear-stream $_test-error-buffered-file->buffer)
 1551     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1552     68/push 0/imm32
 1553     68/push 0/imm32
 1554     89/<- %edx 4/r32/esp
 1555     (tailor-exit-descriptor %edx 0x10)
 1556     #
 1557     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1558     (write _test-input-stream "  break\n")
 1559     (write _test-input-stream "  return 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-early-exit-without-return: output should be empty")
 1576     (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")
 1577     # check that stop(1) was called
 1578     (check-ints-equal *(edx+4) 2 "F - test-early-exit-without-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-return-with-too-few-inouts:
 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 "  return\n")
 1604     (write _test-input-stream "}\n")
 1605     # convert
 1606     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1607     # registers except esp clobbered at this point
 1608     # restore ed
 1609     89/<- %edx 4/r32/esp
 1610     (flush _test-output-buffered-file)
 1611     (flush _test-error-buffered-file)
 1612 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 1618     # check output
 1619     (check-stream-equal _test-output-stream  ""  "F - test-return-with-too-few-inouts: output should be empty")
 1620     (check-next-stream-line-equal _test-error-stream  "fn foo: return: too few inouts"  "F - test-return-with-too-few-inouts: error message")
 1621     # check that stop(1) was called
 1622     (check-ints-equal *(edx+4) 2 "F - test-return-with-too-few-inouts: exit status")
 1623     # don't restore from ebp
 1624     81 0/subop/add %esp 8/imm32
 1625     # . epilogue
 1626     5d/pop-to-ebp
 1627     c3/return
 1628 
 1629 test-return-with-too-many-inouts:
 1630     # . prologue
 1631     55/push-ebp
 1632     89/<- %ebp 4/r32/esp
 1633     # setup
 1634     (clear-stream _test-input-stream)
 1635     (clear-stream $_test-input-buffered-file->buffer)
 1636     (clear-stream _test-output-stream)
 1637     (clear-stream $_test-output-buffered-file->buffer)
 1638     (clear-stream _test-error-stream)
 1639     (clear-stream $_test-error-buffered-file->buffer)
 1640     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1641     68/push 0/imm32
 1642     68/push 0/imm32
 1643     89/<- %edx 4/r32/esp
 1644     (tailor-exit-descriptor %edx 0x10)
 1645     #
 1646     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1647     (write _test-input-stream "  return 0, 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-return-with-too-many-inouts: output should be empty")
 1664     (check-next-stream-line-equal _test-error-stream  "fn foo: return: too many inouts"  "F - test-return-with-too-many-inouts: error message")
 1665     # check that stop(1) was called
 1666     (check-ints-equal *(edx+4) 2 "F - test-return-with-too-many-inouts: 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-unavailable-value:
 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, _/ecx: int {\n")
 1691     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 1692     (write _test-input-stream "  var y/ecx: int <- copy 0\n")
 1693     (write _test-input-stream "  return y, x\n")
 1694     (write _test-input-stream "}\n")
 1695     # convert
 1696     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1697     # registers except esp clobbered at this point
 1698     # restore ed
 1699     89/<- %edx 4/r32/esp
 1700     (flush _test-output-buffered-file)
 1701     (flush _test-error-buffered-file)
 1702 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 1708     # check output
 1709     (check-stream-equal _test-output-stream  ""  "F - test-return-unavailable-value: output should be empty")
 1710     (check-next-stream-line-equal _test-error-stream  "fn foo: return: 'x' is no longer available"  "F - test-return-unavailable-value: error message")
 1711     # check that stop(1) was called
 1712     (check-ints-equal *(edx+4) 2 "F - test-return-unavailable-value: exit status")
 1713     # don't restore from ebp
 1714     81 0/subop/add %esp 8/imm32
 1715     # . epilogue
 1716     5d/pop-to-ebp
 1717     c3/return
 1718 
 1719 test-convert-return-with-duplicate-values:
 1720     # . prologue
 1721     55/push-ebp
 1722     89/<- %ebp 4/r32/esp
 1723     # setup
 1724     (clear-stream _test-input-stream)
 1725     (clear-stream $_test-input-buffered-file->buffer)
 1726     (clear-stream _test-output-stream)
 1727     (clear-stream $_test-output-buffered-file->buffer)
 1728     #
 1729     (write _test-input-stream "fn foo -> _/eax: int, _/ecx: int {\n")
 1730     (write _test-input-stream "  var x/eax: int <- copy 0x34\n")
 1731     (write _test-input-stream "  return x, x\n")
 1732     (write _test-input-stream "}\n")
 1733     # convert
 1734     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1735     (flush _test-output-buffered-file)
 1736 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 1742     # check output
 1743     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-return-with-duplicate-values/0")
 1744     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-return-with-duplicate-values/1")
 1745     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-return-with-duplicate-values/2")
 1746     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-return-with-duplicate-values/3")
 1747     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-return-with-duplicate-values/4")
 1748     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-return-with-duplicate-values/5")
 1749     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-return-with-duplicate-values/6")
 1750     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0x34/imm32"  "F - test-convert-return-with-duplicate-values/7")
 1751     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32"  "F - test-convert-return-with-duplicate-values/8")
 1752     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000001/r32"  "F - test-convert-return-with-duplicate-values/9")
 1753     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-return-with-duplicate-values/10")
 1754     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-return-with-duplicate-values/11")
 1755     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-return-with-duplicate-values/12")
 1756     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-return-with-duplicate-values/13")
 1757     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-return-with-duplicate-values/14")
 1758     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-return-with-duplicate-values/15")
 1759     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-return-with-duplicate-values/16")
 1760     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-return-with-duplicate-values/17")
 1761     # . epilogue
 1762     89/<- %esp 5/r32/ebp
 1763     5d/pop-to-ebp
 1764     c3/return
 1765 
 1766 test-convert-return-with-duplicate-values-2:
 1767     # . prologue
 1768     55/push-ebp
 1769     89/<- %ebp 4/r32/esp
 1770     # setup
 1771     (clear-stream _test-input-stream)
 1772     (clear-stream $_test-input-buffered-file->buffer)
 1773     (clear-stream _test-output-stream)
 1774     (clear-stream $_test-output-buffered-file->buffer)
 1775     #
 1776     (write _test-input-stream "fn foo -> _/eax: int, _/ecx: int {\n")
 1777     (write _test-input-stream "  var x/ecx: int <- copy 0x34\n")
 1778     (write _test-input-stream "  return x, x\n")
 1779     (write _test-input-stream "}\n")
 1780     # convert
 1781     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1782     (flush _test-output-buffered-file)
 1783 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 1789     # check output
 1790     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-return-with-duplicate-values-2/0")
 1791     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-return-with-duplicate-values-2/1")
 1792     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-return-with-duplicate-values-2/2")
 1793     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-return-with-duplicate-values-2/3")
 1794     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-return-with-duplicate-values-2/4")
 1795     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-return-with-duplicate-values-2/5")
 1796     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-return-with-duplicate-values-2/6")
 1797     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0x34/imm32"  "F - test-convert-return-with-duplicate-values-2/7")
 1798     (check-next-stream-line-equal _test-output-stream "    8b/-> %ecx 0x00000000/r32"  "F - test-convert-return-with-duplicate-values-2/8")
 1799     (check-next-stream-line-equal _test-output-stream "    8b/-> %ecx 0x00000001/r32"  "F - test-convert-return-with-duplicate-values-2/9")
 1800     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-return-with-duplicate-values-2/10")
 1801     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-return-with-duplicate-values-2/11")
 1802     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-return-with-duplicate-values-2/12")
 1803     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-return-with-duplicate-values-2/13")
 1804     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-return-with-duplicate-values-2/14")
 1805     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-return-with-duplicate-values-2/15")
 1806     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-return-with-duplicate-values-2/16")
 1807     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-return-with-duplicate-values-2/17")
 1808     # . epilogue
 1809     89/<- %esp 5/r32/ebp
 1810     5d/pop-to-ebp
 1811     c3/return
 1812 
 1813 test-stmt-with-unknown-var:
 1814     # . prologue
 1815     55/push-ebp
 1816     89/<- %ebp 4/r32/esp
 1817     # setup
 1818     (clear-stream _test-input-stream)
 1819     (clear-stream $_test-input-buffered-file->buffer)
 1820     (clear-stream _test-output-stream)
 1821     (clear-stream $_test-output-buffered-file->buffer)
 1822     (clear-stream _test-error-stream)
 1823     (clear-stream $_test-error-buffered-file->buffer)
 1824     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1825     68/push 0/imm32
 1826     68/push 0/imm32
 1827     89/<- %edx 4/r32/esp
 1828     (tailor-exit-descriptor %edx 0x10)
 1829     #
 1830     (write _test-input-stream "fn foo {\n")
 1831     (write _test-input-stream "  x <- copy 0x34\n")
 1832     (write _test-input-stream "}\n")
 1833     # convert
 1834     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1835     # registers except esp clobbered at this point
 1836     # restore ed
 1837     89/<- %edx 4/r32/esp
 1838     (flush _test-output-buffered-file)
 1839     (flush _test-error-buffered-file)
 1840 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 1846     # check output
 1847     (check-stream-equal _test-output-stream  ""  "F - test-stmt-with-unknown-var: output should be empty")
 1848     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-stmt-with-unknown-var: error message")
 1849     # check that stop(1) was called
 1850     (check-ints-equal *(edx+4) 2 "F - test-stmt-with-unknown-var: exit status")
 1851     # don't restore from ebp
 1852     81 0/subop/add %esp 8/imm32
 1853     # . epilogue
 1854     5d/pop-to-ebp
 1855     c3/return
 1856 
 1857 test-stmt-with-invalid-identifier:
 1858     # . prologue
 1859     55/push-ebp
 1860     89/<- %ebp 4/r32/esp
 1861     # setup
 1862     (clear-stream _test-input-stream)
 1863     (clear-stream $_test-input-buffered-file->buffer)
 1864     (clear-stream _test-output-stream)
 1865     (clear-stream $_test-output-buffered-file->buffer)
 1866     (clear-stream _test-error-stream)
 1867     (clear-stream $_test-error-buffered-file->buffer)
 1868     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1869     68/push 0/imm32
 1870     68/push 0/imm32
 1871     89/<- %edx 4/r32/esp
 1872     (tailor-exit-descriptor %edx 0x10)
 1873     #
 1874     (write _test-input-stream "fn foo {\n")
 1875     (write _test-input-stream "  1 <- copy 0x34\n")
 1876     (write _test-input-stream "}\n")
 1877     # convert
 1878     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1879     # registers except esp clobbered at this point
 1880     # restore ed
 1881     89/<- %edx 4/r32/esp
 1882     (flush _test-output-buffered-file)
 1883     (flush _test-error-buffered-file)
 1884 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 1890     # check output
 1891     (check-stream-equal _test-output-stream  ""  "F - test-stmt-with-invalid-identifier: output should be empty")
 1892     (check-next-stream-line-equal _test-error-stream  "fn foo: invalid identifier '1'"  "F - test-stmt-with-invalid-identifier: error message")
 1893     # check that stop(1) was called
 1894     (check-ints-equal *(edx+4) 2 "F - test-stmt-with-invalid-identifier: exit status")
 1895     # don't restore from ebp
 1896     81 0/subop/add %esp 8/imm32
 1897     # . epilogue
 1898     5d/pop-to-ebp
 1899     c3/return
 1900 
 1901 test-stmt-with-deref-var:
 1902     # . prologue
 1903     55/push-ebp
 1904     89/<- %ebp 4/r32/esp
 1905     # setup
 1906     (clear-stream _test-input-stream)
 1907     (clear-stream $_test-input-buffered-file->buffer)
 1908     (clear-stream _test-output-stream)
 1909     (clear-stream $_test-output-buffered-file->buffer)
 1910     (clear-stream _test-error-stream)
 1911     (clear-stream $_test-error-buffered-file->buffer)
 1912     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1913     68/push 0/imm32
 1914     68/push 0/imm32
 1915     89/<- %edx 4/r32/esp
 1916     (tailor-exit-descriptor %edx 0x10)
 1917     #
 1918     (write _test-input-stream "fn foo {\n")
 1919     (write _test-input-stream "  *x <- copy 0x34\n")
 1920     (write _test-input-stream "}\n")
 1921     # convert
 1922     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1923     # registers except esp clobbered at this point
 1924     # restore ed
 1925     89/<- %edx 4/r32/esp
 1926     (flush _test-output-buffered-file)
 1927     (flush _test-error-buffered-file)
 1928 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 1934     # check output
 1935     (check-stream-equal _test-output-stream  ""  "F - test-stmt-with-deref-var: output should be empty")
 1936     (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")
 1937     # check that stop(1) was called
 1938     (check-ints-equal *(edx+4) 2 "F - test-stmt-with-deref-var: exit status")
 1939     # don't restore from ebp
 1940     81 0/subop/add %esp 8/imm32
 1941     # . epilogue
 1942     5d/pop-to-ebp
 1943     c3/return
 1944 
 1945 test-convert-function-with-literal-arg:
 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     #
 1955     (write _test-input-stream "fn foo a: int, b: int -> _/eax: int {\n")
 1956     (write _test-input-stream "  var result/eax: int <- copy a\n")
 1957     (write _test-input-stream "  result <- add 1\n")
 1958     (write _test-input-stream "  return result\n")
 1959     (write _test-input-stream "}\n")
 1960     # convert
 1961     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1962     (flush _test-output-buffered-file)
 1963 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 1969     # check output
 1970     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-literal-arg/0")
 1971     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-literal-arg/1")
 1972     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-literal-arg/2")
 1973     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-literal-arg/3")
 1974     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-literal-arg/4")
 1975     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-literal-arg/5")
 1976     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-literal-arg/6")
 1977     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-with-literal-arg/7")
 1978     (check-next-stream-line-equal _test-output-stream "    05/add-to-eax 1/imm32"  "F - test-convert-function-with-literal-arg/8")
 1979     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-literal-arg/9")
 1980     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-literal-arg/10")
 1981     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-literal-arg/11")
 1982     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-literal-arg/12")
 1983     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-literal-arg/13")
 1984     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-literal-arg/14")
 1985     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-literal-arg/15")
 1986     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-literal-arg/16")
 1987     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-literal-arg/17")
 1988     # . epilogue
 1989     89/<- %esp 5/r32/ebp
 1990     5d/pop-to-ebp
 1991     c3/return
 1992 
 1993 test-convert-function-with-literal-arg-2:
 1994     # . prologue
 1995     55/push-ebp
 1996     89/<- %ebp 4/r32/esp
 1997     # setup
 1998     (clear-stream _test-input-stream)
 1999     (clear-stream $_test-input-buffered-file->buffer)
 2000     (clear-stream _test-output-stream)
 2001     (clear-stream $_test-output-buffered-file->buffer)
 2002     #
 2003     (write _test-input-stream "fn foo a: int, b: int -> _/ebx: int {\n")
 2004     (write _test-input-stream "  var result/ebx: int <- copy a\n")
 2005     (write _test-input-stream "  result <- add 1\n")
 2006     (write _test-input-stream "  return result\n")
 2007     (write _test-input-stream "}\n")
 2008     # convert
 2009     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2010     (flush _test-output-buffered-file)
 2011 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 2017     # check output
 2018     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-literal-arg-2/0")
 2019     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-literal-arg-2/1")
 2020     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-literal-arg-2/2")
 2021     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-literal-arg-2/3")
 2022     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-literal-arg-2/4")
 2023     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-literal-arg-2/5")
 2024     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-with-literal-arg-2/6")
 2025     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000003/r32"  "F - test-convert-function-with-literal-arg-2/7")
 2026     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %ebx 1/imm32"  "F - test-convert-function-with-literal-arg-2/8")
 2027     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-with-literal-arg-2/9")
 2028     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-literal-arg-2/10")
 2029     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-literal-arg-2/11")
 2030     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-literal-arg-2/12")
 2031     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-literal-arg-2/13")
 2032     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-literal-arg-2/14")
 2033     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-literal-arg-2/15")
 2034     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-literal-arg-2/16")
 2035     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-literal-arg-2/17")
 2036     # . epilogue
 2037     89/<- %esp 5/r32/ebp
 2038     5d/pop-to-ebp
 2039     c3/return
 2040 
 2041 test-convert-function-call-with-literal-arg:
 2042     # . prologue
 2043     55/push-ebp
 2044     89/<- %ebp 4/r32/esp
 2045     # setup
 2046     (clear-stream _test-input-stream)
 2047     (clear-stream $_test-input-buffered-file->buffer)
 2048     (clear-stream _test-output-stream)
 2049     (clear-stream $_test-output-buffered-file->buffer)
 2050     #
 2051     (write _test-input-stream "fn main -> _/ebx: int {\n")
 2052     (write _test-input-stream "  var result/eax: int <- do-add 3 4\n")
 2053     (write _test-input-stream "  return result\n")
 2054     (write _test-input-stream "}\n")
 2055     (write _test-input-stream "fn do-add a: int, b: int -> _/eax: int {\n")
 2056     (write _test-input-stream "  var result/eax: int <- copy a\n")
 2057     (write _test-input-stream "  result <- add b\n")
 2058     (write _test-input-stream "  return result\n")
 2059     (write _test-input-stream "}\n")
 2060     # convert
 2061     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2062     (flush _test-output-buffered-file)
 2063 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 2069     # check output
 2070     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call-with-literal-arg/0")
 2071     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-literal-arg/1")
 2072     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-literal-arg/2")
 2073     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-literal-arg/3")
 2074     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-literal-arg/4")
 2075     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call-with-literal-arg/5")
 2076     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/6")
 2077     (check-next-stream-line-equal _test-output-stream "    (do-add 3 4)"        "F - test-convert-function-call-with-literal-arg/7")
 2078     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 2079     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-with-local-var-in-reg/9")
 2080     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 2081     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-literal-arg/11")
 2082     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call-with-literal-arg/12")
 2083     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-literal-arg/13")
 2084     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-literal-arg/14")
 2085     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-literal-arg/15")
 2086     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-literal-arg/16")
 2087     (check-next-stream-line-equal _test-output-stream "do-add:"                 "F - test-convert-function-call-with-literal-arg/17")
 2088     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-literal-arg/18")
 2089     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-literal-arg/19")
 2090     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-literal-arg/20")
 2091     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-literal-arg/21")
 2092     (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:loop:"  "F - test-convert-function-call-with-literal-arg/22")
 2093     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/23")
 2094     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-call-with-literal-arg/24")
 2095     (check-next-stream-line-equal _test-output-stream "    03/add *(ebp+0x0000000c) 0x00000000/r32"  "F - test-convert-function-call-with-literal-arg/25")
 2096     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-call-with-literal-arg/26")
 2097     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
 2098     (check-next-stream-line-equal _test-output-stream "    e9/jump $do-add:0x00000002:break/disp32"  "F - test-convert-function-call-with-literal-arg/28")
 2099     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-literal-arg/29")
 2100     (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:break:"  "F - test-convert-function-call-with-literal-arg/30")
 2101     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-literal-arg/31")
 2102     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-literal-arg/32")
 2103     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-literal-arg/33")
 2104     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-literal-arg/34")
 2105     # . epilogue
 2106     89/<- %esp 5/r32/ebp
 2107     5d/pop-to-ebp
 2108     c3/return
 2109 
 2110 test-convert-function-call-with-literal-string-arg:
 2111     # . prologue
 2112     55/push-ebp
 2113     89/<- %ebp 4/r32/esp
 2114     # setup
 2115     (clear-stream _test-input-stream)
 2116     (clear-stream $_test-input-buffered-file->buffer)
 2117     (clear-stream _test-output-stream)
 2118     (clear-stream $_test-output-buffered-file->buffer)
 2119     #
 2120     (write _test-input-stream "fn foo {\n")
 2121     (write _test-input-stream "  string-func \"abc\"\n")
 2122     (write _test-input-stream "}\n")
 2123     (write _test-input-stream "sig string-func in: (addr array byte)\n")
 2124     # convert
 2125     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2126     # no errors
 2127     # not bothering checking output
 2128     # . epilogue
 2129     89/<- %esp 5/r32/ebp
 2130     5d/pop-to-ebp
 2131     c3/return
 2132 
 2133 test-convert-function-call-with-null-addr:
 2134     # . prologue
 2135     55/push-ebp
 2136     89/<- %ebp 4/r32/esp
 2137     # setup
 2138     (clear-stream _test-input-stream)
 2139     (clear-stream $_test-input-buffered-file->buffer)
 2140     (clear-stream _test-output-stream)
 2141     (clear-stream $_test-output-buffered-file->buffer)
 2142     #
 2143     (write _test-input-stream "fn foo {\n")
 2144     (write _test-input-stream "  bar 0\n")
 2145     (write _test-input-stream "}\n")
 2146     (write _test-input-stream "sig bar in: (addr int)\n")
 2147     # convert
 2148     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2149     # no errors
 2150     # not bothering checking output
 2151     # . epilogue
 2152     89/<- %esp 5/r32/ebp
 2153     5d/pop-to-ebp
 2154     c3/return
 2155 
 2156 test-convert-function-call-with-signature:
 2157     # . prologue
 2158     55/push-ebp
 2159     89/<- %ebp 4/r32/esp
 2160     # setup
 2161     (clear-stream _test-input-stream)
 2162     (clear-stream $_test-input-buffered-file->buffer)
 2163     (clear-stream _test-output-stream)
 2164     (clear-stream $_test-output-buffered-file->buffer)
 2165     #
 2166     (write _test-input-stream "fn main -> _/ebx: int {\n")
 2167     (write _test-input-stream "  var result/eax: int <- do-add 3 4\n")
 2168     (write _test-input-stream "  return result\n")
 2169     (write _test-input-stream "}\n")
 2170     (write _test-input-stream "sig do-add a: int, b: int -> _/eax: int\n")
 2171     # convert
 2172     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2173     (flush _test-output-buffered-file)
 2174 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 2180     # check output
 2181     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call-with-signature/0")
 2182     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-signature/1")
 2183     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-signature/2")
 2184     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-signature/3")
 2185     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-signature/4")
 2186     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call-with-signature/5")
 2187     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/6")
 2188     (check-next-stream-line-equal _test-output-stream "    (do-add 3 4)"        "F - test-convert-function-call-with-signature/6")
 2189     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 2190     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-with-local-var-in-reg/9")
 2191     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 2192     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-signature/7")
 2193     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call-with-signature/8")
 2194     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-signature/9")
 2195     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-signature/10")
 2196     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-signature/11")
 2197     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-signature/12")
 2198     # . epilogue
 2199     89/<- %esp 5/r32/ebp
 2200     5d/pop-to-ebp
 2201     c3/return
 2202 
 2203 test-convert-function-with-local-var-in-mem:
 2204     # . prologue
 2205     55/push-ebp
 2206     89/<- %ebp 4/r32/esp
 2207     # setup
 2208     (clear-stream _test-input-stream)
 2209     (clear-stream $_test-input-buffered-file->buffer)
 2210     (clear-stream _test-output-stream)
 2211     (clear-stream $_test-output-buffered-file->buffer)
 2212     #
 2213     (write _test-input-stream "fn foo {\n")
 2214     (write _test-input-stream "  var x: int\n")
 2215     (write _test-input-stream "  increment x\n")
 2216     (write _test-input-stream "}\n")
 2217     # convert
 2218     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2219     (flush _test-output-buffered-file)
 2220 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 2226     # check output
 2227     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-mem/0")
 2228     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-mem/1")
 2229     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-mem/2")
 2230     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-mem/3")
 2231     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-mem/4")
 2232     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-mem/5")
 2233     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-in-mem/6")
 2234     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-local-var-in-mem/7")
 2235     (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")
 2236     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-mem/9")
 2237     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-mem/10")
 2238     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-mem/11")
 2239     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-mem/12")
 2240     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-mem/13")
 2241     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-mem/14")
 2242     # . epilogue
 2243     89/<- %esp 5/r32/ebp
 2244     5d/pop-to-ebp
 2245     c3/return
 2246 
 2247 test-convert-invalid-literal:
 2248     # . prologue
 2249     55/push-ebp
 2250     89/<- %ebp 4/r32/esp
 2251     # setup
 2252     (clear-stream _test-input-stream)
 2253     (clear-stream $_test-input-buffered-file->buffer)
 2254     (clear-stream _test-output-stream)
 2255     (clear-stream $_test-output-buffered-file->buffer)
 2256     (clear-stream _test-error-stream)
 2257     (clear-stream $_test-error-buffered-file->buffer)
 2258     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2259     68/push 0/imm32
 2260     68/push 0/imm32
 2261     89/<- %edx 4/r32/esp
 2262     (tailor-exit-descriptor %edx 0x10)
 2263     #
 2264     (write _test-input-stream "fn foo {\n")
 2265     (write _test-input-stream "  increment 1n\n")
 2266     (write _test-input-stream "}\n")
 2267     # convert
 2268     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2269     # registers except esp clobbered at this point
 2270     # restore ed
 2271     89/<- %edx 4/r32/esp
 2272     (flush _test-output-buffered-file)
 2273     (flush _test-error-buffered-file)
 2274 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 2280     # check output
 2281     (check-stream-equal _test-output-stream  ""  "F - test-convert-invalid-literal: output should be empty")
 2282     (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")
 2283     # check that stop(1) was called
 2284     (check-ints-equal *(edx+4) 2 "F - test-convert-invalid-literal: exit status")
 2285     # don't restore from ebp
 2286     81 0/subop/add %esp 8/imm32
 2287     # . epilogue
 2288     5d/pop-to-ebp
 2289     c3/return
 2290 
 2291 test-local-var-in-mem-has-no-initializer:
 2292     # . prologue
 2293     55/push-ebp
 2294     89/<- %ebp 4/r32/esp
 2295     # setup
 2296     (clear-stream _test-input-stream)
 2297     (clear-stream $_test-input-buffered-file->buffer)
 2298     (clear-stream _test-output-stream)
 2299     (clear-stream $_test-output-buffered-file->buffer)
 2300     (clear-stream _test-error-stream)
 2301     (clear-stream $_test-error-buffered-file->buffer)
 2302     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2303     68/push 0/imm32
 2304     68/push 0/imm32
 2305     89/<- %edx 4/r32/esp
 2306     (tailor-exit-descriptor %edx 0x10)
 2307     #
 2308     (write _test-input-stream "fn foo {\n")
 2309     (write _test-input-stream "  var x: int <- copy 0\n")
 2310     (write _test-input-stream "  increment x\n")
 2311     (write _test-input-stream "}\n")
 2312     # convert
 2313     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2314     # registers except esp clobbered at this point
 2315     # restore ed
 2316     89/<- %edx 4/r32/esp
 2317     (flush _test-output-buffered-file)
 2318     (flush _test-error-buffered-file)
 2319 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 2325     # check output
 2326     (check-stream-equal _test-output-stream  ""  "F - test-var-in-mem-has-no-initializer: output should be empty")
 2327     (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")
 2328     # check that stop(1) was called
 2329     (check-ints-equal *(edx+4) 2 "F - test-var-in-mem-has-no-initializer: exit status")
 2330     # don't restore from ebp
 2331     81 0/subop/add %esp 8/imm32
 2332     # . epilogue
 2333     5d/pop-to-ebp
 2334     c3/return
 2335 
 2336 test-convert-function-with-local-var-with-compound-type-in-mem:
 2337     # . prologue
 2338     55/push-ebp
 2339     89/<- %ebp 4/r32/esp
 2340     # setup
 2341     (clear-stream _test-input-stream)
 2342     (clear-stream $_test-input-buffered-file->buffer)
 2343     (clear-stream _test-output-stream)
 2344     (clear-stream $_test-output-buffered-file->buffer)
 2345     #
 2346     (write _test-input-stream "fn foo {\n")
 2347     (write _test-input-stream "  var x: (addr int)\n")
 2348     (write _test-input-stream "  copy-to x, 0\n")
 2349     (write _test-input-stream "}\n")
 2350     # convert
 2351     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2352     (flush _test-output-buffered-file)
 2353 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 2359     # check output
 2360     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-with-compound-type-in-mem/0")
 2361     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-with-compound-type-in-mem/1")
 2362     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-with-compound-type-in-mem/2")
 2363     (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")
 2364     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-compound-type-in-mem/4")
 2365     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-with-compound-type-in-mem/5")
 2366     (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")
 2367     (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")
 2368     (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")
 2369     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-compound-type-in-mem/9")
 2370     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-with-compound-type-in-mem/10")
 2371     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-with-compound-type-in-mem/11")
 2372     (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")
 2373     (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")
 2374     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-with-compound-type-in-mem/14")
 2375     # . epilogue
 2376     89/<- %esp 5/r32/ebp
 2377     5d/pop-to-ebp
 2378     c3/return
 2379 
 2380 test-convert-function-with-local-var-in-reg:
 2381     # . prologue
 2382     55/push-ebp
 2383     89/<- %ebp 4/r32/esp
 2384     # setup
 2385     (clear-stream _test-input-stream)
 2386     (clear-stream $_test-input-buffered-file->buffer)
 2387     (clear-stream _test-output-stream)
 2388     (clear-stream $_test-output-buffered-file->buffer)
 2389     #
 2390     (write _test-input-stream "fn foo {\n")
 2391     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2392     (write _test-input-stream "  x <- increment\n")
 2393     (write _test-input-stream "}\n")
 2394     # convert
 2395     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2396     (flush _test-output-buffered-file)
 2397 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 2403     # check output
 2404     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-reg/0")
 2405     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-reg/1")
 2406     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-reg/2")
 2407     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-reg/3")
 2408     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-reg/4")
 2409     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-reg/5")
 2410     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-in-reg/6")
 2411     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-convert-function-with-local-var-in-reg/7")
 2412     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-convert-function-with-local-var-in-reg/8")
 2413     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-in-reg/9")
 2414     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-reg/10")
 2415     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-reg/11")
 2416     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-reg/12")
 2417     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-reg/13")
 2418     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-reg/14")
 2419     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-reg/15")
 2420     # . epilogue
 2421     89/<- %esp 5/r32/ebp
 2422     5d/pop-to-ebp
 2423     c3/return
 2424 
 2425 test-float-var-in-wrong-register:
 2426     # . prologue
 2427     55/push-ebp
 2428     89/<- %ebp 4/r32/esp
 2429     # setup
 2430     (clear-stream _test-input-stream)
 2431     (clear-stream $_test-input-buffered-file->buffer)
 2432     (clear-stream _test-output-stream)
 2433     (clear-stream $_test-output-buffered-file->buffer)
 2434     (clear-stream _test-error-stream)
 2435     (clear-stream $_test-error-buffered-file->buffer)
 2436     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2437     68/push 0/imm32
 2438     68/push 0/imm32
 2439     89/<- %edx 4/r32/esp
 2440     (tailor-exit-descriptor %edx 0x10)
 2441     #
 2442     (write _test-input-stream "fn foo {\n")
 2443     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 2444     (write _test-input-stream "  var y/eax: float <- convert x\n")
 2445     (write _test-input-stream "}\n")
 2446     # convert
 2447     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2448     # registers except esp clobbered at this point
 2449     # restore ed
 2450     89/<- %edx 4/r32/esp
 2451     (flush _test-output-buffered-file)
 2452     (flush _test-error-buffered-file)
 2453 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 2459     # check output
 2460     (check-stream-equal _test-output-stream  ""  "F - test-float-var-in-wrong-register: output should be empty")
 2461     (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")
 2462     # check that stop(1) was called
 2463     (check-ints-equal *(edx+4) 2 "F - test-float-var-in-wrong-register: exit status")
 2464     # don't restore from ebp
 2465     81 0/subop/add %esp 8/imm32
 2466     # . epilogue
 2467     5d/pop-to-ebp
 2468     c3/return
 2469 
 2470 test-non-float-var-in-wrong-register:
 2471     # . prologue
 2472     55/push-ebp
 2473     89/<- %ebp 4/r32/esp
 2474     # setup
 2475     (clear-stream _test-input-stream)
 2476     (clear-stream $_test-input-buffered-file->buffer)
 2477     (clear-stream _test-output-stream)
 2478     (clear-stream $_test-output-buffered-file->buffer)
 2479     (clear-stream _test-error-stream)
 2480     (clear-stream $_test-error-buffered-file->buffer)
 2481     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2482     68/push 0/imm32
 2483     68/push 0/imm32
 2484     89/<- %edx 4/r32/esp
 2485     (tailor-exit-descriptor %edx 0x10)
 2486     #
 2487     (write _test-input-stream "fn foo {\n")
 2488     (write _test-input-stream "  var x/xmm5: int <- copy 0\n")
 2489     (write _test-input-stream "}\n")
 2490     # convert
 2491     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2492     # registers except esp clobbered at this point
 2493     # restore ed
 2494     89/<- %edx 4/r32/esp
 2495     (flush _test-output-buffered-file)
 2496     (flush _test-error-buffered-file)
 2497 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 2503     # check output
 2504     (check-stream-equal _test-output-stream  ""  "F - test-non-float-var-in-wrong-register: output should be empty")
 2505     (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")
 2506     # check that stop(1) was called
 2507     (check-ints-equal *(edx+4) 2 "F - test-non-float-var-in-wrong-register: exit status")
 2508     # don't restore from ebp
 2509     81 0/subop/add %esp 8/imm32
 2510     # . epilogue
 2511     5d/pop-to-ebp
 2512     c3/return
 2513 
 2514 test-convert-function-with-allocate:
 2515     # . prologue
 2516     55/push-ebp
 2517     89/<- %ebp 4/r32/esp
 2518     # setup
 2519     (clear-stream _test-input-stream)
 2520     (clear-stream $_test-input-buffered-file->buffer)
 2521     (clear-stream _test-output-stream)
 2522     (clear-stream $_test-output-buffered-file->buffer)
 2523     #
 2524     (write _test-input-stream "fn foo {\n")
 2525     (write _test-input-stream "  var x/ecx: (addr handle int) <- copy 0\n")
 2526     (write _test-input-stream "  allocate x\n")
 2527     (write _test-input-stream "}\n")
 2528     # convert
 2529     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2530     (flush _test-output-buffered-file)
 2531 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 2537     # check output
 2538     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-allocate/0")
 2539     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-allocate/1")
 2540     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-allocate/2")
 2541     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-allocate/3")
 2542     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-allocate/4")
 2543     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-allocate/5")
 2544     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-allocate/6")
 2545     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-allocate/7")
 2546     (check-next-stream-line-equal _test-output-stream "    (allocate Heap 0x00000004 %ecx)"  "F - test-convert-function-with-allocate/8")  # 4 = size-of(int)
 2547     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-allocate/9")
 2548     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-allocate/10")
 2549     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-allocate/11")
 2550     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-allocate/12")
 2551     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-allocate/13")
 2552     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-allocate/14")
 2553     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-allocate/15")
 2554     # . epilogue
 2555     89/<- %esp 5/r32/ebp
 2556     5d/pop-to-ebp
 2557     c3/return
 2558 
 2559 test-initializer-in-hex:
 2560     # . prologue
 2561     55/push-ebp
 2562     89/<- %ebp 4/r32/esp
 2563     # setup
 2564     (clear-stream _test-input-stream)
 2565     (clear-stream $_test-input-buffered-file->buffer)
 2566     (clear-stream _test-output-stream)
 2567     (clear-stream $_test-output-buffered-file->buffer)
 2568     (clear-stream _test-error-stream)
 2569     (clear-stream $_test-error-buffered-file->buffer)
 2570     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2571     68/push 0/imm32
 2572     68/push 0/imm32
 2573     89/<- %edx 4/r32/esp
 2574     (tailor-exit-descriptor %edx 0x10)
 2575     #
 2576     (write _test-input-stream "fn foo {\n")
 2577     (write _test-input-stream "  var x/ecx: int <- copy 10\n")
 2578     (write _test-input-stream "}\n")
 2579     # convert
 2580     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2581     # registers except esp clobbered at this point
 2582     # restore ed
 2583     89/<- %edx 4/r32/esp
 2584     (flush _test-output-buffered-file)
 2585     (flush _test-error-buffered-file)
 2586 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 2592     # check output
 2593     (check-stream-equal _test-output-stream  ""  "F - test-initializer-in-hex: output should be empty")
 2594     (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")
 2595     # check that stop(1) was called
 2596     (check-ints-equal *(edx+4) 2 "F - test-initializer-in-hex: exit status")
 2597     # don't restore from ebp
 2598     81 0/subop/add %esp 8/imm32
 2599     # . epilogue
 2600     5d/pop-to-ebp
 2601     c3/return
 2602 
 2603 test-convert-function-with-second-local-var-in-same-reg:
 2604     # . prologue
 2605     55/push-ebp
 2606     89/<- %ebp 4/r32/esp
 2607     # setup
 2608     (clear-stream _test-input-stream)
 2609     (clear-stream $_test-input-buffered-file->buffer)
 2610     (clear-stream _test-output-stream)
 2611     (clear-stream $_test-output-buffered-file->buffer)
 2612     #
 2613     (write _test-input-stream "fn foo {\n")
 2614     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2615     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 2616     (write _test-input-stream "  y <- increment\n")
 2617     (write _test-input-stream "}\n")
 2618     # convert
 2619     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2620     (flush _test-output-buffered-file)
 2621 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 2627     # check output
 2628     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-second-local-var-in-same-reg/0")
 2629     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-second-local-var-in-same-reg/1")
 2630     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-second-local-var-in-same-reg/2")
 2631     (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")
 2632     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-second-local-var-in-same-reg/4")
 2633     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-second-local-var-in-same-reg/5")
 2634     (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")
 2635     (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")
 2636     (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")
 2637     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-convert-function-with-second-local-var-in-same-reg/9")
 2638     (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")
 2639     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-second-local-var-in-same-reg/11")
 2640     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-second-local-var-in-same-reg/12")
 2641     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-second-local-var-in-same-reg/13")
 2642     (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")
 2643     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-second-local-var-in-same-reg/15")
 2644     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-second-local-var-in-same-reg/16")
 2645     # . epilogue
 2646     89/<- %esp 5/r32/ebp
 2647     5d/pop-to-ebp
 2648     c3/return
 2649 
 2650 test-read-clobbered-reg-var:
 2651     # . prologue
 2652     55/push-ebp
 2653     89/<- %ebp 4/r32/esp
 2654     # setup
 2655     (clear-stream _test-input-stream)
 2656     (clear-stream $_test-input-buffered-file->buffer)
 2657     (clear-stream _test-output-stream)
 2658     (clear-stream $_test-output-buffered-file->buffer)
 2659     (clear-stream _test-error-stream)
 2660     (clear-stream $_test-error-buffered-file->buffer)
 2661     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
 2662     68/push 0/imm32
 2663     68/push 0/imm32
 2664     89/<- %edx 4/r32/esp
 2665     (tailor-exit-descriptor %edx 0x10)
 2666     #
 2667     (write _test-input-stream "fn foo {\n")
 2668     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2669     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 2670     (write _test-input-stream "  x <- increment\n")
 2671     (write _test-input-stream "}\n")
 2672     # convert
 2673     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2674     # registers except esp clobbered at this point
 2675     # restore ed
 2676     89/<- %edx 4/r32/esp
 2677     (flush _test-output-buffered-file)
 2678     (flush _test-error-buffered-file)
 2679 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 2685     # check output
 2686     (check-stream-equal _test-output-stream  ""  "F - test-read-clobbered-reg-var: output should be empty")
 2687     (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")
 2688     # check that stop(1) was called
 2689     (check-ints-equal *(edx+4) 2 "F - test-read-clobbered-reg-var: exit status")
 2690     # don't restore from ebp
 2691     81 0/subop/add %esp 8/imm32
 2692     # . epilogue
 2693     5d/pop-to-ebp
 2694     c3/return
 2695 
 2696 test-overlapping-int-fp-registers:
 2697     # . prologue
 2698     55/push-ebp
 2699     89/<- %ebp 4/r32/esp
 2700     # setup
 2701     (clear-stream _test-input-stream)
 2702     (clear-stream $_test-input-buffered-file->buffer)
 2703     (clear-stream _test-output-stream)
 2704     (clear-stream $_test-output-buffered-file->buffer)
 2705     (clear-stream _test-error-stream)
 2706     (clear-stream $_test-error-buffered-file->buffer)
 2707     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
 2708     68/push 0/imm32
 2709     68/push 0/imm32
 2710     89/<- %edx 4/r32/esp
 2711     (tailor-exit-descriptor %edx 0x10)
 2712     #
 2713     (write _test-input-stream "fn foo {\n")
 2714     (write _test-input-stream "  var x/eax: int <- copy 3\n")
 2715     (write _test-input-stream "  var y/xmm0: float <- convert x\n")
 2716     (write _test-input-stream "  x <- increment\n")
 2717     (write _test-input-stream "}\n")
 2718     # convert
 2719     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2720     # registers except esp clobbered at this point
 2721     # restore ed
 2722     89/<- %edx 4/r32/esp
 2723     (flush _test-output-buffered-file)
 2724     (flush _test-error-buffered-file)
 2725 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 2731     # no errors
 2732     (check-next-stream-line-equal _test-error-stream  ""  "F - test-overlapping-int-fp-registers: error message")
 2733     # don't bother checking the generated code
 2734     # don't restore from ebp
 2735     81 0/subop/add %esp 8/imm32
 2736     # . epilogue
 2737     5d/pop-to-ebp
 2738     c3/return
 2739 
 2740 test-convert-function-call:
 2741     # . prologue
 2742     55/push-ebp
 2743     89/<- %ebp 4/r32/esp
 2744     # setup
 2745     (clear-stream _test-input-stream)
 2746     (clear-stream $_test-input-buffered-file->buffer)
 2747     (clear-stream _test-output-stream)
 2748     (clear-stream $_test-output-buffered-file->buffer)
 2749     #
 2750     (write _test-input-stream "fn main -> _/ebx: int {\n")
 2751     (write _test-input-stream "  var result/ebx: int <- foo\n")
 2752     (write _test-input-stream "  return result\n")
 2753     (write _test-input-stream "}\n")
 2754     (write _test-input-stream "fn foo -> _/ebx: int {\n")
 2755     (write _test-input-stream "  var result/ebx: int <- copy 3\n")
 2756     (write _test-input-stream "  return result\n")
 2757     (write _test-input-stream "}\n")
 2758     # convert
 2759     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2760     (flush _test-output-buffered-file)
 2761 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 2767     # check output
 2768     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call/0")
 2769     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call/1")
 2770     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call/2")
 2771     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call/3")
 2772     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call/4")
 2773     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call/5")
 2774     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-call-with-literal-arg/6")
 2775     (check-next-stream-line-equal _test-output-stream "    (foo)"               "F - test-convert-function-call/6")
 2776     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 2777     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
 2778     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 2779     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call/7")
 2780     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call/8")
 2781     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call/9")
 2782     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call/10")
 2783     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call/11")
 2784     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call/12")
 2785     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call/13")
 2786     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call/14")
 2787     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call/15")
 2788     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call/16")
 2789     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call/17")
 2790     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"  "F - test-convert-function-call/18")
 2791     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-call-with-literal-arg/6")
 2792     (check-next-stream-line-equal _test-output-stream "    bb/copy-to-ebx 3/imm32"  "F - test-convert-function-call/19")
 2793     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 2794     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
 2795     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 2796     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call/20")
 2797     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-call/21")
 2798     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call/22")
 2799     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call/23")
 2800     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call/24")
 2801     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call/25")
 2802     # . epilogue
 2803     89/<- %esp 5/r32/ebp
 2804     5d/pop-to-ebp
 2805     c3/return
 2806 
 2807 test-convert-function-call-with-inout-with-compound-type:
 2808     # . prologue
 2809     55/push-ebp
 2810     89/<- %ebp 4/r32/esp
 2811     # setup
 2812     (clear-stream _test-input-stream)
 2813     (clear-stream $_test-input-buffered-file->buffer)
 2814     (clear-stream _test-output-stream)
 2815     (clear-stream $_test-output-buffered-file->buffer)
 2816     #
 2817     (write _test-input-stream "fn f {\n")
 2818     (write _test-input-stream "  var x: (addr int)\n")
 2819     (write _test-input-stream "  g x\n")
 2820     (write _test-input-stream "}\n")
 2821     (write _test-input-stream "fn g a: (addr int) {\n")
 2822     (write _test-input-stream "}\n")
 2823     # convert
 2824     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2825     (flush _test-output-buffered-file)
 2826 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 2832     # check output
 2833     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-inout-with-compound-type/0")
 2834     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-inout-with-compound-type/1")
 2835     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-inout-with-compound-type/2")
 2836     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-inout-with-compound-type/3")
 2837     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-inout-with-compound-type/4")
 2838     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-inout-with-compound-type/5")
 2839     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-inout-with-compound-type/6")
 2840     (check-next-stream-line-equal _test-output-stream "    (g *(ebp+0xfffffffc))"  "F - test-convert-function-call-with-inout-with-compound-type/7")
 2841     (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")
 2842     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-inout-with-compound-type/9")
 2843     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-inout-with-compound-type/10")
 2844     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-inout-with-compound-type/11")
 2845     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-inout-with-compound-type/12")
 2846     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-inout-with-compound-type/13")
 2847     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-inout-with-compound-type/14")
 2848     (check-next-stream-line-equal _test-output-stream "g:"                      "F - test-convert-function-call-with-inout-with-compound-type/15")
 2849     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-inout-with-compound-type/16")
 2850     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-inout-with-compound-type/17")
 2851     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-inout-with-compound-type/18")
 2852     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-inout-with-compound-type/19")
 2853     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-inout-with-compound-type/20")
 2854     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-inout-with-compound-type/21")
 2855     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-inout-with-compound-type/22")
 2856     # . epilogue
 2857     89/<- %esp 5/r32/ebp
 2858     5d/pop-to-ebp
 2859     c3/return
 2860 
 2861 test-convert-function-call-with-inout-with-type-parameter:
 2862     # . prologue
 2863     55/push-ebp
 2864     89/<- %ebp 4/r32/esp
 2865     # setup
 2866     (clear-stream _test-input-stream)
 2867     (clear-stream $_test-input-buffered-file->buffer)
 2868     (clear-stream _test-output-stream)
 2869     (clear-stream $_test-output-buffered-file->buffer)
 2870     (clear-stream _test-error-stream)
 2871     (clear-stream $_test-error-buffered-file->buffer)
 2872     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2873     68/push 0/imm32
 2874     68/push 0/imm32
 2875     89/<- %edx 4/r32/esp
 2876     (tailor-exit-descriptor %edx 0x10)
 2877     #
 2878     (write _test-input-stream "fn f {\n")
 2879     (write _test-input-stream "  var x: (addr int)\n")
 2880     (write _test-input-stream "  g x\n")
 2881     (write _test-input-stream "}\n")
 2882     (write _test-input-stream "fn g a: (addr _) {\n")
 2883     (write _test-input-stream "}\n")
 2884     # convert
 2885     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2886     # registers except esp clobbered at this point
 2887     # restore ed
 2888     89/<- %edx 4/r32/esp
 2889     (flush _test-output-buffered-file)
 2890     (flush _test-error-buffered-file)
 2891 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 2897     # no error; types matched
 2898     (check-stream-equal _test-error-stream  ""  "F - test-convert-function-call-with-inout-with-type-parameter: error stream should be empty")
 2899     # don't bother checking the generated code; that's in the test 'test-local-clobbered-by-fn-output' below
 2900     # don't restore from ebp
 2901     81 0/subop/add %esp 8/imm32
 2902     # . epilogue
 2903     5d/pop-to-ebp
 2904     c3/return
 2905 
 2906 test-convert-function-call-with-incorrect-inout-type:
 2907     # . prologue
 2908     55/push-ebp
 2909     89/<- %ebp 4/r32/esp
 2910     # setup
 2911     (clear-stream _test-input-stream)
 2912     (clear-stream $_test-input-buffered-file->buffer)
 2913     (clear-stream _test-output-stream)
 2914     (clear-stream $_test-output-buffered-file->buffer)
 2915     (clear-stream _test-error-stream)
 2916     (clear-stream $_test-error-buffered-file->buffer)
 2917     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2918     68/push 0/imm32
 2919     68/push 0/imm32
 2920     89/<- %edx 4/r32/esp
 2921     (tailor-exit-descriptor %edx 0x10)
 2922     #
 2923     (write _test-input-stream "fn f {\n")
 2924     (write _test-input-stream "  var x: int\n")
 2925     (write _test-input-stream "  g x\n")
 2926     (write _test-input-stream "}\n")
 2927     (write _test-input-stream "fn g a: foo {\n")
 2928     (write _test-input-stream "}\n")
 2929     # convert
 2930     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2931     # registers except esp clobbered at this point
 2932     # restore ed
 2933     89/<- %edx 4/r32/esp
 2934     (flush _test-output-buffered-file)
 2935     (flush _test-error-buffered-file)
 2936 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 2942     # check output
 2943     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-inout-type: output should be empty")
 2944     (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")
 2945     # check that stop(1) was called
 2946     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-inout-type: exit status")
 2947     # don't restore from ebp
 2948     81 0/subop/add %esp 8/imm32
 2949     5d/pop-to-ebp
 2950     c3/return
 2951 
 2952 test-convert-function-call-with-inout-with-incorrect-compound-type:
 2953     # . prologue
 2954     55/push-ebp
 2955     89/<- %ebp 4/r32/esp
 2956     # setup
 2957     (clear-stream _test-input-stream)
 2958     (clear-stream $_test-input-buffered-file->buffer)
 2959     (clear-stream _test-output-stream)
 2960     (clear-stream $_test-output-buffered-file->buffer)
 2961     (clear-stream _test-error-stream)
 2962     (clear-stream $_test-error-buffered-file->buffer)
 2963     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2964     68/push 0/imm32
 2965     68/push 0/imm32
 2966     89/<- %edx 4/r32/esp
 2967     (tailor-exit-descriptor %edx 0x10)
 2968     #
 2969     (write _test-input-stream "fn f {\n")
 2970     (write _test-input-stream "  var x: (addr int)\n")
 2971     (write _test-input-stream "  g x\n")
 2972     (write _test-input-stream "}\n")
 2973     (write _test-input-stream "fn g a: (addr bool) {\n")
 2974     (write _test-input-stream "}\n")
 2975     # convert
 2976     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2977     # registers except esp clobbered at this point
 2978     # restore ed
 2979     89/<- %edx 4/r32/esp
 2980     (flush _test-output-buffered-file)
 2981     (flush _test-error-buffered-file)
 2982 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 2988     # check output
 2989     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-inout-with-incorrect-compound-type: output should be empty")
 2990     (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")
 2991     # don't restore from ebp
 2992     81 0/subop/add %esp 8/imm32
 2993     # . epilogue
 2994     5d/pop-to-ebp
 2995     c3/return
 2996 
 2997 test-convert-function-call-with-inout-with-multiple-type-parameters:
 2998     # . prologue
 2999     55/push-ebp
 3000     89/<- %ebp 4/r32/esp
 3001     # setup
 3002     (clear-stream _test-input-stream)
 3003     (clear-stream $_test-input-buffered-file->buffer)
 3004     (clear-stream _test-output-stream)
 3005     (clear-stream $_test-output-buffered-file->buffer)
 3006     (clear-stream _test-error-stream)
 3007     (clear-stream $_test-error-buffered-file->buffer)
 3008     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3009     68/push 0/imm32
 3010     68/push 0/imm32
 3011     89/<- %edx 4/r32/esp
 3012     (tailor-exit-descriptor %edx 0x10)
 3013     #
 3014     (write _test-input-stream "fn f {\n")
 3015     (write _test-input-stream "  var x: (addr int)\n")
 3016     (write _test-input-stream "  var y: (addr int)\n")
 3017     (write _test-input-stream "  g x, y\n")
 3018     (write _test-input-stream "}\n")
 3019     (write _test-input-stream "fn g a: (addr _), b: (addr _) {\n")
 3020     (write _test-input-stream "}\n")
 3021     # convert
 3022     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3023     # registers except esp clobbered at this point
 3024     # restore ed
 3025     89/<- %edx 4/r32/esp
 3026     (flush _test-output-buffered-file)
 3027     (flush _test-error-buffered-file)
 3028 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 3034     # no errors
 3035     (check-stream-equal _test-error-stream  ""  "F - test-convert-function-call-with-inout-with-multiple-type-parameters: error stream should be empty")
 3036     # don't bother checking the generated code
 3037     # don't restore from ebp
 3038     81 0/subop/add %esp 8/imm32
 3039     # . epilogue
 3040     5d/pop-to-ebp
 3041     c3/return
 3042 
 3043 test-type-parameter-matches-rest-of-type:
 3044     # . prologue
 3045     55/push-ebp
 3046     89/<- %ebp 4/r32/esp
 3047     # setup
 3048     (clear-stream _test-input-stream)
 3049     (clear-stream $_test-input-buffered-file->buffer)
 3050     (clear-stream _test-output-stream)
 3051     (clear-stream $_test-output-buffered-file->buffer)
 3052     (clear-stream _test-error-stream)
 3053     (clear-stream $_test-error-buffered-file->buffer)
 3054     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3055     68/push 0/imm32
 3056     68/push 0/imm32
 3057     89/<- %edx 4/r32/esp
 3058     (tailor-exit-descriptor %edx 0x10)
 3059     #
 3060     (write _test-input-stream "fn f {\n")
 3061     (write _test-input-stream "  var x: (addr array int)\n")
 3062     (write _test-input-stream "  g x\n")
 3063     (write _test-input-stream "}\n")
 3064     (write _test-input-stream "fn g a: (addr _) {\n")
 3065     (write _test-input-stream "}\n")
 3066     # convert
 3067     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3068     # registers except esp clobbered at this point
 3069     # restore ed
 3070     89/<- %edx 4/r32/esp
 3071     (flush _test-output-buffered-file)
 3072     (flush _test-error-buffered-file)
 3073 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 3079     # no errors
 3080     (check-stream-equal _test-error-stream  ""  "F - test-type-parameter-matches-rest-of-type: error stream should be empty")
 3081     # don't bother checking the generated code
 3082     # don't restore from ebp
 3083     81 0/subop/add %esp 8/imm32
 3084     # . epilogue
 3085     5d/pop-to-ebp
 3086     c3/return
 3087 
 3088 test-convert-function-call-with-inout-with-incompatible-type-parameters:
 3089     # . prologue
 3090     55/push-ebp
 3091     89/<- %ebp 4/r32/esp
 3092     # setup
 3093     (clear-stream _test-input-stream)
 3094     (clear-stream $_test-input-buffered-file->buffer)
 3095     (clear-stream _test-output-stream)
 3096     (clear-stream $_test-output-buffered-file->buffer)
 3097     (clear-stream _test-error-stream)
 3098     (clear-stream $_test-error-buffered-file->buffer)
 3099     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3100     68/push 0/imm32
 3101     68/push 0/imm32
 3102     89/<- %edx 4/r32/esp
 3103     (tailor-exit-descriptor %edx 0x10)
 3104     #
 3105     (write _test-input-stream "fn f {\n")
 3106     (write _test-input-stream "  var x: (addr int)\n")
 3107     (write _test-input-stream "  var y: (addr boolean)\n")
 3108     (write _test-input-stream "  g x, y\n")
 3109     (write _test-input-stream "}\n")
 3110     (write _test-input-stream "fn g a: (addr _T), b: (addr _T) {\n")
 3111     (write _test-input-stream "}\n")
 3112     # convert
 3113     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3114     # registers except esp clobbered at this point
 3115     # restore ed
 3116     89/<- %edx 4/r32/esp
 3117     (flush _test-output-buffered-file)
 3118     (flush _test-error-buffered-file)
 3119 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 3125     # check output
 3126     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-inout-with-incompatible-type-parameters: output should be empty")
 3127     (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")
 3128     # don't restore from ebp
 3129     81 0/subop/add %esp 8/imm32
 3130     # . epilogue
 3131     5d/pop-to-ebp
 3132     c3/return
 3133 
 3134 test-convert-function-call-with-too-few-inouts:
 3135     # . prologue
 3136     55/push-ebp
 3137     89/<- %ebp 4/r32/esp
 3138     # setup
 3139     (clear-stream _test-input-stream)
 3140     (clear-stream $_test-input-buffered-file->buffer)
 3141     (clear-stream _test-output-stream)
 3142     (clear-stream $_test-output-buffered-file->buffer)
 3143     (clear-stream _test-error-stream)
 3144     (clear-stream $_test-error-buffered-file->buffer)
 3145     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3146     68/push 0/imm32
 3147     68/push 0/imm32
 3148     89/<- %edx 4/r32/esp
 3149     (tailor-exit-descriptor %edx 0x10)
 3150     #
 3151     (write _test-input-stream "fn f {\n")
 3152     (write _test-input-stream "  g\n")
 3153     (write _test-input-stream "}\n")
 3154     (write _test-input-stream "fn g a: int {\n")
 3155     (write _test-input-stream "}\n")
 3156     # convert
 3157     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3158     # registers except esp clobbered at this point
 3159     # restore ed
 3160     89/<- %edx 4/r32/esp
 3161     (flush _test-output-buffered-file)
 3162     (flush _test-error-buffered-file)
 3163 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 3169     # check output
 3170     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-few-inouts: output should be empty")
 3171     (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")
 3172     # check that stop(1) was called
 3173     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-few-inouts: exit status")
 3174     # don't restore from ebp
 3175     81 0/subop/add %esp 8/imm32
 3176     5d/pop-to-ebp
 3177     c3/return
 3178 
 3179 test-convert-function-call-with-too-many-inouts:
 3180     # . prologue
 3181     55/push-ebp
 3182     89/<- %ebp 4/r32/esp
 3183     # setup
 3184     (clear-stream _test-input-stream)
 3185     (clear-stream $_test-input-buffered-file->buffer)
 3186     (clear-stream _test-output-stream)
 3187     (clear-stream $_test-output-buffered-file->buffer)
 3188     (clear-stream _test-error-stream)
 3189     (clear-stream $_test-error-buffered-file->buffer)
 3190     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3191     68/push 0/imm32
 3192     68/push 0/imm32
 3193     89/<- %edx 4/r32/esp
 3194     (tailor-exit-descriptor %edx 0x10)
 3195     #
 3196     (write _test-input-stream "fn f {\n")
 3197     (write _test-input-stream "  var x: int\n")
 3198     (write _test-input-stream "  g x\n")
 3199     (write _test-input-stream "}\n")
 3200     (write _test-input-stream "fn g {\n")
 3201     (write _test-input-stream "}\n")
 3202     # convert
 3203     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3204     # registers except esp clobbered at this point
 3205     # restore ed
 3206     89/<- %edx 4/r32/esp
 3207     (flush _test-output-buffered-file)
 3208     (flush _test-error-buffered-file)
 3209 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 3215     # check output
 3216     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-many-inouts: output should be empty")
 3217     (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")
 3218     # check that stop(1) was called
 3219     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-many-inouts: exit status")
 3220     # don't restore from ebp
 3221     81 0/subop/add %esp 8/imm32
 3222     5d/pop-to-ebp
 3223     c3/return
 3224 
 3225 test-convert-function-call-with-incorrect-output-type:
 3226     # . prologue
 3227     55/push-ebp
 3228     89/<- %ebp 4/r32/esp
 3229     # setup
 3230     (clear-stream _test-input-stream)
 3231     (clear-stream $_test-input-buffered-file->buffer)
 3232     (clear-stream _test-output-stream)
 3233     (clear-stream $_test-output-buffered-file->buffer)
 3234     (clear-stream _test-error-stream)
 3235     (clear-stream $_test-error-buffered-file->buffer)
 3236     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3237     68/push 0/imm32
 3238     68/push 0/imm32
 3239     89/<- %edx 4/r32/esp
 3240     (tailor-exit-descriptor %edx 0x10)
 3241     #
 3242     (write _test-input-stream "fn f {\n")
 3243     (write _test-input-stream "  var x/eax: int <- g\n")
 3244     (write _test-input-stream "}\n")
 3245     (write _test-input-stream "fn g -> _/eax: foo {\n")
 3246     (write _test-input-stream "}\n")
 3247     # convert
 3248     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3249     # registers except esp clobbered at this point
 3250     # restore ed
 3251     89/<- %edx 4/r32/esp
 3252     (flush _test-output-buffered-file)
 3253     (flush _test-error-buffered-file)
 3254 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 3260     # check output
 3261     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-output-type: output should be empty")
 3262     (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")
 3263     # check that stop(1) was called
 3264     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-output-type: exit status")
 3265     # don't restore from ebp
 3266     81 0/subop/add %esp 8/imm32
 3267     5d/pop-to-ebp
 3268     c3/return
 3269 
 3270 test-convert-function-call-with-too-few-outputs:
 3271     # . prologue
 3272     55/push-ebp
 3273     89/<- %ebp 4/r32/esp
 3274     # setup
 3275     (clear-stream _test-input-stream)
 3276     (clear-stream $_test-input-buffered-file->buffer)
 3277     (clear-stream _test-output-stream)
 3278     (clear-stream $_test-output-buffered-file->buffer)
 3279     (clear-stream _test-error-stream)
 3280     (clear-stream $_test-error-buffered-file->buffer)
 3281     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3282     68/push 0/imm32
 3283     68/push 0/imm32
 3284     89/<- %edx 4/r32/esp
 3285     (tailor-exit-descriptor %edx 0x10)
 3286     #
 3287     (write _test-input-stream "fn f {\n")
 3288     (write _test-input-stream "  g\n")
 3289     (write _test-input-stream "}\n")
 3290     (write _test-input-stream "fn g -> _/eax: int {\n")
 3291     (write _test-input-stream "}\n")
 3292     # convert
 3293     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3294     # registers except esp clobbered at this point
 3295     # restore ed
 3296     89/<- %edx 4/r32/esp
 3297     (flush _test-output-buffered-file)
 3298     (flush _test-error-buffered-file)
 3299 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 3305     # check output
 3306     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-few-outputs: output should be empty")
 3307     (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")
 3308     # check that stop(1) was called
 3309     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-few-outputs: exit status")
 3310     # don't restore from ebp
 3311     81 0/subop/add %esp 8/imm32
 3312     5d/pop-to-ebp
 3313     c3/return
 3314 
 3315 test-convert-function-call-with-too-many-outputs:
 3316     # . prologue
 3317     55/push-ebp
 3318     89/<- %ebp 4/r32/esp
 3319     # setup
 3320     (clear-stream _test-input-stream)
 3321     (clear-stream $_test-input-buffered-file->buffer)
 3322     (clear-stream _test-output-stream)
 3323     (clear-stream $_test-output-buffered-file->buffer)
 3324     (clear-stream _test-error-stream)
 3325     (clear-stream $_test-error-buffered-file->buffer)
 3326     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3327     68/push 0/imm32
 3328     68/push 0/imm32
 3329     89/<- %edx 4/r32/esp
 3330     (tailor-exit-descriptor %edx 0x10)
 3331     #
 3332     (write _test-input-stream "fn f {\n")
 3333     (write _test-input-stream "  var x/eax: int <- g\n")
 3334     (write _test-input-stream "}\n")
 3335     (write _test-input-stream "fn g {\n")
 3336     (write _test-input-stream "}\n")
 3337     # convert
 3338     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3339     # registers except esp clobbered at this point
 3340     # restore ed
 3341     89/<- %edx 4/r32/esp
 3342     (flush _test-output-buffered-file)
 3343     (flush _test-error-buffered-file)
 3344 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 3350     # check output
 3351     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-many-outputs: output should be empty")
 3352     (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")
 3353     # check that stop(1) was called
 3354     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-many-outputs: exit status")
 3355     # don't restore from ebp
 3356     81 0/subop/add %esp 8/imm32
 3357     5d/pop-to-ebp
 3358     c3/return
 3359 
 3360 test-convert-function-call-with-missing-output-register:
 3361     # . prologue
 3362     55/push-ebp
 3363     89/<- %ebp 4/r32/esp
 3364     # setup
 3365     (clear-stream _test-input-stream)
 3366     (clear-stream $_test-input-buffered-file->buffer)
 3367     (clear-stream _test-output-stream)
 3368     (clear-stream $_test-output-buffered-file->buffer)
 3369     (clear-stream _test-error-stream)
 3370     (clear-stream $_test-error-buffered-file->buffer)
 3371     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3372     68/push 0/imm32
 3373     68/push 0/imm32
 3374     89/<- %edx 4/r32/esp
 3375     (tailor-exit-descriptor %edx 0x10)
 3376     #
 3377     (write _test-input-stream "fn f {\n")
 3378     (write _test-input-stream "  var x: int\n")
 3379     (write _test-input-stream "  x <- g\n")
 3380     (write _test-input-stream "}\n")
 3381     (write _test-input-stream "fn g -> _/eax: int {\n")
 3382     (write _test-input-stream "}\n")
 3383     # convert
 3384     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3385     # registers except esp clobbered at this point
 3386     # restore ed
 3387     89/<- %edx 4/r32/esp
 3388     (flush _test-output-buffered-file)
 3389     (flush _test-error-buffered-file)
 3390 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 3396     # check output
 3397     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-missing-output-register: output should be empty")
 3398     (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")
 3399     # check that stop(1) was called
 3400     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-missing-output-register: exit status")
 3401     # don't restore from ebp
 3402     81 0/subop/add %esp 8/imm32
 3403     5d/pop-to-ebp
 3404     c3/return
 3405 
 3406 test-convert-function-call-with-incorrect-output-register:
 3407     # . prologue
 3408     55/push-ebp
 3409     89/<- %ebp 4/r32/esp
 3410     # setup
 3411     (clear-stream _test-input-stream)
 3412     (clear-stream $_test-input-buffered-file->buffer)
 3413     (clear-stream _test-output-stream)
 3414     (clear-stream $_test-output-buffered-file->buffer)
 3415     (clear-stream _test-error-stream)
 3416     (clear-stream $_test-error-buffered-file->buffer)
 3417     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3418     68/push 0/imm32
 3419     68/push 0/imm32
 3420     89/<- %edx 4/r32/esp
 3421     (tailor-exit-descriptor %edx 0x10)
 3422     #
 3423     (write _test-input-stream "fn f {\n")
 3424     (write _test-input-stream "  var x/ecx: int <- g\n")
 3425     (write _test-input-stream "}\n")
 3426     (write _test-input-stream "fn g -> _/eax: int {\n")
 3427     (write _test-input-stream "}\n")
 3428     # convert
 3429     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3430     # registers except esp clobbered at this point
 3431     # restore ed
 3432     89/<- %edx 4/r32/esp
 3433     (flush _test-output-buffered-file)
 3434     (flush _test-error-buffered-file)
 3435 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 3441     # check output
 3442     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-output-register: output should be empty")
 3443     (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")
 3444     # check that stop(1) was called
 3445     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-output-register: exit status")
 3446     # don't restore from ebp
 3447     81 0/subop/add %esp 8/imm32
 3448     5d/pop-to-ebp
 3449     c3/return
 3450 
 3451 test-convert-function-with-local-var-dereferenced:
 3452     # . prologue
 3453     55/push-ebp
 3454     89/<- %ebp 4/r32/esp
 3455     # setup
 3456     (clear-stream _test-input-stream)
 3457     (clear-stream $_test-input-buffered-file->buffer)
 3458     (clear-stream _test-output-stream)
 3459     (clear-stream $_test-output-buffered-file->buffer)
 3460     #
 3461     (write _test-input-stream "fn foo {\n")
 3462     (write _test-input-stream "  var x/ecx: (addr int) <- copy 0\n")
 3463     (write _test-input-stream "  increment *x\n")
 3464     (write _test-input-stream "}\n")
 3465     # convert
 3466     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3467     (flush _test-output-buffered-file)
 3468 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 3474     # check output
 3475     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-dereferenced/0")
 3476     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-dereferenced/1")
 3477     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-dereferenced/2")
 3478     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-dereferenced/3")
 3479     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-dereferenced/4")
 3480     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-dereferenced/5")
 3481     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-dereferenced/6")
 3482     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-local-var-dereferenced/7")
 3483     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *ecx"  "F - test-convert-function-with-local-var-dereferenced/8")
 3484     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-dereferenced/9")
 3485     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-dereferenced/10")
 3486     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-dereferenced/11")
 3487     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-dereferenced/12")
 3488     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-dereferenced/13")
 3489     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-dereferenced/14")
 3490     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-dereferenced/15")
 3491     # . epilogue
 3492     89/<- %esp 5/r32/ebp
 3493     5d/pop-to-ebp
 3494     c3/return
 3495 
 3496 test-dereference-of-var-on-stack:
 3497     # . prologue
 3498     55/push-ebp
 3499     89/<- %ebp 4/r32/esp
 3500     # setup
 3501     (clear-stream _test-input-stream)
 3502     (clear-stream $_test-input-buffered-file->buffer)
 3503     (clear-stream _test-output-stream)
 3504     (clear-stream $_test-output-buffered-file->buffer)
 3505     (clear-stream _test-error-stream)
 3506     (clear-stream $_test-error-buffered-file->buffer)
 3507     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3508     68/push 0/imm32
 3509     68/push 0/imm32
 3510     89/<- %edx 4/r32/esp
 3511     (tailor-exit-descriptor %edx 0x10)
 3512     #
 3513     (write _test-input-stream "fn foo {\n")
 3514     (write _test-input-stream "  var x: (addr int)\n")
 3515     (write _test-input-stream "  increment *x\n")
 3516     (write _test-input-stream "}\n")
 3517     # convert
 3518     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3519     # registers except esp clobbered at this point
 3520     # restore ed
 3521     89/<- %edx 4/r32/esp
 3522     (flush _test-output-buffered-file)
 3523     (flush _test-error-buffered-file)
 3524 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 3530     # check output
 3531     (check-stream-equal _test-output-stream  ""  "F - test-dereference-of-var-on-stack: output should be empty")
 3532     (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")
 3533     # check that stop(1) was called
 3534     (check-ints-equal *(edx+4) 2 "F - test-dereference-of-var-on-stack: exit status")
 3535     # don't restore from ebp
 3536     81 0/subop/add %esp 8/imm32
 3537     # . epilogue
 3538     5d/pop-to-ebp
 3539     c3/return
 3540 
 3541 test-convert-function-with-byte-operations:
 3542     # . prologue
 3543     55/push-ebp
 3544     89/<- %ebp 4/r32/esp
 3545     # setup
 3546     (clear-stream _test-input-stream)
 3547     (clear-stream $_test-input-buffered-file->buffer)
 3548     (clear-stream _test-output-stream)
 3549     (clear-stream $_test-output-buffered-file->buffer)
 3550     #
 3551     (write _test-input-stream "fn foo {\n")
 3552     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
 3553     (write _test-input-stream "  var y/ecx: byte <- copy 0\n")
 3554     (write _test-input-stream "  y <- copy-byte x\n")
 3555     (write _test-input-stream "  var z/edx: (addr byte) <- copy 0\n")
 3556     (write _test-input-stream "  y <- copy-byte *z\n")
 3557     (write _test-input-stream "  copy-byte-to *z, x\n")
 3558     (write _test-input-stream "}\n")
 3559     # convert
 3560     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3561     (flush _test-output-buffered-file)
 3562 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 3568     # check output
 3569     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-function-with-byte-operations/0")
 3570     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-function-with-byte-operations/1")
 3571     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-function-with-byte-operations/2")
 3572     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-function-with-byte-operations/3")
 3573     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-function-with-byte-operations/4")
 3574     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-function-with-byte-operations/5")
 3575     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-function-with-byte-operations/6")
 3576     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-function-with-byte-operations/7")
 3577     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-function-with-byte-operations/8")
 3578     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"                  "F - test-convert-function-with-byte-operations/9")
 3579     (check-next-stream-line-equal _test-output-stream "    8a/byte-> %eax 0x00000001/r32"           "F - test-convert-function-with-byte-operations/10")
 3580     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %edx"                    "F - test-convert-function-with-byte-operations/11")
 3581     (check-next-stream-line-equal _test-output-stream "    ba/copy-to-edx 0/imm32"                  "F - test-convert-function-with-byte-operations/12")
 3582     (check-next-stream-line-equal _test-output-stream "    8a/byte-> *edx 0x00000001/r32"           "F - test-convert-function-with-byte-operations/13")
 3583     (check-next-stream-line-equal _test-output-stream "    88/byte<- *edx 0x00000000/r32"           "F - test-convert-function-with-byte-operations/14")
 3584     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %edx"                     "F - test-convert-function-with-byte-operations/15")
 3585     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-function-with-byte-operations/16")
 3586     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-function-with-byte-operations/17")
 3587     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-function-with-byte-operations/18")
 3588     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-function-with-byte-operations/19")
 3589     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-function-with-byte-operations/20")
 3590     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-function-with-byte-operations/21")
 3591     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-function-with-byte-operations/22")
 3592     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-function-with-byte-operations/23")
 3593     # . epilogue
 3594     89/<- %esp 5/r32/ebp
 3595     5d/pop-to-ebp
 3596     c3/return
 3597 
 3598 # variables of type 'byte' are not allowed on the stack
 3599 test-byte-values-on-stack:
 3600     # . prologue
 3601     55/push-ebp
 3602     89/<- %ebp 4/r32/esp
 3603     # setup
 3604     (clear-stream _test-input-stream)
 3605     (clear-stream $_test-input-buffered-file->buffer)
 3606     (clear-stream _test-output-stream)
 3607     (clear-stream $_test-output-buffered-file->buffer)
 3608     (clear-stream _test-error-stream)
 3609     (clear-stream $_test-error-buffered-file->buffer)
 3610     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3611     68/push 0/imm32
 3612     68/push 0/imm32
 3613     89/<- %edx 4/r32/esp
 3614     (tailor-exit-descriptor %edx 0x10)
 3615     #
 3616     (write _test-input-stream "fn foo {\n")
 3617     (write _test-input-stream "  var x: byte\n")
 3618     (write _test-input-stream "}\n")
 3619     # convert
 3620     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3621     # registers except esp clobbered at this point
 3622     # restore ed
 3623     89/<- %edx 4/r32/esp
 3624     (flush _test-output-buffered-file)
 3625     (flush _test-error-buffered-file)
 3626 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 3632     # check output
 3633     (check-stream-equal _test-output-stream  ""  "F - test-byte-values-on-stack: output should be empty")
 3634     (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")
 3635     # check that stop(1) was called
 3636     (check-ints-equal *(edx+4) 2 "F - test-byte-values-on-stack: exit status")
 3637     # don't restore from ebp
 3638     81 0/subop/add %esp 8/imm32
 3639     # . epilogue
 3640     5d/pop-to-ebp
 3641     c3/return
 3642 
 3643 # variables of type 'byte' are not allowed in esi or edi
 3644 test-byte-values-in-unsupported-registers:
 3645     # . prologue
 3646     55/push-ebp
 3647     89/<- %ebp 4/r32/esp
 3648     # setup
 3649     (clear-stream _test-input-stream)
 3650     (clear-stream $_test-input-buffered-file->buffer)
 3651     (clear-stream _test-output-stream)
 3652     (clear-stream $_test-output-buffered-file->buffer)
 3653     (clear-stream _test-error-stream)
 3654     (clear-stream $_test-error-buffered-file->buffer)
 3655     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3656     68/push 0/imm32
 3657     68/push 0/imm32
 3658     89/<- %edx 4/r32/esp
 3659     (tailor-exit-descriptor %edx 0x10)
 3660     #
 3661     (write _test-input-stream "fn foo {\n")
 3662     (write _test-input-stream "  var x/esi: byte <- copy 0\n")
 3663     (write _test-input-stream "}\n")
 3664     # convert
 3665     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3666     # registers except esp clobbered at this point
 3667     # restore ed
 3668     89/<- %edx 4/r32/esp
 3669     (flush _test-output-buffered-file)
 3670     (flush _test-error-buffered-file)
 3671 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 3677     # check output
 3678     (check-stream-equal _test-output-stream  ""  "F - test-byte-values-in-unsupported-registers: output should be empty")
 3679     (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")
 3680     # check that stop(1) was called
 3681     (check-ints-equal *(edx+4) 2 "F - test-byte-values-in-unsupported-registers: exit status")
 3682     # don't restore from ebp
 3683     81 0/subop/add %esp 8/imm32
 3684     # . epilogue
 3685     5d/pop-to-ebp
 3686     c3/return
 3687 
 3688 # variables of type 'byte' _can_ be function args. They then occupy 4 bytes.
 3689 test-copy-byte-var-from-fn-arg:
 3690     # . prologue
 3691     55/push-ebp
 3692     89/<- %ebp 4/r32/esp
 3693     # setup
 3694     (clear-stream _test-input-stream)
 3695     (clear-stream $_test-input-buffered-file->buffer)
 3696     (clear-stream _test-output-stream)
 3697     (clear-stream $_test-output-buffered-file->buffer)
 3698     #
 3699     (write _test-input-stream "fn foo x: byte, y: int {\n")
 3700     (write _test-input-stream "  var a/eax: byte <- copy x\n")
 3701     (write _test-input-stream "  var b/eax: int <- copy y\n")
 3702     (write _test-input-stream "}\n")
 3703     # convert
 3704     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3705     (flush _test-output-buffered-file)
 3706 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 3712     # check output
 3713     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-copy-byte-from-fn-arg/0")
 3714     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-copy-byte-from-fn-arg/1")
 3715     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-copy-byte-from-fn-arg/2")
 3716     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-copy-byte-from-fn-arg/3")
 3717     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-copy-byte-from-fn-arg/4")
 3718     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-copy-byte-from-fn-arg/5")
 3719     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-copy-byte-from-fn-arg/6")
 3720     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-copy-byte-from-fn-arg/7")
 3721     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x0000000c) 0x00000000/r32"  "F - test-copy-byte-from-fn-arg/8")
 3722     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"   "F - test-copy-byte-from-fn-arg/9")
 3723     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-copy-byte-from-fn-arg/10")
 3724     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-copy-byte-from-fn-arg/11")
 3725     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-copy-byte-from-fn-arg/12")
 3726     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-copy-byte-from-fn-arg/13")
 3727     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-copy-byte-from-fn-arg/14")
 3728     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-copy-byte-from-fn-arg/15")
 3729     # . epilogue
 3730     89/<- %esp 5/r32/ebp
 3731     5d/pop-to-ebp
 3732     c3/return
 3733 
 3734 test-convert-compare-register-with-literal:
 3735     # . prologue
 3736     55/push-ebp
 3737     89/<- %ebp 4/r32/esp
 3738     # setup
 3739     (clear-stream _test-input-stream)
 3740     (clear-stream $_test-input-buffered-file->buffer)
 3741     (clear-stream _test-output-stream)
 3742     (clear-stream $_test-output-buffered-file->buffer)
 3743     #
 3744     (write _test-input-stream "fn foo {\n")
 3745     (write _test-input-stream "  var x/ecx: int <- copy 0\n")
 3746     (write _test-input-stream "  compare x, 0\n")
 3747     (write _test-input-stream "}\n")
 3748     # convert
 3749     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3750     (flush _test-output-buffered-file)
 3751 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 3757     # check output
 3758     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-compare-register-with-literal/0")
 3759     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-compare-register-with-literal/1")
 3760     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-compare-register-with-literal/2")
 3761     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-compare-register-with-literal/3")
 3762     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-compare-register-with-literal/4")
 3763     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-compare-register-with-literal/5")
 3764     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-compare-register-with-literal/6")
 3765     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-compare-register-with-literal/7")
 3766     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %ecx 0/imm32"  "F - test-convert-compare-register-with-literal/8")
 3767     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-compare-register-with-literal/9")
 3768     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-compare-register-with-literal/10")
 3769     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-compare-register-with-literal/11")
 3770     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-compare-register-with-literal/12")
 3771     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-compare-register-with-literal/13")
 3772     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-compare-register-with-literal/14")
 3773     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-compare-register-with-literal/15")
 3774     # . epilogue
 3775     89/<- %esp 5/r32/ebp
 3776     5d/pop-to-ebp
 3777     c3/return
 3778 
 3779 test-unknown-variable:
 3780     # . prologue
 3781     55/push-ebp
 3782     89/<- %ebp 4/r32/esp
 3783     # setup
 3784     (clear-stream _test-input-stream)
 3785     (clear-stream $_test-input-buffered-file->buffer)
 3786     (clear-stream _test-output-stream)
 3787     (clear-stream $_test-output-buffered-file->buffer)
 3788     (clear-stream _test-error-stream)
 3789     (clear-stream $_test-error-buffered-file->buffer)
 3790     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3791     68/push 0/imm32
 3792     68/push 0/imm32
 3793     89/<- %edx 4/r32/esp
 3794     (tailor-exit-descriptor %edx 0x10)
 3795     #
 3796     (write _test-input-stream "fn foo {\n")
 3797     (write _test-input-stream "  compare x, 0\n")
 3798     (write _test-input-stream "}\n")
 3799     # convert
 3800     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3801     # registers except esp clobbered at this point
 3802     # restore ed
 3803     89/<- %edx 4/r32/esp
 3804     (flush _test-output-buffered-file)
 3805     (flush _test-error-buffered-file)
 3806 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 3812     # check output
 3813     (check-stream-equal _test-output-stream  ""  "F - test-unknown-variable: output should be empty")
 3814     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-unknown-variable: error message")
 3815     # check that stop(1) was called
 3816     (check-ints-equal *(edx+4) 2 "F - test-unknown-variable: exit status")
 3817     # don't restore from ebp
 3818     81 0/subop/add %esp 8/imm32
 3819     # . epilogue
 3820     5d/pop-to-ebp
 3821     c3/return
 3822 
 3823 test-convert-function-with-local-var-in-block:
 3824     # . prologue
 3825     55/push-ebp
 3826     89/<- %ebp 4/r32/esp
 3827     # setup
 3828     (clear-stream _test-input-stream)
 3829     (clear-stream $_test-input-buffered-file->buffer)
 3830     (clear-stream _test-output-stream)
 3831     (clear-stream $_test-output-buffered-file->buffer)
 3832     #
 3833     (write _test-input-stream "fn foo {\n")
 3834     (write _test-input-stream "  {\n")
 3835     (write _test-input-stream "    var x: int\n")
 3836     (write _test-input-stream "    increment x\n")
 3837     (write _test-input-stream "  }\n")
 3838     (write _test-input-stream "}\n")
 3839     # convert
 3840     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3841     (flush _test-output-buffered-file)
 3842 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 3848     # check output
 3849     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-block/0")
 3850     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-block/1")
 3851     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-block/2")
 3852     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-block/3")
 3853     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-block/4")
 3854     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-block/5")
 3855     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-block/6")
 3856     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-local-var-in-block/7")
 3857     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-block/8")
 3858     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-local-var-in-block/9")
 3859     (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")
 3860     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-block/11")
 3861     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-local-var-in-block/12")
 3862     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-block/13")
 3863     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-block/14")
 3864     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-block/15")
 3865     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-block/16")
 3866     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-block/17")
 3867     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-block/18")
 3868     # . epilogue
 3869     89/<- %esp 5/r32/ebp
 3870     5d/pop-to-ebp
 3871     c3/return
 3872 
 3873 test-convert-function-with-local-var-in-mem-after-block:
 3874     # . prologue
 3875     55/push-ebp
 3876     89/<- %ebp 4/r32/esp
 3877     # setup
 3878     (clear-stream _test-input-stream)
 3879     (clear-stream $_test-input-buffered-file->buffer)
 3880     (clear-stream _test-output-stream)
 3881     (clear-stream $_test-output-buffered-file->buffer)
 3882     #
 3883     (write _test-input-stream "fn foo {\n")
 3884     (write _test-input-stream "  {\n")
 3885     (write _test-input-stream "    var y: int\n")
 3886     (write _test-input-stream "  }\n")
 3887     (write _test-input-stream "  var x: int\n")
 3888     (write _test-input-stream "  increment x\n")
 3889     (write _test-input-stream "}\n")
 3890     # convert
 3891     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3892     (flush _test-output-buffered-file)
 3893 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 3899     # check output
 3900     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-mem-after-block/0")
 3901     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-mem-after-block/1")
 3902     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-mem-after-block/2")
 3903     (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")
 3904     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-mem-after-block/4")
 3905     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-mem-after-block/5")
 3906     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-mem-after-block/6")
 3907     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-local-var-in-mem-after-block/7")
 3908     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-mem-after-block/8")
 3909     (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")
 3910     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-mem-after-block/10")
 3911     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-local-var-in-mem-after-block/11")
 3912     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-in-mem-after-block/12")
 3913     (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")
 3914     (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")
 3915     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-mem-after-block/15")
 3916     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-mem-after-block/16")
 3917     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-mem-after-block/17")
 3918     (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")
 3919     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-mem-after-block/19")
 3920     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-mem-after-block/20")
 3921     # . epilogue
 3922     89/<- %esp 5/r32/ebp
 3923     5d/pop-to-ebp
 3924     c3/return
 3925 
 3926 test-convert-function-with-local-var-in-named-block:
 3927     # . prologue
 3928     55/push-ebp
 3929     89/<- %ebp 4/r32/esp
 3930     # setup
 3931     (clear-stream _test-input-stream)
 3932     (clear-stream $_test-input-buffered-file->buffer)
 3933     (clear-stream _test-output-stream)
 3934     (clear-stream $_test-output-buffered-file->buffer)
 3935     #
 3936     (write _test-input-stream "fn foo {\n")
 3937     (write _test-input-stream "  $bar: {\n")
 3938     (write _test-input-stream "    var x: int\n")
 3939     (write _test-input-stream "    increment x\n")
 3940     (write _test-input-stream "  }\n")
 3941     (write _test-input-stream "}\n")
 3942     # convert
 3943     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3944     (flush _test-output-buffered-file)
 3945 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 3951     # check output
 3952     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-named-block/0")
 3953     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-named-block/1")
 3954     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-named-block/2")
 3955     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-named-block/3")
 3956     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-named-block/4")
 3957     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-named-block/5")
 3958     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-named-block/6")
 3959     (check-next-stream-line-equal _test-output-stream "$bar:loop:"              "F - test-convert-function-with-local-var-in-named-block/7")
 3960     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-named-block/8")
 3961     (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")
 3962     (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")
 3963     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-named-block/11")
 3964     (check-next-stream-line-equal _test-output-stream "$bar:break:"             "F - test-convert-function-with-local-var-in-named-block/12")
 3965     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-named-block/13")
 3966     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-named-block/14")
 3967     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-named-block/15")
 3968     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-named-block/16")
 3969     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-named-block/17")
 3970     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-named-block/18")
 3971     # . epilogue
 3972     89/<- %esp 5/r32/ebp
 3973     5d/pop-to-ebp
 3974     c3/return
 3975 
 3976 test-unknown-variable-in-named-block:
 3977     # . prologue
 3978     55/push-ebp
 3979     89/<- %ebp 4/r32/esp
 3980     # setup
 3981     (clear-stream _test-input-stream)
 3982     (clear-stream $_test-input-buffered-file->buffer)
 3983     (clear-stream _test-output-stream)
 3984     (clear-stream $_test-output-buffered-file->buffer)
 3985     (clear-stream _test-error-stream)
 3986     (clear-stream $_test-error-buffered-file->buffer)
 3987     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3988     68/push 0/imm32
 3989     68/push 0/imm32
 3990     89/<- %edx 4/r32/esp
 3991     (tailor-exit-descriptor %edx 0x10)
 3992     #
 3993     (write _test-input-stream "fn foo {\n")
 3994     (write _test-input-stream "  $a: {\n")
 3995     (write _test-input-stream "    compare x, 0\n")
 3996     (write _test-input-stream "  }\n")
 3997     (write _test-input-stream "}\n")
 3998     # convert
 3999     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 4000     # registers except esp clobbered at this point
 4001     # restore ed
 4002     89/<- %edx 4/r32/esp
 4003     (flush _test-output-buffered-file)
 4004     (flush _test-error-buffered-file)
 4005 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 4011     # check output
 4012     (check-stream-equal _test-output-stream  ""  "F - test-unknown-variable-in-named-block: output should be empty")
 4013     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-unknown-variable-in-named-block: error message")
 4014     # check that stop(1) was called
 4015     (check-ints-equal *(edx+4) 2 "F - test-unknown-variable-in-named-block: exit status")
 4016     # don't restore from ebp
 4017     81 0/subop/add %esp 8/imm32
 4018     # . epilogue
 4019     5d/pop-to-ebp
 4020     c3/return
 4021 
 4022 test-always-shadow-outermost-reg-vars-in-function:
 4023     # . prologue
 4024     55/push-ebp
 4025     89/<- %ebp 4/r32/esp
 4026     # setup
 4027     (clear-stream _test-input-stream)
 4028     (clear-stream $_test-input-buffered-file->buffer)
 4029     (clear-stream _test-output-stream)
 4030     (clear-stream $_test-output-buffered-file->buffer)
 4031     #
 4032     (write _test-input-stream "fn foo {\n")
 4033     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4034     (write _test-input-stream "}\n")
 4035     # convert
 4036     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4037     (flush _test-output-buffered-file)
 4038 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 4044     # check output
 4045     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-always-shadow-outermost-reg-vars-in-function/0")
 4046     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-always-shadow-outermost-reg-vars-in-function/1")
 4047     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-always-shadow-outermost-reg-vars-in-function/2")
 4048     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-always-shadow-outermost-reg-vars-in-function/3")
 4049     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-always-shadow-outermost-reg-vars-in-function/4")
 4050     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-always-shadow-outermost-reg-vars-in-function/5")
 4051     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-compare-register-with-literal/6")
 4052     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-always-shadow-outermost-reg-vars-in-function/8")
 4053     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-compare-register-with-literal/9")
 4054     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-always-shadow-outermost-reg-vars-in-function/12")
 4055     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-always-shadow-outermost-reg-vars-in-function/13")
 4056     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-always-shadow-outermost-reg-vars-in-function/14")
 4057     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-always-shadow-outermost-reg-vars-in-function/15")
 4058     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-always-shadow-outermost-reg-vars-in-function/16")
 4059     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-always-shadow-outermost-reg-vars-in-function/17")
 4060     # . epilogue
 4061     89/<- %esp 5/r32/ebp
 4062     5d/pop-to-ebp
 4063     c3/return
 4064 
 4065 test-shadow-local:
 4066     # . prologue
 4067     55/push-ebp
 4068     89/<- %ebp 4/r32/esp
 4069     # setup
 4070     (clear-stream _test-input-stream)
 4071     (clear-stream $_test-input-buffered-file->buffer)
 4072     (clear-stream _test-output-stream)
 4073     (clear-stream $_test-output-buffered-file->buffer)
 4074     #
 4075     (write _test-input-stream "fn foo {\n")
 4076     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4077     (write _test-input-stream "  {\n")
 4078     (write _test-input-stream "    var y/ecx: int <- copy 4\n")
 4079     (write _test-input-stream "  }\n")
 4080     (write _test-input-stream "  x <- increment\n")
 4081     (write _test-input-stream "}\n")
 4082     # convert
 4083     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4084     (flush _test-output-buffered-file)
 4085 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 4091     # check output
 4092     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-local/0")
 4093     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-local/1")
 4094     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-local/2")
 4095     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-local/3")
 4096     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-local/4")
 4097     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-local/5")
 4098     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-local/6")
 4099     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-local/7")
 4100     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-local/8")
 4101     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-local/9")
 4102     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %ecx"  "F - test-shadow-local/10")
 4103     (check-next-stream-line-equal _test-output-stream "      b9/copy-to-ecx 4/imm32"  "F - test-shadow-local/11")
 4104     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %ecx" "F - test-shadow-local/12")
 4105     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-local/13")
 4106     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-local/14")
 4107     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-local/15")
 4108     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-local/16")
 4109     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-local/17")
 4110     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-local/18")
 4111     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-local/19")
 4112     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-local/20")
 4113     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-local/21")
 4114     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-local/22")
 4115     # . epilogue
 4116     89/<- %esp 5/r32/ebp
 4117     5d/pop-to-ebp
 4118     c3/return
 4119 
 4120 test-shadow-name:
 4121     # . prologue
 4122     55/push-ebp
 4123     89/<- %ebp 4/r32/esp
 4124     # setup
 4125     (clear-stream _test-input-stream)
 4126     (clear-stream $_test-input-buffered-file->buffer)
 4127     (clear-stream _test-output-stream)
 4128     (clear-stream $_test-output-buffered-file->buffer)
 4129     #
 4130     (write _test-input-stream "fn foo {\n")
 4131     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4132     (write _test-input-stream "  {\n")
 4133     (write _test-input-stream "    var x/edx: int <- copy 4\n")
 4134     (write _test-input-stream "  }\n")
 4135     (write _test-input-stream "  x <- increment\n")
 4136     (write _test-input-stream "}\n")
 4137     # convert
 4138     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4139     (flush _test-output-buffered-file)
 4140 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 4146     # check output
 4147     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-name/0")
 4148     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-name/1")
 4149     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-name/2")
 4150     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-name/3")
 4151     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-name/4")
 4152     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-name/5")
 4153     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-name/6")
 4154     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-name/7")
 4155     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-name/8")
 4156     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-name/9")
 4157     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %edx"  "F - test-shadow-name/10")
 4158     (check-next-stream-line-equal _test-output-stream "      ba/copy-to-edx 4/imm32"  "F - test-shadow-name/11")
 4159     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %edx" "F - test-shadow-name/12")
 4160     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-name/13")
 4161     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-name/14")
 4162     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-name/15")
 4163     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-name/16")
 4164     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-name/17")
 4165     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-name/18")
 4166     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-name/19")
 4167     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-name/20")
 4168     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-name/21")
 4169     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-name/22")
 4170     # . epilogue
 4171     89/<- %esp 5/r32/ebp
 4172     5d/pop-to-ebp
 4173     c3/return
 4174 
 4175 test-shadow-name-2:
 4176     # . prologue
 4177     55/push-ebp
 4178     89/<- %ebp 4/r32/esp
 4179     # setup
 4180     (clear-stream _test-input-stream)
 4181     (clear-stream $_test-input-buffered-file->buffer)
 4182     (clear-stream _test-output-stream)
 4183     (clear-stream $_test-output-buffered-file->buffer)
 4184     #
 4185     (write _test-input-stream "fn foo {\n")
 4186     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4187     (write _test-input-stream "  {\n")
 4188     (write _test-input-stream "    var x/edx: int <- copy 4\n")
 4189     (write _test-input-stream "    var y/ecx: int <- copy 5\n")
 4190     (write _test-input-stream "  }\n")
 4191     (write _test-input-stream "  x <- increment\n")
 4192     (write _test-input-stream "}\n")
 4193     # convert
 4194     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4195     (flush _test-output-buffered-file)
 4196 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 4202     # check output
 4203     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-name-2/0")
 4204     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-name-2/1")
 4205     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-name-2/2")
 4206     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-name-2/3")
 4207     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-name-2/4")
 4208     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-name-2/5")
 4209     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-name-2/6")
 4210     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-name-2/7")
 4211     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-name-2/8")
 4212     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-name-2/9")
 4213     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %edx"  "F - test-shadow-name-2/10")
 4214     (check-next-stream-line-equal _test-output-stream "      ba/copy-to-edx 4/imm32"  "F - test-shadow-name-2/11")
 4215     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %ecx"  "F - test-shadow-name-2/12")
 4216     (check-next-stream-line-equal _test-output-stream "      b9/copy-to-ecx 5/imm32"  "F - test-shadow-name-2/13")
 4217     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %ecx" "F - test-shadow-name-2/14")
 4218     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %edx" "F - test-shadow-name-2/15")
 4219     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-name-2/16")
 4220     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-name-2/17")
 4221     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-name-2/18")
 4222     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-name-2/19")
 4223     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-name-2/20")
 4224     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-name-2/21")
 4225     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-name-2/22")
 4226     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-name-2/23")
 4227     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-name-2/24")
 4228     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-name-2/25")
 4229     # . epilogue
 4230     89/<- %esp 5/r32/ebp
 4231     5d/pop-to-ebp
 4232     c3/return
 4233 
 4234 test-do-not-spill-same-register-in-block:
 4235     # . prologue
 4236     55/push-ebp
 4237     89/<- %ebp 4/r32/esp
 4238     # setup
 4239     (clear-stream _test-input-stream)
 4240     (clear-stream $_test-input-buffered-file->buffer)
 4241     (clear-stream _test-output-stream)
 4242     (clear-stream $_test-output-buffered-file->buffer)
 4243     #
 4244     (write _test-input-stream "fn foo {\n")
 4245     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4246     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 4247     (write _test-input-stream "  y <- increment\n")
 4248     (write _test-input-stream "}\n")
 4249     # convert
 4250     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4251     (flush _test-output-buffered-file)
 4252 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 4258     # check output
 4259     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-do-not-spill-same-register-in-block/0")
 4260     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-do-not-spill-same-register-in-block/1")
 4261     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-do-not-spill-same-register-in-block/2")
 4262     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-do-not-spill-same-register-in-block/3")
 4263     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-do-not-spill-same-register-in-block/4")
 4264     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-do-not-spill-same-register-in-block/5")
 4265     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-do-not-spill-same-register-in-block/6")
 4266     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-do-not-spill-same-register-in-block/7")
 4267     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-do-not-spill-same-register-in-block/8")
 4268     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-do-not-spill-same-register-in-block/9")
 4269     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-do-not-spill-same-register-in-block/10")
 4270     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-do-not-spill-same-register-in-block/11")
 4271     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-do-not-spill-same-register-in-block/12")
 4272     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-do-not-spill-same-register-in-block/13")
 4273     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-do-not-spill-same-register-in-block/14")
 4274     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-do-not-spill-same-register-in-block/15")
 4275     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-do-not-spill-same-register-in-block/16")
 4276     # . epilogue
 4277     89/<- %esp 5/r32/ebp
 4278     5d/pop-to-ebp
 4279     c3/return
 4280 
 4281 test-spill-different-register-in-block:
 4282     # . prologue
 4283     55/push-ebp
 4284     89/<- %ebp 4/r32/esp
 4285     # setup
 4286     (clear-stream _test-input-stream)
 4287     (clear-stream $_test-input-buffered-file->buffer)
 4288     (clear-stream _test-output-stream)
 4289     (clear-stream $_test-output-buffered-file->buffer)
 4290     #
 4291     (write _test-input-stream "fn foo {\n")
 4292     (write _test-input-stream "  var x/eax: int <- copy 3\n")
 4293     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 4294     (write _test-input-stream "  y <- increment\n")
 4295     (write _test-input-stream "}\n")
 4296     # convert
 4297     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4298     (flush _test-output-buffered-file)
 4299 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 4305     # check output
 4306     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-spill-different-register-in-block/0")
 4307     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-spill-different-register-in-block/1")
 4308     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-spill-different-register-in-block/2")
 4309     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-spill-different-register-in-block/3")
 4310     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-spill-different-register-in-block/4")
 4311     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-spill-different-register-in-block/5")
 4312     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-spill-different-register-in-block/6")
 4313     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-spill-different-register-in-block/7")
 4314     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-spill-different-register-in-block/8")
 4315     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-spill-different-register-in-block/9")
 4316     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-spill-different-register-in-block/10")
 4317     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-spill-different-register-in-block/11")
 4318     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-spill-different-register-in-block/12")
 4319     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-spill-different-register-in-block/13")
 4320     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-spill-different-register-in-block/14")
 4321     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-spill-different-register-in-block/15")
 4322     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-spill-different-register-in-block/16")
 4323     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-spill-different-register-in-block/17")
 4324     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-spill-different-register-in-block/18")
 4325     # . epilogue
 4326     89/<- %esp 5/r32/ebp
 4327     5d/pop-to-ebp
 4328     c3/return
 4329 
 4330 test-convert-function-with-branches-in-block:
 4331     # . prologue
 4332     55/push-ebp
 4333     89/<- %ebp 4/r32/esp
 4334     # setup
 4335     (clear-stream _test-input-stream)
 4336     (clear-stream $_test-input-buffered-file->buffer)
 4337     (clear-stream _test-output-stream)
 4338     (clear-stream $_test-output-buffered-file->buffer)
 4339     #
 4340     (write _test-input-stream "fn foo x: int {\n")
 4341     (write _test-input-stream "  {\n")
 4342     (write _test-input-stream "    break-if->=\n")
 4343     (write _test-input-stream "    loop-if-addr<\n")
 4344     (write _test-input-stream "    increment x\n")
 4345     (write _test-input-stream "    loop\n")
 4346     (write _test-input-stream "  }\n")
 4347     (write _test-input-stream "}\n")
 4348     # convert
 4349     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4350     (flush _test-output-buffered-file)
 4351 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 4357     # check output
 4358     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-block/0")
 4359     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-block/1")
 4360     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-block/2")
 4361     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-block/3")
 4362     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-block/4")
 4363     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-block/5")
 4364     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-block/6")
 4365     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-in-block/7")
 4366     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/8")
 4367     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-block/9")
 4368     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-in-block/10")
 4369     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/11")
 4370     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/12")
 4371     (check-next-stream-line-equal _test-output-stream "        0f 83/jump-if-addr>= break/disp32"  "F - test-convert-function-with-branches-in-block/13")
 4372     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:loop/disp32"  "F - test-convert-function-with-branches-in-block/14")
 4373     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/15")
 4374     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-block/16")
 4375     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-in-block/17")
 4376     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-block/18")
 4377     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-in-block/19")
 4378     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-block/20")
 4379     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-block/21")
 4380     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-block/22")
 4381     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-block/23")
 4382     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-block/24")
 4383     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-block/25")
 4384     # . epilogue
 4385     89/<- %esp 5/r32/ebp
 4386     5d/pop-to-ebp
 4387     c3/return
 4388 
 4389 test-convert-function-with-branches-in-block-2:
 4390     # . prologue
 4391     55/push-ebp
 4392     89/<- %ebp 4/r32/esp
 4393     # setup
 4394     (clear-stream _test-input-stream)
 4395     (clear-stream $_test-input-buffered-file->buffer)
 4396     (clear-stream _test-output-stream)
 4397     (clear-stream $_test-output-buffered-file->buffer)
 4398     #
 4399     (write _test-input-stream "fn foo x: int {\n")
 4400     (write _test-input-stream "  {\n")
 4401     (write _test-input-stream "    break-if->=\n")
 4402     (write _test-input-stream "    loop-if-float<\n")
 4403     (write _test-input-stream "    increment x\n")
 4404     (write _test-input-stream "    loop\n")
 4405     (write _test-input-stream "  }\n")
 4406     (write _test-input-stream "}\n")
 4407     # convert
 4408     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4409     (flush _test-output-buffered-file)
 4410 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 4416     # check output
 4417     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-block/0")
 4418     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-block/1")
 4419     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-block/2")
 4420     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-block/3")
 4421     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-block/4")
 4422     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-block/5")
 4423     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-block/6")
 4424     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-in-block/7")
 4425     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/8")
 4426     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-block/9")
 4427     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-in-block/10")
 4428     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/11")
 4429     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/12")
 4430     (check-next-stream-line-equal _test-output-stream "        0f 83/jump-if-addr>= break/disp32"  "F - test-convert-function-with-branches-in-block/13")
 4431     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:loop/disp32"  "F - test-convert-function-with-branches-in-block/14")
 4432     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/15")
 4433     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-block/16")
 4434     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-in-block/17")
 4435     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-block/18")
 4436     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-in-block/19")
 4437     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-block/20")
 4438     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-block/21")
 4439     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-block/22")
 4440     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-block/23")
 4441     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-block/24")
 4442     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-block/25")
 4443     # . epilogue
 4444     89/<- %esp 5/r32/ebp
 4445     5d/pop-to-ebp
 4446     c3/return
 4447 
 4448 test-convert-function-with-branches-in-named-block:
 4449     # . prologue
 4450     55/push-ebp
 4451     89/<- %ebp 4/r32/esp
 4452     # setup
 4453     (clear-stream _test-input-stream)
 4454     (clear-stream $_test-input-buffered-file->buffer)
 4455     (clear-stream _test-output-stream)
 4456     (clear-stream $_test-output-buffered-file->buffer)
 4457     #
 4458     (write _test-input-stream "fn foo x: int {\n")
 4459     (write _test-input-stream "  $bar: {\n")
 4460     (write _test-input-stream "    break-if->= $bar\n")
 4461     (write _test-input-stream "    loop-if-addr< $bar\n")
 4462     (write _test-input-stream "    increment x\n")
 4463     (write _test-input-stream "    loop\n")
 4464     (write _test-input-stream "  }\n")
 4465     (write _test-input-stream "}\n")
 4466     # convert
 4467     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4468     (flush _test-output-buffered-file)
 4469 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 4475     # check output
 4476     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-named-block/0")
 4477     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-named-block/1")
 4478     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-named-block/2")
 4479     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-named-block/3")
 4480     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-named-block/4")
 4481     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-named-block/5")
 4482     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-named-block/6")
 4483     (check-next-stream-line-equal _test-output-stream "$bar:loop:"              "F - test-convert-function-with-branches-in-named-block/7")
 4484     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-named-block/8")
 4485     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-named-block/9")
 4486     (check-next-stream-line-equal _test-output-stream "        e9/jump $bar:break/disp32"  "F - test-convert-function-with-branches-in-named-block/10")
 4487     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-named-block/11")
 4488     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-named-block/12")
 4489     (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")
 4490     (check-next-stream-line-equal _test-output-stream "        e9/jump $bar:loop/disp32"  "F - test-convert-function-with-branches-in-named-block/14")
 4491     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-named-block/15")
 4492     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-named-block/16")
 4493     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"   "F - test-convert-function-with-branches-in-named-block/17")
 4494     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-named-block/18")
 4495     (check-next-stream-line-equal _test-output-stream "$bar:break:"             "F - test-convert-function-with-branches-in-named-block/19")
 4496     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-named-block/20")
 4497     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-named-block/21")
 4498     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-named-block/22")
 4499     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-named-block/23")
 4500     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-named-block/24")
 4501     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-named-block/25")
 4502     # . epilogue
 4503     89/<- %esp 5/r32/ebp
 4504     5d/pop-to-ebp
 4505     c3/return
 4506 
 4507 test-convert-function-with-var-in-nested-block:
 4508     # . prologue
 4509     55/push-ebp
 4510     89/<- %ebp 4/r32/esp
 4511     # setup
 4512     (clear-stream _test-input-stream)
 4513     (clear-stream $_test-input-buffered-file->buffer)
 4514     (clear-stream _test-output-stream)
 4515     (clear-stream $_test-output-buffered-file->buffer)
 4516     #
 4517     (write _test-input-stream "fn foo x: int {\n")
 4518     (write _test-input-stream "  {\n")
 4519     (write _test-input-stream "    {\n")
 4520     (write _test-input-stream "      var x: int\n")
 4521     (write _test-input-stream "      increment x\n")
 4522     (write _test-input-stream "    }\n")
 4523     (write _test-input-stream "  }\n")
 4524     (write _test-input-stream "}\n")
 4525     # convert
 4526     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4527     (flush _test-output-buffered-file)
 4528 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 4534     # check output
 4535     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-var-in-nested-block/0")
 4536     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-var-in-nested-block/1")
 4537     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-var-in-nested-block/2")
 4538     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-var-in-nested-block/3")
 4539     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-var-in-nested-block/4")
 4540     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-var-in-nested-block/5")
 4541     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-var-in-nested-block/6")
 4542     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-var-in-nested-block/7")
 4543     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-var-in-nested-block/8")
 4544     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-var-in-nested-block/9")
 4545     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-var-in-nested-block/10")
 4546     (check-next-stream-line-equal _test-output-stream "        ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-var-in-nested-block/11")
 4547     (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")
 4548     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-var-in-nested-block/13")
 4549     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-var-in-nested-block/14")
 4550     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-var-in-nested-block/15")
 4551     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-var-in-nested-block/16")
 4552     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-var-in-nested-block/17")
 4553     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-var-in-nested-block/18")
 4554     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-var-in-nested-block/19")
 4555     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-var-in-nested-block/20")
 4556     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-var-in-nested-block/21")
 4557     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-var-in-nested-block/22")
 4558     # . epilogue
 4559     89/<- %esp 5/r32/ebp
 4560     5d/pop-to-ebp
 4561     c3/return
 4562 
 4563 test-convert-function-with-multiple-vars-in-nested-blocks:
 4564     # . prologue
 4565     55/push-ebp
 4566     89/<- %ebp 4/r32/esp
 4567     # setup
 4568     (clear-stream _test-input-stream)
 4569     (clear-stream $_test-input-buffered-file->buffer)
 4570     (clear-stream _test-output-stream)
 4571     (clear-stream $_test-output-buffered-file->buffer)
 4572     #
 4573     (write _test-input-stream "fn foo x: int {\n")
 4574     (write _test-input-stream "  {\n")
 4575     (write _test-input-stream "    var x/eax: int <- copy 0\n")
 4576     (write _test-input-stream "    {\n")
 4577     (write _test-input-stream "      var y: int\n")
 4578     (write _test-input-stream "      x <- add y\n")
 4579     (write _test-input-stream "    }\n")
 4580     (write _test-input-stream "  }\n")
 4581     (write _test-input-stream "}\n")
 4582     # convert
 4583     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4584     (flush _test-output-buffered-file)
 4585 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 4591     # check output
 4592     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-multiple-vars-in-nested-blocks/0")
 4593     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-multiple-vars-in-nested-blocks/1")
 4594     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-multiple-vars-in-nested-blocks/2")
 4595     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/3")
 4596     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-multiple-vars-in-nested-blocks/4")
 4597     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/5")
 4598     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-multiple-vars-in-nested-blocks/6")
 4599     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/7")
 4600     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %eax"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/8")
 4601     (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")
 4602     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-multiple-vars-in-nested-blocks/10")
 4603     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/11")
 4604     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-multiple-vars-in-nested-blocks/12")
 4605     (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")
 4606     (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")
 4607     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-multiple-vars-in-nested-blocks/15")
 4608     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/16")
 4609     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %eax"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/17")
 4610     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-multiple-vars-in-nested-blocks/18")
 4611     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/19")
 4612     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-multiple-vars-in-nested-blocks/20")
 4613     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/21")
 4614     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-multiple-vars-in-nested-blocks/22")
 4615     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/23")
 4616     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-multiple-vars-in-nested-blocks/24")
 4617     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-multiple-vars-in-nested-blocks/25")
 4618     # . epilogue
 4619     89/<- %esp 5/r32/ebp
 4620     5d/pop-to-ebp
 4621     c3/return
 4622 
 4623 test-convert-function-with-branches-and-local-vars:
 4624     # A conditional 'break' after a 'var' in a block is converted into a
 4625     # nested block that performs all necessary cleanup before jumping. This
 4626     # results in some ugly code duplication.
 4627     # . prologue
 4628     55/push-ebp
 4629     89/<- %ebp 4/r32/esp
 4630     # setup
 4631     (clear-stream _test-input-stream)
 4632     (clear-stream $_test-input-buffered-file->buffer)
 4633     (clear-stream _test-output-stream)
 4634     (clear-stream $_test-output-buffered-file->buffer)
 4635     #
 4636     (write _test-input-stream "fn foo {\n")
 4637     (write _test-input-stream "  {\n")
 4638     (write _test-input-stream "    var x: int\n")
 4639     (write _test-input-stream "    break-if->=\n")
 4640     (write _test-input-stream "    increment x\n")
 4641     (write _test-input-stream "  }\n")
 4642     (write _test-input-stream "}\n")
 4643     # convert
 4644     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4645     (flush _test-output-buffered-file)
 4646 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 4652     # check output
 4653     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-and-local-vars/0")
 4654     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-and-local-vars/1")
 4655     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-and-local-vars/2")
 4656     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-and-local-vars/3")
 4657     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-and-local-vars/4")
 4658     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-and-local-vars/5")
 4659     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-and-local-vars/6")
 4660     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-and-local-vars/7")
 4661     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-branches-and-local-vars/8")
 4662     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-and-local-vars/9")
 4663     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-and-local-vars/10")
 4664     (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")
 4665     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-and-local-vars/12")
 4666     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-and-local-vars/13")
 4667     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-branches-and-local-vars/14")
 4668     (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")
 4669     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-and-local-vars/16")
 4670     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-and-local-vars/17")
 4671     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-and-local-vars/18")
 4672     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-and-local-vars/19")
 4673     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-and-local-vars/20")
 4674     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-and-local-vars/21")
 4675     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-and-local-vars/22")
 4676     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-and-local-vars/23")
 4677     # . epilogue
 4678     89/<- %esp 5/r32/ebp
 4679     5d/pop-to-ebp
 4680     c3/return
 4681 
 4682 test-convert-function-with-conditional-loops-and-local-vars:
 4683     # A conditional 'loop' after a 'var' in a block is converted into a nested
 4684     # block that performs all necessary cleanup before jumping. This results
 4685     # in some ugly code duplication.
 4686     # . prologue
 4687     55/push-ebp
 4688     89/<- %ebp 4/r32/esp
 4689     # setup
 4690     (clear-stream _test-input-stream)
 4691     (clear-stream $_test-input-buffered-file->buffer)
 4692     (clear-stream _test-output-stream)
 4693     (clear-stream $_test-output-buffered-file->buffer)
 4694     #
 4695     (write _test-input-stream "fn foo {\n")
 4696     (write _test-input-stream "  {\n")
 4697     (write _test-input-stream "    var x: int\n")
 4698     (write _test-input-stream "    loop-if->=\n")
 4699     (write _test-input-stream "    increment x\n")
 4700     (write _test-input-stream "  }\n")
 4701     (write _test-input-stream "}\n")
 4702     # convert
 4703     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4704     (flush _test-output-buffered-file)
 4705 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 4711     # check output
 4712     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-conditional-loops-and-local-vars/0")
 4713     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-conditional-loops-and-local-vars/1")
 4714     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-conditional-loops-and-local-vars/2")
 4715     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-conditional-loops-and-local-vars/3")
 4716     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-conditional-loops-and-local-vars/4")
 4717     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-conditional-loops-and-local-vars/5")
 4718     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-conditional-loops-and-local-vars/6")
 4719     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-conditional-loops-and-local-vars/7")
 4720     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-conditional-loops-and-local-vars/8")
 4721     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-conditional-loops-and-local-vars/9")
 4722     (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")
 4723     (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")
 4724     (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")
 4725     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-conditional-loops-and-local-vars/13")
 4726     (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")
 4727     (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")
 4728     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-conditional-loops-and-local-vars/16")
 4729     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-conditional-loops-and-local-vars/17")
 4730     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-conditional-loops-and-local-vars/18")
 4731     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-conditional-loops-and-local-vars/19")
 4732     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-conditional-loops-and-local-vars/20")
 4733     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-conditional-loops-and-local-vars/21")
 4734     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-conditional-loops-and-local-vars/22")
 4735     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-conditional-loops-and-local-vars/23")
 4736     # . epilogue
 4737     89/<- %esp 5/r32/ebp
 4738     5d/pop-to-ebp
 4739     c3/return
 4740 
 4741 test-convert-function-with-unconditional-loops-and-local-vars:
 4742     # An unconditional 'loop' after a 'var' in a block is emitted _after_ the
 4743     # regular block cleanup. Any instructions after 'loop' are dead and
 4744     # therefore skipped.
 4745     # . prologue
 4746     55/push-ebp
 4747     89/<- %ebp 4/r32/esp
 4748     # setup
 4749     (clear-stream _test-input-stream)
 4750     (clear-stream $_test-input-buffered-file->buffer)
 4751     (clear-stream _test-output-stream)
 4752     (clear-stream $_test-output-buffered-file->buffer)
 4753     #
 4754     (write _test-input-stream "fn foo {\n")
 4755     (write _test-input-stream "  {\n")
 4756     (write _test-input-stream "    var x: int\n")
 4757     (write _test-input-stream "    loop\n")
 4758     (write _test-input-stream "    increment x\n")
 4759     (write _test-input-stream "  }\n")
 4760     (write _test-input-stream "}\n")
 4761     # convert
 4762     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4763     (flush _test-output-buffered-file)
 4764 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 4770     # check output
 4771     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-unconditional-loops-and-local-vars/0")
 4772     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-unconditional-loops-and-local-vars/1")
 4773     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-unconditional-loops-and-local-vars/2")
 4774     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-unconditional-loops-and-local-vars/3")
 4775     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-unconditional-loops-and-local-vars/4")
 4776     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-unconditional-loops-and-local-vars/5")
 4777     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-unconditional-loops-and-local-vars/6")
 4778     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-unconditional-loops-and-local-vars/7")
 4779     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-unconditional-loops-and-local-vars/8")
 4780     (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")
 4781     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-unconditional-loops-and-local-vars/10")
 4782     # not emitted:                                           ff 0/subop/increment *(ebp+0xfffffffc)
 4783     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-unconditional-loops-and-local-vars/11")
 4784     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-unconditional-loops-and-local-vars/12")
 4785     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-unconditional-loops-and-local-vars/13")
 4786     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-unconditional-loops-and-local-vars/14")
 4787     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-unconditional-loops-and-local-vars/15")
 4788     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-unconditional-loops-and-local-vars/16")
 4789     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-unconditional-loops-and-local-vars/17")
 4790     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-unconditional-loops-and-local-vars/18")
 4791     # . epilogue
 4792     89/<- %esp 5/r32/ebp
 4793     5d/pop-to-ebp
 4794     c3/return
 4795 
 4796 test-convert-function-with-branches-and-loops-and-local-vars:
 4797     # . prologue
 4798     55/push-ebp
 4799     89/<- %ebp 4/r32/esp
 4800     # setup
 4801     (clear-stream _test-input-stream)
 4802     (clear-stream $_test-input-buffered-file->buffer)
 4803     (clear-stream _test-output-stream)
 4804     (clear-stream $_test-output-buffered-file->buffer)
 4805     #
 4806     (write _test-input-stream "fn foo {\n")
 4807     (write _test-input-stream "  {\n")
 4808     (write _test-input-stream "    var x: int\n")
 4809     (write _test-input-stream "    break-if->=\n")
 4810     (write _test-input-stream "    increment x\n")
 4811     (write _test-input-stream "    loop\n")
 4812     (write _test-input-stream "  }\n")
 4813     (write _test-input-stream "}\n")
 4814     # convert
 4815     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4816     (flush _test-output-buffered-file)
 4817 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 4823     # check output
 4824     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-and-loops-and-local-vars/0")
 4825     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-and-loops-and-local-vars/1")
 4826     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-and-loops-and-local-vars/2")
 4827     (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")
 4828     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-and-loops-and-local-vars/4")
 4829     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-and-loops-and-local-vars/5")
 4830     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-and-loops-and-local-vars/6")
 4831     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-and-loops-and-local-vars/7")
 4832     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-branches-and-loops-and-local-vars/8")
 4833     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-and-loops-and-local-vars/9")
 4834     (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")
 4835     (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")
 4836     (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")
 4837     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-and-loops-and-local-vars/13")
 4838     (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")
 4839     (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")
 4840     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-and-loops-and-local-vars/16")
 4841     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-and-loops-and-local-vars/17")
 4842     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-and-loops-and-local-vars/18")
 4843     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-and-loops-and-local-vars/19")
 4844     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-and-loops-and-local-vars/20")
 4845     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-and-loops-and-local-vars/21")
 4846     (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")
 4847     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-and-loops-and-local-vars/23")
 4848     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-and-loops-and-local-vars/24")
 4849     # . epilogue
 4850     89/<- %esp 5/r32/ebp
 4851     5d/pop-to-ebp
 4852     c3/return
 4853 
 4854 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars:
 4855     # . prologue
 4856     55/push-ebp
 4857     89/<- %ebp 4/r32/esp
 4858     # setup
 4859     (clear-stream _test-input-stream)
 4860     (clear-stream $_test-input-buffered-file->buffer)
 4861     (clear-stream _test-output-stream)
 4862     (clear-stream $_test-output-buffered-file->buffer)
 4863     #
 4864     (write _test-input-stream "fn foo {\n")
 4865     (write _test-input-stream "  a: {\n")
 4866     (write _test-input-stream "    var x: int\n")
 4867     (write _test-input-stream "    {\n")
 4868     (write _test-input-stream "      var y: int\n")
 4869     (write _test-input-stream "      break-if->= a\n")
 4870     (write _test-input-stream "      increment x\n")
 4871     (write _test-input-stream "      loop\n")
 4872     (write _test-input-stream "    }\n")
 4873     (write _test-input-stream "  }\n")
 4874     (write _test-input-stream "}\n")
 4875     # convert
 4876     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4877     (flush _test-output-buffered-file)
 4878 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 4884     # check output
 4885     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/0")
 4886     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/1")
 4887     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/2")
 4888     (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")
 4889     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/4")
 4890     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/5")
 4891     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/6")
 4892     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/7")
 4893     (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")
 4894     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/9")
 4895     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/10")
 4896     (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")
 4897     (check-next-stream-line-equal _test-output-stream "        {"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/12")
 4898     (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")
 4899     (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")
 4900     (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")
 4901     (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")
 4902     (check-next-stream-line-equal _test-output-stream "        }"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/17")
 4903     (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")
 4904     (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")
 4905     (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")
 4906     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/21")
 4907     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/22")
 4908     (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")
 4909     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/24")
 4910     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/25")
 4911     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/26")
 4912     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/27")
 4913     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/28")
 4914     (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")
 4915     (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")
 4916     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/31")
 4917     # . epilogue
 4918     89/<- %esp 5/r32/ebp
 4919     5d/pop-to-ebp
 4920     c3/return
 4921 
 4922 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2:
 4923     # . prologue
 4924     55/push-ebp
 4925     89/<- %ebp 4/r32/esp
 4926     # setup
 4927     (clear-stream _test-input-stream)
 4928     (clear-stream $_test-input-buffered-file->buffer)
 4929     (clear-stream _test-output-stream)
 4930     (clear-stream $_test-output-buffered-file->buffer)
 4931     # non-local conditional branch from a block without a local variable,
 4932     # unwinding a local on the stack
 4933     (write _test-input-stream "fn foo {\n")
 4934     (write _test-input-stream "  a: {\n")
 4935     (write _test-input-stream "    var x: int\n")
 4936     (write _test-input-stream "    {\n")
 4937     (write _test-input-stream "      break-if->= a\n")
 4938     (write _test-input-stream "    }\n")
 4939     (write _test-input-stream "  }\n")
 4940     (write _test-input-stream "}\n")
 4941     # convert
 4942     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4943     (flush _test-output-buffered-file)
 4944 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 4950     # check output
 4951     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/0")
 4952     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/1")
 4953     (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")
 4954     (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")
 4955     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/4")
 4956     (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")
 4957     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/6")
 4958     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/7")
 4959     (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")
 4960     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/9")
 4961     (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")
 4962     (check-next-stream-line-equal _test-output-stream "        {"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/11")
 4963     (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")
 4964     (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")
 4965     (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")
 4966     (check-next-stream-line-equal _test-output-stream "        }"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/15")
 4967     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/16")
 4968     (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")
 4969     (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")
 4970     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/19")
 4971     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/20")
 4972     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/21")
 4973     (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")
 4974     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/23")
 4975     (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")
 4976     (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")
 4977     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/26")
 4978     # . epilogue
 4979     89/<- %esp 5/r32/ebp
 4980     5d/pop-to-ebp
 4981     c3/return
 4982 
 4983 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3:
 4984     # . prologue
 4985     55/push-ebp
 4986     89/<- %ebp 4/r32/esp
 4987     # setup
 4988     (clear-stream _test-input-stream)
 4989     (clear-stream $_test-input-buffered-file->buffer)
 4990     (clear-stream _test-output-stream)
 4991     (clear-stream $_test-output-buffered-file->buffer)
 4992     # non-local unconditional branch from a block without a local variable,
 4993     # unwinding a local on the stack
 4994     (write _test-input-stream "fn foo {\n")
 4995     (write _test-input-stream "  a: {\n")
 4996     (write _test-input-stream "    var x: int\n")
 4997     (write _test-input-stream "    {\n")
 4998     (write _test-input-stream "      break a\n")
 4999     (write _test-input-stream "    }\n")
 5000     (write _test-input-stream "  }\n")
 5001     (write _test-input-stream "}\n")
 5002     # convert
 5003     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5004     (flush _test-output-buffered-file)
 5005 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 5011     # check output
 5012     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/0")
 5013     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/1")
 5014     (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")
 5015     (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")
 5016     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/4")
 5017     (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")
 5018     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/6")
 5019     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/7")
 5020     (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")
 5021     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/9")
 5022     (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")
 5023     (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")
 5024     (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")
 5025     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/14")
 5026     (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")
 5027     (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")
 5028     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/17")
 5029     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/18")
 5030     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/19")
 5031     (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")
 5032     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/21")
 5033     (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")
 5034     (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")
 5035     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/24")
 5036     # . epilogue
 5037     89/<- %esp 5/r32/ebp
 5038     5d/pop-to-ebp
 5039     c3/return
 5040 
 5041 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4:
 5042     # . prologue
 5043     55/push-ebp
 5044     89/<- %ebp 4/r32/esp
 5045     # setup
 5046     (clear-stream _test-input-stream)
 5047     (clear-stream $_test-input-buffered-file->buffer)
 5048     (clear-stream _test-output-stream)
 5049     (clear-stream $_test-output-buffered-file->buffer)
 5050     #
 5051     (write _test-input-stream "fn foo {\n")
 5052     (write _test-input-stream "  a: {\n")
 5053     (write _test-input-stream "    var x/esi: int <- copy 0\n")
 5054     (write _test-input-stream "    {\n")
 5055     (write _test-input-stream "      break a\n")
 5056     (write _test-input-stream "    }\n")
 5057     (write _test-input-stream "  }\n")
 5058     (write _test-input-stream "}\n")
 5059     # convert
 5060     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5061     (flush _test-output-buffered-file)
 5062 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 5068     # check output
 5069     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/0")
 5070     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/1")
 5071     (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")
 5072     (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")
 5073     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/4")
 5074     (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")
 5075     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/6")
 5076     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/7")
 5077     (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")
 5078     (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")
 5079     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/10")
 5080     (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")
 5081     (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")
 5082     (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")
 5083     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/14")
 5084     (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")
 5085     (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")
 5086     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/17")
 5087     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/18")
 5088     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/19")
 5089     (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")
 5090     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/21")
 5091     (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")
 5092     (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")
 5093     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/24")
 5094     # . epilogue
 5095     89/<- %esp 5/r32/ebp
 5096     5d/pop-to-ebp
 5097     c3/return
 5098 
 5099 test-convert-function-with-nonlocal-unconditional-break-and-local-vars:
 5100     # . prologue
 5101     55/push-ebp
 5102     89/<- %ebp 4/r32/esp
 5103     # setup
 5104     (clear-stream _test-input-stream)
 5105     (clear-stream $_test-input-buffered-file->buffer)
 5106     (clear-stream _test-output-stream)
 5107     (clear-stream $_test-output-buffered-file->buffer)
 5108     #
 5109     (write _test-input-stream "fn foo {\n")
 5110     (write _test-input-stream "  a: {\n")
 5111     (write _test-input-stream "    var x: int\n")
 5112     (write _test-input-stream "    {\n")
 5113     (write _test-input-stream "      var y: int\n")
 5114     (write _test-input-stream "      break a\n")
 5115     (write _test-input-stream "      increment x\n")
 5116     (write _test-input-stream "    }\n")
 5117     (write _test-input-stream "  }\n")
 5118     (write _test-input-stream "}\n")
 5119     # convert
 5120     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5121     (flush _test-output-buffered-file)
 5122 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 5128     # check output
 5129     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/0")
 5130     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/1")
 5131     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/2")
 5132     (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")
 5133     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/4")
 5134     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/5")
 5135     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/6")
 5136     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/7")
 5137     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/8")
 5138     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/9")
 5139     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/10")
 5140     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/11")
 5141     (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")
 5142     (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")
 5143     (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")
 5144     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/15")
 5145     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/16")
 5146     (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")
 5147     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/18")
 5148     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/19")
 5149     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/20")
 5150     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/21")
 5151     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/22")
 5152     (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")
 5153     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/24")
 5154     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/25")
 5155     # . epilogue
 5156     89/<- %esp 5/r32/ebp
 5157     5d/pop-to-ebp
 5158     c3/return
 5159 
 5160 test-convert-function-with-unconditional-break-and-local-vars:
 5161     # . prologue
 5162     55/push-ebp
 5163     89/<- %ebp 4/r32/esp
 5164     # setup
 5165     (clear-stream _test-input-stream)
 5166     (clear-stream $_test-input-buffered-file->buffer)
 5167     (clear-stream _test-output-stream)
 5168     (clear-stream $_test-output-buffered-file->buffer)
 5169     #
 5170     (write _test-input-stream "fn foo {\n")
 5171     (write _test-input-stream "  {\n")
 5172     (write _test-input-stream "    var x: int\n")
 5173     (write _test-input-stream "    {\n")
 5174     (write _test-input-stream "      var y: int\n")
 5175     (write _test-input-stream "      break\n")
 5176     (write _test-input-stream "      increment x\n")
 5177     (write _test-input-stream "    }\n")
 5178     (write _test-input-stream "  }\n")
 5179     (write _test-input-stream "}\n")
 5180     # convert
 5181     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5182     (flush _test-output-buffered-file)
 5183 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 5189     # check output
 5190     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-unconditional-break-and-local-vars/0")
 5191     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-unconditional-break-and-local-vars/1")
 5192     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-unconditional-break-and-local-vars/2")
 5193     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-unconditional-break-and-local-vars/3")
 5194     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-unconditional-break-and-local-vars/4")
 5195     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/5")
 5196     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-unconditional-break-and-local-vars/6")
 5197     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/7")
 5198     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-unconditional-break-and-local-vars/8")
 5199     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-unconditional-break-and-local-vars/9")
 5200     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/10")
 5201     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-unconditional-break-and-local-vars/11")
 5202     (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")
 5203     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-unconditional-break-and-local-vars/13")
 5204     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/14")
 5205     (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")
 5206     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-unconditional-break-and-local-vars/16")
 5207     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/17")
 5208     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-unconditional-break-and-local-vars/18")
 5209     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/19")
 5210     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-unconditional-break-and-local-vars/20")
 5211     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-unconditional-break-and-local-vars/21")
 5212     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-unconditional-break-and-local-vars/22")
 5213     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-unconditional-break-and-local-vars/23")
 5214     # . epilogue
 5215     89/<- %esp 5/r32/ebp
 5216     5d/pop-to-ebp
 5217     c3/return
 5218 
 5219 test-convert-function-with-nonlocal-unconditional-loop-and-local-vars:
 5220     # . prologue
 5221     55/push-ebp
 5222     89/<- %ebp 4/r32/esp
 5223     # setup
 5224     (clear-stream _test-input-stream)
 5225     (clear-stream $_test-input-buffered-file->buffer)
 5226     (clear-stream _test-output-stream)
 5227     (clear-stream $_test-output-buffered-file->buffer)
 5228     #
 5229     (write _test-input-stream "fn foo {\n")
 5230     (write _test-input-stream "  a: {\n")
 5231     (write _test-input-stream "    var x: int\n")
 5232     (write _test-input-stream "    {\n")
 5233     (write _test-input-stream "      var y: int\n")
 5234     (write _test-input-stream "      loop a\n")
 5235     (write _test-input-stream "      increment x\n")
 5236     (write _test-input-stream "    }\n")
 5237     (write _test-input-stream "  }\n")
 5238     (write _test-input-stream "}\n")
 5239     # convert
 5240     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5241     (flush _test-output-buffered-file)
 5242 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 5248     # check output
 5249     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/0")
 5250     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/1")
 5251     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/2")
 5252     (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")
 5253     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/4")
 5254     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/5")
 5255     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/6")
 5256     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/7")
 5257     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/8")
 5258     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/9")
 5259     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/10")
 5260     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/11")
 5261     (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")
 5262     (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")
 5263     (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")
 5264     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/15")
 5265     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/16")
 5266     (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")
 5267     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/18")
 5268     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/19")
 5269     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/20")
 5270     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/21")
 5271     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/22")
 5272     (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")
 5273     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/24")
 5274     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/25")
 5275     # . epilogue
 5276     89/<- %esp 5/r32/ebp
 5277     5d/pop-to-ebp
 5278     c3/return
 5279 
 5280 test-convert-function-with-local-array-var-in-mem:
 5281     # . prologue
 5282     55/push-ebp
 5283     89/<- %ebp 4/r32/esp
 5284     # setup
 5285     (clear-stream _test-input-stream)
 5286     (clear-stream $_test-input-buffered-file->buffer)
 5287     (clear-stream _test-output-stream)
 5288     (clear-stream $_test-output-buffered-file->buffer)
 5289     #
 5290     (write _test-input-stream "fn foo {\n")
 5291     (write _test-input-stream "  var x: (array int 3)\n")
 5292     (write _test-input-stream "}\n")
 5293     # convert
 5294     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5295     (flush _test-output-buffered-file)
 5296 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 5302     # check output
 5303     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-array-var-in-mem/0")
 5304     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-array-var-in-mem/1")
 5305     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-array-var-in-mem/2")
 5306     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-array-var-in-mem/3")
 5307     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-array-var-in-mem/4")
 5308     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-array-var-in-mem/5")
 5309     # define x
 5310     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"  "F - test-convert-function-with-local-array-var-in-mem/7")
 5311     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"  "F - test-convert-function-with-local-array-var-in-mem/8")
 5312     # reclaim x
 5313     (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")
 5314     #
 5315     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-array-var-in-mem/10")
 5316     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-array-var-in-mem/11")
 5317     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-array-var-in-mem/12")
 5318     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-array-var-in-mem/13")
 5319     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-array-var-in-mem/14")
 5320     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-array-var-in-mem/15")
 5321     # . epilogue
 5322     89/<- %esp 5/r32/ebp
 5323     5d/pop-to-ebp
 5324     c3/return
 5325 
 5326 test-array-size-in-hex:
 5327     # . prologue
 5328     55/push-ebp
 5329     89/<- %ebp 4/r32/esp
 5330     # setup
 5331     (clear-stream _test-input-stream)
 5332     (clear-stream $_test-input-buffered-file->buffer)
 5333     (clear-stream _test-output-stream)
 5334     (clear-stream $_test-output-buffered-file->buffer)
 5335     (clear-stream _test-error-stream)
 5336     (clear-stream $_test-error-buffered-file->buffer)
 5337     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 5338     68/push 0/imm32
 5339     68/push 0/imm32
 5340     89/<- %edx 4/r32/esp
 5341     (tailor-exit-descriptor %edx 0x10)
 5342     #
 5343     (write _test-input-stream "fn foo {\n")
 5344     (write _test-input-stream "  var x: (array int 10)\n")
 5345     (write _test-input-stream "}\n")
 5346     # convert
 5347     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 5348     # registers except esp clobbered at this point
 5349     # restore ed
 5350     89/<- %edx 4/r32/esp
 5351     (flush _test-output-buffered-file)
 5352     (flush _test-error-buffered-file)
 5353 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 5359     # check output
 5360     (check-stream-equal _test-output-stream  ""  "F - test-array-size-in-hex: output should be empty")
 5361     (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")
 5362     # check that stop(1) was called
 5363     (check-ints-equal *(edx+4) 2 "F - test-array-size-in-hex: exit status")
 5364     # don't restore from ebp
 5365     81 0/subop/add %esp 8/imm32
 5366     # . epilogue
 5367     5d/pop-to-ebp
 5368     c3/return
 5369 
 5370 test-convert-function-with-populate:
 5371     # . prologue
 5372     55/push-ebp
 5373     89/<- %ebp 4/r32/esp
 5374     # setup
 5375     (clear-stream _test-input-stream)
 5376     (clear-stream $_test-input-buffered-file->buffer)
 5377     (clear-stream _test-output-stream)
 5378     (clear-stream $_test-output-buffered-file->buffer)
 5379     #
 5380     (write _test-input-stream "fn foo {\n")
 5381     (write _test-input-stream "  var x/ecx: (addr handle array int) <- copy 0\n")
 5382     (write _test-input-stream "  populate x, 7\n")
 5383     (write _test-input-stream "}\n")
 5384     # convert
 5385     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5386     (flush _test-output-buffered-file)
 5387 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 5393     # check output
 5394     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-populate/0")
 5395     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-populate/1")
 5396     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-populate/2")
 5397     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-populate/3")
 5398     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-populate/4")
 5399     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-populate/5")
 5400     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-populate/6")
 5401     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-populate/7")
 5402     (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)
 5403     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-populate/9")
 5404     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-populate/10")
 5405     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-populate/11")
 5406     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-populate/12")
 5407     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-populate/13")
 5408     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-populate/14")
 5409     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-populate/15")
 5410     # . epilogue
 5411     89/<- %esp 5/r32/ebp
 5412     5d/pop-to-ebp
 5413     c3/return
 5414 
 5415 # special-case for size(byte) when allocating array
 5416 test-convert-function-with-local-array-of-bytes-in-mem:
 5417     # . prologue
 5418     55/push-ebp
 5419     89/<- %ebp 4/r32/esp
 5420     # setup
 5421     (clear-stream _test-input-stream)
 5422     (clear-stream $_test-input-buffered-file->buffer)
 5423     (clear-stream _test-output-stream)
 5424     (clear-stream $_test-output-buffered-file->buffer)
 5425     #
 5426     (write _test-input-stream "fn foo {\n")
 5427     (write _test-input-stream "  var x: (array byte 3)\n")
 5428     (write _test-input-stream "}\n")
 5429     # convert
 5430     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5431     (flush _test-output-buffered-file)
 5432 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 5438     # check output
 5439     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-array-of-bytes-in-mem/0")
 5440     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-array-of-bytes-in-mem/1")
 5441     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-array-of-bytes-in-mem/2")
 5442     (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")
 5443     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-array-of-bytes-in-mem/4")
 5444     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-array-of-bytes-in-mem/5")
 5445     # define x
 5446     (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")
 5447     (check-next-stream-line-equal _test-output-stream "    68/push 0x00000003/imm32"  "F - test-convert-function-with-local-array-of-bytes-in-mem/8")
 5448     # reclaim x
 5449     (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")
 5450     #
 5451     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-array-of-bytes-in-mem/10")
 5452     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-array-of-bytes-in-mem/11")
 5453     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-array-of-bytes-in-mem/12")
 5454     (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")
 5455     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-array-of-bytes-in-mem/14")
 5456     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-array-of-bytes-in-mem/15")
 5457     # . epilogue
 5458     89/<- %esp 5/r32/ebp
 5459     5d/pop-to-ebp
 5460     c3/return
 5461 
 5462 test-convert-address:
 5463     # . prologue
 5464     55/push-ebp
 5465     89/<- %ebp 4/r32/esp
 5466     # setup
 5467     (clear-stream _test-input-stream)
 5468     (clear-stream $_test-input-buffered-file->buffer)
 5469     (clear-stream _test-output-stream)
 5470     (clear-stream $_test-output-buffered-file->buffer)
 5471     #
 5472     (write _test-input-stream "fn foo {\n")
 5473     (write _test-input-stream "  var a: int\n")
 5474     (write _test-input-stream "  var b/eax: (addr int) <- address a\n")
 5475     (write _test-input-stream "}\n")
 5476     # convert
 5477     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5478     (flush _test-output-buffered-file)
 5479 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 5485     # check output
 5486     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-address/0")
 5487     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-address/1")
 5488     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-address/2")
 5489     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-address/3")
 5490     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-address/4")
 5491     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-address/5")
 5492     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-address/6")
 5493     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-address/7")
 5494     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0xfffffffc) 0x00000000/r32"  "F - test-convert-address/8")
 5495     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-address/9")
 5496     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-address/10")
 5497     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-address/11")
 5498     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-address/12")
 5499     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-address/13")
 5500     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-address/14")
 5501     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-address/15")
 5502     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-address/16")
 5503     # . epilogue
 5504     89/<- %esp 5/r32/ebp
 5505     5d/pop-to-ebp
 5506     c3/return
 5507 
 5508 test-convert-floating-point-convert:
 5509     # . prologue
 5510     55/push-ebp
 5511     89/<- %ebp 4/r32/esp
 5512     # setup
 5513     (clear-stream _test-input-stream)
 5514     (clear-stream $_test-input-buffered-file->buffer)
 5515     (clear-stream _test-output-stream)
 5516     (clear-stream $_test-output-buffered-file->buffer)
 5517     #
 5518     (write _test-input-stream "fn foo {\n")
 5519     (write _test-input-stream "  var a/eax: int <- copy 0\n")
 5520     (write _test-input-stream "  var b/xmm1: float <- convert a\n")
 5521     (write _test-input-stream "}\n")
 5522     # convert
 5523     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5524     (flush _test-output-buffered-file)
 5525 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 5531     # check output
 5532     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-floating-point-convert/0")
 5533     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-floating-point-convert/1")
 5534     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-floating-point-convert/2")
 5535     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-floating-point-convert/3")
 5536     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-floating-point-convert/4")
 5537     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-floating-point-convert/5")
 5538     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-floating-point-convert/6")
 5539     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-floating-point-convert/7")
 5540     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"  "F - test-convert-floating-point-convert/8")
 5541     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"  "F - test-convert-floating-point-convert/9")
 5542     (check-next-stream-line-equal _test-output-stream "    f3 0f 2a/convert-to-float %eax 0x00000001/x32"  "F - test-convert-floating-point-convert/10")
 5543     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"  "F - test-convert-floating-point-convert/11")
 5544     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-floating-point-convert/12")
 5545     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-floating-point-convert/13")
 5546     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-floating-point-convert/14")
 5547     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-floating-point-convert/15")
 5548     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-floating-point-convert/16")
 5549     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-floating-point-convert/17")
 5550     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-floating-point-convert/18")
 5551     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-floating-point-convert/19")
 5552     # . epilogue
 5553     89/<- %esp 5/r32/ebp
 5554     5d/pop-to-ebp
 5555     c3/return
 5556 
 5557 test-convert-floating-point-convert-2:
 5558     # . prologue
 5559     55/push-ebp
 5560     89/<- %ebp 4/r32/esp
 5561     # setup
 5562     (clear-stream _test-input-stream)
 5563     (clear-stream $_test-input-buffered-file->buffer)
 5564     (clear-stream _test-output-stream)
 5565     (clear-stream $_test-output-buffered-file->buffer)
 5566     #
 5567     (write _test-input-stream "fn foo {\n")
 5568     (write _test-input-stream "  var a/eax: int <- copy 0\n")
 5569     (write _test-input-stream "  var b/xmm1: float <- convert a\n")
 5570     (write _test-input-stream "  a <- convert b\n")
 5571     (write _test-input-stream "}\n")
 5572     # convert
 5573     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5574     (flush _test-output-buffered-file)
 5575 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 5581     # check output
 5582     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-floating-point-convert-2/0")
 5583     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-floating-point-convert-2/1")
 5584     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-floating-point-convert-2/2")
 5585     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-floating-point-convert-2/3")
 5586     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-floating-point-convert-2/4")
 5587     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-floating-point-convert-2/5")
 5588     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-floating-point-convert-2/6")
 5589     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-floating-point-convert-2/7")
 5590     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"  "F - test-convert-floating-point-convert-2/8")
 5591     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"  "F - test-convert-floating-point-convert-2/9")
 5592     (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")
 5593     (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")
 5594     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"  "F - test-convert-floating-point-convert-2/12")
 5595     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-floating-point-convert-2/13")
 5596     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-floating-point-convert-2/14")
 5597     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-floating-point-convert-2/15")
 5598     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-floating-point-convert-2/16")
 5599     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-floating-point-convert-2/17")
 5600     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-floating-point-convert-2/18")
 5601     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-floating-point-convert-2/19")
 5602     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-floating-point-convert-2/20")
 5603     # . epilogue
 5604     89/<- %esp 5/r32/ebp
 5605     5d/pop-to-ebp
 5606     c3/return
 5607 
 5608 test-convert-floating-point-operation:
 5609     # . prologue
 5610     55/push-ebp
 5611     89/<- %ebp 4/r32/esp
 5612     # setup
 5613     (clear-stream _test-input-stream)
 5614     (clear-stream $_test-input-buffered-file->buffer)
 5615     (clear-stream _test-output-stream)
 5616     (clear-stream $_test-output-buffered-file->buffer)
 5617     #
 5618     (write _test-input-stream "fn f {\n")
 5619     (write _test-input-stream "  var m: float\n")
 5620     (write _test-input-stream "  var x/xmm1: float <- copy m\n")
 5621     (write _test-input-stream "  var y/xmm5: float <- copy m\n")
 5622     (write _test-input-stream "  x <- copy y\n")
 5623     (write _test-input-stream "  copy-to m, y\n")
 5624     (write _test-input-stream "  x <- add y\n")
 5625     (write _test-input-stream "  x <- add m\n")
 5626     (write _test-input-stream "  x <- subtract y\n")
 5627     (write _test-input-stream "  x <- subtract m\n")
 5628     (write _test-input-stream "  x <- multiply y\n")
 5629     (write _test-input-stream "  x <- multiply m\n")
 5630     (write _test-input-stream "  x <- divide y\n")
 5631     (write _test-input-stream "  x <- divide m\n")
 5632     (write _test-input-stream "  x <- reciprocal y\n")
 5633     (write _test-input-stream "  x <- reciprocal m\n")
 5634     (write _test-input-stream "  x <- square-root y\n")
 5635     (write _test-input-stream "  x <- square-root m\n")
 5636     (write _test-input-stream "  x <- inverse-square-root y\n")
 5637     (write _test-input-stream "  x <- inverse-square-root m\n")
 5638     (write _test-input-stream "  x <- max y\n")
 5639     (write _test-input-stream "  x <- max m\n")
 5640     (write _test-input-stream "  x <- min y\n")
 5641     (write _test-input-stream "  x <- min m\n")
 5642     (write _test-input-stream "  compare x, y\n")
 5643     (write _test-input-stream "  compare x, m\n")
 5644     (write _test-input-stream "}\n")
 5645     # convert
 5646     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5647     (flush _test-output-buffered-file)
 5648 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 5654     # check output
 5655     (check-next-stream-line-equal _test-output-stream "f:"                                                                     "F - test-convert-floating-point-operation/0")
 5656     (check-next-stream-line-equal _test-output-stream "  # . prologue"                                                         "F - test-convert-floating-point-operation/1")
 5657     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                                                          "F - test-convert-floating-point-operation/2")
 5658     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                                                 "F - test-convert-floating-point-operation/3")
 5659     (check-next-stream-line-equal _test-output-stream "  {"                                                                    "F - test-convert-floating-point-operation/4")
 5660     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"                                                    "F - test-convert-floating-point-operation/5")
 5661     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                                                    "F - test-convert-floating-point-operation/6")
 5662     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-operation/7")
 5663     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"                                             "F - test-convert-floating-point-operation/8")
 5664     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-operation/9")
 5665     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-operation/10")
 5666     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 5/x32"                                             "F - test-convert-floating-point-operation/11")
 5667     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000005/x32"                     "F - test-convert-floating-point-operation/12")
 5668     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/copy %xmm1 0x00000005/x32"                                 "F - test-convert-floating-point-operation/13")
 5669     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/copy *(ebp+0xfffffffc) 0x00000005/x32"                     "F - test-convert-floating-point-operation/14")
 5670     (check-next-stream-line-equal _test-output-stream "    f3 0f 58/add %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/15")
 5671     (check-next-stream-line-equal _test-output-stream "    f3 0f 58/add *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/16")
 5672     (check-next-stream-line-equal _test-output-stream "    f3 0f 5c/subtract %xmm5 0x00000001/x32"                             "F - test-convert-floating-point-operation/17")
 5673     (check-next-stream-line-equal _test-output-stream "    f3 0f 5c/subtract *(ebp+0xfffffffc) 0x00000001/x32"                 "F - test-convert-floating-point-operation/18")
 5674     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply %xmm5 0x00000001/x32"                             "F - test-convert-floating-point-operation/19")
 5675     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply *(ebp+0xfffffffc) 0x00000001/x32"                 "F - test-convert-floating-point-operation/20")
 5676     (check-next-stream-line-equal _test-output-stream "    f3 0f 5e/divide %xmm5 0x00000001/x32"                               "F - test-convert-floating-point-operation/21")
 5677     (check-next-stream-line-equal _test-output-stream "    f3 0f 5e/divide *(ebp+0xfffffffc) 0x00000001/x32"                   "F - test-convert-floating-point-operation/22")
 5678     (check-next-stream-line-equal _test-output-stream "    f3 0f 53/reciprocal %xmm5 0x00000001/x32"                           "F - test-convert-floating-point-operation/23")
 5679     (check-next-stream-line-equal _test-output-stream "    f3 0f 53/reciprocal *(ebp+0xfffffffc) 0x00000001/x32"               "F - test-convert-floating-point-operation/24")
 5680     (check-next-stream-line-equal _test-output-stream "    f3 0f 51/square-root %xmm5 0x00000001/x32"                          "F - test-convert-floating-point-operation/25")
 5681     (check-next-stream-line-equal _test-output-stream "    f3 0f 51/square-root *(ebp+0xfffffffc) 0x00000001/x32"              "F - test-convert-floating-point-operation/26")
 5682     (check-next-stream-line-equal _test-output-stream "    f3 0f 52/inverse-square-root %xmm5 0x00000001/x32"                  "F - test-convert-floating-point-operation/27")
 5683     (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")
 5684     (check-next-stream-line-equal _test-output-stream "    f3 0f 5f/max %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/29")
 5685     (check-next-stream-line-equal _test-output-stream "    f3 0f 5f/max *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/30")
 5686     (check-next-stream-line-equal _test-output-stream "    f3 0f 5d/min %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/31")
 5687     (check-next-stream-line-equal _test-output-stream "    f3 0f 5d/min *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/32")
 5688     (check-next-stream-line-equal _test-output-stream "    0f 2f/compare %xmm1 0x00000005/x32"                                 "F - test-convert-floating-point-operation/33")
 5689     (check-next-stream-line-equal _test-output-stream "    0f 2f/compare *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-operation/34")
 5690     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 5/x32"                                             "F - test-convert-floating-point-operation/35")
 5691     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-operation/36")
 5692     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"                                             "F - test-convert-floating-point-operation/37")
 5693     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-operation/38")
 5694     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"                               "F - test-convert-floating-point-operation/39")
 5695     (check-next-stream-line-equal _test-output-stream "  }"                                                                    "F - test-convert-floating-point-operation/40")
 5696     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"                                                   "F - test-convert-floating-point-operation/41")
 5697     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                                                         "F - test-convert-floating-point-operation/42")
 5698     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                                                 "F - test-convert-floating-point-operation/43")
 5699     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                                                        "F - test-convert-floating-point-operation/44")
 5700     (check-next-stream-line-equal _test-output-stream "  c3/return"                                                            "F - test-convert-floating-point-operation/45")
 5701     # . epilogue
 5702     89/<- %esp 5/r32/ebp
 5703     5d/pop-to-ebp
 5704     c3/return
 5705 
 5706 test-convert-floating-point-dereferenced:
 5707     # . prologue
 5708     55/push-ebp
 5709     89/<- %ebp 4/r32/esp
 5710     # setup
 5711     (clear-stream _test-input-stream)
 5712     (clear-stream $_test-input-buffered-file->buffer)
 5713     (clear-stream _test-output-stream)
 5714     (clear-stream $_test-output-buffered-file->buffer)
 5715     #
 5716     (write _test-input-stream "fn f {\n")
 5717     (write _test-input-stream "  var m: float\n")
 5718     (write _test-input-stream "  var x/xmm1: float <- copy m\n")
 5719     (write _test-input-stream "  var y/eax: (addr float) <- copy 0\n")
 5720     (write _test-input-stream "  x <- multiply *y\n")
 5721     (write _test-input-stream "}\n")
 5722     # convert
 5723     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5724     (flush _test-output-buffered-file)
 5725 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 5731     # check output
 5732     (check-next-stream-line-equal _test-output-stream "f:"                                                                     "F - test-convert-floating-point-dereferenced/0")
 5733     (check-next-stream-line-equal _test-output-stream "  # . prologue"                                                         "F - test-convert-floating-point-dereferenced/1")
 5734     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                                                          "F - test-convert-floating-point-dereferenced/2")
 5735     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                                                 "F - test-convert-floating-point-dereferenced/3")
 5736     (check-next-stream-line-equal _test-output-stream "  {"                                                                    "F - test-convert-floating-point-dereferenced/4")
 5737     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"                                                    "F - test-convert-floating-point-dereferenced/5")
 5738     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                                                    "F - test-convert-floating-point-dereferenced/6")
 5739     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-dereferenced/7")
 5740     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"                                             "F - test-convert-floating-point-dereferenced/8")
 5741     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-dereferenced/9")
 5742     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                                               "F - test-convert-floating-point-dereferenced/10")
 5743     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                                             "F - test-convert-floating-point-dereferenced/11")
 5744     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply *eax 0x00000001/x32"                              "F - test-convert-floating-point-dereferenced/12")
 5745     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                                                "F - test-convert-floating-point-dereferenced/13")
 5746     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"                                             "F - test-convert-floating-point-dereferenced/14")
 5747     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-dereferenced/15")
 5748     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"                               "F - test-convert-floating-point-dereferenced/16")
 5749     (check-next-stream-line-equal _test-output-stream "  }"                                                                    "F - test-convert-floating-point-dereferenced/17")
 5750     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"                                                   "F - test-convert-floating-point-dereferenced/18")
 5751     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                                                         "F - test-convert-floating-point-dereferenced/19")
 5752     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                                                 "F - test-convert-floating-point-dereferenced/20")
 5753     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                                                        "F - test-convert-floating-point-dereferenced/21")
 5754     (check-next-stream-line-equal _test-output-stream "  c3/return"                                                            "F - test-convert-floating-point-dereferenced/22")
 5755     # . epilogue
 5756     89/<- %esp 5/r32/ebp
 5757     5d/pop-to-ebp
 5758     c3/return
 5759 
 5760 test-convert-length-of-array:
 5761     # . prologue
 5762     55/push-ebp
 5763     89/<- %ebp 4/r32/esp
 5764     # setup
 5765     (clear-stream _test-input-stream)
 5766     (clear-stream $_test-input-buffered-file->buffer)
 5767     (clear-stream _test-output-stream)
 5768     (clear-stream $_test-output-buffered-file->buffer)
 5769     #
 5770     (write _test-input-stream "fn foo a: (addr array int) {\n")
 5771     (write _test-input-stream "  var b/eax: (addr array int) <- copy a\n")
 5772     (write _test-input-stream "  var c/eax: int <- length b\n")
 5773     (write _test-input-stream "}\n")
 5774     # convert
 5775     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5776     (flush _test-output-buffered-file)
 5777 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 5783     # check output
 5784     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array/0")
 5785     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array/1")
 5786     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array/2")
 5787     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array/3")
 5788     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array/4")
 5789     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array/5")
 5790     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array/6")
 5791     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-length-of-array/7")
 5792     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array/8")
 5793     (check-next-stream-line-equal _test-output-stream "    c1/shift 5/subop/>> %eax 0x00000002/imm8"  "F - test-convert-length-of-array/9")
 5794     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array/10")
 5795     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array/11")
 5796     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array/12")
 5797     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array/13")
 5798     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array/14")
 5799     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array/15")
 5800     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array/16")
 5801     # . epilogue
 5802     89/<- %esp 5/r32/ebp
 5803     5d/pop-to-ebp
 5804     c3/return
 5805 
 5806 # special-case for size(byte) when computing array length
 5807 test-convert-length-of-array-of-bytes:
 5808     # . prologue
 5809     55/push-ebp
 5810     89/<- %ebp 4/r32/esp
 5811     # setup
 5812     (clear-stream _test-input-stream)
 5813     (clear-stream $_test-input-buffered-file->buffer)
 5814     (clear-stream _test-output-stream)
 5815     (clear-stream $_test-output-buffered-file->buffer)
 5816     #
 5817     (write _test-input-stream "fn foo a: (addr array byte) {\n")
 5818     (write _test-input-stream "  var b/eax: (addr array byte) <- copy a\n")
 5819     (write _test-input-stream "  var c/eax: int <- length b\n")
 5820     (write _test-input-stream "}\n")
 5821     # convert
 5822     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5823     (flush _test-output-buffered-file)
 5824 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 5830     # check output
 5831     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-bytes/0")
 5832     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-bytes/1")
 5833     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-bytes/2")
 5834     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-bytes/3")
 5835     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-bytes/4")
 5836     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-bytes/5")
 5837     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-of-bytes/6")
 5838     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-length-of-array-of-bytes/7")
 5839     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array-of-bytes/8")
 5840     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-of-bytes/9")
 5841     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-bytes/10")
 5842     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-bytes/11")
 5843     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-bytes/12")
 5844     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-of-bytes/13")
 5845     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-of-bytes/14")
 5846     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-bytes/15")
 5847     # . epilogue
 5848     89/<- %esp 5/r32/ebp
 5849     5d/pop-to-ebp
 5850     c3/return
 5851 
 5852 test-convert-length-of-array-on-stack:
 5853     # . prologue
 5854     55/push-ebp
 5855     89/<- %ebp 4/r32/esp
 5856     # setup
 5857     (clear-stream _test-input-stream)
 5858     (clear-stream $_test-input-buffered-file->buffer)
 5859     (clear-stream _test-output-stream)
 5860     (clear-stream $_test-output-buffered-file->buffer)
 5861     #
 5862     (write _test-input-stream "fn foo {\n")
 5863     (write _test-input-stream "  var a: (array int 3)\n")
 5864     (write _test-input-stream "  var b/eax: int <- length a\n")
 5865     (write _test-input-stream "}\n")
 5866     # convert
 5867     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5868     (flush _test-output-buffered-file)
 5869 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 5875     # check output
 5876     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-on-stack/0")
 5877     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-on-stack/1")
 5878     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-on-stack/2")
 5879     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-on-stack/3")
 5880     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-on-stack/4")
 5881     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-on-stack/5")
 5882     # define x
 5883     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"  "F - test-convert-length-of-array-on-stack/6")
 5884     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"  "F - test-convert-length-of-array-on-stack/7")
 5885     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-on-stack/8")
 5886     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0xfffffff0) 0x00000000/r32"  "F - test-convert-length-of-array-on-stack/9")
 5887     (check-next-stream-line-equal _test-output-stream "    c1/shift 5/subop/>> %eax 0x00000002/imm8"  "F - test-convert-length-of-array-on-stack/10")
 5888     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-on-stack/11")
 5889     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"  "F - test-convert-length-of-array-on-stack/12")
 5890     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-on-stack/13")
 5891     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-on-stack/14")
 5892     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-on-stack/15")
 5893     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-on-stack/16")
 5894     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-on-stack/17")
 5895     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-on-stack/18")
 5896     # . epilogue
 5897     89/<- %esp 5/r32/ebp
 5898     5d/pop-to-ebp
 5899     c3/return
 5900 
 5901 test-reg-var-def-with-read-of-same-register:
 5902     # . prologue
 5903     55/push-ebp
 5904     89/<- %ebp 4/r32/esp
 5905     # setup
 5906     (clear-stream _test-input-stream)
 5907     (clear-stream $_test-input-buffered-file->buffer)
 5908     (clear-stream _test-output-stream)
 5909     (clear-stream $_test-output-buffered-file->buffer)
 5910     (clear-stream _test-error-stream)
 5911     (clear-stream $_test-error-buffered-file->buffer)
 5912     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
 5913     68/push 0/imm32
 5914     68/push 0/imm32
 5915     89/<- %edx 4/r32/esp
 5916     (tailor-exit-descriptor %edx 0x10)
 5917     #
 5918     (write _test-input-stream "fn foo {\n")
 5919     (write _test-input-stream "  var x/eax: int <- copy 3\n")
 5920     (write _test-input-stream "  var y/eax: int <- add x\n")
 5921     (write _test-input-stream "}\n")
 5922     # convert
 5923     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 5924     # registers except esp could be clobbered at this point (though they shouldn't be)
 5925     # restore ed
 5926     89/<- %edx 4/r32/esp
 5927     (flush _test-output-buffered-file)
 5928     (flush _test-error-buffered-file)
 5929 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 5935 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 5941     (check-stream-equal _test-error-stream  ""  "F - test-reg-var-def-with-read-of-same-register: error stream should be empty")
 5942     # check output
 5943     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-reg-var-def-with-read-of-same-register/0")
 5944     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-reg-var-def-with-read-of-same-register/1")
 5945     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-reg-var-def-with-read-of-same-register/2")
 5946     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-reg-var-def-with-read-of-same-register/3")
 5947     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-reg-var-def-with-read-of-same-register/4")
 5948     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-reg-var-def-with-read-of-same-register/5")
 5949     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-reg-var-def-with-read-of-same-register/6")
 5950     (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")
 5951     (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")
 5952     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-reg-var-def-with-read-of-same-register/9")
 5953     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-reg-var-def-with-read-of-same-register/10")
 5954     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-reg-var-def-with-read-of-same-register/11")
 5955     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-reg-var-def-with-read-of-same-register/12")
 5956     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-reg-var-def-with-read-of-same-register/13")
 5957     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-reg-var-def-with-read-of-same-register/14")
 5958     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-reg-var-def-with-read-of-same-register/15")
 5959     # don't restore from ebp
 5960     81 0/subop/add %esp 8/imm32
 5961     # . epilogue
 5962     5d/pop-to-ebp
 5963     c3/return
 5964 
 5965 test-convert-index-into-array:
 5966     # . prologue
 5967     55/push-ebp
 5968     89/<- %ebp 4/r32/esp
 5969     # setup
 5970     (clear-stream _test-input-stream)
 5971     (clear-stream $_test-input-buffered-file->buffer)
 5972     (clear-stream _test-output-stream)
 5973     (clear-stream $_test-output-buffered-file->buffer)
 5974     #
 5975     (write _test-input-stream "fn foo {\n")
 5976     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 5977     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 5978     (write _test-input-stream "  var x/eax: (addr int) <- index arr, idx\n")
 5979     (write _test-input-stream "}\n")
 5980     # convert
 5981     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5982     (flush _test-output-buffered-file)
 5983 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 5989     # check output
 5990     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array/0")
 5991     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array/1")
 5992     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array/2")
 5993     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array/3")
 5994     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array/4")
 5995     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array/5")
 5996     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array/6")
 5997     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array/7")
 5998     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array/8")
 5999     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array/9")
 6000     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 0x00000004 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array/10")
 6001     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx<<0x00000002 + 4) 0x00000000/r32"  "F - test-convert-index-into-array/11")
 6002     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array/12")
 6003     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array/13")
 6004     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array/14")
 6005     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array/15")
 6006     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array/16")
 6007     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array/17")
 6008     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array/18")
 6009     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array/19")
 6010     # . epilogue
 6011     89/<- %esp 5/r32/ebp
 6012     5d/pop-to-ebp
 6013     c3/return
 6014 
 6015 test-convert-index-into-array-of-bytes:
 6016     # . prologue
 6017     55/push-ebp
 6018     89/<- %ebp 4/r32/esp
 6019     # setup
 6020     (clear-stream _test-input-stream)
 6021     (clear-stream $_test-input-buffered-file->buffer)
 6022     (clear-stream _test-output-stream)
 6023     (clear-stream $_test-output-buffered-file->buffer)
 6024     #
 6025     (write _test-input-stream "fn foo {\n")
 6026     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 6027     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 6028     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, idx\n")
 6029     (write _test-input-stream "}\n")
 6030     # convert
 6031     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6032     (flush _test-output-buffered-file)
 6033 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 6039     # check output
 6040     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes/0")
 6041     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes/1")
 6042     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes/2")
 6043     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes/3")
 6044     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes/4")
 6045     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes/5")
 6046     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes/6")
 6047     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-of-bytes/7")
 6048     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-of-bytes/8")
 6049     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array-of-bytes/9")
 6050     (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")
 6051     (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")
 6052     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes/12")
 6053     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes/13")
 6054     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes/14")
 6055     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes/15")
 6056     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes/16")
 6057     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes/17")
 6058     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes/18")
 6059     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes/19")
 6060     # . epilogue
 6061     89/<- %esp 5/r32/ebp
 6062     5d/pop-to-ebp
 6063     c3/return
 6064 
 6065 test-convert-index-into-array-with-literal:
 6066     # . prologue
 6067     55/push-ebp
 6068     89/<- %ebp 4/r32/esp
 6069     # setup
 6070     (clear-stream _test-input-stream)
 6071     (clear-stream $_test-input-buffered-file->buffer)
 6072     (clear-stream _test-output-stream)
 6073     (clear-stream $_test-output-buffered-file->buffer)
 6074     #
 6075     (write _test-input-stream "fn foo {\n")
 6076     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 6077     (write _test-input-stream "  var x/eax: (addr int) <- index arr, 2\n")
 6078     (write _test-input-stream "}\n")
 6079     # convert
 6080     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6081     (flush _test-output-buffered-file)
 6082 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 6088     # check output
 6089     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-with-literal/0")
 6090     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-with-literal/1")
 6091     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-with-literal/2")
 6092     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-with-literal/3")
 6093     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-with-literal/4")
 6094     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-with-literal/5")
 6095     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-with-literal/6")
 6096     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-with-literal/7")
 6097     (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")
 6098                                                                                  # 2 * 4 bytes/elem + 4 bytes for size = offset 12
 6099     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x0000000c) 0x00000000/r32"  "F - test-convert-index-into-array-with-literal/9")
 6100     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-with-literal/10")
 6101     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-with-literal/11")
 6102     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-with-literal/12")
 6103     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-with-literal/13")
 6104     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-with-literal/14")
 6105     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-with-literal/15")
 6106     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-with-literal/16")
 6107     # . epilogue
 6108     89/<- %esp 5/r32/ebp
 6109     5d/pop-to-ebp
 6110     c3/return
 6111 
 6112 test-convert-index-into-array-of-bytes-with-literal:
 6113     # . prologue
 6114     55/push-ebp
 6115     89/<- %ebp 4/r32/esp
 6116     # setup
 6117     (clear-stream _test-input-stream)
 6118     (clear-stream $_test-input-buffered-file->buffer)
 6119     (clear-stream _test-output-stream)
 6120     (clear-stream $_test-output-buffered-file->buffer)
 6121     #
 6122     (write _test-input-stream "fn foo {\n")
 6123     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 6124     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, 2\n")
 6125     (write _test-input-stream "}\n")
 6126     # convert
 6127     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6128     (flush _test-output-buffered-file)
 6129 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 6135     # check output
 6136     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-with-literal/0")
 6137     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-with-literal/1")
 6138     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-with-literal/2")
 6139     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes-with-literal/3")
 6140     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-with-literal/4")
 6141     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-with-literal/5")
 6142     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes-with-literal/6")
 6143     (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")
 6144     (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")
 6145                                                                                  # 2 * 1 byte/elem + 4 bytes for size = offset 6
 6146     (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")
 6147     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-with-literal/9")
 6148     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-with-literal/10")
 6149     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-with-literal/11")
 6150     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-with-literal/12")
 6151     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-with-literal/13")
 6152     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-with-literal/14")
 6153     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-with-literal/15")
 6154     # . epilogue
 6155     89/<- %esp 5/r32/ebp
 6156     5d/pop-to-ebp
 6157     c3/return
 6158 
 6159 test-convert-index-into-array-on-stack:
 6160     # . prologue
 6161     55/push-ebp
 6162     89/<- %ebp 4/r32/esp
 6163     # setup
 6164     (clear-stream _test-input-stream)
 6165     (clear-stream $_test-input-buffered-file->buffer)
 6166     (clear-stream _test-output-stream)
 6167     (clear-stream $_test-output-buffered-file->buffer)
 6168     #
 6169     (write _test-input-stream "fn foo {\n")
 6170     (write _test-input-stream "  var arr: (array int 3)\n")
 6171     (write _test-input-stream "  var idx/eax: int <- copy 2\n")
 6172     (write _test-input-stream "  var x/eax: (addr int) <- index arr, idx\n")
 6173     (write _test-input-stream "}\n")
 6174     # convert
 6175     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6176     (flush _test-output-buffered-file)
 6177 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 6183     # check output
 6184     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-on-stack/0")
 6185     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-on-stack/1")
 6186     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-on-stack/2")
 6187     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-on-stack/3")
 6188     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-on-stack/4")
 6189     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-on-stack/5")
 6190     # var arr
 6191     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"          "F - test-convert-index-into-array-on-stack/6")
 6192     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"                "F - test-convert-index-into-array-on-stack/7")
 6193     # var idx
 6194     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-on-stack/8")
 6195     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 2/imm32"                  "F - test-convert-index-into-array-on-stack/9")
 6196     (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")
 6197     # var x is at (ebp-0x10) + idx<<2 + 4 = ebp + idx<<2 - 0xc
 6198     (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")
 6199     # reclaim idx
 6200     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-on-stack/12")
 6201     # reclaim arr
 6202     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"    "F - test-convert-index-into-array-on-stack/13")
 6203     #
 6204     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-on-stack/14")
 6205     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-on-stack/15")
 6206     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-on-stack/16")
 6207     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-on-stack/17")
 6208     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-on-stack/18")
 6209     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-on-stack/19")
 6210     # . epilogue
 6211     89/<- %esp 5/r32/ebp
 6212     5d/pop-to-ebp
 6213     c3/return
 6214 
 6215 test-convert-index-into-array-on-stack-with-literal:
 6216     # . prologue
 6217     55/push-ebp
 6218     89/<- %ebp 4/r32/esp
 6219     # setup
 6220     (clear-stream _test-input-stream)
 6221     (clear-stream $_test-input-buffered-file->buffer)
 6222     (clear-stream _test-output-stream)
 6223     (clear-stream $_test-output-buffered-file->buffer)
 6224     #
 6225     (write _test-input-stream "fn foo {\n")
 6226     (write _test-input-stream "  var arr: (array int 3)\n")
 6227     (write _test-input-stream "  var x/eax: (addr int) <- index arr, 2\n")
 6228     (write _test-input-stream "}\n")
 6229     # convert
 6230     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6231     (flush _test-output-buffered-file)
 6232 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 6238     # check output
 6239     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-on-stack-with-literal/0")
 6240     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-on-stack-with-literal/1")
 6241     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-on-stack-with-literal/2")
 6242     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-on-stack-with-literal/3")
 6243     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-on-stack-with-literal/4")
 6244     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-on-stack-with-literal/5")
 6245     # var arr
 6246     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"          "F - test-convert-index-into-array-on-stack-with-literal/6")
 6247     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"                "F - test-convert-index-into-array-on-stack-with-literal/7")
 6248     # var x
 6249     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-on-stack-with-literal/8")
 6250     (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")
 6251     # x is at (ebp-0x10) + 4 + 2*4 = ebp-4
 6252     (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")
 6253     # reclaim x
 6254     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-on-stack-with-literal/11")
 6255     # reclaim arr
 6256     (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")
 6257     #
 6258     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-on-stack-with-literal/13")
 6259     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-on-stack-with-literal/14")
 6260     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-on-stack-with-literal/15")
 6261     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-on-stack-with-literal/16")
 6262     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-on-stack-with-literal/17")
 6263     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-on-stack-with-literal/18")
 6264     # . epilogue
 6265     89/<- %esp 5/r32/ebp
 6266     5d/pop-to-ebp
 6267     c3/return
 6268 
 6269 test-convert-index-into-array-of-bytes-on-stack-with-literal:
 6270     # . prologue
 6271     55/push-ebp
 6272     89/<- %ebp 4/r32/esp
 6273     # setup
 6274     (clear-stream _test-input-stream)
 6275     (clear-stream $_test-input-buffered-file->buffer)
 6276     (clear-stream _test-output-stream)
 6277     (clear-stream $_test-output-buffered-file->buffer)
 6278     #
 6279     (write _test-input-stream "fn foo {\n")
 6280     (write _test-input-stream "  var arr: (array byte 3)\n")
 6281     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, 2\n")
 6282     (write _test-input-stream "}\n")
 6283     # convert
 6284     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6285     (flush _test-output-buffered-file)
 6286 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 6292     # check output
 6293     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/0")
 6294     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/1")
 6295     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/2")
 6296     (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")
 6297     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/4")
 6298     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/5")
 6299     # var arr
 6300     (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")
 6301     (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")
 6302     # var x
 6303     (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")
 6304     (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")
 6305     # x is at (ebp-7) + 4 + 2 = ebp-1
 6306     (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")
 6307     # reclaim x
 6308     (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")
 6309     # reclaim arr
 6310     (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")
 6311     #
 6312     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/13")
 6313     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/14")
 6314     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/15")
 6315     (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")
 6316     (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")
 6317     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/18")
 6318     # . epilogue
 6319     89/<- %esp 5/r32/ebp
 6320     5d/pop-to-ebp
 6321     c3/return
 6322 
 6323 test-convert-index-into-array-using-offset:
 6324     # . prologue
 6325     55/push-ebp
 6326     89/<- %ebp 4/r32/esp
 6327     # setup
 6328     (clear-stream _test-input-stream)
 6329     (clear-stream $_test-input-buffered-file->buffer)
 6330     (clear-stream _test-output-stream)
 6331     (clear-stream $_test-output-buffered-file->buffer)
 6332     #
 6333     (write _test-input-stream "fn foo {\n")
 6334     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 6335     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 6336     (write _test-input-stream "  var off/ecx: (offset int) <- compute-offset arr, idx\n")
 6337     (write _test-input-stream "  var x/eax: (addr int) <- index arr, off\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-using-offset/0")
 6350     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-using-offset/1")
 6351     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-using-offset/2")
 6352     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-using-offset/3")
 6353     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-using-offset/4")
 6354     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-using-offset/5")
 6355     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-using-offset/6")
 6356     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-using-offset/7")
 6357     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-using-offset/8")
 6358     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array-using-offset/9")
 6359     (check-next-stream-line-equal _test-output-stream "    69/multiply %ecx 0x00000004/imm32 0x00000001/r32"  "F - test-convert-index-into-array-using-offset/10")
 6360     (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")
 6361     (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")
 6362     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-using-offset/13")
 6363     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-using-offset/14")
 6364     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-using-offset/15")
 6365     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-using-offset/16")
 6366     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-using-offset/17")
 6367     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-using-offset/18")
 6368     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-using-offset/19")
 6369     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-using-offset/20")
 6370     # . epilogue
 6371     89/<- %esp 5/r32/ebp
 6372     5d/pop-to-ebp
 6373     c3/return
 6374 
 6375 test-convert-index-into-array-of-bytes-using-offset:
 6376     # . prologue
 6377     55/push-ebp
 6378     89/<- %ebp 4/r32/esp
 6379     # setup
 6380     (clear-stream _test-input-stream)
 6381     (clear-stream $_test-input-buffered-file->buffer)
 6382     (clear-stream _test-output-stream)
 6383     (clear-stream $_test-output-buffered-file->buffer)
 6384     #
 6385     (write _test-input-stream "fn foo {\n")
 6386     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 6387     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 6388     (write _test-input-stream "  var off/ecx: (offset byte) <- compute-offset arr, idx\n")
 6389     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, off\n")
 6390     (write _test-input-stream "}\n")
 6391     # convert
 6392     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6393     (flush _test-output-buffered-file)
 6394 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 6400     # check output
 6401     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-using-offset/0")
 6402     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-using-offset/1")
 6403     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-using-offset/2")
 6404     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes-using-offset/3")
 6405     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-using-offset/4")
 6406     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-using-offset/5")
 6407     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes-using-offset/6")
 6408     (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")
 6409     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-of-bytes-using-offset/8")
 6410     (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")
 6411     (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")
 6412     (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")
 6413     (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")
 6414     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes-using-offset/13")
 6415     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-using-offset/14")
 6416     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-using-offset/15")
 6417     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-using-offset/16")
 6418     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-using-offset/17")
 6419     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-using-offset/18")
 6420     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-using-offset/19")
 6421     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-using-offset/20")
 6422     # . epilogue
 6423     89/<- %esp 5/r32/ebp
 6424     5d/pop-to-ebp
 6425     c3/return
 6426 
 6427 test-convert-index-into-array-using-offset-on-stack:
 6428     # . prologue
 6429     55/push-ebp
 6430     89/<- %ebp 4/r32/esp
 6431     # setup
 6432     (clear-stream _test-input-stream)
 6433     (clear-stream $_test-input-buffered-file->buffer)
 6434     (clear-stream _test-output-stream)
 6435     (clear-stream $_test-output-buffered-file->buffer)
 6436     #
 6437     (write _test-input-stream "fn foo {\n")
 6438     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 6439     (write _test-input-stream "  var idx: int\n")
 6440     (write _test-input-stream "  var off/ecx: (offset int) <- compute-offset arr, idx\n")
 6441     (write _test-input-stream "  var x/eax: (addr int) <- index arr, off\n")
 6442     (write _test-input-stream "}\n")
 6443     # convert
 6444     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6445     (flush _test-output-buffered-file)
 6446 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 6452     # check output
 6453     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-using-offset-on-stack/0")
 6454     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-using-offset-on-stack/1")
 6455     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-using-offset-on-stack/2")
 6456     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-using-offset-on-stack/3")
 6457     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-using-offset-on-stack/4")
 6458     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-using-offset-on-stack/5")
 6459     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-using-offset-on-stack/6")
 6460     (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")
 6461     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                         "F - test-convert-index-into-array-using-offset-on-stack/8")
 6462     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-using-offset-on-stack/9")
 6463     (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")
 6464     (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")
 6465     (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")
 6466     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-using-offset-on-stack/13")
 6467     (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")
 6468     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-using-offset-on-stack/15")
 6469     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-using-offset-on-stack/16")
 6470     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-using-offset-on-stack/17")
 6471     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-using-offset-on-stack/18")
 6472     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-using-offset-on-stack/19")
 6473     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-using-offset-on-stack/20")
 6474     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-using-offset-on-stack/21")
 6475     # . epilogue
 6476     89/<- %esp 5/r32/ebp
 6477     5d/pop-to-ebp
 6478     c3/return
 6479 
 6480 test-convert-index-into-array-of-bytes-using-offset-on-stack:
 6481     # . prologue
 6482     55/push-ebp
 6483     89/<- %ebp 4/r32/esp
 6484     # setup
 6485     (clear-stream _test-input-stream)
 6486     (clear-stream $_test-input-buffered-file->buffer)
 6487     (clear-stream _test-output-stream)
 6488     (clear-stream $_test-output-buffered-file->buffer)
 6489     #
 6490     (write _test-input-stream "fn foo {\n")
 6491     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 6492     (write _test-input-stream "  var idx: int\n")
 6493     (write _test-input-stream "  var off/ecx: (offset byte) <- compute-offset arr, idx\n")
 6494     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, off\n")
 6495     (write _test-input-stream "}\n")
 6496     # convert
 6497     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6498     (flush _test-output-buffered-file)
 6499 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 6505     # check output
 6506     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/0")
 6507     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/1")
 6508     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/2")
 6509     (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")
 6510     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/4")
 6511     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/5")
 6512     (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")
 6513     (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")
 6514     (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")
 6515     (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")
 6516     (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")
 6517     (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")
 6518     (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")
 6519     (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")
 6520     (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")
 6521     (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")
 6522     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/16")
 6523     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/17")
 6524     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/18")
 6525     (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")
 6526     (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")
 6527     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/21")
 6528     # . epilogue
 6529     89/<- %esp 5/r32/ebp
 6530     5d/pop-to-ebp
 6531     c3/return
 6532 
 6533 test-convert-function-and-type-definition:
 6534     # . prologue
 6535     55/push-ebp
 6536     89/<- %ebp 4/r32/esp
 6537     # setup
 6538     (clear-stream _test-input-stream)
 6539     (clear-stream $_test-input-buffered-file->buffer)
 6540     (clear-stream _test-output-stream)
 6541     (clear-stream $_test-output-buffered-file->buffer)
 6542     #
 6543     (write _test-input-stream "fn foo a: (addr t) {\n")
 6544     (write _test-input-stream "  var _a/eax: (addr t) <- copy a\n")
 6545     (write _test-input-stream "  var b/ecx: (addr int) <- get _a, x\n")
 6546     (write _test-input-stream "  var c/ecx: (addr int) <- get _a, y\n")
 6547     (write _test-input-stream "}\n")
 6548     (write _test-input-stream "type t {\n")
 6549     (write _test-input-stream "  x: int\n")
 6550     (write _test-input-stream "  y: int\n")
 6551     (write _test-input-stream "}\n")
 6552     # convert
 6553     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6554     (flush _test-output-buffered-file)
 6555 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 6561     # check output
 6562     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-and-type-definition/0")
 6563     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-and-type-definition/1")
 6564     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-and-type-definition/2")
 6565     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-and-type-definition/3")
 6566     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-and-type-definition/4")
 6567     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-and-type-definition/5")
 6568     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-and-type-definition/6")
 6569     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-and-type-definition/7")
 6570     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-and-type-definition/8")
 6571     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x00000000) 0x00000001/r32"  "F - test-convert-function-and-type-definition/9")
 6572     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x00000004) 0x00000001/r32"  "F - test-convert-function-and-type-definition/11")
 6573     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-and-type-definition/13")
 6574     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-and-type-definition/14")
 6575     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-and-type-definition/15")
 6576     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-and-type-definition/16")
 6577     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-and-type-definition/17")
 6578     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-and-type-definition/18")
 6579     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-and-type-definition/19")
 6580     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-and-type-definition/20")
 6581     # . epilogue
 6582     89/<- %esp 5/r32/ebp
 6583     5d/pop-to-ebp
 6584     c3/return
 6585 
 6586 test-type-definition-with-array:
 6587     # . prologue
 6588     55/push-ebp
 6589     89/<- %ebp 4/r32/esp
 6590     # setup
 6591     (clear-stream _test-input-stream)
 6592     (clear-stream $_test-input-buffered-file->buffer)
 6593     (clear-stream _test-output-stream)
 6594     (clear-stream $_test-output-buffered-file->buffer)
 6595     (clear-stream _test-error-stream)
 6596     (clear-stream $_test-error-buffered-file->buffer)
 6597     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6598     68/push 0/imm32
 6599     68/push 0/imm32
 6600     89/<- %edx 4/r32/esp
 6601     (tailor-exit-descriptor %edx 0x10)
 6602     #
 6603     (write _test-input-stream "type t {\n")
 6604     (write _test-input-stream "  a: (array int 3)\n")
 6605     (write _test-input-stream "}\n")
 6606     # convert
 6607     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6608     # registers except esp clobbered at this point
 6609     # restore ed
 6610     89/<- %edx 4/r32/esp
 6611     (flush _test-output-buffered-file)
 6612     (flush _test-error-buffered-file)
 6613 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 6619     # check output
 6620     (check-stream-equal _test-output-stream  ""  "F - test-type-definition-with-array: output should be empty")
 6621     (check-next-stream-line-equal _test-error-stream  "type t: 'array' elements not allowed for now"  "F - test-type-definition-with-array: error message")
 6622     # check that stop(1) was called
 6623     (check-ints-equal *(edx+4) 2 "F - test-type-definition-with-array: exit status")
 6624     # don't restore from ebp
 6625     81 0/subop/add %esp 8/imm32
 6626     # . epilogue
 6627     5d/pop-to-ebp
 6628     c3/return
 6629 
 6630 test-type-definition-with-addr:
 6631     # . prologue
 6632     55/push-ebp
 6633     89/<- %ebp 4/r32/esp
 6634     # setup
 6635     (clear-stream _test-input-stream)
 6636     (clear-stream $_test-input-buffered-file->buffer)
 6637     (clear-stream _test-output-stream)
 6638     (clear-stream $_test-output-buffered-file->buffer)
 6639     (clear-stream _test-error-stream)
 6640     (clear-stream $_test-error-buffered-file->buffer)
 6641     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6642     68/push 0/imm32
 6643     68/push 0/imm32
 6644     89/<- %edx 4/r32/esp
 6645     (tailor-exit-descriptor %edx 0x10)
 6646     #
 6647     (write _test-input-stream "type t {\n")
 6648     (write _test-input-stream "  a: (addr int)\n")
 6649     (write _test-input-stream "}\n")
 6650     # convert
 6651     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6652     # registers except esp clobbered at this point
 6653     # restore ed
 6654     89/<- %edx 4/r32/esp
 6655     (flush _test-output-buffered-file)
 6656     (flush _test-error-buffered-file)
 6657 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 6663     # check output
 6664     (check-stream-equal _test-output-stream  ""  "F - test-type-definition-with-addr: output should be empty")
 6665     (check-next-stream-line-equal _test-error-stream  "type t: 'addr' elements not allowed"  "F - test-type-definition-with-addr: error message")
 6666     # check that stop(1) was called
 6667     (check-ints-equal *(edx+4) 2 "F - test-type-definition-with-addr: exit status")
 6668     # don't restore from ebp
 6669     81 0/subop/add %esp 8/imm32
 6670     # . epilogue
 6671     5d/pop-to-ebp
 6672     c3/return
 6673 
 6674 test-convert-function-with-local-var-with-user-defined-type:
 6675     # . prologue
 6676     55/push-ebp
 6677     89/<- %ebp 4/r32/esp
 6678     # setup
 6679     (clear-stream _test-input-stream)
 6680     (clear-stream $_test-input-buffered-file->buffer)
 6681     (clear-stream _test-output-stream)
 6682     (clear-stream $_test-output-buffered-file->buffer)
 6683     #
 6684     (write _test-input-stream "fn foo {\n")
 6685     (write _test-input-stream "  var a: t\n")
 6686     (write _test-input-stream "}\n")
 6687     (write _test-input-stream "type t {\n")
 6688     (write _test-input-stream "  x: int\n")
 6689     (write _test-input-stream "  y: int\n")
 6690     (write _test-input-stream "}\n")
 6691     # convert
 6692     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6693     (flush _test-output-buffered-file)
 6694 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 6700     # check output
 6701     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-with-user-defined-type/0")
 6702     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-with-user-defined-type/1")
 6703     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-with-user-defined-type/2")
 6704     (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")
 6705     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-user-defined-type/4")
 6706     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-with-user-defined-type/5")
 6707     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-user-defined-type/6")
 6708     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-user-defined-type/7")
 6709     (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")
 6710     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-user-defined-type/9")
 6711     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-with-user-defined-type/10")
 6712     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-with-user-defined-type/11")
 6713     (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")
 6714     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-with-user-defined-type/13")
 6715     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-with-user-defined-type/14")
 6716     # . epilogue
 6717     89/<- %esp 5/r32/ebp
 6718     5d/pop-to-ebp
 6719     c3/return
 6720 
 6721 test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type:
 6722     # . prologue
 6723     55/push-ebp
 6724     89/<- %ebp 4/r32/esp
 6725     # setup
 6726     (clear-stream _test-input-stream)
 6727     (clear-stream $_test-input-buffered-file->buffer)
 6728     (clear-stream _test-output-stream)
 6729     (clear-stream $_test-output-buffered-file->buffer)
 6730     #
 6731     (write _test-input-stream "fn foo {\n")
 6732     (write _test-input-stream "  var a: t\n")
 6733     (write _test-input-stream "}\n")
 6734     (write _test-input-stream "type t {\n")
 6735     (write _test-input-stream "  x: s\n")
 6736     (write _test-input-stream "}\n")
 6737     (write _test-input-stream "type s {\n")
 6738     (write _test-input-stream "  z: int\n")
 6739     (write _test-input-stream "}\n")
 6740     # convert
 6741     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6742     (flush _test-output-buffered-file)
 6743 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 6749     # check output
 6750     (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")
 6751     (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")
 6752     (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")
 6753     (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")
 6754     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/4")
 6755     (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")
 6756     (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")
 6757     (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")
 6758     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/9")
 6759     (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")
 6760     (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")
 6761     (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")
 6762     (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")
 6763     (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")
 6764     # . epilogue
 6765     89/<- %esp 5/r32/ebp
 6766     5d/pop-to-ebp
 6767     c3/return
 6768 
 6769 test-convert-function-call-with-arg-of-user-defined-type:
 6770     # . prologue
 6771     55/push-ebp
 6772     89/<- %ebp 4/r32/esp
 6773     # setup
 6774     (clear-stream _test-input-stream)
 6775     (clear-stream $_test-input-buffered-file->buffer)
 6776     (clear-stream _test-output-stream)
 6777     (clear-stream $_test-output-buffered-file->buffer)
 6778     #
 6779     (write _test-input-stream "fn f {\n")
 6780     (write _test-input-stream "  var a: t\n")
 6781     (write _test-input-stream "  foo a\n")
 6782     (write _test-input-stream "}\n")
 6783     (write _test-input-stream "fn foo x: t {\n")
 6784     (write _test-input-stream "}\n")
 6785     (write _test-input-stream "type t {\n")
 6786     (write _test-input-stream "  x: int\n")
 6787     (write _test-input-stream "  y: int\n")
 6788     (write _test-input-stream "}\n")
 6789     # convert
 6790     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6791     (flush _test-output-buffered-file)
 6792 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 6798     # check output
 6799     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type/0")
 6800     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/1")
 6801     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/2")
 6802     (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")
 6803     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type/4")
 6804     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-arg-of-user-defined-type/5")
 6805     # var a: t
 6806     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-arg-of-user-defined-type/6")
 6807     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-arg-of-user-defined-type/7")
 6808     # foo a
 6809     (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")
 6810     #
 6811     (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")
 6812     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type/10")
 6813     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-arg-of-user-defined-type/11")
 6814     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/12")
 6815     (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")
 6816     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/14")
 6817     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/15")
 6818     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type/16")
 6819     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/17")
 6820     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/18")
 6821     (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")
 6822     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/20")
 6823     (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")
 6824     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/22")
 6825     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/23")
 6826     # . epilogue
 6827     89/<- %esp 5/r32/ebp
 6828     5d/pop-to-ebp
 6829     c3/return
 6830 
 6831 test-convert-function-call-with-arg-of-user-defined-type-register-indirect:
 6832     # . prologue
 6833     55/push-ebp
 6834     89/<- %ebp 4/r32/esp
 6835     # setup
 6836     (clear-stream _test-input-stream)
 6837     (clear-stream $_test-input-buffered-file->buffer)
 6838     (clear-stream _test-output-stream)
 6839     (clear-stream $_test-output-buffered-file->buffer)
 6840     #
 6841     (write _test-input-stream "fn f {\n")
 6842     (write _test-input-stream "  var a/eax: (addr t) <- copy 0\n")
 6843     (write _test-input-stream "  foo *a\n")
 6844     (write _test-input-stream "}\n")
 6845     (write _test-input-stream "fn foo x: t {\n")
 6846     (write _test-input-stream "}\n")
 6847     (write _test-input-stream "type t {\n")
 6848     (write _test-input-stream "  x: int\n")
 6849     (write _test-input-stream "  y: int\n")
 6850     (write _test-input-stream "}\n")
 6851     # convert
 6852     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6853     (flush _test-output-buffered-file)
 6854 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 6860     # check output
 6861     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type/0")
 6862     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/1")
 6863     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/2")
 6864     (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")
 6865     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type/4")
 6866     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-arg-of-user-defined-type/5")
 6867     # var a
 6868     (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")
 6869     (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")
 6870     # foo a
 6871     (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")
 6872     #
 6873     (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")
 6874     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type/10")
 6875     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-arg-of-user-defined-type/11")
 6876     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/12")
 6877     (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")
 6878     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/14")
 6879     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/15")
 6880     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type/16")
 6881     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/17")
 6882     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/18")
 6883     (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")
 6884     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/20")
 6885     (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")
 6886     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/22")
 6887     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/23")
 6888     # . epilogue
 6889     89/<- %esp 5/r32/ebp
 6890     5d/pop-to-ebp
 6891     c3/return
 6892 
 6893 # we don't have special support for call-by-reference; just explicitly create
 6894 # a new variable with the address of the arg
 6895 test-convert-function-call-with-arg-of-user-defined-type-by-reference:
 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     #
 6905     (write _test-input-stream "fn f {\n")
 6906     (write _test-input-stream "  var a: t\n")
 6907     (write _test-input-stream "  var b/eax: (addr t) <- address a\n")
 6908     (write _test-input-stream "  foo b\n")
 6909     (write _test-input-stream "}\n")
 6910     (write _test-input-stream "fn foo x: (addr t) {\n")
 6911     (write _test-input-stream "  var x/ecx: (addr t) <- copy x\n")
 6912     (write _test-input-stream "}\n")
 6913     (write _test-input-stream "type t {\n")
 6914     (write _test-input-stream "  x: int\n")
 6915     (write _test-input-stream "  y: int\n")
 6916     (write _test-input-stream "}\n")
 6917     # convert
 6918     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6919     (flush _test-output-buffered-file)
 6920 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 6926     # check output
 6927     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/0")
 6928     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/1")
 6929     (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")
 6930     (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")
 6931     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/4")
 6932     (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")
 6933     # var a: t
 6934     (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")
 6935     (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")
 6936     # var b/eax: (addr t)
 6937     (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")
 6938     (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")
 6939     # foo a
 6940     (check-next-stream-line-equal _test-output-stream "    (foo %eax)"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/10")
 6941     #
 6942     (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")
 6943     (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")
 6944     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/13")
 6945     (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")
 6946     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/15")
 6947     (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")
 6948     (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")
 6949     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/18")
 6950     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/19")
 6951     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/20")
 6952     (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")
 6953     (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")
 6954     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/23")
 6955     (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")
 6956     (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")
 6957     (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")
 6958     (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")
 6959     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/28")
 6960     (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")
 6961     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/30")
 6962     (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")
 6963     (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")
 6964     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/33")
 6965     # . epilogue
 6966     89/<- %esp 5/r32/ebp
 6967     5d/pop-to-ebp
 6968     c3/return
 6969 
 6970 test-convert-get-on-local-variable:
 6971     # . prologue
 6972     55/push-ebp
 6973     89/<- %ebp 4/r32/esp
 6974     # setup
 6975     (clear-stream _test-input-stream)
 6976     (clear-stream $_test-input-buffered-file->buffer)
 6977     (clear-stream _test-output-stream)
 6978     (clear-stream $_test-output-buffered-file->buffer)
 6979     #
 6980     (write _test-input-stream "fn foo {\n")
 6981     (write _test-input-stream "  var a: t\n")
 6982     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 6983     (write _test-input-stream "}\n")
 6984     (write _test-input-stream "type t {\n")
 6985     (write _test-input-stream "  x: int\n")
 6986     (write _test-input-stream "  y: int\n")
 6987     (write _test-input-stream "}\n")
 6988     # convert
 6989     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6990     (flush _test-output-buffered-file)
 6991 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 6997     # check output
 6998     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-local-variable/0")
 6999     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-local-variable/1")
 7000     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-local-variable/2")
 7001     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-local-variable/3")
 7002     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-local-variable/4")
 7003     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-local-variable/5")
 7004     # var a
 7005     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-get-on-local-variable/6")
 7006     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-get-on-local-variable/7")
 7007     # var c
 7008     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-local-variable/8")
 7009     # get
 7010     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0xfffffffc) 0x00000001/r32"  "F - test-convert-get-on-local-variable/9")
 7011     # reclaim c
 7012     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-local-variable/10")
 7013     # reclaim a
 7014     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000008/imm32"  "F - test-convert-get-on-local-variable/11")
 7015     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-local-variable/12")
 7016     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-local-variable/13")
 7017     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-local-variable/14")
 7018     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-local-variable/15")
 7019     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-local-variable/16")
 7020     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-local-variable/17")
 7021     # . epilogue
 7022     89/<- %esp 5/r32/ebp
 7023     5d/pop-to-ebp
 7024     c3/return
 7025 
 7026 test-convert-get-on-function-argument:
 7027     # . prologue
 7028     55/push-ebp
 7029     89/<- %ebp 4/r32/esp
 7030     # setup
 7031     (clear-stream _test-input-stream)
 7032     (clear-stream $_test-input-buffered-file->buffer)
 7033     (clear-stream _test-output-stream)
 7034     (clear-stream $_test-output-buffered-file->buffer)
 7035     #
 7036     (write _test-input-stream "fn foo a: t {\n")
 7037     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 7038     (write _test-input-stream "}\n")
 7039     (write _test-input-stream "type t {\n")
 7040     (write _test-input-stream "  x: int\n")
 7041     (write _test-input-stream "  y: int\n")
 7042     (write _test-input-stream "}\n")
 7043     # convert
 7044     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7045     (flush _test-output-buffered-file)
 7046 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 7052     # check output
 7053     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-function-argument/0")
 7054     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-function-argument/1")
 7055     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-function-argument/2")
 7056     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-function-argument/3")
 7057     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-function-argument/4")
 7058     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-function-argument/5")
 7059     # var c
 7060     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-function-argument/6")
 7061     # get
 7062     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0x0000000c) 0x00000001/r32"  "F - test-convert-get-on-function-argument/7")
 7063     # reclaim c
 7064     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-function-argument/8")
 7065     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-function-argument/9")
 7066     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-function-argument/10")
 7067     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-function-argument/11")
 7068     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-function-argument/12")
 7069     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-function-argument/13")
 7070     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-function-argument/14")
 7071     # . epilogue
 7072     89/<- %esp 5/r32/ebp
 7073     5d/pop-to-ebp
 7074     c3/return
 7075 
 7076 test-convert-get-on-function-argument-with-known-type:
 7077     # . prologue
 7078     55/push-ebp
 7079     89/<- %ebp 4/r32/esp
 7080     # setup
 7081     (clear-stream _test-input-stream)
 7082     (clear-stream $_test-input-buffered-file->buffer)
 7083     (clear-stream _test-output-stream)
 7084     (clear-stream $_test-output-buffered-file->buffer)
 7085     #
 7086     (write _test-input-stream "type t {\n")
 7087     (write _test-input-stream "  x: int\n")
 7088     (write _test-input-stream "  y: int\n")
 7089     (write _test-input-stream "}\n")
 7090     (write _test-input-stream "fn foo a: t {\n")
 7091     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 7092     (write _test-input-stream "}\n")
 7093     # convert
 7094     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7095     (flush _test-output-buffered-file)
 7096 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 7102     # check output
 7103     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-function-argument-with-known-type/0")
 7104     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-function-argument-with-known-type/1")
 7105     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-function-argument-with-known-type/2")
 7106     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-function-argument-with-known-type/3")
 7107     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-function-argument-with-known-type/4")
 7108     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-function-argument-with-known-type/5")
 7109     # var c
 7110     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-function-argument-with-known-type/6")
 7111     # get
 7112     (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")
 7113     # reclaim c
 7114     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-function-argument-with-known-type/8")
 7115     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-function-argument-with-known-type/9")
 7116     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-function-argument-with-known-type/10")
 7117     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-function-argument-with-known-type/11")
 7118     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-function-argument-with-known-type/12")
 7119     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-function-argument-with-known-type/13")
 7120     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-function-argument-with-known-type/14")
 7121     # . epilogue
 7122     89/<- %esp 5/r32/ebp
 7123     5d/pop-to-ebp
 7124     c3/return
 7125 
 7126 test-add-with-too-many-inouts:
 7127     # . prologue
 7128     55/push-ebp
 7129     89/<- %ebp 4/r32/esp
 7130     # setup
 7131     (clear-stream _test-input-stream)
 7132     (clear-stream $_test-input-buffered-file->buffer)
 7133     (clear-stream _test-output-stream)
 7134     (clear-stream $_test-output-buffered-file->buffer)
 7135     (clear-stream _test-error-stream)
 7136     (clear-stream $_test-error-buffered-file->buffer)
 7137     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7138     68/push 0/imm32
 7139     68/push 0/imm32
 7140     89/<- %edx 4/r32/esp
 7141     (tailor-exit-descriptor %edx 0x10)
 7142     #
 7143     (write _test-input-stream "fn foo {\n")
 7144     (write _test-input-stream "  var a: int\n")
 7145     (write _test-input-stream "  var b/ecx: int <- add a, 0\n")
 7146     (write _test-input-stream "}\n")
 7147     # convert
 7148     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7149     # registers except esp clobbered at this point
 7150     # restore ed
 7151     89/<- %edx 4/r32/esp
 7152     (flush _test-output-buffered-file)
 7153     (flush _test-error-buffered-file)
 7154 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 7160     # check output
 7161     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-inouts: output should be empty")
 7162     (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")
 7163     # check that stop(1) was called
 7164     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-inouts: exit status")
 7165     # don't restore from ebp
 7166     81 0/subop/add %esp 8/imm32
 7167     # . epilogue
 7168     5d/pop-to-ebp
 7169     c3/return
 7170 
 7171 test-add-with-too-many-inouts-2:
 7172     # . prologue
 7173     55/push-ebp
 7174     89/<- %ebp 4/r32/esp
 7175     # setup
 7176     (clear-stream _test-input-stream)
 7177     (clear-stream $_test-input-buffered-file->buffer)
 7178     (clear-stream _test-output-stream)
 7179     (clear-stream $_test-output-buffered-file->buffer)
 7180     (clear-stream _test-error-stream)
 7181     (clear-stream $_test-error-buffered-file->buffer)
 7182     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7183     68/push 0/imm32
 7184     68/push 0/imm32
 7185     89/<- %edx 4/r32/esp
 7186     (tailor-exit-descriptor %edx 0x10)
 7187     #
 7188     (write _test-input-stream "fn foo {\n")
 7189     (write _test-input-stream "  var a: int\n")
 7190     (write _test-input-stream "  add-to a, 0, 1\n")
 7191     (write _test-input-stream "}\n")
 7192     # convert
 7193     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7194     # registers except esp clobbered at this point
 7195     # restore ed
 7196     89/<- %edx 4/r32/esp
 7197     (flush _test-output-buffered-file)
 7198     (flush _test-error-buffered-file)
 7199 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 7205     # check output
 7206     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-inouts-2: output should be empty")
 7207     (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")
 7208     # check that stop(1) was called
 7209     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-inouts-2: exit status")
 7210     # don't restore from ebp
 7211     81 0/subop/add %esp 8/imm32
 7212     # . epilogue
 7213     5d/pop-to-ebp
 7214     c3/return
 7215 
 7216 test-add-with-too-many-outputs:
 7217     # . prologue
 7218     55/push-ebp
 7219     89/<- %ebp 4/r32/esp
 7220     # setup
 7221     (clear-stream _test-input-stream)
 7222     (clear-stream $_test-input-buffered-file->buffer)
 7223     (clear-stream _test-output-stream)
 7224     (clear-stream $_test-output-buffered-file->buffer)
 7225     (clear-stream _test-error-stream)
 7226     (clear-stream $_test-error-buffered-file->buffer)
 7227     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7228     68/push 0/imm32
 7229     68/push 0/imm32
 7230     89/<- %edx 4/r32/esp
 7231     (tailor-exit-descriptor %edx 0x10)
 7232     #
 7233     (write _test-input-stream "fn foo {\n")
 7234     (write _test-input-stream "  var a/eax: int <- copy 0\n")
 7235     (write _test-input-stream "  var b/ebx: int <- copy 0\n")
 7236     (write _test-input-stream "  var c/ecx: int <- copy 0\n")
 7237     (write _test-input-stream "  c, b <- add a\n")
 7238     (write _test-input-stream "}\n")
 7239     # convert
 7240     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7241     # registers except esp clobbered at this point
 7242     # restore ed
 7243     89/<- %edx 4/r32/esp
 7244     (flush _test-output-buffered-file)
 7245     (flush _test-error-buffered-file)
 7246 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 7252     # check output
 7253     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-outputs: output should be empty")
 7254     (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")
 7255     # check that stop(1) was called
 7256     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-outputs: exit status")
 7257     # don't restore from ebp
 7258     81 0/subop/add %esp 8/imm32
 7259     # . epilogue
 7260     5d/pop-to-ebp
 7261     c3/return
 7262 
 7263 test-add-with-non-number:
 7264     # . prologue
 7265     55/push-ebp
 7266     89/<- %ebp 4/r32/esp
 7267     # setup
 7268     (clear-stream _test-input-stream)
 7269     (clear-stream $_test-input-buffered-file->buffer)
 7270     (clear-stream _test-output-stream)
 7271     (clear-stream $_test-output-buffered-file->buffer)
 7272     (clear-stream _test-error-stream)
 7273     (clear-stream $_test-error-buffered-file->buffer)
 7274     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7275     68/push 0/imm32
 7276     68/push 0/imm32
 7277     89/<- %edx 4/r32/esp
 7278     (tailor-exit-descriptor %edx 0x10)
 7279     #
 7280     (write _test-input-stream "fn foo {\n")
 7281     (write _test-input-stream "  var a: int\n")
 7282     (write _test-input-stream "  var b/ecx: (addr int) <- add a\n")
 7283     (write _test-input-stream "}\n")
 7284     # convert
 7285     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7286     # registers except esp clobbered at this point
 7287     # restore ed
 7288     89/<- %edx 4/r32/esp
 7289     (flush _test-output-buffered-file)
 7290     (flush _test-error-buffered-file)
 7291 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 7297     # check output
 7298     (check-stream-equal _test-output-stream  ""  "F - test-add-with-non-number: output should be empty")
 7299     (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")
 7300     # check that stop(1) was called
 7301     (check-ints-equal *(edx+4) 2 "F - test-add-with-non-number: exit status")
 7302     # don't restore from ebp
 7303     81 0/subop/add %esp 8/imm32
 7304     # . epilogue
 7305     5d/pop-to-ebp
 7306     c3/return
 7307 
 7308 test-add-with-addr-dereferenced:
 7309     # . prologue
 7310     55/push-ebp
 7311     89/<- %ebp 4/r32/esp
 7312     # setup
 7313     (clear-stream _test-input-stream)
 7314     (clear-stream $_test-input-buffered-file->buffer)
 7315     (clear-stream _test-output-stream)
 7316     (clear-stream $_test-output-buffered-file->buffer)
 7317     #
 7318     (write _test-input-stream "fn foo {\n")
 7319     (write _test-input-stream "  var a/eax: (addr int) <- copy 0\n")
 7320     (write _test-input-stream "  add-to *a, 1\n")
 7321     (write _test-input-stream "}\n")
 7322     # convert
 7323     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7324     (flush _test-output-buffered-file)
 7325     # no error
 7326     # . epilogue
 7327     89/<- %esp 5/r32/ebp
 7328     5d/pop-to-ebp
 7329     c3/return
 7330 
 7331 test-copy-with-no-inout:
 7332     # . prologue
 7333     55/push-ebp
 7334     89/<- %ebp 4/r32/esp
 7335     # setup
 7336     (clear-stream _test-input-stream)
 7337     (clear-stream $_test-input-buffered-file->buffer)
 7338     (clear-stream _test-output-stream)
 7339     (clear-stream $_test-output-buffered-file->buffer)
 7340     (clear-stream _test-error-stream)
 7341     (clear-stream $_test-error-buffered-file->buffer)
 7342     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7343     68/push 0/imm32
 7344     68/push 0/imm32
 7345     89/<- %edx 4/r32/esp
 7346     (tailor-exit-descriptor %edx 0x10)
 7347     #
 7348     (write _test-input-stream "fn foo {\n")
 7349     (write _test-input-stream "  var x/eax: boolean <- copy\n")
 7350     (write _test-input-stream "}\n")
 7351     # convert
 7352     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7353     # registers except esp clobbered at this point
 7354     # restore ed
 7355     89/<- %edx 4/r32/esp
 7356     (flush _test-output-buffered-file)
 7357     (flush _test-error-buffered-file)
 7358 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 7364     # check output
 7365     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-no-inout: output should be empty")
 7366     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy' expects an inout"  "F - test-copy-with-no-inout: error message")
 7367     # check that stop(1) was called
 7368     (check-ints-equal *(edx+4) 2 "F - test-copy-with-no-inout: exit status")
 7369     # don't restore from ebp
 7370     81 0/subop/add %esp 8/imm32
 7371     # . epilogue
 7372     5d/pop-to-ebp
 7373     c3/return
 7374 
 7375 test-copy-with-multiple-inouts:
 7376     # . prologue
 7377     55/push-ebp
 7378     89/<- %ebp 4/r32/esp
 7379     # setup
 7380     (clear-stream _test-input-stream)
 7381     (clear-stream $_test-input-buffered-file->buffer)
 7382     (clear-stream _test-output-stream)
 7383     (clear-stream $_test-output-buffered-file->buffer)
 7384     (clear-stream _test-error-stream)
 7385     (clear-stream $_test-error-buffered-file->buffer)
 7386     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7387     68/push 0/imm32
 7388     68/push 0/imm32
 7389     89/<- %edx 4/r32/esp
 7390     (tailor-exit-descriptor %edx 0x10)
 7391     #
 7392     (write _test-input-stream "fn foo {\n")
 7393     (write _test-input-stream "  var x/eax: boolean <- copy 0, 0\n")
 7394     (write _test-input-stream "}\n")
 7395     # convert
 7396     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7397     # registers except esp clobbered at this point
 7398     # restore ed
 7399     89/<- %edx 4/r32/esp
 7400     (flush _test-output-buffered-file)
 7401     (flush _test-error-buffered-file)
 7402 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 7408     # check output
 7409     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-multiple-inouts: output should be empty")
 7410     (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")
 7411     # check that stop(1) was called
 7412     (check-ints-equal *(edx+4) 2 "F - test-copy-with-multiple-inouts: exit status")
 7413     # don't restore from ebp
 7414     81 0/subop/add %esp 8/imm32
 7415     # . epilogue
 7416     5d/pop-to-ebp
 7417     c3/return
 7418 
 7419 test-copy-with-no-output:
 7420     # . prologue
 7421     55/push-ebp
 7422     89/<- %ebp 4/r32/esp
 7423     # setup
 7424     (clear-stream _test-input-stream)
 7425     (clear-stream $_test-input-buffered-file->buffer)
 7426     (clear-stream _test-output-stream)
 7427     (clear-stream $_test-output-buffered-file->buffer)
 7428     (clear-stream _test-error-stream)
 7429     (clear-stream $_test-error-buffered-file->buffer)
 7430     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7431     68/push 0/imm32
 7432     68/push 0/imm32
 7433     89/<- %edx 4/r32/esp
 7434     (tailor-exit-descriptor %edx 0x10)
 7435     #
 7436     (write _test-input-stream "fn foo {\n")
 7437     (write _test-input-stream "  copy 0\n")
 7438     (write _test-input-stream "}\n")
 7439     # convert
 7440     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7441     # registers except esp clobbered at this point
 7442     # restore ed
 7443     89/<- %edx 4/r32/esp
 7444     (flush _test-output-buffered-file)
 7445     (flush _test-error-buffered-file)
 7446 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 7452     # check output
 7453     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-no-output: output should be empty")
 7454     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy' expects an output"  "F - test-copy-with-no-output: error message")
 7455     # check that stop(1) was called
 7456     (check-ints-equal *(edx+4) 2 "F - test-copy-with-no-output: exit status")
 7457     # don't restore from ebp
 7458     81 0/subop/add %esp 8/imm32
 7459     # . epilogue
 7460     5d/pop-to-ebp
 7461     c3/return
 7462 
 7463 test-copy-with-multiple-outputs:
 7464     # . prologue
 7465     55/push-ebp
 7466     89/<- %ebp 4/r32/esp
 7467     # setup
 7468     (clear-stream _test-input-stream)
 7469     (clear-stream $_test-input-buffered-file->buffer)
 7470     (clear-stream _test-output-stream)
 7471     (clear-stream $_test-output-buffered-file->buffer)
 7472     (clear-stream _test-error-stream)
 7473     (clear-stream $_test-error-buffered-file->buffer)
 7474     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7475     68/push 0/imm32
 7476     68/push 0/imm32
 7477     89/<- %edx 4/r32/esp
 7478     (tailor-exit-descriptor %edx 0x10)
 7479     #
 7480     (write _test-input-stream "fn foo {\n")
 7481     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 7482     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
 7483     (write _test-input-stream "  x, y <- copy 0\n")
 7484     (write _test-input-stream "}\n")
 7485     # convert
 7486     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7487     # registers except esp clobbered at this point
 7488     # restore ed
 7489     89/<- %edx 4/r32/esp
 7490     (flush _test-output-buffered-file)
 7491     (flush _test-error-buffered-file)
 7492 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 7498     # check output
 7499     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-multiple-outputs: output should be empty")
 7500     (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")
 7501     # check that stop(1) was called
 7502     (check-ints-equal *(edx+4) 2 "F - test-copy-with-multiple-outputs: exit status")
 7503     # don't restore from ebp
 7504     81 0/subop/add %esp 8/imm32
 7505     # . epilogue
 7506     5d/pop-to-ebp
 7507     c3/return
 7508 
 7509 test-copy-invalid-value-to-address:
 7510     # . prologue
 7511     55/push-ebp
 7512     89/<- %ebp 4/r32/esp
 7513     # setup
 7514     (clear-stream _test-input-stream)
 7515     (clear-stream $_test-input-buffered-file->buffer)
 7516     (clear-stream _test-output-stream)
 7517     (clear-stream $_test-output-buffered-file->buffer)
 7518     (clear-stream _test-error-stream)
 7519     (clear-stream $_test-error-buffered-file->buffer)
 7520     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7521     68/push 0/imm32
 7522     68/push 0/imm32
 7523     89/<- %edx 4/r32/esp
 7524     (tailor-exit-descriptor %edx 0x10)
 7525     #
 7526     (write _test-input-stream "fn foo {\n")
 7527     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 7528     (write _test-input-stream "  var y/ecx: (addr int) <- copy x\n")
 7529     (write _test-input-stream "}\n")
 7530     # convert
 7531     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7532     # registers except esp clobbered at this point
 7533     # restore ed
 7534     89/<- %edx 4/r32/esp
 7535     (flush _test-output-buffered-file)
 7536     (flush _test-error-buffered-file)
 7537 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 7543     # check output
 7544     (check-stream-equal _test-output-stream  ""  "F - test-copy-invalid-value-to-address: output should be empty")
 7545     (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")
 7546     # check that stop(1) was called
 7547     (check-ints-equal *(edx+4) 2 "F - test-copy-invalid-value-to-address: exit status")
 7548     # don't restore from ebp
 7549     81 0/subop/add %esp 8/imm32
 7550     # . epilogue
 7551     5d/pop-to-ebp
 7552     c3/return
 7553 
 7554 test-copy-null-value-to-addr:
 7555     # . prologue
 7556     55/push-ebp
 7557     89/<- %ebp 4/r32/esp
 7558     # setup
 7559     (clear-stream _test-input-stream)
 7560     (clear-stream $_test-input-buffered-file->buffer)
 7561     (clear-stream _test-output-stream)
 7562     (clear-stream $_test-output-buffered-file->buffer)
 7563     #
 7564     (write _test-input-stream "fn foo {\n")
 7565     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
 7566     (write _test-input-stream "}\n")
 7567     # convert
 7568     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7569     (flush _test-output-buffered-file)
 7570 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 7576     # no errors
 7577     # . epilogue
 7578     89/<- %esp 5/r32/ebp
 7579     5d/pop-to-ebp
 7580     c3/return
 7581 
 7582 test-copy-invalid-value-to-offset:
 7583     # . prologue
 7584     55/push-ebp
 7585     89/<- %ebp 4/r32/esp
 7586     # setup
 7587     (clear-stream _test-input-stream)
 7588     (clear-stream $_test-input-buffered-file->buffer)
 7589     (clear-stream _test-output-stream)
 7590     (clear-stream $_test-output-buffered-file->buffer)
 7591     (clear-stream _test-error-stream)
 7592     (clear-stream $_test-error-buffered-file->buffer)
 7593     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7594     68/push 0/imm32
 7595     68/push 0/imm32
 7596     89/<- %edx 4/r32/esp
 7597     (tailor-exit-descriptor %edx 0x10)
 7598     #
 7599     (write _test-input-stream "fn foo {\n")
 7600     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 7601     (write _test-input-stream "  var y/ecx: (offset int) <- copy x\n")
 7602     (write _test-input-stream "}\n")
 7603     # convert
 7604     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7605     # registers except esp clobbered at this point
 7606     # restore ed
 7607     89/<- %edx 4/r32/esp
 7608     (flush _test-output-buffered-file)
 7609     (flush _test-error-buffered-file)
 7610 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 7616     # check output
 7617     (check-stream-equal _test-output-stream  ""  "F - test-copy-invalid-value-to-address: output should be empty")
 7618     (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")
 7619     # check that stop(1) was called
 7620     (check-ints-equal *(edx+4) 2 "F - test-copy-invalid-value-to-offset: exit status")
 7621     # don't restore from ebp
 7622     81 0/subop/add %esp 8/imm32
 7623     # . epilogue
 7624     5d/pop-to-ebp
 7625     c3/return
 7626 
 7627 test-copy-null-value-to-offset:
 7628     # . prologue
 7629     55/push-ebp
 7630     89/<- %ebp 4/r32/esp
 7631     # setup
 7632     (clear-stream _test-input-stream)
 7633     (clear-stream $_test-input-buffered-file->buffer)
 7634     (clear-stream _test-output-stream)
 7635     (clear-stream $_test-output-buffered-file->buffer)
 7636     #
 7637     (write _test-input-stream "fn foo {\n")
 7638     (write _test-input-stream "  var y/ecx: (offset int) <- copy 0\n")
 7639     (write _test-input-stream "}\n")
 7640     # convert
 7641     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7642     (flush _test-output-buffered-file)
 7643 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 7649     # no errors
 7650     # . epilogue
 7651     89/<- %esp 5/r32/ebp
 7652     5d/pop-to-ebp
 7653     c3/return
 7654 
 7655 test-copy-deref-address:
 7656     # . prologue
 7657     55/push-ebp
 7658     89/<- %ebp 4/r32/esp
 7659     # setup
 7660     (clear-stream _test-input-stream)
 7661     (clear-stream $_test-input-buffered-file->buffer)
 7662     (clear-stream _test-output-stream)
 7663     (clear-stream $_test-output-buffered-file->buffer)
 7664     #
 7665     (write _test-input-stream "fn foo {\n")
 7666     (write _test-input-stream "  var x/eax: (addr addr int) <- copy 0\n")
 7667     (write _test-input-stream "  var y/ecx: (addr int) <- copy *x\n")
 7668     (write _test-input-stream "}\n")
 7669     # convert
 7670     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7671     (flush _test-output-buffered-file)
 7672 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 7678     # not bothering checking output
 7679     (check-next-stream-line-equal _test-error-stream  ""  "F - test-copy-deref-address: error message")
 7680     # . epilogue
 7681     5d/pop-to-ebp
 7682     c3/return
 7683 
 7684 test-copy-to-non-register:
 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: int\n")
 7703     (write _test-input-stream "  x <- copy 0\n")
 7704     (write _test-input-stream "}\n")
 7705     # convert
 7706     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7707     # registers except esp clobbered at this point
 7708     # restore ed
 7709     89/<- %edx 4/r32/esp
 7710     (flush _test-output-buffered-file)
 7711     (flush _test-error-buffered-file)
 7712 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 7718     # check output
 7719     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-non-register: output should be empty")
 7720     (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")
 7721     # check that stop(1) was called
 7722     (check-ints-equal *(edx+4) 2 "F - test-copy-to-non-register: exit status")
 7723     # don't restore from ebp
 7724     81 0/subop/add %esp 8/imm32
 7725     # . epilogue
 7726     5d/pop-to-ebp
 7727     c3/return
 7728 
 7729 test-copy-non-scalar:
 7730     # . prologue
 7731     55/push-ebp
 7732     89/<- %ebp 4/r32/esp
 7733     # setup
 7734     (clear-stream _test-input-stream)
 7735     (clear-stream $_test-input-buffered-file->buffer)
 7736     (clear-stream _test-output-stream)
 7737     (clear-stream $_test-output-buffered-file->buffer)
 7738     (clear-stream _test-error-stream)
 7739     (clear-stream $_test-error-buffered-file->buffer)
 7740     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7741     68/push 0/imm32
 7742     68/push 0/imm32
 7743     89/<- %edx 4/r32/esp
 7744     (tailor-exit-descriptor %edx 0x10)
 7745     #
 7746     (write _test-input-stream "fn foo {\n")
 7747     (write _test-input-stream "  var x: (handle int)\n")
 7748     (write _test-input-stream "  var y/eax: int <- copy x\n")
 7749     (write _test-input-stream "}\n")
 7750     # convert
 7751     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7752     # registers except esp clobbered at this point
 7753     # restore ed
 7754     89/<- %edx 4/r32/esp
 7755     (flush _test-output-buffered-file)
 7756     (flush _test-error-buffered-file)
 7757 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 7763     # check output
 7764     (check-stream-equal _test-output-stream  ""  "F - test-copy-non-scalar: output should be empty")
 7765     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy: 'x' is too large to fit in a register"  "F - test-copy-non-scalar: error message")
 7766     # check that stop(1) was called
 7767     (check-ints-equal *(edx+4) 2 "F - test-copy-non-scalar: exit status")
 7768     # don't restore from ebp
 7769     81 0/subop/add %esp 8/imm32
 7770     # . epilogue
 7771     5d/pop-to-ebp
 7772     c3/return
 7773 
 7774 test-copy-to-with-no-inout:
 7775     # . prologue
 7776     55/push-ebp
 7777     89/<- %ebp 4/r32/esp
 7778     # setup
 7779     (clear-stream _test-input-stream)
 7780     (clear-stream $_test-input-buffered-file->buffer)
 7781     (clear-stream _test-output-stream)
 7782     (clear-stream $_test-output-buffered-file->buffer)
 7783     (clear-stream _test-error-stream)
 7784     (clear-stream $_test-error-buffered-file->buffer)
 7785     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7786     68/push 0/imm32
 7787     68/push 0/imm32
 7788     89/<- %edx 4/r32/esp
 7789     (tailor-exit-descriptor %edx 0x10)
 7790     #
 7791     (write _test-input-stream "fn foo {\n")
 7792     (write _test-input-stream "  copy-to\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-to-with-no-inout: output should be empty")
 7809     (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")
 7810     # check that stop(1) was called
 7811     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-inout: 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-to-with-no-input:
 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: boolean\n")
 7837     (write _test-input-stream "  copy-to 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-to-with-no-input: output should be empty")
 7854     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-to' must have two inouts"  "F - test-copy-to-with-no-input: error message")
 7855     # check that stop(1) was called
 7856     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-input: 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-to-with-no-register:
 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     (clear-stream _test-error-stream)
 7873     (clear-stream $_test-error-buffered-file->buffer)
 7874     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7875     68/push 0/imm32
 7876     68/push 0/imm32
 7877     89/<- %edx 4/r32/esp
 7878     (tailor-exit-descriptor %edx 0x10)
 7879     #
 7880     (write _test-input-stream "fn foo {\n")
 7881     (write _test-input-stream "  var x: boolean\n")
 7882     (write _test-input-stream "  copy-to x, x\n")
 7883     (write _test-input-stream "}\n")
 7884     # convert
 7885     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7886     # registers except esp clobbered at this point
 7887     # restore ed
 7888     89/<- %edx 4/r32/esp
 7889     (flush _test-output-buffered-file)
 7890     (flush _test-error-buffered-file)
 7891 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 7897     # check output
 7898     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-no-register: output should be empty")
 7899     (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")
 7900     # check that stop(1) was called
 7901     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-register: exit status")
 7902     # don't restore from ebp
 7903     81 0/subop/add %esp 8/imm32
 7904     # . epilogue
 7905     5d/pop-to-ebp
 7906     c3/return
 7907 
 7908 test-copy-to-with-too-many-inouts:
 7909     # . prologue
 7910     55/push-ebp
 7911     89/<- %ebp 4/r32/esp
 7912     # setup
 7913     (clear-stream _test-input-stream)
 7914     (clear-stream $_test-input-buffered-file->buffer)
 7915     (clear-stream _test-output-stream)
 7916     (clear-stream $_test-output-buffered-file->buffer)
 7917     (clear-stream _test-error-stream)
 7918     (clear-stream $_test-error-buffered-file->buffer)
 7919     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7920     68/push 0/imm32
 7921     68/push 0/imm32
 7922     89/<- %edx 4/r32/esp
 7923     (tailor-exit-descriptor %edx 0x10)
 7924     #
 7925     (write _test-input-stream "fn foo {\n")
 7926     (write _test-input-stream "  var x: boolean\n")
 7927     (write _test-input-stream "  copy-to x, 0, 0\n")
 7928     (write _test-input-stream "}\n")
 7929     # convert
 7930     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7931     # registers except esp clobbered at this point
 7932     # restore ed
 7933     89/<- %edx 4/r32/esp
 7934     (flush _test-output-buffered-file)
 7935     (flush _test-error-buffered-file)
 7936 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 7942     # check output
 7943     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-too-many-inouts: output should be empty")
 7944     (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")
 7945     # check that stop(1) was called
 7946     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-too-many-inouts: exit status")
 7947     # don't restore from ebp
 7948     81 0/subop/add %esp 8/imm32
 7949     # . epilogue
 7950     5d/pop-to-ebp
 7951     c3/return
 7952 
 7953 test-copy-to-with-output:
 7954     # . prologue
 7955     55/push-ebp
 7956     89/<- %ebp 4/r32/esp
 7957     # setup
 7958     (clear-stream _test-input-stream)
 7959     (clear-stream $_test-input-buffered-file->buffer)
 7960     (clear-stream _test-output-stream)
 7961     (clear-stream $_test-output-buffered-file->buffer)
 7962     (clear-stream _test-error-stream)
 7963     (clear-stream $_test-error-buffered-file->buffer)
 7964     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7965     68/push 0/imm32
 7966     68/push 0/imm32
 7967     89/<- %edx 4/r32/esp
 7968     (tailor-exit-descriptor %edx 0x10)
 7969     #
 7970     (write _test-input-stream "fn foo {\n")
 7971     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 7972     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
 7973     (write _test-input-stream "  x <- copy-to y, 0\n")
 7974     (write _test-input-stream "}\n")
 7975     # convert
 7976     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7977     # registers except esp clobbered at this point
 7978     # restore ed
 7979     89/<- %edx 4/r32/esp
 7980     (flush _test-output-buffered-file)
 7981     (flush _test-error-buffered-file)
 7982 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 7988     # check output
 7989     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-output: output should be empty")
 7990     (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")
 7991     # check that stop(1) was called
 7992     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-output: exit status")
 7993     # don't restore from ebp
 7994     81 0/subop/add %esp 8/imm32
 7995     # . epilogue
 7996     5d/pop-to-ebp
 7997     c3/return
 7998 
 7999 test-copy-to-invalid-value-to-address:
 8000     # . prologue
 8001     55/push-ebp
 8002     89/<- %ebp 4/r32/esp
 8003     # setup
 8004     (clear-stream _test-input-stream)
 8005     (clear-stream $_test-input-buffered-file->buffer)
 8006     (clear-stream _test-output-stream)
 8007     (clear-stream $_test-output-buffered-file->buffer)
 8008     (clear-stream _test-error-stream)
 8009     (clear-stream $_test-error-buffered-file->buffer)
 8010     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8011     68/push 0/imm32
 8012     68/push 0/imm32
 8013     89/<- %edx 4/r32/esp
 8014     (tailor-exit-descriptor %edx 0x10)
 8015     #
 8016     (write _test-input-stream "fn foo {\n")
 8017     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 8018     (write _test-input-stream "  var y: (addr int)\n")
 8019     (write _test-input-stream "  copy-to y, x\n")
 8020     (write _test-input-stream "}\n")
 8021     # convert
 8022     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8023     # registers except esp clobbered at this point
 8024     # restore ed
 8025     89/<- %edx 4/r32/esp
 8026     (flush _test-output-buffered-file)
 8027     (flush _test-error-buffered-file)
 8028 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 8034     # check output
 8035     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-invalid-value-to-address: output should be empty")
 8036     (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")
 8037     # check that stop(1) was called
 8038     (check-ints-equal *(edx+4) 2 "F - test-copy-to-invalid-value-to-address: exit status")
 8039     # don't restore from ebp
 8040     81 0/subop/add %esp 8/imm32
 8041     # . epilogue
 8042     5d/pop-to-ebp
 8043     c3/return
 8044 
 8045 test-copy-to-deref-address:
 8046     # . prologue
 8047     55/push-ebp
 8048     89/<- %ebp 4/r32/esp
 8049     # setup
 8050     (clear-stream _test-input-stream)
 8051     (clear-stream $_test-input-buffered-file->buffer)
 8052     (clear-stream _test-output-stream)
 8053     (clear-stream $_test-output-buffered-file->buffer)
 8054     #
 8055     (write _test-input-stream "fn foo {\n")
 8056     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
 8057     (write _test-input-stream "  var y/ecx: (addr addr int) <- copy 0\n")
 8058     (write _test-input-stream "  copy-to *y, x\n")
 8059     (write _test-input-stream "}\n")
 8060     # convert
 8061     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8062     (flush _test-output-buffered-file)
 8063 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 8069     # not bothering checking output
 8070     (check-next-stream-line-equal _test-error-stream  ""  "F - test-copy-to-deref-address: error message")
 8071     # . epilogue
 8072     5d/pop-to-ebp
 8073     c3/return
 8074 
 8075 test-copy-to-non-scalar:
 8076     # . prologue
 8077     55/push-ebp
 8078     89/<- %ebp 4/r32/esp
 8079     # setup
 8080     (clear-stream _test-input-stream)
 8081     (clear-stream $_test-input-buffered-file->buffer)
 8082     (clear-stream _test-output-stream)
 8083     (clear-stream $_test-output-buffered-file->buffer)
 8084     (clear-stream _test-error-stream)
 8085     (clear-stream $_test-error-buffered-file->buffer)
 8086     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8087     68/push 0/imm32
 8088     68/push 0/imm32
 8089     89/<- %edx 4/r32/esp
 8090     (tailor-exit-descriptor %edx 0x10)
 8091     #
 8092     (write _test-input-stream "fn foo {\n")
 8093     (write _test-input-stream "  var x: (handle int)\n")
 8094     (write _test-input-stream "  var y: int\n")
 8095     (write _test-input-stream "  copy-to y, x\n")
 8096     (write _test-input-stream "}\n")
 8097     # convert
 8098     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8099     # registers except esp clobbered at this point
 8100     # restore ed
 8101     89/<- %edx 4/r32/esp
 8102     (flush _test-output-buffered-file)
 8103     (flush _test-error-buffered-file)
 8104 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 8110     # check output
 8111     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-non-scalar: output should be empty")
 8112 #?     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-to: 'x' is too large to copy"  "F - test-copy-to-non-scalar: error message")
 8113     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-to: source (second inout) is in memory"  "F - test-copy-to-non-scalar: error message")
 8114     # check that stop(1) was called
 8115     (check-ints-equal *(edx+4) 2 "F - test-copy-to-non-scalar: exit status")
 8116     # don't restore from ebp
 8117     81 0/subop/add %esp 8/imm32
 8118     # . epilogue
 8119     5d/pop-to-ebp
 8120     c3/return
 8121 
 8122 test-compare-with-no-inout:
 8123     # . prologue
 8124     55/push-ebp
 8125     89/<- %ebp 4/r32/esp
 8126     # setup
 8127     (clear-stream _test-input-stream)
 8128     (clear-stream $_test-input-buffered-file->buffer)
 8129     (clear-stream _test-output-stream)
 8130     (clear-stream $_test-output-buffered-file->buffer)
 8131     (clear-stream _test-error-stream)
 8132     (clear-stream $_test-error-buffered-file->buffer)
 8133     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8134     68/push 0/imm32
 8135     68/push 0/imm32
 8136     89/<- %edx 4/r32/esp
 8137     (tailor-exit-descriptor %edx 0x10)
 8138     #
 8139     (write _test-input-stream "fn foo {\n")
 8140     (write _test-input-stream "  var x: boolean\n")
 8141     (write _test-input-stream "  compare\n")
 8142     (write _test-input-stream "}\n")
 8143     # convert
 8144     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8145     # registers except esp clobbered at this point
 8146     # restore ed
 8147     89/<- %edx 4/r32/esp
 8148     (flush _test-output-buffered-file)
 8149     (flush _test-error-buffered-file)
 8150 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 8156     # check output
 8157     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-no-inout: output should be empty")
 8158     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must have two inouts"  "F - test-compare-with-no-inout: error message")
 8159     # check that stop(1) was called
 8160     (check-ints-equal *(edx+4) 2 "F - test-compare-with-no-inout: exit status")
 8161     # don't restore from ebp
 8162     81 0/subop/add %esp 8/imm32
 8163     # . epilogue
 8164     5d/pop-to-ebp
 8165     c3/return
 8166 
 8167 test-compare-with-no-input:
 8168     # . prologue
 8169     55/push-ebp
 8170     89/<- %ebp 4/r32/esp
 8171     # setup
 8172     (clear-stream _test-input-stream)
 8173     (clear-stream $_test-input-buffered-file->buffer)
 8174     (clear-stream _test-output-stream)
 8175     (clear-stream $_test-output-buffered-file->buffer)
 8176     (clear-stream _test-error-stream)
 8177     (clear-stream $_test-error-buffered-file->buffer)
 8178     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8179     68/push 0/imm32
 8180     68/push 0/imm32
 8181     89/<- %edx 4/r32/esp
 8182     (tailor-exit-descriptor %edx 0x10)
 8183     #
 8184     (write _test-input-stream "fn foo {\n")
 8185     (write _test-input-stream "  var x: boolean\n")
 8186     (write _test-input-stream "  compare x\n")
 8187     (write _test-input-stream "}\n")
 8188     # convert
 8189     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8190     # registers except esp clobbered at this point
 8191     # restore ed
 8192     89/<- %edx 4/r32/esp
 8193     (flush _test-output-buffered-file)
 8194     (flush _test-error-buffered-file)
 8195 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 8201     # check output
 8202     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-no-input: output should be empty")
 8203     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must have two inouts"  "F - test-compare-with-no-input: error message")
 8204     # check that stop(1) was called
 8205     (check-ints-equal *(edx+4) 2 "F - test-compare-with-no-input: exit status")
 8206     # don't restore from ebp
 8207     81 0/subop/add %esp 8/imm32
 8208     # . epilogue
 8209     5d/pop-to-ebp
 8210     c3/return
 8211 
 8212 test-compare-with-too-many-inouts:
 8213     # . prologue
 8214     55/push-ebp
 8215     89/<- %ebp 4/r32/esp
 8216     # setup
 8217     (clear-stream _test-input-stream)
 8218     (clear-stream $_test-input-buffered-file->buffer)
 8219     (clear-stream _test-output-stream)
 8220     (clear-stream $_test-output-buffered-file->buffer)
 8221     (clear-stream _test-error-stream)
 8222     (clear-stream $_test-error-buffered-file->buffer)
 8223     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8224     68/push 0/imm32
 8225     68/push 0/imm32
 8226     89/<- %edx 4/r32/esp
 8227     (tailor-exit-descriptor %edx 0x10)
 8228     #
 8229     (write _test-input-stream "fn foo {\n")
 8230     (write _test-input-stream "  var x: boolean\n")
 8231     (write _test-input-stream "  compare x, 0, 0\n")
 8232     (write _test-input-stream "}\n")
 8233     # convert
 8234     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8235     # registers except esp clobbered at this point
 8236     # restore ed
 8237     89/<- %edx 4/r32/esp
 8238     (flush _test-output-buffered-file)
 8239     (flush _test-error-buffered-file)
 8240 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 8246     # check output
 8247     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-too-many-inouts: output should be empty")
 8248     (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")
 8249     # check that stop(1) was called
 8250     (check-ints-equal *(edx+4) 2 "F - test-compare-with-too-many-inouts: exit status")
 8251     # don't restore from ebp
 8252     81 0/subop/add %esp 8/imm32
 8253     # . epilogue
 8254     5d/pop-to-ebp
 8255     c3/return
 8256 
 8257 test-compare-with-output:
 8258     # . prologue
 8259     55/push-ebp
 8260     89/<- %ebp 4/r32/esp
 8261     # setup
 8262     (clear-stream _test-input-stream)
 8263     (clear-stream $_test-input-buffered-file->buffer)
 8264     (clear-stream _test-output-stream)
 8265     (clear-stream $_test-output-buffered-file->buffer)
 8266     (clear-stream _test-error-stream)
 8267     (clear-stream $_test-error-buffered-file->buffer)
 8268     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8269     68/push 0/imm32
 8270     68/push 0/imm32
 8271     89/<- %edx 4/r32/esp
 8272     (tailor-exit-descriptor %edx 0x10)
 8273     #
 8274     (write _test-input-stream "fn foo {\n")
 8275     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 8276     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
 8277     (write _test-input-stream "  x <- compare y, 0\n")
 8278     (write _test-input-stream "}\n")
 8279     # convert
 8280     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8281     # registers except esp clobbered at this point
 8282     # restore ed
 8283     89/<- %edx 4/r32/esp
 8284     (flush _test-output-buffered-file)
 8285     (flush _test-error-buffered-file)
 8286 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 8292     # check output
 8293     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-output: output should be empty")
 8294     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must not have any outputs"  "F - test-compare-with-output: error message")
 8295     # check that stop(1) was called
 8296     (check-ints-equal *(edx+4) 2 "F - test-compare-with-output: exit status")
 8297     # don't restore from ebp
 8298     81 0/subop/add %esp 8/imm32
 8299     # . epilogue
 8300     5d/pop-to-ebp
 8301     c3/return
 8302 
 8303 test-compare-invalid-value-to-address:
 8304     # . prologue
 8305     55/push-ebp
 8306     89/<- %ebp 4/r32/esp
 8307     # setup
 8308     (clear-stream _test-input-stream)
 8309     (clear-stream $_test-input-buffered-file->buffer)
 8310     (clear-stream _test-output-stream)
 8311     (clear-stream $_test-output-buffered-file->buffer)
 8312     (clear-stream _test-error-stream)
 8313     (clear-stream $_test-error-buffered-file->buffer)
 8314     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8315     68/push 0/imm32
 8316     68/push 0/imm32
 8317     89/<- %edx 4/r32/esp
 8318     (tailor-exit-descriptor %edx 0x10)
 8319     #
 8320     (write _test-input-stream "fn foo {\n")
 8321     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 8322     (write _test-input-stream "  var y: (addr int)\n")
 8323     (write _test-input-stream "  compare y, x\n")
 8324     (write _test-input-stream "}\n")
 8325     # convert
 8326     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8327     # registers except esp clobbered at this point
 8328     # restore ed
 8329     89/<- %edx 4/r32/esp
 8330     (flush _test-output-buffered-file)
 8331     (flush _test-error-buffered-file)
 8332 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 8338     # check output
 8339     (check-stream-equal _test-output-stream  ""  "F - test-compare-invalid-value-to-address: output should be empty")
 8340     (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")
 8341     # check that stop(1) was called
 8342     (check-ints-equal *(edx+4) 2 "F - test-compare-invalid-value-to-address: exit status")
 8343     # don't restore from ebp
 8344     81 0/subop/add %esp 8/imm32
 8345     # . epilogue
 8346     5d/pop-to-ebp
 8347     c3/return
 8348 
 8349 test-compare-address:
 8350     # . prologue
 8351     55/push-ebp
 8352     89/<- %ebp 4/r32/esp
 8353     # setup
 8354     (clear-stream _test-input-stream)
 8355     (clear-stream $_test-input-buffered-file->buffer)
 8356     (clear-stream _test-output-stream)
 8357     (clear-stream $_test-output-buffered-file->buffer)
 8358     #
 8359     (write _test-input-stream "fn foo {\n")
 8360     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
 8361     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
 8362     (write _test-input-stream "  compare y, x\n")
 8363     (write _test-input-stream "}\n")
 8364     # convert
 8365     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8366     (flush _test-output-buffered-file)
 8367 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 8373     # not bothering checking output
 8374     (check-next-stream-line-equal _test-error-stream  ""  "F - test-compare-address: error message")
 8375     # . epilogue
 8376     5d/pop-to-ebp
 8377     c3/return
 8378 
 8379 test-compare-deref-address:
 8380     # . prologue
 8381     55/push-ebp
 8382     89/<- %ebp 4/r32/esp
 8383     # setup
 8384     (clear-stream _test-input-stream)
 8385     (clear-stream $_test-input-buffered-file->buffer)
 8386     (clear-stream _test-output-stream)
 8387     (clear-stream $_test-output-buffered-file->buffer)
 8388     #
 8389     (write _test-input-stream "fn foo {\n")
 8390     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
 8391     (write _test-input-stream "  var y/ecx: (addr addr int) <- copy 0\n")
 8392     (write _test-input-stream "  compare *y, x\n")
 8393     (write _test-input-stream "}\n")
 8394     # convert
 8395     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8396     (flush _test-output-buffered-file)
 8397 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 8403     # not bothering checking output
 8404     (check-next-stream-line-equal _test-error-stream  ""  "F - test-compare-deref-address: error message")
 8405     # . epilogue
 8406     5d/pop-to-ebp
 8407     c3/return
 8408 
 8409 test-compare-two-vars-in-memory:
 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: boolean\n")
 8428     (write _test-input-stream "  compare x, x\n")
 8429     (write _test-input-stream "}\n")
 8430     # convert
 8431     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8432     # registers except esp clobbered at this point
 8433     # restore ed
 8434     89/<- %edx 4/r32/esp
 8435     (flush _test-output-buffered-file)
 8436     (flush _test-error-buffered-file)
 8437 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 8443     # check output
 8444     (check-stream-equal _test-output-stream  ""  "F - test-compare-two-vars-in-memory: output should be empty")
 8445     (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")
 8446     # check that stop(1) was called
 8447     (check-ints-equal *(edx+4) 2 "F - test-compare-two-vars-in-memory: exit status")
 8448     # don't restore from ebp
 8449     81 0/subop/add %esp 8/imm32
 8450     # . epilogue
 8451     5d/pop-to-ebp
 8452     c3/return
 8453 
 8454 test-compare-non-scalar:
 8455     # . prologue
 8456     55/push-ebp
 8457     89/<- %ebp 4/r32/esp
 8458     # setup
 8459     (clear-stream _test-input-stream)
 8460     (clear-stream $_test-input-buffered-file->buffer)
 8461     (clear-stream _test-output-stream)
 8462     (clear-stream $_test-output-buffered-file->buffer)
 8463     (clear-stream _test-error-stream)
 8464     (clear-stream $_test-error-buffered-file->buffer)
 8465     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8466     68/push 0/imm32
 8467     68/push 0/imm32
 8468     89/<- %edx 4/r32/esp
 8469     (tailor-exit-descriptor %edx 0x10)
 8470     #
 8471     (write _test-input-stream "fn foo {\n")
 8472     (write _test-input-stream "  var x: (handle int)\n")
 8473     (write _test-input-stream "  var y: int\n")
 8474     (write _test-input-stream "  compare y, x\n")
 8475     (write _test-input-stream "}\n")
 8476     # convert
 8477     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8478     # registers except esp clobbered at this point
 8479     # restore ed
 8480     89/<- %edx 4/r32/esp
 8481     (flush _test-output-buffered-file)
 8482     (flush _test-error-buffered-file)
 8483 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 8489     # check output
 8490     (check-stream-equal _test-output-stream  ""  "F - test-compare-non-scalar: output should be empty")
 8491 #?     (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")
 8492     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compare: both inouts are in memory"  "F - test-compare-non-scalar: error message")
 8493     # check that stop(1) was called
 8494     (check-ints-equal *(edx+4) 2 "F - test-compare-non-scalar: exit status")
 8495     # don't restore from ebp
 8496     81 0/subop/add %esp 8/imm32
 8497     # . epilogue
 8498     5d/pop-to-ebp
 8499     c3/return
 8500 
 8501 test-address-with-no-inout:
 8502     # . prologue
 8503     55/push-ebp
 8504     89/<- %ebp 4/r32/esp
 8505     # setup
 8506     (clear-stream _test-input-stream)
 8507     (clear-stream $_test-input-buffered-file->buffer)
 8508     (clear-stream _test-output-stream)
 8509     (clear-stream $_test-output-buffered-file->buffer)
 8510     (clear-stream _test-error-stream)
 8511     (clear-stream $_test-error-buffered-file->buffer)
 8512     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8513     68/push 0/imm32
 8514     68/push 0/imm32
 8515     89/<- %edx 4/r32/esp
 8516     (tailor-exit-descriptor %edx 0x10)
 8517     #
 8518     (write _test-input-stream "fn foo {\n")
 8519     (write _test-input-stream "  var x/eax: boolean <- address\n")
 8520     (write _test-input-stream "}\n")
 8521     # convert
 8522     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8523     # registers except esp clobbered at this point
 8524     # restore ed
 8525     89/<- %edx 4/r32/esp
 8526     (flush _test-output-buffered-file)
 8527     (flush _test-error-buffered-file)
 8528 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 8534     # check output
 8535     (check-stream-equal _test-output-stream  ""  "F - test-address-with-no-inout: output should be empty")
 8536     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'address' expects an inout"  "F - test-address-with-no-inout: error message")
 8537     # check that stop(1) was called
 8538     (check-ints-equal *(edx+4) 2 "F - test-address-with-no-inout: exit status")
 8539     # don't restore from ebp
 8540     81 0/subop/add %esp 8/imm32
 8541     # . epilogue
 8542     5d/pop-to-ebp
 8543     c3/return
 8544 
 8545 test-address-with-multiple-inouts:
 8546     # . prologue
 8547     55/push-ebp
 8548     89/<- %ebp 4/r32/esp
 8549     # setup
 8550     (clear-stream _test-input-stream)
 8551     (clear-stream $_test-input-buffered-file->buffer)
 8552     (clear-stream _test-output-stream)
 8553     (clear-stream $_test-output-buffered-file->buffer)
 8554     (clear-stream _test-error-stream)
 8555     (clear-stream $_test-error-buffered-file->buffer)
 8556     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8557     68/push 0/imm32
 8558     68/push 0/imm32
 8559     89/<- %edx 4/r32/esp
 8560     (tailor-exit-descriptor %edx 0x10)
 8561     #
 8562     (write _test-input-stream "fn foo {\n")
 8563     (write _test-input-stream "  var x/eax: boolean <- address 0, 0\n")
 8564     (write _test-input-stream "}\n")
 8565     # convert
 8566     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8567     # registers except esp clobbered at this point
 8568     # restore ed
 8569     89/<- %edx 4/r32/esp
 8570     (flush _test-output-buffered-file)
 8571     (flush _test-error-buffered-file)
 8572 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 8578     # check output
 8579     (check-stream-equal _test-output-stream  ""  "F - test-address-with-multiple-inouts: output should be empty")
 8580     (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")
 8581     # check that stop(1) was called
 8582     (check-ints-equal *(edx+4) 2 "F - test-address-with-multiple-inouts: exit status")
 8583     # don't restore from ebp
 8584     81 0/subop/add %esp 8/imm32
 8585     # . epilogue
 8586     5d/pop-to-ebp
 8587     c3/return
 8588 
 8589 test-address-with-no-output:
 8590     # . prologue
 8591     55/push-ebp
 8592     89/<- %ebp 4/r32/esp
 8593     # setup
 8594     (clear-stream _test-input-stream)
 8595     (clear-stream $_test-input-buffered-file->buffer)
 8596     (clear-stream _test-output-stream)
 8597     (clear-stream $_test-output-buffered-file->buffer)
 8598     (clear-stream _test-error-stream)
 8599     (clear-stream $_test-error-buffered-file->buffer)
 8600     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8601     68/push 0/imm32
 8602     68/push 0/imm32
 8603     89/<- %edx 4/r32/esp
 8604     (tailor-exit-descriptor %edx 0x10)
 8605     #
 8606     (write _test-input-stream "fn foo {\n")
 8607     (write _test-input-stream "  address 0\n")
 8608     (write _test-input-stream "}\n")
 8609     # convert
 8610     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8611     # registers except esp clobbered at this point
 8612     # restore ed
 8613     89/<- %edx 4/r32/esp
 8614     (flush _test-output-buffered-file)
 8615     (flush _test-error-buffered-file)
 8616 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 8622     # check output
 8623     (check-stream-equal _test-output-stream  ""  "F - test-address-with-no-output: output should be empty")
 8624     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'address' expects an output"  "F - test-address-with-no-output: error message")
 8625     # check that stop(1) was called
 8626     (check-ints-equal *(edx+4) 2 "F - test-address-with-no-output: exit status")
 8627     # don't restore from ebp
 8628     81 0/subop/add %esp 8/imm32
 8629     # . epilogue
 8630     5d/pop-to-ebp
 8631     c3/return
 8632 
 8633 test-address-with-multiple-outputs:
 8634     # . prologue
 8635     55/push-ebp
 8636     89/<- %ebp 4/r32/esp
 8637     # setup
 8638     (clear-stream _test-input-stream)
 8639     (clear-stream $_test-input-buffered-file->buffer)
 8640     (clear-stream _test-output-stream)
 8641     (clear-stream $_test-output-buffered-file->buffer)
 8642     (clear-stream _test-error-stream)
 8643     (clear-stream $_test-error-buffered-file->buffer)
 8644     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8645     68/push 0/imm32
 8646     68/push 0/imm32
 8647     89/<- %edx 4/r32/esp
 8648     (tailor-exit-descriptor %edx 0x10)
 8649     #
 8650     (write _test-input-stream "fn foo {\n")
 8651     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 8652     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
 8653     (write _test-input-stream "  x, y <- address 0\n")
 8654     (write _test-input-stream "}\n")
 8655     # convert
 8656     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8657     # registers except esp clobbered at this point
 8658     # restore ed
 8659     89/<- %edx 4/r32/esp
 8660     (flush _test-output-buffered-file)
 8661     (flush _test-error-buffered-file)
 8662 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 8668     # check output
 8669     (check-stream-equal _test-output-stream  ""  "F - test-address-with-multiple-outputs: output should be empty")
 8670     (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")
 8671     # check that stop(1) was called
 8672     (check-ints-equal *(edx+4) 2 "F - test-address-with-multiple-outputs: exit status")
 8673     # don't restore from ebp
 8674     81 0/subop/add %esp 8/imm32
 8675     # . epilogue
 8676     5d/pop-to-ebp
 8677     c3/return
 8678 
 8679 # silly but it works
 8680 test-address-of-deref:
 8681     # . prologue
 8682     55/push-ebp
 8683     89/<- %ebp 4/r32/esp
 8684     # setup
 8685     (clear-stream _test-input-stream)
 8686     (clear-stream $_test-input-buffered-file->buffer)
 8687     (clear-stream _test-output-stream)
 8688     (clear-stream $_test-output-buffered-file->buffer)
 8689     #
 8690     (write _test-input-stream "fn foo {\n")
 8691     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
 8692     (write _test-input-stream "  var y/ecx: (addr int) <- address *x\n")
 8693     (write _test-input-stream "}\n")
 8694     # convert
 8695     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8696     (flush _test-output-buffered-file)
 8697 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 8703     # not bothering checking output
 8704     (check-next-stream-line-equal _test-error-stream  ""  "F - test-address-of-deref: error message")
 8705     # . epilogue
 8706     5d/pop-to-ebp
 8707     c3/return
 8708 
 8709 test-address-to-non-register:
 8710     # . prologue
 8711     55/push-ebp
 8712     89/<- %ebp 4/r32/esp
 8713     # setup
 8714     (clear-stream _test-input-stream)
 8715     (clear-stream $_test-input-buffered-file->buffer)
 8716     (clear-stream _test-output-stream)
 8717     (clear-stream $_test-output-buffered-file->buffer)
 8718     (clear-stream _test-error-stream)
 8719     (clear-stream $_test-error-buffered-file->buffer)
 8720     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8721     68/push 0/imm32
 8722     68/push 0/imm32
 8723     89/<- %edx 4/r32/esp
 8724     (tailor-exit-descriptor %edx 0x10)
 8725     #
 8726     (write _test-input-stream "fn foo {\n")
 8727     (write _test-input-stream "  var x: (addr int)\n")
 8728     (write _test-input-stream "  x <- address 0\n")
 8729     (write _test-input-stream "}\n")
 8730     # convert
 8731     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8732     # registers except esp clobbered at this point
 8733     # restore ed
 8734     89/<- %edx 4/r32/esp
 8735     (flush _test-output-buffered-file)
 8736     (flush _test-error-buffered-file)
 8737 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 8743     # check output
 8744     (check-stream-equal _test-output-stream  ""  "F - test-address-to-non-register: output should be empty")
 8745     (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")
 8746     # check that stop(1) was called
 8747     (check-ints-equal *(edx+4) 2 "F - test-address-to-non-register: exit status")
 8748     # don't restore from ebp
 8749     81 0/subop/add %esp 8/imm32
 8750     # . epilogue
 8751     5d/pop-to-ebp
 8752     c3/return
 8753 
 8754 test-address-with-wrong-type:
 8755     # . prologue
 8756     55/push-ebp
 8757     89/<- %ebp 4/r32/esp
 8758     # setup
 8759     (clear-stream _test-input-stream)
 8760     (clear-stream $_test-input-buffered-file->buffer)
 8761     (clear-stream _test-output-stream)
 8762     (clear-stream $_test-output-buffered-file->buffer)
 8763     (clear-stream _test-error-stream)
 8764     (clear-stream $_test-error-buffered-file->buffer)
 8765     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8766     68/push 0/imm32
 8767     68/push 0/imm32
 8768     89/<- %edx 4/r32/esp
 8769     (tailor-exit-descriptor %edx 0x10)
 8770     #
 8771     (write _test-input-stream "fn foo {\n")
 8772     (write _test-input-stream "  var x: int\n")
 8773     (write _test-input-stream "  var y/eax: (addr boolean) <- address x\n")
 8774     (write _test-input-stream "}\n")
 8775     # convert
 8776     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8777     # registers except esp clobbered at this point
 8778     # restore ed
 8779     89/<- %edx 4/r32/esp
 8780     (flush _test-output-buffered-file)
 8781     (flush _test-error-buffered-file)
 8782 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 8788     # check output
 8789     (check-stream-equal _test-output-stream  ""  "F - test-address-with-wrong-type: output should be empty")
 8790     (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")
 8791     # check that stop(1) was called
 8792     (check-ints-equal *(edx+4) 2 "F - test-address-with-wrong-type: exit status")
 8793     # don't restore from ebp
 8794     81 0/subop/add %esp 8/imm32
 8795     # . epilogue
 8796     5d/pop-to-ebp
 8797     c3/return
 8798 
 8799 test-address-with-right-type-for-array:
 8800     # . prologue
 8801     55/push-ebp
 8802     89/<- %ebp 4/r32/esp
 8803     # setup
 8804     (clear-stream _test-input-stream)
 8805     (clear-stream $_test-input-buffered-file->buffer)
 8806     (clear-stream _test-output-stream)
 8807     (clear-stream $_test-output-buffered-file->buffer)
 8808     #
 8809     (write _test-input-stream "fn foo {\n")
 8810     (write _test-input-stream "  var x: (array int 3)\n")
 8811     (write _test-input-stream "  var y/eax: (addr array int) <- address x\n")
 8812     (write _test-input-stream "}\n")
 8813     # convert
 8814     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8815     (flush _test-output-buffered-file)
 8816 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 8822     # no error
 8823     (check-next-stream-line-equal _test-error-stream  ""  "F - test-address-with-right-type-for-array: error message")
 8824     # don't bother checking output
 8825     # . epilogue
 8826     89/<- %esp 5/r32/ebp
 8827     5d/pop-to-ebp
 8828     c3/return
 8829 
 8830 test-address-with-right-type-for-stream:
 8831     # . prologue
 8832     55/push-ebp
 8833     89/<- %ebp 4/r32/esp
 8834     # setup
 8835     (clear-stream _test-input-stream)
 8836     (clear-stream $_test-input-buffered-file->buffer)
 8837     (clear-stream _test-output-stream)
 8838     (clear-stream $_test-output-buffered-file->buffer)
 8839     #
 8840     (write _test-input-stream "fn foo {\n")
 8841     (write _test-input-stream "  var x: (stream int 3)\n")
 8842     (write _test-input-stream "  var y/eax: (addr stream int) <- address x\n")
 8843     (write _test-input-stream "}\n")
 8844     # convert
 8845     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8846     (flush _test-output-buffered-file)
 8847 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 8853     # no error
 8854     (check-next-stream-line-equal _test-error-stream  ""  "F - test-address-with-right-type-for-stream: error message")
 8855     # don't bother checking output
 8856     # . epilogue
 8857     89/<- %esp 5/r32/ebp
 8858     5d/pop-to-ebp
 8859     c3/return
 8860 
 8861 test-get-with-wrong-field:
 8862     # . prologue
 8863     55/push-ebp
 8864     89/<- %ebp 4/r32/esp
 8865     # setup
 8866     (clear-stream _test-input-stream)
 8867     (clear-stream $_test-input-buffered-file->buffer)
 8868     (clear-stream _test-output-stream)
 8869     (clear-stream $_test-output-buffered-file->buffer)
 8870     (clear-stream _test-error-stream)
 8871     (clear-stream $_test-error-buffered-file->buffer)
 8872     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8873     68/push 0/imm32
 8874     68/push 0/imm32
 8875     89/<- %edx 4/r32/esp
 8876     (tailor-exit-descriptor %edx 0x10)
 8877     #
 8878     (write _test-input-stream "fn foo {\n")
 8879     (write _test-input-stream "  var a: t\n")
 8880     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 8881     (write _test-input-stream "}\n")
 8882     (write _test-input-stream "type t {\n")
 8883     (write _test-input-stream "  x: int\n")
 8884     (write _test-input-stream "}\n")
 8885     # convert
 8886     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8887     # registers except esp clobbered at this point
 8888     # restore ed
 8889     89/<- %edx 4/r32/esp
 8890     (flush _test-output-buffered-file)
 8891     (flush _test-error-buffered-file)
 8892 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 8898     # check output
 8899     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-field: output should be empty")
 8900     (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")
 8901     # check that stop(1) was called
 8902     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-field: exit status")
 8903     # don't restore from ebp
 8904     81 0/subop/add %esp 8/imm32
 8905     # . epilogue
 8906     5d/pop-to-ebp
 8907     c3/return
 8908 
 8909 test-get-with-wrong-base-type:
 8910     # . prologue
 8911     55/push-ebp
 8912     89/<- %ebp 4/r32/esp
 8913     # setup
 8914     (clear-stream _test-input-stream)
 8915     (clear-stream $_test-input-buffered-file->buffer)
 8916     (clear-stream _test-output-stream)
 8917     (clear-stream $_test-output-buffered-file->buffer)
 8918     (clear-stream _test-error-stream)
 8919     (clear-stream $_test-error-buffered-file->buffer)
 8920     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8921     68/push 0/imm32
 8922     68/push 0/imm32
 8923     89/<- %edx 4/r32/esp
 8924     (tailor-exit-descriptor %edx 0x10)
 8925     #
 8926     (write _test-input-stream "fn foo {\n")
 8927     (write _test-input-stream "  var a: int\n")
 8928     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 8929     (write _test-input-stream "}\n")
 8930     # convert
 8931     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8932     # registers except esp clobbered at this point
 8933     # restore ed
 8934     89/<- %edx 4/r32/esp
 8935     (flush _test-output-buffered-file)
 8936     (flush _test-error-buffered-file)
 8937 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 8943     # check output
 8944     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type: output should be empty")
 8945     (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")
 8946     # check that stop(1) was called
 8947     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type: exit status")
 8948     # don't restore from ebp
 8949     81 0/subop/add %esp 8/imm32
 8950     # . epilogue
 8951     5d/pop-to-ebp
 8952     c3/return
 8953 
 8954 test-get-with-wrong-base-type-2:
 8955     # . prologue
 8956     55/push-ebp
 8957     89/<- %ebp 4/r32/esp
 8958     # setup
 8959     (clear-stream _test-input-stream)
 8960     (clear-stream $_test-input-buffered-file->buffer)
 8961     (clear-stream _test-output-stream)
 8962     (clear-stream $_test-output-buffered-file->buffer)
 8963     (clear-stream _test-error-stream)
 8964     (clear-stream $_test-error-buffered-file->buffer)
 8965     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8966     68/push 0/imm32
 8967     68/push 0/imm32
 8968     89/<- %edx 4/r32/esp
 8969     (tailor-exit-descriptor %edx 0x10)
 8970     #
 8971     (write _test-input-stream "fn foo {\n")
 8972     (write _test-input-stream "  var a: (addr t)\n")
 8973     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 8974     (write _test-input-stream "}\n")
 8975     (write _test-input-stream "type t {\n")
 8976     (write _test-input-stream "  x: int\n")
 8977     (write _test-input-stream "}\n")
 8978     # convert
 8979     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8980     # registers except esp clobbered at this point
 8981     # restore ed
 8982     89/<- %edx 4/r32/esp
 8983     (flush _test-output-buffered-file)
 8984     (flush _test-error-buffered-file)
 8985 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 8991     # check output
 8992     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type-2: output should be empty")
 8993     (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")
 8994     # check that stop(1) was called
 8995     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type-2: exit status")
 8996     # don't restore from ebp
 8997     81 0/subop/add %esp 8/imm32
 8998     # . epilogue
 8999     5d/pop-to-ebp
 9000     c3/return
 9001 
 9002 test-get-with-wrong-base-type-3:
 9003     # . prologue
 9004     55/push-ebp
 9005     89/<- %ebp 4/r32/esp
 9006     # setup
 9007     (clear-stream _test-input-stream)
 9008     (clear-stream $_test-input-buffered-file->buffer)
 9009     (clear-stream _test-output-stream)
 9010     (clear-stream $_test-output-buffered-file->buffer)
 9011     (clear-stream _test-error-stream)
 9012     (clear-stream $_test-error-buffered-file->buffer)
 9013     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9014     68/push 0/imm32
 9015     68/push 0/imm32
 9016     89/<- %edx 4/r32/esp
 9017     (tailor-exit-descriptor %edx 0x10)
 9018     #
 9019     (write _test-input-stream "fn foo {\n")
 9020     (write _test-input-stream "  var a: (handle int)\n")
 9021     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 9022     (write _test-input-stream "}\n")
 9023     # convert
 9024     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9025     # registers except esp clobbered at this point
 9026     # restore ed
 9027     89/<- %edx 4/r32/esp
 9028     (flush _test-output-buffered-file)
 9029     (flush _test-error-buffered-file)
 9030 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 9036     # check output
 9037     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type-3: output should be empty")
 9038     (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")
 9039     # check that stop(1) was called
 9040     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type-3: exit status")
 9041     # don't restore from ebp
 9042     81 0/subop/add %esp 8/imm32
 9043     # . epilogue
 9044     5d/pop-to-ebp
 9045     c3/return
 9046 
 9047 test-get-with-wrong-offset-type:
 9048     # . prologue
 9049     55/push-ebp
 9050     89/<- %ebp 4/r32/esp
 9051     # setup
 9052     (clear-stream _test-input-stream)
 9053     (clear-stream $_test-input-buffered-file->buffer)
 9054     (clear-stream _test-output-stream)
 9055     (clear-stream $_test-output-buffered-file->buffer)
 9056     (clear-stream _test-error-stream)
 9057     (clear-stream $_test-error-buffered-file->buffer)
 9058     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9059     68/push 0/imm32
 9060     68/push 0/imm32
 9061     89/<- %edx 4/r32/esp
 9062     (tailor-exit-descriptor %edx 0x10)
 9063     #
 9064     (write _test-input-stream "fn foo {\n")
 9065     (write _test-input-stream "  var a: t\n")
 9066     (write _test-input-stream "  var b: int\n")
 9067     (write _test-input-stream "  var c/ecx: (addr int) <- get a, b\n")
 9068     (write _test-input-stream "}\n")
 9069     (write _test-input-stream "type t {\n")
 9070     (write _test-input-stream "  x: int\n")
 9071     (write _test-input-stream "}\n")
 9072     # convert
 9073     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9074     # registers except esp clobbered at this point
 9075     # restore ed
 9076     89/<- %edx 4/r32/esp
 9077     (flush _test-output-buffered-file)
 9078     (flush _test-error-buffered-file)
 9079 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 9085     # check output
 9086     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-offset-type: output should be empty")
 9087     (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")
 9088     # check that stop(1) was called
 9089     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-offset-type: exit status")
 9090     # don't restore from ebp
 9091     81 0/subop/add %esp 8/imm32
 9092     # . epilogue
 9093     5d/pop-to-ebp
 9094     c3/return
 9095 
 9096 test-get-with-wrong-output-type:
 9097     # . prologue
 9098     55/push-ebp
 9099     89/<- %ebp 4/r32/esp
 9100     # setup
 9101     (clear-stream _test-input-stream)
 9102     (clear-stream $_test-input-buffered-file->buffer)
 9103     (clear-stream _test-output-stream)
 9104     (clear-stream $_test-output-buffered-file->buffer)
 9105     (clear-stream _test-error-stream)
 9106     (clear-stream $_test-error-buffered-file->buffer)
 9107     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9108     68/push 0/imm32
 9109     68/push 0/imm32
 9110     89/<- %edx 4/r32/esp
 9111     (tailor-exit-descriptor %edx 0x10)
 9112     #
 9113     (write _test-input-stream "fn foo {\n")
 9114     (write _test-input-stream "  var a: t\n")
 9115     (write _test-input-stream "  var c: (addr int)\n")
 9116     (write _test-input-stream "  c <- get a, x\n")
 9117     (write _test-input-stream "}\n")
 9118     (write _test-input-stream "type t {\n")
 9119     (write _test-input-stream "  x: int\n")
 9120     (write _test-input-stream "}\n")
 9121     # convert
 9122     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9123     # registers except esp clobbered at this point
 9124     # restore ed
 9125     89/<- %edx 4/r32/esp
 9126     (flush _test-output-buffered-file)
 9127     (flush _test-error-buffered-file)
 9128 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 9134     # check output
 9135     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type: output should be empty")
 9136     (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")
 9137     # check that stop(1) was called
 9138     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type: exit status")
 9139     # don't restore from ebp
 9140     81 0/subop/add %esp 8/imm32
 9141     # . epilogue
 9142     5d/pop-to-ebp
 9143     c3/return
 9144 
 9145 test-get-with-wrong-output-type-2:
 9146     # . prologue
 9147     55/push-ebp
 9148     89/<- %ebp 4/r32/esp
 9149     # setup
 9150     (clear-stream _test-input-stream)
 9151     (clear-stream $_test-input-buffered-file->buffer)
 9152     (clear-stream _test-output-stream)
 9153     (clear-stream $_test-output-buffered-file->buffer)
 9154     (clear-stream _test-error-stream)
 9155     (clear-stream $_test-error-buffered-file->buffer)
 9156     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9157     68/push 0/imm32
 9158     68/push 0/imm32
 9159     89/<- %edx 4/r32/esp
 9160     (tailor-exit-descriptor %edx 0x10)
 9161     #
 9162     (write _test-input-stream "fn foo {\n")
 9163     (write _test-input-stream "  var a: t\n")
 9164     (write _test-input-stream "  var c/ecx: int <- get a, x\n")
 9165     (write _test-input-stream "}\n")
 9166     (write _test-input-stream "type t {\n")
 9167     (write _test-input-stream "  x: int\n")
 9168     (write _test-input-stream "}\n")
 9169     # convert
 9170     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9171     # registers except esp clobbered at this point
 9172     # restore ed
 9173     89/<- %edx 4/r32/esp
 9174     (flush _test-output-buffered-file)
 9175     (flush _test-error-buffered-file)
 9176 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 9182     # check output
 9183     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-2: output should be empty")
 9184     (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")
 9185     # check that stop(1) was called
 9186     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-2: exit status")
 9187     # don't restore from ebp
 9188     81 0/subop/add %esp 8/imm32
 9189     # . epilogue
 9190     5d/pop-to-ebp
 9191     c3/return
 9192 
 9193 test-get-with-wrong-output-type-3:
 9194     # . prologue
 9195     55/push-ebp
 9196     89/<- %ebp 4/r32/esp
 9197     # setup
 9198     (clear-stream _test-input-stream)
 9199     (clear-stream $_test-input-buffered-file->buffer)
 9200     (clear-stream _test-output-stream)
 9201     (clear-stream $_test-output-buffered-file->buffer)
 9202     (clear-stream _test-error-stream)
 9203     (clear-stream $_test-error-buffered-file->buffer)
 9204     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9205     68/push 0/imm32
 9206     68/push 0/imm32
 9207     89/<- %edx 4/r32/esp
 9208     (tailor-exit-descriptor %edx 0x10)
 9209     #
 9210     (write _test-input-stream "fn foo {\n")
 9211     (write _test-input-stream "  var a: t\n")
 9212     (write _test-input-stream "  var c/ecx: (array int) <- get a, x\n")
 9213     (write _test-input-stream "}\n")
 9214     (write _test-input-stream "type t {\n")
 9215     (write _test-input-stream "  x: int\n")
 9216     (write _test-input-stream "}\n")
 9217     # convert
 9218     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9219     # registers except esp clobbered at this point
 9220     # restore ed
 9221     89/<- %edx 4/r32/esp
 9222     (flush _test-output-buffered-file)
 9223     (flush _test-error-buffered-file)
 9224 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 9230     # check output
 9231     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-3: output should be empty")
 9232     (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")
 9233     # check that stop(1) was called
 9234     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-3: exit status")
 9235     # don't restore from ebp
 9236     81 0/subop/add %esp 8/imm32
 9237     # . epilogue
 9238     5d/pop-to-ebp
 9239     c3/return
 9240 
 9241 test-get-with-wrong-output-type-4:
 9242     # . prologue
 9243     55/push-ebp
 9244     89/<- %ebp 4/r32/esp
 9245     # setup
 9246     (clear-stream _test-input-stream)
 9247     (clear-stream $_test-input-buffered-file->buffer)
 9248     (clear-stream _test-output-stream)
 9249     (clear-stream $_test-output-buffered-file->buffer)
 9250     (clear-stream _test-error-stream)
 9251     (clear-stream $_test-error-buffered-file->buffer)
 9252     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9253     68/push 0/imm32
 9254     68/push 0/imm32
 9255     89/<- %edx 4/r32/esp
 9256     (tailor-exit-descriptor %edx 0x10)
 9257     #
 9258     (write _test-input-stream "fn foo {\n")
 9259     (write _test-input-stream "  var a: t\n")
 9260     (write _test-input-stream "  var c/ecx: (addr boolean) <- get a, x\n")
 9261     (write _test-input-stream "}\n")
 9262     (write _test-input-stream "type t {\n")
 9263     (write _test-input-stream "  x: int\n")
 9264     (write _test-input-stream "}\n")
 9265     # convert
 9266     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9267     # registers except esp clobbered at this point
 9268     # restore ed
 9269     89/<- %edx 4/r32/esp
 9270     (flush _test-output-buffered-file)
 9271     (flush _test-error-buffered-file)
 9272 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 9278     # check output
 9279     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-4: output should be empty")
 9280     (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")
 9281     # check that stop(1) was called
 9282     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-4: exit status")
 9283     # don't restore from ebp
 9284     81 0/subop/add %esp 8/imm32
 9285     # . epilogue
 9286     5d/pop-to-ebp
 9287     c3/return
 9288 
 9289 test-get-with-wrong-output-type-5:
 9290     # . prologue
 9291     55/push-ebp
 9292     89/<- %ebp 4/r32/esp
 9293     # setup
 9294     (clear-stream _test-input-stream)
 9295     (clear-stream $_test-input-buffered-file->buffer)
 9296     (clear-stream _test-output-stream)
 9297     (clear-stream $_test-output-buffered-file->buffer)
 9298     #
 9299     (write _test-input-stream "fn foo {\n")
 9300     (write _test-input-stream "  var a: t\n")
 9301     (write _test-input-stream "  var c/ecx: (addr handle int) <- get a, x\n")
 9302     (write _test-input-stream "}\n")
 9303     (write _test-input-stream "type t {\n")
 9304     (write _test-input-stream "  x: (handle int)\n")
 9305     (write _test-input-stream "}\n")
 9306     # convert
 9307     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9308     (flush _test-output-buffered-file)
 9309     # no errors
 9310     # . epilogue
 9311     89/<- %esp 5/r32/ebp
 9312     5d/pop-to-ebp
 9313     c3/return
 9314 
 9315 test-get-with-too-few-inouts:
 9316     # . prologue
 9317     55/push-ebp
 9318     89/<- %ebp 4/r32/esp
 9319     # setup
 9320     (clear-stream _test-input-stream)
 9321     (clear-stream $_test-input-buffered-file->buffer)
 9322     (clear-stream _test-output-stream)
 9323     (clear-stream $_test-output-buffered-file->buffer)
 9324     (clear-stream _test-error-stream)
 9325     (clear-stream $_test-error-buffered-file->buffer)
 9326     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9327     68/push 0/imm32
 9328     68/push 0/imm32
 9329     89/<- %edx 4/r32/esp
 9330     (tailor-exit-descriptor %edx 0x10)
 9331     #
 9332     (write _test-input-stream "fn foo {\n")
 9333     (write _test-input-stream "  var a: t\n")
 9334     (write _test-input-stream "  var c/ecx: (addr int) <- get a\n")
 9335     (write _test-input-stream "}\n")
 9336     (write _test-input-stream "type t {\n")
 9337     (write _test-input-stream "  x: int\n")
 9338     (write _test-input-stream "}\n")
 9339     # convert
 9340     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9341     # registers except esp clobbered at this point
 9342     # restore ed
 9343     89/<- %edx 4/r32/esp
 9344     (flush _test-output-buffered-file)
 9345     (flush _test-error-buffered-file)
 9346 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 9352     # check output
 9353     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-few-inouts: output should be empty")
 9354     (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")
 9355     # check that stop(1) was called
 9356     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-few-inouts: exit status")
 9357     # don't restore from ebp
 9358     81 0/subop/add %esp 8/imm32
 9359     # . epilogue
 9360     5d/pop-to-ebp
 9361     c3/return
 9362 
 9363 test-get-with-too-many-inouts:
 9364     # . prologue
 9365     55/push-ebp
 9366     89/<- %ebp 4/r32/esp
 9367     # setup
 9368     (clear-stream _test-input-stream)
 9369     (clear-stream $_test-input-buffered-file->buffer)
 9370     (clear-stream _test-output-stream)
 9371     (clear-stream $_test-output-buffered-file->buffer)
 9372     (clear-stream _test-error-stream)
 9373     (clear-stream $_test-error-buffered-file->buffer)
 9374     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9375     68/push 0/imm32
 9376     68/push 0/imm32
 9377     89/<- %edx 4/r32/esp
 9378     (tailor-exit-descriptor %edx 0x10)
 9379     #
 9380     (write _test-input-stream "fn foo {\n")
 9381     (write _test-input-stream "  var a: t\n")
 9382     (write _test-input-stream "  var c/ecx: (addr int) <- get a, x, 0\n")
 9383     (write _test-input-stream "}\n")
 9384     (write _test-input-stream "type t {\n")
 9385     (write _test-input-stream "  x: int\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-get-with-too-many-inouts: output should be empty")
 9402     (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")
 9403     # check that stop(1) was called
 9404     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-many-inouts: 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-get-with-no-output:
 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 a: t\n")
 9430     (write _test-input-stream "  get a, x\n")
 9431     (write _test-input-stream "}\n")
 9432     (write _test-input-stream "type t {\n")
 9433     (write _test-input-stream "  x: int\n")
 9434     (write _test-input-stream "}\n")
 9435     # convert
 9436     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9437     # registers except esp clobbered at this point
 9438     # restore ed
 9439     89/<- %edx 4/r32/esp
 9440     (flush _test-output-buffered-file)
 9441     (flush _test-error-buffered-file)
 9442 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 9448     # check output
 9449     (check-stream-equal _test-output-stream  ""  "F - test-get-with-no-output: output should be empty")
 9450     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: must have an output"  "F - test-get-with-no-output: error message")
 9451     # check that stop(1) was called
 9452     (check-ints-equal *(edx+4) 2 "F - test-get-with-no-output: exit status")
 9453     # don't restore from ebp
 9454     81 0/subop/add %esp 8/imm32
 9455     # . epilogue
 9456     5d/pop-to-ebp
 9457     c3/return
 9458 
 9459 test-get-with-too-many-outputs:
 9460     # . prologue
 9461     55/push-ebp
 9462     89/<- %ebp 4/r32/esp
 9463     # setup
 9464     (clear-stream _test-input-stream)
 9465     (clear-stream $_test-input-buffered-file->buffer)
 9466     (clear-stream _test-output-stream)
 9467     (clear-stream $_test-output-buffered-file->buffer)
 9468     (clear-stream _test-error-stream)
 9469     (clear-stream $_test-error-buffered-file->buffer)
 9470     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9471     68/push 0/imm32
 9472     68/push 0/imm32
 9473     89/<- %edx 4/r32/esp
 9474     (tailor-exit-descriptor %edx 0x10)
 9475     #
 9476     (write _test-input-stream "fn foo {\n")
 9477     (write _test-input-stream "  var a: t\n")
 9478     (write _test-input-stream "  var b: int\n")
 9479     (write _test-input-stream "  var c/eax: (addr int) <- copy 0\n")
 9480     (write _test-input-stream "  c, b <- get a, x\n")
 9481     (write _test-input-stream "}\n")
 9482     (write _test-input-stream "type t {\n")
 9483     (write _test-input-stream "  x: int\n")
 9484     (write _test-input-stream "}\n")
 9485     # convert
 9486     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9487     # registers except esp clobbered at this point
 9488     # restore ed
 9489     89/<- %edx 4/r32/esp
 9490     (flush _test-output-buffered-file)
 9491     (flush _test-error-buffered-file)
 9492 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 9498     # check output
 9499     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-many-outputs: output should be empty")
 9500     (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")
 9501     # check that stop(1) was called
 9502     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-many-outputs: exit status")
 9503     # don't restore from ebp
 9504     81 0/subop/add %esp 8/imm32
 9505     # . epilogue
 9506     5d/pop-to-ebp
 9507     c3/return
 9508 
 9509 test-convert-array-of-user-defined-types:
 9510     # . prologue
 9511     55/push-ebp
 9512     89/<- %ebp 4/r32/esp
 9513     # setup
 9514     (clear-stream _test-input-stream)
 9515     (clear-stream $_test-input-buffered-file->buffer)
 9516     (clear-stream _test-output-stream)
 9517     (clear-stream $_test-output-buffered-file->buffer)
 9518     #
 9519     (write _test-input-stream "type t {\n")  # each t is 8 bytes, which is a power of 2
 9520     (write _test-input-stream "  x: int\n")
 9521     (write _test-input-stream "  y: int\n")
 9522     (write _test-input-stream "}\n")
 9523     (write _test-input-stream "fn foo {\n")
 9524     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
 9525     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 9526     (write _test-input-stream "  var x/eax: (addr t) <- index arr, idx\n")
 9527     (write _test-input-stream "}\n")
 9528     # convert
 9529     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9530     (flush _test-output-buffered-file)
 9531 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 9537     # check output
 9538     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-array-of-user-defined-types/0")
 9539     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-array-of-user-defined-types/1")
 9540     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-array-of-user-defined-types/2")
 9541     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-array-of-user-defined-types/3")
 9542     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-array-of-user-defined-types/4")
 9543     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-array-of-user-defined-types/5")
 9544     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-array-of-user-defined-types/6")
 9545     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-array-of-user-defined-types/7")
 9546     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-array-of-user-defined-types/8")
 9547     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-array-of-user-defined-types/9")
 9548     (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")
 9549     (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")
 9550     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-array-of-user-defined-types/12")
 9551     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-array-of-user-defined-types/13")
 9552     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-array-of-user-defined-types/14")
 9553     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-array-of-user-defined-types/15")
 9554     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-array-of-user-defined-types/16")
 9555     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-array-of-user-defined-types/17")
 9556     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-array-of-user-defined-types/18")
 9557     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-array-of-user-defined-types/19")
 9558     # . epilogue
 9559     89/<- %esp 5/r32/ebp
 9560     5d/pop-to-ebp
 9561     c3/return
 9562 
 9563 test-convert-length-of-array-of-user-defined-types-to-eax:
 9564     # . prologue
 9565     55/push-ebp
 9566     89/<- %ebp 4/r32/esp
 9567     # setup
 9568     (clear-stream _test-input-stream)
 9569     (clear-stream $_test-input-buffered-file->buffer)
 9570     (clear-stream _test-output-stream)
 9571     (clear-stream $_test-output-buffered-file->buffer)
 9572     #
 9573     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
 9574     (write _test-input-stream "  x: int\n")
 9575     (write _test-input-stream "  y: int\n")
 9576     (write _test-input-stream "  z: int\n")
 9577     (write _test-input-stream "}\n")
 9578     (write _test-input-stream "fn foo {\n")
 9579     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
 9580     (write _test-input-stream "  var x/eax: int <- length arr\n")
 9581     (write _test-input-stream "}\n")
 9582     # convert
 9583     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9584     (flush _test-output-buffered-file)
 9585 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 9591     # check output
 9592     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-eax/0")
 9593     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-eax/1")
 9594     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-eax/2")
 9595     (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")
 9596     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-eax/4")
 9597     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-eax/5")
 9598     # var arr
 9599     (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")
 9600     (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")
 9601     # length instruction
 9602     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types-to-eax/8")
 9603     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types-to-eax/9")
 9604     (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")
 9605     (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")
 9606     (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")
 9607     (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")
 9608     (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")
 9609     (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")
 9610     # reclaim arr
 9611     (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")
 9612     #
 9613     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-eax/17")
 9614     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/18")
 9615     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-eax/19")
 9616     (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")
 9617     (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")
 9618     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-eax/22")
 9619     # . epilogue
 9620     89/<- %esp 5/r32/ebp
 9621     5d/pop-to-ebp
 9622     c3/return
 9623 
 9624 test-convert-length-of-array-of-user-defined-types-to-ecx:
 9625     # . prologue
 9626     55/push-ebp
 9627     89/<- %ebp 4/r32/esp
 9628     # setup
 9629     (clear-stream _test-input-stream)
 9630     (clear-stream $_test-input-buffered-file->buffer)
 9631     (clear-stream _test-output-stream)
 9632     (clear-stream $_test-output-buffered-file->buffer)
 9633     #
 9634     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
 9635     (write _test-input-stream "  x: int\n")
 9636     (write _test-input-stream "  y: int\n")
 9637     (write _test-input-stream "  z: int\n")
 9638     (write _test-input-stream "}\n")
 9639     (write _test-input-stream "fn foo {\n")
 9640     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
 9641     (write _test-input-stream "  var x/ecx: int <- length arr\n")
 9642     (write _test-input-stream "}\n")
 9643     # convert
 9644     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9645     (flush _test-output-buffered-file)
 9646 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 9652     # check output
 9653     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-ecx/0")
 9654     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-ecx/1")
 9655     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-ecx/2")
 9656     (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")
 9657     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-ecx/4")
 9658     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-ecx/5")
 9659     # var a
 9660     (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")
 9661     (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")
 9662     # var x
 9663     (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")
 9664     # length instruction
 9665     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types-to-ecx/9")
 9666     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types-to-ecx/10")
 9667     (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")
 9668     (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")
 9669     (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")
 9670     (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")
 9671     (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")
 9672     (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")
 9673     (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")
 9674     # reclaim x
 9675     (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")
 9676     # reclaim a
 9677     (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")
 9678     #
 9679     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-ecx/20")
 9680     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/21")
 9681     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-ecx/22")
 9682     (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")
 9683     (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")
 9684     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-ecx/25")
 9685     # . epilogue
 9686     89/<- %esp 5/r32/ebp
 9687     5d/pop-to-ebp
 9688     c3/return
 9689 
 9690 test-convert-length-of-array-of-user-defined-types-to-edx:
 9691     # . prologue
 9692     55/push-ebp
 9693     89/<- %ebp 4/r32/esp
 9694     # setup
 9695     (clear-stream _test-input-stream)
 9696     (clear-stream $_test-input-buffered-file->buffer)
 9697     (clear-stream _test-output-stream)
 9698     (clear-stream $_test-output-buffered-file->buffer)
 9699     #
 9700     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
 9701     (write _test-input-stream "  x: int\n")
 9702     (write _test-input-stream "  y: int\n")
 9703     (write _test-input-stream "  z: int\n")
 9704     (write _test-input-stream "}\n")
 9705     (write _test-input-stream "fn foo {\n")
 9706     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
 9707     (write _test-input-stream "  var x/edx: int <- length arr\n")
 9708     (write _test-input-stream "}\n")
 9709     # convert
 9710     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9711     (flush _test-output-buffered-file)
 9712 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 9718     # check output
 9719     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-edx/0")
 9720     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-edx/1")
 9721     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-edx/2")
 9722     (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")
 9723     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-edx/4")
 9724     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-edx/5")
 9725     # var a
 9726     (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")
 9727     (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")
 9728     # var x
 9729     (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")
 9730     # length instruction
 9731     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types-to-edx/9")
 9732     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types-to-edx/10")
 9733     (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")
 9734     (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")
 9735     (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")
 9736     (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")
 9737     (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")
 9738     (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")
 9739     (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")
 9740     # reclaim x
 9741     (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")
 9742     # reclaim a
 9743     (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")
 9744     #
 9745     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-edx/20")
 9746     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/21")
 9747     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-edx/22")
 9748     (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")
 9749     (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")
 9750     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-edx/25")
 9751     # . epilogue
 9752     89/<- %esp 5/r32/ebp
 9753     5d/pop-to-ebp
 9754     c3/return
 9755 
 9756 test-convert-length-of-array-of-user-defined-types:
 9757     # . prologue
 9758     55/push-ebp
 9759     89/<- %ebp 4/r32/esp
 9760     # setup
 9761     (clear-stream _test-input-stream)
 9762     (clear-stream $_test-input-buffered-file->buffer)
 9763     (clear-stream _test-output-stream)
 9764     (clear-stream $_test-output-buffered-file->buffer)
 9765     #
 9766     (write _test-input-stream "type t {\n")  # each t is 8 bytes, which is a power of 2
 9767     (write _test-input-stream "  x: int\n")
 9768     (write _test-input-stream "  y: int\n")
 9769     (write _test-input-stream "  z: int\n")
 9770     (write _test-input-stream "}\n")
 9771     (write _test-input-stream "fn foo {\n")
 9772     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
 9773     (write _test-input-stream "  var x/ebx: int <- length arr\n")
 9774     (write _test-input-stream "}\n")
 9775     # convert
 9776     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9777     (flush _test-output-buffered-file)
 9778 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
 9784     # check output
 9785     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types/0")
 9786     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types/1")
 9787     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types/2")
 9788     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-user-defined-types/3")
 9789     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types/4")
 9790     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types/5")
 9791     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-of-user-defined-types/6")
 9792     (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")
 9793     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-length-of-array-of-user-defined-types/8")
 9794     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types/9")
 9795     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types/10")
 9796     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types/11")
 9797     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array-of-user-defined-types/12")
 9798     (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")
 9799     (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")
 9800     (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")
 9801     (check-next-stream-line-equal _test-output-stream "    89/<- %ebx 0/r32/eax"  "F - test-convert-length-of-array-of-user-defined-types/16")
 9802     (check-next-stream-line-equal _test-output-stream "    5a/pop-to-edx"       "F - test-convert-length-of-array-of-user-defined-types/17")
 9803     (check-next-stream-line-equal _test-output-stream "    59/pop-to-ecx"       "F - test-convert-length-of-array-of-user-defined-types/18")
 9804     (check-next-stream-line-equal _test-output-stream "    58/pop-to-eax"       "F - test-convert-length-of-array-of-user-defined-types/19")
 9805     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ebx"  "F - test-convert-length-of-array-of-user-defined-types/20")
 9806     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-of-user-defined-types/21")
 9807     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types/22")
 9808     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types/23")
 9809     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types/24")
 9810     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-of-user-defined-types/25")
 9811     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-of-user-defined-types/26")
 9812     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types/27")
 9813     # . epilogue
 9814     89/<- %esp 5/r32/ebp
 9815     5d/pop-to-ebp
 9816     c3/return
 9817 
 9818 test-index-with-non-array-atom-base-type:
 9819     # . prologue
 9820     55/push-ebp
 9821     89/<- %ebp 4/r32/esp
 9822     # setup
 9823     (clear-stream _test-input-stream)
 9824     (clear-stream $_test-input-buffered-file->buffer)
 9825     (clear-stream _test-output-stream)
 9826     (clear-stream $_test-output-buffered-file->buffer)
 9827     (clear-stream _test-error-stream)
 9828     (clear-stream $_test-error-buffered-file->buffer)
 9829     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9830     68/push 0/imm32
 9831     68/push 0/imm32
 9832     89/<- %edx 4/r32/esp
 9833     (tailor-exit-descriptor %edx 0x10)
 9834     #
 9835     (write _test-input-stream "fn foo {\n")
 9836     (write _test-input-stream "  var a: int\n")
 9837     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
 9838     (write _test-input-stream "}\n")
 9839     # convert
 9840     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9841     # registers except esp clobbered at this point
 9842     # restore ed
 9843     89/<- %edx 4/r32/esp
 9844     (flush _test-output-buffered-file)
 9845     (flush _test-error-buffered-file)
 9846 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 9852     # check output
 9853     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-atom-base-type: output should be empty")
 9854     (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")
 9855     # check that stop(1) was called
 9856     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-atom-base-type: exit status")
 9857     # don't restore from ebp
 9858     81 0/subop/add %esp 8/imm32
 9859     # . epilogue
 9860     5d/pop-to-ebp
 9861     c3/return
 9862 
 9863 test-index-with-non-array-compound-base-type:
 9864     # . prologue
 9865     55/push-ebp
 9866     89/<- %ebp 4/r32/esp
 9867     # setup
 9868     (clear-stream _test-input-stream)
 9869     (clear-stream $_test-input-buffered-file->buffer)
 9870     (clear-stream _test-output-stream)
 9871     (clear-stream $_test-output-buffered-file->buffer)
 9872     (clear-stream _test-error-stream)
 9873     (clear-stream $_test-error-buffered-file->buffer)
 9874     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9875     68/push 0/imm32
 9876     68/push 0/imm32
 9877     89/<- %edx 4/r32/esp
 9878     (tailor-exit-descriptor %edx 0x10)
 9879     #
 9880     (write _test-input-stream "fn foo {\n")
 9881     (write _test-input-stream "  var a: (handle int)\n")
 9882     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
 9883     (write _test-input-stream "}\n")
 9884     # convert
 9885     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9886     # registers except esp clobbered at this point
 9887     # restore ed
 9888     89/<- %edx 4/r32/esp
 9889     (flush _test-output-buffered-file)
 9890     (flush _test-error-buffered-file)
 9891 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 9897     # check output
 9898     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-compound-base-type: output should be empty")
 9899     (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")
 9900     # check that stop(1) was called
 9901     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-compound-base-type: exit status")
 9902     # don't restore from ebp
 9903     81 0/subop/add %esp 8/imm32
 9904     # . epilogue
 9905     5d/pop-to-ebp
 9906     c3/return
 9907 
 9908 test-index-with-non-array-compound-base-type-2:
 9909     # . prologue
 9910     55/push-ebp
 9911     89/<- %ebp 4/r32/esp
 9912     # setup
 9913     (clear-stream _test-input-stream)
 9914     (clear-stream $_test-input-buffered-file->buffer)
 9915     (clear-stream _test-output-stream)
 9916     (clear-stream $_test-output-buffered-file->buffer)
 9917     (clear-stream _test-error-stream)
 9918     (clear-stream $_test-error-buffered-file->buffer)
 9919     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9920     68/push 0/imm32
 9921     68/push 0/imm32
 9922     89/<- %edx 4/r32/esp
 9923     (tailor-exit-descriptor %edx 0x10)
 9924     #
 9925     (write _test-input-stream "fn foo {\n")
 9926     (write _test-input-stream "  var a: (addr int)\n")
 9927     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
 9928     (write _test-input-stream "}\n")
 9929     # convert
 9930     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9931     # registers except esp clobbered at this point
 9932     # restore ed
 9933     89/<- %edx 4/r32/esp
 9934     (flush _test-output-buffered-file)
 9935     (flush _test-error-buffered-file)
 9936 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 9942     # check output
 9943     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-compound-base-type-2: output should be empty")
 9944     (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")
 9945     # check that stop(1) was called
 9946     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-compound-base-type-2: exit status")
 9947     # don't restore from ebp
 9948     81 0/subop/add %esp 8/imm32
 9949     # . epilogue
 9950     5d/pop-to-ebp
 9951     c3/return
 9952 
 9953 test-index-with-array-atom-base-type:
 9954     # . prologue
 9955     55/push-ebp
 9956     89/<- %ebp 4/r32/esp
 9957     # setup
 9958     (clear-stream _test-input-stream)
 9959     (clear-stream $_test-input-buffered-file->buffer)
 9960     (clear-stream _test-output-stream)
 9961     (clear-stream $_test-output-buffered-file->buffer)
 9962     (clear-stream _test-error-stream)
 9963     (clear-stream $_test-error-buffered-file->buffer)
 9964     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9965     68/push 0/imm32
 9966     68/push 0/imm32
 9967     89/<- %edx 4/r32/esp
 9968     (tailor-exit-descriptor %edx 0x10)
 9969     #
 9970     (write _test-input-stream "fn foo {\n")
 9971     (write _test-input-stream "  var a: array\n")
 9972     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
 9973     (write _test-input-stream "}\n")
 9974     # convert
 9975     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9976     # registers except esp clobbered at this point
 9977     # restore ed
 9978     89/<- %edx 4/r32/esp
 9979     (flush _test-output-buffered-file)
 9980     (flush _test-error-buffered-file)
 9981 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
 9987     # check output
 9988     (check-stream-equal _test-output-stream  ""  "F - test-index-with-array-atom-base-type: output should be empty")
 9989     (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")
 9990     # check that stop(1) was called
 9991     (check-ints-equal *(edx+4) 2 "F - test-index-with-array-atom-base-type: exit status")
 9992     # don't restore from ebp
 9993     81 0/subop/add %esp 8/imm32
 9994     # . epilogue
 9995     5d/pop-to-ebp
 9996     c3/return
 9997 
 9998 test-index-with-addr-base-on-stack:
 9999     # . prologue
10000     55/push-ebp
10001     89/<- %ebp 4/r32/esp
10002     # setup
10003     (clear-stream _test-input-stream)
10004     (clear-stream $_test-input-buffered-file->buffer)
10005     (clear-stream _test-output-stream)
10006     (clear-stream $_test-output-buffered-file->buffer)
10007     (clear-stream _test-error-stream)
10008     (clear-stream $_test-error-buffered-file->buffer)
10009     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10010     68/push 0/imm32
10011     68/push 0/imm32
10012     89/<- %edx 4/r32/esp
10013     (tailor-exit-descriptor %edx 0x10)
10014     #
10015     (write _test-input-stream "fn foo {\n")
10016     (write _test-input-stream "  var a: (addr array int)\n")
10017     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
10018     (write _test-input-stream "}\n")
10019     # convert
10020     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10021     # registers except esp clobbered at this point
10022     # restore ed
10023     89/<- %edx 4/r32/esp
10024     (flush _test-output-buffered-file)
10025     (flush _test-error-buffered-file)
10026 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
10032     # check output
10033     (check-stream-equal _test-output-stream  ""  "F - test-index-with-addr-base-on-stack: output should be empty")
10034     (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")
10035     # check that stop(1) was called
10036     (check-ints-equal *(edx+4) 2 "F - test-index-with-addr-base-on-stack: exit status")
10037     # don't restore from ebp
10038     81 0/subop/add %esp 8/imm32
10039     # . epilogue
10040     5d/pop-to-ebp
10041     c3/return
10042 
10043 test-index-with-wrong-index-type:
10044     # . prologue
10045     55/push-ebp
10046     89/<- %ebp 4/r32/esp
10047     # setup
10048     (clear-stream _test-input-stream)
10049     (clear-stream $_test-input-buffered-file->buffer)
10050     (clear-stream _test-output-stream)
10051     (clear-stream $_test-output-buffered-file->buffer)
10052     (clear-stream _test-error-stream)
10053     (clear-stream $_test-error-buffered-file->buffer)
10054     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10055     68/push 0/imm32
10056     68/push 0/imm32
10057     89/<- %edx 4/r32/esp
10058     (tailor-exit-descriptor %edx 0x10)
10059     #
10060     (write _test-input-stream "fn foo {\n")
10061     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
10062     (write _test-input-stream "  var b: boolean\n")
10063     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
10064     (write _test-input-stream "}\n")
10065     # convert
10066     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10067     # registers except esp clobbered at this point
10068     # restore ed
10069     89/<- %edx 4/r32/esp
10070     (flush _test-output-buffered-file)
10071     (flush _test-error-buffered-file)
10072 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
10078     # check output
10079     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-index-type: output should be empty")
10080     (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")
10081     # check that stop(1) was called
10082     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-index-type: exit status")
10083     # don't restore from ebp
10084     81 0/subop/add %esp 8/imm32
10085     # . epilogue
10086     5d/pop-to-ebp
10087     c3/return
10088 
10089 test-index-with-offset-atom-index-type:
10090     # . prologue
10091     55/push-ebp
10092     89/<- %ebp 4/r32/esp
10093     # setup
10094     (clear-stream _test-input-stream)
10095     (clear-stream $_test-input-buffered-file->buffer)
10096     (clear-stream _test-output-stream)
10097     (clear-stream $_test-output-buffered-file->buffer)
10098     (clear-stream _test-error-stream)
10099     (clear-stream $_test-error-buffered-file->buffer)
10100     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10101     68/push 0/imm32
10102     68/push 0/imm32
10103     89/<- %edx 4/r32/esp
10104     (tailor-exit-descriptor %edx 0x10)
10105     #
10106     (write _test-input-stream "fn foo {\n")
10107     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
10108     (write _test-input-stream "  var b: offset\n")
10109     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
10110     (write _test-input-stream "}\n")
10111     # convert
10112     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10113     # registers except esp clobbered at this point
10114     # restore ed
10115     89/<- %edx 4/r32/esp
10116     (flush _test-output-buffered-file)
10117     (flush _test-error-buffered-file)
10118 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
10124     # check output
10125     (check-stream-equal _test-output-stream  ""  "F - test-index-with-offset-atom-index-type: output should be empty")
10126     (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")
10127     # check that stop(1) was called
10128     (check-ints-equal *(edx+4) 2 "F - test-index-with-offset-atom-index-type: exit status")
10129     # don't restore from ebp
10130     81 0/subop/add %esp 8/imm32
10131     # . epilogue
10132     5d/pop-to-ebp
10133     c3/return
10134 
10135 test-index-with-offset-on-stack:
10136     # . prologue
10137     55/push-ebp
10138     89/<- %ebp 4/r32/esp
10139     # setup
10140     (clear-stream _test-input-stream)
10141     (clear-stream $_test-input-buffered-file->buffer)
10142     (clear-stream _test-output-stream)
10143     (clear-stream $_test-output-buffered-file->buffer)
10144     (clear-stream _test-error-stream)
10145     (clear-stream $_test-error-buffered-file->buffer)
10146     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10147     68/push 0/imm32
10148     68/push 0/imm32
10149     89/<- %edx 4/r32/esp
10150     (tailor-exit-descriptor %edx 0x10)
10151     #
10152     (write _test-input-stream "fn foo {\n")
10153     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
10154     (write _test-input-stream "  var b: int\n")
10155     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
10156     (write _test-input-stream "}\n")
10157     # convert
10158     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10159     # registers except esp clobbered at this point
10160     # restore ed
10161     89/<- %edx 4/r32/esp
10162     (flush _test-output-buffered-file)
10163     (flush _test-error-buffered-file)
10164 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
10170     # check output
10171     (check-stream-equal _test-output-stream  ""  "F - test-index-with-offset-on-stack: output should be empty")
10172     (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")
10173     # check that stop(1) was called
10174     (check-ints-equal *(edx+4) 2 "F - test-index-with-offset-on-stack: exit status")
10175     # don't restore from ebp
10176     81 0/subop/add %esp 8/imm32
10177     # . epilogue
10178     5d/pop-to-ebp
10179     c3/return
10180 
10181 test-index-needs-offset-type:
10182     # . prologue
10183     55/push-ebp
10184     89/<- %ebp 4/r32/esp
10185     # setup
10186     (clear-stream _test-input-stream)
10187     (clear-stream $_test-input-buffered-file->buffer)
10188     (clear-stream _test-output-stream)
10189     (clear-stream $_test-output-buffered-file->buffer)
10190     (clear-stream _test-error-stream)
10191     (clear-stream $_test-error-buffered-file->buffer)
10192     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10193     68/push 0/imm32
10194     68/push 0/imm32
10195     89/<- %edx 4/r32/esp
10196     (tailor-exit-descriptor %edx 0x10)
10197     #
10198     (write _test-input-stream "fn foo {\n")
10199     (write _test-input-stream "  var a/eax: (addr array t) <- copy 0\n")
10200     (write _test-input-stream "  var b/ebx: int <- copy 0\n")
10201     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
10202     (write _test-input-stream "}\n")
10203     (write _test-input-stream "type t {\n")  # size 12 is not a power of two
10204     (write _test-input-stream "  x: int\n")
10205     (write _test-input-stream "  y: int\n")
10206     (write _test-input-stream "  z: int\n")
10207     (write _test-input-stream "}\n")
10208     # convert
10209     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10210     # registers except esp clobbered at this point
10211     # restore ed
10212     89/<- %edx 4/r32/esp
10213     (flush _test-output-buffered-file)
10214     (flush _test-error-buffered-file)
10215 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
10221     # check output
10222     (check-stream-equal _test-output-stream  ""  "F - test-index-needs-offset-type: output should be empty")
10223     (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")
10224     # check that stop(1) was called
10225     (check-ints-equal *(edx+4) 2 "F - test-index-needs-offset-type: exit status")
10226     # don't restore from ebp
10227     81 0/subop/add %esp 8/imm32
10228     # . epilogue
10229     5d/pop-to-ebp
10230     c3/return
10231 
10232 test-index-with-output-not-address:
10233     # . prologue
10234     55/push-ebp
10235     89/<- %ebp 4/r32/esp
10236     # setup
10237     (clear-stream _test-input-stream)
10238     (clear-stream $_test-input-buffered-file->buffer)
10239     (clear-stream _test-output-stream)
10240     (clear-stream $_test-output-buffered-file->buffer)
10241     (clear-stream _test-error-stream)
10242     (clear-stream $_test-error-buffered-file->buffer)
10243     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10244     68/push 0/imm32
10245     68/push 0/imm32
10246     89/<- %edx 4/r32/esp
10247     (tailor-exit-descriptor %edx 0x10)
10248     #
10249     (write _test-input-stream "fn foo {\n")
10250     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
10251     (write _test-input-stream "  var o/edi: int <- index a, 0\n")
10252     (write _test-input-stream "}\n")
10253     # convert
10254     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10255     # registers except esp clobbered at this point
10256     # restore ed
10257     89/<- %edx 4/r32/esp
10258     (flush _test-output-buffered-file)
10259     (flush _test-error-buffered-file)
10260 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
10266     # check output
10267     (check-stream-equal _test-output-stream  ""  "F - test-index-with-output-not-address: output should be empty")
10268     (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")
10269     # check that stop(1) was called
10270     (check-ints-equal *(edx+4) 2 "F - test-index-with-output-not-address: exit status")
10271     # don't restore from ebp
10272     81 0/subop/add %esp 8/imm32
10273     # . epilogue
10274     5d/pop-to-ebp
10275     c3/return
10276 
10277 test-index-with-output-not-address-2:
10278     # . prologue
10279     55/push-ebp
10280     89/<- %ebp 4/r32/esp
10281     # setup
10282     (clear-stream _test-input-stream)
10283     (clear-stream $_test-input-buffered-file->buffer)
10284     (clear-stream _test-output-stream)
10285     (clear-stream $_test-output-buffered-file->buffer)
10286     (clear-stream _test-error-stream)
10287     (clear-stream $_test-error-buffered-file->buffer)
10288     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10289     68/push 0/imm32
10290     68/push 0/imm32
10291     89/<- %edx 4/r32/esp
10292     (tailor-exit-descriptor %edx 0x10)
10293     #
10294     (write _test-input-stream "fn foo {\n")
10295     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
10296     (write _test-input-stream "  var o/edi: (int) <- index a, 0\n")
10297     (write _test-input-stream "}\n")
10298     # convert
10299     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10300     # registers except esp clobbered at this point
10301     # restore ed
10302     89/<- %edx 4/r32/esp
10303     (flush _test-output-buffered-file)
10304     (flush _test-error-buffered-file)
10305 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
10311     # check output
10312     (check-stream-equal _test-output-stream  ""  "F - test-index-with-output-not-address-2: output should be empty")
10313     (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")
10314     # check that stop(1) was called
10315     (check-ints-equal *(edx+4) 2 "F - test-index-with-output-not-address-2: exit status")
10316     # don't restore from ebp
10317     81 0/subop/add %esp 8/imm32
10318     # . epilogue
10319     5d/pop-to-ebp
10320     c3/return
10321 
10322 test-index-with-wrong-output-type:
10323     # . prologue
10324     55/push-ebp
10325     89/<- %ebp 4/r32/esp
10326     # setup
10327     (clear-stream _test-input-stream)
10328     (clear-stream $_test-input-buffered-file->buffer)
10329     (clear-stream _test-output-stream)
10330     (clear-stream $_test-output-buffered-file->buffer)
10331     (clear-stream _test-error-stream)
10332     (clear-stream $_test-error-buffered-file->buffer)
10333     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10334     68/push 0/imm32
10335     68/push 0/imm32
10336     89/<- %edx 4/r32/esp
10337     (tailor-exit-descriptor %edx 0x10)
10338     #
10339     (write _test-input-stream "fn foo {\n")
10340     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
10341     (write _test-input-stream "  var o/edi: (addr int) <- index a, 0\n")
10342     (write _test-input-stream "}\n")
10343     # convert
10344     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10345     # registers except esp clobbered at this point
10346     # restore ed
10347     89/<- %edx 4/r32/esp
10348     (flush _test-output-buffered-file)
10349     (flush _test-error-buffered-file)
10350 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
10356     # check output
10357     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-output-type: output should be empty")
10358     (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")
10359     # check that stop(1) was called
10360     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-output-type: exit status")
10361     # don't restore from ebp
10362     81 0/subop/add %esp 8/imm32
10363     # . epilogue
10364     5d/pop-to-ebp
10365     c3/return
10366 
10367 test-index-with-wrong-output-compound-type:
10368     # . prologue
10369     55/push-ebp
10370     89/<- %ebp 4/r32/esp
10371     # setup
10372     (clear-stream _test-input-stream)
10373     (clear-stream $_test-input-buffered-file->buffer)
10374     (clear-stream _test-output-stream)
10375     (clear-stream $_test-output-buffered-file->buffer)
10376     (clear-stream _test-error-stream)
10377     (clear-stream $_test-error-buffered-file->buffer)
10378     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10379     68/push 0/imm32
10380     68/push 0/imm32
10381     89/<- %edx 4/r32/esp
10382     (tailor-exit-descriptor %edx 0x10)
10383     #
10384     (write _test-input-stream "fn foo {\n")
10385     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
10386     (write _test-input-stream "  var o/edi: (addr handle int) <- index a, 0\n")
10387     (write _test-input-stream "}\n")
10388     # convert
10389     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10390     # registers except esp clobbered at this point
10391     # restore ed
10392     89/<- %edx 4/r32/esp
10393     (flush _test-output-buffered-file)
10394     (flush _test-error-buffered-file)
10395 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
10401     # check output
10402     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-output-compound-type: output should be empty")
10403     (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")
10404     # check that stop(1) was called
10405     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-output-compound-type: exit status")
10406     # don't restore from ebp
10407     81 0/subop/add %esp 8/imm32
10408     # . epilogue
10409     5d/pop-to-ebp
10410     c3/return
10411 
10412 test-index-with-no-inouts:
10413     # . prologue
10414     55/push-ebp
10415     89/<- %ebp 4/r32/esp
10416     # setup
10417     (clear-stream _test-input-stream)
10418     (clear-stream $_test-input-buffered-file->buffer)
10419     (clear-stream _test-output-stream)
10420     (clear-stream $_test-output-buffered-file->buffer)
10421     (clear-stream _test-error-stream)
10422     (clear-stream $_test-error-buffered-file->buffer)
10423     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10424     68/push 0/imm32
10425     68/push 0/imm32
10426     89/<- %edx 4/r32/esp
10427     (tailor-exit-descriptor %edx 0x10)
10428     #
10429     (write _test-input-stream "fn foo {\n")
10430     (write _test-input-stream "  var c/ecx: (addr int) <- index\n")
10431     (write _test-input-stream "}\n")
10432     # convert
10433     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10434     # registers except esp clobbered at this point
10435     # restore ed
10436     89/<- %edx 4/r32/esp
10437     (flush _test-output-buffered-file)
10438     (flush _test-error-buffered-file)
10439 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
10445     # check output
10446     (check-stream-equal _test-output-stream  ""  "F - test-index-with-no-inouts: output should be empty")
10447     (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")
10448     # check that stop(1) was called
10449     (check-ints-equal *(edx+4) 2 "F - test-index-with-no-inouts: exit status")
10450     # don't restore from ebp
10451     81 0/subop/add %esp 8/imm32
10452     # . epilogue
10453     5d/pop-to-ebp
10454     c3/return
10455 
10456 test-index-with-too-few-inouts:
10457     # . prologue
10458     55/push-ebp
10459     89/<- %ebp 4/r32/esp
10460     # setup
10461     (clear-stream _test-input-stream)
10462     (clear-stream $_test-input-buffered-file->buffer)
10463     (clear-stream _test-output-stream)
10464     (clear-stream $_test-output-buffered-file->buffer)
10465     (clear-stream _test-error-stream)
10466     (clear-stream $_test-error-buffered-file->buffer)
10467     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10468     68/push 0/imm32
10469     68/push 0/imm32
10470     89/<- %edx 4/r32/esp
10471     (tailor-exit-descriptor %edx 0x10)
10472     #
10473     (write _test-input-stream "fn foo {\n")
10474     (write _test-input-stream "  var a: (array int 3)\n")
10475     (write _test-input-stream "  var c/ecx: (addr int) <- index a\n")
10476     (write _test-input-stream "}\n")
10477     # convert
10478     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10479     # registers except esp clobbered at this point
10480     # restore ed
10481     89/<- %edx 4/r32/esp
10482     (flush _test-output-buffered-file)
10483     (flush _test-error-buffered-file)
10484 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
10490     # check output
10491     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-few-inouts: output should be empty")
10492     (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")
10493     # check that stop(1) was called
10494     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-few-inouts: exit status")
10495     # don't restore from ebp
10496     81 0/subop/add %esp 8/imm32
10497     # . epilogue
10498     5d/pop-to-ebp
10499     c3/return
10500 
10501 test-index-with-too-many-inouts:
10502     # . prologue
10503     55/push-ebp
10504     89/<- %ebp 4/r32/esp
10505     # setup
10506     (clear-stream _test-input-stream)
10507     (clear-stream $_test-input-buffered-file->buffer)
10508     (clear-stream _test-output-stream)
10509     (clear-stream $_test-output-buffered-file->buffer)
10510     (clear-stream _test-error-stream)
10511     (clear-stream $_test-error-buffered-file->buffer)
10512     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10513     68/push 0/imm32
10514     68/push 0/imm32
10515     89/<- %edx 4/r32/esp
10516     (tailor-exit-descriptor %edx 0x10)
10517     #
10518     (write _test-input-stream "fn foo {\n")
10519     (write _test-input-stream "  var a: (array int 3)\n")
10520     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0, 0\n")
10521     (write _test-input-stream "}\n")
10522     # convert
10523     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10524     # registers except esp clobbered at this point
10525     # restore ed
10526     89/<- %edx 4/r32/esp
10527     (flush _test-output-buffered-file)
10528     (flush _test-error-buffered-file)
10529 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
10535     # check output
10536     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-many-inouts: output should be empty")
10537     (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")
10538     # check that stop(1) was called
10539     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-many-inouts: exit status")
10540     # don't restore from ebp
10541     81 0/subop/add %esp 8/imm32
10542     # . epilogue
10543     5d/pop-to-ebp
10544     c3/return
10545 
10546 test-index-with-no-output:
10547     # . prologue
10548     55/push-ebp
10549     89/<- %ebp 4/r32/esp
10550     # setup
10551     (clear-stream _test-input-stream)
10552     (clear-stream $_test-input-buffered-file->buffer)
10553     (clear-stream _test-output-stream)
10554     (clear-stream $_test-output-buffered-file->buffer)
10555     (clear-stream _test-error-stream)
10556     (clear-stream $_test-error-buffered-file->buffer)
10557     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10558     68/push 0/imm32
10559     68/push 0/imm32
10560     89/<- %edx 4/r32/esp
10561     (tailor-exit-descriptor %edx 0x10)
10562     #
10563     (write _test-input-stream "fn foo {\n")
10564     (write _test-input-stream "  var a: (array int 3)\n")
10565     (write _test-input-stream "  index a, 0\n")
10566     (write _test-input-stream "}\n")
10567     # convert
10568     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10569     # registers except esp clobbered at this point
10570     # restore ed
10571     89/<- %edx 4/r32/esp
10572     (flush _test-output-buffered-file)
10573     (flush _test-error-buffered-file)
10574 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
10580     # check output
10581     (check-stream-equal _test-output-stream  ""  "F - test-index-with-no-output: output should be empty")
10582     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: must have an output"  "F - test-index-with-no-output: error message")
10583     # check that stop(1) was called
10584     (check-ints-equal *(edx+4) 2 "F - test-index-with-no-output: exit status")
10585     # don't restore from ebp
10586     81 0/subop/add %esp 8/imm32
10587     # . epilogue
10588     5d/pop-to-ebp
10589     c3/return
10590 
10591 test-index-with-too-many-outputs:
10592     # . prologue
10593     55/push-ebp
10594     89/<- %ebp 4/r32/esp
10595     # setup
10596     (clear-stream _test-input-stream)
10597     (clear-stream $_test-input-buffered-file->buffer)
10598     (clear-stream _test-output-stream)
10599     (clear-stream $_test-output-buffered-file->buffer)
10600     (clear-stream _test-error-stream)
10601     (clear-stream $_test-error-buffered-file->buffer)
10602     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10603     68/push 0/imm32
10604     68/push 0/imm32
10605     89/<- %edx 4/r32/esp
10606     (tailor-exit-descriptor %edx 0x10)
10607     #
10608     (write _test-input-stream "fn foo {\n")
10609     (write _test-input-stream "  var a: (array int 3)\n")
10610     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
10611     (write _test-input-stream "  var c/ecx: (addr int) <- copy 0\n")
10612     (write _test-input-stream "  b, c <- index a, 0\n")
10613     (write _test-input-stream "}\n")
10614     # convert
10615     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10616     # registers except esp clobbered at this point
10617     # restore ed
10618     89/<- %edx 4/r32/esp
10619     (flush _test-output-buffered-file)
10620     (flush _test-error-buffered-file)
10621 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
10627     # check output
10628     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-many-outputs: output should be empty")
10629     (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")
10630     # check that stop(1) was called
10631     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-many-outputs: exit status")
10632     # don't restore from ebp
10633     81 0/subop/add %esp 8/imm32
10634     # . epilogue
10635     5d/pop-to-ebp
10636     c3/return
10637 
10638 test-compute-offset-with-non-array-atom-base-type:
10639     # . prologue
10640     55/push-ebp
10641     89/<- %ebp 4/r32/esp
10642     # setup
10643     (clear-stream _test-input-stream)
10644     (clear-stream $_test-input-buffered-file->buffer)
10645     (clear-stream _test-output-stream)
10646     (clear-stream $_test-output-buffered-file->buffer)
10647     (clear-stream _test-error-stream)
10648     (clear-stream $_test-error-buffered-file->buffer)
10649     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10650     68/push 0/imm32
10651     68/push 0/imm32
10652     89/<- %edx 4/r32/esp
10653     (tailor-exit-descriptor %edx 0x10)
10654     #
10655     (write _test-input-stream "fn foo {\n")
10656     (write _test-input-stream "  var a: int\n")
10657     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
10658     (write _test-input-stream "}\n")
10659     # convert
10660     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10661     # registers except esp clobbered at this point
10662     # restore ed
10663     89/<- %edx 4/r32/esp
10664     (flush _test-output-buffered-file)
10665     (flush _test-error-buffered-file)
10666 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
10672     # check output
10673     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-atom-base-type: output should be empty")
10674     (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")
10675     # check that stop(1) was called
10676     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-atom-base-type: exit status")
10677     # don't restore from ebp
10678     81 0/subop/add %esp 8/imm32
10679     # . epilogue
10680     5d/pop-to-ebp
10681     c3/return
10682 
10683 test-compute-offset-with-non-array-compound-base-type:
10684     # . prologue
10685     55/push-ebp
10686     89/<- %ebp 4/r32/esp
10687     # setup
10688     (clear-stream _test-input-stream)
10689     (clear-stream $_test-input-buffered-file->buffer)
10690     (clear-stream _test-output-stream)
10691     (clear-stream $_test-output-buffered-file->buffer)
10692     (clear-stream _test-error-stream)
10693     (clear-stream $_test-error-buffered-file->buffer)
10694     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10695     68/push 0/imm32
10696     68/push 0/imm32
10697     89/<- %edx 4/r32/esp
10698     (tailor-exit-descriptor %edx 0x10)
10699     #
10700     (write _test-input-stream "fn foo {\n")
10701     (write _test-input-stream "  var a: (handle int)\n")
10702     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
10703     (write _test-input-stream "}\n")
10704     # convert
10705     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10706     # registers except esp clobbered at this point
10707     # restore ed
10708     89/<- %edx 4/r32/esp
10709     (flush _test-output-buffered-file)
10710     (flush _test-error-buffered-file)
10711 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
10717     # check output
10718     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-compound-base-type: output should be empty")
10719     (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")
10720     # check that stop(1) was called
10721     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-compound-base-type: exit status")
10722     # don't restore from ebp
10723     81 0/subop/add %esp 8/imm32
10724     # . epilogue
10725     5d/pop-to-ebp
10726     c3/return
10727 
10728 test-compute-offset-with-non-array-compound-base-type-2:
10729     # . prologue
10730     55/push-ebp
10731     89/<- %ebp 4/r32/esp
10732     # setup
10733     (clear-stream _test-input-stream)
10734     (clear-stream $_test-input-buffered-file->buffer)
10735     (clear-stream _test-output-stream)
10736     (clear-stream $_test-output-buffered-file->buffer)
10737     (clear-stream _test-error-stream)
10738     (clear-stream $_test-error-buffered-file->buffer)
10739     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10740     68/push 0/imm32
10741     68/push 0/imm32
10742     89/<- %edx 4/r32/esp
10743     (tailor-exit-descriptor %edx 0x10)
10744     #
10745     (write _test-input-stream "fn foo {\n")
10746     (write _test-input-stream "  var a: (addr int)\n")
10747     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
10748     (write _test-input-stream "}\n")
10749     # convert
10750     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10751     # registers except esp clobbered at this point
10752     # restore ed
10753     89/<- %edx 4/r32/esp
10754     (flush _test-output-buffered-file)
10755     (flush _test-error-buffered-file)
10756 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
10762     # check output
10763     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-compound-base-type-2: output should be empty")
10764     (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")
10765     # check that stop(1) was called
10766     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-compound-base-type-2: exit status")
10767     # don't restore from ebp
10768     81 0/subop/add %esp 8/imm32
10769     # . epilogue
10770     5d/pop-to-ebp
10771     c3/return
10772 
10773 test-compute-offset-with-array-atom-base-type:
10774     # . prologue
10775     55/push-ebp
10776     89/<- %ebp 4/r32/esp
10777     # setup
10778     (clear-stream _test-input-stream)
10779     (clear-stream $_test-input-buffered-file->buffer)
10780     (clear-stream _test-output-stream)
10781     (clear-stream $_test-output-buffered-file->buffer)
10782     (clear-stream _test-error-stream)
10783     (clear-stream $_test-error-buffered-file->buffer)
10784     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10785     68/push 0/imm32
10786     68/push 0/imm32
10787     89/<- %edx 4/r32/esp
10788     (tailor-exit-descriptor %edx 0x10)
10789     #
10790     (write _test-input-stream "fn foo {\n")
10791     (write _test-input-stream "  var a: array\n")
10792     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
10793     (write _test-input-stream "}\n")
10794     # convert
10795     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10796     # registers except esp clobbered at this point
10797     # restore ed
10798     89/<- %edx 4/r32/esp
10799     (flush _test-output-buffered-file)
10800     (flush _test-error-buffered-file)
10801 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
10807     # check output
10808     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-array-atom-base-type: output should be empty")
10809     (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")
10810     # check that stop(1) was called
10811     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-array-atom-base-type: exit status")
10812     # don't restore from ebp
10813     81 0/subop/add %esp 8/imm32
10814     # . epilogue
10815     5d/pop-to-ebp
10816     c3/return
10817 
10818 test-compute-offset-with-wrong-index-type:
10819     # . prologue
10820     55/push-ebp
10821     89/<- %ebp 4/r32/esp
10822     # setup
10823     (clear-stream _test-input-stream)
10824     (clear-stream $_test-input-buffered-file->buffer)
10825     (clear-stream _test-output-stream)
10826     (clear-stream $_test-output-buffered-file->buffer)
10827     (clear-stream _test-error-stream)
10828     (clear-stream $_test-error-buffered-file->buffer)
10829     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10830     68/push 0/imm32
10831     68/push 0/imm32
10832     89/<- %edx 4/r32/esp
10833     (tailor-exit-descriptor %edx 0x10)
10834     #
10835     (write _test-input-stream "fn foo {\n")
10836     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
10837     (write _test-input-stream "  var b: boolean\n")
10838     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, b\n")
10839     (write _test-input-stream "}\n")
10840     # convert
10841     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10842     # registers except esp clobbered at this point
10843     # restore ed
10844     89/<- %edx 4/r32/esp
10845     (flush _test-output-buffered-file)
10846     (flush _test-error-buffered-file)
10847 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
10853     # check output
10854     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-index-type: output should be empty")
10855     (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")
10856     # check that stop(1) was called
10857     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-index-type: exit status")
10858     # don't restore from ebp
10859     81 0/subop/add %esp 8/imm32
10860     # . epilogue
10861     5d/pop-to-ebp
10862     c3/return
10863 
10864 test-compute-offset-with-output-not-offset:
10865     # . prologue
10866     55/push-ebp
10867     89/<- %ebp 4/r32/esp
10868     # setup
10869     (clear-stream _test-input-stream)
10870     (clear-stream $_test-input-buffered-file->buffer)
10871     (clear-stream _test-output-stream)
10872     (clear-stream $_test-output-buffered-file->buffer)
10873     (clear-stream _test-error-stream)
10874     (clear-stream $_test-error-buffered-file->buffer)
10875     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10876     68/push 0/imm32
10877     68/push 0/imm32
10878     89/<- %edx 4/r32/esp
10879     (tailor-exit-descriptor %edx 0x10)
10880     #
10881     (write _test-input-stream "fn foo {\n")
10882     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
10883     (write _test-input-stream "  var o/edi: int <- compute-offset a, 0\n")
10884     (write _test-input-stream "}\n")
10885     # convert
10886     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10887     # registers except esp clobbered at this point
10888     # restore ed
10889     89/<- %edx 4/r32/esp
10890     (flush _test-output-buffered-file)
10891     (flush _test-error-buffered-file)
10892 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
10898     # check output
10899     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-output-not-offset: output should be empty")
10900     (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")
10901     # check that stop(1) was called
10902     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-output-not-offset: exit status")
10903     # don't restore from ebp
10904     81 0/subop/add %esp 8/imm32
10905     # . epilogue
10906     5d/pop-to-ebp
10907     c3/return
10908 
10909 test-compute-offset-with-output-not-address-2:
10910     # . prologue
10911     55/push-ebp
10912     89/<- %ebp 4/r32/esp
10913     # setup
10914     (clear-stream _test-input-stream)
10915     (clear-stream $_test-input-buffered-file->buffer)
10916     (clear-stream _test-output-stream)
10917     (clear-stream $_test-output-buffered-file->buffer)
10918     (clear-stream _test-error-stream)
10919     (clear-stream $_test-error-buffered-file->buffer)
10920     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10921     68/push 0/imm32
10922     68/push 0/imm32
10923     89/<- %edx 4/r32/esp
10924     (tailor-exit-descriptor %edx 0x10)
10925     #
10926     (write _test-input-stream "fn foo {\n")
10927     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
10928     (write _test-input-stream "  var o/edi: (int) <- compute-offset a, 0\n")
10929     (write _test-input-stream "}\n")
10930     # convert
10931     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10932     # registers except esp clobbered at this point
10933     # restore ed
10934     89/<- %edx 4/r32/esp
10935     (flush _test-output-buffered-file)
10936     (flush _test-error-buffered-file)
10937 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
10943     # check output
10944     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-output-not-address-2: output should be empty")
10945     (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")
10946     # check that stop(1) was called
10947     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-output-not-address-2: exit status")
10948     # don't restore from ebp
10949     81 0/subop/add %esp 8/imm32
10950     # . epilogue
10951     5d/pop-to-ebp
10952     c3/return
10953 
10954 test-compute-offset-with-wrong-output-type:
10955     # . prologue
10956     55/push-ebp
10957     89/<- %ebp 4/r32/esp
10958     # setup
10959     (clear-stream _test-input-stream)
10960     (clear-stream $_test-input-buffered-file->buffer)
10961     (clear-stream _test-output-stream)
10962     (clear-stream $_test-output-buffered-file->buffer)
10963     (clear-stream _test-error-stream)
10964     (clear-stream $_test-error-buffered-file->buffer)
10965     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10966     68/push 0/imm32
10967     68/push 0/imm32
10968     89/<- %edx 4/r32/esp
10969     (tailor-exit-descriptor %edx 0x10)
10970     #
10971     (write _test-input-stream "fn foo {\n")
10972     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
10973     (write _test-input-stream "  var o/edi: (offset int) <- compute-offset a, 0\n")
10974     (write _test-input-stream "}\n")
10975     # convert
10976     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10977     # registers except esp clobbered at this point
10978     # restore ed
10979     89/<- %edx 4/r32/esp
10980     (flush _test-output-buffered-file)
10981     (flush _test-error-buffered-file)
10982 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
10988     # check output
10989     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-output-type: output should be empty")
10990     (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")
10991     # check that stop(1) was called
10992     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-output-type: exit status")
10993     # don't restore from ebp
10994     81 0/subop/add %esp 8/imm32
10995     # . epilogue
10996     5d/pop-to-ebp
10997     c3/return
10998 
10999 test-compute-offset-with-wrong-output-compound-type:
11000     # . prologue
11001     55/push-ebp
11002     89/<- %ebp 4/r32/esp
11003     # setup
11004     (clear-stream _test-input-stream)
11005     (clear-stream $_test-input-buffered-file->buffer)
11006     (clear-stream _test-output-stream)
11007     (clear-stream $_test-output-buffered-file->buffer)
11008     (clear-stream _test-error-stream)
11009     (clear-stream $_test-error-buffered-file->buffer)
11010     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11011     68/push 0/imm32
11012     68/push 0/imm32
11013     89/<- %edx 4/r32/esp
11014     (tailor-exit-descriptor %edx 0x10)
11015     #
11016     (write _test-input-stream "fn foo {\n")
11017     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
11018     (write _test-input-stream "  var o/edi: (offset handle int) <- compute-offset a, 0\n")
11019     (write _test-input-stream "}\n")
11020     # convert
11021     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11022     # registers except esp clobbered at this point
11023     # restore ed
11024     89/<- %edx 4/r32/esp
11025     (flush _test-output-buffered-file)
11026     (flush _test-error-buffered-file)
11027 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
11033     # check output
11034     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-output-compound-type: output should be empty")
11035     (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")
11036     # check that stop(1) was called
11037     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-output-compound-type: exit status")
11038     # don't restore from ebp
11039     81 0/subop/add %esp 8/imm32
11040     # . epilogue
11041     5d/pop-to-ebp
11042     c3/return
11043 
11044 test-compute-offset-with-no-inouts:
11045     # . prologue
11046     55/push-ebp
11047     89/<- %ebp 4/r32/esp
11048     # setup
11049     (clear-stream _test-input-stream)
11050     (clear-stream $_test-input-buffered-file->buffer)
11051     (clear-stream _test-output-stream)
11052     (clear-stream $_test-output-buffered-file->buffer)
11053     (clear-stream _test-error-stream)
11054     (clear-stream $_test-error-buffered-file->buffer)
11055     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11056     68/push 0/imm32
11057     68/push 0/imm32
11058     89/<- %edx 4/r32/esp
11059     (tailor-exit-descriptor %edx 0x10)
11060     #
11061     (write _test-input-stream "fn foo {\n")
11062     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset\n")
11063     (write _test-input-stream "}\n")
11064     # convert
11065     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11066     # registers except esp clobbered at this point
11067     # restore ed
11068     89/<- %edx 4/r32/esp
11069     (flush _test-output-buffered-file)
11070     (flush _test-error-buffered-file)
11071 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
11077     # check output
11078     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-no-inouts: output should be empty")
11079     (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")
11080     # check that stop(1) was called
11081     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-no-inouts: exit status")
11082     # don't restore from ebp
11083     81 0/subop/add %esp 8/imm32
11084     # . epilogue
11085     5d/pop-to-ebp
11086     c3/return
11087 
11088 test-compute-offset-with-too-few-inouts:
11089     # . prologue
11090     55/push-ebp
11091     89/<- %ebp 4/r32/esp
11092     # setup
11093     (clear-stream _test-input-stream)
11094     (clear-stream $_test-input-buffered-file->buffer)
11095     (clear-stream _test-output-stream)
11096     (clear-stream $_test-output-buffered-file->buffer)
11097     (clear-stream _test-error-stream)
11098     (clear-stream $_test-error-buffered-file->buffer)
11099     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11100     68/push 0/imm32
11101     68/push 0/imm32
11102     89/<- %edx 4/r32/esp
11103     (tailor-exit-descriptor %edx 0x10)
11104     #
11105     (write _test-input-stream "fn foo {\n")
11106     (write _test-input-stream "  var a: (array int 3)\n")
11107     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a\n")
11108     (write _test-input-stream "}\n")
11109     # convert
11110     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11111     # registers except esp clobbered at this point
11112     # restore ed
11113     89/<- %edx 4/r32/esp
11114     (flush _test-output-buffered-file)
11115     (flush _test-error-buffered-file)
11116 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
11122     # check output
11123     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-few-inouts: output should be empty")
11124     (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")
11125     # check that stop(1) was called
11126     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-few-inouts: exit status")
11127     # don't restore from ebp
11128     81 0/subop/add %esp 8/imm32
11129     # . epilogue
11130     5d/pop-to-ebp
11131     c3/return
11132 
11133 test-compute-offset-with-too-many-inouts:
11134     # . prologue
11135     55/push-ebp
11136     89/<- %ebp 4/r32/esp
11137     # setup
11138     (clear-stream _test-input-stream)
11139     (clear-stream $_test-input-buffered-file->buffer)
11140     (clear-stream _test-output-stream)
11141     (clear-stream $_test-output-buffered-file->buffer)
11142     (clear-stream _test-error-stream)
11143     (clear-stream $_test-error-buffered-file->buffer)
11144     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11145     68/push 0/imm32
11146     68/push 0/imm32
11147     89/<- %edx 4/r32/esp
11148     (tailor-exit-descriptor %edx 0x10)
11149     #
11150     (write _test-input-stream "fn foo {\n")
11151     (write _test-input-stream "  var a: (array int 3)\n")
11152     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0, 0\n")
11153     (write _test-input-stream "}\n")
11154     # convert
11155     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11156     # registers except esp clobbered at this point
11157     # restore ed
11158     89/<- %edx 4/r32/esp
11159     (flush _test-output-buffered-file)
11160     (flush _test-error-buffered-file)
11161 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
11167     # check output
11168     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-many-inouts: output should be empty")
11169     (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")
11170     # check that stop(1) was called
11171     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-many-inouts: exit status")
11172     # don't restore from ebp
11173     81 0/subop/add %esp 8/imm32
11174     # . epilogue
11175     5d/pop-to-ebp
11176     c3/return
11177 
11178 test-compute-offset-with-no-output:
11179     # . prologue
11180     55/push-ebp
11181     89/<- %ebp 4/r32/esp
11182     # setup
11183     (clear-stream _test-input-stream)
11184     (clear-stream $_test-input-buffered-file->buffer)
11185     (clear-stream _test-output-stream)
11186     (clear-stream $_test-output-buffered-file->buffer)
11187     (clear-stream _test-error-stream)
11188     (clear-stream $_test-error-buffered-file->buffer)
11189     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11190     68/push 0/imm32
11191     68/push 0/imm32
11192     89/<- %edx 4/r32/esp
11193     (tailor-exit-descriptor %edx 0x10)
11194     #
11195     (write _test-input-stream "fn foo {\n")
11196     (write _test-input-stream "  var a: (array int 3)\n")
11197     (write _test-input-stream "  compute-offset a, 0\n")
11198     (write _test-input-stream "}\n")
11199     # convert
11200     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11201     # registers except esp clobbered at this point
11202     # restore ed
11203     89/<- %edx 4/r32/esp
11204     (flush _test-output-buffered-file)
11205     (flush _test-error-buffered-file)
11206 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
11212     # check output
11213     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-no-output: output should be empty")
11214     (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")
11215     # check that stop(1) was called
11216     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-no-output: exit status")
11217     # don't restore from ebp
11218     81 0/subop/add %esp 8/imm32
11219     # . epilogue
11220     5d/pop-to-ebp
11221     c3/return
11222 
11223 test-compute-offset-with-too-many-outputs:
11224     # . prologue
11225     55/push-ebp
11226     89/<- %ebp 4/r32/esp
11227     # setup
11228     (clear-stream _test-input-stream)
11229     (clear-stream $_test-input-buffered-file->buffer)
11230     (clear-stream _test-output-stream)
11231     (clear-stream $_test-output-buffered-file->buffer)
11232     (clear-stream _test-error-stream)
11233     (clear-stream $_test-error-buffered-file->buffer)
11234     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11235     68/push 0/imm32
11236     68/push 0/imm32
11237     89/<- %edx 4/r32/esp
11238     (tailor-exit-descriptor %edx 0x10)
11239     #
11240     (write _test-input-stream "fn foo {\n")
11241     (write _test-input-stream "  var a: (array int 3)\n")
11242     (write _test-input-stream "  var b/eax: (offset int) <- compute-offset a, 0\n")
11243     (write _test-input-stream "  var c/ecx: (addr int) <- copy 0\n")
11244     (write _test-input-stream "  b, c <- compute-offset a, 0\n")
11245     (write _test-input-stream "}\n")
11246     # convert
11247     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11248     # registers except esp clobbered at this point
11249     # restore ed
11250     89/<- %edx 4/r32/esp
11251     (flush _test-output-buffered-file)
11252     (flush _test-error-buffered-file)
11253 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
11259     # check output
11260     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-many-outputs: output should be empty")
11261     (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")
11262     # check that stop(1) was called
11263     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-many-outputs: exit status")
11264     # don't restore from ebp
11265     81 0/subop/add %esp 8/imm32
11266     # . epilogue
11267     5d/pop-to-ebp
11268     c3/return
11269 
11270 test-convert-read-from-stream:
11271     # . prologue
11272     55/push-ebp
11273     89/<- %ebp 4/r32/esp
11274     # setup
11275     (clear-stream _test-input-stream)
11276     (clear-stream $_test-input-buffered-file->buffer)
11277     (clear-stream _test-output-stream)
11278     (clear-stream $_test-output-buffered-file->buffer)
11279     #
11280     (write _test-input-stream "fn foo {\n")
11281     (write _test-input-stream "  var s/esi: (addr stream int) <- copy 0\n")
11282     (write _test-input-stream "  var o/ecx: (addr int) <- copy 0\n")
11283     (write _test-input-stream "  read-from-stream s, o\n")
11284     (write _test-input-stream "}\n")
11285     # convert
11286     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
11287     # registers except esp clobbered at this point
11288     # restore ed
11289     89/<- %edx 4/r32/esp
11290     (flush _test-output-buffered-file)
11291     (flush _test-error-buffered-file)
11292 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
11298     # check output
11299     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-read-from-stream/0")
11300     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-read-from-stream/1")
11301     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-read-from-stream/2")
11302     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-read-from-stream/3")
11303     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-read-from-stream/4")
11304     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-read-from-stream/5")
11305     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-read-from-stream/6")
11306     (check-next-stream-line-equal _test-output-stream "    be/copy-to-esi 0/imm32"      "F - test-convert-read-from-stream/7")
11307     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-read-from-stream/8")
11308     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"      "F - test-convert-read-from-stream/9")
11309     (check-next-stream-line-equal _test-output-stream "    (read-from-stream %esi %ecx 0x00000004)"  "F - test-convert-read-from-stream/10")
11310     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-read-from-stream/11")
11311     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-read-from-stream/12")
11312     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-read-from-stream/13")
11313     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-read-from-stream/14")
11314     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-read-from-stream/15")
11315     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-read-from-stream/16")
11316     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-read-from-stream/17")
11317     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-read-from-stream/18")
11318     # . epilogue
11319     89/<- %esp 5/r32/ebp
11320     5d/pop-to-ebp
11321     c3/return
11322 
11323 test-convert-read-from-stream-with-correct-payload-size:
11324     # . prologue
11325     55/push-ebp
11326     89/<- %ebp 4/r32/esp
11327     # setup
11328     (clear-stream _test-input-stream)
11329     (clear-stream $_test-input-buffered-file->buffer)
11330     (clear-stream _test-output-stream)
11331     (clear-stream $_test-output-buffered-file->buffer)
11332     #
11333     (write _test-input-stream "fn foo {\n")
11334     (write _test-input-stream "  var s/esi: (addr stream handle int) <- copy 0\n")
11335     (write _test-input-stream "  var o/ecx: (addr handle int) <- copy 0\n")
11336     (write _test-input-stream "  read-from-stream s, o\n")
11337     (write _test-input-stream "}\n")
11338     # convert
11339     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
11340     # registers except esp clobbered at this point
11341     # restore ed
11342     89/<- %edx 4/r32/esp
11343     (flush _test-output-buffered-file)
11344     (flush _test-error-buffered-file)
11345 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
11351     # check output
11352     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-read-from-stream-with-correct-payload-size/0")
11353     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-read-from-stream-with-correct-payload-size/1")
11354     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-read-from-stream-with-correct-payload-size/2")
11355     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-read-from-stream-with-correct-payload-size/3")
11356     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-read-from-stream-with-correct-payload-size/4")
11357     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-read-from-stream-with-correct-payload-size/5")
11358     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-read-from-stream-with-correct-payload-size/6")
11359     (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")
11360     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-read-from-stream-with-correct-payload-size/8")
11361     (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")
11362     (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")
11363     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-read-from-stream-with-correct-payload-size/11")
11364     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-read-from-stream-with-correct-payload-size/12")
11365     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-read-from-stream-with-correct-payload-size/13")
11366     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-read-from-stream-with-correct-payload-size/14")
11367     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-read-from-stream-with-correct-payload-size/15")
11368     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-read-from-stream-with-correct-payload-size/16")
11369     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-read-from-stream-with-correct-payload-size/17")
11370     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-read-from-stream-with-correct-payload-size/18")
11371     # . epilogue
11372     89/<- %esp 5/r32/ebp
11373     5d/pop-to-ebp
11374     c3/return
11375 
11376 test-read-from-stream-with-non-stream-atom-base-type:
11377     # . prologue
11378     55/push-ebp
11379     89/<- %ebp 4/r32/esp
11380     # setup
11381     (clear-stream _test-input-stream)
11382     (clear-stream $_test-input-buffered-file->buffer)
11383     (clear-stream _test-output-stream)
11384     (clear-stream $_test-output-buffered-file->buffer)
11385     (clear-stream _test-error-stream)
11386     (clear-stream $_test-error-buffered-file->buffer)
11387     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11388     68/push 0/imm32
11389     68/push 0/imm32
11390     89/<- %edx 4/r32/esp
11391     (tailor-exit-descriptor %edx 0x10)
11392     #
11393     (write _test-input-stream "fn foo {\n")
11394     (write _test-input-stream "  var a: int\n")
11395     (write _test-input-stream "  read-from-stream a, 0\n")
11396     (write _test-input-stream "}\n")
11397     # convert
11398     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11399     # registers except esp clobbered at this point
11400     # restore ed
11401     89/<- %edx 4/r32/esp
11402     (flush _test-output-buffered-file)
11403     (flush _test-error-buffered-file)
11404 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
11410     # check output
11411     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-atom-base-type: output should be empty")
11412     (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")
11413     # check that stop(1) was called
11414     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-atom-base-type: exit status")
11415     # don't restore from ebp
11416     81 0/subop/add %esp 8/imm32
11417     # . epilogue
11418     5d/pop-to-ebp
11419     c3/return
11420 
11421 test-read-from-stream-with-non-stream-compound-base-type:
11422     # . prologue
11423     55/push-ebp
11424     89/<- %ebp 4/r32/esp
11425     # setup
11426     (clear-stream _test-input-stream)
11427     (clear-stream $_test-input-buffered-file->buffer)
11428     (clear-stream _test-output-stream)
11429     (clear-stream $_test-output-buffered-file->buffer)
11430     (clear-stream _test-error-stream)
11431     (clear-stream $_test-error-buffered-file->buffer)
11432     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11433     68/push 0/imm32
11434     68/push 0/imm32
11435     89/<- %edx 4/r32/esp
11436     (tailor-exit-descriptor %edx 0x10)
11437     #
11438     (write _test-input-stream "fn foo {\n")
11439     (write _test-input-stream "  var a: (handle int)\n")
11440     (write _test-input-stream "  read-from-stream a, 0\n")
11441     (write _test-input-stream "}\n")
11442     # convert
11443     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11444     # registers except esp clobbered at this point
11445     # restore ed
11446     89/<- %edx 4/r32/esp
11447     (flush _test-output-buffered-file)
11448     (flush _test-error-buffered-file)
11449 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
11455     # check output
11456     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-compound-base-type: output should be empty")
11457     (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")
11458     # check that stop(1) was called
11459     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-compound-base-type: exit status")
11460     # don't restore from ebp
11461     81 0/subop/add %esp 8/imm32
11462     # . epilogue
11463     5d/pop-to-ebp
11464     c3/return
11465 
11466 test-read-from-stream-with-non-stream-compound-base-type-2:
11467     # . prologue
11468     55/push-ebp
11469     89/<- %ebp 4/r32/esp
11470     # setup
11471     (clear-stream _test-input-stream)
11472     (clear-stream $_test-input-buffered-file->buffer)
11473     (clear-stream _test-output-stream)
11474     (clear-stream $_test-output-buffered-file->buffer)
11475     (clear-stream _test-error-stream)
11476     (clear-stream $_test-error-buffered-file->buffer)
11477     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11478     68/push 0/imm32
11479     68/push 0/imm32
11480     89/<- %edx 4/r32/esp
11481     (tailor-exit-descriptor %edx 0x10)
11482     #
11483     (write _test-input-stream "fn foo {\n")
11484     (write _test-input-stream "  var a: (addr int)\n")
11485     (write _test-input-stream "  read-from-stream a, 0\n")
11486     (write _test-input-stream "}\n")
11487     # convert
11488     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11489     # registers except esp clobbered at this point
11490     # restore ed
11491     89/<- %edx 4/r32/esp
11492     (flush _test-output-buffered-file)
11493     (flush _test-error-buffered-file)
11494 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
11500     # check output
11501     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-compound-base-type-2: output should be empty")
11502     (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")
11503     # check that stop(1) was called
11504     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-compound-base-type-2: exit status")
11505     # don't restore from ebp
11506     81 0/subop/add %esp 8/imm32
11507     # . epilogue
11508     5d/pop-to-ebp
11509     c3/return
11510 
11511 test-read-from-stream-with-stream-atom-base-type:
11512     # . prologue
11513     55/push-ebp
11514     89/<- %ebp 4/r32/esp
11515     # setup
11516     (clear-stream _test-input-stream)
11517     (clear-stream $_test-input-buffered-file->buffer)
11518     (clear-stream _test-output-stream)
11519     (clear-stream $_test-output-buffered-file->buffer)
11520     (clear-stream _test-error-stream)
11521     (clear-stream $_test-error-buffered-file->buffer)
11522     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11523     68/push 0/imm32
11524     68/push 0/imm32
11525     89/<- %edx 4/r32/esp
11526     (tailor-exit-descriptor %edx 0x10)
11527     #
11528     (write _test-input-stream "fn foo {\n")
11529     (write _test-input-stream "  var a: stream\n")
11530     (write _test-input-stream "  read-from-stream a, 0\n")
11531     (write _test-input-stream "}\n")
11532     # convert
11533     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11534     # registers except esp clobbered at this point
11535     # restore ed
11536     89/<- %edx 4/r32/esp
11537     (flush _test-output-buffered-file)
11538     (flush _test-error-buffered-file)
11539 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
11545     # check output
11546     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-stream-atom-base-type: output should be empty")
11547     (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")
11548     # check that stop(1) was called
11549     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-stream-atom-base-type: exit status")
11550     # don't restore from ebp
11551     81 0/subop/add %esp 8/imm32
11552     # . epilogue
11553     5d/pop-to-ebp
11554     c3/return
11555 
11556 test-read-from-stream-with-wrong-index-type:
11557     # . prologue
11558     55/push-ebp
11559     89/<- %ebp 4/r32/esp
11560     # setup
11561     (clear-stream _test-input-stream)
11562     (clear-stream $_test-input-buffered-file->buffer)
11563     (clear-stream _test-output-stream)
11564     (clear-stream $_test-output-buffered-file->buffer)
11565     (clear-stream _test-error-stream)
11566     (clear-stream $_test-error-buffered-file->buffer)
11567     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11568     68/push 0/imm32
11569     68/push 0/imm32
11570     89/<- %edx 4/r32/esp
11571     (tailor-exit-descriptor %edx 0x10)
11572     #
11573     (write _test-input-stream "fn foo {\n")
11574     (write _test-input-stream "  var a/eax: (addr stream int) <- copy 0\n")
11575     (write _test-input-stream "  var b: boolean\n")
11576     (write _test-input-stream "  read-from-stream a, b\n")
11577     (write _test-input-stream "}\n")
11578     # convert
11579     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11580     # registers except esp clobbered at this point
11581     # restore ed
11582     89/<- %edx 4/r32/esp
11583     (flush _test-output-buffered-file)
11584     (flush _test-error-buffered-file)
11585 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
11591     # check output
11592     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-wrong-index-type: output should be empty")
11593     (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")
11594     # check that stop(1) was called
11595     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-wrong-index-type: exit status")
11596     # don't restore from ebp
11597     81 0/subop/add %esp 8/imm32
11598     # . epilogue
11599     5d/pop-to-ebp
11600     c3/return
11601 
11602 test-read-from-stream-with-no-inouts:
11603     # . prologue
11604     55/push-ebp
11605     89/<- %ebp 4/r32/esp
11606     # setup
11607     (clear-stream _test-input-stream)
11608     (clear-stream $_test-input-buffered-file->buffer)
11609     (clear-stream _test-output-stream)
11610     (clear-stream $_test-output-buffered-file->buffer)
11611     (clear-stream _test-error-stream)
11612     (clear-stream $_test-error-buffered-file->buffer)
11613     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11614     68/push 0/imm32
11615     68/push 0/imm32
11616     89/<- %edx 4/r32/esp
11617     (tailor-exit-descriptor %edx 0x10)
11618     #
11619     (write _test-input-stream "fn foo {\n")
11620     (write _test-input-stream "  read-from-stream\n")
11621     (write _test-input-stream "}\n")
11622     # convert
11623     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11624     # registers except esp clobbered at this point
11625     # restore ed
11626     89/<- %edx 4/r32/esp
11627     (flush _test-output-buffered-file)
11628     (flush _test-error-buffered-file)
11629 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
11635     # check output
11636     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-no-inouts: output should be empty")
11637     (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")
11638     # check that stop(1) was called
11639     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-no-inouts: exit status")
11640     # don't restore from ebp
11641     81 0/subop/add %esp 8/imm32
11642     # . epilogue
11643     5d/pop-to-ebp
11644     c3/return
11645 
11646 test-read-from-stream-with-too-few-inouts:
11647     # . prologue
11648     55/push-ebp
11649     89/<- %ebp 4/r32/esp
11650     # setup
11651     (clear-stream _test-input-stream)
11652     (clear-stream $_test-input-buffered-file->buffer)
11653     (clear-stream _test-output-stream)
11654     (clear-stream $_test-output-buffered-file->buffer)
11655     (clear-stream _test-error-stream)
11656     (clear-stream $_test-error-buffered-file->buffer)
11657     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11658     68/push 0/imm32
11659     68/push 0/imm32
11660     89/<- %edx 4/r32/esp
11661     (tailor-exit-descriptor %edx 0x10)
11662     #
11663     (write _test-input-stream "fn foo {\n")
11664     (write _test-input-stream "  var a: (addr stream int)\n")
11665     (write _test-input-stream "  read-from-stream a\n")
11666     (write _test-input-stream "}\n")
11667     # convert
11668     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11669     # registers except esp clobbered at this point
11670     # restore ed
11671     89/<- %edx 4/r32/esp
11672     (flush _test-output-buffered-file)
11673     (flush _test-error-buffered-file)
11674 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
11680     # check output
11681     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-too-few-inouts: output should be empty")
11682     (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")
11683     # check that stop(1) was called
11684     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-too-few-inouts: exit status")
11685     # don't restore from ebp
11686     81 0/subop/add %esp 8/imm32
11687     # . epilogue
11688     5d/pop-to-ebp
11689     c3/return
11690 
11691 test-read-from-stream-with-too-many-inouts:
11692     # . prologue
11693     55/push-ebp
11694     89/<- %ebp 4/r32/esp
11695     # setup
11696     (clear-stream _test-input-stream)
11697     (clear-stream $_test-input-buffered-file->buffer)
11698     (clear-stream _test-output-stream)
11699     (clear-stream $_test-output-buffered-file->buffer)
11700     (clear-stream _test-error-stream)
11701     (clear-stream $_test-error-buffered-file->buffer)
11702     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11703     68/push 0/imm32
11704     68/push 0/imm32
11705     89/<- %edx 4/r32/esp
11706     (tailor-exit-descriptor %edx 0x10)
11707     #
11708     (write _test-input-stream "fn foo {\n")
11709     (write _test-input-stream "  var a: (addr stream int)\n")
11710     (write _test-input-stream "  var b: (addr int)\n")
11711     (write _test-input-stream "  read-from-stream a, b, 0\n")
11712     (write _test-input-stream "}\n")
11713     # convert
11714     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11715     # registers except esp clobbered at this point
11716     # restore ed
11717     89/<- %edx 4/r32/esp
11718     (flush _test-output-buffered-file)
11719     (flush _test-error-buffered-file)
11720 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
11726     # check output
11727     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-too-many-inouts: output should be empty")
11728     (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")
11729     # check that stop(1) was called
11730     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-too-many-inouts: exit status")
11731     # don't restore from ebp
11732     81 0/subop/add %esp 8/imm32
11733     # . epilogue
11734     5d/pop-to-ebp
11735     c3/return
11736 
11737 test-read-from-stream-with-output:
11738     # . prologue
11739     55/push-ebp
11740     89/<- %ebp 4/r32/esp
11741     # setup
11742     (clear-stream _test-input-stream)
11743     (clear-stream $_test-input-buffered-file->buffer)
11744     (clear-stream _test-output-stream)
11745     (clear-stream $_test-output-buffered-file->buffer)
11746     (clear-stream _test-error-stream)
11747     (clear-stream $_test-error-buffered-file->buffer)
11748     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11749     68/push 0/imm32
11750     68/push 0/imm32
11751     89/<- %edx 4/r32/esp
11752     (tailor-exit-descriptor %edx 0x10)
11753     #
11754     (write _test-input-stream "fn foo {\n")
11755     (write _test-input-stream "  var a: (addr stream int)\n")
11756     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
11757     (write _test-input-stream "  b <- read-from-stream a, b\n")
11758     (write _test-input-stream "}\n")
11759     # convert
11760     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11761     # registers except esp clobbered at this point
11762     # restore ed
11763     89/<- %edx 4/r32/esp
11764     (flush _test-output-buffered-file)
11765     (flush _test-error-buffered-file)
11766 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
11772     # check output
11773     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-output: output should be empty")
11774     (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")
11775     # check that stop(1) was called
11776     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-output: exit status")
11777     # don't restore from ebp
11778     81 0/subop/add %esp 8/imm32
11779     # . epilogue
11780     5d/pop-to-ebp
11781     c3/return
11782 
11783 test-convert-write-to-stream:
11784     # . prologue
11785     55/push-ebp
11786     89/<- %ebp 4/r32/esp
11787     # setup
11788     (clear-stream _test-input-stream)
11789     (clear-stream $_test-input-buffered-file->buffer)
11790     (clear-stream _test-output-stream)
11791     (clear-stream $_test-output-buffered-file->buffer)
11792     #
11793     (write _test-input-stream "fn foo {\n")
11794     (write _test-input-stream "  var s/esi: (addr stream int) <- copy 0\n")
11795     (write _test-input-stream "  var o/ecx: (addr int) <- copy 0\n")
11796     (write _test-input-stream "  write-to-stream s, o\n")
11797     (write _test-input-stream "}\n")
11798     # convert
11799     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
11800     # registers except esp clobbered at this point
11801     # restore ed
11802     89/<- %edx 4/r32/esp
11803     (flush _test-output-buffered-file)
11804     (flush _test-error-buffered-file)
11805 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
11811     # check output
11812     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-write-to-stream/0")
11813     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-write-to-stream/1")
11814     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-write-to-stream/2")
11815     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-write-to-stream/3")
11816     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-write-to-stream/4")
11817     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-write-to-stream/5")
11818     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-write-to-stream/6")
11819     (check-next-stream-line-equal _test-output-stream "    be/copy-to-esi 0/imm32"      "F - test-convert-write-to-stream/7")
11820     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-write-to-stream/8")
11821     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"      "F - test-convert-write-to-stream/9")
11822     (check-next-stream-line-equal _test-output-stream "    (write-to-stream %esi %ecx 0x00000004)"  "F - test-convert-write-to-stream/10")
11823     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-write-to-stream/11")
11824     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-write-to-stream/12")
11825     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-write-to-stream/13")
11826     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-write-to-stream/14")
11827     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-write-to-stream/15")
11828     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-write-to-stream/16")
11829     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-write-to-stream/17")
11830     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-write-to-stream/18")
11831     # . epilogue
11832     89/<- %esp 5/r32/ebp
11833     5d/pop-to-ebp
11834     c3/return
11835 
11836 test-convert-write-to-stream-with-correct-payload-size:
11837     # . prologue
11838     55/push-ebp
11839     89/<- %ebp 4/r32/esp
11840     # setup
11841     (clear-stream _test-input-stream)
11842     (clear-stream $_test-input-buffered-file->buffer)
11843     (clear-stream _test-output-stream)
11844     (clear-stream $_test-output-buffered-file->buffer)
11845     #
11846     (write _test-input-stream "fn foo {\n")
11847     (write _test-input-stream "  var s/esi: (addr stream handle int) <- copy 0\n")
11848     (write _test-input-stream "  var o/ecx: (addr handle int) <- copy 0\n")
11849     (write _test-input-stream "  write-to-stream s, o\n")
11850     (write _test-input-stream "}\n")
11851     # convert
11852     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
11853     # registers except esp clobbered at this point
11854     # restore ed
11855     89/<- %edx 4/r32/esp
11856     (flush _test-output-buffered-file)
11857     (flush _test-error-buffered-file)
11858 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
11864     # check output
11865     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-write-to-stream-with-correct-payload-size/0")
11866     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-write-to-stream-with-correct-payload-size/1")
11867     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-write-to-stream-with-correct-payload-size/2")
11868     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-write-to-stream-with-correct-payload-size/3")
11869     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-write-to-stream-with-correct-payload-size/4")
11870     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-write-to-stream-with-correct-payload-size/5")
11871     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-write-to-stream-with-correct-payload-size/6")
11872     (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")
11873     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-write-to-stream-with-correct-payload-size/8")
11874     (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")
11875     (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")
11876     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-write-to-stream-with-correct-payload-size/11")
11877     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-write-to-stream-with-correct-payload-size/12")
11878     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-write-to-stream-with-correct-payload-size/13")
11879     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-write-to-stream-with-correct-payload-size/14")
11880     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-write-to-stream-with-correct-payload-size/15")
11881     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-write-to-stream-with-correct-payload-size/16")
11882     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-write-to-stream-with-correct-payload-size/17")
11883     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-write-to-stream-with-correct-payload-size/18")
11884     # . epilogue
11885     89/<- %esp 5/r32/ebp
11886     5d/pop-to-ebp
11887     c3/return
11888 
11889 test-write-to-stream-with-non-stream-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: int\n")
11908     (write _test-input-stream "  write-to-stream 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-write-to-stream-with-non-stream-atom-base-type: output should be empty")
11925     (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")
11926     # check that stop(1) was called
11927     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-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-write-to-stream-with-non-stream-compound-base-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: (handle int)\n")
11953     (write _test-input-stream "  write-to-stream a, 0\n")
11954     (write _test-input-stream "}\n")
11955     # convert
11956     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11957     # registers except esp clobbered at this point
11958     # restore ed
11959     89/<- %edx 4/r32/esp
11960     (flush _test-output-buffered-file)
11961     (flush _test-error-buffered-file)
11962 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
11968     # check output
11969     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-compound-base-type: output should be empty")
11970     (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")
11971     # check that stop(1) was called
11972     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-compound-base-type: exit status")
11973     # don't restore from ebp
11974     81 0/subop/add %esp 8/imm32
11975     # . epilogue
11976     5d/pop-to-ebp
11977     c3/return
11978 
11979 test-write-to-stream-with-non-stream-compound-base-type-2:
11980     # . prologue
11981     55/push-ebp
11982     89/<- %ebp 4/r32/esp
11983     # setup
11984     (clear-stream _test-input-stream)
11985     (clear-stream $_test-input-buffered-file->buffer)
11986     (clear-stream _test-output-stream)
11987     (clear-stream $_test-output-buffered-file->buffer)
11988     (clear-stream _test-error-stream)
11989     (clear-stream $_test-error-buffered-file->buffer)
11990     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11991     68/push 0/imm32
11992     68/push 0/imm32
11993     89/<- %edx 4/r32/esp
11994     (tailor-exit-descriptor %edx 0x10)
11995     #
11996     (write _test-input-stream "fn foo {\n")
11997     (write _test-input-stream "  var a: (addr int)\n")
11998     (write _test-input-stream "  write-to-stream a, 0\n")
11999     (write _test-input-stream "}\n")
12000     # convert
12001     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12002     # registers except esp clobbered at this point
12003     # restore ed
12004     89/<- %edx 4/r32/esp
12005     (flush _test-output-buffered-file)
12006     (flush _test-error-buffered-file)
12007 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
12013     # check output
12014     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-compound-base-type-2: output should be empty")
12015     (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")
12016     # check that stop(1) was called
12017     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-compound-base-type-2: exit status")
12018     # don't restore from ebp
12019     81 0/subop/add %esp 8/imm32
12020     # . epilogue
12021     5d/pop-to-ebp
12022     c3/return
12023 
12024 test-write-to-stream-with-stream-atom-base-type:
12025     # . prologue
12026     55/push-ebp
12027     89/<- %ebp 4/r32/esp
12028     # setup
12029     (clear-stream _test-input-stream)
12030     (clear-stream $_test-input-buffered-file->buffer)
12031     (clear-stream _test-output-stream)
12032     (clear-stream $_test-output-buffered-file->buffer)
12033     (clear-stream _test-error-stream)
12034     (clear-stream $_test-error-buffered-file->buffer)
12035     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12036     68/push 0/imm32
12037     68/push 0/imm32
12038     89/<- %edx 4/r32/esp
12039     (tailor-exit-descriptor %edx 0x10)
12040     #
12041     (write _test-input-stream "fn foo {\n")
12042     (write _test-input-stream "  var a: stream\n")
12043     (write _test-input-stream "  write-to-stream a, 0\n")
12044     (write _test-input-stream "}\n")
12045     # convert
12046     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12047     # registers except esp clobbered at this point
12048     # restore ed
12049     89/<- %edx 4/r32/esp
12050     (flush _test-output-buffered-file)
12051     (flush _test-error-buffered-file)
12052 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
12058     # check output
12059     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-stream-atom-base-type: output should be empty")
12060     (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")
12061     # check that stop(1) was called
12062     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-stream-atom-base-type: exit status")
12063     # don't restore from ebp
12064     81 0/subop/add %esp 8/imm32
12065     # . epilogue
12066     5d/pop-to-ebp
12067     c3/return
12068 
12069 test-write-to-stream-with-wrong-index-type:
12070     # . prologue
12071     55/push-ebp
12072     89/<- %ebp 4/r32/esp
12073     # setup
12074     (clear-stream _test-input-stream)
12075     (clear-stream $_test-input-buffered-file->buffer)
12076     (clear-stream _test-output-stream)
12077     (clear-stream $_test-output-buffered-file->buffer)
12078     (clear-stream _test-error-stream)
12079     (clear-stream $_test-error-buffered-file->buffer)
12080     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12081     68/push 0/imm32
12082     68/push 0/imm32
12083     89/<- %edx 4/r32/esp
12084     (tailor-exit-descriptor %edx 0x10)
12085     #
12086     (write _test-input-stream "fn foo {\n")
12087     (write _test-input-stream "  var a/eax: (addr stream int) <- copy 0\n")
12088     (write _test-input-stream "  var b: boolean\n")
12089     (write _test-input-stream "  write-to-stream a, b\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-write-to-stream-with-wrong-index-type: output should be empty")
12106     (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")
12107     # check that stop(1) was called
12108     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-wrong-index-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-write-to-stream-with-no-inouts:
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 "  write-to-stream\n")
12134     (write _test-input-stream "}\n")
12135     # convert
12136     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12137     # registers except esp clobbered at this point
12138     # restore ed
12139     89/<- %edx 4/r32/esp
12140     (flush _test-output-buffered-file)
12141     (flush _test-error-buffered-file)
12142 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
12148     # check output
12149     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-no-inouts: output should be empty")
12150     (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")
12151     # check that stop(1) was called
12152     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-no-inouts: exit status")
12153     # don't restore from ebp
12154     81 0/subop/add %esp 8/imm32
12155     # . epilogue
12156     5d/pop-to-ebp
12157     c3/return
12158 
12159 test-write-to-stream-with-too-few-inouts:
12160     # . prologue
12161     55/push-ebp
12162     89/<- %ebp 4/r32/esp
12163     # setup
12164     (clear-stream _test-input-stream)
12165     (clear-stream $_test-input-buffered-file->buffer)
12166     (clear-stream _test-output-stream)
12167     (clear-stream $_test-output-buffered-file->buffer)
12168     (clear-stream _test-error-stream)
12169     (clear-stream $_test-error-buffered-file->buffer)
12170     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12171     68/push 0/imm32
12172     68/push 0/imm32
12173     89/<- %edx 4/r32/esp
12174     (tailor-exit-descriptor %edx 0x10)
12175     #
12176     (write _test-input-stream "fn foo {\n")
12177     (write _test-input-stream "  var a: (addr stream int)\n")
12178     (write _test-input-stream "  write-to-stream a\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-write-to-stream-with-too-few-inouts: output should be empty")
12195     (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")
12196     # check that stop(1) was called
12197     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-too-few-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-write-to-stream-with-too-many-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: (addr stream int)\n")
12223     (write _test-input-stream "  var b: (addr int)\n")
12224     (write _test-input-stream "  write-to-stream a, b, 0\n")
12225     (write _test-input-stream "}\n")
12226     # convert
12227     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12228     # registers except esp clobbered at this point
12229     # restore ed
12230     89/<- %edx 4/r32/esp
12231     (flush _test-output-buffered-file)
12232     (flush _test-error-buffered-file)
12233 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
12239     # check output
12240     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-too-many-inouts: output should be empty")
12241     (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")
12242     # check that stop(1) was called
12243     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-too-many-inouts: exit status")
12244     # don't restore from ebp
12245     81 0/subop/add %esp 8/imm32
12246     # . epilogue
12247     5d/pop-to-ebp
12248     c3/return
12249 
12250 test-write-to-stream-with-output:
12251     # . prologue
12252     55/push-ebp
12253     89/<- %ebp 4/r32/esp
12254     # setup
12255     (clear-stream _test-input-stream)
12256     (clear-stream $_test-input-buffered-file->buffer)
12257     (clear-stream _test-output-stream)
12258     (clear-stream $_test-output-buffered-file->buffer)
12259     (clear-stream _test-error-stream)
12260     (clear-stream $_test-error-buffered-file->buffer)
12261     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12262     68/push 0/imm32
12263     68/push 0/imm32
12264     89/<- %edx 4/r32/esp
12265     (tailor-exit-descriptor %edx 0x10)
12266     #
12267     (write _test-input-stream "fn foo {\n")
12268     (write _test-input-stream "  var a: (addr stream int)\n")
12269     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
12270     (write _test-input-stream "  b <- write-to-stream a, b\n")
12271     (write _test-input-stream "}\n")
12272     # convert
12273     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12274     # registers except esp clobbered at this point
12275     # restore ed
12276     89/<- %edx 4/r32/esp
12277     (flush _test-output-buffered-file)
12278     (flush _test-error-buffered-file)
12279 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
12285     # check output
12286     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-output: output should be empty")
12287     (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")
12288     # check that stop(1) was called
12289     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-output: exit status")
12290     # don't restore from ebp
12291     81 0/subop/add %esp 8/imm32
12292     # . epilogue
12293     5d/pop-to-ebp
12294     c3/return
12295 
12296 test-length-with-non-array-atom-base-type:
12297     # . prologue
12298     55/push-ebp
12299     89/<- %ebp 4/r32/esp
12300     # setup
12301     (clear-stream _test-input-stream)
12302     (clear-stream $_test-input-buffered-file->buffer)
12303     (clear-stream _test-output-stream)
12304     (clear-stream $_test-output-buffered-file->buffer)
12305     (clear-stream _test-error-stream)
12306     (clear-stream $_test-error-buffered-file->buffer)
12307     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12308     68/push 0/imm32
12309     68/push 0/imm32
12310     89/<- %edx 4/r32/esp
12311     (tailor-exit-descriptor %edx 0x10)
12312     #
12313     (write _test-input-stream "fn foo {\n")
12314     (write _test-input-stream "  var a: int\n")
12315     (write _test-input-stream "  var c/ecx: int <- length a\n")
12316     (write _test-input-stream "}\n")
12317     # convert
12318     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12319     # registers except esp clobbered at this point
12320     # restore ed
12321     89/<- %edx 4/r32/esp
12322     (flush _test-output-buffered-file)
12323     (flush _test-error-buffered-file)
12324 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
12330     # check output
12331     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-atom-base-type: output should be empty")
12332     (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")
12333     # check that stop(1) was called
12334     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-atom-base-type: exit status")
12335     # don't restore from ebp
12336     81 0/subop/add %esp 8/imm32
12337     # . epilogue
12338     5d/pop-to-ebp
12339     c3/return
12340 
12341 test-length-with-non-array-compound-base-type:
12342     # . prologue
12343     55/push-ebp
12344     89/<- %ebp 4/r32/esp
12345     # setup
12346     (clear-stream _test-input-stream)
12347     (clear-stream $_test-input-buffered-file->buffer)
12348     (clear-stream _test-output-stream)
12349     (clear-stream $_test-output-buffered-file->buffer)
12350     (clear-stream _test-error-stream)
12351     (clear-stream $_test-error-buffered-file->buffer)
12352     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12353     68/push 0/imm32
12354     68/push 0/imm32
12355     89/<- %edx 4/r32/esp
12356     (tailor-exit-descriptor %edx 0x10)
12357     #
12358     (write _test-input-stream "fn foo {\n")
12359     (write _test-input-stream "  var a: (handle int)\n")
12360     (write _test-input-stream "  var c/ecx: (addr int) <- length 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-length-with-non-array-compound-base-type: output should be empty")
12377     (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")
12378     # check that stop(1) was called
12379     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-compound-base-type: 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-length-with-non-array-compound-base-type-2:
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     (clear-stream _test-error-stream)
12396     (clear-stream $_test-error-buffered-file->buffer)
12397     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12398     68/push 0/imm32
12399     68/push 0/imm32
12400     89/<- %edx 4/r32/esp
12401     (tailor-exit-descriptor %edx 0x10)
12402     #
12403     (write _test-input-stream "fn foo {\n")
12404     (write _test-input-stream "  var a: (addr int)\n")
12405     (write _test-input-stream "  var c/ecx: (addr int) <- length a, 0\n")
12406     (write _test-input-stream "}\n")
12407     # convert
12408     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12409     # registers except esp clobbered at this point
12410     # restore ed
12411     89/<- %edx 4/r32/esp
12412     (flush _test-output-buffered-file)
12413     (flush _test-error-buffered-file)
12414 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
12420     # check output
12421     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-compound-base-type-2: output should be empty")
12422     (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")
12423     # check that stop(1) was called
12424     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-compound-base-type-2: exit status")
12425     # don't restore from ebp
12426     81 0/subop/add %esp 8/imm32
12427     # . epilogue
12428     5d/pop-to-ebp
12429     c3/return
12430 
12431 test-length-with-array-atom-base-type:
12432     # . prologue
12433     55/push-ebp
12434     89/<- %ebp 4/r32/esp
12435     # setup
12436     (clear-stream _test-input-stream)
12437     (clear-stream $_test-input-buffered-file->buffer)
12438     (clear-stream _test-output-stream)
12439     (clear-stream $_test-output-buffered-file->buffer)
12440     (clear-stream _test-error-stream)
12441     (clear-stream $_test-error-buffered-file->buffer)
12442     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12443     68/push 0/imm32
12444     68/push 0/imm32
12445     89/<- %edx 4/r32/esp
12446     (tailor-exit-descriptor %edx 0x10)
12447     #
12448     (write _test-input-stream "fn foo {\n")
12449     (write _test-input-stream "  var a: array\n")
12450     (write _test-input-stream "  var c/ecx: (addr int) <- length a\n")
12451     (write _test-input-stream "}\n")
12452     # convert
12453     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12454     # registers except esp clobbered at this point
12455     # restore ed
12456     89/<- %edx 4/r32/esp
12457     (flush _test-output-buffered-file)
12458     (flush _test-error-buffered-file)
12459 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
12465     # check output
12466     (check-stream-equal _test-output-stream  ""  "F - test-length-with-array-atom-base-type: output should be empty")
12467     (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")
12468     # check that stop(1) was called
12469     (check-ints-equal *(edx+4) 2 "F - test-length-with-array-atom-base-type: exit status")
12470     # don't restore from ebp
12471     81 0/subop/add %esp 8/imm32
12472     # . epilogue
12473     5d/pop-to-ebp
12474     c3/return
12475 
12476 test-length-with-addr-base-on-stack:
12477     # . prologue
12478     55/push-ebp
12479     89/<- %ebp 4/r32/esp
12480     # setup
12481     (clear-stream _test-input-stream)
12482     (clear-stream $_test-input-buffered-file->buffer)
12483     (clear-stream _test-output-stream)
12484     (clear-stream $_test-output-buffered-file->buffer)
12485     (clear-stream _test-error-stream)
12486     (clear-stream $_test-error-buffered-file->buffer)
12487     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12488     68/push 0/imm32
12489     68/push 0/imm32
12490     89/<- %edx 4/r32/esp
12491     (tailor-exit-descriptor %edx 0x10)
12492     #
12493     (write _test-input-stream "fn foo {\n")
12494     (write _test-input-stream "  var a: (addr array int)\n")
12495     (write _test-input-stream "  var c/ecx: (addr int) <- length a\n")
12496     (write _test-input-stream "}\n")
12497     # convert
12498     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12499     # registers except esp clobbered at this point
12500     # restore ed
12501     89/<- %edx 4/r32/esp
12502     (flush _test-output-buffered-file)
12503     (flush _test-error-buffered-file)
12504 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
12510     # check output
12511     (check-stream-equal _test-output-stream  ""  "F - test-length-with-addr-base-on-stack: output should be empty")
12512     (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")
12513     # check that stop(1) was called
12514     (check-ints-equal *(edx+4) 2 "F - test-length-with-addr-base-on-stack: exit status")
12515     # don't restore from ebp
12516     81 0/subop/add %esp 8/imm32
12517     # . epilogue
12518     5d/pop-to-ebp
12519     c3/return
12520 
12521 test-length-with-wrong-output-type:
12522     # . prologue
12523     55/push-ebp
12524     89/<- %ebp 4/r32/esp
12525     # setup
12526     (clear-stream _test-input-stream)
12527     (clear-stream $_test-input-buffered-file->buffer)
12528     (clear-stream _test-output-stream)
12529     (clear-stream $_test-output-buffered-file->buffer)
12530     (clear-stream _test-error-stream)
12531     (clear-stream $_test-error-buffered-file->buffer)
12532     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12533     68/push 0/imm32
12534     68/push 0/imm32
12535     89/<- %edx 4/r32/esp
12536     (tailor-exit-descriptor %edx 0x10)
12537     #
12538     (write _test-input-stream "fn foo {\n")
12539     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
12540     (write _test-input-stream "  var o/edi: (addr int) <- length a\n")
12541     (write _test-input-stream "}\n")
12542     # convert
12543     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12544     # registers except esp clobbered at this point
12545     # restore ed
12546     89/<- %edx 4/r32/esp
12547     (flush _test-output-buffered-file)
12548     (flush _test-error-buffered-file)
12549 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
12555     # check output
12556     (check-stream-equal _test-output-stream  ""  "F - test-length-with-wrong-output-type: output should be empty")
12557     (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")
12558     # check that stop(1) was called
12559     (check-ints-equal *(edx+4) 2 "F - test-length-with-wrong-output-type: exit status")
12560     # don't restore from ebp
12561     81 0/subop/add %esp 8/imm32
12562     # . epilogue
12563     5d/pop-to-ebp
12564     c3/return
12565 
12566 test-length-with-wrong-output-compound-type:
12567     # . prologue
12568     55/push-ebp
12569     89/<- %ebp 4/r32/esp
12570     # setup
12571     (clear-stream _test-input-stream)
12572     (clear-stream $_test-input-buffered-file->buffer)
12573     (clear-stream _test-output-stream)
12574     (clear-stream $_test-output-buffered-file->buffer)
12575     (clear-stream _test-error-stream)
12576     (clear-stream $_test-error-buffered-file->buffer)
12577     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12578     68/push 0/imm32
12579     68/push 0/imm32
12580     89/<- %edx 4/r32/esp
12581     (tailor-exit-descriptor %edx 0x10)
12582     #
12583     (write _test-input-stream "fn foo {\n")
12584     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
12585     (write _test-input-stream "  var o/edi: (addr handle int) <- length a\n")
12586     (write _test-input-stream "}\n")
12587     # convert
12588     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12589     # registers except esp clobbered at this point
12590     # restore ed
12591     89/<- %edx 4/r32/esp
12592     (flush _test-output-buffered-file)
12593     (flush _test-error-buffered-file)
12594 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
12600     # check output
12601     (check-stream-equal _test-output-stream  ""  "F - test-length-with-wrong-output-compound-type: output should be empty")
12602     (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")
12603     # check that stop(1) was called
12604     (check-ints-equal *(edx+4) 2 "F - test-length-with-wrong-output-compound-type: exit status")
12605     # don't restore from ebp
12606     81 0/subop/add %esp 8/imm32
12607     # . epilogue
12608     5d/pop-to-ebp
12609     c3/return
12610 
12611 test-length-with-no-inouts:
12612     # . prologue
12613     55/push-ebp
12614     89/<- %ebp 4/r32/esp
12615     # setup
12616     (clear-stream _test-input-stream)
12617     (clear-stream $_test-input-buffered-file->buffer)
12618     (clear-stream _test-output-stream)
12619     (clear-stream $_test-output-buffered-file->buffer)
12620     (clear-stream _test-error-stream)
12621     (clear-stream $_test-error-buffered-file->buffer)
12622     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12623     68/push 0/imm32
12624     68/push 0/imm32
12625     89/<- %edx 4/r32/esp
12626     (tailor-exit-descriptor %edx 0x10)
12627     #
12628     (write _test-input-stream "fn foo {\n")
12629     (write _test-input-stream "  var c/ecx: int <- length\n")
12630     (write _test-input-stream "}\n")
12631     # convert
12632     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12633     # registers except esp clobbered at this point
12634     # restore ed
12635     89/<- %edx 4/r32/esp
12636     (flush _test-output-buffered-file)
12637     (flush _test-error-buffered-file)
12638 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
12644     # check output
12645     (check-stream-equal _test-output-stream  ""  "F - test-length-with-no-inouts: output should be empty")
12646     (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")
12647     # check that stop(1) was called
12648     (check-ints-equal *(edx+4) 2 "F - test-length-with-no-inouts: exit status")
12649     # don't restore from ebp
12650     81 0/subop/add %esp 8/imm32
12651     # . epilogue
12652     5d/pop-to-ebp
12653     c3/return
12654 
12655 test-length-with-too-many-inouts:
12656     # . prologue
12657     55/push-ebp
12658     89/<- %ebp 4/r32/esp
12659     # setup
12660     (clear-stream _test-input-stream)
12661     (clear-stream $_test-input-buffered-file->buffer)
12662     (clear-stream _test-output-stream)
12663     (clear-stream $_test-output-buffered-file->buffer)
12664     (clear-stream _test-error-stream)
12665     (clear-stream $_test-error-buffered-file->buffer)
12666     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12667     68/push 0/imm32
12668     68/push 0/imm32
12669     89/<- %edx 4/r32/esp
12670     (tailor-exit-descriptor %edx 0x10)
12671     #
12672     (write _test-input-stream "fn foo {\n")
12673     (write _test-input-stream "  var a: (array int 3)\n")
12674     (write _test-input-stream "  var c/ecx: int <- length a, 0, 0\n")
12675     (write _test-input-stream "}\n")
12676     # convert
12677     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12678     # registers except esp clobbered at this point
12679     # restore ed
12680     89/<- %edx 4/r32/esp
12681     (flush _test-output-buffered-file)
12682     (flush _test-error-buffered-file)
12683 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
12689     # check output
12690     (check-stream-equal _test-output-stream  ""  "F - test-length-with-too-many-inouts: output should be empty")
12691     (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")
12692     # check that stop(1) was called
12693     (check-ints-equal *(edx+4) 2 "F - test-length-with-too-many-inouts: exit status")
12694     # don't restore from ebp
12695     81 0/subop/add %esp 8/imm32
12696     # . epilogue
12697     5d/pop-to-ebp
12698     c3/return
12699 
12700 test-length-with-no-output:
12701     # . prologue
12702     55/push-ebp
12703     89/<- %ebp 4/r32/esp
12704     # setup
12705     (clear-stream _test-input-stream)
12706     (clear-stream $_test-input-buffered-file->buffer)
12707     (clear-stream _test-output-stream)
12708     (clear-stream $_test-output-buffered-file->buffer)
12709     (clear-stream _test-error-stream)
12710     (clear-stream $_test-error-buffered-file->buffer)
12711     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12712     68/push 0/imm32
12713     68/push 0/imm32
12714     89/<- %edx 4/r32/esp
12715     (tailor-exit-descriptor %edx 0x10)
12716     #
12717     (write _test-input-stream "fn foo {\n")
12718     (write _test-input-stream "  var a: (array int 3)\n")
12719     (write _test-input-stream "  length a\n")
12720     (write _test-input-stream "}\n")
12721     # convert
12722     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12723     # registers except esp clobbered at this point
12724     # restore ed
12725     89/<- %edx 4/r32/esp
12726     (flush _test-output-buffered-file)
12727     (flush _test-error-buffered-file)
12728 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
12734     # check output
12735     (check-stream-equal _test-output-stream  ""  "F - test-length-with-no-output: output should be empty")
12736     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: must have an output"  "F - test-length-with-no-output: error message")
12737     # check that stop(1) was called
12738     (check-ints-equal *(edx+4) 2 "F - test-length-with-no-output: exit status")
12739     # don't restore from ebp
12740     81 0/subop/add %esp 8/imm32
12741     # . epilogue
12742     5d/pop-to-ebp
12743     c3/return
12744 
12745 test-length-with-too-many-outputs:
12746     # . prologue
12747     55/push-ebp
12748     89/<- %ebp 4/r32/esp
12749     # setup
12750     (clear-stream _test-input-stream)
12751     (clear-stream $_test-input-buffered-file->buffer)
12752     (clear-stream _test-output-stream)
12753     (clear-stream $_test-output-buffered-file->buffer)
12754     (clear-stream _test-error-stream)
12755     (clear-stream $_test-error-buffered-file->buffer)
12756     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12757     68/push 0/imm32
12758     68/push 0/imm32
12759     89/<- %edx 4/r32/esp
12760     (tailor-exit-descriptor %edx 0x10)
12761     #
12762     (write _test-input-stream "fn foo {\n")
12763     (write _test-input-stream "  var a: (array int 3)\n")
12764     (write _test-input-stream "  var b/eax: int <- copy 0\n")
12765     (write _test-input-stream "  var c/ecx: int <- copy 0\n")
12766     (write _test-input-stream "  b, c <- length a\n")
12767     (write _test-input-stream "}\n")
12768     # convert
12769     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12770     # registers except esp clobbered at this point
12771     # restore ed
12772     89/<- %edx 4/r32/esp
12773     (flush _test-output-buffered-file)
12774     (flush _test-error-buffered-file)
12775 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
12781     # check output
12782     (check-stream-equal _test-output-stream  ""  "F - test-length-with-too-many-outputs: output should be empty")
12783     (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")
12784     # check that stop(1) was called
12785     (check-ints-equal *(edx+4) 2 "F - test-length-with-too-many-outputs: exit status")
12786     # don't restore from ebp
12787     81 0/subop/add %esp 8/imm32
12788     # . epilogue
12789     5d/pop-to-ebp
12790     c3/return
12791 
12792 test-convert-function-with-return-register-and-local:
12793     # . prologue
12794     55/push-ebp
12795     89/<- %ebp 4/r32/esp
12796     # setup
12797     (clear-stream _test-input-stream)
12798     (clear-stream $_test-input-buffered-file->buffer)
12799     (clear-stream _test-output-stream)
12800     (clear-stream $_test-output-buffered-file->buffer)
12801     #
12802     (write _test-input-stream "fn foo -> _/eax: int {\n")
12803     (write _test-input-stream "  var y/eax: int <- copy 3\n")
12804     (write _test-input-stream "  var z/ecx: int <- copy 4\n")
12805     (write _test-input-stream "  return y\n")
12806     (write _test-input-stream "}\n")
12807     # convert
12808     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
12809     (flush _test-output-buffered-file)
12810 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
12816     # check output
12817     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register-and-local/0")
12818     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register-and-local/1")
12819     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register-and-local/2")
12820     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register-and-local/3")
12821     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register-and-local/4")
12822     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register-and-local/5")
12823     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register-and-local/6")
12824     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-convert-function-with-return-register-and-local/7")
12825     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-return-register-and-local/8")
12826     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-convert-function-with-return-register-and-local/9")
12827     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-return-register-and-local/10")
12828     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-function-with-return-register-and-local/11")
12829     (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")
12830     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-register-and-local/13")
12831     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register-and-local/14")
12832     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register-and-local/15")
12833     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register-and-local/16")
12834     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register-and-local/17")
12835     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register-and-local/18")
12836     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register-and-local/19")
12837     # . epilogue
12838     89/<- %esp 5/r32/ebp
12839     5d/pop-to-ebp
12840     c3/return
12841 
12842 test-convert-function-with-return-register-and-local-2:
12843     # . prologue
12844     55/push-ebp
12845     89/<- %ebp 4/r32/esp
12846     # setup
12847     (clear-stream _test-input-stream)
12848     (clear-stream $_test-input-buffered-file->buffer)
12849     (clear-stream _test-output-stream)
12850     (clear-stream $_test-output-buffered-file->buffer)
12851     #
12852     (write _test-input-stream "fn foo -> _/eax: int {\n")
12853     (write _test-input-stream "  var y/eax: int <- copy 3\n")
12854     (write _test-input-stream "  var z/ecx: int <- copy 4\n")
12855     (write _test-input-stream "  return z\n")
12856     (write _test-input-stream "}\n")
12857     # convert
12858     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
12859     (flush _test-output-buffered-file)
12860 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
12866     # check output
12867     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register-and-local-2/0")
12868     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register-and-local-2/1")
12869     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register-and-local-2/2")
12870     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register-and-local-2/3")
12871     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register-and-local-2/4")
12872     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register-and-local-2/5")
12873     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register-and-local-2/6")
12874     (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")
12875     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-return-register-and-local-2/8")
12876     (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")
12877     (check-next-stream-line-equal _test-output-stream "    8b/-> %ecx 0x00000000/r32" "F - test-convert-function-with-return-register-and-local-2/10")
12878     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-function-with-return-register-and-local-2/11")
12879     (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")
12880     (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")
12881     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register-and-local-2/14")
12882     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register-and-local-2/15")
12883     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register-and-local-2/16")
12884     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register-and-local-2/17")
12885     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register-and-local-2/18")
12886     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register-and-local-2/19")
12887     # . epilogue
12888     89/<- %esp 5/r32/ebp
12889     5d/pop-to-ebp
12890     c3/return
12891 
12892 test-convert-function-with-return-float-register-and-local:
12893     # . prologue
12894     55/push-ebp
12895     89/<- %ebp 4/r32/esp
12896     # setup
12897     (clear-stream _test-input-stream)
12898     (clear-stream $_test-input-buffered-file->buffer)
12899     (clear-stream _test-output-stream)
12900     (clear-stream $_test-output-buffered-file->buffer)
12901     #
12902     (write _test-input-stream "fn foo -> _/xmm1: float {\n")
12903     (write _test-input-stream "  var y/eax: int <- copy 3\n")
12904     (write _test-input-stream "  var g/xmm0: float <- convert y\n")
12905     (write _test-input-stream "  var h/xmm1: float <- convert y\n")
12906     (write _test-input-stream "  return g\n")
12907     (write _test-input-stream "}\n")
12908     # convert
12909     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
12910     (flush _test-output-buffered-file)
12911 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
12917     # check output
12918     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-float-register-and-local/0")
12919     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-float-register-and-local/1")
12920     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-float-register-and-local/2")
12921     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-float-register-and-local/3")
12922     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-float-register-and-local/4")
12923     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-float-register-and-local/5")
12924     (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
12925     (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")
12926     (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
12927     (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")
12928     (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")
12929     (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
12930     (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")
12931     (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")
12932     (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
12933     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-floating-point-dereferenced/15")  # reclaim h
12934     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 0/x32"  "F - test-convert-floating-point-dereferenced/16")  # reclaim g
12935     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-floating-point-dereferenced/17")
12936     (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
12937     (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")
12938     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-float-register-and-local/20")
12939     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-float-register-and-local/21")
12940     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-float-register-and-local/22")
12941     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-float-register-and-local/23")
12942     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-float-register-and-local/24")
12943     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-float-register-and-local/25")
12944     # . epilogue
12945     89/<- %esp 5/r32/ebp
12946     5d/pop-to-ebp
12947     c3/return
12948 
12949 test-convert-function-with-return-and-local-vars:
12950     # . prologue
12951     55/push-ebp
12952     89/<- %ebp 4/r32/esp
12953     # setup
12954     (clear-stream _test-input-stream)
12955     (clear-stream $_test-input-buffered-file->buffer)
12956     (clear-stream _test-output-stream)
12957     (clear-stream $_test-output-buffered-file->buffer)
12958     #
12959     (write _test-input-stream "fn foo -> _/eax: int {\n")
12960     (write _test-input-stream "  {\n")
12961     (write _test-input-stream "    var x: int\n")
12962     (write _test-input-stream "    {\n")
12963     (write _test-input-stream "      var y: int\n")
12964     (write _test-input-stream "      return y\n")
12965     (write _test-input-stream "      increment x\n")
12966     (write _test-input-stream "    }\n")
12967     (write _test-input-stream "  }\n")
12968     (write _test-input-stream "  return 0\n")
12969     (write _test-input-stream "}\n")
12970     # convert
12971     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
12972     (flush _test-output-buffered-file)
12973 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
12979     # check output
12980     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-and-local-vars/0")
12981     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-and-local-vars/1")
12982     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-and-local-vars/2")
12983     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-and-local-vars/3")
12984     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-and-local-vars/4")
12985     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-and-local-vars/5")
12986     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-return-and-local-vars/6")
12987     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-return-and-local-vars/7")
12988     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-return-and-local-vars/8")  # var x
12989     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-return-and-local-vars/9")
12990     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-return-and-local-vars/10")
12991     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-return-and-local-vars/11")  # var y
12992     (check-next-stream-line-equal _test-output-stream "        8b/-> *(ebp+0xfffffff8) 0x00000000/r32" "F - test-convert-function-with-return-and-local-vars/12")
12993     (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")
12994     (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")
12995     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-and-local-vars/15")
12996     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-return-and-local-vars/16")
12997     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-return-and-local-vars/17")
12998     (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")
12999     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-return-and-local-vars/19")
13000     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-return-and-local-vars/20")
13001     (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")
13002     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-and-local-vars/21")
13003     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-and-local-vars/21")
13004     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-and-local-vars/22")
13005     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-and-local-vars/23")
13006     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-and-local-vars/24")
13007     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-and-local-vars/25")
13008     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-and-local-vars/26")
13009     # . epilogue
13010     89/<- %esp 5/r32/ebp
13011     5d/pop-to-ebp
13012     c3/return
13013 
13014 test-copy-object-with-no-inout:
13015     # . prologue
13016     55/push-ebp
13017     89/<- %ebp 4/r32/esp
13018     # setup
13019     (clear-stream _test-input-stream)
13020     (clear-stream $_test-input-buffered-file->buffer)
13021     (clear-stream _test-output-stream)
13022     (clear-stream $_test-output-buffered-file->buffer)
13023     (clear-stream _test-error-stream)
13024     (clear-stream $_test-error-buffered-file->buffer)
13025     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13026     68/push 0/imm32
13027     68/push 0/imm32
13028     89/<- %edx 4/r32/esp
13029     (tailor-exit-descriptor %edx 0x10)
13030     #
13031     (write _test-input-stream "fn foo {\n")
13032     (write _test-input-stream "  copy-object\n")
13033     (write _test-input-stream "}\n")
13034     # convert
13035     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13036     # registers except esp clobbered at this point
13037     # restore ed
13038     89/<- %edx 4/r32/esp
13039     (flush _test-output-buffered-file)
13040     (flush _test-error-buffered-file)
13041 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
13047     # check output
13048     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-no-inout: output should be empty")
13049     (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")
13050     # check that stop(1) was called
13051     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-no-inout: exit status")
13052     # don't restore from ebp
13053     81 0/subop/add %esp 8/imm32
13054     # . epilogue
13055     5d/pop-to-ebp
13056     c3/return
13057 
13058 test-copy-object-with-no-input:
13059     # . prologue
13060     55/push-ebp
13061     89/<- %ebp 4/r32/esp
13062     # setup
13063     (clear-stream _test-input-stream)
13064     (clear-stream $_test-input-buffered-file->buffer)
13065     (clear-stream _test-output-stream)
13066     (clear-stream $_test-output-buffered-file->buffer)
13067     (clear-stream _test-error-stream)
13068     (clear-stream $_test-error-buffered-file->buffer)
13069     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13070     68/push 0/imm32
13071     68/push 0/imm32
13072     89/<- %edx 4/r32/esp
13073     (tailor-exit-descriptor %edx 0x10)
13074     #
13075     (write _test-input-stream "fn foo {\n")
13076     (write _test-input-stream "  var x: (addr int)\n")
13077     (write _test-input-stream "  copy-object x\n")
13078     (write _test-input-stream "}\n")
13079     # convert
13080     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13081     # registers except esp clobbered at this point
13082     # restore ed
13083     89/<- %edx 4/r32/esp
13084     (flush _test-output-buffered-file)
13085     (flush _test-error-buffered-file)
13086 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
13092     # check output
13093     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-no-input: output should be empty")
13094     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-object' must have two inouts"  "F - test-copy-object-with-no-input: error message")
13095     # check that stop(1) was called
13096     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-no-input: exit status")
13097     # don't restore from ebp
13098     81 0/subop/add %esp 8/imm32
13099     # . epilogue
13100     5d/pop-to-ebp
13101     c3/return
13102 
13103 test-copy-object-with-too-many-inouts:
13104     # . prologue
13105     55/push-ebp
13106     89/<- %ebp 4/r32/esp
13107     # setup
13108     (clear-stream _test-input-stream)
13109     (clear-stream $_test-input-buffered-file->buffer)
13110     (clear-stream _test-output-stream)
13111     (clear-stream $_test-output-buffered-file->buffer)
13112     (clear-stream _test-error-stream)
13113     (clear-stream $_test-error-buffered-file->buffer)
13114     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13115     68/push 0/imm32
13116     68/push 0/imm32
13117     89/<- %edx 4/r32/esp
13118     (tailor-exit-descriptor %edx 0x10)
13119     #
13120     (write _test-input-stream "fn foo {\n")
13121     (write _test-input-stream "  var x: (addr boolean)\n")
13122     (write _test-input-stream "  copy-object x, x, x\n")
13123     (write _test-input-stream "}\n")
13124     # convert
13125     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13126     # registers except esp clobbered at this point
13127     # restore ed
13128     89/<- %edx 4/r32/esp
13129     (flush _test-output-buffered-file)
13130     (flush _test-error-buffered-file)
13131 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
13137     # check output
13138     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-too-many-inouts: output should be empty")
13139     (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")
13140     # check that stop(1) was called
13141     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-too-many-inouts: exit status")
13142     # don't restore from ebp
13143     81 0/subop/add %esp 8/imm32
13144     # . epilogue
13145     5d/pop-to-ebp
13146     c3/return
13147 
13148 test-copy-object-with-output:
13149     # . prologue
13150     55/push-ebp
13151     89/<- %ebp 4/r32/esp
13152     # setup
13153     (clear-stream _test-input-stream)
13154     (clear-stream $_test-input-buffered-file->buffer)
13155     (clear-stream _test-output-stream)
13156     (clear-stream $_test-output-buffered-file->buffer)
13157     (clear-stream _test-error-stream)
13158     (clear-stream $_test-error-buffered-file->buffer)
13159     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13160     68/push 0/imm32
13161     68/push 0/imm32
13162     89/<- %edx 4/r32/esp
13163     (tailor-exit-descriptor %edx 0x10)
13164     #
13165     (write _test-input-stream "fn foo {\n")
13166     (write _test-input-stream "  var x/eax: (addr boolean) <- copy 0\n")
13167     (write _test-input-stream "  var y/ecx: (addr boolean) <- copy 0\n")
13168     (write _test-input-stream "  x <- copy-object x, y\n")
13169     (write _test-input-stream "}\n")
13170     # convert
13171     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13172     # registers except esp clobbered at this point
13173     # restore ed
13174     89/<- %edx 4/r32/esp
13175     (flush _test-output-buffered-file)
13176     (flush _test-error-buffered-file)
13177 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
13183     # check output
13184     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-output: output should be empty")
13185     (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")
13186     # check that stop(1) was called
13187     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-output: exit status")
13188     # don't restore from ebp
13189     81 0/subop/add %esp 8/imm32
13190     # . epilogue
13191     5d/pop-to-ebp
13192     c3/return
13193 
13194 test-copy-object-deref-address:
13195     # . prologue
13196     55/push-ebp
13197     89/<- %ebp 4/r32/esp
13198     # setup
13199     (clear-stream _test-input-stream)
13200     (clear-stream $_test-input-buffered-file->buffer)
13201     (clear-stream _test-output-stream)
13202     (clear-stream $_test-output-buffered-file->buffer)
13203     #
13204     (write _test-input-stream "fn foo {\n")
13205     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
13206     (write _test-input-stream "  var y/ecx: (addr addr int) <- copy 0\n")
13207     (write _test-input-stream "  copy-object *y, x\n")
13208     (write _test-input-stream "}\n")
13209     # convert
13210     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
13211     (flush _test-output-buffered-file)
13212 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
13218     # not bothering checking output
13219     (check-next-stream-line-equal _test-error-stream  ""  "F - test-copy-object-deref-address: error message")
13220     # . epilogue
13221     5d/pop-to-ebp
13222     c3/return
13223 
13224 test-copy-object-non-addr:
13225     # . prologue
13226     55/push-ebp
13227     89/<- %ebp 4/r32/esp
13228     # setup
13229     (clear-stream _test-input-stream)
13230     (clear-stream $_test-input-buffered-file->buffer)
13231     (clear-stream _test-output-stream)
13232     (clear-stream $_test-output-buffered-file->buffer)
13233     (clear-stream _test-error-stream)
13234     (clear-stream $_test-error-buffered-file->buffer)
13235     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13236     68/push 0/imm32
13237     68/push 0/imm32
13238     89/<- %edx 4/r32/esp
13239     (tailor-exit-descriptor %edx 0x10)
13240     #
13241     (write _test-input-stream "fn foo {\n")
13242     (write _test-input-stream "  var x: int\n")
13243     (write _test-input-stream "  var y: int\n")
13244     (write _test-input-stream "  copy-object y, x\n")
13245     (write _test-input-stream "}\n")
13246     # convert
13247     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13248     # registers except esp clobbered at this point
13249     # restore ed
13250     89/<- %edx 4/r32/esp
13251     (flush _test-output-buffered-file)
13252     (flush _test-error-buffered-file)
13253 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
13259     # check output
13260     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-non-addr: output should be empty")
13261     (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")
13262     # check that stop(1) was called
13263     (check-ints-equal *(edx+4) 2 "F - test-copy-object-non-addr: exit status")
13264     # don't restore from ebp
13265     81 0/subop/add %esp 8/imm32
13266     # . epilogue
13267     5d/pop-to-ebp
13268     c3/return
13269 
13270 test-copy-object-non-equal:
13271     # . prologue
13272     55/push-ebp
13273     89/<- %ebp 4/r32/esp
13274     # setup
13275     (clear-stream _test-input-stream)
13276     (clear-stream $_test-input-buffered-file->buffer)
13277     (clear-stream _test-output-stream)
13278     (clear-stream $_test-output-buffered-file->buffer)
13279     (clear-stream _test-error-stream)
13280     (clear-stream $_test-error-buffered-file->buffer)
13281     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13282     68/push 0/imm32
13283     68/push 0/imm32
13284     89/<- %edx 4/r32/esp
13285     (tailor-exit-descriptor %edx 0x10)
13286     #
13287     (write _test-input-stream "fn foo {\n")
13288     (write _test-input-stream "  var x: (addr int)\n")
13289     (write _test-input-stream "  var y: (addr boolean)\n")
13290     (write _test-input-stream "  copy-object y, x\n")
13291     (write _test-input-stream "}\n")
13292     # convert
13293     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13294     # registers except esp clobbered at this point
13295     # restore ed
13296     89/<- %edx 4/r32/esp
13297     (flush _test-output-buffered-file)
13298     (flush _test-error-buffered-file)
13299 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
13305     # check output
13306     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-non-equal: output should be empty")
13307     (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")
13308     # check that stop(1) was called
13309     (check-ints-equal *(edx+4) 2 "F - test-copy-object-non-equal: exit status")
13310     # don't restore from ebp
13311     81 0/subop/add %esp 8/imm32
13312     # . epilogue
13313     5d/pop-to-ebp
13314     c3/return
13315 
13316 test-allocate-with-no-inout:
13317     # . prologue
13318     55/push-ebp
13319     89/<- %ebp 4/r32/esp
13320     # setup
13321     (clear-stream _test-input-stream)
13322     (clear-stream $_test-input-buffered-file->buffer)
13323     (clear-stream _test-output-stream)
13324     (clear-stream $_test-output-buffered-file->buffer)
13325     (clear-stream _test-error-stream)
13326     (clear-stream $_test-error-buffered-file->buffer)
13327     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13328     68/push 0/imm32
13329     68/push 0/imm32
13330     89/<- %edx 4/r32/esp
13331     (tailor-exit-descriptor %edx 0x10)
13332     #
13333     (write _test-input-stream "fn foo {\n")
13334     (write _test-input-stream "  allocate\n")
13335     (write _test-input-stream "}\n")
13336     # convert
13337     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13338     # registers except esp clobbered at this point
13339     # restore ed
13340     89/<- %edx 4/r32/esp
13341     (flush _test-output-buffered-file)
13342     (flush _test-error-buffered-file)
13343 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
13349     # check output
13350     (check-stream-equal _test-output-stream  ""  "F - test-allocate-with-no-inout: output should be empty")
13351     (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")
13352     # check that stop(1) was called
13353     (check-ints-equal *(edx+4) 2 "F - test-allocate-with-no-inout: exit status")
13354     # don't restore from ebp
13355     81 0/subop/add %esp 8/imm32
13356     # . epilogue
13357     5d/pop-to-ebp
13358     c3/return
13359 
13360 test-allocate-with-too-many-inouts:
13361     # . prologue
13362     55/push-ebp
13363     89/<- %ebp 4/r32/esp
13364     # setup
13365     (clear-stream _test-input-stream)
13366     (clear-stream $_test-input-buffered-file->buffer)
13367     (clear-stream _test-output-stream)
13368     (clear-stream $_test-output-buffered-file->buffer)
13369     (clear-stream _test-error-stream)
13370     (clear-stream $_test-error-buffered-file->buffer)
13371     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13372     68/push 0/imm32
13373     68/push 0/imm32
13374     89/<- %edx 4/r32/esp
13375     (tailor-exit-descriptor %edx 0x10)
13376     #
13377     (write _test-input-stream "fn foo {\n")
13378     (write _test-input-stream "  var x: (addr handle int)\n")
13379     (write _test-input-stream "  allocate x, 0\n")
13380     (write _test-input-stream "}\n")
13381     # convert
13382     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13383     # registers except esp clobbered at this point
13384     # restore ed
13385     89/<- %edx 4/r32/esp
13386     (flush _test-output-buffered-file)
13387     (flush _test-error-buffered-file)
13388 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
13394     # check output
13395     (check-stream-equal _test-output-stream  ""  "F - test-allocate-with-too-many-inouts: output should be empty")
13396     (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")
13397     # check that stop(1) was called
13398     (check-ints-equal *(edx+4) 2 "F - test-allocate-with-too-many-inouts: exit status")
13399     # don't restore from ebp
13400     81 0/subop/add %esp 8/imm32
13401     # . epilogue
13402     5d/pop-to-ebp
13403     c3/return
13404 
13405 test-allocate-with-output:
13406     # . prologue
13407     55/push-ebp
13408     89/<- %ebp 4/r32/esp
13409     # setup
13410     (clear-stream _test-input-stream)
13411     (clear-stream $_test-input-buffered-file->buffer)
13412     (clear-stream _test-output-stream)
13413     (clear-stream $_test-output-buffered-file->buffer)
13414     (clear-stream _test-error-stream)
13415     (clear-stream $_test-error-buffered-file->buffer)
13416     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13417     68/push 0/imm32
13418     68/push 0/imm32
13419     89/<- %edx 4/r32/esp
13420     (tailor-exit-descriptor %edx 0x10)
13421     #
13422     (write _test-input-stream "fn foo {\n")
13423     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
13424     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
13425     (write _test-input-stream "  x <- allocate y\n")
13426     (write _test-input-stream "}\n")
13427     # convert
13428     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13429     # registers except esp clobbered at this point
13430     # restore ed
13431     89/<- %edx 4/r32/esp
13432     (flush _test-output-buffered-file)
13433     (flush _test-error-buffered-file)
13434 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
13440     # check output
13441     (check-stream-equal _test-output-stream  ""  "F - test-allocate-with-output: output should be empty")
13442     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'allocate' must not have any outputs"  "F - test-allocate-with-output: error message")
13443     # check that stop(1) was called
13444     (check-ints-equal *(edx+4) 2 "F - test-allocate-with-output: exit status")
13445     # don't restore from ebp
13446     81 0/subop/add %esp 8/imm32
13447     # . epilogue
13448     5d/pop-to-ebp
13449     c3/return
13450 
13451 test-allocate-non-addr:
13452     # . prologue
13453     55/push-ebp
13454     89/<- %ebp 4/r32/esp
13455     # setup
13456     (clear-stream _test-input-stream)
13457     (clear-stream $_test-input-buffered-file->buffer)
13458     (clear-stream _test-output-stream)
13459     (clear-stream $_test-output-buffered-file->buffer)
13460     (clear-stream _test-error-stream)
13461     (clear-stream $_test-error-buffered-file->buffer)
13462     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13463     68/push 0/imm32
13464     68/push 0/imm32
13465     89/<- %edx 4/r32/esp
13466     (tailor-exit-descriptor %edx 0x10)
13467     #
13468     (write _test-input-stream "fn foo {\n")
13469     (write _test-input-stream "  var y: (handle int)\n")
13470     (write _test-input-stream "  allocate y\n")
13471     (write _test-input-stream "}\n")
13472     # convert
13473     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13474     # registers except esp clobbered at this point
13475     # restore ed
13476     89/<- %edx 4/r32/esp
13477     (flush _test-output-buffered-file)
13478     (flush _test-error-buffered-file)
13479 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
13485     # check output
13486     (check-stream-equal _test-output-stream  ""  "F - test-allocate-non-addr: output must be empty")
13487     (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")
13488     # check that stop(1) was called
13489     (check-ints-equal *(edx+4) 2 "F - test-allocate-non-addr: exit status")
13490     # don't restore from ebp
13491     81 0/subop/add %esp 8/imm32
13492     # . epilogue
13493     5d/pop-to-ebp
13494     c3/return
13495 
13496 test-allocate-non-addr-handle:
13497     # . prologue
13498     55/push-ebp
13499     89/<- %ebp 4/r32/esp
13500     # setup
13501     (clear-stream _test-input-stream)
13502     (clear-stream $_test-input-buffered-file->buffer)
13503     (clear-stream _test-output-stream)
13504     (clear-stream $_test-output-buffered-file->buffer)
13505     (clear-stream _test-error-stream)
13506     (clear-stream $_test-error-buffered-file->buffer)
13507     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13508     68/push 0/imm32
13509     68/push 0/imm32
13510     89/<- %edx 4/r32/esp
13511     (tailor-exit-descriptor %edx 0x10)
13512     #
13513     (write _test-input-stream "fn foo {\n")
13514     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
13515     (write _test-input-stream "  allocate y\n")
13516     (write _test-input-stream "}\n")
13517     # convert
13518     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13519     # registers except esp clobbered at this point
13520     # restore ed
13521     89/<- %edx 4/r32/esp
13522     (flush _test-output-buffered-file)
13523     (flush _test-error-buffered-file)
13524 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
13530     # check output
13531     (check-stream-equal _test-output-stream  ""  "F - test-allocate-non-addr-handle: output should be empty")
13532     (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")
13533     # check that stop(1) was called
13534     (check-ints-equal *(edx+4) 2 "F - test-allocate-non-addr-handle: exit status")
13535     # don't restore from ebp
13536     81 0/subop/add %esp 8/imm32
13537     # . epilogue
13538     5d/pop-to-ebp
13539     c3/return
13540 
13541 test-allocate-deref-address:
13542     # . prologue
13543     55/push-ebp
13544     89/<- %ebp 4/r32/esp
13545     # setup
13546     (clear-stream _test-input-stream)
13547     (clear-stream $_test-input-buffered-file->buffer)
13548     (clear-stream _test-output-stream)
13549     (clear-stream $_test-output-buffered-file->buffer)
13550     #
13551     (write _test-input-stream "fn foo {\n")
13552     (write _test-input-stream "  var y/ecx: (addr addr handle int) <- copy 0\n")
13553     (write _test-input-stream "  allocate *y\n")
13554     (write _test-input-stream "}\n")
13555     # convert
13556     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
13557     (flush _test-output-buffered-file)
13558 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
13564     # not bothering checking output
13565     (check-next-stream-line-equal _test-error-stream  ""  "F - test-allocate-deref-address: error message")
13566     # . epilogue
13567     5d/pop-to-ebp
13568     c3/return
13569 
13570 test-populate-with-no-inout:
13571     # . prologue
13572     55/push-ebp
13573     89/<- %ebp 4/r32/esp
13574     # setup
13575     (clear-stream _test-input-stream)
13576     (clear-stream $_test-input-buffered-file->buffer)
13577     (clear-stream _test-output-stream)
13578     (clear-stream $_test-output-buffered-file->buffer)
13579     (clear-stream _test-error-stream)
13580     (clear-stream $_test-error-buffered-file->buffer)
13581     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13582     68/push 0/imm32
13583     68/push 0/imm32
13584     89/<- %edx 4/r32/esp
13585     (tailor-exit-descriptor %edx 0x10)
13586     #
13587     (write _test-input-stream "fn foo {\n")
13588     (write _test-input-stream "  populate\n")
13589     (write _test-input-stream "}\n")
13590     # convert
13591     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13592     # registers except esp clobbered at this point
13593     # restore ed
13594     89/<- %edx 4/r32/esp
13595     (flush _test-output-buffered-file)
13596     (flush _test-error-buffered-file)
13597 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
13603     # check output
13604     (check-stream-equal _test-output-stream  ""  "F - test-populate-with-no-inout: output should be empty")
13605     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate' must have two inouts"  "F - test-populate-with-no-inout: error message")
13606     # check that stop(1) was called
13607     (check-ints-equal *(edx+4) 2 "F - test-populate-with-no-inout: exit status")
13608     # don't restore from ebp
13609     81 0/subop/add %esp 8/imm32
13610     # . epilogue
13611     5d/pop-to-ebp
13612     c3/return
13613 
13614 test-populate-with-too-many-inouts:
13615     # . prologue
13616     55/push-ebp
13617     89/<- %ebp 4/r32/esp
13618     # setup
13619     (clear-stream _test-input-stream)
13620     (clear-stream $_test-input-buffered-file->buffer)
13621     (clear-stream _test-output-stream)
13622     (clear-stream $_test-output-buffered-file->buffer)
13623     (clear-stream _test-error-stream)
13624     (clear-stream $_test-error-buffered-file->buffer)
13625     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13626     68/push 0/imm32
13627     68/push 0/imm32
13628     89/<- %edx 4/r32/esp
13629     (tailor-exit-descriptor %edx 0x10)
13630     #
13631     (write _test-input-stream "fn foo {\n")
13632     (write _test-input-stream "  var x: (addr handle int)\n")
13633     (write _test-input-stream "  populate x, 3, 0\n")
13634     (write _test-input-stream "}\n")
13635     # convert
13636     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13637     # registers except esp clobbered at this point
13638     # restore ed
13639     89/<- %edx 4/r32/esp
13640     (flush _test-output-buffered-file)
13641     (flush _test-error-buffered-file)
13642 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
13648     # check output
13649     (check-stream-equal _test-output-stream  ""  "F - test-populate-with-too-many-inouts: output should be empty")
13650     (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")
13651     # check that stop(1) was called
13652     (check-ints-equal *(edx+4) 2 "F - test-populate-with-too-many-inouts: exit status")
13653     # don't restore from ebp
13654     81 0/subop/add %esp 8/imm32
13655     # . epilogue
13656     5d/pop-to-ebp
13657     c3/return
13658 
13659 test-populate-with-output:
13660     # . prologue
13661     55/push-ebp
13662     89/<- %ebp 4/r32/esp
13663     # setup
13664     (clear-stream _test-input-stream)
13665     (clear-stream $_test-input-buffered-file->buffer)
13666     (clear-stream _test-output-stream)
13667     (clear-stream $_test-output-buffered-file->buffer)
13668     (clear-stream _test-error-stream)
13669     (clear-stream $_test-error-buffered-file->buffer)
13670     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13671     68/push 0/imm32
13672     68/push 0/imm32
13673     89/<- %edx 4/r32/esp
13674     (tailor-exit-descriptor %edx 0x10)
13675     #
13676     (write _test-input-stream "fn foo {\n")
13677     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
13678     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
13679     (write _test-input-stream "  x <- populate y\n")
13680     (write _test-input-stream "}\n")
13681     # convert
13682     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13683     # registers except esp clobbered at this point
13684     # restore ed
13685     89/<- %edx 4/r32/esp
13686     (flush _test-output-buffered-file)
13687     (flush _test-error-buffered-file)
13688 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
13694     # check output
13695     (check-stream-equal _test-output-stream  ""  "F - test-populate-with-output: output should be empty")
13696     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate' must not have any outputs"  "F - test-populate-with-output: error message")
13697     # check that stop(1) was called
13698     (check-ints-equal *(edx+4) 2 "F - test-populate-with-output: exit status")
13699     # don't restore from ebp
13700     81 0/subop/add %esp 8/imm32
13701     # . epilogue
13702     5d/pop-to-ebp
13703     c3/return
13704 
13705 test-populate-non-addr:
13706     # . prologue
13707     55/push-ebp
13708     89/<- %ebp 4/r32/esp
13709     # setup
13710     (clear-stream _test-input-stream)
13711     (clear-stream $_test-input-buffered-file->buffer)
13712     (clear-stream _test-output-stream)
13713     (clear-stream $_test-output-buffered-file->buffer)
13714     (clear-stream _test-error-stream)
13715     (clear-stream $_test-error-buffered-file->buffer)
13716     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13717     68/push 0/imm32
13718     68/push 0/imm32
13719     89/<- %edx 4/r32/esp
13720     (tailor-exit-descriptor %edx 0x10)
13721     #
13722     (write _test-input-stream "fn foo {\n")
13723     (write _test-input-stream "  var y: (handle int)\n")
13724     (write _test-input-stream "  populate y, 3\n")
13725     (write _test-input-stream "}\n")
13726     # convert
13727     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13728     # registers except esp clobbered at this point
13729     # restore ed
13730     89/<- %edx 4/r32/esp
13731     (flush _test-output-buffered-file)
13732     (flush _test-error-buffered-file)
13733 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
13739     # check output
13740     (check-stream-equal _test-output-stream  ""  "F - test-populate-non-addr: output must be empty")
13741     (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")
13742     # check that stop(1) was called
13743     (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr: exit status")
13744     # don't restore from ebp
13745     81 0/subop/add %esp 8/imm32
13746     # . epilogue
13747     5d/pop-to-ebp
13748     c3/return
13749 
13750 test-populate-non-addr-handle:
13751     # . prologue
13752     55/push-ebp
13753     89/<- %ebp 4/r32/esp
13754     # setup
13755     (clear-stream _test-input-stream)
13756     (clear-stream $_test-input-buffered-file->buffer)
13757     (clear-stream _test-output-stream)
13758     (clear-stream $_test-output-buffered-file->buffer)
13759     (clear-stream _test-error-stream)
13760     (clear-stream $_test-error-buffered-file->buffer)
13761     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13762     68/push 0/imm32
13763     68/push 0/imm32
13764     89/<- %edx 4/r32/esp
13765     (tailor-exit-descriptor %edx 0x10)
13766     #
13767     (write _test-input-stream "fn foo {\n")
13768     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
13769     (write _test-input-stream "  populate y, 3\n")
13770     (write _test-input-stream "}\n")
13771     # convert
13772     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13773     # registers except esp clobbered at this point
13774     # restore ed
13775     89/<- %edx 4/r32/esp
13776     (flush _test-output-buffered-file)
13777     (flush _test-error-buffered-file)
13778 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
13784     # check output
13785     (check-stream-equal _test-output-stream  ""  "F - test-populate-non-addr-handle: output should be empty")
13786     (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")
13787     # check that stop(1) was called
13788     (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr-handle: exit status")
13789     # don't restore from ebp
13790     81 0/subop/add %esp 8/imm32
13791     # . epilogue
13792     5d/pop-to-ebp
13793     c3/return
13794 
13795 test-populate-non-addr-handle-array:
13796     # . prologue
13797     55/push-ebp
13798     89/<- %ebp 4/r32/esp
13799     # setup
13800     (clear-stream _test-input-stream)
13801     (clear-stream $_test-input-buffered-file->buffer)
13802     (clear-stream _test-output-stream)
13803     (clear-stream $_test-output-buffered-file->buffer)
13804     (clear-stream _test-error-stream)
13805     (clear-stream $_test-error-buffered-file->buffer)
13806     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13807     68/push 0/imm32
13808     68/push 0/imm32
13809     89/<- %edx 4/r32/esp
13810     (tailor-exit-descriptor %edx 0x10)
13811     #
13812     (write _test-input-stream "fn foo {\n")
13813     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
13814     (write _test-input-stream "  populate y, 3\n")
13815     (write _test-input-stream "}\n")
13816     # convert
13817     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13818     # registers except esp clobbered at this point
13819     # restore ed
13820     89/<- %edx 4/r32/esp
13821     (flush _test-output-buffered-file)
13822     (flush _test-error-buffered-file)
13823 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
13829     # check output
13830     (check-stream-equal _test-output-stream  ""  "F - test-populate-non-addr-handle-array: output should be empty")
13831     (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")
13832     # check that stop(1) was called
13833     (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr-handle-array: exit status")
13834     # don't restore from ebp
13835     81 0/subop/add %esp 8/imm32
13836     # . epilogue
13837     5d/pop-to-ebp
13838     c3/return
13839 
13840 test-populate-deref-address:
13841     # . prologue
13842     55/push-ebp
13843     89/<- %ebp 4/r32/esp
13844     # setup
13845     (clear-stream _test-input-stream)
13846     (clear-stream $_test-input-buffered-file->buffer)
13847     (clear-stream _test-output-stream)
13848     (clear-stream $_test-output-buffered-file->buffer)
13849     #
13850     (write _test-input-stream "fn foo {\n")
13851     (write _test-input-stream "  var y/ecx: (addr addr handle array int) <- copy 0\n")
13852     (write _test-input-stream "  populate *y, 3\n")
13853     (write _test-input-stream "}\n")
13854     # convert
13855     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
13856     (flush _test-output-buffered-file)
13857 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
13863     # not bothering checking output
13864     (check-next-stream-line-equal _test-error-stream  ""  "F - test-populate-deref-address: error message")
13865     # . epilogue
13866     5d/pop-to-ebp
13867     c3/return
13868 
13869 test-populate-stream-with-no-inout:
13870     # . prologue
13871     55/push-ebp
13872     89/<- %ebp 4/r32/esp
13873     # setup
13874     (clear-stream _test-input-stream)
13875     (clear-stream $_test-input-buffered-file->buffer)
13876     (clear-stream _test-output-stream)
13877     (clear-stream $_test-output-buffered-file->buffer)
13878     (clear-stream _test-error-stream)
13879     (clear-stream $_test-error-buffered-file->buffer)
13880     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13881     68/push 0/imm32
13882     68/push 0/imm32
13883     89/<- %edx 4/r32/esp
13884     (tailor-exit-descriptor %edx 0x10)
13885     #
13886     (write _test-input-stream "fn foo {\n")
13887     (write _test-input-stream "  populate-stream\n")
13888     (write _test-input-stream "}\n")
13889     # convert
13890     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13891     # registers except esp clobbered at this point
13892     # restore ed
13893     89/<- %edx 4/r32/esp
13894     (flush _test-output-buffered-file)
13895     (flush _test-error-buffered-file)
13896 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
13902     # check output
13903     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-with-no-inout: output should be empty")
13904     (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")
13905     # check that stop(1) was called
13906     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-no-inout: exit status")
13907     # don't restore from ebp
13908     81 0/subop/add %esp 8/imm32
13909     # . epilogue
13910     5d/pop-to-ebp
13911     c3/return
13912 
13913 test-populate-stream-with-too-many-inouts:
13914     # . prologue
13915     55/push-ebp
13916     89/<- %ebp 4/r32/esp
13917     # setup
13918     (clear-stream _test-input-stream)
13919     (clear-stream $_test-input-buffered-file->buffer)
13920     (clear-stream _test-output-stream)
13921     (clear-stream $_test-output-buffered-file->buffer)
13922     (clear-stream _test-error-stream)
13923     (clear-stream $_test-error-buffered-file->buffer)
13924     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13925     68/push 0/imm32
13926     68/push 0/imm32
13927     89/<- %edx 4/r32/esp
13928     (tailor-exit-descriptor %edx 0x10)
13929     #
13930     (write _test-input-stream "fn foo {\n")
13931     (write _test-input-stream "  var x: (addr handle int)\n")
13932     (write _test-input-stream "  populate-stream x, 3, 0\n")
13933     (write _test-input-stream "}\n")
13934     # convert
13935     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13936     # registers except esp clobbered at this point
13937     # restore ed
13938     89/<- %edx 4/r32/esp
13939     (flush _test-output-buffered-file)
13940     (flush _test-error-buffered-file)
13941 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
13947     # check output
13948     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-with-too-many-inouts: output should be empty")
13949     (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")
13950     # check that stop(1) was called
13951     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-too-many-inouts: exit status")
13952     # don't restore from ebp
13953     81 0/subop/add %esp 8/imm32
13954     # . epilogue
13955     5d/pop-to-ebp
13956     c3/return
13957 
13958 test-populate-stream-with-output:
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     (clear-stream _test-error-stream)
13968     (clear-stream $_test-error-buffered-file->buffer)
13969     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13970     68/push 0/imm32
13971     68/push 0/imm32
13972     89/<- %edx 4/r32/esp
13973     (tailor-exit-descriptor %edx 0x10)
13974     #
13975     (write _test-input-stream "fn foo {\n")
13976     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
13977     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
13978     (write _test-input-stream "  x <- populate-stream y\n")
13979     (write _test-input-stream "}\n")
13980     # convert
13981     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13982     # registers except esp clobbered at this point
13983     # restore ed
13984     89/<- %edx 4/r32/esp
13985     (flush _test-output-buffered-file)
13986     (flush _test-error-buffered-file)
13987 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
13993     # check output
13994     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-with-output: output should be empty")
13995     (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")
13996     # check that stop(1) was called
13997     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-output: exit status")
13998     # don't restore from ebp
13999     81 0/subop/add %esp 8/imm32
14000     # . epilogue
14001     5d/pop-to-ebp
14002     c3/return
14003 
14004 test-populate-stream-non-addr:
14005     # . prologue
14006     55/push-ebp
14007     89/<- %ebp 4/r32/esp
14008     # setup
14009     (clear-stream _test-input-stream)
14010     (clear-stream $_test-input-buffered-file->buffer)
14011     (clear-stream _test-output-stream)
14012     (clear-stream $_test-output-buffered-file->buffer)
14013     (clear-stream _test-error-stream)
14014     (clear-stream $_test-error-buffered-file->buffer)
14015     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14016     68/push 0/imm32
14017     68/push 0/imm32
14018     89/<- %edx 4/r32/esp
14019     (tailor-exit-descriptor %edx 0x10)
14020     #
14021     (write _test-input-stream "fn foo {\n")
14022     (write _test-input-stream "  var y: (handle int)\n")
14023     (write _test-input-stream "  populate-stream y, 3\n")
14024     (write _test-input-stream "}\n")
14025     # convert
14026     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14027     # registers except esp clobbered at this point
14028     # restore ed
14029     89/<- %edx 4/r32/esp
14030     (flush _test-output-buffered-file)
14031     (flush _test-error-buffered-file)
14032 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
14038     # check output
14039     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-non-addr: output must be empty")
14040     (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")
14041     # check that stop(1) was called
14042     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr: exit status")
14043     # don't restore from ebp
14044     81 0/subop/add %esp 8/imm32
14045     # . epilogue
14046     5d/pop-to-ebp
14047     c3/return
14048 
14049 test-populate-stream-non-addr-handle:
14050     # . prologue
14051     55/push-ebp
14052     89/<- %ebp 4/r32/esp
14053     # setup
14054     (clear-stream _test-input-stream)
14055     (clear-stream $_test-input-buffered-file->buffer)
14056     (clear-stream _test-output-stream)
14057     (clear-stream $_test-output-buffered-file->buffer)
14058     (clear-stream _test-error-stream)
14059     (clear-stream $_test-error-buffered-file->buffer)
14060     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14061     68/push 0/imm32
14062     68/push 0/imm32
14063     89/<- %edx 4/r32/esp
14064     (tailor-exit-descriptor %edx 0x10)
14065     #
14066     (write _test-input-stream "fn foo {\n")
14067     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
14068     (write _test-input-stream "  populate-stream y, 3\n")
14069     (write _test-input-stream "}\n")
14070     # convert
14071     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14072     # registers except esp clobbered at this point
14073     # restore ed
14074     89/<- %edx 4/r32/esp
14075     (flush _test-output-buffered-file)
14076     (flush _test-error-buffered-file)
14077 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
14083     # check output
14084     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-non-addr-handle: output should be empty")
14085     (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")
14086     # check that stop(1) was called
14087     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr-handle: exit status")
14088     # don't restore from ebp
14089     81 0/subop/add %esp 8/imm32
14090     # . epilogue
14091     5d/pop-to-ebp
14092     c3/return
14093 
14094 test-populate-stream-non-addr-handle-stream:
14095     # . prologue
14096     55/push-ebp
14097     89/<- %ebp 4/r32/esp
14098     # setup
14099     (clear-stream _test-input-stream)
14100     (clear-stream $_test-input-buffered-file->buffer)
14101     (clear-stream _test-output-stream)
14102     (clear-stream $_test-output-buffered-file->buffer)
14103     (clear-stream _test-error-stream)
14104     (clear-stream $_test-error-buffered-file->buffer)
14105     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14106     68/push 0/imm32
14107     68/push 0/imm32
14108     89/<- %edx 4/r32/esp
14109     (tailor-exit-descriptor %edx 0x10)
14110     #
14111     (write _test-input-stream "fn foo {\n")
14112     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
14113     (write _test-input-stream "  populate-stream y, 3\n")
14114     (write _test-input-stream "}\n")
14115     # convert
14116     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14117     # registers except esp clobbered at this point
14118     # restore ed
14119     89/<- %edx 4/r32/esp
14120     (flush _test-output-buffered-file)
14121     (flush _test-error-buffered-file)
14122 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
14128     # check output
14129     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-non-addr-handle-stream: output should be empty")
14130     (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")
14131     # check that stop(1) was called
14132     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr-handle-stream: exit status")
14133     # don't restore from ebp
14134     81 0/subop/add %esp 8/imm32
14135     # . epilogue
14136     5d/pop-to-ebp
14137     c3/return
14138 
14139 test-populate-stream-deref-address:
14140     # . prologue
14141     55/push-ebp
14142     89/<- %ebp 4/r32/esp
14143     # setup
14144     (clear-stream _test-input-stream)
14145     (clear-stream $_test-input-buffered-file->buffer)
14146     (clear-stream _test-output-stream)
14147     (clear-stream $_test-output-buffered-file->buffer)
14148     #
14149     (write _test-input-stream "fn foo {\n")
14150     (write _test-input-stream "  var y/ecx: (addr addr handle stream int) <- copy 0\n")
14151     (write _test-input-stream "  populate-stream *y, 3\n")
14152     (write _test-input-stream "}\n")
14153     # convert
14154     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
14155     (flush _test-output-buffered-file)
14156 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
14162     # not bothering checking output
14163     (check-next-stream-line-equal _test-error-stream  ""  "F - test-populate-stream-deref-address: error message")
14164     # . epilogue
14165     5d/pop-to-ebp
14166     c3/return
14167 
14168 test-convert-with-no-inout:
14169     # . prologue
14170     55/push-ebp
14171     89/<- %ebp 4/r32/esp
14172     # setup
14173     (clear-stream _test-input-stream)
14174     (clear-stream $_test-input-buffered-file->buffer)
14175     (clear-stream _test-output-stream)
14176     (clear-stream $_test-output-buffered-file->buffer)
14177     (clear-stream _test-error-stream)
14178     (clear-stream $_test-error-buffered-file->buffer)
14179     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14180     68/push 0/imm32
14181     68/push 0/imm32
14182     89/<- %edx 4/r32/esp
14183     (tailor-exit-descriptor %edx 0x10)
14184     #
14185     (write _test-input-stream "fn foo {\n")
14186     (write _test-input-stream "  var x/eax: int <- convert\n")
14187     (write _test-input-stream "}\n")
14188     # convert
14189     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14190     # registers except esp clobbered at this point
14191     # restore ed
14192     89/<- %edx 4/r32/esp
14193     (flush _test-output-buffered-file)
14194     (flush _test-error-buffered-file)
14195 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
14201     # check output
14202     (check-stream-equal _test-output-stream  ""  "F - test-convert-with-no-inout: output should be empty")
14203     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'convert' expects an inout"  "F - test-convert-with-no-inout: error message")
14204     # check that stop(1) was called
14205     (check-ints-equal *(edx+4) 2 "F - test-convert-with-no-inout: exit status")
14206     # don't restore from ebp
14207     81 0/subop/add %esp 8/imm32
14208     # . epilogue
14209     5d/pop-to-ebp
14210     c3/return
14211 
14212 test-convert-with-multiple-inouts:
14213     # . prologue
14214     55/push-ebp
14215     89/<- %ebp 4/r32/esp
14216     # setup
14217     (clear-stream _test-input-stream)
14218     (clear-stream $_test-input-buffered-file->buffer)
14219     (clear-stream _test-output-stream)
14220     (clear-stream $_test-output-buffered-file->buffer)
14221     (clear-stream _test-error-stream)
14222     (clear-stream $_test-error-buffered-file->buffer)
14223     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14224     68/push 0/imm32
14225     68/push 0/imm32
14226     89/<- %edx 4/r32/esp
14227     (tailor-exit-descriptor %edx 0x10)
14228     #
14229     (write _test-input-stream "fn foo {\n")
14230     (write _test-input-stream "  var x/eax: int <- convert 0, 0\n")
14231     (write _test-input-stream "}\n")
14232     # convert
14233     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14234     # registers except esp clobbered at this point
14235     # restore ed
14236     89/<- %edx 4/r32/esp
14237     (flush _test-output-buffered-file)
14238     (flush _test-error-buffered-file)
14239 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
14245     # check output
14246     (check-stream-equal _test-output-stream  ""  "F - test-convert-with-multiple-inouts: output should be empty")
14247     (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")
14248     # check that stop(1) was called
14249     (check-ints-equal *(edx+4) 2 "F - test-convert-with-multiple-inouts: exit status")
14250     # don't restore from ebp
14251     81 0/subop/add %esp 8/imm32
14252     # . epilogue
14253     5d/pop-to-ebp
14254     c3/return
14255 
14256 test-convert-with-no-output:
14257     # . prologue
14258     55/push-ebp
14259     89/<- %ebp 4/r32/esp
14260     # setup
14261     (clear-stream _test-input-stream)
14262     (clear-stream $_test-input-buffered-file->buffer)
14263     (clear-stream _test-output-stream)
14264     (clear-stream $_test-output-buffered-file->buffer)
14265     (clear-stream _test-error-stream)
14266     (clear-stream $_test-error-buffered-file->buffer)
14267     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14268     68/push 0/imm32
14269     68/push 0/imm32
14270     89/<- %edx 4/r32/esp
14271     (tailor-exit-descriptor %edx 0x10)
14272     #
14273     (write _test-input-stream "fn foo {\n")
14274     (write _test-input-stream "  convert 0\n")
14275     (write _test-input-stream "}\n")
14276     # convert
14277     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14278     # registers except esp clobbered at this point
14279     # restore ed
14280     89/<- %edx 4/r32/esp
14281     (flush _test-output-buffered-file)
14282     (flush _test-error-buffered-file)
14283 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
14289     # check output
14290     (check-stream-equal _test-output-stream  ""  "F - test-convert-with-no-output: output should be empty")
14291     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'convert' expects an output"  "F - test-convert-with-no-output: error message")
14292     # check that stop(1) was called
14293     (check-ints-equal *(edx+4) 2 "F - test-convert-with-no-output: exit status")
14294     # don't restore from ebp
14295     81 0/subop/add %esp 8/imm32
14296     # . epilogue
14297     5d/pop-to-ebp
14298     c3/return
14299 
14300 test-convert-with-multiple-outputs:
14301     # . prologue
14302     55/push-ebp
14303     89/<- %ebp 4/r32/esp
14304     # setup
14305     (clear-stream _test-input-stream)
14306     (clear-stream $_test-input-buffered-file->buffer)
14307     (clear-stream _test-output-stream)
14308     (clear-stream $_test-output-buffered-file->buffer)
14309     (clear-stream _test-error-stream)
14310     (clear-stream $_test-error-buffered-file->buffer)
14311     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14312     68/push 0/imm32
14313     68/push 0/imm32
14314     89/<- %edx 4/r32/esp
14315     (tailor-exit-descriptor %edx 0x10)
14316     #
14317     (write _test-input-stream "fn foo {\n")
14318     (write _test-input-stream "  var x/eax: int <- copy 0\n")
14319     (write _test-input-stream "  var y/ecx: int <- copy 0\n")
14320     (write _test-input-stream "  x, y <- convert 0\n")
14321     (write _test-input-stream "}\n")
14322     # convert
14323     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14324     # registers except esp clobbered at this point
14325     # restore ed
14326     89/<- %edx 4/r32/esp
14327     (flush _test-output-buffered-file)
14328     (flush _test-error-buffered-file)
14329 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
14335     # check output
14336     (check-stream-equal _test-output-stream  ""  "F - test-convert-with-multiple-outputs: output should be empty")
14337     (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")
14338     # check that stop(1) was called
14339     (check-ints-equal *(edx+4) 2 "F - test-convert-with-multiple-outputs: exit status")
14340     # don't restore from ebp
14341     81 0/subop/add %esp 8/imm32
14342     # . epilogue
14343     5d/pop-to-ebp
14344     c3/return
14345 
14346 test-convert-deref-address:
14347     # . prologue
14348     55/push-ebp
14349     89/<- %ebp 4/r32/esp
14350     # setup
14351     (clear-stream _test-input-stream)
14352     (clear-stream $_test-input-buffered-file->buffer)
14353     (clear-stream _test-output-stream)
14354     (clear-stream $_test-output-buffered-file->buffer)
14355     #
14356     (write _test-input-stream "fn foo {\n")
14357     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
14358     (write _test-input-stream "  var y/xmm4: float <- convert *x\n")
14359     (write _test-input-stream "}\n")
14360     # convert
14361     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
14362     (flush _test-output-buffered-file)
14363 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
14369     # not bothering checking output
14370     (check-next-stream-line-equal _test-error-stream  ""  "F - test-convert-deref-address: error message")
14371     # . epilogue
14372     5d/pop-to-ebp
14373     c3/return
14374 
14375 test-convert-to-non-register:
14376     # . prologue
14377     55/push-ebp
14378     89/<- %ebp 4/r32/esp
14379     # setup
14380     (clear-stream _test-input-stream)
14381     (clear-stream $_test-input-buffered-file->buffer)
14382     (clear-stream _test-output-stream)
14383     (clear-stream $_test-output-buffered-file->buffer)
14384     (clear-stream _test-error-stream)
14385     (clear-stream $_test-error-buffered-file->buffer)
14386     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14387     68/push 0/imm32
14388     68/push 0/imm32
14389     89/<- %edx 4/r32/esp
14390     (tailor-exit-descriptor %edx 0x10)
14391     #
14392     (write _test-input-stream "fn foo {\n")
14393     (write _test-input-stream "  var x: float\n")
14394     (write _test-input-stream "  var y: int\n")
14395     (write _test-input-stream "  x <- convert y\n")
14396     (write _test-input-stream "}\n")
14397     # convert
14398     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14399     # registers except esp clobbered at this point
14400     # restore ed
14401     89/<- %edx 4/r32/esp
14402     (flush _test-output-buffered-file)
14403     (flush _test-error-buffered-file)
14404 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
14410     # check output
14411     (check-stream-equal _test-output-stream  ""  "F - test-convert-to-non-register: output should be empty")
14412     (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")
14413     # check that stop(1) was called
14414     (check-ints-equal *(edx+4) 2 "F - test-convert-to-non-register: exit status")
14415     # don't restore from ebp
14416     81 0/subop/add %esp 8/imm32
14417     # . epilogue
14418     5d/pop-to-ebp
14419     c3/return
14420 
14421 test-convert-invalid-inout-type:
14422     # . prologue
14423     55/push-ebp
14424     89/<- %ebp 4/r32/esp
14425     # setup
14426     (clear-stream _test-input-stream)
14427     (clear-stream $_test-input-buffered-file->buffer)
14428     (clear-stream _test-output-stream)
14429     (clear-stream $_test-output-buffered-file->buffer)
14430     (clear-stream _test-error-stream)
14431     (clear-stream $_test-error-buffered-file->buffer)
14432     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14433     68/push 0/imm32
14434     68/push 0/imm32
14435     89/<- %edx 4/r32/esp
14436     (tailor-exit-descriptor %edx 0x10)
14437     #
14438     (write _test-input-stream "fn foo {\n")
14439     (write _test-input-stream "  var x: boolean\n")
14440     (write _test-input-stream "  var y/xmm1: float <- convert x\n")
14441     (write _test-input-stream "}\n")
14442     # convert
14443     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14444     # registers except esp clobbered at this point
14445     # restore ed
14446     89/<- %edx 4/r32/esp
14447     (flush _test-output-buffered-file)
14448     (flush _test-error-buffered-file)
14449 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
14455     # check output
14456     (check-stream-equal _test-output-stream  ""  "F - test-convert-invalid-inout-type: output should be empty")
14457     (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")
14458     # check that stop(1) was called
14459     (check-ints-equal *(edx+4) 2 "F - test-convert-invalid-inout-type: exit status")
14460     # don't restore from ebp
14461     81 0/subop/add %esp 8/imm32
14462     # . epilogue
14463     5d/pop-to-ebp
14464     c3/return
14465 
14466 test-convert-invalid-output-type:
14467     # . prologue
14468     55/push-ebp
14469     89/<- %ebp 4/r32/esp
14470     # setup
14471     (clear-stream _test-input-stream)
14472     (clear-stream $_test-input-buffered-file->buffer)
14473     (clear-stream _test-output-stream)
14474     (clear-stream $_test-output-buffered-file->buffer)
14475     (clear-stream _test-error-stream)
14476     (clear-stream $_test-error-buffered-file->buffer)
14477     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14478     68/push 0/imm32
14479     68/push 0/imm32
14480     89/<- %edx 4/r32/esp
14481     (tailor-exit-descriptor %edx 0x10)
14482     #
14483     (write _test-input-stream "fn foo {\n")
14484     (write _test-input-stream "  var x: float\n")
14485     (write _test-input-stream "  var y/eax: boolean <- convert x\n")
14486     (write _test-input-stream "}\n")
14487     # convert
14488     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14489     # registers except esp clobbered at this point
14490     # restore ed
14491     89/<- %edx 4/r32/esp
14492     (flush _test-output-buffered-file)
14493     (flush _test-error-buffered-file)
14494 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
14500     # check output
14501     (check-stream-equal _test-output-stream  ""  "F - test-convert-invalid-output-type: output should be empty")
14502     (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")
14503     # check that stop(1) was called
14504     (check-ints-equal *(edx+4) 2 "F - test-convert-invalid-output-type: exit status")
14505     # don't restore from ebp
14506     81 0/subop/add %esp 8/imm32
14507     # . epilogue
14508     5d/pop-to-ebp
14509     c3/return
14510 
14511 test-convert-int-to-int:
14512     # . prologue
14513     55/push-ebp
14514     89/<- %ebp 4/r32/esp
14515     # setup
14516     (clear-stream _test-input-stream)
14517     (clear-stream $_test-input-buffered-file->buffer)
14518     (clear-stream _test-output-stream)
14519     (clear-stream $_test-output-buffered-file->buffer)
14520     (clear-stream _test-error-stream)
14521     (clear-stream $_test-error-buffered-file->buffer)
14522     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14523     68/push 0/imm32
14524     68/push 0/imm32
14525     89/<- %edx 4/r32/esp
14526     (tailor-exit-descriptor %edx 0x10)
14527     #
14528     (write _test-input-stream "fn foo {\n")
14529     (write _test-input-stream "  var x: int\n")
14530     (write _test-input-stream "  var y/eax: int <- convert x\n")
14531     (write _test-input-stream "}\n")
14532     # convert
14533     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14534     # registers except esp clobbered at this point
14535     # restore ed
14536     89/<- %edx 4/r32/esp
14537     (flush _test-output-buffered-file)
14538     (flush _test-error-buffered-file)
14539 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
14545     # check output
14546     (check-stream-equal _test-output-stream  ""  "F - test-convert-int-to-int: output should be empty")
14547     (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")
14548     # check that stop(1) was called
14549     (check-ints-equal *(edx+4) 2 "F - test-convert-int-to-int: exit status")
14550     # don't restore from ebp
14551     81 0/subop/add %esp 8/imm32
14552     # . epilogue
14553     5d/pop-to-ebp
14554     c3/return
14555 
14556 test-convert-float-to-float:
14557     # . prologue
14558     55/push-ebp
14559     89/<- %ebp 4/r32/esp
14560     # setup
14561     (clear-stream _test-input-stream)
14562     (clear-stream $_test-input-buffered-file->buffer)
14563     (clear-stream _test-output-stream)
14564     (clear-stream $_test-output-buffered-file->buffer)
14565     (clear-stream _test-error-stream)
14566     (clear-stream $_test-error-buffered-file->buffer)
14567     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14568     68/push 0/imm32
14569     68/push 0/imm32
14570     89/<- %edx 4/r32/esp
14571     (tailor-exit-descriptor %edx 0x10)
14572     #
14573     (write _test-input-stream "fn foo {\n")
14574     (write _test-input-stream "  var x: float\n")
14575     (write _test-input-stream "  var y/xmm6: float <- convert x\n")
14576     (write _test-input-stream "}\n")
14577     # convert
14578     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14579     # registers except esp clobbered at this point
14580     # restore ed
14581     89/<- %edx 4/r32/esp
14582     (flush _test-output-buffered-file)
14583     (flush _test-error-buffered-file)
14584 +--  6 lines: #?     # dump _test-error-stream ----------------------------------------------------------------------------------------------------------------------------------------
14590     # check output
14591     (check-stream-equal _test-output-stream  ""  "F - test-convert-float-to-float: output should be empty")
14592     (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")
14593     # check that stop(1) was called
14594     (check-ints-equal *(edx+4) 2 "F - test-convert-float-to-float: exit status")
14595     # don't restore from ebp
14596     81 0/subop/add %esp 8/imm32
14597     # . epilogue
14598     5d/pop-to-ebp
14599     c3/return
14600 
14601 #######################################################
14602 # Parsing
14603 #######################################################
14604 
14605 == data
14606 
14607 # Global state added to each var record when parsing a function
14608 Next-block-index:  # (addr int)
14609     1/imm32
14610 
14611 Curr-block-depth:  # (addr int)
14612     1/imm32
14613 
14614 == code
14615 
14616 parse-mu:  # in: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
14617     # pseudocode
14618     #   var curr-function: (addr handle function) = Program->functions
14619     #   var curr-signature: (addr handle function) = Program->signatures
14620     #   var curr-type: (addr handle typeinfo) = Program->types
14621     #   var line: (stream byte 512)
14622     #   var word-slice: slice
14623     #   while true                                  # line loop
14624     #     clear-stream(line)
14625     #     read-line-buffered(in, line)
14626     #     if (line->write == 0) break               # end of file
14627     #     word-slice = next-mu-token(line)
14628     #     if slice-empty?(word-slice)               # end of line
14629     #       continue
14630     #     else if slice-starts-with?(word-slice, "#")  # comment
14631     #       continue                                # end of line
14632     #     else if slice-equal?(word-slice, "fn")
14633     #       var new-function: (handle function) = allocate(function)
14634     #       var vars: (stack live-var 256)
14635     #       populate-mu-function-header(line, new-function, vars)
14636     #       populate-mu-function-body(in, new-function, vars)
14637     #       assert(vars->top == 0)
14638     #       *curr-function = new-function
14639     #       curr-function = &new-function->next
14640     #     else if slice-equal?(word-slice, "sig")
14641     #       var new-function: (handle function) = allocate(function)
14642     #       populate-mu-function-signature(line, new-function)
14643     #       *curr-signature = new-function
14644     #       curr-signature = &new-function->next
14645     #     else if slice-equal?(word-slice, "type")
14646     #       word-slice = next-mu-token(line)
14647     #       type-id = pos-or-insert-slice(Type-id, word-slice)
14648     #       var new-type: (handle typeinfo) = find-or-create-typeinfo(type-id)
14649     #       assert(next-word(line) == "{")
14650     #       populate-mu-type(in, new-type)
14651     #     else
14652     #       abort()
14653     #
14654     # . prologue
14655     55/push-ebp
14656     89/<- %ebp 4/r32/esp
14657     # var curr-signature: (addr handle function) at *(ebp-4)
14658     68/push _Program-signatures/imm32
14659     # . save registers
14660     50/push-eax
14661     51/push-ecx
14662     52/push-edx
14663     53/push-ebx
14664     56/push-esi
14665     57/push-edi
14666     # var line/ecx: (stream byte 512)
14667     81 5/subop/subtract %esp 0x200/imm32
14668     68/push 0x200/imm32/size
14669     68/push 0/imm32/read
14670     68/push 0/imm32/write
14671     89/<- %ecx 4/r32/esp
14672     # var word-slice/edx: slice
14673     68/push 0/imm32/end
14674     68/push 0/imm32/start
14675     89/<- %edx 4/r32/esp
14676     # var curr-function/edi: (addr handle function)
14677     bf/copy-to-edi _Program-functions/imm32
14678     # var vars/ebx: (stack live-var 256)
14679     81 5/subop/subtract %esp 0xc00/imm32
14680     68/push 0xc00/imm32/size
14681     68/push 0/imm32/top
14682     89/<- %ebx 4/r32/esp
14683     {
14684 $parse-mu:line-loop:
14685       (clear-stream %ecx)
14686       (read-line-buffered *(ebp+8) %ecx)
14687       # if (line->write == 0) break
14688       81 7/subop/compare *ecx 0/imm32
14689       0f 84/jump-if-= break/disp32
14690 +--  6 lines: #?       # dump line ----------------------------------------------------------------------------------------------------------------------------------------------------
14696       (next-mu-token %ecx %edx)
14697       # if slice-empty?(word-slice) continue
14698       (slice-empty? %edx)  # => eax
14699       3d/compare-eax-and 0/imm32/false
14700       0f 85/jump-if-!= loop/disp32
14701       # if (*word-slice->start == "#") continue
14702       # . eax = *word-slice->start
14703       8b/-> *edx 0/r32/eax
14704       8a/copy-byte *eax 0/r32/AL
14705       81 4/subop/and %eax 0xff/imm32
14706       # . if (eax == '#') continue
14707       3d/compare-eax-and 0x23/imm32/hash
14708       0f 84/jump-if-= loop/disp32
14709       # if (slice-equal?(word-slice, "fn")) parse a function
14710       {
14711 $parse-mu:fn:
14712         (slice-equal? %edx "fn")  # => eax
14713         3d/compare-eax-and 0/imm32/false
14714         0f 84/jump-if-= break/disp32
14715         # var new-function/esi: (handle function)
14716         68/push 0/imm32
14717         68/push 0/imm32
14718         89/<- %esi 4/r32/esp
14719         # populate-mu-function(line, in, vars, new-function)
14720         (allocate Heap *Function-size %esi)
14721         # var new-function-addr/eax: (addr function)
14722         (lookup *esi *(esi+4))  # => eax
14723         # initialize vars
14724         (clear-stack %ebx)
14725         #
14726         (populate-mu-function-header %ecx %eax %ebx *(ebp+0xc) *(ebp+0x10))
14727         (populate-mu-function-body *(ebp+8) %eax %ebx *(ebp+0xc) *(ebp+0x10))
14728         # *curr-function = new-function
14729         8b/-> *esi 0/r32/eax
14730         89/<- *edi 0/r32/eax
14731         8b/-> *(esi+4) 0/r32/eax
14732         89/<- *(edi+4) 0/r32/eax
14733         # curr-function = &new-function->next
14734         # . var tmp/eax: (addr function) = lookup(new-function)
14735         (lookup *esi *(esi+4))  # => eax
14736         # . curr-function = &tmp->next
14737         8d/copy-address *(eax+0x20) 7/r32/edi  # Function-next
14738         # reclaim new-function
14739         81 0/subop/add %esp 8/imm32
14740         #
14741         e9/jump $parse-mu:line-loop/disp32
14742       }
14743       # if (slice-equal?(word-slice, "sig")) parse a function signature
14744       # Function signatures are for providing types to SubX functions.
14745       {
14746 $parse-mu:sig:
14747         (slice-equal? %edx "sig")  # => eax
14748         3d/compare-eax-and 0/imm32/false
14749         0f 84/jump-if-= break/disp32
14750         # edi = curr-function
14751         57/push-edi
14752         8b/-> *(ebp-4) 7/r32/edi
14753         # var new-function/esi: (handle function)
14754         68/push 0/imm32
14755         68/push 0/imm32
14756         89/<- %esi 4/r32/esp
14757         # populate-mu-function(line, in, vars, new-function)
14758         (allocate Heap *Function-size %esi)
14759         # var new-function-addr/eax: (addr function)
14760         (lookup *esi *(esi+4))  # => eax
14761         #
14762         (populate-mu-function-signature %ecx %eax *(ebp+0xc) *(ebp+0x10))
14763         # *curr-signature = new-function
14764         8b/-> *esi 0/r32/eax
14765         89/<- *edi 0/r32/eax
14766         8b/-> *(esi+4) 0/r32/eax
14767         89/<- *(edi+4) 0/r32/eax
14768         # curr-signature = &new-function->next
14769         # . var tmp/eax: (addr function) = lookup(new-function)
14770         (lookup *esi *(esi+4))  # => eax
14771         # . curr-function = &tmp->next
14772         8d/copy-address *(eax+0x20) 7/r32/edi  # Function-next
14773         # reclaim new-function
14774         81 0/subop/add %esp 8/imm32
14775         # save curr-function
14776         89/<- *(ebp-4) 7/r32/edi
14777         # restore edi
14778         5f/pop-to-edi
14779         #
14780         e9/jump $parse-mu:line-loop/disp32
14781       }
14782       # if (slice-equal?(word-slice, "type")) parse a type (struct/record) definition
14783       {
14784 $parse-mu:type:
14785         (slice-equal? %edx "type")  # => eax
14786         3d/compare-eax-and 0/imm32
14787         0f 84/jump-if-= break/disp32
14788         (next-mu-token %ecx %edx)
14789         # var type-id/eax: int
14790         (pos-or-insert-slice Type-id %edx)  # => eax
14791         # spill
14792         51/push-ecx
14793         # var new-type/ecx: (handle typeinfo)
14794         68/push 0/imm32
14795         68/push 0/imm32
14796         89/<- %ecx 4/r32/esp
14797         (find-or-create-typeinfo %eax %ecx)
14798         #
14799         (lookup *ecx *(ecx+4))  # => eax
14800         # TODO: ensure that 'line' has nothing else but '{'
14801 #? (dump-typeinfos "=== aaa\n")
14802         (populate-mu-type *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10))  # => eax
14803 #? (dump-typeinfos "=== zzz\n")
14804         # reclaim new-type
14805         81 0/subop/add %esp 8/imm32
14806         # restore
14807         59/pop-to-ecx
14808         e9/jump $parse-mu:line-loop/disp32
14809       }
14810       # otherwise abort
14811       e9/jump $parse-mu:error1/disp32
14812     } # end line loop
14813 $parse-mu:end:
14814     # . reclaim locals
14815     81 0/subop/add %esp 0x20c/imm32  # line
14816     81 0/subop/add %esp 0xc08/imm32  # vars
14817     81 0/subop/add %esp 8/imm32
14818     # . restore registers
14819     5f/pop-to-edi
14820     5e/pop-to-esi
14821     5b/pop-to-ebx
14822     5a/pop-to-edx
14823     59/pop-to-ecx
14824     58/pop-to-eax
14825     # . reclaim local
14826     81 0/subop/add %esp 4/imm32
14827     # . epilogue
14828     89/<- %esp 5/r32/ebp
14829     5d/pop-to-ebp
14830     c3/return
14831 
14832 $parse-mu:error1:
14833     # error("unexpected top-level command: " word-slice "\n")
14834     (write-buffered *(ebp+0xc) "unexpected top-level command: ")
14835     (write-slice-buffered *(ebp+0xc) %edx)
14836     (write-buffered *(ebp+0xc) "\n")
14837     (flush *(ebp+0xc))
14838     (stop *(ebp+0x10) 1)
14839     # never gets here
14840 
14841 $parse-mu:error2:
14842     # error(vars->top " vars not reclaimed after fn '" new-function->name "'\n")
14843     (write-int32-hex-buffered *(ebp+0xc) *ebx)
14844     (write-buffered *(ebp+0xc) " vars not reclaimed after fn '")
14845     (write-slice-buffered *(ebp+0xc) *eax)  # Function-name
14846     (write-buffered *(ebp+0xc) "'\n")
14847     (flush *(ebp+0xc))
14848     (stop *(ebp+0x10) 1)
14849     # never gets here
14850 
14851 # scenarios considered:
14852 # ✗ fn foo  # no block
14853 # ✓ fn foo {
14854 # ✗ fn foo { {
14855 # ✗ fn foo { }
14856 # ✗ fn foo { } {
14857 # ✗ fn foo x {
14858 # ✗ fn foo x: {
14859 # ✓ fn foo x: int {
14860 # ✓ fn foo x: int {
14861 # ✓ fn foo x: int -> _/eax: int {
14862 # TODO:
14863 #   disallow outputs of type `(... addr ...)`
14864 #   disallow inputs of type `(... addr ... addr ...)`
14865 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)
14866     # pseudocode:
14867     #   var word-slice: slice
14868     #   next-mu-token(first-line, word-slice)
14869     #   if slice-empty?(word-slice) abort
14870     #   assert(word-slice not in '{' '}' '->')
14871     #   out->name = slice-to-string(word-slice)
14872     #   ## inouts
14873     #   while true
14874     #     word-slice = next-mu-token(first-line)
14875     #     if slice-empty?(word-slice) abort
14876     #     if (word-slice == '{') goto done
14877     #     if (word-slice == '->') break
14878     #     assert(word-slice != '}')
14879     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
14880     #     assert(v->register == null)
14881     #     # v->block-depth is implicitly 0
14882     #     out->inouts = append(v, out->inouts)
14883     #     push(vars, {v, false})
14884     #   ## outputs
14885     #   while true
14886     #     word-slice = next-mu-token(first-line)
14887     #     if slice-empty?(word-slice) abort
14888     #     if (word-slice == '{') break
14889     #     assert(word-slice not in '}' '->')
14890     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
14891     #     assert(v->register != null)
14892     #     assert(v->name == "_")
14893     #     out->outputs = append(v, out->outputs)
14894     #   done:
14895     #
14896     # . prologue
14897     55/push-ebp
14898     89/<- %ebp 4/r32/esp
14899     # . save registers
14900     50/push-eax
14901     51/push-ecx
14902     52/push-edx
14903     53/push-ebx
14904     57/push-edi
14905     # edi = out
14906     8b/-> *(ebp+0xc) 7/r32/edi
14907     # var word-slice/ecx: slice
14908     68/push 0/imm32/end
14909     68/push 0/imm32/start
14910     89/<- %ecx 4/r32/esp
14911     # var v/ebx: (handle var)
14912     68/push 0/imm32
14913     68/push 0/imm32
14914     89/<- %ebx 4/r32/esp
14915     # read function name
14916     (next-mu-token *(ebp+8) %ecx)
14917     # error checking
14918     # if slice-empty?(word-slice) abort
14919     (slice-empty? %ecx)  # => eax
14920     3d/compare-eax-and 0/imm32/false
14921     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
14922     # if (word-slice == '{') abort
14923     (slice-equal? %ecx "{")   # => eax
14924     3d/compare-eax-and 0/imm32/false
14925     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
14926     # if (word-slice == '->') abort
14927     (slice-equal? %ecx "->")   # => eax
14928     3d/compare-eax-and 0/imm32/false
14929     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
14930     # if (word-slice == '}') abort
14931     (slice-equal? %ecx "}")   # => eax
14932     3d/compare-eax-and 0/imm32/false
14933     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
14934     # if word-slice already defined, abort
14935     (function-exists? %ecx)  # => eax
14936     3d/compare-eax-and 0/imm32/false
14937     0f 85/jump-if-!= $populate-mu-function-header:error-duplicate/disp32
14938     #
14939     (slice-starts-with? %ecx "break")  # => eax
14940     3d/compare-eax-and 0/imm32/false
14941     0f 85/jump-if-!= $populate-mu-function-header:error-break/disp32
14942     (slice-starts-with? %ecx "loop")  # => eax
14943     3d/compare-eax-and 0/imm32/false
14944     0f 85/jump-if-!= $populate-mu-function-header:error-loop/disp32
14945     (slice-equal? %ecx "lookup")  # => eax
14946     3d/compare-eax-and 0/imm32/false
14947     0f 85/jump-if-!= $populate-mu-function-header:error-lookup/disp32
14948     # save function name
14949     (slice-to-string Heap %ecx %edi)  # Function-name
14950     # save function inouts
14951     {
14952 $populate-mu-function-header:check-for-inout:
14953       (next-mu-token *(ebp+8) %ecx)
14954       # if slice-empty?(word-slice) abort
14955       (slice-empty? %ecx)  # => eax
14956       3d/compare-eax-and 0/imm32/false
14957       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
14958       # if (word-slice == '{') goto done
14959       (slice-equal? %ecx "{")   # => eax
14960       3d/compare-eax-and 0/imm32/false
14961       0f 85/jump-if-!= $populate-mu-function-header:done/disp32
14962       # if (word-slice == '->') break
14963       (slice-equal? %ecx "->")   # => eax
14964       3d/compare-eax-and 0/imm32/false
14965       0f 85/jump-if-!= break/disp32
14966       # if (word-slice == '}') abort
14967       (slice-equal? %ecx "}")   # => eax
14968       3d/compare-eax-and 0/imm32/false
14969       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
14970       # v = parse-var-with-type(word-slice, first-line)
14971       (lookup *edi *(edi+4))  # Function-name Function-name => eax
14972       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x14) *(ebp+0x18))
14973       # if (v->register != null) abort
14974       # . eax: (addr var) = lookup(v)
14975       (lookup *ebx *(ebx+4))  # => eax
14976       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
14977       0f 85/jump-if-!= $populate-mu-function-header:error2/disp32
14978       # if function name is not "main"
14979       #    and v->type contains an 'addr' anywhere except the start, abort
14980       {
14981         (lookup *edi *(edi+4))  # Function-name Function-name => eax
14982         (string-equal? %eax "main")  # => eax
14983         3d/compare-eax-and 0/imm32/false
14984         75/jump-if-!= break/disp8
14985         (lookup *ebx *(ebx+4))  # => eax
14986         (addr-payload-contains-addr? %eax)  # => eax
14987         3d/compare-eax-and 0/imm32/false
14988         0f 85/jump-if-!= $populate-mu-function-header:error-nested-addr-inout/disp32
14989       }
14990       # v->block-depth is implicitly 0
14991       #
14992       # out->inouts = append(v, out->inouts)
14993       8d/copy-address *(edi+8) 0/r32/eax  # Function-inouts
14994       (append-list Heap  *ebx *(ebx+4)  *(edi+8) *(edi+0xc)  %eax)  # Function-inouts, Function-inouts
14995       # push(vars, {v, false})
14996       (push *(ebp+0x10) *ebx)
14997       (push *(ebp+0x10) *(ebx+4))
14998       (push *(ebp+0x10) 0)  # false
14999       #
15000       e9/jump loop/disp32
15001     }
15002     # save function outputs
15003     {
15004 $populate-mu-function-header:check-for-out:
15005       (next-mu-token *(ebp+8) %ecx)
15006       # if slice-empty?(word-slice) abort
15007       (slice-empty? %ecx)  # => eax
15008       3d/compare-eax-and 0/imm32/false
15009       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
15010       # if (word-slice == '{') break
15011       (slice-equal? %ecx "{")   # => eax
15012       3d/compare-eax-and 0/imm32/false
15013       0f 85/jump-if-!= break/disp32
15014       # if (word-slice == '->') abort
15015       (slice-equal? %ecx "->")   # => eax
15016       3d/compare-eax-and 0/imm32/false
15017       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
15018       # if (word-slice == '}') abort
15019       (slice-equal? %ecx "}")   # => eax
15020       3d/compare-eax-and 0/imm32/false
15021       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
15022       # v = parse-var-with-type(word-slice, first-line)
15023       (lookup *edi *(edi+4))  # Function-name Function-name => eax
15024       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x14) *(ebp+0x18))
15025       # assert(var->register != null)
15026       # . eax: (addr var) = lookup(v)
15027       (lookup *ebx *(ebx+4))  # => eax
15028       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
15029       0f 84/jump-if-= $populate-mu-function-header:error3/disp32
15030       # if (var->name != "_") abort
15031       (lookup *eax *(eax+4))  # Var-name Var-name => eax
15032       (string-equal? %eax "_")  # => eax
15033       3d/compare-eax-and 0/imm32/false
15034       0f 84/jump-if-= $populate-mu-function-header:error4/disp32
15035       # if v->type is an addr, abort
15036       (lookup *ebx *(ebx+4))  # => eax
15037       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
15038       (is-mu-addr-type? %eax)  # => eax
15039       3d/compare-eax-and 0/imm32/false
15040       0f 85/jump-if-!= $populate-mu-function-header:error-addr-output/disp32
15041       # out->outputs = append(v, out->outputs)
15042       8d/copy-address *(edi+0x10) 0/r32/eax  # Function-outputs
15043       (append-list Heap  *ebx *(ebx+4)  *(edi+0x10) *(edi+0x14)  %eax)  # Function-outputs, Function-outputs
15044       #
15045       e9/jump loop/disp32
15046     }
15047 $populate-mu-function-header:done:
15048     (check-no-tokens-left *(ebp+8))
15049 $populate-mu-function-header:end:
15050     # . reclaim locals
15051     81 0/subop/add %esp 0x10/imm32
15052     # . restore registers
15053     5f/pop-to-edi
15054     5b/pop-to-ebx
15055     5a/pop-to-edx
15056     59/pop-to-ecx
15057     58/pop-to-eax
15058     # . epilogue
15059     89/<- %esp 5/r32/ebp
15060     5d/pop-to-ebp
15061     c3/return
15062 
15063 $populate-mu-function-header:error1:
15064     # error("function header not in form 'fn <name> {'")
15065     (write-buffered *(ebp+0x14) "function header not in form 'fn <name> [inouts] [-> outputs] {' -- '")
15066     (flush *(ebp+0x14))
15067     (rewind-stream *(ebp+8))
15068     (write-stream-data *(ebp+0x14) *(ebp+8))
15069     (write-buffered *(ebp+0x14) "'\n")
15070     (flush *(ebp+0x14))
15071     (stop *(ebp+0x18) 1)
15072     # never gets here
15073 
15074 $populate-mu-function-header:error2:
15075     # error("fn " fn ": function inout '" var "' cannot be in a register")
15076     (write-buffered *(ebp+0x14) "fn ")
15077     50/push-eax
15078     (lookup *edi *(edi+4))  # Function-name Function-name => eax
15079     (write-buffered *(ebp+0x14) %eax)
15080     58/pop-to-eax
15081     (write-buffered *(ebp+0x14) ": function inout '")
15082     (lookup *eax *(eax+4))  # Var-name Var-name => eax
15083     (write-buffered *(ebp+0x14) %eax)
15084     (write-buffered *(ebp+0x14) "' cannot be in a register")
15085     (flush *(ebp+0x14))
15086     (stop *(ebp+0x18) 1)
15087     # never gets here
15088 
15089 $populate-mu-function-header:error3:
15090     # error("fn " fn ": function output '" var "' must be in a register")
15091     (write-buffered *(ebp+0x14) "fn ")
15092     50/push-eax
15093     (lookup *edi *(edi+4))  # Function-name Function-name => eax
15094     (write-buffered *(ebp+0x14) %eax)
15095     58/pop-to-eax
15096     (write-buffered *(ebp+0x14) ": function output '")
15097     (lookup *ebx *(ebx+4))  # => eax
15098     (lookup *eax *(eax+4))  # Var-name Var-name => eax
15099     (write-buffered *(ebp+0x14) %eax)
15100     (write-buffered *(ebp+0x14) "' must be in a register, in instruction '")
15101     (rewind-stream *(ebp+8))
15102     (write-stream-data *(ebp+0x14) *(ebp+8))
15103     (write-buffered *(ebp+0x14) "'\n")
15104     (flush *(ebp+0x14))
15105     (stop *(ebp+0x18) 1)
15106     # never gets here
15107 
15108 $populate-mu-function-header:error4:
15109     # error("fn " fn ": function outputs cannot be named; rename '" var "' in the header to '_'")
15110     (write-buffered *(ebp+0x14) "fn ")
15111     50/push-eax
15112     (lookup *edi *(edi+4))  # Function-name Function-name => eax
15113     (write-buffered *(ebp+0x14) %eax)
15114     58/pop-to-eax
15115     (write-buffered *(ebp+0x14) ": function outputs cannot be named; rename '")
15116     (lookup *ebx *(ebx+4))  # => eax
15117     (lookup *eax *(eax+4))  # Var-name Var-name => eax
15118     (write-buffered *(ebp+0x14) %eax)
15119     (write-buffered *(ebp+0x14) "' in the header to '_'\n")
15120     (flush *(ebp+0x14))
15121     (stop *(ebp+0x18) 1)
15122     # never gets here
15123 
15124 $populate-mu-function-header:error-duplicate:
15125     (write-buffered *(ebp+0x14) "fn ")
15126     (write-slice-buffered *(ebp+0x14) %ecx)
15127     (write-buffered *(ebp+0x14) " defined more than once\n")
15128     (flush *(ebp+0x14))
15129     (stop *(ebp+0x18) 1)
15130     # never gets here
15131 
15132 $populate-mu-function-header:error-break:
15133     (write-buffered *(ebp+0x14) "Sorry, I've reserved all function names starting with 'break' for now. Please contact mu@akkartik.com.\n")
15134     (flush *(ebp+0x14))
15135     (stop *(ebp+0x18) 1)
15136     # never gets here
15137 
15138 $populate-mu-function-header:error-loop:
15139     (write-buffered *(ebp+0x14) "Sorry, I've reserved all function names starting with 'loop' for now. Please contact mu@akkartik.com.\n")
15140     (flush *(ebp+0x14))
15141     (stop *(ebp+0x18) 1)
15142     # never gets here
15143 
15144 $populate-mu-function-header:error-lookup:
15145     (write-buffered *(ebp+0x14) "cannot define a function called 'lookup'\n")
15146     (flush *(ebp+0x14))
15147     (stop *(ebp+0x18) 1)
15148     # never gets here
15149 
15150 $populate-mu-function-header:error-addr-output:
15151     # error("fn " fn ": output cannot have an addr type; that could allow unsafe addresses to escape the function")
15152     (write-buffered *(ebp+0x14) "fn ")
15153     50/push-eax
15154     (lookup *edi *(edi+4))  # Function-name Function-name => eax
15155     (write-buffered *(ebp+0x14) %eax)
15156     58/pop-to-eax
15157     (write-buffered *(ebp+0x14) ": output cannot have an addr type; that could allow unsafe addresses to escape the function\n")
15158     (flush *(ebp+0x14))
15159     (stop *(ebp+0x18) 1)
15160     # never gets here
15161 
15162 $populate-mu-function-header:error-nested-addr-inout:
15163     # 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")
15164     (write-buffered *(ebp+0x14) "fn ")
15165     (lookup *edi *(edi+4))  # Function-name Function-name => eax
15166     (write-buffered *(ebp+0x14) %eax)
15167     (write-buffered *(ebp+0x14) ": inout '")
15168     (lookup *ebx *(ebx+4))  # => eax
15169     (lookup *eax *(eax+4))  # Var-name Var-name => eax
15170     (write-buffered *(ebp+0x14) %eax)
15171     (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")
15172     (flush *(ebp+0x14))
15173     (stop *(ebp+0x18) 1)
15174     # never gets here
15175 
15176 # scenarios considered:
15177 # ✓ fn foo
15178 # ✗ fn foo {
15179 # ✓ fn foo x
15180 # ✓ fn foo x: int
15181 # ✓ fn foo x: int -> _/eax: int
15182 # TODO:
15183 #   disallow outputs of type `(... addr ...)`
15184 #   disallow inputs of type `(... addr ... addr ...)`
15185 populate-mu-function-signature:  # first-line: (addr stream byte), out: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
15186     # pseudocode:
15187     #   var word-slice: slice
15188     #   next-mu-token(first-line, word-slice)
15189     #   assert(word-slice not in '{' '}' '->')
15190     #   out->name = slice-to-string(word-slice)
15191     #   ## inouts
15192     #   while true
15193     #     word-slice = next-mu-token(first-line)
15194     #     if slice-empty?(word-slice) break
15195     #     if (word-slice == '->') break
15196     #     assert(word-slice not in '{' '}')
15197     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
15198     #     assert(v->register == null)
15199     #     # v->block-depth is implicitly 0
15200     #     out->inouts = append(v, out->inouts)
15201     #   ## outputs
15202     #   while true
15203     #     word-slice = next-mu-token(first-line)
15204     #     if slice-empty?(word-slice) break
15205     #     assert(word-slice not in '{' '}' '->')
15206     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
15207     #     assert(v->register != null)
15208     #     out->outputs = append(v, out->outputs)
15209     #
15210     # . prologue
15211     55/push-ebp
15212     89/<- %ebp 4/r32/esp
15213     # . save registers
15214     50/push-eax
15215     51/push-ecx
15216     52/push-edx
15217     53/push-ebx
15218     57/push-edi
15219     # edi = out
15220     8b/-> *(ebp+0xc) 7/r32/edi
15221     # var word-slice/ecx: slice
15222     68/push 0/imm32/end
15223     68/push 0/imm32/start
15224     89/<- %ecx 4/r32/esp
15225     # var v/ebx: (handle var)
15226     68/push 0/imm32
15227     68/push 0/imm32
15228     89/<- %ebx 4/r32/esp
15229     # read function name
15230     (next-mu-token *(ebp+8) %ecx)
15231     # error checking
15232     # if (word-slice == '{') abort
15233     (slice-equal? %ecx "{")   # => eax
15234     3d/compare-eax-and 0/imm32/false
15235     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
15236     # if (word-slice == '->') abort
15237     (slice-equal? %ecx "->")   # => eax
15238     3d/compare-eax-and 0/imm32/false
15239     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
15240     # if (word-slice == '}') abort
15241     (slice-equal? %ecx "}")   # => eax
15242     3d/compare-eax-and 0/imm32/false
15243     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
15244     # if word-slice already defined, abort
15245     (function-exists? %ecx)  # => eax
15246     3d/compare-eax-and 0/imm32/false
15247     0f 85/jump-if-!= $populate-mu-function-signature:error-duplicate/disp32
15248     #
15249     (slice-starts-with? %ecx "break")  # => eax
15250     3d/compare-eax-and 0/imm32/false
15251     0f 85/jump-if-!= $populate-mu-function-signature:error-break/disp32
15252     (slice-starts-with? %ecx "loop")  # => eax
15253     3d/compare-eax-and 0/imm32/false
15254     0f 85/jump-if-!= $populate-mu-function-signature:error-loop/disp32
15255     # save function name
15256     (slice-to-string Heap %ecx %edi)  # Function-name
15257     # save function inouts
15258     {
15259 $populate-mu-function-signature:check-for-inout:
15260       (next-mu-token *(ebp+8) %ecx)
15261       (slice-empty? %ecx)  # => eax
15262       3d/compare-eax-and 0/imm32/false
15263       0f 85/jump-if-!= break/disp32
15264       # if (word-slice == '->') break
15265       (slice-equal? %ecx "->")   # => eax
15266       3d/compare-eax-and 0/imm32/false
15267       0f 85/jump-if-!= break/disp32
15268       # if (word-slice == '{') abort
15269       (slice-equal? %ecx "{")   # => eax
15270       3d/compare-eax-and 0/imm32/false
15271       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
15272       # if (word-slice == '}') abort
15273       (slice-equal? %ecx "}")   # => eax
15274       3d/compare-eax-and 0/imm32/false
15275       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
15276       # v = parse-var-with-type(word-slice, first-line)
15277       (lookup *edi *(edi+4))  # Function-name Function-name => eax
15278       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x10) *(ebp+0x14))
15279       # if (v->register != null) abort
15280       # . eax: (addr var) = lookup(v)
15281       (lookup *ebx *(ebx+4))  # => eax
15282       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
15283       0f 85/jump-if-!= $populate-mu-function-signature:error2/disp32
15284       # if function name is not "main"
15285       #    and v->type contains an 'addr' anywhere except the start, abort
15286       {
15287         (lookup *edi *(edi+4))  # Function-name Function-name => eax
15288         (string-equal? %eax "main")  # => eax
15289         3d/compare-eax-and 0/imm32/false
15290         75/jump-if-!= break/disp8
15291         (lookup *ebx *(ebx+4))  # => eax
15292         (addr-payload-contains-addr? %eax)  # => eax
15293         3d/compare-eax-and 0/imm32/false
15294         0f 85/jump-if-!= $populate-mu-function-signature:error-nested-addr-inout/disp32
15295       }
15296       # assert(v->register == null)
15297       # . eax: (addr var) = lookup(v)
15298       (lookup *ebx *(ebx+4))  # => eax
15299       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
15300       0f 85/jump-if-!= $populate-mu-function-signature:error2/disp32
15301       # v->block-depth is implicitly 0
15302       #
15303       # out->inouts = append(v, out->inouts)
15304       8d/copy-address *(edi+8) 0/r32/eax  # Function-inouts
15305       (append-list Heap  *ebx *(ebx+4)  *(edi+8) *(edi+0xc)  %eax)  # Function-inouts, Function-inouts
15306       #
15307       e9/jump loop/disp32
15308     }
15309     # save function outputs
15310     {
15311 $populate-mu-function-signature:check-for-out:
15312       (next-mu-token *(ebp+8) %ecx)
15313       (slice-empty? %ecx)  # => eax
15314       3d/compare-eax-and 0/imm32/false
15315       0f 85/jump-if-!= break/disp32
15316       # if (word-slice == '{') abort
15317       (slice-equal? %ecx "{")   # => eax
15318       3d/compare-eax-and 0/imm32/false
15319       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
15320       # if (word-slice == '->') abort
15321       (slice-equal? %ecx "->")   # => eax
15322       3d/compare-eax-and 0/imm32/false
15323       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
15324       # if (word-slice == '}') abort
15325       (slice-equal? %ecx "}")   # => eax
15326       3d/compare-eax-and 0/imm32/false
15327       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
15328       # v = parse-var-with-type(word-slice, first-line)
15329       (lookup *edi *(edi+4))  # Function-name Function-name => eax
15330       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x10) *(ebp+0x14))
15331       # assert(var->register != null)
15332       # . eax: (addr var) = lookup(v)
15333       (lookup *ebx *(ebx+4))  # => eax
15334       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
15335       0f 84/jump-if-= $populate-mu-function-signature:error3/disp32
15336       # if (var->name != "_") abort
15337       (lookup *eax *(eax+4))  # Var-name Var-name => eax
15338       (string-equal? %eax "_")  # => eax
15339       3d/compare-eax-and 0/imm32/false
15340       0f 84/jump-if-= $populate-mu-function-signature:error4/disp32
15341       # if function name is not "lookup"
15342       #    and v->type is an addr, abort
15343       {
15344         (lookup *edi *(edi+4))  # Function-name Function-name => eax
15345         (string-equal? %eax "lookup")  # => eax
15346         3d/compare-eax-and 0/imm32/false
15347         75/jump-if-!= break/disp8
15348         (lookup *ebx *(ebx+4))  # => eax
15349         (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
15350         (is-mu-addr-type? %eax)  # => eax
15351         3d/compare-eax-and 0/imm32/false
15352         0f 85/jump-if-!= $populate-mu-function-signature:error-addr-output/disp32
15353       }
15354       # out->outputs = append(v, out->outputs)
15355       8d/copy-address *(edi+0x10) 0/r32/eax  # Function-outputs
15356       (append-list Heap  *ebx *(ebx+4)  *(edi+0x10) *(edi+0x14)  %eax)  # Function-outputs, Function-outputs
15357       #
15358       e9/jump loop/disp32
15359     }
15360 $populate-mu-function-signature:done:
15361     (check-no-tokens-left *(ebp+8))
15362 $populate-mu-function-signature:end:
15363     # . reclaim locals
15364     81 0/subop/add %esp 0x10/imm32
15365     # . restore registers
15366     5f/pop-to-edi
15367     5b/pop-to-ebx
15368     5a/pop-to-edx
15369     59/pop-to-ecx
15370     58/pop-to-eax
15371     # . epilogue
15372     89/<- %esp 5/r32/ebp
15373     5d/pop-to-ebp
15374     c3/return
15375 
15376 $populate-mu-function-signature:error1:
15377     # error("function signature not in form 'fn <name> {'")
15378     (write-buffered *(ebp+0x10) "function signature not in form 'fn <name> [inouts] [-> outputs] {' -- '")
15379     (flush *(ebp+0x10))
15380     (rewind-stream *(ebp+8))
15381     (write-stream-data *(ebp+0x10) *(ebp+8))
15382     (write-buffered *(ebp+0x10) "'\n")
15383     (flush *(ebp+0x10))
15384     (stop *(ebp+0x14) 1)
15385     # never gets here
15386 
15387 $populate-mu-function-signature:error2:
15388     # error("fn " fn ": function inout '" var "' cannot be in a register")
15389     (write-buffered *(ebp+0x10) "fn ")
15390     50/push-eax
15391     (lookup *edi *(edi+4))  # Function-name Function-name => eax
15392     (write-buffered *(ebp+0x10) %eax)
15393     58/pop-to-eax
15394     (write-buffered *(ebp+0x10) ": function inout '")
15395     (lookup *eax *(eax+4))  # Var-name Var-name => eax
15396     (write-buffered *(ebp+0x10) %eax)
15397     (write-buffered *(ebp+0x10) "' cannot be in a register")
15398     (flush *(ebp+0x10))
15399     (stop *(ebp+0x14) 1)
15400     # never gets here
15401 
15402 $populate-mu-function-signature:error3:
15403     # error("fn " fn ": function output '" var "' must be in a register")
15404     (write-buffered *(ebp+0x10) "fn ")
15405     50/push-eax
15406     (lookup *edi *(edi+4))  # Function-name Function-name => eax
15407     (write-buffered *(ebp+0x10) %eax)
15408     58/pop-to-eax
15409     (write-buffered *(ebp+0x10) ": function output '")
15410     (lookup *ebx *(ebx+4))  # => eax
15411     (lookup *eax *(eax+4))  # Var-name Var-name => eax
15412     (write-buffered *(ebp+0x10) %eax)
15413     (write-buffered *(ebp+0x10) "' must be in a register, in instruction '")
15414     (rewind-stream *(ebp+8))
15415     (write-stream-data *(ebp+0x10) *(ebp+8))
15416     (write-buffered *(ebp+0x10) "'\n")
15417     (flush *(ebp+0x10))
15418     (stop *(ebp+0x14) 1)
15419     # never gets here
15420 
15421 $populate-mu-function-signature:error4:
15422     # error("fn " fn ": function outputs cannot be named; rename '" var "' in the header to '_'")
15423     (write-buffered *(ebp+0x10) "fn ")
15424     50/push-eax
15425     (lookup *edi *(edi+4))  # Function-name Function-name => eax
15426     (write-buffered *(ebp+0x10) %eax)
15427     58/pop-to-eax
15428     (write-buffered *(ebp+0x10) ": function outputs cannot be named; rename '")
15429     (lookup *ebx *(ebx+4))  # => eax
15430     (lookup *eax *(eax+4))  # Var-name Var-name => eax
15431     (write-buffered *(ebp+0x10) %eax)
15432     (write-buffered *(ebp+0x10) "' in the header to '_'\n")
15433     (flush *(ebp+0x10))
15434     (stop *(ebp+0x14) 1)
15435     # never gets here
15436 
15437 $populate-mu-function-signature:error-duplicate:
15438     (write-buffered *(ebp+0x10) "fn ")
15439     (write-slice-buffered *(ebp+0x10) %ecx)
15440     (write-buffered *(ebp+0x10) " defined more than once\n")
15441     (flush *(ebp+0x10))
15442     (stop *(ebp+0x14) 1)
15443     # never gets here
15444 
15445 $populate-mu-function-signature:error-break:
15446     (write-buffered *(ebp+0x10) "Sorry, I've reserved all function names starting with 'break' for now. Please contact mu@akkartik.com.\n")
15447     (flush *(ebp+0x10))
15448     (stop *(ebp+0x14) 1)
15449     # never gets here
15450 
15451 $populate-mu-function-signature:error-loop:
15452     (write-buffered *(ebp+0x10) "Sorry, I've reserved all function names starting with 'loop' for now. Please contact mu@akkartik.com.\n")
15453     (flush *(ebp+0x10))
15454     (stop *(ebp+0x14) 1)
15455     # never gets here
15456 
15457 $populate-mu-function-signature:error-addr-output:
15458     # error("fn " fn ": output cannot have an addr type; that could allow unsafe addresses to escape the function")
15459     (write-buffered *(ebp+0x10) "fn ")
15460     50/push-eax
15461     (lookup *edi *(edi+4))  # Function-name Function-name => eax
15462     (write-buffered *(ebp+0x10) %eax)
15463     58/pop-to-eax
15464     (write-buffered *(ebp+0x10) ": output cannot have an addr type; that could allow unsafe addresses to escape the function\n")
15465     (flush *(ebp+0x10))
15466     (stop *(ebp+0x14) 1)
15467     # never gets here
15468 
15469 $populate-mu-function-signature:error-nested-addr-inout:
15470     # 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")
15471     (write-buffered *(ebp+0x10) "fn ")
15472     (lookup *edi *(edi+4))  # Function-name Function-name => eax
15473     (write-buffered *(ebp+0x10) %eax)
15474     (write-buffered *(ebp+0x10) ": inout '")
15475     (lookup *ebx *(ebx+4))  # => eax
15476     (lookup *eax *(eax+4))  # Var-name Var-name => eax
15477     (write-buffered *(ebp+0x10) %eax)
15478     (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")
15479     (flush *(ebp+0x10))
15480     (stop *(ebp+0x14) 1)
15481     # never gets here
15482 
15483 addr-payload-contains-addr?:  # v: (addr var) -> result/eax: boolean
15484     # . prologue
15485     55/push-ebp
15486     89/<- %ebp 4/r32/esp
15487     # var t/eax: (addr type-tree) = v->type
15488     8b/-> *(ebp+8) 0/r32/eax
15489     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
15490     # if t->right contains addr, return true
15491     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
15492     (type-tree-contains? %eax 2)  # addr => eax
15493     # we don't have to look at t->left as long as it's guaranteed to be an atom
15494 $addr-payload-contains-addr?:end:
15495     # . epilogue
15496     89/<- %esp 5/r32/ebp
15497     5d/pop-to-ebp
15498     c3/return
15499 
15500 type-tree-contains?:  # t: (addr type-tree), n: type-id -> result/eax: boolean
15501     # . prologue
15502     55/push-ebp
15503     89/<- %ebp 4/r32/esp
15504     # . save registers
15505     51/push-ecx
15506     # if t is null, return false
15507     8b/-> *(ebp+8) 0/r32/eax
15508     3d/compare-eax-and 0/imm32
15509     0f 84/jump-if-= $type-tree-contains?:end/disp32  # eax changes type
15510     # if t is an atom, return (t->value == n)
15511     81 7/subop/compare *eax 0/imm32/false
15512     {
15513       74/jump-if-= break/disp8
15514       8b/-> *(ebp+0xc) 1/r32/ecx
15515       39/compare *(eax+4) 1/r32/ecx  # Type-tree-value
15516       0f 94/set-if-= %al
15517       81 4/subop/and %eax 0xff/imm32
15518       eb/jump $type-tree-contains?:end/disp8
15519     }
15520     # if t->left contains n, return true
15521     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
15522     (type-tree-contains? %eax *(ebp+0xc))  # => eax
15523     3d/compare-eax-and 0/imm32/false
15524     75/jump-if-!= $type-tree-contains?:end/disp8
15525     # otherwise return whether t->right contains n
15526     8b/-> *(ebp+8) 0/r32/eax
15527     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
15528     (type-tree-contains? %eax *(ebp+0xc))  # => eax
15529 $type-tree-contains?:end:
15530     # . restore registers
15531     59/pop-to-ecx
15532     # . epilogue
15533     89/<- %esp 5/r32/ebp
15534     5d/pop-to-ebp
15535     c3/return
15536 
15537 function-exists?:  # s: (addr slice) -> result/eax: boolean
15538     # . prologue
15539     55/push-ebp
15540     89/<- %ebp 4/r32/esp
15541     # . save registers
15542     51/push-ecx
15543     # var curr/ecx: (addr function) = functions
15544     (lookup *_Program-functions *_Program-functions->payload)  # => eax
15545     89/<- %ecx 0/r32/eax
15546     {
15547       # if (curr == null) break
15548       81 7/subop/compare %ecx 0/imm32
15549       74/jump-if-= break/disp8
15550       # if (curr->name == s) return true
15551       {
15552         (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
15553         (slice-equal? *(ebp+8) %eax)  # => eax
15554         3d/compare-eax-and 0/imm32/false
15555         74/jump-if-= break/disp8
15556         b8/copy-to-eax 1/imm32/true
15557         e9/jump $function-exists?:end/disp32
15558       }
15559       # curr = curr->next
15560       (lookup *(ecx+0x20) *(ecx+0x24))  # Function-next Function-next => eax
15561       89/<- %ecx 0/r32/eax
15562       #
15563       eb/jump loop/disp8
15564     }
15565     # var curr/ecx: (addr function) = signatures
15566     (lookup *_Program-signatures *_Program-signatures->payload)  # => eax
15567     89/<- %ecx 0/r32/eax
15568     {
15569       # if (curr == null) break
15570       81 7/subop/compare %ecx 0/imm32
15571       74/jump-if-= break/disp8
15572       # if (curr->name == s) return true
15573       {
15574         (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
15575         (slice-equal? *(ebp+8) %eax)  # => eax
15576         3d/compare-eax-and 0/imm32/false
15577         74/jump-if-= break/disp8
15578         b8/copy-to-eax 1/imm32/true
15579         eb/jump $function-exists?:end/disp8
15580       }
15581       # curr = curr->next
15582       (lookup *(ecx+0x20) *(ecx+0x24))  # Function-next Function-next => eax
15583       89/<- %ecx 0/r32/eax
15584       #
15585       eb/jump loop/disp8
15586     }
15587     # return false
15588     b8/copy-to-eax 0/imm32/false
15589 $function-exists?:end:
15590     # . restore registers
15591     59/pop-to-ecx
15592     # . epilogue
15593     89/<- %esp 5/r32/ebp
15594     5d/pop-to-ebp
15595     c3/return
15596 
15597 test-function-header-with-arg:
15598     # . prologue
15599     55/push-ebp
15600     89/<- %ebp 4/r32/esp
15601     # setup
15602     8b/-> *Primitive-type-ids 0/r32/eax
15603     89/<- *Type-id 0/r32/eax  # stream-write
15604     c7 0/subop/copy *_Program-functions 0/imm32
15605     c7 0/subop/copy *_Program-functions->payload 0/imm32
15606     c7 0/subop/copy *_Program-types 0/imm32
15607     c7 0/subop/copy *_Program-types->payload 0/imm32
15608     c7 0/subop/copy *_Program-signatures 0/imm32
15609     c7 0/subop/copy *_Program-signatures->payload 0/imm32
15610     (clear-stream _test-input-stream)
15611     (write _test-input-stream "foo n: int {\n")
15612     # var result/ecx: function
15613     2b/subtract *Function-size 4/r32/esp
15614     89/<- %ecx 4/r32/esp
15615     (zero-out %ecx *Function-size)
15616     # var vars/ebx: (stack live-var 16)
15617     81 5/subop/subtract %esp 0xc0/imm32
15618     68/push 0xc0/imm32/size
15619     68/push 0/imm32/top
15620     89/<- %ebx 4/r32/esp
15621     # convert
15622     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
15623     # check result->name
15624     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
15625     (check-strings-equal %eax "foo" "F - test-function-header-with-arg/name")
15626     # var v/edx: (addr var) = result->inouts->value
15627     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
15628     (lookup *eax *(eax+4))  # List-value List-value => eax
15629     89/<- %edx 0/r32/eax
15630     # check v->name
15631     (lookup *edx *(edx+4))  # Var-name Var-name => eax
15632     (check-strings-equal %eax "n" "F - test-function-header-with-arg/inout:0")
15633     # check v->type
15634     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
15635     (check-ints-equal *eax 1 "F - test-function-header-with-arg/inout:0/type:0")  # Type-tree-is-atom
15636     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-arg/inout:0/type:1")  # Type-tree-value
15637     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-arg/inout:0/type:2")  # Type-tree-right
15638     # . epilogue
15639     89/<- %esp 5/r32/ebp
15640     5d/pop-to-ebp
15641     c3/return
15642 
15643 test-function-header-with-multiple-args:
15644     # . prologue
15645     55/push-ebp
15646     89/<- %ebp 4/r32/esp
15647     # setup
15648     8b/-> *Primitive-type-ids 0/r32/eax
15649     89/<- *Type-id 0/r32/eax  # stream-write
15650     c7 0/subop/copy *_Program-functions 0/imm32
15651     c7 0/subop/copy *_Program-functions->payload 0/imm32
15652     c7 0/subop/copy *_Program-types 0/imm32
15653     c7 0/subop/copy *_Program-types->payload 0/imm32
15654     c7 0/subop/copy *_Program-signatures 0/imm32
15655     c7 0/subop/copy *_Program-signatures->payload 0/imm32
15656     (clear-stream _test-input-stream)
15657     (write _test-input-stream "foo a: int, b: int c: int {\n")
15658     # result/ecx: function
15659     2b/subtract *Function-size 4/r32/esp
15660     89/<- %ecx 4/r32/esp
15661     (zero-out %ecx *Function-size)
15662     # var vars/ebx: (stack live-var 16)
15663     81 5/subop/subtract %esp 0xc0/imm32
15664     68/push 0xc0/imm32/size
15665     68/push 0/imm32/top
15666     89/<- %ebx 4/r32/esp
15667     # convert
15668     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
15669     # check result->name
15670     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
15671     (check-strings-equal %eax "foo" "F - test-function-header-with-multiple-args/name")
15672     # var inouts/edx: (addr list var) = lookup(result->inouts)
15673     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
15674     89/<- %edx 0/r32/eax
15675 $test-function-header-with-multiple-args:inout0:
15676     # var v/ebx: (addr var) = lookup(inouts->value)
15677     (lookup *edx *(edx+4))  # List-value List-value => eax
15678     89/<- %ebx 0/r32/eax
15679     # check v->name
15680     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
15681     (check-strings-equal %eax "a" "F - test-function-header-with-multiple-args/inout:0")  # Var-name
15682     # check v->type
15683     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
15684     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:0/type:0")  # Type-tree-is-atom
15685     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:0/type:1")  # Type-tree-value
15686     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:0/type:2")  # Type-tree-right
15687 $test-function-header-with-multiple-args:inout1:
15688     # inouts = lookup(inouts->next)
15689     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
15690     89/<- %edx 0/r32/eax
15691     # v = lookup(inouts->value)
15692     (lookup *edx *(edx+4))  # List-value List-value => eax
15693     89/<- %ebx 0/r32/eax
15694     # check v->name
15695     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
15696     (check-strings-equal %eax "b" "F - test-function-header-with-multiple-args/inout:1")  # Var-name
15697     # check v->type
15698     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
15699     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:1/type:0")  # Type-tree-is-atom
15700     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:1/type:1")  # Type-tree-value
15701     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:1/type:2")  # Type-tree-right
15702 $test-function-header-with-multiple-args:inout2:
15703     # inouts = lookup(inouts->next)
15704     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
15705     89/<- %edx 0/r32/eax
15706     # v = lookup(inouts->value)
15707     (lookup *edx *(edx+4))  # List-value List-value => eax
15708     89/<- %ebx 0/r32/eax
15709     # check v->name
15710     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
15711     (check-strings-equal %eax "c" "F - test-function-header-with-multiple-args/inout:2")  # Var-name
15712     # check v->type
15713     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
15714     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:2/type:0")  # Type-tree-is-atom
15715     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:2/type:1")  # Type-tree-value
15716     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:2/type:2")  # Type-tree-right
15717     # . epilogue
15718     89/<- %esp 5/r32/ebp
15719     5d/pop-to-ebp
15720     c3/return
15721 
15722 test-function-header-with-multiple-args-and-outputs:
15723     # . prologue
15724     55/push-ebp
15725     89/<- %ebp 4/r32/esp
15726     # setup
15727     8b/-> *Primitive-type-ids 0/r32/eax
15728     89/<- *Type-id 0/r32/eax  # stream-write
15729     c7 0/subop/copy *_Program-functions 0/imm32
15730     c7 0/subop/copy *_Program-functions->payload 0/imm32
15731     c7 0/subop/copy *_Program-types 0/imm32
15732     c7 0/subop/copy *_Program-types->payload 0/imm32
15733     c7 0/subop/copy *_Program-signatures 0/imm32
15734     c7 0/subop/copy *_Program-signatures->payload 0/imm32
15735     (clear-stream _test-input-stream)
15736     (write _test-input-stream "foo a: int, b: int, c: int -> _/ecx: int _/edx: int {\n")
15737     # result/ecx: function
15738     2b/subtract *Function-size 4/r32/esp
15739     89/<- %ecx 4/r32/esp
15740     (zero-out %ecx *Function-size)
15741     # var vars/ebx: (stack live-var 16)
15742     81 5/subop/subtract %esp 0xc0/imm32
15743     68/push 0xc0/imm32/size
15744     68/push 0/imm32/top
15745     89/<- %ebx 4/r32/esp
15746     # convert
15747     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
15748     # check result->name
15749     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
15750     (check-strings-equal %eax "foo" "F - test-function-header-with-multiple-args-and-outputs/name")
15751     # var inouts/edx: (addr list var) = lookup(result->inouts)
15752     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
15753     89/<- %edx 0/r32/eax
15754 $test-function-header-with-multiple-args-and-outputs:inout0:
15755     # var v/ebx: (addr var) = lookup(inouts->value)
15756     (lookup *edx *(edx+4))  # List-value List-value => eax
15757     89/<- %ebx 0/r32/eax
15758     # check v->name
15759     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
15760     (check-strings-equal %eax "a" "F - test-function-header-with-multiple-args-and-outputs/inout:0")
15761     # check v->type
15762     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
15763     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:0")  # Type-tree-is-atom
15764     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:1")  # Type-tree-value
15765     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:2")  # Type-tree-right
15766 $test-function-header-with-multiple-args-and-outputs:inout1:
15767     # inouts = lookup(inouts->next)
15768     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
15769     89/<- %edx 0/r32/eax
15770     # v = lookup(inouts->value)
15771     (lookup *edx *(edx+4))  # List-value List-value => eax
15772     89/<- %ebx 0/r32/eax
15773     # check v->name
15774     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
15775     (check-strings-equal %eax "b" "F - test-function-header-with-multiple-args-and-outputs/inout:1")
15776     # check v->type
15777     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
15778     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:0")  # Type-tree-is-atom
15779     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:1")  # Type-tree-value
15780     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:2")  # Type-tree-right
15781 $test-function-header-with-multiple-args-and-outputs:inout2:
15782     # inouts = lookup(inouts->next)
15783     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
15784     89/<- %edx 0/r32/eax
15785     # v = lookup(inouts->value)
15786     (lookup *edx *(edx+4))  # List-value List-value => eax
15787     89/<- %ebx 0/r32/eax
15788     # check v->name
15789     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
15790     (check-strings-equal %eax "c" "F - test-function-header-with-multiple-args-and-outputs/inout:2")
15791     # check v->type
15792     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
15793     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:0")  # Type-tree-is-atom
15794     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:1")  # Type-tree-value
15795     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:2")  # Type-tree-right
15796 $test-function-header-with-multiple-args-and-outputs:out0:
15797     # var outputs/edx: (addr list var) = lookup(result->outputs)
15798     (lookup *(ecx+0x10) *(ecx+0x14))  # Function-outputs Function-outputs => eax
15799     89/<- %edx 0/r32/eax
15800     # v = lookup(outputs->value)
15801     (lookup *edx *(edx+4))  # List-value List-value => eax
15802     89/<- %ebx 0/r32/eax
15803     # check v->name
15804     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
15805     (check-strings-equal %eax "_" "F - test-function-header-with-multiple-args-and-outputs/output:0")
15806     # check v->register
15807     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
15808     (check-strings-equal %eax "ecx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register")
15809     # check v->type
15810     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
15811     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:0")  # Type-tree-is-atom
15812     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1")  # Type-tree-value
15813     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:2")  # Type-tree-right
15814 $test-function-header-with-multiple-args-and-outputs:out1:
15815     # outputs = lookup(outputs->next)
15816     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
15817     89/<- %edx 0/r32/eax
15818     # v = lookup(inouts->value)
15819     (lookup *edx *(edx+4))  # List-value List-value => eax
15820     89/<- %ebx 0/r32/eax
15821     # check v->name
15822     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
15823     (check-strings-equal %eax "_" "F - test-function-header-with-multiple-args-and-outputs/output:1")
15824     # check v->register
15825     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
15826     (check-strings-equal %eax "edx" "F - test-function-header-with-multiple-args-and-outputs/output:1/register")
15827     # check v->type
15828     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
15829     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:0")  # Type-tree-is-atom
15830     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1")  # Type-tree-value
15831     (check-ints-equal *(eax+0c) 0 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:2")  # Type-tree-right
15832     # . epilogue
15833     89/<- %esp 5/r32/ebp
15834     5d/pop-to-ebp
15835     c3/return
15836 
15837 # format for variables with types
15838 #   x: int
15839 #   x: int,
15840 #   x/eax: int
15841 #   x/eax: int,
15842 # ignores at most one trailing comma
15843 # WARNING: modifies name
15844 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)
15845     # pseudocode:
15846     #   var s: slice
15847     #   if (!slice-ends-with(name, ":"))
15848     #     abort
15849     #   --name->end to skip ':'
15850     #   next-token-from-slice(name->start, name->end, '/', s)
15851     #   new-var-from-slice(s, out)
15852     #   ## register
15853     #   next-token-from-slice(s->end, name->end, '/', s)
15854     #   if (!slice-empty?(s))
15855     #     out->register = slice-to-string(s)
15856     #   ## type
15857     #   var type: (handle type-tree) = parse-type(first-line)
15858     #   out->type = type
15859     #
15860     # . prologue
15861     55/push-ebp
15862     89/<- %ebp 4/r32/esp
15863     # . save registers
15864     50/push-eax
15865     51/push-ecx
15866     52/push-edx
15867     53/push-ebx
15868     56/push-esi
15869     57/push-edi
15870     # esi = name
15871     8b/-> *(ebp+8) 6/r32/esi
15872     # if (!slice-ends-with?(name, ":")) abort
15873     8b/-> *(esi+4) 1/r32/ecx  # Slice-end
15874     49/decrement-ecx
15875     8a/copy-byte *ecx 1/r32/CL
15876     81 4/subop/and %ecx 0xff/imm32
15877     81 7/subop/compare %ecx 0x3a/imm32/colon
15878     0f 85/jump-if-!= $parse-var-with-type:abort/disp32
15879     # --name->end to skip ':'
15880     ff 1/subop/decrement *(esi+4)
15881     # var s/ecx: slice
15882     68/push 0/imm32/end
15883     68/push 0/imm32/start
15884     89/<- %ecx 4/r32/esp
15885 $parse-var-with-type:parse-name:
15886     (next-token-from-slice *esi *(esi+4) 0x2f %ecx)  # Slice-start, Slice-end, '/'
15887 $parse-var-with-type:create-var:
15888     # new-var-from-slice(s, out)
15889     (new-var-from-slice Heap %ecx *(ebp+0x10))
15890     # save out->register
15891 $parse-var-with-type:save-register:
15892     # . var out-addr/edi: (addr var) = lookup(*out)
15893     8b/-> *(ebp+0x10) 7/r32/edi
15894     (lookup *edi *(edi+4))  # => eax
15895     89/<- %edi 0/r32/eax
15896     # . s = next-token(...)
15897     (next-token-from-slice *(ecx+4) *(esi+4) 0x2f %ecx)  # s->end, name->end, '/'
15898     # . if (!slice-empty?(s)) out->register = slice-to-string(s)
15899     {
15900 $parse-var-with-type:write-register:
15901       (slice-empty? %ecx)  # => eax
15902       3d/compare-eax-and 0/imm32/false
15903       75/jump-if-!= break/disp8
15904       # out->register = slice-to-string(s)
15905       8d/copy-address *(edi+0x18) 0/r32/eax  # Var-register
15906       (slice-to-string Heap %ecx %eax)
15907     }
15908 $parse-var-with-type:save-type:
15909     8d/copy-address *(edi+8) 0/r32/eax  # Var-type
15910     (parse-type Heap *(ebp+0xc) %eax *(ebp+0x18) *(ebp+0x1c))
15911 $parse-var-with-type:check-register:
15912     (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
15913     3d/compare-eax-and 0/imm32
15914     74/jump-if-= $parse-var-with-type:end/disp8
15915     (is-float-register? %eax)  # => eax
15916     {
15917       3d/compare-eax-and 0/imm32/false
15918       74/jump-if-= break/disp8
15919       # var is in a float register; ensure type is float
15920       (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
15921       (is-simple-mu-type? %eax 0xf)  # float => eax
15922       3d/compare-eax-and 0/imm32/false
15923       0f 84/jump-if-= $parse-var-with-type:error-non-float-in-floating-point-register/disp32
15924       eb/jump $parse-var-with-type:end/disp8
15925     }
15926     # var is not in a float register; ensure type is not float
15927     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
15928     (is-simple-mu-type? %eax 0xf)  # float => eax
15929     3d/compare-eax-and 0/imm32/false
15930     0f 85/jump-if-!= $parse-var-with-type:error-float-in-integer-register/disp32
15931 $parse-var-with-type:end:
15932     # . reclaim locals
15933     81 0/subop/add %esp 8/imm32
15934     # . restore registers
15935     5f/pop-to-edi
15936     5e/pop-to-esi
15937     5b/pop-to-ebx
15938     5a/pop-to-edx
15939     59/pop-to-ecx
15940     58/pop-to-eax
15941     # . epilogue
15942     89/<- %esp 5/r32/ebp
15943     5d/pop-to-ebp
15944     c3/return
15945 
15946 $parse-var-with-type:abort:
15947     # error("fn " fn ": var should have form 'name: type' in '" line "'\n")
15948     (write-buffered *(ebp+0x18) "fn ")
15949     (write-buffered *(ebp+0x18) *(ebp+0x14))
15950     (write-buffered *(ebp+0x18) ": var should have form 'name: type' in '")
15951     (flush *(ebp+0x18))
15952     (rewind-stream *(ebp+0xc))
15953     (write-stream-data *(ebp+0x18) *(ebp+0xc))
15954     (write-buffered *(ebp+0x18) "'\n")
15955     (flush *(ebp+0x18))
15956     (stop *(ebp+0x1c) 1)
15957     # never gets here
15958 
15959 $parse-var-with-type:error-float-in-integer-register:
15960     # error("fn " fn ": float var '" var "' should be in a floating-point register\n")
15961     (write-buffered *(ebp+0x18) "fn ")
15962     (write-buffered *(ebp+0x18) *(ebp+0x14))
15963     (write-buffered *(ebp+0x18) ": float var '")
15964     (lookup *edi *(edi+4))  # Var-name Var-name => eax
15965     (write-buffered *(ebp+0x18) %eax)
15966     (write-buffered *(ebp+0x18) "' should be in a floating-point register\n")
15967     (flush *(ebp+0x18))
15968     (stop *(ebp+0x1c) 1)
15969     # never gets here
15970 
15971 $parse-var-with-type:error-non-float-in-floating-point-register:
15972     # error("fn " fn ": non-float var '" var "' should be in an integer register\n")
15973     (write-buffered *(ebp+0x18) "fn ")
15974     (write-buffered *(ebp+0x18) *(ebp+0x14))
15975     (write-buffered *(ebp+0x18) ": non-float var '")
15976     (lookup *edi *(edi+4))  # Var-name Var-name => eax
15977     (write-buffered *(ebp+0x18) %eax)
15978     (write-buffered *(ebp+0x18) "' should be in an integer register\n")
15979     (flush *(ebp+0x18))
15980     (stop *(ebp+0x1c) 1)
15981     # never gets here
15982 
15983 is-float-register?:  # r: (addr array byte) -> result/eax: boolean
15984     # . prologue
15985     55/push-ebp
15986     89/<- %ebp 4/r32/esp
15987     #
15988     (get Mu-registers-unique *(ebp+8) 0xc "Mu-registers-unique")  # => eax
15989     81 7/subop/compare *eax 8/imm32/start-of-floating-point-registers
15990     0f 9d/set-if->= %al
15991     81 4/subop/and %eax 0xff/imm32
15992 $is-float-register?:end:
15993     # . epilogue
15994     89/<- %esp 5/r32/ebp
15995     5d/pop-to-ebp
15996     c3/return
15997 
15998 parse-type:  # ad: (addr allocation-descriptor), in: (addr stream byte), out: (addr handle type-tree), err: (addr buffered-file), ed: (addr exit-descriptor)
15999     # pseudocode:
16000     #   var s: slice = next-mu-token(in)
16001     #   assert s != ""
16002     #   assert s != "->"
16003     #   assert s != "{"
16004     #   assert s != "}"
16005     #   if s == ")"
16006     #     return
16007     #   out = allocate(Type-tree)
16008     #   if s != "("
16009     #     HACK: if s is an int, parse and return it
16010     #     out->is-atom? = true
16011     #     if (s[0] == "_")
16012     #       out->value = type-parameter
16013     #       out->parameter-name = slice-to-string(ad, s)
16014     #     else
16015     #       out->value = pos-or-insert-slice(Type-id, s)
16016     #     return
16017     #   out->left = parse-type(ad, in)
16018     #   out->right = parse-type-tree(ad, in)
16019     #
16020     # . prologue
16021     55/push-ebp
16022     89/<- %ebp 4/r32/esp
16023     # . save registers
16024     50/push-eax
16025     51/push-ecx
16026     52/push-edx
16027     # clear out
16028     (zero-out *(ebp+0x10) *Handle-size)
16029     # var s/ecx: slice
16030     68/push 0/imm32
16031     68/push 0/imm32
16032     89/<- %ecx 4/r32/esp
16033     # s = next-mu-token(in)
16034     (next-mu-token *(ebp+0xc) %ecx)
16035 #?     (write-buffered Stderr "tok: ")
16036 #?     (write-slice-buffered Stderr %ecx)
16037 #?     (write-buffered Stderr "$\n")
16038 #?     (flush Stderr)
16039     # assert s != ""
16040     (slice-equal? %ecx "")  # => eax
16041     3d/compare-eax-and 0/imm32/false
16042     0f 85/jump-if-!= $parse-type:abort/disp32
16043     # assert s != "{"
16044     (slice-equal? %ecx "{")  # => eax
16045     3d/compare-eax-and 0/imm32/false
16046     0f 85/jump-if-!= $parse-type:abort/disp32
16047     # assert s != "}"
16048     (slice-equal? %ecx "}")  # => eax
16049     3d/compare-eax-and 0/imm32/false
16050     0f 85/jump-if-!= $parse-type:abort/disp32
16051     # assert s != "->"
16052     (slice-equal? %ecx "->")  # => eax
16053     3d/compare-eax-and 0/imm32/false
16054     0f 85/jump-if-!= $parse-type:abort/disp32
16055     # if (s == ")") return
16056     (slice-equal? %ecx ")")  # => eax
16057     3d/compare-eax-and 0/imm32/false
16058     0f 85/jump-if-!= $parse-type:end/disp32
16059     # out = new tree
16060     (allocate *(ebp+8) *Type-tree-size *(ebp+0x10))
16061     # var out-addr/edx: (addr type-tree) = lookup(*out)
16062     8b/-> *(ebp+0x10) 2/r32/edx
16063     (lookup *edx *(edx+4))  # => eax
16064     89/<- %edx 0/r32/eax
16065     {
16066       # if (s != "(") break
16067       (slice-equal? %ecx "(")  # => eax
16068       3d/compare-eax-and 0/imm32/false
16069       0f 85/jump-if-!= break/disp32
16070       # if s is a number, store it in the type's size field
16071       {
16072 $parse-type:check-for-int:
16073         # var tmp/eax: byte = *s->slice
16074         8b/-> *ecx 0/r32/eax
16075         8a/copy-byte *eax 0/r32/AL
16076         81 4/subop/and %eax 0xff/imm32
16077         # TODO: raise an error on `var x: (array int a)`
16078         (is-decimal-digit? %eax)  # => eax
16079         3d/compare-eax-and 0/imm32/false
16080         74/jump-if-= break/disp8
16081         #
16082         (is-hex-int? %ecx)  # => eax
16083         3d/compare-eax-and 0/imm32/false
16084         74/jump-if-= break/disp8
16085 $parse-type:int:
16086         (check-mu-hex-int %ecx *(ebp+0x14) *(ebp+0x18))
16087         (parse-hex-int-from-slice %ecx)  # => eax
16088         c7 0/subop/copy *(edx+4) 9/imm32/type-id-array-capacity  # Type-tree-value
16089         89/<- *(edx+8) 0/r32/eax  # Type-tree-value-size
16090         e9/jump $parse-type:end/disp32
16091       }
16092 $parse-type:atom:
16093       # out->is-atom? = true
16094       c7 0/subop/copy *edx 1/imm32/true  # Type-tree-is-atom
16095       {
16096 $parse-type:check-for-type-parameter:
16097         # var tmp/eax: byte = *s->slice
16098         8b/-> *ecx 0/r32/eax
16099         8a/copy-byte *eax 0/r32/AL
16100         81 4/subop/and %eax 0xff/imm32
16101         # if (tmp != '_') break
16102         3d/compare-eax-and 0x5f/imm32/_
16103         75/jump-if-!= break/disp8
16104 $parse-type:type-parameter:
16105         # out->value = type-parameter
16106         c7 0/subop/copy *(edx+4) 0xa/imm32/type-parameter  # Type-tree-value
16107         # out->parameter-name = slice-to-string(ad, s)
16108         8d/copy-address *(edx+8) 0/r32/eax  # Type-tree-parameter-name
16109         (slice-to-string *(ebp+8) %ecx %eax)
16110         e9/jump $parse-type:end/disp32
16111       }
16112 $parse-type:non-type-parameter:
16113       # out->value = pos-or-insert-slice(Type-id, s)
16114       (pos-or-insert-slice Type-id %ecx)  # => eax
16115       89/<- *(edx+4) 0/r32/eax  # Type-tree-value
16116       e9/jump $parse-type:end/disp32
16117     }
16118 $parse-type:non-atom:
16119     # otherwise s == "("
16120     # out->left = parse-type(ad, in)
16121     8d/copy-address *(edx+4) 0/r32/eax  # Type-tree-left
16122     (parse-type *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
16123     # out->right = parse-type-tree(ad, in)
16124     8d/copy-address *(edx+0xc) 0/r32/eax  # Type-tree-right
16125     (parse-type-tree *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
16126 $parse-type:end:
16127     # . reclaim locals
16128     81 0/subop/add %esp 8/imm32
16129     # . restore registers
16130     5a/pop-to-edx
16131     59/pop-to-ecx
16132     58/pop-to-eax
16133     # . epilogue
16134     89/<- %esp 5/r32/ebp
16135     5d/pop-to-ebp
16136     c3/return
16137 
16138 $parse-type:abort:
16139     # error("unexpected token when parsing type: '" s "'\n")
16140     (write-buffered *(ebp+0x14) "unexpected token when parsing type: '")
16141     (write-slice-buffered *(ebp+0x14) %ecx)
16142     (write-buffered *(ebp+0x14) "'\n")
16143     (flush *(ebp+0x14))
16144     (stop *(ebp+0x18) 1)
16145     # never gets here
16146 
16147 parse-type-tree:  # ad: (addr allocation-descriptor), in: (addr stream byte), out: (addr handle type-tree), err: (addr buffered-file), ed: (addr exit-descriptor)
16148     # pseudocode:
16149     #   var tmp: (handle type-tree) = parse-type(ad, in)
16150     #   if tmp == 0
16151     #     return 0
16152     #   out = allocate(Type-tree)
16153     #   out->left = tmp
16154     #   out->right = parse-type-tree(ad, in)
16155     #
16156     # . prologue
16157     55/push-ebp
16158     89/<- %ebp 4/r32/esp
16159     # . save registers
16160     50/push-eax
16161     51/push-ecx
16162     52/push-edx
16163     #
16164     (zero-out *(ebp+0x10) *Handle-size)
16165     # var tmp/ecx: (handle type-tree)
16166     68/push 0/imm32
16167     68/push 0/imm32
16168     89/<- %ecx 4/r32/esp
16169     # tmp = parse-type(ad, in)
16170     (parse-type *(ebp+8) *(ebp+0xc) %ecx *(ebp+0x14) *(ebp+0x18))
16171     # if (tmp == 0) return
16172     81 7/subop/compare *ecx 0/imm32
16173     74/jump-if-= $parse-type-tree:end/disp8
16174     # out = new tree
16175     (allocate *(ebp+8) *Type-tree-size *(ebp+0x10))
16176     # var out-addr/edx: (addr tree) = lookup(*out)
16177     8b/-> *(ebp+0x10) 2/r32/edx
16178     (lookup *edx *(edx+4))  # => eax
16179     89/<- %edx 0/r32/eax
16180     # out->left = tmp
16181     8b/-> *ecx 0/r32/eax
16182     89/<- *(edx+4) 0/r32/eax  # Type-tree-left
16183     8b/-> *(ecx+4) 0/r32/eax
16184     89/<- *(edx+8) 0/r32/eax  # Type-tree-left
16185     # out->right = parse-type-tree(ad, in)
16186     8d/copy-address *(edx+0xc) 0/r32/eax  # Type-tree-right
16187     (parse-type-tree *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
16188 $parse-type-tree:end:
16189     # . reclaim locals
16190     81 0/subop/add %esp 8/imm32
16191     # . restore registers
16192     5a/pop-to-edx
16193     59/pop-to-ecx
16194     58/pop-to-eax
16195     # . epilogue
16196     89/<- %esp 5/r32/ebp
16197     5d/pop-to-ebp
16198     c3/return
16199 
16200 next-mu-token:  # in: (addr stream byte), out: (addr slice)
16201     # pseudocode:
16202     # start:
16203     #   skip-chars-matching-whitespace(in)
16204     #   if in->read >= in->write              # end of in
16205     #     out = {0, 0}
16206     #     return
16207     #   out->start = &in->data[in->read]
16208     #   var curr-byte/eax: byte = in->data[in->read]
16209     #   if curr->byte == ','                  # comment token
16210     #     ++in->read
16211     #     goto start
16212     #   if curr-byte == '#'                   # comment
16213     #     goto done                             # treat as eof
16214     #   if curr-byte == '"'                   # string literal
16215     #     skip-string(in)
16216     #     goto done                           # no metadata
16217     #   if curr-byte == '('
16218     #     ++in->read
16219     #     goto done
16220     #   if curr-byte == ')'
16221     #     ++in->read
16222     #     goto done
16223     #   # read a word
16224     #   while true
16225     #     if in->read >= in->write
16226     #       break
16227     #     curr-byte = in->data[in->read]
16228     #     if curr-byte == ' '
16229     #       break
16230     #     if curr-byte == '\r'
16231     #       break
16232     #     if curr-byte == '\n'
16233     #       break
16234     #     if curr-byte == '('
16235     #       break
16236     #     if curr-byte == ')'
16237     #       break
16238     #     if curr-byte == ','
16239     #       break
16240     #     ++in->read
16241     # done:
16242     #   out->end = &in->data[in->read]
16243     #
16244     # . prologue
16245     55/push-ebp
16246     89/<- %ebp 4/r32/esp
16247     # . save registers
16248     50/push-eax
16249     51/push-ecx
16250     56/push-esi
16251     57/push-edi
16252     # esi = in
16253     8b/-> *(ebp+8) 6/r32/esi
16254     # edi = out
16255     8b/-> *(ebp+0xc) 7/r32/edi
16256 $next-mu-token:start:
16257     (skip-chars-matching-whitespace %esi)
16258 $next-mu-token:check0:
16259     # if (in->read >= in->write) return out = {0, 0}
16260     # . ecx = in->read
16261     8b/-> *(esi+4) 1/r32/ecx
16262     # . if (ecx >= in->write) return out = {0, 0}
16263     3b/compare<- *esi 1/r32/ecx
16264     c7 0/subop/copy *edi 0/imm32
16265     c7 0/subop/copy *(edi+4) 0/imm32
16266     0f 8d/jump-if->= $next-mu-token:end/disp32
16267     # out->start = &in->data[in->read]
16268     8d/copy-address *(esi+ecx+0xc) 0/r32/eax
16269     89/<- *edi 0/r32/eax
16270     # var curr-byte/eax: byte = in->data[in->read]
16271     31/xor-with %eax 0/r32/eax
16272     8a/copy-byte *(esi+ecx+0xc) 0/r32/AL
16273     {
16274 $next-mu-token:check-for-comma:
16275       # if (curr-byte != ',') break
16276       3d/compare-eax-and 0x2c/imm32/comma
16277       75/jump-if-!= break/disp8
16278       # ++in->read
16279       ff 0/subop/increment *(esi+4)
16280       # restart
16281       e9/jump $next-mu-token:start/disp32
16282     }
16283     {
16284 $next-mu-token:check-for-comment:
16285       # if (curr-byte != '#') break
16286       3d/compare-eax-and 0x23/imm32/pound
16287       75/jump-if-!= break/disp8
16288       # return eof
16289       e9/jump $next-mu-token:done/disp32
16290     }
16291     {
16292 $next-mu-token:check-for-string-literal:
16293       # if (curr-byte != '"') break
16294       3d/compare-eax-and 0x22/imm32/dquote
16295       75/jump-if-!= break/disp8
16296       (skip-string %esi)
16297       # return
16298       e9/jump $next-mu-token:done/disp32
16299     }
16300     {
16301 $next-mu-token:check-for-open-paren:
16302       # if (curr-byte != '(') break
16303       3d/compare-eax-and 0x28/imm32/open-paren
16304       75/jump-if-!= break/disp8
16305       # ++in->read
16306       ff 0/subop/increment *(esi+4)
16307       # return
16308       e9/jump $next-mu-token:done/disp32
16309     }
16310     {
16311 $next-mu-token:check-for-close-paren:
16312       # if (curr-byte != ')') break
16313       3d/compare-eax-and 0x29/imm32/close-paren
16314       75/jump-if-!= break/disp8
16315       # ++in->read
16316       ff 0/subop/increment *(esi+4)
16317       # return
16318       e9/jump $next-mu-token:done/disp32
16319     }
16320     {
16321 $next-mu-token:regular-word-without-metadata:
16322       # if (in->read >= in->write) break
16323       # . ecx = in->read
16324       8b/-> *(esi+4) 1/r32/ecx
16325       # . if (ecx >= in->write) break
16326       3b/compare<- *esi 1/r32/ecx
16327       7d/jump-if->= break/disp8
16328       # var c/eax: byte = in->data[in->read]
16329       31/xor-with %eax 0/r32/eax
16330       8a/copy-byte *(esi+ecx+0xc) 0/r32/AL
16331       # if (c == ' ') break
16332       3d/compare-eax-and 0x20/imm32/space
16333       74/jump-if-= break/disp8
16334       # if (c == '\r') break
16335       3d/compare-eax-and 0xd/imm32/carriage-return
16336       74/jump-if-= break/disp8
16337       # if (c == '\n') break
16338       3d/compare-eax-and 0xa/imm32/newline
16339       74/jump-if-= break/disp8
16340       # if (c == '(') break
16341       3d/compare-eax-and 0x28/imm32/open-paren
16342       0f 84/jump-if-= break/disp32
16343       # if (c == ')') break
16344       3d/compare-eax-and 0x29/imm32/close-paren
16345       0f 84/jump-if-= break/disp32
16346       # if (c == ',') break
16347       3d/compare-eax-and 0x2c/imm32/comma
16348       0f 84/jump-if-= break/disp32
16349       # ++in->read
16350       ff 0/subop/increment *(esi+4)
16351       #
16352       e9/jump loop/disp32
16353     }
16354 $next-mu-token:done:
16355     # out->end = &in->data[in->read]
16356     8b/-> *(esi+4) 1/r32/ecx
16357     8d/copy-address *(esi+ecx+0xc) 0/r32/eax
16358     89/<- *(edi+4) 0/r32/eax
16359 $next-mu-token:end:
16360     # . restore registers
16361     5f/pop-to-edi
16362     5e/pop-to-esi
16363     59/pop-to-ecx
16364     58/pop-to-eax
16365     # . epilogue
16366     89/<- %esp 5/r32/ebp
16367     5d/pop-to-ebp
16368     c3/return
16369 
16370 pos-or-insert-slice:  # arr: (addr stream (addr array byte)), s: (addr slice) -> index/eax: int
16371     # . prologue
16372     55/push-ebp
16373     89/<- %ebp 4/r32/esp
16374     # if (pos-slice(arr, s) != -1) return it
16375     (pos-slice *(ebp+8) *(ebp+0xc))  # => eax
16376     3d/compare-eax-and -1/imm32
16377     75/jump-if-!= $pos-or-insert-slice:end/disp8
16378 $pos-or-insert-slice:insert:
16379     # var s2/eax: (handle array byte)
16380     68/push 0/imm32
16381     68/push 0/imm32
16382     89/<- %eax 4/r32/esp
16383     (slice-to-string Heap *(ebp+0xc) %eax)
16384     # throw away alloc-id
16385     (lookup *eax *(eax+4))  # => eax
16386     (write-int *(ebp+8) %eax)
16387     (pos-slice *(ebp+8) *(ebp+0xc))  # => eax
16388 $pos-or-insert-slice:end:
16389     # . reclaim locals
16390     81 0/subop/add %esp 8/imm32
16391     # . epilogue
16392     89/<- %esp 5/r32/ebp
16393     5d/pop-to-ebp
16394     c3/return
16395 
16396 # return the index in an array of strings matching 's', -1 if not found
16397 # index is denominated in elements, not bytes
16398 pos-slice:  # arr: (addr stream (addr array byte)), s: (addr slice) -> index/eax: int
16399     # . prologue
16400     55/push-ebp
16401     89/<- %ebp 4/r32/esp
16402     # . save registers
16403     51/push-ecx
16404     52/push-edx
16405     53/push-ebx
16406     56/push-esi
16407 #?     (write-buffered Stderr "pos-slice: ")
16408 #?     (write-slice-buffered Stderr *(ebp+0xc))
16409 #?     (write-buffered Stderr "\n")
16410 #?     (flush Stderr)
16411     # esi = arr
16412     8b/-> *(ebp+8) 6/r32/esi
16413     # var index/ecx: int = 0
16414     b9/copy-to-ecx 0/imm32
16415     # var curr/edx: (addr (addr array byte)) = arr->data
16416     8d/copy-address *(esi+0xc) 2/r32/edx
16417     # var max/ebx: (addr (addr array byte)) = &arr->data[arr->write]
16418     8b/-> *esi 3/r32/ebx
16419     8d/copy-address *(esi+ebx+0xc) 3/r32/ebx
16420     {
16421 #?       (write-buffered Stderr "  ")
16422 #?       (write-int32-hex-buffered Stderr %ecx)
16423 #?       (write-buffered Stderr "\n")
16424 #?       (flush Stderr)
16425       # if (curr >= max) return -1
16426       39/compare %edx 3/r32/ebx
16427       b8/copy-to-eax -1/imm32
16428       73/jump-if-addr>= $pos-slice:end/disp8
16429       # if (slice-equal?(s, *curr)) break
16430       (slice-equal? *(ebp+0xc) *edx)  # => eax
16431       3d/compare-eax-and 0/imm32/false
16432       75/jump-if-!= break/disp8
16433       # ++index
16434       41/increment-ecx
16435       # curr += 4
16436       81 0/subop/add %edx 4/imm32
16437       #
16438       eb/jump loop/disp8
16439     }
16440     # return index
16441     89/<- %eax 1/r32/ecx
16442 $pos-slice:end:
16443 #?     (write-buffered Stderr "=> ")
16444 #?     (write-int32-hex-buffered Stderr %eax)
16445 #?     (write-buffered Stderr "\n")
16446     # . restore registers
16447     5e/pop-to-esi
16448     5b/pop-to-ebx
16449     5a/pop-to-edx
16450     59/pop-to-ecx
16451     # . epilogue
16452     89/<- %esp 5/r32/ebp
16453     5d/pop-to-ebp
16454     c3/return
16455 
16456 test-parse-var-with-type:
16457     # . prologue
16458     55/push-ebp
16459     89/<- %ebp 4/r32/esp
16460     # setup
16461     8b/-> *Primitive-type-ids 0/r32/eax
16462     89/<- *Type-id 0/r32/eax  # stream-write
16463     # (eax..ecx) = "x:"
16464     b8/copy-to-eax "x:"/imm32
16465     8b/-> *eax 1/r32/ecx
16466     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16467     05/add-to-eax 4/imm32
16468     # var slice/ecx: slice = {eax, ecx}
16469     51/push-ecx
16470     50/push-eax
16471     89/<- %ecx 4/r32/esp
16472     # _test-input-stream contains "int"
16473     (clear-stream _test-input-stream)
16474     (write _test-input-stream "int")
16475     # var v/edx: (handle var)
16476     68/push 0/imm32
16477     68/push 0/imm32
16478     89/<- %edx 4/r32/esp
16479     #
16480     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
16481     # var v-addr/edx: (addr var) = lookup(v)
16482     (lookup *edx *(edx+4))  # => eax
16483     89/<- %edx 0/r32/eax
16484     # check v-addr->name
16485     (lookup *edx *(edx+4))  # Var-name Var-name => eax
16486     (check-strings-equal %eax "x" "F - test-parse-var-with-type/name")
16487     # check v-addr->type
16488     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
16489     (check-ints-equal *eax 1 "F - test-parse-var-with-type/type:0")  # Type-tree-is-atom
16490     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-type/type:1")  # Type-tree-value
16491     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-type/type:2")  # Type-tree-right
16492     # . epilogue
16493     89/<- %esp 5/r32/ebp
16494     5d/pop-to-ebp
16495     c3/return
16496 
16497 test-parse-var-with-type-and-register:
16498     # . prologue
16499     55/push-ebp
16500     89/<- %ebp 4/r32/esp
16501     # setup
16502     8b/-> *Primitive-type-ids 0/r32/eax
16503     89/<- *Type-id 0/r32/eax  # stream-write
16504     # (eax..ecx) = "x/eax:"
16505     b8/copy-to-eax "x/eax:"/imm32
16506     8b/-> *eax 1/r32/ecx
16507     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16508     05/add-to-eax 4/imm32
16509     # var slice/ecx: slice = {eax, ecx}
16510     51/push-ecx
16511     50/push-eax
16512     89/<- %ecx 4/r32/esp
16513     # _test-input-stream contains "int"
16514     (clear-stream _test-input-stream)
16515     (write _test-input-stream "int")
16516     # var v/edx: (handle var)
16517     68/push 0/imm32
16518     68/push 0/imm32
16519     89/<- %edx 4/r32/esp
16520     #
16521     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
16522     # var v-addr/edx: (addr var) = lookup(v)
16523     (lookup *edx *(edx+4))  # => eax
16524     89/<- %edx 0/r32/eax
16525     # check v-addr->name
16526     (lookup *edx *(edx+4))  # Var-name Var-name => eax
16527     (check-strings-equal %eax "x" "F - test-parse-var-with-type-and-register/name")
16528     # check v-addr->register
16529     (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
16530     (check-strings-equal %eax "eax" "F - test-parse-var-with-type-and-register/register")
16531     # check v-addr->type
16532     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
16533     (check-ints-equal *eax 1 "F - test-parse-var-with-type-and-register/type:0")  # Type-tree-is-atom
16534     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-type-and-register/type:1")  # Type-tree-left
16535     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-type-and-register/type:2")  # Type-tree-right
16536     # . epilogue
16537     89/<- %esp 5/r32/ebp
16538     5d/pop-to-ebp
16539     c3/return
16540 
16541 test-parse-var-with-trailing-characters:
16542     # . prologue
16543     55/push-ebp
16544     89/<- %ebp 4/r32/esp
16545     # setup
16546     8b/-> *Primitive-type-ids 0/r32/eax
16547     89/<- *Type-id 0/r32/eax  # stream-write
16548     # (eax..ecx) = "x:"
16549     b8/copy-to-eax "x:"/imm32
16550     8b/-> *eax 1/r32/ecx
16551     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16552     05/add-to-eax 4/imm32
16553     # var slice/ecx: slice = {eax, ecx}
16554     51/push-ecx
16555     50/push-eax
16556     89/<- %ecx 4/r32/esp
16557     # _test-input-stream contains "int,"
16558     (clear-stream _test-input-stream)
16559     (write _test-input-stream "int,")
16560     # var v/edx: (handle var)
16561     68/push 0/imm32
16562     68/push 0/imm32
16563     89/<- %edx 4/r32/esp
16564     #
16565     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
16566     # var v-addr/edx: (addr var) = lookup(v)
16567     (lookup *edx *(edx+4))  # => eax
16568     89/<- %edx 0/r32/eax
16569     # check v-addr->name
16570     (lookup *edx *(edx+4))  # Var-name Var-name => eax
16571     (check-strings-equal %eax "x" "F - test-parse-var-with-trailing-characters/name")
16572     # check v-addr->register
16573     (check-ints-equal *(edx+0x18) 0 "F - test-parse-var-with-trailing-characters/register")  # Var-register
16574     # check v-addr->type
16575     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
16576     (check-ints-equal *eax 1 "F - test-parse-var-with-trailing-characters/type:0")  # Type-tree-is-atom
16577     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-trailing-characters/type:1")  # Type-tree-left
16578     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-trailing-characters/type:1")  # Type-tree-right
16579     # . epilogue
16580     89/<- %esp 5/r32/ebp
16581     5d/pop-to-ebp
16582     c3/return
16583 
16584 test-parse-var-with-register-and-trailing-characters:
16585     # . prologue
16586     55/push-ebp
16587     89/<- %ebp 4/r32/esp
16588     # setup
16589     8b/-> *Primitive-type-ids 0/r32/eax
16590     89/<- *Type-id 0/r32/eax  # stream-write
16591     # (eax..ecx) = "x/eax:"
16592     b8/copy-to-eax "x/eax:"/imm32
16593     8b/-> *eax 1/r32/ecx
16594     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16595     05/add-to-eax 4/imm32
16596     # var slice/ecx: slice = {eax, ecx}
16597     51/push-ecx
16598     50/push-eax
16599     89/<- %ecx 4/r32/esp
16600     # _test-input-stream contains "int,"
16601     (clear-stream _test-input-stream)
16602     (write _test-input-stream "int,")
16603     # var v/edx: (handle var)
16604     68/push 0/imm32
16605     68/push 0/imm32
16606     89/<- %edx 4/r32/esp
16607     #
16608     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
16609     # var v-addr/edx: (addr var) = lookup(v)
16610     (lookup *edx *(edx+4))  # => eax
16611     89/<- %edx 0/r32/eax
16612     # check v-addr->name
16613     (lookup *edx *(edx+4))  # Var-name Var-name => eax
16614     (check-strings-equal %eax "x" "F - test-parse-var-with-register-and-trailing-characters/name")
16615     # check v-addr->register
16616     (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
16617     (check-strings-equal %eax "eax" "F - test-parse-var-with-register-and-trailing-characters/register")
16618     # check v-addr->type
16619     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
16620     (check-ints-equal *eax 1 "F - test-parse-var-with-register-and-trailing-characters/type:0")  # Type-tree-is-atom
16621     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-register-and-trailing-characters/type:1")  # Type-tree-left
16622     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-register-and-trailing-characters/type:2")  # Type-tree-right
16623     # . epilogue
16624     89/<- %esp 5/r32/ebp
16625     5d/pop-to-ebp
16626     c3/return
16627 
16628 test-parse-var-with-compound-type:
16629     # . prologue
16630     55/push-ebp
16631     89/<- %ebp 4/r32/esp
16632     # setup
16633     8b/-> *Primitive-type-ids 0/r32/eax
16634     89/<- *Type-id 0/r32/eax  # stream-write
16635     # (eax..ecx) = "x:"
16636     b8/copy-to-eax "x:"/imm32
16637     8b/-> *eax 1/r32/ecx
16638     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16639     05/add-to-eax 4/imm32
16640     # var slice/ecx: slice = {eax, ecx}
16641     51/push-ecx
16642     50/push-eax
16643     89/<- %ecx 4/r32/esp
16644     # _test-input-stream contains "(addr int)"
16645     (clear-stream _test-input-stream)
16646     (write _test-input-stream "(addr int)")
16647     # var v/edx: (handle var)
16648     68/push 0/imm32
16649     68/push 0/imm32
16650     89/<- %edx 4/r32/esp
16651     #
16652     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
16653     # var v-addr/edx: (addr var) = lookup(v)
16654     (lookup *edx *(edx+4))  # => eax
16655     89/<- %edx 0/r32/eax
16656     # check v-addr->name
16657     (lookup *edx *(edx+4))  # Var-name Var-name => eax
16658     (check-strings-equal %eax "x" "F - test-parse-var-with-compound-type/name")
16659     # check v-addr->register
16660     (check-ints-equal *(edx+0x18) 0 "F - test-parse-var-with-compound-type/register")  # Var-register
16661     # - check v-addr->type
16662     # var type/edx: (addr type-tree) = var->type
16663     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
16664     89/<- %edx 0/r32/eax
16665     # type is a non-atom
16666     (check-ints-equal *edx 0 "F - test-parse-var-with-compound-type/type:0")  # Type-tree-is-atom
16667     # type->left == atom(addr)
16668     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
16669     (check-ints-equal *eax 1 "F - test-parse-var-with-compound-type/type:1")  # Type-tree-is-atom
16670     (check-ints-equal *(eax+4) 2 "F - test-parse-var-with-compound-type/type:2")  # Type-tree-value
16671     # type->right->left == atom(int)
16672     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
16673     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
16674     (check-ints-equal *eax 1 "F - test-parse-var-with-compound-type/type:3")  # Type-tree-is-atom
16675     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-compound-type/type:4")  # Type-tree-value
16676     # type->right->right == null
16677     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-compound-type/type:5")  # Type-tree-right
16678     # . epilogue
16679     89/<- %esp 5/r32/ebp
16680     5d/pop-to-ebp
16681     c3/return
16682 
16683 # identifier starts with a letter or '$' or '_'
16684 # no constraints at the moment on later letters
16685 # all we really want to do so far is exclude '{', '}' and '->'
16686 is-identifier?:  # in: (addr slice) -> result/eax: boolean
16687     # . prologue
16688     55/push-ebp
16689     89/<- %ebp 4/r32/esp
16690     # if (slice-empty?(in)) return false
16691     (slice-empty? *(ebp+8))  # => eax
16692     3d/compare-eax-and 0/imm32/false
16693     75/jump-if-!= $is-identifier?:false/disp8
16694     # var c/eax: byte = *in->start
16695     8b/-> *(ebp+8) 0/r32/eax
16696     8b/-> *eax 0/r32/eax
16697     8a/copy-byte *eax 0/r32/AL
16698     81 4/subop/and %eax 0xff/imm32
16699     # if (c == '$') return true
16700     3d/compare-eax-and 0x24/imm32/$
16701     74/jump-if-= $is-identifier?:true/disp8
16702     # if (c == '_') return true
16703     3d/compare-eax-and 0x5f/imm32/_
16704     74/jump-if-= $is-identifier?:true/disp8
16705     # drop case
16706     25/and-eax-with 0x5f/imm32
16707     # if (c < 'A') return false
16708     3d/compare-eax-and 0x41/imm32/A
16709     7c/jump-if-< $is-identifier?:false/disp8
16710     # if (c > 'Z') return false
16711     3d/compare-eax-and 0x5a/imm32/Z
16712     7f/jump-if-> $is-identifier?:false/disp8
16713     # otherwise return true
16714 $is-identifier?:true:
16715     b8/copy-to-eax 1/imm32/true
16716     eb/jump $is-identifier?:end/disp8
16717 $is-identifier?:false:
16718     b8/copy-to-eax 0/imm32/false
16719 $is-identifier?:end:
16720     # . epilogue
16721     89/<- %esp 5/r32/ebp
16722     5d/pop-to-ebp
16723     c3/return
16724 
16725 test-is-identifier-dollar:
16726     # . prologue
16727     55/push-ebp
16728     89/<- %ebp 4/r32/esp
16729     # (eax..ecx) = "$a"
16730     b8/copy-to-eax "$a"/imm32
16731     8b/-> *eax 1/r32/ecx
16732     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16733     05/add-to-eax 4/imm32
16734     # var slice/ecx: slice = {eax, ecx}
16735     51/push-ecx
16736     50/push-eax
16737     89/<- %ecx 4/r32/esp
16738     #
16739     (is-identifier? %ecx)
16740     (check-ints-equal %eax 1 "F - test-is-identifier-dollar")
16741     # . epilogue
16742     89/<- %esp 5/r32/ebp
16743     5d/pop-to-ebp
16744     c3/return
16745 
16746 test-is-identifier-underscore:
16747     # . prologue
16748     55/push-ebp
16749     89/<- %ebp 4/r32/esp
16750     # (eax..ecx) = "_a"
16751     b8/copy-to-eax "_a"/imm32
16752     8b/-> *eax 1/r32/ecx
16753     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16754     05/add-to-eax 4/imm32
16755     # var slice/ecx: slice = {eax, ecx}
16756     51/push-ecx
16757     50/push-eax
16758     89/<- %ecx 4/r32/esp
16759     #
16760     (is-identifier? %ecx)
16761     (check-ints-equal %eax 1 "F - test-is-identifier-underscore")
16762     # . epilogue
16763     89/<- %esp 5/r32/ebp
16764     5d/pop-to-ebp
16765     c3/return
16766 
16767 test-is-identifier-a:
16768     # . prologue
16769     55/push-ebp
16770     89/<- %ebp 4/r32/esp
16771     # (eax..ecx) = "a$"
16772     b8/copy-to-eax "a$"/imm32
16773     8b/-> *eax 1/r32/ecx
16774     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16775     05/add-to-eax 4/imm32
16776     # var slice/ecx: slice = {eax, ecx}
16777     51/push-ecx
16778     50/push-eax
16779     89/<- %ecx 4/r32/esp
16780     #
16781     (is-identifier? %ecx)
16782     (check-ints-equal %eax 1 "F - test-is-identifier-a")
16783     # . epilogue
16784     89/<- %esp 5/r32/ebp
16785     5d/pop-to-ebp
16786     c3/return
16787 
16788 test-is-identifier-z:
16789     # . prologue
16790     55/push-ebp
16791     89/<- %ebp 4/r32/esp
16792     # (eax..ecx) = "z$"
16793     b8/copy-to-eax "z$"/imm32
16794     8b/-> *eax 1/r32/ecx
16795     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16796     05/add-to-eax 4/imm32
16797     # var slice/ecx: slice = {eax, ecx}
16798     51/push-ecx
16799     50/push-eax
16800     89/<- %ecx 4/r32/esp
16801     #
16802     (is-identifier? %ecx)
16803     (check-ints-equal %eax 1 "F - test-is-identifier-z")
16804     # . epilogue
16805     89/<- %esp 5/r32/ebp
16806     5d/pop-to-ebp
16807     c3/return
16808 
16809 test-is-identifier-A:
16810     # . prologue
16811     55/push-ebp
16812     89/<- %ebp 4/r32/esp
16813     # (eax..ecx) = "A$"
16814     b8/copy-to-eax "A$"/imm32
16815     8b/-> *eax 1/r32/ecx
16816     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16817     05/add-to-eax 4/imm32
16818     # var slice/ecx: slice = {eax, ecx}
16819     51/push-ecx
16820     50/push-eax
16821     89/<- %ecx 4/r32/esp
16822     #
16823     (is-identifier? %ecx)
16824     (check-ints-equal %eax 1 "F - test-is-identifier-A")
16825     # . epilogue
16826     89/<- %esp 5/r32/ebp
16827     5d/pop-to-ebp
16828     c3/return
16829 
16830 test-is-identifier-Z:
16831     # . prologue
16832     55/push-ebp
16833     89/<- %ebp 4/r32/esp
16834     # (eax..ecx) = "Z$"
16835     b8/copy-to-eax "Z$"/imm32
16836     8b/-> *eax 1/r32/ecx
16837     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16838     05/add-to-eax 4/imm32
16839     # var slice/ecx: slice = {eax, ecx}
16840     51/push-ecx
16841     50/push-eax
16842     89/<- %ecx 4/r32/esp
16843     #
16844     (is-identifier? %ecx)
16845     (check-ints-equal %eax 1 "F - test-is-identifier-Z")
16846     # . epilogue
16847     89/<- %esp 5/r32/ebp
16848     5d/pop-to-ebp
16849     c3/return
16850 
16851 test-is-identifier-at:
16852     # character before 'A' is invalid
16853     # . prologue
16854     55/push-ebp
16855     89/<- %ebp 4/r32/esp
16856     # (eax..ecx) = "@a"
16857     b8/copy-to-eax "@a"/imm32
16858     8b/-> *eax 1/r32/ecx
16859     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16860     05/add-to-eax 4/imm32
16861     # var slice/ecx: slice = {eax, ecx}
16862     51/push-ecx
16863     50/push-eax
16864     89/<- %ecx 4/r32/esp
16865     #
16866     (is-identifier? %ecx)
16867     (check-ints-equal %eax 0 "F - test-is-identifier-@")
16868     # . epilogue
16869     89/<- %esp 5/r32/ebp
16870     5d/pop-to-ebp
16871     c3/return
16872 
16873 test-is-identifier-square-bracket:
16874     # character after 'Z' is invalid
16875     # . prologue
16876     55/push-ebp
16877     89/<- %ebp 4/r32/esp
16878     # (eax..ecx) = "[a"
16879     b8/copy-to-eax "[a"/imm32
16880     8b/-> *eax 1/r32/ecx
16881     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16882     05/add-to-eax 4/imm32
16883     # var slice/ecx: slice = {eax, ecx}
16884     51/push-ecx
16885     50/push-eax
16886     89/<- %ecx 4/r32/esp
16887     #
16888     (is-identifier? %ecx)
16889     (check-ints-equal %eax 0 "F - test-is-identifier-@")
16890     # . epilogue
16891     89/<- %esp 5/r32/ebp
16892     5d/pop-to-ebp
16893     c3/return
16894 
16895 test-is-identifier-backtick:
16896     # character before 'a' is invalid
16897     # . prologue
16898     55/push-ebp
16899     89/<- %ebp 4/r32/esp
16900     # (eax..ecx) = "`a"
16901     b8/copy-to-eax "`a"/imm32
16902     8b/-> *eax 1/r32/ecx
16903     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16904     05/add-to-eax 4/imm32
16905     # var slice/ecx: slice = {eax, ecx}
16906     51/push-ecx
16907     50/push-eax
16908     89/<- %ecx 4/r32/esp
16909     #
16910     (is-identifier? %ecx)
16911     (check-ints-equal %eax 0 "F - test-is-identifier-backtick")
16912     # . epilogue
16913     89/<- %esp 5/r32/ebp
16914     5d/pop-to-ebp
16915     c3/return
16916 
16917 test-is-identifier-curly-brace-open:
16918     # character after 'z' is invalid; also used for blocks
16919     # . prologue
16920     55/push-ebp
16921     89/<- %ebp 4/r32/esp
16922     # (eax..ecx) = "{a"
16923     b8/copy-to-eax "{a"/imm32
16924     8b/-> *eax 1/r32/ecx
16925     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16926     05/add-to-eax 4/imm32
16927     # var slice/ecx: slice = {eax, ecx}
16928     51/push-ecx
16929     50/push-eax
16930     89/<- %ecx 4/r32/esp
16931     #
16932     (is-identifier? %ecx)
16933     (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-open")
16934     # . epilogue
16935     89/<- %esp 5/r32/ebp
16936     5d/pop-to-ebp
16937     c3/return
16938 
16939 test-is-identifier-curly-brace-close:
16940     # . prologue
16941     55/push-ebp
16942     89/<- %ebp 4/r32/esp
16943     # (eax..ecx) = "}a"
16944     b8/copy-to-eax "}a"/imm32
16945     8b/-> *eax 1/r32/ecx
16946     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16947     05/add-to-eax 4/imm32
16948     # var slice/ecx: slice = {eax, ecx}
16949     51/push-ecx
16950     50/push-eax
16951     89/<- %ecx 4/r32/esp
16952     #
16953     (is-identifier? %ecx)
16954     (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-close")
16955     # . epilogue
16956     89/<- %esp 5/r32/ebp
16957     5d/pop-to-ebp
16958     c3/return
16959 
16960 test-is-identifier-hyphen:
16961     # disallow leading '-' since '->' has special meaning
16962     # . prologue
16963     55/push-ebp
16964     89/<- %ebp 4/r32/esp
16965     # (eax..ecx) = "-a"
16966     b8/copy-to-eax "-a"/imm32
16967     8b/-> *eax 1/r32/ecx
16968     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16969     05/add-to-eax 4/imm32
16970     # var slice/ecx: slice = {eax, ecx}
16971     51/push-ecx
16972     50/push-eax
16973     89/<- %ecx 4/r32/esp
16974     #
16975     (is-identifier? %ecx)
16976     (check-ints-equal %eax 0 "F - test-is-identifier-hyphen")
16977     # . epilogue
16978     89/<- %esp 5/r32/ebp
16979     5d/pop-to-ebp
16980     c3/return
16981 
16982 populate-mu-function-body:  # in: (addr buffered-file), out: (addr function), vars: (addr stack live-var), err: (addr buffered-file), ed: (addr exit-descriptor)
16983     # . prologue
16984     55/push-ebp
16985     89/<- %ebp 4/r32/esp
16986     # . save registers
16987     50/push-eax
16988     56/push-esi
16989     57/push-edi
16990     # esi = in
16991     8b/-> *(ebp+8) 6/r32/esi
16992     # edi = out
16993     8b/-> *(ebp+0xc) 7/r32/edi
16994     # initialize some global state
16995     c7 0/subop/copy *Curr-block-depth 1/imm32
16996     # parse-mu-block(in, vars, out, out->body)
16997     8d/copy-address *(edi+0x18) 0/r32/eax  # Function-body
16998     (parse-mu-block %esi *(ebp+0x10) %edi %eax *(ebp+0x14) *(ebp+0x18))
16999 $populate-mu-function-body:end:
17000     # . restore registers
17001     5f/pop-to-edi
17002     5e/pop-to-esi
17003     58/pop-to-eax
17004     # . epilogue
17005     89/<- %esp 5/r32/ebp
17006     5d/pop-to-ebp
17007     c3/return
17008 
17009 # parses a block, assuming that the leading '{' has already been read by the caller
17010 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)
17011     # pseudocode:
17012     #   var line: (stream byte 512)
17013     #   var word-slice: slice
17014     #   allocate(Heap, Stmt-size, out)
17015     #   var out-addr: (addr block) = lookup(*out)
17016     #   out-addr->tag = 0/block
17017     #   out-addr->var = some unique name
17018     #   push(vars, {out-addr->var, false})
17019     #   while true                                  # line loop
17020     #     clear-stream(line)
17021     #     read-line-buffered(in, line)
17022     #     if (line->write == 0) break               # end of file
17023     #     word-slice = next-mu-token(line)
17024     #     if slice-empty?(word-slice)               # end of line
17025     #       continue
17026     #     else if slice-starts-with?(word-slice, "#")
17027     #       continue
17028     #     else if slice-equal?(word-slice, "{")
17029     #       assert(no-tokens-in(line))
17030     #       block = parse-mu-block(in, vars, fn)
17031     #       append-to-block(out-addr, block)
17032     #     else if slice-equal?(word-slice, "}")
17033     #       break
17034     #     else if slice-ends-with?(word-slice, ":")
17035     #       # TODO: error-check the rest of 'line'
17036     #       --word-slice->end to skip ':'
17037     #       named-block = parse-mu-named-block(word-slice, in, vars, fn)
17038     #       append-to-block(out-addr, named-block)
17039     #     else if slice-equal?(word-slice, "var")
17040     #       var-def = parse-mu-var-def(line, vars, fn)
17041     #       append-to-block(out-addr, var-def)
17042     #     else
17043     #       stmt = parse-mu-stmt(line, vars, fn)
17044     #       append-to-block(out-addr, stmt)
17045     #   pop(vars)
17046     #
17047     # . prologue
17048     55/push-ebp
17049     89/<- %ebp 4/r32/esp
17050     # . save registers
17051     50/push-eax
17052     51/push-ecx
17053     52/push-edx
17054     53/push-ebx
17055     57/push-edi
17056     # var line/ecx: (stream byte 512)
17057     81 5/subop/subtract %esp 0x200/imm32
17058     68/push 0x200/imm32/size
17059     68/push 0/imm32/read
17060     68/push 0/imm32/write
17061     89/<- %ecx 4/r32/esp
17062     # var word-slice/edx: slice
17063     68/push 0/imm32/end
17064     68/push 0/imm32/start
17065     89/<- %edx 4/r32/esp
17066     # allocate into out
17067     (allocate Heap *Stmt-size *(ebp+0x14))
17068     # var out-addr/edi: (addr block) = lookup(*out)
17069     8b/-> *(ebp+0x14) 7/r32/edi
17070     (lookup *edi *(edi+4))  # => eax
17071     89/<- %edi 0/r32/eax
17072     # out-addr->tag is 0 (block) by default
17073     # set out-addr->var
17074     8d/copy-address *(edi+0xc) 0/r32/eax  # Block-var
17075     (new-block-name *(ebp+0x10) %eax)
17076     # push(vars, out-addr->var)
17077     (push *(ebp+0xc) *(edi+0xc))  # Block-var
17078     (push *(ebp+0xc) *(edi+0x10))  # Block-var
17079     (push *(ebp+0xc) 0)  # false
17080     # increment *Curr-block-depth
17081     ff 0/subop/increment *Curr-block-depth
17082     {
17083 $parse-mu-block:line-loop:
17084       # line = read-line-buffered(in)
17085       (clear-stream %ecx)
17086       (read-line-buffered *(ebp+8) %ecx)
17087 #?       (write-buffered Stderr "line: ")
17088 #?       (write-stream-data Stderr %ecx)
17089 #? #?       (write-buffered Stderr Newline)  # line has its own newline
17090 #?       (flush Stderr)
17091 #?       (rewind-stream %ecx)
17092       # if (line->write == 0) break
17093       81 7/subop/compare *ecx 0/imm32
17094       0f 84/jump-if-= break/disp32
17095 #?       (write-buffered Stderr "vars:\n")
17096 #?       (dump-vars *(ebp+0xc))
17097       # word-slice = next-mu-token(line)
17098       (next-mu-token %ecx %edx)
17099 #?       (write-buffered Stderr "word: ")
17100 #?       (write-slice-buffered Stderr %edx)
17101 #?       (write-buffered Stderr Newline)
17102 #?       (flush Stderr)
17103       # if slice-empty?(word-slice) continue
17104       (slice-empty? %edx)
17105       3d/compare-eax-and 0/imm32/false
17106       0f 85/jump-if-!= loop/disp32
17107       # if (slice-starts-with?(word-slice, '#') continue
17108       # . eax = *word-slice->start
17109       8b/-> *edx 0/r32/eax
17110       8a/copy-byte *eax 0/r32/AL
17111       81 4/subop/and %eax 0xff/imm32
17112       # . if (eax == '#') continue
17113       3d/compare-eax-and 0x23/imm32/hash
17114       0f 84/jump-if-= loop/disp32
17115       # if slice-equal?(word-slice, "{")
17116       {
17117 $parse-mu-block:check-for-block:
17118         (slice-equal? %edx "{")
17119         3d/compare-eax-and 0/imm32/false
17120         74/jump-if-= break/disp8
17121         (check-no-tokens-left %ecx)
17122         # parse new block and append
17123         # . var tmp/eax: (handle block)
17124         68/push 0/imm32
17125         68/push 0/imm32
17126         89/<- %eax 4/r32/esp
17127         # .
17128         (parse-mu-block *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
17129         (append-to-block Heap %edi  *eax *(eax+4))
17130         # . reclaim tmp
17131         81 0/subop/add %esp 8/imm32
17132         # .
17133         e9/jump $parse-mu-block:line-loop/disp32
17134       }
17135       # if slice-equal?(word-slice, "}") break
17136 $parse-mu-block:check-for-end:
17137       (slice-equal? %edx "}")
17138       3d/compare-eax-and 0/imm32/false
17139       0f 85/jump-if-!= break/disp32
17140       # if slice-ends-with?(word-slice, ":") parse named block and append
17141       {
17142 $parse-mu-block:check-for-named-block:
17143         # . eax = *(word-slice->end-1)
17144         8b/-> *(edx+4) 0/r32/eax
17145         48/decrement-eax
17146         8a/copy-byte *eax 0/r32/AL
17147         81 4/subop/and %eax 0xff/imm32
17148         # . if (eax != ':') break
17149         3d/compare-eax-and 0x3a/imm32/colon
17150         0f 85/jump-if-!= break/disp32
17151         # TODO: error-check the rest of 'line'
17152         #
17153         # skip ':'
17154         ff 1/subop/decrement *(edx+4)  # Slice-end
17155         # var tmp/eax: (handle block)
17156         68/push 0/imm32
17157         68/push 0/imm32
17158         89/<- %eax 4/r32/esp
17159         #
17160         (parse-mu-named-block %edx *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
17161         (append-to-block Heap %edi  *eax *(eax+4))
17162         # reclaim tmp
17163         81 0/subop/add %esp 8/imm32
17164         #
17165         e9/jump $parse-mu-block:line-loop/disp32
17166       }
17167       # if slice-equal?(word-slice, "var")
17168       {
17169 $parse-mu-block:check-for-var:
17170         (slice-equal? %edx "var")
17171         3d/compare-eax-and 0/imm32/false
17172         74/jump-if-= break/disp8
17173         # var tmp/eax: (handle block)
17174         68/push 0/imm32
17175         68/push 0/imm32
17176         89/<- %eax 4/r32/esp
17177         #
17178         (parse-mu-var-def %ecx *(ebp+0xc) %eax *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
17179         (append-to-block Heap %edi  *eax *(eax+4))
17180         # reclaim tmp
17181         81 0/subop/add %esp 8/imm32
17182         #
17183         e9/jump $parse-mu-block:line-loop/disp32
17184       }
17185 $parse-mu-block:regular-stmt:
17186       # otherwise
17187       # var tmp/eax: (handle block)
17188       68/push 0/imm32
17189       68/push 0/imm32
17190       89/<- %eax 4/r32/esp
17191       #
17192       (parse-mu-stmt %ecx *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
17193       (append-to-block Heap %edi  *eax *(eax+4))
17194       # reclaim tmp
17195       81 0/subop/add %esp 8/imm32
17196       #
17197       e9/jump loop/disp32
17198     } # end line loop
17199     (clean-up-blocks *(ebp+0xc) *Curr-block-depth *(ebp+0x10))
17200     # decrement *Curr-block-depth
17201     ff 1/subop/decrement *Curr-block-depth
17202     # pop(vars)
17203     (pop *(ebp+0xc))  # => eax
17204     (pop *(ebp+0xc))  # => eax
17205     (pop *(ebp+0xc))  # => eax
17206 $parse-mu-block:end:
17207     # . reclaim locals
17208     81 0/subop/add %esp 0x214/imm32
17209     # . restore registers
17210     5f/pop-to-edi
17211     5b/pop-to-ebx
17212     5a/pop-to-edx
17213     59/pop-to-ecx
17214     58/pop-to-eax
17215     # . epilogue
17216     89/<- %esp 5/r32/ebp
17217     5d/pop-to-ebp
17218     c3/return
17219 
17220 $parse-mu-block:abort:
17221     # error("'{' or '}' should be on its own line, but got '")
17222     (write-buffered *(ebp+0x18) "'{' or '}' should be on its own line, but got '")
17223     (rewind-stream %ecx)
17224     (write-stream-data *(ebp+0x18) %ecx)
17225     (write-buffered *(ebp+0x18) "'\n")
17226     (flush *(ebp+0x18))
17227     (stop *(ebp+0x1c) 1)
17228     # never gets here
17229 
17230 new-block-name:  # fn: (addr function), out: (addr handle var)
17231     # . prologue
17232     55/push-ebp
17233     89/<- %ebp 4/r32/esp
17234     # . save registers
17235     50/push-eax
17236     51/push-ecx
17237     52/push-edx
17238     # var n/ecx: int = len(fn->name) + 10 for an int + 2 for '$:'
17239     8b/-> *(ebp+8) 0/r32/eax
17240     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17241     8b/-> *eax 0/r32/eax  # String-size
17242     05/add-to-eax 0xd/imm32  # 10 + 2 for '$:'
17243     89/<- %ecx 0/r32/eax
17244     # var name/edx: (stream byte n)
17245     29/subtract-from %esp 1/r32/ecx
17246     ff 6/subop/push %ecx
17247     68/push 0/imm32/read
17248     68/push 0/imm32/write
17249     89/<- %edx 4/r32/esp
17250     (clear-stream %edx)
17251     # eax = fn->name
17252     8b/-> *(ebp+8) 0/r32/eax
17253     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17254     # construct result using Next-block-index (and increment it)
17255     (write %edx "$")
17256     (write %edx %eax)
17257     (write %edx ":")
17258     (write-int32-hex %edx *Next-block-index)
17259     ff 0/subop/increment *Next-block-index
17260     # var s/eax: slice = {name->data, name->data + name->write}  (clobbering edx)
17261     # . eax = name->write
17262     8b/-> *edx 0/r32/eax
17263     # . edx = name->data
17264     8d/copy-address *(edx+0xc) 2/r32/edx
17265     # . eax = name->write + name->data
17266     01/add-to %eax 2/r32/edx
17267     # . push {edx, eax}
17268     ff 6/subop/push %eax
17269     ff 6/subop/push %edx
17270     89/<- %eax 4/r32/esp
17271     # out = new literal(s)
17272     (new-literal Heap %eax *(ebp+0xc))
17273 #?     8b/-> *(ebp+0xc) 0/r32/eax
17274 #?     (write-buffered Stderr "type allocid in caller after new-literal: ")
17275 #?     (write-int32-hex-buffered Stderr *(eax+8))
17276 #?     (write-buffered Stderr " for var ")
17277 #?     (write-int32-hex-buffered Stderr %eax)
17278 #?     (write-buffered Stderr Newline)
17279 #?     (flush Stderr)
17280 $new-block-name:end:
17281     # . reclaim locals
17282     81 0/subop/add %ecx 0xc/imm32  # name.{read/write/len}
17283     81 0/subop/add %ecx 8/imm32  # slice
17284     01/add-to %esp 1/r32/ecx
17285     # . restore registers
17286     5a/pop-to-edx
17287     59/pop-to-ecx
17288     58/pop-to-eax
17289     # . epilogue
17290     89/<- %esp 5/r32/ebp
17291     5d/pop-to-ebp
17292     c3/return
17293 
17294 check-no-tokens-left:  # line: (addr stream byte)
17295     # . prologue
17296     55/push-ebp
17297     89/<- %ebp 4/r32/esp
17298     # . save registers
17299     50/push-eax
17300     51/push-ecx
17301     # var s/ecx: slice
17302     68/push 0/imm32/end
17303     68/push 0/imm32/start
17304     89/<- %ecx 4/r32/esp
17305     #
17306     (next-mu-token *(ebp+8) %ecx)
17307     # if slice-empty?(s) return
17308     (slice-empty? %ecx)
17309     3d/compare-eax-and 0/imm32/false
17310     75/jump-if-!= $check-no-tokens-left:end/disp8
17311     # if (slice-starts-with?(s, '#') return
17312     # . eax = *s->start
17313     8b/-> *edx 0/r32/eax
17314     8a/copy-byte *eax 0/r32/AL
17315     81 4/subop/and %eax 0xff/imm32
17316     # . if (eax == '#') continue
17317     3d/compare-eax-and 0x23/imm32/hash
17318     74/jump-if-= $check-no-tokens-left:end/disp8
17319     # abort
17320     (write-buffered Stderr "'{' or '}' should be on its own line, but got '")
17321     (rewind-stream %ecx)
17322     (write-stream 2 %ecx)
17323     (write-buffered Stderr "'\n")
17324     (flush Stderr)
17325     # . syscall(exit, 1)
17326     bb/copy-to-ebx  1/imm32
17327     e8/call syscall_exit/disp32
17328     # never gets here
17329 $check-no-tokens-left:end:
17330     # . reclaim locals
17331     81 0/subop/add %esp 8/imm32
17332     # . restore registers
17333     59/pop-to-ecx
17334     58/pop-to-eax
17335     # . epilogue
17336     89/<- %esp 5/r32/ebp
17337     5d/pop-to-ebp
17338     c3/return
17339 
17340 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)
17341     # pseudocode:
17342     #   var v: (handle var)
17343     #   new-literal(name, v)
17344     #   push(vars, {v, false})
17345     #   parse-mu-block(in, vars, fn, out)
17346     #   pop(vars)
17347     #   out->tag = block
17348     #   out->var = v
17349     #
17350     # . prologue
17351     55/push-ebp
17352     89/<- %ebp 4/r32/esp
17353     # . save registers
17354     50/push-eax
17355     51/push-ecx
17356     57/push-edi
17357     # var v/ecx: (handle var)
17358     68/push 0/imm32
17359     68/push 0/imm32
17360     89/<- %ecx 4/r32/esp
17361     #
17362     (new-literal Heap *(ebp+8) %ecx)
17363     # push(vars, v)
17364     (push *(ebp+0x10) *ecx)
17365     (push *(ebp+0x10) *(ecx+4))
17366     (push *(ebp+0x10) 0)  # false
17367     #
17368     (parse-mu-block *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c) *(ebp+0x20))
17369     # pop v off vars
17370     (pop *(ebp+0x10))  # => eax
17371     (pop *(ebp+0x10))  # => eax
17372     (pop *(ebp+0x10))  # => eax
17373     # var out-addr/edi: (addr stmt) = lookup(*out)
17374     8b/-> *(ebp+0x18) 7/r32/edi
17375     (lookup *edi *(edi+4))  # => eax
17376     89/<- %edi 0/r32/eax
17377     # out-addr->tag = named-block
17378     c7 0/subop/copy *edi 0/imm32/block  # Stmt-tag
17379     # out-addr->var = v
17380     8b/-> *ecx 0/r32/eax
17381     89/<- *(edi+0xc) 0/r32/eax  # Block-var
17382     8b/-> *(ecx+4) 0/r32/eax
17383     89/<- *(edi+0x10) 0/r32/eax  # Block-var
17384 $parse-mu-named-block:end:
17385     # . reclaim locals
17386     81 0/subop/add %esp 8/imm32
17387     # . restore registers
17388     5f/pop-to-edi
17389     59/pop-to-ecx
17390     58/pop-to-eax
17391     # . epilogue
17392     89/<- %esp 5/r32/ebp
17393     5d/pop-to-ebp
17394     c3/return
17395 
17396 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)
17397     # . prologue
17398     55/push-ebp
17399     89/<- %ebp 4/r32/esp
17400     # . save registers
17401     50/push-eax
17402     51/push-ecx
17403     52/push-edx
17404     56/push-esi
17405     57/push-edi
17406     # edi = out
17407     8b/-> *(ebp+0x10) 7/r32/edi
17408     # var word-slice/ecx: slice
17409     68/push 0/imm32/end
17410     68/push 0/imm32/start
17411     89/<- %ecx 4/r32/esp
17412     # var v/edx: (handle var)
17413     68/push 0/imm32
17414     68/push 0/imm32
17415     89/<- %edx 4/r32/esp
17416     # v = parse-var-with-type(next-mu-token(line))
17417     (next-mu-token *(ebp+8) %ecx)
17418     {
17419       # just for tests, support null fn
17420       8b/-> *(ebp+0x14) 0/r32/eax
17421       3d/compare-eax-and 0/imm32
17422       74/jump-if-= break/disp8
17423       (lookup *eax *(eax+4))  # Var-name Var-name => eax
17424     }
17425     (parse-var-with-type %ecx *(ebp+8) %edx %eax *(ebp+0x18) *(ebp+0x1c))
17426     # var v-addr/esi: (addr var)
17427     (lookup *edx *(edx+4))  # => eax
17428     89/<- %esi 0/r32/eax
17429     # v->block-depth = *Curr-block-depth
17430     8b/-> *Curr-block-depth 0/r32/eax
17431     89/<- *(esi+0x10) 0/r32/eax  # Var-block-depth
17432     # either v has no register and there's no more to this line
17433     81 7/subop/compare *(esi+0x18) 0/imm32
17434     {
17435       75/jump-if-!= break/disp8
17436       # if v-addr->type == byte, abort
17437       (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
17438       (is-simple-mu-type? %eax 8)  # byte => eax
17439       3d/compare-eax-and 0/imm32/false
17440       0f 85/jump-if-!= $parse-mu-var-def:error-byte-on-stack/disp32
17441       # ensure that there's nothing else on this line
17442       (next-mu-token *(ebp+8) %ecx)
17443       (slice-empty? %ecx)  # => eax
17444       3d/compare-eax-and 0/imm32/false
17445       0f 84/jump-if-= $parse-mu-var-def:error2/disp32
17446       #
17447       (new-var-def Heap  *edx *(edx+4)  %edi)
17448       e9/jump $parse-mu-var-def:update-vars/disp32
17449     }
17450     # or v has a register and there's more to this line
17451     {
17452       0f 84/jump-if-= break/disp32
17453       # if v-addr->type == byte, check for unsupported registers
17454       {
17455         (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
17456         (is-simple-mu-type? %eax 8)  # byte => eax
17457         3d/compare-eax-and 0/imm32/false
17458         74/jump-if-= break/disp8
17459         (lookup *(esi+0x18) *(esi+0x1c))  # => eax
17460         (string-equal? %eax "esi")  # => eax
17461         3d/compare-eax-and 0/imm32/false
17462         0f 85/jump-if-!= $parse-mu-var-def:error-byte-registers/disp32
17463         (lookup *(esi+0x18) *(esi+0x1c))  # => eax
17464         (string-equal? %eax "edi")  # => eax
17465         3d/compare-eax-and 0/imm32/false
17466         0f 85/jump-if-!= $parse-mu-var-def:error-byte-registers/disp32
17467       }
17468       # TODO: vars of type 'byte' should only be initialized by clearing to 0
17469       # ensure that the next word is '<-'
17470       (next-mu-token *(ebp+8) %ecx)
17471       (slice-equal? %ecx "<-")  # => eax
17472       3d/compare-eax-and 0/imm32/false
17473       0f 84/jump-if-= $parse-mu-var-def:error1/disp32
17474       #
17475       (new-reg-var-def Heap  *edx *(edx+4)  %edi)
17476       (lookup *edi *(edi+4))  # => eax
17477       (add-operation-and-inputs-to-stmt %eax *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
17478     }
17479 $parse-mu-var-def:update-vars:
17480     # push 'v' at end of function
17481     (push *(ebp+0xc) *edx)
17482     (push *(ebp+0xc) *(edx+4))
17483     (push *(ebp+0xc) 0)  # Live-var-register-spilled is unused during parsing
17484 $parse-mu-var-def:end:
17485     # . reclaim locals
17486     81 0/subop/add %esp 0x10/imm32
17487     # . restore registers
17488     5f/pop-to-edi
17489     5e/pop-to-esi
17490     5a/pop-to-edx
17491     59/pop-to-ecx
17492     58/pop-to-eax
17493     # . epilogue
17494     89/<- %esp 5/r32/ebp
17495     5d/pop-to-ebp
17496     c3/return
17497 
17498 $parse-mu-var-def:error1:
17499     (rewind-stream *(ebp+8))
17500     # error("register variable requires a valid instruction to initialize but got '" line "'\n")
17501     (write-buffered *(ebp+0x18) "register variable requires a valid instruction to initialize but got '")
17502     (flush *(ebp+0x18))
17503     (write-stream-data *(ebp+0x18) *(ebp+8))
17504     (write-buffered *(ebp+0x18) "'\n")
17505     (flush *(ebp+0x18))
17506     (stop *(ebp+0x1c) 1)
17507     # never gets here
17508 
17509 $parse-mu-var-def:error2:
17510     # error("fn " fn ": var " var ": variables on the stack can't take an initializer\n")
17511     (write-buffered *(ebp+0x18) "fn ")
17512     8b/-> *(ebp+0x14) 0/r32/eax
17513     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17514     (write-buffered *(ebp+0x18) %eax)
17515     (write-buffered *(ebp+0x18) ": var ")
17516     # var v-addr/eax: (addr var) = lookup(v)
17517     (lookup *edx *(edx+4))  # => eax
17518     (lookup *eax *(eax+4))  # Var-name Var-name => eax
17519     (write-buffered *(ebp+0x18) %eax)
17520     (write-buffered *(ebp+0x18) ": variables on the stack can't take an initializer\n")
17521     (flush *(ebp+0x18))
17522     (stop *(ebp+0x1c) 1)
17523     # never gets here
17524 
17525 $parse-mu-var-def:error-byte-on-stack:
17526     # error("fn " fn ": var '" var "' of type 'byte' cannot be on the stack\n")
17527     (write-buffered *(ebp+0x18) "fn ")
17528     8b/-> *(ebp+0x14) 0/r32/eax
17529     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17530     (write-buffered *(ebp+0x18) %eax)
17531     (write-buffered *(ebp+0x18) ": var '")
17532     # var v-addr/eax: (addr var) = lookup(v)
17533     (lookup *edx *(edx+4))  # => eax
17534     (lookup *eax *(eax+4))  # Var-name Var-name => eax
17535     (write-buffered *(ebp+0x18) %eax)
17536     (write-buffered *(ebp+0x18) "' of type 'byte' cannot be on the stack\n")
17537     (flush *(ebp+0x18))
17538     (stop *(ebp+0x1c) 1)
17539     # never gets here
17540 
17541 $parse-mu-var-def:error-byte-registers:
17542     # error("fn " fn ": var '" var "' of type 'byte' cannot be in esi or edi\n")
17543     (write-buffered *(ebp+0x18) "fn ")
17544     8b/-> *(ebp+0x14) 0/r32/eax
17545     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17546     (write-buffered *(ebp+0x18) %eax)
17547     (write-buffered *(ebp+0x18) ": var '")
17548     # var v-addr/eax: (addr var) = lookup(v)
17549     (lookup *edx *(edx+4))  # => eax
17550     (lookup *eax *(eax+4))  # Var-name Var-name => eax
17551     (write-buffered *(ebp+0x18) %eax)
17552     (write-buffered *(ebp+0x18) "' of type 'byte' cannot be in esi or edi\n")
17553     (flush *(ebp+0x18))
17554     (stop *(ebp+0x1c) 1)
17555     # never gets here
17556 
17557 test-parse-mu-var-def:
17558     # 'var n: int'
17559     # . prologue
17560     55/push-ebp
17561     89/<- %ebp 4/r32/esp
17562     # setup
17563     8b/-> *Primitive-type-ids 0/r32/eax
17564     89/<- *Type-id 0/r32/eax  # stream-write
17565     (clear-stream _test-input-stream)
17566     (write _test-input-stream "n: int\n")  # caller has consumed the 'var'
17567     c7 0/subop/copy *Curr-block-depth 1/imm32
17568     # var out/esi: (handle stmt)
17569     68/push 0/imm32
17570     68/push 0/imm32
17571     89/<- %esi 4/r32/esp
17572     # var vars/ecx: (stack (addr var) 16)
17573     81 5/subop/subtract %esp 0xc0/imm32
17574     68/push 0xc0/imm32/size
17575     68/push 0/imm32/top
17576     89/<- %ecx 4/r32/esp
17577     (clear-stack %ecx)
17578     # convert
17579     (parse-mu-var-def _test-input-stream %ecx %esi 0 Stderr 0)
17580     # var out-addr/esi: (addr stmt)
17581     (lookup *esi *(esi+4))  # => eax
17582     89/<- %esi 0/r32/eax
17583     #
17584     (check-ints-equal *esi 2 "F - test-parse-mu-var-def/tag")  # Stmt-tag is var-def
17585     # var v/ecx: (addr var) = lookup(out->var)
17586     (lookup *(esi+4) *(esi+8))  # Vardef-var Vardef-var => eax
17587     89/<- %ecx 0/r32/eax
17588     # v->name
17589     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
17590     (check-strings-equal %eax "n" "F - test-parse-mu-var-def/var-name")
17591     # v->register
17592     (check-ints-equal *(ecx+0x18) 0 "F - test-parse-mu-var-def/var-register")  # Var-register
17593     # v->block-depth
17594     (check-ints-equal *(ecx+0x10) 1 "F - test-parse-mu-var-def/output-block-depth")  # Var-block-depth
17595     # v->type == int
17596     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
17597     (check-ints-equal *eax 1 "F - test-parse-mu-var-def/var-type:0")  # Type-tree-is-atom
17598     (check-ints-equal *(eax+4) 1 "F - test-parse-mu-var-def/var-type:1")  # Type-tree-value
17599     (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-var-def/var-type:2")  # Type-tree-right
17600     # . epilogue
17601     89/<- %esp 5/r32/ebp
17602     5d/pop-to-ebp
17603     c3/return
17604 
17605 test-parse-mu-reg-var-def:
17606     # 'var n/eax: int <- copy 0'
17607     # . prologue
17608     55/push-ebp
17609     89/<- %ebp 4/r32/esp
17610     # setup
17611     8b/-> *Primitive-type-ids 0/r32/eax
17612     89/<- *Type-id 0/r32/eax  # stream-write
17613     (clear-stream _test-input-stream)
17614     (write _test-input-stream "n/eax: int <- copy 0\n")  # caller has consumed the 'var'
17615     c7 0/subop/copy *Curr-block-depth 1/imm32
17616     # var out/esi: (handle stmt)
17617     68/push 0/imm32
17618     68/push 0/imm32
17619     89/<- %esi 4/r32/esp
17620     # var vars/ecx: (stack (addr var) 16)
17621     81 5/subop/subtract %esp 0xc0/imm32
17622     68/push 0xc0/imm32/size
17623     68/push 0/imm32/top
17624     89/<- %ecx 4/r32/esp
17625     (clear-stack %ecx)
17626     # convert
17627     (parse-mu-var-def _test-input-stream %ecx %esi 0 Stderr 0)
17628     # var out-addr/esi: (addr stmt)
17629     (lookup *esi *(esi+4))  # => eax
17630     89/<- %esi 0/r32/eax
17631     #
17632     (check-ints-equal *esi 3 "F - test-parse-mu-reg-var-def/tag")  # Stmt-tag is reg-var-def
17633     # var v/ecx: (addr var) = lookup(out->outputs->value)
17634     # . eax: (addr stmt-var) = lookup(out->outputs)
17635     (lookup *(esi+0x14) *(esi+0x18))  # Regvardef-outputs Regvardef-outputs => eax
17636     # .
17637     (check-ints-equal *(eax+8) 0 "F - test-parse-mu-reg-var-def/single-output")  # Stmt-var-next
17638     # . eax: (addr var) = lookup(eax->value)
17639     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
17640     # . ecx = eax
17641     89/<- %ecx 0/r32/eax
17642     # v->name
17643     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
17644     (check-strings-equal %eax "n" "F - test-parse-mu-reg-var-def/output-name")  # Var-name
17645     # v->register
17646     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
17647     (check-strings-equal %eax "eax" "F - test-parse-mu-reg-var-def/output-register")
17648     # v->block-depth
17649     (check-ints-equal *(ecx+0x10) 1 "F - test-parse-mu-reg-var-def/output-block-depth")  # Var-block-depth
17650     # v->type == int
17651     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
17652     (check-ints-equal *eax 1 "F - test-parse-mu-reg-var-def/output-type:0")  # Type-tree-is-atom
17653     (check-ints-equal *(eax+4) 1 "F - test-parse-mu-reg-var-def/output-type:1")  # Type-tree-value
17654     (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-reg-var-def/output-type:2")  # Type-tree-right
17655     # . epilogue
17656     89/<- %esp 5/r32/ebp
17657     5d/pop-to-ebp
17658     c3/return
17659 
17660 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)
17661     # pseudocode:
17662     #   var name: slice
17663     #   allocate(Heap, Stmt-size, out)
17664     #   var out-addr: (addr stmt) = lookup(*out)
17665     #   out-addr->tag = stmt
17666     #   if stmt-has-outputs?(line)
17667     #     while true
17668     #       name = next-mu-token(line)
17669     #       if (name == '<-') break
17670     #       assert(is-identifier?(name))
17671     #       var v: (handle var) = lookup-var(name, vars)
17672     #       out-addr->outputs = append(v, out-addr->outputs)
17673     #   add-operation-and-inputs-to-stmt(out-addr, line, vars)
17674     #
17675     # . prologue
17676     55/push-ebp
17677     89/<- %ebp 4/r32/esp
17678     # . save registers
17679     50/push-eax
17680     51/push-ecx
17681     52/push-edx
17682     53/push-ebx
17683     57/push-edi
17684     # var name/ecx: slice
17685     68/push 0/imm32/end
17686     68/push 0/imm32/start
17687     89/<- %ecx 4/r32/esp
17688     # var is-deref?/edx: boolean = false
17689     ba/copy-to-edx 0/imm32/false
17690     # var v: (handle var)
17691     68/push 0/imm32
17692     68/push 0/imm32
17693     89/<- %ebx 4/r32/esp
17694     #
17695     (allocate Heap *Stmt-size *(ebp+0x14))
17696     # var out-addr/edi: (addr stmt) = lookup(*out)
17697     8b/-> *(ebp+0x14) 7/r32/edi
17698     (lookup *edi *(edi+4))  # => eax
17699     89/<- %edi 0/r32/eax
17700     # out-addr->tag = 1/stmt
17701     c7 0/subop/copy *edi 1/imm32/stmt1  # Stmt-tag
17702     {
17703       (stmt-has-outputs? *(ebp+8))
17704       3d/compare-eax-and 0/imm32/false
17705       0f 84/jump-if-= break/disp32
17706       {
17707 $parse-mu-stmt:read-outputs:
17708         # name = next-mu-token(line)
17709         (next-mu-token *(ebp+8) %ecx)
17710         # if slice-empty?(word-slice) break
17711         (slice-empty? %ecx)  # => eax
17712         3d/compare-eax-and 0/imm32/false
17713         0f 85/jump-if-!= break/disp32
17714         # if (name == "<-") break
17715         (slice-equal? %ecx "<-")  # => eax
17716         3d/compare-eax-and 0/imm32/false
17717         0f 85/jump-if-!= break/disp32
17718         # if slice-starts-with?(name, "*") abort
17719         8b/-> *ecx 0/r32/eax  # Slice-start
17720         8a/copy-byte *eax 0/r32/AL
17721         81 4/subop/and %eax 0xff/imm32
17722         3d/compare-eax-and 0x2a/imm32/asterisk
17723         0f 84/jump-if-= $parse-mu-stmt:error-output-dereferenced/disp32
17724         # assert(is-identifier?(name))
17725         (is-identifier? %ecx)  # => eax
17726         3d/compare-eax-and 0/imm32/false
17727         0f 84/jump-if-= $parse-mu-stmt:abort/disp32
17728         #
17729         (lookup-var %ecx *(ebp+0xc) %ebx *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
17730         8d/copy-address *(edi+0x14) 0/r32/eax  # Stmt1-outputs
17731         (append-stmt-var Heap  *ebx *(ebx+4)  *(edi+0x14) *(edi+0x18)  0  %eax)  # Stmt1-outputs
17732         #
17733         e9/jump loop/disp32
17734       }
17735     }
17736     (add-operation-and-inputs-to-stmt %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
17737 $parse-mu-stmt:end:
17738     # . reclaim locals
17739     81 0/subop/add %esp 0x10/imm32
17740     # . restore registers
17741     5f/pop-to-edi
17742     5b/pop-to-ebx
17743     5a/pop-to-edx
17744     59/pop-to-ecx
17745     58/pop-to-eax
17746     # . epilogue
17747     89/<- %esp 5/r32/ebp
17748     5d/pop-to-ebp
17749     c3/return
17750 
17751 $parse-mu-stmt:abort:
17752     # error("invalid identifier '" name "'\n")
17753     (write-buffered *(ebp+0x18) "fn ")
17754     8b/-> *(ebp+0x10) 0/r32/eax
17755     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17756     (write-buffered *(ebp+0x18) %eax)
17757     (write-buffered *(ebp+0x18) ": invalid identifier '")
17758     (write-slice-buffered *(ebp+0x18) %ecx)
17759     (write-buffered *(ebp+0x18) "'\n")
17760     (flush *(ebp+0x18))
17761     (stop *(ebp+0x1c) 1)
17762     # never gets here
17763 
17764 $parse-mu-stmt:error-output-dereferenced:
17765     # error("invalid identifier '" name "'\n")
17766     (write-buffered *(ebp+0x18) "fn ")
17767     8b/-> *(ebp+0x10) 0/r32/eax
17768     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17769     (write-buffered *(ebp+0x18) %eax)
17770     (write-buffered *(ebp+0x18) ": output '")
17771     (write-slice-buffered *(ebp+0x18) %ecx)
17772     (write-buffered *(ebp+0x18) "' should write to a register, and therefore cannot be dereferenced\n")
17773     (flush *(ebp+0x18))
17774     (stop *(ebp+0x1c) 1)
17775     # never gets here
17776 
17777 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)
17778     # pseudocode:
17779     #   stmt->name = slice-to-string(next-mu-token(line))
17780     #   while true
17781     #     name = next-mu-token(line)
17782     #     v = lookup-var-or-literal(name)
17783     #     stmt->inouts = append(v, stmt->inouts)
17784     #
17785     # . prologue
17786     55/push-ebp
17787     89/<- %ebp 4/r32/esp
17788     # . save registers
17789     50/push-eax
17790     51/push-ecx
17791     52/push-edx
17792     53/push-ebx
17793     56/push-esi
17794     57/push-edi
17795     # edi = stmt
17796     8b/-> *(ebp+8) 7/r32/edi
17797     # var name/ecx: slice
17798     68/push 0/imm32/end
17799     68/push 0/imm32/start
17800     89/<- %ecx 4/r32/esp
17801     # var is-deref?/edx: boolean = false
17802     ba/copy-to-edx 0/imm32/false
17803     # var v/esi: (handle var)
17804     68/push 0/imm32
17805     68/push 0/imm32
17806     89/<- %esi 4/r32/esp
17807 $add-operation-and-inputs-to-stmt:read-operation:
17808     (next-mu-token *(ebp+0xc) %ecx)
17809     8d/copy-address *(edi+4) 0/r32/eax  # Stmt1-operation or Regvardef-operationStmt1-operation or Regvardef-operation
17810     (slice-to-string Heap %ecx %eax)
17811     # var is-get?/ebx: boolean = (name == "get")
17812     (slice-equal? %ecx "get")  # => eax
17813     89/<- %ebx 0/r32/eax
17814     {
17815 $add-operation-and-inputs-to-stmt:read-inouts:
17816       # name = next-mu-token(line)
17817       (next-mu-token *(ebp+0xc) %ecx)
17818       # if slice-empty?(word-slice) break
17819       (slice-empty? %ecx)  # => eax
17820       3d/compare-eax-and 0/imm32/false
17821       0f 85/jump-if-!= break/disp32
17822       # if (name == "<-") abort
17823       (slice-equal? %ecx "<-")
17824       3d/compare-eax-and 0/imm32/false
17825       0f 85/jump-if-!= $add-operation-and-inputs-to-stmt:abort/disp32
17826       # if (is-get? && second operand) lookup or create offset
17827       {
17828         81 7/subop/compare %ebx 0/imm32/false
17829         74/jump-if-= break/disp8
17830         (lookup *(edi+0xc) *(edi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
17831         3d/compare-eax-and 0/imm32
17832         74/jump-if-= break/disp8
17833         (lookup-or-create-constant %eax %ecx %esi)
17834 #?         (lookup *esi *(esi+4))
17835 #?         (write-buffered Stderr "creating new output var ")
17836 #?         (write-int32-hex-buffered Stderr %eax)
17837 #?         (write-buffered Stderr " for field called ")
17838 #?         (write-slice-buffered Stderr %ecx)
17839 #?         (write-buffered Stderr "; var name ")
17840 #?         (lookup *eax *(eax+4))  # Var-name
17841 #?         (write-buffered Stderr %eax)
17842 #?         (write-buffered Stderr Newline)
17843 #?         (flush Stderr)
17844         e9/jump $add-operation-and-inputs-to-stmt:save-var/disp32
17845       }
17846       # is-deref? = false
17847       ba/copy-to-edx 0/imm32/false
17848       # if (slice-starts-with?(name, '*')) ++name->start and set is-deref?
17849       8b/-> *ecx 0/r32/eax  # Slice-start
17850       8a/copy-byte *eax 0/r32/AL
17851       81 4/subop/and %eax 0xff/imm32
17852       3d/compare-eax-and 0x2a/imm32/asterisk
17853       {
17854         75/jump-if-!= break/disp8
17855 $add-operation-and-inputs-to-stmt:inout-is-deref:
17856         ff 0/subop/increment *ecx
17857         ba/copy-to-edx 1/imm32/true
17858       }
17859       (lookup-var-or-literal %ecx *(ebp+0x10) %esi *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
17860       # if (is-deref?) some additional checks
17861       81 7/subop/compare %edx 0/imm32/false
17862       {
17863         74/jump-if-= break/disp8
17864         # if var is not in register, abort
17865         (lookup *esi *(esi+4))  # => eax
17866         81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
17867         0f 84/jump-if-= $add-operation-and-inputs-to-stmt:error-deref-on-stack/disp32
17868         # if var is not an address, abort
17869         (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
17870         (is-mu-addr-type? %eax)  # => eax
17871         3d/compare-eax-and 0/imm32/false
17872         0f 84/jump-if-= $add-operation-and-inputs-to-stmt:error-deref-non-addr/disp32
17873       }
17874 $add-operation-and-inputs-to-stmt:save-var:
17875       8d/copy-address *(edi+0xc) 0/r32/eax
17876       (append-stmt-var Heap  *esi *(esi+4)  *(edi+0xc) *(edi+0x10)  %edx  %eax)  # Stmt1-inouts or Regvardef-inouts
17877       #
17878       e9/jump loop/disp32
17879     }
17880 $add-operation-and-inputs-to-stmt:end:
17881     # . reclaim locals
17882     81 0/subop/add %esp 0x10/imm32
17883     # . restore registers
17884     5f/pop-to-edi
17885     5e/pop-to-esi
17886     5b/pop-to-ebx
17887     5a/pop-to-edx
17888     59/pop-to-ecx
17889     58/pop-to-eax
17890     # . epilogue
17891     89/<- %esp 5/r32/ebp
17892     5d/pop-to-ebp
17893     c3/return
17894 
17895 $add-operation-and-inputs-to-stmt:abort:
17896     # error("fn ___: invalid identifier in '" line "'\n")
17897     (write-buffered *(ebp+0x18) "fn ")
17898     8b/-> *(ebp+0x14) 0/r32/eax
17899     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17900     (write-buffered *(ebp+0x18) %eax)
17901     (rewind-stream *(ebp+0xc))
17902     (write-buffered *(ebp+0x18) ": invalid identifier in '")
17903     (write-stream-data *(ebp+0x18) *(ebp+0xc))
17904     (write-buffered *(ebp+0x18) "'\n")
17905     (flush *(ebp+0x18))
17906     (stop *(ebp+0x1c) 1)
17907     # never gets here
17908 
17909 $add-operation-and-inputs-to-stmt:error-deref-on-stack:
17910     # error("fn ___: cannot dereference var ___ on stack\n")
17911     (write-buffered *(ebp+0x18) "fn ")
17912     8b/-> *(ebp+0x14) 0/r32/eax
17913     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17914     (write-buffered *(ebp+0x18) %eax)
17915     (rewind-stream *(ebp+0xc))
17916     (write-buffered *(ebp+0x18) ": cannot dereference var '")
17917     (lookup *esi *(esi+4))  # => eax
17918     (lookup *eax *(eax+4))  # Var-name Var-name => eax
17919     (write-buffered *(ebp+0x18) %eax)
17920     (write-buffered *(ebp+0x18) "' on stack\n")
17921     (flush *(ebp+0x18))
17922     (stop *(ebp+0x1c) 1)
17923     # never gets here
17924 
17925 $add-operation-and-inputs-to-stmt:error-deref-non-addr:
17926     # error("fn ___: cannot dereference non-addr var ___\n")
17927     (write-buffered *(ebp+0x18) "fn ")
17928     8b/-> *(ebp+0x14) 0/r32/eax
17929     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17930     (write-buffered *(ebp+0x18) %eax)
17931     (rewind-stream *(ebp+0xc))
17932     (write-buffered *(ebp+0x18) ": cannot dereference non-addr var '")
17933     (lookup *esi *(esi+4))  # => eax
17934     (lookup *eax *(eax+4))  # Var-name Var-name => eax
17935     (write-buffered *(ebp+0x18) %eax)
17936     (write-buffered *(ebp+0x18) "'\n")
17937     (flush *(ebp+0x18))
17938     (stop *(ebp+0x1c) 1)
17939     # never gets here
17940 
17941 stmt-has-outputs?:  # line: (addr stream byte) -> result/eax: boolean
17942     # . prologue
17943     55/push-ebp
17944     89/<- %ebp 4/r32/esp
17945     # . save registers
17946     51/push-ecx
17947     # var word-slice/ecx: slice
17948     68/push 0/imm32/end
17949     68/push 0/imm32/start
17950     89/<- %ecx 4/r32/esp
17951     # result = false
17952     b8/copy-to-eax 0/imm32/false
17953     (rewind-stream *(ebp+8))
17954     {
17955       (next-mu-token *(ebp+8) %ecx)
17956       # if slice-empty?(word-slice) break
17957       (slice-empty? %ecx)
17958       3d/compare-eax-and 0/imm32/false
17959       b8/copy-to-eax 0/imm32/false/result  # restore result (if we're here it's still false)
17960       0f 85/jump-if-!= break/disp32
17961       # if slice-starts-with?(word-slice, '#') break
17962       # . eax = *word-slice->start
17963       8b/-> *ecx 0/r32/eax
17964       8a/copy-byte *eax 0/r32/AL
17965       81 4/subop/and %eax 0xff/imm32
17966       # . if (eax == '#') break
17967       3d/compare-eax-and 0x23/imm32/hash
17968       b8/copy-to-eax 0/imm32/false/result  # restore result (if we're here it's still false)
17969       0f 84/jump-if-= break/disp32
17970       # if slice-equal?(word-slice, '<-') return true
17971       (slice-equal? %ecx "<-")
17972       3d/compare-eax-and 0/imm32/false
17973       74/jump-if-= loop/disp8
17974       b8/copy-to-eax 1/imm32/true
17975     }
17976 $stmt-has-outputs:end:
17977     (rewind-stream *(ebp+8))
17978     # . reclaim locals
17979     81 0/subop/add %esp 8/imm32
17980     # . restore registers
17981     59/pop-to-ecx
17982     # . epilogue
17983     89/<- %esp 5/r32/ebp
17984     5d/pop-to-ebp
17985     c3/return
17986 
17987 # if 'name' starts with a digit, create a new literal var for it
17988 # otherwise return first 'name' from the top (back) of 'vars' and abort if not found
17989 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)
17990     # . prologue
17991     55/push-ebp
17992     89/<- %ebp 4/r32/esp
17993     # . save registers
17994     50/push-eax
17995     51/push-ecx
17996     56/push-esi
17997     # esi = name
17998     8b/-> *(ebp+8) 6/r32/esi
17999     # if slice-empty?(name) abort
18000     (slice-empty? %esi)  # => eax
18001     3d/compare-eax-and 0/imm32/false
18002     0f 85/jump-if-!= $lookup-var-or-literal:abort/disp32
18003     # var c/ecx: byte = *name->start
18004     8b/-> *esi 1/r32/ecx
18005     8a/copy-byte *ecx 1/r32/CL
18006     81 4/subop/and %ecx 0xff/imm32
18007     # if (is-decimal-digit?(c) || c == '-') return new var(name)
18008     {
18009       81 7/subop/compare %ecx 0x2d/imm32/dash
18010       74/jump-if-= $lookup-var-or-literal:literal/disp8
18011       (is-decimal-digit? %ecx)  # => eax
18012       3d/compare-eax-and 0/imm32/false
18013       74/jump-if-= break/disp8
18014 $lookup-var-or-literal:literal:
18015       (new-literal-integer Heap %esi *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
18016       eb/jump $lookup-var-or-literal:end/disp8
18017     }
18018     # else if (c == '"') return new var(name)
18019     {
18020       81 7/subop/compare %ecx 0x22/imm32/dquote
18021       75/jump-if-!= break/disp8
18022 $lookup-var-or-literal:literal-string:
18023       (new-literal-string Heap %esi *(ebp+0x10))
18024       eb/jump $lookup-var-or-literal:end/disp8
18025     }
18026     # otherwise return lookup-var(name, vars)
18027     {
18028 $lookup-var-or-literal:var:
18029       (lookup-var %esi *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
18030     }
18031 $lookup-var-or-literal:end:
18032     # . restore registers
18033     5e/pop-to-esi
18034     59/pop-to-ecx
18035     58/pop-to-eax
18036     # . epilogue
18037     89/<- %esp 5/r32/ebp
18038     5d/pop-to-ebp
18039     c3/return
18040 
18041 $lookup-var-or-literal:abort:
18042     (write-buffered *(ebp+0x18) "fn ")
18043     8b/-> *(ebp+0x14) 0/r32/eax
18044     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18045     (write-buffered *(ebp+0x18) %eax)
18046     (write-buffered *(ebp+0x18) ": empty variable!")
18047     (flush *(ebp+0x18))
18048     (stop *(ebp+0x1c) 1)
18049     # never gets here
18050 
18051 # return first 'name' from the top (back) of 'vars' and abort if not found
18052 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)
18053     # . prologue
18054     55/push-ebp
18055     89/<- %ebp 4/r32/esp
18056     # . save registers
18057     50/push-eax
18058     #
18059     (lookup-var-helper *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
18060     # if (*out == 0) abort
18061     8b/-> *(ebp+0x10) 0/r32/eax
18062     81 7/subop/compare *eax 0/imm32
18063     74/jump-if-= $lookup-var:abort/disp8
18064 $lookup-var:end:
18065     # . restore registers
18066     58/pop-to-eax
18067     # . epilogue
18068     89/<- %esp 5/r32/ebp
18069     5d/pop-to-ebp
18070     c3/return
18071 
18072 $lookup-var:abort:
18073     (write-buffered *(ebp+0x18) "fn ")
18074     8b/-> *(ebp+0x14) 0/r32/eax
18075     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18076     (write-buffered *(ebp+0x18) %eax)
18077     (write-buffered *(ebp+0x18) ": unknown variable '")
18078     (write-slice-buffered *(ebp+0x18) *(ebp+8))
18079     (write-buffered *(ebp+0x18) "'\n")
18080     (flush *(ebp+0x18))
18081     (stop *(ebp+0x1c) 1)
18082     # never gets here
18083 
18084 # return first 'name' from the top (back) of 'vars', and 0/null if not found
18085 # ensure that 'name' if in a register is the topmost variable in that register
18086 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)
18087     # pseudocode:
18088     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
18089     #   var min = vars->data
18090     #   while curr >= min
18091     #     var v: (handle var) = *curr
18092     #     if v->name == name
18093     #       return
18094     #     curr -= 12
18095     #
18096     # . prologue
18097     55/push-ebp
18098     89/<- %ebp 4/r32/esp
18099     # . save registers
18100     50/push-eax
18101     51/push-ecx
18102     52/push-edx
18103     53/push-ebx
18104     56/push-esi
18105     57/push-edi
18106     # clear out
18107     (zero-out *(ebp+0x10) *Handle-size)
18108     # esi = vars
18109     8b/-> *(ebp+0xc) 6/r32/esi
18110     # ebx = vars->top
18111     8b/-> *esi 3/r32/ebx
18112     # if (vars->top > vars->size) abort
18113     3b/compare<- *(esi+4) 0/r32/eax
18114     0f 8f/jump-if-> $lookup-var-helper:error1/disp32
18115     # var min/edx: (addr handle var) = vars->data
18116     8d/copy-address *(esi+8) 2/r32/edx
18117     # var curr/ebx: (addr handle var) = &vars->data[vars->top - 12]
18118     8d/copy-address *(esi+ebx-4) 3/r32/ebx  # vars + 8 + vars->type - 12
18119     # var var-in-reg/edi: 16 addrs
18120     68/push 0/imm32
18121     68/push 0/imm32
18122     68/push 0/imm32
18123     68/push 0/imm32
18124     68/push 0/imm32
18125     68/push 0/imm32
18126     68/push 0/imm32
18127     68/push 0/imm32
18128     68/push 0/imm32
18129     68/push 0/imm32
18130     68/push 0/imm32
18131     68/push 0/imm32
18132     68/push 0/imm32
18133     68/push 0/imm32
18134     68/push 0/imm32
18135     68/push 0/imm32
18136     89/<- %edi 4/r32/esp
18137     {
18138 $lookup-var-helper:loop:
18139       # if (curr < min) return
18140       39/compare %ebx 2/r32/edx
18141       0f 82/jump-if-addr< break/disp32
18142       # var v/ecx: (addr var) = lookup(*curr)
18143       (lookup *ebx *(ebx+4))  # => eax
18144       89/<- %ecx 0/r32/eax
18145       # var vn/eax: (addr array byte) = lookup(v->name)
18146       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
18147       # if (vn == name) return curr
18148       (slice-equal? *(ebp+8) %eax)  # => eax
18149       3d/compare-eax-and 0/imm32/false
18150       {
18151         74/jump-if-= break/disp8
18152 $lookup-var-helper:found:
18153         # var vr/eax: (addr array byte) = lookup(v->register)
18154         (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
18155         3d/compare-eax-and 0/imm32
18156         {
18157           74/jump-if-= break/disp8
18158 $lookup-var-helper:found-register:
18159           # var reg/eax: int = get(Registers, vr)
18160           (get Mu-registers-unique %eax 0xc "Mu-registers-unique")  # => eax
18161           8b/-> *eax 0/r32/eax
18162           # if (var-in-reg[reg]) error
18163           8b/-> *(edi+eax<<2) 0/r32/eax
18164           3d/compare-eax-and 0/imm32
18165           0f 85/jump-if-!= $lookup-var-helper:error2/disp32
18166         }
18167 $lookup-var-helper:return:
18168         # esi = out
18169         8b/-> *(ebp+0x10) 6/r32/esi
18170         # *out = *curr
18171         8b/-> *ebx 0/r32/eax
18172         89/<- *esi 0/r32/eax
18173         8b/-> *(ebx+4) 0/r32/eax
18174         89/<- *(esi+4) 0/r32/eax
18175         # return
18176         eb/jump $lookup-var-helper:end/disp8
18177       }
18178       # 'name' not yet found; update var-in-reg if v in register
18179       # . var vr/eax: (addr array byte) = lookup(v->register)
18180       (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
18181       # . if (vr == 0) continue
18182       3d/compare-eax-and 0/imm32
18183       74/jump-if-= $lookup-var-helper:continue/disp8
18184       # . var reg/eax: int = get(Registers, vr)
18185       (get Mu-registers-unique %eax 0xc "Mu-registers-unique")  # => eax
18186       8b/-> *eax 0/r32/eax
18187       # . var-in-reg[reg] = v
18188       89/<- *(edi+eax<<2) 1/r32/ecx
18189 $lookup-var-helper:continue:
18190       # curr -= 12
18191       81 5/subop/subtract %ebx 0xc/imm32
18192       e9/jump loop/disp32
18193     }
18194 $lookup-var-helper:end:
18195     # . reclaim locals
18196     81 0/subop/add %esp 0x40/imm32
18197     # . restore registers
18198     5f/pop-to-edi
18199     5e/pop-to-esi
18200     5b/pop-to-ebx
18201     5a/pop-to-edx
18202     59/pop-to-ecx
18203     58/pop-to-eax
18204     # . epilogue
18205     89/<- %esp 5/r32/ebp
18206     5d/pop-to-ebp
18207     c3/return
18208 
18209 $lookup-var-helper:error1:
18210     (write-buffered *(ebp+0x18) "fn ")
18211     8b/-> *(ebp+0x14) 0/r32/eax
18212     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18213     (write-buffered *(ebp+0x18) %eax)
18214     (write-buffered *(ebp+0x18) ": malformed stack when looking up '")
18215     (write-slice-buffered *(ebp+0x18) *(ebp+8))
18216     (write-buffered *(ebp+0x18) "'\n")
18217     (flush *(ebp+0x18))
18218     (stop *(ebp+0x1c) 1)
18219     # never gets here
18220 
18221 $lookup-var-helper:error2:
18222     # eax contains the conflicting var at this point
18223     (write-buffered *(ebp+0x18) "fn ")
18224     50/push-eax
18225     8b/-> *(ebp+0x14) 0/r32/eax
18226     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18227     (write-buffered *(ebp+0x18) %eax)
18228     58/pop-eax
18229     (write-buffered *(ebp+0x18) ": register ")
18230     50/push-eax
18231     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
18232     (write-buffered *(ebp+0x18) %eax)
18233     58/pop-to-eax
18234     (write-buffered *(ebp+0x18) " reads var '")
18235     (write-slice-buffered *(ebp+0x18) *(ebp+8))
18236     (write-buffered *(ebp+0x18) "' after writing var '")
18237     (lookup *eax *(eax+4))  # Var-name Var-name => eax
18238     (write-buffered *(ebp+0x18) %eax)
18239     (write-buffered *(ebp+0x18) "'\n")
18240     (flush *(ebp+0x18))
18241     (stop *(ebp+0x1c) 1)
18242     # never gets here
18243 
18244 dump-vars:  # vars: (addr stack live-var)
18245     # pseudocode:
18246     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
18247     #   var min = vars->data
18248     #   while curr >= min
18249     #     var v: (handle var) = *curr
18250     #     print v
18251     #     curr -= 12
18252     #
18253     # . prologue
18254     55/push-ebp
18255     89/<- %ebp 4/r32/esp
18256     # . save registers
18257     52/push-edx
18258     53/push-ebx
18259     56/push-esi
18260     # esi = vars
18261     8b/-> *(ebp+8) 6/r32/esi
18262     # ebx = vars->top
18263     8b/-> *esi 3/r32/ebx
18264     # var min/edx: (addr handle var) = vars->data
18265     8d/copy-address *(esi+8) 2/r32/edx
18266     # var curr/ebx: (addr handle var) = &vars->data[vars->top - 12]
18267     8d/copy-address *(esi+ebx-4) 3/r32/ebx  # vars + 8 + vars->type - 12
18268     {
18269 $dump-vars:loop:
18270       # if (curr < min) return
18271       39/compare %ebx 2/r32/edx
18272       0f 82/jump-if-addr< break/disp32
18273       #
18274       (write-buffered Stderr "  var@")
18275       (dump-var 2 %ebx)
18276       # curr -= 12
18277       81 5/subop/subtract %ebx 0xc/imm32
18278       e9/jump loop/disp32
18279     }
18280 $dump-vars:end:
18281     # . restore registers
18282     5e/pop-to-esi
18283     5b/pop-to-ebx
18284     5a/pop-to-edx
18285     # . epilogue
18286     89/<- %esp 5/r32/ebp
18287     5d/pop-to-ebp
18288     c3/return
18289 
18290 == data
18291 # Like Registers, but no esp or ebp
18292 Mu-registers:  # (addr stream {(handle array byte), int})
18293   # a table is a stream
18294   0xa8/imm32/write
18295   0/imm32/read
18296   0xa8/imm32/length
18297   # data
18298   # general-purpose registers
18299   # it is perfectly ok to use fake alloc-ids -- as long as you never try to reclaim them
18300   0x11/imm32/alloc-id $Mu-register-eax/imm32 0/imm32
18301   0x11/imm32/alloc-id $Mu-register-ecx/imm32 1/imm32
18302   0x11/imm32/alloc-id $Mu-register-edx/imm32 2/imm32
18303   0x11/imm32/alloc-id $Mu-register-ebx/imm32 3/imm32
18304   0x11/imm32/alloc-id $Mu-register-esi/imm32 6/imm32
18305   0x11/imm32/alloc-id $Mu-register-edi/imm32 7/imm32
18306   # floating-point registers
18307   0x11/imm32/alloc-id $Mu-register-xmm0/imm32 0/imm32
18308   0x11/imm32/alloc-id $Mu-register-xmm1/imm32 1/imm32
18309   0x11/imm32/alloc-id $Mu-register-xmm2/imm32 2/imm32
18310   0x11/imm32/alloc-id $Mu-register-xmm3/imm32 3/imm32
18311   0x11/imm32/alloc-id $Mu-register-xmm4/imm32 4/imm32
18312   0x11/imm32/alloc-id $Mu-register-xmm5/imm32 5/imm32
18313   0x11/imm32/alloc-id $Mu-register-xmm6/imm32 6/imm32
18314   0x11/imm32/alloc-id $Mu-register-xmm7/imm32 7/imm32
18315 
18316 # Like Mu-registers, but with unique codes for integer and floating-point
18317 # registers.
18318 # Don't use this for code-generation, only for checking.
18319 Mu-registers-unique:  # (addr stream {(handle array byte), int})
18320   # a table is a stream
18321   0xa8/imm32/write
18322   0/imm32/read
18323   0xa8/imm32/length
18324   # data
18325   # general-purpose registers
18326   0x11/imm32/alloc-id $Mu-register-eax/imm32 0/imm32
18327   0x11/imm32/alloc-id $Mu-register-ecx/imm32 1/imm32
18328   0x11/imm32/alloc-id $Mu-register-edx/imm32 2/imm32
18329   0x11/imm32/alloc-id $Mu-register-ebx/imm32 3/imm32
18330   0x11/imm32/alloc-id $Mu-register-esi/imm32 6/imm32
18331   0x11/imm32/alloc-id $Mu-register-edi/imm32 7/imm32
18332   # floating-point registers
18333   0x11/imm32/alloc-id $Mu-register-xmm0/imm32 8/imm32
18334   0x11/imm32/alloc-id $Mu-register-xmm1/imm32 9/imm32
18335   0x11/imm32/alloc-id $Mu-register-xmm2/imm32 0xa/imm32
18336   0x11/imm32/alloc-id $Mu-register-xmm3/imm32 0xb/imm32
18337   0x11/imm32/alloc-id $Mu-register-xmm4/imm32 0xc/imm32
18338   0x11/imm32/alloc-id $Mu-register-xmm5/imm32 0xd/imm32
18339   0x11/imm32/alloc-id $Mu-register-xmm6/imm32 0xe/imm32
18340   0x11/imm32/alloc-id $Mu-register-xmm7/imm32 0xf/imm32
18341 
18342 $Mu-register-eax:
18343   0x11/imm32/alloc-id
18344   3/imm32/size
18345   0x65/e 0x61/a 0x78/x
18346 
18347 $Mu-register-ecx:
18348   0x11/imm32/alloc-id
18349   3/imm32/size
18350   0x65/e 0x63/c 0x78/x
18351 
18352 $Mu-register-edx:
18353   0x11/imm32/alloc-id
18354   3/imm32/size
18355   0x65/e 0x64/d 0x78/x
18356 
18357 $Mu-register-ebx:
18358   0x11/imm32/alloc-id
18359   3/imm32/size
18360   0x65/e 0x62/b 0x78/x
18361 
18362 $Mu-register-esi:
18363   0x11/imm32/alloc-id
18364   3/imm32/size
18365   0x65/e 0x73/s 0x69/i
18366 
18367 $Mu-register-edi:
18368   0x11/imm32/alloc-id
18369   3/imm32/size
18370   0x65/e 0x64/d 0x69/i
18371 
18372 $Mu-register-xmm0:
18373   0x11/imm32/alloc-id:fake:payload
18374   # "xmm0"
18375   0x4/imm32/size
18376   0x78/x 0x6d/m 0x6d/m 0x30/0
18377 
18378 $Mu-register-xmm1:
18379   0x11/imm32/alloc-id:fake:payload
18380   # "xmm1"
18381   0x4/imm32/size
18382   0x78/x 0x6d/m 0x6d/m 0x31/1
18383 
18384 $Mu-register-xmm2:
18385   0x11/imm32/alloc-id:fake:payload
18386   # "xmm2"
18387   0x4/imm32/size
18388   0x78/x 0x6d/m 0x6d/m 0x32/2
18389 
18390 $Mu-register-xmm3:
18391   0x11/imm32/alloc-id:fake:payload
18392   # "xmm3"
18393   0x4/imm32/size
18394   0x78/x 0x6d/m 0x6d/m 0x33/3
18395 
18396 $Mu-register-xmm4:
18397   0x11/imm32/alloc-id:fake:payload
18398   # "xmm4"
18399   0x4/imm32/size
18400   0x78/x 0x6d/m 0x6d/m 0x34/4
18401 
18402 $Mu-register-xmm5:
18403   0x11/imm32/alloc-id:fake:payload
18404   # "xmm5"
18405   0x4/imm32/size
18406   0x78/x 0x6d/m 0x6d/m 0x35/5
18407 
18408 $Mu-register-xmm6:
18409   0x11/imm32/alloc-id:fake:payload
18410   # "xmm6"
18411   0x4/imm32/size
18412   0x78/x 0x6d/m 0x6d/m 0x36/6
18413 
18414 $Mu-register-xmm7:
18415   0x11/imm32/alloc-id:fake:payload
18416   # "xmm7"
18417   0x4/imm32/size
18418   0x78/x 0x6d/m 0x6d/m 0x37/7
18419 
18420 == code
18421 
18422 # push 'out' to 'vars' if not already there; it's assumed to be a fn output
18423 maybe-define-var:  # out: (handle var), vars: (addr stack live-var)
18424     # . prologue
18425     55/push-ebp
18426     89/<- %ebp 4/r32/esp
18427     # . save registers
18428     50/push-eax
18429     # var out-addr/eax: (addr var)
18430     (lookup *(ebp+8) *(ebp+0xc))  # => eax
18431     #
18432     (binding-exists? %eax *(ebp+0x10))  # => eax
18433     3d/compare-eax-and 0/imm32/false
18434     75/jump-if-!= $maybe-define-var:end/disp8
18435     # otherwise update vars
18436     (push *(ebp+0x10) *(ebp+8))
18437     (push *(ebp+0x10) *(ebp+0xc))
18438     (push *(ebp+0x10) 0)  # 'out' is always a fn output; never spill it
18439 $maybe-define-var:end:
18440     # . restore registers
18441     58/pop-to-eax
18442     # . epilogue
18443     89/<- %esp 5/r32/ebp
18444     5d/pop-to-ebp
18445     c3/return
18446 
18447 # simpler version of lookup-var-helper
18448 binding-exists?:  # target: (addr var), vars: (addr stack live-var) -> result/eax: boolean
18449     # pseudocode:
18450     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
18451     #   var min = vars->data
18452     #   while curr >= min
18453     #     var v: (handle var) = *curr
18454     #     if v->name == target->name
18455     #       return true
18456     #     curr -= 12
18457     #   return false
18458     #
18459     # . prologue
18460     55/push-ebp
18461     89/<- %ebp 4/r32/esp
18462     # . save registers
18463     51/push-ecx
18464     52/push-edx
18465     56/push-esi
18466     # var target-name/ecx: (addr array byte) = lookup(target->name)
18467     8b/-> *(ebp+8) 0/r32/eax
18468     (lookup *eax *(eax+4))  # Var-name Var-name => eax
18469     89/<- %ecx 0/r32/eax
18470     # esi = vars
18471     8b/-> *(ebp+0xc) 6/r32/esi
18472     # eax = vars->top
18473     8b/-> *esi 0/r32/eax
18474     # var min/edx: (addr handle var) = vars->data
18475     8d/copy-address *(esi+8) 2/r32/edx
18476     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
18477     8d/copy-address *(esi+eax-4) 6/r32/esi  # vars + 8 + vars->type - 12
18478     {
18479 $binding-exists?:loop:
18480       # if (curr < min) return
18481       39/compare %esi 2/r32/edx
18482       0f 82/jump-if-addr< break/disp32
18483       # var v/eax: (addr var) = lookup(*curr)
18484       (lookup *esi *(esi+4))  # => eax
18485       # var vn/eax: (addr array byte) = lookup(v->name)
18486       (lookup *eax *(eax+4))  # Var-name Var-name => eax
18487       # if (vn == target-name) return true
18488       (string-equal? %ecx %eax)  # => eax
18489       3d/compare-eax-and 0/imm32/false
18490       75/jump-if-!= $binding-exists?:end/disp8  # eax already contains true
18491       # curr -= 12
18492       81 5/subop/subtract %esi 0xc/imm32
18493       e9/jump loop/disp32
18494     }
18495     b8/copy-to-eax 0/imm32/false
18496 $binding-exists?:end:
18497     # . restore registers
18498     5e/pop-to-esi
18499     5a/pop-to-edx
18500     59/pop-to-ecx
18501     # . epilogue
18502     89/<- %esp 5/r32/ebp
18503     5d/pop-to-ebp
18504     c3/return
18505 
18506 test-parse-mu-stmt:
18507     # . prologue
18508     55/push-ebp
18509     89/<- %ebp 4/r32/esp
18510     # setup
18511     8b/-> *Primitive-type-ids 0/r32/eax
18512     89/<- *Type-id 0/r32/eax  # stream-write
18513     (clear-stream _test-input-stream)
18514     (write _test-input-stream "increment n\n")
18515     # var vars/ecx: (stack (addr var) 16)
18516     81 5/subop/subtract %esp 0xc0/imm32
18517     68/push 0xc0/imm32/size
18518     68/push 0/imm32/top
18519     89/<- %ecx 4/r32/esp
18520     (clear-stack %ecx)
18521     # var v/edx: (handle var)
18522     68/push 0/imm32
18523     68/push 0/imm32
18524     89/<- %edx 4/r32/esp
18525     # var s/eax: (handle array byte)
18526     68/push 0/imm32
18527     68/push 0/imm32
18528     89/<- %eax 4/r32/esp
18529     # v = new var("n")
18530     (copy-array Heap "n" %eax)
18531     (new-var Heap *eax *(eax+4) %edx)
18532     #
18533     (push %ecx *edx)
18534     (push %ecx *(edx+4))
18535     (push %ecx 0)
18536     # var out/eax: (handle stmt)
18537     68/push 0/imm32
18538     68/push 0/imm32
18539     89/<- %eax 4/r32/esp
18540     # convert
18541     (parse-mu-stmt _test-input-stream %ecx 0 %eax Stderr 0)
18542     # var out-addr/edx: (addr stmt) = lookup(*out)
18543     (lookup *eax *(eax+4))  # => eax
18544     89/<- %edx 0/r32/eax
18545     # out->tag
18546     (check-ints-equal *edx 1 "F - test-parse-mu-stmt/tag")  # Stmt-tag is Stmt1
18547     # out->operation
18548     (lookup *(edx+4) *(edx+8))  # Stmt1-operation Stmt1-operation => eax
18549     (check-strings-equal %eax "increment" "F - test-parse-mu-stmt/name")  # Stmt1-operation
18550     # out->inouts->value->name
18551     # . eax = out->inouts
18552     (lookup *(edx+0xc) *(edx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
18553     # . eax = out->inouts->value
18554     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
18555     # . eax = out->inouts->value->name
18556     (lookup *eax *(eax+4))  # Var-name Var-name => eax
18557     # .
18558     (check-strings-equal %eax "n" "F - test-parse-mu-stmt/inout:0")
18559     # . epilogue
18560     89/<- %esp 5/r32/ebp
18561     5d/pop-to-ebp
18562     c3/return
18563 
18564 test-parse-mu-stmt-with-comma:
18565     # . prologue
18566     55/push-ebp
18567     89/<- %ebp 4/r32/esp
18568     # setup
18569     8b/-> *Primitive-type-ids 0/r32/eax
18570     89/<- *Type-id 0/r32/eax  # stream-write
18571     (clear-stream _test-input-stream)
18572     (write _test-input-stream "copy-to n, 3\n")
18573     # var vars/ecx: (stack (addr var) 16)
18574     81 5/subop/subtract %esp 0xc0/imm32
18575     68/push 0xc0/imm32/size
18576     68/push 0/imm32/top
18577     89/<- %ecx 4/r32/esp
18578     (clear-stack %ecx)
18579     # var v/edx: (handle var)
18580     68/push 0/imm32
18581     68/push 0/imm32
18582     89/<- %edx 4/r32/esp
18583     # var s/eax: (handle array byte)
18584     68/push 0/imm32
18585     68/push 0/imm32
18586     89/<- %eax 4/r32/esp
18587     # v = new var("n")
18588     (copy-array Heap "n" %eax)
18589     (new-var Heap *eax *(eax+4) %edx)
18590     #
18591     (push %ecx *edx)
18592     (push %ecx *(edx+4))
18593     (push %ecx 0)
18594     # var out/eax: (handle stmt)
18595     68/push 0/imm32
18596     68/push 0/imm32
18597     89/<- %eax 4/r32/esp
18598     # convert
18599     (parse-mu-stmt _test-input-stream %ecx 0 %eax Stderr 0)
18600     # var out-addr/edx: (addr stmt) = lookup(*out)
18601     (lookup *eax *(eax+4))  # => eax
18602     89/<- %edx 0/r32/eax
18603     # out->tag
18604     (check-ints-equal *edx 1 "F - test-parse-mu-stmt-with-comma/tag")  # Stmt-tag is Stmt1
18605     # out->operation
18606     (lookup *(edx+4) *(edx+8))  # Stmt1-operation Stmt1-operation => eax
18607     (check-strings-equal %eax "copy-to" "F - test-parse-mu-stmt-with-comma/name")  # Stmt1-operation
18608     # out->inouts->value->name
18609     # . eax = out->inouts
18610     (lookup *(edx+0xc) *(edx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
18611     # . eax = out->inouts->value
18612     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
18613     # . eax = out->inouts->value->name
18614     (lookup *eax *(eax+4))  # Var-name Var-name => eax
18615     # .
18616     (check-strings-equal %eax "n" "F - test-parse-mu-stmt-with-comma/inout:0")
18617     # . epilogue
18618     89/<- %esp 5/r32/ebp
18619     5d/pop-to-ebp
18620     c3/return
18621 
18622 new-var:  # ad: (addr allocation-descriptor), name: (handle array byte), out: (addr handle var)
18623     # . prologue
18624     55/push-ebp
18625     89/<- %ebp 4/r32/esp
18626     # . save registers
18627     50/push-eax
18628     51/push-ecx
18629     # ecx = out
18630     8b/-> *(ebp+0x14) 1/r32/ecx
18631     #
18632     (allocate *(ebp+8) *Var-size %ecx)
18633     # var out-addr/eax: (addr var)
18634     (lookup *ecx *(ecx+4))  # => eax
18635     # out-addr->name = name
18636     8b/-> *(ebp+0xc) 1/r32/ecx
18637     89/<- *eax 1/r32/ecx  # Var-name
18638     8b/-> *(ebp+0x10) 1/r32/ecx
18639     89/<- *(eax+4) 1/r32/ecx  # Var-name
18640 #?     (write-buffered Stderr "var ")
18641 #?     (lookup *(ebp+0xc) *(ebp+0x10))
18642 #?     (write-buffered Stderr %eax)
18643 #?     (write-buffered Stderr " at ")
18644 #?     8b/-> *(ebp+0x14) 1/r32/ecx
18645 #?     (lookup *ecx *(ecx+4))  # => eax
18646 #?     (write-int32-hex-buffered Stderr %eax)
18647 #?     (write-buffered Stderr Newline)
18648 #?     (flush Stderr)
18649 $new-var:end:
18650     # . restore registers
18651     59/pop-to-ecx
18652     58/pop-to-eax
18653     # . epilogue
18654     89/<- %esp 5/r32/ebp
18655     5d/pop-to-ebp
18656     c3/return
18657 
18658 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)
18659     # . prologue
18660     55/push-ebp
18661     89/<- %ebp 4/r32/esp
18662     # . save registers
18663     50/push-eax
18664     51/push-ecx
18665     # if (!is-hex-int?(name)) abort
18666     (is-hex-int? *(ebp+0xc))  # => eax
18667     3d/compare-eax-and 0/imm32/false
18668     0f 84/jump-if-= $new-literal-integer:abort/disp32
18669     # a little more error-checking
18670     (check-mu-hex-int *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
18671     # out = new var(s)
18672     (new-var-from-slice *(ebp+8) *(ebp+0xc) *(ebp+0x10))
18673     # var out-addr/ecx: (addr var) = lookup(*out)
18674     8b/-> *(ebp+0x10) 0/r32/eax
18675     (lookup *eax *(eax+4))  # => eax
18676     89/<- %ecx 0/r32/eax
18677     # out-addr->block-depth = *Curr-block-depth
18678     8b/-> *Curr-block-depth 0/r32/eax
18679     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
18680     # out-addr->type = new tree()
18681     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
18682     (allocate *(ebp+8) *Type-tree-size %eax)
18683     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
18684     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
18685     # nothing else to do; default type is 'literal'
18686 $new-literal-integer:end:
18687     # . reclaim locals
18688     81 0/subop/add %esp 8/imm32
18689     # . restore registers
18690     59/pop-to-ecx
18691     58/pop-to-eax
18692     # . epilogue
18693     89/<- %esp 5/r32/ebp
18694     5d/pop-to-ebp
18695     c3/return
18696 
18697 $new-literal-integer:abort:
18698     (write-buffered *(ebp+0x18) "fn ")
18699     8b/-> *(ebp+0x14) 0/r32/eax
18700     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18701     (write-buffered *(ebp+0x18) %eax)
18702     (write-buffered *(ebp+0x18) ": variable '")
18703     (write-slice-buffered *(ebp+0x18) *(ebp+0xc))
18704     (write-buffered *(ebp+0x18) "' cannot begin with a digit (or do you have a typo in a number?)\n")
18705     (flush *(ebp+0x18))
18706     (stop *(ebp+0x1c) 1)
18707     # never gets here
18708 
18709 # precondition: name is a valid hex integer; require a '0x' prefix
18710 check-mu-hex-int:  # name: (addr slice), err: (addr buffered-file), ed: (addr exit-descriptor)
18711     # . prologue
18712     55/push-ebp
18713     89/<- %ebp 4/r32/esp
18714     # . save registers
18715     50/push-eax
18716     51/push-ecx
18717     52/push-edx
18718     # ecx = name
18719     8b/-> *(ebp+8) 1/r32/ecx
18720     # var start/edx: (addr byte) = name->start
18721     8b/-> *ecx 2/r32/edx
18722     # if (*start == '-') ++start
18723     b8/copy-to-eax 0/imm32
18724     8a/copy-byte *edx 0/r32/AL
18725     3d/compare-eax-and 0x2d/imm32/dash
18726     {
18727       75/jump-if-!= break/disp8
18728       42/increment-edx
18729     }
18730     # var end/ecx: (addr byte) = name->end
18731     8b/-> *(ecx+4) 1/r32/ecx
18732     # var len/eax: int = name->end - name->start
18733     89/<- %eax 1/r32/ecx
18734     29/subtract-from %eax 2/r32/edx
18735     # if (len <= 1) return
18736     3d/compare-eax-with 1/imm32
18737     0f 8e/jump-if-<= $check-mu-hex-int:end/disp32
18738 $check-mu-hex-int:length->-1:
18739     # if slice-starts-with?({start, end}, "0x") return
18740     # . var tmp = {start, end}
18741     51/push-ecx
18742     52/push-edx
18743     89/<- %eax 4/r32/esp
18744     # .
18745     (slice-starts-with? %eax "0x")  # => eax
18746     # . reclaim tmp
18747     81 0/subop/add %esp 8/imm32
18748     # .
18749     3d/compare-eax-with 0/imm32/false
18750     75/jump-if-!= $check-mu-hex-int:end/disp8
18751 $check-mu-hex-int:abort:
18752     # otherwise abort
18753     (write-buffered *(ebp+0xc) "literal integers are always hex in Mu; start '")
18754     (write-slice-buffered *(ebp+0xc) *(ebp+8))
18755     (write-buffered *(ebp+0xc) "' with a '0x' to be unambiguous, converting it to hexadecimal as necessary.\n")
18756     (flush *(ebp+0xc))
18757     (stop *(ebp+0x10) 1)
18758 $check-mu-hex-int:end:
18759     # . restore registers
18760     5a/pop-to-edx
18761     59/pop-to-ecx
18762     58/pop-to-eax
18763     # . epilogue
18764     89/<- %esp 5/r32/ebp
18765     5d/pop-to-ebp
18766     c3/return
18767 
18768 new-literal:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
18769     # . prologue
18770     55/push-ebp
18771     89/<- %ebp 4/r32/esp
18772     # . save registers
18773     50/push-eax
18774     51/push-ecx
18775     # var s/ecx: (handle array byte)
18776     68/push 0/imm32
18777     68/push 0/imm32
18778     89/<- %ecx 4/r32/esp
18779     # s = slice-to-string(name)
18780     (slice-to-string Heap *(ebp+0xc) %ecx)
18781     # allocate to out
18782     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
18783     # var out-addr/ecx: (addr var) = lookup(*out)
18784     8b/-> *(ebp+0x10) 1/r32/ecx
18785     (lookup *ecx *(ecx+4))  # => eax
18786     89/<- %ecx 0/r32/eax
18787     # out-addr->block-depth = *Curr-block-depth
18788     8b/-> *Curr-block-depth 0/r32/eax
18789     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
18790     # out-addr->type/eax = new type
18791     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
18792     (allocate *(ebp+8) *Type-tree-size %eax)
18793     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
18794     # nothing else to do; default type is 'literal'
18795     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
18796 $new-literal:end:
18797     # . reclaim locals
18798     81 0/subop/add %esp 8/imm32
18799     # . restore registers
18800     59/pop-to-ecx
18801     58/pop-to-eax
18802     # . epilogue
18803     89/<- %esp 5/r32/ebp
18804     5d/pop-to-ebp
18805     c3/return
18806 
18807 new-literal-string:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
18808     # . prologue
18809     55/push-ebp
18810     89/<- %ebp 4/r32/esp
18811     # . save registers
18812     50/push-eax
18813     51/push-ecx
18814     # var s/ecx: (handle array byte)
18815     68/push 0/imm32
18816     68/push 0/imm32
18817     89/<- %ecx 4/r32/esp
18818     # s = slice-to-string(name)
18819     (slice-to-string Heap *(ebp+0xc) %ecx)
18820     # allocate to out
18821     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
18822     # var out-addr/ecx: (addr var) = lookup(*out)
18823     8b/-> *(ebp+0x10) 1/r32/ecx
18824     (lookup *ecx *(ecx+4))  # => eax
18825     89/<- %ecx 0/r32/eax
18826     # out-addr->block-depth = *Curr-block-depth
18827     8b/-> *Curr-block-depth 0/r32/eax
18828     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
18829     # out-addr->type/eax = new type
18830     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
18831     (allocate *(ebp+8) *Type-tree-size %eax)
18832     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
18833     # out-addr->type->value = literal-string
18834     c7 0/subop/copy *(eax+4) 0x10/imm32/type-id-string-literal  # Type-tree-value
18835     # out-addr->type->is-atom? = true
18836     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
18837 $new-literal-string:end:
18838     # . reclaim locals
18839     81 0/subop/add %esp 8/imm32
18840     # . restore registers
18841     59/pop-to-ecx
18842     58/pop-to-eax
18843     # . epilogue
18844     89/<- %esp 5/r32/ebp
18845     5d/pop-to-ebp
18846     c3/return
18847 
18848 new-var-from-slice:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
18849     # . prologue
18850     55/push-ebp
18851     89/<- %ebp 4/r32/esp
18852     # . save registers
18853     51/push-ecx
18854     # var tmp/ecx: (handle array byte)
18855     68/push 0/imm32
18856     68/push 0/imm32
18857     89/<- %ecx 4/r32/esp
18858     # tmp = slice-to-string(name)
18859     (slice-to-string Heap *(ebp+0xc) %ecx)
18860     # out = new-var(tmp)
18861     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
18862 $new-var-from-slice:end:
18863     # . reclaim locals
18864     81 0/subop/add %esp 8/imm32
18865     # . restore registers
18866     59/pop-to-ecx
18867     # . epilogue
18868     89/<- %esp 5/r32/ebp
18869     5d/pop-to-ebp
18870     c3/return
18871 
18872 new-var-def:  # ad: (addr allocation-descriptor), var: (handle var), out: (addr handle stmt)
18873     # . prologue
18874     55/push-ebp
18875     89/<- %ebp 4/r32/esp
18876     # . save registers
18877     50/push-eax
18878     51/push-ecx
18879     #
18880     (allocate *(ebp+8) *Stmt-size *(ebp+0x14))
18881     # var out-addr/eax: (addr stmt) = lookup(*out)
18882     8b/-> *(ebp+0x14) 0/r32/eax
18883     (lookup *eax *(eax+4))  # => eax
18884     # out-addr->tag = stmt
18885     c7 0/subop/copy *eax 2/imm32/tag/var-on-stack  # Stmt-tag
18886     # result->var = var
18887     8b/-> *(ebp+0xc) 1/r32/ecx
18888     89/<- *(eax+4) 1/r32/ecx  # Vardef-var
18889     8b/-> *(ebp+0x10) 1/r32/ecx
18890     89/<- *(eax+8) 1/r32/ecx  # Vardef-var
18891 $new-var-def:end:
18892     # . restore registers
18893     59/pop-to-ecx
18894     58/pop-to-eax
18895     # . epilogue
18896     89/<- %esp 5/r32/ebp
18897     5d/pop-to-ebp
18898     c3/return
18899 
18900 new-reg-var-def:  # ad: (addr allocation-descriptor), var: (handle var), out: (addr handle stmt)
18901     # . prologue
18902     55/push-ebp
18903     89/<- %ebp 4/r32/esp
18904     # . save registers
18905     50/push-eax
18906     # eax = out
18907     8b/-> *(ebp+0x14) 0/r32/eax
18908     #
18909     (allocate *(ebp+8) *Stmt-size %eax)
18910     # var out-addr/eax: (addr stmt) = lookup(*out)
18911     (lookup *eax *(eax+4))  # => eax
18912     # set tag
18913     c7 0/subop/copy *eax 3/imm32/tag/var-in-register  # Stmt-tag
18914     # set output
18915     8d/copy-address *(eax+0x14) 0/r32/eax  # Regvardef-outputs
18916     (append-stmt-var Heap  *(ebp+0xc) *(ebp+0x10)  0 0  0  %eax)
18917 $new-reg-var-def:end:
18918     # . restore registers
18919     58/pop-to-eax
18920     # . epilogue
18921     89/<- %esp 5/r32/ebp
18922     5d/pop-to-ebp
18923     c3/return
18924 
18925 append-list:  # ad: (addr allocation-descriptor), value: (handle _type), list: (handle list _type), out: (addr handle list _type)
18926     # . prologue
18927     55/push-ebp
18928     89/<- %ebp 4/r32/esp
18929     # . save registers
18930     50/push-eax
18931     51/push-ecx
18932     57/push-edi
18933     # edi = out
18934     8b/-> *(ebp+0x1c) 7/r32/edi
18935     # *out = new list
18936     (allocate *(ebp+8) *List-size %edi)
18937     # var out-addr/edi: (addr list _type) = lookup(*out)
18938     (lookup *edi *(edi+4))  # => eax
18939     89/<- %edi 0/r32/eax
18940     # out-addr->value = value
18941     8b/-> *(ebp+0xc) 0/r32/eax
18942     89/<- *edi 0/r32/eax  # List-value
18943     8b/-> *(ebp+0x10) 0/r32/eax
18944     89/<- *(edi+4) 0/r32/eax  # List-value
18945     # if (list == null) return
18946     81 7/subop/compare *(ebp+0x14) 0/imm32
18947     74/jump-if-= $append-list:end/disp8
18948     # otherwise append
18949 $append-list:non-empty-list:
18950     # var curr/eax: (addr list _type) = lookup(list)
18951     (lookup *(ebp+0x14) *(ebp+0x18))  # => eax
18952     # while (curr->next != null) curr = curr->next
18953     {
18954       81 7/subop/compare *(eax+8) 0/imm32  # List-next
18955       74/jump-if-= break/disp8
18956       # curr = lookup(curr->next)
18957       (lookup *(eax+8) *(eax+0xc))  # List-next, List-next => eax
18958       #
18959       eb/jump loop/disp8
18960     }
18961     # edi = out
18962     8b/-> *(ebp+0x1c) 7/r32/edi
18963     # curr->next = out
18964     8b/-> *edi 1/r32/ecx
18965     89/<- *(eax+8) 1/r32/ecx  # List-next
18966     8b/-> *(edi+4) 1/r32/ecx
18967     89/<- *(eax+0xc) 1/r32/ecx  # List-next
18968     # out = list
18969     8b/-> *(ebp+0x14) 1/r32/ecx
18970     89/<- *edi 1/r32/ecx
18971     8b/-> *(ebp+0x18) 1/r32/ecx
18972     89/<- *(edi+4) 1/r32/ecx
18973 $append-list:end:
18974     # . restore registers
18975     5f/pop-to-edi
18976     59/pop-to-ecx
18977     58/pop-to-eax
18978     # . epilogue
18979     89/<- %esp 5/r32/ebp
18980     5d/pop-to-ebp
18981     c3/return
18982 
18983 append-stmt-var:  # ad: (addr allocation-descriptor), v: (handle var), vars: (handle stmt-var), is-deref?: boolean, out: (addr handle stmt-var)
18984     # . prologue
18985     55/push-ebp
18986     89/<- %ebp 4/r32/esp
18987     # . save registers
18988     50/push-eax
18989     51/push-ecx
18990     57/push-edi
18991     # edi = out
18992     8b/-> *(ebp+0x20) 7/r32/edi
18993     # out = new stmt-var
18994     (allocate *(ebp+8) *Stmt-var-size %edi)
18995     # var out-addr/ecx: (addr stmt-var) = lookup(*out)
18996     (lookup *edi *(edi+4))  # => eax
18997     89/<- %ecx 0/r32/eax
18998     # out-addr->value = v
18999     8b/-> *(ebp+0xc) 0/r32/eax
19000     89/<- *ecx 0/r32/eax  # Stmt-var-value
19001     8b/-> *(ebp+0x10) 0/r32/eax
19002     89/<- *(ecx+4) 0/r32/eax  # Stmt-var-value
19003     # out-addr->is-deref? = is-deref?
19004     8b/-> *(ebp+0x1c) 0/r32/eax
19005     89/<- *(ecx+0x10) 0/r32/eax  # Stmt-var-is-deref
19006     # if (vars == null) return result
19007     81 7/subop/compare *(ebp+0x14) 0/imm32/null
19008     74/jump-if-= $append-stmt-var:end/disp8
19009     # otherwise append
19010     # var curr/eax: (addr stmt-var) = lookup(vars)
19011     (lookup *(ebp+0x14) *(ebp+0x18))  # => eax
19012     # while (curr->next != null) curr = curr->next
19013     {
19014       81 7/subop/compare *(eax+8) 0/imm32  # Stmt-var-next
19015       74/jump-if-= break/disp8
19016       # curr = lookup(curr->next)
19017       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next, Stmt-var-next => eax
19018       #
19019       eb/jump loop/disp8
19020     }
19021     # curr->next = out
19022     8b/-> *edi 1/r32/ecx
19023     89/<- *(eax+8) 1/r32/ecx  # Stmt-var-next
19024     8b/-> *(edi+4) 1/r32/ecx
19025     89/<- *(eax+0xc) 1/r32/ecx  # Stmt-var-next
19026     # out = vars
19027     8b/-> *(ebp+0x14) 1/r32/ecx
19028     89/<- *edi 1/r32/ecx
19029     8b/-> *(ebp+0x18) 1/r32/ecx
19030     89/<- *(edi+4) 1/r32/ecx
19031 $append-stmt-var:end:
19032     # . restore registers
19033     5f/pop-to-edi
19034     59/pop-to-ecx
19035     58/pop-to-eax
19036     # . epilogue
19037     89/<- %esp 5/r32/ebp
19038     5d/pop-to-ebp
19039     c3/return
19040 
19041 append-to-block:  # ad: (addr allocation-descriptor), block: (addr block), x: (handle stmt)
19042     # . prologue
19043     55/push-ebp
19044     89/<- %ebp 4/r32/esp
19045     # . save registers
19046     50/push-eax
19047     56/push-esi
19048     # esi = block
19049     8b/-> *(ebp+0xc) 6/r32/esi
19050     # block->stmts = append(x, block->stmts)
19051     8d/copy-address *(esi+4) 0/r32/eax  # Block-stmts
19052     (append-list *(ebp+8)  *(ebp+0x10) *(ebp+0x14)  *(esi+4) *(esi+8)  %eax)  # ad, x, x, Block-stmts, Block-stmts
19053 $append-to-block:end:
19054     # . restore registers
19055     5e/pop-to-esi
19056     58/pop-to-eax
19057     # . epilogue
19058     89/<- %esp 5/r32/ebp
19059     5d/pop-to-ebp
19060     c3/return
19061 
19062 ## Parsing types
19063 # We need to create metadata on user-defined types, and we need to use this
19064 # metadata as we parse instructions.
19065 # However, we also want to allow types to be used before their definitions.
19066 # This means we can't ever assume any type data structures exist.
19067 
19068 lookup-or-create-constant:  # container: (addr stmt-var), field-name: (addr slice), out: (addr handle var)
19069     # . prologue
19070     55/push-ebp
19071     89/<- %ebp 4/r32/esp
19072     # . save registers
19073     50/push-eax
19074     56/push-esi
19075     # var container-type/esi: type-id
19076     (container-type *(ebp+8))  # => eax
19077     89/<- %esi 0/r32/eax
19078     # var tmp/eax: (handle typeinfo) = find-or-create-typeinfo(container-type)
19079     68/push 0/imm32
19080     68/push 0/imm32
19081     89/<- %eax 4/r32/esp
19082     (find-or-create-typeinfo %esi %eax)
19083     # var tmp-addr/eax: (addr typeinfo) = lookup(tmp)
19084     (lookup *eax *(eax+4))  # => eax
19085     # result = find-or-create-typeinfo-output-var(typeinfo, field-name)
19086 #?     (write-buffered Stderr "constant: ")
19087 #?     (write-slice-buffered Stderr *(ebp+0xc))
19088 #?     (write-buffered Stderr Newline)
19089 #?     (flush Stderr)
19090     (find-or-create-typeinfo-output-var %eax *(ebp+0xc) *(ebp+0x10))
19091 #?     8b/-> *(ebp+0x10) 0/r32/eax
19092 #?     (write-buffered Stderr "@")
19093 #?     (lookup *eax *(eax+4))
19094 #?     (write-int32-hex-buffered Stderr %eax)
19095 #?     (lookup *eax *(eax+4))
19096 #?     (write-buffered Stderr %eax)
19097 #?     (write-buffered Stderr Newline)
19098 #?     (flush Stderr)
19099 #?     (write-buffered Stderr "offset: ")
19100 #?     8b/-> *(eax+0x14) 0/r32/eax
19101 #?     (write-int32-hex-buffered Stderr %eax)
19102 #?     (write-buffered Stderr Newline)
19103 #?     (flush Stderr)
19104 $lookup-or-create-constant:end:
19105     # . reclaim locals
19106     81 0/subop/add %esp 8/imm32
19107     # . restore registers
19108     5e/pop-to-esi
19109     58/pop-to-eax
19110     # . epilogue
19111     89/<- %esp 5/r32/ebp
19112     5d/pop-to-ebp
19113     c3/return
19114 
19115 # if addr var:
19116 #   container->var->type->right->left->value
19117 # otherwise
19118 #   container->var->type->value
19119 container-type:  # container: (addr stmt-var) -> result/eax: type-id
19120     # . prologue
19121     55/push-ebp
19122     89/<- %ebp 4/r32/esp
19123     #
19124     8b/-> *(ebp+8) 0/r32/eax
19125     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
19126     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
19127     {
19128       81 7/subop/compare *(eax+8) 0/imm32  # Type-tree-right
19129       74/jump-if-= break/disp8
19130       (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
19131       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
19132     }
19133     8b/-> *(eax+4) 0/r32/eax  # Type-tree-value
19134 $container-type:end:
19135     # . epilogue
19136     89/<- %esp 5/r32/ebp
19137     5d/pop-to-ebp
19138     c3/return
19139 
19140 is-container?:  # t: type-id -> result/eax: boolean
19141     # . prologue
19142     55/push-ebp
19143     89/<- %ebp 4/r32/esp
19144     #
19145     8b/-> *(ebp+8) 0/r32/eax
19146     c1/shift 4/subop/left %eax 2/imm8
19147     3b/compare 0/r32/eax *Primitive-type-ids
19148     0f 9d/set-if->= %al
19149     81 4/subop/and %eax 0xff/imm32
19150 $is-container?:end:
19151     # . epilogue
19152     89/<- %esp 5/r32/ebp
19153     5d/pop-to-ebp
19154     c3/return
19155 
19156 find-or-create-typeinfo:  # t: type-id, out: (addr handle typeinfo)
19157     # . prologue
19158     55/push-ebp
19159     89/<- %ebp 4/r32/esp
19160     # . save registers
19161     50/push-eax
19162     51/push-ecx
19163     52/push-edx
19164     57/push-edi
19165     # edi = out
19166     8b/-> *(ebp+0xc) 7/r32/edi
19167     # var fields/ecx: (handle table (handle array byte) (handle typeinfo-entry))
19168     68/push 0/imm32
19169     68/push 0/imm32
19170     89/<- %ecx 4/r32/esp
19171     # find-typeinfo(t, out)
19172     (find-typeinfo *(ebp+8) %edi)
19173     {
19174       # if (*out != 0) break
19175       81 7/subop/compare *edi 0/imm32
19176       0f 85/jump-if-!= break/disp32
19177 $find-or-create-typeinfo:create:
19178       # *out = allocate
19179       (allocate Heap *Typeinfo-size %edi)
19180       # var tmp/eax: (addr typeinfo) = lookup(*out)
19181       (lookup *edi *(edi+4))  # => eax
19182 #?     (write-buffered Stderr "created typeinfo at ")
19183 #?     (write-int32-hex-buffered Stderr %eax)
19184 #?     (write-buffered Stderr " for type-id ")
19185 #?     (write-int32-hex-buffered Stderr *(ebp+8))
19186 #?     (write-buffered Stderr Newline)
19187 #?     (flush Stderr)
19188       # tmp->id = t
19189       8b/-> *(ebp+8) 2/r32/edx
19190       89/<- *eax 2/r32/edx  # Typeinfo-id
19191       # tmp->fields = new table
19192       # . fields = new table
19193       (new-stream Heap 0x40 *Typeinfo-fields-row-size %ecx)
19194       # . tmp->fields = fields
19195       8b/-> *ecx 2/r32/edx
19196       89/<- *(eax+4) 2/r32/edx  # Typeinfo-fields
19197       8b/-> *(ecx+4) 2/r32/edx
19198       89/<- *(eax+8) 2/r32/edx  # Typeinfo-fields
19199       # tmp->next = Program->types
19200       8b/-> *_Program-types 1/r32/ecx
19201       89/<- *(eax+0x10) 1/r32/ecx  # Typeinfo-next
19202       8b/-> *_Program-types->payload 1/r32/ecx
19203       89/<- *(eax+0x14) 1/r32/ecx  # Typeinfo-next
19204       # Program->types = out
19205       8b/-> *edi 1/r32/ecx
19206       89/<- *_Program-types 1/r32/ecx
19207       8b/-> *(edi+4) 1/r32/ecx
19208       89/<- *_Program-types->payload 1/r32/ecx
19209     }
19210 $find-or-create-typeinfo:end:
19211     # . reclaim locals
19212     81 0/subop/add %esp 8/imm32
19213     # . restore registers
19214     5f/pop-to-edi
19215     5a/pop-to-edx
19216     59/pop-to-ecx
19217     58/pop-to-eax
19218     # . epilogue
19219     89/<- %esp 5/r32/ebp
19220     5d/pop-to-ebp
19221     c3/return
19222 
19223 find-typeinfo:  # t: type-id, out: (addr handle typeinfo)
19224     # . prologue
19225     55/push-ebp
19226     89/<- %ebp 4/r32/esp
19227     # . save registers
19228     50/push-eax
19229     51/push-ecx
19230     52/push-edx
19231     57/push-edi
19232     # ecx = t
19233     8b/-> *(ebp+8) 1/r32/ecx
19234     # edi = out
19235     8b/-> *(ebp+0xc) 7/r32/edi
19236     # *out = Program->types
19237     8b/-> *_Program-types 0/r32/eax
19238     89/<- *edi 0/r32/eax
19239     8b/-> *_Program-types->payload 0/r32/eax
19240     89/<- *(edi+4) 0/r32/eax
19241     {
19242 $find-typeinfo:loop:
19243       # if (*out == 0) break
19244       81 7/subop/compare *edi 0/imm32
19245       74/jump-if-= break/disp8
19246 $find-typeinfo:check:
19247       # var tmp/eax: (addr typeinfo) = lookup(*out)
19248       (lookup *edi *(edi+4))  # => eax
19249       # if (tmp->id == t) break
19250       39/compare *eax 1/r32/ecx  # Typeinfo-id
19251       74/jump-if-= break/disp8
19252 $find-typeinfo:continue:
19253       # *out = tmp->next
19254       8b/-> *(eax+0x10) 2/r32/edx  # Typeinfo-next
19255       89/<- *edi 2/r32/edx
19256       8b/-> *(eax+0x14) 2/r32/edx  # Typeinfo-next
19257       89/<- *(edi+4) 2/r32/edx
19258       #
19259       eb/jump loop/disp8
19260     }
19261 $find-typeinfo:end:
19262     # . restore registers
19263     5f/pop-to-edi
19264     5a/pop-to-edx
19265     59/pop-to-ecx
19266     58/pop-to-eax
19267     # . epilogue
19268     89/<- %esp 5/r32/ebp
19269     5d/pop-to-ebp
19270     c3/return
19271 
19272 find-or-create-typeinfo-output-var:  # T: (addr typeinfo), f: (addr slice), out: (addr handle var)
19273     # . prologue
19274     55/push-ebp
19275     89/<- %ebp 4/r32/esp
19276     # . save registers
19277     50/push-eax
19278     52/push-edx
19279     57/push-edi
19280     # var dest/edi: (handle typeinfo-entry)
19281     68/push 0/imm32
19282     68/push 0/imm32
19283     89/<- %edi 4/r32/esp
19284     # find-or-create-typeinfo-fields(T, f, dest)
19285     (find-or-create-typeinfo-fields *(ebp+8) *(ebp+0xc) %edi)
19286     # var dest-addr/edi: (addr typeinfo-entry) = lookup(dest)
19287     (lookup *edi *(edi+4))  # => eax
19288     89/<- %edi 0/r32/eax
19289     # if dest-addr->output-var doesn't exist, create it
19290     {
19291       81 7/subop/compare *(edi+0xc) 0/imm32  # Typeinfo-entry-output-var
19292       0f 85/jump-if-!= break/disp32
19293       # dest-addr->output-var = new var(dummy name, type, -1 offset)
19294       # . var name/eax: (handle array byte) = "field"
19295       68/push 0/imm32
19296       68/push 0/imm32
19297       89/<- %eax 4/r32/esp
19298       (slice-to-string Heap *(ebp+0xc) %eax)
19299       # . new var
19300       8d/copy-address *(edi+0xc) 2/r32/edx
19301       (new-var Heap  *eax *(eax+4)  %edx)
19302       # . reclaim name
19303       81 0/subop/add %esp 8/imm32
19304       # var result/edx: (addr var) = lookup(dest-addr->output-var)
19305       (lookup *(edi+0xc) *(edi+0x10))  # => eax
19306       89/<- %edx 0/r32/eax
19307       # result->type = new constant type
19308       8d/copy-address *(edx+8) 0/r32/eax  # Var-type
19309       (allocate Heap *Type-tree-size %eax)
19310       (lookup *(edx+8) *(edx+0xc))  # => eax
19311       c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
19312       c7 0/subop/copy *(eax+4) 6/imm32/constant  # Type-tree-value
19313       c7 0/subop/copy *(eax+8) 0/imm32  # Type-tree-left
19314       c7 0/subop/copy *(eax+0xc) 0/imm32  # Type-tree-right
19315       c7 0/subop/copy *(eax+0x10) 0/imm32  # Type-tree-right
19316       # result->offset isn't filled out yet
19317       c7 0/subop/copy *(edx+0x14) -1/imm32/uninitialized  # Var-offset
19318     }
19319     # out = dest-addr->output-var
19320     8b/-> *(ebp+0x10) 2/r32/edx
19321     8b/-> *(edi+0xc) 0/r32/eax  # Typeinfo-entry-output-var
19322     89/<- *edx 0/r32/eax
19323     8b/-> *(edi+0x10) 0/r32/eax  # Typeinfo-entry-output-var
19324     89/<- *(edx+4) 0/r32/eax
19325 $find-or-create-typeinfo-output-var:end:
19326     # . reclaim locals
19327     81 0/subop/add %esp 8/imm32
19328     # . restore registers
19329     5f/pop-to-edi
19330     5a/pop-to-edx
19331     58/pop-to-eax
19332     # . epilogue
19333     89/<- %esp 5/r32/ebp
19334     5d/pop-to-ebp
19335     c3/return
19336 
19337 find-or-create-typeinfo-fields:  # T: (addr typeinfo), f: (addr slice), out: (addr handle typeinfo-entry)
19338     # . prologue
19339     55/push-ebp
19340     89/<- %ebp 4/r32/esp
19341     # . save registers
19342     50/push-eax
19343     56/push-esi
19344     57/push-edi
19345     # eax = lookup(T->fields)
19346     8b/-> *(ebp+8) 0/r32/eax
19347     (lookup *(eax+4) *(eax+8))  # Typeinfo-fields Typeinfo-fields => eax
19348     # edi = out
19349     8b/-> *(ebp+0x10) 7/r32/edi
19350     # var src/esi: (addr handle typeinfo-entry) = get-or-insert-slice(T->fields, f)
19351     (get-or-insert-slice %eax *(ebp+0xc) *Typeinfo-fields-row-size Heap)  # => eax
19352     89/<- %esi 0/r32/eax
19353     # if src doesn't exist, allocate it
19354     {
19355       81 7/subop/compare *esi 0/imm32
19356       75/jump-if-!= break/disp8
19357       (allocate Heap *Typeinfo-entry-size %esi)
19358 #?       (write-buffered Stderr "handle at ")
19359 #?       (write-int32-hex-buffered Stderr %esi)
19360 #?       (write-buffered Stderr ": ")
19361 #?       (write-int32-hex-buffered Stderr *esi)
19362 #?       (write-buffered Stderr " ")
19363 #?       (write-int32-hex-buffered Stderr *(esi+4))
19364 #?       (write-buffered Stderr Newline)
19365 #?       (flush Stderr)
19366 #?       (lookup *esi *(esi+4))
19367 #?       (write-buffered Stderr "created typeinfo fields at ")
19368 #?       (write-int32-hex-buffered Stderr %esi)
19369 #?       (write-buffered Stderr " for ")
19370 #?       (write-int32-hex-buffered Stderr *(ebp+8))
19371 #?       (write-buffered Stderr Newline)
19372 #?       (flush Stderr)
19373     }
19374     # *out = src
19375     # . *edi = *src
19376     8b/-> *esi 0/r32/eax
19377     89/<- *edi 0/r32/eax
19378     8b/-> *(esi+4) 0/r32/eax
19379     89/<- *(edi+4) 0/r32/eax
19380 $find-or-create-typeinfo-fields:end:
19381     # . restore registers
19382     5f/pop-to-edi
19383     5e/pop-to-esi
19384     58/pop-to-eax
19385     # . epilogue
19386     89/<- %esp 5/r32/ebp
19387     5d/pop-to-ebp
19388     c3/return
19389 
19390 populate-mu-type:  # in: (addr stream byte), t: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
19391     # pseudocode:
19392     #   var line: (stream byte 512)
19393     #   curr-index = 0
19394     #   while true
19395     #     clear-stream(line)
19396     #     read-line-buffered(in, line)
19397     #     if line->write == 0
19398     #       abort
19399     #     word-slice = next-mu-token(line)
19400     #     if slice-empty?(word-slice)               # end of line
19401     #       continue
19402     #     if slice-equal?(word-slice, "}")
19403     #       break
19404     #     var v: (handle var) = parse-var-with-type(word-slice, line)
19405     #     var r: (handle typeinfo-fields) = find-or-create-typeinfo-fields(t, word-slice/v->name)
19406     #     TODO: ensure that r->first is null
19407     #     r->index = curr-index
19408     #     curr-index++
19409     #     r->input-var = v
19410     #     if r->output-var == 0
19411     #       r->output-var = new literal
19412     #     TODO: ensure nothing else in line
19413     # t->total-size-in-bytes = -2 (not yet initialized)
19414     #
19415     # . prologue
19416     55/push-ebp
19417     89/<- %ebp 4/r32/esp
19418     # var curr-index: int at *(ebp-4)
19419     68/push 0/imm32
19420     # . save registers
19421     50/push-eax
19422     51/push-ecx
19423     52/push-edx
19424     53/push-ebx
19425     56/push-esi
19426     57/push-edi
19427     # edi = t
19428     8b/-> *(ebp+0xc) 7/r32/edi
19429     # var line/ecx: (stream byte 512)
19430     81 5/subop/subtract %esp 0x200/imm32
19431     68/push 0x200/imm32/size
19432     68/push 0/imm32/read
19433     68/push 0/imm32/write
19434     89/<- %ecx 4/r32/esp
19435     # var word-slice/edx: slice
19436     68/push 0/imm32/end
19437     68/push 0/imm32/start
19438     89/<- %edx 4/r32/esp
19439     # var v/esi: (handle var)
19440     68/push 0/imm32
19441     68/push 0/imm32
19442     89/<- %esi 4/r32/esp
19443     # var r/ebx: (handle typeinfo-entry)
19444     68/push 0/imm32
19445     68/push 0/imm32
19446     89/<- %ebx 4/r32/esp
19447     {
19448 $populate-mu-type:line-loop:
19449       (clear-stream %ecx)
19450       (read-line-buffered *(ebp+8) %ecx)
19451       # if (line->write == 0) abort
19452       81 7/subop/compare *ecx 0/imm32
19453       0f 84/jump-if-= $populate-mu-type:error1/disp32
19454 +--  6 lines: #?       # dump line ----------------------------------------------------------------------------------------------------------------------------------------------------
19460       (next-mu-token %ecx %edx)
19461       # if slice-empty?(word-slice) continue
19462       (slice-empty? %edx)  # => eax
19463       3d/compare-eax-and 0/imm32
19464       0f 85/jump-if-!= loop/disp32
19465       # if slice-equal?(word-slice, "}") break
19466       (slice-equal? %edx "}")
19467       3d/compare-eax-and 0/imm32
19468       0f 85/jump-if-!= break/disp32
19469 $populate-mu-type:parse-element:
19470       # v = parse-var-with-type(word-slice, first-line)
19471       # must do this first to strip the trailing ':' from word-slice before
19472       # using it in find-or-create-typeinfo-fields below
19473       # TODO: clean up that mutation in parse-var-with-type
19474       (type-name *edi)  # Typeinfo-id => eax
19475       (parse-var-with-type %edx %ecx %esi %eax *(ebp+0x10) *(ebp+0x14))
19476       # if v is an addr, abort
19477       (lookup *esi *(esi+4))  # => eax
19478       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
19479       (is-mu-addr-type? %eax)  # => eax
19480       3d/compare-eax-and 0/imm32/false
19481       0f 85/jump-if-!= $populate-mu-type:error2/disp32
19482       # if v is an array, abort  (we could support it, but initialization gets complex)
19483       (lookup *esi *(esi+4))  # => eax
19484       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
19485       (is-mu-array-type? %eax)  # => eax
19486       3d/compare-eax-and 0/imm32/false
19487       0f 85/jump-if-!= $populate-mu-type:error3/disp32
19488       # if v is a byte, abort
19489       (lookup *esi *(esi+4))  # => eax
19490       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
19491       (is-simple-mu-type? %eax 8)  # byte => eax
19492       3d/compare-eax-and 0/imm32/false
19493       0f 85/jump-if-!= $populate-mu-type:error4/disp32
19494       # if v is a slice, abort
19495       (lookup *esi *(esi+4))  # => eax
19496       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
19497       (is-simple-mu-type? %eax 0xc)  # slice => eax
19498       3d/compare-eax-and 0/imm32/false
19499       0f 85/jump-if-!= $populate-mu-type:error5/disp32
19500       # if v is a stream, abort  (we could support it, but initialization gets even more complex)
19501       (lookup *esi *(esi+4))  # => eax
19502       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
19503       (is-mu-stream-type? %eax)  # => eax
19504       3d/compare-eax-and 0/imm32/false
19505       0f 85/jump-if-!= $populate-mu-type:error6/disp32
19506       # var tmp/ecx
19507       51/push-ecx
19508 $populate-mu-type:create-typeinfo-fields:
19509       # var r/ebx: (handle typeinfo-entry)
19510       (find-or-create-typeinfo-fields %edi %edx %ebx)
19511       # r->index = curr-index
19512       (lookup *ebx *(ebx+4))  # => eax
19513       8b/-> *(ebp-4) 1/r32/ecx
19514 #?       (write-buffered Stderr "saving index ")
19515 #?       (write-int32-hex-buffered Stderr %ecx)
19516 #?       (write-buffered Stderr " at ")
19517 #?       (write-int32-hex-buffered Stderr %edi)
19518 #?       (write-buffered Stderr Newline)
19519 #?       (flush Stderr)
19520       89/<- *(eax+8) 1/r32/ecx  # Typeinfo-entry-index
19521       # ++curr-index
19522       ff 0/subop/increment *(ebp-4)
19523 $populate-mu-type:set-input-type:
19524       # r->input-var = v
19525       8b/-> *esi 1/r32/ecx
19526       89/<- *eax 1/r32/ecx  # Typeinfo-entry-input-var
19527       8b/-> *(esi+4) 1/r32/ecx
19528       89/<- *(eax+4) 1/r32/ecx  # Typeinfo-entry-input-var
19529       # restore line
19530       59/pop-to-ecx
19531       {
19532 $populate-mu-type:create-output-type:
19533         # if (r->output-var == 0) create a new var with some placeholder data
19534         81 7/subop/compare *(eax+0xc) 0/imm32  # Typeinfo-entry-output-var
19535         75/jump-if-!= break/disp8
19536         8d/copy-address *(eax+0xc) 0/r32/eax  # Typeinfo-entry-output-var
19537         (new-literal Heap %edx %eax)
19538       }
19539       e9/jump loop/disp32
19540     }
19541 $populate-mu-type:invalidate-total-size-in-bytes:
19542     # Offsets and total size may not be accurate here since we may not yet
19543     # have encountered the element types.
19544     # We'll recompute them separately after parsing the entire program.
19545     c7 0/subop/copy *(edi+0xc) -2/imm32/uninitialized  # Typeinfo-total-size-in-bytes
19546 $populate-mu-type:end:
19547     # . reclaim locals
19548     81 0/subop/add %esp 0x224/imm32
19549     # . restore registers
19550     5f/pop-to-edi
19551     5e/pop-to-esi
19552     5b/pop-to-ebx
19553     5a/pop-to-edx
19554     59/pop-to-ecx
19555     58/pop-to-eax
19556     # reclaim curr-index
19557     81 0/subop/add %esp 4/imm32
19558     # . epilogue
19559     89/<- %esp 5/r32/ebp
19560     5d/pop-to-ebp
19561     c3/return
19562 
19563 $populate-mu-type:error1:
19564     # error("incomplete type definition '" t->name "'\n")
19565     (write-buffered *(ebp+0x10) "incomplete type definition '")
19566     (type-name *edi)  # Typeinfo-id => eax
19567     (write-buffered *(ebp+0x10) %eax)
19568     (write-buffered *(ebp+0x10) "\n")
19569     (flush *(ebp+0x10))
19570     (stop *(ebp+0x14) 1)
19571     # never gets here
19572 
19573 $populate-mu-type:error2:
19574     (write-buffered *(ebp+0x10) "type ")
19575     (type-name *edi)  # Typeinfo-id => eax
19576     (write-buffered *(ebp+0x10) %eax)
19577     (write-buffered *(ebp+0x10) ": 'addr' elements not allowed\n")
19578     (flush *(ebp+0x10))
19579     (stop *(ebp+0x14) 1)
19580     # never gets here
19581 
19582 $populate-mu-type:error3:
19583     (write-buffered *(ebp+0x10) "type ")
19584     (type-name *edi)  # Typeinfo-id => eax
19585     (write-buffered *(ebp+0x10) %eax)
19586     (write-buffered *(ebp+0x10) ": 'array' elements not allowed for now\n")
19587     (flush *(ebp+0x10))
19588     (stop *(ebp+0x14) 1)
19589     # never gets here
19590 
19591 $populate-mu-type:error4:
19592     (write-buffered *(ebp+0x10) "type ")
19593     (type-name *edi)  # Typeinfo-id => eax
19594     (write-buffered *(ebp+0x10) %eax)
19595     (write-buffered *(ebp+0x10) ": 'byte' elements not allowed\n")
19596     (flush *(ebp+0x10))
19597     (stop *(ebp+0x14) 1)
19598     # never gets here
19599 
19600 $populate-mu-type:error5:
19601     (write-buffered *(ebp+0x10) "type ")
19602     (type-name *edi)  # Typeinfo-id => eax
19603     (write-buffered *(ebp+0x10) %eax)
19604     (write-buffered *(ebp+0x10) ": 'slice' elements not allowed\n")
19605     (flush *(ebp+0x10))
19606     (stop *(ebp+0x14) 1)
19607     # never gets here
19608 
19609 $populate-mu-type:error6:
19610     (write-buffered *(ebp+0x10) "type ")
19611     (type-name *edi)  # Typeinfo-id => eax
19612     (write-buffered *(ebp+0x10) %eax)
19613     (write-buffered *(ebp+0x10) ": 'stream' elements not allowed for now\n")
19614     (flush *(ebp+0x10))
19615     (stop *(ebp+0x14) 1)
19616     # never gets here
19617 
19618 type-name:  # index: int -> result/eax: (addr array byte)
19619     # . prologue
19620     55/push-ebp
19621     89/<- %ebp 4/r32/esp
19622     #
19623     (index Type-id *(ebp+8))
19624 $type-name:end:
19625     # . epilogue
19626     89/<- %esp 5/r32/ebp
19627     5d/pop-to-ebp
19628     c3/return
19629 
19630 index:  # arr: (addr stream (handle array byte)), index: int -> result/eax: (addr array byte)
19631     # . prologue
19632     55/push-ebp
19633     89/<- %ebp 4/r32/esp
19634     # . save registers
19635     56/push-esi
19636     # TODO: bounds-check index
19637     # esi = arr
19638     8b/-> *(ebp+8) 6/r32/esi
19639     # eax = index
19640     8b/-> *(ebp+0xc) 0/r32/eax
19641     # eax = *(arr + 12 + index)
19642     8b/-> *(esi+eax<<2+0xc) 0/r32/eax
19643 $index:end:
19644     # . restore registers
19645     5e/pop-to-esi
19646     # . epilogue
19647     89/<- %esp 5/r32/ebp
19648     5d/pop-to-ebp
19649     c3/return
19650 
19651 #######################################################
19652 # Compute type sizes
19653 #######################################################
19654 
19655 # Compute the sizes of all user-defined types.
19656 # We'll need the sizes of their elements, which may be other user-defined
19657 # types, which we will compute as needed.
19658 
19659 # Initially, all user-defined types have their sizes set to -2 (invalid)
19660 populate-mu-type-sizes:  # err: (addr buffered-file), ed: (addr exit-descriptor)
19661     # . prologue
19662     55/push-ebp
19663     89/<- %ebp 4/r32/esp
19664 $populate-mu-type-sizes:total-sizes:
19665     # var curr/eax: (addr typeinfo) = lookup(Program->types)
19666     (lookup *_Program-types *_Program-types->payload)  # => eax
19667     {
19668       # if (curr == null) break
19669       3d/compare-eax-and 0/imm32/null
19670       74/jump-if-= break/disp8
19671       (populate-mu-type-sizes-in-type %eax *(ebp+8) *(ebp+0xc))
19672       # curr = lookup(curr->next)
19673       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
19674       eb/jump loop/disp8
19675     }
19676 $populate-mu-type-sizes:offsets:
19677     # curr = *Program->types
19678     (lookup *_Program-types *_Program-types->payload)  # => eax
19679     {
19680       # if (curr == null) break
19681       3d/compare-eax-and 0/imm32/null
19682       74/jump-if-= break/disp8
19683       (populate-mu-type-offsets %eax *(ebp+8) *(ebp+0xc))
19684       # curr = curr->next
19685       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
19686       eb/jump loop/disp8
19687     }
19688 $populate-mu-type-sizes:end:
19689     # . epilogue
19690     89/<- %esp 5/r32/ebp
19691     5d/pop-to-ebp
19692     c3/return
19693 
19694 # compute sizes of all fields, recursing as necessary
19695 # sum up all their sizes to arrive at total size
19696 # fields may be out of order, but that doesn't affect the answer
19697 populate-mu-type-sizes-in-type:  # T: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
19698     # . prologue
19699     55/push-ebp
19700     89/<- %ebp 4/r32/esp
19701     # . save registers
19702     50/push-eax
19703     51/push-ecx
19704     52/push-edx
19705     56/push-esi
19706     57/push-edi
19707     # esi = T
19708     8b/-> *(ebp+8) 6/r32/esi
19709     # if T is already computed, return
19710     81 7/subop/compare *(esi+0xc) 0/imm32  # Typeinfo-total-size-in-bytes
19711     0f 8d/jump-if->= $populate-mu-type-sizes-in-type:end/disp32
19712     # if T is being computed, abort
19713     81 7/subop/compare *(esi+0xc) -1/imm32/being-computed  # Typeinfo-total-size-in-bytes
19714     0f 84/jump-if-= $populate-mu-type-sizes-in-type:abort/disp32
19715     # tag T (-2 to -1) to avoid infinite recursion
19716     c7 0/subop/copy *(esi+0xc) -1/imm32/being-computed  # Typeinfo-total-size-in-bytes
19717     # var total-size/edi: int = 0
19718     bf/copy-to-edi 0/imm32
19719     # - for every field, if it's a user-defined type, compute its size
19720     # var table/ecx: (addr table (handle array byte) (handle typeinfo-entry)) = lookup(T->fields)
19721     (lookup *(esi+4) *(esi+8))  # Typeinfo-fields Typeinfo-fields => eax
19722     89/<- %ecx 0/r32/eax
19723     # var table-size/edx: int = table->write
19724     8b/-> *ecx 2/r32/edx  # stream-write
19725     # var curr/ecx: (addr table_row) = table->data
19726     8d/copy-address *(ecx+0xc) 1/r32/ecx
19727     # var max/edx: (addr table_row) = table->data + table->write
19728     8d/copy-address *(ecx+edx) 2/r32/edx
19729     {
19730 $populate-mu-type-sizes-in-type:loop:
19731       # if (curr >= max) break
19732       39/compare %ecx 2/r32/edx
19733       73/jump-if-addr>= break/disp8
19734       # var t/eax: (addr typeinfo-entry) = lookup(curr->value)
19735       (lookup *(ecx+8) *(ecx+0xc))  # => eax
19736       # if (t->input-var == 0) silently ignore it; we'll emit a nice error message while type-checking
19737       81 7/subop/compare *eax 0/imm32  # Typeinfo-entry-input-var
19738       74/jump-if-= $populate-mu-type-sizes-in-type:end/disp8
19739       # compute size of t->input-var
19740       (lookup *eax *(eax+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
19741       (compute-size-of-var %eax *(ebp+0xc) *(ebp+0x10))  # => eax
19742       # result += eax
19743       01/add-to %edi 0/r32/eax
19744       # curr += row-size
19745       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-fields-row-size
19746       #
19747       eb/jump loop/disp8
19748     }
19749     # - save result
19750     89/<- *(esi+0xc) 7/r32/edi  # Typeinfo-total-size-in-bytes
19751 $populate-mu-type-sizes-in-type:end:
19752     # . restore registers
19753     5f/pop-to-edi
19754     5e/pop-to-esi
19755     5a/pop-to-edx
19756     59/pop-to-ecx
19757     58/pop-to-eax
19758     # . epilogue
19759     89/<- %esp 5/r32/ebp
19760     5d/pop-to-ebp
19761     c3/return
19762 
19763 $populate-mu-type-sizes-in-type:abort:
19764     (write-buffered *(ebp+0xc) "cycle in type definitions\n")
19765     (flush *(ebp+0xc))
19766     (stop *(ebp+0x10) 1)
19767     # never gets here
19768 
19769 # Analogous to size-of, except we need to compute what size-of can just read
19770 # off the right data structures.
19771 compute-size-of-var:  # in: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
19772     # . prologue
19773     55/push-ebp
19774     89/<- %ebp 4/r32/esp
19775     # . push registers
19776     51/push-ecx
19777     # var t/ecx: (addr type-tree) = lookup(v->type)
19778     8b/-> *(ebp+8) 1/r32/ecx
19779     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
19780     89/<- %ecx 0/r32/eax
19781     # if (t->is-atom == false) t = lookup(t->left)
19782     {
19783       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
19784       75/jump-if-!= break/disp8
19785       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
19786       89/<- %ecx 0/r32/eax
19787     }
19788     # TODO: ensure t is an atom
19789     (compute-size-of-type-id *(ecx+4) *(ebp+0xc) *(ebp+0x10))  # Type-tree-value => eax
19790 $compute-size-of-var:end:
19791     # . restore registers
19792     59/pop-to-ecx
19793     # . epilogue
19794     89/<- %esp 5/r32/ebp
19795     5d/pop-to-ebp
19796     c3/return
19797 
19798 compute-size-of-type-id:  # t: type-id, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
19799     # . prologue
19800     55/push-ebp
19801     89/<- %ebp 4/r32/esp
19802     # . save registers
19803     51/push-ecx
19804     # var out/ecx: (handle typeinfo)
19805     68/push 0/imm32
19806     68/push 0/imm32
19807     89/<- %ecx 4/r32/esp
19808     # eax = t
19809     8b/-> *(ebp+8) 0/r32/eax
19810     # if t is a literal, return 0
19811     3d/compare-eax-and 0/imm32/literal
19812     0f 84/jump-if-= $compute-size-of-type-id:end/disp32  # eax changes type from type-id to int
19813     # if t is a byte, return 4 (because we don't really support non-multiples of 4)
19814     3d/compare-eax-and 8/imm32/byte
19815     {
19816       75/jump-if-!= break/disp8
19817       b8/copy-to-eax 4/imm32
19818       eb/jump $compute-size-of-type-id:end/disp8
19819     }
19820     # if t is a handle, return 8
19821     3d/compare-eax-and 4/imm32/handle
19822     {
19823       75/jump-if-!= break/disp8
19824       b8/copy-to-eax 8/imm32
19825       eb/jump $compute-size-of-type-id:end/disp8  # eax changes type from type-id to int
19826     }
19827     # if t is a slice, return 8
19828     3d/compare-eax-and 0xc/imm32/slice
19829     {
19830       75/jump-if-!= break/disp8
19831       b8/copy-to-eax 8/imm32
19832       eb/jump $compute-size-of-type-id:end/disp8  # eax changes type from type-id to int
19833     }
19834     # if t is a user-defined type, compute its size
19835     # TODO: support non-atom type
19836     (find-typeinfo %eax %ecx)
19837     {
19838       81 7/subop/compare *ecx 0/imm32
19839       74/jump-if-= break/disp8
19840 $compute-size-of-type-id:user-defined:
19841       (lookup *ecx *(ecx+4))  # => eax
19842       (populate-mu-type-sizes-in-type %eax *(ebp+0xc) *(ebp+0x10))
19843       8b/-> *(eax+0xc) 0/r32/eax  # Typeinfo-total-size-in-bytes
19844       eb/jump $compute-size-of-type-id:end/disp8
19845     }
19846     # otherwise return the word size
19847     b8/copy-to-eax 4/imm32
19848 $compute-size-of-type-id:end:
19849     # . reclaim locals
19850     81 0/subop/add %esp 8/imm32
19851     # . restore registers
19852     59/pop-to-ecx
19853     # . epilogue
19854     89/<- %esp 5/r32/ebp
19855     5d/pop-to-ebp
19856     c3/return
19857 
19858 # at this point we have total sizes for all user-defined types
19859 # compute offsets for each element
19860 # complication: fields may be out of order
19861 populate-mu-type-offsets:  # in: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
19862     # . prologue
19863     55/push-ebp
19864     89/<- %ebp 4/r32/esp
19865     # . save registers
19866     50/push-eax
19867     51/push-ecx
19868     52/push-edx
19869     53/push-ebx
19870     56/push-esi
19871     57/push-edi
19872 #?     (dump-typeinfos "aaa\n")
19873     # var curr-offset/edi: int = 0
19874     bf/copy-to-edi 0/imm32
19875     # var table/ecx: (addr table string_key (handle typeinfo-entry)) = lookup(in->fields)
19876     8b/-> *(ebp+8) 1/r32/ecx
19877     (lookup *(ecx+4) *(ecx+8))  # Typeinfo-fields Typeinfo-fields => eax
19878     89/<- %ecx 0/r32/eax
19879     # var num-elems/edx: int = table->write / Typeinfo-fields-row-size
19880     8b/-> *ecx 2/r32/edx  # stream-write
19881     c1 5/subop/shift-right-logical  %edx 4/imm8
19882     # var i/ebx: int = 0
19883     bb/copy-to-ebx 0/imm32
19884     {
19885 $populate-mu-type-offsets:loop:
19886       39/compare %ebx 2/r32/edx
19887       0f 8d/jump-if->= break/disp32
19888 #?       (write-buffered Stderr "looking up index ")
19889 #?       (write-int32-hex-buffered Stderr %ebx)
19890 #?       (write-buffered Stderr " in ")
19891 #?       (write-int32-hex-buffered Stderr *(ebp+8))
19892 #?       (write-buffered Stderr Newline)
19893 #?       (flush Stderr)
19894       # var v/esi: (addr typeinfo-entry)
19895       (locate-typeinfo-entry-with-index %ecx %ebx *(ebp+0xc) *(ebp+0x10))  # => eax
19896       89/<- %esi 0/r32/eax
19897       # if v is null, silently move on; we'll emit a nice error message while type-checking
19898       81 7/subop/compare %esi 0/imm32  # Typeinfo-entry-input-var
19899       74/jump-if-= $populate-mu-type-offsets:end/disp8
19900       # if (v->input-var == 0) silently ignore v; we'll emit a nice error message while type-checking
19901       81 7/subop/compare *esi 0/imm32  # Typeinfo-entry-input-var
19902       74/jump-if-= $populate-mu-type-offsets:end/disp8
19903       # v->output-var->offset = curr-offset
19904       # . eax: (addr var)
19905       (lookup *(esi+0xc) *(esi+0x10))  # Typeinfo-entry-output-var Typeinfo-entry-output-var => eax
19906       89/<- *(eax+0x14) 7/r32/edi  # Var-offset
19907       # curr-offset += size-of(v->input-var)
19908       (lookup *esi *(esi+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
19909       (size-of %eax)  # => eax
19910       01/add-to %edi 0/r32/eax
19911       # ++i
19912       43/increment-ebx
19913       e9/jump loop/disp32
19914     }
19915 $populate-mu-type-offsets:end:
19916     # . restore registers
19917     5f/pop-to-edi
19918     5e/pop-to-esi
19919     5b/pop-to-ebx
19920     5a/pop-to-edx
19921     59/pop-to-ecx
19922     58/pop-to-eax
19923     # . epilogue
19924     89/<- %esp 5/r32/ebp
19925     5d/pop-to-ebp
19926     c3/return
19927 
19928 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)
19929     # . prologue
19930     55/push-ebp
19931     89/<- %ebp 4/r32/esp
19932     # . save registers
19933     51/push-ecx
19934     52/push-edx
19935     53/push-ebx
19936     56/push-esi
19937     57/push-edi
19938     # esi = table
19939     8b/-> *(ebp+8) 6/r32/esi
19940     # var curr/ecx: (addr row (handle array byte) (handle typeinfo-entry)) = table->data
19941     8d/copy-address *(esi+0xc) 1/r32/ecx
19942     # var max/edx: (addr byte) = &table->data[table->write]
19943     8b/-> *esi 2/r32/edx
19944     8d/copy-address *(ecx+edx) 2/r32/edx
19945     {
19946 $locate-typeinfo-entry-with-index:loop:
19947       39/compare %ecx 2/r32/edx
19948       73/jump-if-addr>= break/disp8
19949       # var v/eax: (addr typeinfo-entry)
19950       (lookup *(ecx+8) *(ecx+0xc))  # => eax
19951       # if (v->index == idx) return v
19952       8b/-> *(eax+8) 3/r32/ebx  # Typeinfo-entry-index
19953 #?       (write-buffered Stderr "comparing ")
19954 #?       (write-int32-hex-buffered Stderr %ebx)
19955 #?       (write-buffered Stderr " and ")
19956 #?       (write-int32-hex-buffered Stderr *(ebp+0xc))
19957 #?       (write-buffered Stderr Newline)
19958 #?       (flush Stderr)
19959       39/compare *(ebp+0xc) 3/r32/ebx
19960       74/jump-if-= $locate-typeinfo-entry-with-index:end/disp8
19961       # curr += Typeinfo-entry-size
19962       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-entry-size
19963       #
19964       eb/jump loop/disp8
19965     }
19966     # return 0
19967     b8/copy-to-eax 0/imm32
19968 $locate-typeinfo-entry-with-index:end:
19969 #?     (write-buffered Stderr "returning ")
19970 #?     (write-int32-hex-buffered Stderr %eax)
19971 #?     (write-buffered Stderr Newline)
19972 #?     (flush Stderr)
19973     # . restore registers
19974     5f/pop-to-edi
19975     5e/pop-to-esi
19976     5b/pop-to-ebx
19977     5a/pop-to-edx
19978     59/pop-to-ecx
19979     # . epilogue
19980     89/<- %esp 5/r32/ebp
19981     5d/pop-to-ebp
19982     c3/return
19983 
19984 dump-typeinfos:  # hdr: (addr array byte)
19985     # . prologue
19986     55/push-ebp
19987     89/<- %ebp 4/r32/esp
19988     # . save registers
19989     50/push-eax
19990     #
19991     (write-buffered Stderr *(ebp+8))
19992     (flush Stderr)
19993     # var curr/eax: (addr typeinfo) = lookup(Program->types)
19994     (lookup *_Program-types *_Program-types->payload)  # => eax
19995     {
19996       # if (curr == null) break
19997       3d/compare-eax-and 0/imm32
19998       74/jump-if-= break/disp8
19999       (write-buffered Stderr "---\n")
20000       (flush Stderr)
20001       (dump-typeinfo %eax)
20002       # curr = lookup(curr->next)
20003       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
20004       eb/jump loop/disp8
20005     }
20006 $dump-typeinfos:end:
20007     # . restore registers
20008     58/pop-to-eax
20009     # . epilogue
20010     89/<- %esp 5/r32/ebp
20011     5d/pop-to-ebp
20012     c3/return
20013 
20014 dump-typeinfo:  # in: (addr typeinfo)
20015     # . prologue
20016     55/push-ebp
20017     89/<- %ebp 4/r32/esp
20018     # . save registers
20019     50/push-eax
20020     51/push-ecx
20021     52/push-edx
20022     53/push-ebx
20023     56/push-esi
20024     57/push-edi
20025     # esi = in
20026     8b/-> *(ebp+8) 6/r32/esi
20027     # var table/ecx: (addr table (handle array byte) (handle typeinfo-entry)) = lookup(T->fields)
20028     (lookup *(esi+4) *(esi+8))  # Typeinfo-fields Typeinfo-fields => eax
20029     89/<- %ecx 0/r32/eax
20030     (write-buffered Stderr "id:")
20031     (write-int32-hex-buffered Stderr *esi)
20032     (write-buffered Stderr "\n")
20033     (write-buffered Stderr "fields @ ")
20034     (write-int32-hex-buffered Stderr %ecx)
20035     (write-buffered Stderr Newline)
20036     (flush Stderr)
20037     (write-buffered Stderr "  write: ")
20038     (write-int32-hex-buffered Stderr *ecx)
20039     (write-buffered Stderr Newline)
20040     (flush Stderr)
20041     (write-buffered Stderr "  read: ")
20042     (write-int32-hex-buffered Stderr *(ecx+4))
20043     (write-buffered Stderr Newline)
20044     (flush Stderr)
20045     (write-buffered Stderr "  size: ")
20046     (write-int32-hex-buffered Stderr *(ecx+8))
20047     (write-buffered Stderr Newline)
20048     (flush Stderr)
20049     # var table-size/edx: int = table->write
20050     8b/-> *ecx 2/r32/edx  # stream-write
20051     # var curr/ecx: (addr table_row) = table->data
20052     8d/copy-address *(ecx+0xc) 1/r32/ecx
20053     # var max/edx: (addr table_row) = table->data + table->write
20054     8d/copy-address *(ecx+edx) 2/r32/edx
20055     {
20056 $dump-typeinfo:loop:
20057       # if (curr >= max) break
20058       39/compare %ecx 2/r32/edx
20059       0f 83/jump-if-addr>= break/disp32
20060       (write-buffered Stderr "  row:\n")
20061       (write-buffered Stderr "    key: ")
20062       (write-int32-hex-buffered Stderr *ecx)
20063       (write-buffered Stderr ",")
20064       (write-int32-hex-buffered Stderr *(ecx+4))
20065       (write-buffered Stderr " = '")
20066       (lookup *ecx *(ecx+4))
20067       (write-buffered Stderr %eax)
20068       (write-buffered Stderr "' @ ")
20069       (write-int32-hex-buffered Stderr %eax)
20070       (write-buffered Stderr Newline)
20071       (flush Stderr)
20072       (write-buffered Stderr "    value: ")
20073       (write-int32-hex-buffered Stderr *(ecx+8))
20074       (write-buffered Stderr ",")
20075       (write-int32-hex-buffered Stderr *(ecx+0xc))
20076       (write-buffered Stderr " = typeinfo-entry@")
20077       (lookup *(ecx+8) *(ecx+0xc))
20078       (write-int32-hex-buffered Stderr %eax)
20079       (write-buffered Stderr Newline)
20080       (flush Stderr)
20081       (write-buffered Stderr "        input var@")
20082       (dump-var 5 %eax)
20083       (lookup *(ecx+8) *(ecx+0xc))
20084       (write-buffered Stderr "        index: ")
20085       (write-int32-hex-buffered Stderr *(eax+8))
20086       (write-buffered Stderr Newline)
20087       (flush Stderr)
20088       (write-buffered Stderr "        output var@")
20089       8d/copy-address *(eax+0xc) 0/r32/eax  # Typeinfo-entry-output-var
20090       (dump-var 5 %eax)
20091       (flush Stderr)
20092       # curr += row-size
20093       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-fields-row-size
20094       #
20095       e9/jump loop/disp32
20096     }
20097 $dump-typeinfo:end:
20098     # . restore registers
20099     5f/pop-to-edi
20100     5e/pop-to-esi
20101     5b/pop-to-ebx
20102     5a/pop-to-edx
20103     59/pop-to-ecx
20104     58/pop-to-eax
20105     # . epilogue
20106     89/<- %esp 5/r32/ebp
20107     5d/pop-to-ebp
20108     c3/return
20109 
20110 dump-var:  # indent: int, v: (addr handle var)
20111     # . prologue
20112     55/push-ebp
20113     89/<- %ebp 4/r32/esp
20114     # . save registers
20115     50/push-eax
20116     53/push-ebx
20117     # eax = v
20118     8b/-> *(ebp+0xc) 0/r32/eax
20119     #
20120     (write-int32-hex-buffered Stderr *eax)
20121     (write-buffered Stderr ",")
20122     (write-int32-hex-buffered Stderr *(eax+4))
20123     (write-buffered Stderr "->")
20124     (lookup *eax *(eax+4))
20125     (write-int32-hex-buffered Stderr %eax)
20126     (write-buffered Stderr Newline)
20127     (flush Stderr)
20128     {
20129       3d/compare-eax-and 0/imm32
20130       0f 84/jump-if-= break/disp32
20131       (emit-indent Stderr *(ebp+8))
20132       (write-buffered Stderr "name: ")
20133       89/<- %ebx 0/r32/eax
20134       (write-int32-hex-buffered Stderr *ebx)  # Var-name
20135       (write-buffered Stderr ",")
20136       (write-int32-hex-buffered Stderr *(ebx+4))  # Var-name
20137       (write-buffered Stderr "->")
20138       (lookup *ebx *(ebx+4))  # Var-name
20139       (write-int32-hex-buffered Stderr %eax)
20140       {
20141         3d/compare-eax-and 0/imm32
20142         74/jump-if-= break/disp8
20143         (write-buffered Stderr Space)
20144         (write-buffered Stderr %eax)
20145       }
20146       (write-buffered Stderr Newline)
20147       (flush Stderr)
20148       (emit-indent Stderr *(ebp+8))
20149       (write-buffered Stderr "block depth: ")
20150       (write-int32-hex-buffered Stderr *(ebx+0x10))  # Var-block-depth
20151       (write-buffered Stderr Newline)
20152       (flush Stderr)
20153       (emit-indent Stderr *(ebp+8))
20154       (write-buffered Stderr "stack offset: ")
20155       (write-int32-hex-buffered Stderr *(ebx+0x14))  # Var-offset
20156       (write-buffered Stderr Newline)
20157       (flush Stderr)
20158       (emit-indent Stderr *(ebp+8))
20159       (write-buffered Stderr "reg: ")
20160       (write-int32-hex-buffered Stderr *(ebx+0x18))  # Var-register
20161       (write-buffered Stderr ",")
20162       (write-int32-hex-buffered Stderr *(ebx+0x1c))  # Var-register
20163       (write-buffered Stderr "->")
20164       (flush Stderr)
20165       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register
20166       (write-int32-hex-buffered Stderr %eax)
20167       {
20168         3d/compare-eax-and 0/imm32
20169         74/jump-if-= break/disp8
20170         (write-buffered Stderr Space)
20171         (write-buffered Stderr %eax)
20172       }
20173       (write-buffered Stderr Newline)
20174       (flush Stderr)
20175     }
20176 $dump-var:end:
20177     # . restore registers
20178     5b/pop-to-ebx
20179     58/pop-to-eax
20180     # . epilogue
20181     89/<- %esp 5/r32/ebp
20182     5d/pop-to-ebp
20183     c3/return
20184 
20185 #######################################################
20186 # Type-checking
20187 #######################################################
20188 
20189 check-mu-types:  # err: (addr buffered-file), ed: (addr exit-descriptor)
20190     # . prologue
20191     55/push-ebp
20192     89/<- %ebp 4/r32/esp
20193     # . save registers
20194     50/push-eax
20195     # var curr/eax: (addr function) = lookup(Program->functions)
20196     (lookup *_Program-functions *_Program-functions->payload)  # => eax
20197     {
20198 $check-mu-types:loop:
20199       # if (curr == null) break
20200       3d/compare-eax-and 0/imm32
20201       0f 84/jump-if-= break/disp32
20202 +--  8 lines: #?       # dump curr->name ----------------------------------------------------------------------------------------------------------------------------------------------
20210       (check-mu-function %eax *(ebp+8) *(ebp+0xc))
20211       # curr = lookup(curr->next)
20212       (lookup *(eax+0x20) *(eax+0x24))  # Function-next Function-next => eax
20213       e9/jump loop/disp32
20214     }
20215 $check-mu-types:end:
20216     # . restore registers
20217     58/pop-to-eax
20218     # . epilogue
20219     89/<- %esp 5/r32/ebp
20220     5d/pop-to-ebp
20221     c3/return
20222 
20223 check-mu-function:  # fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
20224     # . prologue
20225     55/push-ebp
20226     89/<- %ebp 4/r32/esp
20227     # . save registers
20228     50/push-eax
20229     56/push-esi
20230     # esi = f
20231     8b/-> *(ebp+8) 6/r32/esi
20232     # outputs
20233     (lookup *(esi+0x10) *(esi+0x14))  # Function-outputs Function-outputs => eax
20234     (check-all-unique-registers %eax %esi *(ebp+0xc) *(ebp+0x10))
20235     # body
20236     (lookup *(esi+0x18) *(esi+0x1c))  # Function-body Function-body => eax
20237     (check-mu-block %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10))
20238     # if function has no outputs, we're done
20239     81 7/subop/compare *(esi+0x10) 0/imm32
20240     74/jump-if-= $check-mu-function:end/disp8
20241     # some final checks on body
20242     (check-final-stmt-is-return %eax %esi *(ebp+0xc) *(ebp+0x10))
20243     (check-no-breaks %eax %esi *(ebp+0xc) *(ebp+0x10))
20244 $check-mu-function:end:
20245     # . restore registers
20246     5e/pop-to-esi
20247     58/pop-to-eax
20248     # . epilogue
20249     89/<- %esp 5/r32/ebp
20250     5d/pop-to-ebp
20251     c3/return
20252 
20253 check-mu-block:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
20254     # . prologue
20255     55/push-ebp
20256     89/<- %ebp 4/r32/esp
20257     # . save registers
20258     50/push-eax
20259     # eax = block
20260     8b/-> *(ebp+8) 0/r32/eax
20261     # var stmts/eax: (addr list stmt) = lookup(block->statements)
20262     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
20263     #
20264     {
20265 $check-mu-block:check-empty:
20266       3d/compare-eax-and 0/imm32
20267       0f 84/jump-if-= break/disp32
20268       # emit block->statements
20269       (check-mu-stmt-list %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20270     }
20271 $check-mu-block:end:
20272     # . restore registers
20273     58/pop-to-eax
20274     # . epilogue
20275     89/<- %esp 5/r32/ebp
20276     5d/pop-to-ebp
20277     c3/return
20278 
20279 check-mu-stmt-list:  # stmts: (addr list stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
20280     # . prologue
20281     55/push-ebp
20282     89/<- %ebp 4/r32/esp
20283     # . save registers
20284     50/push-eax
20285     56/push-esi
20286     # esi = stmts
20287     8b/-> *(ebp+8) 6/r32/esi
20288     {
20289 $check-mu-stmt-list:loop:
20290       81 7/subop/compare %esi 0/imm32
20291       0f 84/jump-if-= break/disp32
20292       # var curr-stmt/eax: (addr stmt) = lookup(stmts->value)
20293       (lookup *esi *(esi+4))  # List-value List-value => eax
20294       {
20295 $check-mu-stmt-list:check-for-block:
20296         81 7/subop/compare *eax 0/imm32/block  # Stmt-tag
20297         75/jump-if-!= break/disp8
20298 $check-mu-stmt-list:block:
20299         (check-mu-block %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20300         eb/jump $check-mu-stmt-list:continue/disp8
20301       }
20302       {
20303 $check-mu-stmt-list:check-for-stmt1:
20304         81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
20305         0f 85/jump-if-!= break/disp32
20306 $check-mu-stmt-list:stmt1:
20307         (check-mu-stmt %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20308         eb/jump $check-mu-stmt-list:continue/disp8
20309       }
20310       {
20311 $check-mu-stmt-list:check-for-reg-var-def:
20312         81 7/subop/compare *eax 3/imm32/reg-var-def  # Stmt-tag
20313         0f 85/jump-if-!= break/disp32
20314 $check-mu-stmt-list:reg-var-def:
20315         (check-mu-stmt %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20316         eb/jump $check-mu-stmt-list:continue/disp8
20317       }
20318 $check-mu-stmt-list:continue:
20319       # TODO: raise an error on unrecognized Stmt-tag
20320       (lookup *(esi+8) *(esi+0xc))  # List-next List-next => eax
20321       89/<- %esi 0/r32/eax
20322       e9/jump loop/disp32
20323     }
20324 $check-mu-stmt-list:end:
20325     # . restore registers
20326     5e/pop-to-esi
20327     58/pop-to-eax
20328     # . epilogue
20329     89/<- %esp 5/r32/ebp
20330     5d/pop-to-ebp
20331     c3/return
20332 
20333 check-mu-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
20334     # . prologue
20335     55/push-ebp
20336     89/<- %ebp 4/r32/esp
20337     # . save registers
20338     50/push-eax
20339     # - if stmt's operation matches a primitive, check against it
20340     (has-primitive-name? *(ebp+8))  # => eax
20341     3d/compare-eax-and 0/imm32/false
20342     {
20343       74/jump-if-= break/disp8
20344       (check-mu-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20345       e9/jump $check-mu-stmt:end/disp32
20346     }
20347     # - otherwise find a function to check against
20348     # var f/eax: (addr function) = lookup(*Program->functions)
20349     (lookup *_Program-functions *_Program-functions->payload)  # => eax
20350     (find-matching-function %eax *(ebp+8))  # => eax
20351     3d/compare-eax-and 0/imm32
20352     {
20353       74/jump-if-= break/disp8
20354       (check-mu-call *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20355       eb/jump $check-mu-stmt:end/disp8
20356     }
20357     # var f/eax: (addr function) = lookup(*Program->signatures)
20358     (lookup *_Program-signatures *_Program-signatures->payload)  # => eax
20359     (find-matching-function %eax *(ebp+8))  # => eax
20360     3d/compare-eax-and 0/imm32
20361     {
20362       74/jump-if-= break/disp8
20363       (check-mu-call *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20364       eb/jump $check-mu-stmt:end/disp8
20365     }
20366     # - otherwise abort
20367     e9/jump $check-mu-stmt:unknown-call/disp32
20368 $check-mu-stmt:end:
20369     # . restore registers
20370     58/pop-to-eax
20371     # . epilogue
20372     89/<- %esp 5/r32/ebp
20373     5d/pop-to-ebp
20374     c3/return
20375 
20376 $check-mu-stmt:unknown-call:
20377     (write-buffered *(ebp+0x10) "unknown function '")
20378     8b/-> *(ebp+8) 0/r32/eax
20379     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
20380     (write-buffered *(ebp+0x10) %eax)
20381     (write-buffered *(ebp+0x10) "'\n")
20382     (flush *(ebp+0x10))
20383     (stop *(ebp+0x14) 1)
20384     # never gets here
20385 
20386 has-primitive-name?:  # stmt: (addr stmt) -> result/eax: boolean
20387     # . prologue
20388     55/push-ebp
20389     89/<- %ebp 4/r32/esp
20390     # . save registers
20391     51/push-ecx
20392     56/push-esi
20393     # var name/esi: (addr array byte) = lookup(stmt->operation)
20394     8b/-> *(ebp+8) 6/r32/esi
20395     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
20396     89/<- %esi 0/r32/eax
20397     # if (name == "return") return true
20398     (string-equal? %esi "return")  # => eax
20399     3d/compare-eax-and 0/imm32/false
20400     0f 85/jump-if-!= $has-primitive-name?:end/disp32
20401     # if (name == "get") return true
20402     (string-equal? %esi "get")  # => eax
20403     3d/compare-eax-and 0/imm32/false
20404     0f 85/jump-if-!= $has-primitive-name?:end/disp32
20405     # if (name == "index") return true
20406     (string-equal? %esi "index")  # => eax
20407     3d/compare-eax-and 0/imm32/false
20408     0f 85/jump-if-!= $has-primitive-name?:end/disp32
20409     # if (name == "length") return true
20410     (string-equal? %esi "length")  # => eax
20411     3d/compare-eax-and 0/imm32/false
20412     0f 85/jump-if-!= $has-primitive-name?:end/disp32
20413     # if (name == "compute-offset") return true
20414     (string-equal? %esi "compute-offset")  # => eax
20415     3d/compare-eax-and 0/imm32/false
20416     0f 85/jump-if-!= $has-primitive-name?:end/disp32
20417     # if (name == "copy-object") return true
20418     (string-equal? %esi "copy-object")  # => eax
20419     3d/compare-eax-and 0/imm32/false
20420     0f 85/jump-if-!= $has-primitive-name?:end/disp32
20421     # if (name == "clear-object") return true
20422     (string-equal? %esi "clear-object")  # => eax
20423     3d/compare-eax-and 0/imm32/false
20424     0f 85/jump-if-!= $has-primitive-name?:end/disp32
20425     # if (name == "allocate") return true
20426     (string-equal? %esi "allocate")  # => eax
20427     3d/compare-eax-and 0/imm32/false
20428     0f 85/jump-if-!= $has-primitive-name?:end/disp32
20429     # if (name == "populate") return true
20430     (string-equal? %esi "populate")  # => eax
20431     3d/compare-eax-and 0/imm32/false
20432     0f 85/jump-if-!= $has-primitive-name?:end/disp32
20433     # if (name == "populate-stream") return true
20434     (string-equal? %esi "populate-stream")  # => eax
20435     3d/compare-eax-and 0/imm32/false
20436     0f 85/jump-if-!= $has-primitive-name?:end/disp32
20437     # if (name == "read-from-stream") return true
20438     (string-equal? %esi "read-from-stream")  # => eax
20439     3d/compare-eax-and 0/imm32/false
20440     0f 85/jump-if-!= $has-primitive-name?:end/disp32
20441     # if (name == "write-to-stream") return true
20442     (string-equal? %esi "write-to-stream")  # => eax
20443     3d/compare-eax-and 0/imm32/false
20444     0f 85/jump-if-!= $has-primitive-name?:end/disp32
20445     # var curr/ecx: (addr primitive) = Primitives
20446     b9/copy-to-ecx Primitives/imm32
20447     {
20448 $has-primitive-name?:loop:
20449       # if (curr == null) break
20450       81 7/subop/compare %ecx 0/imm32
20451       74/jump-if-= break/disp8
20452       # if (primitive->name == name) return true
20453       (lookup *ecx *(ecx+4))  # Primitive-name Primitive-name => eax
20454 #?       (write-buffered Stderr %eax)
20455 #?       (write-buffered Stderr Newline)
20456 #?       (flush Stderr)
20457       (string-equal? %esi %eax)  # => eax
20458       3d/compare-eax-and 0/imm32/false
20459       75/jump-if-!= $has-primitive-name?:end/disp8
20460 $has-primitive-name?:next-primitive:
20461       # curr = curr->next
20462       (lookup *(ecx+0x3c) *(ecx+0x40))  # Primitive-next Primitive-next => eax
20463       89/<- %ecx 0/r32/eax
20464       #
20465       e9/jump loop/disp32
20466     }
20467     # return null
20468     b8/copy-to-eax 0/imm32
20469 $has-primitive-name?:end:
20470     # . restore registers
20471     5e/pop-to-esi
20472     59/pop-to-ecx
20473     # . epilogue
20474     89/<- %esp 5/r32/ebp
20475     5d/pop-to-ebp
20476     c3/return
20477 
20478 check-mu-primitive:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
20479     # . prologue
20480     55/push-ebp
20481     89/<- %ebp 4/r32/esp
20482     # . save registers
20483     50/push-eax
20484     51/push-ecx
20485     # var op/ecx: (addr array byte) = lookup(stmt->operation)
20486     8b/-> *(ebp+8) 0/r32/eax
20487     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
20488     89/<- %ecx 0/r32/eax
20489     # if (op == "copy") check-mu-copy-stmt
20490     {
20491       (string-equal? %ecx "copy")  # => eax
20492       3d/compare-eax-and 0/imm32/false
20493       74/jump-if-= break/disp8
20494       (check-mu-copy-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20495       e9/jump $check-mu-primitive:end/disp32
20496     }
20497     # if (op == "copy-to") check-mu-copy-to-stmt
20498     {
20499       (string-equal? %ecx "copy-to")  # => eax
20500       3d/compare-eax-and 0/imm32/false
20501       74/jump-if-= break/disp8
20502       (check-mu-copy-to-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20503       e9/jump $check-mu-primitive:end/disp32
20504     }
20505     # if (op == "compare") check-mu-compare-stmt
20506     {
20507       (string-equal? %ecx "compare")  # => eax
20508       3d/compare-eax-and 0/imm32/false
20509       74/jump-if-= break/disp8
20510       (check-mu-compare-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20511       e9/jump $check-mu-primitive:end/disp32
20512     }
20513     # if (op == "address") check-mu-address-stmt
20514     {
20515       (string-equal? %ecx "address")  # => eax
20516       3d/compare-eax-and 0/imm32/false
20517       74/jump-if-= break/disp8
20518       (check-mu-address-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20519       e9/jump $check-mu-primitive:end/disp32
20520     }
20521     # if (op == "return") check-mu-return-stmt
20522     {
20523       (string-equal? %ecx "return")  # => eax
20524       3d/compare-eax-and 0/imm32/false
20525       74/jump-if-= break/disp8
20526       (check-mu-return-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20527       e9/jump $check-mu-primitive:end/disp32
20528     }
20529     # if (op == "get") check-mu-get-stmt
20530     {
20531       (string-equal? %ecx "get")  # => eax
20532       3d/compare-eax-and 0/imm32/false
20533       74/jump-if-= break/disp8
20534       (check-mu-get-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20535       e9/jump $check-mu-primitive:end/disp32
20536     }
20537     # if (op == "index") check-mu-index-stmt
20538     {
20539       (string-equal? %ecx "index")  # => eax
20540       3d/compare-eax-and 0/imm32/false
20541       74/jump-if-= break/disp8
20542       (check-mu-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20543       e9/jump $check-mu-primitive:end/disp32
20544     }
20545     # if (op == "length") check-mu-length-stmt
20546     {
20547       (string-equal? %ecx "length")  # => eax
20548       3d/compare-eax-and 0/imm32/false
20549       74/jump-if-= break/disp8
20550       (check-mu-length-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20551       e9/jump $check-mu-primitive:end/disp32
20552     }
20553     # if (op == "compute-offset") check-mu-compute-offset-stmt
20554     {
20555       (string-equal? %ecx "compute-offset")  # => eax
20556       3d/compare-eax-and 0/imm32/false
20557       74/jump-if-= break/disp8
20558       (check-mu-compute-offset-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20559       e9/jump $check-mu-primitive:end/disp32
20560     }
20561     # if (op == "copy-object") check-mu-copy-object-stmt
20562     {
20563       (string-equal? %ecx "copy-object")  # => eax
20564       3d/compare-eax-and 0/imm32/false
20565       74/jump-if-= break/disp8
20566       (check-mu-copy-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20567       e9/jump $check-mu-primitive:end/disp32
20568     }
20569     # if (op == "clear-object") check-mu-clear-object-stmt
20570     {
20571       (string-equal? %ecx "clear-object")  # => eax
20572       3d/compare-eax-and 0/imm32/false
20573       74/jump-if-= break/disp8
20574       (check-mu-clear-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20575       e9/jump $check-mu-primitive:end/disp32
20576     }
20577     # if (op == "allocate") check-mu-allocate-stmt
20578     {
20579       (string-equal? %ecx "allocate")  # => eax
20580       3d/compare-eax-and 0/imm32/false
20581       74/jump-if-= break/disp8
20582       (check-mu-allocate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20583       e9/jump $check-mu-primitive:end/disp32
20584     }
20585     # if (op == "populate") check-mu-populate-stmt
20586     {
20587       (string-equal? %ecx "populate")  # => eax
20588       3d/compare-eax-and 0/imm32/false
20589       74/jump-if-= break/disp8
20590       (check-mu-populate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20591       e9/jump $check-mu-primitive:end/disp32
20592     }
20593     # if (op == "populate-stream") check-mu-populate-stream-stmt
20594     {
20595       (string-equal? %ecx "populate-stream")  # => eax
20596       3d/compare-eax-and 0/imm32/false
20597       74/jump-if-= break/disp8
20598       (check-mu-populate-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20599       e9/jump $check-mu-primitive:end/disp32
20600     }
20601     # if (op == "read-from-stream") check-mu-read-from-stream-stmt
20602     {
20603       (string-equal? %ecx "read-from-stream")  # => eax
20604       3d/compare-eax-and 0/imm32/false
20605       74/jump-if-= break/disp8
20606       (check-mu-read-from-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20607       e9/jump $check-mu-primitive:end/disp32
20608     }
20609     # if (op == "write-to-stream") check-mu-write-to-stream-stmt
20610     {
20611       (string-equal? %ecx "write-to-stream")  # => eax
20612       3d/compare-eax-and 0/imm32/false
20613       74/jump-if-= break/disp8
20614       (check-mu-write-to-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20615       e9/jump $check-mu-primitive:end/disp32
20616     }
20617     # if (op == "convert") check-mu-convert-stmt
20618     {
20619       (string-equal? %ecx "convert")  # => eax
20620       3d/compare-eax-and 0/imm32/false
20621       74/jump-if-= break/disp8
20622       (check-mu-convert-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20623       e9/jump $check-mu-primitive:end/disp32
20624     }
20625     # otherwise check-numberlike-stmt
20626     (check-mu-numberlike-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20627 $check-mu-primitive:end:
20628     # . restore registers
20629     59/pop-to-ecx
20630     58/pop-to-eax
20631     # . epilogue
20632     89/<- %esp 5/r32/ebp
20633     5d/pop-to-ebp
20634     c3/return
20635 
20636 # by default, Mu primitives should only operate on 'number-like' types
20637 check-mu-numberlike-primitive:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
20638     # . prologue
20639     55/push-ebp
20640     89/<- %ebp 4/r32/esp
20641     # . save registers
20642     50/push-eax
20643     51/push-ecx
20644     56/push-esi
20645     # esi = stmt
20646     8b/-> *(ebp+8) 6/r32/esi
20647     # var gas/ecx: int = 2
20648     b9/copy-to-ecx 2/imm32
20649     # - check at most 1 output
20650     # var output/eax: (addr stmt-var) = stmt->outputs
20651     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
20652     {
20653       3d/compare-eax-and 0/imm32
20654       74/jump-if-= break/disp8
20655 $check-mu-numberlike-primitive:output:
20656       (check-mu-numberlike-output %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20657       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
20658       3d/compare-eax-and 0/imm32
20659       0f 85/jump-if-!= $check-mu-numberlike-primitive:error-too-many-outputs/disp32
20660       # check output is in a register
20661       # --gas
20662       49/decrement-ecx
20663     }
20664     # - check first inout
20665     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
20666     {
20667       3d/compare-eax-and 0/imm32
20668       0f 84/jump-if-= $check-mu-numberlike-primitive:end/disp32
20669 $check-mu-numberlike-primitive:first-inout:
20670       (check-mu-numberlike-arg %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20671       # --gas
20672       49/decrement-ecx
20673     }
20674     # - check second inout
20675     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
20676     {
20677       3d/compare-eax-and 0/imm32
20678       74/jump-if-= $check-mu-numberlike-primitive:end/disp8
20679 $check-mu-numberlike-primitive:second-inout:
20680       # is a second inout allowed?
20681       81 7/subop/compare %ecx 0/imm32
20682       0f 84/jump-if-= $check-mu-numberlike-primitive:error-too-many-inouts/disp32
20683 $check-mu-numberlike-primitive:second-inout-permitted:
20684       (check-mu-numberlike-arg %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20685     }
20686 $check-mu-numberlike-primitive:third-inout:
20687     # if there's a third arg, raise an error
20688     81 7/subop/compare *(eax+8) 0/imm32  # Stmt-var-next
20689     0f 85/jump-if-!= $check-mu-numberlike-primitive:error-too-many-inouts/disp32
20690 $check-mu-numberlike-primitive:end:
20691     # . restore registers
20692     5e/pop-to-esi
20693     59/pop-to-ecx
20694     58/pop-to-eax
20695     # . epilogue
20696     89/<- %esp 5/r32/ebp
20697     5d/pop-to-ebp
20698     c3/return
20699 
20700 $check-mu-numberlike-primitive:error-too-many-inouts:
20701     (write-buffered *(ebp+0x10) "fn ")
20702     8b/-> *(ebp+0xc) 0/r32/eax
20703     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20704     (write-buffered *(ebp+0x10) %eax)
20705     (write-buffered *(ebp+0x10) ": stmt ")
20706     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
20707     (write-buffered *(ebp+0x10) %eax)
20708     (write-buffered *(ebp+0x10) ": too many inouts; most primitives support at most two arguments, across inouts and outputs\n")
20709     (flush *(ebp+0x10))
20710     (stop *(ebp+0x14) 1)
20711     # never gets here
20712 
20713 $check-mu-numberlike-primitive:error-too-many-outputs:
20714     (write-buffered *(ebp+0x10) "fn ")
20715     8b/-> *(ebp+0xc) 0/r32/eax
20716     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20717     (write-buffered *(ebp+0x10) %eax)
20718     (write-buffered *(ebp+0x10) ": stmt ")
20719     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
20720     (write-buffered *(ebp+0x10) %eax)
20721     (write-buffered *(ebp+0x10) ": too many outputs; most primitives support at most one output\n")
20722     (flush *(ebp+0x10))
20723     (stop *(ebp+0x14) 1)
20724     # never gets here
20725 
20726 check-mu-numberlike-arg:  # v: (addr stmt-var), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
20727     # . prologue
20728     55/push-ebp
20729     89/<- %ebp 4/r32/esp
20730     # . save registers
20731     50/push-eax
20732     56/push-esi
20733     # var t/esi: (addr type-tree) = lookup(v->value->type)
20734     8b/-> *(ebp+8) 0/r32/eax
20735     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
20736     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20737     89/<- %esi 0/r32/eax
20738 $check-mu-numberlike-arg:check-literal:
20739     # if t is an int, return
20740     (is-simple-mu-type? %esi 0)  # literal => eax
20741     3d/compare-eax-and 0/imm32/false
20742     0f 85/jump-if-!= $check-mu-numberlike-arg:end/disp32
20743 $check-mu-numberlike-arg:check-addr:
20744     # if t is an addr and v is dereferenced, return whether t->payload is an addr
20745     {
20746       (is-mu-addr-type? %esi)  # => eax
20747       3d/compare-eax-and 0/imm32/false
20748       74/jump-if-= break/disp8
20749       8b/-> *(ebp+8) 0/r32/eax
20750       8b/-> *(eax+0x10) 0/r32/eax  # Stmt-var-is-deref
20751       3d/compare-eax-and 0/imm32/false
20752       {
20753         74/jump-if-= break/disp8
20754         (lookup *(esi+0xc) *(esi+0x10))  # Type-tree-right Type-tree-right => eax
20755         # if t->right is null, t = t->left
20756         81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
20757         {
20758           75/jump-if-!= break/disp8
20759           (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20760         }
20761         (is-mu-addr-type? %eax)  # => eax
20762         3d/compare-eax-and 0/imm32/false
20763         74/jump-if-= $check-mu-numberlike-arg:end/disp8
20764       }
20765     }
20766 $check-mu-numberlike-arg:output-checks:
20767     (check-mu-numberlike-output *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18))
20768 $check-mu-numberlike-arg:end:
20769     # . restore registers
20770     5e/pop-to-esi
20771     58/pop-to-eax
20772     # . epilogue
20773     89/<- %esp 5/r32/ebp
20774     5d/pop-to-ebp
20775     c3/return
20776 
20777 check-mu-numberlike-output:  # v: (addr stmt-var), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
20778     # . prologue
20779     55/push-ebp
20780     89/<- %ebp 4/r32/esp
20781     # . save registers
20782     50/push-eax
20783     #
20784     (is-mu-numberlike-output-var? *(ebp+8))  # => eax
20785     3d/compare-eax-and 0/imm32/false
20786     0f 84/jump-if-= $check-mu-numberlike-output:fail/disp32
20787 $check-mu-numberlike-output:end:
20788     # . restore registers
20789     58/pop-to-eax
20790     # . epilogue
20791     89/<- %esp 5/r32/ebp
20792     5d/pop-to-ebp
20793     c3/return
20794 
20795 $check-mu-numberlike-output:fail:
20796     # otherwise raise an error
20797     (write-buffered *(ebp+0x14) "fn ")
20798     8b/-> *(ebp+0x10) 0/r32/eax
20799     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20800     (write-buffered *(ebp+0x14) %eax)
20801     (write-buffered *(ebp+0x14) ": stmt ")
20802     8b/-> *(ebp+0xc) 0/r32/eax
20803     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
20804     (write-buffered *(ebp+0x14) %eax)
20805     (write-buffered *(ebp+0x14) ": '")
20806     8b/-> *(ebp+8) 0/r32/eax
20807     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
20808     (lookup *eax *(eax+4))  # Var-name Var-name => eax
20809     (write-buffered *(ebp+0x14) %eax)
20810     (write-buffered *(ebp+0x14) "' must be a non-addr non-offset scalar\n")
20811     (flush *(ebp+0x14))
20812     (stop *(ebp+0x18) 1)
20813     # never gets here
20814 
20815 is-mu-numberlike-output-var?:  # v: (addr stmt-var) -> result/eax: boolean
20816     # . prologue
20817     55/push-ebp
20818     89/<- %ebp 4/r32/esp
20819     #
20820     8b/-> *(ebp+8) 0/r32/eax
20821     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
20822     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20823     (is-mu-numberlike-output? %eax)  # => eax
20824 $is-mu-numberlike-output-var?:end:
20825     # . epilogue
20826     89/<- %esp 5/r32/ebp
20827     5d/pop-to-ebp
20828     c3/return
20829 
20830 is-mu-numberlike-output?:  # v: (addr type-tree) -> result/eax: boolean
20831     # . prologue
20832     55/push-ebp
20833     89/<- %ebp 4/r32/esp
20834     # . save registers
20835     56/push-esi
20836     # var t/esi: (addr type-tree) = lookup(v->value->type)
20837     8b/-> *(ebp+8) 6/r32/esi
20838 $is-mu-numberlike-output?:check-int:
20839     # if t is an int, return
20840     (is-simple-mu-type? %esi 1)  # int => eax
20841     3d/compare-eax-and 0/imm32/false
20842     0f 85/jump-if-!= $is-mu-numberlike-output?:return-true/disp32
20843 $is-mu-numberlike-output?:check-float:
20844     # if t is a float, return
20845     (is-simple-mu-type? %esi 0xf)  # float => eax
20846     3d/compare-eax-and 0/imm32/false
20847     75/jump-if-!= $is-mu-numberlike-output?:return-true/disp8
20848 $is-mu-numberlike-output?:check-boolean:
20849     # if t is a boolean, return
20850     (is-simple-mu-type? %esi 5)  # boolean => eax
20851     3d/compare-eax-and 0/imm32/false
20852     75/jump-if-!= $is-mu-numberlike-output?:return-true/disp8
20853 $is-mu-numberlike-output?:check-byte:
20854     # if t is a byte, return
20855     (is-simple-mu-type? %esi 8)  # byte => eax
20856     3d/compare-eax-and 0/imm32/false
20857     75/jump-if-!= $is-mu-numberlike-output?:return-true/disp8
20858 $is-mu-numberlike-output?:check-code-point:
20859     # if t is a code-point, return
20860     (is-simple-mu-type? %esi 0xd)  # code-point => eax
20861     3d/compare-eax-and 0/imm32/false
20862     75/jump-if-!= $is-mu-numberlike-output?:return-true/disp8
20863 $is-mu-numberlike-output?:check-grapheme:
20864     # if t is a grapheme, return
20865     (is-simple-mu-type? %esi 0xe)  # grapheme => eax
20866     3d/compare-eax-and 0/imm32/false
20867     75/jump-if-!= $is-mu-numberlike-output?:return-true/disp8
20868 $is-mu-numberlike-output?:return-false:
20869     b8/copy-to-eax 0/imm32/false
20870     eb/jump $is-mu-numberlike-output?:end/disp8
20871 $is-mu-numberlike-output?:return-true:
20872     b8/copy-to-eax 1/imm32/true
20873 $is-mu-numberlike-output?:end:
20874     # . restore registers
20875     5e/pop-to-esi
20876     # . epilogue
20877     89/<- %esp 5/r32/ebp
20878     5d/pop-to-ebp
20879     c3/return
20880 
20881 check-mu-copy-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
20882     # . prologue
20883     55/push-ebp
20884     89/<- %ebp 4/r32/esp
20885     # . save registers
20886     50/push-eax
20887     51/push-ecx
20888     52/push-edx
20889     56/push-esi
20890     57/push-edi
20891     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
20892     81 5/subop/subtract %esp 0x60/imm32
20893     68/push 0x60/imm32/size
20894     68/push 0/imm32/read
20895     68/push 0/imm32/write
20896     89/<- %edx 4/r32/esp
20897 $check-mu-copy-stmt:get-output:
20898     # esi = stmt
20899     8b/-> *(ebp+8) 6/r32/esi
20900     # var output/edi: (addr stmt-var) = stmt->outputs
20901     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
20902     89/<- %edi 0/r32/eax
20903     # zero outputs
20904     3d/compare-eax-and 0/imm32
20905     0f 84/jump-if-= $check-mu-copy-stmt:error-no-output/disp32
20906     # > 1 output
20907     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
20908     3d/compare-eax-and 0/imm32
20909     0f 85/jump-if-!= $check-mu-copy-stmt:error-too-many-outputs/disp32
20910 $check-mu-copy-stmt:get-inout:
20911     # var inout/esi: (addr stmt-var) = stmt->inouts
20912     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
20913     89/<- %esi 0/r32/eax
20914     # zero inouts
20915     3d/compare-eax-and 0/imm32
20916     0f 84/jump-if-= $check-mu-copy-stmt:error-no-inout/disp32
20917     # > 1 inout
20918     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
20919     3d/compare-eax-and 0/imm32
20920     0f 85/jump-if-!= $check-mu-copy-stmt:error-too-many-inouts/disp32
20921 $check-mu-copy-stmt:types:
20922     # var inout-type/ecx: (addr type-tree) = inout->value->type
20923     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
20924     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20925     89/<- %ecx 0/r32/eax
20926     # if (inout->is-deref?) inout-type = inout-type->payload
20927     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
20928     3d/compare-eax-and 0/imm32/false
20929     {
20930       74/jump-if-= break/disp8
20931       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
20932       # if inout-type->right is null, t = inout-type->left
20933       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
20934       {
20935         75/jump-if-!= break/disp8
20936         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20937       }
20938       89/<- %ecx 0/r32/eax
20939     }
20940     # if output not in register, abort
20941     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
20942     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
20943     3d/compare-eax-and 0/imm32
20944     0f 84/jump-if-= $check-mu-copy-stmt:error-output-not-in-register/disp32
20945     # if inout is not a scalar, abort
20946     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
20947     (size-of %eax)  # => eax
20948     3d/compare-eax-and 4/imm32
20949     0f 8f/jump-if-> $check-mu-copy-stmt:error-inout-too-large/disp32
20950     # var output-type/eax: (addr type-tree) = output->value->type
20951     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
20952     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20953     # if (inout-type == output-type) return
20954     (type-match? %eax %ecx %edx)  # => eax
20955     3d/compare-eax-and 0/imm32
20956     0f 85/jump-if-!= $check-mu-copy-stmt:end/disp32
20957     # if output is an addr and inout is 0, return
20958     {
20959       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
20960       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20961       (is-mu-addr-type? %eax)  # => eax
20962       3d/compare-eax-and 0/imm32/false
20963       74/jump-if-= break/disp8
20964       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
20965       (lookup *eax *(eax+4))  # Var-name Var-name => eax
20966       (string-equal? %eax "0")  # => eax
20967       3d/compare-eax-and 0/imm32/false
20968       74/jump-if-= break/disp8
20969       e9/jump $check-mu-copy-stmt:end/disp32
20970     }
20971     # if output is an offset and inout is 0, return
20972     {
20973       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
20974       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20975       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
20976       75/jump-if-!= break/disp8
20977       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20978       (is-simple-mu-type? %eax 7)  # offset => eax
20979       3d/compare-eax-and 0/imm32/false
20980       74/jump-if-= break/disp8
20981       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
20982       (lookup *eax *(eax+4))  # Var-name Var-name => eax
20983       (string-equal? %eax "0")  # => eax
20984       3d/compare-eax-and 0/imm32/false
20985       74/jump-if-= break/disp8
20986       eb/jump $check-mu-copy-stmt:end/disp8
20987     }
20988     # if output is not number-like, abort
20989     (check-mu-numberlike-output %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20990 $check-mu-copy-stmt:end:
20991     # . reclaim locals
20992     81 0/subop/add %esp 0x6c/imm32
20993     # . restore registers
20994     5f/pop-to-edi
20995     5e/pop-to-esi
20996     5a/pop-to-edx
20997     59/pop-to-ecx
20998     58/pop-to-eax
20999     # . epilogue
21000     89/<- %esp 5/r32/ebp
21001     5d/pop-to-ebp
21002     c3/return
21003 
21004 $check-mu-copy-stmt:error-no-inout:
21005     (write-buffered *(ebp+0x10) "fn ")
21006     8b/-> *(ebp+0xc) 0/r32/eax
21007     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21008     (write-buffered *(ebp+0x10) %eax)
21009     (write-buffered *(ebp+0x10) ": stmt 'copy' expects an inout\n")
21010     (flush *(ebp+0x10))
21011     (stop *(ebp+0x14) 1)
21012     # never gets here
21013 
21014 $check-mu-copy-stmt:error-too-many-inouts:
21015     (write-buffered *(ebp+0x10) "fn ")
21016     8b/-> *(ebp+0xc) 0/r32/eax
21017     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21018     (write-buffered *(ebp+0x10) %eax)
21019     (write-buffered *(ebp+0x10) ": stmt 'copy' must have just one inout\n")
21020     (flush *(ebp+0x10))
21021     (stop *(ebp+0x14) 1)
21022     # never gets here
21023 
21024 $check-mu-copy-stmt:error-no-output:
21025     (write-buffered *(ebp+0x10) "fn ")
21026     8b/-> *(ebp+0xc) 0/r32/eax
21027     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21028     (write-buffered *(ebp+0x10) %eax)
21029     (write-buffered *(ebp+0x10) ": stmt 'copy' expects an output\n")
21030     (flush *(ebp+0x10))
21031     (stop *(ebp+0x14) 1)
21032     # never gets here
21033 
21034 $check-mu-copy-stmt:error-output-not-in-register:
21035     (write-buffered *(ebp+0x10) "fn ")
21036     8b/-> *(ebp+0xc) 0/r32/eax
21037     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21038     (write-buffered *(ebp+0x10) %eax)
21039     (write-buffered *(ebp+0x10) ": stmt copy: output '")
21040     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21041     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21042     (write-buffered *(ebp+0x10) %eax)
21043     (write-buffered *(ebp+0x10) "' not in a register\n")
21044     (flush *(ebp+0x10))
21045     (stop *(ebp+0x14) 1)
21046     # never gets here
21047 
21048 $check-mu-copy-stmt:error-too-many-outputs:
21049     (write-buffered *(ebp+0x10) "fn ")
21050     8b/-> *(ebp+0xc) 0/r32/eax
21051     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21052     (write-buffered *(ebp+0x10) %eax)
21053     (write-buffered *(ebp+0x10) ": stmt 'copy' must have just one output\n")
21054     (flush *(ebp+0x10))
21055     (stop *(ebp+0x14) 1)
21056     # never gets here
21057 
21058 $check-mu-copy-stmt:error-inout-too-large:
21059     (write-buffered *(ebp+0x10) "fn ")
21060     8b/-> *(ebp+0xc) 0/r32/eax
21061     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21062     (write-buffered *(ebp+0x10) %eax)
21063     (write-buffered *(ebp+0x10) ": stmt copy: '")
21064     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
21065     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21066     (write-buffered *(ebp+0x10) %eax)
21067     (write-buffered *(ebp+0x10) "' is too large to fit in a register\n")
21068     (flush *(ebp+0x10))
21069     (stop *(ebp+0x14) 1)
21070     # never gets here
21071 
21072 check-mu-copy-to-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21073     # . prologue
21074     55/push-ebp
21075     89/<- %ebp 4/r32/esp
21076     # . save registers
21077     50/push-eax
21078     51/push-ecx
21079     52/push-edx
21080     53/push-ebx
21081     56/push-esi
21082     57/push-edi
21083     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
21084     81 5/subop/subtract %esp 0x60/imm32
21085     68/push 0x60/imm32/size
21086     68/push 0/imm32/read
21087     68/push 0/imm32/write
21088     89/<- %edx 4/r32/esp
21089     # esi = stmt
21090     8b/-> *(ebp+8) 6/r32/esi
21091 $check-mu-copy-to-stmt:check-for-output:
21092     # if stmt->outputs abort
21093     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
21094     3d/compare-eax-and 0/imm32
21095     0f 85/jump-if-!= $check-mu-copy-to-stmt:error-too-many-outputs/disp32
21096 $check-mu-copy-to-stmt:get-dest:
21097     # var dest/edi: (addr stmt-var) = stmt->inouts
21098     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21099     89/<- %edi 0/r32/eax
21100     # zero inouts
21101     3d/compare-eax-and 0/imm32
21102     0f 84/jump-if-= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32
21103 $check-mu-copy-to-stmt:get-src:
21104     # var src/esi: (addr stmt-var) = dest->next
21105     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
21106     89/<- %esi 0/r32/eax
21107     # 1 inout
21108     3d/compare-eax-and 0/imm32
21109     0f 84/jump-if-= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32
21110     # > 2 inouts
21111     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
21112     3d/compare-eax-and 0/imm32
21113     0f 85/jump-if-!= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32
21114 $check-mu-copy-to-stmt:types:
21115     # var src-type/ecx: (addr type-tree) = src->value->type
21116     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
21117     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21118     89/<- %ecx 0/r32/eax
21119     # if src not in register or literal, abort
21120     # (we can't use stack-offset because it hasn't been computed yet)
21121     {
21122       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
21123       (lookup *(eax+0x8) *(eax+0xc))  # Var-type Var-type => eax
21124       (is-simple-mu-type? %eax 0)  # => eax
21125       3d/compare-eax-and 0/imm32
21126       75/jump-if-!= break/disp8
21127       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
21128       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
21129       3d/compare-eax-and 0/imm32
21130       75/jump-if-!= break/disp8
21131       e9/jump $check-mu-copy-to-stmt:error-src-not-literal-or-in-register/disp32
21132     }
21133     # if src is not a scalar, abort
21134     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
21135     (size-of %eax)  # => eax
21136     3d/compare-eax-and 4/imm32
21137     0f 8f/jump-if-> $check-mu-copy-to-stmt:error-src-too-large/disp32
21138     # var dest-type/ebx: (addr type-tree) = dest->value->type
21139     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21140     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21141     89/<- %ebx 0/r32/eax
21142     # if (dest->is-deref?) dest-type = dest-type->payload
21143     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
21144     3d/compare-eax-and 0/imm32/false
21145     {
21146       74/jump-if-= break/disp8
21147       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
21148       # if dest-type->right is null, dest-type = dest-type->left
21149       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
21150       {
21151         75/jump-if-!= break/disp8
21152         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21153       }
21154       89/<- %ebx 0/r32/eax
21155     }
21156     # if (src-type == dest-type) return
21157     (type-match? %ebx %ecx %edx)  # => eax
21158     3d/compare-eax-and 0/imm32
21159     0f 85/jump-if-!= $check-mu-copy-to-stmt:end/disp32
21160     # if dest is an addr and src is 0, return
21161     {
21162       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21163       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21164       (is-mu-addr-type? %eax)  # => eax
21165       3d/compare-eax-and 0/imm32/false
21166       74/jump-if-= break/disp8
21167       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
21168       (lookup *eax *(eax+4))  # Var-name Var-name => eax
21169       (string-equal? %eax "0")  # => eax
21170       3d/compare-eax-and 0/imm32/false
21171       74/jump-if-= break/disp8
21172       eb/jump $check-mu-copy-to-stmt:end/disp8
21173     }
21174     # if dest is not number-like, abort
21175     (check-mu-numberlike-arg %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21176 $check-mu-copy-to-stmt:end:
21177     # . reclaim locals
21178     81 0/subop/add %esp 0x6c/imm32
21179     # . restore registers
21180     5f/pop-to-edi
21181     5e/pop-to-esi
21182     5b/pop-to-ebx
21183     5a/pop-to-edx
21184     59/pop-to-ecx
21185     58/pop-to-eax
21186     # . epilogue
21187     89/<- %esp 5/r32/ebp
21188     5d/pop-to-ebp
21189     c3/return
21190 
21191 $check-mu-copy-to-stmt:error-incorrect-inouts:
21192     (write-buffered *(ebp+0x10) "fn ")
21193     8b/-> *(ebp+0xc) 0/r32/eax
21194     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21195     (write-buffered *(ebp+0x10) %eax)
21196     (write-buffered *(ebp+0x10) ": stmt 'copy-to' must have two inouts\n")
21197     (flush *(ebp+0x10))
21198     (stop *(ebp+0x14) 1)
21199     # never gets here
21200 
21201 $check-mu-copy-to-stmt:error-too-many-outputs:
21202     (write-buffered *(ebp+0x10) "fn ")
21203     8b/-> *(ebp+0xc) 0/r32/eax
21204     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21205     (write-buffered *(ebp+0x10) %eax)
21206     (write-buffered *(ebp+0x10) ": stmt 'copy-to' must not have any outputs\n")
21207     (flush *(ebp+0x10))
21208     (stop *(ebp+0x14) 1)
21209     # never gets here
21210 
21211 $check-mu-copy-to-stmt:error-src-not-literal-or-in-register:
21212     (write-buffered *(ebp+0x10) "fn ")
21213     8b/-> *(ebp+0xc) 0/r32/eax
21214     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21215     (write-buffered *(ebp+0x10) %eax)
21216     (write-buffered *(ebp+0x10) ": stmt copy-to: source (second inout) is in memory\n")
21217     (flush *(ebp+0x10))
21218     (stop *(ebp+0x14) 1)
21219     # never gets here
21220 
21221 $check-mu-copy-to-stmt:error-src-too-large:
21222     (write-buffered *(ebp+0x10) "fn ")
21223     8b/-> *(ebp+0xc) 0/r32/eax
21224     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21225     (write-buffered *(ebp+0x10) %eax)
21226     (write-buffered *(ebp+0x10) ": stmt copy-to: '")
21227     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
21228     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21229     (write-buffered *(ebp+0x10) %eax)
21230     (write-buffered *(ebp+0x10) "' is too large to copy\n")
21231     (flush *(ebp+0x10))
21232     (stop *(ebp+0x14) 1)
21233     # never gets here
21234 
21235 check-mu-compare-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21236     # . prologue
21237     55/push-ebp
21238     89/<- %ebp 4/r32/esp
21239     # . save registers
21240     50/push-eax
21241     51/push-ecx
21242     52/push-edx
21243     53/push-ebx
21244     56/push-esi
21245     57/push-edi
21246     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
21247     81 5/subop/subtract %esp 0x60/imm32
21248     68/push 0x60/imm32/size
21249     68/push 0/imm32/read
21250     68/push 0/imm32/write
21251     89/<- %edx 4/r32/esp
21252     # esi = stmt
21253     8b/-> *(ebp+8) 6/r32/esi
21254 $check-mu-compare-stmt:check-for-output:
21255     # if stmt->outputs abort
21256     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
21257     3d/compare-eax-and 0/imm32
21258     0f 85/jump-if-!= $check-mu-compare-stmt:error-too-many-outputs/disp32
21259 $check-mu-compare-stmt:get-left:
21260     # var left/edi: (addr stmt-var) = stmt->inouts
21261     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21262     89/<- %edi 0/r32/eax
21263     # zero inouts
21264     3d/compare-eax-and 0/imm32
21265     0f 84/jump-if-= $check-mu-compare-stmt:error-incorrect-inouts/disp32
21266 $check-mu-compare-stmt:get-right:
21267     # var right/esi: (addr stmt-var) = left->next
21268     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
21269     89/<- %esi 0/r32/eax
21270     # 1 inout
21271     3d/compare-eax-and 0/imm32
21272     0f 84/jump-if-= $check-mu-compare-stmt:error-incorrect-inouts/disp32
21273     # > 2 inouts
21274     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
21275     3d/compare-eax-and 0/imm32
21276     0f 85/jump-if-!= $check-mu-compare-stmt:error-incorrect-inouts/disp32
21277     # if both inouts are in memory, abort
21278     {
21279 $check-mu-compare-stmt:both-in-mem:
21280       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
21281       (lookup *(eax+0x8) *(eax+0xc))  # Var-type Var-type => eax
21282       (is-simple-mu-type? %eax 0)  # => eax
21283       3d/compare-eax-and 0/imm32
21284       0f 85/jump-if-!= break/disp32
21285       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
21286       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
21287       3d/compare-eax-and 0/imm32
21288       75/jump-if-!= break/disp8
21289       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21290       (lookup *(eax+0x8) *(eax+0xc))  # Var-type Var-type => eax
21291       (is-simple-mu-type? %eax 0)  # => eax
21292       3d/compare-eax-and 0/imm32
21293       75/jump-if-!= break/disp8
21294       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21295       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
21296       3d/compare-eax-and 0/imm32
21297       75/jump-if-!= break/disp8
21298       e9/jump $check-mu-compare-stmt:error-both-in-memory/disp32
21299     }
21300 $check-mu-compare-stmt:types:
21301     # var right-type/ecx: (addr type-tree) = right->value->type
21302     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
21303     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21304     89/<- %ecx 0/r32/eax
21305     # if (right->is-deref?) right-type = right-type->payload
21306     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
21307     3d/compare-eax-and 0/imm32/false
21308     {
21309       74/jump-if-= break/disp8
21310       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
21311       # if right-type->right is null, right-type = right-type->left
21312       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
21313       {
21314         75/jump-if-!= break/disp8
21315         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21316       }
21317       89/<- %ecx 0/r32/eax
21318     }
21319     # if right is not a scalar, abort
21320     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
21321     (size-of %eax)  # => eax
21322     3d/compare-eax-and 4/imm32
21323     0f 8f/jump-if-> $check-mu-compare-stmt:error-right-too-large/disp32
21324     # if left is not a scalar, abort
21325     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21326     (size-of %eax)  # => eax
21327     3d/compare-eax-and 4/imm32
21328     0f 8f/jump-if-> $check-mu-compare-stmt:error-left-too-large/disp32
21329     # var left-type/ebx: (addr type-tree) = left->value->type
21330     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21331     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21332     89/<- %ebx 0/r32/eax
21333     # if (left->is-deref?) left-type = left-type->payload
21334     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
21335     3d/compare-eax-and 0/imm32/false
21336     {
21337       74/jump-if-= break/disp8
21338       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
21339       # if left-type->right is null, left-type = left-type->left
21340       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
21341       {
21342         75/jump-if-!= break/disp8
21343         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21344       }
21345       89/<- %ebx 0/r32/eax
21346     }
21347     # if (left-type == right-type) return
21348     (type-match? %ebx %ecx %edx)  # => eax
21349     3d/compare-eax-and 0/imm32
21350     0f 85/jump-if-!= $check-mu-compare-stmt:end/disp32
21351     # if left is an addr and right is 0, return
21352     {
21353       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21354       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21355       (is-mu-addr-type? %eax)  # => eax
21356       3d/compare-eax-and 0/imm32/false
21357       74/jump-if-= break/disp8
21358       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
21359       (lookup *eax *(eax+4))  # Var-name Var-name => eax
21360       (string-equal? %eax "0")  # => eax
21361       3d/compare-eax-and 0/imm32/false
21362       74/jump-if-= break/disp8
21363       eb/jump $check-mu-compare-stmt:end/disp8
21364     }
21365     # if left is not number-like, abort
21366     (check-mu-numberlike-arg %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21367 $check-mu-compare-stmt:end:
21368     # . reclaim locals
21369     81 0/subop/add %esp 0x6c/imm32
21370     # . restore registers
21371     5f/pop-to-edi
21372     5e/pop-to-esi
21373     5b/pop-to-ebx
21374     5a/pop-to-edx
21375     59/pop-to-ecx
21376     58/pop-to-eax
21377     # . epilogue
21378     89/<- %esp 5/r32/ebp
21379     5d/pop-to-ebp
21380     c3/return
21381 
21382 $check-mu-compare-stmt:error-incorrect-inouts:
21383     (write-buffered *(ebp+0x10) "fn ")
21384     8b/-> *(ebp+0xc) 0/r32/eax
21385     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21386     (write-buffered *(ebp+0x10) %eax)
21387     (write-buffered *(ebp+0x10) ": stmt 'compare' must have two inouts\n")
21388     (flush *(ebp+0x10))
21389     (stop *(ebp+0x14) 1)
21390     # never gets here
21391 
21392 $check-mu-compare-stmt:error-too-many-outputs:
21393     (write-buffered *(ebp+0x10) "fn ")
21394     8b/-> *(ebp+0xc) 0/r32/eax
21395     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21396     (write-buffered *(ebp+0x10) %eax)
21397     (write-buffered *(ebp+0x10) ": stmt 'compare' must not have any outputs\n")
21398     (flush *(ebp+0x10))
21399     (stop *(ebp+0x14) 1)
21400     # never gets here
21401 
21402 $check-mu-compare-stmt:error-both-in-memory:
21403     (write-buffered *(ebp+0x10) "fn ")
21404     8b/-> *(ebp+0xc) 0/r32/eax
21405     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21406     (write-buffered *(ebp+0x10) %eax)
21407     (write-buffered *(ebp+0x10) ": stmt compare: both inouts are in memory\n")
21408     (flush *(ebp+0x10))
21409     (stop *(ebp+0x14) 1)
21410     # never gets here
21411 
21412 $check-mu-compare-stmt:error-left-too-large:
21413     (write-buffered *(ebp+0x10) "fn ")
21414     8b/-> *(ebp+0xc) 0/r32/eax
21415     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21416     (write-buffered *(ebp+0x10) %eax)
21417     (write-buffered *(ebp+0x10) ": stmt compare: '")
21418     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21419     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21420     (write-buffered *(ebp+0x10) %eax)
21421     (write-buffered *(ebp+0x10) "' is too large to compare\n")
21422     (flush *(ebp+0x10))
21423     (stop *(ebp+0x14) 1)
21424     # never gets here
21425 
21426 $check-mu-compare-stmt:error-right-too-large:
21427     (write-buffered *(ebp+0x10) "fn ")
21428     8b/-> *(ebp+0xc) 0/r32/eax
21429     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21430     (write-buffered *(ebp+0x10) %eax)
21431     (write-buffered *(ebp+0x10) ": stmt compare: '")
21432     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
21433     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21434     (write-buffered *(ebp+0x10) %eax)
21435     (write-buffered *(ebp+0x10) "' is too large to compare\n")
21436     (flush *(ebp+0x10))
21437     (stop *(ebp+0x14) 1)
21438     # never gets here
21439 
21440 check-mu-address-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21441     # . prologue
21442     55/push-ebp
21443     89/<- %ebp 4/r32/esp
21444     # . save registers
21445     50/push-eax
21446     51/push-ecx
21447     52/push-edx
21448     56/push-esi
21449     57/push-edi
21450 $check-mu-address-stmt:get-output:
21451     # esi = stmt
21452     8b/-> *(ebp+8) 6/r32/esi
21453     # var output/edi: (addr stmt-var) = stmt->outputs
21454     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
21455     89/<- %edi 0/r32/eax
21456     # zero outputs
21457     3d/compare-eax-and 0/imm32
21458     0f 84/jump-if-= $check-mu-address-stmt:error-no-output/disp32
21459     # > 1 output
21460     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
21461     3d/compare-eax-and 0/imm32
21462     0f 85/jump-if-!= $check-mu-address-stmt:error-too-many-outputs/disp32
21463 $check-mu-address-stmt:get-inout:
21464     # var inout/esi: (addr stmt-var) = stmt->inouts
21465     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21466     89/<- %esi 0/r32/eax
21467     # zero inouts
21468     3d/compare-eax-and 0/imm32
21469     0f 84/jump-if-= $check-mu-address-stmt:error-no-inout/disp32
21470     # > 1 inout
21471     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
21472     3d/compare-eax-and 0/imm32
21473     0f 85/jump-if-!= $check-mu-address-stmt:error-too-many-inouts/disp32
21474 $check-mu-address-stmt:types:
21475     # if output not in register, abort
21476     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21477     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
21478     3d/compare-eax-and 0/imm32
21479     0f 84/jump-if-= $check-mu-address-stmt:error-output-not-in-register/disp32
21480     # var output-type/edx: (addr type-tree) = output->value->type
21481     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21482     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21483     89/<- %edx 0/r32/eax
21484     # if output-type not an addr, abort
21485     (is-mu-addr-type? %edx)  # => eax
21486     3d/compare-eax-and 0/imm32/false
21487     0f 84/jump-if-= $check-mu-address-stmt:error-output-not-address/disp32
21488     # output-type = output-type->right
21489     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
21490     # if output-type->right is null, output-type = output-type->left
21491     81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
21492     {
21493       75/jump-if-!= break/disp8
21494       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21495     }
21496     89/<- %edx 0/r32/eax
21497     # var inout-type/ecx: (addr type-tree) = inout->value->type
21498     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
21499     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21500     89/<- %ecx 0/r32/eax
21501     # if (inout->is-deref?) inout-type = inout-type->payload
21502     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
21503     3d/compare-eax-and 0/imm32/false
21504     {
21505       74/jump-if-= break/disp8
21506       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
21507       # if inout-type->right is null, t = inout-type->left
21508       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
21509       {
21510         75/jump-if-!= break/disp8
21511         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21512       }
21513       89/<- %ecx 0/r32/eax
21514     }
21515     # if (inout-type != output-type) abort
21516     (type-equal-ignoring-capacity? %edx %ecx)  # => eax
21517     3d/compare-eax-and 0/imm32
21518     0f 84/jump-if-= $check-mu-address-stmt:error-type-mismatch/disp32
21519 $check-mu-address-stmt:end:
21520     # . restore registers
21521     5f/pop-to-edi
21522     5e/pop-to-esi
21523     5a/pop-to-edx
21524     59/pop-to-ecx
21525     58/pop-to-eax
21526     # . epilogue
21527     89/<- %esp 5/r32/ebp
21528     5d/pop-to-ebp
21529     c3/return
21530 
21531 $check-mu-address-stmt:error-no-inout:
21532     (write-buffered *(ebp+0x10) "fn ")
21533     8b/-> *(ebp+0xc) 0/r32/eax
21534     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21535     (write-buffered *(ebp+0x10) %eax)
21536     (write-buffered *(ebp+0x10) ": stmt 'address' expects an inout\n")
21537     (flush *(ebp+0x10))
21538     (stop *(ebp+0x14) 1)
21539     # never gets here
21540 
21541 $check-mu-address-stmt:error-too-many-inouts:
21542     (write-buffered *(ebp+0x10) "fn ")
21543     8b/-> *(ebp+0xc) 0/r32/eax
21544     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21545     (write-buffered *(ebp+0x10) %eax)
21546     (write-buffered *(ebp+0x10) ": stmt 'address' must have just one inout\n")
21547     (flush *(ebp+0x10))
21548     (stop *(ebp+0x14) 1)
21549     # never gets here
21550 
21551 $check-mu-address-stmt:error-no-output:
21552     (write-buffered *(ebp+0x10) "fn ")
21553     8b/-> *(ebp+0xc) 0/r32/eax
21554     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21555     (write-buffered *(ebp+0x10) %eax)
21556     (write-buffered *(ebp+0x10) ": stmt 'address' expects an output\n")
21557     (flush *(ebp+0x10))
21558     (stop *(ebp+0x14) 1)
21559     # never gets here
21560 
21561 $check-mu-address-stmt:error-output-not-in-register:
21562     (write-buffered *(ebp+0x10) "fn ")
21563     8b/-> *(ebp+0xc) 0/r32/eax
21564     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21565     (write-buffered *(ebp+0x10) %eax)
21566     (write-buffered *(ebp+0x10) ": stmt address: output '")
21567     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21568     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21569     (write-buffered *(ebp+0x10) %eax)
21570     (write-buffered *(ebp+0x10) "' not in a register\n")
21571     (flush *(ebp+0x10))
21572     (stop *(ebp+0x14) 1)
21573     # never gets here
21574 
21575 $check-mu-address-stmt:error-too-many-outputs:
21576     (write-buffered *(ebp+0x10) "fn ")
21577     8b/-> *(ebp+0xc) 0/r32/eax
21578     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21579     (write-buffered *(ebp+0x10) %eax)
21580     (write-buffered *(ebp+0x10) ": stmt 'address' must have just one output\n")
21581     (flush *(ebp+0x10))
21582     (stop *(ebp+0x14) 1)
21583     # never gets here
21584 
21585 $check-mu-address-stmt:error-output-not-address:
21586     (write-buffered *(ebp+0x10) "fn ")
21587     8b/-> *(ebp+0xc) 0/r32/eax
21588     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21589     (write-buffered *(ebp+0x10) %eax)
21590     (write-buffered *(ebp+0x10) ": stmt address: output '")
21591     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21592     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21593     (write-buffered *(ebp+0x10) %eax)
21594     (write-buffered *(ebp+0x10) "' is not an addr\n")
21595     (flush *(ebp+0x10))
21596     (stop *(ebp+0x14) 1)
21597     # never gets here
21598 
21599 $check-mu-address-stmt:error-type-mismatch:
21600     (write-buffered *(ebp+0x10) "fn ")
21601     8b/-> *(ebp+0xc) 0/r32/eax
21602     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21603     (write-buffered *(ebp+0x10) %eax)
21604     (write-buffered *(ebp+0x10) ": stmt address: output '")
21605     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21606     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21607     (write-buffered *(ebp+0x10) %eax)
21608     (write-buffered *(ebp+0x10) "' cannot hold address of '")
21609     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
21610     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21611     (write-buffered *(ebp+0x10) %eax)
21612     (write-buffered *(ebp+0x10) "'\n")
21613     (flush *(ebp+0x10))
21614     (stop *(ebp+0x14) 1)
21615     # never gets here
21616 
21617 type-equal-ignoring-capacity?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
21618     # . prologue
21619     55/push-ebp
21620     89/<- %ebp 4/r32/esp
21621     # . save registers
21622     51/push-ecx
21623     52/push-edx
21624     53/push-ebx
21625     # var curr-a/ecx: (addr type-tree) = a
21626     8b/-> *(ebp+8) 1/r32/ecx
21627     # var curr-b/ebx: (addr type-tree) = b
21628     8b/-> *(ebp+0xc) 3/r32/ebx
21629     # if (curr-a->is-atom?) fall back to regular equality
21630     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
21631     0f 85/jump-if-!= $type-equal-ignoring-capacity?:base-case/disp32
21632     # if (curr-a->left != curr-b->left) return false
21633     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
21634     89/<- %edx 0/r32/eax
21635     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
21636     (type-equal? %edx %eax)  # => eax
21637     3d/compare-eax-and 0/imm32/false
21638     0f 84/jump-if-= $type-equal-ignoring-capacity?:end/disp32  # eax switches meaning
21639     # if (curr-a->left == "array") curr-a = curr-a->element-type
21640     {
21641       (is-mu-array? %edx)  # => eax
21642       3d/compare-eax-and 0/imm32/false
21643       75/jump-if-!= break/disp8
21644 $type-equal-ignoring-capacity?:array:
21645       # curr-a = curr-a->right->left
21646       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
21647       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21648       89/<- %ecx 0/r32/eax
21649       # curr-b = curr-b->right->left
21650       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
21651       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21652       89/<- %ebx 0/r32/eax
21653       eb/jump $type-equal-ignoring-capacity?:base-case/disp8
21654     }
21655     # if (curr-a->left == "stream") curr-a = curr-a->element-type
21656     {
21657       (is-mu-stream? %edx)  # => eax
21658       3d/compare-eax-and 0/imm32/false
21659       75/jump-if-!= break/disp8
21660 $type-equal-ignoring-capacity?:stream:
21661       # curr-a = curr-a->right->left
21662       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
21663       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21664       89/<- %ecx 0/r32/eax
21665       # curr-b = curr-b->right->left
21666       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
21667       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21668       89/<- %ebx 0/r32/eax
21669       eb/jump $type-equal-ignoring-capacity?:base-case/disp8
21670     }
21671 $type-equal-ignoring-capacity?:base-case:
21672     # return type-equal?(curr-a, curr-b)
21673     (type-equal? %ecx %ebx)  # => eax
21674 $type-equal-ignoring-capacity?:end:
21675     # . restore registers
21676     5b/pop-to-ebx
21677     5a/pop-to-edx
21678     59/pop-to-ecx
21679     # . epilogue
21680     89/<- %esp 5/r32/ebp
21681     5d/pop-to-ebp
21682     c3/return
21683 
21684 check-mu-return-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21685     # . prologue
21686     55/push-ebp
21687     89/<- %ebp 4/r32/esp
21688     # . save registers
21689     50/push-eax
21690     51/push-ecx
21691     52/push-edx
21692     53/push-ebx
21693     56/push-esi
21694     57/push-edi
21695     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
21696     81 5/subop/subtract %esp 0x60/imm32
21697     68/push 0x60/imm32/size
21698     68/push 0/imm32/read
21699     68/push 0/imm32/write
21700     89/<- %edx 4/r32/esp
21701     # var template/esi: (addr list var) = fn->outputs
21702     8b/-> *(ebp+0xc) 0/r32/eax
21703     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
21704     89/<- %esi 0/r32/eax
21705     # var curr-template/ebx: (addr list var) = fn->outputs
21706     89/<- %ebx 0/r32/eax
21707     # var curr/edi: (addr stmt-var) = stmt->inouts
21708     8b/-> *(ebp+8) 0/r32/eax
21709     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21710     89/<- %edi 0/r32/eax
21711     {
21712       # if template is null, break
21713       81 7/subop/compare %ebx 0/imm32
21714       0f 84/jump-if-= break/disp32
21715       # if curr is null, abort
21716       81 7/subop/compare %edi 0/imm32
21717       0f 84/jump-if-= $check-mu-return-stmt:error-too-few-inouts/disp32
21718       # var template-type/ecx: (addr type-tree) = template->value->type
21719       (lookup *ebx *(ebx+4))  # List-value List-value => eax
21720       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21721       89/<- %ecx 0/r32/eax
21722       # var curr-type/eax: (addr type-tree) = curr->value->type
21723       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21724       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21725       # if (curr->is-deref?) curr-type = payload of curr-type
21726       81 7/subop/compare *(edi+0x10) 0/imm32/false  # Stmt-var-is-deref
21727       {
21728         74/jump-if-= break/disp8
21729         (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
21730         # if t->right is null, t = t->left
21731         81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
21732         75/jump-if-!= break/disp8
21733         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21734       }
21735       # if (curr-type != template-type) abort
21736       (type-match? %ecx %eax %edx)  # => eax
21737       3d/compare-eax-and 0/imm32/false
21738       0f 84/jump-if-= $check-mu-return-stmt:error1/disp32
21739       # if register-within-list-with-conflict?(curr, original template, curr-template, stmt) abort
21740       (register-within-list-with-conflict? %edi %esi %ebx *(ebp+8))  # => eax
21741       3d/compare-eax-and 0/imm32/false
21742       0f 85/jump-if-!= $check-mu-return-stmt:error2/disp32
21743       # template = template->next
21744       (lookup *(ebx+8) *(ebx+0xc))  # List-next List-next => eax
21745       89/<- %ebx 0/r32/eax
21746       # curr = curr->next
21747       (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
21748       89/<- %edi 0/r32/eax
21749       #
21750       e9/jump loop/disp32
21751     }
21752     # if curr is not null, abort
21753     81 7/subop/compare %edi 0/imm32
21754     0f 85/jump-if-!= $check-mu-return-stmt:error-too-many-inouts/disp32
21755 $check-mu-return-stmt:end:
21756     # . reclaim locals
21757     81 0/subop/add %esp 0x6c/imm32
21758     # . restore registers
21759     5f/pop-to-edi
21760     5e/pop-to-esi
21761     5b/pop-to-ebx
21762     5a/pop-to-edx
21763     59/pop-to-ecx
21764     58/pop-to-eax
21765     # . epilogue
21766     89/<- %esp 5/r32/ebp
21767     5d/pop-to-ebp
21768     c3/return
21769 
21770 $check-mu-return-stmt:error1:
21771     (write-buffered *(ebp+0x10) "fn ")
21772     8b/-> *(ebp+0xc) 0/r32/eax
21773     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21774     (write-buffered *(ebp+0x10) %eax)
21775     (write-buffered *(ebp+0x10) ": return: '")
21776     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21777     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21778     (write-buffered *(ebp+0x10) %eax)
21779     (write-buffered *(ebp+0x10) "' has the wrong type\n")
21780     (flush *(ebp+0x10))
21781     (stop *(ebp+0x14) 1)
21782     # never gets here
21783 
21784 $check-mu-return-stmt:error2:
21785     (write-buffered *(ebp+0x10) "fn ")
21786     8b/-> *(ebp+0xc) 0/r32/eax
21787     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21788     (write-buffered *(ebp+0x10) %eax)
21789     (write-buffered *(ebp+0x10) ": return: '")
21790     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21791     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21792     (write-buffered *(ebp+0x10) %eax)
21793     (write-buffered *(ebp+0x10) "' is no longer available\n")
21794     (flush *(ebp+0x10))
21795     (stop *(ebp+0x14) 1)
21796     # never gets here
21797 
21798 $check-mu-return-stmt:error-too-few-inouts:
21799     (write-buffered *(ebp+0x10) "fn ")
21800     8b/-> *(ebp+0xc) 0/r32/eax
21801     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21802     (write-buffered *(ebp+0x10) %eax)
21803     (write-buffered *(ebp+0x10) ": return: too few inouts\n")
21804     (flush *(ebp+0x10))
21805     (stop *(ebp+0x14) 1)
21806     # never gets here
21807 
21808 $check-mu-return-stmt:error-too-many-inouts:
21809     (write-buffered *(ebp+0x10) "fn ")
21810     8b/-> *(ebp+0xc) 0/r32/eax
21811     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21812     (write-buffered *(ebp+0x10) %eax)
21813     (write-buffered *(ebp+0x10) ": return: too many inouts\n")
21814     (flush *(ebp+0x10))
21815     (stop *(ebp+0x14) 1)
21816     # never gets here
21817 
21818 check-all-unique-registers:  # outputs: (addr list var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21819     # . prologue
21820     55/push-ebp
21821     89/<- %ebp 4/r32/esp
21822     # . save registers
21823     50/push-eax
21824     51/push-ecx
21825     56/push-esi
21826     # var table/esi: (addr table (handle array byte) int 8)
21827     81 5/subop/subtract %esp 0x60/imm32
21828     68/push 0x60/imm32/size
21829     68/push 0/imm32/read
21830     68/push 0/imm32/write
21831     89/<- %esi 4/r32/esp
21832     # var curr/ecx: (addr list var) = outputs
21833     8b/-> *(ebp+8) 1/r32/ecx
21834     {
21835       # if (curr == 0) break
21836       81 7/subop/compare %ecx 0/imm32
21837       0f 84/jump-if-= break/disp32
21838       # var reg/eax: (addr array byte) = curr->value->register  # guaranteed to exist
21839       (lookup *ecx *(ecx+4))  # List-value List-value => eax
21840       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
21841       # if reg exists in table, abort
21842       (maybe-get %esi %eax 0xc)  # => eax
21843       3d/compare-eax-and 0/imm32
21844       0f 85/jump-if-!= $check-all-unique-registers:abort/disp32
21845       # insert reg in table
21846       (lookup *ecx *(ecx+4))  # List-value List-value => eax
21847       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
21848       (get-or-insert %esi %eax 0xc Heap)
21849       # curr = curr->next
21850       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
21851       89/<- %ecx 0/r32/eax
21852       e9/jump loop/disp32
21853     }
21854 $check-all-unique-registers:end:
21855     # . reclaim locals
21856     81 0/subop/add %esp 0x6c/imm32
21857     # . restore registers
21858     5e/pop-to-esi
21859     59/pop-to-ecx
21860     58/pop-to-eax
21861     # . epilogue
21862     89/<- %esp 5/r32/ebp
21863     5d/pop-to-ebp
21864     c3/return
21865 
21866 $check-all-unique-registers:abort:
21867     (write-buffered *(ebp+0x10) "fn ")
21868     8b/-> *(ebp+0xc) 0/r32/eax
21869     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21870     (write-buffered *(ebp+0x10) %eax)
21871     (write-buffered *(ebp+0x10) ": outputs must be in unique registers\n")
21872     (flush *(ebp+0x10))
21873     (stop *(ebp+0x14) 1)
21874     # never gets here
21875 
21876 # return false if s's register is not between start (inclusive) and end (exclusive)
21877 # return false if the positionally corresponding register in stmt->inouts (where s comes from) is also s's register
21878 # otherwise return true
21879 register-within-list-with-conflict?:  # s: (addr stmt-var), start: (addr list var), end: (addr list var), stmt: (addr stmt) -> result/eax: boolean
21880     # . prologue
21881     55/push-ebp
21882     89/<- %ebp 4/r32/esp
21883     # . save registers
21884     51/push-ecx
21885     52/push-edx
21886     53/push-ebx
21887     56/push-esi
21888     57/push-edi
21889     # var target/ebx: (addr array byte) = s->value->register
21890     8b/-> *(ebp+8) 0/r32/eax
21891     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21892     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
21893 #?     (write-buffered Stderr "AA: ")
21894 #?     (write-buffered Stderr %eax)
21895 #?     (write-buffered Stderr Newline)
21896 #?     (flush Stderr)
21897     # if (var->register == 0) return false
21898     3d/compare-eax-and 0/imm32
21899     0f 84/jump-if-= $register-within-list-with-conflict?:end/disp32  # eax turns into result
21900     89/<- %ebx 0/r32/eax
21901     # var curr/ecx: (addr list var) = start
21902     8b/-> *(ebp+0xc) 1/r32/ecx
21903     # edx = end
21904     8b/-> *(ebp+0x10) 2/r32/edx
21905     {
21906       # if (curr == 0) break
21907       81 7/subop/compare %edi 0/imm32
21908       0f 84/jump-if-= break/disp32
21909       # if (curr == end) break
21910       39/compare %ecx 2/r32/edx
21911       0f 84/jump-if-= break/disp32
21912       # var curr-reg/eax: (addr array byte) = curr->value->register
21913       (lookup *ecx *(ecx+4))  # List-value List-value => eax
21914       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
21915       # if (curr-reg == 0) continue
21916       3d/compare-eax-and 0/imm32
21917       74/jump-if-= $register-within-list-with-conflict?:continue/disp8
21918       # if (curr-reg == target) check for conflict
21919       (string-equal? %eax %ebx)  # => eax
21920       3d/compare-eax-and 0/imm32/false
21921       {
21922         74/jump-if-= break/disp8
21923 #?         (write-buffered Stderr "conflict?\n")
21924 #?         (flush Stderr)
21925         # var return-inouts/eax: (addr stmt-var) = stmt->inouts
21926         8b/-> *(ebp+0x14) 0/r32/eax
21927         (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21928         (register-conflict? %ebx %eax *(ebp+0xc))  # => eax
21929         eb/jump $register-within-list-with-conflict?:end/disp8
21930       }
21931 $register-within-list-with-conflict?:continue:
21932       # curr = curr->next
21933       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
21934       89/<- %ecx 0/r32/eax
21935       e9/jump loop/disp32
21936     }
21937     # return false
21938     b8/copy-to-eax 0/imm32/false
21939 $register-within-list-with-conflict?:end:
21940     # . restore registers
21941     5f/pop-to-edi
21942     5e/pop-to-esi
21943     5b/pop-to-ebx
21944     5a/pop-to-edx
21945     59/pop-to-ecx
21946     # . epilogue
21947     89/<- %esp 5/r32/ebp
21948     5d/pop-to-ebp
21949     c3/return
21950 
21951 # At the first occurrence of register 'reg' in fn-outputs,
21952 # check if the corresponding element of return-inouts has a different register.
21953 # This hacky helper is intended to be called in one specific place. Don't
21954 # reuse it as is.
21955 register-conflict?:  # reg: (addr array byte), return-inouts: (addr stmt-var), fn-outputs: (addr list var) => result/eax: boolean
21956     # . prologue
21957     55/push-ebp
21958     89/<- %ebp 4/r32/esp
21959     # . save registers
21960     51/push-ecx
21961     52/push-edx
21962     53/push-ebx
21963     56/push-esi
21964     57/push-edi
21965 #?     (write-buffered Stderr "BB: ")
21966 #?     (write-buffered Stderr *(ebp+8))
21967 #?     (write-buffered Stderr Newline)
21968 #?     (flush Stderr)
21969     # var curr-output/edi: (addr list var) = fn-outputs
21970     8b/-> *(ebp+0x10) 7/r32/edi
21971     # var curr-inout/esi: (addr stmt-var) = return-inouts
21972     8b/-> *(ebp+0xc) 6/r32/esi
21973     {
21974       # if (curr-output == 0) abort
21975       81 7/subop/compare %edi 0/imm32
21976       0f 84/jump-if-= break/disp32
21977       # if (curr-output->value->register != reg) continue
21978       (lookup *edi *(edi+4))  # List-value List-value => eax
21979       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
21980       (string-equal? %eax *(ebp+8))  # => eax
21981       3d/compare-eax-and 0/imm32/false
21982       0f 84/jump-if= $register-conflict?:continue/disp32
21983 #?       (write-buffered Stderr "rescan\n")
21984 #?       (flush Stderr)
21985       # var curr-reg/eax: (addr array byte) = curr-inout->value->register
21986       (lookup *esi *(esi+4))  # List-value List-value => eax
21987       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
21988       # if (curr-reg == 0) return true
21989       3d/compare-eax-and 0/imm32
21990       {
21991         75/jump-if-!= break/disp8
21992 #?         (write-buffered Stderr "no register\n")
21993 #?         (flush Stderr)
21994         b8/copy-to-eax 1/imm32/true
21995         e9/jump $register-conflict?:end/disp32
21996       }
21997       # return (curr-reg != reg)
21998       (string-equal? %eax *(ebp+8))  # => eax
21999       3d/compare-eax-and 0/imm32/false
22000       0f 94/set-if-= %al
22001 #?       (write-buffered Stderr "final: ")
22002 #?       (write-int32-hex-buffered Stderr %eax)
22003 #?       (write-buffered Stderr Newline)
22004 #?       (flush Stderr)
22005       eb/jump $register-conflict?:end/disp8
22006 $register-conflict?:continue:
22007       # curr-output = curr-output->next
22008       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
22009       89/<- %edi 0/r32/eax
22010       # curr-inout = curr-inout->next
22011       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
22012       89/<- %esi 0/r32/eax
22013       e9/jump loop/disp32
22014     }
22015     # should never get here
22016     (write-buffered Stderr "register-conflict? misused\n")
22017     (flush Stderr)
22018     e8/call syscall_exit/disp32
22019 $register-conflict?:end:
22020     # . restore registers
22021     5f/pop-to-edi
22022     5e/pop-to-esi
22023     5b/pop-to-ebx
22024     5a/pop-to-edx
22025     59/pop-to-ecx
22026     # . epilogue
22027     89/<- %esp 5/r32/ebp
22028     5d/pop-to-ebp
22029     c3/return
22030 
22031 check-final-stmt-is-return:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22032     # . prologue
22033     55/push-ebp
22034     89/<- %ebp 4/r32/esp
22035     # . save registers
22036     50/push-eax
22037     51/push-ecx
22038     # var curr/ecx: (addr list stmt) = block->stmts
22039     8b/-> *(ebp+8) 0/r32/eax
22040     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
22041     3d/compare-eax-and 0/imm32
22042     74/jump-if-= $check-final-stmt-is-return:end/disp8
22043     89/<- %ecx 0/r32/eax
22044     {
22045       # if curr->next == 0, break
22046       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
22047       3d/compare-eax-and 0/imm32
22048       74/jump-if-= break/disp8
22049       # curr = curr->next
22050       89/<- %ecx 0/r32/eax
22051       e9/jump loop/disp32
22052     }
22053 $check-final-stmt-is-return:check-tag:
22054     # if curr->value->tag != Stmt1, abort
22055     (lookup *ecx *(ecx+4))  # List-value List-value => eax
22056     81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
22057     75/jump-if-!= $check-final-stmt-is-return:error/disp8
22058 $check-final-stmt-is-return:check-operation:
22059     # if curr->operation != "return", abort
22060     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
22061     (string-equal? %eax "return")
22062     3d/compare-eax-and 0/imm32/false
22063     74/jump-if-= $check-final-stmt-is-return:error/disp8
22064 $check-final-stmt-is-return:end:
22065     # . restore registers
22066     59/pop-to-ecx
22067     58/pop-to-eax
22068     # . epilogue
22069     89/<- %esp 5/r32/ebp
22070     5d/pop-to-ebp
22071     c3/return
22072 
22073 $check-final-stmt-is-return:error:
22074     (write-buffered *(ebp+0x10) "fn ")
22075     8b/-> *(ebp+0xc) 0/r32/eax
22076     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22077     (write-buffered *(ebp+0x10) %eax)
22078     (write-buffered *(ebp+0x10) ": final statement should be a 'return'\n")
22079     (flush *(ebp+0x10))
22080     (stop *(ebp+0x14) 1)
22081     # never gets here
22082 
22083 check-no-breaks:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22084     # . prologue
22085     55/push-ebp
22086     89/<- %ebp 4/r32/esp
22087     # . save registers
22088     50/push-eax
22089     51/push-ecx
22090     # var curr/ecx: (addr list stmt) = block->stmts
22091     8b/-> *(ebp+8) 0/r32/eax
22092     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
22093     3d/compare-eax-and 0/imm32
22094     0f 84/jump-if-= $check-no-breaks:end/disp32
22095     89/<- %ecx 0/r32/eax
22096     {
22097       # if curr->next == 0, break
22098       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
22099       3d/compare-eax-and 0/imm32
22100       74/jump-if-= break/disp8
22101       # if curr->value->tag != Stmt1, continue
22102       (lookup *ecx *(ecx+4))  # List-value List-value => eax
22103       81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
22104       75/jump-if-!= $check-no-breaks:continue/disp8
22105       # if curr->value->operation starts with "break", abort
22106       (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
22107       (string-starts-with? %eax "break")  # => eax
22108       3d/compare-eax-and 0/imm32/false
22109       75/jump-if-!= $check-no-breaks:error/disp8
22110 $check-no-breaks:continue:
22111       # curr = curr->next
22112       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
22113       89/<- %ecx 0/r32/eax
22114       e9/jump loop/disp32
22115     }
22116 $check-no-breaks:end:
22117     # . restore registers
22118     59/pop-to-ecx
22119     58/pop-to-eax
22120     # . epilogue
22121     89/<- %esp 5/r32/ebp
22122     5d/pop-to-ebp
22123     c3/return
22124 
22125 $check-no-breaks:error:
22126     (write-buffered *(ebp+0x10) "fn ")
22127     8b/-> *(ebp+0xc) 0/r32/eax
22128     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22129     (write-buffered *(ebp+0x10) %eax)
22130     (write-buffered *(ebp+0x10) " has outputs, so you cannot 'break' out of the outermost block. Use 'return'.\n")
22131     (flush *(ebp+0x10))
22132     (stop *(ebp+0x14) 1)
22133     # never gets here
22134 
22135 check-mu-get-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22136     # . prologue
22137     55/push-ebp
22138     89/<- %ebp 4/r32/esp
22139     # . save registers
22140     50/push-eax
22141     51/push-ecx
22142     52/push-edx
22143     53/push-ebx
22144     56/push-esi
22145     57/push-edi
22146     # esi = stmt
22147     8b/-> *(ebp+8) 6/r32/esi
22148     # - check for 0 inouts
22149     # var base/ecx: (addr var) = stmt->inouts->value
22150     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22151     3d/compare-eax-and 0/imm32/false
22152     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-inouts/disp32
22153     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22154     89/<- %ecx 0/r32/eax
22155 $check-mu-get-stmt:check-base:
22156     # - check base type
22157     # if it's an 'addr', check that it's in a register
22158     # var base-type/ebx: (addr type-tree) = lookup(base->type)
22159     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
22160     89/<- %ebx 0/r32/eax
22161     {
22162       81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
22163       0f 85/jump-if-!= break/disp32
22164 $check-mu-get-stmt:base-is-compound:
22165       # if (type->left != addr) break
22166       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22167       (is-simple-mu-type? %eax 2)  # addr => eax
22168       3d/compare-eax-and 0/imm32/false
22169       74/jump-if-= break/disp8
22170 $check-mu-get-stmt:base-is-addr:
22171       # now check for register
22172       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
22173       0f 84/jump-if-= $check-mu-get-stmt:error-base-type-addr-but-not-register/disp32
22174 $check-mu-get-stmt:base-is-addr-in-register:
22175       # type->left is now an addr; skip it
22176       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22177       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
22178       0f 85/jump-if-!= $check-mu-get-stmt:error-bad-base/disp32
22179 $check-mu-get-stmt:base-is-addr-to-atom-in-register:
22180       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22181       89/<- %ebx 0/r32/eax
22182     }
22183 $check-mu-get-stmt:check-base-typeinfo:
22184     # ensure type is a container
22185     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
22186     {
22187       75/jump-if-!= break/disp8
22188       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22189       89/<- %ebx 0/r32/eax
22190     }
22191     # var base-type-id/ebx: type-id = base-type->value
22192     8b/-> *(ebx+4) 3/r32/ebx  # Type-tree-value
22193     (is-container? %ebx)  # => eax
22194     3d/compare-eax-and 0/imm32/false
22195     0f 84/jump-if-= $check-mu-get-stmt:error-bad-base/disp32
22196     # var base-typeinfo/edx: (addr typeinfo) = find-typeinfo(base-type-id)
22197     # . var container/ecx: (handle typeinfo)
22198     68/push 0/imm32
22199     68/push 0/imm32
22200     89/<- %ecx 4/r32/esp
22201     # .
22202     (find-typeinfo %ebx %ecx)
22203     (lookup *ecx *(ecx+4))  # => eax
22204     # . reclaim container
22205     81 0/subop/add %esp 8/imm32
22206     # .
22207     89/<- %edx 0/r32/eax
22208     # var offset/ecx: (addr stmt-var) = stmt->inouts->next
22209     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22210     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
22211     89/<- %ecx 0/r32/eax
22212     # - check for 1 inout
22213     3d/compare-eax-and 0/imm32/false
22214     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-inouts/disp32
22215     # var offset/ecx: (addr var) = lookup(offset->value)
22216     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
22217     89/<- %ecx 0/r32/eax
22218     # - check for valid field
22219     81 7/subop/compare *(ecx+0x14) -1/imm32/uninitialized  # Var-offset
22220     0f 84/jump-if-= $check-mu-get-stmt:error-bad-field/disp32
22221     # - check for too many inouts
22222     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22223     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
22224     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
22225     3d/compare-eax-and 0/imm32/false
22226     0f 85/jump-if-!= $check-mu-get-stmt:error-too-many-inouts/disp32
22227     # var output/edi: (addr var) = stmt->outputs->value
22228     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22229     # - check for 0 outputs
22230     3d/compare-eax-and 0/imm32/false
22231     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-outputs/disp32
22232     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22233     89/<- %edi 0/r32/eax
22234 $check-mu-get-stmt:check-output-type:
22235     # - check output type
22236     # must be in register
22237     (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
22238     3d/compare-eax-and 0/imm32
22239     0f 84/jump-if-= $check-mu-get-stmt:error-output-not-in-register/disp32
22240     # must have a non-atomic type
22241     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
22242     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
22243     0f 85/jump-if-!= $check-mu-get-stmt:error-output-type-not-address/disp32
22244     # type must start with (addr ...)
22245     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22246     (is-simple-mu-type? %eax 2)  # => eax
22247     3d/compare-eax-and 0/imm32/false
22248     0f 84/jump-if-= $check-mu-get-stmt:error-output-type-not-address/disp32
22249 $check-mu-get-stmt:check-output-type-match:
22250     # payload of addr type must match 'type' definition
22251     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
22252     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
22253     # if (payload->right == null) payload = payload->left
22254     81 7/subop/compare *(eax+0xc) 0/imm32/null  # Type-tree-right
22255     {
22256       75/jump-if-!= break/disp8
22257       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22258     }
22259     89/<- %edi 0/r32/eax
22260     # . var output-name/ecx: (addr array byte)
22261     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22262     89/<- %ecx 0/r32/eax
22263     # . var base-typeinfo-entry/eax: (addr handle typeinfo-entry)
22264     (lookup *(edx+4) *(edx+8))  # Typeinfo-fields Typeinfo-fields => eax
22265     (get %eax %ecx 0x10)  # => eax
22266     # .
22267     (lookup *eax *(eax+4))  # => eax
22268     (lookup *eax *(eax+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
22269     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22270     # .
22271     (type-equal? %edi %eax)  # => eax
22272     3d/compare-eax-and 0/imm32/false
22273     0f 84/jump-if-= $check-mu-get-stmt:error-bad-output-type/disp32
22274     # - check for too many outputs
22275     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22276     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
22277     3d/compare-eax-and 0/imm32/false
22278     0f 85/jump-if-!= $check-mu-get-stmt:error-too-many-outputs/disp32
22279 $check-mu-get-stmt:end:
22280     # . restore registers
22281     5f/pop-to-edi
22282     5e/pop-to-esi
22283     5b/pop-to-ebx
22284     5a/pop-to-edx
22285     59/pop-to-ecx
22286     58/pop-to-eax
22287     # . epilogue
22288     89/<- %esp 5/r32/ebp
22289     5d/pop-to-ebp
22290     c3/return
22291 
22292 $check-mu-get-stmt:error-too-few-inouts:
22293     (write-buffered *(ebp+0x10) "fn ")
22294     8b/-> *(ebp+0xc) 0/r32/eax
22295     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22296     (write-buffered *(ebp+0x10) %eax)
22297     (write-buffered *(ebp+0x10) ": stmt get: too few inouts (2 required)\n")
22298     (flush *(ebp+0x10))
22299     (stop *(ebp+0x14) 1)
22300     # never gets here
22301 
22302 $check-mu-get-stmt:error-too-many-inouts:
22303     (write-buffered *(ebp+0x10) "fn ")
22304     8b/-> *(ebp+0xc) 0/r32/eax
22305     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22306     (write-buffered *(ebp+0x10) %eax)
22307     (write-buffered *(ebp+0x10) ": stmt get: too many inouts (2 required)\n")
22308     (flush *(ebp+0x10))
22309     (stop *(ebp+0x14) 1)
22310     # never gets here
22311 
22312 $check-mu-get-stmt:error-too-few-outputs:
22313     (write-buffered *(ebp+0x10) "fn ")
22314     8b/-> *(ebp+0xc) 0/r32/eax
22315     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22316     (write-buffered *(ebp+0x10) %eax)
22317     (write-buffered *(ebp+0x10) ": stmt get: must have an output\n")
22318     (flush *(ebp+0x10))
22319     (stop *(ebp+0x14) 1)
22320     # never gets here
22321 
22322 $check-mu-get-stmt:error-too-many-outputs:
22323     (write-buffered *(ebp+0x10) "fn ")
22324     8b/-> *(ebp+0xc) 0/r32/eax
22325     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22326     (write-buffered *(ebp+0x10) %eax)
22327     (write-buffered *(ebp+0x10) ": stmt get: too many outputs (1 required)\n")
22328     (flush *(ebp+0x10))
22329     (stop *(ebp+0x14) 1)
22330     # never gets here
22331 
22332 $check-mu-get-stmt:error-bad-base:
22333     # error("fn " fn ": stmt get: var '" base->name "' must have a 'type' definition\n")
22334     (write-buffered *(ebp+0x10) "fn ")
22335     8b/-> *(ebp+0xc) 0/r32/eax
22336     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22337     (write-buffered *(ebp+0x10) %eax)
22338     (write-buffered *(ebp+0x10) ": stmt get: var '")
22339     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22340     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22341     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22342     (write-buffered *(ebp+0x10) %eax)
22343     (write-buffered *(ebp+0x10) "' must have a 'type' definition\n")
22344     (flush *(ebp+0x10))
22345     (stop *(ebp+0x14) 1)
22346     # never gets here
22347 
22348 $check-mu-get-stmt:error-base-type-addr-but-not-register:
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 get: var '")
22354     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22355     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22356     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22357     (write-buffered *(ebp+0x10) %eax)
22358     (write-buffered *(ebp+0x10) "' is an 'addr' type, and so must live in a register\n")
22359     (flush *(ebp+0x10))
22360     (stop *(ebp+0x14) 1)
22361     # never gets here
22362 
22363 $check-mu-get-stmt:error-bad-field:
22364     # error("fn " fn ": stmt get: type " type " has no member called '" curr->name "'\n")
22365     (write-buffered *(ebp+0x10) "fn ")
22366     8b/-> *(ebp+0xc) 0/r32/eax
22367     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22368     (write-buffered *(ebp+0x10) %eax)
22369     (write-buffered *(ebp+0x10) ": stmt get: type '")
22370     # . write(Type-id->data[tmp])
22371     bf/copy-to-edi Type-id/imm32
22372     8b/-> *(edi+ebx<<2+0xc) 6/r32/esi
22373     {
22374       81 7/subop/compare %esi 0/imm32
22375       74/jump-if-= break/disp8
22376       (write-buffered *(ebp+0x10) %esi)
22377     }
22378     # .
22379     (write-buffered *(ebp+0x10) "' has no member called '")
22380     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22381     (write-buffered *(ebp+0x10) %eax)
22382     (write-buffered *(ebp+0x10) "'\n")
22383     (flush *(ebp+0x10))
22384     (stop *(ebp+0x14) 1)
22385     # never gets here
22386 
22387 $check-mu-get-stmt:error-output-not-in-register:
22388     (write-buffered *(ebp+0x10) "fn ")
22389     8b/-> *(ebp+0xc) 0/r32/eax
22390     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22391     (write-buffered *(ebp+0x10) %eax)
22392     (write-buffered *(ebp+0x10) ": stmt get: output '")
22393     (lookup *edi *(edi+4))  # Var-name Var-name => eax
22394     (write-buffered *(ebp+0x10) %eax)
22395     (write-buffered *(ebp+0x10) "' is not in a register\n")
22396     (flush *(ebp+0x10))
22397     (stop *(ebp+0x14) 1)
22398     # never gets here
22399 
22400 $check-mu-get-stmt:error-output-type-not-address:
22401     (write-buffered *(ebp+0x10) "fn ")
22402     8b/-> *(ebp+0xc) 0/r32/eax
22403     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22404     (write-buffered *(ebp+0x10) %eax)
22405     (write-buffered *(ebp+0x10) ": stmt get: output must be an addr\n")
22406     (flush *(ebp+0x10))
22407     (stop *(ebp+0x14) 1)
22408     # never gets here
22409 
22410 $check-mu-get-stmt:error-bad-output-type:
22411     (write-buffered *(ebp+0x10) "fn ")
22412     8b/-> *(ebp+0xc) 0/r32/eax
22413     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22414     (write-buffered *(ebp+0x10) %eax)
22415     (write-buffered *(ebp+0x10) ": stmt get: wrong output type for member '")
22416     (write-buffered *(ebp+0x10) %ecx)
22417     (write-buffered *(ebp+0x10) "' of type '")
22418     bf/copy-to-edi Type-id/imm32
22419     8b/-> *(edi+ebx<<2+0xc) 6/r32/esi
22420     {
22421       81 7/subop/compare %esi 0/imm32
22422       74/jump-if-= break/disp8
22423       (write-buffered *(ebp+0x10) %esi)
22424     }
22425     (write-buffered *(ebp+0x10) "'\n")
22426     (flush *(ebp+0x10))
22427     (stop *(ebp+0x14) 1)
22428     # never gets here
22429 
22430 check-mu-index-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22431     # . prologue
22432     55/push-ebp
22433     89/<- %ebp 4/r32/esp
22434     # . save registers
22435     50/push-eax
22436     51/push-ecx
22437     52/push-edx
22438     53/push-ebx
22439     56/push-esi
22440     57/push-edi
22441     # esi = stmt
22442     8b/-> *(ebp+8) 6/r32/esi
22443     # - check for 0 inouts
22444     # var base/ecx: (addr var) = stmt->inouts->value
22445     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22446 $check-mu-index-stmt:check-no-inouts:
22447     3d/compare-eax-and 0/imm32
22448     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-inouts/disp32
22449     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22450     89/<- %ecx 0/r32/eax
22451     # - check base type is either (addr array ...) in register or (array ...) on stack
22452     # var base-type/ebx: (addr type-tree) = lookup(base->type)
22453     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
22454     89/<- %ebx 0/r32/eax
22455     # if base-type is an atom, abort with a precise error
22456     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
22457     {
22458       74/jump-if-= break/disp8
22459       (is-simple-mu-type? %ebx 3)  # array => eax
22460       3d/compare-eax-and 0/imm32/false
22461       0f 85/jump-if-!= $check-mu-index-stmt:error-base-array-atom-type/disp32
22462       0f 84/jump-if-= $check-mu-index-stmt:error-base-non-array-type/disp32
22463     }
22464 $check-mu-index-stmt:base-is-compound:
22465     # if type->left not addr or array, abort
22466     {
22467       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22468       (is-simple-mu-type? %eax 2)  # addr => eax
22469       3d/compare-eax-and 0/imm32/false
22470       75/jump-if-!= break/disp8
22471       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22472       (is-simple-mu-type? %eax 3)  # array => eax
22473       3d/compare-eax-and 0/imm32/false
22474       75/jump-if-!= break/disp8
22475       e9/jump $check-mu-index-stmt:error-base-non-array-type/disp32
22476     }
22477     # if (type->left == addr) ensure type->right->left == array and type->register exists
22478     {
22479       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22480       (is-simple-mu-type? %eax 2)  # addr => eax
22481       3d/compare-eax-and 0/imm32/false
22482       74/jump-if-= break/disp8
22483 $check-mu-index-stmt:base-is-addr:
22484       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22485       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22486       (is-simple-mu-type? %eax 3)  # array => eax
22487       3d/compare-eax-and 0/imm32/false
22488       0f 84/jump-if-= $check-mu-index-stmt:error-base-non-array-type/disp32
22489 $check-mu-index-stmt:check-base-addr-is-register:
22490       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
22491       0f 84/jump-if-= $check-mu-index-stmt:error-base-address-array-type-on-stack/disp32
22492     }
22493     # if (type->left == array) ensure type->register doesn't exist
22494     {
22495       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22496       (is-simple-mu-type? %eax 3)  # array => eax
22497       3d/compare-eax-and 0/imm32/false
22498       74/jump-if-= break/disp8
22499 $check-mu-index-stmt:base-is-array:
22500       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
22501       0f 85/jump-if-!= $check-mu-index-stmt:error-base-array-type-in-register/disp32
22502     }
22503     # if (base-type->left == addr) base-type = base-type->right
22504     {
22505       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22506       (is-simple-mu-type? %eax 2)  # addr => eax
22507       3d/compare-eax-and 0/imm32/false
22508       74/jump-if-= break/disp8
22509       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22510       89/<- %ebx 0/r32/eax
22511     }
22512     # - check for 1 inout
22513     # var index/ecx: (addr stmt-var) = stmt->inouts->next->value
22514     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22515     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
22516 $check-mu-index-stmt:check-single-inout:
22517     3d/compare-eax-and 0/imm32
22518     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-inouts/disp32
22519     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22520     89/<- %ecx 0/r32/eax
22521     # - check index is either a literal or register
22522     # var index-type/edx: (addr type-tree)
22523     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
22524     89/<- %edx 0/r32/eax
22525     # if index type is an atom, it must be a literal or int
22526     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
22527     {
22528       74/jump-if-= break/disp8
22529 $check-mu-index-stmt:index-type-is-atom:
22530       (is-simple-mu-type? %edx 0)  # literal => eax
22531       3d/compare-eax-and 0/imm32/false
22532       75/jump-if-!= $check-mu-index-stmt:index-type-done/disp8
22533       (is-simple-mu-type? %edx 1)  # int => eax
22534       3d/compare-eax-and 0/imm32/false
22535       75/jump-if-!= $check-mu-index-stmt:index-type-done/disp8
22536       (is-simple-mu-type? %edx 7)  # offset => eax
22537       3d/compare-eax-and 0/imm32/false
22538       0f 85/jump-if-!= $check-mu-index-stmt:error-index-offset-atom-type/disp32
22539       e9/jump $check-mu-index-stmt:error-invalid-index-type/disp32
22540     }
22541     # if index type is a non-atom: it must be an offset
22542     {
22543       75/jump-if-!= break/disp8
22544 $check-mu-index-stmt:index-type-is-non-atom:
22545       (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
22546       (is-simple-mu-type? %eax 7)  # offset => eax
22547       3d/compare-eax-and 0/imm32/false
22548       0f 84/jump-if-= $check-mu-index-stmt:error-invalid-index-type/disp32
22549     }
22550 $check-mu-index-stmt:index-type-done:
22551     # check index is either a literal or in a register
22552     {
22553       (is-simple-mu-type? %edx 0)  # literal => eax
22554       3d/compare-eax-and 0/imm32/false
22555       75/jump-if-!= break/disp8
22556 $check-mu-index-stmt:check-index-in-register:
22557       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
22558       0f 84/jump-if-= $check-mu-index-stmt:error-index-on-stack/disp32
22559     }
22560     # - if index is an 'int', check that element type of base has size 1, 2, 4 or 8 bytes.
22561     {
22562       (is-simple-mu-type? %edx 1)  # int => eax
22563       3d/compare-eax-and 0/imm32/false
22564       74/jump-if-= break/disp8
22565 $check-mu-index-stmt:check-index-can-be-int:
22566       (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22567       (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22568       (array-element-size %eax)  # => eax
22569       3d/compare-eax-and 1/imm32
22570       74/jump-if-= break/disp8
22571       3d/compare-eax-and 2/imm32
22572       74/jump-if-= break/disp8
22573       3d/compare-eax-and 4/imm32
22574       74/jump-if-= break/disp8
22575       3d/compare-eax-and 8/imm32
22576       74/jump-if-= break/disp8
22577       e9/jump $check-mu-index-stmt:error-index-needs-offset/disp32
22578     }
22579     # - check for too many inouts
22580     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22581     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
22582     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
22583     3d/compare-eax-and 0/imm32/false
22584     0f 85/jump-if-!= $check-mu-index-stmt:error-too-many-inouts/disp32
22585     # - check for 0 outputs
22586     # var output/edi: (addr var) = stmt->outputs->value
22587     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22588     3d/compare-eax-and 0/imm32/false
22589     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-outputs/disp32
22590     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22591     89/<- %edi 0/r32/eax
22592     # - check output type
22593     # must have a non-atomic type
22594     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
22595     89/<- %edx 0/r32/eax
22596     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
22597     0f 85/jump-if-!= $check-mu-index-stmt:error-output-type-not-address/disp32
22598     # type must start with (addr ...)
22599     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
22600     (is-simple-mu-type? %eax 2)  # addr => eax
22601     3d/compare-eax-and 0/imm32/false
22602     0f 84/jump-if-= $check-mu-index-stmt:error-output-type-not-address/disp32
22603     # if tail(base-type) != tail(output-type) abort
22604     (type-tail %ebx)  # => eax
22605     89/<- %ebx 0/r32/eax
22606     (type-tail %edx)  # => eax
22607     (type-equal? %ebx %eax)  # => eax
22608     3d/compare-eax-and 0/imm32/false
22609     0f 84/jump-if-= $check-mu-index-stmt:error-bad-output-type/disp32
22610     # - check for too many outputs
22611     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22612     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
22613     3d/compare-eax-and 0/imm32/false
22614     0f 85/jump-if-!= $check-mu-index-stmt:error-too-many-outputs/disp32
22615 $check-mu-index-stmt:end:
22616     # . restore registers
22617     5f/pop-to-edi
22618     5e/pop-to-esi
22619     5b/pop-to-ebx
22620     5a/pop-to-edx
22621     59/pop-to-ecx
22622     58/pop-to-eax
22623     # . epilogue
22624     89/<- %esp 5/r32/ebp
22625     5d/pop-to-ebp
22626     c3/return
22627 
22628 $check-mu-index-stmt:error-base-non-array-type:
22629     (write-buffered *(ebp+0x10) "fn ")
22630     8b/-> *(ebp+0xc) 0/r32/eax
22631     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22632     (write-buffered *(ebp+0x10) %eax)
22633     (write-buffered *(ebp+0x10) ": stmt index: var '")
22634     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22635     (write-buffered *(ebp+0x10) %eax)
22636     (write-buffered *(ebp+0x10) "' is not an array\n")
22637     (flush *(ebp+0x10))
22638     (stop *(ebp+0x14) 1)
22639     # never gets here
22640 
22641 $check-mu-index-stmt:error-base-array-atom-type:
22642     (write-buffered *(ebp+0x10) "fn ")
22643     8b/-> *(ebp+0xc) 0/r32/eax
22644     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22645     (write-buffered *(ebp+0x10) %eax)
22646     (write-buffered *(ebp+0x10) ": stmt index: array '")
22647     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22648     (write-buffered *(ebp+0x10) %eax)
22649     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
22650     (flush *(ebp+0x10))
22651     (stop *(ebp+0x14) 1)
22652     # never gets here
22653 
22654 $check-mu-index-stmt:error-base-address-array-type-on-stack:
22655     (write-buffered *(ebp+0x10) "fn ")
22656     8b/-> *(ebp+0xc) 0/r32/eax
22657     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22658     (write-buffered *(ebp+0x10) %eax)
22659     (write-buffered *(ebp+0x10) ": stmt index: var '")
22660     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22661     (write-buffered *(ebp+0x10) %eax)
22662     (write-buffered *(ebp+0x10) "' is an addr to an array, and so must live in a register\n")
22663     (flush *(ebp+0x10))
22664     (stop *(ebp+0x14) 1)
22665     # never gets here
22666 
22667 $check-mu-index-stmt:error-base-array-type-in-register:
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 index: var '")
22673     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22674     (write-buffered *(ebp+0x10) %eax)
22675     (write-buffered *(ebp+0x10) "' is an array, and so must live on the stack\n")
22676     (flush *(ebp+0x10))
22677     (stop *(ebp+0x14) 1)
22678     # never gets here
22679 
22680 $check-mu-index-stmt:error-too-few-inouts:
22681     (write-buffered *(ebp+0x10) "fn ")
22682     8b/-> *(ebp+0xc) 0/r32/eax
22683     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22684     (write-buffered *(ebp+0x10) %eax)
22685     (write-buffered *(ebp+0x10) ": stmt index: too few inouts (2 required)\n")
22686     (flush *(ebp+0x10))
22687     (stop *(ebp+0x14) 1)
22688     # never gets here
22689 
22690 $check-mu-index-stmt:error-invalid-index-type:
22691     (write-buffered *(ebp+0x10) "fn ")
22692     8b/-> *(ebp+0xc) 0/r32/eax
22693     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22694     (write-buffered *(ebp+0x10) %eax)
22695     (write-buffered *(ebp+0x10) ": stmt index: second argument '")
22696     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22697     (write-buffered *(ebp+0x10) %eax)
22698     (write-buffered *(ebp+0x10) "' must be an int or offset\n")
22699     (flush *(ebp+0x10))
22700     (stop *(ebp+0x14) 1)
22701     # never gets here
22702 
22703 $check-mu-index-stmt:error-index-offset-atom-type:
22704     (write-buffered *(ebp+0x10) "fn ")
22705     8b/-> *(ebp+0xc) 0/r32/eax
22706     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22707     (write-buffered *(ebp+0x10) %eax)
22708     (write-buffered *(ebp+0x10) ": stmt index: offset '")
22709     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22710     (write-buffered *(ebp+0x10) %eax)
22711     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
22712     (flush *(ebp+0x10))
22713     (stop *(ebp+0x14) 1)
22714     # never gets here
22715 
22716 $check-mu-index-stmt:error-index-on-stack:
22717     (write-buffered *(ebp+0x10) "fn ")
22718     8b/-> *(ebp+0xc) 0/r32/eax
22719     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22720     (write-buffered *(ebp+0x10) %eax)
22721     (write-buffered *(ebp+0x10) ": stmt index: second argument '")
22722     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22723     (write-buffered *(ebp+0x10) %eax)
22724     (write-buffered *(ebp+0x10) "' must be in a register\n")
22725     (flush *(ebp+0x10))
22726     (stop *(ebp+0x14) 1)
22727     # never gets here
22728 
22729 $check-mu-index-stmt:error-index-needs-offset:
22730     (write-buffered *(ebp+0x10) "fn ")
22731     8b/-> *(ebp+0xc) 0/r32/eax
22732     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22733     (write-buffered *(ebp+0x10) %eax)
22734     (write-buffered *(ebp+0x10) ": stmt index: cannot take an int for array '")
22735     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22736     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22737     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22738     (write-buffered *(ebp+0x10) %eax)
22739     (write-buffered *(ebp+0x10) "'; create an offset instead. See mu.md for details.\n")
22740     (flush *(ebp+0x10))
22741     (stop *(ebp+0x14) 1)
22742     # never gets here
22743 
22744 $check-mu-index-stmt:error-too-many-inouts:
22745     (write-buffered *(ebp+0x10) "fn ")
22746     8b/-> *(ebp+0xc) 0/r32/eax
22747     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22748     (write-buffered *(ebp+0x10) %eax)
22749     (write-buffered *(ebp+0x10) ": stmt index: too many inouts (2 required)\n")
22750     (flush *(ebp+0x10))
22751     (stop *(ebp+0x14) 1)
22752     # never gets here
22753 
22754 $check-mu-index-stmt:error-too-few-outputs:
22755     (write-buffered *(ebp+0x10) "fn ")
22756     8b/-> *(ebp+0xc) 0/r32/eax
22757     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22758     (write-buffered *(ebp+0x10) %eax)
22759     (write-buffered *(ebp+0x10) ": stmt index: must have an output\n")
22760     (flush *(ebp+0x10))
22761     (stop *(ebp+0x14) 1)
22762     # never gets here
22763 
22764 $check-mu-index-stmt:error-too-many-outputs:
22765     (write-buffered *(ebp+0x10) "fn ")
22766     8b/-> *(ebp+0xc) 0/r32/eax
22767     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22768     (write-buffered *(ebp+0x10) %eax)
22769     (write-buffered *(ebp+0x10) ": stmt index: too many outputs (1 required)\n")
22770     (flush *(ebp+0x10))
22771     (stop *(ebp+0x14) 1)
22772     # never gets here
22773 
22774 $check-mu-index-stmt:error-output-not-in-register:
22775     (write-buffered *(ebp+0x10) "fn ")
22776     8b/-> *(ebp+0xc) 0/r32/eax
22777     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22778     (write-buffered *(ebp+0x10) %eax)
22779     (write-buffered *(ebp+0x10) ": stmt index: output '")
22780     (lookup *edi *(edi+4))  # Var-name Var-name => eax
22781     (write-buffered *(ebp+0x10) %eax)
22782     (write-buffered *(ebp+0x10) "' is not in a register\n")
22783     (flush *(ebp+0x10))
22784     (stop *(ebp+0x14) 1)
22785     # never gets here
22786 
22787 $check-mu-index-stmt:error-output-type-not-address:
22788     (write-buffered *(ebp+0x10) "fn ")
22789     8b/-> *(ebp+0xc) 0/r32/eax
22790     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22791     (write-buffered *(ebp+0x10) %eax)
22792     (write-buffered *(ebp+0x10) ": stmt index: output '")
22793     (lookup *edi *(edi+4))  # Var-name Var-name => eax
22794     (write-buffered *(ebp+0x10) %eax)
22795     (write-buffered *(ebp+0x10) "' must be an addr\n")
22796     (flush *(ebp+0x10))
22797     (stop *(ebp+0x14) 1)
22798     # never gets here
22799 
22800 $check-mu-index-stmt:error-bad-output-type:
22801     (write-buffered *(ebp+0x10) "fn ")
22802     8b/-> *(ebp+0xc) 0/r32/eax
22803     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22804     (write-buffered *(ebp+0x10) %eax)
22805     (write-buffered *(ebp+0x10) ": stmt index: output '")
22806     (lookup *edi *(edi+4))  # Var-name Var-name => eax
22807     (write-buffered *(ebp+0x10) %eax)
22808     (write-buffered *(ebp+0x10) "' does not have the right type\n")
22809     (flush *(ebp+0x10))
22810     (stop *(ebp+0x14) 1)
22811     # never gets here
22812 
22813 check-mu-length-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22814     # . prologue
22815     55/push-ebp
22816     89/<- %ebp 4/r32/esp
22817     # . save registers
22818     50/push-eax
22819     51/push-ecx
22820     52/push-edx
22821     53/push-ebx
22822     56/push-esi
22823     57/push-edi
22824     # esi = stmt
22825     8b/-> *(ebp+8) 6/r32/esi
22826     # - check for 0 inouts
22827     # var base/ecx: (addr var) = stmt->inouts->value
22828     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22829 $check-mu-length-stmt:check-no-inouts:
22830     3d/compare-eax-and 0/imm32
22831     0f 84/jump-if-= $check-mu-length-stmt:error-too-few-inouts/disp32
22832     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22833     89/<- %ecx 0/r32/eax
22834     # - check base type is either (addr array ...) in register or (array ...) on stack
22835     # var base-type/ebx: (addr type-tree) = lookup(base->type)
22836     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
22837     89/<- %ebx 0/r32/eax
22838     # if base-type is an atom, abort with a precise error
22839     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
22840     {
22841       74/jump-if-= break/disp8
22842       (is-simple-mu-type? %ebx 3)  # array => eax
22843       3d/compare-eax-and 0/imm32/false
22844       0f 85/jump-if-!= $check-mu-length-stmt:error-base-array-atom-type/disp32
22845       0f 84/jump-if-= $check-mu-length-stmt:error-base-non-array-type/disp32
22846     }
22847 $check-mu-length-stmt:base-is-compound:
22848     # if type->left not addr or array, abort
22849     {
22850       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22851       (is-simple-mu-type? %eax 2)  # addr => eax
22852       3d/compare-eax-and 0/imm32/false
22853       75/jump-if-!= break/disp8
22854       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22855       (is-simple-mu-type? %eax 3)  # array => eax
22856       3d/compare-eax-and 0/imm32/false
22857       75/jump-if-!= break/disp8
22858       e9/jump $check-mu-length-stmt:error-base-non-array-type/disp32
22859     }
22860     # if (type->left == addr) ensure type->right->left == array and type->register exists
22861     {
22862       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22863       (is-simple-mu-type? %eax 2)  # addr => eax
22864       3d/compare-eax-and 0/imm32/false
22865       74/jump-if-= break/disp8
22866 $check-mu-length-stmt:base-is-addr:
22867       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22868       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22869       (is-simple-mu-type? %eax 3)  # array => eax
22870       3d/compare-eax-and 0/imm32/false
22871       0f 84/jump-if-= $check-mu-length-stmt:error-base-non-array-type/disp32
22872 $check-mu-length-stmt:check-base-addr-is-register:
22873       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
22874       0f 84/jump-if-= $check-mu-length-stmt:error-base-address-array-type-on-stack/disp32
22875     }
22876     # if (type->left == array) ensure type->register doesn't exist
22877     {
22878       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22879       (is-simple-mu-type? %eax 3)  # array => eax
22880       3d/compare-eax-and 0/imm32/false
22881       74/jump-if-= break/disp8
22882 $check-mu-length-stmt:base-is-array:
22883       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
22884       0f 85/jump-if-!= $check-mu-length-stmt:error-base-array-type-in-register/disp32
22885     }
22886     # if (base-type->left == addr) base-type = base-type->right
22887     {
22888       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22889       (is-simple-mu-type? %eax 2)  # addr => eax
22890       3d/compare-eax-and 0/imm32/false
22891       74/jump-if-= break/disp8
22892       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22893       89/<- %ebx 0/r32/eax
22894     }
22895     # - check for too many inouts
22896     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22897     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
22898     3d/compare-eax-and 0/imm32/false
22899     0f 85/jump-if-!= $check-mu-length-stmt:error-too-many-inouts/disp32
22900     # - check for 0 outputs
22901     # var output/edi: (addr var) = stmt->outputs->value
22902     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22903     3d/compare-eax-and 0/imm32/false
22904     0f 84/jump-if-= $check-mu-length-stmt:error-too-few-outputs/disp32
22905     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22906     89/<- %edi 0/r32/eax
22907     # - check output type
22908     # must have a non-atomic type
22909     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
22910     (is-simple-mu-type? %eax 1)  # int => eax
22911     3d/compare-eax-and 0/imm32/false
22912     0f 84/jump-if-= $check-mu-length-stmt:error-invalid-output-type/disp32
22913     # - check for too many outputs
22914     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22915     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
22916     3d/compare-eax-and 0/imm32/false
22917     0f 85/jump-if-!= $check-mu-length-stmt:error-too-many-outputs/disp32
22918 $check-mu-length-stmt:end:
22919     # . restore registers
22920     5f/pop-to-edi
22921     5e/pop-to-esi
22922     5b/pop-to-ebx
22923     5a/pop-to-edx
22924     59/pop-to-ecx
22925     58/pop-to-eax
22926     # . epilogue
22927     89/<- %esp 5/r32/ebp
22928     5d/pop-to-ebp
22929     c3/return
22930 
22931 $check-mu-length-stmt:error-base-non-array-type:
22932     (write-buffered *(ebp+0x10) "fn ")
22933     8b/-> *(ebp+0xc) 0/r32/eax
22934     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22935     (write-buffered *(ebp+0x10) %eax)
22936     (write-buffered *(ebp+0x10) ": stmt length: var '")
22937     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22938     (write-buffered *(ebp+0x10) %eax)
22939     (write-buffered *(ebp+0x10) "' is not an array\n")
22940     (flush *(ebp+0x10))
22941     (stop *(ebp+0x14) 1)
22942     # never gets here
22943 
22944 $check-mu-length-stmt:error-base-array-atom-type:
22945     (write-buffered *(ebp+0x10) "fn ")
22946     8b/-> *(ebp+0xc) 0/r32/eax
22947     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22948     (write-buffered *(ebp+0x10) %eax)
22949     (write-buffered *(ebp+0x10) ": stmt length: array '")
22950     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22951     (write-buffered *(ebp+0x10) %eax)
22952     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
22953     (flush *(ebp+0x10))
22954     (stop *(ebp+0x14) 1)
22955     # never gets here
22956 
22957 $check-mu-length-stmt:error-base-address-array-type-on-stack:
22958     (write-buffered *(ebp+0x10) "fn ")
22959     8b/-> *(ebp+0xc) 0/r32/eax
22960     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22961     (write-buffered *(ebp+0x10) %eax)
22962     (write-buffered *(ebp+0x10) ": stmt length: var '")
22963     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22964     (write-buffered *(ebp+0x10) %eax)
22965     (write-buffered *(ebp+0x10) "' is an addr to an array, and so must live in a register\n")
22966     (flush *(ebp+0x10))
22967     (stop *(ebp+0x14) 1)
22968     # never gets here
22969 
22970 $check-mu-length-stmt:error-base-array-type-in-register:
22971     (write-buffered *(ebp+0x10) "fn ")
22972     8b/-> *(ebp+0xc) 0/r32/eax
22973     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22974     (write-buffered *(ebp+0x10) %eax)
22975     (write-buffered *(ebp+0x10) ": stmt length: var '")
22976     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22977     (write-buffered *(ebp+0x10) %eax)
22978     (write-buffered *(ebp+0x10) "' is an array, and so must live on the stack\n")
22979     (flush *(ebp+0x10))
22980     (stop *(ebp+0x14) 1)
22981     # never gets here
22982 
22983 $check-mu-length-stmt:error-too-few-inouts:
22984     (write-buffered *(ebp+0x10) "fn ")
22985     8b/-> *(ebp+0xc) 0/r32/eax
22986     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22987     (write-buffered *(ebp+0x10) %eax)
22988     (write-buffered *(ebp+0x10) ": stmt length: too few inouts (1 required)\n")
22989     (flush *(ebp+0x10))
22990     (stop *(ebp+0x14) 1)
22991     # never gets here
22992 
22993 $check-mu-length-stmt:error-invalid-index-type:
22994     (write-buffered *(ebp+0x10) "fn ")
22995     8b/-> *(ebp+0xc) 0/r32/eax
22996     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22997     (write-buffered *(ebp+0x10) %eax)
22998     (write-buffered *(ebp+0x10) ": stmt length: second argument '")
22999     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
23000     (write-buffered *(ebp+0x10) %eax)
23001     (write-buffered *(ebp+0x10) "' must be an int or offset\n")
23002     (flush *(ebp+0x10))
23003     (stop *(ebp+0x14) 1)
23004     # never gets here
23005 
23006 $check-mu-length-stmt:error-index-offset-atom-type:
23007     (write-buffered *(ebp+0x10) "fn ")
23008     8b/-> *(ebp+0xc) 0/r32/eax
23009     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23010     (write-buffered *(ebp+0x10) %eax)
23011     (write-buffered *(ebp+0x10) ": stmt length: offset '")
23012     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
23013     (write-buffered *(ebp+0x10) %eax)
23014     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
23015     (flush *(ebp+0x10))
23016     (stop *(ebp+0x14) 1)
23017     # never gets here
23018 
23019 $check-mu-length-stmt:error-index-on-stack:
23020     (write-buffered *(ebp+0x10) "fn ")
23021     8b/-> *(ebp+0xc) 0/r32/eax
23022     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23023     (write-buffered *(ebp+0x10) %eax)
23024     (write-buffered *(ebp+0x10) ": stmt length: second argument '")
23025     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
23026     (write-buffered *(ebp+0x10) %eax)
23027     (write-buffered *(ebp+0x10) "' must be in a register\n")
23028     (flush *(ebp+0x10))
23029     (stop *(ebp+0x14) 1)
23030     # never gets here
23031 
23032 $check-mu-length-stmt:error-index-needs-offset:
23033     (write-buffered *(ebp+0x10) "fn ")
23034     8b/-> *(ebp+0xc) 0/r32/eax
23035     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23036     (write-buffered *(ebp+0x10) %eax)
23037     (write-buffered *(ebp+0x10) ": stmt length: cannot take an int for array '")
23038     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23039     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23040     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23041     (write-buffered *(ebp+0x10) %eax)
23042     (write-buffered *(ebp+0x10) "'; create an offset instead. See mu.md for details.\n")
23043     (flush *(ebp+0x10))
23044     (stop *(ebp+0x14) 1)
23045     # never gets here
23046 
23047 $check-mu-length-stmt:error-too-many-inouts:
23048     (write-buffered *(ebp+0x10) "fn ")
23049     8b/-> *(ebp+0xc) 0/r32/eax
23050     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23051     (write-buffered *(ebp+0x10) %eax)
23052     (write-buffered *(ebp+0x10) ": stmt length: too many inouts (1 required)\n")
23053     (flush *(ebp+0x10))
23054     (stop *(ebp+0x14) 1)
23055     # never gets here
23056 
23057 $check-mu-length-stmt:error-too-few-outputs:
23058     (write-buffered *(ebp+0x10) "fn ")
23059     8b/-> *(ebp+0xc) 0/r32/eax
23060     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23061     (write-buffered *(ebp+0x10) %eax)
23062     (write-buffered *(ebp+0x10) ": stmt length: must have an output\n")
23063     (flush *(ebp+0x10))
23064     (stop *(ebp+0x14) 1)
23065     # never gets here
23066 
23067 $check-mu-length-stmt:error-too-many-outputs:
23068     (write-buffered *(ebp+0x10) "fn ")
23069     8b/-> *(ebp+0xc) 0/r32/eax
23070     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23071     (write-buffered *(ebp+0x10) %eax)
23072     (write-buffered *(ebp+0x10) ": stmt length: too many outputs (1 required)\n")
23073     (flush *(ebp+0x10))
23074     (stop *(ebp+0x14) 1)
23075     # never gets here
23076 
23077 $check-mu-length-stmt:error-output-not-in-register:
23078     (write-buffered *(ebp+0x10) "fn ")
23079     8b/-> *(ebp+0xc) 0/r32/eax
23080     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23081     (write-buffered *(ebp+0x10) %eax)
23082     (write-buffered *(ebp+0x10) ": stmt length: output '")
23083     (lookup *edi *(edi+4))  # Var-name Var-name => eax
23084     (write-buffered *(ebp+0x10) %eax)
23085     (write-buffered *(ebp+0x10) "' is not in a register\n")
23086     (flush *(ebp+0x10))
23087     (stop *(ebp+0x14) 1)
23088     # never gets here
23089 
23090 $check-mu-length-stmt:error-invalid-output-type:
23091     (write-buffered *(ebp+0x10) "fn ")
23092     8b/-> *(ebp+0xc) 0/r32/eax
23093     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23094     (write-buffered *(ebp+0x10) %eax)
23095     (write-buffered *(ebp+0x10) ": stmt length: output '")
23096     (lookup *edi *(edi+4))  # Var-name Var-name => eax
23097     (write-buffered *(ebp+0x10) %eax)
23098     (write-buffered *(ebp+0x10) "' does not have the right type\n")
23099     (flush *(ebp+0x10))
23100     (stop *(ebp+0x14) 1)
23101     # never gets here
23102 
23103 check-mu-compute-offset-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23104     # . prologue
23105     55/push-ebp
23106     89/<- %ebp 4/r32/esp
23107     # . save registers
23108     50/push-eax
23109     51/push-ecx
23110     52/push-edx
23111     53/push-ebx
23112     56/push-esi
23113     57/push-edi
23114     # esi = stmt
23115     8b/-> *(ebp+8) 6/r32/esi
23116     # - check for 0 inouts
23117     # var base/ecx: (addr var) = stmt->inouts->value
23118     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23119 $check-mu-compute-offset-stmt:check-no-inouts:
23120     3d/compare-eax-and 0/imm32
23121     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-inouts/disp32
23122     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23123     89/<- %ecx 0/r32/eax
23124     # - check base type is either (addr array ...) in register or (array ...) on stack
23125     # var base-type/ebx: (addr type-tree) = lookup(base->type)
23126     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
23127     89/<- %ebx 0/r32/eax
23128     # if base-type is an atom, abort with a precise error
23129     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
23130     {
23131       74/jump-if-= break/disp8
23132       (is-simple-mu-type? %ebx 3)  # array => eax
23133       3d/compare-eax-and 0/imm32/false
23134       0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-base-array-atom-type/disp32
23135       0f 84/jump-if-= $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
23136     }
23137 $check-mu-compute-offset-stmt:base-is-compound:
23138     # if type->left not addr or array, abort
23139     {
23140       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
23141       (is-simple-mu-type? %eax 2)  # addr => eax
23142       3d/compare-eax-and 0/imm32/false
23143       75/jump-if-!= break/disp8
23144       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
23145       (is-simple-mu-type? %eax 3)  # array => eax
23146       3d/compare-eax-and 0/imm32/false
23147       75/jump-if-!= break/disp8
23148       e9/jump $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
23149     }
23150     # if (type->left == addr) ensure type->right->left == array and type->register exists
23151     {
23152       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
23153       (is-simple-mu-type? %eax 2)  # addr => eax
23154       3d/compare-eax-and 0/imm32/false
23155       74/jump-if-= break/disp8
23156 $check-mu-compute-offset-stmt:base-is-addr:
23157       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23158       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23159       (is-simple-mu-type? %eax 3)  # array => eax
23160       3d/compare-eax-and 0/imm32/false
23161       0f 84/jump-if-= $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
23162     }
23163     # if (base-type->left == addr) base-type = base-type->right
23164     {
23165       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
23166       (is-simple-mu-type? %eax 2)  # addr => eax
23167       3d/compare-eax-and 0/imm32/false
23168       74/jump-if-= break/disp8
23169       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23170       89/<- %ebx 0/r32/eax
23171     }
23172     # - check for 1 inout
23173     # var index/ecx: (addr stmt-var) = stmt->inouts->next->value
23174     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23175     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
23176 $check-mu-compute-offset-stmt:check-single-inout:
23177     3d/compare-eax-and 0/imm32
23178     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-inouts/disp32
23179     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23180     89/<- %ecx 0/r32/eax
23181     # - check index is either a literal or register
23182     # var index-type/edx: (addr type-tree)
23183     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
23184     89/<- %edx 0/r32/eax
23185     # index type must be a literal or int
23186     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
23187     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-invalid-index-type/disp32
23188     {
23189 $check-mu-compute-offset-stmt:index-type-is-atom:
23190       (is-simple-mu-type? %edx 0)  # literal => eax
23191       3d/compare-eax-and 0/imm32/false
23192       75/jump-if-!= break/disp8
23193       (is-simple-mu-type? %edx 1)  # int => eax
23194       3d/compare-eax-and 0/imm32/false
23195       75/jump-if-!= break/disp8
23196       e9/jump $check-mu-compute-offset-stmt:error-invalid-index-type/disp32
23197     }
23198     # - check for too many inouts
23199     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23200     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
23201     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
23202     3d/compare-eax-and 0/imm32/false
23203     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-too-many-inouts/disp32
23204     # - check for 0 outputs
23205     # var output/edi: (addr var) = stmt->outputs->value
23206     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
23207     3d/compare-eax-and 0/imm32/false
23208     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-outputs/disp32
23209     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23210     89/<- %edi 0/r32/eax
23211     # - check output type
23212     # must have a non-atomic type
23213     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
23214     89/<- %edx 0/r32/eax
23215     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
23216     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-output-type-not-offset/disp32
23217     # type must start with (offset ...)
23218     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
23219     (is-simple-mu-type? %eax 7)  # offset => eax
23220     3d/compare-eax-and 0/imm32/false
23221     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-output-type-not-offset/disp32
23222     # if tail(base-type) != tail(output-type) abort
23223     (type-tail %ebx)  # => eax
23224     89/<- %ebx 0/r32/eax
23225     (type-tail %edx)  # => eax
23226     (type-equal? %ebx %eax)  # => eax
23227     3d/compare-eax-and 0/imm32/false
23228     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-bad-output-type/disp32
23229     # - check for too many outputs
23230     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
23231     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
23232     3d/compare-eax-and 0/imm32/false
23233     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-too-many-outputs/disp32
23234 $check-mu-compute-offset-stmt:end:
23235     # . restore registers
23236     5f/pop-to-edi
23237     5e/pop-to-esi
23238     5b/pop-to-ebx
23239     5a/pop-to-edx
23240     59/pop-to-ecx
23241     58/pop-to-eax
23242     # . epilogue
23243     89/<- %esp 5/r32/ebp
23244     5d/pop-to-ebp
23245     c3/return
23246 
23247 $check-mu-compute-offset-stmt:error-base-non-array-type:
23248     (write-buffered *(ebp+0x10) "fn ")
23249     8b/-> *(ebp+0xc) 0/r32/eax
23250     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23251     (write-buffered *(ebp+0x10) %eax)
23252     (write-buffered *(ebp+0x10) ": stmt compute-offset: var '")
23253     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
23254     (write-buffered *(ebp+0x10) %eax)
23255     (write-buffered *(ebp+0x10) "' is not an array\n")
23256     (flush *(ebp+0x10))
23257     (stop *(ebp+0x14) 1)
23258     # never gets here
23259 
23260 $check-mu-compute-offset-stmt:error-base-array-atom-type:
23261     (write-buffered *(ebp+0x10) "fn ")
23262     8b/-> *(ebp+0xc) 0/r32/eax
23263     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23264     (write-buffered *(ebp+0x10) %eax)
23265     (write-buffered *(ebp+0x10) ": stmt compute-offset: array '")
23266     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
23267     (write-buffered *(ebp+0x10) %eax)
23268     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
23269     (flush *(ebp+0x10))
23270     (stop *(ebp+0x14) 1)
23271     # never gets here
23272 
23273 $check-mu-compute-offset-stmt:error-too-few-inouts:
23274     (write-buffered *(ebp+0x10) "fn ")
23275     8b/-> *(ebp+0xc) 0/r32/eax
23276     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23277     (write-buffered *(ebp+0x10) %eax)
23278     (write-buffered *(ebp+0x10) ": stmt compute-offset: too few inouts (2 required)\n")
23279     (flush *(ebp+0x10))
23280     (stop *(ebp+0x14) 1)
23281     # never gets here
23282 
23283 $check-mu-compute-offset-stmt:error-invalid-index-type:
23284     (write-buffered *(ebp+0x10) "fn ")
23285     8b/-> *(ebp+0xc) 0/r32/eax
23286     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23287     (write-buffered *(ebp+0x10) %eax)
23288     (write-buffered *(ebp+0x10) ": stmt compute-offset: second argument '")
23289     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
23290     (write-buffered *(ebp+0x10) %eax)
23291     (write-buffered *(ebp+0x10) "' must be an int\n")
23292     (flush *(ebp+0x10))
23293     (stop *(ebp+0x14) 1)
23294     # never gets here
23295 
23296 $check-mu-compute-offset-stmt:error-index-offset-atom-type:
23297     (write-buffered *(ebp+0x10) "fn ")
23298     8b/-> *(ebp+0xc) 0/r32/eax
23299     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23300     (write-buffered *(ebp+0x10) %eax)
23301     (write-buffered *(ebp+0x10) ": stmt compute-offset: offset '")
23302     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
23303     (write-buffered *(ebp+0x10) %eax)
23304     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
23305     (flush *(ebp+0x10))
23306     (stop *(ebp+0x14) 1)
23307     # never gets here
23308 
23309 $check-mu-compute-offset-stmt:error-index-on-stack:
23310     (write-buffered *(ebp+0x10) "fn ")
23311     8b/-> *(ebp+0xc) 0/r32/eax
23312     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23313     (write-buffered *(ebp+0x10) %eax)
23314     (write-buffered *(ebp+0x10) ": stmt compute-offset: second argument '")
23315     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
23316     (write-buffered *(ebp+0x10) %eax)
23317     (write-buffered *(ebp+0x10) "' must be in a register\n")
23318     (flush *(ebp+0x10))
23319     (stop *(ebp+0x14) 1)
23320     # never gets here
23321 
23322 $check-mu-compute-offset-stmt:error-too-many-inouts:
23323     (write-buffered *(ebp+0x10) "fn ")
23324     8b/-> *(ebp+0xc) 0/r32/eax
23325     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23326     (write-buffered *(ebp+0x10) %eax)
23327     (write-buffered *(ebp+0x10) ": stmt compute-offset: too many inouts (2 required)\n")
23328     (flush *(ebp+0x10))
23329     (stop *(ebp+0x14) 1)
23330     # never gets here
23331 
23332 $check-mu-compute-offset-stmt:error-too-few-outputs:
23333     (write-buffered *(ebp+0x10) "fn ")
23334     8b/-> *(ebp+0xc) 0/r32/eax
23335     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23336     (write-buffered *(ebp+0x10) %eax)
23337     (write-buffered *(ebp+0x10) ": stmt compute-offset: must have an output\n")
23338     (flush *(ebp+0x10))
23339     (stop *(ebp+0x14) 1)
23340     # never gets here
23341 
23342 $check-mu-compute-offset-stmt:error-too-many-outputs:
23343     (write-buffered *(ebp+0x10) "fn ")
23344     8b/-> *(ebp+0xc) 0/r32/eax
23345     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23346     (write-buffered *(ebp+0x10) %eax)
23347     (write-buffered *(ebp+0x10) ": stmt compute-offset: too many outputs (1 required)\n")
23348     (flush *(ebp+0x10))
23349     (stop *(ebp+0x14) 1)
23350     # never gets here
23351 
23352 $check-mu-compute-offset-stmt:error-output-not-in-register:
23353     (write-buffered *(ebp+0x10) "fn ")
23354     8b/-> *(ebp+0xc) 0/r32/eax
23355     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23356     (write-buffered *(ebp+0x10) %eax)
23357     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
23358     (lookup *edi *(edi+4))  # Var-name Var-name => eax
23359     (write-buffered *(ebp+0x10) %eax)
23360     (write-buffered *(ebp+0x10) "' is not in a register\n")
23361     (flush *(ebp+0x10))
23362     (stop *(ebp+0x14) 1)
23363     # never gets here
23364 
23365 $check-mu-compute-offset-stmt:error-output-type-not-offset:
23366     (write-buffered *(ebp+0x10) "fn ")
23367     8b/-> *(ebp+0xc) 0/r32/eax
23368     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23369     (write-buffered *(ebp+0x10) %eax)
23370     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
23371     (lookup *edi *(edi+4))  # Var-name Var-name => eax
23372     (write-buffered *(ebp+0x10) %eax)
23373     (write-buffered *(ebp+0x10) "' must be an offset\n")
23374     (flush *(ebp+0x10))
23375     (stop *(ebp+0x14) 1)
23376     # never gets here
23377 
23378 $check-mu-compute-offset-stmt:error-bad-output-type:
23379     (write-buffered *(ebp+0x10) "fn ")
23380     8b/-> *(ebp+0xc) 0/r32/eax
23381     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23382     (write-buffered *(ebp+0x10) %eax)
23383     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
23384     (lookup *edi *(edi+4))  # Var-name Var-name => eax
23385     (write-buffered *(ebp+0x10) %eax)
23386     (write-buffered *(ebp+0x10) "' does not have the right type\n")
23387     (flush *(ebp+0x10))
23388     (stop *(ebp+0x14) 1)
23389     # never gets here
23390 
23391 check-mu-copy-object-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23392     # . prologue
23393     55/push-ebp
23394     89/<- %ebp 4/r32/esp
23395     # . save registers
23396     50/push-eax
23397     51/push-ecx
23398     53/push-ebx
23399     56/push-esi
23400     57/push-edi
23401     # esi = stmt
23402     8b/-> *(ebp+8) 6/r32/esi
23403 $check-mu-copy-object-stmt:check-for-output:
23404     # if stmt->outputs abort
23405     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
23406     3d/compare-eax-and 0/imm32
23407     0f 85/jump-if-!= $check-mu-copy-object-stmt:error-too-many-outputs/disp32
23408 $check-mu-copy-object-stmt:get-left:
23409     # var dest/edi: (addr stmt-var) = stmt->inouts
23410     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23411     89/<- %edi 0/r32/eax
23412     # zero inouts
23413     3d/compare-eax-and 0/imm32
23414     0f 84/jump-if-= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
23415 $check-mu-copy-object-stmt:get-src:
23416     # var src/esi: (addr stmt-var) = dest->next
23417     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
23418     89/<- %esi 0/r32/eax
23419     # 1 inout
23420     3d/compare-eax-and 0/imm32
23421     0f 84/jump-if-= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
23422     # > 2 inouts
23423     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
23424     3d/compare-eax-and 0/imm32
23425     0f 85/jump-if-!= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
23426 $check-mu-copy-object-stmt:types:
23427     # var src-type/ecx: (addr type-tree) = src->value->type
23428     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
23429     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23430     89/<- %ecx 0/r32/eax
23431     # if (src->is-deref?) src-type = src-type->payload
23432     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
23433     3d/compare-eax-and 0/imm32/false
23434     {
23435       74/jump-if-= break/disp8
23436       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
23437       # if src-type->right is null, src-type = src-type->left
23438       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
23439       {
23440         75/jump-if-!= break/disp8
23441         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23442       }
23443       89/<- %ecx 0/r32/eax
23444     }
23445     # if src-type is not addr, abort
23446     (is-mu-addr-type? %ecx)  # => eax
23447     3d/compare-eax-and 0/imm32/false
23448     0f 84/jump-if-= $check-mu-copy-object-stmt:error-invalid-types/disp32
23449     # var dest-type/ebx: (addr type-tree) = dest->value->type
23450     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23451     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23452     89/<- %ebx 0/r32/eax
23453     # if (dest->is-deref?) dest-type = dest-type->payload
23454     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
23455     3d/compare-eax-and 0/imm32/false
23456     {
23457       74/jump-if-= break/disp8
23458       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23459       # if dest-type->right is null, dest-type = dest-type->left
23460       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
23461       {
23462         75/jump-if-!= break/disp8
23463         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23464       }
23465       89/<- %ebx 0/r32/eax
23466     }
23467     # if (dest-type != src-type) abort
23468     (type-equal? %ecx %ebx)  # => eax
23469     3d/compare-eax-and 0/imm32
23470     0f 84/jump-if-= $check-mu-copy-object-stmt:error-invalid-types/disp32
23471 $check-mu-copy-object-stmt:end:
23472     # . restore registers
23473     5f/pop-to-edi
23474     5e/pop-to-esi
23475     5b/pop-to-ebx
23476     59/pop-to-ecx
23477     58/pop-to-eax
23478     # . epilogue
23479     89/<- %esp 5/r32/ebp
23480     5d/pop-to-ebp
23481     c3/return
23482 
23483 $check-mu-copy-object-stmt:error-incorrect-inouts:
23484     (write-buffered *(ebp+0x10) "fn ")
23485     8b/-> *(ebp+0xc) 0/r32/eax
23486     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23487     (write-buffered *(ebp+0x10) %eax)
23488     (write-buffered *(ebp+0x10) ": stmt 'copy-object' must have two inouts\n")
23489     (flush *(ebp+0x10))
23490     (stop *(ebp+0x14) 1)
23491     # never gets here
23492 
23493 $check-mu-copy-object-stmt:error-too-many-outputs:
23494     (write-buffered *(ebp+0x10) "fn ")
23495     8b/-> *(ebp+0xc) 0/r32/eax
23496     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23497     (write-buffered *(ebp+0x10) %eax)
23498     (write-buffered *(ebp+0x10) ": stmt 'copy-object' must not have any outputs\n")
23499     (flush *(ebp+0x10))
23500     (stop *(ebp+0x14) 1)
23501     # never gets here
23502 
23503 $check-mu-copy-object-stmt:error-invalid-types:
23504     (write-buffered *(ebp+0x10) "fn ")
23505     8b/-> *(ebp+0xc) 0/r32/eax
23506     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23507     (write-buffered *(ebp+0x10) %eax)
23508     (write-buffered *(ebp+0x10) ": stmt copy-object: two inouts with identical addr types expected\n")
23509     (flush *(ebp+0x10))
23510     (stop *(ebp+0x14) 1)
23511     # never gets here
23512 
23513 check-mu-clear-object-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23514     # . prologue
23515     55/push-ebp
23516     89/<- %ebp 4/r32/esp
23517     # . save registers
23518     50/push-eax
23519     51/push-ecx
23520     53/push-ebx
23521     56/push-esi
23522     57/push-edi
23523     # esi = stmt
23524     8b/-> *(ebp+8) 6/r32/esi
23525 $check-mu-clear-object-stmt:check-for-output:
23526     # if stmt->outputs abort
23527     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
23528     3d/compare-eax-and 0/imm32
23529     0f 85/jump-if-!= $check-mu-clear-object-stmt:error-too-many-outputs/disp32
23530 $check-mu-clear-object-stmt:get-left:
23531     # var dest/edi: (addr stmt-var) = stmt->inouts
23532     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23533     89/<- %edi 0/r32/eax
23534     # zero inouts
23535     3d/compare-eax-and 0/imm32
23536     0f 84/jump-if-= $check-mu-clear-object-stmt:error-incorrect-inouts/disp32
23537 $check-mu-clear-object-stmt:get-src:
23538     # > 1 inout
23539     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
23540     3d/compare-eax-and 0/imm32
23541     0f 85/jump-if-!= $check-mu-clear-object-stmt:error-incorrect-inouts/disp32
23542 $check-mu-clear-object-stmt:types:
23543     # var src-type/ecx: (addr type-tree) = src->value->type
23544     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23545     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23546     89/<- %ecx 0/r32/eax
23547     # if (src->is-deref?) src-type = src-type->payload
23548     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
23549     3d/compare-eax-and 0/imm32/false
23550     {
23551       74/jump-if-= break/disp8
23552       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
23553       # if src-type->right is null, src-type = src-type->left
23554       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
23555       {
23556         75/jump-if-!= break/disp8
23557         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23558       }
23559       89/<- %ecx 0/r32/eax
23560     }
23561     # if src-type is not addr, abort
23562     (is-mu-addr-type? %ecx)  # => eax
23563     3d/compare-eax-and 0/imm32/false
23564     0f 84/jump-if-= $check-mu-clear-object-stmt:error-invalid-type/disp32
23565 $check-mu-clear-object-stmt:end:
23566     # . restore registers
23567     5f/pop-to-edi
23568     5e/pop-to-esi
23569     5b/pop-to-ebx
23570     59/pop-to-ecx
23571     58/pop-to-eax
23572     # . epilogue
23573     89/<- %esp 5/r32/ebp
23574     5d/pop-to-ebp
23575     c3/return
23576 
23577 $check-mu-clear-object-stmt:error-incorrect-inouts:
23578     (write-buffered *(ebp+0x10) "fn ")
23579     8b/-> *(ebp+0xc) 0/r32/eax
23580     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23581     (write-buffered *(ebp+0x10) %eax)
23582     (write-buffered *(ebp+0x10) ": stmt 'clear-object' must have a single inout\n")
23583     (flush *(ebp+0x10))
23584     (stop *(ebp+0x14) 1)
23585     # never gets here
23586 
23587 $check-mu-clear-object-stmt:error-too-many-outputs:
23588     (write-buffered *(ebp+0x10) "fn ")
23589     8b/-> *(ebp+0xc) 0/r32/eax
23590     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23591     (write-buffered *(ebp+0x10) %eax)
23592     (write-buffered *(ebp+0x10) ": stmt 'clear-object' must not have any outputs\n")
23593     (flush *(ebp+0x10))
23594     (stop *(ebp+0x14) 1)
23595     # never gets here
23596 
23597 $check-mu-clear-object-stmt:error-invalid-type:
23598     (write-buffered *(ebp+0x10) "fn ")
23599     8b/-> *(ebp+0xc) 0/r32/eax
23600     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23601     (write-buffered *(ebp+0x10) %eax)
23602     (write-buffered *(ebp+0x10) ": stmt clear-object: inout must have an addr type\n")
23603     (flush *(ebp+0x10))
23604     (stop *(ebp+0x14) 1)
23605     # never gets here
23606 
23607 check-mu-allocate-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23608     # . prologue
23609     55/push-ebp
23610     89/<- %ebp 4/r32/esp
23611     # . save registers
23612     50/push-eax
23613     53/push-ebx
23614     56/push-esi
23615     57/push-edi
23616     # esi = stmt
23617     8b/-> *(ebp+8) 6/r32/esi
23618 $check-mu-allocate-stmt:check-for-output:
23619     # if stmt->outputs abort
23620     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
23621     3d/compare-eax-and 0/imm32
23622     0f 85/jump-if-!= $check-mu-allocate-stmt:error-too-many-outputs/disp32
23623 $check-mu-allocate-stmt:get-target:
23624     # var target/edi: (addr stmt-var) = stmt->inouts
23625     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23626     89/<- %edi 0/r32/eax
23627     # zero inouts
23628     3d/compare-eax-and 0/imm32
23629     0f 84/jump-if-= $check-mu-allocate-stmt:error-incorrect-inouts/disp32
23630     # > 1 inouts
23631     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
23632     3d/compare-eax-and 0/imm32
23633     0f 85/jump-if-!= $check-mu-allocate-stmt:error-incorrect-inouts/disp32
23634 $check-mu-allocate-stmt:check-type:
23635     # var target-type/ebx: (addr type-tree) = target->value->type
23636     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23637     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23638     89/<- %ebx 0/r32/eax
23639     # if (target->is-deref?) target-type = target-type->payload
23640     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
23641     3d/compare-eax-and 0/imm32/false
23642     {
23643       74/jump-if-= break/disp8
23644       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23645       # if target-type->right is null, target-type = target-type->left
23646       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
23647       {
23648         75/jump-if-!= break/disp8
23649         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23650       }
23651       89/<- %ebx 0/r32/eax
23652     }
23653     # if target-type is not addr, abort
23654     (is-mu-addr-type? %ebx)  # => eax
23655     3d/compare-eax-and 0/imm32/false
23656     0f 84/jump-if-= $check-mu-allocate-stmt:error-invalid-type/disp32
23657     # if target-type->right is an atom, abort
23658     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23659     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
23660     0f 85/jump-if-!= $check-mu-allocate-stmt:error-invalid-type/disp32
23661     # if target-type->right->left is not handle, abort
23662     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23663     (is-simple-mu-type? %eax 4)  # handle => eax
23664     3d/compare-eax-and 0/imm32/false
23665     0f 84/jump-if-= $check-mu-allocate-stmt:error-invalid-type/disp32
23666 $check-mu-allocate-stmt:end:
23667     # . restore registers
23668     5f/pop-to-edi
23669     5e/pop-to-esi
23670     5b/pop-to-ebx
23671     58/pop-to-eax
23672     # . epilogue
23673     89/<- %esp 5/r32/ebp
23674     5d/pop-to-ebp
23675     c3/return
23676 
23677 $check-mu-allocate-stmt:error-incorrect-inouts:
23678     (write-buffered *(ebp+0x10) "fn ")
23679     8b/-> *(ebp+0xc) 0/r32/eax
23680     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23681     (write-buffered *(ebp+0x10) %eax)
23682     (write-buffered *(ebp+0x10) ": stmt 'allocate' must have a single inout\n")
23683     (flush *(ebp+0x10))
23684     (stop *(ebp+0x14) 1)
23685     # never gets here
23686 
23687 $check-mu-allocate-stmt:error-too-many-outputs:
23688     (write-buffered *(ebp+0x10) "fn ")
23689     8b/-> *(ebp+0xc) 0/r32/eax
23690     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23691     (write-buffered *(ebp+0x10) %eax)
23692     (write-buffered *(ebp+0x10) ": stmt 'allocate' must not have any outputs\n")
23693     (flush *(ebp+0x10))
23694     (stop *(ebp+0x14) 1)
23695     # never gets here
23696 
23697 $check-mu-allocate-stmt:error-invalid-type:
23698     (write-buffered *(ebp+0x10) "fn ")
23699     8b/-> *(ebp+0xc) 0/r32/eax
23700     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23701     (write-buffered *(ebp+0x10) %eax)
23702     (write-buffered *(ebp+0x10) ": stmt allocate: inout '")
23703     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23704     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23705     (write-buffered *(ebp+0x10) %eax)
23706     (write-buffered *(ebp+0x10) "' must have type (addr handle ...)\n")
23707     (flush *(ebp+0x10))
23708     (stop *(ebp+0x14) 1)
23709     # never gets here
23710 
23711 check-mu-populate-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23712     # . prologue
23713     55/push-ebp
23714     89/<- %ebp 4/r32/esp
23715     # . save registers
23716     50/push-eax
23717     53/push-ebx
23718     56/push-esi
23719     57/push-edi
23720     # esi = stmt
23721     8b/-> *(ebp+8) 6/r32/esi
23722 $check-mu-populate-stmt:check-for-output:
23723     # if stmt->outputs abort
23724     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
23725     3d/compare-eax-and 0/imm32
23726     0f 85/jump-if-!= $check-mu-populate-stmt:error-too-many-outputs/disp32
23727 $check-mu-populate-stmt:get-target:
23728     # var target/edi: (addr stmt-var) = stmt->inouts
23729     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23730     89/<- %edi 0/r32/eax
23731     # zero inouts
23732     3d/compare-eax-and 0/imm32
23733     0f 84/jump-if-= $check-mu-populate-stmt:error-incorrect-inouts/disp32
23734 $check-mu-populate-stmt:get-length:
23735     # var length/esi: (addr stmt-var) = dest->next
23736     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
23737     89/<- %esi 0/r32/eax
23738     # 1 inout
23739     3d/compare-eax-and 0/imm32
23740     0f 84/jump-if-= $check-mu-populate-stmt:error-incorrect-inouts/disp32
23741     # > 2 inouts
23742     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
23743     3d/compare-eax-and 0/imm32
23744     0f 85/jump-if-!= $check-mu-populate-stmt:error-incorrect-inouts/disp32
23745 $check-mu-populate-stmt:check-target-type:
23746     # var target-type/ebx: (addr type-tree) = target->value->type
23747     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23748     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23749     89/<- %ebx 0/r32/eax
23750 $check-mu-populate-stmt:check-target-type-deref:
23751     # if (target->is-deref?) target-type = target-type->payload
23752     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
23753     3d/compare-eax-and 0/imm32/false
23754     {
23755       74/jump-if-= break/disp8
23756       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23757       # if target-type->right is null, target-type = target-type->left
23758       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
23759       {
23760         75/jump-if-!= break/disp8
23761         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23762       }
23763       89/<- %ebx 0/r32/eax
23764     }
23765 $check-mu-populate-stmt:check-target-type-addr:
23766     # if target-type is not addr, abort
23767     (is-mu-addr-type? %ebx)  # => eax
23768     3d/compare-eax-and 0/imm32/false
23769     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32
23770     # if target-type->right is an atom, abort
23771     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23772     89/<- %ebx 0/r32/eax
23773     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
23774     0f 85/jump-if-!= $check-mu-populate-stmt:error-invalid-target-type/disp32
23775 $check-mu-populate-stmt:check-target-type-handle:
23776     # if target-type->right->left is not handle, abort
23777     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
23778     (is-simple-mu-type? %eax 4)  # handle => eax
23779     3d/compare-eax-and 0/imm32/false
23780     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32
23781     # if target-type->right->right is an atom, abort
23782     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23783     89/<- %ebx 0/r32/eax
23784     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
23785     0f 85/jump-if-!= $check-mu-populate-stmt:error-invalid-target-type/disp32
23786 $check-mu-populate-stmt:check-target-type-array:
23787     # if target-type->right->right->left is not array, abort
23788     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
23789     (is-simple-mu-type? %eax 3)  # array => eax
23790     3d/compare-eax-and 0/imm32/false
23791     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32
23792 $check-mu-populate-stmt:check-length-type:
23793     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
23794     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23795     89/<- %ebx 0/r32/eax
23796     (is-simple-mu-type? %ebx 0)  # literal => eax
23797     3d/compare-eax-and 0/imm32/false
23798     75/jump-if-!= $check-mu-populate-stmt:end/disp8
23799     (is-simple-mu-type? %ebx 1)  # int => eax
23800     3d/compare-eax-and 0/imm32/false
23801     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-length-type/disp32
23802 $check-mu-populate-stmt:end:
23803     # . restore registers
23804     5f/pop-to-edi
23805     5e/pop-to-esi
23806     5b/pop-to-ebx
23807     58/pop-to-eax
23808     # . epilogue
23809     89/<- %esp 5/r32/ebp
23810     5d/pop-to-ebp
23811     c3/return
23812 
23813 $check-mu-populate-stmt:error-incorrect-inouts:
23814     (write-buffered *(ebp+0x10) "fn ")
23815     8b/-> *(ebp+0xc) 0/r32/eax
23816     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23817     (write-buffered *(ebp+0x10) %eax)
23818     (write-buffered *(ebp+0x10) ": stmt 'populate' must have two inouts\n")
23819     (flush *(ebp+0x10))
23820     (stop *(ebp+0x14) 1)
23821     # never gets here
23822 
23823 $check-mu-populate-stmt:error-too-many-outputs:
23824     (write-buffered *(ebp+0x10) "fn ")
23825     8b/-> *(ebp+0xc) 0/r32/eax
23826     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23827     (write-buffered *(ebp+0x10) %eax)
23828     (write-buffered *(ebp+0x10) ": stmt 'populate' must not have any outputs\n")
23829     (flush *(ebp+0x10))
23830     (stop *(ebp+0x14) 1)
23831     # never gets here
23832 
23833 $check-mu-populate-stmt:error-invalid-target-type:
23834     (write-buffered *(ebp+0x10) "fn ")
23835     8b/-> *(ebp+0xc) 0/r32/eax
23836     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23837     (write-buffered *(ebp+0x10) %eax)
23838     (write-buffered *(ebp+0x10) ": stmt populate: first inout '")
23839     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23840     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23841     (write-buffered *(ebp+0x10) %eax)
23842     (write-buffered *(ebp+0x10) "' must have type (addr handle array ...)\n")
23843     (flush *(ebp+0x10))
23844     (stop *(ebp+0x14) 1)
23845     # never gets here
23846 
23847 $check-mu-populate-stmt:error-invalid-length-type:
23848     (write-buffered *(ebp+0x10) "fn ")
23849     8b/-> *(ebp+0xc) 0/r32/eax
23850     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23851     (write-buffered *(ebp+0x10) %eax)
23852     (write-buffered *(ebp+0x10) ": stmt populate: second inout '")
23853     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
23854     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23855     (write-buffered *(ebp+0x10) %eax)
23856     (write-buffered *(ebp+0x10) "' must be an int\n")
23857     (flush *(ebp+0x10))
23858     (stop *(ebp+0x14) 1)
23859     # never gets here
23860 
23861 check-mu-populate-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23862     # . prologue
23863     55/push-ebp
23864     89/<- %ebp 4/r32/esp
23865     # . save registers
23866     50/push-eax
23867     53/push-ebx
23868     56/push-esi
23869     57/push-edi
23870     # esi = stmt
23871     8b/-> *(ebp+8) 6/r32/esi
23872 $check-mu-populate-stream-stmt:check-for-output:
23873     # if stmt->outputs abort
23874     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
23875     3d/compare-eax-and 0/imm32
23876     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-too-many-outputs/disp32
23877 $check-mu-populate-stream-stmt:get-target:
23878     # var target/edi: (addr stmt-var) = stmt->inouts
23879     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23880     89/<- %edi 0/r32/eax
23881     # zero inouts
23882     3d/compare-eax-and 0/imm32
23883     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32
23884 $check-mu-populate-stream-stmt:get-length:
23885     # var length/esi: (addr stmt-var) = dest->next
23886     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
23887     89/<- %esi 0/r32/eax
23888     # 1 inout
23889     3d/compare-eax-and 0/imm32
23890     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32
23891     # > 2 inouts
23892     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
23893     3d/compare-eax-and 0/imm32
23894     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32
23895 $check-mu-populate-stream-stmt:check-target-type:
23896     # var target-type/ebx: (addr type-tree) = target->value->type
23897     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23898     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23899     89/<- %ebx 0/r32/eax
23900 $check-mu-populate-stream-stmt:check-target-type-deref:
23901     # if (target->is-deref?) target-type = target-type->payload
23902     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
23903     3d/compare-eax-and 0/imm32/false
23904     {
23905       74/jump-if-= break/disp8
23906       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23907       # if target-type->right is null, target-type = target-type->left
23908       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
23909       {
23910         75/jump-if-!= break/disp8
23911         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23912       }
23913       89/<- %ebx 0/r32/eax
23914     }
23915 $check-mu-populate-stream-stmt:check-target-type-addr:
23916     # if target-type is not addr, abort
23917     (is-mu-addr-type? %ebx)  # => eax
23918     3d/compare-eax-and 0/imm32/false
23919     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
23920     # if target-type->right is an atom, abort
23921     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23922     89/<- %ebx 0/r32/eax
23923     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
23924     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
23925 $check-mu-populate-stream-stmt:check-target-type-handle:
23926     # if target-type->right->left is not handle, abort
23927     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
23928     (is-simple-mu-type? %eax 4)  # handle => eax
23929     3d/compare-eax-and 0/imm32/false
23930     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
23931     # if target-type->right->right is an atom, abort
23932     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23933     89/<- %ebx 0/r32/eax
23934     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
23935     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
23936 $check-mu-populate-stream-stmt:check-target-type-stream:
23937     # if target-type->right->right->left is not stream, abort
23938     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
23939     (is-simple-mu-type? %eax 0xb)  # stream => eax
23940     3d/compare-eax-and 0/imm32/false
23941     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
23942 $check-mu-populate-stream-stmt:check-length-type:
23943     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
23944     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23945     89/<- %ebx 0/r32/eax
23946     (is-simple-mu-type? %ebx 0)  # literal => eax
23947     3d/compare-eax-and 0/imm32/false
23948     75/jump-if-!= $check-mu-populate-stream-stmt:end/disp8
23949     (is-simple-mu-type? %ebx 1)  # int => eax
23950     3d/compare-eax-and 0/imm32/false
23951     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-length-type/disp32
23952 $check-mu-populate-stream-stmt:end:
23953     # . restore registers
23954     5f/pop-to-edi
23955     5e/pop-to-esi
23956     5b/pop-to-ebx
23957     58/pop-to-eax
23958     # . epilogue
23959     89/<- %esp 5/r32/ebp
23960     5d/pop-to-ebp
23961     c3/return
23962 
23963 $check-mu-populate-stream-stmt:error-incorrect-inouts:
23964     (write-buffered *(ebp+0x10) "fn ")
23965     8b/-> *(ebp+0xc) 0/r32/eax
23966     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23967     (write-buffered *(ebp+0x10) %eax)
23968     (write-buffered *(ebp+0x10) ": stmt 'populate-stream' must have two inouts\n")
23969     (flush *(ebp+0x10))
23970     (stop *(ebp+0x14) 1)
23971     # never gets here
23972 
23973 $check-mu-populate-stream-stmt:error-too-many-outputs:
23974     (write-buffered *(ebp+0x10) "fn ")
23975     8b/-> *(ebp+0xc) 0/r32/eax
23976     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23977     (write-buffered *(ebp+0x10) %eax)
23978     (write-buffered *(ebp+0x10) ": stmt 'populate-stream' must not have any outputs\n")
23979     (flush *(ebp+0x10))
23980     (stop *(ebp+0x14) 1)
23981     # never gets here
23982 
23983 $check-mu-populate-stream-stmt:error-invalid-target-type:
23984     (write-buffered *(ebp+0x10) "fn ")
23985     8b/-> *(ebp+0xc) 0/r32/eax
23986     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23987     (write-buffered *(ebp+0x10) %eax)
23988     (write-buffered *(ebp+0x10) ": stmt populate-stream: first inout '")
23989     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23990     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23991     (write-buffered *(ebp+0x10) %eax)
23992     (write-buffered *(ebp+0x10) "' must have type (addr handle stream ...)\n")
23993     (flush *(ebp+0x10))
23994     (stop *(ebp+0x14) 1)
23995     # never gets here
23996 
23997 $check-mu-populate-stream-stmt:error-invalid-length-type:
23998     (write-buffered *(ebp+0x10) "fn ")
23999     8b/-> *(ebp+0xc) 0/r32/eax
24000     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24001     (write-buffered *(ebp+0x10) %eax)
24002     (write-buffered *(ebp+0x10) ": stmt populate-stream: second inout '")
24003     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
24004     (lookup *eax *(eax+4))  # Var-name Var-name => eax
24005     (write-buffered *(ebp+0x10) %eax)
24006     (write-buffered *(ebp+0x10) "' must be an int\n")
24007     (flush *(ebp+0x10))
24008     (stop *(ebp+0x14) 1)
24009     # never gets here
24010 
24011 check-mu-read-from-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
24012     # . prologue
24013     55/push-ebp
24014     89/<- %ebp 4/r32/esp
24015     # . save registers
24016     50/push-eax
24017     51/push-ecx
24018     52/push-edx
24019     53/push-ebx
24020     56/push-esi
24021     57/push-edi
24022     # esi = stmt
24023     8b/-> *(ebp+8) 6/r32/esi
24024     # - check for 0 inouts
24025     # var base/ecx: (addr var) = stmt->inouts->value
24026     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24027 $check-mu-read-from-stream-stmt:check-no-inouts:
24028     3d/compare-eax-and 0/imm32
24029     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-too-few-inouts/disp32
24030     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24031     89/<- %ecx 0/r32/eax
24032     # - check base type is (addr stream T)
24033     # var base-type/ebx: (addr type-tree) = lookup(base->type)
24034     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
24035     89/<- %ebx 0/r32/eax
24036 $check-mu-read-from-stream-stmt:check-base-is-compound:
24037     # if base-type is an atom, abort
24038     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
24039     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
24040 $check-mu-read-from-stream-stmt:check-base-is-addr:
24041     # if type->left not addr, abort
24042     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24043     (is-simple-mu-type? %eax 2)  # addr => eax
24044     3d/compare-eax-and 0/imm32/false
24045     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
24046 $check-mu-read-from-stream-stmt:check-base-is-addr-to-stream:
24047     # base-type = base-type->right
24048     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
24049     89/<- %ebx 0/r32/eax
24050     # ensure base-type->left == stream
24051     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
24052     (is-simple-mu-type? %eax 0xb)  # stream => eax
24053     3d/compare-eax-and 0/imm32/false
24054     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
24055     # - check target type is (addr T)
24056     # var target/ecx: (addr stmt-var) = stmt->inouts->next->value
24057     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24058     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24059 $check-mu-read-from-stream-stmt:check-single-inout:
24060     3d/compare-eax-and 0/imm32
24061     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-too-few-inouts/disp32
24062     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24063     89/<- %ecx 0/r32/eax
24064     # var target-type/edx: (addr type-tree)
24065     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
24066     89/<- %edx 0/r32/eax
24067     # if target-type is an atom, it must be a literal or int
24068 $check-mu-read-from-stream-stmt:check-target-is-compound:
24069     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
24070     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-target-type-not-address/disp32
24071 $check-mu-read-from-stream-stmt:check-target-type:
24072     # target type must start with (addr ...)
24073     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
24074     (is-simple-mu-type? %eax 2)  # addr => eax
24075     3d/compare-eax-and 0/imm32/false
24076     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-target-type-not-address/disp32
24077     # if tail(base-type) != tail(target-type) abort
24078     (type-tail %ebx)  # => eax
24079     89/<- %ebx 0/r32/eax
24080     (type-tail %edx)  # => eax
24081     (type-equal? %ebx %eax)  # => eax
24082     3d/compare-eax-and 0/imm32/false
24083     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-target-type/disp32
24084 $check-mu-read-from-stream-stmt:check-too-many-inouts:
24085     # - check for too many inouts
24086     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24087     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24088     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24089     3d/compare-eax-and 0/imm32/false
24090     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-too-many-inouts/disp32
24091 $check-mu-read-from-stream-stmt:check-unexpected-output:
24092     # - check for any output
24093     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24094     3d/compare-eax-and 0/imm32/false
24095     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-unexpected-output/disp32
24096 $check-mu-read-from-stream-stmt:end:
24097     # . restore registers
24098     5f/pop-to-edi
24099     5e/pop-to-esi
24100     5b/pop-to-ebx
24101     5a/pop-to-edx
24102     59/pop-to-ecx
24103     58/pop-to-eax
24104     # . epilogue
24105     89/<- %esp 5/r32/ebp
24106     5d/pop-to-ebp
24107     c3/return
24108 
24109 $check-mu-read-from-stream-stmt:error-invalid-base-type:
24110     (write-buffered *(ebp+0x10) "fn ")
24111     8b/-> *(ebp+0xc) 0/r32/eax
24112     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24113     (write-buffered *(ebp+0x10) %eax)
24114     (write-buffered *(ebp+0x10) ": stmt read-from-stream: var '")
24115     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24116     (write-buffered *(ebp+0x10) %eax)
24117     (write-buffered *(ebp+0x10) "' must be an addr to a stream\n")
24118     (flush *(ebp+0x10))
24119     (stop *(ebp+0x14) 1)
24120     # never gets here
24121 
24122 $check-mu-read-from-stream-stmt:error-too-few-inouts:
24123     (write-buffered *(ebp+0x10) "fn ")
24124     8b/-> *(ebp+0xc) 0/r32/eax
24125     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24126     (write-buffered *(ebp+0x10) %eax)
24127     (write-buffered *(ebp+0x10) ": stmt read-from-stream: too few inouts (2 required)\n")
24128     (flush *(ebp+0x10))
24129     (stop *(ebp+0x14) 1)
24130     # never gets here
24131 
24132 $check-mu-read-from-stream-stmt:error-target-type-not-address:
24133     (write-buffered *(ebp+0x10) "fn ")
24134     8b/-> *(ebp+0xc) 0/r32/eax
24135     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24136     (write-buffered *(ebp+0x10) %eax)
24137     (write-buffered *(ebp+0x10) ": stmt read-from-stream: target '")
24138     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24139     (write-buffered *(ebp+0x10) %eax)
24140     (write-buffered *(ebp+0x10) "' must be an addr\n")
24141     (flush *(ebp+0x10))
24142     (stop *(ebp+0x14) 1)
24143     # never gets here
24144 
24145 $check-mu-read-from-stream-stmt:error-invalid-target-type:
24146     (write-buffered *(ebp+0x10) "fn ")
24147     8b/-> *(ebp+0xc) 0/r32/eax
24148     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24149     (write-buffered *(ebp+0x10) %eax)
24150     (write-buffered *(ebp+0x10) ": stmt read-from-stream: second inout '")
24151     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24152     (write-buffered *(ebp+0x10) %eax)
24153     (write-buffered *(ebp+0x10) "' does not have the right type\n")
24154     (flush *(ebp+0x10))
24155     (stop *(ebp+0x14) 1)
24156     # never gets here
24157 
24158 $check-mu-read-from-stream-stmt:error-too-many-inouts:
24159     (write-buffered *(ebp+0x10) "fn ")
24160     8b/-> *(ebp+0xc) 0/r32/eax
24161     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24162     (write-buffered *(ebp+0x10) %eax)
24163     (write-buffered *(ebp+0x10) ": stmt read-from-stream: too many inouts (2 required)\n")
24164     (flush *(ebp+0x10))
24165     (stop *(ebp+0x14) 1)
24166     # never gets here
24167 
24168 $check-mu-read-from-stream-stmt:error-unexpected-output:
24169     (write-buffered *(ebp+0x10) "fn ")
24170     8b/-> *(ebp+0xc) 0/r32/eax
24171     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24172     (write-buffered *(ebp+0x10) %eax)
24173     (write-buffered *(ebp+0x10) ": stmt read-from-stream: unexpected output\n")
24174     (flush *(ebp+0x10))
24175     (stop *(ebp+0x14) 1)
24176     # never gets here
24177 
24178 check-mu-write-to-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
24179     # . prologue
24180     55/push-ebp
24181     89/<- %ebp 4/r32/esp
24182     # . save registers
24183     50/push-eax
24184     51/push-ecx
24185     52/push-edx
24186     53/push-ebx
24187     56/push-esi
24188     57/push-edi
24189     # esi = stmt
24190     8b/-> *(ebp+8) 6/r32/esi
24191     # - check for 0 inouts
24192     # var base/ecx: (addr var) = stmt->inouts->value
24193     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24194 $check-mu-write-to-stream-stmt:check-no-inouts:
24195     3d/compare-eax-and 0/imm32
24196     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-too-few-inouts/disp32
24197     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24198     89/<- %ecx 0/r32/eax
24199     # - check base type is (addr stream T)
24200     # var base-type/ebx: (addr type-tree) = lookup(base->type)
24201     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
24202     89/<- %ebx 0/r32/eax
24203 $check-mu-write-to-stream-stmt:check-base-is-compound:
24204     # if base-type is an atom, abort
24205     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
24206     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
24207 $check-mu-write-to-stream-stmt:check-base-is-addr:
24208     # if type->left not addr, abort
24209     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24210     (is-simple-mu-type? %eax 2)  # addr => eax
24211     3d/compare-eax-and 0/imm32/false
24212     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
24213 $check-mu-write-to-stream-stmt:check-base-is-addr-to-stream:
24214     # base-type = base-type->right
24215     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
24216     89/<- %ebx 0/r32/eax
24217     # ensure base-type->left == stream
24218     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
24219     (is-simple-mu-type? %eax 0xb)  # stream => eax
24220     3d/compare-eax-and 0/imm32/false
24221     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
24222     # - check target type is (addr T)
24223     # var target/ecx: (addr stmt-var) = stmt->inouts->next->value
24224     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24225     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24226 $check-mu-write-to-stream-stmt:check-single-inout:
24227     3d/compare-eax-and 0/imm32
24228     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-too-few-inouts/disp32
24229     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24230     89/<- %ecx 0/r32/eax
24231     # var target-type/edx: (addr type-tree)
24232     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
24233     89/<- %edx 0/r32/eax
24234     # if target-type is an atom, it must be a literal or int
24235 $check-mu-write-to-stream-stmt:check-target-is-compound:
24236     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
24237     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-target-type-not-address/disp32
24238 $check-mu-write-to-stream-stmt:check-target-type:
24239     # target type must start with (addr ...)
24240     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
24241     (is-simple-mu-type? %eax 2)  # addr => eax
24242     3d/compare-eax-and 0/imm32/false
24243     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-target-type-not-address/disp32
24244     # if tail(base-type) != tail(target-type) abort
24245     (type-tail %ebx)  # => eax
24246     89/<- %ebx 0/r32/eax
24247     (type-tail %edx)  # => eax
24248     (type-equal? %ebx %eax)  # => eax
24249     3d/compare-eax-and 0/imm32/false
24250     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-target-type/disp32
24251 $check-mu-write-to-stream-stmt:check-too-many-inouts:
24252     # - check for too many inouts
24253     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24254     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24255     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24256     3d/compare-eax-and 0/imm32/false
24257     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-too-many-inouts/disp32
24258 $check-mu-write-to-stream-stmt:check-unexpected-output:
24259     # - check for any output
24260     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24261     3d/compare-eax-and 0/imm32/false
24262     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-unexpected-output/disp32
24263 $check-mu-write-to-stream-stmt:end:
24264     # . restore registers
24265     5f/pop-to-edi
24266     5e/pop-to-esi
24267     5b/pop-to-ebx
24268     5a/pop-to-edx
24269     59/pop-to-ecx
24270     58/pop-to-eax
24271     # . epilogue
24272     89/<- %esp 5/r32/ebp
24273     5d/pop-to-ebp
24274     c3/return
24275 
24276 $check-mu-write-to-stream-stmt:error-invalid-base-type:
24277     (write-buffered *(ebp+0x10) "fn ")
24278     8b/-> *(ebp+0xc) 0/r32/eax
24279     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24280     (write-buffered *(ebp+0x10) %eax)
24281     (write-buffered *(ebp+0x10) ": stmt write-to-stream: var '")
24282     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24283     (write-buffered *(ebp+0x10) %eax)
24284     (write-buffered *(ebp+0x10) "' must be an addr to a stream\n")
24285     (flush *(ebp+0x10))
24286     (stop *(ebp+0x14) 1)
24287     # never gets here
24288 
24289 $check-mu-write-to-stream-stmt:error-too-few-inouts:
24290     (write-buffered *(ebp+0x10) "fn ")
24291     8b/-> *(ebp+0xc) 0/r32/eax
24292     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24293     (write-buffered *(ebp+0x10) %eax)
24294     (write-buffered *(ebp+0x10) ": stmt write-to-stream: too few inouts (2 required)\n")
24295     (flush *(ebp+0x10))
24296     (stop *(ebp+0x14) 1)
24297     # never gets here
24298 
24299 $check-mu-write-to-stream-stmt:error-target-type-not-address:
24300     (write-buffered *(ebp+0x10) "fn ")
24301     8b/-> *(ebp+0xc) 0/r32/eax
24302     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24303     (write-buffered *(ebp+0x10) %eax)
24304     (write-buffered *(ebp+0x10) ": stmt write-to-stream: target '")
24305     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24306     (write-buffered *(ebp+0x10) %eax)
24307     (write-buffered *(ebp+0x10) "' must be an addr\n")
24308     (flush *(ebp+0x10))
24309     (stop *(ebp+0x14) 1)
24310     # never gets here
24311 
24312 $check-mu-write-to-stream-stmt:error-invalid-target-type:
24313     (write-buffered *(ebp+0x10) "fn ")
24314     8b/-> *(ebp+0xc) 0/r32/eax
24315     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24316     (write-buffered *(ebp+0x10) %eax)
24317     (write-buffered *(ebp+0x10) ": stmt write-to-stream: second inout '")
24318     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24319     (write-buffered *(ebp+0x10) %eax)
24320     (write-buffered *(ebp+0x10) "' does not have the right type\n")
24321     (flush *(ebp+0x10))
24322     (stop *(ebp+0x14) 1)
24323     # never gets here
24324 
24325 $check-mu-write-to-stream-stmt:error-too-many-inouts:
24326     (write-buffered *(ebp+0x10) "fn ")
24327     8b/-> *(ebp+0xc) 0/r32/eax
24328     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24329     (write-buffered *(ebp+0x10) %eax)
24330     (write-buffered *(ebp+0x10) ": stmt write-to-stream: too many inouts (2 required)\n")
24331     (flush *(ebp+0x10))
24332     (stop *(ebp+0x14) 1)
24333     # never gets here
24334 
24335 $check-mu-write-to-stream-stmt:error-unexpected-output:
24336     (write-buffered *(ebp+0x10) "fn ")
24337     8b/-> *(ebp+0xc) 0/r32/eax
24338     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24339     (write-buffered *(ebp+0x10) %eax)
24340     (write-buffered *(ebp+0x10) ": stmt write-to-stream: unexpected output\n")
24341     (flush *(ebp+0x10))
24342     (stop *(ebp+0x14) 1)
24343     # never gets here
24344 
24345 check-mu-convert-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
24346     # . prologue
24347     55/push-ebp
24348     89/<- %ebp 4/r32/esp
24349     # . save registers
24350     50/push-eax
24351     51/push-ecx
24352     52/push-edx
24353     56/push-esi
24354     57/push-edi
24355 $check-mu-convert-stmt:get-output:
24356     # esi = stmt
24357     8b/-> *(ebp+8) 6/r32/esi
24358     # var output/edi: (addr stmt-var) = stmt->outputs
24359     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24360     89/<- %edi 0/r32/eax
24361     # zero outputs
24362     3d/compare-eax-and 0/imm32
24363     0f 84/jump-if-= $check-mu-convert-stmt:error-no-output/disp32
24364     # > 1 output
24365     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
24366     3d/compare-eax-and 0/imm32
24367     0f 85/jump-if-!= $check-mu-convert-stmt:error-too-many-outputs/disp32
24368 $check-mu-convert-stmt:get-inout:
24369     # var inout/esi: (addr stmt-var) = stmt->inouts
24370     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24371     89/<- %esi 0/r32/eax
24372     # zero inouts
24373     3d/compare-eax-and 0/imm32
24374     0f 84/jump-if-= $check-mu-convert-stmt:error-no-inout/disp32
24375     # > 1 inout
24376     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
24377     3d/compare-eax-and 0/imm32
24378     0f 85/jump-if-!= $check-mu-convert-stmt:error-too-many-inouts/disp32
24379 $check-mu-convert-stmt:types:
24380     # var inout-type/ecx: (addr type-tree) = inout->value->type
24381     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
24382     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
24383     89/<- %ecx 0/r32/eax
24384     # if (inout->is-deref?) inout-type = inout-type->payload
24385     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
24386     3d/compare-eax-and 0/imm32/false
24387     {
24388       74/jump-if-= break/disp8
24389       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
24390       # if inout-type->right is null, t = inout-type->left
24391       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
24392       {
24393         75/jump-if-!= break/disp8
24394         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
24395       }
24396       89/<- %ecx 0/r32/eax
24397     }
24398     # if input is not int or float, abort
24399     {
24400       (is-simple-mu-type? %ecx 1)  # int => eax
24401       3d/compare-eax-and 0/imm32/false
24402       75/jump-if-!= break/disp8
24403       (is-simple-mu-type? %ecx 0xf)  # float => eax
24404       3d/compare-eax-and 0/imm32/false
24405       75/jump-if-!= break/disp8
24406       e9/jump $check-mu-convert-stmt:error-invalid-inout-type/disp32
24407     }
24408     # if output not in register, abort
24409     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
24410     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
24411     3d/compare-eax-and 0/imm32
24412     0f 84/jump-if-= $check-mu-convert-stmt:error-output-not-in-register/disp32
24413     # var output-type/edx: (addr type-tree) = output->value->type
24414     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
24415     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
24416     89/<- %edx 0/r32/eax
24417     # if output is not int or float, abort
24418     {
24419       (is-simple-mu-type? %edx 1)  # int => eax
24420       3d/compare-eax-and 0/imm32/false
24421       75/jump-if-!= break/disp8
24422       (is-simple-mu-type? %edx 0xf)  # float => eax
24423       3d/compare-eax-and 0/imm32/false
24424       75/jump-if-!= break/disp8
24425       e9/jump $check-mu-convert-stmt:error-invalid-output-type/disp32
24426     }
24427     # if both are ints, abort
24428     {
24429       (is-simple-mu-type? %edx 1)  # int => eax
24430       3d/compare-eax-and 0/imm32/false
24431       74/jump-if-= break/disp8
24432       (is-simple-mu-type? %ecx 1)  # int => eax
24433       3d/compare-eax-and 0/imm32/false
24434       74/jump-if-= break/disp8
24435       e9/jump $check-mu-convert-stmt:error-int-to-int/disp32
24436     }
24437     # if both are floats, abort
24438     {
24439       (is-simple-mu-type? %edx 0xf)  # float => eax
24440       3d/compare-eax-and 0/imm32/false
24441       74/jump-if-= break/disp8
24442       (is-simple-mu-type? %ecx 0xf)  # float => eax
24443       3d/compare-eax-and 0/imm32/false
24444       74/jump-if-= break/disp8
24445       e9/jump $check-mu-convert-stmt:error-float-to-float/disp32
24446     }
24447 $check-mu-convert-stmt:end:
24448     # . restore registers
24449     5f/pop-to-edi
24450     5e/pop-to-esi
24451     5a/pop-to-edx
24452     59/pop-to-ecx
24453     58/pop-to-eax
24454     # . epilogue
24455     89/<- %esp 5/r32/ebp
24456     5d/pop-to-ebp
24457     c3/return
24458 
24459 $check-mu-convert-stmt:error-no-inout:
24460     (write-buffered *(ebp+0x10) "fn ")
24461     8b/-> *(ebp+0xc) 0/r32/eax
24462     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24463     (write-buffered *(ebp+0x10) %eax)
24464     (write-buffered *(ebp+0x10) ": stmt 'convert' expects an inout\n")
24465     (flush *(ebp+0x10))
24466     (stop *(ebp+0x14) 1)
24467     # never gets here
24468 
24469 $check-mu-convert-stmt:error-too-many-inouts:
24470     (write-buffered *(ebp+0x10) "fn ")
24471     8b/-> *(ebp+0xc) 0/r32/eax
24472     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24473     (write-buffered *(ebp+0x10) %eax)
24474     (write-buffered *(ebp+0x10) ": stmt 'convert' must have just one inout\n")
24475     (flush *(ebp+0x10))
24476     (stop *(ebp+0x14) 1)
24477     # never gets here
24478 
24479 $check-mu-convert-stmt:error-no-output:
24480     (write-buffered *(ebp+0x10) "fn ")
24481     8b/-> *(ebp+0xc) 0/r32/eax
24482     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24483     (write-buffered *(ebp+0x10) %eax)
24484     (write-buffered *(ebp+0x10) ": stmt 'convert' expects an output\n")
24485     (flush *(ebp+0x10))
24486     (stop *(ebp+0x14) 1)
24487     # never gets here
24488 
24489 $check-mu-convert-stmt:error-output-not-in-register:
24490     (write-buffered *(ebp+0x10) "fn ")
24491     8b/-> *(ebp+0xc) 0/r32/eax
24492     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24493     (write-buffered *(ebp+0x10) %eax)
24494     (write-buffered *(ebp+0x10) ": stmt convert: output '")
24495     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
24496     (lookup *eax *(eax+4))  # Var-name Var-name => eax
24497     (write-buffered *(ebp+0x10) %eax)
24498     (write-buffered *(ebp+0x10) "' not in a register\n")
24499     (flush *(ebp+0x10))
24500     (stop *(ebp+0x14) 1)
24501     # never gets here
24502 
24503 $check-mu-convert-stmt:error-too-many-outputs:
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 'convert' must have just one output\n")
24509     (flush *(ebp+0x10))
24510     (stop *(ebp+0x14) 1)
24511     # never gets here
24512 
24513 $check-mu-convert-stmt:error-invalid-inout-type:
24514     (write-buffered *(ebp+0x10) "fn ")
24515     8b/-> *(ebp+0xc) 0/r32/eax
24516     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24517     (write-buffered *(ebp+0x10) %eax)
24518     (write-buffered *(ebp+0x10) ": stmt convert: inout '")
24519     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
24520     (lookup *eax *(eax+4))  # Var-name Var-name => eax
24521     (write-buffered *(ebp+0x10) %eax)
24522     (write-buffered *(ebp+0x10) "' must be an int or float\n")
24523     (flush *(ebp+0x10))
24524     (stop *(ebp+0x14) 1)
24525     # never gets here
24526 
24527 $check-mu-convert-stmt:error-invalid-output-type:
24528     (write-buffered *(ebp+0x10) "fn ")
24529     8b/-> *(ebp+0xc) 0/r32/eax
24530     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24531     (write-buffered *(ebp+0x10) %eax)
24532     (write-buffered *(ebp+0x10) ": stmt convert: output '")
24533     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
24534     (lookup *eax *(eax+4))  # Var-name Var-name => eax
24535     (write-buffered *(ebp+0x10) %eax)
24536     (write-buffered *(ebp+0x10) "' must be an int or float\n")
24537     (flush *(ebp+0x10))
24538     (stop *(ebp+0x14) 1)
24539     # never gets here
24540 
24541 $check-mu-convert-stmt:error-int-to-int:
24542     (write-buffered *(ebp+0x10) "fn ")
24543     8b/-> *(ebp+0xc) 0/r32/eax
24544     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24545     (write-buffered *(ebp+0x10) %eax)
24546     (write-buffered *(ebp+0x10) ": stmt convert: no need to convert int to int\n")
24547     (flush *(ebp+0x10))
24548     (stop *(ebp+0x14) 1)
24549     # never gets here
24550 
24551 $check-mu-convert-stmt:error-float-to-float:
24552     (write-buffered *(ebp+0x10) "fn ")
24553     8b/-> *(ebp+0xc) 0/r32/eax
24554     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24555     (write-buffered *(ebp+0x10) %eax)
24556     (write-buffered *(ebp+0x10) ": stmt convert: no need to convert float to float\n")
24557     (flush *(ebp+0x10))
24558     (stop *(ebp+0x14) 1)
24559     # never gets here
24560 
24561 check-mu-call:  # stmt: (addr stmt), callee: (addr function), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
24562     # . prologue
24563     55/push-ebp
24564     89/<- %ebp 4/r32/esp
24565     # var type-parameters: (addr table (handle array byte) (addr type-tree) 8)
24566     68/push 0/imm32
24567     # var type-parameters-storage: (table (handle array byte) (addr type-tree) 8)
24568     81 5/subop/subtract %esp 0x60/imm32
24569     68/push 0x60/imm32/size
24570     68/push 0/imm32/read
24571     68/push 0/imm32/write
24572     # save a pointer to type-parameters-storage at type-parameters
24573     89/<- *(ebp-4) 4/r32/esp
24574     (clear-stream *(ebp-4))
24575     # . save registers
24576     50/push-eax
24577     51/push-ecx
24578     52/push-edx
24579     53/push-ebx
24580     56/push-esi
24581     57/push-edi
24582     # esi = stmt
24583     8b/-> *(ebp+8) 6/r32/esi
24584     # edi = callee
24585     8b/-> *(ebp+0xc) 7/r32/edi
24586     # var inouts/ecx: (addr stmt-var) = lookup(stmt->inouts)
24587     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24588     89/<- %ecx 0/r32/eax
24589     # var expected/edx: (addr list var) = lookup(f->inouts)
24590     (lookup *(edi+8) *(edi+0xc))  # Function-inouts Function-inouts => eax
24591     89/<- %edx 0/r32/eax
24592     {
24593 $check-mu-call:check-for-inouts:
24594       # if (inouts == 0) break
24595       81 7/subop/compare %ecx 0/imm32
24596       0f 84/jump-if-= break/disp32
24597       # if (expected == 0) error
24598       81 7/subop/compare %edx 0/imm32
24599       0f 84/jump-if-= break/disp32
24600 $check-mu-call:check-null-addr:
24601       # if (inouts->value->name == "0") continue
24602       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
24603       (lookup *eax *(eax+4))  # Var-name Var-name => eax
24604       (string-equal? %eax "0")  # => eax
24605       3d/compare-eax-and 0/imm32/false
24606       0f 85/jump-if-!= $check-mu-call:continue-to-next-inout/disp32
24607 $check-mu-call:check-inout-type:
24608       # var t/ebx: (addr type-tree) = inouts->value->type
24609       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
24610       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
24611       89/<- %ebx 0/r32/eax
24612       # if (inouts->is-deref?) t = t->right
24613       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
24614       {
24615         74/jump-if-= break/disp8
24616         (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
24617         89/<- %ebx 0/r32/eax
24618         # if t->right is null, t = t->left
24619         81 7/subop/compare *(ebx+0xc) 0/imm32  # Type-tree-right
24620         75/jump-if-!= break/disp8
24621         (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24622         89/<- %ebx 0/r32/eax
24623       }
24624       # var v2/eax: (addr v) = lookup(expected->value)
24625       (lookup *edx *(edx+4))  # List-value List-value => eax
24626       # var t2/eax: (addr type-tree) = lookup(v2->type)
24627       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
24628       # if (t != t2) error
24629       (type-match? %eax %ebx *(ebp-4))  # => eax
24630       3d/compare-eax-and 0/imm32/false
24631       {
24632         0f 85/jump-if-!= break/disp32
24633         (write-buffered *(ebp+0x14) "fn ")
24634         8b/-> *(ebp+0x10) 0/r32/eax
24635         (lookup *eax *(eax+4))  # Function-name Function-name => eax
24636         (write-buffered *(ebp+0x14) %eax)
24637         (write-buffered *(ebp+0x14) ": call ")
24638         (lookup *edi *(edi+4))  # Function-name Function-name => eax
24639         (write-buffered *(ebp+0x14) %eax)
24640         (write-buffered *(ebp+0x14) ": type for inout '")
24641         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
24642         (lookup *eax *(eax+4))  # Var-name Var-name => eax
24643         (write-buffered *(ebp+0x14) %eax)
24644         (write-buffered *(ebp+0x14) "' is not right\n")
24645         (flush *(ebp+0x14))
24646         (stop *(ebp+0x18) 1)
24647       }
24648 $check-mu-call:continue-to-next-inout:
24649       # inouts = lookup(inouts->next)
24650       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
24651       89/<- %ecx 0/r32/eax
24652       # expected = lookup(expected->next)
24653       (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
24654       89/<- %edx 0/r32/eax
24655       #
24656       e9/jump loop/disp32
24657     }
24658 $check-mu-call:check-inout-count:
24659     # if (inouts == expected) proceed
24660     39/compare %ecx 2/r32/edx
24661     {
24662       0f 84/jump-if-= break/disp32
24663       # exactly one of the two is null
24664       # if (inouts == 0) error("too many inouts")
24665       {
24666         81 7/subop/compare %ecx 0/imm32
24667         0f 84/jump-if-= break/disp32
24668         (write-buffered *(ebp+0x14) "fn ")
24669         8b/-> *(ebp+0x10) 0/r32/eax
24670         (lookup *eax *(eax+4))  # Function-name Function-name => eax
24671         (write-buffered *(ebp+0x14) %eax)
24672         (write-buffered *(ebp+0x14) ": call ")
24673         (lookup *edi *(edi+4))  # Function-name Function-name => eax
24674         (write-buffered *(ebp+0x14) %eax)
24675         (write-buffered *(ebp+0x14) ": too many inouts\n")
24676         (flush *(ebp+0x14))
24677         (stop *(ebp+0x18) 1)
24678       }
24679       # if (expected == 0) error("too few inouts")
24680       {
24681         81 7/subop/compare %edx 0/imm32
24682         0f 84/jump-if-= break/disp32
24683         (write-buffered *(ebp+0x14) "fn ")
24684         8b/-> *(ebp+0x10) 0/r32/eax
24685         (lookup *eax *(eax+4))  # Function-name Function-name => eax
24686         (write-buffered *(ebp+0x14) %eax)
24687         (write-buffered *(ebp+0x14) ": call ")
24688         (lookup *edi *(edi+4))  # Function-name Function-name => eax
24689         (write-buffered *(ebp+0x14) %eax)
24690         (write-buffered *(ebp+0x14) ": too few inouts\n")
24691         (flush *(ebp+0x14))
24692         (stop *(ebp+0x18) 1)
24693       }
24694     }
24695 $check-mu-call:check-outputs:
24696     # var outputs/ecx: (addr stmt-var) = lookup(stmt->outputs)
24697     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24698     89/<- %ecx 0/r32/eax
24699     # var expected/edx: (addr list var) = lookup(f->outputs)
24700     (lookup *(edi+0x10) *(edi+0x14))  # Function-outputs Function-outputs => eax
24701     89/<- %edx 0/r32/eax
24702     {
24703 $check-mu-call:check-for-outputs:
24704       # if (outputs == 0) break
24705       81 7/subop/compare %ecx 0/imm32
24706       0f 84/jump-if-= break/disp32
24707       # if (expected == 0) error
24708       81 7/subop/compare %edx 0/imm32
24709       0f 84/jump-if-= break/disp32
24710 $check-mu-call:check-output-type:
24711       # var v/eax: (addr v) = lookup(outputs->value)
24712       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
24713       # var t/ebx: (addr type-tree) = lookup(v->type)
24714       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
24715       89/<- %ebx 0/r32/eax
24716       # if (outputs->is-deref?) t = t->right  # TODO: check that t->left is an addr
24717       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
24718       {
24719         74/jump-if-= break/disp8
24720         (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
24721         89/<- %ebx 0/r32/eax
24722       }
24723       # var v2/eax: (addr v) = lookup(expected->value)
24724       (lookup *edx *(edx+4))  # List-value List-value => eax
24725       # var t2/eax: (addr type-tree) = lookup(v2->type)
24726       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
24727       # if (t != t2) error
24728       (type-match? %eax %ebx *(ebp-4))  # => eax
24729       3d/compare-eax-and 0/imm32/false
24730       {
24731         0f 85/jump-if-!= break/disp32
24732         (write-buffered *(ebp+0x14) "fn ")
24733         8b/-> *(ebp+0x10) 0/r32/eax
24734         (lookup *eax *(eax+4))  # Function-name Function-name => eax
24735         (write-buffered *(ebp+0x14) %eax)
24736         (write-buffered *(ebp+0x14) ": call ")
24737         (lookup *edi *(edi+4))  # Function-name Function-name => eax
24738         (write-buffered *(ebp+0x14) %eax)
24739         (write-buffered *(ebp+0x14) ": type for output '")
24740         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
24741         (lookup *eax *(eax+4))  # Var-name Var-name => eax
24742         (write-buffered *(ebp+0x14) %eax)
24743         (write-buffered *(ebp+0x14) "' is not right\n")
24744         (flush *(ebp+0x14))
24745         (stop *(ebp+0x18) 1)
24746       }
24747 $check-mu-call:check-output-register:
24748       # var v/eax: (addr v) = lookup(outputs->value)
24749       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
24750       # var r/ebx: (addr array byte) = lookup(v->register)
24751       (lookup *(eax+18) *(eax+0x1c))  # Var-register Var-register => eax
24752       89/<- %ebx 0/r32/eax
24753       # if (r == 0) error
24754       3d/compare-eax-and 0/imm32
24755       {
24756         0f 85/jump-if-!= break/disp32
24757         (write-buffered *(ebp+0x14) "fn ")
24758         8b/-> *(ebp+0x10) 0/r32/eax
24759         (lookup *eax *(eax+4))  # Function-name Function-name => eax
24760         (write-buffered *(ebp+0x14) %eax)
24761         (write-buffered *(ebp+0x14) ": call ")
24762         (lookup *edi *(edi+4))  # Function-name Function-name => eax
24763         (write-buffered *(ebp+0x14) %eax)
24764         (write-buffered *(ebp+0x14) ": output '")
24765         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
24766         (lookup *eax *(eax+4))  # Var-name Var-name => eax
24767         (write-buffered *(ebp+0x14) %eax)
24768         (write-buffered *(ebp+0x14) "' is not in a register\n")
24769         (flush *(ebp+0x14))
24770         (stop *(ebp+0x18) 1)
24771       }
24772       # var v2/eax: (addr v) = lookup(expected->value)
24773       (lookup *edx *(edx+4))  # Stmt-var-value Stmt-var-value => eax
24774       # var r2/eax: (addr array byte) = lookup(v2->register)
24775       (lookup *(eax+18) *(eax+0x1c))  # Var-register Var-register => eax
24776       # if (r != r2) error
24777       (string-equal? %eax %ebx)  # => eax
24778       3d/compare-eax-and 0/imm32/false
24779       {
24780         0f 85/jump-if-!= break/disp32
24781         (write-buffered *(ebp+0x14) "fn ")
24782         8b/-> *(ebp+0x10) 0/r32/eax
24783         (lookup *eax *(eax+4))  # Function-name Function-name => eax
24784         (write-buffered *(ebp+0x14) %eax)
24785         (write-buffered *(ebp+0x14) ": call ")
24786         (lookup *edi *(edi+4))  # Function-name Function-name => eax
24787         (write-buffered *(ebp+0x14) %eax)
24788         (write-buffered *(ebp+0x14) ": register for output '")
24789         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
24790         (lookup *eax *(eax+4))  # Var-name Var-name => eax
24791         (write-buffered *(ebp+0x14) %eax)
24792         (write-buffered *(ebp+0x14) "' is not right\n")
24793         (flush *(ebp+0x14))
24794         (stop *(ebp+0x18) 1)
24795       }
24796 $check-mu-call:continue-to-next-output:
24797       # outputs = lookup(outputs->next)
24798       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
24799       89/<- %ecx 0/r32/eax
24800       # expected = lookup(expected->next)
24801       (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
24802       89/<- %edx 0/r32/eax
24803       #
24804       e9/jump loop/disp32
24805     }
24806 $check-mu-call:check-output-count:
24807     # if (outputs == expected) proceed
24808     39/compare %ecx 2/r32/edx
24809     {
24810       0f 84/jump-if-= break/disp32
24811       # exactly one of the two is null
24812       # if (outputs == 0) error("too many outputs")
24813       {
24814         81 7/subop/compare %ecx 0/imm32
24815         0f 84/jump-if-= break/disp32
24816         (write-buffered *(ebp+0x14) "fn ")
24817         8b/-> *(ebp+0x10) 0/r32/eax
24818         (lookup *eax *(eax+4))  # Function-name Function-name => eax
24819         (write-buffered *(ebp+0x14) %eax)
24820         (write-buffered *(ebp+0x14) ": call ")
24821         (lookup *edi *(edi+4))  # Function-name Function-name => eax
24822         (write-buffered *(ebp+0x14) %eax)
24823         (write-buffered *(ebp+0x14) ": too many outputs\n")
24824         (flush *(ebp+0x14))
24825         (stop *(ebp+0x18) 1)
24826       }
24827       # if (expected == 0) error("too few outputs")
24828       {
24829         81 7/subop/compare %edx 0/imm32
24830         0f 84/jump-if-= break/disp32
24831         (write-buffered *(ebp+0x14) "fn ")
24832         8b/-> *(ebp+0x10) 0/r32/eax
24833         (lookup *eax *(eax+4))  # Function-name Function-name => eax
24834         (write-buffered *(ebp+0x14) %eax)
24835         (write-buffered *(ebp+0x14) ": call ")
24836         (lookup *edi *(edi+4))  # Function-name Function-name => eax
24837         (write-buffered *(ebp+0x14) %eax)
24838         (write-buffered *(ebp+0x14) ": too few outputs\n")
24839         (flush *(ebp+0x14))
24840         (stop *(ebp+0x18) 1)
24841       }
24842     }
24843 $check-mu-call:end:
24844     # . restore registers
24845     5f/pop-to-edi
24846     5e/pop-to-esi
24847     5b/pop-to-ebx
24848     5a/pop-to-edx
24849     59/pop-to-ecx
24850     58/pop-to-eax
24851     # . reclaim locals exclusively on the stack
24852     81 0/subop/add %esp 0x70/imm32
24853     # . epilogue
24854     89/<- %esp 5/r32/ebp
24855     5d/pop-to-ebp
24856     c3/return
24857 
24858 # like type-equal? but takes literals type parameters into account
24859 type-match?:  # def: (addr type-tree), call: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean
24860     # . prologue
24861     55/push-ebp
24862     89/<- %ebp 4/r32/esp
24863     # if (call is literal and def is numberlike) return true
24864     {
24865 $type-match?:check-literal-int:
24866       (is-simple-mu-type? *(ebp+0xc) 0)  # literal => eax
24867       3d/compare-eax-and 0/imm32/false
24868       74/jump-if-= break/disp8
24869       (is-mu-numberlike-output? *(ebp+8))  # => eax
24870       3d/compare-eax-and 0/imm32/false
24871       74/jump-if-= break/disp8
24872       b8/copy-to-eax 1/imm32/true
24873       e9/jump $type-match?:end/disp32
24874     }
24875     # if (call is literal-string and def is string) return true
24876     {
24877 $type-match?:check-literal-string:
24878       (is-simple-mu-type? *(ebp+0xc) 0x10)  # literal-string => eax
24879       3d/compare-eax-and 0/imm32/false
24880       74/jump-if-= break/disp8
24881       (is-mu-string-type? *(ebp+8))  # => eax
24882       3d/compare-eax-and 0/imm32/false
24883       74/jump-if-= break/disp8
24884       b8/copy-to-eax 1/imm32/true
24885       e9/jump $type-match?:end/disp32
24886     }
24887 $type-match?:baseline:
24888     # otherwise fall back
24889     (type-component-match? *(ebp+8) *(ebp+0xc) *(ebp+0x10))  # => eax
24890 $type-match?:end:
24891     # . epilogue
24892     89/<- %esp 5/r32/ebp
24893     5d/pop-to-ebp
24894     c3/return
24895 
24896 type-component-match?:  # def: (addr type-tree), call: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean
24897     # . prologue
24898     55/push-ebp
24899     89/<- %ebp 4/r32/esp
24900     # . save registers
24901     51/push-ecx
24902     52/push-edx
24903     53/push-ebx
24904     # ecx = def
24905     8b/-> *(ebp+8) 1/r32/ecx
24906     # edx = call
24907     8b/-> *(ebp+0xc) 2/r32/edx
24908 $type-component-match?:compare-addr:
24909     # if (def == call) return true
24910     8b/-> %ecx 0/r32/eax  # Var-type
24911     39/compare %edx 0/r32/eax  # Var-type
24912     b8/copy-to-eax 1/imm32/true
24913     0f 84/jump-if-= $type-component-match?:end/disp32
24914     # if (def == 0) return false
24915     b8/copy-to-eax 0/imm32/false
24916     81 7/subop/compare %ecx 0/imm32  # Type-tree-is-atom
24917     0f 84/jump-if-= $type-component-match?:end/disp32
24918     # if (call == 0) return false
24919     81 7/subop/compare %edx 0/imm32  # Type-tree-is-atom
24920     0f 84/jump-if-= $type-component-match?:end/disp32
24921     # if def is a type parameter, just check in type-parameters
24922     {
24923 $type-component-match?:check-type-parameter:
24924       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
24925       74/jump-if-= break/disp8
24926       81 7/subop/compare *(ecx+4) 0xa/imm32/type-parameter  # Type-tree-value
24927       75/jump-if-!= break/disp8
24928 $type-component-match?:type-parameter:
24929       (type-parameter-match? *(ecx+8) *(ecx+0xc)  %edx  *(ebp+0x10))  # => eax
24930       e9/jump $type-component-match?:end/disp32
24931     }
24932     # if def is a list containing just a type parameter, just check in type-parameters
24933     {
24934 $type-component-match?:check-list-type-parameter:
24935       # if def is a list..
24936       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
24937       75/jump-if-!= break/disp8
24938       #   ..that's a singleton
24939       81 7/subop/compare *(ecx+0xc) 0/imm32  # Type-tree-left
24940       75/jump-if-!= break/disp8
24941       #   ..and whose head is a type parameter
24942       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
24943       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
24944       74/jump-if-= break/disp8
24945       81 7/subop/compare *(eax+4) 0xa/imm32/type-parameter  # Type-tree-value
24946       75/jump-if-!= break/disp8
24947 $type-component-match?:list-type-parameter:
24948       (type-parameter-match? *(eax+8) *(eax+0xc)  %edx  *(ebp+0x10))  # => eax
24949       e9/jump $type-component-match?:end/disp32
24950     }
24951 $type-component-match?:compare-atom-state:
24952     # if (def->is-atom? != call->is-atom?) return false
24953     8b/-> *ecx 3/r32/ebx  # Type-tree-is-atom
24954     39/compare *edx 3/r32/ebx  # Type-tree-is-atom
24955     b8/copy-to-eax 0/imm32/false
24956     0f 85/jump-if-!= $type-component-match?:end/disp32
24957     # if def->is-atom? return (def->value == call->value)
24958     {
24959 $type-component-match?:check-atom:
24960       81 7/subop/compare %ebx 0/imm32/false
24961       74/jump-if-= break/disp8
24962 $type-component-match?:is-atom:
24963       8b/-> *(ecx+4) 0/r32/eax  # Type-tree-value
24964       39/compare *(edx+4) 0/r32/eax  # Type-tree-value
24965       0f 94/set-if-= %al
24966       81 4/subop/and %eax 0xff/imm32
24967       e9/jump $type-component-match?:end/disp32
24968     }
24969 $type-component-match?:check-left:
24970     # if (!type-component-match?(def->left, call->left)) return false
24971     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
24972     89/<- %ebx 0/r32/eax
24973     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
24974     (type-component-match? %ebx %eax *(ebp+0x10))  # => eax
24975     3d/compare-eax-and 0/imm32/false
24976     74/jump-if-= $type-component-match?:end/disp8
24977 $type-component-match?:check-right:
24978     # return type-component-match?(def->right, call->right)
24979     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
24980     89/<- %ebx 0/r32/eax
24981     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
24982     (type-component-match? %ebx %eax *(ebp+0x10))  # => eax
24983 $type-component-match?:end:
24984     # . restore registers
24985     5b/pop-to-ebx
24986     5a/pop-to-edx
24987     59/pop-to-ecx
24988     # . epilogue
24989     89/<- %esp 5/r32/ebp
24990     5d/pop-to-ebp
24991     c3/return
24992 
24993 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
24994     # . prologue
24995     55/push-ebp
24996     89/<- %ebp 4/r32/esp
24997     # . save registers
24998     51/push-ecx
24999     #
25000     (get-or-insert-handle *(ebp+0x14)  *(ebp+8) *(ebp+0xc)  0xc)  # => eax
25001     # if parameter wasn't saved, save it
25002     {
25003       81 7/subop/compare *eax 0/imm32
25004       75/jump-if-!= break/disp8
25005       8b/-> *(ebp+0x10) 1/r32/ecx
25006       89/<- *eax 1/r32/ecx
25007     }
25008     #
25009     (type-equal? *(ebp+0x10) *eax)  # => eax
25010 $type-parameter-match?:end:
25011     # . restore registers
25012     59/pop-to-ecx
25013     # . epilogue
25014     89/<- %esp 5/r32/ebp
25015     5d/pop-to-ebp
25016     c3/return
25017 
25018 size-of:  # v: (addr var) -> result/eax: int
25019     # . prologue
25020     55/push-ebp
25021     89/<- %ebp 4/r32/esp
25022     # . save registers
25023     51/push-ecx
25024     # var t/ecx: (addr type-tree) = lookup(v->type)
25025     8b/-> *(ebp+8) 1/r32/ecx
25026 #?     (write-buffered Stderr "size-of ")
25027 #?     (write-int32-hex-buffered Stderr %ecx)
25028 #?     (write-buffered Stderr Newline)
25029 #?     (write-buffered Stderr "type allocid: ")
25030 #?     (write-int32-hex-buffered Stderr *(ecx+8))
25031 #?     (write-buffered Stderr Newline)
25032 #?     (flush Stderr)
25033     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
25034     89/<- %ecx 0/r32/eax
25035     # if is-mu-array?(t) return size-of-array(t)
25036     {
25037       (is-mu-array? %ecx)  # => eax
25038       3d/compare-eax-and 0/imm32/false
25039       74/jump-if-= break/disp8
25040       (size-of-array %ecx)  # => eax
25041       eb/jump $size-of:end/disp8
25042     }
25043     # if is-mu-stream?(t) return size-of-stream(t)
25044     {
25045       (is-mu-stream? %ecx)  # => eax
25046       3d/compare-eax-and 0/imm32/false
25047       74/jump-if-= break/disp8
25048       (size-of-stream %ecx)  # => eax
25049       eb/jump $size-of:end/disp8
25050     }
25051     # if (!t->is-atom?) t = lookup(t->left)
25052     {
25053       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
25054       75/jump-if-!= break/disp8
25055       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
25056       89/<- %ecx 0/r32/eax
25057     }
25058     # TODO: assert t->is-atom?
25059     (size-of-type-id *(ecx+4))  # Type-tree-value => eax
25060 $size-of:end:
25061     # . restore registers
25062     59/pop-to-ecx
25063     # . epilogue
25064     89/<- %esp 5/r32/ebp
25065     5d/pop-to-ebp
25066     c3/return
25067 
25068 size-of-deref:  # v: (addr var) -> result/eax: int
25069     # . prologue
25070     55/push-ebp
25071     89/<- %ebp 4/r32/esp
25072     # . save registers
25073     51/push-ecx
25074     # var t/ecx: (addr type-tree) = lookup(v->type)
25075     8b/-> *(ebp+8) 1/r32/ecx
25076     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
25077     89/<- %ecx 0/r32/eax
25078     # TODO: assert(t is an addr)
25079     # t = lookup(t->right)
25080     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
25081     89/<- %ecx 0/r32/eax
25082     # if is-mu-array?(t) return size-of-array(t)
25083     {
25084       (is-mu-array? %ecx)  # => eax
25085       3d/compare-eax-and 0/imm32/false
25086       74/jump-if-= break/disp8
25087       (size-of-array %ecx)  # => eax
25088       eb/jump $size-of-deref:end/disp8
25089     }
25090     # if is-mu-stream?(t) return size-of-stream(t)
25091     {
25092       (is-mu-stream? %ecx)  # => eax
25093       3d/compare-eax-and 0/imm32/false
25094       74/jump-if-= break/disp8
25095       (size-of-stream %ecx)  # => eax
25096       eb/jump $size-of-deref:end/disp8
25097     }
25098     # if (!t->is-atom?) t = lookup(t->left)
25099     {
25100       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
25101       75/jump-if-!= break/disp8
25102       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
25103       89/<- %ecx 0/r32/eax
25104     }
25105     # TODO: assert t->is-atom?
25106     (size-of-type-id *(ecx+4))  # Type-tree-value => eax
25107 $size-of-deref:end:
25108     # . restore registers
25109     59/pop-to-ecx
25110     # . epilogue
25111     89/<- %esp 5/r32/ebp
25112     5d/pop-to-ebp
25113     c3/return
25114 
25115 is-mu-array?:  # t: (addr type-tree) -> result/eax: boolean
25116     # . prologue
25117     55/push-ebp
25118     89/<- %ebp 4/r32/esp
25119     # . save registers
25120     51/push-ecx
25121     # ecx = t
25122     8b/-> *(ebp+8) 1/r32/ecx
25123     # if t->is-atom?, return false
25124     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
25125     75/jump-if-!= $is-mu-array?:return-false/disp8
25126     # if !t->left->is-atom?, return false
25127     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
25128     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
25129     74/jump-if-= $is-mu-array?:return-false/disp8
25130     # return t->left->value == array
25131     81 7/subop/compare *(eax+4) 3/imm32/array-type-id  # Type-tree-value
25132     0f 94/set-if-= %al
25133     81 4/subop/and %eax 0xff/imm32
25134     eb/jump $is-mu-array?:end/disp8
25135 $is-mu-array?:return-false:
25136     b8/copy-to-eax 0/imm32/false
25137 $is-mu-array?:end:
25138     # . restore registers
25139     59/pop-to-ecx
25140     # . epilogue
25141     89/<- %esp 5/r32/ebp
25142     5d/pop-to-ebp
25143     c3/return
25144 
25145 # size of a statically allocated array where the size is part of the type expression
25146 size-of-array:  # a: (addr type-tree) -> result/eax: int
25147     # . prologue
25148     55/push-ebp
25149     89/<- %ebp 4/r32/esp
25150     # . save registers
25151     51/push-ecx
25152     52/push-edx
25153     #
25154     8b/-> *(ebp+8) 1/r32/ecx
25155     # TODO: assert that a->left is 'array'
25156     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
25157     89/<- %ecx 0/r32/eax
25158     # var elem-type/edx: type-id = a->right->left->value
25159     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
25160     8b/-> *(eax+4) 2/r32/edx  # Type-tree-value
25161     # TODO: assert that a->right->right->left->value == size
25162     # var array-size/ecx: int = a->right->right->left->value-size
25163     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
25164     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25165     8b/-> *(eax+8) 1/r32/ecx  # Type-tree-value-size
25166     # return 4 + array-size * size-of(elem-type)
25167     (size-of-type-id-as-array-element %edx)  # => eax
25168     f7 4/subop/multiply-into-edx-eax %ecx
25169     05/add-to-eax 4/imm32  # for array size
25170     # TODO: check edx for overflow
25171 $size-of-array:end:
25172     # . restore registers
25173     5a/pop-to-edx
25174     59/pop-to-ecx
25175     # . epilogue
25176     89/<- %esp 5/r32/ebp
25177     5d/pop-to-ebp
25178     c3/return
25179 
25180 is-mu-stream?:  # t: (addr type-tree) -> result/eax: boolean
25181     # . prologue
25182     55/push-ebp
25183     89/<- %ebp 4/r32/esp
25184     # . save registers
25185     51/push-ecx
25186     # ecx = t
25187     8b/-> *(ebp+8) 1/r32/ecx
25188     # if t->is-atom?, return false
25189     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
25190     75/jump-if-!= $is-mu-stream?:return-false/disp8
25191     # if !t->left->is-atom?, return false
25192     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
25193     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
25194     74/jump-if-= $is-mu-stream?:return-false/disp8
25195     # return t->left->value == stream
25196     81 7/subop/compare *(eax+4) 0xb/imm32/stream-type-id  # Type-tree-value
25197     0f 94/set-if-= %al
25198     81 4/subop/and %eax 0xff/imm32
25199     eb/jump $is-mu-stream?:end/disp8
25200 $is-mu-stream?:return-false:
25201     b8/copy-to-eax 0/imm32/false
25202 $is-mu-stream?:end:
25203     # . restore registers
25204     59/pop-to-ecx
25205     # . epilogue
25206     89/<- %esp 5/r32/ebp
25207     5d/pop-to-ebp
25208     c3/return
25209 
25210 # size of a statically allocated stream where the size is part of the type expression
25211 size-of-stream:  # a: (addr type-tree) -> result/eax: int
25212     # . prologue
25213     55/push-ebp
25214     89/<- %ebp 4/r32/esp
25215     #
25216     (size-of-array *(ebp+8))  # assumes we ignore the actual type name 'array' in the type
25217     05/add-to-eax 8/imm32  # for read/write pointers
25218 $size-of-stream:end:
25219     # . epilogue
25220     89/<- %esp 5/r32/ebp
25221     5d/pop-to-ebp
25222     c3/return
25223 
25224 size-of-type-id:  # t: type-id -> result/eax: int
25225     # . prologue
25226     55/push-ebp
25227     89/<- %ebp 4/r32/esp
25228     # . save registers
25229     51/push-ecx
25230     # var out/ecx: (handle typeinfo)
25231     68/push 0/imm32
25232     68/push 0/imm32
25233     89/<- %ecx 4/r32/esp
25234     # eax = t
25235     8b/-> *(ebp+8) 0/r32/eax
25236     # if t is a literal, return 0
25237     3d/compare-eax-and 0/imm32
25238     0f 84/jump-if-= $size-of-type-id:end/disp32  # eax changes type from type-id to int
25239     # if t is a byte, return 4 (because we don't really support non-multiples of 4)
25240     3d/compare-eax-and 8/imm32/byte
25241     {
25242       75/jump-if-!= break/disp8
25243       b8/copy-to-eax 4/imm32
25244       eb/jump $size-of-type-id:end/disp8
25245     }
25246     # if t is a handle, return 8
25247     3d/compare-eax-and 4/imm32/handle
25248     {
25249       75/jump-if-!= break/disp8
25250       b8/copy-to-eax 8/imm32
25251       eb/jump $size-of-type-id:end/disp8  # eax changes type from type-id to int
25252     }
25253     # if t is a slice, return 8
25254     3d/compare-eax-and 0xc/imm32/slice
25255     {
25256       75/jump-if-!= break/disp8
25257       b8/copy-to-eax 8/imm32
25258       eb/jump $size-of-type-id:end/disp8  # eax changes type from type-id to int
25259     }
25260     # if t is a user-defined type, return its size
25261     # TODO: support non-atom type
25262     (find-typeinfo %eax %ecx)
25263     {
25264       81 7/subop/compare *ecx 0/imm32
25265       74/jump-if-= break/disp8
25266 $size-of-type-id:user-defined:
25267       (lookup *ecx *(ecx+4))  # => eax
25268       8b/-> *(eax+0xc) 0/r32/eax  # Typeinfo-total-size-in-bytes
25269       eb/jump $size-of-type-id:end/disp8
25270     }
25271     # otherwise return the word size
25272     b8/copy-to-eax 4/imm32
25273 $size-of-type-id:end:
25274     # . reclaim locals
25275     81 0/subop/add %esp 8/imm32
25276     # . restore registers
25277     59/pop-to-ecx
25278     # . epilogue
25279     89/<- %esp 5/r32/ebp
25280     5d/pop-to-ebp
25281     c3/return
25282 
25283 # Minor violation of our type system since it returns an addr. But we could
25284 # replace it with a handle some time.
25285 # Returns null if t is an atom.
25286 type-tail:  # t: (addr type-tree) -> out/eax: (addr type-tree)
25287     # . prologue
25288     55/push-ebp
25289     89/<- %ebp 4/r32/esp
25290     # . save registers
25291     51/push-ecx
25292     # eax = 0
25293     b8/copy-to-eax 0/imm32
25294     # ecx = t
25295     8b/-> *(ebp+8) 1/r32/ecx
25296 $type-tail:check-atom:
25297     # if t->is-atom? return 0
25298     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
25299     0f 85/jump-if-!= $type-tail:end/disp32
25300     # var tail = t->right
25301     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
25302     89/<- %ecx 0/r32/eax
25303 $type-tail:check-singleton:
25304     # if (tail->right == 0) return tail->left
25305     {
25306       81 7/subop/compare *(ecx+0xc) 0/imm32  # Type-tree-right
25307       75/jump-if-!= break/disp8
25308       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
25309       e9/jump $type-tail:end/disp32
25310     }
25311     # if tail->right->left is an array-capacity, return tail->left
25312     {
25313 $type-tail:check-array-capacity:
25314       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
25315       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
25316       75/jump-if-!= break/disp8
25317 $type-tail:check-array-capacity-1:
25318       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25319       3d/compare-eax-and 0/imm32
25320       74/jump-if-= break/disp8
25321 $type-tail:check-array-capacity-2:
25322       (is-simple-mu-type? %eax 9)  # array-capacity => eax
25323       3d/compare-eax-and 0/imm32/false
25324       74/jump-if-= break/disp8
25325 $type-tail:array-capacity:
25326       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
25327       eb/jump $type-tail:end/disp8
25328     }
25329 $type-tail:check-compound-left:
25330     # if !tail->left->is-atom? return tail->left
25331     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
25332     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
25333     74/jump-if-= $type-tail:end/disp8
25334 $type-tail:return-tail:
25335     # return tail
25336     89/<- %eax 1/r32/ecx
25337 $type-tail:end:
25338     # . restore registers
25339     59/pop-to-ecx
25340     # . epilogue
25341     89/<- %esp 5/r32/ebp
25342     5d/pop-to-ebp
25343     c3/return
25344 
25345 type-equal?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
25346     # . prologue
25347     55/push-ebp
25348     89/<- %ebp 4/r32/esp
25349     # . save registers
25350     51/push-ecx
25351     52/push-edx
25352     53/push-ebx
25353     # ecx = a
25354     8b/-> *(ebp+8) 1/r32/ecx
25355     # edx = b
25356     8b/-> *(ebp+0xc) 2/r32/edx
25357 $type-equal?:compare-addr:
25358     # if (a == b) return true
25359     8b/-> %ecx 0/r32/eax  # Var-type
25360     39/compare %edx 0/r32/eax  # Var-type
25361     b8/copy-to-eax 1/imm32/true
25362     0f 84/jump-if-= $type-equal?:end/disp32
25363 $type-equal?:compare-null-a:
25364     # if (a == 0) return false
25365     b8/copy-to-eax 0/imm32/false
25366     81 7/subop/compare %ecx 0/imm32
25367     0f 84/jump-if-= $type-equal?:end/disp32
25368 $type-equal?:compare-null-b:
25369     # if (b == 0) return false
25370     81 7/subop/compare %edx 0/imm32
25371     0f 84/jump-if-= $type-equal?:end/disp32
25372 $type-equal?:compare-atom-state:
25373     # if (a->is-atom? != b->is-atom?) return false
25374     8b/-> *ecx 3/r32/ebx  # Type-tree-is-atom
25375     39/compare *edx 3/r32/ebx  # Type-tree-is-atom
25376     b8/copy-to-eax 0/imm32/false
25377     0f 85/jump-if-!= $type-equal?:end/disp32
25378     # if a->is-atom? return (a->value == b->value)
25379     {
25380 $type-equal?:check-atom:
25381       81 7/subop/compare %ebx 0/imm32/false
25382       74/jump-if-= break/disp8
25383 $type-equal?:is-atom:
25384       8b/-> *(ecx+4) 0/r32/eax  # Type-tree-value
25385       39/compare *(edx+4) 0/r32/eax  # Type-tree-value
25386       0f 94/set-if-= %al
25387       81 4/subop/and %eax 0xff/imm32
25388       e9/jump $type-equal?:end/disp32
25389     }
25390 $type-equal?:check-left:
25391     # if (!type-equal?(a->left, b->left)) return false
25392     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
25393     89/<- %ebx 0/r32/eax
25394     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
25395     (type-equal? %eax %ebx)  # => eax
25396     3d/compare-eax-and 0/imm32/false
25397     74/jump-if-= $type-equal?:end/disp8
25398 $type-equal?:check-right:
25399     # return type-equal?(a->right, b->right)
25400     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
25401     89/<- %ebx 0/r32/eax
25402     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
25403     (type-equal? %eax %ebx)  # => eax
25404 $type-equal?:end:
25405     # . restore registers
25406     5b/pop-to-ebx
25407     5a/pop-to-edx
25408     59/pop-to-ecx
25409     # . epilogue
25410     89/<- %esp 5/r32/ebp
25411     5d/pop-to-ebp
25412     c3/return
25413 
25414 #######################################################
25415 # Code-generation
25416 #######################################################
25417 
25418 == data
25419 
25420 # Global state added to each var record when performing code-generation.
25421 Curr-local-stack-offset:  # (addr int)
25422     0/imm32
25423 
25424 == code
25425 
25426 # We may not need to pass err/ed everywhere here. I think they're relics of Mu
25427 # getting type checks later in life.
25428 # But we do need them for runtime checks, particularly array index bounds checks.
25429 # So perhaps it's not worth taking them out. They're a safety net.
25430 
25431 emit-subx:  # out: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
25432     # . prologue
25433     55/push-ebp
25434     89/<- %ebp 4/r32/esp
25435     # . save registers
25436     50/push-eax
25437     # var curr/eax: (addr function) = *Program->functions
25438     (lookup *_Program-functions *_Program-functions->payload)  # => eax
25439     {
25440       # if (curr == null) break
25441       3d/compare-eax-and 0/imm32
25442       0f 84/jump-if-= break/disp32
25443       (emit-subx-function *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10))
25444       # curr = lookup(curr->next)
25445       (lookup *(eax+0x20) *(eax+0x24))  # Function-next Function-next => eax
25446       e9/jump loop/disp32
25447     }
25448 $emit-subx:end:
25449     # . restore registers
25450     58/pop-to-eax
25451     # . epilogue
25452     89/<- %esp 5/r32/ebp
25453     5d/pop-to-ebp
25454     c3/return
25455 
25456 emit-subx-function:  # out: (addr buffered-file), f: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
25457     # . prologue
25458     55/push-ebp
25459     89/<- %ebp 4/r32/esp
25460     # some preprocessing
25461     (populate-mu-type-offsets-in-inouts *(ebp+0xc))
25462     # . save registers
25463     50/push-eax
25464     51/push-ecx
25465     52/push-edx
25466     # initialize some global state
25467     c7 0/subop/copy *Curr-block-depth 1/imm32  # Important: keep this in sync with the parse phase
25468     c7 0/subop/copy *Curr-local-stack-offset 0/imm32
25469     # ecx = f
25470     8b/-> *(ebp+0xc) 1/r32/ecx
25471     # var vars/edx: (stack (addr var) 256)
25472     81 5/subop/subtract %esp 0xc00/imm32
25473     68/push 0xc00/imm32/size
25474     68/push 0/imm32/top
25475     89/<- %edx 4/r32/esp
25476     # var name/eax: (addr array byte) = lookup(f->name)
25477     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
25478     #
25479     (write-buffered *(ebp+8) %eax)
25480     (write-buffered *(ebp+8) ":\n")
25481     (emit-subx-prologue *(ebp+8))
25482     # var body/eax: (addr block) = lookup(f->body)
25483     (lookup *(ecx+0x18) *(ecx+0x1c))  # Function-body Function-body => eax
25484     #
25485     (emit-subx-block *(ebp+8) %eax %edx *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
25486     (emit-subx-epilogue *(ebp+8))
25487     # TODO: validate that *Curr-block-depth and *Curr-local-stack-offset have
25488     # been cleaned up
25489 $emit-subx-function:end:
25490     # . reclaim locals
25491     81 0/subop/add %esp 0xc08/imm32
25492     # . restore registers
25493     5a/pop-to-edx
25494     59/pop-to-ecx
25495     58/pop-to-eax
25496     # . epilogue
25497     89/<- %esp 5/r32/ebp
25498     5d/pop-to-ebp
25499     c3/return
25500 
25501 populate-mu-type-offsets-in-inouts:  # f: (addr function)
25502     # . prologue
25503     55/push-ebp
25504     89/<- %ebp 4/r32/esp
25505     # . save registers
25506     50/push-eax
25507     51/push-ecx
25508     52/push-edx
25509     53/push-ebx
25510     57/push-edi
25511     # var next-offset/edx: int = 8
25512     ba/copy-to-edx 8/imm32
25513     # var curr/ecx: (addr list var) = lookup(f->inouts)
25514     8b/-> *(ebp+8) 1/r32/ecx
25515     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
25516     89/<- %ecx 0/r32/eax
25517     {
25518 $populate-mu-type-offsets-in-inouts:loop:
25519       81 7/subop/compare %ecx 0/imm32
25520       74/jump-if-= break/disp8
25521       # var v/ebx: (addr var) = lookup(curr->value)
25522       (lookup *ecx *(ecx+4))  # List-value List-value => eax
25523       89/<- %ebx 0/r32/eax
25524 #?       (lookup *ebx *(ebx+4))
25525 #?       (write-buffered Stderr "setting offset of fn inout ")
25526 #?       (write-buffered Stderr %eax)
25527 #?       (write-buffered Stderr "@")
25528 #?       (write-int32-hex-buffered Stderr %ebx)
25529 #?       (write-buffered Stderr " to ")
25530 #?       (write-int32-hex-buffered Stderr %edx)
25531 #?       (write-buffered Stderr Newline)
25532 #?       (flush Stderr)
25533       # v->offset = next-offset
25534       89/<- *(ebx+0x14) 2/r32/edx  # Var-offset
25535       # next-offset += size-of(v)
25536       (size-of %ebx)  # => eax
25537       01/add-to %edx 0/r32/eax
25538       # curr = lookup(curr->next)
25539       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
25540       89/<- %ecx 0/r32/eax
25541       #
25542       eb/jump loop/disp8
25543     }
25544 $populate-mu-type-offsets-in-inouts:end:
25545     # . restore registers
25546     5f/pop-to-edi
25547     5b/pop-to-ebx
25548     5a/pop-to-edx
25549     59/pop-to-ecx
25550     58/pop-to-eax
25551     # . epilogue
25552     89/<- %esp 5/r32/ebp
25553     5d/pop-to-ebp
25554     c3/return
25555 
25556 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)
25557     # . prologue
25558     55/push-ebp
25559     89/<- %ebp 4/r32/esp
25560     # . save registers
25561     50/push-eax
25562     51/push-ecx
25563     53/push-ebx
25564     56/push-esi
25565     # esi = stmts
25566     8b/-> *(ebp+0xc) 6/r32/esi
25567     #
25568     {
25569 $emit-subx-stmt-list:loop:
25570       81 7/subop/compare %esi 0/imm32
25571       0f 84/jump-if-= break/disp32
25572       # var curr-stmt/ecx: (addr stmt) = lookup(stmts->value)
25573       (lookup *esi *(esi+4))  # List-value List-value => eax
25574       89/<- %ecx 0/r32/eax
25575       {
25576 $emit-subx-stmt-list:check-for-block:
25577         81 7/subop/compare *ecx 0/imm32/block  # Stmt-tag
25578         75/jump-if-!= break/disp8
25579 $emit-subx-stmt-list:block:
25580         (emit-subx-block *(ebp+8) %ecx *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
25581       }
25582       {
25583 $emit-subx-stmt-list:check-for-stmt:
25584         81 7/subop/compare *ecx 1/imm32/stmt1  # Stmt-tag
25585         0f 85/jump-if-!= break/disp32
25586 $emit-subx-stmt-list:stmt1:
25587         {
25588           (is-mu-branch? %ecx)  # => eax
25589           3d/compare-eax-and 0/imm32/false
25590           0f 84/jump-if-= break/disp32
25591 $emit-subx-stmt-list:branch-stmt:
25592 +-- 25 lines: # unconditional return --------------------------------------------------------------------------------------------------------------------------------------------------
25617 +-- 27 lines: # unconditional loops ---------------------------------------------------------------------------------------------------------------------------------------------------
25644 +-- 16 lines: # unconditional breaks --------------------------------------------------------------------------------------------------------------------------------------------------
25660 +-- 38 lines: # simple conditional branches without a target --------------------------------------------------------------------------------------------------------------------------
25698 +-- 19 lines: # conditional branches with an explicit target --------------------------------------------------------------------------------------------------------------------------
25717         }
25718 $emit-subx-stmt-list:1-to-1:
25719         (emit-subx-stmt *(ebp+8) %ecx Primitives *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
25720         e9/jump $emit-subx-stmt-list:continue/disp32
25721       }
25722       {
25723 $emit-subx-stmt-list:check-for-var-def:
25724         81 7/subop/compare *ecx 2/imm32/var-def  # Stmt-tag
25725         75/jump-if-!= break/disp8
25726 $emit-subx-stmt-list:var-def:
25727         (emit-subx-var-def *(ebp+8) %ecx)
25728         (push *(ebp+0x10) *(ecx+4))  # Vardef-var
25729         (push *(ebp+0x10) *(ecx+8))  # Vardef-var
25730         (push *(ebp+0x10) 0)  # Live-var-register-spilled = 0 for vars on the stack
25731         #
25732         eb/jump $emit-subx-stmt-list:continue/disp8
25733       }
25734       {
25735 $emit-subx-stmt-list:check-for-reg-var-def:
25736         81 7/subop/compare *ecx 3/imm32/reg-var-def  # Stmt-tag
25737         0f 85/jump-if-!= break/disp32
25738 $emit-subx-stmt-list:reg-var-def:
25739         # TODO: ensure that there's exactly one output
25740         (push-output-and-maybe-emit-spill *(ebp+8) %ecx *(ebp+0x10) %esi *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
25741         # emit the instruction as usual
25742         (emit-subx-stmt *(ebp+8) %ecx Primitives *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
25743         #
25744         eb/jump $emit-subx-stmt-list:continue/disp8
25745       }
25746 $emit-subx-stmt-list:continue:
25747       # TODO: raise an error on unrecognized Stmt-tag
25748       (lookup *(esi+8) *(esi+0xc))  # List-next List-next => eax
25749       89/<- %esi 0/r32/eax
25750       e9/jump loop/disp32
25751     }
25752 $emit-subx-stmt-list:emit-cleanup:
25753     (emit-cleanup-code-until-depth *(ebp+8) *(ebp+0x10) *Curr-block-depth)
25754 $emit-subx-stmt-list:clean-up:
25755     (clean-up-stack-offset-state *(ebp+0x10) *Curr-block-depth)
25756     (clean-up-blocks *(ebp+0x10) *Curr-block-depth *(ebp+0x14))
25757 $emit-subx-stmt-list:end:
25758     # . restore registers
25759     5e/pop-to-esi
25760     5b/pop-to-ebx
25761     59/pop-to-ecx
25762     58/pop-to-eax
25763     # . epilogue
25764     89/<- %esp 5/r32/ebp
25765     5d/pop-to-ebp
25766     c3/return
25767 
25768 # 'later-stmts' includes 'stmt', but will behave the same even without it; reg-var-def stmts are guaranteed not to write to function outputs.
25769 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)
25770     # . prologue
25771     55/push-ebp
25772     89/<- %ebp 4/r32/esp
25773     # . save registers
25774     50/push-eax
25775     51/push-ecx
25776     52/push-edx
25777     # ecx = stmt
25778     8b/-> *(ebp+0xc) 1/r32/ecx
25779     # var sv/eax: (addr stmt-var) = lookup(curr-stmt->outputs)
25780     (lookup *(ecx+0x14) *(ecx+0x18))  # Regvardef-outputs Regvardef-outputs => eax
25781     # TODO: assert !sv->is-deref?
25782     # var v/ecx: (addr var) = lookup(sv->value)
25783     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25784     89/<- %ecx 0/r32/eax
25785     # v->block-depth = *Curr-block-depth
25786     8b/-> *Curr-block-depth 0/r32/eax
25787     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
25788 #?     (write-buffered Stderr "var ")
25789 #?     (lookup *ecx *(ecx+4))
25790 #?     (write-buffered Stderr %eax)
25791 #?     (write-buffered Stderr " at depth ")
25792 #?     (write-int32-hex-buffered Stderr *(ecx+0x10))
25793 #?     (write-buffered Stderr Newline)
25794 #?     (flush Stderr)
25795     # ensure that v is in a register
25796     81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
25797     0f 84/jump-if-= $push-output-and-maybe-emit-spill:abort/disp32
25798     # var emit-spill?/edx: boolean = not-yet-spilled-this-block? && will-not-write-some-register?(fn)
25799     (not-yet-spilled-this-block? %ecx *(ebp+0x10))  # => eax
25800     89/<- %edx 0/r32/eax
25801     3d/compare-eax-and 0/imm32/false
25802     0f 84/jump-if-= $push-output-and-maybe-emit-spill:push/disp32
25803     (will-not-write-some-register? %ecx *(ebp+0x14) *(ebp+0x18))  # => eax
25804     89/<- %edx 0/r32/eax
25805     # check emit-spill?
25806     3d/compare-eax-and 0/imm32/false
25807     0f 84/jump-if-= $push-output-and-maybe-emit-spill:push/disp32
25808     # TODO: assert(size-of(output) == 4)
25809     # *Curr-local-stack-offset -= 4
25810     81 5/subop/subtract *Curr-local-stack-offset 4/imm32
25811     # emit spill
25812     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
25813     (emit-push-register *(ebp+8) %eax)
25814 $push-output-and-maybe-emit-spill:push:
25815     8b/-> *(ebp+0xc) 1/r32/ecx
25816     (lookup *(ecx+0x14) *(ecx+0x18))  # Regvardef-outputs Regvardef-outputs => eax
25817     # push(vars, {sv->value, emit-spill?})
25818     (push *(ebp+0x10) *eax)  # Stmt-var-value
25819     (push *(ebp+0x10) *(eax+4))  # Stmt-var-value
25820     (push *(ebp+0x10) %edx)
25821 $push-output-and-maybe-emit-spill:end:
25822     # . restore registers
25823     5a/pop-to-edx
25824     59/pop-to-ecx
25825     58/pop-to-eax
25826     # . epilogue
25827     89/<- %esp 5/r32/ebp
25828     5d/pop-to-ebp
25829     c3/return
25830 
25831 $push-output-and-maybe-emit-spill:abort:
25832     # error("var '" var->name "' initialized from an instruction must live in a register\n")
25833     (write-buffered *(ebp+0x1c) "var '")
25834     (write-buffered *(ebp+0x1c) *eax)  # Var-name
25835     (write-buffered *(ebp+0x1c) "' initialized from an instruction must live in a register\n")
25836     (flush *(ebp+0x1c))
25837     (stop *(ebp+0x20) 1)
25838     # never gets here
25839 
25840 emit-subx-cleanup-and-unconditional-nonlocal-branch:  # out: (addr buffered-file), stmt: (addr stmt1), vars: (addr stack live-var)
25841     # . prologue
25842     55/push-ebp
25843     89/<- %ebp 4/r32/esp
25844     # . save registers
25845     50/push-eax
25846     51/push-ecx
25847     # ecx = stmt
25848     8b/-> *(ebp+0xc) 1/r32/ecx
25849     # var target/eax: (addr array byte) = curr-stmt->inouts->value->name
25850     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25851     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25852     (lookup *eax *(eax+4))  # Var-name Var-name => eax
25853     # clean up until target block
25854     (emit-cleanup-code-until-target *(ebp+8) *(ebp+0x10) %eax)
25855     # emit jump to target block
25856     (emit-indent *(ebp+8) *Curr-block-depth)
25857     (write-buffered *(ebp+8) "e9/jump ")
25858     (write-buffered *(ebp+8) %eax)
25859     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
25860     (string-starts-with? %eax "break")
25861     3d/compare-eax-and 0/imm32/false
25862     {
25863       74/jump-if-= break/disp8
25864       (write-buffered *(ebp+8) ":break/disp32\n")
25865       eb/jump $emit-subx-cleanup-and-unconditional-nonlocal-branch:end/disp8
25866     }
25867     (write-buffered *(ebp+8) ":loop/disp32\n")
25868 $emit-subx-cleanup-and-unconditional-nonlocal-branch:end:
25869     # . restore registers
25870     59/pop-to-ecx
25871     58/pop-to-eax
25872     # . epilogue
25873     89/<- %esp 5/r32/ebp
25874     5d/pop-to-ebp
25875     c3/return
25876 
25877 emit-outputs:  # out: (addr buffered-file), return-stmt: (addr stmt1), fn: (addr function)
25878     # pseudocode:
25879     #   for every inout, output in return-stmt, fn->outputs
25880     #     if inout is a literal
25881     #       c7 0/subop/copy %output inout/imm32
25882     #     otherwise
25883     #       8b/-> inout %output
25884     #
25885     # . prologue
25886     55/push-ebp
25887     89/<- %ebp 4/r32/esp
25888     # . save registers
25889     50/push-eax
25890     51/push-ecx
25891     56/push-esi
25892     57/push-edi
25893     # var curr-inout/esi: (addr stmt-var) = return-stmt->inouts
25894     8b/-> *(ebp+0xc) 0/r32/eax
25895     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25896     89/<- %esi 0/r32/eax
25897     # var curr-output/edi: (addr list var) = fn->outputs
25898     8b/-> *(ebp+0x10) 0/r32/eax
25899     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
25900     89/<- %edi 0/r32/eax
25901     {
25902 $emit-outputs:loop:
25903       81 7/subop/compare %esi 0/imm32
25904       0f 84/jump-if-= break/disp32
25905       # emit copy to output register
25906       # var curr-var/ecx = lookup(curr-inout->value)
25907       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
25908       89/<- %ecx 0/r32/eax
25909       # if curr-var is a literal, emit copy of a literal to the output
25910       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
25911       (is-simple-mu-type? %eax 0)  # literal => eax
25912       {
25913         3d/compare-eax-and 0/imm32/false
25914         0f 84/jump-if-= break/disp32
25915         (emit-indent *(ebp+8) *Curr-block-depth)
25916         (write-buffered *(ebp+8) "c7 0/subop/copy %")
25917         (lookup *edi *(edi+4))  # List-value List-value => eax
25918         (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
25919         (write-buffered *(ebp+8) %eax)
25920         (write-buffered *(ebp+8) " ")
25921         (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
25922         (write-buffered *(ebp+8) %eax)
25923         (write-buffered *(ebp+8) "/imm32\n")
25924         e9/jump $emit-outputs:continue/disp32
25925       }
25926       # if the non-literal is a register starting with "x", emit a floating-point copy
25927       (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
25928       {
25929         3d/compare-eax-and 0/imm32
25930         0f 84/jump-if-= break/disp32
25931         8a/copy-byte *(eax+4) 0/r32/AL
25932         81 4/subop/and %eax 0xff/imm32
25933         3d/compare-eax-and 0x78/imm32/x
25934         0f 85/jump-if-!= break/disp32
25935         (emit-indent *(ebp+8) *Curr-block-depth)
25936         (write-buffered *(ebp+8) "f3 0f 10/->")
25937         (emit-subx-var-as-rm32 *(ebp+8) %esi)
25938         (write-buffered *(ebp+8) " ")
25939         (lookup *edi *(edi+4))  # List-value List-value => eax
25940         (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
25941         (get Mu-registers %eax 0xc "Mu-registers")  # => eax
25942         (write-int32-hex-buffered *(ebp+8) *eax)
25943         (write-buffered *(ebp+8) "/x32\n")
25944         e9/jump $emit-outputs:continue/disp32
25945       }
25946       # otherwise emit an integer copy
25947       (emit-indent *(ebp+8) *Curr-block-depth)
25948       (write-buffered *(ebp+8) "8b/->")
25949       (emit-subx-var-as-rm32 *(ebp+8) %esi)
25950       (write-buffered *(ebp+8) " ")
25951       (lookup *edi *(edi+4))  # List-value List-value => eax
25952       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
25953       (get Mu-registers %eax 0xc "Mu-registers")  # => eax
25954       (write-int32-hex-buffered *(ebp+8) *eax)
25955       (write-buffered *(ebp+8) "/r32\n")
25956 $emit-outputs:continue:
25957       # curr-inout = curr-inout->next
25958       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
25959       89/<- %esi 0/r32/eax
25960       # curr-output = curr-output->next
25961       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
25962       89/<- %edi 0/r32/eax
25963       #
25964       e9/jump loop/disp32
25965     }
25966 $emit-outputs:end:
25967     # . restore registers
25968     5f/pop-to-edi
25969     5e/pop-to-esi
25970     59/pop-to-ecx
25971     58/pop-to-eax
25972     # . epilogue
25973     89/<- %esp 5/r32/ebp
25974     5d/pop-to-ebp
25975     c3/return
25976 
25977 is-mu-branch?:  # stmt: (addr stmt1) -> result/eax: boolean
25978     # . prologue
25979     55/push-ebp
25980     89/<- %ebp 4/r32/esp
25981     # . save registers
25982     51/push-ecx
25983     # ecx = lookup(stmt->operation)
25984     8b/-> *(ebp+8) 1/r32/ecx
25985     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
25986     89/<- %ecx 0/r32/eax
25987     # if (stmt->operation starts with "loop") return true
25988     (string-starts-with? %ecx "loop")  # => eax
25989     3d/compare-eax-and 0/imm32/false
25990     75/jump-if-not-equal $is-mu-branch?:end/disp8
25991     # if (stmt->operation starts with "break") return true
25992     (string-starts-with? %ecx "break")  # => eax
25993     3d/compare-eax-and 0/imm32/false
25994     75/jump-if-not-equal $is-mu-branch?:end/disp8
25995     # otherwise return (stmt->operation starts with "return")
25996     (string-starts-with? %ecx "return")  # => eax
25997 $is-mu-branch?:end:
25998     # . restore registers
25999     59/pop-to-ecx
26000     # . epilogue
26001     89/<- %esp 5/r32/ebp
26002     5d/pop-to-ebp
26003     c3/return
26004 
26005 emit-reverse-break:  # out: (addr buffered-file), stmt: (addr stmt1)
26006     # . prologue
26007     55/push-ebp
26008     89/<- %ebp 4/r32/esp
26009     # . save registers
26010     50/push-eax
26011     # eax = stmt
26012     8b/-> *(ebp+0xc) 0/r32/eax
26013     #
26014     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
26015     (get Reverse-branch %eax 0x10 "reverse-branch: ")  # => eax: (addr handle array byte)
26016     (emit-indent *(ebp+8) *Curr-block-depth)
26017     (lookup *eax *(eax+4))  # => eax
26018     (write-buffered *(ebp+8) %eax)
26019     (write-buffered *(ebp+8) " break/disp32\n")
26020 $emit-reverse-break:end:
26021     # . restore registers
26022     58/pop-to-eax
26023     # . epilogue
26024     89/<- %esp 5/r32/ebp
26025     5d/pop-to-ebp
26026     c3/return
26027 
26028 == data
26029 
26030 # Table from Mu branch instructions to the reverse SubX opcodes for them.
26031 Reverse-branch:  # (table (handle array byte) (handle array byte))
26032   # a table is a stream
26033   0x1c0/imm32/write
26034   0/imm32/read
26035   0x1c0/imm32/size
26036   # data
26037   0x11/imm32/alloc-id   _string-break-if-=/imm32                0x11/imm32/alloc-id   _string_0f_85_jump_label/imm32
26038   0x11/imm32/alloc-id   _string-loop-if-=/imm32                 0x11/imm32/alloc-id   _string_0f_85_jump_label/imm32
26039   0x11/imm32/alloc-id   _string-break-if-!=/imm32               0x11/imm32/alloc-id   _string_0f_84_jump_label/imm32
26040   0x11/imm32/alloc-id   _string-loop-if-!=/imm32                0x11/imm32/alloc-id   _string_0f_84_jump_label/imm32
26041   0x11/imm32/alloc-id   _string-break-if-</imm32                0x11/imm32/alloc-id   _string_0f_8d_jump_label/imm32
26042   0x11/imm32/alloc-id   _string-loop-if-</imm32                 0x11/imm32/alloc-id   _string_0f_8d_jump_label/imm32
26043   0x11/imm32/alloc-id   _string-break-if->/imm32                0x11/imm32/alloc-id   _string_0f_8e_jump_label/imm32
26044   0x11/imm32/alloc-id   _string-loop-if->/imm32                 0x11/imm32/alloc-id   _string_0f_8e_jump_label/imm32
26045   0x11/imm32/alloc-id   _string-break-if-<=/imm32               0x11/imm32/alloc-id   _string_0f_8f_jump_label/imm32
26046   0x11/imm32/alloc-id   _string-loop-if-<=/imm32                0x11/imm32/alloc-id   _string_0f_8f_jump_label/imm32
26047   0x11/imm32/alloc-id   _string-break-if->=/imm32               0x11/imm32/alloc-id   _string_0f_8c_jump_label/imm32
26048   0x11/imm32/alloc-id   _string-loop-if->=/imm32                0x11/imm32/alloc-id   _string_0f_8c_jump_label/imm32
26049   0x11/imm32/alloc-id   _string-break-if-addr</imm32            0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
26050   0x11/imm32/alloc-id   _string-loop-if-addr</imm32             0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
26051   0x11/imm32/alloc-id   _string-break-if-addr>/imm32            0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
26052   0x11/imm32/alloc-id   _string-loop-if-addr>/imm32             0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
26053   0x11/imm32/alloc-id   _string-break-if-addr<=/imm32           0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
26054   0x11/imm32/alloc-id   _string-loop-if-addr<=/imm32            0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
26055   0x11/imm32/alloc-id   _string-break-if-addr>=/imm32           0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
26056   0x11/imm32/alloc-id   _string-loop-if-addr>=/imm32            0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
26057   0x11/imm32/alloc-id   _string-break-if-float</imm32           0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
26058   0x11/imm32/alloc-id   _string-loop-if-float</imm32            0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
26059   0x11/imm32/alloc-id   _string-break-if-float>/imm32           0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
26060   0x11/imm32/alloc-id   _string-loop-if-float>/imm32            0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
26061   0x11/imm32/alloc-id   _string-break-if-float<=/imm32          0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
26062   0x11/imm32/alloc-id   _string-loop-if-float<=/imm32           0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
26063   0x11/imm32/alloc-id   _string-break-if-float>=/imm32          0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
26064   0x11/imm32/alloc-id   _string-loop-if-float>=/imm32           0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
26065 
26066 == code
26067 
26068 emit-unconditional-jump-to-depth:  # out: (addr buffered-file), vars: (addr stack live-var), depth: int, label-suffix: (addr array byte)
26069     # . prologue
26070     55/push-ebp
26071     89/<- %ebp 4/r32/esp
26072     # . save registers
26073     50/push-eax
26074     51/push-ecx
26075     52/push-edx
26076     53/push-ebx
26077     56/push-esi
26078     # ecx = vars
26079     8b/-> *(ebp+0xc) 1/r32/ecx
26080     # var eax: int = vars->top
26081     8b/-> *ecx 0/r32/eax
26082     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
26083     8d/copy-address *(ecx+eax-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
26084     # var min/ecx: (addr handle var) = vars->data
26085     8d/copy-address *(ecx+8) 1/r32/ecx
26086     # edx = depth
26087     8b/-> *(ebp+0x10) 2/r32/edx
26088     {
26089 $emit-unconditional-jump-to-depth:loop:
26090       # if (curr < min) break
26091       39/compare %esi 1/r32/ecx
26092       0f 82/jump-if-addr< break/disp32
26093       # var v/ebx: (addr var) = lookup(*curr)
26094       (lookup *esi *(esi+4))  # => eax
26095       89/<- %ebx 0/r32/eax
26096       # if (v->block-depth < until-block-depth) break
26097       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
26098       0f 8c/jump-if-< break/disp32
26099       {
26100 $emit-unconditional-jump-to-depth:check:
26101         # if v->block-depth != until-block-depth, continue
26102         39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
26103         0f 85/jump-if-!= break/disp32
26104 $emit-unconditional-jump-to-depth:depth-found:
26105         # if v is not a literal, continue
26106         (size-of %ebx)  # => eax
26107         3d/compare-eax-and 0/imm32
26108         0f 85/jump-if-!= break/disp32
26109 $emit-unconditional-jump-to-depth:label-found:
26110         # emit unconditional jump, then return
26111         (emit-indent *(ebp+8) *Curr-block-depth)
26112         (write-buffered *(ebp+8) "e9/jump ")
26113         (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
26114         (write-buffered *(ebp+8) %eax)
26115         (write-buffered *(ebp+8) ":")
26116         (write-buffered *(ebp+8) *(ebp+0x14))
26117         (write-buffered *(ebp+8) "/disp32\n")
26118         eb/jump $emit-unconditional-jump-to-depth:end/disp8
26119       }
26120       # curr -= 12
26121       81 5/subop/subtract %esi 0xc/imm32
26122       e9/jump loop/disp32
26123     }
26124     # TODO: error if no label at 'depth' was found
26125 $emit-unconditional-jump-to-depth:end:
26126     # . restore registers
26127     5e/pop-to-esi
26128     5b/pop-to-ebx
26129     5a/pop-to-edx
26130     59/pop-to-ecx
26131     58/pop-to-eax
26132     # . epilogue
26133     89/<- %esp 5/r32/ebp
26134     5d/pop-to-ebp
26135     c3/return
26136 
26137 # emit clean-up code for 'vars' until some block depth
26138 # doesn't actually modify 'vars' so we need traverse manually inside the stack
26139 emit-cleanup-code-until-depth:  # out: (addr buffered-file), vars: (addr stack live-var), until-block-depth: int
26140     # . prologue
26141     55/push-ebp
26142     89/<- %ebp 4/r32/esp
26143     # . save registers
26144     50/push-eax
26145     51/push-ecx
26146     52/push-edx
26147     53/push-ebx
26148     56/push-esi
26149 #?     (write-buffered Stderr "--- cleanup\n")
26150 #?     (flush Stderr)
26151     # ecx = vars
26152     8b/-> *(ebp+0xc) 1/r32/ecx
26153     # var esi: int = vars->top
26154     8b/-> *ecx 6/r32/esi
26155     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
26156     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
26157     # var min/ecx: (addr handle var) = vars->data
26158     81 0/subop/add %ecx 8/imm32
26159     # edx = until-block-depth
26160     8b/-> *(ebp+0x10) 2/r32/edx
26161     {
26162 $emit-cleanup-code-until-depth:loop:
26163       # if (curr < min) break
26164       39/compare %esi 1/r32/ecx
26165       0f 82/jump-if-addr< break/disp32
26166       # var v/ebx: (addr var) = lookup(*curr)
26167       (lookup *esi *(esi+4))  # => eax
26168       89/<- %ebx 0/r32/eax
26169 #?       (lookup *ebx *(ebx+4))  # Var-name
26170 #?       (write-buffered Stderr "var ")
26171 #?       (write-buffered Stderr %eax)
26172 #?       (write-buffered Stderr Newline)
26173 #?       (flush Stderr)
26174       # if (v->block-depth < until-block-depth) break
26175       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
26176       0f 8c/jump-if-< break/disp32
26177       # if v is in a register
26178       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
26179       {
26180         0f 84/jump-if-= break/disp32
26181         {
26182 $emit-cleanup-code-until-depth:check-for-previous-spill:
26183           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
26184           3d/compare-eax-and 0/imm32/false
26185           74/jump-if-= break/disp8
26186 $emit-cleanup-code-until-depth:reclaim-var-in-register:
26187           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
26188           (emit-pop-register *(ebp+8) %eax)
26189         }
26190         eb/jump $emit-cleanup-code-until-depth:continue/disp8
26191       }
26192       # otherwise v is on the stack
26193       {
26194         75/jump-if-!= break/disp8
26195 $emit-cleanup-code-until-depth:var-on-stack:
26196         (size-of %ebx)  # => eax
26197         # don't emit code for labels
26198         3d/compare-eax-and 0/imm32
26199         74/jump-if-= break/disp8
26200 $emit-cleanup-code-until-depth:reclaim-var-on-stack:
26201         (emit-indent *(ebp+8) *Curr-block-depth)
26202         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
26203         (write-int32-hex-buffered *(ebp+8) %eax)
26204         (write-buffered *(ebp+8) "/imm32\n")
26205       }
26206 $emit-cleanup-code-until-depth:continue:
26207       # curr -= 12
26208       81 5/subop/subtract %esi 0xc/imm32
26209       e9/jump loop/disp32
26210     }
26211 $emit-cleanup-code-until-depth:end:
26212     # . restore registers
26213     5e/pop-to-esi
26214     5b/pop-to-ebx
26215     5a/pop-to-edx
26216     59/pop-to-ecx
26217     58/pop-to-eax
26218     # . epilogue
26219     89/<- %esp 5/r32/ebp
26220     5d/pop-to-ebp
26221     c3/return
26222 
26223 # emit clean-up code for 'vars' that don't conflict with output registers
26224 # doesn't actually modify 'vars' so we need traverse manually inside the stack
26225 emit-cleanup-code-for-non-outputs:  # out: (addr buffered-file), vars: (addr stack live-var), fn: (addr function)
26226     # . prologue
26227     55/push-ebp
26228     89/<- %ebp 4/r32/esp
26229     # . save registers
26230     50/push-eax
26231     51/push-ecx
26232     52/push-edx
26233     53/push-ebx
26234     56/push-esi
26235     57/push-edi
26236     # ecx = vars
26237     8b/-> *(ebp+0xc) 1/r32/ecx
26238     # var esi: int = vars->top
26239     8b/-> *ecx 6/r32/esi
26240     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
26241     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
26242     # var min/ecx: (addr handle var) = vars->data
26243     81 0/subop/add %ecx 8/imm32
26244     {
26245 $emit-cleanup-code-for-non-outputs:loop:
26246       # if (curr < min) break
26247       39/compare %esi 1/r32/ecx
26248       0f 82/jump-if-addr< break/disp32
26249       # var v/ebx: (addr var) = lookup(*curr)
26250       (lookup *esi *(esi+4))  # => eax
26251       89/<- %ebx 0/r32/eax
26252       # if v is in a register
26253       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
26254       {
26255         0f 84/jump-if-= break/disp32
26256         {
26257 $emit-cleanup-code-for-non-outputs:check-for-previous-spill:
26258           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
26259           3d/compare-eax-and 0/imm32/false
26260           0f 84/jump-if-= break/disp32
26261 $emit-cleanup-code-for-non-outputs:reclaim-var-in-register:
26262           # var reg/edi: (addr array name) = v->register
26263           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
26264           89/<- %edi 0/r32/eax
26265           # if reg is not in function outputs, emit a pop
26266           (reg-in-function-outputs? *(ebp+0x10) %edi)  # => eax
26267           3d/compare-eax-and 0/imm32/false
26268           {
26269             75/jump-if-!= break/disp8
26270             (emit-pop-register *(ebp+8) %edi)
26271             eb/jump $emit-cleanup-code-for-non-outputs:reclaim-var-in-register-done/disp8
26272           }
26273           # otherwise just drop it from the stack
26274           (emit-indent *(ebp+8) *Curr-block-depth)
26275           (write-buffered *(ebp+8) "81 0/subop/add %esp 4/imm32\n")
26276         }
26277 $emit-cleanup-code-for-non-outputs:reclaim-var-in-register-done:
26278         eb/jump $emit-cleanup-code-for-non-outputs:continue/disp8
26279       }
26280       # otherwise v is on the stack
26281       {
26282         75/jump-if-!= break/disp8
26283 $emit-cleanup-code-for-non-outputs:var-on-stack:
26284         (size-of %ebx)  # => eax
26285         # don't emit code for labels
26286         3d/compare-eax-and 0/imm32
26287         74/jump-if-= break/disp8
26288 $emit-cleanup-code-for-non-outputs:reclaim-var-on-stack:
26289         (emit-indent *(ebp+8) *Curr-block-depth)
26290         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
26291         (write-int32-hex-buffered *(ebp+8) %eax)
26292         (write-buffered *(ebp+8) "/imm32\n")
26293       }
26294 $emit-cleanup-code-for-non-outputs:continue:
26295       # curr -= 12
26296       81 5/subop/subtract %esi 0xc/imm32
26297       e9/jump loop/disp32
26298     }
26299 $emit-cleanup-code-for-non-outputs:end:
26300     # . restore registers
26301     5f/pop-to-edi
26302     5e/pop-to-esi
26303     5b/pop-to-ebx
26304     5a/pop-to-edx
26305     59/pop-to-ecx
26306     58/pop-to-eax
26307     # . epilogue
26308     89/<- %esp 5/r32/ebp
26309     5d/pop-to-ebp
26310     c3/return
26311 
26312 emit-push-register:  # out: (addr buffered-file), reg: (addr array byte)
26313     # . prologue
26314     55/push-ebp
26315     89/<- %ebp 4/r32/esp
26316     # eax = reg
26317     8b/-> *(ebp+0xc) 0/r32/eax
26318     # var prefix/eax: byte = reg->data[0]
26319     8a/copy-byte *(eax+4) 0/r32/AL
26320     81 4/subop/and %eax 0xff/imm32
26321     # if (prefix == 'x') push xmm register
26322     {
26323       3d/compare-eax-and 0x78/imm32/x
26324       0f 85/jump-if-!= break/disp32
26325       # TODO validate register
26326       (emit-indent *(ebp+8) *Curr-block-depth)
26327       (write-buffered *(ebp+8) "81 5/subop/subtract %esp 4/imm32\n")
26328       (emit-indent *(ebp+8) *Curr-block-depth)
26329       (write-buffered *(ebp+8) "f3 0f 11/<- *esp ")
26330       # var prefix/eax: byte = reg->data[3]
26331       8b/-> *(ebp+0xc) 0/r32/eax
26332       8a/copy-byte *(eax+7) 0/r32/AL
26333       81 4/subop/and %eax 0xff/imm32
26334       (write-byte-buffered *(ebp+8) %eax)
26335       (write-buffered *(ebp+8) "/x32\n")
26336       e9/jump $emit-push-register:end/disp32
26337     }
26338     # otherwise push gp register
26339     (emit-indent *(ebp+8) *Curr-block-depth)
26340     (write-buffered *(ebp+8) "ff 6/subop/push %")
26341     (write-buffered *(ebp+8) *(ebp+0xc))
26342     (write-buffered *(ebp+8) Newline)
26343 $emit-push-register:end:
26344     # . epilogue
26345     89/<- %esp 5/r32/ebp
26346     5d/pop-to-ebp
26347     c3/return
26348 
26349 emit-pop-register:  # out: (addr buffered-file), reg: (addr array byte)
26350     # . prologue
26351     55/push-ebp
26352     89/<- %ebp 4/r32/esp
26353     # . save registers
26354     50/push-eax
26355     # eax = reg
26356     8b/-> *(ebp+0xc) 0/r32/eax
26357     # var prefix/eax: byte = reg->data[0]
26358     8a/copy-byte *(eax+4) 0/r32/AL
26359     81 4/subop/and %eax 0xff/imm32
26360     # if (prefix == 'x') pop to xmm register
26361     {
26362       3d/compare-eax-and 0x78/imm32/x
26363       0f 85/jump-if-!= break/disp32
26364       # TODO validate register
26365       (emit-indent *(ebp+8) *Curr-block-depth)
26366       (write-buffered *(ebp+8) "f3 0f 10/-> *esp ")
26367       # var prefix/eax: byte = reg->data[3]
26368       8b/-> *(ebp+0xc) 0/r32/eax
26369       8a/copy-byte *(eax+7) 0/r32/AL
26370       81 4/subop/and %eax 0xff/imm32
26371       (write-byte-buffered *(ebp+8) %eax)
26372       (write-buffered *(ebp+8) "/x32\n")
26373       (emit-indent *(ebp+8) *Curr-block-depth)
26374       (write-buffered *(ebp+8) "81 0/subop/add %esp 4/imm32\n")
26375       e9/jump $emit-pop-register:end/disp32
26376     }
26377     # otherwise pop to gp register
26378     (emit-indent *(ebp+8) *Curr-block-depth)
26379     (write-buffered *(ebp+8) "8f 0/subop/pop %")
26380     (write-buffered *(ebp+8) *(ebp+0xc))
26381     (write-buffered *(ebp+8) Newline)
26382 $emit-pop-register:end:
26383     # . restore registers
26384     58/pop-to-eax
26385     # . epilogue
26386     89/<- %esp 5/r32/ebp
26387     5d/pop-to-ebp
26388     c3/return
26389 
26390 # emit clean-up code for 'vars' until a given label is encountered
26391 # doesn't actually modify 'vars' so we need traverse manually inside the stack
26392 emit-cleanup-code-until-target:  # out: (addr buffered-file), vars: (addr stack live-var), until-block-label: (addr array byte)
26393     # . prologue
26394     55/push-ebp
26395     89/<- %ebp 4/r32/esp
26396     # . save registers
26397     50/push-eax
26398     51/push-ecx
26399     52/push-edx
26400     53/push-ebx
26401     # ecx = vars
26402     8b/-> *(ebp+0xc) 1/r32/ecx
26403     # var eax: int = vars->top
26404     8b/-> *ecx 0/r32/eax
26405     # var curr/edx: (addr handle var) = &vars->data[vars->top - 12]
26406     8d/copy-address *(ecx+eax-4) 2/r32/edx  # vars + 8 + vars->top - 12/Live-var-size
26407     # var min/ecx: (addr handle var) = vars->data
26408     81 0/subop/add %ecx 8/imm32
26409     {
26410 $emit-cleanup-code-until-target:loop:
26411       # if (curr < min) break
26412       39/compare %edx 1/r32/ecx
26413       0f 82/jump-if-addr< break/disp32
26414       # var v/ebx: (handle var) = lookup(*curr)
26415       (lookup *edx *(edx+4))  # => eax
26416       89/<- %ebx 0/r32/eax
26417       # if (v->name == until-block-label) break
26418       (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
26419       (string-equal? %eax *(ebp+0x10))  # => eax
26420       3d/compare-eax-and 0/imm32/false
26421       0f 85/jump-if-!= break/disp32
26422       # if v is in a register
26423       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
26424       {
26425         0f 84/jump-if-= break/disp32
26426         {
26427 $emit-cleanup-code-until-target:check-for-previous-spill:
26428           8b/-> *(edx+8) 0/r32/eax  # Live-var-register-spilled
26429           3d/compare-eax-and 0/imm32/false
26430           74/jump-if-= break/disp8
26431 $emit-cleanup-code-until-target:reclaim-var-in-register:
26432           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
26433           (emit-pop-register *(ebp+8) %eax)
26434         }
26435         eb/jump $emit-cleanup-code-until-target:continue/disp8
26436       }
26437       # otherwise v is on the stack
26438       {
26439         75/jump-if-!= break/disp8
26440 $emit-cleanup-code-until-target:reclaim-var-on-stack:
26441         (size-of %ebx)  # => eax
26442         # don't emit code for labels
26443         3d/compare-eax-and 0/imm32
26444         74/jump-if-= break/disp8
26445         #
26446         (emit-indent *(ebp+8) *Curr-block-depth)
26447         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
26448         (write-int32-hex-buffered *(ebp+8) %eax)
26449         (write-buffered *(ebp+8) "/imm32\n")
26450       }
26451 $emit-cleanup-code-until-target:continue:
26452       # curr -= 12
26453       81 5/subop/subtract %edx 0xc/imm32
26454       e9/jump loop/disp32
26455     }
26456 $emit-cleanup-code-until-target:end:
26457     # . restore registers
26458     5b/pop-to-ebx
26459     5a/pop-to-edx
26460     59/pop-to-ecx
26461     58/pop-to-eax
26462     # . epilogue
26463     89/<- %esp 5/r32/ebp
26464     5d/pop-to-ebp
26465     c3/return
26466 
26467 # update Curr-local-stack-offset assuming vars until some block depth are popped
26468 # doesn't actually modify 'vars', so we need traverse manually inside the stack
26469 clean-up-stack-offset-state:  # vars: (addr stack live-var), until-block-depth: int
26470     # . prologue
26471     55/push-ebp
26472     89/<- %ebp 4/r32/esp
26473     # . save registers
26474     50/push-eax
26475     51/push-ecx
26476     52/push-edx
26477     53/push-ebx
26478     56/push-esi
26479     # ecx = vars
26480     8b/-> *(ebp+8) 1/r32/ecx
26481     # var esi: int = vars->top
26482     8b/-> *ecx 6/r32/esi
26483     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
26484     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
26485     # var min/ecx: (addr handle var) = vars->data
26486     81 0/subop/add %ecx 8/imm32
26487     # edx = until-block-depth
26488     8b/-> *(ebp+0xc) 2/r32/edx
26489     {
26490 $clean-up-stack-offset-state:loop:
26491       # if (curr < min) break
26492       39/compare %esi 1/r32/ecx
26493       0f 82/jump-if-addr< break/disp32
26494       # var v/ebx: (addr var) = lookup(*curr)
26495       (lookup *esi *(esi+4))  # => eax
26496       89/<- %ebx 0/r32/eax
26497       # if (v->block-depth < until-block-depth) break
26498       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
26499       0f 8c/jump-if-< break/disp32
26500       # if v is in a register
26501       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
26502       {
26503         0f 84/jump-if-= break/disp32
26504         {
26505 $clean-up-stack-offset-state:check-for-previous-spill:
26506           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
26507           3d/compare-eax-and 0/imm32/false
26508           74/jump-if-= break/disp8
26509 $clean-up-stack-offset-state:reclaim-var-in-register:
26510           81 0/subop/add *Curr-local-stack-offset 4/imm32
26511         }
26512         eb/jump $clean-up-stack-offset-state:continue/disp8
26513       }
26514       # otherwise v is on the stack
26515       {
26516         75/jump-if-!= break/disp8
26517 $clean-up-stack-offset-state:var-on-stack:
26518         (size-of %ebx)  # => eax
26519         01/add-to *Curr-local-stack-offset 0/r32/eax
26520       }
26521 $clean-up-stack-offset-state:continue:
26522       # curr -= 12
26523       81 5/subop/subtract %esi 0xc/imm32
26524       e9/jump loop/disp32
26525     }
26526 $clean-up-stack-offset-state:end:
26527     # . restore registers
26528     5e/pop-to-esi
26529     5b/pop-to-ebx
26530     5a/pop-to-edx
26531     59/pop-to-ecx
26532     58/pop-to-eax
26533     # . epilogue
26534     89/<- %esp 5/r32/ebp
26535     5d/pop-to-ebp
26536     c3/return
26537 
26538 # Return true if there isn't a variable in 'vars' with the same block-depth
26539 # and register as 'v'.
26540 # 'v' is guaranteed not to be within 'vars'.
26541 not-yet-spilled-this-block?:  # v: (addr var), vars: (addr stack live-var) -> result/eax: boolean
26542     # . prologue
26543     55/push-ebp
26544     89/<- %ebp 4/r32/esp
26545     # . save registers
26546     51/push-ecx
26547     52/push-edx
26548     53/push-ebx
26549     56/push-esi
26550     57/push-edi
26551     # ecx = vars
26552     8b/-> *(ebp+0xc) 1/r32/ecx
26553     # var eax: int = vars->top
26554     8b/-> *ecx 0/r32/eax
26555     # var curr/edx: (addr handle var) = &vars->data[vars->top - 12]
26556     8d/copy-address *(ecx+eax-4) 2/r32/edx  # vars + 8 + vars->top - 12/Live-var-size
26557     # var min/ecx: (addr handle var) = vars->data
26558     8d/copy-address *(ecx+8) 1/r32/ecx
26559     # var depth/ebx: int = v->block-depth
26560     8b/-> *(ebp+8) 3/r32/ebx
26561     8b/-> *(ebx+0x10) 3/r32/ebx  # Var-block-depth
26562     # var needle/esi: (addr array byte) = v->register
26563     8b/-> *(ebp+8) 6/r32/esi
26564     (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
26565     89/<- %esi 0/r32/eax
26566     {
26567 $not-yet-spilled-this-block?:loop:
26568       # if (curr < min) break
26569       39/compare %edx 1/r32/ecx
26570       0f 82/jump-if-addr< break/disp32
26571       # var cand/edi: (addr var) = lookup(*curr)
26572       (lookup *edx *(edx+4))  # => eax
26573       89/<- %edi 0/r32/eax
26574       # if (cand->block-depth < depth) break
26575       39/compare *(edi+0x10) 3/r32/ebx  # Var-block-depth
26576       0f 8c/jump-if-< break/disp32
26577       # var cand-reg/edi: (array array byte) = cand->reg
26578       (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
26579       89/<- %edi 0/r32/eax
26580       # if (cand-reg == null) continue
26581       {
26582 $not-yet-spilled-this-block?:check-reg:
26583         81 7/subop/compare %edi 0/imm32
26584         0f 84/jump-if-= break/disp32
26585         # if (cand-reg == needle) return true
26586         (string-equal? %esi %edi)  # => eax
26587         3d/compare-eax-and 0/imm32/false
26588         74/jump-if-= break/disp8
26589 $not-yet-spilled-this-block?:return-false:
26590         b8/copy-to-eax 0/imm32/false
26591         eb/jump $not-yet-spilled-this-block?:end/disp8
26592       }
26593 $not-yet-spilled-this-block?:continue:
26594       # curr -= 12
26595       81 5/subop/subtract %edx 0xc/imm32
26596       e9/jump loop/disp32
26597     }
26598 $not-yet-spilled-this-block?:return-true:
26599     # return true
26600     b8/copy-to-eax 1/imm32/true
26601 $not-yet-spilled-this-block?:end:
26602     # . restore registers
26603     5f/pop-to-edi
26604     5e/pop-to-esi
26605     5b/pop-to-ebx
26606     5a/pop-to-edx
26607     59/pop-to-ecx
26608     # . epilogue
26609     89/<- %esp 5/r32/ebp
26610     5d/pop-to-ebp
26611     c3/return
26612 
26613 # could the register of 'v' ever be written to by one of the vars in fn-outputs?
26614 will-not-write-some-register?:  # v: (addr var), stmts: (addr list stmt), fn: (addr function) -> result/eax: boolean
26615     # . prologue
26616     55/push-ebp
26617     89/<- %ebp 4/r32/esp
26618     # eax = v
26619     8b/-> *(ebp+8) 0/r32/eax
26620     # var reg/eax: (addr array byte) = lookup(v->register)
26621     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
26622     # var target/eax: (addr var) = find-register(fn-outputs, reg)
26623     (find-register *(ebp+0x10) %eax)  # => eax
26624     # if (target == 0) return true
26625     {
26626       3d/compare-eax-and 0/imm32
26627       75/jump-if-!= break/disp8
26628       b8/copy-to-eax 1/imm32/true
26629       eb/jump $will-not-write-some-register?:end/disp8
26630     }
26631     # return !assigns-in-stmts?(stmts, target)
26632     (assigns-in-stmts? *(ebp+0xc) %eax)  # => eax
26633     3d/compare-eax-and 0/imm32/false
26634     # assume: true = 1, so no need to mask with 0x000000ff
26635     0f 94/set-if-= %al
26636 $will-not-write-some-register?:end:
26637     # . epilogue
26638     89/<- %esp 5/r32/ebp
26639     5d/pop-to-ebp
26640     c3/return
26641 
26642 # return fn output with matching register
26643 # always returns false if 'reg' is null
26644 find-register:  # fn: (addr function), reg: (addr array byte) -> result/eax: (addr var)
26645     # . prologue
26646     55/push-ebp
26647     89/<- %ebp 4/r32/esp
26648     # . save registers
26649     51/push-ecx
26650     # var curr/ecx: (addr list var) = lookup(fn->outputs)
26651     8b/-> *(ebp+8) 1/r32/ecx
26652     (lookup *(ecx+0x10) *(ecx+0x14))  # Function-outputs Function-outputs => eax
26653     89/<- %ecx 0/r32/eax
26654     {
26655 $find-register:loop:
26656       # if (curr == 0) break
26657       81 7/subop/compare %ecx 0/imm32
26658       74/jump-if-= break/disp8
26659       # eax = curr->value->register
26660       (lookup *ecx *(ecx+4))  # List-value List-value => eax
26661       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
26662       # if (eax == reg) return curr->value
26663 $find-register:compare:
26664       (string-equal? *(ebp+0xc) %eax)  # => eax
26665       {
26666         3d/compare-eax-and 0/imm32/false
26667         74/jump-if-= break/disp8
26668 $find-register:found:
26669         (lookup *ecx *(ecx+4))  # List-value List-value => eax
26670         eb/jump $find-register:end/disp8
26671       }
26672       # curr = lookup(curr->next)
26673       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
26674       89/<- %ecx 0/r32/eax
26675       #
26676       eb/jump loop/disp8
26677     }
26678 $find-register:end:
26679     # . restore registers
26680     59/pop-to-ecx
26681     # . epilogue
26682     89/<- %esp 5/r32/ebp
26683     5d/pop-to-ebp
26684     c3/return
26685 
26686 assigns-in-stmts?:  # stmts: (addr list stmt), v: (addr var) -> result/eax: boolean
26687     # . prologue
26688     55/push-ebp
26689     89/<- %ebp 4/r32/esp
26690     # . save registers
26691     51/push-ecx
26692     # var curr/ecx: (addr list stmt) = stmts
26693     8b/-> *(ebp+8) 1/r32/ecx
26694     {
26695       # if (curr == 0) break
26696       81 7/subop/compare %ecx 0/imm32
26697       74/jump-if-= break/disp8
26698       # if assigns-in-stmt?(curr->value, v) return true
26699       (lookup *ecx *(ecx+4))  # List-value List-value => eax
26700       (assigns-in-stmt? %eax *(ebp+0xc))  # => eax
26701       3d/compare-eax-and 0/imm32/false
26702       75/jump-if-!= break/disp8
26703       # curr = lookup(curr->next)
26704       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
26705       89/<- %ecx 0/r32/eax
26706       #
26707       eb/jump loop/disp8
26708     }
26709 $assigns-in-stmts?:end:
26710     # . restore registers
26711     59/pop-to-ecx
26712     # . epilogue
26713     89/<- %esp 5/r32/ebp
26714     5d/pop-to-ebp
26715     c3/return
26716 
26717 assigns-in-stmt?:  # stmt: (addr stmt), v: (addr var) -> result/eax: boolean
26718     # . prologue
26719     55/push-ebp
26720     89/<- %ebp 4/r32/esp
26721     # . save registers
26722     51/push-ecx
26723     # ecx = stmt
26724     8b/-> *(ebp+8) 1/r32/ecx
26725     # if stmt is a stmt1, return assigns-in-stmt-vars?(stmt->outputs, v)
26726     {
26727       81 7/subop/compare *ecx 1/imm32/stmt1  # Stmt-tag
26728       75/jump-if-!= break/disp8
26729       (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
26730       (assigns-in-stmt-vars? %eax *(ebp+0xc))  # => eax
26731       eb/jump $assigns-in-stmt?:end/disp8
26732     }
26733     # if stmt is a block, return assigns-in-stmts?(stmt->stmts, v)
26734     {
26735       81 7/subop/compare *ecx 0/imm32/block  # Stmt-tag
26736       75/jump-if-!= break/disp8
26737       (lookup *(ecx+4) *(ecx+8))  # Block-stmts Block-stmts => eax
26738       (assigns-in-stmts? %eax *(ebp+0xc))  # => eax
26739       eb/jump $assigns-in-stmt?:end/disp8
26740     }
26741     # otherwise return false
26742     b8/copy 0/imm32/false
26743 $assigns-in-stmt?:end:
26744     # . restore registers
26745     59/pop-to-ecx
26746     # . epilogue
26747     89/<- %esp 5/r32/ebp
26748     5d/pop-to-ebp
26749     c3/return
26750 
26751 assigns-in-stmt-vars?:  # stmt-var: (addr stmt-var), v: (addr var) -> result/eax: boolean
26752     # . prologue
26753     55/push-ebp
26754     89/<- %ebp 4/r32/esp
26755     # . save registers
26756     51/push-ecx
26757     # var curr/ecx: (addr stmt-var) = stmt-var
26758     8b/-> *(ebp+8) 1/r32/ecx
26759     {
26760       # if (curr == 0) break
26761       81 7/subop/compare %ecx 0/imm32
26762       74/jump-if-= break/disp8
26763       # eax = lookup(curr->value)
26764       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26765       # if (eax == v  &&  curr->is-deref? == false) return true
26766       {
26767         39/compare *(ebp+0xc) 0/r32/eax
26768         75/jump-if-!= break/disp8
26769         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
26770         75/jump-if-!= break/disp8
26771         b8/copy-to-eax 1/imm32/true
26772         eb/jump $assigns-in-stmt-vars?:end/disp8
26773       }
26774       # curr = lookup(curr->next)
26775       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
26776       89/<- %ecx 0/r32/eax
26777       #
26778       eb/jump loop/disp8
26779     }
26780 $assigns-in-stmt-vars?:end:
26781     # . restore registers
26782     59/pop-to-ecx
26783     # . epilogue
26784     89/<- %esp 5/r32/ebp
26785     5d/pop-to-ebp
26786     c3/return
26787 
26788 # is there a var before 'v' with the same block-depth and register on the 'vars' stack?
26789 # v is guaranteed to be within vars
26790 # 'start' is provided as an optimization, a pointer within vars
26791 # *start == v
26792 same-register-spilled-before?:  # v: (addr var), vars: (addr stack (handle var)), start: (addr var) -> result/eax: boolean
26793     # . prologue
26794     55/push-ebp
26795     89/<- %ebp 4/r32/esp
26796     # . save registers
26797     51/push-ecx
26798     52/push-edx
26799     53/push-ebx
26800     56/push-esi
26801     57/push-edi
26802     # ecx = v
26803     8b/-> *(ebp+8) 1/r32/ecx
26804     # var reg/edx: (addr array byte) = lookup(v->register)
26805     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
26806     89/<- %edx 0/r32/eax
26807     # var depth/ebx: int = v->block-depth
26808     8b/-> *(ecx+0x10) 3/r32/ebx  # Var-block-depth
26809     # var min/ecx: (addr handle var) = vars->data
26810     8b/-> *(ebp+0xc) 1/r32/ecx
26811     81 0/subop/add %ecx 8/imm32
26812     # TODO: check that start >= min and start < &vars->data[top]
26813     # TODO: check that *start == v
26814     # var curr/esi: (addr handle var) = start
26815     8b/-> *(ebp+0x10) 6/r32/esi
26816     # curr -= 8
26817     81 5/subop/subtract %esi 8/imm32
26818     {
26819 $same-register-spilled-before?:loop:
26820       # if (curr < min) break
26821       39/compare %esi 1/r32/ecx
26822       0f 82/jump-if-addr< break/disp32
26823       # var x/eax: (addr var) = lookup(*curr)
26824       (lookup *esi *(esi+4))  # => eax
26825       # if (x->block-depth < depth) break
26826       39/compare *(eax+0x10) 3/r32/ebx  # Var-block-depth
26827       0f 8c/jump-if-< break/disp32
26828       # if (x->register == 0) continue
26829       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
26830       74/jump-if-= $same-register-spilled-before?:continue/disp8
26831       # if (x->register == reg) return true
26832       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
26833       (string-equal? %eax %edx)  # => eax
26834       3d/compare-eax-and 0/imm32/false
26835       b8/copy-to-eax 1/imm32/true
26836       75/jump-if-!= $same-register-spilled-before?:end/disp8
26837 $same-register-spilled-before?:continue:
26838       # curr -= 8
26839       81 5/subop/subtract %esi 8/imm32
26840       e9/jump loop/disp32
26841     }
26842 $same-register-spilled-before?:false:
26843     b8/copy-to-eax 0/imm32/false
26844 $same-register-spilled-before?:end:
26845     # . restore registers
26846     5f/pop-to-edi
26847     5e/pop-to-esi
26848     5b/pop-to-ebx
26849     5a/pop-to-edx
26850     59/pop-to-ecx
26851     # . epilogue
26852     89/<- %esp 5/r32/ebp
26853     5d/pop-to-ebp
26854     c3/return
26855 
26856 # clean up global state for 'vars' until some block depth (inclusive)
26857 clean-up-blocks:  # vars: (addr stack live-var), until-block-depth: int, fn: (addr function)
26858     # . prologue
26859     55/push-ebp
26860     89/<- %ebp 4/r32/esp
26861     # . save registers
26862     50/push-eax
26863     51/push-ecx
26864     56/push-esi
26865     # esi = vars
26866     8b/-> *(ebp+8) 6/r32/esi
26867     # ecx = until-block-depth
26868     8b/-> *(ebp+0xc) 1/r32/ecx
26869     {
26870 $clean-up-blocks:reclaim-loop:
26871       # if (vars->top <= 0) break
26872       8b/-> *esi 0/r32/eax  # Stack-top
26873       3d/compare-eax-and 0/imm32
26874       0f 8e/jump-if-<= break/disp32
26875       # var v/eax: (addr var) = lookup(vars[vars->top-12])
26876       (lookup *(esi+eax-4) *(esi+eax))  # vars + 8 + vars->top - 12 => eax
26877       # if (v->block-depth < until-block-depth) break
26878       39/compare *(eax+0x10) 1/r32/ecx  # Var-block-depth
26879       0f 8c/jump-if-< break/disp32
26880       (pop %esi)  # => eax
26881       (pop %esi)  # => eax
26882       (pop %esi)  # => eax
26883       e9/jump loop/disp32
26884     }
26885 $clean-up-blocks:end:
26886     # . restore registers
26887     5e/pop-to-esi
26888     59/pop-to-ecx
26889     58/pop-to-eax
26890     # . epilogue
26891     89/<- %esp 5/r32/ebp
26892     5d/pop-to-ebp
26893     c3/return
26894 
26895 reg-in-function-outputs?:  # fn: (addr function), target: (addr array byte) -> result/eax: boolean
26896     # . prologue
26897     55/push-ebp
26898     89/<- %ebp 4/r32/esp
26899     # . save registers
26900     51/push-ecx
26901     # var curr/ecx: (addr list var) = lookup(fn->outputs)
26902     8b/-> *(ebp+8) 0/r32/eax
26903     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
26904     89/<- %ecx 0/r32/eax
26905     # while curr != null
26906     {
26907       81 7/subop/compare %ecx 0/imm32
26908       74/jump-if-= break/disp8
26909       # var v/eax: (addr var) = lookup(curr->value)
26910       (lookup *ecx *(ecx+4))  # List-value List-value => eax
26911       # var reg/eax: (addr array byte) = lookup(v->register)
26912       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
26913       # if (reg == target) return true
26914       (string-equal? %eax *(ebp+0xc))  # => eax
26915       3d/compare-eax-and 0/imm32/false
26916       75/jump-if-!= $reg-in-function-outputs?:end/disp8
26917       # curr = curr->next
26918       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
26919       89/<- %ecx 0/r32/eax
26920       #
26921       eb/jump loop/disp8
26922     }
26923     # return false
26924     b8/copy-to-eax 0/imm32
26925 $reg-in-function-outputs?:end:
26926     # . restore registers
26927     59/pop-to-ecx
26928     # . epilogue
26929     89/<- %esp 5/r32/ebp
26930     5d/pop-to-ebp
26931     c3/return
26932 
26933 emit-subx-var-def:  # out: (addr buffered-file), stmt: (addr stmt)
26934     # . prologue
26935     55/push-ebp
26936     89/<- %ebp 4/r32/esp
26937     # . save registers
26938     50/push-eax
26939     51/push-ecx
26940     52/push-edx
26941     # eax = stmt
26942     8b/-> *(ebp+0xc) 0/r32/eax
26943     # var v/ecx: (addr var)
26944     (lookup *(eax+4) *(eax+8))  # Vardef-var Vardef-var => eax
26945     89/<- %ecx 0/r32/eax
26946     # v->block-depth = *Curr-block-depth
26947     8b/-> *Curr-block-depth 0/r32/eax
26948     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
26949     # var n/edx: int = size-of(stmt->var)
26950     (size-of %ecx)  # => eax
26951     89/<- %edx 0/r32/eax
26952     # *Curr-local-stack-offset -= n
26953     29/subtract-from *Curr-local-stack-offset 2/r32/edx
26954     # v->offset = *Curr-local-stack-offset
26955     8b/-> *Curr-local-stack-offset 0/r32/eax
26956     89/<- *(ecx+0x14) 0/r32/eax  # Var-offset
26957     # if v is an array, do something special to initialize it
26958     {
26959       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
26960       (is-mu-array? %eax)  # => eax
26961       3d/compare-eax-and 0/imm32/false
26962       0f 84/jump-if-= break/disp32
26963       # var array-size-without-size/edx: int = n-4
26964       81 5/subop/subtract %edx 4/imm32
26965       #
26966       (emit-array-data-initialization *(ebp+8) %edx)
26967       e9/jump $emit-subx-var-def:end/disp32
26968     }
26969     # another special-case for initializing streams
26970     # a stream is an array with 2 extra pointers
26971     {
26972       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
26973       (is-mu-stream? %eax)  # => eax
26974       3d/compare-eax-and 0/imm32/false
26975       0f 84/jump-if-= break/disp32
26976       # var array-size-without-size/edx: int = n-12
26977       81 5/subop/subtract %edx 0xc/imm32
26978       (emit-array-data-initialization *(ebp+8) %edx)
26979       # emit read and write pointers
26980       (emit-indent *(ebp+8) *Curr-block-depth)
26981       (write-buffered *(ebp+8) "68/push 0/imm32\n")
26982       (emit-indent *(ebp+8) *Curr-block-depth)
26983       (write-buffered *(ebp+8) "68/push 0/imm32\n")
26984       #
26985       eb/jump $emit-subx-var-def:end/disp8
26986     }
26987     # while n > 0
26988     {
26989       81 7/subop/compare %edx 0/imm32
26990       7e/jump-if-<= break/disp8
26991       (emit-indent *(ebp+8) *Curr-block-depth)
26992       (write-buffered *(ebp+8) "68/push 0/imm32\n")
26993       # n -= 4
26994       81 5/subop/subtract %edx 4/imm32
26995       #
26996       eb/jump loop/disp8
26997     }
26998 $emit-subx-var-def:end:
26999     # . restore registers
27000     5a/pop-to-edx
27001     59/pop-to-ecx
27002     58/pop-to-eax
27003     # . epilogue
27004     89/<- %esp 5/r32/ebp
27005     5d/pop-to-ebp
27006     c3/return
27007 
27008 emit-array-data-initialization:  # out: (addr buffered-file), n: int
27009     # . prologue
27010     55/push-ebp
27011     89/<- %ebp 4/r32/esp
27012     #
27013     (emit-indent *(ebp+8) *Curr-block-depth)
27014     (write-buffered *(ebp+8) "(push-n-zero-bytes ")
27015     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
27016     (write-buffered *(ebp+8) ")\n")
27017     (emit-indent *(ebp+8) *Curr-block-depth)
27018     (write-buffered *(ebp+8) "68/push ")
27019     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
27020     (write-buffered *(ebp+8) "/imm32\n")
27021 $emit-array-data-initialization:end:
27022     # . epilogue
27023     89/<- %esp 5/r32/ebp
27024     5d/pop-to-ebp
27025     c3/return
27026 
27027 emit-subx-stmt:  # out: (addr buffered-file), stmt: (addr stmt), primitives: (addr primitive), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
27028     # . prologue
27029     55/push-ebp
27030     89/<- %ebp 4/r32/esp
27031     # . save registers
27032     50/push-eax
27033     51/push-ecx
27034     # - some special-case primitives that don't actually use the 'primitives' data structure
27035     # var op/ecx: (addr array byte) = lookup(stmt->operation)
27036     8b/-> *(ebp+0xc) 1/r32/ecx
27037     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
27038     89/<- %ecx 0/r32/eax
27039     # array size
27040     {
27041       # if (!string-equal?(stmt->operation, "length")) break
27042       (string-equal? %ecx "length")  # => eax
27043       3d/compare-eax-and 0/imm32
27044       0f 84/jump-if-= break/disp32
27045       (translate-mu-length-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
27046       e9/jump $emit-subx-stmt:end/disp32
27047     }
27048     # index into array
27049     {
27050       # if (!string-equal?(stmt->operation, "index")) break
27051       (string-equal? %ecx "index")  # => eax
27052       3d/compare-eax-and 0/imm32
27053       0f 84/jump-if-= break/disp32
27054       (translate-mu-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
27055       e9/jump $emit-subx-stmt:end/disp32
27056     }
27057     # compute-offset for index into array
27058     {
27059       # if (!string-equal?(stmt->operation, "compute-offset")) break
27060       (string-equal? %ecx "compute-offset")  # => eax
27061       3d/compare-eax-and 0/imm32
27062       0f 84/jump-if-= break/disp32
27063       (translate-mu-compute-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
27064       e9/jump $emit-subx-stmt:end/disp32
27065     }
27066     # get field from record
27067     {
27068       # if (!string-equal?(stmt->operation, "get")) break
27069       (string-equal? %ecx "get")  # => eax
27070       3d/compare-eax-and 0/imm32
27071       0f 84/jump-if-= break/disp32
27072       (translate-mu-get-stmt *(ebp+8) *(ebp+0xc))
27073       e9/jump $emit-subx-stmt:end/disp32
27074     }
27075     # allocate scalar
27076     {
27077       # if (!string-equal?(stmt->operation, "allocate")) break
27078       (string-equal? %ecx "allocate")  # => eax
27079       3d/compare-eax-and 0/imm32
27080       0f 84/jump-if-= break/disp32
27081       (translate-mu-allocate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
27082       e9/jump $emit-subx-stmt:end/disp32
27083     }
27084     # copy-object
27085     {
27086       # if (!string-equal?(stmt->operation, "copy-object")) break
27087       (string-equal? %ecx "copy-object")  # => eax
27088       3d/compare-eax-and 0/imm32
27089       0f 84/jump-if-= break/disp32
27090       (translate-mu-copy-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
27091       e9/jump $emit-subx-stmt:end/disp32
27092     }
27093     # clear-object
27094     {
27095       # if (!string-equal?(stmt->operation, "clear-object")) break
27096       (string-equal? %ecx "clear-object")  # => eax
27097       3d/compare-eax-and 0/imm32
27098       0f 84/jump-if-= break/disp32
27099       (translate-mu-clear-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
27100       e9/jump $emit-subx-stmt:end/disp32
27101     }
27102     # allocate array
27103     {
27104       # if (!string-equal?(stmt->operation, "populate")) break
27105       (string-equal? %ecx "populate")  # => eax
27106       3d/compare-eax-and 0/imm32
27107       0f 84/jump-if-= break/disp32
27108       (translate-mu-populate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
27109       e9/jump $emit-subx-stmt:end/disp32
27110     }
27111     # allocate stream
27112     {
27113       # if (!string-equal?(stmt->operation, "populate-stream")) break
27114       (string-equal? %ecx "populate-stream")  # => eax
27115       3d/compare-eax-and 0/imm32
27116       0f 84/jump-if-= break/disp32
27117       (translate-mu-populate-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
27118       e9/jump $emit-subx-stmt:end/disp32
27119     }
27120     # read from stream
27121     {
27122       # if (!string-equal?(stmt->operation, "read-from-stream")) break
27123       (string-equal? %ecx "read-from-stream")  # => eax
27124       3d/compare-eax-and 0/imm32
27125       0f 84/jump-if-= break/disp32
27126       (translate-mu-read-from-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
27127       e9/jump $emit-subx-stmt:end/disp32
27128     }
27129     # write to stream
27130     {
27131       # if (!string-equal?(stmt->operation, "write-to-stream")) break
27132       (string-equal? %ecx "write-to-stream")  # => eax
27133       3d/compare-eax-and 0/imm32
27134       0f 84/jump-if-= break/disp32
27135       (translate-mu-write-to-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
27136       e9/jump $emit-subx-stmt:end/disp32
27137     }
27138     # - if stmt matches a primitive, emit it
27139     {
27140 $emit-subx-stmt:check-for-primitive:
27141       # var curr/eax: (addr primitive)
27142       (find-matching-primitive *(ebp+0x10) *(ebp+0xc))  # primitives, stmt => eax
27143       3d/compare-eax-and 0/imm32
27144       74/jump-if-= break/disp8
27145 $emit-subx-stmt:primitive:
27146       (emit-subx-primitive *(ebp+8) *(ebp+0xc) %eax)  # out, stmt, curr
27147       e9/jump $emit-subx-stmt:end/disp32
27148     }
27149     # - otherwise emit a call
27150     # TODO: type-checking
27151 $emit-subx-stmt:call:
27152     (emit-call *(ebp+8) *(ebp+0xc))
27153 $emit-subx-stmt:end:
27154     # . restore registers
27155     59/pop-to-ecx
27156     58/pop-to-eax
27157     # . epilogue
27158     89/<- %esp 5/r32/ebp
27159     5d/pop-to-ebp
27160     c3/return
27161 
27162 translate-mu-length-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
27163     # . prologue
27164     55/push-ebp
27165     89/<- %ebp 4/r32/esp
27166     # . save registers
27167     50/push-eax
27168     51/push-ecx
27169     52/push-edx
27170     53/push-ebx
27171     56/push-esi
27172     # esi = stmt
27173     8b/-> *(ebp+0xc) 6/r32/esi
27174     # var base/ebx: (addr var) = stmt->inouts[0]->value
27175     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27176     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27177     89/<- %ebx 0/r32/eax
27178     # var elemsize/ecx: int = array-element-size(base)
27179     (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
27180     89/<- %ecx 0/r32/eax
27181     # var outreg/edx: (addr array byte) = stmt->outputs[0]->value->register
27182     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
27183     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27184     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
27185     89/<- %edx 0/r32/eax
27186     # if elemsize == 1
27187     {
27188       81 7/subop/compare %ecx 1/imm32
27189       75/jump-if-!= break/disp8
27190 $translate-mu-length-stmt:size-1:
27191       (emit-save-size-to *(ebp+8) %ebx %edx)
27192       e9/jump $translate-mu-length-stmt:end/disp32
27193     }
27194     # if elemsize is a power of 2 less than 256
27195     {
27196       (power-of-2? %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
27197       3d/compare-eax-and 0/imm32/false
27198       74/jump-if-= break/disp8
27199       81 7/subop/compare %ecx 0xff/imm32
27200       7f/jump-if-> break/disp8
27201 $translate-mu-length-stmt:size-power-of-2:
27202       (emit-save-size-to *(ebp+8) %ebx %edx)
27203       (emit-divide-by-shift-right *(ebp+8) %edx %ecx)
27204       e9/jump $translate-mu-length-stmt:end/disp32
27205     }
27206     # otherwise, the complex case
27207     # . emit register spills
27208     {
27209 $translate-mu-length-stmt:complex:
27210       (string-equal? %edx "eax")  # => eax
27211       3d/compare-eax-and 0/imm32/false
27212       75/break-if-!= break/disp8
27213       (emit-indent *(ebp+8) *Curr-block-depth)
27214       (write-buffered *(ebp+8) "50/push-eax\n")
27215     }
27216     {
27217       (string-equal? %edx "ecx")  # => eax
27218       3d/compare-eax-and 0/imm32/false
27219       75/break-if-!= break/disp8
27220       (emit-indent *(ebp+8) *Curr-block-depth)
27221       (write-buffered *(ebp+8) "51/push-ecx\n")
27222     }
27223     {
27224       (string-equal? %edx "edx")  # => eax
27225       3d/compare-eax-and 0/imm32/false
27226       75/break-if-!= break/disp8
27227       (emit-indent *(ebp+8) *Curr-block-depth)
27228       (write-buffered *(ebp+8) "52/push-edx\n")
27229     }
27230     # .
27231     (emit-save-size-to *(ebp+8) %ebx "eax")
27232     (emit-indent *(ebp+8) *Curr-block-depth)
27233     (write-buffered *(ebp+8) "31/xor %edx 2/r32/edx\n")
27234     (emit-indent *(ebp+8) *Curr-block-depth)
27235     (write-buffered *(ebp+8) "b9/copy-to-ecx ")
27236     (write-int32-hex-buffered *(ebp+8) %ecx)
27237     (write-buffered *(ebp+8) "/imm32\n")
27238     (emit-indent *(ebp+8) *Curr-block-depth)
27239     (write-buffered *(ebp+8) "f7 7/subop/idiv-eax-edx-by %ecx\n")
27240     {
27241       (string-equal? %edx "eax")  # => eax
27242       3d/compare-eax-and 0/imm32/false
27243       75/break-if-!= break/disp8
27244       (emit-indent *(ebp+8) *Curr-block-depth)
27245       (write-buffered *(ebp+8) "89/<- %")
27246       (write-buffered *(ebp+8) %edx)
27247       (write-buffered *(ebp+8) " 0/r32/eax\n")
27248     }
27249     # . emit register restores
27250     {
27251       (string-equal? %edx "edx")  # => eax
27252       3d/compare-eax-and 0/imm32/false
27253       75/break-if-!= break/disp8
27254       (emit-indent *(ebp+8) *Curr-block-depth)
27255       (write-buffered *(ebp+8) "5a/pop-to-edx\n")
27256     }
27257     {
27258       (string-equal? %edx "ecx")  # => eax
27259       3d/compare-eax-and 0/imm32/false
27260       75/break-if-!= break/disp8
27261       (emit-indent *(ebp+8) *Curr-block-depth)
27262       (write-buffered *(ebp+8) "59/pop-to-ecx\n")
27263     }
27264     {
27265       (string-equal? %edx "eax")  # => eax
27266       3d/compare-eax-and 0/imm32/false
27267       75/break-if-!= break/disp8
27268       (emit-indent *(ebp+8) *Curr-block-depth)
27269       (write-buffered *(ebp+8) "58/pop-to-eax\n")
27270     }
27271 $translate-mu-length-stmt:end:
27272     # . restore registers
27273     5e/pop-to-esi
27274     5b/pop-to-ebx
27275     5a/pop-to-edx
27276     59/pop-to-ecx
27277     58/pop-to-eax
27278     # . epilogue
27279     89/<- %esp 5/r32/ebp
27280     5d/pop-to-ebp
27281     c3/return
27282 
27283 array-element-size:  # arr: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
27284     # . prologue
27285     55/push-ebp
27286     89/<- %ebp 4/r32/esp
27287     #
27288     (array-element-type-id *(ebp+8) *(ebp+0xc) *(ebp+0x10))  # => eax
27289     (size-of-type-id-as-array-element %eax)  # => eax
27290 $array-element-size:end:
27291     # . epilogue
27292     89/<- %esp 5/r32/ebp
27293     5d/pop-to-ebp
27294     c3/return
27295 
27296 array-element-type-id:  # v: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: type-id
27297     # precondition: n is positive
27298     # . prologue
27299     55/push-ebp
27300     89/<- %ebp 4/r32/esp
27301     #
27302     8b/-> *(ebp+8) 0/r32/eax
27303     # var t/eax: (addr type-tree)
27304     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
27305     # if t == 0 abort
27306     3d/compare-eax-with 0/imm32
27307     0f 84/jump-if-== $array-element-type-id:error0/disp32
27308     # if t->is-atom? abort
27309     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
27310     0f 85/jump-if-!= $array-element-type-id:error1/disp32
27311     # if (t->left == addr) t = t->right
27312     {
27313       50/push-eax
27314       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
27315       (is-simple-mu-type? %eax 2)  # addr => eax
27316       3d/compare-eax-with 0/imm32/false
27317       58/pop-to-eax
27318       74/jump-if-= break/disp8
27319 $array-element-type-id:skip-addr:
27320       (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
27321     }
27322     # if t == 0 abort
27323     3d/compare-eax-with 0/imm32
27324     0f 84/jump-if-= $array-element-type-id:error2/disp32
27325     # if t->is-atom? abort
27326     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
27327     0f 85/jump-if-!= $array-element-type-id:error2/disp32
27328     # if t->left != array abort
27329     {
27330       50/push-eax
27331       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
27332       (is-simple-mu-type? %eax 3)  # array => eax
27333       3d/compare-eax-with 0/imm32/false
27334       58/pop-to-eax
27335 $array-element-type-id:no-array:
27336       0f 84/jump-if-= $array-element-type-id:error2/disp32
27337     }
27338 $array-element-type-id:skip-array:
27339     # t = t->right
27340     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
27341     # if t == 0 abort
27342     3d/compare-eax-with 0/imm32
27343     0f 84/jump-if-= $array-element-type-id:error2/disp32
27344     # if t->is-atom? abort
27345     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
27346     0f 85/jump-if-!= $array-element-type-id:error2/disp32
27347     # t = t->left
27348     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
27349     # if (!t->is-atom?) t = t->left     # TODO: assumes array element size can be determined from just first word of array element type
27350     # if (t->is-atom == false) t = lookup(t->left)
27351     {
27352       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
27353       75/jump-if-!= break/disp8
27354       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
27355     }
27356     # return t->value
27357     8b/-> *(eax+4) 0/r32/eax  # Type-tree-value
27358 $array-element-type-id:end:
27359     # . epilogue
27360     89/<- %esp 5/r32/ebp
27361     5d/pop-to-ebp
27362     c3/return
27363 
27364 $array-element-type-id:error0:
27365     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
27366     50/push-eax
27367     8b/-> *(ebp+8) 0/r32/eax
27368     (lookup *eax *(eax+4))  # Var-name Var-name => eax
27369     (write-buffered *(ebp+0xc) %eax)
27370     58/pop-to-eax
27371     (write-buffered *(ebp+0xc) "' has no type\n")
27372     (flush *(ebp+0xc))
27373     (stop *(ebp+0x10) 1)
27374     # never gets here
27375 
27376 $array-element-type-id:error1:
27377     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
27378     50/push-eax
27379     8b/-> *(ebp+8) 0/r32/eax
27380     (lookup *eax *(eax+4))  # Var-name Var-name => eax
27381     (write-buffered *(ebp+0xc) %eax)
27382     58/pop-to-eax
27383     (write-buffered *(ebp+0xc) "' has atomic type ")
27384     (write-int32-hex-buffered *(ebp+0xc) *(eax+4))  # Type-tree-value
27385     (write-buffered *(ebp+0xc) Newline)
27386     (flush *(ebp+0xc))
27387     (stop *(ebp+0x10) 1)
27388     # never gets here
27389 
27390 $array-element-type-id:error2:
27391     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
27392     50/push-eax
27393     8b/-> *(ebp+8) 0/r32/eax
27394     (lookup *eax *(eax+4))  # Var-name Var-name => eax
27395     (write-buffered *(ebp+0xc) %eax)
27396     58/pop-to-eax
27397     (write-buffered *(ebp+0xc) "' has non-array type\n")
27398     (flush *(ebp+0xc))
27399     (stop *(ebp+0x10) 1)
27400     # never gets here
27401 
27402 size-of-type-id-as-array-element:  # t: type-id -> result/eax: int
27403     # . prologue
27404     55/push-ebp
27405     89/<- %ebp 4/r32/esp
27406     # eax = t
27407     8b/-> *(ebp+8) 0/r32/eax
27408     # if t is 'byte', size is 1
27409     3d/compare-eax-and 8/imm32/byte
27410     {
27411       75/jump-if-!= break/disp8
27412       b8/copy-to-eax 1/imm32
27413       eb/jump $size-of-type-id-as-array-element:end/disp8
27414     }
27415     # otherwise proceed as usual
27416     (size-of-type-id %eax)  # => eax
27417 $size-of-type-id-as-array-element:end:
27418     # . epilogue
27419     89/<- %esp 5/r32/ebp
27420     5d/pop-to-ebp
27421     c3/return
27422 
27423 emit-save-size-to:  # out: (addr buffered-file), base: (addr var), outreg: (addr array byte)
27424     # . prologue
27425     55/push-ebp
27426     89/<- %ebp 4/r32/esp
27427     # . save registers
27428     50/push-eax
27429     53/push-ebx
27430     # ebx = base
27431     8b/-> *(ebp+0xc) 3/r32/ebx
27432     (emit-indent *(ebp+8) *Curr-block-depth)
27433     (write-buffered *(ebp+8) "8b/-> *")
27434     # if base is an (addr array ...) in a register
27435     {
27436       81 7/subop/compare *(ebx+0x18)) 0/imm32  # Var-register
27437       74/jump-if-= break/disp8
27438 $emit-save-size-to:emit-base-from-register:
27439       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
27440       (write-buffered *(ebp+8) %eax)
27441       eb/jump $emit-save-size-to:emit-output/disp8
27442     }
27443     # otherwise if base is an (array ...) on the stack
27444     {
27445       81 7/subop/compare *(ebx+0x14)) 0/imm32  # Var-offset
27446       74/jump-if-= break/disp8
27447 $emit-save-size-to:emit-base-from-stack:
27448       (write-buffered *(ebp+8) "(ebp+")
27449       (write-int32-hex-buffered *(ebp+8) *(ebx+0x14))  # Var-offset
27450       (write-buffered *(ebp+8) ")")
27451     }
27452 $emit-save-size-to:emit-output:
27453     (write-buffered *(ebp+8) " ")
27454     (get Mu-registers *(ebp+0x10) 0xc "Mu-registers")  # => eax
27455     (write-int32-hex-buffered *(ebp+8) *eax)
27456     (write-buffered *(ebp+8) "/r32\n")
27457 $emit-save-size-to:end:
27458     # . restore registers
27459     5b/pop-to-ebx
27460     58/pop-to-eax
27461     # . epilogue
27462     89/<- %esp 5/r32/ebp
27463     5d/pop-to-ebp
27464     c3/return
27465 
27466 emit-divide-by-shift-right:  # out: (addr buffered-file), reg: (addr array byte), size: int
27467     # . prologue
27468     55/push-ebp
27469     89/<- %ebp 4/r32/esp
27470     # . save registers
27471     50/push-eax
27472     #
27473     (emit-indent *(ebp+8) *Curr-block-depth)
27474     (write-buffered *(ebp+8) "c1/shift 5/subop/>> %")
27475     (write-buffered *(ebp+8) *(ebp+0xc))
27476     (write-buffered *(ebp+8) Space)
27477     (num-shift-rights *(ebp+0x10))  # => eax
27478     (write-int32-hex-buffered *(ebp+8) %eax)
27479     (write-buffered *(ebp+8) "/imm8\n")
27480 $emit-divide-by-shift-right:end:
27481     # . restore registers
27482     58/pop-to-eax
27483     # . epilogue
27484     89/<- %esp 5/r32/ebp
27485     5d/pop-to-ebp
27486     c3/return
27487 
27488 # a little different from other translate- functions; notice the extra 'fn' argument
27489 translate-mu-index-stmt:  # out: (addr buffered-file), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
27490     # . prologue
27491     55/push-ebp
27492     89/<- %ebp 4/r32/esp
27493     # . save registers
27494     53/push-ebx
27495     # ebx = stmt
27496     8b/-> *(ebp+0xc) 3/r32/ebx
27497     # var base/ebx: (addr var) = stmt->inouts[0]
27498     (lookup *(ebx+0xc) *(ebx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27499     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27500     89/<- %ebx 0/r32/eax
27501     # emit bounds-check
27502     (emit-mu-index-bounds-check *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18))
27503     # if (var->register) do one thing
27504     {
27505       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
27506       74/jump-if-= break/disp8
27507       # TODO: ensure there's no dereference
27508       (translate-mu-index-stmt-with-array-in-register *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
27509       eb/jump $translate-mu-index-stmt:end/disp8
27510     }
27511     # if (var->offset) do a different thing
27512     {
27513       81 7/subop/compare *(ebx+0x14) 0/imm32  # Var-offset
27514       74/jump-if-= break/disp8
27515       # TODO: ensure there's no dereference
27516       (translate-mu-index-stmt-with-array-on-stack *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
27517       eb/jump $translate-mu-index-stmt:end/disp8
27518     }
27519 $translate-mu-index-stmt:end:
27520     # . restore registers
27521     5b/pop-to-ebx
27522     # . epilogue
27523     89/<- %esp 5/r32/ebp
27524     5d/pop-to-ebp
27525     c3/return
27526 
27527 $translate-mu-index-stmt:error1:
27528     (write-buffered *(ebp+0x14) "couldn't translate an index instruction. second (index) input must either lie in a register or be a literal\n")
27529     (flush *(ebp+0x14))
27530     (stop *(ebp+0x18) 1)
27531     # never gets here
27532 
27533 $translate-mu-index-stmt:error2:
27534     (write-buffered *(ebp+0x14) "couldn't translate an index instruction. second (index) input when in a register must be an int or offset\n")
27535     (flush *(ebp+0x14))
27536     (stop *(ebp+0x18) 1)
27537     # never gets here
27538 
27539 emit-mu-index-bounds-check:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
27540     # . prologue
27541     55/push-ebp
27542     89/<- %ebp 4/r32/esp
27543     # . save registers
27544     50/push-eax
27545     51/push-ecx
27546     52/push-edx
27547     53/push-ebx
27548     # ecx = stmt
27549     8b/-> *(ebp+0xc) 1/r32/ecx
27550     #
27551     (emit-indent *(ebp+8) *Curr-block-depth)
27552     (write-buffered *(ebp+8) "(__check-mu-array-bounds ")
27553 $emit-mu-index-bounds-check:compute-base:
27554     # var base/ebx: (addr var) = inouts[0]
27555     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27556     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27557     89/<- %ebx 0/r32/eax
27558 $emit-mu-index-bounds-check:emit-index:
27559     # var index/edx: (addr var) = inouts[1]
27560     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27561     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
27562     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27563     89/<- %edx 0/r32/eax
27564     # if index->register, print its code
27565     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
27566     {
27567       0f 84/jump-if-= break/disp32
27568 $emit-mu-index-bounds-check:emit-register-index:
27569       (write-buffered *(ebp+8) "%")
27570       (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
27571       (write-buffered *(ebp+8) %eax)
27572       eb/jump $emit-mu-index-bounds-check:index-done/disp8
27573     }
27574     # otherwise if index is a literal, print it
27575 $emit-mu-index-bounds-check:emit-literal-index:
27576     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
27577     (is-simple-mu-type? %eax 0)  # => eax
27578     3d/compare-eax-and 0/imm32/false
27579     {
27580       0f 84/jump-if-= break/disp32
27581       (lookup *edx *(edx+4))  # Var-name Var-name => eax
27582       (write-buffered *(ebp+8) %eax)
27583     }
27584 $emit-mu-index-bounds-check:index-done:
27585     (write-buffered *(ebp+8) " ")
27586 $emit-mu-index-bounds-check:emit-element-size:
27587     # if index is a literal or int, print size of array element
27588     {
27589       {
27590         (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
27591         (is-simple-mu-type? %eax 0)  # literal => eax
27592         3d/compare-eax-and 0/imm32/false
27593         75/jump-if-!= break/disp8
27594         (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
27595         (is-simple-mu-type? %eax 1)  # int => eax
27596         3d/compare-eax-and 0/imm32/false
27597         75/jump-if-!= break/disp8
27598         eb/jump $emit-mu-index-bounds-check:emit-element-size-offset/disp8
27599       }
27600 $emit-mu-index-bounds-check:emit-int-register-index:
27601       (array-element-size %ebx *(ebp+0x14) *(ebp+0x18))  # => eax
27602       (write-int32-hex-buffered *(ebp+8) %eax)
27603       e9/jump $emit-mu-index-bounds-check:emit-base/disp32
27604     }
27605 $emit-mu-index-bounds-check:emit-element-size-offset:
27606     # if index has type (offset ...), print "1"
27607     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
27608     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
27609     {
27610       75/jump-if-!= break/disp8
27611       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
27612       (is-simple-mu-type? %eax 7)  # => eax
27613       3d/compare-eax-and 0/imm32/false
27614       {
27615         0f 84/jump-if-= break/disp32
27616 $emit-mu-index-bounds-check:emit-offset-register-index:
27617         (write-buffered *(ebp+8) "1")
27618       }
27619     }
27620 $emit-mu-index-bounds-check:emit-base:
27621     # if base is in a register, print " *" base->register
27622     81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
27623     {
27624       74/jump-if-= break/disp8
27625       (write-buffered *(ebp+8) " *")
27626       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
27627       (write-buffered *(ebp+8) %eax)
27628       e9/jump $emit-mu-index-bounds-check:emit-function-name/disp32
27629     }
27630     # otherwise print " *(ebp+" base->offset ")"
27631     (write-buffered *(ebp+8) " *(ebp+")
27632     (write-int32-hex-buffered *(ebp+8) *(ebx+0x14))  # Var-offset
27633     (write-buffered *(ebp+8) ")")
27634 $emit-mu-index-bounds-check:emit-function-name:
27635     # " \"" function-name "\""
27636     (write-buffered *(ebp+8) " \"")
27637     8b/-> *(ebp+0x10) 1/r32/ecx
27638     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
27639     (write-buffered *(ebp+8) %eax)
27640     (write-buffered *(ebp+8) "\"")
27641 $emit-mu-index-bounds-check:emit-array-name:
27642     # " \"" base->name "\""
27643     (write-buffered *(ebp+8) " \"")
27644     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
27645     (write-buffered *(ebp+8) %eax)
27646     (write-buffered *(ebp+8) "\")\n")
27647 $emit-mu-index-bounds-check:end:
27648     # . restore registers
27649     5b/pop-to-ebx
27650     5a/pop-to-edx
27651     59/pop-to-ecx
27652     58/pop-to-eax
27653     # . epilogue
27654     89/<- %esp 5/r32/ebp
27655     5d/pop-to-ebp
27656     c3/return
27657 
27658 translate-mu-index-stmt-with-array-in-register:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
27659     # . prologue
27660     55/push-ebp
27661     89/<- %ebp 4/r32/esp
27662     # . save registers
27663     50/push-eax
27664     51/push-ecx
27665     52/push-edx
27666     53/push-ebx
27667     #
27668     (emit-indent *(ebp+8) *Curr-block-depth)
27669     (write-buffered *(ebp+8) "8d/copy-address *(")
27670     # TODO: ensure inouts[0] is in a register and not dereferenced
27671 $translate-mu-index-stmt-with-array-in-register:emit-base:
27672     # ecx = stmt
27673     8b/-> *(ebp+0xc) 1/r32/ecx
27674     # var base/ebx: (addr var) = inouts[0]
27675     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27676     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27677     89/<- %ebx 0/r32/eax
27678     # print base->register " + "
27679     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
27680     (write-buffered *(ebp+8) %eax)
27681     (write-buffered *(ebp+8) " + ")
27682     # var index/edx: (addr var) = inouts[1]
27683     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27684     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
27685     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27686     89/<- %edx 0/r32/eax
27687     # if index->register
27688     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
27689     {
27690       0f 84/jump-if-= break/disp32
27691 $translate-mu-index-stmt-with-array-in-register:emit-register-index:
27692       # if index is an int
27693       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
27694       (is-simple-mu-type? %eax 1)  # int => eax
27695       3d/compare-eax-and 0/imm32/false
27696       {
27697         0f 84/jump-if-= break/disp32
27698 $translate-mu-index-stmt-with-array-in-register:emit-int-register-index:
27699         # print index->register "<<" log2(array-element-size(base)) " + 4) "
27700         # . index->register "<<"
27701         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
27702         (write-buffered *(ebp+8) %eax)
27703         (write-buffered *(ebp+8) "<<")
27704         # . log2(array-element-size(base->type))
27705         # we know size is a power of 2
27706         (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
27707         (num-shift-rights %eax)  # => eax
27708         (write-int32-hex-buffered *(ebp+8) %eax)
27709         e9/jump $translate-mu-index-stmt-with-array-in-register:emit-register-index-done/disp32
27710       }
27711       # if index->type is any other atom, abort
27712       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
27713       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
27714       0f 85/jump-if-!= $translate-mu-index-stmt:error2/disp32
27715       # if index has type (offset ...)
27716       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
27717       (is-simple-mu-type? %eax 7)  # => eax
27718       3d/compare-eax-and 0/imm32/false
27719       {
27720         0f 84/jump-if-= break/disp32
27721         # print index->register
27722 $translate-mu-index-stmt-with-array-in-register:emit-offset-register-index:
27723         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
27724         (write-buffered *(ebp+8) %eax)
27725       }
27726 $translate-mu-index-stmt-with-array-in-register:emit-register-index-done:
27727       (write-buffered *(ebp+8) " + 4) ")
27728       e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32
27729     }
27730     # otherwise if index is a literal
27731     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
27732     (is-simple-mu-type? %eax 0)  # => eax
27733     3d/compare-eax-and 0/imm32/false
27734     {
27735       0f 84/jump-if-= break/disp32
27736 $translate-mu-index-stmt-with-array-in-register:emit-literal-index:
27737       # var index-value/edx: int = parse-hex-int(index->name)
27738       (lookup *edx *(edx+4))  # Var-name Var-name => eax
27739       (parse-hex-int %eax)  # => eax
27740       89/<- %edx 0/r32/eax
27741       # offset = idx-value * array-element-size(base->type)
27742       (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
27743       f7 4/subop/multiply-into-edx-eax %edx  # clobbers edx
27744       # offset += 4 for array size
27745       05/add-to-eax 4/imm32
27746       # TODO: check edx for overflow
27747       # print offset
27748       (write-int32-hex-buffered *(ebp+8) %eax)
27749       (write-buffered *(ebp+8) ") ")
27750       e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32
27751     }
27752     # otherwise abort
27753     e9/jump $translate-mu-index-stmt:error1/disp32
27754 $translate-mu-index-stmt-with-array-in-register:emit-output:
27755     # outputs[0] "/r32"
27756     8b/-> *(ebp+0xc) 1/r32/ecx
27757     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
27758     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27759     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
27760     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
27761     (write-int32-hex-buffered *(ebp+8) *eax)
27762     (write-buffered *(ebp+8) "/r32\n")
27763 $translate-mu-index-stmt-with-array-in-register:end:
27764     # . restore registers
27765     5b/pop-to-ebx
27766     5a/pop-to-edx
27767     59/pop-to-ecx
27768     58/pop-to-eax
27769     # . epilogue
27770     89/<- %esp 5/r32/ebp
27771     5d/pop-to-ebp
27772     c3/return
27773 
27774 translate-mu-index-stmt-with-array-on-stack:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
27775     # . prologue
27776     55/push-ebp
27777     89/<- %ebp 4/r32/esp
27778     # . save registers
27779     50/push-eax
27780     51/push-ecx
27781     52/push-edx
27782     53/push-ebx
27783     #
27784     (emit-indent *(ebp+8) *Curr-block-depth)
27785     (write-buffered *(ebp+8) "8d/copy-address *(ebp + ")
27786     # var curr/edx: (addr stmt-var) = lookup(stmt->inouts)
27787     8b/-> *(ebp+0xc) 0/r32/eax
27788     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27789     89/<- %edx 0/r32/eax
27790     # var base/ecx: (addr var) = lookup(curr->value)
27791     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27792     89/<- %ecx 0/r32/eax
27793     # var curr2/eax: (addr stmt-var) = lookup(curr->next)
27794     (lookup *(edx+8) *(edx+0xc))  # Stmt-var-next Stmt-var-next => eax
27795     # var index/edx: (handle var) = curr2->value
27796     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27797     89/<- %edx 0/r32/eax
27798     # if index->register
27799     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
27800     {
27801       0f 84/jump-if-= break/disp32
27802 $translate-mu-index-stmt-with-array-on-stack:emit-register-index:
27803       # if index is an int
27804       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
27805       (is-simple-mu-type? %eax 1)  # int => eax
27806       3d/compare-eax-and 0/imm32/false
27807       {
27808         0f 84/jump-if-= break/disp32
27809 $translate-mu-index-stmt-with-array-on-stack:emit-int-register-index:
27810         # print index->register "<<" log2(array-element-size(base)) " + " base->offset+4
27811         # . inouts[1]->register "<<"
27812         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
27813         (write-buffered *(ebp+8) %eax)
27814         (write-buffered *(ebp+8) "<<")
27815         # . log2(array-element-size(base))
27816         # TODO: ensure size is a power of 2
27817         (array-element-size %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
27818         (num-shift-rights %eax)  # => eax
27819         (write-int32-hex-buffered *(ebp+8) %eax)
27820         #
27821         (write-buffered *(ebp+8) " + ")
27822         #
27823         8b/-> *(ecx+0x14) 0/r32/eax  # Var-offset
27824         05/add-to-eax 4/imm32  # for array length
27825         (write-int32-hex-buffered *(ebp+8) %eax)
27826         e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done/disp32
27827       }
27828       # if index->type is any other atom, abort
27829       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
27830       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
27831       0f 85/jump-if-!= $translate-mu-index-stmt:error2/disp32
27832       # if index has type (offset ...)
27833       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
27834       (is-simple-mu-type? %eax 7)  # => eax
27835       3d/compare-eax-and 0/imm32/false
27836       {
27837         0f 84/jump-if-= break/disp32
27838         # print index->register
27839 $translate-mu-index-stmt-with-array-on-stack:emit-offset-register-index:
27840         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
27841         (write-buffered *(ebp+8) %eax)
27842       }
27843 $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done:
27844       (write-buffered *(ebp+8) ") ")
27845       e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32
27846     }
27847     # otherwise if index is a literal
27848     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
27849     (is-simple-mu-type? %eax 0)  # => eax
27850     3d/compare-eax-and 0/imm32/false
27851     {
27852       0f 84/jump-if-= break/disp32
27853 $translate-mu-index-stmt-with-array-on-stack:emit-literal-index:
27854       # var idx-value/edx: int = parse-hex-int(index->name)
27855       (lookup *edx *(edx+4))  # Var-name Var-name => eax
27856       (parse-hex-int %eax)  # Var-name => eax
27857       89/<- %edx 0/r32/eax
27858       # offset = idx-value * array-element-size(base)
27859       (array-element-size %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
27860       f7 4/subop/multiply-into-edx-eax %edx  # clobbers edx
27861       # offset += base->offset
27862       03/add *(ecx+0x14) 0/r32/eax  # Var-offset
27863       # offset += 4 for array size
27864       05/add-to-eax 4/imm32
27865       # TODO: check edx for overflow
27866       # print offset
27867       (write-int32-hex-buffered *(ebp+8) %eax)
27868       (write-buffered *(ebp+8) ") ")
27869       e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32
27870     }
27871     # otherwise abort
27872     e9/jump $translate-mu-index-stmt:error1/disp32
27873 $translate-mu-index-stmt-with-array-on-stack:emit-output:
27874     # outputs[0] "/r32"
27875     8b/-> *(ebp+0xc) 0/r32/eax
27876     (lookup *(eax+0x14) *(eax+0x18))  # Stmt1-outputs Stmt1-outputs => eax
27877     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27878     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
27879     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
27880     (write-int32-hex-buffered *(ebp+8) *eax)
27881     (write-buffered *(ebp+8) "/r32\n")
27882 $translate-mu-index-stmt-with-array-on-stack:end:
27883     # . restore registers
27884     5b/pop-to-ebx
27885     5a/pop-to-edx
27886     59/pop-to-ecx
27887     58/pop-to-eax
27888     # . epilogue
27889     89/<- %esp 5/r32/ebp
27890     5d/pop-to-ebp
27891     c3/return
27892 
27893 translate-mu-compute-index-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
27894     # . prologue
27895     55/push-ebp
27896     89/<- %ebp 4/r32/esp
27897     # . save registers
27898     50/push-eax
27899     51/push-ecx
27900     52/push-edx
27901     53/push-ebx
27902     #
27903     (emit-indent *(ebp+8) *Curr-block-depth)
27904     (write-buffered *(ebp+8) "69/multiply")
27905     # ecx = stmt
27906     8b/-> *(ebp+0xc) 1/r32/ecx
27907     # var first-inout/ebx: (addr stmt-var) = stmt->inouts[0]
27908     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27909     89/<- %ebx 0/r32/eax
27910 $translate-mu-compute-index-stmt:emit-index:
27911     (lookup *(ebx+8) *(ebx+0xc))  # Stmt-var-next Stmt-var-next => eax
27912     (emit-subx-var-as-rm32 *(ebp+8) %eax)
27913     (write-buffered *(ebp+8) Space)
27914 $translate-mu-compute-index-stmt:emit-elem-size:
27915     # var base/ebx: (addr var)
27916     (lookup *ebx *(ebx+4))  # Stmt-var-value Stmt-var-value => eax
27917     89/<- %ebx 0/r32/eax
27918     # print array-element-size(base)
27919     (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
27920     (write-int32-hex-buffered *(ebp+8) %eax)
27921     (write-buffered *(ebp+8) "/imm32 ")
27922 $translate-mu-compute-index-stmt:emit-output:
27923     # outputs[0] "/r32"
27924     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
27925     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27926     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
27927     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
27928     (write-int32-hex-buffered *(ebp+8) *eax)
27929     (write-buffered *(ebp+8) "/r32\n")
27930 $translate-mu-compute-index-stmt:end:
27931     # . restore registers
27932     5b/pop-to-ebx
27933     5a/pop-to-edx
27934     59/pop-to-ecx
27935     58/pop-to-eax
27936     # . epilogue
27937     89/<- %esp 5/r32/ebp
27938     5d/pop-to-ebp
27939     c3/return
27940 
27941 translate-mu-get-stmt:  # out: (addr buffered-file), stmt: (addr stmt)
27942     # . prologue
27943     55/push-ebp
27944     89/<- %ebp 4/r32/esp
27945     # . save registers
27946     50/push-eax
27947     51/push-ecx
27948     52/push-edx
27949     #
27950     (emit-indent *(ebp+8) *Curr-block-depth)
27951     (write-buffered *(ebp+8) "8d/copy-address ")
27952     # ecx = stmt
27953     8b/-> *(ebp+0xc) 1/r32/ecx
27954     # var offset/edx: int = get offset of stmt
27955     (mu-get-offset %ecx)  # => eax
27956     89/<- %edx 0/r32/eax
27957     # var base/eax: (addr var) = stmt->inouts->value
27958     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27959     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27960     # if base is in a register
27961     81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
27962     {
27963       0f 84/jump-if-= break/disp32
27964 $translate-mu-get-stmt:emit-register-input:
27965       # emit "*(" base->register " + " offset ") "
27966       (write-buffered *(ebp+8) "*(")
27967       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
27968       (write-buffered *(ebp+8) %eax)
27969       (write-buffered *(ebp+8) " + ")
27970       (write-int32-hex-buffered *(ebp+8) %edx)
27971       (write-buffered *(ebp+8) ") ")
27972       e9/jump $translate-mu-get-stmt:emit-output/disp32
27973     }
27974     # otherwise base is on the stack
27975     {
27976 $translate-mu-get-stmt:emit-stack-input:
27977       # emit "*(ebp + " inouts[0]->stack-offset + offset ") "
27978       (write-buffered *(ebp+8) "*(ebp+")
27979       03/add *(eax+0x14) 2/r32/edx  # Var-offset
27980       (write-int32-hex-buffered *(ebp+8) %edx)
27981       (write-buffered *(ebp+8) ") ")
27982       eb/jump $translate-mu-get-stmt:emit-output/disp8
27983     }
27984 $translate-mu-get-stmt:emit-output:
27985     # var output/eax: (addr var) = stmt->outputs->value
27986     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
27987     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27988     # emit offset->register "/r32"
27989     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
27990     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
27991     (write-int32-hex-buffered *(ebp+8) *eax)
27992     (write-buffered *(ebp+8) "/r32\n")
27993 $translate-mu-get-stmt:end:
27994     # . restore registers
27995     5a/pop-to-edx
27996     59/pop-to-ecx
27997     58/pop-to-eax
27998     # . epilogue
27999     89/<- %esp 5/r32/ebp
28000     5d/pop-to-ebp
28001     c3/return
28002 
28003 translate-mu-copy-object-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
28004     # . prologue
28005     55/push-ebp
28006     89/<- %ebp 4/r32/esp
28007     # . save registers
28008     50/push-eax
28009     #
28010     (emit-indent *(ebp+8) *Curr-block-depth)
28011     (write-buffered *(ebp+8) "(copy-bytes")
28012     # eax = stmt
28013     8b/-> *(ebp+0xc) 0/r32/eax
28014     # var first-inout/eax: (addr stmt-var) = stmt->inouts[0]
28015     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
28016     (emit-subx-call-operand *(ebp+8) %eax)
28017     # var second-inout/eax: (addr stmt-var) = stmt->inouts[1]
28018     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
28019     (emit-subx-call-operand *(ebp+8) %eax)
28020     # emit size of inouts
28021     (write-buffered *(ebp+8) Space)
28022     (addr-payload-size %eax *(ebp+0x10) *(ebp+0x14))  # => eax
28023     (write-int32-hex-buffered *(ebp+8) %eax)
28024     (write-buffered *(ebp+8) ")\n")
28025 $translate-mu-copy-object-stmt:end:
28026     # . restore registers
28027     58/pop-to-eax
28028     # . epilogue
28029     89/<- %esp 5/r32/ebp
28030     5d/pop-to-ebp
28031     c3/return
28032 
28033 translate-mu-clear-object-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
28034     # . prologue
28035     55/push-ebp
28036     89/<- %ebp 4/r32/esp
28037     # . save registers
28038     50/push-eax
28039     #
28040     (emit-indent *(ebp+8) *Curr-block-depth)
28041     (write-buffered *(ebp+8) "(zero-out")
28042     # eax = stmt
28043     8b/-> *(ebp+0xc) 0/r32/eax
28044     # var dest/eax: (addr stmt-var) = stmt->inouts[0]
28045     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
28046     #
28047     (emit-subx-call-operand *(ebp+8) %eax)
28048     (write-buffered *(ebp+8) Space)
28049     (addr-payload-size %eax *(ebp+0x10) *(ebp+0x14))  # => eax
28050     (write-int32-hex-buffered *(ebp+8) %eax)
28051     (write-buffered *(ebp+8) ")\n")
28052 $translate-mu-clear-object-stmt:end:
28053     # . restore registers
28054     58/pop-to-eax
28055     # . epilogue
28056     89/<- %esp 5/r32/ebp
28057     5d/pop-to-ebp
28058     c3/return
28059 
28060 translate-mu-allocate-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
28061     # . prologue
28062     55/push-ebp
28063     89/<- %ebp 4/r32/esp
28064     # . save registers
28065     50/push-eax
28066     56/push-esi
28067     57/push-edi
28068     # esi = stmt
28069     8b/-> *(ebp+0xc) 6/r32/esi
28070     # var target/edi: (addr stmt-var) = stmt->inouts[0]
28071     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
28072     89/<- %edi 0/r32/eax
28073     #
28074     (emit-indent *(ebp+8) *Curr-block-depth)
28075     (write-buffered *(ebp+8) "(allocate Heap ")
28076     (addr-handle-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
28077     (write-int32-hex-buffered *(ebp+8) %eax)
28078     (emit-subx-call-operand *(ebp+8) %edi)
28079     (write-buffered *(ebp+8) ")\n")
28080 $translate-mu-allocate-stmt:end:
28081     # . restore registers
28082     5f/pop-to-edi
28083     5e/pop-to-esi
28084     58/pop-to-eax
28085     # . epilogue
28086     89/<- %esp 5/r32/ebp
28087     5d/pop-to-ebp
28088     c3/return
28089 
28090 addr-handle-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
28091     # . prologue
28092     55/push-ebp
28093     89/<- %ebp 4/r32/esp
28094     # var t/eax: (addr type-tree) = s->value->type
28095     8b/-> *(ebp+8) 0/r32/eax
28096     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
28097     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
28098     # TODO: check eax != 0
28099     # TODO: check !t->is-atom?
28100     # TODO: check t->left == addr
28101     # t = t->right
28102 $addr-handle-payload-size:skip-addr:
28103     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
28104     # TODO: check eax != 0
28105     # TODO: check !t->is-atom?
28106     # TODO: check t->left == handle
28107     # t = t->right
28108 $addr-handle-payload-size:skip-handle:
28109     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
28110     # TODO: check eax != 0
28111     # if !t->is-atom? t = t->left
28112     81 7/subop/compare *eax 0/imm32/false
28113     {
28114       75/jump-if-!= break/disp8
28115       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
28116     }
28117     # TODO: check t->is-atom?
28118     # return size(t->value)
28119     (size-of-type-id *(eax+4))  # Type-tree-value => eax
28120 $addr-handle-payload-size:end:
28121     # . epilogue
28122     89/<- %esp 5/r32/ebp
28123     5d/pop-to-ebp
28124     c3/return
28125 
28126 addr-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
28127     # . prologue
28128     55/push-ebp
28129     89/<- %ebp 4/r32/esp
28130     # var t/eax: (addr type-tree) = s->value->type
28131     8b/-> *(ebp+8) 0/r32/eax
28132     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
28133     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
28134     # TODO: check eax != 0
28135     # TODO: check !t->is-atom?
28136     # TODO: check t->left == addr
28137     # t = t->right
28138 $addr-payload-size:skip-addr:
28139     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
28140     # TODO: check eax != 0
28141     # if !t->is-atom? t = t->left
28142     81 7/subop/compare *eax 0/imm32/false
28143     {
28144       75/jump-if-!= break/disp8
28145       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
28146     }
28147     # TODO: check t->is-atom?
28148     # return size(t->value)
28149     (size-of-type-id *(eax+4))  # Type-tree-value => eax
28150 $addr-payload-size:end:
28151     # . epilogue
28152     89/<- %esp 5/r32/ebp
28153     5d/pop-to-ebp
28154     c3/return
28155 
28156 translate-mu-populate-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
28157     # . prologue
28158     55/push-ebp
28159     89/<- %ebp 4/r32/esp
28160     # . save registers
28161     50/push-eax
28162     51/push-ecx
28163     56/push-esi
28164     57/push-edi
28165     # esi = stmt
28166     8b/-> *(ebp+0xc) 6/r32/esi
28167     # var target/edi: (addr stmt-var) = stmt->inouts[0]
28168     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
28169     89/<- %edi 0/r32/eax
28170     # var len/ecx: (addr stmt-var) = stmt->inouts[1]
28171     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
28172     89/<- %ecx 0/r32/eax
28173     #
28174     (emit-indent *(ebp+8) *Curr-block-depth)
28175     (write-buffered *(ebp+8) "(allocate-array2 Heap ")
28176     (addr-handle-array-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
28177     (write-int32-hex-buffered *(ebp+8) %eax)
28178     (emit-subx-call-operand *(ebp+8) %ecx)
28179     (emit-subx-call-operand *(ebp+8) %edi)
28180     (write-buffered *(ebp+8) ")\n")
28181 $translate-mu-populate-stmt:end:
28182     # . restore registers
28183     5f/pop-to-edi
28184     5e/pop-to-esi
28185     59/pop-to-ecx
28186     58/pop-to-eax
28187     # . epilogue
28188     89/<- %esp 5/r32/ebp
28189     5d/pop-to-ebp
28190     c3/return
28191 
28192 translate-mu-populate-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
28193     # . prologue
28194     55/push-ebp
28195     89/<- %ebp 4/r32/esp
28196     # . save registers
28197     50/push-eax
28198     51/push-ecx
28199     56/push-esi
28200     57/push-edi
28201     # esi = stmt
28202     8b/-> *(ebp+0xc) 6/r32/esi
28203     # var target/edi: (addr stmt-var) = stmt->inouts[0]
28204     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
28205     89/<- %edi 0/r32/eax
28206     # var len/ecx: (addr stmt-var) = stmt->inouts[1]
28207     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
28208     89/<- %ecx 0/r32/eax
28209     #
28210     (emit-indent *(ebp+8) *Curr-block-depth)
28211     (write-buffered *(ebp+8) "(new-stream Heap ")
28212     (addr-handle-stream-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
28213     (write-int32-hex-buffered *(ebp+8) %eax)
28214     (emit-subx-call-operand *(ebp+8) %ecx)
28215     (emit-subx-call-operand *(ebp+8) %edi)
28216     (write-buffered *(ebp+8) ")\n")
28217 $translate-mu-populate-stream-stmt:end:
28218     # . restore registers
28219     5f/pop-to-edi
28220     5e/pop-to-esi
28221     59/pop-to-ecx
28222     58/pop-to-eax
28223     # . epilogue
28224     89/<- %esp 5/r32/ebp
28225     5d/pop-to-ebp
28226     c3/return
28227 
28228 translate-mu-read-from-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
28229     # . prologue
28230     55/push-ebp
28231     89/<- %ebp 4/r32/esp
28232     # . save registers
28233     50/push-eax
28234     51/push-ecx
28235     56/push-esi
28236     57/push-edi
28237     # esi = stmt
28238     8b/-> *(ebp+0xc) 6/r32/esi
28239     # var stream/ecx: (addr stmt-var) = stmt->inouts[0]
28240     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
28241     89/<- %ecx 0/r32/eax
28242     # var target/edi: (addr stmt-var) = stmt->inouts[1]
28243     (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
28244     89/<- %edi 0/r32/eax
28245     #
28246     (emit-indent *(ebp+8) *Curr-block-depth)
28247     (write-buffered *(ebp+8) "(read-from-stream")
28248     (emit-subx-call-operand *(ebp+8) %ecx)
28249     (emit-subx-call-operand *(ebp+8) %edi)
28250     (write-buffered *(ebp+8) Space)
28251     (addr-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
28252     (write-int32-hex-buffered *(ebp+8) %eax)
28253     (write-buffered *(ebp+8) ")\n")
28254 $translate-mu-read-from-stream-stmt:end:
28255     # . restore registers
28256     5f/pop-to-edi
28257     5e/pop-to-esi
28258     59/pop-to-ecx
28259     58/pop-to-eax
28260     # . epilogue
28261     89/<- %esp 5/r32/ebp
28262     5d/pop-to-ebp
28263     c3/return
28264 
28265 translate-mu-write-to-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
28266     # . prologue
28267     55/push-ebp
28268     89/<- %ebp 4/r32/esp
28269     # . save registers
28270     50/push-eax
28271     51/push-ecx
28272     56/push-esi
28273     57/push-edi
28274     # esi = stmt
28275     8b/-> *(ebp+0xc) 6/r32/esi
28276     # var stream/ecx: (addr stmt-var) = stmt->inouts[0]
28277     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
28278     89/<- %ecx 0/r32/eax
28279     # var target/edi: (addr stmt-var) = stmt->inouts[1]
28280     (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
28281     89/<- %edi 0/r32/eax
28282     #
28283     (emit-indent *(ebp+8) *Curr-block-depth)
28284     (write-buffered *(ebp+8) "(write-to-stream")
28285     (emit-subx-call-operand *(ebp+8) %ecx)
28286     (flush *(ebp+8))
28287     (emit-subx-call-operand *(ebp+8) %edi)
28288     (flush *(ebp+8))
28289     (write-buffered *(ebp+8) Space)
28290     (flush *(ebp+8))
28291     (addr-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
28292     (write-int32-hex-buffered *(ebp+8) %eax)
28293     (write-buffered *(ebp+8) ")\n")
28294 $translate-mu-write-to-stream-stmt:end:
28295     # . restore registers
28296     5f/pop-to-edi
28297     5e/pop-to-esi
28298     59/pop-to-ecx
28299     58/pop-to-eax
28300     # . epilogue
28301     89/<- %esp 5/r32/ebp
28302     5d/pop-to-ebp
28303     c3/return
28304 
28305 addr-handle-array-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
28306     # . prologue
28307     55/push-ebp
28308     89/<- %ebp 4/r32/esp
28309     # var t/eax: (addr type-tree) = s->value->type
28310     8b/-> *(ebp+8) 0/r32/eax
28311     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
28312     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
28313     # TODO: check eax != 0
28314     # TODO: check !t->is-atom?
28315     # TODO: check t->left == addr
28316     # t = t->right
28317 $addr-handle-array-payload-size:skip-addr:
28318     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
28319     # TODO: check eax != 0
28320     # TODO: check !t->is-atom?
28321     # TODO: check t->left == handle
28322     # t = t->right
28323 $addr-handle-array-payload-size:skip-handle:
28324     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
28325     # TODO: check eax != 0
28326     # TODO: check !t->is-atom?
28327     # TODO: check t->left == array
28328     # t = t->right
28329 $addr-handle-array-payload-size:skip-array:
28330     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
28331     # TODO: check eax != 0
28332     # if !t->is-atom? t = t->left
28333     81 7/subop/compare *eax 0/imm32/false
28334     {
28335       75/jump-if-!= break/disp8
28336       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
28337     }
28338 $addr-handle-array-payload-size:compute-size:
28339     # TODO: check t->is-atom?
28340     # return size(t->value)
28341     (size-of-type-id-as-array-element *(eax+4))  # Type-tree-value => eax
28342 $addr-handle-array-payload-size:end:
28343     # . epilogue
28344     89/<- %esp 5/r32/ebp
28345     5d/pop-to-ebp
28346     c3/return
28347 
28348 addr-handle-stream-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
28349     # . prologue
28350     55/push-ebp
28351     89/<- %ebp 4/r32/esp
28352     # var t/eax: (addr type-tree) = s->value->type
28353     8b/-> *(ebp+8) 0/r32/eax
28354     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
28355     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
28356     # TODO: check eax != 0
28357     # TODO: check !t->is-atom?
28358     # TODO: check t->left == addr
28359     # t = t->right
28360 $addr-handle-stream-payload-size:skip-addr:
28361     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
28362     # TODO: check eax != 0
28363     # TODO: check !t->is-atom?
28364     # TODO: check t->left == handle
28365     # t = t->right
28366 $addr-handle-stream-payload-size:skip-handle:
28367     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
28368     # TODO: check eax != 0
28369     # TODO: check !t->is-atom?
28370     # TODO: check t->left == stream
28371     # t = t->right
28372 $addr-handle-stream-payload-size:skip-stream:
28373     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
28374     # TODO: check eax != 0
28375     # if !t->is-atom? t = t->left
28376     81 7/subop/compare *eax 0/imm32/false
28377     {
28378       75/jump-if-!= break/disp8
28379       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
28380     }
28381 $addr-handle-stream-payload-size:compute-size:
28382     # TODO: check t->is-atom?
28383     # return size(t->value)
28384     (size-of-type-id-as-array-element *(eax+4))  # Type-tree-value => eax
28385 $addr-handle-stream-payload-size:end:
28386     # . epilogue
28387     89/<- %esp 5/r32/ebp
28388     5d/pop-to-ebp
28389     c3/return
28390 
28391 power-of-2?:  # n: int, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: boolean
28392     # precondition: n is positive
28393     # . prologue
28394     55/push-ebp
28395     89/<- %ebp 4/r32/esp
28396     # eax = n
28397     8b/-> *(ebp+8) 0/r32/eax
28398     # if (n < 0) abort
28399     3d/compare-eax-with 0/imm32
28400     0f 8c/jump-if-< $power-of-2?:abort/disp32
28401     # var tmp/eax: int = n-1
28402     48/decrement-eax
28403     # var tmp2/eax: int = n & tmp
28404     23/and-> *(ebp+8) 0/r32/eax
28405     # return (tmp2 == 0)
28406     3d/compare-eax-and 0/imm32
28407     0f 94/set-byte-if-= %al
28408     81 4/subop/and %eax 0xff/imm32
28409 $power-of-2?:end:
28410     # . epilogue
28411     89/<- %esp 5/r32/ebp
28412     5d/pop-to-ebp
28413     c3/return
28414 
28415 $power-of-2?:abort:
28416     (write-buffered *(ebp+0xc) "power-of-2?: negative number\n")
28417     (flush *(ebp+0xc))
28418     (stop *(ebp+0x10) 1)
28419     # never gets here
28420 
28421 num-shift-rights:  # n: int -> result/eax: int
28422     # precondition: n is a positive power of 2
28423     # . prologue
28424     55/push-ebp
28425     89/<- %ebp 4/r32/esp
28426     # . save registers
28427     51/push-ecx
28428     # var curr/ecx: int = n
28429     8b/-> *(ebp+8) 1/r32/ecx
28430     # result = 0
28431     b8/copy-to-eax 0/imm32
28432     {
28433       # if (curr <= 1) break
28434       81 7/subop/compare %ecx 1/imm32
28435       7e/jump-if-<= break/disp8
28436       40/increment-eax
28437       c1/shift 5/subop/arithmetic-right %ecx 1/imm8
28438       eb/jump loop/disp8
28439     }
28440 $num-shift-rights:end:
28441     # . restore registers
28442     59/pop-to-ecx
28443     # . epilogue
28444     89/<- %esp 5/r32/ebp
28445     5d/pop-to-ebp
28446     c3/return
28447 
28448 mu-get-offset:  # stmt: (addr stmt) -> result/eax: int
28449     # . prologue
28450     55/push-ebp
28451     89/<- %ebp 4/r32/esp
28452     # var second-inout/eax: (addr stmt-var) = stmt->inouts->next
28453     8b/-> *(ebp+8) 0/r32/eax
28454     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
28455     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
28456     # var output-var/eax: (addr var) = second-inout->value
28457     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
28458 #?     (write-buffered Stderr "mu-get-offset: ")
28459 #?     (write-int32-hex-buffered Stderr %eax)
28460 #?     (write-buffered Stderr " name: ")
28461 #?     50/push-eax
28462 #?     (lookup *eax *(eax+4))  # Var-name
28463 #?     (write-buffered Stderr %eax)
28464 #?     58/pop-to-eax
28465 #?     (write-buffered Stderr Newline)
28466 #?     (flush Stderr)
28467     # return output-var->stack-offset
28468     8b/-> *(eax+0x14) 0/r32/eax  # Var-offset
28469 #?     (write-buffered Stderr "=> ")
28470 #?     (write-int32-hex-buffered Stderr %eax)
28471 #?     (write-buffered Stderr Newline)
28472 #?     (flush Stderr)
28473 $emit-get-offset:end:
28474     # . epilogue
28475     89/<- %esp 5/r32/ebp
28476     5d/pop-to-ebp
28477     c3/return
28478 
28479 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)
28480     # . prologue
28481     55/push-ebp
28482     89/<- %ebp 4/r32/esp
28483     # . save registers
28484     50/push-eax
28485     51/push-ecx
28486     56/push-esi
28487     # esi = block
28488     8b/-> *(ebp+0xc) 6/r32/esi
28489     # block->var->block-depth = *Curr-block-depth
28490     (lookup *(esi+0xc) *(esi+0x10))  # Block-var Block-var => eax
28491     8b/-> *Curr-block-depth 1/r32/ecx
28492     89/<- *(eax+0x10) 1/r32/ecx  # Var-block-depth
28493     # var stmts/eax: (addr list stmt) = lookup(block->statements)
28494     (lookup *(esi+4) *(esi+8))  # Block-stmts Block-stmts => eax
28495     #
28496     {
28497 $emit-subx-block:check-empty:
28498       3d/compare-eax-and 0/imm32
28499       0f 84/jump-if-= break/disp32
28500       (emit-indent *(ebp+8) *Curr-block-depth)
28501       (write-buffered *(ebp+8) "{\n")
28502       # var v/ecx: (addr var) = lookup(block->var)
28503       (lookup *(esi+0xc) *(esi+0x10))  # Block-var Block-var => eax
28504       89/<- %ecx 0/r32/eax
28505       #
28506       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
28507       (write-buffered *(ebp+8) %eax)
28508       (write-buffered *(ebp+8) ":loop:\n")
28509       ff 0/subop/increment *Curr-block-depth
28510       (push *(ebp+0x10) *(esi+0xc))  # Block-var
28511       (push *(ebp+0x10) *(esi+0x10))  # Block-var
28512       (push *(ebp+0x10) 0)  # false
28513       # emit block->statements
28514       (lookup *(esi+4) *(esi+8))  # Block-stmts Block-stmts => eax
28515       (emit-subx-stmt-list *(ebp+8) %eax *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
28516       (pop *(ebp+0x10))  # => eax
28517       (pop *(ebp+0x10))  # => eax
28518       (pop *(ebp+0x10))  # => eax
28519       ff 1/subop/decrement *Curr-block-depth
28520       (emit-indent *(ebp+8) *Curr-block-depth)
28521       (write-buffered *(ebp+8) "}\n")
28522       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
28523       (write-buffered *(ebp+8) %eax)
28524       (write-buffered *(ebp+8) ":break:\n")
28525     }
28526 $emit-subx-block:end:
28527     # . restore registers
28528     5e/pop-to-esi
28529     59/pop-to-ecx
28530     58/pop-to-eax
28531     # . epilogue
28532     89/<- %esp 5/r32/ebp
28533     5d/pop-to-ebp
28534     c3/return
28535 
28536 # Primitives supported
28537 # See mu_instructions for a summary of this linked-list data structure.
28538 #
28539 # For each operation, put variants with hard-coded registers before flexible ones.
28540 #
28541 # Unfortunately, our restrictions on addresses require that various fields in
28542 # primitives be handles, which complicates these definitions.
28543 #   - we need to insert dummy fields all over the place for fake alloc-ids
28544 #   - we can't use our syntax sugar of quoted literals for string fields
28545 #
28546 # Fake alloc-ids are needed because our type definitions up top require
28547 # handles but it's clearer to statically allocate these long-lived objects.
28548 # Fake alloc-ids are perfectly safe, but they can't be reclaimed.
28549 #
28550 # Every 'object' below starts with a fake alloc-id. It may also contain other
28551 # fake alloc-ids for various handle fields.
28552 #
28553 # I think of objects starting with a fake alloc-id as having type 'payload'.
28554 # It's not really intended to be created dynamically; for that use `allocate`
28555 # as usual.
28556 #
28557 # Idea for a notation to simplify such definitions:
28558 #   _Primitive-increment-eax:  # (payload primitive)
28559 #     0x11/alloc-id:fake:payload
28560 #     0x11 @(0x11 "increment")  # name
28561 #     0 0                       # inouts
28562 #     0x11 @(0x11/payload
28563 #            0x11 @(0x11/payload  # List-value
28564 #                   0 0             # Var-name
28565 #                   0x11 @(0x11     # Var-type
28566 #                          1/is-atom
28567 #                          1/value 0/unused   # Type-tree-left
28568 #                          0 0                # Type-tree-right
28569 #                         )
28570 #                   1               # block-depth
28571 #                   0               # stack-offset
28572 #                   0x11 @(0x11 "eax")  # Var-register
28573 #                  )
28574 #            0 0)                 # List-next
28575 #     ...
28576 #     _Primitive-increment-ecx/imm32/next
28577 #   ...
28578 # Awfully complex and non-obvious. But also clearly signals there's something
28579 # to learn here, so may be worth trying.
28580 #
28581 # '@' is just an initial thought. Punctuation used so far in Mu: () * % # / "
28582 #
28583 # For now we'll continue to just use comments and manually ensure they stay up
28584 # to date.
28585 == data
28586 Primitives:  # (addr primitive)
28587 # - increment/decrement
28588 _Primitive-increment-eax:  # (addr primitive)
28589     # var/eax <- increment => 40/increment-eax
28590     0x11/imm32/alloc-id:fake
28591     _string-increment/imm32/name
28592     0/imm32/no-inouts
28593     0/imm32/no-inouts
28594     0x11/imm32/alloc-id:fake
28595     Single-int-var-in-eax/imm32/outputs
28596     0x11/imm32/alloc-id:fake
28597     _string_40_increment_eax/imm32/subx-name
28598     0/imm32/no-rm32
28599     0/imm32/no-r32
28600     0/imm32/no-imm32
28601     0/imm32/no-imm8
28602     0/imm32/no-disp32
28603     0/imm32/no-xm32
28604     0/imm32/no-x32
28605     0x11/imm32/alloc-id:fake
28606     _Primitive-increment-ecx/imm32/next
28607 _Primitive-increment-ecx:  # (payload primitive)
28608     0x11/imm32/alloc-id:fake:payload
28609     # var/ecx <- increment => 41/increment-ecx
28610     0x11/imm32/alloc-id:fake
28611     _string-increment/imm32/name
28612     0/imm32/no-inouts
28613     0/imm32/no-inouts
28614     0x11/imm32/alloc-id:fake
28615     Single-int-var-in-ecx/imm32/outputs
28616     0x11/imm32/alloc-id:fake
28617     _string_41_increment_ecx/imm32/subx-name
28618     0/imm32/no-rm32
28619     0/imm32/no-r32
28620     0/imm32/no-imm32
28621     0/imm32/no-imm8
28622     0/imm32/no-disp32
28623     0/imm32/no-xm32
28624     0/imm32/no-x32
28625     0x11/imm32/alloc-id:fake
28626     _Primitive-increment-edx/imm32/next
28627 _Primitive-increment-edx:  # (payload primitive)
28628     0x11/imm32/alloc-id:fake:payload
28629     # var/edx <- increment => 42/increment-edx
28630     0x11/imm32/alloc-id:fake
28631     _string-increment/imm32/name
28632     0/imm32/no-inouts
28633     0/imm32/no-inouts
28634     0x11/imm32/alloc-id:fake
28635     Single-int-var-in-edx/imm32/outputs
28636     0x11/imm32/alloc-id:fake
28637     _string_42_increment_edx/imm32/subx-name
28638     0/imm32/no-rm32
28639     0/imm32/no-r32
28640     0/imm32/no-imm32
28641     0/imm32/no-imm8
28642     0/imm32/no-disp32
28643     0/imm32/no-xm32
28644     0/imm32/no-x32
28645     0x11/imm32/alloc-id:fake
28646     _Primitive-increment-ebx/imm32/next
28647 _Primitive-increment-ebx:  # (payload primitive)
28648     0x11/imm32/alloc-id:fake:payload
28649     # var/ebx <- increment => 43/increment-ebx
28650     0x11/imm32/alloc-id:fake
28651     _string-increment/imm32/name
28652     0/imm32/no-inouts
28653     0/imm32/no-inouts
28654     0x11/imm32/alloc-id:fake
28655     Single-int-var-in-ebx/imm32/outputs
28656     0x11/imm32/alloc-id:fake
28657     _string_43_increment_ebx/imm32/subx-name
28658     0/imm32/no-rm32
28659     0/imm32/no-r32
28660     0/imm32/no-imm32
28661     0/imm32/no-imm8
28662     0/imm32/no-disp32
28663     0/imm32/no-xm32
28664     0/imm32/no-x32
28665     0x11/imm32/alloc-id:fake
28666     _Primitive-increment-esi/imm32/next
28667 _Primitive-increment-esi:  # (payload primitive)
28668     0x11/imm32/alloc-id:fake:payload
28669     # var/esi <- increment => 46/increment-esi
28670     0x11/imm32/alloc-id:fake
28671     _string-increment/imm32/name
28672     0/imm32/no-inouts
28673     0/imm32/no-inouts
28674     0x11/imm32/alloc-id:fake
28675     Single-int-var-in-esi/imm32/outputs
28676     0x11/imm32/alloc-id:fake
28677     _string_46_increment_esi/imm32/subx-name
28678     0/imm32/no-rm32
28679     0/imm32/no-r32
28680     0/imm32/no-imm32
28681     0/imm32/no-imm8
28682     0/imm32/no-disp32
28683     0/imm32/no-xm32
28684     0/imm32/no-x32
28685     0x11/imm32/alloc-id:fake
28686     _Primitive-increment-edi/imm32/next
28687 _Primitive-increment-edi:  # (payload primitive)
28688     0x11/imm32/alloc-id:fake:payload
28689     # var/edi <- increment => 47/increment-edi
28690     0x11/imm32/alloc-id:fake
28691     _string-increment/imm32/name
28692     0/imm32/no-inouts
28693     0/imm32/no-inouts
28694     0x11/imm32/alloc-id:fake
28695     Single-int-var-in-edi/imm32/outputs
28696     0x11/imm32/alloc-id:fake
28697     _string_47_increment_edi/imm32/subx-name
28698     0/imm32/no-rm32
28699     0/imm32/no-r32
28700     0/imm32/no-imm32
28701     0/imm32/no-imm8
28702     0/imm32/no-disp32
28703     0/imm32/no-xm32
28704     0/imm32/no-x32
28705     0x11/imm32/alloc-id:fake
28706     _Primitive-decrement-eax/imm32/next
28707 _Primitive-decrement-eax:  # (payload primitive)
28708     0x11/imm32/alloc-id:fake:payload
28709     # var/eax <- decrement => 48/decrement-eax
28710     0x11/imm32/alloc-id:fake
28711     _string-decrement/imm32/name
28712     0/imm32/no-inouts
28713     0/imm32/no-inouts
28714     0x11/imm32/alloc-id:fake
28715     Single-int-var-in-eax/imm32/outputs
28716     0x11/imm32/alloc-id:fake
28717     _string_48_decrement_eax/imm32/subx-name
28718     0/imm32/no-rm32
28719     0/imm32/no-r32
28720     0/imm32/no-imm32
28721     0/imm32/no-imm8
28722     0/imm32/no-disp32
28723     0/imm32/no-xm32
28724     0/imm32/no-x32
28725     0x11/imm32/alloc-id:fake
28726     _Primitive-decrement-ecx/imm32/next
28727 _Primitive-decrement-ecx:  # (payload primitive)
28728     0x11/imm32/alloc-id:fake:payload
28729     # var/ecx <- decrement => 49/decrement-ecx
28730     0x11/imm32/alloc-id:fake
28731     _string-decrement/imm32/name
28732     0/imm32/no-inouts
28733     0/imm32/no-inouts
28734     0x11/imm32/alloc-id:fake
28735     Single-int-var-in-ecx/imm32/outputs
28736     0x11/imm32/alloc-id:fake
28737     _string_49_decrement_ecx/imm32/subx-name
28738     0/imm32/no-rm32
28739     0/imm32/no-r32
28740     0/imm32/no-imm32
28741     0/imm32/no-imm8
28742     0/imm32/no-disp32
28743     0/imm32/no-xm32
28744     0/imm32/no-x32
28745     0x11/imm32/alloc-id:fake
28746     _Primitive-decrement-edx/imm32/next
28747 _Primitive-decrement-edx:  # (payload primitive)
28748     0x11/imm32/alloc-id:fake:payload
28749     # var/edx <- decrement => 4a/decrement-edx
28750     0x11/imm32/alloc-id:fake
28751     _string-decrement/imm32/name
28752     0/imm32/no-inouts
28753     0/imm32/no-inouts
28754     0x11/imm32/alloc-id:fake
28755     Single-int-var-in-edx/imm32/outputs
28756     0x11/imm32/alloc-id:fake
28757     _string_4a_decrement_edx/imm32/subx-name
28758     0/imm32/no-rm32
28759     0/imm32/no-r32
28760     0/imm32/no-imm32
28761     0/imm32/no-imm8
28762     0/imm32/no-disp32
28763     0/imm32/no-xm32
28764     0/imm32/no-x32
28765     0x11/imm32/alloc-id:fake
28766     _Primitive-decrement-ebx/imm32/next
28767 _Primitive-decrement-ebx:  # (payload primitive)
28768     0x11/imm32/alloc-id:fake:payload
28769     # var/ebx <- decrement => 4b/decrement-ebx
28770     0x11/imm32/alloc-id:fake
28771     _string-decrement/imm32/name
28772     0/imm32/no-inouts
28773     0/imm32/no-inouts
28774     0x11/imm32/alloc-id:fake
28775     Single-int-var-in-ebx/imm32/outputs
28776     0x11/imm32/alloc-id:fake
28777     _string_4b_decrement_ebx/imm32/subx-name
28778     0/imm32/no-rm32
28779     0/imm32/no-r32
28780     0/imm32/no-imm32
28781     0/imm32/no-imm8
28782     0/imm32/no-disp32
28783     0/imm32/no-xm32
28784     0/imm32/no-x32
28785     0x11/imm32/alloc-id:fake
28786     _Primitive-decrement-esi/imm32/next
28787 _Primitive-decrement-esi:  # (payload primitive)
28788     0x11/imm32/alloc-id:fake:payload
28789     # var/esi <- decrement => 4e/decrement-esi
28790     0x11/imm32/alloc-id:fake
28791     _string-decrement/imm32/name
28792     0/imm32/no-inouts
28793     0/imm32/no-inouts
28794     0x11/imm32/alloc-id:fake
28795     Single-int-var-in-esi/imm32/outputs
28796     0x11/imm32/alloc-id:fake
28797     _string_4e_decrement_esi/imm32/subx-name
28798     0/imm32/no-rm32
28799     0/imm32/no-r32
28800     0/imm32/no-imm32
28801     0/imm32/no-imm8
28802     0/imm32/no-disp32
28803     0/imm32/no-xm32
28804     0/imm32/no-x32
28805     0x11/imm32/alloc-id:fake
28806     _Primitive-decrement-edi/imm32/next
28807 _Primitive-decrement-edi:  # (payload primitive)
28808     0x11/imm32/alloc-id:fake:payload
28809     # var/edi <- decrement => 4f/decrement-edi
28810     0x11/imm32/alloc-id:fake
28811     _string-decrement/imm32/name
28812     0/imm32/no-inouts
28813     0/imm32/no-inouts
28814     0x11/imm32/alloc-id:fake
28815     Single-int-var-in-edi/imm32/outputs
28816     0x11/imm32/alloc-id:fake
28817     _string_4f_decrement_edi/imm32/subx-name
28818     0/imm32/no-rm32
28819     0/imm32/no-r32
28820     0/imm32/no-imm32
28821     0/imm32/no-imm8
28822     0/imm32/no-disp32
28823     0/imm32/no-xm32
28824     0/imm32/no-x32
28825     0x11/imm32/alloc-id:fake
28826     _Primitive-increment-mem/imm32/next
28827 _Primitive-increment-mem:  # (payload primitive)
28828     0x11/imm32/alloc-id:fake:payload
28829     # increment var => ff 0/subop/increment *(ebp+__)
28830     0x11/imm32/alloc-id:fake
28831     _string-increment/imm32/name
28832     0x11/imm32/alloc-id:fake
28833     Single-int-var-in-mem/imm32/inouts
28834     0/imm32/no-outputs
28835     0/imm32/no-outputs
28836     0x11/imm32/alloc-id:fake
28837     _string_ff_subop_increment/imm32/subx-name
28838     1/imm32/rm32-is-first-inout
28839     0/imm32/no-r32
28840     0/imm32/no-imm32
28841     0/imm32/no-imm8
28842     0/imm32/no-disp32
28843     0/imm32/no-xm32
28844     0/imm32/no-x32
28845     0x11/imm32/alloc-id:fake
28846     _Primitive-increment-reg/imm32/next
28847 _Primitive-increment-reg:  # (payload primitive)
28848     0x11/imm32/alloc-id:fake:payload
28849     # var/reg <- increment => ff 0/subop/increment %__
28850     0x11/imm32/alloc-id:fake
28851     _string-increment/imm32/name
28852     0/imm32/no-inouts
28853     0/imm32/no-inouts
28854     0x11/imm32/alloc-id:fake
28855     Single-int-var-in-some-register/imm32/outputs
28856     0x11/imm32/alloc-id:fake
28857     _string_ff_subop_increment/imm32/subx-name
28858     3/imm32/rm32-is-first-output
28859     0/imm32/no-r32
28860     0/imm32/no-imm32
28861     0/imm32/no-imm8
28862     0/imm32/no-disp32
28863     0/imm32/no-xm32
28864     0/imm32/no-x32
28865     0x11/imm32/alloc-id:fake
28866     _Primitive-decrement-mem/imm32/next
28867 _Primitive-decrement-mem:  # (payload primitive)
28868     0x11/imm32/alloc-id:fake:payload
28869     # decrement var => ff 1/subop/decrement *(ebp+__)
28870     0x11/imm32/alloc-id:fake
28871     _string-decrement/imm32/name
28872     0x11/imm32/alloc-id:fake
28873     Single-int-var-in-mem/imm32/inouts
28874     0/imm32/no-outputs
28875     0/imm32/no-outputs
28876     0x11/imm32/alloc-id:fake
28877     _string_ff_subop_decrement/imm32/subx-name
28878     1/imm32/rm32-is-first-inout
28879     0/imm32/no-r32
28880     0/imm32/no-imm32
28881     0/imm32/no-imm8
28882     0/imm32/no-disp32
28883     0/imm32/no-xm32
28884     0/imm32/no-x32
28885     0x11/imm32/alloc-id:fake
28886     _Primitive-decrement-reg/imm32/next
28887 _Primitive-decrement-reg:  # (payload primitive)
28888     0x11/imm32/alloc-id:fake:payload
28889     # var/reg <- decrement => ff 1/subop/decrement %__
28890     0x11/imm32/alloc-id:fake
28891     _string-decrement/imm32/name
28892     0/imm32/no-inouts
28893     0/imm32/no-inouts
28894     0x11/imm32/alloc-id:fake
28895     Single-int-var-in-some-register/imm32/outputs
28896     0x11/imm32/alloc-id:fake
28897     _string_ff_subop_decrement/imm32/subx-name
28898     3/imm32/rm32-is-first-output
28899     0/imm32/no-r32
28900     0/imm32/no-imm32
28901     0/imm32/no-imm8
28902     0/imm32/no-disp32
28903     0/imm32/no-xm32
28904     0/imm32/no-x32
28905     0x11/imm32/alloc-id:fake
28906     _Primitive-add-to-eax/imm32/next
28907 # - add
28908 _Primitive-add-to-eax:  # (payload primitive)
28909     0x11/imm32/alloc-id:fake:payload
28910     # var/eax <- add lit => 05/add-to-eax lit/imm32
28911     0x11/imm32/alloc-id:fake
28912     _string-add/imm32/name
28913     0x11/imm32/alloc-id:fake
28914     Single-lit-var/imm32/inouts
28915     0x11/imm32/alloc-id:fake
28916     Single-int-var-in-eax/imm32/outputs
28917     0x11/imm32/alloc-id:fake
28918     _string_05_add_to_eax/imm32/subx-name
28919     0/imm32/no-rm32
28920     0/imm32/no-r32
28921     1/imm32/imm32-is-first-inout
28922     0/imm32/no-imm8
28923     0/imm32/no-disp32
28924     0/imm32/no-xm32
28925     0/imm32/no-x32
28926     0x11/imm32/alloc-id:fake
28927     _Primitive-add-reg-to-reg/imm32/next
28928 _Primitive-add-reg-to-reg:  # (payload primitive)
28929     0x11/imm32/alloc-id:fake:payload
28930     # var1/reg <- add var2/reg => 01/add-to var1/rm32 var2/r32
28931     0x11/imm32/alloc-id:fake
28932     _string-add/imm32/name
28933     0x11/imm32/alloc-id:fake
28934     Single-int-var-in-some-register/imm32/inouts
28935     0x11/imm32/alloc-id:fake
28936     Single-int-var-in-some-register/imm32/outputs
28937     0x11/imm32/alloc-id:fake
28938     _string_01_add_to/imm32/subx-name
28939     3/imm32/rm32-is-first-output
28940     1/imm32/r32-is-first-inout
28941     0/imm32/no-imm32
28942     0/imm32/no-imm8
28943     0/imm32/no-disp32
28944     0/imm32/no-xm32
28945     0/imm32/no-x32
28946     0x11/imm32/alloc-id:fake
28947     _Primitive-add-reg-to-mem/imm32/next
28948 _Primitive-add-reg-to-mem:  # (payload primitive)
28949     0x11/imm32/alloc-id:fake:payload
28950     # add-to var1 var2/reg => 01/add-to var1 var2/r32
28951     0x11/imm32/alloc-id:fake
28952     _string-add-to/imm32/name
28953     0x11/imm32/alloc-id:fake
28954     Two-args-int-stack-int-reg/imm32/inouts
28955     0/imm32/no-outputs
28956     0/imm32/no-outputs
28957     0x11/imm32/alloc-id:fake
28958     _string_01_add_to/imm32/subx-name
28959     1/imm32/rm32-is-first-inout
28960     2/imm32/r32-is-second-inout
28961     0/imm32/no-imm32
28962     0/imm32/no-imm8
28963     0/imm32/no-disp32
28964     0/imm32/no-xm32
28965     0/imm32/no-x32
28966     0x11/imm32/alloc-id:fake
28967     _Primitive-add-mem-to-reg/imm32/next
28968 _Primitive-add-mem-to-reg:  # (payload primitive)
28969     0x11/imm32/alloc-id:fake:payload
28970     # var1/reg <- add var2 => 03/add var2/rm32 var1/r32
28971     0x11/imm32/alloc-id:fake
28972     _string-add/imm32/name
28973     0x11/imm32/alloc-id:fake
28974     Single-int-var-in-mem/imm32/inouts
28975     0x11/imm32/alloc-id:fake
28976     Single-int-var-in-some-register/imm32/outputs
28977     0x11/imm32/alloc-id:fake
28978     _string_03_add/imm32/subx-name
28979     1/imm32/rm32-is-first-inout
28980     3/imm32/r32-is-first-output
28981     0/imm32/no-imm32
28982     0/imm32/no-imm8
28983     0/imm32/no-disp32
28984     0/imm32/no-xm32
28985     0/imm32/no-x32
28986     0x11/imm32/alloc-id:fake
28987     _Primitive-add-lit-to-reg/imm32/next
28988 _Primitive-add-lit-to-reg:  # (payload primitive)
28989     0x11/imm32/alloc-id:fake:payload
28990     # var1/reg <- add lit => 81 0/subop/add var1/rm32 lit/imm32
28991     0x11/imm32/alloc-id:fake
28992     _string-add/imm32/name
28993     0x11/imm32/alloc-id:fake
28994     Single-lit-var/imm32/inouts
28995     0x11/imm32/alloc-id:fake
28996     Single-int-var-in-some-register/imm32/outputs
28997     0x11/imm32/alloc-id:fake
28998     _string_81_subop_add/imm32/subx-name
28999     3/imm32/rm32-is-first-output
29000     0/imm32/no-r32
29001     1/imm32/imm32-is-first-inout
29002     0/imm32/no-imm8
29003     0/imm32/no-disp32
29004     0/imm32/no-xm32
29005     0/imm32/no-x32
29006     0x11/imm32/alloc-id:fake
29007     _Primitive-add-lit-to-mem/imm32/next
29008 _Primitive-add-lit-to-mem:  # (payload primitive)
29009     0x11/imm32/alloc-id:fake:payload
29010     # add-to var1, lit => 81 0/subop/add var1/rm32 lit/imm32
29011     0x11/imm32/alloc-id:fake
29012     _string-add-to/imm32/name
29013     0x11/imm32/alloc-id:fake
29014     Int-var-and-literal/imm32/inouts
29015     0/imm32/no-outputs
29016     0/imm32/no-outputs
29017     0x11/imm32/alloc-id:fake
29018     _string_81_subop_add/imm32/subx-name
29019     1/imm32/rm32-is-first-inout
29020     0/imm32/no-r32
29021     2/imm32/imm32-is-second-inout
29022     0/imm32/no-imm8
29023     0/imm32/no-disp32
29024     0/imm32/no-xm32
29025     0/imm32/no-x32
29026     0x11/imm32/alloc-id:fake
29027     _Primitive-subtract-from-eax/imm32/next
29028 # - subtract
29029 _Primitive-subtract-from-eax:  # (payload primitive)
29030     0x11/imm32/alloc-id:fake:payload
29031     # var/eax <- subtract lit => 2d/subtract-from-eax lit/imm32
29032     0x11/imm32/alloc-id:fake
29033     _string-subtract/imm32/name
29034     0x11/imm32/alloc-id:fake
29035     Single-lit-var/imm32/inouts
29036     0x11/imm32/alloc-id:fake
29037     Single-int-var-in-eax/imm32/outputs
29038     0x11/imm32/alloc-id:fake
29039     _string_2d_subtract_from_eax/imm32/subx-name
29040     0/imm32/no-rm32
29041     0/imm32/no-r32
29042     1/imm32/imm32-is-first-inout
29043     0/imm32/no-imm8
29044     0/imm32/no-disp32
29045     0/imm32/no-xm32
29046     0/imm32/no-x32
29047     0x11/imm32/alloc-id:fake
29048     _Primitive-subtract-reg-from-reg/imm32/next
29049 _Primitive-subtract-reg-from-reg:  # (payload primitive)
29050     0x11/imm32/alloc-id:fake:payload
29051     # var1/reg <- subtract var2/reg => 29/subtract-from var1/rm32 var2/r32
29052     0x11/imm32/alloc-id:fake
29053     _string-subtract/imm32/name
29054     0x11/imm32/alloc-id:fake
29055     Single-int-var-in-some-register/imm32/inouts
29056     0x11/imm32/alloc-id:fake
29057     Single-int-var-in-some-register/imm32/outputs
29058     0x11/imm32/alloc-id:fake
29059     _string_29_subtract_from/imm32/subx-name
29060     3/imm32/rm32-is-first-output
29061     1/imm32/r32-is-first-inout
29062     0/imm32/no-imm32
29063     0/imm32/no-imm8
29064     0/imm32/no-disp32
29065     0/imm32/no-xm32
29066     0/imm32/no-x32
29067     0x11/imm32/alloc-id:fake
29068     _Primitive-subtract-reg-from-mem/imm32/next
29069 _Primitive-subtract-reg-from-mem:  # (payload primitive)
29070     0x11/imm32/alloc-id:fake:payload
29071     # subtract-from var1 var2/reg => 29/subtract-from var1 var2/r32
29072     0x11/imm32/alloc-id:fake
29073     _string-subtract-from/imm32/name
29074     0x11/imm32/alloc-id:fake
29075     Two-args-int-stack-int-reg/imm32/inouts
29076     0/imm32/no-outputs
29077     0/imm32/no-outputs
29078     0x11/imm32/alloc-id:fake
29079     _string_29_subtract_from/imm32/subx-name
29080     1/imm32/rm32-is-first-inout
29081     2/imm32/r32-is-second-inout
29082     0/imm32/no-imm32
29083     0/imm32/no-imm8
29084     0/imm32/no-disp32
29085     0/imm32/no-xm32
29086     0/imm32/no-x32
29087     0x11/imm32/alloc-id:fake
29088     _Primitive-subtract-mem-from-reg/imm32/next
29089 _Primitive-subtract-mem-from-reg:  # (payload primitive)
29090     0x11/imm32/alloc-id:fake:payload
29091     # var1/reg <- subtract var2 => 2b/subtract var2/rm32 var1/r32
29092     0x11/imm32/alloc-id:fake
29093     _string-subtract/imm32/name
29094     0x11/imm32/alloc-id:fake
29095     Single-int-var-in-mem/imm32/inouts
29096     0x11/imm32/alloc-id:fake
29097     Single-int-var-in-some-register/imm32/outputs
29098     0x11/imm32/alloc-id:fake
29099     _string_2b_subtract/imm32/subx-name
29100     1/imm32/rm32-is-first-inout
29101     3/imm32/r32-is-first-output
29102     0/imm32/no-imm32
29103     0/imm32/no-imm8
29104     0/imm32/no-disp32
29105     0/imm32/no-xm32
29106     0/imm32/no-x32
29107     0x11/imm32/alloc-id:fake
29108     _Primitive-subtract-lit-from-reg/imm32/next
29109 _Primitive-subtract-lit-from-reg:  # (payload primitive)
29110     0x11/imm32/alloc-id:fake:payload
29111     # var1/reg <- subtract lit => 81 5/subop/subtract var1/rm32 lit/imm32
29112     0x11/imm32/alloc-id:fake
29113     _string-subtract/imm32/name
29114     0x11/imm32/alloc-id:fake
29115     Single-lit-var/imm32/inouts
29116     0x11/imm32/alloc-id:fake
29117     Single-int-var-in-some-register/imm32/outputs
29118     0x11/imm32/alloc-id:fake
29119     _string_81_subop_subtract/imm32/subx-name
29120     3/imm32/rm32-is-first-output
29121     0/imm32/no-r32
29122     1/imm32/imm32-is-first-inout
29123     0/imm32/no-imm8
29124     0/imm32/no-disp32
29125     0/imm32/no-xm32
29126     0/imm32/no-x32
29127     0x11/imm32/alloc-id:fake
29128     _Primitive-subtract-lit-from-mem/imm32/next
29129 _Primitive-subtract-lit-from-mem:  # (payload primitive)
29130     0x11/imm32/alloc-id:fake:payload
29131     # subtract-from var1, lit => 81 5/subop/subtract var1/rm32 lit/imm32
29132     0x11/imm32/alloc-id:fake
29133     _string-subtract-from/imm32/name
29134     0x11/imm32/alloc-id:fake
29135     Int-var-and-literal/imm32/inouts
29136     0/imm32/no-outputs
29137     0/imm32/no-outputs
29138     0x11/imm32/alloc-id:fake
29139     _string_81_subop_subtract/imm32/subx-name
29140     1/imm32/rm32-is-first-inout
29141     0/imm32/no-r32
29142     2/imm32/imm32-is-second-inout
29143     0/imm32/no-imm8
29144     0/imm32/no-disp32
29145     0/imm32/no-xm32
29146     0/imm32/no-x32
29147     0x11/imm32/alloc-id:fake
29148     _Primitive-and-with-eax/imm32/next
29149 # - and
29150 _Primitive-and-with-eax:  # (payload primitive)
29151     0x11/imm32/alloc-id:fake:payload
29152     # var/eax <- and lit => 25/and-with-eax lit/imm32
29153     0x11/imm32/alloc-id:fake
29154     _string-and/imm32/name
29155     0x11/imm32/alloc-id:fake
29156     Single-lit-var/imm32/inouts
29157     0x11/imm32/alloc-id:fake
29158     Single-int-var-in-eax/imm32/outputs
29159     0x11/imm32/alloc-id:fake
29160     _string_25_and_with_eax/imm32/subx-name
29161     0/imm32/no-rm32
29162     0/imm32/no-r32
29163     1/imm32/imm32-is-first-inout
29164     0/imm32/no-imm8
29165     0/imm32/no-disp32
29166     0/imm32/no-xm32
29167     0/imm32/no-x32
29168     0x11/imm32/alloc-id:fake
29169     _Primitive-and-reg-with-reg/imm32/next
29170 _Primitive-and-reg-with-reg:  # (payload primitive)
29171     0x11/imm32/alloc-id:fake:payload
29172     # var1/reg <- and var2/reg => 21/and-with var1/rm32 var2/r32
29173     0x11/imm32/alloc-id:fake
29174     _string-and/imm32/name
29175     0x11/imm32/alloc-id:fake
29176     Single-int-var-in-some-register/imm32/inouts
29177     0x11/imm32/alloc-id:fake
29178     Single-int-var-in-some-register/imm32/outputs
29179     0x11/imm32/alloc-id:fake
29180     _string_21_and_with/imm32/subx-name
29181     3/imm32/rm32-is-first-output
29182     1/imm32/r32-is-first-inout
29183     0/imm32/no-imm32
29184     0/imm32/no-imm8
29185     0/imm32/no-disp32
29186     0/imm32/no-xm32
29187     0/imm32/no-x32
29188     0x11/imm32/alloc-id:fake
29189     _Primitive-and-reg-with-mem/imm32/next
29190 _Primitive-and-reg-with-mem:  # (payload primitive)
29191     0x11/imm32/alloc-id:fake:payload
29192     # and-with var1 var2/reg => 21/and-with var1 var2/r32
29193     0x11/imm32/alloc-id:fake
29194     _string-and-with/imm32/name
29195     0x11/imm32/alloc-id:fake
29196     Two-args-int-stack-int-reg/imm32/inouts
29197     0/imm32/no-outputs
29198     0/imm32/no-outputs
29199     0x11/imm32/alloc-id:fake
29200     _string_21_and_with/imm32/subx-name
29201     1/imm32/rm32-is-first-inout
29202     2/imm32/r32-is-second-inout
29203     0/imm32/no-imm32
29204     0/imm32/no-imm8
29205     0/imm32/no-disp32
29206     0/imm32/no-xm32
29207     0/imm32/no-x32
29208     0x11/imm32/alloc-id:fake
29209     _Primitive-and-mem-with-reg/imm32/next
29210 _Primitive-and-mem-with-reg:  # (payload primitive)
29211     0x11/imm32/alloc-id:fake:payload
29212     # var1/reg <- and var2 => 23/and var2/rm32 var1/r32
29213     0x11/imm32/alloc-id:fake
29214     _string-and/imm32/name
29215     0x11/imm32/alloc-id:fake
29216     Single-int-var-in-mem/imm32/inouts
29217     0x11/imm32/alloc-id:fake
29218     Single-int-var-in-some-register/imm32/outputs
29219     0x11/imm32/alloc-id:fake
29220     _string_23_and/imm32/subx-name
29221     1/imm32/rm32-is-first-inout
29222     3/imm32/r32-is-first-output
29223     0/imm32/no-imm32
29224     0/imm32/no-imm8
29225     0/imm32/no-disp32
29226     0/imm32/no-xm32
29227     0/imm32/no-x32
29228     0x11/imm32/alloc-id:fake
29229     _Primitive-and-lit-with-reg/imm32/next
29230 _Primitive-and-lit-with-reg:  # (payload primitive)
29231     0x11/imm32/alloc-id:fake:payload
29232     # var1/reg <- and lit => 81 4/subop/and var1/rm32 lit/imm32
29233     0x11/imm32/alloc-id:fake
29234     _string-and/imm32/name
29235     0x11/imm32/alloc-id:fake
29236     Single-lit-var/imm32/inouts
29237     0x11/imm32/alloc-id:fake
29238     Single-int-var-in-some-register/imm32/outputs
29239     0x11/imm32/alloc-id:fake
29240     _string_81_subop_and/imm32/subx-name
29241     3/imm32/rm32-is-first-output
29242     0/imm32/no-r32
29243     1/imm32/imm32-is-first-inout
29244     0/imm32/no-imm8
29245     0/imm32/no-disp32
29246     0/imm32/no-xm32
29247     0/imm32/no-x32
29248     0x11/imm32/alloc-id:fake
29249     _Primitive-and-lit-with-mem/imm32/next
29250 _Primitive-and-lit-with-mem:  # (payload primitive)
29251     0x11/imm32/alloc-id:fake:payload
29252     # and-with var1, lit => 81 4/subop/and var1/rm32 lit/imm32
29253     0x11/imm32/alloc-id:fake
29254     _string-and-with/imm32/name
29255     0x11/imm32/alloc-id:fake
29256     Int-var-and-literal/imm32/inouts
29257     0/imm32/no-outputs
29258     0/imm32/no-outputs
29259     0x11/imm32/alloc-id:fake
29260     _string_81_subop_and/imm32/subx-name
29261     1/imm32/rm32-is-first-inout
29262     0/imm32/no-r32
29263     2/imm32/imm32-is-second-inout
29264     0/imm32/no-imm8
29265     0/imm32/no-disp32
29266     0/imm32/no-xm32
29267     0/imm32/no-x32
29268     0x11/imm32/alloc-id:fake
29269     _Primitive-or-with-eax/imm32/next
29270 # - or
29271 _Primitive-or-with-eax:  # (payload primitive)
29272     0x11/imm32/alloc-id:fake:payload
29273     # var/eax <- or lit => 0d/or-with-eax lit/imm32
29274     0x11/imm32/alloc-id:fake
29275     _string-or/imm32/name
29276     0x11/imm32/alloc-id:fake
29277     Single-lit-var/imm32/inouts
29278     0x11/imm32/alloc-id:fake
29279     Single-int-var-in-eax/imm32/outputs
29280     0x11/imm32/alloc-id:fake
29281     _string_0d_or_with_eax/imm32/subx-name
29282     0/imm32/no-rm32
29283     0/imm32/no-r32
29284     1/imm32/imm32-is-first-inout
29285     0/imm32/no-imm8
29286     0/imm32/no-disp32
29287     0/imm32/no-xm32
29288     0/imm32/no-x32
29289     0x11/imm32/alloc-id:fake
29290     _Primitive-or-reg-with-reg/imm32/next
29291 _Primitive-or-reg-with-reg:  # (payload primitive)
29292     0x11/imm32/alloc-id:fake:payload
29293     # var1/reg <- or var2/reg => 09/or-with var1/rm32 var2/r32
29294     0x11/imm32/alloc-id:fake
29295     _string-or/imm32/name
29296     0x11/imm32/alloc-id:fake
29297     Single-int-var-in-some-register/imm32/inouts
29298     0x11/imm32/alloc-id:fake
29299     Single-int-var-in-some-register/imm32/outputs
29300     0x11/imm32/alloc-id:fake
29301     _string_09_or_with/imm32/subx-name
29302     3/imm32/rm32-is-first-output
29303     1/imm32/r32-is-first-inout
29304     0/imm32/no-imm32
29305     0/imm32/no-imm8
29306     0/imm32/no-disp32
29307     0/imm32/no-xm32
29308     0/imm32/no-x32
29309     0x11/imm32/alloc-id:fake
29310     _Primitive-or-reg-with-mem/imm32/next
29311 _Primitive-or-reg-with-mem:  # (payload primitive)
29312     0x11/imm32/alloc-id:fake:payload
29313     # or-with var1 var2/reg => 09/or-with var1 var2/r32
29314     0x11/imm32/alloc-id:fake
29315     _string-or-with/imm32/name
29316     0x11/imm32/alloc-id:fake
29317     Two-args-int-stack-int-reg/imm32/inouts
29318     0/imm32/no-outputs
29319     0/imm32/no-outputs
29320     0x11/imm32/alloc-id:fake
29321     _string_09_or_with/imm32/subx-name
29322     1/imm32/rm32-is-first-inout
29323     2/imm32/r32-is-second-inout
29324     0/imm32/no-imm32
29325     0/imm32/no-imm8
29326     0/imm32/no-disp32
29327     0/imm32/no-xm32
29328     0/imm32/no-x32
29329     0x11/imm32/alloc-id:fake
29330     _Primitive-or-mem-with-reg/imm32/next
29331 _Primitive-or-mem-with-reg:  # (payload primitive)
29332     0x11/imm32/alloc-id:fake:payload
29333     # var1/reg <- or var2 => 0b/or var2/rm32 var1/r32
29334     0x11/imm32/alloc-id:fake
29335     _string-or/imm32/name
29336     0x11/imm32/alloc-id:fake
29337     Single-int-var-in-mem/imm32/inouts
29338     0x11/imm32/alloc-id:fake
29339     Single-int-var-in-some-register/imm32/outputs
29340     0x11/imm32/alloc-id:fake
29341     _string_0b_or/imm32/subx-name
29342     1/imm32/rm32-is-first-inout
29343     3/imm32/r32-is-first-output
29344     0/imm32/no-imm32
29345     0/imm32/no-imm8
29346     0/imm32/no-disp32
29347     0/imm32/no-xm32
29348     0/imm32/no-x32
29349     0x11/imm32/alloc-id:fake
29350     _Primitive-or-lit-with-reg/imm32/next
29351 _Primitive-or-lit-with-reg:  # (payload primitive)
29352     0x11/imm32/alloc-id:fake:payload
29353     # var1/reg <- or lit => 81 1/subop/or var1/rm32 lit/imm32
29354     0x11/imm32/alloc-id:fake
29355     _string-or/imm32/name
29356     0x11/imm32/alloc-id:fake
29357     Single-lit-var/imm32/inouts
29358     0x11/imm32/alloc-id:fake
29359     Single-int-var-in-some-register/imm32/outputs
29360     0x11/imm32/alloc-id:fake
29361     _string_81_subop_or/imm32/subx-name
29362     3/imm32/rm32-is-first-output
29363     0/imm32/no-r32
29364     1/imm32/imm32-is-first-inout
29365     0/imm32/no-imm8
29366     0/imm32/no-disp32
29367     0/imm32/no-xm32
29368     0/imm32/no-x32
29369     0x11/imm32/alloc-id:fake
29370     _Primitive-or-lit-with-mem/imm32/next
29371 _Primitive-or-lit-with-mem:  # (payload primitive)
29372     0x11/imm32/alloc-id:fake:payload
29373     # or-with var1, lit => 81 1/subop/or var1/rm32 lit/imm32
29374     0x11/imm32/alloc-id:fake
29375     _string-or-with/imm32/name
29376     0x11/imm32/alloc-id:fake
29377     Int-var-and-literal/imm32/inouts
29378     0/imm32/no-outputs
29379     0/imm32/no-outputs
29380     0x11/imm32/alloc-id:fake
29381     _string_81_subop_or/imm32/subx-name
29382     1/imm32/rm32-is-first-inout
29383     0/imm32/no-r32
29384     2/imm32/imm32-is-second-inout
29385     0/imm32/no-imm8
29386     0/imm32/no-disp32
29387     0/imm32/no-xm32
29388     0/imm32/no-x32
29389     0x11/imm32/alloc-id:fake
29390     _Primitive-xor-with-eax/imm32/next
29391 # - xor
29392 _Primitive-xor-with-eax:  # (payload primitive)
29393     0x11/imm32/alloc-id:fake:payload
29394     # var/eax <- xor lit => 35/xor-with-eax lit/imm32
29395     0x11/imm32/alloc-id:fake
29396     _string-xor/imm32/name
29397     0x11/imm32/alloc-id:fake
29398     Single-lit-var/imm32/inouts
29399     0x11/imm32/alloc-id:fake
29400     Single-int-var-in-eax/imm32/outputs
29401     0x11/imm32/alloc-id:fake
29402     _string_35_xor_with_eax/imm32/subx-name
29403     0/imm32/no-rm32
29404     0/imm32/no-r32
29405     1/imm32/imm32-is-first-inout
29406     0/imm32/no-imm8
29407     0/imm32/no-disp32
29408     0/imm32/no-xm32
29409     0/imm32/no-x32
29410     0x11/imm32/alloc-id:fake
29411     _Primitive-xor-reg-with-reg/imm32/next
29412 _Primitive-xor-reg-with-reg:  # (payload primitive)
29413     0x11/imm32/alloc-id:fake:payload
29414     # var1/reg <- xor var2/reg => 31/xor-with var1/rm32 var2/r32
29415     0x11/imm32/alloc-id:fake
29416     _string-xor/imm32/name
29417     0x11/imm32/alloc-id:fake
29418     Single-int-var-in-some-register/imm32/inouts
29419     0x11/imm32/alloc-id:fake
29420     Single-int-var-in-some-register/imm32/outputs
29421     0x11/imm32/alloc-id:fake
29422     _string_31_xor_with/imm32/subx-name
29423     3/imm32/rm32-is-first-output
29424     1/imm32/r32-is-first-inout
29425     0/imm32/no-imm32
29426     0/imm32/no-imm8
29427     0/imm32/no-disp32
29428     0/imm32/no-xm32
29429     0/imm32/no-x32
29430     0x11/imm32/alloc-id:fake
29431     _Primitive-xor-reg-with-mem/imm32/next
29432 _Primitive-xor-reg-with-mem:  # (payload primitive)
29433     0x11/imm32/alloc-id:fake:payload
29434     # xor-with var1 var2/reg => 31/xor-with var1 var2/r32
29435     0x11/imm32/alloc-id:fake
29436     _string-xor-with/imm32/name
29437     0x11/imm32/alloc-id:fake
29438     Two-args-int-stack-int-reg/imm32/inouts
29439     0/imm32/no-outputs
29440     0/imm32/no-outputs
29441     0x11/imm32/alloc-id:fake
29442     _string_31_xor_with/imm32/subx-name
29443     1/imm32/rm32-is-first-inout
29444     2/imm32/r32-is-second-inout
29445     0/imm32/no-imm32
29446     0/imm32/no-imm8
29447     0/imm32/no-disp32
29448     0/imm32/no-xm32
29449     0/imm32/no-x32
29450     0x11/imm32/alloc-id:fake
29451     _Primitive-xor-mem-with-reg/imm32/next
29452 _Primitive-xor-mem-with-reg:  # (payload primitive)
29453     0x11/imm32/alloc-id:fake:payload
29454     # var1/reg <- xor var2 => 33/xor var2/rm32 var1/r32
29455     0x11/imm32/alloc-id:fake
29456     _string-xor/imm32/name
29457     0x11/imm32/alloc-id:fake
29458     Single-int-var-in-mem/imm32/inouts
29459     0x11/imm32/alloc-id:fake
29460     Single-int-var-in-some-register/imm32/outputs
29461     0x11/imm32/alloc-id:fake
29462     _string_33_xor/imm32/subx-name
29463     1/imm32/rm32-is-first-inout
29464     3/imm32/r32-is-first-output
29465     0/imm32/no-imm32
29466     0/imm32/no-imm8
29467     0/imm32/no-disp32
29468     0/imm32/no-xm32
29469     0/imm32/no-x32
29470     0x11/imm32/alloc-id:fake
29471     _Primitive-xor-lit-with-reg/imm32/next
29472 _Primitive-xor-lit-with-reg:  # (payload primitive)
29473     0x11/imm32/alloc-id:fake:payload
29474     # var1/reg <- xor lit => 81 6/subop/xor var1/rm32 lit/imm32
29475     0x11/imm32/alloc-id:fake
29476     _string-xor/imm32/name
29477     0x11/imm32/alloc-id:fake
29478     Single-lit-var/imm32/inouts
29479     0x11/imm32/alloc-id:fake
29480     Single-int-var-in-some-register/imm32/outputs
29481     0x11/imm32/alloc-id:fake
29482     _string_81_subop_xor/imm32/subx-name
29483     3/imm32/rm32-is-first-output
29484     0/imm32/no-r32
29485     1/imm32/imm32-is-first-inout
29486     0/imm32/no-imm8
29487     0/imm32/no-disp32
29488     0/imm32/no-xm32
29489     0/imm32/no-x32
29490     0x11/imm32/alloc-id:fake
29491     _Primitive-xor-lit-with-mem/imm32/next
29492 _Primitive-xor-lit-with-mem:  # (payload primitive)
29493     0x11/imm32/alloc-id:fake:payload
29494     # xor-with var1, lit => 81 6/subop/xor var1/rm32 lit/imm32
29495     0x11/imm32/alloc-id:fake
29496     _string-xor-with/imm32/name
29497     0x11/imm32/alloc-id:fake
29498     Int-var-and-literal/imm32/inouts
29499     0/imm32/no-outputs
29500     0/imm32/no-outputs
29501     0x11/imm32/alloc-id:fake
29502     _string_81_subop_xor/imm32/subx-name
29503     1/imm32/rm32-is-first-inout
29504     0/imm32/no-r32
29505     2/imm32/imm32-is-second-inout
29506     0/imm32/no-imm8
29507     0/imm32/no-disp32
29508     0/imm32/no-xm32
29509     0/imm32/no-x32
29510     0x11/imm32/alloc-id:fake
29511     _Primitive-shift-reg-left-by-lit/imm32/next
29512 _Primitive-shift-reg-left-by-lit:  # (payload primitive)
29513     0x11/imm32/alloc-id:fake:payload
29514     # var1/reg <- shift-left lit => c1/shift 4/subop/left var1/rm32 lit/imm32
29515     0x11/imm32/alloc-id:fake
29516     _string-shift-left/imm32/name
29517     0x11/imm32/alloc-id:fake
29518     Single-lit-var/imm32/inouts
29519     0x11/imm32/alloc-id:fake
29520     Single-int-var-in-some-register/imm32/outputs
29521     0x11/imm32/alloc-id:fake
29522     _string_c1_subop_shift_left/imm32/subx-name
29523     3/imm32/rm32-is-first-output
29524     0/imm32/no-r32
29525     0/imm32/no-imm32
29526     1/imm32/imm8-is-first-inout
29527     0/imm32/no-disp32
29528     0/imm32/no-xm32
29529     0/imm32/no-x32
29530     0x11/imm32/alloc-id:fake
29531     _Primitive-shift-reg-right-by-lit/imm32/next
29532 _Primitive-shift-reg-right-by-lit:  # (payload primitive)
29533     0x11/imm32/alloc-id:fake:payload
29534     # var1/reg <- shift-right lit => c1/shift 5/subop/right var1/rm32 lit/imm32
29535     0x11/imm32/alloc-id:fake
29536     _string-shift-right/imm32/name
29537     0x11/imm32/alloc-id:fake
29538     Single-lit-var/imm32/inouts
29539     0x11/imm32/alloc-id:fake
29540     Single-int-var-in-some-register/imm32/outputs
29541     0x11/imm32/alloc-id:fake
29542     _string_c1_subop_shift_right_padding_zeroes/imm32/subx-name
29543     3/imm32/rm32-is-first-output
29544     0/imm32/no-r32
29545     0/imm32/no-imm32
29546     1/imm32/imm8-is-first-inout
29547     0/imm32/no-disp32
29548     0/imm32/no-xm32
29549     0/imm32/no-x32
29550     0x11/imm32/alloc-id:fake
29551     _Primitive-shift-reg-right-signed-by-lit/imm32/next
29552 _Primitive-shift-reg-right-signed-by-lit:  # (payload primitive)
29553     0x11/imm32/alloc-id:fake:payload
29554     # var1/reg <- shift-right-signed lit => c1/shift 7/subop/right-preserving-sign var1/rm32 lit/imm32
29555     0x11/imm32/alloc-id:fake
29556     _string-shift-right-signed/imm32/name
29557     0x11/imm32/alloc-id:fake
29558     Single-lit-var/imm32/inouts
29559     0x11/imm32/alloc-id:fake
29560     Single-int-var-in-some-register/imm32/outputs
29561     0x11/imm32/alloc-id:fake
29562     _string_c1_subop_shift_right_preserving_sign/imm32/subx-name
29563     3/imm32/rm32-is-first-output
29564     0/imm32/no-r32
29565     0/imm32/no-imm32
29566     1/imm32/imm8-is-first-inout
29567     0/imm32/no-disp32
29568     0/imm32/no-xm32
29569     0/imm32/no-x32
29570     0x11/imm32/alloc-id:fake
29571     _Primitive-shift-mem-left-by-lit/imm32/next
29572 _Primitive-shift-mem-left-by-lit:  # (payload primitive)
29573     0x11/imm32/alloc-id:fake:payload
29574     # shift-left var1, lit => c1/shift 4/subop/left var1/rm32 lit/imm32
29575     0x11/imm32/alloc-id:fake
29576     _string-shift-left/imm32/name
29577     0x11/imm32/alloc-id:fake
29578     Int-var-and-literal/imm32/inouts
29579     0/imm32/no-outputs
29580     0/imm32/no-outputs
29581     0x11/imm32/alloc-id:fake
29582     _string_c1_subop_shift_left/imm32/subx-name
29583     1/imm32/rm32-is-first-inout
29584     0/imm32/no-r32
29585     0/imm32/no-imm32
29586     2/imm32/imm8-is-second-inout
29587     0/imm32/no-disp32
29588     0/imm32/no-xm32
29589     0/imm32/no-x32
29590     0x11/imm32/alloc-id:fake
29591     _Primitive-shift-mem-right-by-lit/imm32/next
29592 _Primitive-shift-mem-right-by-lit:  # (payload primitive)
29593     0x11/imm32/alloc-id:fake:payload
29594     # shift-right var1, lit => c1/shift 5/subop/right var1/rm32 lit/imm32
29595     0x11/imm32/alloc-id:fake
29596     _string-shift-right/imm32/name
29597     0x11/imm32/alloc-id:fake
29598     Int-var-and-literal/imm32/inouts
29599     0/imm32/no-outputs
29600     0/imm32/no-outputs
29601     0x11/imm32/alloc-id:fake
29602     _string_c1_subop_shift_right_padding_zeroes/imm32/subx-name
29603     1/imm32/rm32-is-first-inout
29604     0/imm32/no-r32
29605     0/imm32/no-imm32
29606     2/imm32/imm8-is-second-inout
29607     0/imm32/no-disp32
29608     0/imm32/no-xm32
29609     0/imm32/no-x32
29610     0x11/imm32/alloc-id:fake
29611     _Primitive-shift-mem-right-signed-by-lit/imm32/next
29612 _Primitive-shift-mem-right-signed-by-lit:  # (payload primitive)
29613     0x11/imm32/alloc-id:fake:payload
29614     # shift-right-signed var1, lit => c1/shift 7/subop/right-preserving-sign var1/rm32 lit/imm32
29615     0x11/imm32/alloc-id:fake
29616     _string-shift-right-signed/imm32/name
29617     0x11/imm32/alloc-id:fake
29618     Int-var-and-literal/imm32/inouts
29619     0/imm32/no-outputs
29620     0/imm32/no-outputs
29621     0x11/imm32/alloc-id:fake
29622     _string_c1_subop_shift_right_preserving_sign/imm32/subx-name
29623     1/imm32/rm32-is-first-inout
29624     0/imm32/no-r32
29625     0/imm32/no-imm32
29626     2/imm32/imm8-is-second-inout
29627     0/imm32/no-disp32
29628     0/imm32/no-xm32
29629     0/imm32/no-x32
29630     0x11/imm32/alloc-id:fake
29631     _Primitive-copy-to-eax/imm32/next
29632 # - copy
29633 _Primitive-copy-to-eax:  # (payload primitive)
29634     0x11/imm32/alloc-id:fake:payload
29635     # var/eax <- copy lit => b8/copy-to-eax lit/imm32
29636     0x11/imm32/alloc-id:fake
29637     _string-copy/imm32/name
29638     0x11/imm32/alloc-id:fake
29639     Single-lit-var/imm32/inouts
29640     0x11/imm32/alloc-id:fake
29641     Single-int-var-in-eax/imm32/outputs
29642     0x11/imm32/alloc-id:fake
29643     _string_b8_copy_to_eax/imm32/subx-name
29644     0/imm32/no-rm32
29645     0/imm32/no-r32
29646     1/imm32/imm32-is-first-inout
29647     0/imm32/no-imm8
29648     0/imm32/no-disp32
29649     0/imm32/no-xm32
29650     0/imm32/no-x32
29651     0x11/imm32/alloc-id:fake
29652     _Primitive-copy-to-ecx/imm32/next
29653 _Primitive-copy-to-ecx:  # (payload primitive)
29654     0x11/imm32/alloc-id:fake:payload
29655     # var/ecx <- copy lit => b9/copy-to-ecx lit/imm32
29656     0x11/imm32/alloc-id:fake
29657     _string-copy/imm32/name
29658     0x11/imm32/alloc-id:fake
29659     Single-lit-var/imm32/inouts
29660     0x11/imm32/alloc-id:fake
29661     Single-int-var-in-ecx/imm32/outputs
29662     0x11/imm32/alloc-id:fake
29663     _string_b9_copy_to_ecx/imm32/subx-name
29664     0/imm32/no-rm32
29665     0/imm32/no-r32
29666     1/imm32/imm32-is-first-inout
29667     0/imm32/no-imm8
29668     0/imm32/no-disp32
29669     0/imm32/no-xm32
29670     0/imm32/no-x32
29671     0x11/imm32/alloc-id:fake
29672     _Primitive-copy-to-edx/imm32/next
29673 _Primitive-copy-to-edx:  # (payload primitive)
29674     0x11/imm32/alloc-id:fake:payload
29675     # var/edx <- copy lit => ba/copy-to-edx lit/imm32
29676     0x11/imm32/alloc-id:fake
29677     _string-copy/imm32/name
29678     0x11/imm32/alloc-id:fake
29679     Single-lit-var/imm32/inouts
29680     0x11/imm32/alloc-id:fake
29681     Single-int-var-in-edx/imm32/outputs
29682     0x11/imm32/alloc-id:fake
29683     _string_ba_copy_to_edx/imm32/subx-name
29684     0/imm32/no-rm32
29685     0/imm32/no-r32
29686     1/imm32/imm32-is-first-inout
29687     0/imm32/no-imm8
29688     0/imm32/no-disp32
29689     0/imm32/no-xm32
29690     0/imm32/no-x32
29691     0x11/imm32/alloc-id:fake
29692     _Primitive-copy-to-ebx/imm32/next
29693 _Primitive-copy-to-ebx:  # (payload primitive)
29694     0x11/imm32/alloc-id:fake:payload
29695     # var/ebx <- copy lit => bb/copy-to-ebx lit/imm32
29696     0x11/imm32/alloc-id:fake
29697     _string-copy/imm32/name
29698     0x11/imm32/alloc-id:fake
29699     Single-lit-var/imm32/inouts
29700     0x11/imm32/alloc-id:fake
29701     Single-int-var-in-ebx/imm32/outputs
29702     0x11/imm32/alloc-id:fake
29703     _string_bb_copy_to_ebx/imm32/subx-name
29704     0/imm32/no-rm32
29705     0/imm32/no-r32
29706     1/imm32/imm32-is-first-inout
29707     0/imm32/no-imm8
29708     0/imm32/no-disp32
29709     0/imm32/no-xm32
29710     0/imm32/no-x32
29711     0x11/imm32/alloc-id:fake
29712     _Primitive-copy-to-esi/imm32/next
29713 _Primitive-copy-to-esi:  # (payload primitive)
29714     0x11/imm32/alloc-id:fake:payload
29715     # var/esi <- copy lit => be/copy-to-esi lit/imm32
29716     0x11/imm32/alloc-id:fake
29717     _string-copy/imm32/name
29718     0x11/imm32/alloc-id:fake
29719     Single-lit-var/imm32/inouts
29720     0x11/imm32/alloc-id:fake
29721     Single-int-var-in-esi/imm32/outputs
29722     0x11/imm32/alloc-id:fake
29723     _string_be_copy_to_esi/imm32/subx-name
29724     0/imm32/no-rm32
29725     0/imm32/no-r32
29726     1/imm32/imm32-is-first-inout
29727     0/imm32/no-imm8
29728     0/imm32/no-disp32
29729     0/imm32/no-xm32
29730     0/imm32/no-x32
29731     0x11/imm32/alloc-id:fake
29732     _Primitive-copy-to-edi/imm32/next
29733 _Primitive-copy-to-edi:  # (payload primitive)
29734     0x11/imm32/alloc-id:fake:payload
29735     # var/edi <- copy lit => bf/copy-to-edi lit/imm32
29736     0x11/imm32/alloc-id:fake
29737     _string-copy/imm32/name
29738     0x11/imm32/alloc-id:fake
29739     Single-lit-var/imm32/inouts
29740     0x11/imm32/alloc-id:fake
29741     Single-int-var-in-edi/imm32/outputs
29742     0x11/imm32/alloc-id:fake
29743     _string_bf_copy_to_edi/imm32/subx-name
29744     0/imm32/no-rm32
29745     0/imm32/no-r32
29746     1/imm32/imm32-is-first-inout
29747     0/imm32/no-imm8
29748     0/imm32/no-disp32
29749     0/imm32/no-xm32
29750     0/imm32/no-x32
29751     0x11/imm32/alloc-id:fake
29752     _Primitive-copy-reg-to-reg/imm32/next
29753 _Primitive-copy-reg-to-reg:  # (payload primitive)
29754     0x11/imm32/alloc-id:fake:payload
29755     # var1/reg <- copy var2/reg => 89/<- var1/rm32 var2/r32
29756     0x11/imm32/alloc-id:fake
29757     _string-copy/imm32/name
29758     0x11/imm32/alloc-id:fake
29759     Single-int-var-in-some-register/imm32/inouts
29760     0x11/imm32/alloc-id:fake
29761     Single-int-var-in-some-register/imm32/outputs
29762     0x11/imm32/alloc-id:fake
29763     _string_89_<-/imm32/subx-name
29764     3/imm32/rm32-is-first-output
29765     1/imm32/r32-is-first-inout
29766     0/imm32/no-imm32
29767     0/imm32/no-imm8
29768     0/imm32/no-disp32
29769     0/imm32/no-xm32
29770     0/imm32/no-x32
29771     0x11/imm32/alloc-id:fake
29772     _Primitive-copy-reg-to-mem/imm32/next
29773 _Primitive-copy-reg-to-mem:  # (payload primitive)
29774     0x11/imm32/alloc-id:fake:payload
29775     # copy-to var1 var2/reg => 89/<- var1 var2/r32
29776     0x11/imm32/alloc-id:fake
29777     _string-copy-to/imm32/name
29778     0x11/imm32/alloc-id:fake
29779     Two-args-int-stack-int-reg/imm32/inouts
29780     0/imm32/no-outputs
29781     0/imm32/no-outputs
29782     0x11/imm32/alloc-id:fake
29783     _string_89_<-/imm32/subx-name
29784     1/imm32/rm32-is-first-inout
29785     2/imm32/r32-is-second-inout
29786     0/imm32/no-imm32
29787     0/imm32/no-imm8
29788     0/imm32/no-disp32
29789     0/imm32/no-xm32
29790     0/imm32/no-x32
29791     0x11/imm32/alloc-id:fake
29792     _Primitive-copy-mem-to-reg/imm32/next
29793 _Primitive-copy-mem-to-reg:  # (payload primitive)
29794     0x11/imm32/alloc-id:fake:payload
29795     # var1/reg <- copy var2 => 8b/-> var2/rm32 var1/r32
29796     0x11/imm32/alloc-id:fake
29797     _string-copy/imm32/name
29798     0x11/imm32/alloc-id:fake
29799     Single-int-var-in-mem/imm32/inouts
29800     0x11/imm32/alloc-id:fake
29801     Single-int-var-in-some-register/imm32/outputs
29802     0x11/imm32/alloc-id:fake
29803     _string_8b_->/imm32/subx-name
29804     1/imm32/rm32-is-first-inout
29805     3/imm32/r32-is-first-output
29806     0/imm32/no-imm32
29807     0/imm32/no-imm8
29808     0/imm32/no-disp32
29809     0/imm32/no-xm32
29810     0/imm32/no-x32
29811     0x11/imm32/alloc-id:fake
29812     _Primitive-copy-lit-to-reg/imm32/next
29813 _Primitive-copy-lit-to-reg:  # (payload primitive)
29814     0x11/imm32/alloc-id:fake:payload
29815     # var1/reg <- copy lit => c7 0/subop/copy var1/rm32 lit/imm32
29816     0x11/imm32/alloc-id:fake
29817     _string-copy/imm32/name
29818     0x11/imm32/alloc-id:fake
29819     Single-lit-var/imm32/inouts
29820     0x11/imm32/alloc-id:fake
29821     Single-int-var-in-some-register/imm32/outputs
29822     0x11/imm32/alloc-id:fake
29823     _string_c7_subop_copy/imm32/subx-name
29824     3/imm32/rm32-is-first-output
29825     0/imm32/no-r32
29826     1/imm32/imm32-is-first-inout
29827     0/imm32/no-imm8
29828     0/imm32/no-disp32
29829     0/imm32/no-xm32
29830     0/imm32/no-x32
29831     0x11/imm32/alloc-id:fake
29832     _Primitive-copy-lit-to-mem/imm32/next
29833 _Primitive-copy-lit-to-mem:  # (payload primitive)
29834     0x11/imm32/alloc-id:fake:payload
29835     # copy-to var1, lit => c7 0/subop/copy var1/rm32 lit/imm32
29836     0x11/imm32/alloc-id:fake
29837     _string-copy-to/imm32/name
29838     0x11/imm32/alloc-id:fake
29839     Int-var-and-literal/imm32/inouts
29840     0/imm32/no-outputs
29841     0/imm32/no-outputs
29842     0x11/imm32/alloc-id:fake
29843     _string_c7_subop_copy/imm32/subx-name
29844     1/imm32/rm32-is-first-inout
29845     0/imm32/no-r32
29846     2/imm32/imm32-is-second-inout
29847     0/imm32/no-imm8
29848     0/imm32/no-disp32
29849     0/imm32/no-xm32
29850     0/imm32/no-x32
29851     0x11/imm32/alloc-id:fake
29852     _Primitive-copy-byte-from-reg/imm32/next
29853 # - copy byte
29854 _Primitive-copy-byte-from-reg:
29855     0x11/imm32/alloc-id:fake:payload
29856     # var/reg <- copy-byte var2/reg2 => 8a/byte-> %var2 var/r32
29857     0x11/imm32/alloc-id:fake
29858     _string-copy-byte/imm32/name
29859     0x11/imm32/alloc-id:fake
29860     Single-byte-var-in-some-register/imm32/inouts
29861     0x11/imm32/alloc-id:fake
29862     Single-byte-var-in-some-register/imm32/outputs
29863     0x11/imm32/alloc-id:fake
29864     _string_8a_copy_byte/imm32/subx-name
29865     1/imm32/rm32-is-first-inout
29866     3/imm32/r32-is-first-output
29867     0/imm32/no-imm32
29868     0/imm32/no-imm8
29869     0/imm32/no-disp32
29870     0/imm32/no-xm32
29871     0/imm32/no-x32
29872     0x11/imm32/alloc-id:fake
29873     _Primitive-copy-byte-from-mem/imm32/next
29874 _Primitive-copy-byte-from-mem:
29875     0x11/imm32/alloc-id:fake:payload
29876     # var/reg <- copy-byte *var2/reg2 => 8a/byte-> *var2 var/r32
29877     0x11/imm32/alloc-id:fake
29878     _string-copy-byte/imm32/name
29879     0x11/imm32/alloc-id:fake
29880     Single-byte-var-in-mem/imm32/inouts
29881     0x11/imm32/alloc-id:fake
29882     Single-byte-var-in-some-register/imm32/outputs
29883     0x11/imm32/alloc-id:fake
29884     _string_8a_copy_byte/imm32/subx-name
29885     1/imm32/rm32-is-first-inout
29886     3/imm32/r32-is-first-output
29887     0/imm32/no-imm32
29888     0/imm32/no-imm8
29889     0/imm32/no-disp32
29890     0/imm32/no-xm32
29891     0/imm32/no-x32
29892     0x11/imm32/alloc-id:fake
29893     _Primitive-copy-byte-to-mem/imm32/next
29894 _Primitive-copy-byte-to-mem:
29895     0x11/imm32/alloc-id:fake:payload
29896     # copy-byte-to *var1/reg1, var2/reg2 => 88/byte<- *reg1 reg2/r32
29897     0x11/imm32/alloc-id:fake
29898     _string-copy-byte-to/imm32/name
29899     0x11/imm32/alloc-id:fake
29900     Two-args-byte-stack-byte-reg/imm32/inouts
29901     0/imm32/no-outputs
29902     0/imm32/no-outputs
29903     0x11/imm32/alloc-id:fake
29904     _string_88_copy_byte/imm32/subx-name
29905     1/imm32/rm32-is-first-inout
29906     2/imm32/r32-is-second-inout
29907     0/imm32/no-imm32
29908     0/imm32/no-imm8
29909     0/imm32/no-disp32
29910     0/imm32/no-xm32
29911     0/imm32/no-x32
29912     0x11/imm32/alloc-id:fake
29913     _Primitive-address/imm32/next
29914 # - address
29915 _Primitive-address:  # (payload primitive)
29916     0x11/imm32/alloc-id:fake:payload
29917     # var1/reg <- address var2 => 8d/copy-address var2/rm32 var1/r32
29918     0x11/imm32/alloc-id:fake
29919     _string-address/imm32/name
29920     0x11/imm32/alloc-id:fake
29921     Single-int-var-in-mem/imm32/inouts
29922     0x11/imm32/alloc-id:fake
29923     Single-addr-var-in-some-register/imm32/outputs
29924     0x11/imm32/alloc-id:fake
29925     _string_8d_copy_address/imm32/subx-name
29926     1/imm32/rm32-is-first-inout
29927     3/imm32/r32-is-first-output
29928     0/imm32/no-imm32
29929     0/imm32/no-imm8
29930     0/imm32/no-disp32
29931     0/imm32/no-xm32
29932     0/imm32/no-x32
29933     0x11/imm32/alloc-id:fake
29934     _Primitive-compare-reg-with-reg/imm32/next
29935 # - compare
29936 _Primitive-compare-reg-with-reg:  # (payload primitive)
29937     0x11/imm32/alloc-id:fake:payload
29938     # compare var1/reg1 var2/reg2 => 39/compare var1/rm32 var2/r32
29939     0x11/imm32/alloc-id:fake
29940     _string-compare/imm32/name
29941     0x11/imm32/alloc-id:fake
29942     Two-int-args-in-regs/imm32/inouts
29943     0/imm32/no-outputs
29944     0/imm32/no-outputs
29945     0x11/imm32/alloc-id:fake
29946     _string_39_compare->/imm32/subx-name
29947     1/imm32/rm32-is-first-inout
29948     2/imm32/r32-is-second-inout
29949     0/imm32/no-imm32
29950     0/imm32/no-imm8
29951     0/imm32/no-disp32
29952     0/imm32/no-xm32
29953     0/imm32/no-x32
29954     0x11/imm32/alloc-id:fake
29955     _Primitive-compare-mem-with-reg/imm32/next
29956 _Primitive-compare-mem-with-reg:  # (payload primitive)
29957     0x11/imm32/alloc-id:fake:payload
29958     # compare var1 var2/reg => 39/compare var1/rm32 var2/r32
29959     0x11/imm32/alloc-id:fake
29960     _string-compare/imm32/name
29961     0x11/imm32/alloc-id:fake
29962     Two-args-int-stack-int-reg/imm32/inouts
29963     0/imm32/no-outputs
29964     0/imm32/no-outputs
29965     0x11/imm32/alloc-id:fake
29966     _string_39_compare->/imm32/subx-name
29967     1/imm32/rm32-is-first-inout
29968     2/imm32/r32-is-second-inout
29969     0/imm32/no-imm32
29970     0/imm32/no-imm8
29971     0/imm32/no-disp32
29972     0/imm32/no-xm32
29973     0/imm32/no-x32
29974     0x11/imm32/alloc-id:fake
29975     _Primitive-compare-reg-with-mem/imm32/next
29976 _Primitive-compare-reg-with-mem:  # (payload primitive)
29977     0x11/imm32/alloc-id:fake:payload
29978     # compare var1/reg var2 => 3b/compare<- var2/rm32 var1/r32
29979     0x11/imm32/alloc-id:fake
29980     _string-compare/imm32/name
29981     0x11/imm32/alloc-id:fake
29982     Two-args-int-reg-int-stack/imm32/inouts
29983     0/imm32/no-outputs
29984     0/imm32/no-outputs
29985     0x11/imm32/alloc-id:fake
29986     _string_3b_compare<-/imm32/subx-name
29987     2/imm32/rm32-is-second-inout
29988     1/imm32/r32-is-first-inout
29989     0/imm32/no-imm32
29990     0/imm32/no-imm8
29991     0/imm32/no-disp32
29992     0/imm32/no-xm32
29993     0/imm32/no-x32
29994     0x11/imm32/alloc-id:fake
29995     _Primitive-compare-eax-with-literal/imm32/next
29996 _Primitive-compare-eax-with-literal:  # (payload primitive)
29997     0x11/imm32/alloc-id:fake:payload
29998     # compare var1/eax n => 3d/compare-eax-with n/imm32
29999     0x11/imm32/alloc-id:fake
30000     _string-compare/imm32/name
30001     0x11/imm32/alloc-id:fake
30002     Two-args-int-eax-int-literal/imm32/inouts
30003     0/imm32/no-outputs
30004     0/imm32/no-outputs
30005     0x11/imm32/alloc-id:fake
30006     _string_3d_compare_eax_with/imm32/subx-name
30007     0/imm32/no-rm32
30008     0/imm32/no-r32
30009     2/imm32/imm32-is-second-inout
30010     0/imm32/no-imm8
30011     0/imm32/no-disp32
30012     0/imm32/no-xm32
30013     0/imm32/no-x32
30014     0x11/imm32/alloc-id:fake
30015     _Primitive-compare-reg-with-literal/imm32/next
30016 _Primitive-compare-reg-with-literal:  # (payload primitive)
30017     0x11/imm32/alloc-id:fake:payload
30018     # compare var1/reg n => 81 7/subop/compare %reg n/imm32
30019     0x11/imm32/alloc-id:fake
30020     _string-compare/imm32/name
30021     0x11/imm32/alloc-id:fake
30022     Int-var-in-register-and-literal/imm32/inouts
30023     0/imm32/no-outputs
30024     0/imm32/no-outputs
30025     0x11/imm32/alloc-id:fake
30026     _string_81_subop_compare/imm32/subx-name
30027     1/imm32/rm32-is-first-inout
30028     0/imm32/no-r32
30029     2/imm32/imm32-is-second-inout
30030     0/imm32/no-imm8
30031     0/imm32/no-disp32
30032     0/imm32/no-xm32
30033     0/imm32/no-x32
30034     0x11/imm32/alloc-id:fake
30035     _Primitive-compare-mem-with-literal/imm32/next
30036 _Primitive-compare-mem-with-literal:  # (payload primitive)
30037     0x11/imm32/alloc-id:fake:payload
30038     # compare var1 n => 81 7/subop/compare *(ebp+___) n/imm32
30039     0x11/imm32/alloc-id:fake
30040     _string-compare/imm32/name
30041     0x11/imm32/alloc-id:fake
30042     Int-var-and-literal/imm32/inouts
30043     0/imm32/no-outputs
30044     0/imm32/no-outputs
30045     0x11/imm32/alloc-id:fake
30046     _string_81_subop_compare/imm32/subx-name
30047     1/imm32/rm32-is-first-inout
30048     0/imm32/no-r32
30049     2/imm32/imm32-is-second-inout
30050     0/imm32/no-imm8
30051     0/imm32/no-disp32
30052     0/imm32/no-xm32
30053     0/imm32/no-x32
30054     0x11/imm32/alloc-id:fake
30055     _Primitive-negate-reg/imm32/next
30056 # - negate
30057 _Primitive-negate-reg:  # (payload primitive)
30058     0x11/imm32/alloc-id:fake:payload
30059     # var1/reg <- negate => f7 3/subop/negate var1/rm32
30060     0x11/imm32/alloc-id:fake
30061     _string-negate/imm32/name
30062     0/imm32/no-inouts
30063     0/imm32/no-inouts
30064     0x11/imm32/alloc-id:fake
30065     Single-int-var-in-some-register/imm32/outputs
30066     0x11/imm32/alloc-id:fake
30067     _string_f7_subop_negate/imm32/subx-name
30068     3/imm32/rm32-is-first-output
30069     0/imm32/no-r32
30070     0/imm32/no-imm32
30071     0/imm32/no-imm8
30072     0/imm32/no-disp32
30073     0/imm32/no-xm32
30074     0/imm32/no-x32
30075     0x11/imm32/alloc-id:fake
30076     _Primitive-negate-mem/imm32/next
30077 _Primitive-negate-mem:  # (payload primitive)
30078     0x11/imm32/alloc-id:fake:payload
30079     # negate var1 => f7 3/subop/negate var1/rm32
30080     0x11/imm32/alloc-id:fake
30081     _string-negate/imm32/name
30082     0x11/imm32/alloc-id:fake
30083     Single-int-var-in-mem/imm32/inouts
30084     0/imm32/no-outputs
30085     0/imm32/no-outputs
30086     0x11/imm32/alloc-id:fake
30087     _string_f7_subop_negate/imm32/subx-name
30088     1/imm32/rm32-is-first-inout
30089     0/imm32/no-r32
30090     0/imm32/no-imm32
30091     0/imm32/no-imm8
30092     0/imm32/no-disp32
30093     0/imm32/no-xm32
30094     0/imm32/no-x32
30095     0x11/imm32/alloc-id:fake
30096     _Primitive-multiply-reg-by-reg/imm32/next
30097 # - multiply
30098 _Primitive-multiply-reg-by-reg:  # (payload primitive)
30099     0x11/imm32/alloc-id:fake:payload
30100     # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32
30101     0x11/imm32/alloc-id:fake
30102     _string-multiply/imm32/name
30103     0x11/imm32/alloc-id:fake
30104     Single-int-var-in-some-register/imm32/inouts
30105     0x11/imm32/alloc-id:fake
30106     Single-int-var-in-some-register/imm32/outputs
30107     0x11/imm32/alloc-id:fake
30108     _string_0f_af_multiply/imm32/subx-name
30109     1/imm32/rm32-is-first-inout
30110     3/imm32/r32-is-first-output
30111     0/imm32/no-imm32
30112     0/imm32/no-imm8
30113     0/imm32/no-disp32
30114     0/imm32/no-xm32
30115     0/imm32/no-x32
30116     0x11/imm32/alloc-id:fake
30117     _Primitive-multiply-reg-by-mem/imm32/next
30118 _Primitive-multiply-reg-by-mem:  # (payload primitive)
30119     0x11/imm32/alloc-id:fake:payload
30120     # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32
30121     0x11/imm32/alloc-id:fake
30122     _string-multiply/imm32/name
30123     0x11/imm32/alloc-id:fake
30124     Single-int-var-in-mem/imm32/inouts
30125     0x11/imm32/alloc-id:fake
30126     Single-int-var-in-some-register/imm32/outputs
30127     0x11/imm32/alloc-id:fake
30128     _string_0f_af_multiply/imm32/subx-name
30129     1/imm32/rm32-is-first-inout
30130     3/imm32/r32-is-first-output
30131     0/imm32/no-imm32
30132     0/imm32/no-imm8
30133     0/imm32/no-disp32
30134     0/imm32/no-xm32
30135     0/imm32/no-x32
30136     0x11/imm32/alloc-id:fake
30137     _Primitive-convert-mem-to-xreg/imm32/next
30138 # - convert int to floating point
30139 _Primitive-convert-mem-to-xreg:  # (payload primitive)
30140     0x11/imm32/alloc-id:fake:payload
30141     # var1/xreg <- convert var2 => f3 0f 2a/convert-to-float var2/rm32 var1/x32
30142     0x11/imm32/alloc-id:fake
30143     _string-convert/imm32/name
30144     0x11/imm32/alloc-id:fake
30145     Single-int-var-in-mem/imm32/inouts
30146     0x11/imm32/alloc-id:fake
30147     Single-float-var-in-some-register/imm32/outputs
30148     0x11/imm32/alloc-id:fake
30149     _string_f3_0f_2a_convert_to_float/imm32/subx-name
30150     1/imm32/rm32-is-first-inout
30151     0/imm32/no-r32
30152     0/imm32/no-imm32
30153     0/imm32/no-imm8
30154     0/imm32/no-disp32
30155     0/imm32/no-xm32
30156     3/imm32/x32-is-first-output
30157     0x11/imm32/alloc-id:fake
30158     _Primitive-convert-reg-to-xreg/imm32/next
30159 _Primitive-convert-reg-to-xreg:  # (payload primitive)
30160     0x11/imm32/alloc-id:fake:payload
30161     # var1/xreg <- convert var2/reg => f3 0f 2a/convert-to-float var2/rm32 var1/x32
30162     0x11/imm32/alloc-id:fake
30163     _string-convert/imm32/name
30164     0x11/imm32/alloc-id:fake
30165     Single-int-var-in-some-register/imm32/inouts
30166     0x11/imm32/alloc-id:fake
30167     Single-float-var-in-some-register/imm32/outputs
30168     0x11/imm32/alloc-id:fake
30169     _string_f3_0f_2a_convert_to_float/imm32/subx-name
30170     1/imm32/rm32-is-first-inout
30171     0/imm32/no-r32
30172     0/imm32/no-imm32
30173     0/imm32/no-imm8
30174     0/imm32/no-disp32
30175     0/imm32/no-xm32
30176     3/imm32/x32-is-first-output
30177     0x11/imm32/alloc-id:fake
30178     _Primitive-convert-xmem-to-reg/imm32/next
30179 # - convert floating point to int
30180 _Primitive-convert-xmem-to-reg:  # (payload primitive)
30181     0x11/imm32/alloc-id:fake:payload
30182     # var1/reg <- convert var2 => f3 0f 2d/convert-to-int var2/xm32 var1/r32
30183     0x11/imm32/alloc-id:fake
30184     _string-convert/imm32/name
30185     0x11/imm32/alloc-id:fake
30186     Single-float-var-in-mem/imm32/inouts
30187     0x11/imm32/alloc-id:fake
30188     Single-int-var-in-some-register/imm32/outputs
30189     0x11/imm32/alloc-id:fake
30190     _string_f3_0f_2d_convert_to_int/imm32/subx-name
30191     0/imm32/no-rm32
30192     3/imm32/r32-is-first-output
30193     0/imm32/no-imm32
30194     0/imm32/no-imm8
30195     0/imm32/no-disp32
30196     1/imm32/xm32-is-first-inout
30197     0/imm32/no-x32
30198     0x11/imm32/alloc-id:fake
30199     _Primitive-convert-xreg-to-reg/imm32/next
30200 _Primitive-convert-xreg-to-reg:  # (payload primitive)
30201     0x11/imm32/alloc-id:fake:payload
30202     # var1/reg <- convert var2/xreg => f3 0f 2d/convert-to-int var2/xm32 var1/r32
30203     0x11/imm32/alloc-id:fake
30204     _string-convert/imm32/name
30205     0x11/imm32/alloc-id:fake
30206     Single-float-var-in-some-register/imm32/inouts
30207     0x11/imm32/alloc-id:fake
30208     Single-int-var-in-some-register/imm32/outputs
30209     0x11/imm32/alloc-id:fake
30210     _string_f3_0f_2d_convert_to_int/imm32/subx-name
30211     0/imm32/no-rm32
30212     3/imm32/r32-is-first-output
30213     0/imm32/no-imm32
30214     0/imm32/no-imm8
30215     0/imm32/no-disp32
30216     1/imm32/xm32-is-first-inout
30217     0/imm32/no-x32
30218     0x11/imm32/alloc-id:fake
30219     _Primitive-truncate-xmem-to-reg/imm32/next
30220 _Primitive-truncate-xmem-to-reg:  # (payload primitive)
30221     0x11/imm32/alloc-id:fake:payload
30222     # var1/reg <- truncate var2 => f3 0f 2c/truncate-to-int var2/xm32 var1/r32
30223     0x11/imm32/alloc-id:fake
30224     _string-truncate/imm32/name
30225     0x11/imm32/alloc-id:fake
30226     Single-float-var-in-mem/imm32/inouts
30227     0x11/imm32/alloc-id:fake
30228     Single-int-var-in-some-register/imm32/outputs
30229     0x11/imm32/alloc-id:fake
30230     _string_f3_0f_2c_truncate_to_int/imm32/subx-name
30231     0/imm32/no-rm32
30232     3/imm32/r32-is-first-output
30233     0/imm32/no-imm32
30234     0/imm32/no-imm8
30235     0/imm32/no-disp32
30236     1/imm32/xm32-is-first-inout
30237     0/imm32/no-x32
30238     0x11/imm32/alloc-id:fake
30239     _Primitive-truncate-xreg-to-reg/imm32/next
30240 _Primitive-truncate-xreg-to-reg:  # (payload primitive)
30241     0x11/imm32/alloc-id:fake:payload
30242     # var1/reg <- truncate var2/xreg => f3 0f 2c/truncate-to-int var2/xm32 var1/r32
30243     0x11/imm32/alloc-id:fake
30244     _string-truncate/imm32/name
30245     0x11/imm32/alloc-id:fake
30246     Single-float-var-in-some-register/imm32/inouts
30247     0x11/imm32/alloc-id:fake
30248     Single-int-var-in-some-register/imm32/outputs
30249     0x11/imm32/alloc-id:fake
30250     _string_f3_0f_2c_truncate_to_int/imm32/subx-name
30251     0/imm32/no-rm32
30252     3/imm32/r32-is-first-output
30253     0/imm32/no-imm32
30254     0/imm32/no-imm8
30255     0/imm32/no-disp32
30256     1/imm32/xm32-is-first-inout
30257     0/imm32/no-x32
30258     0x11/imm32/alloc-id:fake
30259     _Primitive-reinterpret-xmem-as-reg/imm32/next
30260 # - reinterpret bytes (just for debugging)
30261 _Primitive-reinterpret-xmem-as-reg:  # (payload primitive)
30262     0x11/imm32/alloc-id:fake:payload
30263     # var1/reg <- reinterpret var2 => 8b/-> var2/xm32 var1/r32
30264     0x11/imm32/alloc-id:fake
30265     _string-reinterpret/imm32/name
30266     0x11/imm32/alloc-id:fake
30267     Single-float-var-in-mem/imm32/inouts
30268     0x11/imm32/alloc-id:fake
30269     Single-int-var-in-some-register/imm32/outputs
30270     0x11/imm32/alloc-id:fake
30271     _string_8b_->/imm32/subx-name
30272     0/imm32/no-rm32
30273     3/imm32/r32-is-first-output
30274     0/imm32/no-imm32
30275     0/imm32/no-imm8
30276     0/imm32/no-disp32
30277     1/imm32/xm32-is-first-inout
30278     0/imm32/no-x32
30279     0x11/imm32/alloc-id:fake
30280     _Primitive-reinterpret-mem-as-xreg/imm32/next
30281 _Primitive-reinterpret-mem-as-xreg:  # (payload primitive)
30282     0x11/imm32/alloc-id:fake:payload
30283     # var1/xreg <- reinterpret var2 => f3 0f 10/-> var2/rm32 var1/x32
30284     0x11/imm32/alloc-id:fake
30285     _string-reinterpret/imm32/name
30286     0x11/imm32/alloc-id:fake
30287     Single-int-var-in-mem/imm32/inouts
30288     0x11/imm32/alloc-id:fake
30289     Single-float-var-in-some-register/imm32/outputs
30290     0x11/imm32/alloc-id:fake
30291     _string_f3_0f_10_copy/imm32/subx-name
30292     1/imm32/rm32-is-first-inout
30293     0/imm32/no-r32
30294     0/imm32/no-imm32
30295     0/imm32/no-imm8
30296     0/imm32/no-disp32
30297     0/imm32/no-xm32
30298     3/imm32/x32-is-first-output
30299     0x11/imm32/alloc-id:fake
30300     _Primitive-copy-xreg-to-xreg/imm32/next
30301 # - floating-point copy
30302 _Primitive-copy-xreg-to-xreg:  # (payload primitive)
30303     0x11/imm32/alloc-id:fake:payload
30304     # var1/xreg <- copy var2/xreg => f3 0f 11/<- var1/xm32 var2/x32
30305     0x11/imm32/alloc-id:fake
30306     _string-copy/imm32/name
30307     0x11/imm32/alloc-id:fake
30308     Single-float-var-in-some-register/imm32/inouts
30309     0x11/imm32/alloc-id:fake
30310     Single-float-var-in-some-register/imm32/outputs
30311     0x11/imm32/alloc-id:fake
30312     _string_f3_0f_11_copy/imm32/subx-name
30313     0/imm32/no-rm32
30314     0/imm32/no-r32
30315     0/imm32/no-imm32
30316     0/imm32/no-imm8
30317     0/imm32/no-disp32
30318     3/imm32/xm32-is-first-output
30319     1/imm32/x32-is-first-inout
30320     0x11/imm32/alloc-id:fake
30321     _Primitive-copy-xreg-to-mem/imm32/next
30322 _Primitive-copy-xreg-to-mem:  # (payload primitive)
30323     0x11/imm32/alloc-id:fake:payload
30324     # copy-to var1 var2/xreg => f3 0f 11/<- var1 var2/x32
30325     0x11/imm32/alloc-id:fake
30326     _string-copy-to/imm32/name
30327     0x11/imm32/alloc-id:fake
30328     Two-args-float-stack-float-reg/imm32/inouts
30329     0/imm32/no-outputs
30330     0/imm32/no-outputs
30331     0x11/imm32/alloc-id:fake
30332     _string_f3_0f_11_copy/imm32/subx-name
30333     0/imm32/no-rm32
30334     0/imm32/no-r32
30335     0/imm32/no-imm32
30336     0/imm32/no-imm8
30337     0/imm32/no-disp32
30338     1/imm32/xm32-is-first-inout
30339     2/imm32/x32-is-second-inout
30340     0x11/imm32/alloc-id:fake
30341     _Primitive-copy-mem-to-xreg/imm32/next
30342 _Primitive-copy-mem-to-xreg:  # (payload primitive)
30343     0x11/imm32/alloc-id:fake:payload
30344     # var1/xreg <- copy var2 => f3 0f 10/-> var2/rm32 var1/x32
30345     0x11/imm32/alloc-id:fake
30346     _string-copy/imm32/name
30347     0x11/imm32/alloc-id:fake
30348     Single-float-var-in-mem/imm32/inouts
30349     0x11/imm32/alloc-id:fake
30350     Single-float-var-in-some-register/imm32/outputs
30351     0x11/imm32/alloc-id:fake
30352     _string_f3_0f_10_copy/imm32/subx-name
30353     0/imm32/no-rm32
30354     0/imm32/no-r32
30355     0/imm32/no-imm32
30356     0/imm32/no-imm8
30357     0/imm32/no-disp32
30358     1/imm32/xm32-is-first-inout
30359     3/imm32/x32-is-first-output
30360     0x11/imm32/alloc-id:fake
30361     _Primitive-address-of-xmem/imm32/next
30362 # - floating-point-address
30363 _Primitive-address-of-xmem:  # (payload primitive)
30364     0x11/imm32/alloc-id:fake:payload
30365     # var1/reg <- address var2 => 8d/copy-address var2/rm32 var1/r32
30366     0x11/imm32/alloc-id:fake
30367     _string-address/imm32/name
30368     0x11/imm32/alloc-id:fake
30369     Single-float-var-in-mem/imm32/inouts
30370     0x11/imm32/alloc-id:fake
30371     Single-addr-var-in-some-register/imm32/outputs
30372     0x11/imm32/alloc-id:fake
30373     _string_8d_copy_address/imm32/subx-name
30374     1/imm32/rm32-is-first-inout
30375     3/imm32/r32-is-first-output
30376     0/imm32/no-imm32
30377     0/imm32/no-imm8
30378     0/imm32/no-disp32
30379     0/imm32/no-xm32
30380     0/imm32/no-x32
30381     0x11/imm32/alloc-id:fake
30382     _Primitive-add-xreg-to-xreg/imm32/next
30383 # - floating-point add
30384 _Primitive-add-xreg-to-xreg:  # (payload primitive)
30385     0x11/imm32/alloc-id:fake:payload
30386     # var1/xreg <- add var2/xreg => f3 0f 58/add var1/xm32 var2/x32
30387     0x11/imm32/alloc-id:fake
30388     _string-add/imm32/name
30389     0x11/imm32/alloc-id:fake
30390     Single-float-var-in-some-register/imm32/inouts
30391     0x11/imm32/alloc-id:fake
30392     Single-float-var-in-some-register/imm32/outputs
30393     0x11/imm32/alloc-id:fake
30394     _string_f3_0f_58_add/imm32/subx-name
30395     0/imm32/no-rm32
30396     0/imm32/no-r32
30397     0/imm32/no-imm32
30398     0/imm32/no-imm8
30399     0/imm32/no-disp32
30400     1/imm32/xm32-is-first-inout
30401     3/imm32/x32-is-first-output
30402     0x11/imm32/alloc-id:fake
30403     _Primitive-add-mem-to-xreg/imm32/next
30404 _Primitive-add-mem-to-xreg:  # (payload primitive)
30405     0x11/imm32/alloc-id:fake:payload
30406     # var1/xreg <- add var2 => f3 0f 58/add var2/xm32 var1/x32
30407     0x11/imm32/alloc-id:fake
30408     _string-add/imm32/name
30409     0x11/imm32/alloc-id:fake
30410     Single-float-var-in-mem/imm32/inouts
30411     0x11/imm32/alloc-id:fake
30412     Single-float-var-in-some-register/imm32/outputs
30413     0x11/imm32/alloc-id:fake
30414     _string_f3_0f_58_add/imm32/subx-name
30415     0/imm32/no-rm32
30416     0/imm32/no-r32
30417     0/imm32/no-imm32
30418     0/imm32/no-imm8
30419     0/imm32/no-disp32
30420     1/imm32/xm32-is-first-inout
30421     3/imm32/x32-is-first-output
30422     0x11/imm32/alloc-id:fake
30423     _Primitive-subtract-xreg-from-xreg/imm32/next
30424 # - floating-point subtract
30425 _Primitive-subtract-xreg-from-xreg:  # (payload primitive)
30426     0x11/imm32/alloc-id:fake:payload
30427     # var1/xreg <- subtract var2/xreg => f3 0f 5c/subtract var1/xm32 var2/x32
30428     0x11/imm32/alloc-id:fake
30429     _string-subtract/imm32/name
30430     0x11/imm32/alloc-id:fake
30431     Single-float-var-in-some-register/imm32/inouts
30432     0x11/imm32/alloc-id:fake
30433     Single-float-var-in-some-register/imm32/outputs
30434     0x11/imm32/alloc-id:fake
30435     _string_f3_0f_5c_subtract/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     1/imm32/xm32-is-first-inout
30442     3/imm32/x32-is-first-output
30443     0x11/imm32/alloc-id:fake
30444     _Primitive-subtract-mem-from-xreg/imm32/next
30445 _Primitive-subtract-mem-from-xreg:  # (payload primitive)
30446     0x11/imm32/alloc-id:fake:payload
30447     # var1/xreg <- subtract var2 => f3 0f 5c/subtract var2/xm32 var1/x32
30448     0x11/imm32/alloc-id:fake
30449     _string-subtract/imm32/name
30450     0x11/imm32/alloc-id:fake
30451     Single-float-var-in-mem/imm32/inouts
30452     0x11/imm32/alloc-id:fake
30453     Single-float-var-in-some-register/imm32/outputs
30454     0x11/imm32/alloc-id:fake
30455     _string_f3_0f_5c_subtract/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     1/imm32/xm32-is-first-inout
30462     3/imm32/x32-is-first-output
30463     0x11/imm32/alloc-id:fake
30464     _Primitive-multiply-xreg-by-xreg/imm32/next
30465 # - floating-point multiply
30466 _Primitive-multiply-xreg-by-xreg:  # (payload primitive)
30467     0x11/imm32/alloc-id:fake:payload
30468     # var1/xreg <- multiply var2 => f3 0f 59/multiply var2/xm32 var1/x32
30469     0x11/imm32/alloc-id:fake
30470     _string-multiply/imm32/name
30471     0x11/imm32/alloc-id:fake
30472     Single-float-var-in-some-register/imm32/inouts
30473     0x11/imm32/alloc-id:fake
30474     Single-float-var-in-some-register/imm32/outputs
30475     0x11/imm32/alloc-id:fake
30476     _string_f3_0f_59_multiply/imm32/subx-name
30477     0/imm32/no-rm32
30478     0/imm32/no-r32
30479     0/imm32/no-imm32
30480     0/imm32/no-imm8
30481     0/imm32/no-disp32
30482     1/imm32/xm32-is-first-inout
30483     3/imm32/x32-is-first-output
30484     0x11/imm32/alloc-id:fake
30485     _Primitive-multiply-xreg-by-mem/imm32/next
30486 _Primitive-multiply-xreg-by-mem:  # (payload primitive)
30487     0x11/imm32/alloc-id:fake:payload
30488     # var1/xreg <- multiply var2 => 53 0f 59/multiply var2/xm32 var1/x32
30489     0x11/imm32/alloc-id:fake
30490     _string-multiply/imm32/name
30491     0x11/imm32/alloc-id:fake
30492     Single-float-var-in-mem/imm32/inouts
30493     0x11/imm32/alloc-id:fake
30494     Single-float-var-in-some-register/imm32/outputs
30495     0x11/imm32/alloc-id:fake
30496     _string_f3_0f_59_multiply/imm32/subx-name
30497     0/imm32/no-rm32
30498     0/imm32/no-r32
30499     0/imm32/no-imm32
30500     0/imm32/no-imm8
30501     0/imm32/no-disp32
30502     1/imm32/xm32-is-first-inout
30503     3/imm32/x32-is-first-output
30504     0x11/imm32/alloc-id:fake
30505     _Primitive-divide-xreg-by-xreg/imm32/next
30506 # - floating-point divide
30507 _Primitive-divide-xreg-by-xreg:  # (payload primitive)
30508     0x11/imm32/alloc-id:fake:payload
30509     # var1/xreg <- divide var2 => f3 0f 5e/divide var2/xm32 var1/x32
30510     0x11/imm32/alloc-id:fake
30511     _string-divide/imm32/name
30512     0x11/imm32/alloc-id:fake
30513     Single-float-var-in-some-register/imm32/inouts
30514     0x11/imm32/alloc-id:fake
30515     Single-float-var-in-some-register/imm32/outputs
30516     0x11/imm32/alloc-id:fake
30517     _string_f3_0f_5e_divide/imm32/subx-name
30518     0/imm32/no-rm32
30519     0/imm32/no-r32
30520     0/imm32/no-imm32
30521     0/imm32/no-imm8
30522     0/imm32/no-disp32
30523     1/imm32/xm32-is-first-inout
30524     3/imm32/x32-is-first-output
30525     0x11/imm32/alloc-id:fake
30526     _Primitive-divide-xreg-by-mem/imm32/next
30527 _Primitive-divide-xreg-by-mem:  # (payload primitive)
30528     0x11/imm32/alloc-id:fake:payload
30529     # var1/xreg <- divide var2 => f3 0f 5e/divide var2/xm32 var1/x32
30530     0x11/imm32/alloc-id:fake
30531     _string-divide/imm32/name
30532     0x11/imm32/alloc-id:fake
30533     Single-float-var-in-mem/imm32/inouts
30534     0x11/imm32/alloc-id:fake
30535     Single-float-var-in-some-register/imm32/outputs
30536     0x11/imm32/alloc-id:fake
30537     _string_f3_0f_5e_divide/imm32/subx-name
30538     0/imm32/no-rm32
30539     0/imm32/no-r32
30540     0/imm32/no-imm32
30541     0/imm32/no-imm8
30542     0/imm32/no-disp32
30543     1/imm32/xm32-is-first-inout
30544     3/imm32/x32-is-first-output
30545     0x11/imm32/alloc-id:fake
30546     _Primitive-max-xreg-with-xreg/imm32/next
30547 # - floating-point maximum
30548 _Primitive-max-xreg-with-xreg:  # (payload primitive)
30549     0x11/imm32/alloc-id:fake:payload
30550     # var1/xreg <- max var2 => f3 0f 5f/max var2/xm32 var1/x32
30551     0x11/imm32/alloc-id:fake
30552     _string-max/imm32/name
30553     0x11/imm32/alloc-id:fake
30554     Single-float-var-in-some-register/imm32/inouts
30555     0x11/imm32/alloc-id:fake
30556     Single-float-var-in-some-register/imm32/outputs
30557     0x11/imm32/alloc-id:fake
30558     _string_f3_0f_5f_max/imm32/subx-name
30559     0/imm32/no-rm32
30560     0/imm32/no-r32
30561     0/imm32/no-imm32
30562     0/imm32/no-imm8
30563     0/imm32/no-disp32
30564     1/imm32/xm32-is-first-inout
30565     3/imm32/x32-is-first-output
30566     0x11/imm32/alloc-id:fake
30567     _Primitive-max-xreg-with-mem/imm32/next
30568 _Primitive-max-xreg-with-mem:  # (payload primitive)
30569     0x11/imm32/alloc-id:fake:payload
30570     # var1/xreg <- divide var2 => f3 0f 5f/max var2/xm32 var1/x32
30571     0x11/imm32/alloc-id:fake
30572     _string-max/imm32/name
30573     0x11/imm32/alloc-id:fake
30574     Single-float-var-in-mem/imm32/inouts
30575     0x11/imm32/alloc-id:fake
30576     Single-float-var-in-some-register/imm32/outputs
30577     0x11/imm32/alloc-id:fake
30578     _string_f3_0f_5f_max/imm32/subx-name
30579     0/imm32/no-rm32
30580     0/imm32/no-r32
30581     0/imm32/no-imm32
30582     0/imm32/no-imm8
30583     0/imm32/no-disp32
30584     1/imm32/xm32-is-first-inout
30585     3/imm32/x32-is-first-output
30586     0x11/imm32/alloc-id:fake
30587     _Primitive-min-xreg-with-xreg/imm32/next
30588 # - floating-point minimum
30589 _Primitive-min-xreg-with-xreg:  # (payload primitive)
30590     0x11/imm32/alloc-id:fake:payload
30591     # var1/xreg <- divide var2 => f3 0f 5d/min var2/xm32 var1/x32
30592     0x11/imm32/alloc-id:fake
30593     _string-min/imm32/name
30594     0x11/imm32/alloc-id:fake
30595     Single-float-var-in-some-register/imm32/inouts
30596     0x11/imm32/alloc-id:fake
30597     Single-float-var-in-some-register/imm32/outputs
30598     0x11/imm32/alloc-id:fake
30599     _string_f3_0f_5d_min/imm32/subx-name
30600     0/imm32/no-rm32
30601     0/imm32/no-r32
30602     0/imm32/no-imm32
30603     0/imm32/no-imm8
30604     0/imm32/no-disp32
30605     1/imm32/xm32-is-first-inout
30606     3/imm32/x32-is-first-output
30607     0x11/imm32/alloc-id:fake
30608     _Primitive-min-xreg-with-mem/imm32/next
30609 _Primitive-min-xreg-with-mem:  # (payload primitive)
30610     0x11/imm32/alloc-id:fake:payload
30611     # var1/xreg <- divide var2 => f3 0f 5d/min var2/xm32 var1/x32
30612     0x11/imm32/alloc-id:fake
30613     _string-min/imm32/name
30614     0x11/imm32/alloc-id:fake
30615     Single-float-var-in-mem/imm32/inouts
30616     0x11/imm32/alloc-id:fake
30617     Single-float-var-in-some-register/imm32/outputs
30618     0x11/imm32/alloc-id:fake
30619     _string_f3_0f_5d_min/imm32/subx-name
30620     0/imm32/no-rm32
30621     0/imm32/no-r32
30622     0/imm32/no-imm32
30623     0/imm32/no-imm8
30624     0/imm32/no-disp32
30625     1/imm32/xm32-is-first-inout
30626     3/imm32/x32-is-first-output
30627     0x11/imm32/alloc-id:fake
30628     _Primitive-reciprocal-xreg-to-xreg/imm32/next
30629 # - floating-point reciprocal
30630 _Primitive-reciprocal-xreg-to-xreg:  # (payload primitive)
30631     0x11/imm32/alloc-id:fake:payload
30632     # var1/xreg <- reciprocal var2 => f3 0f 53/reciprocal var2/xm32 var1/x32
30633     0x11/imm32/alloc-id:fake
30634     _string-reciprocal/imm32/name
30635     0x11/imm32/alloc-id:fake
30636     Single-float-var-in-some-register/imm32/inouts
30637     0x11/imm32/alloc-id:fake
30638     Single-float-var-in-some-register/imm32/outputs
30639     0x11/imm32/alloc-id:fake
30640     _string_f3_0f_53_reciprocal/imm32/subx-name
30641     0/imm32/no-rm32
30642     0/imm32/no-r32
30643     0/imm32/no-imm32
30644     0/imm32/no-imm8
30645     0/imm32/no-disp32
30646     1/imm32/xm32-is-first-inout
30647     3/imm32/x32-is-first-output
30648     0x11/imm32/alloc-id:fake
30649     _Primitive-reciprocal-mem-to-xreg/imm32/next
30650 _Primitive-reciprocal-mem-to-xreg:  # (payload primitive)
30651     0x11/imm32/alloc-id:fake:payload
30652     # var1/xreg <- divide var2 => f3 0f 53/reciprocal var2/xm32 var1/x32
30653     0x11/imm32/alloc-id:fake
30654     _string-reciprocal/imm32/name
30655     0x11/imm32/alloc-id:fake
30656     Single-float-var-in-mem/imm32/inouts
30657     0x11/imm32/alloc-id:fake
30658     Single-float-var-in-some-register/imm32/outputs
30659     0x11/imm32/alloc-id:fake
30660     _string_f3_0f_53_reciprocal/imm32/subx-name
30661     0/imm32/no-rm32
30662     0/imm32/no-r32
30663     0/imm32/no-imm32
30664     0/imm32/no-imm8
30665     0/imm32/no-disp32
30666     1/imm32/xm32-is-first-inout
30667     3/imm32/x32-is-first-output
30668     0x11/imm32/alloc-id:fake
30669     _Primitive-square-root-xreg-to-xreg/imm32/next
30670 # - floating-point square root
30671 _Primitive-square-root-xreg-to-xreg:  # (payload primitive)
30672     0x11/imm32/alloc-id:fake:payload
30673     # var1/xreg <- square-root var2 => f3 0f 51/square-root var2/xm32 var1/x32
30674     0x11/imm32/alloc-id:fake
30675     _string-square-root/imm32/name
30676     0x11/imm32/alloc-id:fake
30677     Single-float-var-in-some-register/imm32/inouts
30678     0x11/imm32/alloc-id:fake
30679     Single-float-var-in-some-register/imm32/outputs
30680     0x11/imm32/alloc-id:fake
30681     _string_f3_0f_51_square_root/imm32/subx-name
30682     0/imm32/no-rm32
30683     0/imm32/no-r32
30684     0/imm32/no-imm32
30685     0/imm32/no-imm8
30686     0/imm32/no-disp32
30687     1/imm32/xm32-is-first-inout
30688     3/imm32/x32-is-first-output
30689     0x11/imm32/alloc-id:fake
30690     _Primitive-square-root-mem-to-xreg/imm32/next
30691 _Primitive-square-root-mem-to-xreg:  # (payload primitive)
30692     0x11/imm32/alloc-id:fake:payload
30693     # var1/xreg <- divide var2 => f3 0f 51/square-root var2/xm32 var1/x32
30694     0x11/imm32/alloc-id:fake
30695     _string-square-root/imm32/name
30696     0x11/imm32/alloc-id:fake
30697     Single-float-var-in-mem/imm32/inouts
30698     0x11/imm32/alloc-id:fake
30699     Single-float-var-in-some-register/imm32/outputs
30700     0x11/imm32/alloc-id:fake
30701     _string_f3_0f_51_square_root/imm32/subx-name
30702     0/imm32/no-rm32
30703     0/imm32/no-r32
30704     0/imm32/no-imm32
30705     0/imm32/no-imm8
30706     0/imm32/no-disp32
30707     1/imm32/xm32-is-first-inout
30708     3/imm32/x32-is-first-output
30709     0x11/imm32/alloc-id:fake
30710     _Primitive-inverse-square-root-xreg-to-xreg/imm32/next
30711 # - floating-point inverse square root 1/sqrt(x)
30712 _Primitive-inverse-square-root-xreg-to-xreg:  # (payload primitive)
30713     0x11/imm32/alloc-id:fake:payload
30714     # var1/xreg <- reciprocal var2 => f3 0f 52/inverse-square-root var2/xm32 var1/x32
30715     0x11/imm32/alloc-id:fake
30716     _string-inverse-square-root/imm32/name
30717     0x11/imm32/alloc-id:fake
30718     Single-float-var-in-some-register/imm32/inouts
30719     0x11/imm32/alloc-id:fake
30720     Single-float-var-in-some-register/imm32/outputs
30721     0x11/imm32/alloc-id:fake
30722     _string_f3_0f_52_inverse_square_root/imm32/subx-name
30723     0/imm32/no-rm32
30724     0/imm32/no-r32
30725     0/imm32/no-imm32
30726     0/imm32/no-imm8
30727     0/imm32/no-disp32
30728     1/imm32/xm32-is-first-inout
30729     3/imm32/x32-is-first-output
30730     0x11/imm32/alloc-id:fake
30731     _Primitive-inverse-square-root-mem-to-xreg/imm32/next
30732 _Primitive-inverse-square-root-mem-to-xreg:  # (payload primitive)
30733     0x11/imm32/alloc-id:fake:payload
30734     # var1/xreg <- divide var2 => f3 0f 52/inverse-square-root var2/xm32 var1/x32
30735     0x11/imm32/alloc-id:fake
30736     _string-inverse-square-root/imm32/name
30737     0x11/imm32/alloc-id:fake
30738     Single-float-var-in-mem/imm32/inouts
30739     0x11/imm32/alloc-id:fake
30740     Single-float-var-in-some-register/imm32/outputs
30741     0x11/imm32/alloc-id:fake
30742     _string_f3_0f_52_inverse_square_root/imm32/subx-name
30743     0/imm32/no-rm32
30744     0/imm32/no-r32
30745     0/imm32/no-imm32
30746     0/imm32/no-imm8
30747     0/imm32/no-disp32
30748     1/imm32/xm32-is-first-inout
30749     3/imm32/x32-is-first-output
30750     0x11/imm32/alloc-id:fake
30751     _Primitive-compare-xreg-with-xreg/imm32/next
30752 # - floating-point compare
30753 _Primitive-compare-xreg-with-xreg:  # (payload primitive)
30754     0x11/imm32/alloc-id:fake:payload
30755     # compare var1/reg1 var2/reg2 => 0f 2f/compare var2/x32 var1/xm32
30756     0x11/imm32/alloc-id:fake
30757     _string-compare/imm32/name
30758     0x11/imm32/alloc-id:fake
30759     Two-float-args-in-regs/imm32/inouts
30760     0/imm32/no-outputs
30761     0/imm32/no-outputs
30762     0x11/imm32/alloc-id:fake
30763     _string_0f_2f_compare/imm32/subx-name
30764     0/imm32/no-rm32
30765     0/imm32/no-r32
30766     0/imm32/no-imm32
30767     0/imm32/no-imm8
30768     0/imm32/no-disp32
30769     1/imm32/xm32-is-first-inout
30770     2/imm32/x32-is-second-inout
30771     0x11/imm32/alloc-id:fake
30772     _Primitive-compare-xreg-with-mem/imm32/next
30773 _Primitive-compare-xreg-with-mem:  # (payload primitive)
30774     0x11/imm32/alloc-id:fake:payload
30775     # compare var1/xreg var2 => 0f 2f/compare var1/x32 var2/xm32
30776     0x11/imm32/alloc-id:fake
30777     _string-compare/imm32/name
30778     0x11/imm32/alloc-id:fake
30779     Two-args-float-reg-float-stack/imm32/inouts
30780     0/imm32/no-outputs
30781     0/imm32/no-outputs
30782     0x11/imm32/alloc-id:fake
30783     _string_0f_2f_compare/imm32/subx-name
30784     0/imm32/no-rm32
30785     0/imm32/no-r32
30786     0/imm32/no-imm32
30787     0/imm32/no-imm8
30788     0/imm32/no-disp32
30789     2/imm32/xm32-is-second-inout
30790     1/imm32/x32-is-first-inout
30791     0x11/imm32/alloc-id:fake
30792     _Primitive-break-if-addr</imm32/next
30793 # - branches
30794 _Primitive-break-if-addr<:  # (payload primitive)
30795     0x11/imm32/alloc-id:fake:payload
30796     0x11/imm32/alloc-id:fake
30797     _string-break-if-addr</imm32/name
30798     0/imm32/no-inouts
30799     0/imm32/no-inouts
30800     0/imm32/no-outputs
30801     0/imm32/no-outputs
30802     0x11/imm32/alloc-id:fake
30803     _string_0f_82_jump_break/imm32/subx-name
30804     0/imm32/no-rm32
30805     0/imm32/no-r32
30806     0/imm32/no-imm32
30807     0/imm32/no-imm8
30808     0/imm32/no-disp32
30809     0/imm32/no-xm32
30810     0/imm32/no-x32
30811     0x11/imm32/alloc-id:fake
30812     _Primitive-break-if-addr>=/imm32/next
30813 _Primitive-break-if-addr>=:  # (payload primitive)
30814     0x11/imm32/alloc-id:fake:payload
30815     0x11/imm32/alloc-id:fake
30816     _string-break-if-addr>=/imm32/name
30817     0/imm32/no-inouts
30818     0/imm32/no-inouts
30819     0/imm32/no-outputs
30820     0/imm32/no-outputs
30821     0x11/imm32/alloc-id:fake
30822     _string_0f_83_jump_break/imm32/subx-name
30823     0/imm32/no-rm32
30824     0/imm32/no-r32
30825     0/imm32/no-imm32
30826     0/imm32/no-imm8
30827     0/imm32/no-disp32
30828     0/imm32/no-xm32
30829     0/imm32/no-x32
30830     0x11/imm32/alloc-id:fake
30831     _Primitive-break-if-=/imm32/next
30832 _Primitive-break-if-=:  # (payload primitive)
30833     0x11/imm32/alloc-id:fake:payload
30834     0x11/imm32/alloc-id:fake
30835     _string-break-if-=/imm32/name
30836     0/imm32/no-inouts
30837     0/imm32/no-inouts
30838     0/imm32/no-outputs
30839     0/imm32/no-outputs
30840     0x11/imm32/alloc-id:fake
30841     _string_0f_84_jump_break/imm32/subx-name
30842     0/imm32/no-rm32
30843     0/imm32/no-r32
30844     0/imm32/no-imm32
30845     0/imm32/no-imm8
30846     0/imm32/no-disp32
30847     0/imm32/no-xm32
30848     0/imm32/no-x32
30849     0x11/imm32/alloc-id:fake
30850     _Primitive-break-if-!=/imm32/next
30851 _Primitive-break-if-!=:  # (payload primitive)
30852     0x11/imm32/alloc-id:fake:payload
30853     0x11/imm32/alloc-id:fake
30854     _string-break-if-!=/imm32/name
30855     0/imm32/no-inouts
30856     0/imm32/no-inouts
30857     0/imm32/no-outputs
30858     0/imm32/no-outputs
30859     0x11/imm32/alloc-id:fake
30860     _string_0f_85_jump_break/imm32/subx-name
30861     0/imm32/no-rm32
30862     0/imm32/no-r32
30863     0/imm32/no-imm32
30864     0/imm32/no-imm8
30865     0/imm32/no-disp32
30866     0/imm32/no-xm32
30867     0/imm32/no-x32
30868     0x11/imm32/alloc-id:fake
30869     _Primitive-break-if-addr<=/imm32/next
30870 _Primitive-break-if-addr<=:  # (payload primitive)
30871     0x11/imm32/alloc-id:fake:payload
30872     0x11/imm32/alloc-id:fake
30873     _string-break-if-addr<=/imm32/name
30874     0/imm32/no-inouts
30875     0/imm32/no-inouts
30876     0/imm32/no-outputs
30877     0/imm32/no-outputs
30878     0x11/imm32/alloc-id:fake
30879     _string_0f_86_jump_break/imm32/subx-name
30880     0/imm32/no-rm32
30881     0/imm32/no-r32
30882     0/imm32/no-imm32
30883     0/imm32/no-imm8
30884     0/imm32/no-disp32
30885     0/imm32/no-xm32
30886     0/imm32/no-x32
30887     0x11/imm32/alloc-id:fake
30888     _Primitive-break-if-addr>/imm32/next
30889 _Primitive-break-if-addr>:  # (payload primitive)
30890     0x11/imm32/alloc-id:fake:payload
30891     0x11/imm32/alloc-id:fake
30892     _string-break-if-addr>/imm32/name
30893     0/imm32/no-inouts
30894     0/imm32/no-inouts
30895     0/imm32/no-outputs
30896     0/imm32/no-outputs
30897     0x11/imm32/alloc-id:fake
30898     _string_0f_87_jump_break/imm32/subx-name
30899     0/imm32/no-rm32
30900     0/imm32/no-r32
30901     0/imm32/no-imm32
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-break-if-</imm32/next
30908 _Primitive-break-if-<:  # (payload primitive)
30909     0x11/imm32/alloc-id:fake:payload
30910     0x11/imm32/alloc-id:fake
30911     _string-break-if-</imm32/name
30912     0/imm32/no-inouts
30913     0/imm32/no-inouts
30914     0/imm32/no-outputs
30915     0/imm32/no-outputs
30916     0x11/imm32/alloc-id:fake
30917     _string_0f_8c_jump_break/imm32/subx-name
30918     0/imm32/no-rm32
30919     0/imm32/no-r32
30920     0/imm32/no-imm32
30921     0/imm32/no-imm8
30922     0/imm32/no-disp32
30923     0/imm32/no-xm32
30924     0/imm32/no-x32
30925     0x11/imm32/alloc-id:fake
30926     _Primitive-break-if->=/imm32/next
30927 _Primitive-break-if->=:  # (payload primitive)
30928     0x11/imm32/alloc-id:fake:payload
30929     0x11/imm32/alloc-id:fake
30930     _string-break-if->=/imm32/name
30931     0/imm32/no-inouts
30932     0/imm32/no-inouts
30933     0/imm32/no-outputs
30934     0/imm32/no-outputs
30935     0x11/imm32/alloc-id:fake
30936     _string_0f_8d_jump_break/imm32/subx-name
30937     0/imm32/no-rm32
30938     0/imm32/no-r32
30939     0/imm32/no-imm32
30940     0/imm32/no-imm8
30941     0/imm32/no-disp32
30942     0/imm32/no-xm32
30943     0/imm32/no-x32
30944     0x11/imm32/alloc-id:fake
30945     _Primitive-break-if-<=/imm32/next
30946 _Primitive-break-if-<=:  # (payload primitive)
30947     0x11/imm32/alloc-id:fake:payload
30948     0x11/imm32/alloc-id:fake
30949     _string-break-if-<=/imm32/name
30950     0/imm32/no-inouts
30951     0/imm32/no-inouts
30952     0/imm32/no-outputs
30953     0/imm32/no-outputs
30954     0x11/imm32/alloc-id:fake
30955     _string_0f_8e_jump_break/imm32/subx-name
30956     0/imm32/no-rm32
30957     0/imm32/no-r32
30958     0/imm32/no-imm32
30959     0/imm32/no-imm8
30960     0/imm32/no-disp32
30961     0/imm32/no-xm32
30962     0/imm32/no-x32
30963     0x11/imm32/alloc-id:fake
30964     _Primitive-break-if->/imm32/next
30965 _Primitive-break-if->:  # (payload primitive)
30966     0x11/imm32/alloc-id:fake:payload
30967     0x11/imm32/alloc-id:fake
30968     _string-break-if->/imm32/name
30969     0/imm32/no-inouts
30970     0/imm32/no-inouts
30971     0/imm32/no-outputs
30972     0/imm32/no-outputs
30973     0x11/imm32/alloc-id:fake
30974     _string_0f_8f_jump_break/imm32/subx-name
30975     0/imm32/no-rm32
30976     0/imm32/no-r32
30977     0/imm32/no-imm32
30978     0/imm32/no-imm8
30979     0/imm32/no-disp32
30980     0/imm32/no-xm32
30981     0/imm32/no-x32
30982     0x11/imm32/alloc-id:fake
30983     _Primitive-break/imm32/next
30984 _Primitive-break:  # (payload primitive)
30985     0x11/imm32/alloc-id:fake:payload
30986     0x11/imm32/alloc-id:fake
30987     _string-break/imm32/name
30988     0/imm32/no-inouts
30989     0/imm32/no-inouts
30990     0/imm32/no-outputs
30991     0/imm32/no-outputs
30992     0x11/imm32/alloc-id:fake
30993     _string_e9_jump_break/imm32/subx-name
30994     0/imm32/no-rm32
30995     0/imm32/no-r32
30996     0/imm32/no-imm32
30997     0/imm32/no-imm8
30998     0/imm32/no-disp32
30999     0/imm32/no-xm32
31000     0/imm32/no-x32
31001     0x11/imm32/alloc-id:fake
31002     _Primitive-loop-if-addr</imm32/next
31003 _Primitive-loop-if-addr<:  # (payload primitive)
31004     0x11/imm32/alloc-id:fake:payload
31005     0x11/imm32/alloc-id:fake
31006     _string-loop-if-addr</imm32/name
31007     0/imm32/no-inouts
31008     0/imm32/no-inouts
31009     0/imm32/no-outputs
31010     0/imm32/no-outputs
31011     0x11/imm32/alloc-id:fake
31012     _string_0f_82_jump_loop/imm32/subx-name
31013     0/imm32/no-rm32
31014     0/imm32/no-r32
31015     0/imm32/no-imm32
31016     0/imm32/no-imm8
31017     0/imm32/no-disp32
31018     0/imm32/no-xm32
31019     0/imm32/no-x32
31020     0x11/imm32/alloc-id:fake
31021     _Primitive-loop-if-addr>=/imm32/next
31022 _Primitive-loop-if-addr>=:  # (payload primitive)
31023     0x11/imm32/alloc-id:fake:payload
31024     0x11/imm32/alloc-id:fake
31025     _string-loop-if-addr>=/imm32/name
31026     0/imm32/no-inouts
31027     0/imm32/no-inouts
31028     0/imm32/no-outputs
31029     0/imm32/no-outputs
31030     0x11/imm32/alloc-id:fake
31031     _string_0f_83_jump_loop/imm32/subx-name
31032     0/imm32/no-rm32
31033     0/imm32/no-r32
31034     0/imm32/no-imm32
31035     0/imm32/no-imm8
31036     0/imm32/no-disp32
31037     0/imm32/no-xm32
31038     0/imm32/no-x32
31039     0x11/imm32/alloc-id:fake
31040     _Primitive-loop-if-=/imm32/next
31041 _Primitive-loop-if-=:  # (payload primitive)
31042     0x11/imm32/alloc-id:fake:payload
31043     0x11/imm32/alloc-id:fake
31044     _string-loop-if-=/imm32/name
31045     0/imm32/no-inouts
31046     0/imm32/no-inouts
31047     0/imm32/no-outputs
31048     0/imm32/no-outputs
31049     0x11/imm32/alloc-id:fake
31050     _string_0f_84_jump_loop/imm32/subx-name
31051     0/imm32/no-rm32
31052     0/imm32/no-r32
31053     0/imm32/no-imm32
31054     0/imm32/no-imm8
31055     0/imm32/no-disp32
31056     0/imm32/no-xm32
31057     0/imm32/no-x32
31058     0x11/imm32/alloc-id:fake
31059     _Primitive-loop-if-!=/imm32/next
31060 _Primitive-loop-if-!=:  # (payload primitive)
31061     0x11/imm32/alloc-id:fake:payload
31062     0x11/imm32/alloc-id:fake
31063     _string-loop-if-!=/imm32/name
31064     0/imm32/no-inouts
31065     0/imm32/no-inouts
31066     0/imm32/no-outputs
31067     0/imm32/no-outputs
31068     0x11/imm32/alloc-id:fake
31069     _string_0f_85_jump_loop/imm32/subx-name
31070     0/imm32/no-rm32
31071     0/imm32/no-r32
31072     0/imm32/no-imm32
31073     0/imm32/no-imm8
31074     0/imm32/no-disp32
31075     0/imm32/no-xm32
31076     0/imm32/no-x32
31077     0x11/imm32/alloc-id:fake
31078     _Primitive-loop-if-addr<=/imm32/next
31079 _Primitive-loop-if-addr<=:  # (payload primitive)
31080     0x11/imm32/alloc-id:fake:payload
31081     0x11/imm32/alloc-id:fake
31082     _string-loop-if-addr<=/imm32/name
31083     0/imm32/no-inouts
31084     0/imm32/no-inouts
31085     0/imm32/no-outputs
31086     0/imm32/no-outputs
31087     0x11/imm32/alloc-id:fake
31088     _string_0f_86_jump_loop/imm32/subx-name
31089     0/imm32/no-rm32
31090     0/imm32/no-r32
31091     0/imm32/no-imm32
31092     0/imm32/no-imm8
31093     0/imm32/no-disp32
31094     0/imm32/no-xm32
31095     0/imm32/no-x32
31096     0x11/imm32/alloc-id:fake
31097     _Primitive-loop-if-addr>/imm32/next
31098 _Primitive-loop-if-addr>:  # (payload primitive)
31099     0x11/imm32/alloc-id:fake:payload
31100     0x11/imm32/alloc-id:fake
31101     _string-loop-if-addr>/imm32/name
31102     0/imm32/no-inouts
31103     0/imm32/no-inouts
31104     0/imm32/no-outputs
31105     0/imm32/no-outputs
31106     0x11/imm32/alloc-id:fake
31107     _string_0f_87_jump_loop/imm32/subx-name
31108     0/imm32/no-rm32
31109     0/imm32/no-r32
31110     0/imm32/no-imm32
31111     0/imm32/no-imm8
31112     0/imm32/no-disp32
31113     0/imm32/no-xm32
31114     0/imm32/no-x32
31115     0x11/imm32/alloc-id:fake
31116     _Primitive-loop-if-</imm32/next
31117 _Primitive-loop-if-<:  # (payload primitive)
31118     0x11/imm32/alloc-id:fake:payload
31119     0x11/imm32/alloc-id:fake
31120     _string-loop-if-</imm32/name
31121     0/imm32/no-inouts
31122     0/imm32/no-inouts
31123     0/imm32/no-outputs
31124     0/imm32/no-outputs
31125     0x11/imm32/alloc-id:fake
31126     _string_0f_8c_jump_loop/imm32/subx-name
31127     0/imm32/no-rm32
31128     0/imm32/no-r32
31129     0/imm32/no-imm32
31130     0/imm32/no-imm8
31131     0/imm32/no-disp32
31132     0/imm32/no-xm32
31133     0/imm32/no-x32
31134     0x11/imm32/alloc-id:fake
31135     _Primitive-loop-if->=/imm32/next
31136 _Primitive-loop-if->=:  # (payload primitive)
31137     0x11/imm32/alloc-id:fake:payload
31138     0x11/imm32/alloc-id:fake
31139     _string-loop-if->=/imm32/name
31140     0/imm32/no-inouts
31141     0/imm32/no-inouts
31142     0/imm32/no-outputs
31143     0/imm32/no-outputs
31144     0x11/imm32/alloc-id:fake
31145     _string_0f_8d_jump_loop/imm32/subx-name
31146     0/imm32/no-rm32
31147     0/imm32/no-r32
31148     0/imm32/no-imm32
31149     0/imm32/no-imm8
31150     0/imm32/no-disp32
31151     0/imm32/no-xm32
31152     0/imm32/no-x32
31153     0x11/imm32/alloc-id:fake
31154     _Primitive-loop-if-<=/imm32/next
31155 _Primitive-loop-if-<=:  # (payload primitive)
31156     0x11/imm32/alloc-id:fake:payload
31157     0x11/imm32/alloc-id:fake
31158     _string-loop-if-<=/imm32/name
31159     0/imm32/no-inouts
31160     0/imm32/no-inouts
31161     0/imm32/no-outputs
31162     0/imm32/no-outputs
31163     0x11/imm32/alloc-id:fake
31164     _string_0f_8e_jump_loop/imm32/subx-name
31165     0/imm32/no-rm32
31166     0/imm32/no-r32
31167     0/imm32/no-imm32
31168     0/imm32/no-imm8
31169     0/imm32/no-disp32
31170     0/imm32/no-xm32
31171     0/imm32/no-x32
31172     0x11/imm32/alloc-id:fake
31173     _Primitive-loop-if->/imm32/next
31174 _Primitive-loop-if->:  # (payload primitive)
31175     0x11/imm32/alloc-id:fake:payload
31176     0x11/imm32/alloc-id:fake
31177     _string-loop-if->/imm32/name
31178     0/imm32/no-inouts
31179     0/imm32/no-inouts
31180     0/imm32/no-outputs
31181     0/imm32/no-outputs
31182     0x11/imm32/alloc-id:fake
31183     _string_0f_8f_jump_loop/imm32/subx-name
31184     0/imm32/no-rm32
31185     0/imm32/no-r32
31186     0/imm32/no-imm32
31187     0/imm32/no-imm8
31188     0/imm32/no-disp32
31189     0/imm32/no-xm32
31190     0/imm32/no-x32
31191     0x11/imm32/alloc-id:fake
31192     _Primitive-loop/imm32/next  # we probably don't need an unconditional break
31193 _Primitive-loop:  # (payload primitive)
31194     0x11/imm32/alloc-id:fake:payload
31195     0x11/imm32/alloc-id:fake
31196     _string-loop/imm32/name
31197     0/imm32/no-inouts
31198     0/imm32/no-inouts
31199     0/imm32/no-outputs
31200     0/imm32/no-outputs
31201     0x11/imm32/alloc-id:fake
31202     _string_e9_jump_loop/imm32/subx-name
31203     0/imm32/no-rm32
31204     0/imm32/no-r32
31205     0/imm32/no-imm32
31206     0/imm32/no-imm8
31207     0/imm32/no-disp32
31208     0/imm32/no-xm32
31209     0/imm32/no-x32
31210     0x11/imm32/alloc-id:fake
31211     _Primitive-break-if-addr<-named/imm32/next
31212 # - branches to named blocks
31213 _Primitive-break-if-addr<-named:  # (payload primitive)
31214     0x11/imm32/alloc-id:fake:payload
31215     0x11/imm32/alloc-id:fake
31216     _string-break-if-addr</imm32/name
31217     0x11/imm32/alloc-id:fake
31218     Single-lit-var/imm32/inouts
31219     0/imm32/no-outputs
31220     0/imm32/no-outputs
31221     0x11/imm32/alloc-id:fake
31222     _string_0f_82_jump_label/imm32/subx-name
31223     0/imm32/no-rm32
31224     0/imm32/no-r32
31225     0/imm32/no-imm32
31226     0/imm32/no-imm8
31227     1/imm32/disp32-is-first-inout
31228     0/imm32/no-xm32
31229     0/imm32/no-x32
31230     0x11/imm32/alloc-id:fake
31231     _Primitive-break-if-addr>=-named/imm32/next
31232 _Primitive-break-if-addr>=-named:  # (payload primitive)
31233     0x11/imm32/alloc-id:fake:payload
31234     0x11/imm32/alloc-id:fake
31235     _string-break-if-addr>=/imm32/name
31236     0x11/imm32/alloc-id:fake
31237     Single-lit-var/imm32/inouts
31238     0/imm32/no-outputs
31239     0/imm32/no-outputs
31240     0x11/imm32/alloc-id:fake
31241     _string_0f_83_jump_label/imm32/subx-name
31242     0/imm32/no-rm32
31243     0/imm32/no-r32
31244     0/imm32/no-imm32
31245     0/imm32/no-imm8
31246     1/imm32/disp32-is-first-inout
31247     0/imm32/no-xm32
31248     0/imm32/no-x32
31249     0x11/imm32/alloc-id:fake
31250     _Primitive-break-if-=-named/imm32/next
31251 _Primitive-break-if-=-named:  # (payload primitive)
31252     0x11/imm32/alloc-id:fake:payload
31253     0x11/imm32/alloc-id:fake
31254     _string-break-if-=/imm32/name
31255     0x11/imm32/alloc-id:fake
31256     Single-lit-var/imm32/inouts
31257     0/imm32/no-outputs
31258     0/imm32/no-outputs
31259     0x11/imm32/alloc-id:fake
31260     _string_0f_84_jump_label/imm32/subx-name
31261     0/imm32/no-rm32
31262     0/imm32/no-r32
31263     0/imm32/no-imm32
31264     0/imm32/no-imm8
31265     1/imm32/disp32-is-first-inout
31266     0/imm32/no-xm32
31267     0/imm32/no-x32
31268     0x11/imm32/alloc-id:fake
31269     _Primitive-break-if-!=-named/imm32/next
31270 _Primitive-break-if-!=-named:  # (payload primitive)
31271     0x11/imm32/alloc-id:fake:payload
31272     0x11/imm32/alloc-id:fake
31273     _string-break-if-!=/imm32/name
31274     0x11/imm32/alloc-id:fake
31275     Single-lit-var/imm32/inouts
31276     0/imm32/no-outputs
31277     0/imm32/no-outputs
31278     0x11/imm32/alloc-id:fake
31279     _string_0f_85_jump_label/imm32/subx-name
31280     0/imm32/no-rm32
31281     0/imm32/no-r32
31282     0/imm32/no-imm32
31283     0/imm32/no-imm8
31284     1/imm32/disp32-is-first-inout
31285     0/imm32/no-xm32
31286     0/imm32/no-x32
31287     0x11/imm32/alloc-id:fake
31288     _Primitive-break-if-addr<=-named/imm32/next
31289 _Primitive-break-if-addr<=-named:  # (payload primitive)
31290     0x11/imm32/alloc-id:fake:payload
31291     0x11/imm32/alloc-id:fake
31292     _string-break-if-addr<=/imm32/name
31293     0x11/imm32/alloc-id:fake
31294     Single-lit-var/imm32/inouts
31295     0/imm32/no-outputs
31296     0/imm32/no-outputs
31297     0x11/imm32/alloc-id:fake
31298     _string_0f_86_jump_label/imm32/subx-name
31299     0/imm32/no-rm32
31300     0/imm32/no-r32
31301     0/imm32/no-imm32
31302     0/imm32/no-imm8
31303     1/imm32/disp32-is-first-inout
31304     0/imm32/no-xm32
31305     0/imm32/no-x32
31306     0x11/imm32/alloc-id:fake
31307     _Primitive-break-if-addr>-named/imm32/next
31308 _Primitive-break-if-addr>-named:  # (payload primitive)
31309     0x11/imm32/alloc-id:fake:payload
31310     0x11/imm32/alloc-id:fake
31311     _string-break-if-addr>/imm32/name
31312     0x11/imm32/alloc-id:fake
31313     Single-lit-var/imm32/inouts
31314     0/imm32/no-outputs
31315     0/imm32/no-outputs
31316     0x11/imm32/alloc-id:fake
31317     _string_0f_87_jump_label/imm32/subx-name
31318     0/imm32/no-rm32
31319     0/imm32/no-r32
31320     0/imm32/no-imm32
31321     0/imm32/no-imm8
31322     1/imm32/disp32-is-first-inout
31323     0/imm32/no-xm32
31324     0/imm32/no-x32
31325     0x11/imm32/alloc-id:fake
31326     _Primitive-break-if-<-named/imm32/next
31327 _Primitive-break-if-<-named:  # (payload primitive)
31328     0x11/imm32/alloc-id:fake:payload
31329     0x11/imm32/alloc-id:fake
31330     _string-break-if-</imm32/name
31331     0x11/imm32/alloc-id:fake
31332     Single-lit-var/imm32/inouts
31333     0/imm32/no-outputs
31334     0/imm32/no-outputs
31335     0x11/imm32/alloc-id:fake
31336     _string_0f_8c_jump_label/imm32/subx-name
31337     0/imm32/no-rm32
31338     0/imm32/no-r32
31339     0/imm32/no-imm32
31340     0/imm32/no-imm8
31341     1/imm32/disp32-is-first-inout
31342     0/imm32/no-xm32
31343     0/imm32/no-x32
31344     0x11/imm32/alloc-id:fake
31345     _Primitive-break-if->=-named/imm32/next
31346 _Primitive-break-if->=-named:  # (payload primitive)
31347     0x11/imm32/alloc-id:fake:payload
31348     0x11/imm32/alloc-id:fake
31349     _string-break-if->=/imm32/name
31350     0x11/imm32/alloc-id:fake
31351     Single-lit-var/imm32/inouts
31352     0/imm32/no-outputs
31353     0/imm32/no-outputs
31354     0x11/imm32/alloc-id:fake
31355     _string_0f_8d_jump_label/imm32/subx-name
31356     0/imm32/no-rm32
31357     0/imm32/no-r32
31358     0/imm32/no-imm32
31359     0/imm32/no-imm8
31360     1/imm32/disp32-is-first-inout
31361     0/imm32/no-xm32
31362     0/imm32/no-x32
31363     0x11/imm32/alloc-id:fake
31364     _Primitive-break-if-<=-named/imm32/next
31365 _Primitive-break-if-<=-named:  # (payload primitive)
31366     0x11/imm32/alloc-id:fake:payload
31367     0x11/imm32/alloc-id:fake
31368     _string-break-if-<=/imm32/name
31369     0x11/imm32/alloc-id:fake
31370     Single-lit-var/imm32/inouts
31371     0/imm32/no-outputs
31372     0/imm32/no-outputs
31373     0x11/imm32/alloc-id:fake
31374     _string_0f_8e_jump_label/imm32/subx-name
31375     0/imm32/no-rm32
31376     0/imm32/no-r32
31377     0/imm32/no-imm32
31378     0/imm32/no-imm8
31379     1/imm32/disp32-is-first-inout
31380     0/imm32/no-xm32
31381     0/imm32/no-x32
31382     0x11/imm32/alloc-id:fake
31383     _Primitive-break-if->-named/imm32/next
31384 _Primitive-break-if->-named:  # (payload primitive)
31385     0x11/imm32/alloc-id:fake:payload
31386     0x11/imm32/alloc-id:fake
31387     _string-break-if->/imm32/name
31388     0x11/imm32/alloc-id:fake
31389     Single-lit-var/imm32/inouts
31390     0/imm32/no-outputs
31391     0/imm32/no-outputs
31392     0x11/imm32/alloc-id:fake
31393     _string_0f_8f_jump_label/imm32/subx-name
31394     0/imm32/no-rm32
31395     0/imm32/no-r32
31396     0/imm32/no-imm32
31397     0/imm32/no-imm8
31398     1/imm32/disp32-is-first-inout
31399     0/imm32/no-xm32
31400     0/imm32/no-x32
31401     0x11/imm32/alloc-id:fake
31402     _Primitive-break-named/imm32/next
31403 _Primitive-break-named:  # (payload primitive)
31404     0x11/imm32/alloc-id:fake:payload
31405     0x11/imm32/alloc-id:fake
31406     _string-break/imm32/name
31407     0x11/imm32/alloc-id:fake
31408     Single-lit-var/imm32/inouts
31409     0/imm32/no-outputs
31410     0/imm32/no-outputs
31411     0x11/imm32/alloc-id:fake
31412     _string_e9_jump_label/imm32/subx-name
31413     0/imm32/no-rm32
31414     0/imm32/no-r32
31415     0/imm32/no-imm32
31416     0/imm32/no-imm8
31417     1/imm32/disp32-is-first-inout
31418     0/imm32/no-xm32
31419     0/imm32/no-x32
31420     0x11/imm32/alloc-id:fake
31421     _Primitive-loop-if-addr<-named/imm32/next
31422 _Primitive-loop-if-addr<-named:  # (payload primitive)
31423     0x11/imm32/alloc-id:fake:payload
31424     0x11/imm32/alloc-id:fake
31425     _string-loop-if-addr</imm32/name
31426     0x11/imm32/alloc-id:fake
31427     Single-lit-var/imm32/inouts
31428     0/imm32/no-outputs
31429     0/imm32/no-outputs
31430     0x11/imm32/alloc-id:fake
31431     _string_0f_82_jump_label/imm32/subx-name
31432     0/imm32/no-rm32
31433     0/imm32/no-r32
31434     0/imm32/no-imm32
31435     0/imm32/no-imm8
31436     1/imm32/disp32-is-first-inout
31437     0/imm32/no-xm32
31438     0/imm32/no-x32
31439     0x11/imm32/alloc-id:fake
31440     _Primitive-loop-if-addr>=-named/imm32/next
31441 _Primitive-loop-if-addr>=-named:  # (payload primitive)
31442     0x11/imm32/alloc-id:fake:payload
31443     0x11/imm32/alloc-id:fake
31444     _string-loop-if-addr>=/imm32/name
31445     0x11/imm32/alloc-id:fake
31446     Single-lit-var/imm32/inouts
31447     0/imm32/no-outputs
31448     0/imm32/no-outputs
31449     0x11/imm32/alloc-id:fake
31450     _string_0f_83_jump_label/imm32/subx-name
31451     0/imm32/no-rm32
31452     0/imm32/no-r32
31453     0/imm32/no-imm32
31454     0/imm32/no-imm8
31455     1/imm32/disp32-is-first-inout
31456     0/imm32/no-xm32
31457     0/imm32/no-x32
31458     0x11/imm32/alloc-id:fake
31459     _Primitive-loop-if-=-named/imm32/next
31460 _Primitive-loop-if-=-named:  # (payload primitive)
31461     0x11/imm32/alloc-id:fake:payload
31462     0x11/imm32/alloc-id:fake
31463     _string-loop-if-=/imm32/name
31464     0x11/imm32/alloc-id:fake
31465     Single-lit-var/imm32/inouts
31466     0/imm32/no-outputs
31467     0/imm32/no-outputs
31468     0x11/imm32/alloc-id:fake
31469     _string_0f_84_jump_label/imm32/subx-name
31470     0/imm32/no-rm32
31471     0/imm32/no-r32
31472     0/imm32/no-imm32
31473     0/imm32/no-imm8
31474     1/imm32/disp32-is-first-inout
31475     0/imm32/no-xm32
31476     0/imm32/no-x32
31477     0x11/imm32/alloc-id:fake
31478     _Primitive-loop-if-!=-named/imm32/next
31479 _Primitive-loop-if-!=-named:  # (payload primitive)
31480     0x11/imm32/alloc-id:fake:payload
31481     0x11/imm32/alloc-id:fake
31482     _string-loop-if-!=/imm32/name
31483     0x11/imm32/alloc-id:fake
31484     Single-lit-var/imm32/inouts
31485     0/imm32/no-outputs
31486     0/imm32/no-outputs
31487     0x11/imm32/alloc-id:fake
31488     _string_0f_85_jump_label/imm32/subx-name
31489     0/imm32/no-rm32
31490     0/imm32/no-r32
31491     0/imm32/no-imm32
31492     0/imm32/no-imm8
31493     1/imm32/disp32-is-first-inout
31494     0/imm32/no-xm32
31495     0/imm32/no-x32
31496     0x11/imm32/alloc-id:fake
31497     _Primitive-loop-if-addr<=-named/imm32/next
31498 _Primitive-loop-if-addr<=-named:  # (payload primitive)
31499     0x11/imm32/alloc-id:fake:payload
31500     0x11/imm32/alloc-id:fake
31501     _string-loop-if-addr<=/imm32/name
31502     0x11/imm32/alloc-id:fake
31503     Single-lit-var/imm32/inouts
31504     0/imm32/no-outputs
31505     0/imm32/no-outputs
31506     0x11/imm32/alloc-id:fake
31507     _string_0f_86_jump_label/imm32/subx-name
31508     0/imm32/no-rm32
31509     0/imm32/no-r32
31510     0/imm32/no-imm32
31511     0/imm32/no-imm8
31512     1/imm32/disp32-is-first-inout
31513     0/imm32/no-xm32
31514     0/imm32/no-x32
31515     0x11/imm32/alloc-id:fake
31516     _Primitive-loop-if-addr>-named/imm32/next
31517 _Primitive-loop-if-addr>-named:  # (payload primitive)
31518     0x11/imm32/alloc-id:fake:payload
31519     0x11/imm32/alloc-id:fake
31520     _string-loop-if-addr>/imm32/name
31521     0x11/imm32/alloc-id:fake
31522     Single-lit-var/imm32/inouts
31523     0/imm32/no-outputs
31524     0/imm32/no-outputs
31525     0x11/imm32/alloc-id:fake
31526     _string_0f_87_jump_label/imm32/subx-name
31527     0/imm32/no-rm32
31528     0/imm32/no-r32
31529     0/imm32/no-imm32
31530     0/imm32/no-imm8
31531     1/imm32/disp32-is-first-inout
31532     0/imm32/no-xm32
31533     0/imm32/no-x32
31534     0x11/imm32/alloc-id:fake
31535     _Primitive-loop-if-<-named/imm32/next
31536 _Primitive-loop-if-<-named:  # (payload primitive)
31537     0x11/imm32/alloc-id:fake:payload
31538     0x11/imm32/alloc-id:fake
31539     _string-loop-if-</imm32/name
31540     0x11/imm32/alloc-id:fake
31541     Single-lit-var/imm32/inouts
31542     0/imm32/no-outputs
31543     0/imm32/no-outputs
31544     0x11/imm32/alloc-id:fake
31545     _string_0f_8c_jump_label/imm32/subx-name
31546     0/imm32/no-rm32
31547     0/imm32/no-r32
31548     0/imm32/no-imm32
31549     0/imm32/no-imm8
31550     1/imm32/disp32-is-first-inout
31551     0/imm32/no-xm32
31552     0/imm32/no-x32
31553     0x11/imm32/alloc-id:fake
31554     _Primitive-loop-if->=-named/imm32/next
31555 _Primitive-loop-if->=-named:  # (payload primitive)
31556     0x11/imm32/alloc-id:fake:payload
31557     0x11/imm32/alloc-id:fake
31558     _string-loop-if->=/imm32/name
31559     0x11/imm32/alloc-id:fake
31560     Single-lit-var/imm32/inouts
31561     0/imm32/no-outputs
31562     0/imm32/no-outputs
31563     0x11/imm32/alloc-id:fake
31564     _string_0f_8d_jump_label/imm32/subx-name
31565     0/imm32/no-rm32
31566     0/imm32/no-r32
31567     0/imm32/no-imm32
31568     0/imm32/no-imm8
31569     1/imm32/disp32-is-first-inout
31570     0/imm32/no-xm32
31571     0/imm32/no-x32
31572     0x11/imm32/alloc-id:fake
31573     _Primitive-loop-if-<=-named/imm32/next
31574 _Primitive-loop-if-<=-named:  # (payload primitive)
31575     0x11/imm32/alloc-id:fake:payload
31576     0x11/imm32/alloc-id:fake
31577     _string-loop-if-<=/imm32/name
31578     0x11/imm32/alloc-id:fake
31579     Single-lit-var/imm32/inouts
31580     0/imm32/no-outputs
31581     0/imm32/no-outputs
31582     0x11/imm32/alloc-id:fake
31583     _string_0f_8e_jump_label/imm32/subx-name
31584     0/imm32/no-rm32
31585     0/imm32/no-r32
31586     0/imm32/no-imm32
31587     0/imm32/no-imm8
31588     1/imm32/disp32-is-first-inout
31589     0/imm32/no-xm32
31590     0/imm32/no-x32
31591     0x11/imm32/alloc-id:fake
31592     _Primitive-loop-if->-named/imm32/next
31593 _Primitive-loop-if->-named:  # (payload primitive)
31594     0x11/imm32/alloc-id:fake:payload
31595     0x11/imm32/alloc-id:fake
31596     _string-loop-if->/imm32/name
31597     0x11/imm32/alloc-id:fake
31598     Single-lit-var/imm32/inouts
31599     0/imm32/no-outputs
31600     0/imm32/no-outputs
31601     0x11/imm32/alloc-id:fake
31602     _string_0f_8f_jump_label/imm32/subx-name
31603     0/imm32/no-rm32
31604     0/imm32/no-r32
31605     0/imm32/no-imm32
31606     0/imm32/no-imm8
31607     1/imm32/disp32-is-first-inout
31608     0/imm32/no-xm32
31609     0/imm32/no-x32
31610     0x11/imm32/alloc-id:fake
31611     _Primitive-loop-named/imm32/next  # we probably don't need an unconditional break
31612 _Primitive-loop-named:  # (payload primitive)
31613     0x11/imm32/alloc-id:fake:payload
31614     0x11/imm32/alloc-id:fake
31615     _string-loop/imm32/name
31616     0x11/imm32/alloc-id:fake
31617     Single-lit-var/imm32/inouts
31618     0/imm32/no-outputs
31619     0/imm32/no-outputs
31620     0x11/imm32/alloc-id:fake
31621     _string_e9_jump_label/imm32/subx-name
31622     0/imm32/no-rm32
31623     0/imm32/no-r32
31624     0/imm32/no-imm32
31625     0/imm32/no-imm8
31626     1/imm32/disp32-is-first-inout
31627     0/imm32/no-xm32
31628     0/imm32/no-x32
31629     0x11/imm32/alloc-id:fake
31630     _Primitive-break-if-float</imm32/next
31631 # - branches based on floating-point comparisons
31632 _Primitive-break-if-float<:  # (payload primitive)
31633     0x11/imm32/alloc-id:fake:payload
31634     0x11/imm32/alloc-id:fake
31635     _string-break-if-float</imm32/name
31636     0/imm32/no-inouts
31637     0/imm32/no-inouts
31638     0/imm32/no-outputs
31639     0/imm32/no-outputs
31640     0x11/imm32/alloc-id:fake
31641     _string_0f_82_jump_break/imm32/subx-name
31642     0/imm32/no-rm32
31643     0/imm32/no-r32
31644     0/imm32/no-imm32
31645     0/imm32/no-imm8
31646     0/imm32/no-disp32
31647     0/imm32/no-xm32
31648     0/imm32/no-x32
31649     0x11/imm32/alloc-id:fake
31650     _Primitive-break-if-float>=/imm32/next
31651 _Primitive-break-if-float>=:  # (payload primitive)
31652     0x11/imm32/alloc-id:fake:payload
31653     0x11/imm32/alloc-id:fake
31654     _string-break-if-float>=/imm32/name
31655     0/imm32/no-inouts
31656     0/imm32/no-inouts
31657     0/imm32/no-outputs
31658     0/imm32/no-outputs
31659     0x11/imm32/alloc-id:fake
31660     _string_0f_83_jump_break/imm32/subx-name
31661     0/imm32/no-rm32
31662     0/imm32/no-r32
31663     0/imm32/no-imm32
31664     0/imm32/no-imm8
31665     0/imm32/no-disp32
31666     0/imm32/no-xm32
31667     0/imm32/no-x32
31668     0x11/imm32/alloc-id:fake
31669     _Primitive-break-if-float<=/imm32/next
31670 _Primitive-break-if-float<=:  # (payload primitive)
31671     0x11/imm32/alloc-id:fake:payload
31672     0x11/imm32/alloc-id:fake
31673     _string-break-if-float<=/imm32/name
31674     0/imm32/no-inouts
31675     0/imm32/no-inouts
31676     0/imm32/no-outputs
31677     0/imm32/no-outputs
31678     0x11/imm32/alloc-id:fake
31679     _string_0f_86_jump_break/imm32/subx-name
31680     0/imm32/no-rm32
31681     0/imm32/no-r32
31682     0/imm32/no-imm32
31683     0/imm32/no-imm8
31684     0/imm32/no-disp32
31685     0/imm32/no-xm32
31686     0/imm32/no-x32
31687     0x11/imm32/alloc-id:fake
31688     _Primitive-break-if-float>/imm32/next
31689 _Primitive-break-if-float>:  # (payload primitive)
31690     0x11/imm32/alloc-id:fake:payload
31691     0x11/imm32/alloc-id:fake
31692     _string-break-if-float>/imm32/name
31693     0/imm32/no-inouts
31694     0/imm32/no-inouts
31695     0/imm32/no-outputs
31696     0/imm32/no-outputs
31697     0x11/imm32/alloc-id:fake
31698     _string_0f_87_jump_break/imm32/subx-name
31699     0/imm32/no-rm32
31700     0/imm32/no-r32
31701     0/imm32/no-imm32
31702     0/imm32/no-imm8
31703     0/imm32/no-disp32
31704     0/imm32/no-xm32
31705     0/imm32/no-x32
31706     0x11/imm32/alloc-id:fake
31707     _Primitive-loop-if-float</imm32/next
31708 _Primitive-loop-if-float<:  # (payload primitive)
31709     0x11/imm32/alloc-id:fake:payload
31710     0x11/imm32/alloc-id:fake
31711     _string-loop-if-float</imm32/name
31712     0/imm32/no-inouts
31713     0/imm32/no-inouts
31714     0/imm32/no-outputs
31715     0/imm32/no-outputs
31716     0x11/imm32/alloc-id:fake
31717     _string_0f_82_jump_loop/imm32/subx-name
31718     0/imm32/no-rm32
31719     0/imm32/no-r32
31720     0/imm32/no-imm32
31721     0/imm32/no-imm8
31722     0/imm32/no-disp32
31723     0/imm32/no-xm32
31724     0/imm32/no-x32
31725     0x11/imm32/alloc-id:fake
31726     _Primitive-loop-if-float>=/imm32/next
31727 _Primitive-loop-if-float>=:  # (payload primitive)
31728     0x11/imm32/alloc-id:fake:payload
31729     0x11/imm32/alloc-id:fake
31730     _string-loop-if-float>=/imm32/name
31731     0/imm32/no-inouts
31732     0/imm32/no-inouts
31733     0/imm32/no-outputs
31734     0/imm32/no-outputs
31735     0x11/imm32/alloc-id:fake
31736     _string_0f_83_jump_loop/imm32/subx-name
31737     0/imm32/no-rm32
31738     0/imm32/no-r32
31739     0/imm32/no-imm32
31740     0/imm32/no-imm8
31741     0/imm32/no-disp32
31742     0/imm32/no-xm32
31743     0/imm32/no-x32
31744     0x11/imm32/alloc-id:fake
31745     _Primitive-loop-if-float<=/imm32/next
31746 _Primitive-loop-if-float<=:  # (payload primitive)
31747     0x11/imm32/alloc-id:fake:payload
31748     0x11/imm32/alloc-id:fake
31749     _string-loop-if-float<=/imm32/name
31750     0/imm32/no-inouts
31751     0/imm32/no-inouts
31752     0/imm32/no-outputs
31753     0/imm32/no-outputs
31754     0x11/imm32/alloc-id:fake
31755     _string_0f_86_jump_loop/imm32/subx-name
31756     0/imm32/no-rm32
31757     0/imm32/no-r32
31758     0/imm32/no-imm32
31759     0/imm32/no-imm8
31760     0/imm32/no-disp32
31761     0/imm32/no-xm32
31762     0/imm32/no-x32
31763     0x11/imm32/alloc-id:fake
31764     _Primitive-loop-if-float>/imm32/next
31765 _Primitive-loop-if-float>:  # (payload primitive)
31766     0x11/imm32/alloc-id:fake:payload
31767     0x11/imm32/alloc-id:fake
31768     _string-loop-if-float>/imm32/name
31769     0/imm32/no-inouts
31770     0/imm32/no-inouts
31771     0/imm32/no-outputs
31772     0/imm32/no-outputs
31773     0x11/imm32/alloc-id:fake
31774     _string_0f_87_jump_loop/imm32/subx-name
31775     0/imm32/no-rm32
31776     0/imm32/no-r32
31777     0/imm32/no-imm32
31778     0/imm32/no-imm8
31779     0/imm32/no-disp32
31780     0/imm32/no-xm32
31781     0/imm32/no-x32
31782     0x11/imm32/alloc-id:fake
31783     _Primitive-break-if-float<-named/imm32/next
31784 _Primitive-break-if-float<-named:  # (payload primitive)
31785     0x11/imm32/alloc-id:fake:payload
31786     0x11/imm32/alloc-id:fake
31787     _string-break-if-float</imm32/name
31788     0x11/imm32/alloc-id:fake
31789     Single-lit-var/imm32/inouts
31790     0/imm32/no-outputs
31791     0/imm32/no-outputs
31792     0x11/imm32/alloc-id:fake
31793     _string_0f_82_jump_label/imm32/subx-name
31794     0/imm32/no-rm32
31795     0/imm32/no-r32
31796     0/imm32/no-imm32
31797     0/imm32/no-imm8
31798     1/imm32/disp32-is-first-inout
31799     0/imm32/no-xm32
31800     0/imm32/no-x32
31801     0x11/imm32/alloc-id:fake
31802     _Primitive-break-if-float>=-named/imm32/next
31803 _Primitive-break-if-float>=-named:  # (payload primitive)
31804     0x11/imm32/alloc-id:fake:payload
31805     0x11/imm32/alloc-id:fake
31806     _string-break-if-float>=/imm32/name
31807     0x11/imm32/alloc-id:fake
31808     Single-lit-var/imm32/inouts
31809     0/imm32/no-outputs
31810     0/imm32/no-outputs
31811     0x11/imm32/alloc-id:fake
31812     _string_0f_83_jump_label/imm32/subx-name
31813     0/imm32/no-rm32
31814     0/imm32/no-r32
31815     0/imm32/no-imm32
31816     0/imm32/no-imm8
31817     1/imm32/disp32-is-first-inout
31818     0/imm32/no-xm32
31819     0/imm32/no-x32
31820     0x11/imm32/alloc-id:fake
31821     _Primitive-break-if-float<=-named/imm32/next
31822 _Primitive-break-if-float<=-named:  # (payload primitive)
31823     0x11/imm32/alloc-id:fake:payload
31824     0x11/imm32/alloc-id:fake
31825     _string-break-if-float<=/imm32/name
31826     0x11/imm32/alloc-id:fake
31827     Single-lit-var/imm32/inouts
31828     0/imm32/no-outputs
31829     0/imm32/no-outputs
31830     0x11/imm32/alloc-id:fake
31831     _string_0f_86_jump_label/imm32/subx-name
31832     0/imm32/no-rm32
31833     0/imm32/no-r32
31834     0/imm32/no-imm32
31835     0/imm32/no-imm8
31836     1/imm32/disp32-is-first-inout
31837     0/imm32/no-xm32
31838     0/imm32/no-x32
31839     0x11/imm32/alloc-id:fake
31840     _Primitive-break-if-float>-named/imm32/next
31841 _Primitive-break-if-float>-named:  # (payload primitive)
31842     0x11/imm32/alloc-id:fake:payload
31843     0x11/imm32/alloc-id:fake
31844     _string-break-if-float>/imm32/name
31845     0x11/imm32/alloc-id:fake
31846     Single-lit-var/imm32/inouts
31847     0/imm32/no-outputs
31848     0/imm32/no-outputs
31849     0x11/imm32/alloc-id:fake
31850     _string_0f_87_jump_label/imm32/subx-name
31851     0/imm32/no-rm32
31852     0/imm32/no-r32
31853     0/imm32/no-imm32
31854     0/imm32/no-imm8
31855     1/imm32/disp32-is-first-inout
31856     0/imm32/no-xm32
31857     0/imm32/no-x32
31858     0x11/imm32/alloc-id:fake
31859     _Primitive-loop-if-float<-named/imm32/next
31860 _Primitive-loop-if-float<-named:  # (payload primitive)
31861     0x11/imm32/alloc-id:fake:payload
31862     0x11/imm32/alloc-id:fake
31863     _string-loop-if-float</imm32/name
31864     0x11/imm32/alloc-id:fake
31865     Single-lit-var/imm32/inouts
31866     0/imm32/no-outputs
31867     0/imm32/no-outputs
31868     0x11/imm32/alloc-id:fake
31869     _string_0f_82_jump_label/imm32/subx-name
31870     0/imm32/no-rm32
31871     0/imm32/no-r32
31872     0/imm32/no-imm32
31873     0/imm32/no-imm8
31874     1/imm32/disp32-is-first-inout
31875     0/imm32/no-xm32
31876     0/imm32/no-x32
31877     0x11/imm32/alloc-id:fake
31878     _Primitive-loop-if-float>=-named/imm32/next
31879 _Primitive-loop-if-float>=-named:  # (payload primitive)
31880     0x11/imm32/alloc-id:fake:payload
31881     0x11/imm32/alloc-id:fake
31882     _string-loop-if-float>=/imm32/name
31883     0x11/imm32/alloc-id:fake
31884     Single-lit-var/imm32/inouts
31885     0/imm32/no-outputs
31886     0/imm32/no-outputs
31887     0x11/imm32/alloc-id:fake
31888     _string_0f_83_jump_label/imm32/subx-name
31889     0/imm32/no-rm32
31890     0/imm32/no-r32
31891     0/imm32/no-imm32
31892     0/imm32/no-imm8
31893     1/imm32/disp32-is-first-inout
31894     0/imm32/no-xm32
31895     0/imm32/no-x32
31896     0x11/imm32/alloc-id:fake
31897     _Primitive-loop-if-float<=-named/imm32/next
31898 _Primitive-loop-if-float<=-named:  # (payload primitive)
31899     0x11/imm32/alloc-id:fake:payload
31900     0x11/imm32/alloc-id:fake
31901     _string-loop-if-float<=/imm32/name
31902     0x11/imm32/alloc-id:fake
31903     Single-lit-var/imm32/inouts
31904     0/imm32/no-outputs
31905     0/imm32/no-outputs
31906     0x11/imm32/alloc-id:fake
31907     _string_0f_86_jump_label/imm32/subx-name
31908     0/imm32/no-rm32
31909     0/imm32/no-r32
31910     0/imm32/no-imm32
31911     0/imm32/no-imm8
31912     1/imm32/disp32-is-first-inout
31913     0/imm32/no-xm32
31914     0/imm32/no-x32
31915     0x11/imm32/alloc-id:fake
31916     _Primitive-loop-if-float>-named/imm32/next
31917 _Primitive-loop-if-float>-named:  # (payload primitive)
31918     0x11/imm32/alloc-id:fake:payload
31919     0x11/imm32/alloc-id:fake
31920     _string-loop-if-float>/imm32/name
31921     0x11/imm32/alloc-id:fake
31922     Single-lit-var/imm32/inouts
31923     0/imm32/no-outputs
31924     0/imm32/no-outputs
31925     0x11/imm32/alloc-id:fake
31926     _string_0f_87_jump_label/imm32/subx-name
31927     0/imm32/no-rm32
31928     0/imm32/no-r32
31929     0/imm32/no-imm32
31930     0/imm32/no-imm8
31931     1/imm32/disp32-is-first-inout
31932     0/imm32/no-xm32
31933     0/imm32/no-x32
31934     0/imm32/next
31935     0/imm32/next
31936 
31937 # string literals for Mu instructions
31938 _string-add:  # (payload array byte)
31939     0x11/imm32/alloc-id:fake:payload
31940     # "add"
31941     0x3/imm32/size
31942     0x61/a 0x64/d 0x64/d
31943 _string-address:  # (payload array byte)
31944     0x11/imm32/alloc-id:fake:payload
31945     # "address"
31946     0x7/imm32/size
31947     0x61/a 0x64/d 0x64/d 0x72/r 0x65/e 0x73/s 0x73/s
31948 _string-add-to:  # (payload array byte)
31949     0x11/imm32/alloc-id:fake:payload
31950     # "add-to"
31951     0x6/imm32/size
31952     0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o
31953 _string-and:  # (payload array byte)
31954     0x11/imm32/alloc-id:fake:payload
31955     # "and"
31956     0x3/imm32/size
31957     0x61/a 0x6e/n 0x64/d
31958 _string-and-with:  # (payload array byte)
31959     0x11/imm32/alloc-id:fake:payload
31960     # "and-with"
31961     0x8/imm32/size
31962     0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
31963 _string-break:  # (payload array byte)
31964     0x11/imm32/alloc-id:fake:payload
31965     # "break"
31966     0x5/imm32/size
31967     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k
31968 _string-break-if-<:  # (payload array byte)
31969     0x11/imm32/alloc-id:fake:payload
31970     # "break-if-<"
31971     0xa/imm32/size
31972     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/<
31973 _string-break-if-<=:  # (payload array byte)
31974     0x11/imm32/alloc-id:fake:payload
31975     # "break-if-<="
31976     0xb/imm32/size
31977     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/=
31978 _string-break-if-=:  # (payload array byte)
31979     0x11/imm32/alloc-id:fake:payload
31980     # "break-if-="
31981     0xa/imm32/size
31982     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/=
31983 _string-break-if->:  # (payload array byte)
31984     0x11/imm32/alloc-id:fake:payload
31985     # "break-if->"
31986     0xa/imm32/size
31987     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/>
31988 _string-break-if->=:  # (payload array byte)
31989     0x11/imm32/alloc-id:fake:payload
31990     # "break-if->="
31991     0xb/imm32/size
31992     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/=
31993 _string-break-if-!=:  # (payload array byte)
31994     0x11/imm32/alloc-id:fake:payload
31995     # "break-if-!="
31996     0xb/imm32/size
31997     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/=
31998 _string-break-if-addr<:  # (payload array byte)
31999     0x11/imm32/alloc-id:fake:payload
32000     # "break-if-addr<"
32001     0xe/imm32/size
32002     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/<
32003 _string-break-if-addr<=:  # (payload array byte)
32004     0x11/imm32/alloc-id:fake:payload
32005     # "break-if-addr<="
32006     0xf/imm32/size
32007     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/=
32008 _string-break-if-addr>:  # (payload array byte)
32009     0x11/imm32/alloc-id:fake:payload
32010     # "break-if-addr>"
32011     0xe/imm32/size
32012     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/>
32013 _string-break-if-addr>=:  # (payload array byte)
32014     0x11/imm32/alloc-id:fake:payload
32015     # "break-if-addr>="
32016     0xf/imm32/size
32017     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/=
32018 _string-break-if-float<:  # (payload array byte)
32019     0x11/imm32/alloc-id:fake:payload
32020     # "break-if-float<"
32021     0xf/imm32/size
32022     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/<
32023 _string-break-if-float<=:  # (payload array byte)
32024     0x11/imm32/alloc-id:fake:payload
32025     # "break-if-float<="
32026     0x10/imm32/size
32027     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/=
32028 _string-break-if-float>:  # (payload array byte)
32029     0x11/imm32/alloc-id:fake:payload
32030     # "break-if-float>"
32031     0xf/imm32/size
32032     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/>
32033 _string-break-if-float>=:  # (payload array byte)
32034     0x11/imm32/alloc-id:fake:payload
32035     # "break-if-float>="
32036     0x10/imm32/size
32037     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/=
32038 _string-compare:  # (payload array byte)
32039     0x11/imm32/alloc-id:fake:payload
32040     # "compare"
32041     0x7/imm32/size
32042     0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e
32043 _string-copy:  # (payload array byte)
32044     0x11/imm32/alloc-id:fake:payload
32045     # "copy"
32046     0x4/imm32/size
32047     0x63/c 0x6f/o 0x70/p 0x79/y
32048 _string-copy-to:  # (payload array byte)
32049     0x11/imm32/alloc-id:fake:payload
32050     # "copy-to"
32051     0x7/imm32/size
32052     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o
32053 _string-copy-byte:
32054     0x11/imm32/alloc-id:fake:payload
32055     # "copy-byte"
32056     0x9/imm32/size
32057     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/- 0x62/b 0x79/y 0x74/t 0x65/e
32058 _string-copy-byte-to:
32059     0x11/imm32/alloc-id:fake:payload
32060     # "copy-byte-to"
32061     0xc/imm32/size
32062     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/- 0x62/b 0x79/y 0x74/t 0x65/e 0x2d/- 0x74/t 0x6f/o
32063 _string-decrement:  # (payload array byte)
32064     0x11/imm32/alloc-id:fake:payload
32065     # "decrement"
32066     0x9/imm32/size
32067     0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t
32068 _string-increment:  # (payload array byte)
32069     0x11/imm32/alloc-id:fake:payload
32070     # "increment"
32071     0x9/imm32/size
32072     0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t
32073 _string-loop:  # (payload array byte)
32074     0x11/imm32/alloc-id:fake:payload
32075     # "loop"
32076     0x4/imm32/size
32077     0x6c/l 0x6f/o 0x6f/o 0x70/p
32078 _string-loop-if-<:  # (payload array byte)
32079     0x11/imm32/alloc-id:fake:payload
32080     # "loop-if-<"
32081     0x9/imm32/size
32082     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/<
32083 _string-loop-if-<=:  # (payload array byte)
32084     0x11/imm32/alloc-id:fake:payload
32085     # "loop-if-<="
32086     0xa/imm32/size
32087     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/=
32088 _string-loop-if-=:  # (payload array byte)
32089     0x11/imm32/alloc-id:fake:payload
32090     # "loop-if-="
32091     0x9/imm32/size
32092     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/=
32093 _string-loop-if->:  # (payload array byte)
32094     0x11/imm32/alloc-id:fake:payload
32095     # "loop-if->"
32096     0x9/imm32/size
32097     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/>
32098 _string-loop-if->=:  # (payload array byte)
32099     0x11/imm32/alloc-id:fake:payload
32100     # "loop-if->="
32101     0xa/imm32/size
32102     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/=
32103 _string-loop-if-!=:  # (payload array byte)
32104     0x11/imm32/alloc-id:fake:payload
32105     # "loop-if-!="
32106     0xa/imm32/size
32107     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/=
32108 _string-loop-if-addr<:  # (payload array byte)
32109     0x11/imm32/alloc-id:fake:payload
32110     # "loop-if-addr<"
32111     0xd/imm32/size
32112     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/<
32113 _string-loop-if-addr<=:  # (payload array byte)
32114     0x11/imm32/alloc-id:fake:payload
32115     # "loop-if-addr<="
32116     0xe/imm32/size
32117     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/=
32118 _string-loop-if-addr>:  # (payload array byte)
32119     0x11/imm32/alloc-id:fake:payload
32120     # "loop-if-addr>"
32121     0xd/imm32/size
32122     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/>
32123 _string-loop-if-addr>=:  # (payload array byte)
32124     0x11/imm32/alloc-id:fake:payload
32125     # "loop-if-addr>="
32126     0xe/imm32/size
32127     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/=
32128 _string-loop-if-float<:  # (payload array byte)
32129     0x11/imm32/alloc-id:fake:payload
32130     # "loop-if-float<"
32131     0xe/imm32/size
32132     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/<
32133 _string-loop-if-float<=:  # (payload array byte)
32134     0x11/imm32/alloc-id:fake:payload
32135     # "loop-if-float<="
32136     0xf/imm32/size
32137     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/=
32138 _string-loop-if-float>:  # (payload array byte)
32139     0x11/imm32/alloc-id:fake:payload
32140     # "loop-if-float>"
32141     0xe/imm32/size
32142     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/>
32143 _string-loop-if-float>=:  # (payload array byte)
32144     0x11/imm32/alloc-id:fake:payload
32145     # "loop-if-float>="
32146     0xf/imm32/size
32147     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/=
32148 _string-multiply:  # (payload array byte)
32149     0x11/imm32/alloc-id:fake:payload
32150     # "multiply"
32151     0x8/imm32/size
32152     0x6d/m 0x75/u 0x6c/l 0x74/t 0x69/i 0x70/p 0x6c/l 0x79/y
32153 _string-convert:  # (payload array byte)
32154     0x11/imm32/alloc-id:fake:payload
32155     # "convert"
32156     0x7/imm32/size
32157     0x63/c 0x6f/o 0x6e/n 0x76/v 0x65/e 0x72/r 0x74/t
32158 _string-truncate:  # (payload array byte)
32159     0x11/imm32/alloc-id:fake:payload
32160     # "truncate"
32161     0x8/imm32/size
32162     0x74/t 0x72/r 0x75/u 0x6e/n 0x63/c 0x61/a 0x74/t 0x65/e
32163 _string-reinterpret:  # (payload array byte)
32164     0x11/imm32/alloc-id:fake:payload
32165     # "reinterpret"
32166     0xb/imm32/size
32167     0x72/r 0x65/e 0x69/i 0x6e/n 0x74/t 0x65/e 0x72/r 0x70/p 0x72/r 0x65/e 0x74/t
32168 _string-divide:
32169     0x11/imm32/alloc-id:fake:payload
32170     # "divide"
32171     0x6/imm32/size
32172     0x64/d 0x69/i 0x76/v 0x69/i 0x64/d 0x65/e
32173 _string-max:
32174     0x11/imm32/alloc-id:fake:payload
32175     # "max"
32176     0x3/imm32/size
32177     0x6d/m 0x61/a 0x78/x
32178 _string-min:
32179     0x11/imm32/alloc-id:fake:payload
32180     # "min"
32181     0x3/imm32/size
32182     0x6d/m 0x69/i 0x6e/n
32183 _string-reciprocal:
32184     0x11/imm32/alloc-id:fake:payload
32185     # "reciprocal"
32186     0xa/imm32/size
32187     0x72/r 0x65/e 0x63/c 0x69/i 0x70/p 0x72/r 0x6f/o 0x63/c 0x61/a 0x6c/l
32188 _string-square-root:
32189     0x11/imm32/alloc-id:fake:payload
32190     # "square-root"
32191     0xb/imm32/size
32192     0x73/s 0x71/q 0x75/u 0x61/a 0x72/r 0x65/e 0x2d/- 0x72/r 0x6f/o 0x6f/o 0x74/t
32193 _string-inverse-square-root:
32194     0x11/imm32/alloc-id:fake:payload
32195     # "inverse-square-root"
32196     0x13/imm32/size
32197     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
32198 _string-negate:  # (payload array byte)
32199     0x11/imm32/alloc-id:fake:payload
32200     # "negate"
32201     0x6/imm32/size
32202     0x6e/n 0x65/e 0x67/g 0x61/a 0x74/t 0x65/e
32203 _string-or:  # (payload array byte)
32204     0x11/imm32/alloc-id:fake:payload
32205     # "or"
32206     0x2/imm32/size
32207     0x6f/o 0x72/r
32208 _string-or-with:  # (payload array byte)
32209     0x11/imm32/alloc-id:fake:payload
32210     # "or-with"
32211     0x7/imm32/size
32212     0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
32213 _string-subtract:  # (payload array byte)
32214     0x11/imm32/alloc-id:fake:payload
32215     # "subtract"
32216     0x8/imm32/size
32217     0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t
32218 _string-subtract-from:  # (payload array byte)
32219     0x11/imm32/alloc-id:fake:payload
32220     # "subtract-from"
32221     0xd/imm32/size
32222     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
32223 _string-xor:  # (payload array byte)
32224     0x11/imm32/alloc-id:fake:payload
32225     # "xor"
32226     0x3/imm32/size
32227     0x78/x 0x6f/o 0x72/r
32228 _string-xor-with:  # (payload array byte)
32229     0x11/imm32/alloc-id:fake:payload
32230     # "xor-with"
32231     0x8/imm32/size
32232     0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
32233 _string-shift-left:  # (payload array byte)
32234     0x11/imm32/alloc-id:fake:payload
32235     # "shift-left"
32236     0xa/imm32/size
32237     0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x6c/l 0x65/e 0x66/f 0x74/t
32238 _string-shift-right:  # (payload array byte)
32239     0x11/imm32/alloc-id:fake:payload
32240     # "shift-right"
32241     0xb/imm32/size
32242     0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x72/r 0x69/i 0x67/g 0x68/h 0x74/t
32243 _string-shift-right-signed:  # (payload array byte)
32244     0x11/imm32/alloc-id:fake:payload
32245     # "shift-right-signed"
32246     0x12/imm32/size
32247     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
32248 
32249 # string literals for SubX instructions
32250 _string_01_add_to:  # (payload array byte)
32251     0x11/imm32/alloc-id:fake:payload
32252     # "01/add-to"
32253     0x9/imm32/size
32254     0x30/0 0x31/1 0x2f/slash 0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o
32255 _string_03_add:  # (payload array byte)
32256     0x11/imm32/alloc-id:fake:payload
32257     # "03/add"
32258     0x6/imm32/size
32259     0x30/0 0x33/3 0x2f/slash 0x61/a 0x64/d 0x64/d
32260 _string_05_add_to_eax:  # (payload array byte)
32261     0x11/imm32/alloc-id:fake:payload
32262     # "05/add-to-eax"
32263     0xd/imm32/size
32264     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
32265 _string_09_or_with:  # (payload array byte)
32266     0x11/imm32/alloc-id:fake:payload
32267     # "09/or-with"
32268     0xa/imm32/size
32269     0x30/0 0x39/9 0x2f/slash 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
32270 _string_0b_or:  # (payload array byte)
32271     0x11/imm32/alloc-id:fake:payload
32272     # "0b/or"
32273     0x5/imm32/size
32274     0x30/0 0x62/b 0x2f/slash 0x6f/o 0x72/r
32275 _string_0d_or_with_eax:  # (payload array byte)
32276     0x11/imm32/alloc-id:fake:payload
32277     # "0d/or-with-eax"
32278     0xe/imm32/size
32279     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
32280 _string_0f_82_jump_label:  # (payload array byte)
32281     0x11/imm32/alloc-id:fake:payload
32282     # "0f 82/jump-if-addr<"
32283     0x13/imm32/size
32284     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/<
32285 _string_0f_82_jump_break:  # (payload array byte)
32286     0x11/imm32/alloc-id:fake:payload
32287     # "0f 82/jump-if-addr< break/disp32"
32288     0x20/imm32/size
32289     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
32290 _string_0f_82_jump_loop:  # (payload array byte)
32291     0x11/imm32/alloc-id:fake:payload
32292     # "0f 82/jump-if-addr< loop/disp32"
32293     0x1f/imm32/size
32294     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
32295 _string_0f_83_jump_label:  # (payload array byte)
32296     0x11/imm32/alloc-id:fake:payload
32297     # "0f 83/jump-if-addr>="
32298     0x14/imm32/size
32299     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/=
32300 _string_0f_83_jump_break:  # (payload array byte)
32301     0x11/imm32/alloc-id:fake:payload
32302     # "0f 83/jump-if-addr>= break/disp32"
32303     0x21/imm32/size
32304     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
32305 _string_0f_83_jump_loop:  # (payload array byte)
32306     0x11/imm32/alloc-id:fake:payload
32307     # "0f 83/jump-if-addr>= loop/disp32"
32308     0x20/imm32/size
32309     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
32310 _string_0f_84_jump_label:  # (payload array byte)
32311     0x11/imm32/alloc-id:fake:payload
32312     # "0f 84/jump-if-="
32313     0xf/imm32/size
32314     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/=
32315 _string_0f_84_jump_break:  # (payload array byte)
32316     0x11/imm32/alloc-id:fake:payload
32317     # "0f 84/jump-if-= break/disp32"
32318     0x1c/imm32/size
32319     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
32320 _string_0f_84_jump_loop:  # (payload array byte)
32321     0x11/imm32/alloc-id:fake:payload
32322     # "0f 84/jump-if-= loop/disp32"
32323     0x1b/imm32/size
32324     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
32325 _string_0f_85_jump_label:  # (payload array byte)
32326     0x11/imm32/alloc-id:fake:payload
32327     # "0f 85/jump-if-!="
32328     0x10/imm32/size
32329     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/=
32330 _string_0f_85_jump_break:  # (payload array byte)
32331     0x11/imm32/alloc-id:fake:payload
32332     # "0f 85/jump-if-!= break/disp32"
32333     0x1d/imm32/size
32334     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
32335 _string_0f_85_jump_loop:  # (payload array byte)
32336     0x11/imm32/alloc-id:fake:payload
32337     # "0f 85/jump-if-!= loop/disp32"
32338     0x1c/imm32/size
32339     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
32340 _string_0f_86_jump_label:  # (payload array byte)
32341     0x11/imm32/alloc-id:fake:payload
32342     # "0f 86/jump-if-addr<="
32343     0x14/imm32/size
32344     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/=
32345 _string_0f_86_jump_break:  # (payload array byte)
32346     0x11/imm32/alloc-id:fake:payload
32347     # "0f 86/jump-if-addr<= break/disp32"
32348     0x21/imm32/size
32349     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
32350 _string_0f_86_jump_loop:  # (payload array byte)
32351     0x11/imm32/alloc-id:fake:payload
32352     # "0f 86/jump-if-addr<= loop/disp32"
32353     0x20/imm32/size
32354     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
32355 _string_0f_87_jump_label:  # (payload array byte)
32356     0x11/imm32/alloc-id:fake:payload
32357     # "0f 87/jump-if-addr>"
32358     0x13/imm32/size
32359     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/>
32360 _string_0f_87_jump_break:  # (payload array byte)
32361     0x11/imm32/alloc-id:fake:payload
32362     # "0f 87/jump-if-addr> break/disp32"
32363     0x20/imm32/size
32364     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
32365 _string_0f_87_jump_loop:  # (payload array byte)
32366     0x11/imm32/alloc-id:fake:payload
32367     # "0f 87/jump-if-addr> loop/disp32"
32368     0x1f/imm32/size
32369     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
32370 _string_0f_8c_jump_label:  # (payload array byte)
32371     0x11/imm32/alloc-id:fake:payload
32372     # "0f 8c/jump-if-<"
32373     0xf/imm32/size
32374     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/<
32375 _string_0f_8c_jump_break:  # (payload array byte)
32376     0x11/imm32/alloc-id:fake:payload
32377     # "0f 8c/jump-if-< break/disp32"
32378     0x1c/imm32/size
32379     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
32380 _string_0f_8c_jump_loop:  # (payload array byte)
32381     0x11/imm32/alloc-id:fake:payload
32382     # "0f 8c/jump-if-< loop/disp32"
32383     0x1b/imm32/size
32384     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
32385 _string_0f_8d_jump_label:  # (payload array byte)
32386     0x11/imm32/alloc-id:fake:payload
32387     # "0f 8d/jump-if->="
32388     0x10/imm32/size
32389     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/=
32390 _string_0f_8d_jump_break:  # (payload array byte)
32391     0x11/imm32/alloc-id:fake:payload
32392     # "0f 8d/jump-if->= break/disp32"
32393     0x1d/imm32/size
32394     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
32395 _string_0f_8d_jump_loop:  # (payload array byte)
32396     0x11/imm32/alloc-id:fake:payload
32397     # "0f 8d/jump-if->= loop/disp32"
32398     0x1c/imm32/size
32399     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
32400 _string_0f_8e_jump_label:  # (payload array byte)
32401     0x11/imm32/alloc-id:fake:payload
32402     # "0f 8e/jump-if-<="
32403     0x10/imm32/size
32404     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/=
32405 _string_0f_8e_jump_break:  # (payload array byte)
32406     0x11/imm32/alloc-id:fake:payload
32407     # "0f 8e/jump-if-<= break/disp32"
32408     0x1d/imm32/size
32409     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
32410 _string_0f_8e_jump_loop:  # (payload array byte)
32411     0x11/imm32/alloc-id:fake:payload
32412     # "0f 8e/jump-if-<= loop/disp32"
32413     0x1c/imm32/size
32414     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
32415 _string_0f_8f_jump_label:  # (payload array byte)
32416     0x11/imm32/alloc-id:fake:payload
32417     # "0f 8f/jump-if->"
32418     0xf/imm32/size
32419     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/>
32420 _string_0f_8f_jump_break:  # (payload array byte)
32421     0x11/imm32/alloc-id:fake:payload
32422     # "0f 8f/jump-if-> break/disp32"
32423     0x1c/imm32/size
32424     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
32425 _string_0f_8f_jump_loop:  # (payload array byte)
32426     0x11/imm32/alloc-id:fake:payload
32427     # "0f 8f/jump-if-> loop/disp32"
32428     0x1b/imm32/size
32429     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
32430 _string_0f_af_multiply:  # (payload array byte)
32431     0x11/imm32/alloc-id:fake:payload
32432     # "0f af/multiply"
32433     0xe/imm32/size
32434     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
32435 _string_f3_0f_2a_convert_to_float:
32436     0x11/imm32/alloc-id:fake:payload
32437     # "f3 0f 2a/convert-to-float"
32438     0x19/imm32/size
32439     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
32440 _string_f3_0f_2d_convert_to_int:
32441     0x11/imm32/alloc-id:fake:payload
32442     # "f3 0f 2d/convert-to-int"
32443     0x17/imm32/size
32444     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
32445 _string_f3_0f_2c_truncate_to_int:
32446     0x11/imm32/alloc-id:fake:payload
32447     # "f3 0f 2c/truncate-to-int"
32448     0x18/imm32/size
32449     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
32450 _string_f3_0f_58_add:
32451     0x11/imm32/alloc-id:fake:payload
32452     # "f3 0f 58/add"
32453     0xc/imm32/size
32454     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x38/8 0x2f/slash 0x61/a 0x64/d 0x64/d
32455 _string_f3_0f_5c_subtract:
32456     0x11/imm32/alloc-id:fake:payload
32457     # "f3 0f 5c/subtract"
32458     0x11/imm32/size
32459     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
32460 _string_f3_0f_59_multiply:
32461     0x11/imm32/alloc-id:fake:payload
32462     # "f3 0f 59/multiply"
32463     0x11/imm32/size
32464     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
32465 _string_f3_0f_5e_divide:
32466     0x11/imm32/alloc-id:fake:payload
32467     # "f3 0f 5e/divide"
32468     0xf/imm32/size
32469     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
32470 _string_f3_0f_53_reciprocal:
32471     0x11/imm32/alloc-id:fake:payload
32472     # "f3 0f 53/reciprocal"
32473     0x13/imm32/size
32474     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
32475 _string_f3_0f_51_square_root:
32476     0x11/imm32/alloc-id:fake:payload
32477     # "f3 0f 51/square-root"
32478     0x14/imm32/size
32479     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
32480 _string_f3_0f_52_inverse_square_root:
32481     0x11/imm32/alloc-id:fake:payload
32482     # "f3 0f 52/inverse-square-root"
32483     0x1c/imm32/size
32484     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
32485 _string_f3_0f_5d_min:
32486     0x11/imm32/alloc-id:fake:payload
32487     # "f3 0f 5d/min"
32488     0xc/imm32/size
32489     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x64/d 0x2f/slash 0x6d/m 0x69/i 0x6e/n
32490 _string_f3_0f_5f_max:
32491     0x11/imm32/alloc-id:fake:payload
32492     # "f3 0f 5f/max"
32493     0xc/imm32/size
32494     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x66/f 0x2f/slash 0x6d/m 0x61/a 0x78/x
32495 _string_f3_0f_10_copy:
32496     0x11/imm32/alloc-id:fake:payload
32497     # "f3 0f 10/copy"
32498     0xd/imm32/size
32499     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
32500 _string_f3_0f_11_copy:
32501     0x11/imm32/alloc-id:fake:payload
32502     # "f3 0f 11/copy"
32503     0xd/imm32/size
32504     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
32505 _string_0f_2f_compare:
32506     0x11/imm32/alloc-id:fake:payload
32507     # "0f 2f/compare"
32508     0xd/imm32/size
32509     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
32510 _string_21_and_with:  # (payload array byte)
32511     0x11/imm32/alloc-id:fake:payload
32512     # "21/and-with"
32513     0xb/imm32/size
32514     0x32/2 0x31/1 0x2f/slash 0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
32515 _string_23_and:  # (payload array byte)
32516     0x11/imm32/alloc-id:fake:payload
32517     # "23/and"
32518     0x6/imm32/size
32519     0x32/2 0x33/3 0x2f/slash 0x61/a 0x6e/n 0x64/d
32520 _string_25_and_with_eax:  # (payload array byte)
32521     0x11/imm32/alloc-id:fake:payload
32522     # "25/and-with-eax"
32523     0xf/imm32/size
32524     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
32525 _string_29_subtract_from:  # (payload array byte)
32526     0x11/imm32/alloc-id:fake:payload
32527     # "29/subtract-from"
32528     0x10/imm32/size
32529     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
32530 _string_2b_subtract:  # (payload array byte)
32531     0x11/imm32/alloc-id:fake:payload
32532     # "2b/subtract"
32533     0xb/imm32/size
32534     0x32/2 0x62/b 0x2f/slash 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t
32535 _string_2d_subtract_from_eax:  # (payload array byte)
32536     0x11/imm32/alloc-id:fake:payload
32537     # "2d/subtract-from-eax"
32538     0x14/imm32/size
32539     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
32540 _string_31_xor_with:  # (payload array byte)
32541     0x11/imm32/alloc-id:fake:payload
32542     # "31/xor-with"
32543     0xb/imm32/size
32544     0x33/3 0x31/1 0x2f/slash 0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
32545 _string_33_xor:  # (payload array byte)
32546     0x11/imm32/alloc-id:fake:payload
32547     # "33/xor"
32548     0x6/imm32/size
32549     0x33/3 0x33/3 0x2f/slash 0x78/x 0x6f/o 0x72/r
32550 _string_35_xor_with_eax:  # (payload array byte)
32551     0x11/imm32/alloc-id:fake:payload
32552     # "35/xor-with-eax"
32553     0xf/imm32/size
32554     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
32555 _string_39_compare->:  # (payload array byte)
32556     0x11/imm32/alloc-id:fake:payload
32557     # "39/compare->"
32558     0xc/imm32/size
32559     0x33/3 0x39/9 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x2d/dash 0x3e/>
32560 _string_3b_compare<-:  # (payload array byte)
32561     0x11/imm32/alloc-id:fake:payload
32562     # "3b/compare<-"
32563     0xc/imm32/size
32564     0x33/3 0x62/b 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x3c/< 0x2d/dash
32565 _string_3d_compare_eax_with:  # (payload array byte)
32566     0x11/imm32/alloc-id:fake:payload
32567     # "3d/compare-eax-with"
32568     0x13/imm32/size
32569     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
32570 _string_40_increment_eax:  # (payload array byte)
32571     0x11/imm32/alloc-id:fake:payload
32572     # "40/increment-eax"
32573     0x10/imm32/size
32574     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
32575 _string_41_increment_ecx:  # (payload array byte)
32576     0x11/imm32/alloc-id:fake:payload
32577     # "41/increment-ecx"
32578     0x10/imm32/size
32579     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
32580 _string_42_increment_edx:  # (payload array byte)
32581     0x11/imm32/alloc-id:fake:payload
32582     # "42/increment-edx"
32583     0x10/imm32/size
32584     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
32585 _string_43_increment_ebx:  # (payload array byte)
32586     0x11/imm32/alloc-id:fake:payload
32587     # "43/increment-ebx"
32588     0x10/imm32/size
32589     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
32590 _string_46_increment_esi:  # (payload array byte)
32591     0x11/imm32/alloc-id:fake:payload
32592     # "46/increment-esi"
32593     0x10/imm32/size
32594     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
32595 _string_47_increment_edi:  # (payload array byte)
32596     0x11/imm32/alloc-id:fake:payload
32597     # "47/increment-edi"
32598     0x10/imm32/size
32599     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
32600 _string_48_decrement_eax:  # (payload array byte)
32601     0x11/imm32/alloc-id:fake:payload
32602     # "48/decrement-eax"
32603     0x10/imm32/size
32604     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
32605 _string_49_decrement_ecx:  # (payload array byte)
32606     0x11/imm32/alloc-id:fake:payload
32607     # "49/decrement-ecx"
32608     0x10/imm32/size
32609     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
32610 _string_4a_decrement_edx:  # (payload array byte)
32611     0x11/imm32/alloc-id:fake:payload
32612     # "4a/decrement-edx"
32613     0x10/imm32/size
32614     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
32615 _string_4b_decrement_ebx:  # (payload array byte)
32616     0x11/imm32/alloc-id:fake:payload
32617     # "4b/decrement-ebx"
32618     0x10/imm32/size
32619     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
32620 _string_4e_decrement_esi:  # (payload array byte)
32621     0x11/imm32/alloc-id:fake:payload
32622     # "4e/decrement-esi"
32623     0x10/imm32/size
32624     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
32625 _string_4f_decrement_edi:  # (payload array byte)
32626     0x11/imm32/alloc-id:fake:payload
32627     # "4f/decrement-edi"
32628     0x10/imm32/size
32629     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
32630 _string_81_subop_add:  # (payload array byte)
32631     0x11/imm32/alloc-id:fake:payload
32632     # "81 0/subop/add"
32633     0xe/imm32/size
32634     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
32635 _string_81_subop_or:  # (payload array byte)
32636     0x11/imm32/alloc-id:fake:payload
32637     # "81 1/subop/or"
32638     0xd/imm32/size
32639     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
32640 _string_81_subop_and:  # (payload array byte)
32641     0x11/imm32/alloc-id:fake:payload
32642     # "81 4/subop/and"
32643     0xe/imm32/size
32644     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
32645 _string_81_subop_subtract:  # (payload array byte)
32646     0x11/imm32/alloc-id:fake:payload
32647     # "81 5/subop/subtract"
32648     0x13/imm32/size
32649     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
32650 _string_81_subop_xor:  # (payload array byte)
32651     0x11/imm32/alloc-id:fake:payload
32652     # "81 6/subop/xor"
32653     0xe/imm32/size
32654     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
32655 _string_81_subop_compare:  # (payload array byte)
32656     0x11/imm32/alloc-id:fake:payload
32657     # "81 7/subop/compare"
32658     0x12/imm32/size
32659     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
32660 _string_89_<-:  # (payload array byte)
32661     0x11/imm32/alloc-id:fake:payload
32662     # "89/<-"
32663     0x5/imm32/size
32664     0x38/8 0x39/9 0x2f/slash 0x3c/< 0x2d/dash
32665 _string_8b_->:  # (payload array byte)
32666     0x11/imm32/alloc-id:fake:payload
32667     # "8b/->"
32668     0x5/imm32/size
32669     0x38/8 0x62/b 0x2f/slash 0x2d/dash 0x3e/>
32670 _string_8a_copy_byte:
32671     0x11/imm32/alloc-id:fake:payload
32672     # "8a/byte->"
32673     0x9/imm32/size
32674     0x38/8 0x61/a 0x2f// 0x62/b 0x79/y 0x74/t 0x65/e 0x2d/- 0x3e/>
32675 _string_88_copy_byte:
32676     0x11/imm32/alloc-id:fake:payload
32677     # "88/byte<-"
32678     0x9/imm32/size
32679     0x38/8 0x38/8 0x2f// 0x62/b 0x79/y 0x74/t 0x65/e 0x3c/< 0x2d/-
32680 _string_8d_copy_address:  # (payload array byte)
32681     0x11/imm32/alloc-id:fake:payload
32682     # "8d/copy-address"
32683     0xf/imm32/size
32684     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
32685 _string_b8_copy_to_eax:  # (payload array byte)
32686     0x11/imm32/alloc-id:fake:payload
32687     # "b8/copy-to-eax"
32688     0xe/imm32/size
32689     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
32690 _string_b9_copy_to_ecx:  # (payload array byte)
32691     0x11/imm32/alloc-id:fake:payload
32692     # "b9/copy-to-ecx"
32693     0xe/imm32/size
32694     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
32695 _string_ba_copy_to_edx:  # (payload array byte)
32696     0x11/imm32/alloc-id:fake:payload
32697     # "ba/copy-to-edx"
32698     0xe/imm32/size
32699     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
32700 _string_bb_copy_to_ebx:  # (payload array byte)
32701     0x11/imm32/alloc-id:fake:payload
32702     # "bb/copy-to-ebx"
32703     0xe/imm32/size
32704     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
32705 _string_be_copy_to_esi:  # (payload array byte)
32706     0x11/imm32/alloc-id:fake:payload
32707     # "be/copy-to-esi"
32708     0xe/imm32/size
32709     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
32710 _string_bf_copy_to_edi:  # (payload array byte)
32711     0x11/imm32/alloc-id:fake:payload
32712     # "bf/copy-to-edi"
32713     0xe/imm32/size
32714     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
32715 _string_c7_subop_copy:  # (payload array byte)
32716     0x11/imm32/alloc-id:fake:payload
32717     # "c7 0/subop/copy"
32718     0xf/imm32/size
32719     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
32720 _string_e9_jump_label:  # (payload array byte)
32721     0x11/imm32/alloc-id:fake:payload
32722     # "e9/jump"
32723     0x7/imm32/size
32724     0x65/e 0x39/9 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p
32725 _string_e9_jump_break:  # (payload array byte)
32726     0x11/imm32/alloc-id:fake:payload
32727     # "e9/jump break/disp32"
32728     0x14/imm32/size
32729     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
32730 _string_e9_jump_loop:  # (payload array byte)
32731     0x11/imm32/alloc-id:fake:payload
32732     # "e9/jump loop/disp32"
32733     0x13/imm32/size
32734     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
32735 _string_f7_subop_negate:
32736     0x11/imm32/alloc-id:fake:payload
32737     # "f7 3/subop/negate"
32738     0x11/imm32/size
32739     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
32740 _string_ff_subop_increment:  # (payload array byte)
32741     0x11/imm32/alloc-id:fake:payload
32742     # "ff 0/subop/increment"
32743     0x14/imm32/size
32744     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
32745 _string_ff_subop_decrement:  # (payload array byte)
32746     0x11/imm32/alloc-id:fake:payload
32747     # "ff 1/subop/decrement"
32748     0x14/imm32/size
32749     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
32750 _string_c1_subop_shift_left:  # (payload array byte)
32751     0x11/imm32/alloc-id:fake:payload
32752     # "c1/shift 4/subop/left"
32753     0x15/imm32/size
32754     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
32755 _string_c1_subop_shift_right_padding_zeroes:  # (payload array byte)
32756     0x11/imm32/alloc-id:fake:payload
32757     # "c1/shift 5/subop/right-padding-zeroes"
32758     0x25/imm32/size
32759     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
32760 _string_c1_subop_shift_right_preserving_sign:  # (payload array byte)
32761     0x11/imm32/alloc-id:fake:payload
32762     # "c1/shift 7/subop/right-preserving-sign"
32763     0x26/imm32/size
32764     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
32765 
32766 Single-int-var-in-mem:  # (payload list var)
32767     0x11/imm32/alloc-id:fake:payload
32768     0x11/imm32/alloc-id:fake
32769     Int-var-in-mem/imm32
32770     0/imm32/next
32771     0/imm32/next
32772 
32773 Int-var-in-mem:  # (payload var)
32774     0x11/imm32/alloc-id:fake:payload
32775     0/imm32/name
32776     0/imm32/name
32777     0x11/imm32/alloc-id:fake
32778     Type-int/imm32
32779     1/imm32/some-block-depth
32780     1/imm32/some-stack-offset
32781     0/imm32/no-register
32782     0/imm32/no-register
32783 
32784 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
32785 Single-byte-var-in-mem:  # (payload list var)
32786     0x11/imm32/alloc-id:fake:payload
32787     0x11/imm32/alloc-id:fake
32788     Byte-var-in-mem/imm32
32789     0/imm32/next
32790     0/imm32/next
32791 
32792 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
32793 Byte-var-in-mem:  # (payload var)
32794     0x11/imm32/alloc-id:fake:payload
32795     0/imm32/name
32796     0/imm32/name
32797     0x11/imm32/alloc-id:fake
32798     Type-byte/imm32
32799     1/imm32/some-block-depth
32800     1/imm32/some-stack-offset
32801     0/imm32/no-register
32802     0/imm32/no-register
32803 
32804 Two-args-int-stack-int-reg:  # (payload list var)
32805     0x11/imm32/alloc-id:fake:payload
32806     0x11/imm32/alloc-id:fake
32807     Int-var-in-mem/imm32
32808     0x11/imm32/alloc-id:fake
32809     Single-int-var-in-some-register/imm32/next
32810 
32811 Two-int-args-in-regs:  # (payload list var)
32812     0x11/imm32/alloc-id:fake:payload
32813     0x11/imm32/alloc-id:fake
32814     Int-var-in-some-register/imm32
32815     0x11/imm32/alloc-id:fake
32816     Single-int-var-in-some-register/imm32/next
32817 
32818 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
32819 Two-args-byte-stack-byte-reg:  # (payload list var)
32820     0x11/imm32/alloc-id:fake:payload
32821     0x11/imm32/alloc-id:fake
32822     Byte-var-in-mem/imm32
32823     0x11/imm32/alloc-id:fake
32824     Single-byte-var-in-some-register/imm32/next
32825 
32826 Two-args-int-reg-int-stack:  # (payload list var)
32827     0x11/imm32/alloc-id:fake:payload
32828     0x11/imm32/alloc-id:fake
32829     Int-var-in-some-register/imm32
32830     0x11/imm32/alloc-id:fake
32831     Single-int-var-in-mem/imm32/next
32832 
32833 Two-args-int-eax-int-literal:  # (payload list var)
32834     0x11/imm32/alloc-id:fake:payload
32835     0x11/imm32/alloc-id:fake
32836     Int-var-in-eax/imm32
32837     0x11/imm32/alloc-id:fake
32838     Single-lit-var/imm32/next
32839 
32840 Int-var-and-literal:  # (payload list var)
32841     0x11/imm32/alloc-id:fake:payload
32842     0x11/imm32/alloc-id:fake
32843     Int-var-in-mem/imm32
32844     0x11/imm32/alloc-id:fake
32845     Single-lit-var/imm32/next
32846 
32847 Int-var-in-register-and-literal:  # (payload list var)
32848     0x11/imm32/alloc-id:fake:payload
32849     0x11/imm32/alloc-id:fake
32850     Int-var-in-some-register/imm32
32851     0x11/imm32/alloc-id:fake
32852     Single-lit-var/imm32/next
32853 
32854 Two-float-args-in-regs:  # (payload list var)
32855     0x11/imm32/alloc-id:fake:payload
32856     0x11/imm32/alloc-id:fake
32857     Float-var-in-some-register/imm32
32858     0x11/imm32/alloc-id:fake
32859     Single-float-var-in-some-register/imm32/next
32860 
32861 Two-args-float-reg-float-stack:  # (payload list var)
32862     0x11/imm32/alloc-id:fake:payload
32863     0x11/imm32/alloc-id:fake
32864     Float-var-in-some-register/imm32
32865     0x11/imm32/alloc-id:fake
32866     Single-float-var-in-mem/imm32/next
32867 
32868 Two-args-float-stack-float-reg:  # (payload list var)
32869     0x11/imm32/alloc-id:fake:payload
32870     0x11/imm32/alloc-id:fake
32871     Float-var-in-mem/imm32
32872     0x11/imm32/alloc-id:fake
32873     Single-float-var-in-some-register/imm32/next
32874 
32875 Single-int-var-in-some-register:  # (payload list var)
32876     0x11/imm32/alloc-id:fake:payload
32877     0x11/imm32/alloc-id:fake
32878     Int-var-in-some-register/imm32
32879     0/imm32/next
32880     0/imm32/next
32881 
32882 Single-addr-var-in-some-register:  # (payload list var)
32883     0x11/imm32/alloc-id:fake:payload
32884     0x11/imm32/alloc-id:fake
32885     Addr-var-in-some-register/imm32
32886     0/imm32/next
32887     0/imm32/next
32888 
32889 Single-byte-var-in-some-register:  # (payload list var)
32890     0x11/imm32/alloc-id:fake:payload
32891     0x11/imm32/alloc-id:fake
32892     Byte-var-in-some-register/imm32
32893     0/imm32/next
32894     0/imm32/next
32895 
32896 Int-var-in-some-register:  # (payload var)
32897     0x11/imm32/alloc-id:fake:payload
32898     0/imm32/name
32899     0/imm32/name
32900     0x11/imm32/alloc-id:fake
32901     Type-int/imm32
32902     1/imm32/some-block-depth
32903     0/imm32/no-stack-offset
32904     0x11/imm32/alloc-id:fake
32905     Any-register/imm32
32906 
32907 Any-register:  # (payload array byte)
32908     0x11/imm32/alloc-id:fake:payload
32909     1/imm32/size
32910     # data
32911     2a/asterisk
32912 
32913 Addr-var-in-some-register:  # (payload var)
32914     0x11/imm32/alloc-id:fake:payload
32915     0/imm32/name
32916     0/imm32/name
32917     0x11/imm32/alloc-id:fake
32918     Type-addr/imm32
32919     1/imm32/some-block-depth
32920     0/imm32/no-stack-offset
32921     0x11/imm32/alloc-id:fake
32922     Any-register/imm32
32923 
32924 Byte-var-in-some-register:  # (payload var)
32925     0x11/imm32/alloc-id:fake:payload
32926     0/imm32/name
32927     0/imm32/name
32928     0x11/imm32/alloc-id:fake
32929     Type-byte/imm32
32930     1/imm32/some-block-depth
32931     0/imm32/no-stack-offset
32932     0x11/imm32/alloc-id:fake
32933     Any-register/imm32
32934 
32935 Single-int-var-in-eax:  # (payload list var)
32936     0x11/imm32/alloc-id:fake:payload
32937     0x11/imm32/alloc-id:fake
32938     Int-var-in-eax/imm32
32939     0/imm32/next
32940     0/imm32/next
32941 
32942 Int-var-in-eax:
32943     0x11/imm32/alloc-id:fake:payload
32944     0/imm32/name
32945     0/imm32/name
32946     0x11/imm32/alloc-id:fake
32947     Type-int/imm32
32948     1/imm32/some-block-depth
32949     0/imm32/no-stack-offset
32950     0x11/imm32/alloc-id:fake
32951     $Mu-register-eax/imm32  # can't use Register-eax only to keep our buggy tools/treeshake.cc happy (TODO)
32952 
32953 Single-int-var-in-ecx:  # (payload list var)
32954     0x11/imm32/alloc-id:fake:payload
32955     0x11/imm32/alloc-id:fake
32956     Int-var-in-ecx/imm32
32957     0/imm32/next
32958     0/imm32/next
32959 
32960 Int-var-in-ecx:
32961     0x11/imm32/alloc-id:fake:payload
32962     0/imm32/name
32963     0/imm32/name
32964     0x11/imm32/alloc-id:fake
32965     Type-int/imm32
32966     1/imm32/some-block-depth
32967     0/imm32/no-stack-offset
32968     0x11/imm32/alloc-id:fake
32969     $Register-ecx/imm32/register
32970 
32971 Single-int-var-in-edx:  # (payload list var)
32972     0x11/imm32/alloc-id:fake:payload
32973     0x11/imm32/alloc-id:fake
32974     Int-var-in-edx/imm32
32975     0/imm32/next
32976     0/imm32/next
32977 
32978 Int-var-in-edx:  # (payload list var)
32979     0x11/imm32/alloc-id:fake:payload
32980     0/imm32/name
32981     0/imm32/name
32982     0x11/imm32/alloc-id:fake
32983     Type-int/imm32
32984     1/imm32/some-block-depth
32985     0/imm32/no-stack-offset
32986     0x11/imm32/alloc-id:fake
32987     $Register-edx/imm32/register
32988 
32989 Single-int-var-in-ebx:  # (payload list var)
32990     0x11/imm32/alloc-id:fake:payload
32991     0x11/imm32/alloc-id:fake
32992     Int-var-in-ebx/imm32
32993     0/imm32/next
32994     0/imm32/next
32995 
32996 Int-var-in-ebx:  # (payload list var)
32997     0x11/imm32/alloc-id:fake:payload
32998     0/imm32/name
32999     0/imm32/name
33000     0x11/imm32/alloc-id:fake
33001     Type-int/imm32
33002     1/imm32/some-block-depth
33003     0/imm32/no-stack-offset
33004     0x11/imm32/alloc-id:fake
33005     $Register-ebx/imm32/register
33006 
33007 Single-int-var-in-esi:  # (payload list var)
33008     0x11/imm32/alloc-id:fake:payload
33009     0x11/imm32/alloc-id:fake
33010     Int-var-in-esi/imm32
33011     0/imm32/next
33012     0/imm32/next
33013 
33014 Int-var-in-esi:  # (payload list var)
33015     0x11/imm32/alloc-id:fake:payload
33016     0/imm32/name
33017     0/imm32/name
33018     0x11/imm32/alloc-id:fake
33019     Type-int/imm32
33020     1/imm32/some-block-depth
33021     0/imm32/no-stack-offset
33022     0x11/imm32/alloc-id:fake
33023     $Register-esi/imm32/register
33024 
33025 Single-int-var-in-edi:  # (payload list var)
33026     0x11/imm32/alloc-id:fake:payload
33027     0x11/imm32/alloc-id:fake
33028     Int-var-in-edi/imm32
33029     0/imm32/next
33030     0/imm32/next
33031 
33032 Int-var-in-edi:  # (payload list var)
33033     0x11/imm32/alloc-id:fake:payload
33034     0/imm32/name
33035     0/imm32/name
33036     0x11/imm32/alloc-id:fake
33037     Type-int/imm32
33038     1/imm32/some-block-depth
33039     0/imm32/no-stack-offset
33040     0x11/imm32/alloc-id:fake
33041     $Register-edi/imm32/register
33042 
33043 Single-lit-var:  # (payload list var)
33044     0x11/imm32/alloc-id:fake:payload
33045     0x11/imm32/alloc-id:fake
33046     Lit-var/imm32
33047     0/imm32/next
33048     0/imm32/next
33049 
33050 Lit-var:  # (payload var)
33051     0x11/imm32/alloc-id:fake:payload
33052     0/imm32/name
33053     0/imm32/name
33054     0x11/imm32/alloc-id:fake
33055     Type-literal/imm32
33056     1/imm32/some-block-depth
33057     0/imm32/no-stack-offset
33058     0/imm32/no-register
33059     0/imm32/no-register
33060 
33061 Single-float-var-in-mem:  # (payload list var)
33062     0x11/imm32/alloc-id:fake:payload
33063     0x11/imm32/alloc-id:fake
33064     Float-var-in-mem/imm32
33065     0/imm32/next
33066     0/imm32/next
33067 
33068 Float-var-in-mem:  # (payload var)
33069     0x11/imm32/alloc-id:fake:payload
33070     0/imm32/name
33071     0/imm32/name
33072     0x11/imm32/alloc-id:fake
33073     Type-float/imm32
33074     1/imm32/some-block-depth
33075     1/imm32/some-stack-offset
33076     0/imm32/no-register
33077     0/imm32/no-register
33078 
33079 Single-float-var-in-some-register:  # (payload list var)
33080     0x11/imm32/alloc-id:fake:payload
33081     0x11/imm32/alloc-id:fake
33082     Float-var-in-some-register/imm32
33083     0/imm32/next
33084     0/imm32/next
33085 
33086 Float-var-in-some-register:  # (payload var)
33087     0x11/imm32/alloc-id:fake:payload
33088     0/imm32/name
33089     0/imm32/name
33090     0x11/imm32/alloc-id:fake
33091     Type-float/imm32
33092     1/imm32/some-block-depth
33093     0/imm32/no-stack-offset
33094     0x11/imm32/alloc-id:fake
33095     Any-register/imm32
33096 
33097 Type-int:  # (payload type-tree)
33098     0x11/imm32/alloc-id:fake:payload
33099     1/imm32/is-atom
33100     1/imm32/value:int
33101     0/imm32/left:unused
33102     0/imm32/right:null
33103     0/imm32/right:null
33104 
33105 Type-literal:  # (payload type-tree)
33106     0x11/imm32/alloc-id:fake:payload
33107     1/imm32/is-atom
33108     0/imm32/value:literal
33109     0/imm32/left:unused
33110     0/imm32/right:null
33111     0/imm32/right:null
33112 
33113 Type-addr:  # (payload type-tree)
33114     0x11/imm32/alloc-id:fake:payload
33115     1/imm32/is-atom
33116     2/imm32/value:addr
33117     0/imm32/left:unused
33118     0/imm32/right:null
33119     0/imm32/right:null
33120 
33121 Type-byte:  # (payload type-tree)
33122     0x11/imm32/alloc-id:fake:payload
33123     1/imm32/is-atom
33124     8/imm32/value:byte
33125     0/imm32/left:unused
33126     0/imm32/right:null
33127     0/imm32/right:null
33128 
33129 Type-float:  # (payload type-tree)
33130     0x11/imm32/alloc-id:fake:payload
33131     1/imm32/is-atom
33132     0xf/imm32/value:float
33133     0/imm32/left:unused
33134     0/imm32/right:null
33135     0/imm32/right:null
33136 
33137 == code
33138 emit-subx-primitive:  # out: (addr buffered-file), stmt: (addr stmt), primitive: (addr primitive), err: (addr buffered-file), ed: (addr exit-descriptor)
33139     # . prologue
33140     55/push-ebp
33141     89/<- %ebp 4/r32/esp
33142     # . save registers
33143     50/push-eax
33144     51/push-ecx
33145     # ecx = primitive
33146     8b/-> *(ebp+0x10) 1/r32/ecx
33147     # emit primitive name
33148     (emit-indent *(ebp+8) *Curr-block-depth)
33149     (lookup *(ecx+0x18) *(ecx+0x1c))  # Primitive-subx-name Primitive-subx-name => eax
33150     (write-buffered *(ebp+8) %eax)
33151     # emit rm32 if necessary
33152     (emit-subx-rm32 *(ebp+8) *(ecx+0x20) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-rm32
33153     # emit xm32 if necessary
33154     (emit-subx-rm32 *(ebp+8) *(ecx+0x34) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-xm32
33155     # emit r32 if necessary
33156     (emit-subx-r32 *(ebp+8) *(ecx+0x24) *(ebp+0xc))  # Primitive-subx-r32
33157     # emit x32 if necessary
33158     (emit-subx-x32 *(ebp+8) *(ecx+0x38) *(ebp+0xc))  # Primitive-subx-x32
33159     # emit imm32 if necessary
33160     (emit-subx-imm32 *(ebp+8) *(ecx+0x28) *(ebp+0xc))  # Primitive-subx-imm32
33161     # emit imm8 if necessary
33162     (emit-subx-imm8 *(ebp+8) *(ecx+0x2c) *(ebp+0xc))  # Primitive-subx-imm8
33163     # emit disp32 if necessary
33164     (emit-subx-disp32 *(ebp+8) *(ecx+0x30) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-disp32
33165     (write-buffered *(ebp+8) Newline)
33166 $emit-subx-primitive:end:
33167     # . restore registers
33168     59/pop-to-ecx
33169     58/pop-to-eax
33170     # . epilogue
33171     89/<- %esp 5/r32/ebp
33172     5d/pop-to-ebp
33173     c3/return
33174 
33175 emit-subx-rm32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
33176     # . prologue
33177     55/push-ebp
33178     89/<- %ebp 4/r32/esp
33179     # . save registers
33180     50/push-eax
33181     # if (l == 0) return
33182     81 7/subop/compare *(ebp+0xc) 0/imm32
33183     74/jump-if-= $emit-subx-rm32:end/disp8
33184     # var v/eax: (addr stmt-var)
33185     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # => eax
33186     (emit-subx-var-as-rm32 *(ebp+8) %eax)
33187 $emit-subx-rm32:end:
33188     # . restore registers
33189     58/pop-to-eax
33190     # . epilogue
33191     89/<- %esp 5/r32/ebp
33192     5d/pop-to-ebp
33193     c3/return
33194 
33195 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)
33196     # . prologue
33197     55/push-ebp
33198     89/<- %ebp 4/r32/esp
33199     # . save registers
33200     51/push-ecx
33201     # eax = l
33202     8b/-> *(ebp+0xc) 0/r32/eax
33203     # ecx = stmt
33204     8b/-> *(ebp+8) 1/r32/ecx
33205     # if (l == 1) return stmt->inouts
33206     {
33207       3d/compare-eax-and 1/imm32
33208       75/jump-if-!= break/disp8
33209 $get-stmt-operand-from-arg-location:1:
33210       (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
33211       eb/jump $get-stmt-operand-from-arg-location:end/disp8
33212     }
33213     # if (l == 2) return stmt->inouts->next
33214     {
33215       3d/compare-eax-and 2/imm32
33216       75/jump-if-!= break/disp8
33217 $get-stmt-operand-from-arg-location:2:
33218       (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
33219       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
33220       eb/jump $get-stmt-operand-from-arg-location:end/disp8
33221     }
33222     # if (l == 3) return stmt->outputs
33223     {
33224       3d/compare-eax-and 3/imm32
33225       75/jump-if-!= break/disp8
33226 $get-stmt-operand-from-arg-location:3:
33227       (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
33228       eb/jump $get-stmt-operand-from-arg-location:end/disp8
33229     }
33230     # abort
33231     e9/jump $get-stmt-operand-from-arg-location:abort/disp32
33232 $get-stmt-operand-from-arg-location:end:
33233     # . restore registers
33234     59/pop-to-ecx
33235     # . epilogue
33236     89/<- %esp 5/r32/ebp
33237     5d/pop-to-ebp
33238     c3/return
33239 
33240 $get-stmt-operand-from-arg-location:abort:
33241     # error("invalid arg-location " eax)
33242     (write-buffered *(ebp+0x10) "invalid arg-location ")
33243     (write-int32-hex-buffered *(ebp+0x10) %eax)
33244     (write-buffered *(ebp+0x10) Newline)
33245     (flush *(ebp+0x10))
33246     (stop *(ebp+0x14) 1)
33247     # never gets here
33248 
33249 emit-subx-r32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
33250     # . prologue
33251     55/push-ebp
33252     89/<- %ebp 4/r32/esp
33253     # . save registers
33254     50/push-eax
33255     51/push-ecx
33256     # if (l == 0) return
33257     81 7/subop/compare *(ebp+0xc) 0/imm32
33258     0f 84/jump-if-= $emit-subx-r32:end/disp32
33259     # var v/eax: (addr stmt-var)
33260     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
33261     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
33262     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
33263 #?     (write-buffered Stderr "looking up ")
33264 #?     (write-buffered Stderr %eax)
33265 #?     (write-buffered Stderr Newline)
33266 #?     (flush Stderr)
33267     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
33268     (write-buffered *(ebp+8) Space)
33269     (write-int32-hex-buffered *(ebp+8) *eax)
33270     (write-buffered *(ebp+8) "/r32")
33271 $emit-subx-r32:end:
33272     # . restore registers
33273     59/pop-to-ecx
33274     58/pop-to-eax
33275     # . epilogue
33276     89/<- %esp 5/r32/ebp
33277     5d/pop-to-ebp
33278     c3/return
33279 
33280 emit-subx-x32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
33281     # . prologue
33282     55/push-ebp
33283     89/<- %ebp 4/r32/esp
33284     # . save registers
33285     50/push-eax
33286     51/push-ecx
33287     # if (l == 0) return
33288     81 7/subop/compare *(ebp+0xc) 0/imm32
33289     0f 84/jump-if-= $emit-subx-x32:end/disp32
33290     # var v/eax: (addr stmt-var)
33291     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
33292     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
33293     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
33294 #?     (write-buffered Stderr "looking up ")
33295 #?     (write-buffered Stderr %eax)
33296 #?     (write-buffered Stderr Newline)
33297 #?     (flush Stderr)
33298     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
33299     (write-buffered *(ebp+8) Space)
33300     (write-int32-hex-buffered *(ebp+8) *eax)
33301     (write-buffered *(ebp+8) "/x32")
33302 $emit-subx-x32:end:
33303     # . restore registers
33304     59/pop-to-ecx
33305     58/pop-to-eax
33306     # . epilogue
33307     89/<- %esp 5/r32/ebp
33308     5d/pop-to-ebp
33309     c3/return
33310 
33311 emit-subx-imm32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
33312     # . prologue
33313     55/push-ebp
33314     89/<- %ebp 4/r32/esp
33315     # . save registers
33316     50/push-eax
33317     51/push-ecx
33318     # if (l == 0) return
33319     81 7/subop/compare *(ebp+0xc) 0/imm32
33320     0f 84/jump-if-= $emit-subx-imm32:end/disp32
33321     # var v/eax: (handle var)
33322     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
33323     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
33324     (lookup *eax *(eax+4))  # Var-name Var-name => eax
33325     (write-buffered *(ebp+8) Space)
33326     (write-buffered *(ebp+8) %eax)
33327     (write-buffered *(ebp+8) "/imm32")
33328 $emit-subx-imm32:end:
33329     # . restore registers
33330     59/pop-to-ecx
33331     58/pop-to-eax
33332     # . epilogue
33333     89/<- %esp 5/r32/ebp
33334     5d/pop-to-ebp
33335     c3/return
33336 
33337 emit-subx-imm8:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
33338     # . prologue
33339     55/push-ebp
33340     89/<- %ebp 4/r32/esp
33341     # . save registers
33342     50/push-eax
33343     51/push-ecx
33344     # if (l == 0) return
33345     81 7/subop/compare *(ebp+0xc) 0/imm32
33346     0f 84/jump-if-= $emit-subx-imm32:end/disp32
33347     # var v/eax: (handle var)
33348     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
33349     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
33350     (lookup *eax *(eax+4))  # Var-name Var-name => eax
33351     (write-buffered *(ebp+8) Space)
33352     (write-buffered *(ebp+8) %eax)
33353     (write-buffered *(ebp+8) "/imm8")
33354 $emit-subx-imm8:end:
33355     # . restore registers
33356     59/pop-to-ecx
33357     58/pop-to-eax
33358     # . epilogue
33359     89/<- %esp 5/r32/ebp
33360     5d/pop-to-ebp
33361     c3/return
33362 
33363 emit-subx-disp32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
33364     # . prologue
33365     55/push-ebp
33366     89/<- %ebp 4/r32/esp
33367     # . save registers
33368     50/push-eax
33369     51/push-ecx
33370     # if (location == 0) return
33371     81 7/subop/compare *(ebp+0xc) 0/imm32
33372     0f 84/jump-if-= $emit-subx-disp32:end/disp32
33373     # var v/eax: (addr stmt-var)
33374     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # => eax
33375     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
33376     (lookup *eax *(eax+4))  # Var-name Var-name => eax
33377     (write-buffered *(ebp+8) Space)
33378     (write-buffered *(ebp+8) %eax)
33379     # hack: if instruction operation starts with "break", emit ":break"
33380     # var name/ecx: (addr array byte) = lookup(stmt->operation)
33381     8b/-> *(ebp+0x10) 0/r32/eax
33382     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
33383     89/<- %ecx 0/r32/eax
33384     {
33385       (string-starts-with? %ecx "break")  # => eax
33386       3d/compare-eax-and 0/imm32/false
33387       74/jump-if-= break/disp8
33388       (write-buffered *(ebp+8) ":break")
33389     }
33390     # hack: if instruction operation starts with "loop", emit ":loop"
33391     {
33392       (string-starts-with? %ecx "loop")  # => eax
33393       3d/compare-eax-and 0/imm32/false
33394       74/jump-if-= break/disp8
33395       (write-buffered *(ebp+8) ":loop")
33396     }
33397     (write-buffered *(ebp+8) "/disp32")
33398 $emit-subx-disp32:end:
33399     # . restore registers
33400     59/pop-to-ecx
33401     58/pop-to-eax
33402     # . epilogue
33403     89/<- %esp 5/r32/ebp
33404     5d/pop-to-ebp
33405     c3/return
33406 
33407 emit-call:  # out: (addr buffered-file), stmt: (addr stmt)
33408     # . prologue
33409     55/push-ebp
33410     89/<- %ebp 4/r32/esp
33411     # . save registers
33412     50/push-eax
33413     51/push-ecx
33414     #
33415     (emit-indent *(ebp+8) *Curr-block-depth)
33416     (write-buffered *(ebp+8) "(")
33417     # ecx = stmt
33418     8b/-> *(ebp+0xc) 1/r32/ecx
33419     # - emit function name
33420     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
33421     (write-buffered *(ebp+8) %eax)
33422     # - emit arguments
33423     # var curr/eax: (addr stmt-var) = lookup(stmt->inouts)
33424     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
33425     {
33426       # if (curr == null) break
33427       3d/compare-eax-and 0/imm32
33428       74/jump-if-= break/disp8
33429       #
33430       (emit-subx-call-operand *(ebp+8) %eax)
33431       # curr = lookup(curr->next)
33432       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
33433       eb/jump loop/disp8
33434     }
33435     #
33436     (write-buffered *(ebp+8) ")\n")
33437 $emit-call:end:
33438     # . restore registers
33439     59/pop-to-ecx
33440     58/pop-to-eax
33441     # . epilogue
33442     89/<- %esp 5/r32/ebp
33443     5d/pop-to-ebp
33444     c3/return
33445 
33446 emit-subx-call-operand:  # out: (addr buffered-file), s: (addr stmt-var)
33447     # shares code with emit-subx-var-as-rm32
33448     # . prologue
33449     55/push-ebp
33450     89/<- %ebp 4/r32/esp
33451     # . save registers
33452     50/push-eax
33453     51/push-ecx
33454     56/push-esi
33455     # ecx = s
33456     8b/-> *(ebp+0xc) 1/r32/ecx
33457     # var operand/esi: (addr var) = lookup(s->value)
33458     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
33459     89/<- %esi 0/r32/eax
33460     # if (operand->register && !s->is-deref?) emit "%__"
33461     {
33462 $emit-subx-call-operand:check-for-register-direct:
33463       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
33464       74/jump-if-= break/disp8
33465       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
33466       75/jump-if-!= break/disp8
33467 $emit-subx-call-operand:register-direct:
33468       (write-buffered *(ebp+8) " %")
33469       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
33470       (write-buffered *(ebp+8) %eax)
33471       e9/jump $emit-subx-call-operand:end/disp32
33472     }
33473     # else if (operand->register && s->is-deref?) emit "*__"
33474     {
33475 $emit-subx-call-operand:check-for-register-indirect:
33476       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
33477       74/jump-if-= break/disp8
33478       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
33479       74/jump-if-= break/disp8
33480 $emit-subx-call-operand:register-indirect:
33481       (emit-subx-call-operand-register-indirect *(ebp+8) %esi)
33482       e9/jump $emit-subx-call-operand:end/disp32
33483     }
33484     # else if (operand->stack-offset) emit "*(ebp+__)"
33485     {
33486       81 7/subop/compare *(esi+0x14) 0/imm32  # Var-offset
33487       74/jump-if-= break/disp8
33488 $emit-subx-call-operand:stack:
33489       (emit-subx-call-operand-stack *(ebp+8) %esi)
33490       e9/jump $emit-subx-call-operand:end/disp32
33491     }
33492     # else if (operand->type == literal) emit "__"
33493     {
33494       (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
33495       81 7/subop/compare *(eax+4) 0/imm32  # Type-tree-value
33496       75/jump-if-!= break/disp8
33497 $emit-subx-call-operand:literal:
33498       (write-buffered *(ebp+8) Space)
33499       (lookup *esi *(esi+4))  # Var-name Var-name => eax
33500       (write-buffered *(ebp+8) %eax)
33501       e9/jump $emit-subx-call-operand:end/disp32
33502     }
33503     # else if (operand->type == literal-string) emit "__"
33504     {
33505       (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
33506       81 7/subop/compare *(eax+4) 0x10/imm32  # Type-tree-value
33507       75/jump-if-!= break/disp8
33508 $emit-subx-call-operand:literal-string:
33509       (write-buffered *(ebp+8) Space)
33510       (lookup *esi *(esi+4))  # Var-name Var-name => eax
33511       (write-buffered *(ebp+8) %eax)
33512     }
33513 $emit-subx-call-operand:end:
33514     # . restore registers
33515     5e/pop-to-esi
33516     59/pop-to-ecx
33517     58/pop-to-eax
33518     # . epilogue
33519     89/<- %esp 5/r32/ebp
33520     5d/pop-to-ebp
33521     c3/return
33522 
33523 emit-subx-call-operand-register-indirect:  # out: (addr buffered-file), v: (addr var)
33524     # . prologue
33525     55/push-ebp
33526     89/<- %ebp 4/r32/esp
33527     # . save registers
33528     50/push-eax
33529     51/push-ecx
33530     56/push-esi
33531     # esi = v
33532     8b/-> *(ebp+0xc) 6/r32/esi
33533     # var size/ecx: int = size-of-deref(v)
33534     (size-of-deref %esi)  # => eax
33535     89/<- %ecx 0/r32/eax
33536     # var reg-name/esi: (addr array byte) = lookup(v->register)
33537     (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
33538     89/<- %esi 0/r32/eax
33539     # TODO: assert size is a multiple of 4
33540     # var i/eax: int = 0
33541     b8/copy-to-eax 0/imm32
33542     {
33543 $emit-subx-call-operand-register-indirect:loop:
33544       # if (i >= size) break
33545       39/compare %eax 1/r32/ecx
33546       7d/jump-if->= break/disp8
33547       # emit " *(" v->register "+" i ")"
33548       (write-buffered *(ebp+8) " *(")
33549       (write-buffered *(ebp+8) %esi)
33550       (write-buffered *(ebp+8) "+")
33551       (write-int32-hex-buffered *(ebp+8) %eax)
33552       (write-buffered *(ebp+8) ")")
33553       # i += 4
33554       05/add-to-eax 4/imm32
33555       #
33556       eb/jump loop/disp8
33557     }
33558 $emit-subx-call-operand-register-indirect:end:
33559     # . restore registers
33560     5e/pop-to-esi
33561     59/pop-to-ecx
33562     58/pop-to-eax
33563     # . epilogue
33564     89/<- %esp 5/r32/ebp
33565     5d/pop-to-ebp
33566     c3/return
33567 
33568 emit-subx-call-operand-stack:  # out: (addr buffered-file), v: (addr var)
33569     # . prologue
33570     55/push-ebp
33571     89/<- %ebp 4/r32/esp
33572     # . save registers
33573     50/push-eax
33574     51/push-ecx
33575     56/push-esi
33576     # esi = v
33577     8b/-> *(ebp+0xc) 6/r32/esi
33578     # var curr/ecx: int = v->offset
33579     8b/-> *(esi+0x14) 1/r32/ecx  # Var-offset
33580     # var max/eax: int = v->offset + size-of(v)
33581     (size-of %esi)  # => eax
33582     # TODO: assert size is a multiple of 4
33583     01/add-to %eax 1/r32/ecx
33584     {
33585 $emit-subx-call-operand-stack:loop:
33586       # if (curr >= max) break
33587       39/compare %ecx 0/r32/eax
33588       7d/jump-if->= break/disp8
33589       # emit " *(ebp+" curr ")"
33590       (write-buffered *(ebp+8) " *(ebp+")
33591       (write-int32-hex-buffered *(ebp+8) %ecx)
33592       (write-buffered *(ebp+8) ")")
33593       # i += 4
33594       81 0/subop/add %ecx 4/imm32
33595       #
33596       eb/jump loop/disp8
33597     }
33598 $emit-subx-call-operand-stack:end:
33599     # . restore registers
33600     5e/pop-to-esi
33601     59/pop-to-ecx
33602     58/pop-to-eax
33603     # . epilogue
33604     89/<- %esp 5/r32/ebp
33605     5d/pop-to-ebp
33606     c3/return
33607 
33608 emit-subx-var-as-rm32:  # out: (addr buffered-file), s: (addr stmt-var)
33609     # . prologue
33610     55/push-ebp
33611     89/<- %ebp 4/r32/esp
33612     # . save registers
33613     50/push-eax
33614     51/push-ecx
33615     56/push-esi
33616     # ecx = s
33617     8b/-> *(ebp+0xc) 1/r32/ecx
33618     # var operand/esi: (addr var) = lookup(s->value)
33619     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
33620     89/<- %esi 0/r32/eax
33621     # if (operand->register && s->is-deref?) emit "*__"
33622     {
33623 $emit-subx-var-as-rm32:check-for-register-indirect:
33624       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
33625       74/jump-if-= break/disp8
33626       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
33627       74/jump-if-= break/disp8
33628 $emit-subx-var-as-rm32:register-indirect:
33629       (write-buffered *(ebp+8) " *")
33630       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
33631       (write-buffered *(ebp+8) %eax)
33632       e9/jump $emit-subx-var-as-rm32:end/disp32
33633     }
33634     # if (operand->register && !s->is-deref?) emit "%__"
33635     {
33636 $emit-subx-var-as-rm32:check-for-register-direct:
33637       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
33638       74/jump-if-= break/disp8
33639       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
33640       75/jump-if-!= break/disp8
33641 $emit-subx-var-as-rm32:register-direct:
33642       (write-buffered *(ebp+8) " %")
33643       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
33644       (write-buffered *(ebp+8) %eax)
33645       e9/jump $emit-subx-var-as-rm32:end/disp32
33646     }
33647     # else if (operand->stack-offset) emit "*(ebp+__)"
33648     {
33649       81 7/subop/compare *(esi+0x14) 0/imm32  # Var-offset
33650       74/jump-if-= break/disp8
33651 $emit-subx-var-as-rm32:stack:
33652       (write-buffered *(ebp+8) Space)
33653       (write-buffered *(ebp+8) "*(ebp+")
33654       (write-int32-hex-buffered *(ebp+8) *(esi+0x14))  # Var-offset
33655       (write-buffered *(ebp+8) ")")
33656     }
33657 $emit-subx-var-as-rm32:end:
33658     # . restore registers
33659     5e/pop-to-esi
33660     59/pop-to-ecx
33661     58/pop-to-eax
33662     # . epilogue
33663     89/<- %esp 5/r32/ebp
33664     5d/pop-to-ebp
33665     c3/return
33666 
33667 find-matching-primitive:  # primitives: (addr primitive), stmt: (addr stmt) -> result/eax: (addr primitive)
33668     # . prologue
33669     55/push-ebp
33670     89/<- %ebp 4/r32/esp
33671     # . save registers
33672     51/push-ecx
33673     # var curr/ecx: (addr primitive) = primitives
33674     8b/-> *(ebp+8) 1/r32/ecx
33675     {
33676 $find-matching-primitive:loop:
33677       # if (curr == null) break
33678       81 7/subop/compare %ecx 0/imm32
33679       74/jump-if-= break/disp8
33680       # if match(curr, stmt) return curr
33681       {
33682         (mu-stmt-matches-primitive? *(ebp+0xc) %ecx)  # => eax
33683         3d/compare-eax-and 0/imm32/false
33684         74/jump-if-= break/disp8
33685         89/<- %eax 1/r32/ecx
33686         eb/jump $find-matching-primitive:end/disp8
33687       }
33688 $find-matching-primitive:next-primitive:
33689       # curr = curr->next
33690       (lookup *(ecx+0x3c) *(ecx+0x40))  # Primitive-next Primitive-next => eax
33691       89/<- %ecx 0/r32/eax
33692       #
33693       e9/jump loop/disp32
33694     }
33695     # return null
33696     b8/copy-to-eax 0/imm32
33697 $find-matching-primitive:end:
33698     # . restore registers
33699     59/pop-to-ecx
33700     # . epilogue
33701     89/<- %esp 5/r32/ebp
33702     5d/pop-to-ebp
33703     c3/return
33704 
33705 mu-stmt-matches-primitive?:  # stmt: (addr stmt), primitive: (addr primitive) -> result/eax: boolean
33706     # A mu stmt matches a primitive if the name matches, all the inout vars
33707     # match, and all the output vars match.
33708     # Vars match if types match and registers match.
33709     # In addition, a stmt output matches a primitive's output if types match
33710     # and the primitive has a wildcard register.
33711     # . prologue
33712     55/push-ebp
33713     89/<- %ebp 4/r32/esp
33714     # . save registers
33715     51/push-ecx
33716     52/push-edx
33717     53/push-ebx
33718     56/push-esi
33719     57/push-edi
33720     # ecx = stmt
33721     8b/-> *(ebp+8) 1/r32/ecx
33722     # edx = primitive
33723     8b/-> *(ebp+0xc) 2/r32/edx
33724     {
33725 $mu-stmt-matches-primitive?:check-name:
33726       # if (primitive->name != stmt->operation) return false
33727       # . var esi: (addr array byte) = lookup(stmt->operation)
33728       (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
33729       89/<- %esi 0/r32/eax
33730       # . var edi: (addr array byte) = lookup(primitive->name)
33731       (lookup *edx *(edx+4))  # Primitive-name Primitive-name => eax
33732 #?       (write-buffered Stderr %eax)
33733 #?       (write-buffered Stderr Newline)
33734 #?       (flush Stderr)
33735       89/<- %edi 0/r32/eax
33736       (string-equal? %esi %edi)  # => eax
33737       3d/compare-eax-and 0/imm32/false
33738       75/jump-if-!= break/disp8
33739       b8/copy-to-eax 0/imm32
33740       e9/jump $mu-stmt-matches-primitive?:end/disp32
33741     }
33742     # var curr/esi: (addr stmt-var) = lookup(stmt->inouts)
33743     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
33744     89/<- %esi 0/r32/eax
33745     # var curr2/edi: (addr list var) = lookup(primitive->inouts)
33746     (lookup *(edx+8) *(edx+0xc))  # Primitive-inouts Primitive-inouts => eax
33747     89/<- %edi 0/r32/eax
33748     {
33749 $mu-stmt-matches-primitive?:inouts-loop:
33750       # if (curr == 0 && curr2 == 0) move on to check outputs
33751       {
33752 $mu-stmt-matches-primitive?:check-both-inouts-null:
33753         81 7/subop/compare %esi 0/imm32
33754         75/jump-if-!= break/disp8
33755 $mu-stmt-matches-primitive?:stmt-inout-null:
33756         81 7/subop/compare %edi 0/imm32
33757         0f 84/jump-if-= $mu-stmt-matches-primitive?:check-outputs/disp32
33758 $mu-stmt-matches-primitive?:stmt-inout-null-and-prim-inout-not-null:
33759         # return false
33760         b8/copy-to-eax 0/imm32/false
33761         e9/jump $mu-stmt-matches-primitive?:end/disp32
33762       }
33763       # if (curr2 == 0) return false
33764       {
33765 $mu-stmt-matches-primitive?:check-prim-inout-null:
33766         81 7/subop/compare %edi 0/imm32
33767         75/jump-if-!= break/disp8
33768 $mu-stmt-matches-primitive?:prim-inout-null:
33769         b8/copy-to-eax 0/imm32/false
33770         e9/jump $mu-stmt-matches-primitive?:end/disp32
33771       }
33772       # if (curr != curr2) return false
33773       {
33774 $mu-stmt-matches-primitive?:check-inouts-match:
33775         (lookup *edi *(edi+4))  # List-value List-value => eax
33776         (operand-matches-primitive? %esi %eax)  # => eax
33777         3d/compare-eax-and 0/imm32/false
33778         75/jump-if-!= break/disp8
33779 $mu-stmt-matches-primitive?:inouts-match:
33780         b8/copy-to-eax 0/imm32/false
33781         e9/jump $mu-stmt-matches-primitive?:end/disp32
33782       }
33783 $mu-stmt-matches-primitive?:next-inout:
33784       # curr = lookup(curr->next)
33785       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
33786       89/<- %esi 0/r32/eax
33787       # curr2 = lookup(curr2->next)
33788       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
33789       89/<- %edi 0/r32/eax
33790       #
33791       e9/jump loop/disp32
33792     }
33793 $mu-stmt-matches-primitive?:check-outputs:
33794     # var curr/esi: (addr stmt-var) = lookup(stmt->outputs)
33795     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
33796     89/<- %esi 0/r32/eax
33797     # var curr2/edi: (addr list var) = lookup(primitive->outputs)
33798     (lookup *(edx+0x10) *(edx+0x14))  # Primitive-outputs Primitive-outputs => eax
33799     89/<- %edi 0/r32/eax
33800     {
33801 $mu-stmt-matches-primitive?:outputs-loop:
33802       # if (curr == 0) return (curr2 == 0)
33803       {
33804 $mu-stmt-matches-primitive?:check-both-outputs-null:
33805         81 7/subop/compare %esi 0/imm32
33806         75/jump-if-!= break/disp8
33807         {
33808 $mu-stmt-matches-primitive?:stmt-output-null:
33809           81 7/subop/compare %edi 0/imm32
33810           75/jump-if-!= break/disp8
33811 $mu-stmt-matches-primitive?:both-outputs-null:
33812           # return true
33813           b8/copy-to-eax 1/imm32
33814           e9/jump $mu-stmt-matches-primitive?:end/disp32
33815         }
33816 $mu-stmt-matches-primitive?:stmt-output-null-and-prim-output-not-null:
33817         # return false
33818         b8/copy-to-eax 0/imm32
33819         e9/jump $mu-stmt-matches-primitive?:end/disp32
33820       }
33821       # if (curr2 == 0) return false
33822       {
33823 $mu-stmt-matches-primitive?:check-prim-output-null:
33824         81 7/subop/compare %edi 0/imm32
33825         75/jump-if-!= break/disp8
33826 $mu-stmt-matches-primitive?:prim-output-is-null:
33827         b8/copy-to-eax 0/imm32
33828         e9/jump $mu-stmt-matches-primitive?:end/disp32
33829       }
33830       # if (curr != curr2) return false
33831       {
33832 $mu-stmt-matches-primitive?:check-outputs-match:
33833         (lookup *edi *(edi+4))  # List-value List-value => eax
33834         (operand-matches-primitive? %esi %eax)  # => eax
33835         3d/compare-eax-and 0/imm32/false
33836         75/jump-if-!= break/disp8
33837 $mu-stmt-matches-primitive?:outputs-match:
33838         b8/copy-to-eax 0/imm32
33839         e9/jump $mu-stmt-matches-primitive?:end/disp32
33840       }
33841 $mu-stmt-matches-primitive?:next-output:
33842       # curr = lookup(curr->next)
33843       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
33844       89/<- %esi 0/r32/eax
33845       # curr2 = lookup(curr2->next)
33846       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
33847       89/<- %edi 0/r32/eax
33848       #
33849       e9/jump loop/disp32
33850     }
33851 $mu-stmt-matches-primitive?:return-true:
33852     b8/copy-to-eax 1/imm32
33853 $mu-stmt-matches-primitive?:end:
33854     # . restore registers
33855     5f/pop-to-edi
33856     5e/pop-to-esi
33857     5b/pop-to-ebx
33858     5a/pop-to-edx
33859     59/pop-to-ecx
33860     # . epilogue
33861     89/<- %esp 5/r32/ebp
33862     5d/pop-to-ebp
33863     c3/return
33864 
33865 operand-matches-primitive?:  # s: (addr stmt-var), prim-var: (addr var) -> result/eax: boolean
33866     # . prologue
33867     55/push-ebp
33868     89/<- %ebp 4/r32/esp
33869     # . save registers
33870     51/push-ecx
33871     52/push-edx
33872     53/push-ebx
33873     56/push-esi
33874     57/push-edi
33875     # ecx = s
33876     8b/-> *(ebp+8) 1/r32/ecx
33877     # var var/esi: (addr var) = lookup(s->value)
33878     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
33879     89/<- %esi 0/r32/eax
33880     # edi = prim-var
33881     8b/-> *(ebp+0xc) 7/r32/edi
33882 $operand-matches-primitive?:check-type:
33883     # if !category-match?(var->type, prim-var->type) return false
33884     # . var vtype/ebx: (addr type-tree) = lookup(var->type)
33885     (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
33886     89/<- %ebx 0/r32/eax
33887     # . if s is deref, vtype = vtype->right
33888     {
33889       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
33890       74/jump-if-= break/disp8
33891 $operand-matches-primitive?:is-deref:
33892       # . var t/eax: (addr type)
33893       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
33894       # . if !t->is-atom? t = t->left
33895       81 7/subop/compare *eax 0/imm32/false
33896       {
33897         75/jump-if-!= break/disp8
33898         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
33899       }
33900       # .
33901       89/<- %ebx 0/r32/eax
33902     }
33903     # . var ptype/eax: (addr type-tree) = lookup(prim-var->type)
33904     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
33905     (subx-type-category-match? %ebx %eax)  # => eax
33906     3d/compare-eax-and 0/imm32/false
33907     0f 84/jump-if-= $operand-matches-primitive?:return-false/disp32
33908     {
33909 $operand-matches-primitive?:check-register:
33910       # if prim-var is in memory and var is in register but dereference, match
33911       {
33912         81 7/subop/compare *(edi+0x18) 0/imm32  # Var-register
33913         0f 85/jump-if-!= break/disp32
33914         81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
33915         74/jump-if-= break/disp8
33916         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
33917         74/jump-if-= break/disp8
33918 $operand-matches-primitive?:var-deref-match:
33919         e9/jump $operand-matches-primitive?:return-true/disp32
33920       }
33921       # if prim-var is in register and var is in register but dereference, no match
33922       {
33923         81 7/subop/compare *(edi+0x18) 0/imm32  # Var-register
33924         0f 84/jump-if-= break/disp32
33925         81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
33926         0f 84/jump-if-= break/disp32
33927         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
33928         74/jump-if-= break/disp8
33929 $operand-matches-primitive?:var-deref-no-match:
33930         e9/jump $operand-matches-primitive?:return-false/disp32
33931       }
33932       # return false if var->register doesn't match prim-var->register
33933       {
33934         # if register addresses are equal, it's a match
33935         # var vreg/ebx: (addr array byte) = lookup(var->register)
33936         (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
33937         89/<- %ebx 0/r32/eax
33938         # var preg/ecx: (addr array byte) = lookup(prim-var->register)
33939         (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
33940         89/<- %ecx 0/r32/eax
33941         # if (vreg == preg) break
33942         39/compare %ecx 3/r32/ebx
33943         74/jump-if-= break/disp8
33944 $operand-matches-primitive?:var-register-no-match:
33945         # if either address is 0, return false
33946         81 7/subop/compare %ebx 0/imm32
33947         74/jump-if-=  $operand-matches-primitive?:return-false/disp8
33948         81 7/subop/compare %ecx 0/imm32
33949         74/jump-if-=  $operand-matches-primitive?:return-false/disp8
33950         # if prim-var->register is wildcard, it's a match
33951         (string-equal? %ecx "*")  # Any-register => eax
33952         3d/compare-eax-and 0/imm32/false
33953         75/jump-if-!= break/disp8
33954 $operand-matches-primitive?:wildcard-no-match:
33955         # if string contents aren't equal, return false
33956         (string-equal? %ecx %ebx)  # => eax
33957         3d/compare-eax-and 0/imm32/false
33958         74/jump-if-= $operand-matches-primitive?:return-false/disp8
33959       }
33960     }
33961 $operand-matches-primitive?:return-true:
33962     b8/copy-to-eax 1/imm32/true
33963     eb/jump $operand-matches-primitive?:end/disp8
33964 $operand-matches-primitive?:return-false:
33965     b8/copy-to-eax 0/imm32/false
33966 $operand-matches-primitive?:end:
33967     # . restore registers
33968     5f/pop-to-edi
33969     5e/pop-to-esi
33970     5b/pop-to-ebx
33971     5a/pop-to-edx
33972     59/pop-to-ecx
33973     # . epilogue
33974     89/<- %esp 5/r32/ebp
33975     5d/pop-to-ebp
33976     c3/return
33977 
33978 find-matching-function:  # functions: (addr function), stmt: (addr stmt) -> result/eax: (addr function)
33979     # . prologue
33980     55/push-ebp
33981     89/<- %ebp 4/r32/esp
33982     # . save registers
33983     51/push-ecx
33984     # var curr/ecx: (handle function) = functions
33985     8b/-> *(ebp+8) 1/r32/ecx
33986     {
33987       # if (curr == null) break
33988       81 7/subop/compare %ecx 0/imm32
33989       74/jump-if-= break/disp8
33990 #?       (write-buffered Stderr "iter\n")
33991 #?       (flush Stderr)
33992       # if match(stmt, curr) return curr
33993       {
33994         (mu-stmt-matches-function? *(ebp+0xc) %ecx)  # => eax
33995         3d/compare-eax-and 0/imm32/false
33996         74/jump-if-= break/disp8
33997         89/<- %eax 1/r32/ecx
33998         eb/jump $find-matching-function:end/disp8
33999       }
34000       # curr = curr->next
34001       (lookup *(ecx+0x20) *(ecx+0x24))  # Function-next Function-next => eax
34002       89/<- %ecx 0/r32/eax
34003       #
34004       eb/jump loop/disp8
34005     }
34006     # return null
34007     b8/copy-to-eax 0/imm32
34008 $find-matching-function:end:
34009     # . restore registers
34010     59/pop-to-ecx
34011     # . epilogue
34012     89/<- %esp 5/r32/ebp
34013     5d/pop-to-ebp
34014     c3/return
34015 
34016 # Just compare names; user-defined functions don't support overloading yet.
34017 mu-stmt-matches-function?:  # stmt: (addr stmt1), function: (addr function) -> result/eax: boolean
34018     # . prologue
34019     55/push-ebp
34020     89/<- %ebp 4/r32/esp
34021     # . save registers
34022     51/push-ecx
34023     # return function->name == stmt->operation
34024     # ecx = lookup(stmt->operation)
34025     8b/-> *(ebp+8) 0/r32/eax
34026     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
34027     89/<- %ecx 0/r32/eax
34028     # eax = lookup(function->name)
34029     8b/-> *(ebp+0xc) 0/r32/eax
34030     (lookup *eax *(eax+4))  # Function-name Function-name => eax
34031     (string-equal? %eax %ecx)  # => eax
34032 $mu-stmt-matches-function?:end:
34033     # . restore registers
34034     59/pop-to-ecx
34035     # . epilogue
34036     89/<- %esp 5/r32/ebp
34037     5d/pop-to-ebp
34038     c3/return
34039 
34040 # Type-checking happens elsewhere. This method is for selecting between
34041 # primitives.
34042 subx-type-category-match?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
34043     # . prologue
34044     55/push-ebp
34045     89/<- %ebp 4/r32/esp
34046     # . save registers
34047     51/push-ecx
34048     # var cata/ecx: int = type-category(a)
34049     (type-category *(ebp+8))  # => eax
34050     89/<- %ecx 0/r32/eax
34051     # var catb/eax: int = type-category(b)
34052     (type-category *(ebp+0xc))  # => eax
34053     # return cata == catb
34054     39/compare %eax 1/r32/ecx
34055     0f 94/set-byte-if-= %al
34056     81 4/subop/and %eax 0xff/imm32
34057 $subx-type-category-match?:end:
34058     # . restore registers
34059     59/pop-to-ecx
34060     # . epilogue
34061     89/<- %esp 5/r32/ebp
34062     5d/pop-to-ebp
34063     c3/return
34064 
34065 type-category:  # a: (addr type-tree) -> result/eax: int
34066     # . prologue
34067     55/push-ebp
34068     89/<- %ebp 4/r32/esp
34069     # . save registers
34070     51/push-ecx
34071     # var lit?/ecx: boolean = is-literal-type?(a)
34072     (is-simple-mu-type? *(ebp+8) 0)  # literal => eax
34073     89/<- %ecx 0/r32/eax
34074     # var float?/eax: int = is-float?(a)
34075     (is-simple-mu-type? *(ebp+8) 0xf)  # => eax
34076     # set bits for lit? and float?
34077     c1/shift 4/subop/left %ecx 1/imm8
34078     09/or %eax 1/r32/ecx
34079 $type-category:end:
34080     # . restore registers
34081     59/pop-to-ecx
34082     # . epilogue
34083     89/<- %esp 5/r32/ebp
34084     5d/pop-to-ebp
34085     c3/return
34086 
34087 is-simple-mu-type?:  # a: (addr type-tree), n: type-id -> result/eax: boolean
34088     # . prologue
34089     55/push-ebp
34090     89/<- %ebp 4/r32/esp
34091     # . save registers
34092     51/push-ecx
34093     # ecx = n
34094     8b/-> *(ebp+0xc) 1/r32/ecx
34095     # return (a->value == n)
34096     8b/-> *(ebp+8) 0/r32/eax
34097     39/compare *(eax+4) 1/r32/ecx  # Type-tree-value
34098     0f 94/set-byte-if-= %al
34099     81 4/subop/and %eax 0xff/imm32
34100 $is-simple-mu-type?:end:
34101     # . restore registers
34102     59/pop-to-ecx
34103     # . epilogue
34104     89/<- %esp 5/r32/ebp
34105     5d/pop-to-ebp
34106     c3/return
34107 
34108 is-mu-addr-type?:  # a: (addr type-tree) -> result/eax: boolean
34109     # . prologue
34110     55/push-ebp
34111     89/<- %ebp 4/r32/esp
34112     # eax = a
34113     8b/-> *(ebp+8) 0/r32/eax
34114     # if (!a->is-atom?) a = a->left
34115     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
34116     {
34117       75/jump-if-!= break/disp8
34118       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
34119     }
34120     # return (a->value == addr)
34121     81 7/subop/compare *(eax+4) 2/imm32/addr  # Type-tree-value
34122     0f 94/set-byte-if-= %al
34123     81 4/subop/and %eax 0xff/imm32
34124 $is-mu-addr-type?:end:
34125     # . epilogue
34126     89/<- %esp 5/r32/ebp
34127     5d/pop-to-ebp
34128     c3/return
34129 
34130 is-mu-array-type?:  # a: (addr type-tree) -> result/eax: boolean
34131     # . prologue
34132     55/push-ebp
34133     89/<- %ebp 4/r32/esp
34134     # eax = a
34135     8b/-> *(ebp+8) 0/r32/eax
34136     # if (!a->is-atom?) a = a->left
34137     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
34138     {
34139       75/jump-if-!= break/disp8
34140       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
34141     }
34142     # return (a->value == array)
34143     81 7/subop/compare *(eax+4) 3/imm32/array  # Type-tree-value
34144     0f 94/set-byte-if-= %al
34145     81 4/subop/and %eax 0xff/imm32
34146 $is-mu-array-type?:end:
34147     # . epilogue
34148     89/<- %esp 5/r32/ebp
34149     5d/pop-to-ebp
34150     c3/return
34151 
34152 is-mu-string-type?:  # a: (addr type-tree) -> result/eax: boolean
34153     # . prologue
34154     55/push-ebp
34155     89/<- %ebp 4/r32/esp
34156     # . save registers
34157     56/push-esi
34158     # esi = a
34159     8b/-> *(ebp+8) 6/r32/esi
34160     # if (a->is-atom?) return false
34161     81 7/subop/compare *esi 0/imm32/false  # Type-tree-is-atom
34162     0f 85/jump-if-!= $is-mu-string-type?:return-false/disp32
34163     # if a is not an addr, return false
34164     (is-mu-addr-type? %esi)  # => eax
34165     3d/compare-eax-with 0/imm32/false
34166     0f 84/jump-if-= $is-mu-string-type?:end/disp32  # eax changes var
34167     # if a is not an array, return false
34168     (lookup *(esi+0xc) *(esi+0x10))  # Type-tree-right Type-tree-right => eax
34169     (is-mu-array-type? %eax)  # => eax
34170     3d/compare-eax-with 0/imm32/false
34171     74/jump-if-= $is-mu-string-type?:end/disp8  # eax changes var
34172     # var p/eax: (addr type-tree) = payload of a
34173     (lookup *(esi+0xc) *(esi+0x10))  # Type-tree-right Type-tree-right => eax
34174     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
34175     # if p is an atom, return false
34176     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
34177     75/jump-if-!= $is-mu-string-type?:return-false/disp8
34178     # return (p == byte)
34179     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
34180     (is-simple-mu-type? %eax 8)  # byte => eax
34181     eb/jump $is-mu-string-type?:end/disp8
34182 $is-mu-string-type?:return-false:
34183     b8/copy-to-eax 0/imm32/false
34184 $is-mu-string-type?:end:
34185     # . restore registers
34186     5e/pop-to-esi
34187     # . epilogue
34188     89/<- %esp 5/r32/ebp
34189     5d/pop-to-ebp
34190     c3/return
34191 
34192 is-mu-stream-type?:  # a: (addr type-tree) -> result/eax: boolean
34193     # . prologue
34194     55/push-ebp
34195     89/<- %ebp 4/r32/esp
34196     # eax = a
34197     8b/-> *(ebp+8) 0/r32/eax
34198     # if (!a->is-atom?) a = a->left
34199     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
34200     {
34201       75/jump-if-!= break/disp8
34202       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
34203     }
34204     # return (a->value == stream)
34205     81 7/subop/compare *(eax+4) 0xb/imm32/stream  # Type-tree-value
34206     0f 94/set-byte-if-= %al
34207     81 4/subop/and %eax 0xff/imm32
34208 $is-mu-stream-type?:end:
34209     # . epilogue
34210     89/<- %esp 5/r32/ebp
34211     5d/pop-to-ebp
34212     c3/return
34213 
34214 test-emit-subx-stmt-primitive:
34215     # Primitive operation on a variable on the stack.
34216     #   increment foo
34217     # =>
34218     #   ff 0/subop/increment *(ebp-8)
34219     #
34220     # There's a variable on the var stack as follows:
34221     #   name: 'foo'
34222     #   type: int
34223     #   stack-offset: -8
34224     #
34225     # There's a primitive with this info:
34226     #   name: 'increment'
34227     #   inouts: int/mem
34228     #   value: 'ff 0/subop/increment'
34229     #
34230     # . prologue
34231     55/push-ebp
34232     89/<- %ebp 4/r32/esp
34233     # setup
34234     (clear-stream _test-output-stream)
34235     (clear-stream $_test-output-buffered-file->buffer)
34236     # simulate allocated payloads starting with an initial fake alloc-id (0x11)
34237 $test-emit-subx-stmt-primitive:initialize-type:
34238     # var type/ecx: (payload type-tree) = int
34239     68/push 0/imm32/right:null
34240     68/push 0/imm32/right:null
34241     68/push 0/imm32/left:unused
34242     68/push 1/imm32/value:int
34243     68/push 1/imm32/is-atom?:true
34244     68/push 0x11/imm32/alloc-id:fake:payload
34245     89/<- %ecx 4/r32/esp
34246 $test-emit-subx-stmt-primitive:initialize-var:
34247     # var var-foo/ecx: (payload var) = var(type)
34248     68/push 0/imm32/no-register
34249     68/push 0/imm32/no-register
34250     68/push -8/imm32/stack-offset
34251     68/push 1/imm32/block-depth
34252     51/push-ecx/type
34253     68/push 0x11/imm32/alloc-id:fake
34254     68/push 0/imm32/name
34255     68/push 0/imm32/name
34256     68/push 0x11/imm32/alloc-id:fake:payload
34257     89/<- %ecx 4/r32/esp
34258 $test-emit-subx-stmt-primitive:initialize-var-name:
34259     # var-foo->name = "foo"
34260     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
34261     (copy-array Heap "foo" %eax)
34262 $test-emit-subx-stmt-primitive:initialize-stmt-var:
34263     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
34264     68/push 0/imm32/is-deref:false
34265     68/push 0/imm32/next
34266     68/push 0/imm32/next
34267     51/push-ecx/var-foo
34268     68/push 0x11/imm32/alloc-id:fake
34269     68/push 0x11/imm32/alloc-id:fake:payload
34270     89/<- %ebx 4/r32/esp
34271 $test-emit-subx-stmt-primitive:initialize-stmt:
34272     # var stmt/esi: (addr statement)
34273     68/push 0/imm32/no-outputs
34274     68/push 0/imm32/no-outputs
34275     53/push-ebx/inouts
34276     68/push 0x11/imm32/alloc-id:fake
34277     68/push 0/imm32/operation
34278     68/push 0/imm32/operation
34279     68/push 1/imm32/tag
34280     89/<- %esi 4/r32/esp
34281 $test-emit-subx-stmt-primitive:initialize-stmt-operation:
34282     # stmt->operation = "increment"
34283     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
34284     (copy-array Heap "increment" %eax)
34285 $test-emit-subx-stmt-primitive:initialize-primitive:
34286     # var primitives/ebx: (addr primitive)
34287     68/push 0/imm32/next
34288     68/push 0/imm32/next
34289     68/push 0/imm32/no-x32
34290     68/push 0/imm32/no-xm32
34291     68/push 0/imm32/no-disp32
34292     68/push 0/imm32/no-imm8
34293     68/push 0/imm32/no-imm32
34294     68/push 0/imm32/no-r32
34295     68/push 1/imm32/rm32-is-first-inout
34296     68/push 0/imm32/subx-name
34297     68/push 0/imm32/subx-name
34298     68/push 0/imm32/no-outputs
34299     68/push 0/imm32/no-outputs
34300     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
34301     68/push 0x11/imm32/alloc-id:fake
34302     68/push 0/imm32/name
34303     68/push 0/imm32/name
34304     89/<- %ebx 4/r32/esp
34305 $test-emit-subx-stmt-primitive:initialize-primitive-name:
34306     # primitives->name = "increment"
34307     (copy-array Heap "increment" %ebx)  # Primitive-name
34308 $test-emit-subx-stmt-primitive:initialize-primitive-subx-name:
34309     # primitives->subx-name = "ff 0/subop/increment"
34310     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
34311     (copy-array Heap "ff 0/subop/increment" %eax)
34312     # convert
34313     c7 0/subop/copy *Curr-block-depth 0/imm32
34314     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
34315     (flush _test-output-buffered-file)
34316 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
34322     # check output
34323     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-stmt-primitive")
34324     # . epilogue
34325     89/<- %esp 5/r32/ebp
34326     5d/pop-to-ebp
34327     c3/return
34328 
34329 test-emit-subx-stmt-primitive-register:
34330     # Primitive operation on a variable in a register.
34331     #   foo <- increment
34332     # =>
34333     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
34334     #
34335     # There's a variable on the var stack as follows:
34336     #   name: 'foo'
34337     #   type: int
34338     #   register: 'eax'
34339     #
34340     # There's a primitive with this info:
34341     #   name: 'increment'
34342     #   out: int/reg
34343     #   value: 'ff 0/subop/increment'
34344     #
34345     # . prologue
34346     55/push-ebp
34347     89/<- %ebp 4/r32/esp
34348     # setup
34349     (clear-stream _test-output-stream)
34350     (clear-stream $_test-output-buffered-file->buffer)
34351 $test-emit-subx-stmt-primitive-register:initialize-type:
34352     # var type/ecx: (payload type-tree) = int
34353     68/push 0/imm32/right:null
34354     68/push 0/imm32/right:null
34355     68/push 0/imm32/left:unused
34356     68/push 1/imm32/value:int
34357     68/push 1/imm32/is-atom?:true
34358     68/push 0x11/imm32/alloc-id:fake:payload
34359     89/<- %ecx 4/r32/esp
34360 $test-emit-subx-stmt-primitive-register:initialize-var:
34361     # var var-foo/ecx: (payload var)
34362     68/push 0/imm32/register
34363     68/push 0/imm32/register
34364     68/push 0/imm32/no-stack-offset
34365     68/push 1/imm32/block-depth
34366     51/push-ecx
34367     68/push 0x11/imm32/alloc-id:fake
34368     68/push 0/imm32/name
34369     68/push 0/imm32/name
34370     68/push 0x11/imm32/alloc-id:fake:payload
34371     89/<- %ecx 4/r32/esp
34372 $test-emit-subx-stmt-primitive-register:initialize-var-name:
34373     # var-foo->name = "foo"
34374     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
34375     (copy-array Heap "foo" %eax)
34376 $test-emit-subx-stmt-primitive-register:initialize-var-register:
34377     # var-foo->register = "eax"
34378     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
34379     (copy-array Heap "eax" %eax)
34380 $test-emit-subx-stmt-primitive-register:initialize-stmt-var:
34381     # var operand/ebx: (payload stmt-var)
34382     68/push 0/imm32/is-deref:false
34383     68/push 0/imm32/next
34384     68/push 0/imm32/next
34385     51/push-ecx/var-foo
34386     68/push 0x11/imm32/alloc-id:fake
34387     68/push 0x11/imm32/alloc-id:fake:payload
34388     89/<- %ebx 4/r32/esp
34389 $test-emit-subx-stmt-primitive-register:initialize-stmt:
34390     # var stmt/esi: (addr statement)
34391     53/push-ebx/outputs
34392     68/push 0x11/imm32/alloc-id:fake
34393     68/push 0/imm32/no-inouts
34394     68/push 0/imm32/no-inouts
34395     68/push 0/imm32/operation
34396     68/push 0/imm32/operation
34397     68/push 1/imm32
34398     89/<- %esi 4/r32/esp
34399 $test-emit-subx-stmt-primitive-register:initialize-stmt-operation:
34400     # stmt->operation = "increment"
34401     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
34402     (copy-array Heap "increment" %eax)
34403 $test-emit-subx-stmt-primitive-register:initialize-formal-var:
34404     # var formal-var/ebx: (payload var)
34405     68/push 0/imm32/register
34406     68/push 0/imm32/register
34407     68/push 0/imm32/no-stack-offset
34408     68/push 1/imm32/block-depth
34409     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
34410     68/push 0x11/imm32/alloc-id:fake
34411     68/push 0/imm32/name
34412     68/push 0/imm32/name
34413     68/push 0x11/imm32/alloc-id:fake:payload
34414     89/<- %ebx 4/r32/esp
34415 $test-emit-subx-stmt-primitive-register:initialize-formal-var-name:
34416     # formal-var->name = "dummy"
34417     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
34418     (copy-array Heap "dummy" %eax)
34419 $test-emit-subx-stmt-primitive-register:initialize-formal-register:
34420     # formal-var->register = "*"
34421     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
34422     (copy-array Heap "*" %eax)  # Any-register
34423 $test-emit-subx-stmt-primitive-register:initialize-var-list:
34424     # var formal-outputs/ebx: (payload list var)
34425     68/push 0/imm32/next
34426     68/push 0/imm32/next
34427     53/push-ebx/formal-var
34428     68/push 0x11/imm32/alloc-id:fake
34429     68/push 0x11/imm32/alloc-id:fake:payload
34430     89/<- %ebx 4/r32/esp
34431 $test-emit-subx-stmt-primitive-register:initialize-primitive:
34432     # var primitives/ebx: (addr primitive)
34433     68/push 0/imm32/next
34434     68/push 0/imm32/next
34435     68/push 0/imm32/no-x32
34436     68/push 0/imm32/no-xm32
34437     68/push 0/imm32/no-disp32
34438     68/push 0/imm32/no-imm8
34439     68/push 0/imm32/no-imm32
34440     68/push 0/imm32/no-r32
34441     68/push 3/imm32/rm32-is-first-output
34442     68/push 0/imm32/subx-name
34443     68/push 0/imm32/subx-name
34444     53/push-ebx/outputs
34445     68/push 0x11/imm32/alloc-id:fake
34446     68/push 0/imm32/no-inouts
34447     68/push 0/imm32/no-inouts
34448     68/push 0/imm32/name
34449     68/push 0/imm32/name
34450     89/<- %ebx 4/r32/esp
34451 $test-emit-subx-stmt-primitive-register:initialize-primitive-name:
34452     # primitives->name = "increment"
34453     (copy-array Heap "increment" %ebx)  # Primitive-name
34454 $test-emit-subx-stmt-primitive-register:initialize-primitive-subx-name:
34455     # primitives->subx-name = "ff 0/subop/increment"
34456     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
34457     (copy-array Heap "ff 0/subop/increment" %eax)
34458     # convert
34459     c7 0/subop/copy *Curr-block-depth 0/imm32
34460     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
34461     (flush _test-output-buffered-file)
34462 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
34468     # check output
34469     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-primitive-register")
34470     # . epilogue
34471     89/<- %esp 5/r32/ebp
34472     5d/pop-to-ebp
34473     c3/return
34474 
34475 test-emit-subx-stmt-select-primitive:
34476     # Select the right primitive between overloads.
34477     #   foo <- increment
34478     # =>
34479     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
34480     #
34481     # There's a variable on the var stack as follows:
34482     #   name: 'foo'
34483     #   type: int
34484     #   register: 'eax'
34485     #
34486     # There's two primitives, as follows:
34487     #   - name: 'increment'
34488     #     out: int/reg
34489     #     value: 'ff 0/subop/increment'
34490     #   - name: 'increment'
34491     #     inout: int/mem
34492     #     value: 'ff 0/subop/increment'
34493     #
34494     # . prologue
34495     55/push-ebp
34496     89/<- %ebp 4/r32/esp
34497     # setup
34498     (clear-stream _test-output-stream)
34499     (clear-stream $_test-output-buffered-file->buffer)
34500 $test-emit-subx-stmt-select-primitive:initialize-type:
34501     # var type/ecx: (payload type-tree) = int
34502     68/push 0/imm32/right:null
34503     68/push 0/imm32/right:null
34504     68/push 0/imm32/left:unused
34505     68/push 1/imm32/value:int
34506     68/push 1/imm32/is-atom?:true
34507     68/push 0x11/imm32/alloc-id:fake:payload
34508     89/<- %ecx 4/r32/esp
34509 $test-emit-subx-stmt-select-primitive:initialize-var:
34510     # var var-foo/ecx: (payload var)
34511     68/push 0/imm32/register
34512     68/push 0/imm32/register
34513     68/push 0/imm32/no-stack-offset
34514     68/push 1/imm32/block-depth
34515     51/push-ecx
34516     68/push 0x11/imm32/alloc-id:fake
34517     68/push 0/imm32/name
34518     68/push 0/imm32/name
34519     68/push 0x11/imm32/alloc-id:fake:payload
34520     89/<- %ecx 4/r32/esp
34521 $test-emit-subx-stmt-select-primitive:initialize-var-name:
34522     # var-foo->name = "foo"
34523     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
34524     (copy-array Heap "foo" %eax)
34525 $test-emit-subx-stmt-select-primitive:initialize-var-register:
34526     # var-foo->register = "eax"
34527     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
34528     (copy-array Heap "eax" %eax)
34529 $test-emit-subx-stmt-select-primitive:initialize-stmt-var:
34530     # var operand/ebx: (payload stmt-var)
34531     68/push 0/imm32/is-deref:false
34532     68/push 0/imm32/next
34533     68/push 0/imm32/next
34534     51/push-ecx/var-foo
34535     68/push 0x11/imm32/alloc-id:fake
34536     68/push 0x11/imm32/alloc-id:fake:payload
34537     89/<- %ebx 4/r32/esp
34538 $test-emit-subx-stmt-select-primitive:initialize-stmt:
34539     # var stmt/esi: (addr statement)
34540     53/push-ebx/outputs
34541     68/push 0x11/imm32/alloc-id:fake
34542     68/push 0/imm32/no-inouts
34543     68/push 0/imm32/no-inouts
34544     68/push 0/imm32/operation
34545     68/push 0/imm32/operation
34546     68/push 1/imm32
34547     89/<- %esi 4/r32/esp
34548 $test-emit-subx-stmt-select-primitive:initialize-stmt-operation:
34549     # stmt->operation = "increment"
34550     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
34551     (copy-array Heap "increment" %eax)
34552 $test-emit-subx-stmt-select-primitive:initialize-formal-var:
34553     # var formal-var/ebx: (payload var)
34554     68/push 0/imm32/register
34555     68/push 0/imm32/register
34556     68/push 0/imm32/no-stack-offset
34557     68/push 1/imm32/block-depth
34558     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
34559     68/push 0x11/imm32/alloc-id:fake
34560     68/push 0/imm32/name
34561     68/push 0/imm32/name
34562     68/push 0x11/imm32/alloc-id:fake:payload
34563     89/<- %ebx 4/r32/esp
34564 $test-emit-subx-stmt-select-primitive:initialize-formal-var-name:
34565     # formal-var->name = "dummy"
34566     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
34567     (copy-array Heap "dummy" %eax)
34568 $test-emit-subx-stmt-select-primitive:initialize-formal-register:
34569     # formal-var->register = "*"
34570     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
34571     (copy-array Heap "*" %eax)  # Any-register
34572 $test-emit-subx-stmt-select-primitive:initialize-var-list:
34573     # var formal-outputs/ebx: (payload list var)
34574     68/push 0/imm32/next
34575     68/push 0/imm32/next
34576     53/push-ebx/formal-var
34577     68/push 0x11/imm32/alloc-id:fake
34578     68/push 0x11/imm32/alloc-id:fake:payload
34579     89/<- %ebx 4/r32/esp
34580 $test-emit-subx-stmt-select-primitive:initialize-primitive2:
34581     # var primitive2/edi: (payload primitive)
34582     68/push 0/imm32/next
34583     68/push 0/imm32/next
34584     68/push 0/imm32/no-x32
34585     68/push 0/imm32/no-xm32
34586     68/push 0/imm32/no-disp32
34587     68/push 0/imm32/no-imm8
34588     68/push 0/imm32/no-imm32
34589     68/push 0/imm32/no-r32
34590     68/push 3/imm32/rm32-is-first-output
34591     68/push 0/imm32/subx-name
34592     68/push 0/imm32/subx-name
34593     53/push-ebx/outputs
34594     68/push 0x11/imm32/alloc-id:fake
34595     68/push 0/imm32/no-inouts
34596     68/push 0/imm32/no-inouts
34597     68/push 0/imm32/name
34598     68/push 0/imm32/name
34599     68/push 0x11/imm32/alloc-id:fake:payload
34600     89/<- %edi 4/r32/esp
34601 $test-emit-subx-stmt-select-primitive:initialize-primitive2-name:
34602     # primitives->name = "increment"
34603     8d/copy-address *(edi+4) 0/r32/eax  # Primitive-name + 4
34604     (copy-array Heap "increment" %eax)
34605 $test-emit-subx-stmt-select-primitive:initialize-primitive2-subx-name:
34606     # primitives->subx-name = "ff 0/subop/increment"
34607     8d/copy-address *(edi+0x1c) 0/r32/eax  # Primitive-subx-name + 4
34608     (copy-array Heap "ff 0/subop/increment" %eax)
34609 $test-emit-subx-stmt-select-primitive:initialize-primitive:
34610     # var primitives/ebx: (addr primitive)
34611     57/push-edi
34612     68/push 0x11/imm32/alloc-id:fake
34613     68/push 0/imm32/no-x32
34614     68/push 0/imm32/no-xm32
34615     68/push 0/imm32/no-disp32
34616     68/push 0/imm32/no-imm8
34617     68/push 0/imm32/no-imm32
34618     68/push 0/imm32/no-r32
34619     68/push 1/imm32/rm32-is-first-inout
34620     68/push 0/imm32/subx-name
34621     68/push 0/imm32/subx-name
34622     68/push 0/imm32/no-outputs
34623     68/push 0/imm32/no-outputs
34624     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
34625     68/push 0x11/imm32/alloc-id:fake
34626     68/push 0/imm32/name
34627     68/push 0/imm32/name
34628     89/<- %ebx 4/r32/esp
34629 $test-emit-subx-stmt-select-primitive:initialize-primitive-name:
34630     # primitives->name = "increment"
34631     (copy-array Heap "increment" %ebx)  # Primitive-name
34632 $test-emit-subx-stmt-select-primitive:initialize-primitive-subx-name:
34633     # primitives->subx-name = "ff 0/subop/increment"
34634     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
34635     (copy-array Heap "ff 0/subop/increment" %eax)
34636     # convert
34637     c7 0/subop/copy *Curr-block-depth 0/imm32
34638     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
34639     (flush _test-output-buffered-file)
34640 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
34646     # check output
34647     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive")
34648     # . epilogue
34649     89/<- %esp 5/r32/ebp
34650     5d/pop-to-ebp
34651     c3/return
34652 
34653 test-emit-subx-stmt-select-primitive-2:
34654     # Select the right primitive between overloads.
34655     #   increment foo
34656     # =>
34657     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
34658     #
34659     # There's a variable on the var stack as follows:
34660     #   name: 'foo'
34661     #   type: int
34662     #   register: 'eax'
34663     #
34664     # There's two primitives, as follows:
34665     #   - name: 'increment'
34666     #     out: int/reg
34667     #     value: 'ff 0/subop/increment'
34668     #   - name: 'increment'
34669     #     inout: int/mem
34670     #     value: 'ff 0/subop/increment'
34671     #
34672     # . prologue
34673     55/push-ebp
34674     89/<- %ebp 4/r32/esp
34675     # setup
34676     (clear-stream _test-output-stream)
34677     (clear-stream $_test-output-buffered-file->buffer)
34678 $test-emit-subx-stmt-select-primitive-2:initialize-type:
34679     # var type/ecx: (payload type-tree) = int
34680     68/push 0/imm32/right:null
34681     68/push 0/imm32/right:null
34682     68/push 0/imm32/left:unused
34683     68/push 1/imm32/value:int
34684     68/push 1/imm32/is-atom?:true
34685     68/push 0x11/imm32/alloc-id:fake:payload
34686     89/<- %ecx 4/r32/esp
34687 $test-emit-subx-stmt-select-primitive-2:initialize-var:
34688     # var var-foo/ecx: (payload var)
34689     68/push 0/imm32/register
34690     68/push 0/imm32/register
34691     68/push 0/imm32/no-stack-offset
34692     68/push 1/imm32/block-depth
34693     51/push-ecx
34694     68/push 0x11/imm32/alloc-id:fake
34695     68/push 0/imm32/name
34696     68/push 0/imm32/name
34697     68/push 0x11/imm32/alloc-id:fake:payload
34698     89/<- %ecx 4/r32/esp
34699 $test-emit-subx-stmt-select-primitive-2:initialize-var-name:
34700     # var-foo->name = "foo"
34701     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
34702     (copy-array Heap "foo" %eax)
34703 $test-emit-subx-stmt-select-primitive-2:initialize-var-register:
34704     # var-foo->register = "eax"
34705     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
34706     (copy-array Heap "eax" %eax)
34707 $test-emit-subx-stmt-select-primitive-2:initialize-stmt-var:
34708     # var operand/ebx: (payload stmt-var)
34709     68/push 0/imm32/is-deref:false
34710     68/push 0/imm32/next
34711     68/push 0/imm32/next
34712     51/push-ecx/var-foo
34713     68/push 0x11/imm32/alloc-id:fake
34714     68/push 0x11/imm32/alloc-id:fake:payload
34715     89/<- %ebx 4/r32/esp
34716 $test-emit-subx-stmt-select-primitive-2:initialize-stmt:
34717     # var stmt/esi: (addr statement)
34718     68/push 0/imm32/no-outputs
34719     68/push 0/imm32/no-outputs
34720     53/push-ebx/inouts
34721     68/push 0x11/imm32/alloc-id:fake
34722     68/push 0/imm32/operation
34723     68/push 0/imm32/operation
34724     68/push 1/imm32
34725     89/<- %esi 4/r32/esp
34726 $test-emit-subx-stmt-select-primitive-2:initialize-stmt-operation:
34727     # stmt->operation = "increment"
34728     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
34729     (copy-array Heap "increment" %eax)
34730 $test-emit-subx-stmt-select-primitive-2:initialize-formal-var:
34731     # var formal-var/ebx: (payload var)
34732     68/push 0/imm32/register
34733     68/push 0/imm32/register
34734     68/push 0/imm32/no-stack-offset
34735     68/push 1/imm32/block-depth
34736     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
34737     68/push 0x11/imm32/alloc-id:fake
34738     68/push 0/imm32/name
34739     68/push 0/imm32/name
34740     68/push 0x11/imm32/alloc-id:fake:payload
34741     89/<- %ebx 4/r32/esp
34742 $test-emit-subx-stmt-select-primitive-2:initialize-formal-var-name:
34743     # formal-var->name = "dummy"
34744     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
34745     (copy-array Heap "dummy" %eax)
34746 $test-emit-subx-stmt-select-primitive-2:initialize-formal-register:
34747     # formal-var->register = "*"
34748     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
34749     (copy-array Heap "*" %eax)  # Any-register
34750 $test-emit-subx-stmt-select-primitive-2:initialize-var-list:
34751     # var formal-outputs/ebx: (payload list stmt-var)
34752     68/push 0/imm32/next
34753     68/push 0/imm32/next
34754     53/push-ebx/formal-var
34755     68/push 0x11/imm32/alloc-id:fake
34756     68/push 0x11/imm32/alloc-id:fake:payload
34757     89/<- %ebx 4/r32/esp
34758 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2:
34759     # var primitive2/edi: (payload primitive)
34760     68/push 0/imm32/next
34761     68/push 0/imm32/next
34762     68/push 0/imm32/no-x32
34763     68/push 0/imm32/no-xm32
34764     68/push 0/imm32/no-disp32
34765     68/push 0/imm32/no-imm8
34766     68/push 0/imm32/no-imm32
34767     68/push 0/imm32/no-r32
34768     68/push 3/imm32/rm32-is-first-output
34769     68/push 0/imm32/subx-name
34770     68/push 0/imm32/subx-name
34771     53/push-ebx/outputs
34772     68/push 0x11/imm32/alloc-id:fake
34773     68/push 0/imm32/no-inouts
34774     68/push 0/imm32/no-inouts
34775     68/push 0/imm32/name
34776     68/push 0/imm32/name
34777     68/push 0x11/imm32/alloc-id:fake:payload
34778     89/<- %edi 4/r32/esp
34779 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2-name:
34780     # primitives->name = "increment"
34781     8d/copy-address *(edi+4) 0/r32/eax  # Primitive-name + 4
34782     (copy-array Heap "increment" %eax)
34783 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2-subx-name:
34784     # primitives->subx-name = "ff 0/subop/increment"
34785     8d/copy-address *(edi+0x1c) 0/r32/eax  # Primitive-subx-name + 4
34786     (copy-array Heap "ff 0/subop/increment" %eax)
34787 $test-emit-subx-stmt-select-primitive-2:initialize-primitive:
34788     # var primitives/ebx: (addr primitive)
34789     57/push-edi
34790     68/push 0x11/imm32/alloc-id:fake
34791     68/push 0/imm32/no-x32
34792     68/push 0/imm32/no-xm32
34793     68/push 0/imm32/no-disp32
34794     68/push 0/imm32/no-imm8
34795     68/push 0/imm32/no-imm32
34796     68/push 0/imm32/no-r32
34797     68/push 1/imm32/rm32-is-first-inout
34798     68/push 0/imm32/subx-name
34799     68/push 0/imm32/subx-name
34800     68/push 0/imm32/no-outputs
34801     68/push 0/imm32/no-outputs
34802     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
34803     68/push 0x11/imm32/alloc-id:fake
34804     68/push 0/imm32/name
34805     68/push 0/imm32/name
34806     89/<- %ebx 4/r32/esp
34807 $test-emit-subx-stmt-select-primitive-2:initialize-primitive-name:
34808     # primitives->name = "increment"
34809     (copy-array Heap "increment" %ebx)  # Primitive-name
34810 $test-emit-subx-stmt-select-primitive-2:initialize-primitive-subx-name:
34811     # primitives->subx-name = "ff 0/subop/increment"
34812     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
34813     (copy-array Heap "ff 0/subop/increment" %eax)
34814     # convert
34815     c7 0/subop/copy *Curr-block-depth 0/imm32
34816     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
34817     (flush _test-output-buffered-file)
34818 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
34824     # check output
34825     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive-2")
34826     # . epilogue
34827     89/<- %esp 5/r32/ebp
34828     5d/pop-to-ebp
34829     c3/return
34830 
34831 test-increment-register:
34832     # Select the right register between overloads.
34833     #   foo <- increment
34834     # =>
34835     #   50/increment-eax
34836     #
34837     # There's a variable on the var stack as follows:
34838     #   name: 'foo'
34839     #   type: int
34840     #   register: 'eax'
34841     #
34842     # Primitives are the global definitions.
34843     #
34844     # . prologue
34845     55/push-ebp
34846     89/<- %ebp 4/r32/esp
34847     # setup
34848     (clear-stream _test-output-stream)
34849     (clear-stream $_test-output-buffered-file->buffer)
34850 $test-increment-register:initialize-type:
34851     # var type/ecx: (payload type-tree) = int
34852     68/push 0/imm32/right:null
34853     68/push 0/imm32/right:null
34854     68/push 0/imm32/left:unused
34855     68/push 1/imm32/value:int
34856     68/push 1/imm32/is-atom?:true
34857     68/push 0x11/imm32/alloc-id:fake:payload
34858     89/<- %ecx 4/r32/esp
34859 $test-increment-register:initialize-var:
34860     # var var-foo/ecx: (payload var)
34861     68/push 0/imm32/register
34862     68/push 0/imm32/register
34863     68/push 0/imm32/no-stack-offset
34864     68/push 1/imm32/block-depth
34865     51/push-ecx
34866     68/push 0x11/imm32/alloc-id:fake
34867     68/push 0/imm32/name
34868     68/push 0/imm32/name
34869     68/push 0x11/imm32/alloc-id:fake:payload
34870     89/<- %ecx 4/r32/esp
34871 $test-increment-register:initialize-var-name:
34872     # var-foo->name = "foo"
34873     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
34874     (copy-array Heap "foo" %eax)
34875 $test-increment-register:initialize-var-register:
34876     # var-foo->register = "eax"
34877     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
34878     (copy-array Heap "eax" %eax)
34879 $test-increment-register:initialize-stmt-var:
34880     # var operand/ebx: (payload stmt-var)
34881     68/push 0/imm32/is-deref:false
34882     68/push 0/imm32/next
34883     68/push 0/imm32/next
34884     51/push-ecx/var-foo
34885     68/push 0x11/imm32/alloc-id:fake
34886     68/push 0x11/imm32/alloc-id:fake:payload
34887     89/<- %ebx 4/r32/esp
34888 $test-increment-register:initialize-stmt:
34889     # var stmt/esi: (addr statement)
34890     53/push-ebx/outputs
34891     68/push 0x11/imm32/alloc-id:fake
34892     68/push 0/imm32/no-inouts
34893     68/push 0/imm32/no-inouts
34894     68/push 0/imm32/operation
34895     68/push 0/imm32/operation
34896     68/push 1/imm32
34897     89/<- %esi 4/r32/esp
34898 $test-increment-register:initialize-stmt-operation:
34899     # stmt->operation = "increment"
34900     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
34901     (copy-array Heap "increment" %eax)
34902     # convert
34903     c7 0/subop/copy *Curr-block-depth 0/imm32
34904     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
34905     (flush _test-output-buffered-file)
34906 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
34912     # check output
34913     (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-register")
34914     # . epilogue
34915     89/<- %esp 5/r32/ebp
34916     5d/pop-to-ebp
34917     c3/return
34918 
34919 test-add-reg-to-reg:
34920     #   var1/reg <- add var2/reg
34921     # =>
34922     #   01/add-to %var1 var2
34923     #
34924     # . prologue
34925     55/push-ebp
34926     89/<- %ebp 4/r32/esp
34927     # setup
34928     (clear-stream _test-output-stream)
34929     (clear-stream $_test-output-buffered-file->buffer)
34930 $test-add-reg-to-reg:initialize-type:
34931     # var type/ecx: (payload type-tree) = int
34932     68/push 0/imm32/right:null
34933     68/push 0/imm32/right:null
34934     68/push 0/imm32/left:unused
34935     68/push 1/imm32/value:int
34936     68/push 1/imm32/is-atom?:true
34937     68/push 0x11/imm32/alloc-id:fake:payload
34938     89/<- %ecx 4/r32/esp
34939 $test-add-reg-to-reg:initialize-var1:
34940     # var var1/ecx: (payload var)
34941     68/push 0/imm32/register
34942     68/push 0/imm32/register
34943     68/push 0/imm32/no-stack-offset
34944     68/push 1/imm32/block-depth
34945     51/push-ecx
34946     68/push 0x11/imm32/alloc-id:fake
34947     68/push 0/imm32/name
34948     68/push 0/imm32/name
34949     68/push 0x11/imm32/alloc-id:fake:payload
34950     89/<- %ecx 4/r32/esp
34951 $test-add-reg-to-reg:initialize-var1-name:
34952     # var1->name = "var1"
34953     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
34954     (copy-array Heap "var1" %eax)
34955 $test-add-reg-to-reg:initialize-var1-register:
34956     # var1->register = "eax"
34957     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
34958     (copy-array Heap "eax" %eax)
34959 $test-add-reg-to-reg:initialize-var2:
34960     # var var2/edx: (payload var)
34961     68/push 0/imm32/register
34962     68/push 0/imm32/register
34963     68/push 0/imm32/no-stack-offset
34964     68/push 1/imm32/block-depth
34965     ff 6/subop/push *(ecx+0x10)
34966     68/push 0x11/imm32/alloc-id:fake
34967     68/push 0/imm32/name
34968     68/push 0/imm32/name
34969     68/push 0x11/imm32/alloc-id:fake:payload
34970     89/<- %edx 4/r32/esp
34971 $test-add-reg-to-reg:initialize-var2-name:
34972     # var2->name = "var2"
34973     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
34974     (copy-array Heap "var2" %eax)
34975 $test-add-reg-to-reg:initialize-var2-register:
34976     # var2->register = "ecx"
34977     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
34978     (copy-array Heap "ecx" %eax)
34979 $test-add-reg-to-reg:initialize-inouts:
34980     # var inouts/esi: (payload stmt-var) = [var2]
34981     68/push 0/imm32/is-deref:false
34982     68/push 0/imm32/next
34983     68/push 0/imm32/next
34984     52/push-edx/var2
34985     68/push 0x11/imm32/alloc-id:fake
34986     68/push 0x11/imm32/alloc-id:fake:payload
34987     89/<- %esi 4/r32/esp
34988 $test-add-reg-to-reg:initialize-outputs:
34989     # var outputs/edi: (payload stmt-var) = [var1]
34990     68/push 0/imm32/is-deref:false
34991     68/push 0/imm32/next
34992     68/push 0/imm32/next
34993     51/push-ecx/var1
34994     68/push 0x11/imm32/alloc-id:fake
34995     68/push 0x11/imm32/alloc-id:fake:payload
34996     89/<- %edi 4/r32/esp
34997 $test-add-reg-to-reg:initialize-stmt:
34998     # var stmt/esi: (addr statement)
34999     68/push 0/imm32/next
35000     68/push 0/imm32/next
35001     57/push-edi/outputs
35002     68/push 0x11/imm32/alloc-id:fake
35003     56/push-esi/inouts
35004     68/push 0x11/imm32/alloc-id:fake
35005     68/push 0/imm32/operation
35006     68/push 0/imm32/operation
35007     68/push 1/imm32/tag:stmt1
35008     89/<- %esi 4/r32/esp
35009 $test-add-reg-to-reg:initialize-stmt-operation:
35010     # stmt->operation = "add"
35011     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
35012     (copy-array Heap "add" %eax)
35013     # convert
35014     c7 0/subop/copy *Curr-block-depth 0/imm32
35015     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
35016     (flush _test-output-buffered-file)
35017 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
35023     # check output
35024     (check-next-stream-line-equal _test-output-stream "01/add-to %eax 0x00000001/r32" "F - test-add-reg-to-reg")
35025     # . epilogue
35026     89/<- %esp 5/r32/ebp
35027     5d/pop-to-ebp
35028     c3/return
35029 
35030 test-add-reg-to-mem:
35031     #   add-to var1 var2/reg
35032     # =>
35033     #   01/add-to *(ebp+__) var2
35034     #
35035     # . prologue
35036     55/push-ebp
35037     89/<- %ebp 4/r32/esp
35038     # setup
35039     (clear-stream _test-output-stream)
35040     (clear-stream $_test-output-buffered-file->buffer)
35041 $test-add-reg-to-mem:initialize-type:
35042     # var type/ecx: (payload type-tree) = int
35043     68/push 0/imm32/right:null
35044     68/push 0/imm32/right:null
35045     68/push 0/imm32/left:unused
35046     68/push 1/imm32/value:int
35047     68/push 1/imm32/is-atom?:true
35048     68/push 0x11/imm32/alloc-id:fake:payload
35049     89/<- %ecx 4/r32/esp
35050 $test-add-reg-to-mem:initialize-var1:
35051     # var var1/ecx: (payload var)
35052     68/push 0/imm32/register
35053     68/push 0/imm32/register
35054     68/push 8/imm32/stack-offset
35055     68/push 1/imm32/block-depth
35056     51/push-ecx
35057     68/push 0x11/imm32/alloc-id:fake
35058     68/push 0/imm32/name
35059     68/push 0/imm32/name
35060     68/push 0x11/imm32/alloc-id:fake:payload
35061     89/<- %ecx 4/r32/esp
35062 $test-add-reg-to-mem:initialize-var1-name:
35063     # var1->name = "var1"
35064     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
35065     (copy-array Heap "var1" %eax)
35066 $test-add-reg-to-mem:initialize-var2:
35067     # var var2/edx: (payload var)
35068     68/push 0/imm32/register
35069     68/push 0/imm32/register
35070     68/push 0/imm32/no-stack-offset
35071     68/push 1/imm32/block-depth
35072     ff 6/subop/push *(ecx+0x10)
35073     68/push 0x11/imm32/alloc-id:fake
35074     68/push 0/imm32/name
35075     68/push 0/imm32/name
35076     68/push 0x11/imm32/alloc-id:fake:payload
35077     89/<- %edx 4/r32/esp
35078 $test-add-reg-to-mem:initialize-var2-name:
35079     # var2->name = "var2"
35080     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
35081     (copy-array Heap "var2" %eax)
35082 $test-add-reg-to-mem:initialize-var2-register:
35083     # var2->register = "ecx"
35084     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
35085     (copy-array Heap "ecx" %eax)
35086 $test-add-reg-to-mem:initialize-inouts:
35087     # var inouts/esi: (payload stmt-var) = [var2]
35088     68/push 0/imm32/is-deref:false
35089     68/push 0/imm32/next
35090     68/push 0/imm32/next
35091     52/push-edx/var2
35092     68/push 0x11/imm32/alloc-id:fake
35093     68/push 0x11/imm32/alloc-id:fake:payload
35094     89/<- %esi 4/r32/esp
35095     # inouts = [var1, var2]
35096     68/push 0/imm32/is-deref:false
35097     56/push-esi/next
35098     68/push 0x11/imm32/alloc-id:fake
35099     51/push-ecx/var1
35100     68/push 0x11/imm32/alloc-id:fake
35101     68/push 0x11/imm32/alloc-id:fake:payload
35102     89/<- %esi 4/r32/esp
35103 $test-add-reg-to-mem:initialize-stmt:
35104     # var stmt/esi: (addr statement)
35105     68/push 0/imm32/next
35106     68/push 0/imm32/next
35107     68/push 0/imm32/outputs
35108     68/push 0/imm32/outputs
35109     56/push-esi/inouts
35110     68/push 0x11/imm32/alloc-id:fake
35111     68/push 0/imm32/operation
35112     68/push 0/imm32/operation
35113     68/push 1/imm32/tag:stmt1
35114     89/<- %esi 4/r32/esp
35115 $test-add-reg-to-mem:initialize-stmt-operation:
35116     # stmt->operation = "add-to"
35117     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
35118     (copy-array Heap "add-to" %eax)
35119     # convert
35120     c7 0/subop/copy *Curr-block-depth 0/imm32
35121     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
35122     (flush _test-output-buffered-file)
35123 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
35129     # check output
35130     (check-next-stream-line-equal _test-output-stream "01/add-to *(ebp+0x00000008) 0x00000001/r32" "F - test-add-reg-to-mem")
35131     # . epilogue
35132     89/<- %esp 5/r32/ebp
35133     5d/pop-to-ebp
35134     c3/return
35135 
35136 test-add-mem-to-reg:
35137     #   var1/reg <- add var2
35138     # =>
35139     #   03/add *(ebp+__) var1
35140     #
35141     # . prologue
35142     55/push-ebp
35143     89/<- %ebp 4/r32/esp
35144     # setup
35145     (clear-stream _test-output-stream)
35146     (clear-stream $_test-output-buffered-file->buffer)
35147 $test-add-mem-to-reg:initialize-type:
35148     # var type/ecx: (payload type-tree) = int
35149     68/push 0/imm32/right:null
35150     68/push 0/imm32/right:null
35151     68/push 0/imm32/left:unused
35152     68/push 1/imm32/value:int
35153     68/push 1/imm32/is-atom?:true
35154     68/push 0x11/imm32/alloc-id:fake:payload
35155     89/<- %ecx 4/r32/esp
35156 $test-add-mem-to-reg:initialize-var:
35157     # var var1/ecx: (payload var)
35158     68/push 0/imm32/register
35159     68/push 0/imm32/register
35160     68/push 0/imm32/no-stack-offset
35161     68/push 1/imm32/block-depth
35162     51/push-ecx
35163     68/push 0x11/imm32/alloc-id:fake
35164     68/push 0/imm32/name
35165     68/push 0/imm32/name
35166     68/push 0x11/imm32/alloc-id:fake:payload
35167     89/<- %ecx 4/r32/esp
35168 $test-add-mem-to-reg:initialize-var-name:
35169     # var1->name = "foo"
35170     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
35171     (copy-array Heap "var1" %eax)
35172 $test-add-mem-to-reg:initialize-var-register:
35173     # var1->register = "eax"
35174     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
35175     (copy-array Heap "eax" %eax)
35176 $test-add-mem-to-reg:initialize-var2:
35177     # var var2/edx: (payload var)
35178     68/push 0/imm32/register
35179     68/push 0/imm32/register
35180     68/push 8/imm32/stack-offset
35181     68/push 1/imm32/block-depth
35182     ff 6/subop/push *(ecx+0x10)
35183     68/push 0x11/imm32/alloc-id:fake
35184     68/push 0/imm32/name
35185     68/push 0/imm32/name
35186     68/push 0x11/imm32/alloc-id:fake:payload
35187     89/<- %edx 4/r32/esp
35188 $test-add-mem-to-reg:initialize-var2-name:
35189     # var2->name = "var2"
35190     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
35191     (copy-array Heap "var2" %eax)
35192 $test-add-mem-to-reg:initialize-inouts:
35193     # var inouts/esi: (payload stmt-var) = [var2]
35194     68/push 0/imm32/is-deref:false
35195     68/push 0/imm32/next
35196     68/push 0/imm32/next
35197     52/push-edx/var2
35198     68/push 0x11/imm32/alloc-id:fake
35199     68/push 0x11/imm32/alloc-id:fake:payload
35200     89/<- %esi 4/r32/esp
35201 $test-add-mem-to-reg:initialize-outputs:
35202     # var outputs/edi: (payload stmt-var) = [var1]
35203     68/push 0/imm32/is-deref:false
35204     68/push 0/imm32/next
35205     68/push 0/imm32/next
35206     51/push-ecx/var1
35207     68/push 0x11/imm32/alloc-id:fake
35208     68/push 0x11/imm32/alloc-id:fake:payload
35209     89/<- %edi 4/r32/esp
35210 $test-add-mem-to-reg:initialize-stmt:
35211     # var stmt/esi: (addr statement)
35212     68/push 0/imm32/next
35213     68/push 0/imm32/next
35214     57/push-edi/outputs
35215     68/push 0x11/imm32/alloc-id:fake
35216     56/push-esi/inouts
35217     68/push 0x11/imm32/alloc-id:fake
35218     68/push 0/imm32/operation
35219     68/push 0/imm32/operation
35220     68/push 1/imm32/tag:stmt1
35221     89/<- %esi 4/r32/esp
35222 $test-add-mem-to-reg:initialize-stmt-operation:
35223     # stmt->operation = "add"
35224     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
35225     (copy-array Heap "add" %eax)
35226     # convert
35227     c7 0/subop/copy *Curr-block-depth 0/imm32
35228     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
35229     (flush _test-output-buffered-file)
35230 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
35236     # check output
35237     (check-next-stream-line-equal _test-output-stream "03/add *(ebp+0x00000008) 0x00000000/r32" "F - test-add-mem-to-reg")
35238     # . epilogue
35239     89/<- %esp 5/r32/ebp
35240     5d/pop-to-ebp
35241     c3/return
35242 
35243 test-add-literal-to-eax:
35244     #   var1/eax <- add 0x34
35245     # =>
35246     #   05/add-to-eax 0x34/imm32
35247     #
35248     # . prologue
35249     55/push-ebp
35250     89/<- %ebp 4/r32/esp
35251     # setup
35252     (clear-stream _test-output-stream)
35253     (clear-stream $_test-output-buffered-file->buffer)
35254 $test-add-literal-to-eax:initialize-var-type:
35255     # var type/ecx: (payload type-tree) = int
35256     68/push 0/imm32/right:null
35257     68/push 0/imm32/right:null
35258     68/push 0/imm32/left:unused
35259     68/push 1/imm32/value:int
35260     68/push 1/imm32/is-atom?:true
35261     68/push 0x11/imm32/alloc-id:fake:payload
35262     89/<- %ecx 4/r32/esp
35263 $test-add-literal-to-eax:initialize-var:
35264     # var v/ecx: (payload var)
35265     68/push 0/imm32/register
35266     68/push 0/imm32/register
35267     68/push 0/imm32/no-stack-offset
35268     68/push 1/imm32/block-depth
35269     51/push-ecx
35270     68/push 0x11/imm32/alloc-id:fake
35271     68/push 0/imm32/name
35272     68/push 0/imm32/name
35273     68/push 0x11/imm32/alloc-id:fake:payload
35274     89/<- %ecx 4/r32/esp
35275 $test-add-literal-to-eax:initialize-var-name:
35276     # v->name = "v"
35277     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
35278     (copy-array Heap "v" %eax)
35279 $test-add-literal-to-eax:initialize-var-register:
35280     # v->register = "eax"
35281     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
35282     (copy-array Heap "eax" %eax)
35283 $test-add-literal-to-eax:initialize-literal-type:
35284     # var type/edx: (payload type-tree) = literal
35285     68/push 0/imm32/right:null
35286     68/push 0/imm32/right:null
35287     68/push 0/imm32/left:unused
35288     68/push 0/imm32/value:literal
35289     68/push 1/imm32/is-atom?:true
35290     68/push 0x11/imm32/alloc-id:fake:payload
35291     89/<- %edx 4/r32/esp
35292 $test-add-literal-to-eax:initialize-literal:
35293     # var l/edx: (payload var)
35294     68/push 0/imm32/register
35295     68/push 0/imm32/register
35296     68/push 0/imm32/no-stack-offset
35297     68/push 1/imm32/block-depth
35298     52/push-edx
35299     68/push 0x11/imm32/alloc-id:fake
35300     68/push 0/imm32/name
35301     68/push 0/imm32/name
35302     68/push 0x11/imm32/alloc-id:fake:payload
35303     89/<- %edx 4/r32/esp
35304 $test-add-literal-to-eax:initialize-literal-value:
35305     # l->name = "0x34"
35306     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
35307     (copy-array Heap "0x34" %eax)
35308 $test-add-literal-to-eax:initialize-inouts:
35309     # var inouts/esi: (payload stmt-var) = [l]
35310     68/push 0/imm32/is-deref:false
35311     68/push 0/imm32/next
35312     68/push 0/imm32/next
35313     52/push-edx/l
35314     68/push 0x11/imm32/alloc-id:fake
35315     68/push 0x11/imm32/alloc-id:fake:payload
35316     89/<- %esi 4/r32/esp
35317 $test-add-literal-to-eax:initialize-outputs:
35318     # var outputs/edi: (payload stmt-var) = [v]
35319     68/push 0/imm32/is-deref:false
35320     68/push 0/imm32/next
35321     68/push 0/imm32/next
35322     51/push-ecx/v
35323     68/push 0x11/imm32/alloc-id:fake
35324     68/push 0x11/imm32/alloc-id:fake:payload
35325     89/<- %edi 4/r32/esp
35326 $test-add-literal-to-eax:initialize-stmt:
35327     # var stmt/esi: (addr statement)
35328     68/push 0/imm32/next
35329     68/push 0/imm32/next
35330     57/push-edi/outputs
35331     68/push 0x11/imm32/alloc-id:fake
35332     56/push-esi/inouts
35333     68/push 0x11/imm32/alloc-id:fake
35334     68/push 0/imm32/operation
35335     68/push 0/imm32/operation
35336     68/push 1/imm32/tag:stmt1
35337     89/<- %esi 4/r32/esp
35338 $test-add-literal-to-eax:initialize-stmt-operation:
35339     # stmt->operation = "add"
35340     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
35341     (copy-array Heap "add" %eax)
35342     # convert
35343     c7 0/subop/copy *Curr-block-depth 0/imm32
35344     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
35345     (flush _test-output-buffered-file)
35346 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
35352     # check output
35353     (check-next-stream-line-equal _test-output-stream "05/add-to-eax 0x34/imm32" "F - test-add-literal-to-eax")
35354     # . epilogue
35355     89/<- %esp 5/r32/ebp
35356     5d/pop-to-ebp
35357     c3/return
35358 
35359 test-add-literal-to-reg:
35360     #   var1/ecx <- add 0x34
35361     # =>
35362     #   81 0/subop/add %ecx 0x34/imm32
35363     #
35364     # . prologue
35365     55/push-ebp
35366     89/<- %ebp 4/r32/esp
35367     # setup
35368     (clear-stream _test-output-stream)
35369     (clear-stream $_test-output-buffered-file->buffer)
35370 $test-add-literal-to-reg:initialize-var-type:
35371     # var type/ecx: (payload type-tree) = int
35372     68/push 0/imm32/right:null
35373     68/push 0/imm32/right:null
35374     68/push 0/imm32/left:unused
35375     68/push 1/imm32/value:int
35376     68/push 1/imm32/is-atom?:true
35377     68/push 0x11/imm32/alloc-id:fake:payload
35378     89/<- %ecx 4/r32/esp
35379 $test-add-literal-to-reg:initialize-var:
35380     # var v/ecx: (payload var)
35381     68/push 0/imm32/register
35382     68/push 0/imm32/register
35383     68/push 0/imm32/no-stack-offset
35384     68/push 1/imm32/block-depth
35385     51/push-ecx
35386     68/push 0x11/imm32/alloc-id:fake
35387     68/push 0/imm32/name
35388     68/push 0/imm32/name
35389     68/push 0x11/imm32/alloc-id:fake:payload
35390     89/<- %ecx 4/r32/esp
35391 $test-add-literal-to-reg:initialize-var-name:
35392     # v->name = "v"
35393     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
35394     (copy-array Heap "v" %eax)
35395 $test-add-literal-to-reg:initialize-var-register:
35396     # v->register = "ecx"
35397     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
35398     (copy-array Heap "ecx" %eax)
35399 $test-add-literal-to-reg:initialize-literal-type:
35400     # var type/edx: (payload type-tree) = literal
35401     68/push 0/imm32/right:null
35402     68/push 0/imm32/right:null
35403     68/push 0/imm32/left:unused
35404     68/push 0/imm32/value:literal
35405     68/push 1/imm32/is-atom?:true
35406     68/push 0x11/imm32/alloc-id:fake:payload
35407     89/<- %edx 4/r32/esp
35408 $test-add-literal-to-reg:initialize-literal:
35409     # var l/edx: (payload var)
35410     68/push 0/imm32/register
35411     68/push 0/imm32/register
35412     68/push 0/imm32/no-stack-offset
35413     68/push 1/imm32/block-depth
35414     52/push-edx
35415     68/push 0x11/imm32/alloc-id:fake
35416     68/push 0/imm32/name
35417     68/push 0/imm32/name
35418     68/push 0x11/imm32/alloc-id:fake:payload
35419     89/<- %edx 4/r32/esp
35420 $test-add-literal-to-reg:initialize-literal-value:
35421     # l->name = "0x34"
35422     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
35423     (copy-array Heap "0x34" %eax)
35424 $test-add-literal-to-reg:initialize-inouts:
35425     # var inouts/esi: (payload stmt-var) = [l]
35426     68/push 0/imm32/is-deref:false
35427     68/push 0/imm32/next
35428     68/push 0/imm32/next
35429     52/push-edx/l
35430     68/push 0x11/imm32/alloc-id:fake
35431     68/push 0x11/imm32/alloc-id:fake:payload
35432     89/<- %esi 4/r32/esp
35433 $test-add-literal-to-reg:initialize-outputs:
35434     # var outputs/edi: (payload stmt-var) = [v]
35435     68/push 0/imm32/is-deref:false
35436     68/push 0/imm32/next
35437     68/push 0/imm32/next
35438     51/push-ecx/v
35439     68/push 0x11/imm32/alloc-id:fake
35440     68/push 0x11/imm32/alloc-id:fake:payload
35441     89/<- %edi 4/r32/esp
35442 $test-add-literal-to-reg:initialize-stmt:
35443     # var stmt/esi: (addr statement)
35444     68/push 0/imm32/next
35445     68/push 0/imm32/next
35446     57/push-edi/outputs
35447     68/push 0x11/imm32/alloc-id:fake
35448     56/push-esi/inouts
35449     68/push 0x11/imm32/alloc-id:fake
35450     68/push 0/imm32/operation
35451     68/push 0/imm32/operation
35452     68/push 1/imm32/tag:stmt1
35453     89/<- %esi 4/r32/esp
35454 $test-add-literal-to-reg:initialize-stmt-operation:
35455     # stmt->operation = "add"
35456     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
35457     (copy-array Heap "add" %eax)
35458     # convert
35459     c7 0/subop/copy *Curr-block-depth 0/imm32
35460     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
35461     (flush _test-output-buffered-file)
35462 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
35468     # check output
35469     (check-next-stream-line-equal _test-output-stream "81 0/subop/add %ecx 0x34/imm32" "F - test-add-literal-to-reg")
35470     # . epilogue
35471     89/<- %esp 5/r32/ebp
35472     5d/pop-to-ebp
35473     c3/return
35474 
35475 test-add-literal-to-mem:
35476     #   add-to var1, 0x34
35477     # =>
35478     #   81 0/subop/add %eax 0x34/imm32
35479     #
35480     # . prologue
35481     55/push-ebp
35482     89/<- %ebp 4/r32/esp
35483     # setup
35484     (clear-stream _test-output-stream)
35485     (clear-stream $_test-output-buffered-file->buffer)
35486 $test-add-literal-to-mem:initialize-type:
35487     # var type/ecx: (payload type-tree) = int
35488     68/push 0/imm32/right:null
35489     68/push 0/imm32/right:null
35490     68/push 0/imm32/left:unused
35491     68/push 1/imm32/value:int
35492     68/push 1/imm32/is-atom?:true
35493     68/push 0x11/imm32/alloc-id:fake:payload
35494     89/<- %ecx 4/r32/esp
35495 $test-add-literal-to-mem:initialize-var1:
35496     # var var1/ecx: (payload var)
35497     68/push 0/imm32/register
35498     68/push 0/imm32/register
35499     68/push 8/imm32/stack-offset
35500     68/push 1/imm32/block-depth
35501     51/push-ecx
35502     68/push 0x11/imm32/alloc-id:fake
35503     68/push 0/imm32/name
35504     68/push 0/imm32/name
35505     68/push 0x11/imm32/alloc-id:fake:payload
35506     89/<- %ecx 4/r32/esp
35507 $test-add-literal-to-mem:initialize-var1-name:
35508     # var1->name = "var1"
35509     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
35510     (copy-array Heap "var1" %eax)
35511 $test-add-literal-to-mem:initialize-literal-type:
35512     # var type/edx: (payload type-tree) = literal
35513     68/push 0/imm32/right:null
35514     68/push 0/imm32/right:null
35515     68/push 0/imm32/left:unused
35516     68/push 0/imm32/value:literal
35517     68/push 1/imm32/is-atom?:true
35518     68/push 0x11/imm32/alloc-id:fake:payload
35519     89/<- %edx 4/r32/esp
35520 $test-add-literal-to-mem:initialize-literal:
35521     # var l/edx: (payload var)
35522     68/push 0/imm32/register
35523     68/push 0/imm32/register
35524     68/push 0/imm32/no-stack-offset
35525     68/push 1/imm32/block-depth
35526     52/push-edx
35527     68/push 0x11/imm32/alloc-id:fake
35528     68/push 0/imm32/name
35529     68/push 0/imm32/name
35530     68/push 0x11/imm32/alloc-id:fake:payload
35531     89/<- %edx 4/r32/esp
35532 $test-add-literal-to-mem:initialize-literal-value:
35533     # l->name = "0x34"
35534     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
35535     (copy-array Heap "0x34" %eax)
35536 $test-add-literal-to-mem:initialize-inouts:
35537     # var inouts/esi: (payload stmt-var) = [l]
35538     68/push 0/imm32/is-deref:false
35539     68/push 0/imm32/next
35540     68/push 0/imm32/next
35541     52/push-edx/l
35542     68/push 0x11/imm32/alloc-id:fake
35543     68/push 0x11/imm32/alloc-id:fake:payload
35544     89/<- %esi 4/r32/esp
35545     # var inouts = (handle stmt-var) = [var1, var2]
35546     68/push 0/imm32/is-deref:false
35547     56/push-esi/next
35548     68/push 0x11/imm32/alloc-id:fake
35549     51/push-ecx/var1
35550     68/push 0x11/imm32/alloc-id:fake
35551     68/push 0x11/imm32/alloc-id:fake:payload
35552     89/<- %esi 4/r32/esp
35553 $test-add-literal-to-mem:initialize-stmt:
35554     # var stmt/esi: (addr statement)
35555     68/push 0/imm32/next
35556     68/push 0/imm32/next
35557     68/push 0/imm32/outputs
35558     68/push 0/imm32/outputs
35559     56/push-esi/inouts
35560     68/push 0x11/imm32/alloc-id:fake
35561     68/push 0/imm32/operation
35562     68/push 0/imm32/operation
35563     68/push 1/imm32/tag:stmt1
35564     89/<- %esi 4/r32/esp
35565 $test-add-literal-to-mem:initialize-stmt-operation:
35566     # stmt->operation = "add-to"
35567     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
35568     (copy-array Heap "add-to" %eax)
35569     # convert
35570     c7 0/subop/copy *Curr-block-depth 0/imm32
35571     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
35572     (flush _test-output-buffered-file)
35573 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
35579     # check output
35580     (check-next-stream-line-equal _test-output-stream "81 0/subop/add *(ebp+0x00000008) 0x34/imm32" "F - test-add-literal-to-mem")
35581     # . epilogue
35582     89/<- %esp 5/r32/ebp
35583     5d/pop-to-ebp
35584     c3/return
35585 
35586 test-shift-reg-by-literal:
35587     #   var1/ecx <- shift-left 2
35588     # =>
35589     #   c1/shift 4/subop/left %ecx 2/imm8
35590     #
35591     # . prologue
35592     55/push-ebp
35593     89/<- %ebp 4/r32/esp
35594     # setup
35595     (clear-stream _test-output-stream)
35596     (clear-stream $_test-output-buffered-file->buffer)
35597 $test-shift-reg-by-literal:initialize-var-type:
35598     # var type/ecx: (payload type-tree) = int
35599     68/push 0/imm32/right:null
35600     68/push 0/imm32/right:null
35601     68/push 0/imm32/left:unused
35602     68/push 1/imm32/value:int
35603     68/push 1/imm32/is-atom?:true
35604     68/push 0x11/imm32/alloc-id:fake:payload
35605     89/<- %ecx 4/r32/esp
35606 $test-shift-reg-by-literal:initialize-var:
35607     # var v/ecx: (payload var)
35608     68/push 0/imm32/register
35609     68/push 0/imm32/register
35610     68/push 0/imm32/no-stack-offset
35611     68/push 1/imm32/block-depth
35612     51/push-ecx
35613     68/push 0x11/imm32/alloc-id:fake
35614     68/push 0/imm32/name
35615     68/push 0/imm32/name
35616     68/push 0x11/imm32/alloc-id:fake:payload
35617     89/<- %ecx 4/r32/esp
35618 $test-shift-reg-by-literal:initialize-var-name:
35619     # v->name = "v"
35620     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
35621     (copy-array Heap "v" %eax)
35622 $test-shift-reg-by-literal:initialize-var-register:
35623     # v->register = "ecx"
35624     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
35625     (copy-array Heap "ecx" %eax)
35626 $test-shift-reg-by-literal:initialize-literal-type:
35627     # var type/edx: (payload type-tree) = literal
35628     68/push 0/imm32/right:null
35629     68/push 0/imm32/right:null
35630     68/push 0/imm32/left:unused
35631     68/push 0/imm32/value:literal
35632     68/push 1/imm32/is-atom?:true
35633     68/push 0x11/imm32/alloc-id:fake:payload
35634     89/<- %edx 4/r32/esp
35635 $test-shift-reg-by-literal:initialize-literal:
35636     # var l/edx: (payload var)
35637     68/push 0/imm32/register
35638     68/push 0/imm32/register
35639     68/push 0/imm32/no-stack-offset
35640     68/push 1/imm32/block-depth
35641     52/push-edx
35642     68/push 0x11/imm32/alloc-id:fake
35643     68/push 0/imm32/name
35644     68/push 0/imm32/name
35645     68/push 0x11/imm32/alloc-id:fake:payload
35646     89/<- %edx 4/r32/esp
35647 $test-shift-reg-by-literal:initialize-literal-value:
35648     # l->name = "2"
35649     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
35650     (copy-array Heap "2" %eax)
35651 $test-shift-reg-by-literal:initialize-inouts:
35652     # var inouts/esi: (payload stmt-var) = [l]
35653     68/push 0/imm32/is-deref:false
35654     68/push 0/imm32/next
35655     68/push 0/imm32/next
35656     52/push-edx/l
35657     68/push 0x11/imm32/alloc-id:fake
35658     68/push 0x11/imm32/alloc-id:fake:payload
35659     89/<- %esi 4/r32/esp
35660 $test-shift-reg-by-literal:initialize-outputs:
35661     # var outputs/edi: (payload stmt-var) = [v]
35662     68/push 0/imm32/is-deref:false
35663     68/push 0/imm32/next
35664     68/push 0/imm32/next
35665     51/push-ecx/v
35666     68/push 0x11/imm32/alloc-id:fake
35667     68/push 0x11/imm32/alloc-id:fake:payload
35668     89/<- %edi 4/r32/esp
35669 $test-shift-reg-by-literal:initialize-stmt:
35670     # var stmt/esi: (addr statement)
35671     68/push 0/imm32/next
35672     68/push 0/imm32/next
35673     57/push-edi/outputs
35674     68/push 0x11/imm32/alloc-id:fake
35675     56/push-esi/inouts
35676     68/push 0x11/imm32/alloc-id:fake
35677     68/push 0/imm32/operation
35678     68/push 0/imm32/operation
35679     68/push 1/imm32/tag:stmt1
35680     89/<- %esi 4/r32/esp
35681 $test-shift-reg-by-literal:initialize-stmt-operation:
35682     # stmt->operation = "shift-left"
35683     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
35684     (copy-array Heap "shift-left" %eax)
35685     # convert
35686     c7 0/subop/copy *Curr-block-depth 0/imm32
35687     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
35688     (flush _test-output-buffered-file)
35689 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
35695     # check output
35696     (check-next-stream-line-equal _test-output-stream "c1/shift 4/subop/left %ecx 2/imm8" "F - test-shift-reg-by-literal")
35697     # . epilogue
35698     89/<- %esp 5/r32/ebp
35699     5d/pop-to-ebp
35700     c3/return
35701 
35702 test-shift-mem-by-literal:
35703     #   shift-left var 3
35704     # =>
35705     #   c1/shift 4/subop/left *(ebp+8) 3/imm8
35706     #
35707     # . prologue
35708     55/push-ebp
35709     89/<- %ebp 4/r32/esp
35710     # setup
35711     (clear-stream _test-output-stream)
35712     (clear-stream $_test-output-buffered-file->buffer)
35713 $test-shift-mem-by-literal:initialize-type:
35714     # var type/ecx: (payload type-tree) = int
35715     68/push 0/imm32/right:null
35716     68/push 0/imm32/right:null
35717     68/push 0/imm32/left:unused
35718     68/push 1/imm32/value:int
35719     68/push 1/imm32/is-atom?:true
35720     68/push 0x11/imm32/alloc-id:fake:payload
35721     89/<- %ecx 4/r32/esp
35722 $test-shift-mem-by-literal:initialize-var1:
35723     # var var1/ecx: (payload var)
35724     68/push 0/imm32/register
35725     68/push 0/imm32/register
35726     68/push 8/imm32/stack-offset
35727     68/push 1/imm32/block-depth
35728     51/push-ecx
35729     68/push 0x11/imm32/alloc-id:fake
35730     68/push 0/imm32/name
35731     68/push 0/imm32/name
35732     68/push 0x11/imm32/alloc-id:fake:payload
35733     89/<- %ecx 4/r32/esp
35734 $test-shift-mem-by-literal:initialize-var1-name:
35735     # var1->name = "var1"
35736     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
35737     (copy-array Heap "var1" %eax)
35738 $test-shift-mem-by-literal:initialize-literal-type:
35739     # var type/edx: (payload type-tree) = literal
35740     68/push 0/imm32/right:null
35741     68/push 0/imm32/right:null
35742     68/push 0/imm32/left:unused
35743     68/push 0/imm32/value:literal
35744     68/push 1/imm32/is-atom?:true
35745     68/push 0x11/imm32/alloc-id:fake:payload
35746     89/<- %edx 4/r32/esp
35747 $test-shift-mem-by-literal:initialize-literal:
35748     # var l/edx: (payload var)
35749     68/push 0/imm32/register
35750     68/push 0/imm32/register
35751     68/push 0/imm32/no-stack-offset
35752     68/push 1/imm32/block-depth
35753     52/push-edx
35754     68/push 0x11/imm32/alloc-id:fake
35755     68/push 0/imm32/name
35756     68/push 0/imm32/name
35757     68/push 0x11/imm32/alloc-id:fake:payload
35758     89/<- %edx 4/r32/esp
35759 $test-shift-mem-by-literal:initialize-literal-value:
35760     # l->name = "3"
35761     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
35762     (copy-array Heap "3" %eax)
35763 $test-shift-mem-by-literal:initialize-inouts:
35764     # var inouts/esi: (payload stmt-var) = [l]
35765     68/push 0/imm32/is-deref:false
35766     68/push 0/imm32/next
35767     68/push 0/imm32/next
35768     52/push-edx/l
35769     68/push 0x11/imm32/alloc-id:fake
35770     68/push 0x11/imm32/alloc-id:fake:payload
35771     89/<- %esi 4/r32/esp
35772     # var inouts = (handle stmt-var) = [var1, var2]
35773     68/push 0/imm32/is-deref:false
35774     56/push-esi/next
35775     68/push 0x11/imm32/alloc-id:fake
35776     51/push-ecx/var1
35777     68/push 0x11/imm32/alloc-id:fake
35778     68/push 0x11/imm32/alloc-id:fake:payload
35779     89/<- %esi 4/r32/esp
35780 $test-shift-mem-by-literal:initialize-stmt:
35781     # var stmt/esi: (addr statement)
35782     68/push 0/imm32/next
35783     68/push 0/imm32/next
35784     68/push 0/imm32/outputs
35785     68/push 0/imm32/outputs
35786     56/push-esi/inouts
35787     68/push 0x11/imm32/alloc-id:fake
35788     68/push 0/imm32/operation
35789     68/push 0/imm32/operation
35790     68/push 1/imm32/tag:stmt1
35791     89/<- %esi 4/r32/esp
35792 $test-shift-mem-by-literal:initialize-stmt-operation:
35793     # stmt->operation = "shift-left"
35794     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
35795     (copy-array Heap "shift-left" %eax)
35796     # convert
35797     c7 0/subop/copy *Curr-block-depth 0/imm32
35798     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
35799     (flush _test-output-buffered-file)
35800 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
35806     # check output
35807     (check-next-stream-line-equal _test-output-stream "c1/shift 4/subop/left *(ebp+0x00000008) 3/imm8" "F - test-shift-mem-by-literal")
35808     # . epilogue
35809     89/<- %esp 5/r32/ebp
35810     5d/pop-to-ebp
35811     c3/return
35812 
35813 test-compare-reg-with-reg:
35814     #   compare var1/ecx, var2/eax
35815     # =>
35816     #   39/compare %ecx 0/r32/eax
35817     #
35818     # . prologue
35819     55/push-ebp
35820     89/<- %ebp 4/r32/esp
35821     # setup
35822     (clear-stream _test-output-stream)
35823     (clear-stream $_test-output-buffered-file->buffer)
35824 $test-compare-reg-with-reg:initialize-type:
35825     # var type/ecx: (payload type-tree) = int
35826     68/push 0/imm32/right:null
35827     68/push 0/imm32/right:null
35828     68/push 0/imm32/left:unused
35829     68/push 1/imm32/value:int
35830     68/push 1/imm32/is-atom?:true
35831     68/push 0x11/imm32/alloc-id:fake:payload
35832     89/<- %ecx 4/r32/esp
35833 $test-compare-reg-with-reg:initialize-var1:
35834     # var var1/ecx: (payload var)
35835     68/push 0/imm32/register
35836     68/push 0/imm32/register
35837     68/push 0/imm32/no-stack-offset
35838     68/push 1/imm32/block-depth
35839     51/push-ecx
35840     68/push 0x11/imm32/alloc-id:fake
35841     68/push 0/imm32/name
35842     68/push 0/imm32/name
35843     68/push 0x11/imm32/alloc-id:fake:payload
35844     89/<- %ecx 4/r32/esp
35845 $test-compare-reg-with-reg:initialize-var1-name:
35846     # var1->name = "var1"
35847     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
35848     (copy-array Heap "var1" %eax)
35849 $test-compare-reg-with-reg:initialize-var1-register:
35850     # var1->register = "ecx"
35851     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
35852     (copy-array Heap "ecx" %eax)
35853 $test-compare-reg-with-reg:initialize-var2:
35854     # var var2/edx: (payload var)
35855     68/push 0/imm32/register
35856     68/push 0/imm32/register
35857     68/push 0/imm32/no-stack-offset
35858     68/push 1/imm32/block-depth
35859     ff 6/subop/push *(ecx+0x10)
35860     68/push 0x11/imm32/alloc-id:fake
35861     68/push 0/imm32/name
35862     68/push 0/imm32/name
35863     68/push 0x11/imm32/alloc-id:fake:payload
35864     89/<- %edx 4/r32/esp
35865 $test-compare-reg-with-reg:initialize-var2-name:
35866     # var2->name = "var2"
35867     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
35868     (copy-array Heap "var2" %eax)
35869 $test-compare-reg-with-reg:initialize-var2-register:
35870     # var2->register = "eax"
35871     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
35872     (copy-array Heap "eax" %eax)
35873 $test-compare-reg-with-reg:initialize-inouts:
35874     # var inouts/esi: (payload stmt-var) = [var2]
35875     68/push 0/imm32/is-deref:false
35876     68/push 0/imm32/next
35877     68/push 0/imm32/next
35878     52/push-edx/var2
35879     68/push 0x11/imm32/alloc-id:fake
35880     68/push 0x11/imm32/alloc-id:fake:payload
35881     89/<- %esi 4/r32/esp
35882     # inouts = [var1, var2]
35883     68/push 0/imm32/is-deref:false
35884     56/push-esi/next
35885     68/push 0x11/imm32/alloc-id:fake
35886     51/push-ecx/var1
35887     68/push 0x11/imm32/alloc-id:fake
35888     68/push 0x11/imm32/alloc-id:fake:payload
35889     89/<- %esi 4/r32/esp
35890 $test-compare-reg-with-reg:initialize-stmt:
35891     # var stmt/esi: (addr statement)
35892     68/push 0/imm32/next
35893     68/push 0/imm32/next
35894     68/push 0/imm32/outputs
35895     68/push 0/imm32/outputs
35896     56/push-esi/inouts
35897     68/push 0x11/imm32/alloc-id:fake
35898     68/push 0/imm32/operation
35899     68/push 0/imm32/operation
35900     68/push 1/imm32/tag:stmt1
35901     89/<- %esi 4/r32/esp
35902 $test-compare-reg-with-reg:initialize-stmt-operation:
35903     # stmt->operation = "compare"
35904     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
35905     (copy-array Heap "compare" %eax)
35906     # convert
35907     c7 0/subop/copy *Curr-block-depth 0/imm32
35908     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
35909     (flush _test-output-buffered-file)
35910 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
35916     # check output
35917     (check-next-stream-line-equal _test-output-stream "39/compare-> %ecx 0x00000000/r32" "F - test-compare-reg-with-reg")
35918     # . epilogue
35919     89/<- %esp 5/r32/ebp
35920     5d/pop-to-ebp
35921     c3/return
35922 
35923 test-compare-mem-with-reg:
35924     #   compare var1, var2/eax
35925     # =>
35926     #   39/compare *(ebp+___) 0/r32/eax
35927     #
35928     # . prologue
35929     55/push-ebp
35930     89/<- %ebp 4/r32/esp
35931     # setup
35932     (clear-stream _test-output-stream)
35933     (clear-stream $_test-output-buffered-file->buffer)
35934 $test-compare-mem-with-reg:initialize-type:
35935     # var type/ecx: (payload type-tree) = int
35936     68/push 0/imm32/right:null
35937     68/push 0/imm32/right:null
35938     68/push 0/imm32/left:unused
35939     68/push 1/imm32/value:int
35940     68/push 1/imm32/is-atom?:true
35941     68/push 0x11/imm32/alloc-id:fake:payload
35942     89/<- %ecx 4/r32/esp
35943 $test-compare-mem-with-reg:initialize-var1:
35944     # var var1/ecx: (payload var)
35945     68/push 0/imm32/register
35946     68/push 0/imm32/register
35947     68/push 8/imm32/stack-offset
35948     68/push 1/imm32/block-depth
35949     51/push-ecx
35950     68/push 0x11/imm32/alloc-id:fake
35951     68/push 0/imm32/name
35952     68/push 0/imm32/name
35953     68/push 0x11/imm32/alloc-id:fake:payload
35954     89/<- %ecx 4/r32/esp
35955 $test-compare-mem-with-reg:initialize-var1-name:
35956     # var1->name = "var1"
35957     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
35958     (copy-array Heap "var1" %eax)
35959 $test-compare-mem-with-reg:initialize-var2:
35960     # var var2/edx: (payload var)
35961     68/push 0/imm32/register
35962     68/push 0/imm32/register
35963     68/push 0/imm32/no-stack-offset
35964     68/push 1/imm32/block-depth
35965     ff 6/subop/push *(ecx+0x10)
35966     68/push 0x11/imm32/alloc-id:fake
35967     68/push 0/imm32/name
35968     68/push 0/imm32/name
35969     68/push 0x11/imm32/alloc-id:fake:payload
35970     89/<- %edx 4/r32/esp
35971 $test-compare-mem-with-reg:initialize-var2-name:
35972     # var2->name = "var2"
35973     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
35974     (copy-array Heap "var2" %eax)
35975 $test-compare-mem-with-reg:initialize-var2-register:
35976     # var2->register = "eax"
35977     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
35978     (copy-array Heap "eax" %eax)
35979 $test-compare-mem-with-reg:initialize-inouts:
35980     # var inouts/esi: (payload stmt-var) = [var2]
35981     68/push 0/imm32/is-deref:false
35982     68/push 0/imm32/next
35983     68/push 0/imm32/next
35984     52/push-edx/var2
35985     68/push 0x11/imm32/alloc-id:fake
35986     68/push 0x11/imm32/alloc-id:fake:payload
35987     89/<- %esi 4/r32/esp
35988     # inouts = [var1, var2]
35989     68/push 0/imm32/is-deref:false
35990     56/push-esi/next
35991     68/push 0x11/imm32/alloc-id:fake
35992     51/push-ecx/var1
35993     68/push 0x11/imm32/alloc-id:fake
35994     68/push 0x11/imm32/alloc-id:fake:payload
35995     89/<- %esi 4/r32/esp
35996 $test-compare-mem-with-reg:initialize-stmt:
35997     # var stmt/esi: (addr statement)
35998     68/push 0/imm32/next
35999     68/push 0/imm32/next
36000     68/push 0/imm32/outputs
36001     68/push 0/imm32/outputs
36002     56/push-esi/inouts
36003     68/push 0x11/imm32/alloc-id:fake
36004     68/push 0/imm32/operation
36005     68/push 0/imm32/operation
36006     68/push 1/imm32/tag:stmt1
36007     89/<- %esi 4/r32/esp
36008 $test-compare-mem-with-reg:initialize-stmt-operation:
36009     # stmt->operation = "compare"
36010     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
36011     (copy-array Heap "compare" %eax)
36012     # convert
36013     c7 0/subop/copy *Curr-block-depth 0/imm32
36014     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
36015     (flush _test-output-buffered-file)
36016 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
36022     # check output
36023     (check-next-stream-line-equal _test-output-stream "39/compare-> *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-mem-with-reg")
36024     # . epilogue
36025     89/<- %esp 5/r32/ebp
36026     5d/pop-to-ebp
36027     c3/return
36028 
36029 test-compare-reg-with-mem:
36030     #   compare var1/eax, var2
36031     # =>
36032     #   3b/compare<- *(ebp+___) 0/r32/eax
36033     #
36034     # . prologue
36035     55/push-ebp
36036     89/<- %ebp 4/r32/esp
36037     # setup
36038     (clear-stream _test-output-stream)
36039     (clear-stream $_test-output-buffered-file->buffer)
36040 $test-compare-reg-with-mem:initialize-type:
36041     # var type/ecx: (payload type-tree) = int
36042     68/push 0/imm32/right:null
36043     68/push 0/imm32/right:null
36044     68/push 0/imm32/left:unused
36045     68/push 1/imm32/value:int
36046     68/push 1/imm32/is-atom?:true
36047     68/push 0x11/imm32/alloc-id:fake:payload
36048     89/<- %ecx 4/r32/esp
36049 $test-compare-reg-with-mem:initialize-var1:
36050     # var var1/ecx: (payload var)
36051     68/push 0/imm32/register
36052     68/push 0/imm32/register
36053     68/push 0/imm32/no-stack-offset
36054     68/push 1/imm32/block-depth
36055     51/push-ecx
36056     68/push 0x11/imm32/alloc-id:fake
36057     68/push 0/imm32/name
36058     68/push 0/imm32/name
36059     68/push 0x11/imm32/alloc-id:fake:payload
36060     89/<- %ecx 4/r32/esp
36061 $test-compare-reg-with-mem:initialize-var1-name:
36062     # var1->name = "var1"
36063     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
36064     (copy-array Heap "var1" %eax)
36065 $test-compare-reg-with-mem:initialize-var1-register:
36066     # var1->register = "eax"
36067     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
36068     (copy-array Heap "eax" %eax)
36069 $test-compare-reg-with-mem:initialize-var2:
36070     # var var2/edx: (payload var)
36071     68/push 0/imm32/register
36072     68/push 0/imm32/register
36073     68/push 8/imm32/stack-offset
36074     68/push 1/imm32/block-depth
36075     ff 6/subop/push *(ecx+0x10)
36076     68/push 0x11/imm32/alloc-id:fake
36077     68/push 0/imm32/name
36078     68/push 0/imm32/name
36079     68/push 0x11/imm32/alloc-id:fake:payload
36080     89/<- %edx 4/r32/esp
36081 $test-compare-reg-with-mem:initialize-var2-name:
36082     # var2->name = "var2"
36083     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
36084     (copy-array Heap "var2" %eax)
36085 $test-compare-reg-with-mem:initialize-inouts:
36086     # var inouts/esi: (payload stmt-var) = [var2]
36087     68/push 0/imm32/is-deref:false
36088     68/push 0/imm32/next
36089     68/push 0/imm32/next
36090     52/push-edx/var2
36091     68/push 0x11/imm32/alloc-id:fake
36092     68/push 0x11/imm32/alloc-id:fake:payload
36093     89/<- %esi 4/r32/esp
36094     # inouts = [var1, var2]
36095     68/push 0/imm32/is-deref:false
36096     56/push-esi/next
36097     68/push 0x11/imm32/alloc-id:fake
36098     51/push-ecx/var1
36099     68/push 0x11/imm32/alloc-id:fake
36100     68/push 0x11/imm32/alloc-id:fake:payload
36101     89/<- %esi 4/r32/esp
36102 $test-compare-reg-with-mem:initialize-stmt:
36103     # var stmt/esi: (addr statement)
36104     68/push 0/imm32/next
36105     68/push 0/imm32/next
36106     68/push 0/imm32/outputs
36107     68/push 0/imm32/outputs
36108     56/push-esi/inouts
36109     68/push 0x11/imm32/alloc-id:fake
36110     68/push 0/imm32/operation
36111     68/push 0/imm32/operation
36112     68/push 1/imm32/tag:stmt1
36113     89/<- %esi 4/r32/esp
36114 $test-compare-reg-with-mem:initialize-stmt-operation:
36115     # stmt->operation = "compare"
36116     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
36117     (copy-array Heap "compare" %eax)
36118     # convert
36119     c7 0/subop/copy *Curr-block-depth 0/imm32
36120     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
36121     (flush _test-output-buffered-file)
36122 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
36128     # check output
36129     (check-next-stream-line-equal _test-output-stream "3b/compare<- *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-reg-with-mem")
36130     # . epilogue
36131     89/<- %esp 5/r32/ebp
36132     5d/pop-to-ebp
36133     c3/return
36134 
36135 test-compare-mem-with-literal:
36136     #   compare var1, 0x34
36137     # =>
36138     #   81 7/subop/compare *(ebp+___) 0x34/imm32
36139     #
36140     # . prologue
36141     55/push-ebp
36142     89/<- %ebp 4/r32/esp
36143     # setup
36144     (clear-stream _test-output-stream)
36145     (clear-stream $_test-output-buffered-file->buffer)
36146 $test-compare-mem-with-literal:initialize-type:
36147     # var type/ecx: (payload type-tree) = int
36148     68/push 0/imm32/right:null
36149     68/push 0/imm32/right:null
36150     68/push 0/imm32/left:unused
36151     68/push 1/imm32/value:int
36152     68/push 1/imm32/is-atom?:true
36153     68/push 0x11/imm32/alloc-id:fake:payload
36154     89/<- %ecx 4/r32/esp
36155 $test-compare-mem-with-literal:initialize-var1:
36156     # var var1/ecx: (payload var)
36157     68/push 0/imm32/register
36158     68/push 0/imm32/register
36159     68/push 8/imm32/stack-offset
36160     68/push 1/imm32/block-depth
36161     51/push-ecx
36162     68/push 0x11/imm32/alloc-id:fake
36163     68/push 0/imm32/name
36164     68/push 0/imm32/name
36165     68/push 0x11/imm32/alloc-id:fake:payload
36166     89/<- %ecx 4/r32/esp
36167 $test-compare-mem-with-literal:initialize-var1-name:
36168     # var1->name = "var1"
36169     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
36170     (copy-array Heap "var1" %eax)
36171 $test-compare-mem-with-literal:initialize-literal-type:
36172     # var type/edx: (payload type-tree) = literal
36173     68/push 0/imm32/right:null
36174     68/push 0/imm32/right:null
36175     68/push 0/imm32/left:unused
36176     68/push 0/imm32/value:literal
36177     68/push 1/imm32/is-atom?:true
36178     68/push 0x11/imm32/alloc-id:fake:payload
36179     89/<- %edx 4/r32/esp
36180 $test-compare-mem-with-literal:initialize-literal:
36181     # var l/edx: (payload var)
36182     68/push 0/imm32/register
36183     68/push 0/imm32/register
36184     68/push 0/imm32/no-stack-offset
36185     68/push 1/imm32/block-depth
36186     52/push-edx
36187     68/push 0x11/imm32/alloc-id:fake
36188     68/push 0/imm32/name
36189     68/push 0/imm32/name
36190     68/push 0x11/imm32/alloc-id:fake:payload
36191     89/<- %edx 4/r32/esp
36192 $test-compare-mem-with-literal:initialize-literal-value:
36193     # l->name = "0x34"
36194     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
36195     (copy-array Heap "0x34" %eax)
36196 $test-compare-mem-with-literal:initialize-inouts:
36197     # var inouts/esi: (payload stmt-var) = [l]
36198     68/push 0/imm32/is-deref:false
36199     68/push 0/imm32/next
36200     68/push 0/imm32/next
36201     52/push-edx/l
36202     68/push 0x11/imm32/alloc-id:fake
36203     68/push 0x11/imm32/alloc-id:fake:payload
36204     89/<- %esi 4/r32/esp
36205     # var inouts = (handle stmt-var) = [var1, var2]
36206     68/push 0/imm32/is-deref:false
36207     56/push-esi/next
36208     68/push 0x11/imm32/alloc-id:fake
36209     51/push-ecx/var1
36210     68/push 0x11/imm32/alloc-id:fake
36211     68/push 0x11/imm32/alloc-id:fake:payload
36212     89/<- %esi 4/r32/esp
36213 $test-compare-mem-with-literal:initialize-stmt:
36214     # var stmt/esi: (addr statement)
36215     68/push 0/imm32/next
36216     68/push 0/imm32/next
36217     68/push 0/imm32/outputs
36218     68/push 0/imm32/outputs
36219     56/push-esi/inouts
36220     68/push 0x11/imm32/alloc-id:fake
36221     68/push 0/imm32/operation
36222     68/push 0/imm32/operation
36223     68/push 1/imm32/tag:stmt1
36224     89/<- %esi 4/r32/esp
36225 $test-compare-mem-with-literal:initialize-stmt-operation:
36226     # stmt->operation = "compare"
36227     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
36228     (copy-array Heap "compare" %eax)
36229     # convert
36230     c7 0/subop/copy *Curr-block-depth 0/imm32
36231     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
36232     (flush _test-output-buffered-file)
36233 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
36239     # check output
36240     (check-next-stream-line-equal _test-output-stream "81 7/subop/compare *(ebp+0x00000008) 0x34/imm32" "F - test-compare-mem-with-literal")
36241     # . epilogue
36242     89/<- %esp 5/r32/ebp
36243     5d/pop-to-ebp
36244     c3/return
36245 
36246 test-compare-eax-with-literal:
36247     #   compare var1/eax 0x34
36248     # =>
36249     #   3d/compare-eax-with 0x34/imm32
36250     #
36251     # . prologue
36252     55/push-ebp
36253     89/<- %ebp 4/r32/esp
36254     # setup
36255     (clear-stream _test-output-stream)
36256     (clear-stream $_test-output-buffered-file->buffer)
36257 $test-compare-eax-with-literal:initialize-type:
36258     # var type/ecx: (payload type-tree) = int
36259     68/push 0/imm32/right:null
36260     68/push 0/imm32/right:null
36261     68/push 0/imm32/left:unused
36262     68/push 1/imm32/value:int
36263     68/push 1/imm32/is-atom?:true
36264     68/push 0x11/imm32/alloc-id:fake:payload
36265     89/<- %ecx 4/r32/esp
36266 $test-compare-eax-with-literal:initialize-var1:
36267     # var var1/ecx: (payload var)
36268     68/push 0/imm32/register
36269     68/push 0/imm32/register
36270     68/push 0/imm32/no-stack-offset
36271     68/push 1/imm32/block-depth
36272     51/push-ecx
36273     68/push 0x11/imm32/alloc-id:fake
36274     68/push 0/imm32/name
36275     68/push 0/imm32/name
36276     68/push 0x11/imm32/alloc-id:fake:payload
36277     89/<- %ecx 4/r32/esp
36278 $test-compare-eax-with-literal:initialize-var1-name:
36279     # var1->name = "var1"
36280     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
36281     (copy-array Heap "var1" %eax)
36282 $test-compare-eax-with-literal:initialize-var1-register:
36283     # v->register = "eax"
36284     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
36285     (copy-array Heap "eax" %eax)
36286 $test-compare-eax-with-literal:initialize-literal-type:
36287     # var type/edx: (payload type-tree) = literal
36288     68/push 0/imm32/right:null
36289     68/push 0/imm32/right:null
36290     68/push 0/imm32/left:unused
36291     68/push 0/imm32/value:literal
36292     68/push 1/imm32/is-atom?:true
36293     68/push 0x11/imm32/alloc-id:fake:payload
36294     89/<- %edx 4/r32/esp
36295 $test-compare-eax-with-literal:initialize-literal:
36296     # var l/edx: (payload var)
36297     68/push 0/imm32/register
36298     68/push 0/imm32/register
36299     68/push 0/imm32/no-stack-offset
36300     68/push 1/imm32/block-depth
36301     52/push-edx
36302     68/push 0x11/imm32/alloc-id:fake
36303     68/push 0/imm32/name
36304     68/push 0/imm32/name
36305     68/push 0x11/imm32/alloc-id:fake:payload
36306     89/<- %edx 4/r32/esp
36307 $test-compare-eax-with-literal:initialize-literal-value:
36308     # l->name = "0x34"
36309     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
36310     (copy-array Heap "0x34" %eax)
36311 $test-compare-eax-with-literal:initialize-inouts:
36312     # var inouts/esi: (payload stmt-var) = [l]
36313     68/push 0/imm32/is-deref:false
36314     68/push 0/imm32/next
36315     68/push 0/imm32/next
36316     52/push-edx/l
36317     68/push 0x11/imm32/alloc-id:fake
36318     68/push 0x11/imm32/alloc-id:fake:payload
36319     89/<- %esi 4/r32/esp
36320     # var inouts = (handle stmt-var) = [var1, var2]
36321     68/push 0/imm32/is-deref:false
36322     56/push-esi/next
36323     68/push 0x11/imm32/alloc-id:fake
36324     51/push-ecx/var1
36325     68/push 0x11/imm32/alloc-id:fake
36326     68/push 0x11/imm32/alloc-id:fake:payload
36327     89/<- %esi 4/r32/esp
36328 $test-compare-eax-with-literal:initialize-stmt:
36329     # var stmt/esi: (addr statement)
36330     68/push 0/imm32/next
36331     68/push 0/imm32/next
36332     68/push 0/imm32/outputs
36333     68/push 0/imm32/outputs
36334     56/push-esi/inouts
36335     68/push 0x11/imm32/alloc-id:fake
36336     68/push 0/imm32/operation
36337     68/push 0/imm32/operation
36338     68/push 1/imm32/tag:stmt1
36339     89/<- %esi 4/r32/esp
36340 $test-compare-eax-with-literal:initialize-stmt-operation:
36341     # stmt->operation = "compare"
36342     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
36343     (copy-array Heap "compare" %eax)
36344     # convert
36345     c7 0/subop/copy *Curr-block-depth 0/imm32
36346     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
36347     (flush _test-output-buffered-file)
36348 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
36354     # check output
36355     (check-next-stream-line-equal _test-output-stream "3d/compare-eax-with 0x34/imm32" "F - test-compare-eax-with-literal")
36356     # . epilogue
36357     89/<- %esp 5/r32/ebp
36358     5d/pop-to-ebp
36359     c3/return
36360 
36361 test-compare-reg-with-literal:
36362     #   compare var1/ecx 0x34
36363     # =>
36364     #   81 7/subop/compare %ecx 0x34/imm32
36365     #
36366     # . prologue
36367     55/push-ebp
36368     89/<- %ebp 4/r32/esp
36369     # setup
36370     (clear-stream _test-output-stream)
36371     (clear-stream $_test-output-buffered-file->buffer)
36372 $test-compare-reg-with-literal:initialize-type:
36373     # var type/ecx: (payload type-tree) = int
36374     68/push 0/imm32/right:null
36375     68/push 0/imm32/right:null
36376     68/push 0/imm32/left:unused
36377     68/push 1/imm32/value:int
36378     68/push 1/imm32/is-atom?:true
36379     68/push 0x11/imm32/alloc-id:fake:payload
36380     89/<- %ecx 4/r32/esp
36381 $test-compare-reg-with-literal:initialize-var1:
36382     # var var1/ecx: (payload var)
36383     68/push 0/imm32/register
36384     68/push 0/imm32/register
36385     68/push 0/imm32/no-stack-offset
36386     68/push 1/imm32/block-depth
36387     51/push-ecx
36388     68/push 0x11/imm32/alloc-id:fake
36389     68/push 0/imm32/name
36390     68/push 0/imm32/name
36391     68/push 0x11/imm32/alloc-id:fake:payload
36392     89/<- %ecx 4/r32/esp
36393 $test-compare-reg-with-literal:initialize-var1-name:
36394     # var1->name = "var1"
36395     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
36396     (copy-array Heap "var1" %eax)
36397 $test-compare-reg-with-literal:initialize-var1-register:
36398     # v->register = "ecx"
36399     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
36400     (copy-array Heap "ecx" %eax)
36401 $test-compare-reg-with-literal:initialize-literal-type:
36402     # var type/edx: (payload type-tree) = literal
36403     68/push 0/imm32/right:null
36404     68/push 0/imm32/right:null
36405     68/push 0/imm32/left:unused
36406     68/push 0/imm32/value:literal
36407     68/push 1/imm32/is-atom?:true
36408     68/push 0x11/imm32/alloc-id:fake:payload
36409     89/<- %edx 4/r32/esp
36410 $test-compare-reg-with-literal:initialize-literal:
36411     # var l/edx: (payload var)
36412     68/push 0/imm32/register
36413     68/push 0/imm32/register
36414     68/push 0/imm32/no-stack-offset
36415     68/push 1/imm32/block-depth
36416     52/push-edx
36417     68/push 0x11/imm32/alloc-id:fake
36418     68/push 0/imm32/name
36419     68/push 0/imm32/name
36420     68/push 0x11/imm32/alloc-id:fake:payload
36421     89/<- %edx 4/r32/esp
36422 $test-compare-reg-with-literal:initialize-literal-value:
36423     # l->name = "0x34"
36424     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
36425     (copy-array Heap "0x34" %eax)
36426 $test-compare-reg-with-literal:initialize-inouts:
36427     # var inouts/esi: (payload stmt-var) = [l]
36428     68/push 0/imm32/is-deref:false
36429     68/push 0/imm32/next
36430     68/push 0/imm32/next
36431     52/push-edx/l
36432     68/push 0x11/imm32/alloc-id:fake
36433     68/push 0x11/imm32/alloc-id:fake:payload
36434     89/<- %esi 4/r32/esp
36435     # var inouts = (handle stmt-var) = [var1, var2]
36436     68/push 0/imm32/is-deref:false
36437     56/push-esi/next
36438     68/push 0x11/imm32/alloc-id:fake
36439     51/push-ecx/var1
36440     68/push 0x11/imm32/alloc-id:fake
36441     68/push 0x11/imm32/alloc-id:fake:payload
36442     89/<- %esi 4/r32/esp
36443 $test-compare-reg-with-literal:initialize-stmt:
36444     # var stmt/esi: (addr statement)
36445     68/push 0/imm32/next
36446     68/push 0/imm32/next
36447     68/push 0/imm32/outputs
36448     68/push 0/imm32/outputs
36449     56/push-esi/inouts
36450     68/push 0x11/imm32/alloc-id:fake
36451     68/push 0/imm32/operation
36452     68/push 0/imm32/operation
36453     68/push 1/imm32/tag:stmt1
36454     89/<- %esi 4/r32/esp
36455 $test-compare-reg-with-literal:initialize-stmt-operation:
36456     # stmt->operation = "compare"
36457     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
36458     (copy-array Heap "compare" %eax)
36459     # convert
36460     c7 0/subop/copy *Curr-block-depth 0/imm32
36461     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
36462     (flush _test-output-buffered-file)
36463 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
36469     # check output
36470     (check-next-stream-line-equal _test-output-stream "81 7/subop/compare %ecx 0x34/imm32" "F - test-compare-reg-with-literal")
36471     # . epilogue
36472     89/<- %esp 5/r32/ebp
36473     5d/pop-to-ebp
36474     c3/return
36475 
36476 test-emit-subx-stmt-function-call:
36477     # Call a function on a variable on the stack.
36478     #   f foo
36479     # =>
36480     #   (f *(ebp-8))
36481     # (Changing the function name supports overloading in general, but here it
36482     # just serves to help disambiguate things.)
36483     #
36484     # There's a variable on the var stack as follows:
36485     #   name: 'foo'
36486     #   type: int
36487     #   stack-offset: -8
36488     #
36489     # There's nothing in primitives.
36490     #
36491     # We don't perform any checking here on the type of 'f'.
36492     #
36493     # . prologue
36494     55/push-ebp
36495     89/<- %ebp 4/r32/esp
36496     # setup
36497     (clear-stream _test-output-stream)
36498     (clear-stream $_test-output-buffered-file->buffer)
36499 $test-emit-subx-function-call:initialize-type:
36500     # var type/ecx: (payload type-tree) = int
36501     68/push 0/imm32/right:null
36502     68/push 0/imm32/right:null
36503     68/push 0/imm32/left:unused
36504     68/push 1/imm32/value:int
36505     68/push 1/imm32/is-atom?:true
36506     68/push 0x11/imm32/alloc-id:fake:payload
36507     89/<- %ecx 4/r32/esp
36508 $test-emit-subx-function-call:initialize-var:
36509     # var var-foo/ecx: (payload var) = var(type)
36510     68/push 0/imm32/no-register
36511     68/push 0/imm32/no-register
36512     68/push -8/imm32/stack-offset
36513     68/push 1/imm32/block-depth
36514     51/push-ecx/type
36515     68/push 0x11/imm32/alloc-id:fake
36516     68/push 0/imm32/name
36517     68/push 0/imm32/name
36518     68/push 0x11/imm32/alloc-id:fake:payload
36519     89/<- %ecx 4/r32/esp
36520 $test-emit-subx-function-call:initialize-var-name:
36521     # var-foo->name = "foo"
36522     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
36523     (copy-array Heap "foo" %eax)
36524 $test-emit-subx-function-call:initialize-stmt-var:
36525     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
36526     68/push 0/imm32/is-deref:false
36527     68/push 0/imm32/next
36528     68/push 0/imm32/next
36529     51/push-ecx/var-foo
36530     68/push 0x11/imm32/alloc-id:fake
36531     68/push 0x11/imm32/alloc-id:fake:payload
36532     89/<- %ebx 4/r32/esp
36533 $test-emit-subx-function-call:initialize-stmt:
36534     # var stmt/esi: (addr statement)
36535     68/push 0/imm32/no-outputs
36536     68/push 0/imm32/no-outputs
36537     53/push-ebx/inouts
36538     68/push 0x11/imm32/alloc-id:fake
36539     68/push 0/imm32/operation
36540     68/push 0/imm32/operation
36541     68/push 1/imm32/tag
36542     89/<- %esi 4/r32/esp
36543 $test-emit-subx-function-call:initialize-stmt-operation:
36544     # stmt->operation = "f"
36545     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
36546     (copy-array Heap "f" %eax)
36547     # convert
36548     c7 0/subop/copy *Curr-block-depth 0/imm32
36549     (emit-subx-stmt _test-output-buffered-file %esi 0 0 Stderr 0)
36550     (flush _test-output-buffered-file)
36551 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
36557     # check output
36558     (check-next-stream-line-equal _test-output-stream "(f *(ebp+0xfffffff8))" "F - test-emit-subx-stmt-function-call")
36559     # . epilogue
36560     89/<- %esp 5/r32/ebp
36561     5d/pop-to-ebp
36562     c3/return
36563 
36564 test-emit-subx-stmt-function-call-with-literal-arg:
36565     # Call a function on a literal.
36566     #   f 0x34
36567     # =>
36568     #   (f2 0x34)
36569     #
36570     # . prologue
36571     55/push-ebp
36572     89/<- %ebp 4/r32/esp
36573     # setup
36574     (clear-stream _test-output-stream)
36575     (clear-stream $_test-output-buffered-file->buffer)
36576 $test-emit-subx-function-call-with-literal-arg:initialize-type:
36577     # var type/ecx: (payload type-tree) = int
36578     68/push 0/imm32/right:null
36579     68/push 0/imm32/right:null
36580     68/push 0/imm32/left:unused
36581     68/push 0/imm32/value:literal
36582     68/push 1/imm32/is-atom?:true
36583     68/push 0x11/imm32/alloc-id:fake:payload
36584     89/<- %ecx 4/r32/esp
36585 $test-emit-subx-function-call-with-literal-arg:initialize-var:
36586     # var var-foo/ecx: (payload var) = var(lit)
36587     68/push 0/imm32/no-register
36588     68/push 0/imm32/no-register
36589     68/push 0/imm32/no-stack-offset
36590     68/push 1/imm32/block-depth
36591     51/push-ecx/type
36592     68/push 0x11/imm32/alloc-id:fake
36593     68/push 0/imm32/name
36594     68/push 0/imm32/name
36595     68/push 0x11/imm32/alloc-id:fake:payload
36596     89/<- %ecx 4/r32/esp
36597 $test-emit-subx-function-call-with-literal-arg:initialize-var-name:
36598     # var-foo->name = "0x34"
36599     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
36600     (copy-array Heap "0x34" %eax)
36601 $test-emit-subx-function-call-with-literal-arg:initialize-stmt-var:
36602     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
36603     68/push 0/imm32/is-deref:false
36604     68/push 0/imm32/next
36605     68/push 0/imm32/next
36606     51/push-ecx/var-foo
36607     68/push 0x11/imm32/alloc-id:fake
36608     68/push 0x11/imm32/alloc-id:fake:payload
36609     89/<- %ebx 4/r32/esp
36610 $test-emit-subx-function-call-with-literal-arg:initialize-stmt:
36611     # var stmt/esi: (addr statement)
36612     68/push 0/imm32/no-outputs
36613     68/push 0/imm32/no-outputs
36614     53/push-ebx/inouts
36615     68/push 0x11/imm32/alloc-id:fake
36616     68/push 0/imm32/operation
36617     68/push 0/imm32/operation
36618     68/push 1/imm32/tag
36619     89/<- %esi 4/r32/esp
36620 $test-emit-subx-function-call-with-literal-arg:initialize-stmt-operation:
36621     # stmt->operation = "f"
36622     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
36623     (copy-array Heap "f" %eax)
36624     # convert
36625     c7 0/subop/copy *Curr-block-depth 0/imm32
36626     (emit-subx-stmt _test-output-buffered-file %esi 0 %ebx 0 Stderr 0)
36627     (flush _test-output-buffered-file)
36628 +--  6 lines: #?     # dump _test-output-stream ---------------------------------------------------------------------------------------------------------------------------------------
36634     # check output
36635     (check-next-stream-line-equal _test-output-stream "(f 0x34)" "F - test-emit-subx-stmt-function-call-with-literal-arg")
36636     # . epilogue
36637     89/<- %esp 5/r32/ebp
36638     5d/pop-to-ebp
36639     c3/return
36640 
36641 emit-indent:  # out: (addr buffered-file), n: int
36642     # . prologue
36643     55/push-ebp
36644     89/<- %ebp 4/r32/esp
36645     # . save registers
36646     50/push-eax
36647     # var i/eax: int = n
36648     8b/-> *(ebp+0xc) 0/r32/eax
36649     {
36650       # if (i <= 0) break
36651       3d/compare-eax-with 0/imm32
36652       7e/jump-if-<= break/disp8
36653       (write-buffered *(ebp+8) "  ")
36654       48/decrement-eax
36655       eb/jump loop/disp8
36656     }
36657 $emit-indent:end:
36658     # . restore registers
36659     58/pop-to-eax
36660     # . epilogue
36661     89/<- %esp 5/r32/ebp
36662     5d/pop-to-ebp
36663     c3/return
36664 
36665 emit-subx-prologue:  # out: (addr buffered-file)
36666     # . prologue
36667     55/push-ebp
36668     89/<- %ebp 4/r32/esp
36669     #
36670     (write-buffered *(ebp+8) "  # . prologue\n")
36671     (write-buffered *(ebp+8) "  55/push-ebp\n")
36672     (write-buffered *(ebp+8) "  89/<- %ebp 4/r32/esp\n")
36673 $emit-subx-prologue:end:
36674     # . epilogue
36675     89/<- %esp 5/r32/ebp
36676     5d/pop-to-ebp
36677     c3/return
36678 
36679 emit-subx-epilogue:  # out: (addr buffered-file)
36680     # . prologue
36681     55/push-ebp
36682     89/<- %ebp 4/r32/esp
36683     #
36684     (write-buffered *(ebp+8) "  # . epilogue\n")
36685     (write-buffered *(ebp+8) "  89/<- %esp 5/r32/ebp\n")
36686     (write-buffered *(ebp+8) "  5d/pop-to-ebp\n")
36687     (write-buffered *(ebp+8) "  c3/return\n")
36688 $emit-subx-epilogue:end:
36689     # . epilogue
36690     89/<- %esp 5/r32/ebp
36691     5d/pop-to-ebp
36692     c3/return