https://github.com/akkartik/mu/blob/main/linux/mu.subx
    1 # The Mu computer's level-2 language, also called Mu.
    2 # http://akkartik.name/post/mu-2019-2
    3 #
    4 # To run:
    5 #   $ ./translate_subx init.linux [0-9]*.subx mu.subx
    6 #   $ ./a.elf < prog.mu > prog.elf
    7 
    8 # == Goals
    9 # 1. Be memory safe. It should be impossible to corrupt the heap, or to create
   10 # a bad pointer. (Requires strong type safety.)
   11 # 2. Do as little as possible to achieve goal 1. The translator should be
   12 # implementable in machine code.
   13 #   - minimize impedance mismatch between source language and SubX target
   14 #     (e.g. programmer manages registers manually)
   15 #   - checks over syntax
   16 #     (e.g. programmer's register allocation is checked)
   17 #   - runtime checks to avoid complex static analysis
   18 #     (e.g. array indexing always checks bounds)
   19 
   20 # == Language description
   21 # A program is a sequence of function and type definitions.
   22 #
   23 # Function example:
   24 #   fn foo n: int -> _/eax: int {
   25 #     ...
   26 #   }
   27 #
   28 # Functions consist of a name, optional inputs, optional outputs and a block.
   29 #
   30 # Function inputs and outputs are variables. All variables have a type and
   31 # storage specifier. They can be placed either in memory (on the stack) or in
   32 # one of 6 named registers.
   33 #   eax ecx edx ebx esi edi
   34 # Variables in registers must be primitive 32-bit types.
   35 # Variables not explicitly placed in a register are on the stack.
   36 #
   37 # Function inputs are always passed in memory (on the stack), while outputs
   38 # are always returned in registers. Outputs can't be named; they use the
   39 # dummy value '_'.
   40 #
   41 # Blocks mostly consist of statements.
   42 #
   43 # Statements mostly consist of a name, optional inputs and optional outputs.
   44 #
   45 # Statement inputs are variables or literals. Variables need to specify type
   46 # (and storage) the first time they're mentioned but not later.
   47 #
   48 # Statement outputs, like function outputs, must be variables in registers.
   49 #
   50 # Statement names must be either primitives or user-defined functions.
   51 #
   52 # Primitives can write to any register.
   53 # User-defined functions only write to hard-coded registers. Outputs of each
   54 # call must have the same registers as in the function definition.
   55 #
   56 # There are some other statement types:
   57 #   - blocks. Multiple statements surrounded by '{...}' and optionally
   58 #     prefixed with a label name and ':'
   59 #       - {
   60 #           ...
   61 #         }
   62 #       - foo: {
   63 #           ...
   64 #         }
   65 #
   66 #   - variable definitions on the stack. E.g.:
   67 #       - var foo: int
   68 #       - var bar: (array int 3)
   69 #     There's no initializer; variables are automatically initialized.
   70 #     The type of a local variable is either word-length (4 bytes) or starts with 'ref'.
   71 #
   72 #   - variables definitions in a register. E.g.:
   73 #       - var foo/eax: int <- add bar 1
   74 #     The initializer is mandatory and must be a valid instruction that writes
   75 #     a single output to the right register. In practice registers will
   76 #     usually be either initialized by primitives or copied from eax.
   77 #       - var eax: int <- foo bar quux
   78 #         var floo/ecx: int <- copy eax
   79 #
   80 # Still todo:
   81 #   global variables
   82 #   union types
   83 #
   84 # Formal types:
   85 #   A program is a linked list of functions
   86 #   A function contains:
   87 #     name: (handle array byte)
   88 #     inouts: linked list of vars  <-- 'inouts' is more precise than 'inputs'
   89 #       data: (handle var)
   90 #       next: (handle list)
   91 #     outputs: linked list of vars
   92 #       data: (handle var)
   93 #       next: (handle list)
   94 #     body: (handle block)
   95 #   A var-type contains:
   96 #     name: (handle array byte)
   97 #     type: (handle type-tree)
   98 #
   99 #   A statement can be:
  100 #     tag 0: a block
  101 #     tag 1: a simple statement (stmt1)
  102 #     tag 2: a variable defined on the stack
  103 #     tag 3: a variable defined in a register
  104 #
  105 #   A block contains:
  106 #     tag: 0
  107 #     statements: (handle list stmt)
  108 #     name: (handle array byte) -- starting with '$'
  109 #
  110 #   A regular statement contains:
  111 #     tag: 1
  112 #     operation: (handle array byte)
  113 #     inouts: (handle list operand)
  114 #     outputs: (handle list var)
  115 #
  116 #   A variable defined on the stack contains:
  117 #     tag: 2
  118 #     name: (handle array byte)
  119 #     type: (handle type-tree)
  120 #
  121 #   A variable defined in a register contains:
  122 #     tag: 3
  123 #     name: (handle array byte)
  124 #     type: (handle type-tree)
  125 #     reg: (handle array byte)
  126 
  127 # == Translation: managing the stack
  128 # Now that we know what the language looks like in the large, let's think
  129 # about how translation happens from the bottom up. One crucial piece of the
  130 # puzzle is how Mu will clean up variables defined on the stack for you.
  131 #
  132 # Assume that we maintain a 'functions' list while parsing source code. And a
  133 # 'primitives' list is a global constant. Both these contain enough information
  134 # to perform type-checking on function calls or primitive statements, respectively.
  135 #
  136 # Defining variables pushes them on a stack with the current block depth and
  137 # enough information about their location (stack offset or register).
  138 # Starting a block increments the current block id.
  139 # Each statement now has enough information to emit code for it.
  140 # Ending a block is where the magic happens:
  141 #   pop all variables at the current block depth
  142 #   emit code to restore all register variables introduced at the current depth
  143 #   emit code to clean up all stack variables at the current depth (just increment esp)
  144 #   decrement the current block depth
  145 #
  146 # Formal types:
  147 #   live-vars: stack of vars
  148 #   var:
  149 #     name: (handle array byte)
  150 #     type: (handle type-tree)
  151 #     block: int
  152 #     stack-offset: int  (added to ebp)
  153 #     register: (handle array byte)
  154 #       either usual register names
  155 #       or '*' to indicate any register
  156 #   At most one of stack-offset or register-index must be non-zero.
  157 #   A register of '*' designates a variable _template_. Only legal in formal
  158 #   parameters for primitives.
  159 
  160 # == Translating a single function call
  161 # This one's easy. Assuming we've already checked things, we just drop the
  162 # outputs (which use hard-coded registers) and emit inputs in a standard format.
  163 #
  164 # out1, out2, out3, ... <- name inout1, inout2, inout3, ...
  165 # =>
  166 # (name inout1 inout2 inout3)
  167 #
  168 # Formal types:
  169 #   functions: linked list of info
  170 #     name: (handle array byte)
  171 #     inouts: linked list of vars
  172 #     outputs: linked list of vars
  173 #     body: block (linked list of statements)
  174 
  175 # == Translating a single primitive instruction
  176 # A second crucial piece of the puzzle is how Mu converts fairly regular
  177 # primitives with their uniform syntax to SubX instructions with their gnarly
  178 # x86 details.
  179 #
  180 # Mu instructions have inputs and outputs. Primitives can have up to 2 of
  181 # them.
  182 # SubX instructions have rm32 and r32 operands.
  183 # The translation between them covers almost all the possibilities.
  184 #   Instructions with 1 inout may turn into ones with 1 rm32
  185 #     (e.g. incrementing a var on the stack)
  186 #   Instructions with 1 output may turn into ones with 1 rm32
  187 #     (e.g. incrementing a var in a register)
  188 #   1 inout and 1 output may turn into 1 rm32 and 1 r32
  189 #     (e.g. adding a var to a reg)
  190 #   2 inouts may turn into 1 rm32 and 1 r32
  191 #     (e.g. adding a reg to a var)
  192 #   1 inout and 1 literal may turn into 1 rm32 and 1 imm32
  193 #     (e.g. adding a constant to a var)
  194 #   1 output and 1 literal may turn into 1 rm32 and 1 imm32
  195 #     (e.g. adding a constant to a reg)
  196 #   2 outputs to hardcoded registers and 1 inout may turn into 1 rm32
  197 #     (special-case: divide edx:eax by a var or reg)
  198 # Observations:
  199 #   We always emit rm32. It may be the first inout or the first output.
  200 #   We may emit r32 or imm32 or neither.
  201 #   When we emit r32 it may come from first inout or second inout or first output.
  202 #
  203 # Accordingly, the formal data structure for a primitive looks like this:
  204 #   primitives: linked list of info
  205 #     name: (handle array byte)
  206 #     mu-inouts: linked list of vars to check
  207 #     mu-outputs: linked list of vars to check; at most a singleton
  208 #     subx-name: (handle array byte)
  209 #     subx-rm32: enum arg-location
  210 #     subx-r32: enum arg-location
  211 #     subx-imm32: enum arg-location
  212 #     subx-imm8: enum arg-location
  213 #     subx-disp32: enum arg-location
  214 #     subx-xm32: enum arg-location
  215 #     subx-x32: enum arg-location
  216 #   arg-location: enum
  217 #     0 means none
  218 #     1 means first inout
  219 #     2 means second inout
  220 #     3 means first output
  221 
  222 # == Translating a block
  223 # Emit block name if necessary
  224 # Emit '{'
  225 # When you encounter a statement, emit it as above
  226 # When you encounter a variable declaration
  227 #   emit any code needed for it (bzeros)
  228 #   push it on the var stack
  229 #   update register dict if necessary
  230 # When you encounter '}'
  231 #   While popping variables off the var stack until block id changes
  232 #     Emit code needed to clean up the stack
  233 #       either increment esp
  234 #       or pop into appropriate register
  235 
  236 # The rest is straightforward.
  237 
  238 == data
  239 
  240 Program:
  241 _Program-functions:  # (handle function)
  242   0/imm32
  243 _Program-functions->payload:
  244   0/imm32
  245 _Program-types:  # (handle typeinfo)
  246   0/imm32
  247 _Program-types->payload:
  248   0/imm32
  249 _Program-signatures:  # (handle function)
  250   0/imm32
  251 _Program-signatures->payload:
  252   0/imm32
  253 
  254 # Some constants for simulating the data structures described above.
  255 # Many constants here come with a type in a comment.
  256 #
  257 # Sometimes the type is of the value at that offset for the given type. For
  258 # example, if you start at a function record and move forward Function-inouts
  259 # bytes, you'll find a (handle list var).
  260 #
  261 # At other times, the type is of the constant itself. For example, the type of
  262 # the constant Function-size is (addr int). To get the size of a function,
  263 # look in *Function-size.
  264 
  265 Function-name:  # (handle array byte)
  266   0/imm32
  267 Function-inouts:  # (handle list var)
  268   8/imm32
  269 Function-outputs:  # (handle list var)
  270   0x10/imm32
  271 Function-body:  # (handle block)
  272   0x18/imm32
  273 Function-next:  # (handle function)
  274   0x20/imm32
  275 Function-size:  # (addr int)
  276   0x28/imm32/40
  277 
  278 Primitive-name:  # (handle array byte)
  279   0/imm32
  280 Primitive-inouts:  # (handle list var)
  281   8/imm32
  282 Primitive-outputs:  # (handle list var)
  283   0x10/imm32
  284 Primitive-subx-name:  # (handle array byte)
  285   0x18/imm32
  286 Primitive-subx-rm32:  # enum arg-location
  287   0x20/imm32
  288 Primitive-subx-r32:  # enum arg-location
  289   0x24/imm32
  290 Primitive-subx-imm32:  # enum arg-location
  291   0x28/imm32
  292 Primitive-subx-imm8:  # enum arg-location  -- only for bit shifts
  293   0x2c/imm32
  294 Primitive-subx-disp32:  # enum arg-location  -- only for branches
  295   0x30/imm32
  296 Primitive-subx-xm32:  # enum arg-location
  297   0x34/imm32
  298 Primitive-subx-x32:  # enum arg-location
  299   0x38/imm32
  300 Primitive-next:  # (handle function)
  301   0x3c/imm32
  302 Primitive-size:  # (addr int)
  303   0x44/imm32/68
  304 
  305 Stmt-tag:  # int
  306   0/imm32
  307 
  308 Block-stmts:  # (handle list stmt)
  309   4/imm32
  310 Block-var:  # (handle var)
  311   0xc/imm32
  312 
  313 Stmt1-operation:  # (handle array byte)
  314   4/imm32
  315 Stmt1-inouts:  # (handle stmt-var)
  316   0xc/imm32
  317 Stmt1-outputs:  # (handle stmt-var)
  318   0x14/imm32
  319 
  320 Vardef-var:  # (handle var)
  321   4/imm32
  322 
  323 Regvardef-operation:  # (handle array byte)
  324   4/imm32
  325 Regvardef-inouts:  # (handle stmt-var)
  326   0xc/imm32
  327 Regvardef-outputs:  # (handle stmt-var)  # will have exactly one element
  328   0x14/imm32
  329 
  330 Stmt-size:  # (addr int)
  331   0x1c/imm32
  332 
  333 Var-name:  # (handle array byte)
  334   0/imm32
  335 Var-type:  # (handle type-tree)
  336   8/imm32
  337 Var-block-depth:  # int -- not available until code-generation time
  338   0x10/imm32
  339 Var-offset:  # int -- not available until code-generation time
  340   0x14/imm32
  341 Var-register:  # (handle array byte) -- name of a register
  342   0x18/imm32
  343 Var-size:  # (addr int)
  344   0x20/imm32
  345 
  346 List-value:  # (handle _)
  347   0/imm32
  348 List-next:  # (handle list _)
  349   8/imm32
  350 List-size:  # (addr int)
  351   0x10/imm32
  352 
  353 # A stmt-var is like a list of vars with call-site specific metadata
  354 Stmt-var-value:  # (handle var)
  355   0/imm32
  356 Stmt-var-next:  # (handle stmt-var)
  357   8/imm32
  358 Stmt-var-is-deref:  # boolean
  359   0x10/imm32
  360 Stmt-var-size:  # (addr int)
  361   0x14/imm32
  362 
  363 # A live-var is a var augmented with information needed for tracking live
  364 # variables.
  365 Live-var-value:  # (handle var)
  366   0/imm32
  367 Live-var-register-spilled:  # boolean; only used if value is in a register, and only during code-gen
  368   8/imm32
  369 Live-var-size:  # (addr int)
  370   0xc/imm32
  371 
  372 # Types are expressed as trees (s-expressions) of type-ids (ints).
  373 
  374 Type-tree-is-atom:  # boolean
  375   0/imm32
  376 # if is-atom?
  377 Type-tree-value:  # type-id
  378   4/imm32
  379 Type-tree-value-size:  # int (for static data structure sizes)
  380   8/imm32
  381 Type-tree-parameter-name:  # (handle array byte) for type parameters
  382   8/imm32
  383 # unless is-atom?
  384 Type-tree-left:  # (addr type-tree)
  385   4/imm32
  386 Type-tree-right:  # (addr type-tree)
  387   0xc/imm32
  388 #
  389 Type-tree-size:  # (addr int)
  390   0x14/imm32
  391 
  392 # Types
  393 
  394 # TODO: Turn this data structure into valid Mu, with (fake) handles rather than addrs.
  395 Type-id:  # (stream (addr array byte))
  396   0/imm32/write  # initialized later from Primitive-type-ids
  397   0/imm32/read
  398   0x100/imm32/size
  399   # data
  400   0/imm32  # 0 reserved for literals; value is just the name
  401            # Not to be used directly, so we don't include a name here.
  402   "int"/imm32  # 1
  403   "addr"/imm32  # 2
  404   "array"/imm32  # 3
  405   "handle"/imm32  # 4
  406   "boolean"/imm32  # 5
  407   0/imm32  # 6 reserved for constants; they're like literals, but value is an int in Var-offset
  408            # Not to be used directly, so we don't include a name here.
  409   "offset"/imm32  # 7: (offset T) is guaranteed to be a 32-bit multiple of size-of(T)
  410   # 0x20
  411   "byte"/imm32  # 8
  412   0/imm32  # 9 reserved for array-capacity; value is in Type-tree-size.
  413            # Not to be used directly, so we don't include a name here.
  414   0/imm32  # 10 reserved for type parameters; value is (address array byte) in Type-tree-value2.
  415            # Not to be used directly, so we don't include a name here.
  416   "stream"/imm32  # 11
  417   "slice"/imm32  # 12
  418   "code-point"/imm32  # 13; smallest scannable unit from a text stream
  419   "grapheme"/imm32  # 14; smallest printable unit; will eventually be composed of multiple code-points, but currently corresponds 1:1
  420                     # only 4-byte graphemes in utf-8 are currently supported;
  421                     # unclear how we should deal with larger clusters.
  422   "float"/imm32     # 15
  423   # 0x40
  424   0/imm32  # 16 reserved for literal strings; value is just the name
  425            # Not to be used directly, so we don't include a name here.
  426            # TODO: move this up next to literal ints
  427   # Keep Primitive-type-ids in sync if you add types here.
  428           0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  429   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  430   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  431   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  432   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  433   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  434 
  435 Primitive-type-ids:  # (addr int)
  436   0x44
  437 
  438 # == Type definitions
  439 # Program->types contains some typeinfo for each type definition.
  440 # Types contain vars with types, but can't specify registers.
  441 Typeinfo-id:  # type-id
  442   0/imm32
  443 Typeinfo-fields:  # (handle table (handle array byte) (handle typeinfo-entry))
  444   4/imm32
  445 # Total size must be >= 0
  446 # During parsing it may take on two additional values:
  447 #   -2: not yet initialized
  448 #   -1: in process of being computed
  449 # See populate-mu-type-sizes for details.
  450 Typeinfo-total-size-in-bytes:  # int
  451   0xc/imm32
  452 Typeinfo-next:  # (handle typeinfo)
  453   0x10/imm32
  454 Typeinfo-size:  # (addr int)
  455   0x18/imm32
  456 
  457 # Each entry in the typeinfo->fields table has a pointer to a string and a
  458 # pointer to a typeinfo-entry.
  459 Typeinfo-fields-row-size:  # (addr int)
  460   0x10/imm32
  461 
  462 # typeinfo-entry objects have information about a field in a single record type
  463 #
  464 # each field of a type is represented using two var's:
  465 #   1. the input var: expected type of the field; convenient for creating using parse-var-with-type
  466 #   2. the output var: a constant containing the byte offset; convenient for code-generation
  467 # computing the output happens after parsing; in the meantime we preserve the
  468 # order of fields in the 'index' field.
  469 Typeinfo-entry-input-var:  # (handle var)
  470   0/imm32
  471 Typeinfo-entry-index:  # int
  472   8/imm32
  473 Typeinfo-entry-output-var:  # (handle var)
  474   0xc/imm32
  475 Typeinfo-entry-size:  # (addr int)
  476   0x14/imm32
  477 
  478 == code
  479 
  480 Entry:
  481     # . prologue
  482     89/<- %ebp 4/r32/esp
  483     (new-segment *Heap-size Heap)
  484 #?     (test-address-with-right-type-for-stream)
  485     # if (argv[1] == "test') run-tests()
  486     {
  487       # if (argc <= 1) break
  488       81 7/subop/compare *ebp 1/imm32
  489       7e/jump-if-<= break/disp8
  490       # if (argv[1] != "test") break
  491       (kernel-string-equal? *(ebp+8) "test")  # => eax
  492       3d/compare-eax-and 0/imm32/false
  493       74/jump-if-= break/disp8
  494       #
  495       (run-tests)
  496       # syscall(exit, *Num-test-failures)
  497       8b/-> *Num-test-failures 3/r32/ebx
  498       eb/jump $mu-main:end/disp8
  499     }
  500     # otherwise convert Stdin
  501     (write-buffered Stdout "== code\n")
  502     (convert-mu Stdin Stdout Stderr 0)
  503     (flush Stdout)
  504     # syscall(exit, 0)
  505     bb/copy-to-ebx 0/imm32
  506 $mu-main:end:
  507     e8/call syscall_exit/disp32
  508 
  509 convert-mu:  # in: (addr buffered-file), out: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
  510     # . prologue
  511     55/push-ebp
  512     89/<- %ebp 4/r32/esp
  513     # . save registers
  514     50/push-eax
  515     # initialize global data structures
  516     c7 0/subop/copy *Next-block-index 1/imm32
  517     8b/-> *Primitive-type-ids 0/r32/eax
  518     89/<- *Type-id 0/r32/eax  # stream-write
  519     c7 0/subop/copy *_Program-functions 0/imm32
  520     c7 0/subop/copy *_Program-functions->payload 0/imm32
  521     c7 0/subop/copy *_Program-types 0/imm32
  522     c7 0/subop/copy *_Program-types->payload 0/imm32
  523     c7 0/subop/copy *_Program-signatures 0/imm32
  524     c7 0/subop/copy *_Program-signatures->payload 0/imm32
  525     #
  526     (parse-mu *(ebp+8) *(ebp+0x10) *(ebp+0x14))
  527     (populate-mu-type-sizes *(ebp+0x10) *(ebp+0x14))
  528 #?     (dump-typeinfos "=== typeinfos\n")
  529     (check-mu-types *(ebp+0x10) *(ebp+0x14))
  530     (emit-subx *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
  531 $convert-mu:end:
  532     # . restore registers
  533     58/pop-to-eax
  534     # . epilogue
  535     89/<- %esp 5/r32/ebp
  536     5d/pop-to-ebp
  537     c3/return
  538 
  539 test-convert-empty-input:
  540     # empty input => empty output
  541     # . prologue
  542     55/push-ebp
  543     89/<- %ebp 4/r32/esp
  544     # setup
  545     (clear-stream _test-input-stream)
  546     (clear-stream $_test-input-buffered-file->buffer)
  547     (clear-stream _test-output-stream)
  548     (clear-stream $_test-output-buffered-file->buffer)
  549     #
  550     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  551     (flush _test-output-buffered-file)
  552     (check-stream-equal _test-output-stream "" "F - test-convert-empty-input")
  553     # . epilogue
  554     89/<- %esp 5/r32/ebp
  555     5d/pop-to-ebp
  556     c3/return
  557 
  558 test-convert-function-skeleton:
  559     # . prologue
  560     55/push-ebp
  561     89/<- %ebp 4/r32/esp
  562     # setup
  563     (clear-stream _test-input-stream)
  564     (clear-stream $_test-input-buffered-file->buffer)
  565     (clear-stream _test-output-stream)
  566     (clear-stream $_test-output-buffered-file->buffer)
  567     #
  568     (write _test-input-stream "fn foo {\n")
  569     (write _test-input-stream "}\n")
  570     # convert
  571     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  572     (flush _test-output-buffered-file)
  573 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
  579     # check output
  580     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-skeleton/0")
  581     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-skeleton/1")
  582     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-skeleton/2")
  583     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-skeleton/3")
  584     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-skeleton/4")
  585     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-skeleton/5")
  586     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-skeleton/6")
  587     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-skeleton/7")
  588     # . epilogue
  589     89/<- %esp 5/r32/ebp
  590     5d/pop-to-ebp
  591     c3/return
  592 
  593 test-convert-multiple-function-skeletons:
  594     # . prologue
  595     55/push-ebp
  596     89/<- %ebp 4/r32/esp
  597     # setup
  598     (clear-stream _test-input-stream)
  599     (clear-stream $_test-input-buffered-file->buffer)
  600     (clear-stream _test-output-stream)
  601     (clear-stream $_test-output-buffered-file->buffer)
  602     #
  603     (write _test-input-stream "fn foo {\n")
  604     (write _test-input-stream "}\n")
  605     (write _test-input-stream "fn bar {\n")
  606     (write _test-input-stream "}\n")
  607     # convert
  608     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  609     (flush _test-output-buffered-file)
  610 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
  616     # check first function
  617     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-multiple-function-skeletons/0")
  618     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-multiple-function-skeletons/1")
  619     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-multiple-function-skeletons/2")
  620     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-multiple-function-skeletons/3")
  621     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-multiple-function-skeletons/4")
  622     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-multiple-function-skeletons/5")
  623     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-multiple-function-skeletons/6")
  624     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-multiple-function-skeletons/7")
  625     # check second function
  626     (check-next-stream-line-equal _test-output-stream "bar:"                    "F - test-convert-multiple-function-skeletons/10")
  627     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-multiple-function-skeletons/11")
  628     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-multiple-function-skeletons/12")
  629     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-multiple-function-skeletons/13")
  630     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-multiple-function-skeletons/14")
  631     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-multiple-function-skeletons/15")
  632     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-multiple-function-skeletons/16")
  633     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-multiple-function-skeletons/17")
  634     # . epilogue
  635     89/<- %esp 5/r32/ebp
  636     5d/pop-to-ebp
  637     c3/return
  638 
  639 test-convert-function-with-arg:
  640     # . prologue
  641     55/push-ebp
  642     89/<- %ebp 4/r32/esp
  643     # setup
  644     (clear-stream _test-input-stream)
  645     (clear-stream $_test-input-buffered-file->buffer)
  646     (clear-stream _test-output-stream)
  647     (clear-stream $_test-output-buffered-file->buffer)
  648     #
  649     (write _test-input-stream "fn foo n: int {\n")
  650     (write _test-input-stream "}\n")
  651     # convert
  652     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  653     (flush _test-output-buffered-file)
  654 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
  660     # check output
  661     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-arg/0")
  662     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-arg/1")
  663     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-arg/2")
  664     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-arg/3")
  665     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-arg/4")
  666     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-arg/5")
  667     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-arg/6")
  668     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-arg/7")
  669     # . epilogue
  670     89/<- %esp 5/r32/ebp
  671     5d/pop-to-ebp
  672     c3/return
  673 
  674 test-function-with-redefined-name:
  675     # . prologue
  676     55/push-ebp
  677     89/<- %ebp 4/r32/esp
  678     # setup
  679     (clear-stream _test-input-stream)
  680     (clear-stream $_test-input-buffered-file->buffer)
  681     (clear-stream _test-output-stream)
  682     (clear-stream $_test-output-buffered-file->buffer)
  683     (clear-stream _test-error-stream)
  684     (clear-stream $_test-error-buffered-file->buffer)
  685     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  686     68/push 0/imm32
  687     68/push 0/imm32
  688     89/<- %edx 4/r32/esp
  689     (tailor-exit-descriptor %edx 0x10)
  690     #
  691     (write _test-input-stream "fn foo {\n")
  692     (write _test-input-stream "}\n")
  693     (write _test-input-stream "fn foo {\n")
  694     (write _test-input-stream "}\n")
  695     # convert
  696     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  697     # registers except esp clobbered at this point
  698     # restore ed
  699     89/<- %edx 4/r32/esp
  700     (flush _test-output-buffered-file)
  701     (flush _test-error-buffered-file)
  702 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
  708     # check output
  709     (check-stream-equal _test-output-stream  ""  "F - test-function-with-redefined-name: output should be empty")
  710     (check-next-stream-line-equal _test-error-stream  "fn foo defined more than once"  "F - test-function-with-redefined-name: error message")
  711     # check that stop(1) was called
  712     (check-ints-equal *(edx+4) 2 "F - test-function-with-redefined-name: exit status")
  713     # don't restore from ebp
  714     81 0/subop/add %esp 8/imm32
  715     # . epilogue
  716     5d/pop-to-ebp
  717     c3/return
  718 
  719 test-function-with-redefined-name-2:
  720     # . prologue
  721     55/push-ebp
  722     89/<- %ebp 4/r32/esp
  723     # setup
  724     (clear-stream _test-input-stream)
  725     (clear-stream $_test-input-buffered-file->buffer)
  726     (clear-stream _test-output-stream)
  727     (clear-stream $_test-output-buffered-file->buffer)
  728     (clear-stream _test-error-stream)
  729     (clear-stream $_test-error-buffered-file->buffer)
  730     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  731     68/push 0/imm32
  732     68/push 0/imm32
  733     89/<- %edx 4/r32/esp
  734     (tailor-exit-descriptor %edx 0x10)
  735     #
  736     (write _test-input-stream "fn foo {\n")
  737     (write _test-input-stream "}\n")
  738     (write _test-input-stream "sig foo\n")
  739     # convert
  740     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  741     # registers except esp clobbered at this point
  742     # restore ed
  743     89/<- %edx 4/r32/esp
  744     (flush _test-output-buffered-file)
  745     (flush _test-error-buffered-file)
  746 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
  752     # check output
  753     (check-stream-equal _test-output-stream  ""  "F - test-function-with-redefined-name-2: output should be empty")
  754     (check-next-stream-line-equal _test-error-stream  "fn foo defined more than once"  "F - test-function-with-redefined-name-2: error message")
  755     # check that stop(1) was called
  756     (check-ints-equal *(edx+4) 2 "F - test-function-with-redefined-name-2: exit status")
  757     # don't restore from ebp
  758     81 0/subop/add %esp 8/imm32
  759     # . epilogue
  760     5d/pop-to-ebp
  761     c3/return
  762 
  763 test-function-with-redefined-name-3:
  764     # . prologue
  765     55/push-ebp
  766     89/<- %ebp 4/r32/esp
  767     # setup
  768     (clear-stream _test-input-stream)
  769     (clear-stream $_test-input-buffered-file->buffer)
  770     (clear-stream _test-output-stream)
  771     (clear-stream $_test-output-buffered-file->buffer)
  772     (clear-stream _test-error-stream)
  773     (clear-stream $_test-error-buffered-file->buffer)
  774     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  775     68/push 0/imm32
  776     68/push 0/imm32
  777     89/<- %edx 4/r32/esp
  778     (tailor-exit-descriptor %edx 0x10)
  779     #
  780     (write _test-input-stream "sig foo\n")
  781     (write _test-input-stream "fn foo {\n")
  782     (write _test-input-stream "}\n")
  783     # convert
  784     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  785     # registers except esp clobbered at this point
  786     # restore ed
  787     89/<- %edx 4/r32/esp
  788     (flush _test-output-buffered-file)
  789     (flush _test-error-buffered-file)
  790 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
  796     # check output
  797     (check-stream-equal _test-output-stream  ""  "F - test-function-with-redefined-name-3: output should be empty")
  798     (check-next-stream-line-equal _test-error-stream  "fn foo defined more than once"  "F - test-function-with-redefined-name-3: error message")
  799     # check that stop(1) was called
  800     (check-ints-equal *(edx+4) 2 "F - test-function-with-redefined-name-3: exit status")
  801     # don't restore from ebp
  802     81 0/subop/add %esp 8/imm32
  803     # . epilogue
  804     5d/pop-to-ebp
  805     c3/return
  806 
  807 test-function-with-inout-in-register:
  808     # . prologue
  809     55/push-ebp
  810     89/<- %ebp 4/r32/esp
  811     # setup
  812     (clear-stream _test-input-stream)
  813     (clear-stream $_test-input-buffered-file->buffer)
  814     (clear-stream _test-output-stream)
  815     (clear-stream $_test-output-buffered-file->buffer)
  816     (clear-stream _test-error-stream)
  817     (clear-stream $_test-error-buffered-file->buffer)
  818     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  819     68/push 0/imm32
  820     68/push 0/imm32
  821     89/<- %edx 4/r32/esp
  822     (tailor-exit-descriptor %edx 0x10)
  823     #
  824     (write _test-input-stream "fn foo x/eax: int {\n")
  825     (write _test-input-stream "}\n")
  826     # convert
  827     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  828     # registers except esp clobbered at this point
  829     # restore ed
  830     89/<- %edx 4/r32/esp
  831     (flush _test-output-buffered-file)
  832     (flush _test-error-buffered-file)
  833 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
  839     # check output
  840     (check-stream-equal _test-output-stream  ""  "F - test-function-with-inout-in-register: output should be empty")
  841     (check-next-stream-line-equal _test-error-stream  "fn foo: function inout 'x' cannot be in a register"  "F - test-function-with-inout-in-register: error message")
  842     # check that stop(1) was called
  843     (check-ints-equal *(edx+4) 2 "F - test-function-with-inout-in-register: exit status")
  844     # don't restore from ebp
  845     81 0/subop/add %esp 8/imm32
  846     # . epilogue
  847     5d/pop-to-ebp
  848     c3/return
  849 
  850 test-function-with-addr-output:
  851     # . prologue
  852     55/push-ebp
  853     89/<- %ebp 4/r32/esp
  854     # setup
  855     (clear-stream _test-input-stream)
  856     (clear-stream $_test-input-buffered-file->buffer)
  857     (clear-stream _test-output-stream)
  858     (clear-stream $_test-output-buffered-file->buffer)
  859     (clear-stream _test-error-stream)
  860     (clear-stream $_test-error-buffered-file->buffer)
  861     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  862     68/push 0/imm32
  863     68/push 0/imm32
  864     89/<- %edx 4/r32/esp
  865     (tailor-exit-descriptor %edx 0x10)
  866     #
  867     (write _test-input-stream "fn foo -> _/eax: (addr int) {\n")
  868     (write _test-input-stream "}\n")
  869     # convert
  870     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  871     # registers except esp clobbered at this point
  872     # restore ed
  873     89/<- %edx 4/r32/esp
  874     (flush _test-output-buffered-file)
  875     (flush _test-error-buffered-file)
  876 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
  882     # check output
  883     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-output: output should be empty")
  884     (check-next-stream-line-equal _test-error-stream  "fn foo: output cannot have an addr type; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-output: error message")
  885     # check that stop(1) was called
  886     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-output: exit status")
  887     # don't restore from ebp
  888     81 0/subop/add %esp 8/imm32
  889     # . epilogue
  890     5d/pop-to-ebp
  891     c3/return
  892 
  893 test-function-with-addr-inout:
  894     # . prologue
  895     55/push-ebp
  896     89/<- %ebp 4/r32/esp
  897     # setup
  898     (clear-stream _test-input-stream)
  899     (clear-stream $_test-input-buffered-file->buffer)
  900     (clear-stream _test-output-stream)
  901     (clear-stream $_test-output-buffered-file->buffer)
  902     (clear-stream _test-error-stream)
  903     (clear-stream $_test-error-buffered-file->buffer)
  904     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  905     68/push 0/imm32
  906     68/push 0/imm32
  907     89/<- %edx 4/r32/esp
  908     (tailor-exit-descriptor %edx 0x10)
  909     #
  910     (write _test-input-stream "fn foo a: (addr addr int) {\n")
  911     (write _test-input-stream "}\n")
  912     # convert
  913     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  914     # registers except esp clobbered at this point
  915     # restore ed
  916     89/<- %edx 4/r32/esp
  917     (flush _test-output-buffered-file)
  918     (flush _test-error-buffered-file)
  919 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
  925     # check output
  926     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout: output should be empty")
  927     (check-next-stream-line-equal _test-error-stream  "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-inout: error message")
  928     # check that stop(1) was called
  929     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout: exit status")
  930     # don't restore from ebp
  931     81 0/subop/add %esp 8/imm32
  932     # . epilogue
  933     5d/pop-to-ebp
  934     c3/return
  935 
  936 test-function-with-addr-inout-2:
  937     # . prologue
  938     55/push-ebp
  939     89/<- %ebp 4/r32/esp
  940     # setup
  941     (clear-stream _test-input-stream)
  942     (clear-stream $_test-input-buffered-file->buffer)
  943     (clear-stream _test-output-stream)
  944     (clear-stream $_test-output-buffered-file->buffer)
  945     (clear-stream _test-error-stream)
  946     (clear-stream $_test-error-buffered-file->buffer)
  947     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  948     68/push 0/imm32
  949     68/push 0/imm32
  950     89/<- %edx 4/r32/esp
  951     (tailor-exit-descriptor %edx 0x10)
  952     #
  953     (write _test-input-stream "fn foo a: (addr array addr int) {\n")
  954     (write _test-input-stream "}\n")
  955     # convert
  956     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  957     # registers except esp clobbered at this point
  958     # restore ed
  959     89/<- %edx 4/r32/esp
  960     (flush _test-output-buffered-file)
  961     (flush _test-error-buffered-file)
  962 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
  968     # check output
  969     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout-2: output should be empty")
  970     (check-next-stream-line-equal _test-error-stream  "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-inout-2: error message")
  971     # check that stop(1) was called
  972     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout-2: exit status")
  973     # don't restore from ebp
  974     81 0/subop/add %esp 8/imm32
  975     # . epilogue
  976     5d/pop-to-ebp
  977     c3/return
  978 
  979 test-function-with-addr-inout-3:
  980     # . prologue
  981     55/push-ebp
  982     89/<- %ebp 4/r32/esp
  983     # setup
  984     (clear-stream _test-input-stream)
  985     (clear-stream $_test-input-buffered-file->buffer)
  986     (clear-stream _test-output-stream)
  987     (clear-stream $_test-output-buffered-file->buffer)
  988     (clear-stream _test-error-stream)
  989     (clear-stream $_test-error-buffered-file->buffer)
  990     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  991     68/push 0/imm32
  992     68/push 0/imm32
  993     89/<- %edx 4/r32/esp
  994     (tailor-exit-descriptor %edx 0x10)
  995     #
  996     (write _test-input-stream "fn foo a: (addr array (addr int) 3) {\n")
  997     (write _test-input-stream "}\n")
  998     # convert
  999     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1000     # registers except esp clobbered at this point
 1001     # restore ed
 1002     89/<- %edx 4/r32/esp
 1003     (flush _test-output-buffered-file)
 1004     (flush _test-error-buffered-file)
 1005 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1011     # check output
 1012     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout-3: output should be empty")
 1013     (check-next-stream-line-equal _test-error-stream  "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-inout-3: error message")
 1014     # check that stop(1) was called
 1015     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout-3: exit status")
 1016     # don't restore from ebp
 1017     81 0/subop/add %esp 8/imm32
 1018     # . epilogue
 1019     5d/pop-to-ebp
 1020     c3/return
 1021 
 1022 test-function-with-addr-inout-4:
 1023     # . prologue
 1024     55/push-ebp
 1025     89/<- %ebp 4/r32/esp
 1026     # setup
 1027     (clear-stream _test-input-stream)
 1028     (clear-stream $_test-input-buffered-file->buffer)
 1029     (clear-stream _test-output-stream)
 1030     (clear-stream $_test-output-buffered-file->buffer)
 1031     (clear-stream _test-error-stream)
 1032     (clear-stream $_test-error-buffered-file->buffer)
 1033     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1034     68/push 0/imm32
 1035     68/push 0/imm32
 1036     89/<- %edx 4/r32/esp
 1037     (tailor-exit-descriptor %edx 0x10)
 1038     #
 1039     (write _test-input-stream "fn foo a: (array (addr int) 3) {\n")
 1040     (write _test-input-stream "}\n")
 1041     # convert
 1042     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1043     # registers except esp clobbered at this point
 1044     # restore ed
 1045     89/<- %edx 4/r32/esp
 1046     (flush _test-output-buffered-file)
 1047     (flush _test-error-buffered-file)
 1048 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1054     # check output
 1055     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout-4: output should be empty")
 1056     (check-next-stream-line-equal _test-error-stream  "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-inout-4: error message")
 1057     # check that stop(1) was called
 1058     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout-4: exit status")
 1059     # don't restore from ebp
 1060     81 0/subop/add %esp 8/imm32
 1061     # . epilogue
 1062     5d/pop-to-ebp
 1063     c3/return
 1064 
 1065 # 'main' is an exception
 1066 test-function-main-with-addr-inout:
 1067     # . prologue
 1068     55/push-ebp
 1069     89/<- %ebp 4/r32/esp
 1070     # setup
 1071     (clear-stream _test-input-stream)
 1072     (clear-stream $_test-input-buffered-file->buffer)
 1073     (clear-stream _test-output-stream)
 1074     (clear-stream $_test-output-buffered-file->buffer)
 1075     #
 1076     (write _test-input-stream "fn main a: (addr addr int) {\n")
 1077     (write _test-input-stream "}\n")
 1078     # convert
 1079     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1080     (flush _test-output-buffered-file)
 1081     # no errors
 1082     # . epilogue
 1083     89/<- %esp 5/r32/ebp
 1084     5d/pop-to-ebp
 1085     c3/return
 1086 
 1087 # 'lookup' is an exception, but only in signatures
 1088 test-signature-lookup-with-addr-inout:
 1089     # . prologue
 1090     55/push-ebp
 1091     89/<- %ebp 4/r32/esp
 1092     # setup
 1093     (clear-stream _test-input-stream)
 1094     (clear-stream $_test-input-buffered-file->buffer)
 1095     (clear-stream _test-output-stream)
 1096     (clear-stream $_test-output-buffered-file->buffer)
 1097     #
 1098     (write _test-input-stream "sig lookup h: (handle _T) -> _/eax: (addr _T)\n")
 1099     # convert
 1100     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1101     (flush _test-output-buffered-file)
 1102     # no errors
 1103     # . epilogue
 1104     89/<- %esp 5/r32/ebp
 1105     5d/pop-to-ebp
 1106     c3/return
 1107 
 1108 test-convert-function-with-arg-and-body:
 1109     # . prologue
 1110     55/push-ebp
 1111     89/<- %ebp 4/r32/esp
 1112     # setup
 1113     (clear-stream _test-input-stream)
 1114     (clear-stream $_test-input-buffered-file->buffer)
 1115     (clear-stream _test-output-stream)
 1116     (clear-stream $_test-output-buffered-file->buffer)
 1117     #
 1118     (write _test-input-stream "fn foo n: int {\n")
 1119     (write _test-input-stream "  increment n\n")
 1120     (write _test-input-stream "}\n")
 1121     # convert
 1122     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1123     (flush _test-output-buffered-file)
 1124 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1130     # check output
 1131     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-arg-and-body/0")
 1132     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-arg-and-body/1")
 1133     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-arg-and-body/2")
 1134     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-arg-and-body/3")
 1135     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-arg-and-body/4")
 1136     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-arg-and-body/5")
 1137     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-arg-and-body/6")
 1138     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-arg-and-body/7")
 1139     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-arg-and-body/8")
 1140     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-arg-and-body/9")
 1141     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-arg-and-body/10")
 1142     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-arg-and-body/11")
 1143     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-arg-and-body/12")
 1144     # . epilogue
 1145     89/<- %esp 5/r32/ebp
 1146     5d/pop-to-ebp
 1147     c3/return
 1148 
 1149 test-convert-function-distinguishes-args:
 1150     # . prologue
 1151     55/push-ebp
 1152     89/<- %ebp 4/r32/esp
 1153     # setup
 1154     (clear-stream _test-input-stream)
 1155     (clear-stream $_test-input-buffered-file->buffer)
 1156     (clear-stream _test-output-stream)
 1157     (clear-stream $_test-output-buffered-file->buffer)
 1158     #
 1159     (write _test-input-stream "fn foo a: int, b: int {\n")
 1160     (write _test-input-stream "  increment b\n")
 1161     (write _test-input-stream "}\n")
 1162     # convert
 1163     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1164     (flush _test-output-buffered-file)
 1165 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1171     # check output
 1172     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-distinguishes-args/0")
 1173     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-distinguishes-args/1")
 1174     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-distinguishes-args/2")
 1175     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-distinguishes-args/3")
 1176     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-distinguishes-args/4")
 1177     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-distinguishes-args/5")
 1178     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0x0000000c)"  "F - test-convert-function-distinguishes-args/6")
 1179     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-distinguishes-args/7")
 1180     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-distinguishes-args/8")
 1181     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-distinguishes-args/9")
 1182     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-distinguishes-args/10")
 1183     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-distinguishes-args/11")
 1184     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-distinguishes-args/12")
 1185     # . epilogue
 1186     89/<- %esp 5/r32/ebp
 1187     5d/pop-to-ebp
 1188     c3/return
 1189 
 1190 test-convert-function-with-return-literal:
 1191     # . prologue
 1192     55/push-ebp
 1193     89/<- %ebp 4/r32/esp
 1194     # setup
 1195     (clear-stream _test-input-stream)
 1196     (clear-stream $_test-input-buffered-file->buffer)
 1197     (clear-stream _test-output-stream)
 1198     (clear-stream $_test-output-buffered-file->buffer)
 1199     #
 1200     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1201     (write _test-input-stream "  return 0\n")
 1202     (write _test-input-stream "}\n")
 1203     # convert
 1204     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1205     (flush _test-output-buffered-file)
 1206 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1212     # check output
 1213     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-literal/0")
 1214     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-literal/1")
 1215     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-literal/2")
 1216     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-literal/3")
 1217     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-literal/4")
 1218     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-literal/5")
 1219     (check-next-stream-line-equal _test-output-stream "    c7 0/subop/copy %eax 0/imm32"  "F - test-convert-function-with-return-literal/6")
 1220     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-literal/7")
 1221     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-literal/8")
 1222     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-literal/9")
 1223     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-literal/10")
 1224     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-literal/11")
 1225     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-literal/12")
 1226     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-literal/13")
 1227     # . epilogue
 1228     89/<- %esp 5/r32/ebp
 1229     5d/pop-to-ebp
 1230     c3/return
 1231 
 1232 test-convert-function-with-return:
 1233     # . prologue
 1234     55/push-ebp
 1235     89/<- %ebp 4/r32/esp
 1236     # setup
 1237     (clear-stream _test-input-stream)
 1238     (clear-stream $_test-input-buffered-file->buffer)
 1239     (clear-stream _test-output-stream)
 1240     (clear-stream $_test-output-buffered-file->buffer)
 1241     #
 1242     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1243     (write _test-input-stream "  var y: int\n")
 1244     (write _test-input-stream "  return y\n")
 1245     (write _test-input-stream "}\n")
 1246     # convert
 1247     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1248     (flush _test-output-buffered-file)
 1249 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1255     # check output
 1256     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return/0")
 1257     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return/1")
 1258     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return/2")
 1259     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return/3")
 1260     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return/4")
 1261     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return/5")
 1262     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-return/6")  # y
 1263     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0xfffffffc) 0x00000000/r32" "F - test-convert-function-with-return/7")
 1264     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-return/8")
 1265     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return/9")
 1266     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return/10")
 1267     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return/11")
 1268     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return/12")
 1269     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return/13")
 1270     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return/14")
 1271     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return/15")
 1272     # . epilogue
 1273     89/<- %esp 5/r32/ebp
 1274     5d/pop-to-ebp
 1275     c3/return
 1276 
 1277 test-convert-function-with-return-float:
 1278     # . prologue
 1279     55/push-ebp
 1280     89/<- %ebp 4/r32/esp
 1281     # setup
 1282     (clear-stream _test-input-stream)
 1283     (clear-stream $_test-input-buffered-file->buffer)
 1284     (clear-stream _test-output-stream)
 1285     (clear-stream $_test-output-buffered-file->buffer)
 1286     #
 1287     (write _test-input-stream "fn foo -> _/xmm0: float {\n")
 1288     (write _test-input-stream "  var y: float\n")
 1289     (write _test-input-stream "  return y\n")
 1290     (write _test-input-stream "}\n")
 1291     # convert
 1292     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1293     (flush _test-output-buffered-file)
 1294 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1300     # check output
 1301     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return/0")
 1302     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return/1")
 1303     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return/2")
 1304     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return/3")
 1305     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return/4")
 1306     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return/5")
 1307     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-return/6")  # y
 1308     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *(ebp+0xfffffffc) 0x00000000/x32" "F - test-convert-function-with-return/7")
 1309     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-return/8")
 1310     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return/9")
 1311     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return/10")
 1312     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return/11")
 1313     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return/12")
 1314     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return/13")
 1315     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return/14")
 1316     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return/15")
 1317     # . epilogue
 1318     89/<- %esp 5/r32/ebp
 1319     5d/pop-to-ebp
 1320     c3/return
 1321 
 1322 test-convert-function-with-return-register:
 1323     # . prologue
 1324     55/push-ebp
 1325     89/<- %ebp 4/r32/esp
 1326     # setup
 1327     (clear-stream _test-input-stream)
 1328     (clear-stream $_test-input-buffered-file->buffer)
 1329     (clear-stream _test-output-stream)
 1330     (clear-stream $_test-output-buffered-file->buffer)
 1331     #
 1332     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1333     (write _test-input-stream "  var y/eax: int <- copy 3\n")
 1334     (write _test-input-stream "  return y\n")
 1335     (write _test-input-stream "}\n")
 1336     # convert
 1337     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1338     (flush _test-output-buffered-file)
 1339 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1345     # check output
 1346     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register/0")
 1347     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register/1")
 1348     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register/2")
 1349     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register/3")
 1350     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register/4")
 1351     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register/5")
 1352     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register/6")
 1353     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-convert-function-with-return-register/7")
 1354     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-return-register/8")
 1355     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-return-register/9")
 1356     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-register/10")
 1357     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register/11")
 1358     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register/12")
 1359     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register/13")
 1360     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register/14")
 1361     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register/15")
 1362     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register/16")
 1363     # . epilogue
 1364     89/<- %esp 5/r32/ebp
 1365     5d/pop-to-ebp
 1366     c3/return
 1367 
 1368 test-function-with-output-without-register:
 1369     # . prologue
 1370     55/push-ebp
 1371     89/<- %ebp 4/r32/esp
 1372     # setup
 1373     (clear-stream _test-input-stream)
 1374     (clear-stream $_test-input-buffered-file->buffer)
 1375     (clear-stream _test-output-stream)
 1376     (clear-stream $_test-output-buffered-file->buffer)
 1377     (clear-stream _test-error-stream)
 1378     (clear-stream $_test-error-buffered-file->buffer)
 1379     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1380     68/push 0/imm32
 1381     68/push 0/imm32
 1382     89/<- %edx 4/r32/esp
 1383     (tailor-exit-descriptor %edx 0x10)
 1384     #
 1385     (write _test-input-stream "fn foo -> _: int {\n")
 1386     (write _test-input-stream "}\n")
 1387     # convert
 1388     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1389     # registers except esp clobbered at this point
 1390     # restore ed
 1391     89/<- %edx 4/r32/esp
 1392     (flush _test-output-buffered-file)
 1393     (flush _test-error-buffered-file)
 1394 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1400     # check output
 1401     (check-stream-equal _test-output-stream  ""  "F - test-function-with-output-without-register: output should be empty")
 1402     (check-next-stream-line-equal _test-error-stream  "fn foo: function output '_' must be in a register, in instruction 'fn foo -> _: int {"  "F - test-function-with-output-without-register: error message")
 1403     # check that stop(1) was called
 1404     (check-ints-equal *(edx+4) 2 "F - test-function-with-output-without-register: exit status")
 1405     # don't restore from ebp
 1406     81 0/subop/add %esp 8/imm32
 1407     # . epilogue
 1408     5d/pop-to-ebp
 1409     c3/return
 1410 
 1411 test-function-with-outputs-in-conflicting-registers:
 1412     # . prologue
 1413     55/push-ebp
 1414     89/<- %ebp 4/r32/esp
 1415     # setup
 1416     (clear-stream _test-input-stream)
 1417     (clear-stream $_test-input-buffered-file->buffer)
 1418     (clear-stream _test-output-stream)
 1419     (clear-stream $_test-output-buffered-file->buffer)
 1420     (clear-stream _test-error-stream)
 1421     (clear-stream $_test-error-buffered-file->buffer)
 1422     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1423     68/push 0/imm32
 1424     68/push 0/imm32
 1425     89/<- %edx 4/r32/esp
 1426     (tailor-exit-descriptor %edx 0x10)
 1427     #
 1428     (write _test-input-stream "fn foo -> _/eax: int, _/eax: int {\n")
 1429     (write _test-input-stream "}\n")
 1430     # convert
 1431     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1432     # registers except esp clobbered at this point
 1433     # restore ed
 1434     89/<- %edx 4/r32/esp
 1435     (flush _test-output-buffered-file)
 1436     (flush _test-error-buffered-file)
 1437 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1443     # check output
 1444     (check-stream-equal _test-output-stream  ""  "F - test-function-with-outputs-in-conflicting-registers: output should be empty")
 1445     (check-next-stream-line-equal _test-error-stream  "fn foo: outputs must be in unique registers"  "F - test-function-with-outputs-in-conflicting-registers: error message")
 1446     # check that stop(1) was called
 1447     (check-ints-equal *(edx+4) 2 "F - test-function-with-outputs-in-conflicting-registers: exit status")
 1448     # don't restore from ebp
 1449     81 0/subop/add %esp 8/imm32
 1450     # . epilogue
 1451     5d/pop-to-ebp
 1452     c3/return
 1453 
 1454 test-function-with-named-output:
 1455     # . prologue
 1456     55/push-ebp
 1457     89/<- %ebp 4/r32/esp
 1458     # setup
 1459     (clear-stream _test-input-stream)
 1460     (clear-stream $_test-input-buffered-file->buffer)
 1461     (clear-stream _test-output-stream)
 1462     (clear-stream $_test-output-buffered-file->buffer)
 1463     (clear-stream _test-error-stream)
 1464     (clear-stream $_test-error-buffered-file->buffer)
 1465     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1466     68/push 0/imm32
 1467     68/push 0/imm32
 1468     89/<- %edx 4/r32/esp
 1469     (tailor-exit-descriptor %edx 0x10)
 1470     #
 1471     (write _test-input-stream "fn foo -> x/eax: int {\n")
 1472     (write _test-input-stream "  return 0\n")
 1473     (write _test-input-stream "}\n")
 1474     # convert
 1475     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1476     # registers except esp clobbered at this point
 1477     # restore ed
 1478     89/<- %edx 4/r32/esp
 1479     (flush _test-output-buffered-file)
 1480     (flush _test-error-buffered-file)
 1481 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1487     # check output
 1488     (check-stream-equal _test-output-stream  ""  "F - test-function-with-named-output: output should be empty")
 1489     (check-next-stream-line-equal _test-error-stream  "fn foo: function outputs cannot be named; rename 'x' in the header to '_'"  "F - test-function-with-named-output: error message")
 1490     # check that stop(1) was called
 1491     (check-ints-equal *(edx+4) 2 "F - test-function-with-named-output: exit status")
 1492     # don't restore from ebp
 1493     81 0/subop/add %esp 8/imm32
 1494     # . epilogue
 1495     5d/pop-to-ebp
 1496     c3/return
 1497 
 1498 test-return-with-wrong-type:
 1499     # . prologue
 1500     55/push-ebp
 1501     89/<- %ebp 4/r32/esp
 1502     # setup
 1503     (clear-stream _test-input-stream)
 1504     (clear-stream $_test-input-buffered-file->buffer)
 1505     (clear-stream _test-output-stream)
 1506     (clear-stream $_test-output-buffered-file->buffer)
 1507     (clear-stream _test-error-stream)
 1508     (clear-stream $_test-error-buffered-file->buffer)
 1509     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1510     68/push 0/imm32
 1511     68/push 0/imm32
 1512     89/<- %edx 4/r32/esp
 1513     (tailor-exit-descriptor %edx 0x10)
 1514     #
 1515     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1516     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 1517     (write _test-input-stream "  return x\n")
 1518     (write _test-input-stream "}\n")
 1519     # convert
 1520     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1521     # registers except esp clobbered at this point
 1522     # restore ed
 1523     89/<- %edx 4/r32/esp
 1524     (flush _test-output-buffered-file)
 1525     (flush _test-error-buffered-file)
 1526 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1532     # check output
 1533     (check-stream-equal _test-output-stream  ""  "F - test-return-with-wrong-type: output should be empty")
 1534     (check-next-stream-line-equal _test-error-stream  "fn foo: return: 'x' has the wrong type"  "F - test-return-with-wrong-type: error message")
 1535     # check that stop(1) was called
 1536     (check-ints-equal *(edx+4) 2 "F - test-return-with-wrong-type: exit status")
 1537     # don't restore from ebp
 1538     81 0/subop/add %esp 8/imm32
 1539     # . epilogue
 1540     5d/pop-to-ebp
 1541     c3/return
 1542 
 1543 test-missing-return:
 1544     # . prologue
 1545     55/push-ebp
 1546     89/<- %ebp 4/r32/esp
 1547     # setup
 1548     (clear-stream _test-input-stream)
 1549     (clear-stream $_test-input-buffered-file->buffer)
 1550     (clear-stream _test-output-stream)
 1551     (clear-stream $_test-output-buffered-file->buffer)
 1552     (clear-stream _test-error-stream)
 1553     (clear-stream $_test-error-buffered-file->buffer)
 1554     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1555     68/push 0/imm32
 1556     68/push 0/imm32
 1557     89/<- %edx 4/r32/esp
 1558     (tailor-exit-descriptor %edx 0x10)
 1559     #
 1560     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1561     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 1562     (write _test-input-stream "}\n")
 1563     # convert
 1564     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1565     # registers except esp clobbered at this point
 1566     # restore ed
 1567     89/<- %edx 4/r32/esp
 1568     (flush _test-output-buffered-file)
 1569     (flush _test-error-buffered-file)
 1570 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1576     # check output
 1577     (check-stream-equal _test-output-stream  ""  "F - test-missing-return: output should be empty")
 1578     (check-next-stream-line-equal _test-error-stream  "fn foo: final statement should be a 'return'"  "F - test-missing-return: error message")
 1579     # check that stop(1) was called
 1580     (check-ints-equal *(edx+4) 2 "F - test-missing-return: exit status")
 1581     # don't restore from ebp
 1582     81 0/subop/add %esp 8/imm32
 1583     # . epilogue
 1584     5d/pop-to-ebp
 1585     c3/return
 1586 
 1587 test-missing-return-2:
 1588     # . prologue
 1589     55/push-ebp
 1590     89/<- %ebp 4/r32/esp
 1591     # setup
 1592     (clear-stream _test-input-stream)
 1593     (clear-stream $_test-input-buffered-file->buffer)
 1594     (clear-stream _test-output-stream)
 1595     (clear-stream $_test-output-buffered-file->buffer)
 1596     (clear-stream _test-error-stream)
 1597     (clear-stream $_test-error-buffered-file->buffer)
 1598     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1599     68/push 0/imm32
 1600     68/push 0/imm32
 1601     89/<- %edx 4/r32/esp
 1602     (tailor-exit-descriptor %edx 0x10)
 1603     #
 1604     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1605     (write _test-input-stream "}\n")
 1606     # convert
 1607     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1608     # registers except esp clobbered at this point
 1609     # restore ed
 1610     89/<- %edx 4/r32/esp
 1611     (flush _test-output-buffered-file)
 1612     (flush _test-error-buffered-file)
 1613 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1619     # check output
 1620     (check-stream-equal _test-output-stream  ""  "F - test-missing-return-2: output should be empty")
 1621     (check-next-stream-line-equal _test-error-stream  "fn foo: final statement should be a 'return'"  "F - test-missing-return-2: error message")
 1622     # check that stop(1) was called
 1623     (check-ints-equal *(edx+4) 2 "F - test-missing-return-2: exit status")
 1624     # don't restore from ebp
 1625     81 0/subop/add %esp 8/imm32
 1626     # . epilogue
 1627     5d/pop-to-ebp
 1628     c3/return
 1629 
 1630 test-early-exit-without-return:
 1631     # . prologue
 1632     55/push-ebp
 1633     89/<- %ebp 4/r32/esp
 1634     # setup
 1635     (clear-stream _test-input-stream)
 1636     (clear-stream $_test-input-buffered-file->buffer)
 1637     (clear-stream _test-output-stream)
 1638     (clear-stream $_test-output-buffered-file->buffer)
 1639     (clear-stream _test-error-stream)
 1640     (clear-stream $_test-error-buffered-file->buffer)
 1641     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1642     68/push 0/imm32
 1643     68/push 0/imm32
 1644     89/<- %edx 4/r32/esp
 1645     (tailor-exit-descriptor %edx 0x10)
 1646     #
 1647     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1648     (write _test-input-stream "  break\n")
 1649     (write _test-input-stream "  return 0\n")
 1650     (write _test-input-stream "}\n")
 1651     # convert
 1652     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1653     # registers except esp clobbered at this point
 1654     # restore ed
 1655     89/<- %edx 4/r32/esp
 1656     (flush _test-output-buffered-file)
 1657     (flush _test-error-buffered-file)
 1658 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1664     # check output
 1665     (check-stream-equal _test-output-stream  ""  "F - test-early-exit-without-return: output should be empty")
 1666     (check-next-stream-line-equal _test-error-stream  "fn foo has outputs, so you cannot 'break' out of the outermost block. Use 'return'."  "F - test-early-exit-without-return: error message")
 1667     # check that stop(1) was called
 1668     (check-ints-equal *(edx+4) 2 "F - test-early-exit-without-return: exit status")
 1669     # don't restore from ebp
 1670     81 0/subop/add %esp 8/imm32
 1671     # . epilogue
 1672     5d/pop-to-ebp
 1673     c3/return
 1674 
 1675 test-return-with-too-few-inouts:
 1676     # . prologue
 1677     55/push-ebp
 1678     89/<- %ebp 4/r32/esp
 1679     # setup
 1680     (clear-stream _test-input-stream)
 1681     (clear-stream $_test-input-buffered-file->buffer)
 1682     (clear-stream _test-output-stream)
 1683     (clear-stream $_test-output-buffered-file->buffer)
 1684     (clear-stream _test-error-stream)
 1685     (clear-stream $_test-error-buffered-file->buffer)
 1686     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1687     68/push 0/imm32
 1688     68/push 0/imm32
 1689     89/<- %edx 4/r32/esp
 1690     (tailor-exit-descriptor %edx 0x10)
 1691     #
 1692     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1693     (write _test-input-stream "  return\n")
 1694     (write _test-input-stream "}\n")
 1695     # convert
 1696     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1697     # registers except esp clobbered at this point
 1698     # restore ed
 1699     89/<- %edx 4/r32/esp
 1700     (flush _test-output-buffered-file)
 1701     (flush _test-error-buffered-file)
 1702 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1708     # check output
 1709     (check-stream-equal _test-output-stream  ""  "F - test-return-with-too-few-inouts: output should be empty")
 1710     (check-next-stream-line-equal _test-error-stream  "fn foo: return: too few inouts"  "F - test-return-with-too-few-inouts: error message")
 1711     # check that stop(1) was called
 1712     (check-ints-equal *(edx+4) 2 "F - test-return-with-too-few-inouts: exit status")
 1713     # don't restore from ebp
 1714     81 0/subop/add %esp 8/imm32
 1715     # . epilogue
 1716     5d/pop-to-ebp
 1717     c3/return
 1718 
 1719 test-return-with-too-many-inouts:
 1720     # . prologue
 1721     55/push-ebp
 1722     89/<- %ebp 4/r32/esp
 1723     # setup
 1724     (clear-stream _test-input-stream)
 1725     (clear-stream $_test-input-buffered-file->buffer)
 1726     (clear-stream _test-output-stream)
 1727     (clear-stream $_test-output-buffered-file->buffer)
 1728     (clear-stream _test-error-stream)
 1729     (clear-stream $_test-error-buffered-file->buffer)
 1730     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1731     68/push 0/imm32
 1732     68/push 0/imm32
 1733     89/<- %edx 4/r32/esp
 1734     (tailor-exit-descriptor %edx 0x10)
 1735     #
 1736     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1737     (write _test-input-stream "  return 0, 0\n")
 1738     (write _test-input-stream "}\n")
 1739     # convert
 1740     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1741     # registers except esp clobbered at this point
 1742     # restore ed
 1743     89/<- %edx 4/r32/esp
 1744     (flush _test-output-buffered-file)
 1745     (flush _test-error-buffered-file)
 1746 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1752     # check output
 1753     (check-stream-equal _test-output-stream  ""  "F - test-return-with-too-many-inouts: output should be empty")
 1754     (check-next-stream-line-equal _test-error-stream  "fn foo: return: too many inouts"  "F - test-return-with-too-many-inouts: error message")
 1755     # check that stop(1) was called
 1756     (check-ints-equal *(edx+4) 2 "F - test-return-with-too-many-inouts: exit status")
 1757     # don't restore from ebp
 1758     81 0/subop/add %esp 8/imm32
 1759     # . epilogue
 1760     5d/pop-to-ebp
 1761     c3/return
 1762 
 1763 test-return-unavailable-value:
 1764     # . prologue
 1765     55/push-ebp
 1766     89/<- %ebp 4/r32/esp
 1767     # setup
 1768     (clear-stream _test-input-stream)
 1769     (clear-stream $_test-input-buffered-file->buffer)
 1770     (clear-stream _test-output-stream)
 1771     (clear-stream $_test-output-buffered-file->buffer)
 1772     (clear-stream _test-error-stream)
 1773     (clear-stream $_test-error-buffered-file->buffer)
 1774     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1775     68/push 0/imm32
 1776     68/push 0/imm32
 1777     89/<- %edx 4/r32/esp
 1778     (tailor-exit-descriptor %edx 0x10)
 1779     #
 1780     (write _test-input-stream "fn foo -> _/eax: int, _/ecx: int {\n")
 1781     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 1782     (write _test-input-stream "  var y/ecx: int <- copy 0\n")
 1783     (write _test-input-stream "  return y, x\n")
 1784     (write _test-input-stream "}\n")
 1785     # convert
 1786     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1787     # registers except esp clobbered at this point
 1788     # restore ed
 1789     89/<- %edx 4/r32/esp
 1790     (flush _test-output-buffered-file)
 1791     (flush _test-error-buffered-file)
 1792 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1798     # check output
 1799     (check-stream-equal _test-output-stream  ""  "F - test-return-unavailable-value: output should be empty")
 1800     (check-next-stream-line-equal _test-error-stream  "fn foo: return: 'x' is no longer available"  "F - test-return-unavailable-value: error message")
 1801     # check that stop(1) was called
 1802     (check-ints-equal *(edx+4) 2 "F - test-return-unavailable-value: exit status")
 1803     # don't restore from ebp
 1804     81 0/subop/add %esp 8/imm32
 1805     # . epilogue
 1806     5d/pop-to-ebp
 1807     c3/return
 1808 
 1809 test-return-literal-to-float:
 1810     # . prologue
 1811     55/push-ebp
 1812     89/<- %ebp 4/r32/esp
 1813     # setup
 1814     (clear-stream _test-input-stream)
 1815     (clear-stream $_test-input-buffered-file->buffer)
 1816     (clear-stream _test-output-stream)
 1817     (clear-stream $_test-output-buffered-file->buffer)
 1818     (clear-stream _test-error-stream)
 1819     (clear-stream $_test-error-buffered-file->buffer)
 1820     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1821     68/push 0/imm32
 1822     68/push 0/imm32
 1823     89/<- %edx 4/r32/esp
 1824     (tailor-exit-descriptor %edx 0x10)
 1825     #
 1826     (write _test-input-stream "fn foo -> _/xmm0: float {\n")
 1827     (write _test-input-stream "  return 0\n")
 1828     (write _test-input-stream "}\n")
 1829     # convert
 1830     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1831     # registers except esp clobbered at this point
 1832     # restore ed
 1833     89/<- %edx 4/r32/esp
 1834     (flush _test-output-buffered-file)
 1835     (flush _test-error-buffered-file)
 1836 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1842     # check output
 1843     (check-stream-equal _test-output-stream  ""  "F - test-return-literal-to-float: output should be empty")
 1844     (check-next-stream-line-equal _test-error-stream  "fn foo: return: cannot copy literal '0' to float"  "F - test-return-literal-to-float: error message")
 1845     # check that stop(1) was called
 1846     (check-ints-equal *(edx+4) 2 "F - test-return-literal-to-float: exit status")
 1847     # don't restore from ebp
 1848     81 0/subop/add %esp 8/imm32
 1849     # . epilogue
 1850     5d/pop-to-ebp
 1851     c3/return
 1852 
 1853 test-convert-return-with-duplicate-values:
 1854     # . prologue
 1855     55/push-ebp
 1856     89/<- %ebp 4/r32/esp
 1857     # setup
 1858     (clear-stream _test-input-stream)
 1859     (clear-stream $_test-input-buffered-file->buffer)
 1860     (clear-stream _test-output-stream)
 1861     (clear-stream $_test-output-buffered-file->buffer)
 1862     #
 1863     (write _test-input-stream "fn foo -> _/eax: int, _/ecx: int {\n")
 1864     (write _test-input-stream "  var x/eax: int <- copy 0x34\n")
 1865     (write _test-input-stream "  return x, x\n")
 1866     (write _test-input-stream "}\n")
 1867     # convert
 1868     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1869     (flush _test-output-buffered-file)
 1870 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1876     # check output
 1877     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-return-with-duplicate-values/0")
 1878     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-return-with-duplicate-values/1")
 1879     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-return-with-duplicate-values/2")
 1880     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-return-with-duplicate-values/3")
 1881     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-return-with-duplicate-values/4")
 1882     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-return-with-duplicate-values/5")
 1883     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-return-with-duplicate-values/6")
 1884     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0x34/imm32"  "F - test-convert-return-with-duplicate-values/7")
 1885     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32"  "F - test-convert-return-with-duplicate-values/8")
 1886     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000001/r32"  "F - test-convert-return-with-duplicate-values/9")
 1887     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-return-with-duplicate-values/10")
 1888     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-return-with-duplicate-values/11")
 1889     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-return-with-duplicate-values/12")
 1890     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-return-with-duplicate-values/13")
 1891     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-return-with-duplicate-values/14")
 1892     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-return-with-duplicate-values/15")
 1893     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-return-with-duplicate-values/16")
 1894     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-return-with-duplicate-values/17")
 1895     # . epilogue
 1896     89/<- %esp 5/r32/ebp
 1897     5d/pop-to-ebp
 1898     c3/return
 1899 
 1900 test-convert-return-with-duplicate-values-2:
 1901     # . prologue
 1902     55/push-ebp
 1903     89/<- %ebp 4/r32/esp
 1904     # setup
 1905     (clear-stream _test-input-stream)
 1906     (clear-stream $_test-input-buffered-file->buffer)
 1907     (clear-stream _test-output-stream)
 1908     (clear-stream $_test-output-buffered-file->buffer)
 1909     #
 1910     (write _test-input-stream "fn foo -> _/eax: int, _/ecx: int {\n")
 1911     (write _test-input-stream "  var x/ecx: int <- copy 0x34\n")
 1912     (write _test-input-stream "  return x, x\n")
 1913     (write _test-input-stream "}\n")
 1914     # convert
 1915     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1916     (flush _test-output-buffered-file)
 1917 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1923     # check output
 1924     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-return-with-duplicate-values-2/0")
 1925     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-return-with-duplicate-values-2/1")
 1926     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-return-with-duplicate-values-2/2")
 1927     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-return-with-duplicate-values-2/3")
 1928     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-return-with-duplicate-values-2/4")
 1929     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-return-with-duplicate-values-2/5")
 1930     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-return-with-duplicate-values-2/6")
 1931     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0x34/imm32"  "F - test-convert-return-with-duplicate-values-2/7")
 1932     (check-next-stream-line-equal _test-output-stream "    8b/-> %ecx 0x00000000/r32"  "F - test-convert-return-with-duplicate-values-2/8")
 1933     (check-next-stream-line-equal _test-output-stream "    8b/-> %ecx 0x00000001/r32"  "F - test-convert-return-with-duplicate-values-2/9")
 1934     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-return-with-duplicate-values-2/10")
 1935     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-return-with-duplicate-values-2/11")
 1936     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-return-with-duplicate-values-2/12")
 1937     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-return-with-duplicate-values-2/13")
 1938     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-return-with-duplicate-values-2/14")
 1939     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-return-with-duplicate-values-2/15")
 1940     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-return-with-duplicate-values-2/16")
 1941     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-return-with-duplicate-values-2/17")
 1942     # . epilogue
 1943     89/<- %esp 5/r32/ebp
 1944     5d/pop-to-ebp
 1945     c3/return
 1946 
 1947 test-stmt-with-unknown-var:
 1948     # . prologue
 1949     55/push-ebp
 1950     89/<- %ebp 4/r32/esp
 1951     # setup
 1952     (clear-stream _test-input-stream)
 1953     (clear-stream $_test-input-buffered-file->buffer)
 1954     (clear-stream _test-output-stream)
 1955     (clear-stream $_test-output-buffered-file->buffer)
 1956     (clear-stream _test-error-stream)
 1957     (clear-stream $_test-error-buffered-file->buffer)
 1958     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1959     68/push 0/imm32
 1960     68/push 0/imm32
 1961     89/<- %edx 4/r32/esp
 1962     (tailor-exit-descriptor %edx 0x10)
 1963     #
 1964     (write _test-input-stream "fn foo {\n")
 1965     (write _test-input-stream "  x <- copy 0x34\n")
 1966     (write _test-input-stream "}\n")
 1967     # convert
 1968     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1969     # registers except esp clobbered at this point
 1970     # restore ed
 1971     89/<- %edx 4/r32/esp
 1972     (flush _test-output-buffered-file)
 1973     (flush _test-error-buffered-file)
 1974 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1980     # check output
 1981     (check-stream-equal _test-output-stream  ""  "F - test-stmt-with-unknown-var: output should be empty")
 1982     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-stmt-with-unknown-var: error message")
 1983     # check that stop(1) was called
 1984     (check-ints-equal *(edx+4) 2 "F - test-stmt-with-unknown-var: exit status")
 1985     # don't restore from ebp
 1986     81 0/subop/add %esp 8/imm32
 1987     # . epilogue
 1988     5d/pop-to-ebp
 1989     c3/return
 1990 
 1991 test-stmt-with-invalid-identifier:
 1992     # . prologue
 1993     55/push-ebp
 1994     89/<- %ebp 4/r32/esp
 1995     # setup
 1996     (clear-stream _test-input-stream)
 1997     (clear-stream $_test-input-buffered-file->buffer)
 1998     (clear-stream _test-output-stream)
 1999     (clear-stream $_test-output-buffered-file->buffer)
 2000     (clear-stream _test-error-stream)
 2001     (clear-stream $_test-error-buffered-file->buffer)
 2002     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2003     68/push 0/imm32
 2004     68/push 0/imm32
 2005     89/<- %edx 4/r32/esp
 2006     (tailor-exit-descriptor %edx 0x10)
 2007     #
 2008     (write _test-input-stream "fn foo {\n")
 2009     (write _test-input-stream "  1 <- copy 0x34\n")
 2010     (write _test-input-stream "}\n")
 2011     # convert
 2012     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2013     # registers except esp clobbered at this point
 2014     # restore ed
 2015     89/<- %edx 4/r32/esp
 2016     (flush _test-output-buffered-file)
 2017     (flush _test-error-buffered-file)
 2018 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2024     # check output
 2025     (check-stream-equal _test-output-stream  ""  "F - test-stmt-with-invalid-identifier: output should be empty")
 2026     (check-next-stream-line-equal _test-error-stream  "fn foo: invalid identifier '1'"  "F - test-stmt-with-invalid-identifier: error message")
 2027     # check that stop(1) was called
 2028     (check-ints-equal *(edx+4) 2 "F - test-stmt-with-invalid-identifier: exit status")
 2029     # don't restore from ebp
 2030     81 0/subop/add %esp 8/imm32
 2031     # . epilogue
 2032     5d/pop-to-ebp
 2033     c3/return
 2034 
 2035 test-stmt-with-deref-var:
 2036     # . prologue
 2037     55/push-ebp
 2038     89/<- %ebp 4/r32/esp
 2039     # setup
 2040     (clear-stream _test-input-stream)
 2041     (clear-stream $_test-input-buffered-file->buffer)
 2042     (clear-stream _test-output-stream)
 2043     (clear-stream $_test-output-buffered-file->buffer)
 2044     (clear-stream _test-error-stream)
 2045     (clear-stream $_test-error-buffered-file->buffer)
 2046     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2047     68/push 0/imm32
 2048     68/push 0/imm32
 2049     89/<- %edx 4/r32/esp
 2050     (tailor-exit-descriptor %edx 0x10)
 2051     #
 2052     (write _test-input-stream "fn foo {\n")
 2053     (write _test-input-stream "  *x <- copy 0x34\n")
 2054     (write _test-input-stream "}\n")
 2055     # convert
 2056     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2057     # registers except esp clobbered at this point
 2058     # restore ed
 2059     89/<- %edx 4/r32/esp
 2060     (flush _test-output-buffered-file)
 2061     (flush _test-error-buffered-file)
 2062 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2068     # check output
 2069     (check-stream-equal _test-output-stream  ""  "F - test-stmt-with-deref-var: output should be empty")
 2070     (check-next-stream-line-equal _test-error-stream  "fn foo: output '*x' should write to a register, and therefore cannot be dereferenced"  "F - test-stmt-with-deref-var: error message")
 2071     # check that stop(1) was called
 2072     (check-ints-equal *(edx+4) 2 "F - test-stmt-with-deref-var: exit status")
 2073     # don't restore from ebp
 2074     81 0/subop/add %esp 8/imm32
 2075     # . epilogue
 2076     5d/pop-to-ebp
 2077     c3/return
 2078 
 2079 test-convert-function-with-literal-arg:
 2080     # . prologue
 2081     55/push-ebp
 2082     89/<- %ebp 4/r32/esp
 2083     # setup
 2084     (clear-stream _test-input-stream)
 2085     (clear-stream $_test-input-buffered-file->buffer)
 2086     (clear-stream _test-output-stream)
 2087     (clear-stream $_test-output-buffered-file->buffer)
 2088     #
 2089     (write _test-input-stream "fn foo a: int, b: int -> _/eax: int {\n")
 2090     (write _test-input-stream "  var result/eax: int <- copy a\n")
 2091     (write _test-input-stream "  result <- add 1\n")
 2092     (write _test-input-stream "  return result\n")
 2093     (write _test-input-stream "}\n")
 2094     # convert
 2095     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2096     (flush _test-output-buffered-file)
 2097 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2103     # check output
 2104     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-literal-arg/0")
 2105     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-literal-arg/1")
 2106     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-literal-arg/2")
 2107     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-literal-arg/3")
 2108     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-literal-arg/4")
 2109     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-literal-arg/5")
 2110     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-literal-arg/6")
 2111     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-with-literal-arg/7")
 2112     (check-next-stream-line-equal _test-output-stream "    05/add-to-eax 1/imm32"  "F - test-convert-function-with-literal-arg/8")
 2113     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-literal-arg/9")
 2114     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-literal-arg/10")
 2115     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-literal-arg/11")
 2116     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-literal-arg/12")
 2117     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-literal-arg/13")
 2118     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-literal-arg/14")
 2119     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-literal-arg/15")
 2120     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-literal-arg/16")
 2121     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-literal-arg/17")
 2122     # . epilogue
 2123     89/<- %esp 5/r32/ebp
 2124     5d/pop-to-ebp
 2125     c3/return
 2126 
 2127 test-convert-function-with-literal-arg-2:
 2128     # . prologue
 2129     55/push-ebp
 2130     89/<- %ebp 4/r32/esp
 2131     # setup
 2132     (clear-stream _test-input-stream)
 2133     (clear-stream $_test-input-buffered-file->buffer)
 2134     (clear-stream _test-output-stream)
 2135     (clear-stream $_test-output-buffered-file->buffer)
 2136     #
 2137     (write _test-input-stream "fn foo a: int, b: int -> _/ebx: int {\n")
 2138     (write _test-input-stream "  var result/ebx: int <- copy a\n")
 2139     (write _test-input-stream "  result <- add 1\n")
 2140     (write _test-input-stream "  return result\n")
 2141     (write _test-input-stream "}\n")
 2142     # convert
 2143     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2144     (flush _test-output-buffered-file)
 2145 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2151     # check output
 2152     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-literal-arg-2/0")
 2153     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-literal-arg-2/1")
 2154     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-literal-arg-2/2")
 2155     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-literal-arg-2/3")
 2156     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-literal-arg-2/4")
 2157     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-literal-arg-2/5")
 2158     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-with-literal-arg-2/6")
 2159     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000003/r32"  "F - test-convert-function-with-literal-arg-2/7")
 2160     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %ebx 1/imm32"  "F - test-convert-function-with-literal-arg-2/8")
 2161     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-with-literal-arg-2/9")
 2162     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-literal-arg-2/10")
 2163     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-literal-arg-2/11")
 2164     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-literal-arg-2/12")
 2165     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-literal-arg-2/13")
 2166     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-literal-arg-2/14")
 2167     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-literal-arg-2/15")
 2168     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-literal-arg-2/16")
 2169     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-literal-arg-2/17")
 2170     # . epilogue
 2171     89/<- %esp 5/r32/ebp
 2172     5d/pop-to-ebp
 2173     c3/return
 2174 
 2175 test-convert-function-call-with-literal-arg:
 2176     # . prologue
 2177     55/push-ebp
 2178     89/<- %ebp 4/r32/esp
 2179     # setup
 2180     (clear-stream _test-input-stream)
 2181     (clear-stream $_test-input-buffered-file->buffer)
 2182     (clear-stream _test-output-stream)
 2183     (clear-stream $_test-output-buffered-file->buffer)
 2184     #
 2185     (write _test-input-stream "fn main -> _/ebx: int {\n")
 2186     (write _test-input-stream "  var result/eax: int <- do-add 3 4\n")
 2187     (write _test-input-stream "  return result\n")
 2188     (write _test-input-stream "}\n")
 2189     (write _test-input-stream "fn do-add a: int, b: int -> _/eax: int {\n")
 2190     (write _test-input-stream "  var result/eax: int <- copy a\n")
 2191     (write _test-input-stream "  result <- add b\n")
 2192     (write _test-input-stream "  return result\n")
 2193     (write _test-input-stream "}\n")
 2194     # convert
 2195     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2196     (flush _test-output-buffered-file)
 2197 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2203     # check output
 2204     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call-with-literal-arg/0")
 2205     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-literal-arg/1")
 2206     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-literal-arg/2")
 2207     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-literal-arg/3")
 2208     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-literal-arg/4")
 2209     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call-with-literal-arg/5")
 2210     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/6")
 2211     (check-next-stream-line-equal _test-output-stream "    (do-add 3 4)"        "F - test-convert-function-call-with-literal-arg/7")
 2212     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 2213     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-with-local-var-in-reg/9")
 2214     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 2215     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-literal-arg/11")
 2216     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call-with-literal-arg/12")
 2217     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-literal-arg/13")
 2218     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-literal-arg/14")
 2219     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-literal-arg/15")
 2220     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-literal-arg/16")
 2221     (check-next-stream-line-equal _test-output-stream "do-add:"                 "F - test-convert-function-call-with-literal-arg/17")
 2222     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-literal-arg/18")
 2223     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-literal-arg/19")
 2224     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-literal-arg/20")
 2225     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-literal-arg/21")
 2226     (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:loop:"  "F - test-convert-function-call-with-literal-arg/22")
 2227     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/23")
 2228     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-call-with-literal-arg/24")
 2229     (check-next-stream-line-equal _test-output-stream "    03/add *(ebp+0x0000000c) 0x00000000/r32"  "F - test-convert-function-call-with-literal-arg/25")
 2230     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-call-with-literal-arg/26")
 2231     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
 2232     (check-next-stream-line-equal _test-output-stream "    e9/jump $do-add:0x00000002:break/disp32"  "F - test-convert-function-call-with-literal-arg/28")
 2233     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-literal-arg/29")
 2234     (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:break:"  "F - test-convert-function-call-with-literal-arg/30")
 2235     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-literal-arg/31")
 2236     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-literal-arg/32")
 2237     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-literal-arg/33")
 2238     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-literal-arg/34")
 2239     # . epilogue
 2240     89/<- %esp 5/r32/ebp
 2241     5d/pop-to-ebp
 2242     c3/return
 2243 
 2244 test-convert-function-call-with-literal-string-arg:
 2245     # . prologue
 2246     55/push-ebp
 2247     89/<- %ebp 4/r32/esp
 2248     # setup
 2249     (clear-stream _test-input-stream)
 2250     (clear-stream $_test-input-buffered-file->buffer)
 2251     (clear-stream _test-output-stream)
 2252     (clear-stream $_test-output-buffered-file->buffer)
 2253     #
 2254     (write _test-input-stream "fn foo {\n")
 2255     (write _test-input-stream "  string-func \"abc\"\n")
 2256     (write _test-input-stream "}\n")
 2257     (write _test-input-stream "sig string-func in: (addr array byte)\n")
 2258     # convert
 2259     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2260     # no errors
 2261     # not bothering checking output
 2262     # . epilogue
 2263     89/<- %esp 5/r32/ebp
 2264     5d/pop-to-ebp
 2265     c3/return
 2266 
 2267 test-convert-function-call-with-literal-string-arg-and-type-parameter-in-signature:
 2268     # . prologue
 2269     55/push-ebp
 2270     89/<- %ebp 4/r32/esp
 2271     # setup
 2272     (clear-stream _test-input-stream)
 2273     (clear-stream $_test-input-buffered-file->buffer)
 2274     (clear-stream _test-output-stream)
 2275     (clear-stream $_test-output-buffered-file->buffer)
 2276     #
 2277     (write _test-input-stream "fn foo {\n")
 2278     (write _test-input-stream "  string-func \"abc\"\n")
 2279     (write _test-input-stream "}\n")
 2280     (write _test-input-stream "sig string-func in: (addr array _)\n")
 2281     # convert
 2282     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2283     # no errors
 2284     # not bothering checking output
 2285     # . epilogue
 2286     89/<- %esp 5/r32/ebp
 2287     5d/pop-to-ebp
 2288     c3/return
 2289 
 2290 test-convert-function-call-with-null-addr:
 2291     # . prologue
 2292     55/push-ebp
 2293     89/<- %ebp 4/r32/esp
 2294     # setup
 2295     (clear-stream _test-input-stream)
 2296     (clear-stream $_test-input-buffered-file->buffer)
 2297     (clear-stream _test-output-stream)
 2298     (clear-stream $_test-output-buffered-file->buffer)
 2299     #
 2300     (write _test-input-stream "fn foo {\n")
 2301     (write _test-input-stream "  bar 0\n")
 2302     (write _test-input-stream "}\n")
 2303     (write _test-input-stream "sig bar in: (addr int)\n")
 2304     # convert
 2305     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2306     # no errors
 2307     # not bothering checking output
 2308     # . epilogue
 2309     89/<- %esp 5/r32/ebp
 2310     5d/pop-to-ebp
 2311     c3/return
 2312 
 2313 test-convert-function-call-with-signature:
 2314     # . prologue
 2315     55/push-ebp
 2316     89/<- %ebp 4/r32/esp
 2317     # setup
 2318     (clear-stream _test-input-stream)
 2319     (clear-stream $_test-input-buffered-file->buffer)
 2320     (clear-stream _test-output-stream)
 2321     (clear-stream $_test-output-buffered-file->buffer)
 2322     #
 2323     (write _test-input-stream "fn main -> _/ebx: int {\n")
 2324     (write _test-input-stream "  var result/eax: int <- do-add 3 4\n")
 2325     (write _test-input-stream "  return result\n")
 2326     (write _test-input-stream "}\n")
 2327     (write _test-input-stream "sig do-add a: int, b: int -> _/eax: int\n")
 2328     # convert
 2329     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2330     (flush _test-output-buffered-file)
 2331 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2337     # check output
 2338     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call-with-signature/0")
 2339     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-signature/1")
 2340     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-signature/2")
 2341     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-signature/3")
 2342     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-signature/4")
 2343     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call-with-signature/5")
 2344     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/6")
 2345     (check-next-stream-line-equal _test-output-stream "    (do-add 3 4)"        "F - test-convert-function-call-with-signature/6")
 2346     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 2347     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-with-local-var-in-reg/9")
 2348     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 2349     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-signature/7")
 2350     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call-with-signature/8")
 2351     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-signature/9")
 2352     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-signature/10")
 2353     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-signature/11")
 2354     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-signature/12")
 2355     # . epilogue
 2356     89/<- %esp 5/r32/ebp
 2357     5d/pop-to-ebp
 2358     c3/return
 2359 
 2360 test-convert-function-with-local-var-in-mem:
 2361     # . prologue
 2362     55/push-ebp
 2363     89/<- %ebp 4/r32/esp
 2364     # setup
 2365     (clear-stream _test-input-stream)
 2366     (clear-stream $_test-input-buffered-file->buffer)
 2367     (clear-stream _test-output-stream)
 2368     (clear-stream $_test-output-buffered-file->buffer)
 2369     #
 2370     (write _test-input-stream "fn foo {\n")
 2371     (write _test-input-stream "  var x: int\n")
 2372     (write _test-input-stream "  increment x\n")
 2373     (write _test-input-stream "}\n")
 2374     # convert
 2375     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2376     (flush _test-output-buffered-file)
 2377 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2383     # check output
 2384     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-mem/0")
 2385     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-mem/1")
 2386     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-mem/2")
 2387     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-mem/3")
 2388     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-mem/4")
 2389     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-mem/5")
 2390     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-in-mem/6")
 2391     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-local-var-in-mem/7")
 2392     (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")
 2393     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-mem/9")
 2394     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-mem/10")
 2395     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-mem/11")
 2396     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-mem/12")
 2397     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-mem/13")
 2398     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-mem/14")
 2399     # . epilogue
 2400     89/<- %esp 5/r32/ebp
 2401     5d/pop-to-ebp
 2402     c3/return
 2403 
 2404 test-convert-invalid-literal:
 2405     # . prologue
 2406     55/push-ebp
 2407     89/<- %ebp 4/r32/esp
 2408     # setup
 2409     (clear-stream _test-input-stream)
 2410     (clear-stream $_test-input-buffered-file->buffer)
 2411     (clear-stream _test-output-stream)
 2412     (clear-stream $_test-output-buffered-file->buffer)
 2413     (clear-stream _test-error-stream)
 2414     (clear-stream $_test-error-buffered-file->buffer)
 2415     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2416     68/push 0/imm32
 2417     68/push 0/imm32
 2418     89/<- %edx 4/r32/esp
 2419     (tailor-exit-descriptor %edx 0x10)
 2420     #
 2421     (write _test-input-stream "fn foo {\n")
 2422     (write _test-input-stream "  increment 1n\n")
 2423     (write _test-input-stream "}\n")
 2424     # convert
 2425     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2426     # registers except esp clobbered at this point
 2427     # restore ed
 2428     89/<- %edx 4/r32/esp
 2429     (flush _test-output-buffered-file)
 2430     (flush _test-error-buffered-file)
 2431 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2437     # check output
 2438     (check-stream-equal _test-output-stream  ""  "F - test-convert-invalid-literal: output should be empty")
 2439     (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")
 2440     # check that stop(1) was called
 2441     (check-ints-equal *(edx+4) 2 "F - test-convert-invalid-literal: exit status")
 2442     # don't restore from ebp
 2443     81 0/subop/add %esp 8/imm32
 2444     # . epilogue
 2445     5d/pop-to-ebp
 2446     c3/return
 2447 
 2448 test-convert-valid-literal-with-metadata:
 2449     # . prologue
 2450     55/push-ebp
 2451     89/<- %ebp 4/r32/esp
 2452     # setup
 2453     (clear-stream _test-input-stream)
 2454     (clear-stream $_test-input-buffered-file->buffer)
 2455     (clear-stream _test-output-stream)
 2456     (clear-stream $_test-output-buffered-file->buffer)
 2457     #
 2458     (write _test-input-stream "fn foo {\n")
 2459     (write _test-input-stream "  var x/eax: int <- copy 1/abc\n")
 2460     (write _test-input-stream "}\n")
 2461     # convert
 2462     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2463     (flush _test-output-buffered-file)
 2464 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2470     # no errors
 2471     # . epilogue
 2472     89/<- %esp 5/r32/ebp
 2473     5d/pop-to-ebp
 2474     c3/return
 2475 
 2476 test-local-var-in-mem-has-no-initializer:
 2477     # . prologue
 2478     55/push-ebp
 2479     89/<- %ebp 4/r32/esp
 2480     # setup
 2481     (clear-stream _test-input-stream)
 2482     (clear-stream $_test-input-buffered-file->buffer)
 2483     (clear-stream _test-output-stream)
 2484     (clear-stream $_test-output-buffered-file->buffer)
 2485     (clear-stream _test-error-stream)
 2486     (clear-stream $_test-error-buffered-file->buffer)
 2487     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2488     68/push 0/imm32
 2489     68/push 0/imm32
 2490     89/<- %edx 4/r32/esp
 2491     (tailor-exit-descriptor %edx 0x10)
 2492     #
 2493     (write _test-input-stream "fn foo {\n")
 2494     (write _test-input-stream "  var x: int <- copy 0\n")
 2495     (write _test-input-stream "  increment x\n")
 2496     (write _test-input-stream "}\n")
 2497     # convert
 2498     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2499     # registers except esp clobbered at this point
 2500     # restore ed
 2501     89/<- %edx 4/r32/esp
 2502     (flush _test-output-buffered-file)
 2503     (flush _test-error-buffered-file)
 2504 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2510     # check output
 2511     (check-stream-equal _test-output-stream  ""  "F - test-var-in-mem-has-no-initializer: output should be empty")
 2512     (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")
 2513     # check that stop(1) was called
 2514     (check-ints-equal *(edx+4) 2 "F - test-var-in-mem-has-no-initializer: exit status")
 2515     # don't restore from ebp
 2516     81 0/subop/add %esp 8/imm32
 2517     # . epilogue
 2518     5d/pop-to-ebp
 2519     c3/return
 2520 
 2521 test-convert-function-with-local-var-with-compound-type-in-mem:
 2522     # . prologue
 2523     55/push-ebp
 2524     89/<- %ebp 4/r32/esp
 2525     # setup
 2526     (clear-stream _test-input-stream)
 2527     (clear-stream $_test-input-buffered-file->buffer)
 2528     (clear-stream _test-output-stream)
 2529     (clear-stream $_test-output-buffered-file->buffer)
 2530     #
 2531     (write _test-input-stream "fn foo {\n")
 2532     (write _test-input-stream "  var x: (addr int)\n")
 2533     (write _test-input-stream "  copy-to x, 0\n")
 2534     (write _test-input-stream "}\n")
 2535     # convert
 2536     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2537     (flush _test-output-buffered-file)
 2538 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2544     # check output
 2545     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-with-compound-type-in-mem/0")
 2546     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-with-compound-type-in-mem/1")
 2547     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-with-compound-type-in-mem/2")
 2548     (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")
 2549     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-compound-type-in-mem/4")
 2550     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-with-compound-type-in-mem/5")
 2551     (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")
 2552     (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")
 2553     (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")
 2554     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-compound-type-in-mem/9")
 2555     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-with-compound-type-in-mem/10")
 2556     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-with-compound-type-in-mem/11")
 2557     (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")
 2558     (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")
 2559     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-with-compound-type-in-mem/14")
 2560     # . epilogue
 2561     89/<- %esp 5/r32/ebp
 2562     5d/pop-to-ebp
 2563     c3/return
 2564 
 2565 test-convert-function-with-local-var-in-reg:
 2566     # . prologue
 2567     55/push-ebp
 2568     89/<- %ebp 4/r32/esp
 2569     # setup
 2570     (clear-stream _test-input-stream)
 2571     (clear-stream $_test-input-buffered-file->buffer)
 2572     (clear-stream _test-output-stream)
 2573     (clear-stream $_test-output-buffered-file->buffer)
 2574     #
 2575     (write _test-input-stream "fn foo {\n")
 2576     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2577     (write _test-input-stream "  x <- increment\n")
 2578     (write _test-input-stream "}\n")
 2579     # convert
 2580     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2581     (flush _test-output-buffered-file)
 2582 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2588     # check output
 2589     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-reg/0")
 2590     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-reg/1")
 2591     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-reg/2")
 2592     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-reg/3")
 2593     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-reg/4")
 2594     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-reg/5")
 2595     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-in-reg/6")
 2596     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-convert-function-with-local-var-in-reg/7")
 2597     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-convert-function-with-local-var-in-reg/8")
 2598     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-in-reg/9")
 2599     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-reg/10")
 2600     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-reg/11")
 2601     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-reg/12")
 2602     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-reg/13")
 2603     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-reg/14")
 2604     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-reg/15")
 2605     # . epilogue
 2606     89/<- %esp 5/r32/ebp
 2607     5d/pop-to-ebp
 2608     c3/return
 2609 
 2610 test-convert-function-with-local-var-in-same-reg:
 2611     # . prologue
 2612     55/push-ebp
 2613     89/<- %ebp 4/r32/esp
 2614     # setup
 2615     (clear-stream _test-input-stream)
 2616     (clear-stream $_test-input-buffered-file->buffer)
 2617     (clear-stream _test-output-stream)
 2618     (clear-stream $_test-output-buffered-file->buffer)
 2619     #
 2620     (write _test-input-stream "fn foo {\n")
 2621     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2622     (write _test-input-stream "  var y/ecx: int <- copy x\n")
 2623     (write _test-input-stream "}\n")
 2624     # convert
 2625     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2626     (flush _test-output-buffered-file)
 2627 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2633     # check output
 2634     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-same-reg/0")
 2635     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-same-reg/1")
 2636     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-same-reg/2")
 2637     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-same-reg/3")
 2638     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-same-reg/4")
 2639     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-same-reg/5")
 2640     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-in-same-reg/6")
 2641     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-convert-function-with-local-var-in-same-reg/7")
 2642     # optimization: skip the second copy
 2643     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-in-same-reg/8")
 2644     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-same-reg/9")
 2645     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-same-reg/10")
 2646     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-same-reg/11")
 2647     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-same-reg/12")
 2648     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-same-reg/13")
 2649     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-same-reg/14")
 2650     # . epilogue
 2651     89/<- %esp 5/r32/ebp
 2652     5d/pop-to-ebp
 2653     c3/return
 2654 
 2655 test-convert-function-with-local-var-in-same-reg-dereferenced:
 2656     # . prologue
 2657     55/push-ebp
 2658     89/<- %ebp 4/r32/esp
 2659     # setup
 2660     (clear-stream _test-input-stream)
 2661     (clear-stream $_test-input-buffered-file->buffer)
 2662     (clear-stream _test-output-stream)
 2663     (clear-stream $_test-output-buffered-file->buffer)
 2664     #
 2665     (write _test-input-stream "fn foo {\n")
 2666     (write _test-input-stream "  var x/ecx: (addr int) <- copy 0\n")
 2667     (write _test-input-stream "  var y/ecx: int <- copy *x\n")
 2668     (write _test-input-stream "}\n")
 2669     # convert
 2670     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2671     (flush _test-output-buffered-file)
 2672 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2678     # check output
 2679     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-same-reg-dereferenced/0")
 2680     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-same-reg-dereferenced/1")
 2681     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-same-reg-dereferenced/2")
 2682     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-same-reg-dereferenced/3")
 2683     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-same-reg-dereferenced/4")
 2684     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-same-reg-dereferenced/5")
 2685     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-in-same-reg-dereferenced/6")
 2686     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-local-var-in-same-reg-dereferenced/7")
 2687     (check-next-stream-line-equal _test-output-stream "    8b/-> *ecx 0x00000001/r32"  "F - test-convert-function-with-local-var-in-same-reg-dereferenced/8")  # don't optimize this away
 2688     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-in-same-reg-dereferenced/9")
 2689     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-same-reg-dereferenced/10")
 2690     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-same-reg-dereferenced/11")
 2691     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-same-reg-dereferenced/12")
 2692     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-same-reg-dereferenced/13")
 2693     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-same-reg-dereferenced/14")
 2694     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-same-reg-dereferenced/15")
 2695     # . epilogue
 2696     89/<- %esp 5/r32/ebp
 2697     5d/pop-to-ebp
 2698     c3/return
 2699 
 2700 test-float-var-in-wrong-register:
 2701     # . prologue
 2702     55/push-ebp
 2703     89/<- %ebp 4/r32/esp
 2704     # setup
 2705     (clear-stream _test-input-stream)
 2706     (clear-stream $_test-input-buffered-file->buffer)
 2707     (clear-stream _test-output-stream)
 2708     (clear-stream $_test-output-buffered-file->buffer)
 2709     (clear-stream _test-error-stream)
 2710     (clear-stream $_test-error-buffered-file->buffer)
 2711     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2712     68/push 0/imm32
 2713     68/push 0/imm32
 2714     89/<- %edx 4/r32/esp
 2715     (tailor-exit-descriptor %edx 0x10)
 2716     #
 2717     (write _test-input-stream "fn foo {\n")
 2718     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 2719     (write _test-input-stream "  var y/eax: float <- convert x\n")
 2720     (write _test-input-stream "}\n")
 2721     # convert
 2722     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2723     # registers except esp clobbered at this point
 2724     # restore ed
 2725     89/<- %edx 4/r32/esp
 2726     (flush _test-output-buffered-file)
 2727     (flush _test-error-buffered-file)
 2728 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2734     # check output
 2735     (check-stream-equal _test-output-stream  ""  "F - test-float-var-in-wrong-register: output should be empty")
 2736     (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")
 2737     # check that stop(1) was called
 2738     (check-ints-equal *(edx+4) 2 "F - test-float-var-in-wrong-register: exit status")
 2739     # don't restore from ebp
 2740     81 0/subop/add %esp 8/imm32
 2741     # . epilogue
 2742     5d/pop-to-ebp
 2743     c3/return
 2744 
 2745 test-non-float-var-in-wrong-register:
 2746     # . prologue
 2747     55/push-ebp
 2748     89/<- %ebp 4/r32/esp
 2749     # setup
 2750     (clear-stream _test-input-stream)
 2751     (clear-stream $_test-input-buffered-file->buffer)
 2752     (clear-stream _test-output-stream)
 2753     (clear-stream $_test-output-buffered-file->buffer)
 2754     (clear-stream _test-error-stream)
 2755     (clear-stream $_test-error-buffered-file->buffer)
 2756     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2757     68/push 0/imm32
 2758     68/push 0/imm32
 2759     89/<- %edx 4/r32/esp
 2760     (tailor-exit-descriptor %edx 0x10)
 2761     #
 2762     (write _test-input-stream "fn foo {\n")
 2763     (write _test-input-stream "  var x/xmm5: int <- copy 0\n")
 2764     (write _test-input-stream "}\n")
 2765     # convert
 2766     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2767     # registers except esp clobbered at this point
 2768     # restore ed
 2769     89/<- %edx 4/r32/esp
 2770     (flush _test-output-buffered-file)
 2771     (flush _test-error-buffered-file)
 2772 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2778     # check output
 2779     (check-stream-equal _test-output-stream  ""  "F - test-non-float-var-in-wrong-register: output should be empty")
 2780     (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")
 2781     # check that stop(1) was called
 2782     (check-ints-equal *(edx+4) 2 "F - test-non-float-var-in-wrong-register: exit status")
 2783     # don't restore from ebp
 2784     81 0/subop/add %esp 8/imm32
 2785     # . epilogue
 2786     5d/pop-to-ebp
 2787     c3/return
 2788 
 2789 test-convert-function-with-allocate:
 2790     # . prologue
 2791     55/push-ebp
 2792     89/<- %ebp 4/r32/esp
 2793     # setup
 2794     (clear-stream _test-input-stream)
 2795     (clear-stream $_test-input-buffered-file->buffer)
 2796     (clear-stream _test-output-stream)
 2797     (clear-stream $_test-output-buffered-file->buffer)
 2798     #
 2799     (write _test-input-stream "fn foo {\n")
 2800     (write _test-input-stream "  var x/ecx: (addr handle int) <- copy 0\n")
 2801     (write _test-input-stream "  allocate x\n")
 2802     (write _test-input-stream "}\n")
 2803     # convert
 2804     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2805     (flush _test-output-buffered-file)
 2806 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2812     # check output
 2813     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-allocate/0")
 2814     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-allocate/1")
 2815     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-allocate/2")
 2816     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-allocate/3")
 2817     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-allocate/4")
 2818     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-allocate/5")
 2819     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-allocate/6")
 2820     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-allocate/7")
 2821     (check-next-stream-line-equal _test-output-stream "    (allocate Heap 0x00000004 %ecx)"  "F - test-convert-function-with-allocate/8")  # 4 = size-of(int)
 2822     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-allocate/9")
 2823     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-allocate/10")
 2824     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-allocate/11")
 2825     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-allocate/12")
 2826     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-allocate/13")
 2827     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-allocate/14")
 2828     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-allocate/15")
 2829     # . epilogue
 2830     89/<- %esp 5/r32/ebp
 2831     5d/pop-to-ebp
 2832     c3/return
 2833 
 2834 test-initializer-in-hex:
 2835     # . prologue
 2836     55/push-ebp
 2837     89/<- %ebp 4/r32/esp
 2838     # setup
 2839     (clear-stream _test-input-stream)
 2840     (clear-stream $_test-input-buffered-file->buffer)
 2841     (clear-stream _test-output-stream)
 2842     (clear-stream $_test-output-buffered-file->buffer)
 2843     (clear-stream _test-error-stream)
 2844     (clear-stream $_test-error-buffered-file->buffer)
 2845     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2846     68/push 0/imm32
 2847     68/push 0/imm32
 2848     89/<- %edx 4/r32/esp
 2849     (tailor-exit-descriptor %edx 0x10)
 2850     #
 2851     (write _test-input-stream "fn foo {\n")
 2852     (write _test-input-stream "  var x/ecx: int <- copy 10\n")
 2853     (write _test-input-stream "}\n")
 2854     # convert
 2855     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2856     # registers except esp clobbered at this point
 2857     # restore ed
 2858     89/<- %edx 4/r32/esp
 2859     (flush _test-output-buffered-file)
 2860     (flush _test-error-buffered-file)
 2861 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2867     # check output
 2868     (check-stream-equal _test-output-stream  ""  "F - test-initializer-in-hex: output should be empty")
 2869     (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")
 2870     # check that stop(1) was called
 2871     (check-ints-equal *(edx+4) 2 "F - test-initializer-in-hex: exit status")
 2872     # don't restore from ebp
 2873     81 0/subop/add %esp 8/imm32
 2874     # . epilogue
 2875     5d/pop-to-ebp
 2876     c3/return
 2877 
 2878 test-convert-function-with-second-local-var-in-same-reg:
 2879     # . prologue
 2880     55/push-ebp
 2881     89/<- %ebp 4/r32/esp
 2882     # setup
 2883     (clear-stream _test-input-stream)
 2884     (clear-stream $_test-input-buffered-file->buffer)
 2885     (clear-stream _test-output-stream)
 2886     (clear-stream $_test-output-buffered-file->buffer)
 2887     #
 2888     (write _test-input-stream "fn foo {\n")
 2889     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2890     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 2891     (write _test-input-stream "  y <- increment\n")
 2892     (write _test-input-stream "}\n")
 2893     # convert
 2894     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2895     (flush _test-output-buffered-file)
 2896 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2902     # check output
 2903     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-second-local-var-in-same-reg/0")
 2904     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-second-local-var-in-same-reg/1")
 2905     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-second-local-var-in-same-reg/2")
 2906     (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")
 2907     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-second-local-var-in-same-reg/4")
 2908     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-second-local-var-in-same-reg/5")
 2909     (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")
 2910     (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")
 2911     (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")
 2912     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-convert-function-with-second-local-var-in-same-reg/9")
 2913     (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")
 2914     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-second-local-var-in-same-reg/11")
 2915     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-second-local-var-in-same-reg/12")
 2916     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-second-local-var-in-same-reg/13")
 2917     (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")
 2918     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-second-local-var-in-same-reg/15")
 2919     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-second-local-var-in-same-reg/16")
 2920     # . epilogue
 2921     89/<- %esp 5/r32/ebp
 2922     5d/pop-to-ebp
 2923     c3/return
 2924 
 2925 test-read-clobbered-reg-var:
 2926     # . prologue
 2927     55/push-ebp
 2928     89/<- %ebp 4/r32/esp
 2929     # setup
 2930     (clear-stream _test-input-stream)
 2931     (clear-stream $_test-input-buffered-file->buffer)
 2932     (clear-stream _test-output-stream)
 2933     (clear-stream $_test-output-buffered-file->buffer)
 2934     (clear-stream _test-error-stream)
 2935     (clear-stream $_test-error-buffered-file->buffer)
 2936     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
 2937     68/push 0/imm32
 2938     68/push 0/imm32
 2939     89/<- %edx 4/r32/esp
 2940     (tailor-exit-descriptor %edx 0x10)
 2941     #
 2942     (write _test-input-stream "fn foo {\n")
 2943     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2944     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 2945     (write _test-input-stream "  x <- increment\n")
 2946     (write _test-input-stream "}\n")
 2947     # convert
 2948     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2949     # registers except esp clobbered at this point
 2950     # restore ed
 2951     89/<- %edx 4/r32/esp
 2952     (flush _test-output-buffered-file)
 2953     (flush _test-error-buffered-file)
 2954 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2960     # check output
 2961     (check-stream-equal _test-output-stream  ""  "F - test-read-clobbered-reg-var: output should be empty")
 2962     (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")
 2963     # check that stop(1) was called
 2964     (check-ints-equal *(edx+4) 2 "F - test-read-clobbered-reg-var: exit status")
 2965     # don't restore from ebp
 2966     81 0/subop/add %esp 8/imm32
 2967     # . epilogue
 2968     5d/pop-to-ebp
 2969     c3/return
 2970 
 2971 test-overlapping-int-fp-registers:
 2972     # . prologue
 2973     55/push-ebp
 2974     89/<- %ebp 4/r32/esp
 2975     # setup
 2976     (clear-stream _test-input-stream)
 2977     (clear-stream $_test-input-buffered-file->buffer)
 2978     (clear-stream _test-output-stream)
 2979     (clear-stream $_test-output-buffered-file->buffer)
 2980     (clear-stream _test-error-stream)
 2981     (clear-stream $_test-error-buffered-file->buffer)
 2982     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
 2983     68/push 0/imm32
 2984     68/push 0/imm32
 2985     89/<- %edx 4/r32/esp
 2986     (tailor-exit-descriptor %edx 0x10)
 2987     #
 2988     (write _test-input-stream "fn foo {\n")
 2989     (write _test-input-stream "  var x/eax: int <- copy 3\n")
 2990     (write _test-input-stream "  var y/xmm0: float <- convert x\n")
 2991     (write _test-input-stream "  x <- increment\n")
 2992     (write _test-input-stream "}\n")
 2993     # convert
 2994     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2995     # registers except esp clobbered at this point
 2996     # restore ed
 2997     89/<- %edx 4/r32/esp
 2998     (flush _test-output-buffered-file)
 2999     (flush _test-error-buffered-file)
 3000 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3006     # no errors
 3007     (check-next-stream-line-equal _test-error-stream  ""  "F - test-overlapping-int-fp-registers: error message")
 3008     # don't bother checking the generated code
 3009     # don't restore from ebp
 3010     81 0/subop/add %esp 8/imm32
 3011     # . epilogue
 3012     5d/pop-to-ebp
 3013     c3/return
 3014 
 3015 test-convert-function-call:
 3016     # . prologue
 3017     55/push-ebp
 3018     89/<- %ebp 4/r32/esp
 3019     # setup
 3020     (clear-stream _test-input-stream)
 3021     (clear-stream $_test-input-buffered-file->buffer)
 3022     (clear-stream _test-output-stream)
 3023     (clear-stream $_test-output-buffered-file->buffer)
 3024     #
 3025     (write _test-input-stream "fn main -> _/ebx: int {\n")
 3026     (write _test-input-stream "  var result/ebx: int <- foo\n")
 3027     (write _test-input-stream "  return result\n")
 3028     (write _test-input-stream "}\n")
 3029     (write _test-input-stream "fn foo -> _/ebx: int {\n")
 3030     (write _test-input-stream "  var result/ebx: int <- copy 3\n")
 3031     (write _test-input-stream "  return result\n")
 3032     (write _test-input-stream "}\n")
 3033     # convert
 3034     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3035     (flush _test-output-buffered-file)
 3036 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3042     # check output
 3043     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call/0")
 3044     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call/1")
 3045     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call/2")
 3046     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call/3")
 3047     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call/4")
 3048     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call/5")
 3049     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-call-with-literal-arg/6")
 3050     (check-next-stream-line-equal _test-output-stream "    (foo)"               "F - test-convert-function-call/6")
 3051     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 3052     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
 3053     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 3054     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call/7")
 3055     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call/8")
 3056     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call/9")
 3057     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call/10")
 3058     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call/11")
 3059     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call/12")
 3060     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call/13")
 3061     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call/14")
 3062     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call/15")
 3063     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call/16")
 3064     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call/17")
 3065     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"  "F - test-convert-function-call/18")
 3066     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-call-with-literal-arg/6")
 3067     (check-next-stream-line-equal _test-output-stream "    bb/copy-to-ebx 3/imm32"  "F - test-convert-function-call/19")
 3068     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 3069     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
 3070     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 3071     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call/20")
 3072     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-call/21")
 3073     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call/22")
 3074     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call/23")
 3075     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call/24")
 3076     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call/25")
 3077     # . epilogue
 3078     89/<- %esp 5/r32/ebp
 3079     5d/pop-to-ebp
 3080     c3/return
 3081 
 3082 test-convert-function-call-with-inout-with-compound-type:
 3083     # . prologue
 3084     55/push-ebp
 3085     89/<- %ebp 4/r32/esp
 3086     # setup
 3087     (clear-stream _test-input-stream)
 3088     (clear-stream $_test-input-buffered-file->buffer)
 3089     (clear-stream _test-output-stream)
 3090     (clear-stream $_test-output-buffered-file->buffer)
 3091     #
 3092     (write _test-input-stream "fn f {\n")
 3093     (write _test-input-stream "  var x: (addr int)\n")
 3094     (write _test-input-stream "  g x\n")
 3095     (write _test-input-stream "}\n")
 3096     (write _test-input-stream "fn g a: (addr int) {\n")
 3097     (write _test-input-stream "}\n")
 3098     # convert
 3099     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3100     (flush _test-output-buffered-file)
 3101 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3107     # check output
 3108     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-inout-with-compound-type/0")
 3109     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-inout-with-compound-type/1")
 3110     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-inout-with-compound-type/2")
 3111     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-inout-with-compound-type/3")
 3112     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-inout-with-compound-type/4")
 3113     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-inout-with-compound-type/5")
 3114     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-inout-with-compound-type/6")
 3115     (check-next-stream-line-equal _test-output-stream "    (g *(ebp+0xfffffffc))"  "F - test-convert-function-call-with-inout-with-compound-type/7")
 3116     (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")
 3117     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-inout-with-compound-type/9")
 3118     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-inout-with-compound-type/10")
 3119     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-inout-with-compound-type/11")
 3120     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-inout-with-compound-type/12")
 3121     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-inout-with-compound-type/13")
 3122     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-inout-with-compound-type/14")
 3123     (check-next-stream-line-equal _test-output-stream "g:"                      "F - test-convert-function-call-with-inout-with-compound-type/15")
 3124     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-inout-with-compound-type/16")
 3125     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-inout-with-compound-type/17")
 3126     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-inout-with-compound-type/18")
 3127     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-inout-with-compound-type/19")
 3128     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-inout-with-compound-type/20")
 3129     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-inout-with-compound-type/21")
 3130     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-inout-with-compound-type/22")
 3131     # . epilogue
 3132     89/<- %esp 5/r32/ebp
 3133     5d/pop-to-ebp
 3134     c3/return
 3135 
 3136 test-convert-function-call-with-inout-with-type-parameter:
 3137     # . prologue
 3138     55/push-ebp
 3139     89/<- %ebp 4/r32/esp
 3140     # setup
 3141     (clear-stream _test-input-stream)
 3142     (clear-stream $_test-input-buffered-file->buffer)
 3143     (clear-stream _test-output-stream)
 3144     (clear-stream $_test-output-buffered-file->buffer)
 3145     (clear-stream _test-error-stream)
 3146     (clear-stream $_test-error-buffered-file->buffer)
 3147     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3148     68/push 0/imm32
 3149     68/push 0/imm32
 3150     89/<- %edx 4/r32/esp
 3151     (tailor-exit-descriptor %edx 0x10)
 3152     #
 3153     (write _test-input-stream "fn f {\n")
 3154     (write _test-input-stream "  var x: (addr int)\n")
 3155     (write _test-input-stream "  g x\n")
 3156     (write _test-input-stream "}\n")
 3157     (write _test-input-stream "fn g a: (addr _) {\n")
 3158     (write _test-input-stream "}\n")
 3159     # convert
 3160     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3161     # registers except esp clobbered at this point
 3162     # restore ed
 3163     89/<- %edx 4/r32/esp
 3164     (flush _test-output-buffered-file)
 3165     (flush _test-error-buffered-file)
 3166 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3172     # no error; types matched
 3173     (check-stream-equal _test-error-stream  ""  "F - test-convert-function-call-with-inout-with-type-parameter: error stream should be empty")
 3174     # don't bother checking the generated code; that's in the test 'test-local-clobbered-by-fn-output' below
 3175     # don't restore from ebp
 3176     81 0/subop/add %esp 8/imm32
 3177     # . epilogue
 3178     5d/pop-to-ebp
 3179     c3/return
 3180 
 3181 test-convert-function-call-with-incorrect-inout-type:
 3182     # . prologue
 3183     55/push-ebp
 3184     89/<- %ebp 4/r32/esp
 3185     # setup
 3186     (clear-stream _test-input-stream)
 3187     (clear-stream $_test-input-buffered-file->buffer)
 3188     (clear-stream _test-output-stream)
 3189     (clear-stream $_test-output-buffered-file->buffer)
 3190     (clear-stream _test-error-stream)
 3191     (clear-stream $_test-error-buffered-file->buffer)
 3192     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3193     68/push 0/imm32
 3194     68/push 0/imm32
 3195     89/<- %edx 4/r32/esp
 3196     (tailor-exit-descriptor %edx 0x10)
 3197     #
 3198     (write _test-input-stream "fn f {\n")
 3199     (write _test-input-stream "  var x: int\n")
 3200     (write _test-input-stream "  g x\n")
 3201     (write _test-input-stream "}\n")
 3202     (write _test-input-stream "fn g a: foo {\n")
 3203     (write _test-input-stream "}\n")
 3204     # convert
 3205     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3206     # registers except esp clobbered at this point
 3207     # restore ed
 3208     89/<- %edx 4/r32/esp
 3209     (flush _test-output-buffered-file)
 3210     (flush _test-error-buffered-file)
 3211 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3217     # check output
 3218     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-inout-type: output should be empty")
 3219     (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")
 3220     # check that stop(1) was called
 3221     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-inout-type: exit status")
 3222     # don't restore from ebp
 3223     81 0/subop/add %esp 8/imm32
 3224     5d/pop-to-ebp
 3225     c3/return
 3226 
 3227 test-convert-function-call-with-inout-with-incorrect-compound-type:
 3228     # . prologue
 3229     55/push-ebp
 3230     89/<- %ebp 4/r32/esp
 3231     # setup
 3232     (clear-stream _test-input-stream)
 3233     (clear-stream $_test-input-buffered-file->buffer)
 3234     (clear-stream _test-output-stream)
 3235     (clear-stream $_test-output-buffered-file->buffer)
 3236     (clear-stream _test-error-stream)
 3237     (clear-stream $_test-error-buffered-file->buffer)
 3238     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3239     68/push 0/imm32
 3240     68/push 0/imm32
 3241     89/<- %edx 4/r32/esp
 3242     (tailor-exit-descriptor %edx 0x10)
 3243     #
 3244     (write _test-input-stream "fn f {\n")
 3245     (write _test-input-stream "  var x: (addr int)\n")
 3246     (write _test-input-stream "  g x\n")
 3247     (write _test-input-stream "}\n")
 3248     (write _test-input-stream "fn g a: (addr bool) {\n")
 3249     (write _test-input-stream "}\n")
 3250     # convert
 3251     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3252     # registers except esp clobbered at this point
 3253     # restore ed
 3254     89/<- %edx 4/r32/esp
 3255     (flush _test-output-buffered-file)
 3256     (flush _test-error-buffered-file)
 3257 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3263     # check output
 3264     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-inout-with-incorrect-compound-type: output should be empty")
 3265     (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")
 3266     # don't restore from ebp
 3267     81 0/subop/add %esp 8/imm32
 3268     # . epilogue
 3269     5d/pop-to-ebp
 3270     c3/return
 3271 
 3272 test-convert-function-call-with-inout-with-multiple-type-parameters:
 3273     # . prologue
 3274     55/push-ebp
 3275     89/<- %ebp 4/r32/esp
 3276     # setup
 3277     (clear-stream _test-input-stream)
 3278     (clear-stream $_test-input-buffered-file->buffer)
 3279     (clear-stream _test-output-stream)
 3280     (clear-stream $_test-output-buffered-file->buffer)
 3281     (clear-stream _test-error-stream)
 3282     (clear-stream $_test-error-buffered-file->buffer)
 3283     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3284     68/push 0/imm32
 3285     68/push 0/imm32
 3286     89/<- %edx 4/r32/esp
 3287     (tailor-exit-descriptor %edx 0x10)
 3288     #
 3289     (write _test-input-stream "fn f {\n")
 3290     (write _test-input-stream "  var x: (addr int)\n")
 3291     (write _test-input-stream "  var y: (addr int)\n")
 3292     (write _test-input-stream "  g x, y\n")
 3293     (write _test-input-stream "}\n")
 3294     (write _test-input-stream "fn g a: (addr _), b: (addr _) {\n")
 3295     (write _test-input-stream "}\n")
 3296     # convert
 3297     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3298     # registers except esp clobbered at this point
 3299     # restore ed
 3300     89/<- %edx 4/r32/esp
 3301     (flush _test-output-buffered-file)
 3302     (flush _test-error-buffered-file)
 3303 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3309     # no errors
 3310     (check-stream-equal _test-error-stream  ""  "F - test-convert-function-call-with-inout-with-multiple-type-parameters: error stream should be empty")
 3311     # don't bother checking the generated code
 3312     # don't restore from ebp
 3313     81 0/subop/add %esp 8/imm32
 3314     # . epilogue
 3315     5d/pop-to-ebp
 3316     c3/return
 3317 
 3318 test-type-parameter-matches-rest-of-type:
 3319     # . prologue
 3320     55/push-ebp
 3321     89/<- %ebp 4/r32/esp
 3322     # setup
 3323     (clear-stream _test-input-stream)
 3324     (clear-stream $_test-input-buffered-file->buffer)
 3325     (clear-stream _test-output-stream)
 3326     (clear-stream $_test-output-buffered-file->buffer)
 3327     (clear-stream _test-error-stream)
 3328     (clear-stream $_test-error-buffered-file->buffer)
 3329     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3330     68/push 0/imm32
 3331     68/push 0/imm32
 3332     89/<- %edx 4/r32/esp
 3333     (tailor-exit-descriptor %edx 0x10)
 3334     #
 3335     (write _test-input-stream "fn f {\n")
 3336     (write _test-input-stream "  var x: (addr array int)\n")
 3337     (write _test-input-stream "  g x\n")
 3338     (write _test-input-stream "}\n")
 3339     (write _test-input-stream "fn g a: (addr _) {\n")
 3340     (write _test-input-stream "}\n")
 3341     # convert
 3342     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3343     # registers except esp clobbered at this point
 3344     # restore ed
 3345     89/<- %edx 4/r32/esp
 3346     (flush _test-output-buffered-file)
 3347     (flush _test-error-buffered-file)
 3348 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3354     # no errors
 3355     (check-stream-equal _test-error-stream  ""  "F - test-type-parameter-matches-rest-of-type: error stream should be empty")
 3356     # don't bother checking the generated code
 3357     # don't restore from ebp
 3358     81 0/subop/add %esp 8/imm32
 3359     # . epilogue
 3360     5d/pop-to-ebp
 3361     c3/return
 3362 
 3363 test-convert-function-call-with-inout-with-incompatible-type-parameters:
 3364     # . prologue
 3365     55/push-ebp
 3366     89/<- %ebp 4/r32/esp
 3367     # setup
 3368     (clear-stream _test-input-stream)
 3369     (clear-stream $_test-input-buffered-file->buffer)
 3370     (clear-stream _test-output-stream)
 3371     (clear-stream $_test-output-buffered-file->buffer)
 3372     (clear-stream _test-error-stream)
 3373     (clear-stream $_test-error-buffered-file->buffer)
 3374     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3375     68/push 0/imm32
 3376     68/push 0/imm32
 3377     89/<- %edx 4/r32/esp
 3378     (tailor-exit-descriptor %edx 0x10)
 3379     #
 3380     (write _test-input-stream "fn f {\n")
 3381     (write _test-input-stream "  var x: (addr int)\n")
 3382     (write _test-input-stream "  var y: (addr boolean)\n")
 3383     (write _test-input-stream "  g x, y\n")
 3384     (write _test-input-stream "}\n")
 3385     (write _test-input-stream "fn g a: (addr _T), b: (addr _T) {\n")
 3386     (write _test-input-stream "}\n")
 3387     # convert
 3388     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3389     # registers except esp clobbered at this point
 3390     # restore ed
 3391     89/<- %edx 4/r32/esp
 3392     (flush _test-output-buffered-file)
 3393     (flush _test-error-buffered-file)
 3394 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3400     # check output
 3401     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-inout-with-incompatible-type-parameters: output should be empty")
 3402     (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")
 3403     # don't restore from ebp
 3404     81 0/subop/add %esp 8/imm32
 3405     # . epilogue
 3406     5d/pop-to-ebp
 3407     c3/return
 3408 
 3409 test-convert-function-call-with-too-few-inouts:
 3410     # . prologue
 3411     55/push-ebp
 3412     89/<- %ebp 4/r32/esp
 3413     # setup
 3414     (clear-stream _test-input-stream)
 3415     (clear-stream $_test-input-buffered-file->buffer)
 3416     (clear-stream _test-output-stream)
 3417     (clear-stream $_test-output-buffered-file->buffer)
 3418     (clear-stream _test-error-stream)
 3419     (clear-stream $_test-error-buffered-file->buffer)
 3420     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3421     68/push 0/imm32
 3422     68/push 0/imm32
 3423     89/<- %edx 4/r32/esp
 3424     (tailor-exit-descriptor %edx 0x10)
 3425     #
 3426     (write _test-input-stream "fn f {\n")
 3427     (write _test-input-stream "  g\n")
 3428     (write _test-input-stream "}\n")
 3429     (write _test-input-stream "fn g a: int {\n")
 3430     (write _test-input-stream "}\n")
 3431     # convert
 3432     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3433     # registers except esp clobbered at this point
 3434     # restore ed
 3435     89/<- %edx 4/r32/esp
 3436     (flush _test-output-buffered-file)
 3437     (flush _test-error-buffered-file)
 3438 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3444     # check output
 3445     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-few-inouts: output should be empty")
 3446     (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")
 3447     # check that stop(1) was called
 3448     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-few-inouts: exit status")
 3449     # don't restore from ebp
 3450     81 0/subop/add %esp 8/imm32
 3451     5d/pop-to-ebp
 3452     c3/return
 3453 
 3454 test-convert-function-call-with-too-many-inouts:
 3455     # . prologue
 3456     55/push-ebp
 3457     89/<- %ebp 4/r32/esp
 3458     # setup
 3459     (clear-stream _test-input-stream)
 3460     (clear-stream $_test-input-buffered-file->buffer)
 3461     (clear-stream _test-output-stream)
 3462     (clear-stream $_test-output-buffered-file->buffer)
 3463     (clear-stream _test-error-stream)
 3464     (clear-stream $_test-error-buffered-file->buffer)
 3465     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3466     68/push 0/imm32
 3467     68/push 0/imm32
 3468     89/<- %edx 4/r32/esp
 3469     (tailor-exit-descriptor %edx 0x10)
 3470     #
 3471     (write _test-input-stream "fn f {\n")
 3472     (write _test-input-stream "  var x: int\n")
 3473     (write _test-input-stream "  g x\n")
 3474     (write _test-input-stream "}\n")
 3475     (write _test-input-stream "fn g {\n")
 3476     (write _test-input-stream "}\n")
 3477     # convert
 3478     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3479     # registers except esp clobbered at this point
 3480     # restore ed
 3481     89/<- %edx 4/r32/esp
 3482     (flush _test-output-buffered-file)
 3483     (flush _test-error-buffered-file)
 3484 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3490     # check output
 3491     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-many-inouts: output should be empty")
 3492     (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")
 3493     # check that stop(1) was called
 3494     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-many-inouts: exit status")
 3495     # don't restore from ebp
 3496     81 0/subop/add %esp 8/imm32
 3497     5d/pop-to-ebp
 3498     c3/return
 3499 
 3500 test-convert-function-call-with-incorrect-output-type:
 3501     # . prologue
 3502     55/push-ebp
 3503     89/<- %ebp 4/r32/esp
 3504     # setup
 3505     (clear-stream _test-input-stream)
 3506     (clear-stream $_test-input-buffered-file->buffer)
 3507     (clear-stream _test-output-stream)
 3508     (clear-stream $_test-output-buffered-file->buffer)
 3509     (clear-stream _test-error-stream)
 3510     (clear-stream $_test-error-buffered-file->buffer)
 3511     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3512     68/push 0/imm32
 3513     68/push 0/imm32
 3514     89/<- %edx 4/r32/esp
 3515     (tailor-exit-descriptor %edx 0x10)
 3516     #
 3517     (write _test-input-stream "fn f {\n")
 3518     (write _test-input-stream "  var x/eax: int <- g\n")
 3519     (write _test-input-stream "}\n")
 3520     (write _test-input-stream "fn g -> _/eax: foo {\n")
 3521     (write _test-input-stream "}\n")
 3522     # convert
 3523     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3524     # registers except esp clobbered at this point
 3525     # restore ed
 3526     89/<- %edx 4/r32/esp
 3527     (flush _test-output-buffered-file)
 3528     (flush _test-error-buffered-file)
 3529 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3535     # check output
 3536     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-output-type: output should be empty")
 3537     (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")
 3538     # check that stop(1) was called
 3539     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-output-type: exit status")
 3540     # don't restore from ebp
 3541     81 0/subop/add %esp 8/imm32
 3542     5d/pop-to-ebp
 3543     c3/return
 3544 
 3545 test-convert-function-call-with-too-few-outputs:
 3546     # . prologue
 3547     55/push-ebp
 3548     89/<- %ebp 4/r32/esp
 3549     # setup
 3550     (clear-stream _test-input-stream)
 3551     (clear-stream $_test-input-buffered-file->buffer)
 3552     (clear-stream _test-output-stream)
 3553     (clear-stream $_test-output-buffered-file->buffer)
 3554     (clear-stream _test-error-stream)
 3555     (clear-stream $_test-error-buffered-file->buffer)
 3556     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3557     68/push 0/imm32
 3558     68/push 0/imm32
 3559     89/<- %edx 4/r32/esp
 3560     (tailor-exit-descriptor %edx 0x10)
 3561     #
 3562     (write _test-input-stream "fn f {\n")
 3563     (write _test-input-stream "  g\n")
 3564     (write _test-input-stream "}\n")
 3565     (write _test-input-stream "fn g -> _/eax: int {\n")
 3566     (write _test-input-stream "}\n")
 3567     # convert
 3568     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3569     # registers except esp clobbered at this point
 3570     # restore ed
 3571     89/<- %edx 4/r32/esp
 3572     (flush _test-output-buffered-file)
 3573     (flush _test-error-buffered-file)
 3574 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3580     # check output
 3581     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-few-outputs: output should be empty")
 3582     (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")
 3583     # check that stop(1) was called
 3584     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-few-outputs: exit status")
 3585     # don't restore from ebp
 3586     81 0/subop/add %esp 8/imm32
 3587     5d/pop-to-ebp
 3588     c3/return
 3589 
 3590 test-convert-function-call-with-too-many-outputs:
 3591     # . prologue
 3592     55/push-ebp
 3593     89/<- %ebp 4/r32/esp
 3594     # setup
 3595     (clear-stream _test-input-stream)
 3596     (clear-stream $_test-input-buffered-file->buffer)
 3597     (clear-stream _test-output-stream)
 3598     (clear-stream $_test-output-buffered-file->buffer)
 3599     (clear-stream _test-error-stream)
 3600     (clear-stream $_test-error-buffered-file->buffer)
 3601     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3602     68/push 0/imm32
 3603     68/push 0/imm32
 3604     89/<- %edx 4/r32/esp
 3605     (tailor-exit-descriptor %edx 0x10)
 3606     #
 3607     (write _test-input-stream "fn f {\n")
 3608     (write _test-input-stream "  var x/eax: int <- g\n")
 3609     (write _test-input-stream "}\n")
 3610     (write _test-input-stream "fn g {\n")
 3611     (write _test-input-stream "}\n")
 3612     # convert
 3613     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3614     # registers except esp clobbered at this point
 3615     # restore ed
 3616     89/<- %edx 4/r32/esp
 3617     (flush _test-output-buffered-file)
 3618     (flush _test-error-buffered-file)
 3619 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3625     # check output
 3626     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-many-outputs: output should be empty")
 3627     (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")
 3628     # check that stop(1) was called
 3629     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-many-outputs: exit status")
 3630     # don't restore from ebp
 3631     81 0/subop/add %esp 8/imm32
 3632     5d/pop-to-ebp
 3633     c3/return
 3634 
 3635 test-convert-function-call-with-missing-output-register:
 3636     # . prologue
 3637     55/push-ebp
 3638     89/<- %ebp 4/r32/esp
 3639     # setup
 3640     (clear-stream _test-input-stream)
 3641     (clear-stream $_test-input-buffered-file->buffer)
 3642     (clear-stream _test-output-stream)
 3643     (clear-stream $_test-output-buffered-file->buffer)
 3644     (clear-stream _test-error-stream)
 3645     (clear-stream $_test-error-buffered-file->buffer)
 3646     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3647     68/push 0/imm32
 3648     68/push 0/imm32
 3649     89/<- %edx 4/r32/esp
 3650     (tailor-exit-descriptor %edx 0x10)
 3651     #
 3652     (write _test-input-stream "fn f {\n")
 3653     (write _test-input-stream "  var x: int\n")
 3654     (write _test-input-stream "  x <- g\n")
 3655     (write _test-input-stream "}\n")
 3656     (write _test-input-stream "fn g -> _/eax: int {\n")
 3657     (write _test-input-stream "}\n")
 3658     # convert
 3659     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3660     # registers except esp clobbered at this point
 3661     # restore ed
 3662     89/<- %edx 4/r32/esp
 3663     (flush _test-output-buffered-file)
 3664     (flush _test-error-buffered-file)
 3665 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3671     # check output
 3672     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-missing-output-register: output should be empty")
 3673     (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")
 3674     # check that stop(1) was called
 3675     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-missing-output-register: exit status")
 3676     # don't restore from ebp
 3677     81 0/subop/add %esp 8/imm32
 3678     5d/pop-to-ebp
 3679     c3/return
 3680 
 3681 test-convert-function-call-with-incorrect-output-register:
 3682     # . prologue
 3683     55/push-ebp
 3684     89/<- %ebp 4/r32/esp
 3685     # setup
 3686     (clear-stream _test-input-stream)
 3687     (clear-stream $_test-input-buffered-file->buffer)
 3688     (clear-stream _test-output-stream)
 3689     (clear-stream $_test-output-buffered-file->buffer)
 3690     (clear-stream _test-error-stream)
 3691     (clear-stream $_test-error-buffered-file->buffer)
 3692     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3693     68/push 0/imm32
 3694     68/push 0/imm32
 3695     89/<- %edx 4/r32/esp
 3696     (tailor-exit-descriptor %edx 0x10)
 3697     #
 3698     (write _test-input-stream "fn f {\n")
 3699     (write _test-input-stream "  var x/ecx: int <- g\n")
 3700     (write _test-input-stream "}\n")
 3701     (write _test-input-stream "fn g -> _/eax: int {\n")
 3702     (write _test-input-stream "}\n")
 3703     # convert
 3704     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3705     # registers except esp clobbered at this point
 3706     # restore ed
 3707     89/<- %edx 4/r32/esp
 3708     (flush _test-output-buffered-file)
 3709     (flush _test-error-buffered-file)
 3710 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3716     # check output
 3717     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-output-register: output should be empty")
 3718     (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")
 3719     # check that stop(1) was called
 3720     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-output-register: exit status")
 3721     # don't restore from ebp
 3722     81 0/subop/add %esp 8/imm32
 3723     5d/pop-to-ebp
 3724     c3/return
 3725 
 3726 test-convert-function-with-local-var-dereferenced:
 3727     # . prologue
 3728     55/push-ebp
 3729     89/<- %ebp 4/r32/esp
 3730     # setup
 3731     (clear-stream _test-input-stream)
 3732     (clear-stream $_test-input-buffered-file->buffer)
 3733     (clear-stream _test-output-stream)
 3734     (clear-stream $_test-output-buffered-file->buffer)
 3735     #
 3736     (write _test-input-stream "fn foo {\n")
 3737     (write _test-input-stream "  var x/ecx: (addr int) <- copy 0\n")
 3738     (write _test-input-stream "  increment *x\n")
 3739     (write _test-input-stream "}\n")
 3740     # convert
 3741     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3742     (flush _test-output-buffered-file)
 3743 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3749     # check output
 3750     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-dereferenced/0")
 3751     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-dereferenced/1")
 3752     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-dereferenced/2")
 3753     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-dereferenced/3")
 3754     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-dereferenced/4")
 3755     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-dereferenced/5")
 3756     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-dereferenced/6")
 3757     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-local-var-dereferenced/7")
 3758     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *ecx"  "F - test-convert-function-with-local-var-dereferenced/8")
 3759     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-dereferenced/9")
 3760     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-dereferenced/10")
 3761     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-dereferenced/11")
 3762     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-dereferenced/12")
 3763     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-dereferenced/13")
 3764     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-dereferenced/14")
 3765     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-dereferenced/15")
 3766     # . epilogue
 3767     89/<- %esp 5/r32/ebp
 3768     5d/pop-to-ebp
 3769     c3/return
 3770 
 3771 test-dereference-of-var-on-stack:
 3772     # . prologue
 3773     55/push-ebp
 3774     89/<- %ebp 4/r32/esp
 3775     # setup
 3776     (clear-stream _test-input-stream)
 3777     (clear-stream $_test-input-buffered-file->buffer)
 3778     (clear-stream _test-output-stream)
 3779     (clear-stream $_test-output-buffered-file->buffer)
 3780     (clear-stream _test-error-stream)
 3781     (clear-stream $_test-error-buffered-file->buffer)
 3782     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3783     68/push 0/imm32
 3784     68/push 0/imm32
 3785     89/<- %edx 4/r32/esp
 3786     (tailor-exit-descriptor %edx 0x10)
 3787     #
 3788     (write _test-input-stream "fn foo {\n")
 3789     (write _test-input-stream "  var x: (addr int)\n")
 3790     (write _test-input-stream "  increment *x\n")
 3791     (write _test-input-stream "}\n")
 3792     # convert
 3793     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3794     # registers except esp clobbered at this point
 3795     # restore ed
 3796     89/<- %edx 4/r32/esp
 3797     (flush _test-output-buffered-file)
 3798     (flush _test-error-buffered-file)
 3799 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3805     # check output
 3806     (check-stream-equal _test-output-stream  ""  "F - test-dereference-of-var-on-stack: output should be empty")
 3807     (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")
 3808     # check that stop(1) was called
 3809     (check-ints-equal *(edx+4) 2 "F - test-dereference-of-var-on-stack: exit status")
 3810     # don't restore from ebp
 3811     81 0/subop/add %esp 8/imm32
 3812     # . epilogue
 3813     5d/pop-to-ebp
 3814     c3/return
 3815 
 3816 test-convert-function-with-byte-operations:
 3817     # . prologue
 3818     55/push-ebp
 3819     89/<- %ebp 4/r32/esp
 3820     # setup
 3821     (clear-stream _test-input-stream)
 3822     (clear-stream $_test-input-buffered-file->buffer)
 3823     (clear-stream _test-output-stream)
 3824     (clear-stream $_test-output-buffered-file->buffer)
 3825     #
 3826     (write _test-input-stream "fn foo {\n")
 3827     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
 3828     (write _test-input-stream "  var y/ecx: byte <- copy 0\n")
 3829     (write _test-input-stream "  y <- copy-byte x\n")
 3830     (write _test-input-stream "  var z/edx: (addr byte) <- copy 0\n")
 3831     (write _test-input-stream "  y <- copy-byte *z\n")
 3832     (write _test-input-stream "  copy-byte-to *z, x\n")
 3833     (write _test-input-stream "}\n")
 3834     # convert
 3835     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3836     (flush _test-output-buffered-file)
 3837 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3843     # check output
 3844     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-function-with-byte-operations/0")
 3845     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-function-with-byte-operations/1")
 3846     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-function-with-byte-operations/2")
 3847     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-function-with-byte-operations/3")
 3848     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-function-with-byte-operations/4")
 3849     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-function-with-byte-operations/5")
 3850     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-function-with-byte-operations/6")
 3851     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-function-with-byte-operations/7")
 3852     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-function-with-byte-operations/8")
 3853     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"                  "F - test-convert-function-with-byte-operations/9")
 3854     (check-next-stream-line-equal _test-output-stream "    8a/byte-> %eax 0x00000001/r32"           "F - test-convert-function-with-byte-operations/10")
 3855     (check-next-stream-line-equal _test-output-stream "    81 4/subop/and %ecx 0xff/imm32"          "F - test-convert-function-with-byte-operations/11")
 3856     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %edx"                    "F - test-convert-function-with-byte-operations/12")
 3857     (check-next-stream-line-equal _test-output-stream "    ba/copy-to-edx 0/imm32"                  "F - test-convert-function-with-byte-operations/13")
 3858     (check-next-stream-line-equal _test-output-stream "    8a/byte-> *edx 0x00000001/r32"           "F - test-convert-function-with-byte-operations/14")
 3859     (check-next-stream-line-equal _test-output-stream "    81 4/subop/and %ecx 0xff/imm32"          "F - test-convert-function-with-byte-operations/15")
 3860     (check-next-stream-line-equal _test-output-stream "    88/byte<- *edx 0x00000000/r32"           "F - test-convert-function-with-byte-operations/16")
 3861     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %edx"                     "F - test-convert-function-with-byte-operations/17")
 3862     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-function-with-byte-operations/18")
 3863     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-function-with-byte-operations/19")
 3864     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-function-with-byte-operations/20")
 3865     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-function-with-byte-operations/21")
 3866     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-function-with-byte-operations/22")
 3867     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-function-with-byte-operations/23")
 3868     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-function-with-byte-operations/24")
 3869     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-function-with-byte-operations/25")
 3870     # . epilogue
 3871     89/<- %esp 5/r32/ebp
 3872     5d/pop-to-ebp
 3873     c3/return
 3874 
 3875 # variables of type 'byte' are not allowed on the stack
 3876 test-byte-values-on-stack:
 3877     # . prologue
 3878     55/push-ebp
 3879     89/<- %ebp 4/r32/esp
 3880     # setup
 3881     (clear-stream _test-input-stream)
 3882     (clear-stream $_test-input-buffered-file->buffer)
 3883     (clear-stream _test-output-stream)
 3884     (clear-stream $_test-output-buffered-file->buffer)
 3885     (clear-stream _test-error-stream)
 3886     (clear-stream $_test-error-buffered-file->buffer)
 3887     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3888     68/push 0/imm32
 3889     68/push 0/imm32
 3890     89/<- %edx 4/r32/esp
 3891     (tailor-exit-descriptor %edx 0x10)
 3892     #
 3893     (write _test-input-stream "fn foo {\n")
 3894     (write _test-input-stream "  var x: byte\n")
 3895     (write _test-input-stream "}\n")
 3896     # convert
 3897     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3898     # registers except esp clobbered at this point
 3899     # restore ed
 3900     89/<- %edx 4/r32/esp
 3901     (flush _test-output-buffered-file)
 3902     (flush _test-error-buffered-file)
 3903 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3909     # check output
 3910     (check-stream-equal _test-output-stream  ""  "F - test-byte-values-on-stack: output should be empty")
 3911     (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")
 3912     # check that stop(1) was called
 3913     (check-ints-equal *(edx+4) 2 "F - test-byte-values-on-stack: exit status")
 3914     # don't restore from ebp
 3915     81 0/subop/add %esp 8/imm32
 3916     # . epilogue
 3917     5d/pop-to-ebp
 3918     c3/return
 3919 
 3920 # variables of type 'byte' are not allowed in esi or edi
 3921 test-byte-values-in-unsupported-registers:
 3922     # . prologue
 3923     55/push-ebp
 3924     89/<- %ebp 4/r32/esp
 3925     # setup
 3926     (clear-stream _test-input-stream)
 3927     (clear-stream $_test-input-buffered-file->buffer)
 3928     (clear-stream _test-output-stream)
 3929     (clear-stream $_test-output-buffered-file->buffer)
 3930     (clear-stream _test-error-stream)
 3931     (clear-stream $_test-error-buffered-file->buffer)
 3932     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3933     68/push 0/imm32
 3934     68/push 0/imm32
 3935     89/<- %edx 4/r32/esp
 3936     (tailor-exit-descriptor %edx 0x10)
 3937     #
 3938     (write _test-input-stream "fn foo {\n")
 3939     (write _test-input-stream "  var x/esi: byte <- copy 0\n")
 3940     (write _test-input-stream "}\n")
 3941     # convert
 3942     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3943     # registers except esp clobbered at this point
 3944     # restore ed
 3945     89/<- %edx 4/r32/esp
 3946     (flush _test-output-buffered-file)
 3947     (flush _test-error-buffered-file)
 3948 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3954     # check output
 3955     (check-stream-equal _test-output-stream  ""  "F - test-byte-values-in-unsupported-registers: output should be empty")
 3956     (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")
 3957     # check that stop(1) was called
 3958     (check-ints-equal *(edx+4) 2 "F - test-byte-values-in-unsupported-registers: exit status")
 3959     # don't restore from ebp
 3960     81 0/subop/add %esp 8/imm32
 3961     # . epilogue
 3962     5d/pop-to-ebp
 3963     c3/return
 3964 
 3965 # variables of type 'byte' _can_ be function args. They then occupy 4 bytes.
 3966 test-copy-byte-var-from-fn-arg:
 3967     # . prologue
 3968     55/push-ebp
 3969     89/<- %ebp 4/r32/esp
 3970     # setup
 3971     (clear-stream _test-input-stream)
 3972     (clear-stream $_test-input-buffered-file->buffer)
 3973     (clear-stream _test-output-stream)
 3974     (clear-stream $_test-output-buffered-file->buffer)
 3975     #
 3976     (write _test-input-stream "fn foo x: byte, y: int {\n")
 3977     (write _test-input-stream "  var a/eax: byte <- copy x\n")
 3978     (write _test-input-stream "  var b/eax: int <- copy y\n")
 3979     (write _test-input-stream "}\n")
 3980     # convert
 3981     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3982     (flush _test-output-buffered-file)
 3983 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3989     # check output
 3990     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-copy-byte-from-fn-arg/0")
 3991     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-copy-byte-from-fn-arg/1")
 3992     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-copy-byte-from-fn-arg/2")
 3993     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-copy-byte-from-fn-arg/3")
 3994     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-copy-byte-from-fn-arg/4")
 3995     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-copy-byte-from-fn-arg/5")
 3996     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-copy-byte-from-fn-arg/6")
 3997     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-copy-byte-from-fn-arg/7")
 3998     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x0000000c) 0x00000000/r32"  "F - test-copy-byte-from-fn-arg/8")
 3999     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"   "F - test-copy-byte-from-fn-arg/9")
 4000     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-copy-byte-from-fn-arg/10")
 4001     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-copy-byte-from-fn-arg/11")
 4002     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-copy-byte-from-fn-arg/12")
 4003     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-copy-byte-from-fn-arg/13")
 4004     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-copy-byte-from-fn-arg/14")
 4005     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-copy-byte-from-fn-arg/15")
 4006     # . epilogue
 4007     89/<- %esp 5/r32/ebp
 4008     5d/pop-to-ebp
 4009     c3/return
 4010 
 4011 test-convert-compare-register-with-literal:
 4012     # . prologue
 4013     55/push-ebp
 4014     89/<- %ebp 4/r32/esp
 4015     # setup
 4016     (clear-stream _test-input-stream)
 4017     (clear-stream $_test-input-buffered-file->buffer)
 4018     (clear-stream _test-output-stream)
 4019     (clear-stream $_test-output-buffered-file->buffer)
 4020     #
 4021     (write _test-input-stream "fn foo {\n")
 4022     (write _test-input-stream "  var x/ecx: int <- copy 0\n")
 4023     (write _test-input-stream "  compare x, 0\n")
 4024     (write _test-input-stream "}\n")
 4025     # convert
 4026     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4027     (flush _test-output-buffered-file)
 4028 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4034     # check output
 4035     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-compare-register-with-literal/0")
 4036     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-compare-register-with-literal/1")
 4037     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-compare-register-with-literal/2")
 4038     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-compare-register-with-literal/3")
 4039     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-compare-register-with-literal/4")
 4040     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-compare-register-with-literal/5")
 4041     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-compare-register-with-literal/6")
 4042     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-compare-register-with-literal/7")
 4043     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %ecx 0/imm32"  "F - test-convert-compare-register-with-literal/8")
 4044     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-compare-register-with-literal/9")
 4045     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-compare-register-with-literal/10")
 4046     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-compare-register-with-literal/11")
 4047     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-compare-register-with-literal/12")
 4048     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-compare-register-with-literal/13")
 4049     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-compare-register-with-literal/14")
 4050     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-compare-register-with-literal/15")
 4051     # . epilogue
 4052     89/<- %esp 5/r32/ebp
 4053     5d/pop-to-ebp
 4054     c3/return
 4055 
 4056 test-convert-compare-byte-with-literal:
 4057     # . prologue
 4058     55/push-ebp
 4059     89/<- %ebp 4/r32/esp
 4060     # setup
 4061     (clear-stream _test-input-stream)
 4062     (clear-stream $_test-input-buffered-file->buffer)
 4063     (clear-stream _test-output-stream)
 4064     (clear-stream $_test-output-buffered-file->buffer)
 4065     #
 4066     (write _test-input-stream "fn foo {\n")
 4067     (write _test-input-stream "  var x/ecx: byte <- copy 0\n")
 4068     (write _test-input-stream "  compare x, 0\n")
 4069     (write _test-input-stream "}\n")
 4070     # convert
 4071     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4072     (flush _test-output-buffered-file)
 4073 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4079     # no errors; output is identical to test-convert-compare-register-with-literal
 4080     # . epilogue
 4081     89/<- %esp 5/r32/ebp
 4082     5d/pop-to-ebp
 4083     c3/return
 4084 
 4085 test-unknown-variable:
 4086     # . prologue
 4087     55/push-ebp
 4088     89/<- %ebp 4/r32/esp
 4089     # setup
 4090     (clear-stream _test-input-stream)
 4091     (clear-stream $_test-input-buffered-file->buffer)
 4092     (clear-stream _test-output-stream)
 4093     (clear-stream $_test-output-buffered-file->buffer)
 4094     (clear-stream _test-error-stream)
 4095     (clear-stream $_test-error-buffered-file->buffer)
 4096     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 4097     68/push 0/imm32
 4098     68/push 0/imm32
 4099     89/<- %edx 4/r32/esp
 4100     (tailor-exit-descriptor %edx 0x10)
 4101     #
 4102     (write _test-input-stream "fn foo {\n")
 4103     (write _test-input-stream "  compare x, 0\n")
 4104     (write _test-input-stream "}\n")
 4105     # convert
 4106     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 4107     # registers except esp clobbered at this point
 4108     # restore ed
 4109     89/<- %edx 4/r32/esp
 4110     (flush _test-output-buffered-file)
 4111     (flush _test-error-buffered-file)
 4112 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 4118     # check output
 4119     (check-stream-equal _test-output-stream  ""  "F - test-unknown-variable: output should be empty")
 4120     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-unknown-variable: error message")
 4121     # check that stop(1) was called
 4122     (check-ints-equal *(edx+4) 2 "F - test-unknown-variable: exit status")
 4123     # don't restore from ebp
 4124     81 0/subop/add %esp 8/imm32
 4125     # . epilogue
 4126     5d/pop-to-ebp
 4127     c3/return
 4128 
 4129 test-convert-function-with-local-var-in-block:
 4130     # . prologue
 4131     55/push-ebp
 4132     89/<- %ebp 4/r32/esp
 4133     # setup
 4134     (clear-stream _test-input-stream)
 4135     (clear-stream $_test-input-buffered-file->buffer)
 4136     (clear-stream _test-output-stream)
 4137     (clear-stream $_test-output-buffered-file->buffer)
 4138     #
 4139     (write _test-input-stream "fn foo {\n")
 4140     (write _test-input-stream "  {\n")
 4141     (write _test-input-stream "    var x: int\n")
 4142     (write _test-input-stream "    increment x\n")
 4143     (write _test-input-stream "  }\n")
 4144     (write _test-input-stream "}\n")
 4145     # convert
 4146     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4147     (flush _test-output-buffered-file)
 4148 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4154     # check output
 4155     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-block/0")
 4156     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-block/1")
 4157     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-block/2")
 4158     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-block/3")
 4159     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-block/4")
 4160     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-block/5")
 4161     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-block/6")
 4162     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-local-var-in-block/7")
 4163     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-block/8")
 4164     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-local-var-in-block/9")
 4165     (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")
 4166     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-block/11")
 4167     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-local-var-in-block/12")
 4168     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-block/13")
 4169     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-block/14")
 4170     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-block/15")
 4171     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-block/16")
 4172     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-block/17")
 4173     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-block/18")
 4174     # . epilogue
 4175     89/<- %esp 5/r32/ebp
 4176     5d/pop-to-ebp
 4177     c3/return
 4178 
 4179 test-convert-function-with-local-var-in-mem-after-block:
 4180     # . prologue
 4181     55/push-ebp
 4182     89/<- %ebp 4/r32/esp
 4183     # setup
 4184     (clear-stream _test-input-stream)
 4185     (clear-stream $_test-input-buffered-file->buffer)
 4186     (clear-stream _test-output-stream)
 4187     (clear-stream $_test-output-buffered-file->buffer)
 4188     #
 4189     (write _test-input-stream "fn foo {\n")
 4190     (write _test-input-stream "  {\n")
 4191     (write _test-input-stream "    var y: int\n")
 4192     (write _test-input-stream "  }\n")
 4193     (write _test-input-stream "  var x: int\n")
 4194     (write _test-input-stream "  increment x\n")
 4195     (write _test-input-stream "}\n")
 4196     # convert
 4197     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4198     (flush _test-output-buffered-file)
 4199 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4205     # check output
 4206     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-mem-after-block/0")
 4207     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-mem-after-block/1")
 4208     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-mem-after-block/2")
 4209     (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")
 4210     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-mem-after-block/4")
 4211     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-mem-after-block/5")
 4212     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-mem-after-block/6")
 4213     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-local-var-in-mem-after-block/7")
 4214     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-mem-after-block/8")
 4215     (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")
 4216     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-mem-after-block/10")
 4217     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-local-var-in-mem-after-block/11")
 4218     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-in-mem-after-block/12")
 4219     (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")
 4220     (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")
 4221     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-mem-after-block/15")
 4222     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-mem-after-block/16")
 4223     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-mem-after-block/17")
 4224     (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")
 4225     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-mem-after-block/19")
 4226     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-mem-after-block/20")
 4227     # . epilogue
 4228     89/<- %esp 5/r32/ebp
 4229     5d/pop-to-ebp
 4230     c3/return
 4231 
 4232 test-convert-function-with-local-var-in-named-block:
 4233     # . prologue
 4234     55/push-ebp
 4235     89/<- %ebp 4/r32/esp
 4236     # setup
 4237     (clear-stream _test-input-stream)
 4238     (clear-stream $_test-input-buffered-file->buffer)
 4239     (clear-stream _test-output-stream)
 4240     (clear-stream $_test-output-buffered-file->buffer)
 4241     #
 4242     (write _test-input-stream "fn foo {\n")
 4243     (write _test-input-stream "  $bar: {\n")
 4244     (write _test-input-stream "    var x: int\n")
 4245     (write _test-input-stream "    increment x\n")
 4246     (write _test-input-stream "  }\n")
 4247     (write _test-input-stream "}\n")
 4248     # convert
 4249     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4250     (flush _test-output-buffered-file)
 4251 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4257     # check output
 4258     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-named-block/0")
 4259     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-named-block/1")
 4260     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-named-block/2")
 4261     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-named-block/3")
 4262     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-named-block/4")
 4263     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-named-block/5")
 4264     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-named-block/6")
 4265     (check-next-stream-line-equal _test-output-stream "$bar:loop:"              "F - test-convert-function-with-local-var-in-named-block/7")
 4266     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-named-block/8")
 4267     (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")
 4268     (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")
 4269     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-named-block/11")
 4270     (check-next-stream-line-equal _test-output-stream "$bar:break:"             "F - test-convert-function-with-local-var-in-named-block/12")
 4271     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-named-block/13")
 4272     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-named-block/14")
 4273     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-named-block/15")
 4274     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-named-block/16")
 4275     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-named-block/17")
 4276     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-named-block/18")
 4277     # . epilogue
 4278     89/<- %esp 5/r32/ebp
 4279     5d/pop-to-ebp
 4280     c3/return
 4281 
 4282 test-unknown-variable-in-named-block:
 4283     # . prologue
 4284     55/push-ebp
 4285     89/<- %ebp 4/r32/esp
 4286     # setup
 4287     (clear-stream _test-input-stream)
 4288     (clear-stream $_test-input-buffered-file->buffer)
 4289     (clear-stream _test-output-stream)
 4290     (clear-stream $_test-output-buffered-file->buffer)
 4291     (clear-stream _test-error-stream)
 4292     (clear-stream $_test-error-buffered-file->buffer)
 4293     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 4294     68/push 0/imm32
 4295     68/push 0/imm32
 4296     89/<- %edx 4/r32/esp
 4297     (tailor-exit-descriptor %edx 0x10)
 4298     #
 4299     (write _test-input-stream "fn foo {\n")
 4300     (write _test-input-stream "  $a: {\n")
 4301     (write _test-input-stream "    compare x, 0\n")
 4302     (write _test-input-stream "  }\n")
 4303     (write _test-input-stream "}\n")
 4304     # convert
 4305     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 4306     # registers except esp clobbered at this point
 4307     # restore ed
 4308     89/<- %edx 4/r32/esp
 4309     (flush _test-output-buffered-file)
 4310     (flush _test-error-buffered-file)
 4311 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 4317     # check output
 4318     (check-stream-equal _test-output-stream  ""  "F - test-unknown-variable-in-named-block: output should be empty")
 4319     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-unknown-variable-in-named-block: error message")
 4320     # check that stop(1) was called
 4321     (check-ints-equal *(edx+4) 2 "F - test-unknown-variable-in-named-block: exit status")
 4322     # don't restore from ebp
 4323     81 0/subop/add %esp 8/imm32
 4324     # . epilogue
 4325     5d/pop-to-ebp
 4326     c3/return
 4327 
 4328 test-always-shadow-outermost-reg-vars-in-function:
 4329     # . prologue
 4330     55/push-ebp
 4331     89/<- %ebp 4/r32/esp
 4332     # setup
 4333     (clear-stream _test-input-stream)
 4334     (clear-stream $_test-input-buffered-file->buffer)
 4335     (clear-stream _test-output-stream)
 4336     (clear-stream $_test-output-buffered-file->buffer)
 4337     #
 4338     (write _test-input-stream "fn foo {\n")
 4339     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4340     (write _test-input-stream "}\n")
 4341     # convert
 4342     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4343     (flush _test-output-buffered-file)
 4344 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4350     # check output
 4351     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-always-shadow-outermost-reg-vars-in-function/0")
 4352     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-always-shadow-outermost-reg-vars-in-function/1")
 4353     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-always-shadow-outermost-reg-vars-in-function/2")
 4354     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-always-shadow-outermost-reg-vars-in-function/3")
 4355     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-always-shadow-outermost-reg-vars-in-function/4")
 4356     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-always-shadow-outermost-reg-vars-in-function/5")
 4357     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-compare-register-with-literal/6")
 4358     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-always-shadow-outermost-reg-vars-in-function/8")
 4359     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-compare-register-with-literal/9")
 4360     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-always-shadow-outermost-reg-vars-in-function/12")
 4361     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-always-shadow-outermost-reg-vars-in-function/13")
 4362     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-always-shadow-outermost-reg-vars-in-function/14")
 4363     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-always-shadow-outermost-reg-vars-in-function/15")
 4364     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-always-shadow-outermost-reg-vars-in-function/16")
 4365     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-always-shadow-outermost-reg-vars-in-function/17")
 4366     # . epilogue
 4367     89/<- %esp 5/r32/ebp
 4368     5d/pop-to-ebp
 4369     c3/return
 4370 
 4371 test-shadow-local:
 4372     # . prologue
 4373     55/push-ebp
 4374     89/<- %ebp 4/r32/esp
 4375     # setup
 4376     (clear-stream _test-input-stream)
 4377     (clear-stream $_test-input-buffered-file->buffer)
 4378     (clear-stream _test-output-stream)
 4379     (clear-stream $_test-output-buffered-file->buffer)
 4380     #
 4381     (write _test-input-stream "fn foo {\n")
 4382     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4383     (write _test-input-stream "  {\n")
 4384     (write _test-input-stream "    var y/ecx: int <- copy 4\n")
 4385     (write _test-input-stream "  }\n")
 4386     (write _test-input-stream "  x <- increment\n")
 4387     (write _test-input-stream "}\n")
 4388     # convert
 4389     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4390     (flush _test-output-buffered-file)
 4391 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4397     # check output
 4398     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-local/0")
 4399     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-local/1")
 4400     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-local/2")
 4401     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-local/3")
 4402     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-local/4")
 4403     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-local/5")
 4404     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-local/6")
 4405     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-local/7")
 4406     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-local/8")
 4407     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-local/9")
 4408     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %ecx"  "F - test-shadow-local/10")
 4409     (check-next-stream-line-equal _test-output-stream "      b9/copy-to-ecx 4/imm32"  "F - test-shadow-local/11")
 4410     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %ecx" "F - test-shadow-local/12")
 4411     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-local/13")
 4412     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-local/14")
 4413     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-local/15")
 4414     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-local/16")
 4415     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-local/17")
 4416     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-local/18")
 4417     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-local/19")
 4418     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-local/20")
 4419     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-local/21")
 4420     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-local/22")
 4421     # . epilogue
 4422     89/<- %esp 5/r32/ebp
 4423     5d/pop-to-ebp
 4424     c3/return
 4425 
 4426 test-shadow-name:
 4427     # . prologue
 4428     55/push-ebp
 4429     89/<- %ebp 4/r32/esp
 4430     # setup
 4431     (clear-stream _test-input-stream)
 4432     (clear-stream $_test-input-buffered-file->buffer)
 4433     (clear-stream _test-output-stream)
 4434     (clear-stream $_test-output-buffered-file->buffer)
 4435     #
 4436     (write _test-input-stream "fn foo {\n")
 4437     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4438     (write _test-input-stream "  {\n")
 4439     (write _test-input-stream "    var x/edx: int <- copy 4\n")
 4440     (write _test-input-stream "  }\n")
 4441     (write _test-input-stream "  x <- increment\n")
 4442     (write _test-input-stream "}\n")
 4443     # convert
 4444     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4445     (flush _test-output-buffered-file)
 4446 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4452     # check output
 4453     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-name/0")
 4454     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-name/1")
 4455     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-name/2")
 4456     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-name/3")
 4457     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-name/4")
 4458     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-name/5")
 4459     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-name/6")
 4460     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-name/7")
 4461     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-name/8")
 4462     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-name/9")
 4463     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %edx"  "F - test-shadow-name/10")
 4464     (check-next-stream-line-equal _test-output-stream "      ba/copy-to-edx 4/imm32"  "F - test-shadow-name/11")
 4465     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %edx" "F - test-shadow-name/12")
 4466     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-name/13")
 4467     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-name/14")
 4468     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-name/15")
 4469     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-name/16")
 4470     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-name/17")
 4471     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-name/18")
 4472     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-name/19")
 4473     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-name/20")
 4474     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-name/21")
 4475     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-name/22")
 4476     # . epilogue
 4477     89/<- %esp 5/r32/ebp
 4478     5d/pop-to-ebp
 4479     c3/return
 4480 
 4481 test-shadow-name-2:
 4482     # . prologue
 4483     55/push-ebp
 4484     89/<- %ebp 4/r32/esp
 4485     # setup
 4486     (clear-stream _test-input-stream)
 4487     (clear-stream $_test-input-buffered-file->buffer)
 4488     (clear-stream _test-output-stream)
 4489     (clear-stream $_test-output-buffered-file->buffer)
 4490     #
 4491     (write _test-input-stream "fn foo {\n")
 4492     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4493     (write _test-input-stream "  {\n")
 4494     (write _test-input-stream "    var x/edx: int <- copy 4\n")
 4495     (write _test-input-stream "    var y/ecx: int <- copy 5\n")
 4496     (write _test-input-stream "  }\n")
 4497     (write _test-input-stream "  x <- increment\n")
 4498     (write _test-input-stream "}\n")
 4499     # convert
 4500     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4501     (flush _test-output-buffered-file)
 4502 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4508     # check output
 4509     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-name-2/0")
 4510     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-name-2/1")
 4511     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-name-2/2")
 4512     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-name-2/3")
 4513     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-name-2/4")
 4514     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-name-2/5")
 4515     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-name-2/6")
 4516     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-name-2/7")
 4517     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-name-2/8")
 4518     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-name-2/9")
 4519     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %edx"  "F - test-shadow-name-2/10")
 4520     (check-next-stream-line-equal _test-output-stream "      ba/copy-to-edx 4/imm32"  "F - test-shadow-name-2/11")
 4521     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %ecx"  "F - test-shadow-name-2/12")
 4522     (check-next-stream-line-equal _test-output-stream "      b9/copy-to-ecx 5/imm32"  "F - test-shadow-name-2/13")
 4523     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %ecx" "F - test-shadow-name-2/14")
 4524     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %edx" "F - test-shadow-name-2/15")
 4525     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-name-2/16")
 4526     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-name-2/17")
 4527     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-name-2/18")
 4528     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-name-2/19")
 4529     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-name-2/20")
 4530     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-name-2/21")
 4531     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-name-2/22")
 4532     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-name-2/23")
 4533     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-name-2/24")
 4534     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-name-2/25")
 4535     # . epilogue
 4536     89/<- %esp 5/r32/ebp
 4537     5d/pop-to-ebp
 4538     c3/return
 4539 
 4540 test-do-not-spill-same-register-in-block:
 4541     # . prologue
 4542     55/push-ebp
 4543     89/<- %ebp 4/r32/esp
 4544     # setup
 4545     (clear-stream _test-input-stream)
 4546     (clear-stream $_test-input-buffered-file->buffer)
 4547     (clear-stream _test-output-stream)
 4548     (clear-stream $_test-output-buffered-file->buffer)
 4549     #
 4550     (write _test-input-stream "fn foo {\n")
 4551     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4552     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 4553     (write _test-input-stream "  y <- increment\n")
 4554     (write _test-input-stream "}\n")
 4555     # convert
 4556     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4557     (flush _test-output-buffered-file)
 4558 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4564     # check output
 4565     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-do-not-spill-same-register-in-block/0")
 4566     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-do-not-spill-same-register-in-block/1")
 4567     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-do-not-spill-same-register-in-block/2")
 4568     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-do-not-spill-same-register-in-block/3")
 4569     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-do-not-spill-same-register-in-block/4")
 4570     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-do-not-spill-same-register-in-block/5")
 4571     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-do-not-spill-same-register-in-block/6")
 4572     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-do-not-spill-same-register-in-block/7")
 4573     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-do-not-spill-same-register-in-block/8")
 4574     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-do-not-spill-same-register-in-block/9")
 4575     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-do-not-spill-same-register-in-block/10")
 4576     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-do-not-spill-same-register-in-block/11")
 4577     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-do-not-spill-same-register-in-block/12")
 4578     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-do-not-spill-same-register-in-block/13")
 4579     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-do-not-spill-same-register-in-block/14")
 4580     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-do-not-spill-same-register-in-block/15")
 4581     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-do-not-spill-same-register-in-block/16")
 4582     # . epilogue
 4583     89/<- %esp 5/r32/ebp
 4584     5d/pop-to-ebp
 4585     c3/return
 4586 
 4587 test-spill-different-register-in-block:
 4588     # . prologue
 4589     55/push-ebp
 4590     89/<- %ebp 4/r32/esp
 4591     # setup
 4592     (clear-stream _test-input-stream)
 4593     (clear-stream $_test-input-buffered-file->buffer)
 4594     (clear-stream _test-output-stream)
 4595     (clear-stream $_test-output-buffered-file->buffer)
 4596     #
 4597     (write _test-input-stream "fn foo {\n")
 4598     (write _test-input-stream "  var x/eax: int <- copy 3\n")
 4599     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 4600     (write _test-input-stream "  y <- increment\n")
 4601     (write _test-input-stream "}\n")
 4602     # convert
 4603     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4604     (flush _test-output-buffered-file)
 4605 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4611     # check output
 4612     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-spill-different-register-in-block/0")
 4613     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-spill-different-register-in-block/1")
 4614     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-spill-different-register-in-block/2")
 4615     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-spill-different-register-in-block/3")
 4616     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-spill-different-register-in-block/4")
 4617     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-spill-different-register-in-block/5")
 4618     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-spill-different-register-in-block/6")
 4619     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-spill-different-register-in-block/7")
 4620     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-spill-different-register-in-block/8")
 4621     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-spill-different-register-in-block/9")
 4622     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-spill-different-register-in-block/10")
 4623     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-spill-different-register-in-block/11")
 4624     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-spill-different-register-in-block/12")
 4625     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-spill-different-register-in-block/13")
 4626     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-spill-different-register-in-block/14")
 4627     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-spill-different-register-in-block/15")
 4628     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-spill-different-register-in-block/16")
 4629     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-spill-different-register-in-block/17")
 4630     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-spill-different-register-in-block/18")
 4631     # . epilogue
 4632     89/<- %esp 5/r32/ebp
 4633     5d/pop-to-ebp
 4634     c3/return
 4635 
 4636 test-convert-function-with-branches-in-block:
 4637     # . prologue
 4638     55/push-ebp
 4639     89/<- %ebp 4/r32/esp
 4640     # setup
 4641     (clear-stream _test-input-stream)
 4642     (clear-stream $_test-input-buffered-file->buffer)
 4643     (clear-stream _test-output-stream)
 4644     (clear-stream $_test-output-buffered-file->buffer)
 4645     #
 4646     (write _test-input-stream "fn foo x: int {\n")
 4647     (write _test-input-stream "  {\n")
 4648     (write _test-input-stream "    break-if->=\n")
 4649     (write _test-input-stream "    loop-if-addr<\n")
 4650     (write _test-input-stream "    increment x\n")
 4651     (write _test-input-stream "    loop\n")
 4652     (write _test-input-stream "  }\n")
 4653     (write _test-input-stream "}\n")
 4654     # convert
 4655     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4656     (flush _test-output-buffered-file)
 4657 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4663     # check output
 4664     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-block/0")
 4665     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-block/1")
 4666     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-block/2")
 4667     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-block/3")
 4668     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-block/4")
 4669     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-block/5")
 4670     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-block/6")
 4671     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-in-block/7")
 4672     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/8")
 4673     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-block/9")
 4674     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-in-block/10")
 4675     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/11")
 4676     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/12")
 4677     (check-next-stream-line-equal _test-output-stream "        0f 83/jump-if-addr>= break/disp32"  "F - test-convert-function-with-branches-in-block/13")
 4678     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:loop/disp32"  "F - test-convert-function-with-branches-in-block/14")
 4679     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/15")
 4680     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-block/16")
 4681     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-in-block/17")
 4682     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-block/18")
 4683     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-in-block/19")
 4684     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-block/20")
 4685     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-block/21")
 4686     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-block/22")
 4687     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-block/23")
 4688     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-block/24")
 4689     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-block/25")
 4690     # . epilogue
 4691     89/<- %esp 5/r32/ebp
 4692     5d/pop-to-ebp
 4693     c3/return
 4694 
 4695 test-convert-function-with-branches-in-block-2:
 4696     # . prologue
 4697     55/push-ebp
 4698     89/<- %ebp 4/r32/esp
 4699     # setup
 4700     (clear-stream _test-input-stream)
 4701     (clear-stream $_test-input-buffered-file->buffer)
 4702     (clear-stream _test-output-stream)
 4703     (clear-stream $_test-output-buffered-file->buffer)
 4704     #
 4705     (write _test-input-stream "fn foo x: int {\n")
 4706     (write _test-input-stream "  {\n")
 4707     (write _test-input-stream "    break-if->=\n")
 4708     (write _test-input-stream "    loop-if-float<\n")
 4709     (write _test-input-stream "    increment x\n")
 4710     (write _test-input-stream "    loop\n")
 4711     (write _test-input-stream "  }\n")
 4712     (write _test-input-stream "}\n")
 4713     # convert
 4714     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4715     (flush _test-output-buffered-file)
 4716 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4722     # check output
 4723     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-block/0")
 4724     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-block/1")
 4725     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-block/2")
 4726     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-block/3")
 4727     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-block/4")
 4728     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-block/5")
 4729     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-block/6")
 4730     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-in-block/7")
 4731     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/8")
 4732     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-block/9")
 4733     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-in-block/10")
 4734     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/11")
 4735     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/12")
 4736     (check-next-stream-line-equal _test-output-stream "        0f 83/jump-if-addr>= break/disp32"  "F - test-convert-function-with-branches-in-block/13")
 4737     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:loop/disp32"  "F - test-convert-function-with-branches-in-block/14")
 4738     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/15")
 4739     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-block/16")
 4740     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-in-block/17")
 4741     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-block/18")
 4742     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-in-block/19")
 4743     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-block/20")
 4744     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-block/21")
 4745     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-block/22")
 4746     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-block/23")
 4747     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-block/24")
 4748     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-block/25")
 4749     # . epilogue
 4750     89/<- %esp 5/r32/ebp
 4751     5d/pop-to-ebp
 4752     c3/return
 4753 
 4754 test-convert-function-with-branches-in-named-block:
 4755     # . prologue
 4756     55/push-ebp
 4757     89/<- %ebp 4/r32/esp
 4758     # setup
 4759     (clear-stream _test-input-stream)
 4760     (clear-stream $_test-input-buffered-file->buffer)
 4761     (clear-stream _test-output-stream)
 4762     (clear-stream $_test-output-buffered-file->buffer)
 4763     #
 4764     (write _test-input-stream "fn foo x: int {\n")
 4765     (write _test-input-stream "  $bar: {\n")
 4766     (write _test-input-stream "    break-if->= $bar\n")
 4767     (write _test-input-stream "    loop-if-addr< $bar\n")
 4768     (write _test-input-stream "    increment x\n")
 4769     (write _test-input-stream "    loop\n")
 4770     (write _test-input-stream "  }\n")
 4771     (write _test-input-stream "}\n")
 4772     # convert
 4773     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4774     (flush _test-output-buffered-file)
 4775 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4781     # check output
 4782     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-named-block/0")
 4783     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-named-block/1")
 4784     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-named-block/2")
 4785     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-named-block/3")
 4786     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-named-block/4")
 4787     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-named-block/5")
 4788     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-named-block/6")
 4789     (check-next-stream-line-equal _test-output-stream "$bar:loop:"              "F - test-convert-function-with-branches-in-named-block/7")
 4790     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-named-block/8")
 4791     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-named-block/9")
 4792     (check-next-stream-line-equal _test-output-stream "        e9/jump $bar:break/disp32"  "F - test-convert-function-with-branches-in-named-block/10")
 4793     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-named-block/11")
 4794     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-named-block/12")
 4795     (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")
 4796     (check-next-stream-line-equal _test-output-stream "        e9/jump $bar:loop/disp32"  "F - test-convert-function-with-branches-in-named-block/14")
 4797     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-named-block/15")
 4798     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-named-block/16")
 4799     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"   "F - test-convert-function-with-branches-in-named-block/17")
 4800     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-named-block/18")
 4801     (check-next-stream-line-equal _test-output-stream "$bar:break:"             "F - test-convert-function-with-branches-in-named-block/19")
 4802     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-named-block/20")
 4803     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-named-block/21")
 4804     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-named-block/22")
 4805     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-named-block/23")
 4806     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-named-block/24")
 4807     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-named-block/25")
 4808     # . epilogue
 4809     89/<- %esp 5/r32/ebp
 4810     5d/pop-to-ebp
 4811     c3/return
 4812 
 4813 test-convert-function-with-var-in-nested-block:
 4814     # . prologue
 4815     55/push-ebp
 4816     89/<- %ebp 4/r32/esp
 4817     # setup
 4818     (clear-stream _test-input-stream)
 4819     (clear-stream $_test-input-buffered-file->buffer)
 4820     (clear-stream _test-output-stream)
 4821     (clear-stream $_test-output-buffered-file->buffer)
 4822     #
 4823     (write _test-input-stream "fn foo x: int {\n")
 4824     (write _test-input-stream "  {\n")
 4825     (write _test-input-stream "    {\n")
 4826     (write _test-input-stream "      var x: int\n")
 4827     (write _test-input-stream "      increment x\n")
 4828     (write _test-input-stream "    }\n")
 4829     (write _test-input-stream "  }\n")
 4830     (write _test-input-stream "}\n")
 4831     # convert
 4832     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4833     (flush _test-output-buffered-file)
 4834 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4840     # check output
 4841     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-var-in-nested-block/0")
 4842     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-var-in-nested-block/1")
 4843     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-var-in-nested-block/2")
 4844     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-var-in-nested-block/3")
 4845     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-var-in-nested-block/4")
 4846     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-var-in-nested-block/5")
 4847     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-var-in-nested-block/6")
 4848     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-var-in-nested-block/7")
 4849     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-var-in-nested-block/8")
 4850     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-var-in-nested-block/9")
 4851     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-var-in-nested-block/10")
 4852     (check-next-stream-line-equal _test-output-stream "        ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-var-in-nested-block/11")
 4853     (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")
 4854     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-var-in-nested-block/13")
 4855     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-var-in-nested-block/14")
 4856     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-var-in-nested-block/15")
 4857     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-var-in-nested-block/16")
 4858     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-var-in-nested-block/17")
 4859     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-var-in-nested-block/18")
 4860     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-var-in-nested-block/19")
 4861     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-var-in-nested-block/20")
 4862     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-var-in-nested-block/21")
 4863     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-var-in-nested-block/22")
 4864     # . epilogue
 4865     89/<- %esp 5/r32/ebp
 4866     5d/pop-to-ebp
 4867     c3/return
 4868 
 4869 test-convert-function-with-multiple-vars-in-nested-blocks:
 4870     # . prologue
 4871     55/push-ebp
 4872     89/<- %ebp 4/r32/esp
 4873     # setup
 4874     (clear-stream _test-input-stream)
 4875     (clear-stream $_test-input-buffered-file->buffer)
 4876     (clear-stream _test-output-stream)
 4877     (clear-stream $_test-output-buffered-file->buffer)
 4878     #
 4879     (write _test-input-stream "fn foo x: int {\n")
 4880     (write _test-input-stream "  {\n")
 4881     (write _test-input-stream "    var x/eax: int <- copy 0\n")
 4882     (write _test-input-stream "    {\n")
 4883     (write _test-input-stream "      var y: int\n")
 4884     (write _test-input-stream "      x <- add y\n")
 4885     (write _test-input-stream "    }\n")
 4886     (write _test-input-stream "  }\n")
 4887     (write _test-input-stream "}\n")
 4888     # convert
 4889     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4890     (flush _test-output-buffered-file)
 4891 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4897     # check output
 4898     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-multiple-vars-in-nested-blocks/0")
 4899     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-multiple-vars-in-nested-blocks/1")
 4900     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-multiple-vars-in-nested-blocks/2")
 4901     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/3")
 4902     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-multiple-vars-in-nested-blocks/4")
 4903     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/5")
 4904     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-multiple-vars-in-nested-blocks/6")
 4905     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/7")
 4906     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %eax"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/8")
 4907     (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")
 4908     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-multiple-vars-in-nested-blocks/10")
 4909     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/11")
 4910     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-multiple-vars-in-nested-blocks/12")
 4911     (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")
 4912     (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")
 4913     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-multiple-vars-in-nested-blocks/15")
 4914     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/16")
 4915     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %eax"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/17")
 4916     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-multiple-vars-in-nested-blocks/18")
 4917     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/19")
 4918     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-multiple-vars-in-nested-blocks/20")
 4919     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/21")
 4920     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-multiple-vars-in-nested-blocks/22")
 4921     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/23")
 4922     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-multiple-vars-in-nested-blocks/24")
 4923     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-multiple-vars-in-nested-blocks/25")
 4924     # . epilogue
 4925     89/<- %esp 5/r32/ebp
 4926     5d/pop-to-ebp
 4927     c3/return
 4928 
 4929 test-convert-function-with-branches-and-local-vars:
 4930     # A conditional 'break' after a 'var' in a block is converted into a
 4931     # nested block that performs all necessary cleanup before jumping. This
 4932     # results in some ugly code duplication.
 4933     # . prologue
 4934     55/push-ebp
 4935     89/<- %ebp 4/r32/esp
 4936     # setup
 4937     (clear-stream _test-input-stream)
 4938     (clear-stream $_test-input-buffered-file->buffer)
 4939     (clear-stream _test-output-stream)
 4940     (clear-stream $_test-output-buffered-file->buffer)
 4941     #
 4942     (write _test-input-stream "fn foo {\n")
 4943     (write _test-input-stream "  {\n")
 4944     (write _test-input-stream "    var x: int\n")
 4945     (write _test-input-stream "    break-if->=\n")
 4946     (write _test-input-stream "    increment x\n")
 4947     (write _test-input-stream "  }\n")
 4948     (write _test-input-stream "}\n")
 4949     # convert
 4950     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4951     (flush _test-output-buffered-file)
 4952 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4958     # check output
 4959     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-and-local-vars/0")
 4960     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-and-local-vars/1")
 4961     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-and-local-vars/2")
 4962     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-and-local-vars/3")
 4963     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-and-local-vars/4")
 4964     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-and-local-vars/5")
 4965     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-and-local-vars/6")
 4966     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-and-local-vars/7")
 4967     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-branches-and-local-vars/8")
 4968     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-and-local-vars/9")
 4969     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-and-local-vars/10")
 4970     (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")
 4971     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-and-local-vars/12")
 4972     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-and-local-vars/13")
 4973     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-branches-and-local-vars/14")
 4974     (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")
 4975     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-and-local-vars/16")
 4976     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-and-local-vars/17")
 4977     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-and-local-vars/18")
 4978     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-and-local-vars/19")
 4979     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-and-local-vars/20")
 4980     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-and-local-vars/21")
 4981     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-and-local-vars/22")
 4982     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-and-local-vars/23")
 4983     # . epilogue
 4984     89/<- %esp 5/r32/ebp
 4985     5d/pop-to-ebp
 4986     c3/return
 4987 
 4988 test-convert-function-with-conditional-loops-and-local-vars:
 4989     # A conditional 'loop' after a 'var' in a block is converted into a nested
 4990     # block that performs all necessary cleanup before jumping. This results
 4991     # in some ugly code duplication.
 4992     # . prologue
 4993     55/push-ebp
 4994     89/<- %ebp 4/r32/esp
 4995     # setup
 4996     (clear-stream _test-input-stream)
 4997     (clear-stream $_test-input-buffered-file->buffer)
 4998     (clear-stream _test-output-stream)
 4999     (clear-stream $_test-output-buffered-file->buffer)
 5000     #
 5001     (write _test-input-stream "fn foo {\n")
 5002     (write _test-input-stream "  {\n")
 5003     (write _test-input-stream "    var x: int\n")
 5004     (write _test-input-stream "    loop-if->=\n")
 5005     (write _test-input-stream "    increment x\n")
 5006     (write _test-input-stream "  }\n")
 5007     (write _test-input-stream "}\n")
 5008     # convert
 5009     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5010     (flush _test-output-buffered-file)
 5011 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5017     # check output
 5018     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-conditional-loops-and-local-vars/0")
 5019     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-conditional-loops-and-local-vars/1")
 5020     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-conditional-loops-and-local-vars/2")
 5021     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-conditional-loops-and-local-vars/3")
 5022     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-conditional-loops-and-local-vars/4")
 5023     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-conditional-loops-and-local-vars/5")
 5024     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-conditional-loops-and-local-vars/6")
 5025     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-conditional-loops-and-local-vars/7")
 5026     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-conditional-loops-and-local-vars/8")
 5027     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-conditional-loops-and-local-vars/9")
 5028     (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")
 5029     (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")
 5030     (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")
 5031     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-conditional-loops-and-local-vars/13")
 5032     (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")
 5033     (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")
 5034     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-conditional-loops-and-local-vars/16")
 5035     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-conditional-loops-and-local-vars/17")
 5036     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-conditional-loops-and-local-vars/18")
 5037     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-conditional-loops-and-local-vars/19")
 5038     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-conditional-loops-and-local-vars/20")
 5039     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-conditional-loops-and-local-vars/21")
 5040     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-conditional-loops-and-local-vars/22")
 5041     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-conditional-loops-and-local-vars/23")
 5042     # . epilogue
 5043     89/<- %esp 5/r32/ebp
 5044     5d/pop-to-ebp
 5045     c3/return
 5046 
 5047 test-convert-function-with-unconditional-loops-and-local-vars:
 5048     # An unconditional 'loop' after a 'var' in a block is emitted _after_ the
 5049     # regular block cleanup. Any instructions after 'loop' are dead and
 5050     # therefore skipped.
 5051     # . prologue
 5052     55/push-ebp
 5053     89/<- %ebp 4/r32/esp
 5054     # setup
 5055     (clear-stream _test-input-stream)
 5056     (clear-stream $_test-input-buffered-file->buffer)
 5057     (clear-stream _test-output-stream)
 5058     (clear-stream $_test-output-buffered-file->buffer)
 5059     #
 5060     (write _test-input-stream "fn foo {\n")
 5061     (write _test-input-stream "  {\n")
 5062     (write _test-input-stream "    var x: int\n")
 5063     (write _test-input-stream "    loop\n")
 5064     (write _test-input-stream "    increment x\n")
 5065     (write _test-input-stream "  }\n")
 5066     (write _test-input-stream "}\n")
 5067     # convert
 5068     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5069     (flush _test-output-buffered-file)
 5070 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5076     # check output
 5077     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-unconditional-loops-and-local-vars/0")
 5078     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-unconditional-loops-and-local-vars/1")
 5079     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-unconditional-loops-and-local-vars/2")
 5080     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-unconditional-loops-and-local-vars/3")
 5081     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-unconditional-loops-and-local-vars/4")
 5082     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-unconditional-loops-and-local-vars/5")
 5083     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-unconditional-loops-and-local-vars/6")
 5084     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-unconditional-loops-and-local-vars/7")
 5085     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-unconditional-loops-and-local-vars/8")
 5086     (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")
 5087     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-unconditional-loops-and-local-vars/10")
 5088     # not emitted:                                           ff 0/subop/increment *(ebp+0xfffffffc)
 5089     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-unconditional-loops-and-local-vars/11")
 5090     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-unconditional-loops-and-local-vars/12")
 5091     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-unconditional-loops-and-local-vars/13")
 5092     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-unconditional-loops-and-local-vars/14")
 5093     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-unconditional-loops-and-local-vars/15")
 5094     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-unconditional-loops-and-local-vars/16")
 5095     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-unconditional-loops-and-local-vars/17")
 5096     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-unconditional-loops-and-local-vars/18")
 5097     # . epilogue
 5098     89/<- %esp 5/r32/ebp
 5099     5d/pop-to-ebp
 5100     c3/return
 5101 
 5102 test-convert-function-with-branches-and-loops-and-local-vars:
 5103     # . prologue
 5104     55/push-ebp
 5105     89/<- %ebp 4/r32/esp
 5106     # setup
 5107     (clear-stream _test-input-stream)
 5108     (clear-stream $_test-input-buffered-file->buffer)
 5109     (clear-stream _test-output-stream)
 5110     (clear-stream $_test-output-buffered-file->buffer)
 5111     #
 5112     (write _test-input-stream "fn foo {\n")
 5113     (write _test-input-stream "  {\n")
 5114     (write _test-input-stream "    var x: int\n")
 5115     (write _test-input-stream "    break-if->=\n")
 5116     (write _test-input-stream "    increment x\n")
 5117     (write _test-input-stream "    loop\n")
 5118     (write _test-input-stream "  }\n")
 5119     (write _test-input-stream "}\n")
 5120     # convert
 5121     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5122     (flush _test-output-buffered-file)
 5123 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5129     # check output
 5130     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-and-loops-and-local-vars/0")
 5131     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-and-loops-and-local-vars/1")
 5132     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-and-loops-and-local-vars/2")
 5133     (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")
 5134     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-and-loops-and-local-vars/4")
 5135     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-and-loops-and-local-vars/5")
 5136     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-and-loops-and-local-vars/6")
 5137     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-and-loops-and-local-vars/7")
 5138     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-branches-and-loops-and-local-vars/8")
 5139     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-and-loops-and-local-vars/9")
 5140     (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")
 5141     (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")
 5142     (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")
 5143     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-and-loops-and-local-vars/13")
 5144     (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")
 5145     (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")
 5146     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-and-loops-and-local-vars/16")
 5147     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-and-loops-and-local-vars/17")
 5148     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-and-loops-and-local-vars/18")
 5149     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-and-loops-and-local-vars/19")
 5150     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-and-loops-and-local-vars/20")
 5151     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-and-loops-and-local-vars/21")
 5152     (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")
 5153     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-and-loops-and-local-vars/23")
 5154     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-and-loops-and-local-vars/24")
 5155     # . epilogue
 5156     89/<- %esp 5/r32/ebp
 5157     5d/pop-to-ebp
 5158     c3/return
 5159 
 5160 test-convert-function-with-nonlocal-branches-and-loops-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 "  a: {\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-if->= a\n")
 5176     (write _test-input-stream "      increment x\n")
 5177     (write _test-input-stream "      loop\n")
 5178     (write _test-input-stream "    }\n")
 5179     (write _test-input-stream "  }\n")
 5180     (write _test-input-stream "}\n")
 5181     # convert
 5182     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5183     (flush _test-output-buffered-file)
 5184 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5190     # check output
 5191     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/0")
 5192     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/1")
 5193     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/2")
 5194     (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")
 5195     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/4")
 5196     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/5")
 5197     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/6")
 5198     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/7")
 5199     (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")
 5200     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/9")
 5201     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/10")
 5202     (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")
 5203     (check-next-stream-line-equal _test-output-stream "        {"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/12")
 5204     (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")
 5205     (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")
 5206     (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")
 5207     (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")
 5208     (check-next-stream-line-equal _test-output-stream "        }"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/17")
 5209     (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")
 5210     (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")
 5211     (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")
 5212     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/21")
 5213     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/22")
 5214     (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")
 5215     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/24")
 5216     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/25")
 5217     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/26")
 5218     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/27")
 5219     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/28")
 5220     (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")
 5221     (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")
 5222     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/31")
 5223     # . epilogue
 5224     89/<- %esp 5/r32/ebp
 5225     5d/pop-to-ebp
 5226     c3/return
 5227 
 5228 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2:
 5229     # . prologue
 5230     55/push-ebp
 5231     89/<- %ebp 4/r32/esp
 5232     # setup
 5233     (clear-stream _test-input-stream)
 5234     (clear-stream $_test-input-buffered-file->buffer)
 5235     (clear-stream _test-output-stream)
 5236     (clear-stream $_test-output-buffered-file->buffer)
 5237     # non-local conditional branch from a block without a local variable,
 5238     # unwinding a local on the stack
 5239     (write _test-input-stream "fn foo {\n")
 5240     (write _test-input-stream "  a: {\n")
 5241     (write _test-input-stream "    var x: int\n")
 5242     (write _test-input-stream "    {\n")
 5243     (write _test-input-stream "      break-if->= a\n")
 5244     (write _test-input-stream "    }\n")
 5245     (write _test-input-stream "  }\n")
 5246     (write _test-input-stream "}\n")
 5247     # convert
 5248     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5249     (flush _test-output-buffered-file)
 5250 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5256     # check output
 5257     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/0")
 5258     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/1")
 5259     (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")
 5260     (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")
 5261     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/4")
 5262     (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")
 5263     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/6")
 5264     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/7")
 5265     (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")
 5266     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/9")
 5267     (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")
 5268     (check-next-stream-line-equal _test-output-stream "        {"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/11")
 5269     (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")
 5270     (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")
 5271     (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")
 5272     (check-next-stream-line-equal _test-output-stream "        }"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/15")
 5273     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/16")
 5274     (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")
 5275     (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")
 5276     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/19")
 5277     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/20")
 5278     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/21")
 5279     (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")
 5280     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/23")
 5281     (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")
 5282     (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")
 5283     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/26")
 5284     # . epilogue
 5285     89/<- %esp 5/r32/ebp
 5286     5d/pop-to-ebp
 5287     c3/return
 5288 
 5289 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3:
 5290     # . prologue
 5291     55/push-ebp
 5292     89/<- %ebp 4/r32/esp
 5293     # setup
 5294     (clear-stream _test-input-stream)
 5295     (clear-stream $_test-input-buffered-file->buffer)
 5296     (clear-stream _test-output-stream)
 5297     (clear-stream $_test-output-buffered-file->buffer)
 5298     # non-local unconditional branch from a block without a local variable,
 5299     # unwinding a local on the stack
 5300     (write _test-input-stream "fn foo {\n")
 5301     (write _test-input-stream "  a: {\n")
 5302     (write _test-input-stream "    var x: int\n")
 5303     (write _test-input-stream "    {\n")
 5304     (write _test-input-stream "      break a\n")
 5305     (write _test-input-stream "    }\n")
 5306     (write _test-input-stream "  }\n")
 5307     (write _test-input-stream "}\n")
 5308     # convert
 5309     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5310     (flush _test-output-buffered-file)
 5311 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5317     # check output
 5318     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/0")
 5319     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/1")
 5320     (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")
 5321     (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")
 5322     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/4")
 5323     (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")
 5324     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/6")
 5325     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/7")
 5326     (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")
 5327     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/9")
 5328     (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")
 5329     (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")
 5330     (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")
 5331     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/14")
 5332     (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")
 5333     (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")
 5334     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/17")
 5335     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/18")
 5336     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/19")
 5337     (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")
 5338     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/21")
 5339     (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")
 5340     (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")
 5341     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/24")
 5342     # . epilogue
 5343     89/<- %esp 5/r32/ebp
 5344     5d/pop-to-ebp
 5345     c3/return
 5346 
 5347 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4:
 5348     # . prologue
 5349     55/push-ebp
 5350     89/<- %ebp 4/r32/esp
 5351     # setup
 5352     (clear-stream _test-input-stream)
 5353     (clear-stream $_test-input-buffered-file->buffer)
 5354     (clear-stream _test-output-stream)
 5355     (clear-stream $_test-output-buffered-file->buffer)
 5356     #
 5357     (write _test-input-stream "fn foo {\n")
 5358     (write _test-input-stream "  a: {\n")
 5359     (write _test-input-stream "    var x/esi: int <- copy 0\n")
 5360     (write _test-input-stream "    {\n")
 5361     (write _test-input-stream "      break a\n")
 5362     (write _test-input-stream "    }\n")
 5363     (write _test-input-stream "  }\n")
 5364     (write _test-input-stream "}\n")
 5365     # convert
 5366     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5367     (flush _test-output-buffered-file)
 5368 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5374     # check output
 5375     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/0")
 5376     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/1")
 5377     (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")
 5378     (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")
 5379     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/4")
 5380     (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")
 5381     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/6")
 5382     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/7")
 5383     (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")
 5384     (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")
 5385     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/10")
 5386     (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")
 5387     (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")
 5388     (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")
 5389     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/14")
 5390     (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")
 5391     (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")
 5392     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/17")
 5393     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/18")
 5394     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/19")
 5395     (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")
 5396     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/21")
 5397     (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")
 5398     (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")
 5399     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/24")
 5400     # . epilogue
 5401     89/<- %esp 5/r32/ebp
 5402     5d/pop-to-ebp
 5403     c3/return
 5404 
 5405 test-convert-function-with-nonlocal-unconditional-break-and-local-vars:
 5406     # . prologue
 5407     55/push-ebp
 5408     89/<- %ebp 4/r32/esp
 5409     # setup
 5410     (clear-stream _test-input-stream)
 5411     (clear-stream $_test-input-buffered-file->buffer)
 5412     (clear-stream _test-output-stream)
 5413     (clear-stream $_test-output-buffered-file->buffer)
 5414     #
 5415     (write _test-input-stream "fn foo {\n")
 5416     (write _test-input-stream "  a: {\n")
 5417     (write _test-input-stream "    var x: int\n")
 5418     (write _test-input-stream "    {\n")
 5419     (write _test-input-stream "      var y: int\n")
 5420     (write _test-input-stream "      break a\n")
 5421     (write _test-input-stream "      increment x\n")
 5422     (write _test-input-stream "    }\n")
 5423     (write _test-input-stream "  }\n")
 5424     (write _test-input-stream "}\n")
 5425     # convert
 5426     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5427     (flush _test-output-buffered-file)
 5428 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5434     # check output
 5435     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/0")
 5436     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/1")
 5437     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/2")
 5438     (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")
 5439     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/4")
 5440     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/5")
 5441     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/6")
 5442     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/7")
 5443     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/8")
 5444     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/9")
 5445     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/10")
 5446     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/11")
 5447     (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")
 5448     (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")
 5449     (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")
 5450     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/15")
 5451     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/16")
 5452     (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")
 5453     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/18")
 5454     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/19")
 5455     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/20")
 5456     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/21")
 5457     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/22")
 5458     (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")
 5459     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/24")
 5460     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/25")
 5461     # . epilogue
 5462     89/<- %esp 5/r32/ebp
 5463     5d/pop-to-ebp
 5464     c3/return
 5465 
 5466 test-convert-function-with-unconditional-break-and-local-vars:
 5467     # . prologue
 5468     55/push-ebp
 5469     89/<- %ebp 4/r32/esp
 5470     # setup
 5471     (clear-stream _test-input-stream)
 5472     (clear-stream $_test-input-buffered-file->buffer)
 5473     (clear-stream _test-output-stream)
 5474     (clear-stream $_test-output-buffered-file->buffer)
 5475     #
 5476     (write _test-input-stream "fn foo {\n")
 5477     (write _test-input-stream "  {\n")
 5478     (write _test-input-stream "    var x: int\n")
 5479     (write _test-input-stream "    {\n")
 5480     (write _test-input-stream "      var y: int\n")
 5481     (write _test-input-stream "      break\n")
 5482     (write _test-input-stream "      increment x\n")
 5483     (write _test-input-stream "    }\n")
 5484     (write _test-input-stream "  }\n")
 5485     (write _test-input-stream "}\n")
 5486     # convert
 5487     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5488     (flush _test-output-buffered-file)
 5489 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5495     # check output
 5496     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-unconditional-break-and-local-vars/0")
 5497     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-unconditional-break-and-local-vars/1")
 5498     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-unconditional-break-and-local-vars/2")
 5499     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-unconditional-break-and-local-vars/3")
 5500     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-unconditional-break-and-local-vars/4")
 5501     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/5")
 5502     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-unconditional-break-and-local-vars/6")
 5503     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/7")
 5504     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-unconditional-break-and-local-vars/8")
 5505     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-unconditional-break-and-local-vars/9")
 5506     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/10")
 5507     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-unconditional-break-and-local-vars/11")
 5508     (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")
 5509     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-unconditional-break-and-local-vars/13")
 5510     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/14")
 5511     (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")
 5512     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-unconditional-break-and-local-vars/16")
 5513     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/17")
 5514     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-unconditional-break-and-local-vars/18")
 5515     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/19")
 5516     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-unconditional-break-and-local-vars/20")
 5517     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-unconditional-break-and-local-vars/21")
 5518     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-unconditional-break-and-local-vars/22")
 5519     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-unconditional-break-and-local-vars/23")
 5520     # . epilogue
 5521     89/<- %esp 5/r32/ebp
 5522     5d/pop-to-ebp
 5523     c3/return
 5524 
 5525 test-convert-function-with-nonlocal-unconditional-loop-and-local-vars:
 5526     # . prologue
 5527     55/push-ebp
 5528     89/<- %ebp 4/r32/esp
 5529     # setup
 5530     (clear-stream _test-input-stream)
 5531     (clear-stream $_test-input-buffered-file->buffer)
 5532     (clear-stream _test-output-stream)
 5533     (clear-stream $_test-output-buffered-file->buffer)
 5534     #
 5535     (write _test-input-stream "fn foo {\n")
 5536     (write _test-input-stream "  a: {\n")
 5537     (write _test-input-stream "    var x: int\n")
 5538     (write _test-input-stream "    {\n")
 5539     (write _test-input-stream "      var y: int\n")
 5540     (write _test-input-stream "      loop a\n")
 5541     (write _test-input-stream "      increment x\n")
 5542     (write _test-input-stream "    }\n")
 5543     (write _test-input-stream "  }\n")
 5544     (write _test-input-stream "}\n")
 5545     # convert
 5546     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5547     (flush _test-output-buffered-file)
 5548 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5554     # check output
 5555     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/0")
 5556     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/1")
 5557     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/2")
 5558     (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")
 5559     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/4")
 5560     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/5")
 5561     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/6")
 5562     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/7")
 5563     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/8")
 5564     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/9")
 5565     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/10")
 5566     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/11")
 5567     (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")
 5568     (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")
 5569     (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")
 5570     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/15")
 5571     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/16")
 5572     (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")
 5573     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/18")
 5574     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/19")
 5575     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/20")
 5576     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/21")
 5577     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/22")
 5578     (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")
 5579     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/24")
 5580     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/25")
 5581     # . epilogue
 5582     89/<- %esp 5/r32/ebp
 5583     5d/pop-to-ebp
 5584     c3/return
 5585 
 5586 test-convert-function-with-local-array-var-in-mem:
 5587     # . prologue
 5588     55/push-ebp
 5589     89/<- %ebp 4/r32/esp
 5590     # setup
 5591     (clear-stream _test-input-stream)
 5592     (clear-stream $_test-input-buffered-file->buffer)
 5593     (clear-stream _test-output-stream)
 5594     (clear-stream $_test-output-buffered-file->buffer)
 5595     #
 5596     (write _test-input-stream "fn foo {\n")
 5597     (write _test-input-stream "  var x: (array int 3)\n")
 5598     (write _test-input-stream "}\n")
 5599     # convert
 5600     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5601     (flush _test-output-buffered-file)
 5602 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5608     # check output
 5609     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-array-var-in-mem/0")
 5610     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-array-var-in-mem/1")
 5611     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-array-var-in-mem/2")
 5612     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-array-var-in-mem/3")
 5613     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-array-var-in-mem/4")
 5614     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-array-var-in-mem/5")
 5615     # define x
 5616     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"  "F - test-convert-function-with-local-array-var-in-mem/7")
 5617     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"  "F - test-convert-function-with-local-array-var-in-mem/8")
 5618     # reclaim x
 5619     (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")
 5620     #
 5621     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-array-var-in-mem/10")
 5622     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-array-var-in-mem/11")
 5623     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-array-var-in-mem/12")
 5624     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-array-var-in-mem/13")
 5625     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-array-var-in-mem/14")
 5626     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-array-var-in-mem/15")
 5627     # . epilogue
 5628     89/<- %esp 5/r32/ebp
 5629     5d/pop-to-ebp
 5630     c3/return
 5631 
 5632 test-array-size-in-hex:
 5633     # . prologue
 5634     55/push-ebp
 5635     89/<- %ebp 4/r32/esp
 5636     # setup
 5637     (clear-stream _test-input-stream)
 5638     (clear-stream $_test-input-buffered-file->buffer)
 5639     (clear-stream _test-output-stream)
 5640     (clear-stream $_test-output-buffered-file->buffer)
 5641     (clear-stream _test-error-stream)
 5642     (clear-stream $_test-error-buffered-file->buffer)
 5643     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 5644     68/push 0/imm32
 5645     68/push 0/imm32
 5646     89/<- %edx 4/r32/esp
 5647     (tailor-exit-descriptor %edx 0x10)
 5648     #
 5649     (write _test-input-stream "fn foo {\n")
 5650     (write _test-input-stream "  var x: (array int 10)\n")
 5651     (write _test-input-stream "}\n")
 5652     # convert
 5653     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 5654     # registers except esp clobbered at this point
 5655     # restore ed
 5656     89/<- %edx 4/r32/esp
 5657     (flush _test-output-buffered-file)
 5658     (flush _test-error-buffered-file)
 5659 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 5665     # check output
 5666     (check-stream-equal _test-output-stream  ""  "F - test-array-size-in-hex: output should be empty")
 5667     (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")
 5668     # check that stop(1) was called
 5669     (check-ints-equal *(edx+4) 2 "F - test-array-size-in-hex: exit status")
 5670     # don't restore from ebp
 5671     81 0/subop/add %esp 8/imm32
 5672     # . epilogue
 5673     5d/pop-to-ebp
 5674     c3/return
 5675 
 5676 test-array-size-with-metadata:
 5677     # . prologue
 5678     55/push-ebp
 5679     89/<- %ebp 4/r32/esp
 5680     # setup
 5681     (clear-stream _test-input-stream)
 5682     (clear-stream $_test-input-buffered-file->buffer)
 5683     (clear-stream _test-output-stream)
 5684     (clear-stream $_test-output-buffered-file->buffer)
 5685     #
 5686     (write _test-input-stream "fn foo {\n")
 5687     (write _test-input-stream "  var x: (array int 3/bar)\n")
 5688     (write _test-input-stream "}\n")
 5689     # convert
 5690     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5691     (flush _test-output-buffered-file)
 5692 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5698     # no errors
 5699     # . epilogue
 5700     89/<- %esp 5/r32/ebp
 5701     5d/pop-to-ebp
 5702     c3/return
 5703 
 5704 test-convert-function-with-populate:
 5705     # . prologue
 5706     55/push-ebp
 5707     89/<- %ebp 4/r32/esp
 5708     # setup
 5709     (clear-stream _test-input-stream)
 5710     (clear-stream $_test-input-buffered-file->buffer)
 5711     (clear-stream _test-output-stream)
 5712     (clear-stream $_test-output-buffered-file->buffer)
 5713     #
 5714     (write _test-input-stream "fn foo {\n")
 5715     (write _test-input-stream "  var x/ecx: (addr handle array int) <- copy 0\n")
 5716     (write _test-input-stream "  populate x, 7\n")
 5717     (write _test-input-stream "}\n")
 5718     # convert
 5719     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5720     (flush _test-output-buffered-file)
 5721 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5727     # check output
 5728     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-populate/0")
 5729     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-populate/1")
 5730     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-populate/2")
 5731     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-populate/3")
 5732     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-populate/4")
 5733     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-populate/5")
 5734     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-populate/6")
 5735     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-populate/7")
 5736     (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)
 5737     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-populate/9")
 5738     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-populate/10")
 5739     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-populate/11")
 5740     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-populate/12")
 5741     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-populate/13")
 5742     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-populate/14")
 5743     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-populate/15")
 5744     # . epilogue
 5745     89/<- %esp 5/r32/ebp
 5746     5d/pop-to-ebp
 5747     c3/return
 5748 
 5749 # special-case for size(byte) when allocating array
 5750 test-convert-function-with-local-array-of-bytes-in-mem:
 5751     # . prologue
 5752     55/push-ebp
 5753     89/<- %ebp 4/r32/esp
 5754     # setup
 5755     (clear-stream _test-input-stream)
 5756     (clear-stream $_test-input-buffered-file->buffer)
 5757     (clear-stream _test-output-stream)
 5758     (clear-stream $_test-output-buffered-file->buffer)
 5759     #
 5760     (write _test-input-stream "fn foo {\n")
 5761     (write _test-input-stream "  var x: (array byte 3)\n")
 5762     (write _test-input-stream "}\n")
 5763     # convert
 5764     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5765     (flush _test-output-buffered-file)
 5766 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5772     # check output
 5773     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-array-of-bytes-in-mem/0")
 5774     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-array-of-bytes-in-mem/1")
 5775     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-array-of-bytes-in-mem/2")
 5776     (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")
 5777     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-array-of-bytes-in-mem/4")
 5778     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-array-of-bytes-in-mem/5")
 5779     # define x
 5780     (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")
 5781     (check-next-stream-line-equal _test-output-stream "    68/push 0x00000003/imm32"  "F - test-convert-function-with-local-array-of-bytes-in-mem/8")
 5782     # reclaim x
 5783     (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")
 5784     #
 5785     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-array-of-bytes-in-mem/10")
 5786     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-array-of-bytes-in-mem/11")
 5787     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-array-of-bytes-in-mem/12")
 5788     (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")
 5789     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-array-of-bytes-in-mem/14")
 5790     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-array-of-bytes-in-mem/15")
 5791     # . epilogue
 5792     89/<- %esp 5/r32/ebp
 5793     5d/pop-to-ebp
 5794     c3/return
 5795 
 5796 test-convert-address:
 5797     # . prologue
 5798     55/push-ebp
 5799     89/<- %ebp 4/r32/esp
 5800     # setup
 5801     (clear-stream _test-input-stream)
 5802     (clear-stream $_test-input-buffered-file->buffer)
 5803     (clear-stream _test-output-stream)
 5804     (clear-stream $_test-output-buffered-file->buffer)
 5805     #
 5806     (write _test-input-stream "fn foo {\n")
 5807     (write _test-input-stream "  var a: int\n")
 5808     (write _test-input-stream "  var b/eax: (addr int) <- address a\n")
 5809     (write _test-input-stream "}\n")
 5810     # convert
 5811     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5812     (flush _test-output-buffered-file)
 5813 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5819     # check output
 5820     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-address/0")
 5821     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-address/1")
 5822     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-address/2")
 5823     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-address/3")
 5824     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-address/4")
 5825     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-address/5")
 5826     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-address/6")
 5827     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-address/7")
 5828     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0xfffffffc) 0x00000000/r32"  "F - test-convert-address/8")
 5829     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-address/9")
 5830     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-address/10")
 5831     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-address/11")
 5832     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-address/12")
 5833     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-address/13")
 5834     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-address/14")
 5835     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-address/15")
 5836     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-address/16")
 5837     # . epilogue
 5838     89/<- %esp 5/r32/ebp
 5839     5d/pop-to-ebp
 5840     c3/return
 5841 
 5842 test-convert-floating-point-convert:
 5843     # . prologue
 5844     55/push-ebp
 5845     89/<- %ebp 4/r32/esp
 5846     # setup
 5847     (clear-stream _test-input-stream)
 5848     (clear-stream $_test-input-buffered-file->buffer)
 5849     (clear-stream _test-output-stream)
 5850     (clear-stream $_test-output-buffered-file->buffer)
 5851     #
 5852     (write _test-input-stream "fn foo {\n")
 5853     (write _test-input-stream "  var a/eax: int <- copy 0\n")
 5854     (write _test-input-stream "  var b/xmm1: float <- convert a\n")
 5855     (write _test-input-stream "}\n")
 5856     # convert
 5857     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5858     (flush _test-output-buffered-file)
 5859 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5865     # check output
 5866     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-floating-point-convert/0")
 5867     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-floating-point-convert/1")
 5868     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-floating-point-convert/2")
 5869     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-floating-point-convert/3")
 5870     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-floating-point-convert/4")
 5871     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-floating-point-convert/5")
 5872     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-floating-point-convert/6")
 5873     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-floating-point-convert/7")
 5874     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"  "F - test-convert-floating-point-convert/8")
 5875     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"  "F - test-convert-floating-point-convert/9")
 5876     (check-next-stream-line-equal _test-output-stream "    f3 0f 2a/convert-to-float %eax 0x00000001/x32"  "F - test-convert-floating-point-convert/10")
 5877     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"  "F - test-convert-floating-point-convert/11")
 5878     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-floating-point-convert/12")
 5879     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-floating-point-convert/13")
 5880     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-floating-point-convert/14")
 5881     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-floating-point-convert/15")
 5882     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-floating-point-convert/16")
 5883     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-floating-point-convert/17")
 5884     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-floating-point-convert/18")
 5885     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-floating-point-convert/19")
 5886     # . epilogue
 5887     89/<- %esp 5/r32/ebp
 5888     5d/pop-to-ebp
 5889     c3/return
 5890 
 5891 test-convert-floating-point-convert-2:
 5892     # . prologue
 5893     55/push-ebp
 5894     89/<- %ebp 4/r32/esp
 5895     # setup
 5896     (clear-stream _test-input-stream)
 5897     (clear-stream $_test-input-buffered-file->buffer)
 5898     (clear-stream _test-output-stream)
 5899     (clear-stream $_test-output-buffered-file->buffer)
 5900     #
 5901     (write _test-input-stream "fn foo {\n")
 5902     (write _test-input-stream "  var a/eax: int <- copy 0\n")
 5903     (write _test-input-stream "  var b/xmm1: float <- convert a\n")
 5904     (write _test-input-stream "  a <- convert b\n")
 5905     (write _test-input-stream "}\n")
 5906     # convert
 5907     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5908     (flush _test-output-buffered-file)
 5909 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5915     # check output
 5916     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-floating-point-convert-2/0")
 5917     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-floating-point-convert-2/1")
 5918     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-floating-point-convert-2/2")
 5919     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-floating-point-convert-2/3")
 5920     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-floating-point-convert-2/4")
 5921     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-floating-point-convert-2/5")
 5922     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-floating-point-convert-2/6")
 5923     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-floating-point-convert-2/7")
 5924     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"  "F - test-convert-floating-point-convert-2/8")
 5925     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"  "F - test-convert-floating-point-convert-2/9")
 5926     (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")
 5927     (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")
 5928     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"  "F - test-convert-floating-point-convert-2/12")
 5929     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-floating-point-convert-2/13")
 5930     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-floating-point-convert-2/14")
 5931     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-floating-point-convert-2/15")
 5932     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-floating-point-convert-2/16")
 5933     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-floating-point-convert-2/17")
 5934     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-floating-point-convert-2/18")
 5935     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-floating-point-convert-2/19")
 5936     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-floating-point-convert-2/20")
 5937     # . epilogue
 5938     89/<- %esp 5/r32/ebp
 5939     5d/pop-to-ebp
 5940     c3/return
 5941 
 5942 test-convert-floating-point-operation:
 5943     # . prologue
 5944     55/push-ebp
 5945     89/<- %ebp 4/r32/esp
 5946     # setup
 5947     (clear-stream _test-input-stream)
 5948     (clear-stream $_test-input-buffered-file->buffer)
 5949     (clear-stream _test-output-stream)
 5950     (clear-stream $_test-output-buffered-file->buffer)
 5951     #
 5952     (write _test-input-stream "fn f {\n")
 5953     (write _test-input-stream "  var m: float\n")
 5954     (write _test-input-stream "  var x/xmm1: float <- copy m\n")
 5955     (write _test-input-stream "  var y/xmm5: float <- copy m\n")
 5956     (write _test-input-stream "  x <- copy y\n")
 5957     (write _test-input-stream "  copy-to m, y\n")
 5958     (write _test-input-stream "  x <- add y\n")
 5959     (write _test-input-stream "  x <- add m\n")
 5960     (write _test-input-stream "  x <- subtract y\n")
 5961     (write _test-input-stream "  x <- subtract m\n")
 5962     (write _test-input-stream "  x <- multiply y\n")
 5963     (write _test-input-stream "  x <- multiply m\n")
 5964     (write _test-input-stream "  x <- divide y\n")
 5965     (write _test-input-stream "  x <- divide m\n")
 5966     (write _test-input-stream "  x <- reciprocal y\n")
 5967     (write _test-input-stream "  x <- reciprocal m\n")
 5968     (write _test-input-stream "  x <- square-root y\n")
 5969     (write _test-input-stream "  x <- square-root m\n")
 5970     (write _test-input-stream "  x <- inverse-square-root y\n")
 5971     (write _test-input-stream "  x <- inverse-square-root m\n")
 5972     (write _test-input-stream "  x <- max y\n")
 5973     (write _test-input-stream "  x <- max m\n")
 5974     (write _test-input-stream "  x <- min y\n")
 5975     (write _test-input-stream "  x <- min m\n")
 5976     (write _test-input-stream "  compare x, y\n")
 5977     (write _test-input-stream "  compare x, m\n")
 5978     (write _test-input-stream "}\n")
 5979     # convert
 5980     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5981     (flush _test-output-buffered-file)
 5982 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5988     # check output
 5989     (check-next-stream-line-equal _test-output-stream "f:"                                                                     "F - test-convert-floating-point-operation/0")
 5990     (check-next-stream-line-equal _test-output-stream "  # . prologue"                                                         "F - test-convert-floating-point-operation/1")
 5991     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                                                          "F - test-convert-floating-point-operation/2")
 5992     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                                                 "F - test-convert-floating-point-operation/3")
 5993     (check-next-stream-line-equal _test-output-stream "  {"                                                                    "F - test-convert-floating-point-operation/4")
 5994     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"                                                    "F - test-convert-floating-point-operation/5")
 5995     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                                                    "F - test-convert-floating-point-operation/6")
 5996     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-operation/7")
 5997     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"                                             "F - test-convert-floating-point-operation/8")
 5998     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-operation/9")
 5999     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-operation/10")
 6000     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 5/x32"                                             "F - test-convert-floating-point-operation/11")
 6001     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000005/x32"                     "F - test-convert-floating-point-operation/12")
 6002     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/copy %xmm1 0x00000005/x32"                                 "F - test-convert-floating-point-operation/13")
 6003     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/copy *(ebp+0xfffffffc) 0x00000005/x32"                     "F - test-convert-floating-point-operation/14")
 6004     (check-next-stream-line-equal _test-output-stream "    f3 0f 58/add %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/15")
 6005     (check-next-stream-line-equal _test-output-stream "    f3 0f 58/add *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/16")
 6006     (check-next-stream-line-equal _test-output-stream "    f3 0f 5c/subtract %xmm5 0x00000001/x32"                             "F - test-convert-floating-point-operation/17")
 6007     (check-next-stream-line-equal _test-output-stream "    f3 0f 5c/subtract *(ebp+0xfffffffc) 0x00000001/x32"                 "F - test-convert-floating-point-operation/18")
 6008     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply %xmm5 0x00000001/x32"                             "F - test-convert-floating-point-operation/19")
 6009     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply *(ebp+0xfffffffc) 0x00000001/x32"                 "F - test-convert-floating-point-operation/20")
 6010     (check-next-stream-line-equal _test-output-stream "    f3 0f 5e/divide %xmm5 0x00000001/x32"                               "F - test-convert-floating-point-operation/21")
 6011     (check-next-stream-line-equal _test-output-stream "    f3 0f 5e/divide *(ebp+0xfffffffc) 0x00000001/x32"                   "F - test-convert-floating-point-operation/22")
 6012     (check-next-stream-line-equal _test-output-stream "    f3 0f 53/reciprocal %xmm5 0x00000001/x32"                           "F - test-convert-floating-point-operation/23")
 6013     (check-next-stream-line-equal _test-output-stream "    f3 0f 53/reciprocal *(ebp+0xfffffffc) 0x00000001/x32"               "F - test-convert-floating-point-operation/24")
 6014     (check-next-stream-line-equal _test-output-stream "    f3 0f 51/square-root %xmm5 0x00000001/x32"                          "F - test-convert-floating-point-operation/25")
 6015     (check-next-stream-line-equal _test-output-stream "    f3 0f 51/square-root *(ebp+0xfffffffc) 0x00000001/x32"              "F - test-convert-floating-point-operation/26")
 6016     (check-next-stream-line-equal _test-output-stream "    f3 0f 52/inverse-square-root %xmm5 0x00000001/x32"                  "F - test-convert-floating-point-operation/27")
 6017     (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")
 6018     (check-next-stream-line-equal _test-output-stream "    f3 0f 5f/max %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/29")
 6019     (check-next-stream-line-equal _test-output-stream "    f3 0f 5f/max *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/30")
 6020     (check-next-stream-line-equal _test-output-stream "    f3 0f 5d/min %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/31")
 6021     (check-next-stream-line-equal _test-output-stream "    f3 0f 5d/min *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/32")
 6022     (check-next-stream-line-equal _test-output-stream "    0f 2f/compare %xmm5 0x00000001/x32"                                 "F - test-convert-floating-point-operation/33")
 6023     (check-next-stream-line-equal _test-output-stream "    0f 2f/compare *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-operation/34")
 6024     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 5/x32"                                             "F - test-convert-floating-point-operation/35")
 6025     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-operation/36")
 6026     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"                                             "F - test-convert-floating-point-operation/37")
 6027     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-operation/38")
 6028     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"                               "F - test-convert-floating-point-operation/39")
 6029     (check-next-stream-line-equal _test-output-stream "  }"                                                                    "F - test-convert-floating-point-operation/40")
 6030     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"                                                   "F - test-convert-floating-point-operation/41")
 6031     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                                                         "F - test-convert-floating-point-operation/42")
 6032     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                                                 "F - test-convert-floating-point-operation/43")
 6033     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                                                        "F - test-convert-floating-point-operation/44")
 6034     (check-next-stream-line-equal _test-output-stream "  c3/return"                                                            "F - test-convert-floating-point-operation/45")
 6035     # . epilogue
 6036     89/<- %esp 5/r32/ebp
 6037     5d/pop-to-ebp
 6038     c3/return
 6039 
 6040 test-convert-floating-point-dereferenced:
 6041     # . prologue
 6042     55/push-ebp
 6043     89/<- %ebp 4/r32/esp
 6044     # setup
 6045     (clear-stream _test-input-stream)
 6046     (clear-stream $_test-input-buffered-file->buffer)
 6047     (clear-stream _test-output-stream)
 6048     (clear-stream $_test-output-buffered-file->buffer)
 6049     #
 6050     (write _test-input-stream "fn f {\n")
 6051     (write _test-input-stream "  var m: float\n")
 6052     (write _test-input-stream "  var x/xmm1: float <- copy m\n")
 6053     (write _test-input-stream "  var y/eax: (addr float) <- copy 0\n")
 6054     (write _test-input-stream "  x <- multiply *y\n")
 6055     (write _test-input-stream "}\n")
 6056     # convert
 6057     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6058     (flush _test-output-buffered-file)
 6059 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6065     # check output
 6066     (check-next-stream-line-equal _test-output-stream "f:"                                                                     "F - test-convert-floating-point-dereferenced/0")
 6067     (check-next-stream-line-equal _test-output-stream "  # . prologue"                                                         "F - test-convert-floating-point-dereferenced/1")
 6068     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                                                          "F - test-convert-floating-point-dereferenced/2")
 6069     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                                                 "F - test-convert-floating-point-dereferenced/3")
 6070     (check-next-stream-line-equal _test-output-stream "  {"                                                                    "F - test-convert-floating-point-dereferenced/4")
 6071     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"                                                    "F - test-convert-floating-point-dereferenced/5")
 6072     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                                                    "F - test-convert-floating-point-dereferenced/6")
 6073     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-dereferenced/7")
 6074     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"                                             "F - test-convert-floating-point-dereferenced/8")
 6075     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-dereferenced/9")
 6076     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                                               "F - test-convert-floating-point-dereferenced/10")
 6077     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                                             "F - test-convert-floating-point-dereferenced/11")
 6078     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply *eax 0x00000001/x32"                              "F - test-convert-floating-point-dereferenced/12")
 6079     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                                                "F - test-convert-floating-point-dereferenced/13")
 6080     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"                                             "F - test-convert-floating-point-dereferenced/14")
 6081     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-dereferenced/15")
 6082     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"                               "F - test-convert-floating-point-dereferenced/16")
 6083     (check-next-stream-line-equal _test-output-stream "  }"                                                                    "F - test-convert-floating-point-dereferenced/17")
 6084     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"                                                   "F - test-convert-floating-point-dereferenced/18")
 6085     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                                                         "F - test-convert-floating-point-dereferenced/19")
 6086     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                                                 "F - test-convert-floating-point-dereferenced/20")
 6087     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                                                        "F - test-convert-floating-point-dereferenced/21")
 6088     (check-next-stream-line-equal _test-output-stream "  c3/return"                                                            "F - test-convert-floating-point-dereferenced/22")
 6089     # . epilogue
 6090     89/<- %esp 5/r32/ebp
 6091     5d/pop-to-ebp
 6092     c3/return
 6093 
 6094 test-convert-length-of-array:
 6095     # . prologue
 6096     55/push-ebp
 6097     89/<- %ebp 4/r32/esp
 6098     # setup
 6099     (clear-stream _test-input-stream)
 6100     (clear-stream $_test-input-buffered-file->buffer)
 6101     (clear-stream _test-output-stream)
 6102     (clear-stream $_test-output-buffered-file->buffer)
 6103     #
 6104     (write _test-input-stream "fn foo a: (addr array int) {\n")
 6105     (write _test-input-stream "  var b/eax: (addr array int) <- copy a\n")
 6106     (write _test-input-stream "  var c/eax: int <- length b\n")
 6107     (write _test-input-stream "}\n")
 6108     # convert
 6109     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6110     (flush _test-output-buffered-file)
 6111 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6117     # check output
 6118     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array/0")
 6119     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array/1")
 6120     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array/2")
 6121     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array/3")
 6122     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array/4")
 6123     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array/5")
 6124     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array/6")
 6125     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-length-of-array/7")
 6126     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array/8")
 6127     (check-next-stream-line-equal _test-output-stream "    c1/shift 5/subop/>> %eax 0x00000002/imm8"  "F - test-convert-length-of-array/9")
 6128     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array/10")
 6129     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array/11")
 6130     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array/12")
 6131     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array/13")
 6132     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array/14")
 6133     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array/15")
 6134     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array/16")
 6135     # . epilogue
 6136     89/<- %esp 5/r32/ebp
 6137     5d/pop-to-ebp
 6138     c3/return
 6139 
 6140 # special-case for size(byte) when computing array length
 6141 test-convert-length-of-array-of-bytes:
 6142     # . prologue
 6143     55/push-ebp
 6144     89/<- %ebp 4/r32/esp
 6145     # setup
 6146     (clear-stream _test-input-stream)
 6147     (clear-stream $_test-input-buffered-file->buffer)
 6148     (clear-stream _test-output-stream)
 6149     (clear-stream $_test-output-buffered-file->buffer)
 6150     #
 6151     (write _test-input-stream "fn foo a: (addr array byte) {\n")
 6152     (write _test-input-stream "  var b/eax: (addr array byte) <- copy a\n")
 6153     (write _test-input-stream "  var c/eax: int <- length b\n")
 6154     (write _test-input-stream "}\n")
 6155     # convert
 6156     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6157     (flush _test-output-buffered-file)
 6158 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6164     # check output
 6165     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-bytes/0")
 6166     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-bytes/1")
 6167     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-bytes/2")
 6168     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-bytes/3")
 6169     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-bytes/4")
 6170     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-bytes/5")
 6171     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-of-bytes/6")
 6172     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-length-of-array-of-bytes/7")
 6173     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array-of-bytes/8")
 6174     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-of-bytes/9")
 6175     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-bytes/10")
 6176     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-bytes/11")
 6177     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-bytes/12")
 6178     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-of-bytes/13")
 6179     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-of-bytes/14")
 6180     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-bytes/15")
 6181     # . epilogue
 6182     89/<- %esp 5/r32/ebp
 6183     5d/pop-to-ebp
 6184     c3/return
 6185 
 6186 test-convert-length-of-array-on-stack:
 6187     # . prologue
 6188     55/push-ebp
 6189     89/<- %ebp 4/r32/esp
 6190     # setup
 6191     (clear-stream _test-input-stream)
 6192     (clear-stream $_test-input-buffered-file->buffer)
 6193     (clear-stream _test-output-stream)
 6194     (clear-stream $_test-output-buffered-file->buffer)
 6195     #
 6196     (write _test-input-stream "fn foo {\n")
 6197     (write _test-input-stream "  var a: (array int 3)\n")
 6198     (write _test-input-stream "  var b/eax: int <- length a\n")
 6199     (write _test-input-stream "}\n")
 6200     # convert
 6201     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6202     (flush _test-output-buffered-file)
 6203 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6209     # check output
 6210     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-on-stack/0")
 6211     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-on-stack/1")
 6212     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-on-stack/2")
 6213     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-on-stack/3")
 6214     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-on-stack/4")
 6215     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-on-stack/5")
 6216     # define x
 6217     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"  "F - test-convert-length-of-array-on-stack/6")
 6218     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"  "F - test-convert-length-of-array-on-stack/7")
 6219     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-on-stack/8")
 6220     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0xfffffff0) 0x00000000/r32"  "F - test-convert-length-of-array-on-stack/9")
 6221     (check-next-stream-line-equal _test-output-stream "    c1/shift 5/subop/>> %eax 0x00000002/imm8"  "F - test-convert-length-of-array-on-stack/10")
 6222     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-on-stack/11")
 6223     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"  "F - test-convert-length-of-array-on-stack/12")
 6224     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-on-stack/13")
 6225     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-on-stack/14")
 6226     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-on-stack/15")
 6227     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-on-stack/16")
 6228     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-on-stack/17")
 6229     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-on-stack/18")
 6230     # . epilogue
 6231     89/<- %esp 5/r32/ebp
 6232     5d/pop-to-ebp
 6233     c3/return
 6234 
 6235 test-reg-var-def-with-read-of-same-register:
 6236     # . prologue
 6237     55/push-ebp
 6238     89/<- %ebp 4/r32/esp
 6239     # setup
 6240     (clear-stream _test-input-stream)
 6241     (clear-stream $_test-input-buffered-file->buffer)
 6242     (clear-stream _test-output-stream)
 6243     (clear-stream $_test-output-buffered-file->buffer)
 6244     (clear-stream _test-error-stream)
 6245     (clear-stream $_test-error-buffered-file->buffer)
 6246     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
 6247     68/push 0/imm32
 6248     68/push 0/imm32
 6249     89/<- %edx 4/r32/esp
 6250     (tailor-exit-descriptor %edx 0x10)
 6251     #
 6252     (write _test-input-stream "fn foo {\n")
 6253     (write _test-input-stream "  var x/eax: int <- copy 3\n")
 6254     (write _test-input-stream "  var y/eax: int <- add x\n")
 6255     (write _test-input-stream "}\n")
 6256     # convert
 6257     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6258     # registers except esp could be clobbered at this point (though they shouldn't be)
 6259     # restore ed
 6260     89/<- %edx 4/r32/esp
 6261     (flush _test-output-buffered-file)
 6262     (flush _test-error-buffered-file)
 6263 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6269 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 6275     (check-stream-equal _test-error-stream  ""  "F - test-reg-var-def-with-read-of-same-register: error stream should be empty")
 6276     # check output
 6277     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-reg-var-def-with-read-of-same-register/0")
 6278     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-reg-var-def-with-read-of-same-register/1")
 6279     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-reg-var-def-with-read-of-same-register/2")
 6280     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-reg-var-def-with-read-of-same-register/3")
 6281     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-reg-var-def-with-read-of-same-register/4")
 6282     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-reg-var-def-with-read-of-same-register/5")
 6283     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-reg-var-def-with-read-of-same-register/6")
 6284     (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")
 6285     (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")
 6286     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-reg-var-def-with-read-of-same-register/9")
 6287     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-reg-var-def-with-read-of-same-register/10")
 6288     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-reg-var-def-with-read-of-same-register/11")
 6289     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-reg-var-def-with-read-of-same-register/12")
 6290     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-reg-var-def-with-read-of-same-register/13")
 6291     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-reg-var-def-with-read-of-same-register/14")
 6292     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-reg-var-def-with-read-of-same-register/15")
 6293     # don't restore from ebp
 6294     81 0/subop/add %esp 8/imm32
 6295     # . epilogue
 6296     5d/pop-to-ebp
 6297     c3/return
 6298 
 6299 test-convert-index-into-array:
 6300     # . prologue
 6301     55/push-ebp
 6302     89/<- %ebp 4/r32/esp
 6303     # setup
 6304     (clear-stream _test-input-stream)
 6305     (clear-stream $_test-input-buffered-file->buffer)
 6306     (clear-stream _test-output-stream)
 6307     (clear-stream $_test-output-buffered-file->buffer)
 6308     #
 6309     (write _test-input-stream "fn foo {\n")
 6310     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 6311     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 6312     (write _test-input-stream "  var x/eax: (addr int) <- index arr, idx\n")
 6313     (write _test-input-stream "}\n")
 6314     # convert
 6315     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6316     (flush _test-output-buffered-file)
 6317 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6323     # check output
 6324     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array/0")
 6325     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array/1")
 6326     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array/2")
 6327     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array/3")
 6328     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array/4")
 6329     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array/5")
 6330     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array/6")
 6331     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array/7")
 6332     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array/8")
 6333     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array/9")
 6334     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 0x00000004 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array/10")
 6335     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-index-into-array/11")
 6336     (check-next-stream-line-equal _test-output-stream "    0f 84/jump-if-= __mu-abort-null-index-base-address/disp32"  "F - test-convert-index-into-array/12")
 6337     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx<<0x00000002 + 4) 0x00000000/r32"  "F - test-convert-index-into-array/13")
 6338     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array/14")
 6339     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array/15")
 6340     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array/16")
 6341     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array/17")
 6342     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array/18")
 6343     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array/19")
 6344     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array/20")
 6345     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array/21")
 6346     # . epilogue
 6347     89/<- %esp 5/r32/ebp
 6348     5d/pop-to-ebp
 6349     c3/return
 6350 
 6351 test-convert-index-into-array-of-bytes:
 6352     # . prologue
 6353     55/push-ebp
 6354     89/<- %ebp 4/r32/esp
 6355     # setup
 6356     (clear-stream _test-input-stream)
 6357     (clear-stream $_test-input-buffered-file->buffer)
 6358     (clear-stream _test-output-stream)
 6359     (clear-stream $_test-output-buffered-file->buffer)
 6360     #
 6361     (write _test-input-stream "fn foo {\n")
 6362     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 6363     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 6364     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, idx\n")
 6365     (write _test-input-stream "}\n")
 6366     # convert
 6367     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6368     (flush _test-output-buffered-file)
 6369 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6375     # check output
 6376     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes/0")
 6377     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes/1")
 6378     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes/2")
 6379     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes/3")
 6380     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes/4")
 6381     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes/5")
 6382     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes/6")
 6383     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-of-bytes/7")
 6384     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-of-bytes/8")
 6385     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array-of-bytes/9")
 6386     (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")
 6387     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-index-into-array-of-bytes/11")
 6388     (check-next-stream-line-equal _test-output-stream "    0f 84/jump-if-= __mu-abort-null-index-base-address/disp32"  "F - test-convert-index-into-array-of-bytes/12")
 6389     (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/13")
 6390     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes/14")
 6391     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes/15")
 6392     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes/16")
 6393     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes/17")
 6394     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes/18")
 6395     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes/19")
 6396     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes/20")
 6397     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes/21")
 6398     # . epilogue
 6399     89/<- %esp 5/r32/ebp
 6400     5d/pop-to-ebp
 6401     c3/return
 6402 
 6403 test-convert-index-into-array-with-literal:
 6404     # . prologue
 6405     55/push-ebp
 6406     89/<- %ebp 4/r32/esp
 6407     # setup
 6408     (clear-stream _test-input-stream)
 6409     (clear-stream $_test-input-buffered-file->buffer)
 6410     (clear-stream _test-output-stream)
 6411     (clear-stream $_test-output-buffered-file->buffer)
 6412     #
 6413     (write _test-input-stream "fn foo {\n")
 6414     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 6415     (write _test-input-stream "  var x/eax: (addr int) <- index arr, 2\n")
 6416     (write _test-input-stream "}\n")
 6417     # convert
 6418     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6419     (flush _test-output-buffered-file)
 6420 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6426     # check output
 6427     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-with-literal/0")
 6428     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-with-literal/1")
 6429     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-with-literal/2")
 6430     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-with-literal/3")
 6431     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-with-literal/4")
 6432     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-with-literal/5")
 6433     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-with-literal/6")
 6434     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-with-literal/7")
 6435     (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")
 6436     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-index-into-array-with-literal/9")
 6437     (check-next-stream-line-equal _test-output-stream "    0f 84/jump-if-= __mu-abort-null-index-base-address/disp32"  "F - test-convert-index-into-array-with-literal/10")
 6438                                                                                  # 2 * 4 bytes/elem + 4 bytes for size = offset 12
 6439     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x0000000c) 0x00000000/r32"  "F - test-convert-index-into-array-with-literal/11")
 6440     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-with-literal/12")
 6441     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-with-literal/13")
 6442     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-with-literal/14")
 6443     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-with-literal/15")
 6444     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-with-literal/16")
 6445     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-with-literal/17")
 6446     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-with-literal/18")
 6447     # . epilogue
 6448     89/<- %esp 5/r32/ebp
 6449     5d/pop-to-ebp
 6450     c3/return
 6451 
 6452 test-convert-index-into-array-of-bytes-with-literal:
 6453     # . prologue
 6454     55/push-ebp
 6455     89/<- %ebp 4/r32/esp
 6456     # setup
 6457     (clear-stream _test-input-stream)
 6458     (clear-stream $_test-input-buffered-file->buffer)
 6459     (clear-stream _test-output-stream)
 6460     (clear-stream $_test-output-buffered-file->buffer)
 6461     #
 6462     (write _test-input-stream "fn foo {\n")
 6463     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 6464     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, 2\n")
 6465     (write _test-input-stream "}\n")
 6466     # convert
 6467     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6468     (flush _test-output-buffered-file)
 6469 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6475     # check output
 6476     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-with-literal/0")
 6477     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-with-literal/1")
 6478     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-with-literal/2")
 6479     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes-with-literal/3")
 6480     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-with-literal/4")
 6481     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-with-literal/5")
 6482     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes-with-literal/6")
 6483     (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")
 6484     (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")
 6485     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-index-into-array-of-bytes-with-literal/9")
 6486     (check-next-stream-line-equal _test-output-stream "    0f 84/jump-if-= __mu-abort-null-index-base-address/disp32"  "F - test-convert-index-into-array-of-bytes-with-literal/10")
 6487                                                                                  # 2 * 1 byte/elem + 4 bytes for size = offset 6
 6488     (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/11")
 6489     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-with-literal/12")
 6490     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-with-literal/13")
 6491     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-with-literal/14")
 6492     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-with-literal/15")
 6493     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-with-literal/16")
 6494     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-with-literal/17")
 6495     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-with-literal/18")
 6496     # . epilogue
 6497     89/<- %esp 5/r32/ebp
 6498     5d/pop-to-ebp
 6499     c3/return
 6500 
 6501 test-convert-index-into-array-on-stack:
 6502     # . prologue
 6503     55/push-ebp
 6504     89/<- %ebp 4/r32/esp
 6505     # setup
 6506     (clear-stream _test-input-stream)
 6507     (clear-stream $_test-input-buffered-file->buffer)
 6508     (clear-stream _test-output-stream)
 6509     (clear-stream $_test-output-buffered-file->buffer)
 6510     #
 6511     (write _test-input-stream "fn foo {\n")
 6512     (write _test-input-stream "  var arr: (array int 3)\n")
 6513     (write _test-input-stream "  var idx/eax: int <- copy 2\n")
 6514     (write _test-input-stream "  var x/eax: (addr int) <- index arr, idx\n")
 6515     (write _test-input-stream "}\n")
 6516     # convert
 6517     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6518     (flush _test-output-buffered-file)
 6519 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6525     # check output
 6526     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-on-stack/0")
 6527     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-on-stack/1")
 6528     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-on-stack/2")
 6529     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-on-stack/3")
 6530     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-on-stack/4")
 6531     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-on-stack/5")
 6532     # var arr
 6533     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"          "F - test-convert-index-into-array-on-stack/6")
 6534     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"                "F - test-convert-index-into-array-on-stack/7")
 6535     # var idx
 6536     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-on-stack/8")
 6537     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 2/imm32"                  "F - test-convert-index-into-array-on-stack/9")
 6538     (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")
 6539     # var x is at (ebp-0x10) + idx<<2 + 4 = ebp + idx<<2 - 0xc
 6540     (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")
 6541     # reclaim idx
 6542     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-on-stack/12")
 6543     # reclaim arr
 6544     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"    "F - test-convert-index-into-array-on-stack/13")
 6545     #
 6546     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-on-stack/14")
 6547     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-on-stack/15")
 6548     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-on-stack/16")
 6549     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-on-stack/17")
 6550     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-on-stack/18")
 6551     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-on-stack/19")
 6552     # . epilogue
 6553     89/<- %esp 5/r32/ebp
 6554     5d/pop-to-ebp
 6555     c3/return
 6556 
 6557 test-convert-index-into-array-on-stack-with-literal:
 6558     # . prologue
 6559     55/push-ebp
 6560     89/<- %ebp 4/r32/esp
 6561     # setup
 6562     (clear-stream _test-input-stream)
 6563     (clear-stream $_test-input-buffered-file->buffer)
 6564     (clear-stream _test-output-stream)
 6565     (clear-stream $_test-output-buffered-file->buffer)
 6566     #
 6567     (write _test-input-stream "fn foo {\n")
 6568     (write _test-input-stream "  var arr: (array int 3)\n")
 6569     (write _test-input-stream "  var x/eax: (addr int) <- index arr, 2\n")
 6570     (write _test-input-stream "}\n")
 6571     # convert
 6572     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6573     (flush _test-output-buffered-file)
 6574 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6580     # check output
 6581     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-on-stack-with-literal/0")
 6582     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-on-stack-with-literal/1")
 6583     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-on-stack-with-literal/2")
 6584     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-on-stack-with-literal/3")
 6585     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-on-stack-with-literal/4")
 6586     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-on-stack-with-literal/5")
 6587     # var arr
 6588     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"          "F - test-convert-index-into-array-on-stack-with-literal/6")
 6589     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"                "F - test-convert-index-into-array-on-stack-with-literal/7")
 6590     # var x
 6591     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-on-stack-with-literal/8")
 6592     (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")
 6593     # x is at (ebp-0x10) + 4 + 2*4 = ebp-4
 6594     (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")
 6595     # reclaim x
 6596     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-on-stack-with-literal/11")
 6597     # reclaim arr
 6598     (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")
 6599     #
 6600     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-on-stack-with-literal/13")
 6601     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-on-stack-with-literal/14")
 6602     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-on-stack-with-literal/15")
 6603     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-on-stack-with-literal/16")
 6604     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-on-stack-with-literal/17")
 6605     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-on-stack-with-literal/18")
 6606     # . epilogue
 6607     89/<- %esp 5/r32/ebp
 6608     5d/pop-to-ebp
 6609     c3/return
 6610 
 6611 test-convert-index-into-array-of-bytes-on-stack-with-literal:
 6612     # . prologue
 6613     55/push-ebp
 6614     89/<- %ebp 4/r32/esp
 6615     # setup
 6616     (clear-stream _test-input-stream)
 6617     (clear-stream $_test-input-buffered-file->buffer)
 6618     (clear-stream _test-output-stream)
 6619     (clear-stream $_test-output-buffered-file->buffer)
 6620     #
 6621     (write _test-input-stream "fn foo {\n")
 6622     (write _test-input-stream "  var arr: (array byte 3)\n")
 6623     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, 2\n")
 6624     (write _test-input-stream "}\n")
 6625     # convert
 6626     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6627     (flush _test-output-buffered-file)
 6628 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6634     # check output
 6635     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/0")
 6636     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/1")
 6637     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/2")
 6638     (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")
 6639     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/4")
 6640     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/5")
 6641     # var arr
 6642     (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")
 6643     (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")
 6644     # var x
 6645     (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")
 6646     (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")
 6647     # x is at (ebp-7) + 4 + 2 = ebp-1
 6648     (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")
 6649     # reclaim x
 6650     (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")
 6651     # reclaim arr
 6652     (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")
 6653     #
 6654     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/13")
 6655     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/14")
 6656     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/15")
 6657     (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")
 6658     (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")
 6659     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/18")
 6660     # . epilogue
 6661     89/<- %esp 5/r32/ebp
 6662     5d/pop-to-ebp
 6663     c3/return
 6664 
 6665 test-convert-index-into-array-using-offset:
 6666     # . prologue
 6667     55/push-ebp
 6668     89/<- %ebp 4/r32/esp
 6669     # setup
 6670     (clear-stream _test-input-stream)
 6671     (clear-stream $_test-input-buffered-file->buffer)
 6672     (clear-stream _test-output-stream)
 6673     (clear-stream $_test-output-buffered-file->buffer)
 6674     #
 6675     (write _test-input-stream "fn foo {\n")
 6676     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 6677     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 6678     (write _test-input-stream "  var off/ecx: (offset int) <- compute-offset arr, idx\n")
 6679     (write _test-input-stream "  var x/eax: (addr int) <- index arr, off\n")
 6680     (write _test-input-stream "}\n")
 6681     # convert
 6682     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6683     (flush _test-output-buffered-file)
 6684 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6690     # check output
 6691     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-using-offset/0")
 6692     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-using-offset/1")
 6693     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-using-offset/2")
 6694     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-using-offset/3")
 6695     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-using-offset/4")
 6696     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-using-offset/5")
 6697     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-using-offset/6")
 6698     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-using-offset/7")
 6699     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-using-offset/8")
 6700     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array-using-offset/9")
 6701     (check-next-stream-line-equal _test-output-stream "    69/multiply %ecx 0x00000004/imm32 0x00000001/r32"  "F - test-convert-index-into-array-using-offset/10")
 6702     (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")
 6703     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-index-into-array-using-offset/12")
 6704     (check-next-stream-line-equal _test-output-stream "    0f 84/jump-if-= __mu-abort-null-index-base-address/disp32"  "F - test-convert-index-into-array-using-offset/13")
 6705     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx + 4) 0x00000000/r32"  "F - test-convert-index-into-array-using-offset/15")
 6706     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-using-offset/16")
 6707     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-using-offset/17")
 6708     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-using-offset/18")
 6709     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-using-offset/19")
 6710     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-using-offset/20")
 6711     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-using-offset/21")
 6712     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-using-offset/22")
 6713     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-using-offset/23")
 6714     # . epilogue
 6715     89/<- %esp 5/r32/ebp
 6716     5d/pop-to-ebp
 6717     c3/return
 6718 
 6719 test-convert-index-into-array-of-bytes-using-offset:
 6720     # . prologue
 6721     55/push-ebp
 6722     89/<- %ebp 4/r32/esp
 6723     # setup
 6724     (clear-stream _test-input-stream)
 6725     (clear-stream $_test-input-buffered-file->buffer)
 6726     (clear-stream _test-output-stream)
 6727     (clear-stream $_test-output-buffered-file->buffer)
 6728     #
 6729     (write _test-input-stream "fn foo {\n")
 6730     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 6731     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 6732     (write _test-input-stream "  var off/ecx: (offset byte) <- compute-offset arr, idx\n")
 6733     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, off\n")
 6734     (write _test-input-stream "}\n")
 6735     # convert
 6736     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6737     (flush _test-output-buffered-file)
 6738 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6744     # check output
 6745     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-using-offset/0")
 6746     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-using-offset/1")
 6747     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-using-offset/2")
 6748     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes-using-offset/3")
 6749     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-using-offset/4")
 6750     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-using-offset/5")
 6751     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes-using-offset/6")
 6752     (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")
 6753     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-of-bytes-using-offset/8")
 6754     (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")
 6755     (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")
 6756     (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")
 6757     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-index-into-array-of-bytes-using-offset/12")
 6758     (check-next-stream-line-equal _test-output-stream "    0f 84/jump-if-= __mu-abort-null-index-base-address/disp32"  "F - test-convert-index-into-array-of-bytes-using-offset/13")
 6759     (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/14")
 6760     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes-using-offset/15")
 6761     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-using-offset/16")
 6762     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-using-offset/17")
 6763     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-using-offset/18")
 6764     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-using-offset/19")
 6765     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-using-offset/20")
 6766     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-using-offset/21")
 6767     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-using-offset/22")
 6768     # . epilogue
 6769     89/<- %esp 5/r32/ebp
 6770     5d/pop-to-ebp
 6771     c3/return
 6772 
 6773 test-convert-index-into-array-using-offset-on-stack:
 6774     # . prologue
 6775     55/push-ebp
 6776     89/<- %ebp 4/r32/esp
 6777     # setup
 6778     (clear-stream _test-input-stream)
 6779     (clear-stream $_test-input-buffered-file->buffer)
 6780     (clear-stream _test-output-stream)
 6781     (clear-stream $_test-output-buffered-file->buffer)
 6782     #
 6783     (write _test-input-stream "fn foo {\n")
 6784     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 6785     (write _test-input-stream "  var idx: int\n")
 6786     (write _test-input-stream "  var off/ecx: (offset int) <- compute-offset arr, idx\n")
 6787     (write _test-input-stream "  var x/eax: (addr int) <- index arr, off\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 "foo:"                                        "F - test-convert-index-into-array-using-offset-on-stack/0")
 6800     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-using-offset-on-stack/1")
 6801     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-using-offset-on-stack/2")
 6802     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-using-offset-on-stack/3")
 6803     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-using-offset-on-stack/4")
 6804     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-using-offset-on-stack/5")
 6805     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-using-offset-on-stack/6")
 6806     (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")
 6807     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                         "F - test-convert-index-into-array-using-offset-on-stack/8")
 6808     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-using-offset-on-stack/9")
 6809     (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")
 6810     (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")
 6811     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-index-into-array-using-offset-on-stack/12")
 6812     (check-next-stream-line-equal _test-output-stream "    0f 84/jump-if-= __mu-abort-null-index-base-address/disp32"  "F - test-convert-index-into-array-using-offset-on-stack/13")
 6813     (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/14")
 6814     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-using-offset-on-stack/15")
 6815     (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/16")
 6816     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-using-offset-on-stack/17")
 6817     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-using-offset-on-stack/18")
 6818     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-using-offset-on-stack/19")
 6819     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-using-offset-on-stack/20")
 6820     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-using-offset-on-stack/21")
 6821     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-using-offset-on-stack/22")
 6822     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-using-offset-on-stack/23")
 6823     # . epilogue
 6824     89/<- %esp 5/r32/ebp
 6825     5d/pop-to-ebp
 6826     c3/return
 6827 
 6828 test-convert-index-into-array-of-bytes-using-offset-on-stack:
 6829     # . prologue
 6830     55/push-ebp
 6831     89/<- %ebp 4/r32/esp
 6832     # setup
 6833     (clear-stream _test-input-stream)
 6834     (clear-stream $_test-input-buffered-file->buffer)
 6835     (clear-stream _test-output-stream)
 6836     (clear-stream $_test-output-buffered-file->buffer)
 6837     #
 6838     (write _test-input-stream "fn foo {\n")
 6839     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 6840     (write _test-input-stream "  var idx: int\n")
 6841     (write _test-input-stream "  var off/ecx: (offset byte) <- compute-offset arr, idx\n")
 6842     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, off\n")
 6843     (write _test-input-stream "}\n")
 6844     # convert
 6845     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6846     (flush _test-output-buffered-file)
 6847 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6853     # check output
 6854     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/0")
 6855     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/1")
 6856     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/2")
 6857     (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")
 6858     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/4")
 6859     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/5")
 6860     (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")
 6861     (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")
 6862     (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")
 6863     (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")
 6864     (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")
 6865     (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")
 6866     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/12")
 6867     (check-next-stream-line-equal _test-output-stream "    0f 84/jump-if-= __mu-abort-null-index-base-address/disp32"  "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/13")
 6868     (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/14")
 6869     (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/15")
 6870     (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/16")
 6871     (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/17")
 6872     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/18")
 6873     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/19")
 6874     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/20")
 6875     (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/21")
 6876     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/22")
 6877     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/23")
 6878     # . epilogue
 6879     89/<- %esp 5/r32/ebp
 6880     5d/pop-to-ebp
 6881     c3/return
 6882 
 6883 test-convert-function-and-type-definition:
 6884     # . prologue
 6885     55/push-ebp
 6886     89/<- %ebp 4/r32/esp
 6887     # setup
 6888     (clear-stream _test-input-stream)
 6889     (clear-stream $_test-input-buffered-file->buffer)
 6890     (clear-stream _test-output-stream)
 6891     (clear-stream $_test-output-buffered-file->buffer)
 6892     #
 6893     (write _test-input-stream "fn foo a: (addr t) {\n")
 6894     (write _test-input-stream "  var _a/eax: (addr t) <- copy a\n")
 6895     (write _test-input-stream "  var b/ecx: (addr int) <- get _a, x\n")
 6896     (write _test-input-stream "  var c/ecx: (addr int) <- get _a, y\n")
 6897     (write _test-input-stream "}\n")
 6898     (write _test-input-stream "type t {\n")
 6899     (write _test-input-stream "  x: int\n")
 6900     (write _test-input-stream "  y: int\n")
 6901     (write _test-input-stream "}\n")
 6902     # convert
 6903     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6904     (flush _test-output-buffered-file)
 6905 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6911     # check output
 6912     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-and-type-definition/0")
 6913     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-and-type-definition/1")
 6914     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-and-type-definition/2")
 6915     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-and-type-definition/3")
 6916     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-and-type-definition/4")
 6917     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-and-type-definition/5")
 6918     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-and-type-definition/6")
 6919     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-and-type-definition/7")
 6920     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-and-type-definition/8")
 6921     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-function-and-type-definition/9")
 6922     (check-next-stream-line-equal _test-output-stream "    0f 84/jump-if-= __mu-abort-null-get-base-address/disp32"  "F - test-convert-function-and-type-definition/10")
 6923     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x00000000) 0x00000001/r32"  "F - test-convert-function-and-type-definition/11")
 6924     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-function-and-type-definition/12")
 6925     (check-next-stream-line-equal _test-output-stream "    0f 84/jump-if-= __mu-abort-null-get-base-address/disp32"  "F - test-convert-function-and-type-definition/13")
 6926     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x00000004) 0x00000001/r32"  "F - test-convert-function-and-type-definition/14")
 6927     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-and-type-definition/15")
 6928     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-and-type-definition/16")
 6929     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-and-type-definition/17")
 6930     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-and-type-definition/18")
 6931     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-and-type-definition/19")
 6932     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-and-type-definition/20")
 6933     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-and-type-definition/21")
 6934     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-and-type-definition/22")
 6935     # . epilogue
 6936     89/<- %esp 5/r32/ebp
 6937     5d/pop-to-ebp
 6938     c3/return
 6939 
 6940 test-type-definition-with-array:
 6941     # . prologue
 6942     55/push-ebp
 6943     89/<- %ebp 4/r32/esp
 6944     # setup
 6945     (clear-stream _test-input-stream)
 6946     (clear-stream $_test-input-buffered-file->buffer)
 6947     (clear-stream _test-output-stream)
 6948     (clear-stream $_test-output-buffered-file->buffer)
 6949     (clear-stream _test-error-stream)
 6950     (clear-stream $_test-error-buffered-file->buffer)
 6951     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6952     68/push 0/imm32
 6953     68/push 0/imm32
 6954     89/<- %edx 4/r32/esp
 6955     (tailor-exit-descriptor %edx 0x10)
 6956     #
 6957     (write _test-input-stream "type t {\n")
 6958     (write _test-input-stream "  a: (array int 3)\n")
 6959     (write _test-input-stream "}\n")
 6960     # convert
 6961     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6962     # registers except esp clobbered at this point
 6963     # restore ed
 6964     89/<- %edx 4/r32/esp
 6965     (flush _test-output-buffered-file)
 6966     (flush _test-error-buffered-file)
 6967 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 6973     # check output
 6974     (check-stream-equal _test-output-stream  ""  "F - test-type-definition-with-array: output should be empty")
 6975     (check-next-stream-line-equal _test-error-stream  "type t: 'array' elements not allowed for now"  "F - test-type-definition-with-array: error message")
 6976     # check that stop(1) was called
 6977     (check-ints-equal *(edx+4) 2 "F - test-type-definition-with-array: exit status")
 6978     # don't restore from ebp
 6979     81 0/subop/add %esp 8/imm32
 6980     # . epilogue
 6981     5d/pop-to-ebp
 6982     c3/return
 6983 
 6984 test-type-definition-with-addr:
 6985     # . prologue
 6986     55/push-ebp
 6987     89/<- %ebp 4/r32/esp
 6988     # setup
 6989     (clear-stream _test-input-stream)
 6990     (clear-stream $_test-input-buffered-file->buffer)
 6991     (clear-stream _test-output-stream)
 6992     (clear-stream $_test-output-buffered-file->buffer)
 6993     (clear-stream _test-error-stream)
 6994     (clear-stream $_test-error-buffered-file->buffer)
 6995     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6996     68/push 0/imm32
 6997     68/push 0/imm32
 6998     89/<- %edx 4/r32/esp
 6999     (tailor-exit-descriptor %edx 0x10)
 7000     #
 7001     (write _test-input-stream "type t {\n")
 7002     (write _test-input-stream "  a: (addr int)\n")
 7003     (write _test-input-stream "}\n")
 7004     # convert
 7005     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7006     # registers except esp clobbered at this point
 7007     # restore ed
 7008     89/<- %edx 4/r32/esp
 7009     (flush _test-output-buffered-file)
 7010     (flush _test-error-buffered-file)
 7011 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7017     # check output
 7018     (check-stream-equal _test-output-stream  ""  "F - test-type-definition-with-addr: output should be empty")
 7019     (check-next-stream-line-equal _test-error-stream  "type t: 'addr' elements not allowed"  "F - test-type-definition-with-addr: error message")
 7020     # check that stop(1) was called
 7021     (check-ints-equal *(edx+4) 2 "F - test-type-definition-with-addr: exit status")
 7022     # don't restore from ebp
 7023     81 0/subop/add %esp 8/imm32
 7024     # . epilogue
 7025     5d/pop-to-ebp
 7026     c3/return
 7027 
 7028 test-convert-function-with-local-var-with-user-defined-type:
 7029     # . prologue
 7030     55/push-ebp
 7031     89/<- %ebp 4/r32/esp
 7032     # setup
 7033     (clear-stream _test-input-stream)
 7034     (clear-stream $_test-input-buffered-file->buffer)
 7035     (clear-stream _test-output-stream)
 7036     (clear-stream $_test-output-buffered-file->buffer)
 7037     #
 7038     (write _test-input-stream "fn foo {\n")
 7039     (write _test-input-stream "  var a: t\n")
 7040     (write _test-input-stream "}\n")
 7041     (write _test-input-stream "type t {\n")
 7042     (write _test-input-stream "  x: int\n")
 7043     (write _test-input-stream "  y: int\n")
 7044     (write _test-input-stream "}\n")
 7045     # convert
 7046     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7047     (flush _test-output-buffered-file)
 7048 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7054     # check output
 7055     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-with-user-defined-type/0")
 7056     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-with-user-defined-type/1")
 7057     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-with-user-defined-type/2")
 7058     (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")
 7059     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-user-defined-type/4")
 7060     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-with-user-defined-type/5")
 7061     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-user-defined-type/6")
 7062     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-user-defined-type/7")
 7063     (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")
 7064     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-user-defined-type/9")
 7065     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-with-user-defined-type/10")
 7066     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-with-user-defined-type/11")
 7067     (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")
 7068     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-with-user-defined-type/13")
 7069     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-with-user-defined-type/14")
 7070     # . epilogue
 7071     89/<- %esp 5/r32/ebp
 7072     5d/pop-to-ebp
 7073     c3/return
 7074 
 7075 test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type:
 7076     # . prologue
 7077     55/push-ebp
 7078     89/<- %ebp 4/r32/esp
 7079     # setup
 7080     (clear-stream _test-input-stream)
 7081     (clear-stream $_test-input-buffered-file->buffer)
 7082     (clear-stream _test-output-stream)
 7083     (clear-stream $_test-output-buffered-file->buffer)
 7084     #
 7085     (write _test-input-stream "fn foo {\n")
 7086     (write _test-input-stream "  var a: t\n")
 7087     (write _test-input-stream "}\n")
 7088     (write _test-input-stream "type t {\n")
 7089     (write _test-input-stream "  x: s\n")
 7090     (write _test-input-stream "}\n")
 7091     (write _test-input-stream "type s {\n")
 7092     (write _test-input-stream "  z: int\n")
 7093     (write _test-input-stream "}\n")
 7094     # convert
 7095     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7096     (flush _test-output-buffered-file)
 7097 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7103     # check output
 7104     (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")
 7105     (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")
 7106     (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")
 7107     (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")
 7108     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/4")
 7109     (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")
 7110     (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")
 7111     (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")
 7112     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/9")
 7113     (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")
 7114     (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")
 7115     (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")
 7116     (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")
 7117     (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")
 7118     # . epilogue
 7119     89/<- %esp 5/r32/ebp
 7120     5d/pop-to-ebp
 7121     c3/return
 7122 
 7123 test-convert-function-call-with-arg-of-user-defined-type:
 7124     # . prologue
 7125     55/push-ebp
 7126     89/<- %ebp 4/r32/esp
 7127     # setup
 7128     (clear-stream _test-input-stream)
 7129     (clear-stream $_test-input-buffered-file->buffer)
 7130     (clear-stream _test-output-stream)
 7131     (clear-stream $_test-output-buffered-file->buffer)
 7132     #
 7133     (write _test-input-stream "fn f {\n")
 7134     (write _test-input-stream "  var a: t\n")
 7135     (write _test-input-stream "  foo a\n")
 7136     (write _test-input-stream "}\n")
 7137     (write _test-input-stream "fn foo x: t {\n")
 7138     (write _test-input-stream "}\n")
 7139     (write _test-input-stream "type t {\n")
 7140     (write _test-input-stream "  x: int\n")
 7141     (write _test-input-stream "  y: int\n")
 7142     (write _test-input-stream "}\n")
 7143     # convert
 7144     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7145     (flush _test-output-buffered-file)
 7146 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7152     # check output
 7153     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type/0")
 7154     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/1")
 7155     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/2")
 7156     (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")
 7157     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type/4")
 7158     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-arg-of-user-defined-type/5")
 7159     # var a: t
 7160     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-arg-of-user-defined-type/6")
 7161     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-arg-of-user-defined-type/7")
 7162     # foo a
 7163     (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")
 7164     #
 7165     (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")
 7166     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type/10")
 7167     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-arg-of-user-defined-type/11")
 7168     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/12")
 7169     (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")
 7170     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/14")
 7171     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/15")
 7172     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type/16")
 7173     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/17")
 7174     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/18")
 7175     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-arg-of-user-defined-type/19")
 7176     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/20")
 7177     (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")
 7178     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/22")
 7179     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/23")
 7180     # . epilogue
 7181     89/<- %esp 5/r32/ebp
 7182     5d/pop-to-ebp
 7183     c3/return
 7184 
 7185 test-convert-function-call-with-arg-of-user-defined-type-register-indirect:
 7186     # . prologue
 7187     55/push-ebp
 7188     89/<- %ebp 4/r32/esp
 7189     # setup
 7190     (clear-stream _test-input-stream)
 7191     (clear-stream $_test-input-buffered-file->buffer)
 7192     (clear-stream _test-output-stream)
 7193     (clear-stream $_test-output-buffered-file->buffer)
 7194     #
 7195     (write _test-input-stream "fn f {\n")
 7196     (write _test-input-stream "  var a/eax: (addr t) <- copy 0\n")
 7197     (write _test-input-stream "  foo *a\n")
 7198     (write _test-input-stream "}\n")
 7199     (write _test-input-stream "fn foo x: t {\n")
 7200     (write _test-input-stream "}\n")
 7201     (write _test-input-stream "type t {\n")
 7202     (write _test-input-stream "  x: int\n")
 7203     (write _test-input-stream "  y: int\n")
 7204     (write _test-input-stream "}\n")
 7205     # convert
 7206     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7207     (flush _test-output-buffered-file)
 7208 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7214     # check output
 7215     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type/0")
 7216     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/1")
 7217     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/2")
 7218     (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")
 7219     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type/4")
 7220     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-arg-of-user-defined-type/5")
 7221     # var a
 7222     (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")
 7223     (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")
 7224     # foo a
 7225     (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")
 7226     #
 7227     (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")
 7228     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type/10")
 7229     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-arg-of-user-defined-type/11")
 7230     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/12")
 7231     (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")
 7232     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/14")
 7233     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/15")
 7234     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type/16")
 7235     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/17")
 7236     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/18")
 7237     (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")
 7238     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/20")
 7239     (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")
 7240     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/22")
 7241     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/23")
 7242     # . epilogue
 7243     89/<- %esp 5/r32/ebp
 7244     5d/pop-to-ebp
 7245     c3/return
 7246 
 7247 # we don't have special support for call-by-reference; just explicitly create
 7248 # a new variable with the address of the arg
 7249 test-convert-function-call-with-arg-of-user-defined-type-by-reference:
 7250     # . prologue
 7251     55/push-ebp
 7252     89/<- %ebp 4/r32/esp
 7253     # setup
 7254     (clear-stream _test-input-stream)
 7255     (clear-stream $_test-input-buffered-file->buffer)
 7256     (clear-stream _test-output-stream)
 7257     (clear-stream $_test-output-buffered-file->buffer)
 7258     #
 7259     (write _test-input-stream "fn f {\n")
 7260     (write _test-input-stream "  var a: t\n")
 7261     (write _test-input-stream "  var b/eax: (addr t) <- address a\n")
 7262     (write _test-input-stream "  foo b\n")
 7263     (write _test-input-stream "}\n")
 7264     (write _test-input-stream "fn foo x: (addr t) {\n")
 7265     (write _test-input-stream "  var x/ecx: (addr t) <- copy x\n")
 7266     (write _test-input-stream "}\n")
 7267     (write _test-input-stream "type t {\n")
 7268     (write _test-input-stream "  x: int\n")
 7269     (write _test-input-stream "  y: int\n")
 7270     (write _test-input-stream "}\n")
 7271     # convert
 7272     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7273     (flush _test-output-buffered-file)
 7274 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7280     # check output
 7281     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/0")
 7282     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/1")
 7283     (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")
 7284     (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")
 7285     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/4")
 7286     (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")
 7287     # var a: t
 7288     (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")
 7289     (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")
 7290     # var b/eax: (addr t)
 7291     (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")
 7292     (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")
 7293     # foo a
 7294     (check-next-stream-line-equal _test-output-stream "    (foo %eax)"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/10")
 7295     #
 7296     (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")
 7297     (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")
 7298     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/13")
 7299     (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")
 7300     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/15")
 7301     (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")
 7302     (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")
 7303     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/18")
 7304     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/19")
 7305     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/20")
 7306     (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")
 7307     (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")
 7308     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/23")
 7309     (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")
 7310     (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")
 7311     (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")
 7312     (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")
 7313     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/28")
 7314     (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")
 7315     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/30")
 7316     (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")
 7317     (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")
 7318     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/33")
 7319     # . epilogue
 7320     89/<- %esp 5/r32/ebp
 7321     5d/pop-to-ebp
 7322     c3/return
 7323 
 7324 test-convert-get-on-local-variable:
 7325     # . prologue
 7326     55/push-ebp
 7327     89/<- %ebp 4/r32/esp
 7328     # setup
 7329     (clear-stream _test-input-stream)
 7330     (clear-stream $_test-input-buffered-file->buffer)
 7331     (clear-stream _test-output-stream)
 7332     (clear-stream $_test-output-buffered-file->buffer)
 7333     #
 7334     (write _test-input-stream "fn foo {\n")
 7335     (write _test-input-stream "  var a: t\n")
 7336     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 7337     (write _test-input-stream "}\n")
 7338     (write _test-input-stream "type t {\n")
 7339     (write _test-input-stream "  x: int\n")
 7340     (write _test-input-stream "  y: int\n")
 7341     (write _test-input-stream "}\n")
 7342     # convert
 7343     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7344     (flush _test-output-buffered-file)
 7345 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7351     # check output
 7352     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-local-variable/0")
 7353     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-local-variable/1")
 7354     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-local-variable/2")
 7355     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-local-variable/3")
 7356     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-local-variable/4")
 7357     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-local-variable/5")
 7358     # var a
 7359     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-get-on-local-variable/6")
 7360     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-get-on-local-variable/7")
 7361     # var c
 7362     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-local-variable/8")
 7363     # get
 7364     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0xfffffffc) 0x00000001/r32"  "F - test-convert-get-on-local-variable/9")
 7365     # reclaim c
 7366     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-local-variable/10")
 7367     # reclaim a
 7368     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000008/imm32"  "F - test-convert-get-on-local-variable/11")
 7369     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-local-variable/12")
 7370     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-local-variable/13")
 7371     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-local-variable/14")
 7372     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-local-variable/15")
 7373     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-local-variable/16")
 7374     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-local-variable/17")
 7375     # . epilogue
 7376     89/<- %esp 5/r32/ebp
 7377     5d/pop-to-ebp
 7378     c3/return
 7379 
 7380 test-convert-get-on-function-argument:
 7381     # . prologue
 7382     55/push-ebp
 7383     89/<- %ebp 4/r32/esp
 7384     # setup
 7385     (clear-stream _test-input-stream)
 7386     (clear-stream $_test-input-buffered-file->buffer)
 7387     (clear-stream _test-output-stream)
 7388     (clear-stream $_test-output-buffered-file->buffer)
 7389     #
 7390     (write _test-input-stream "fn foo a: t {\n")
 7391     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 7392     (write _test-input-stream "}\n")
 7393     (write _test-input-stream "type t {\n")
 7394     (write _test-input-stream "  x: int\n")
 7395     (write _test-input-stream "  y: int\n")
 7396     (write _test-input-stream "}\n")
 7397     # convert
 7398     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7399     (flush _test-output-buffered-file)
 7400 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7406     # check output
 7407     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-function-argument/0")
 7408     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-function-argument/1")
 7409     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-function-argument/2")
 7410     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-function-argument/3")
 7411     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-function-argument/4")
 7412     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-function-argument/5")
 7413     # var c
 7414     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-function-argument/6")
 7415     # get
 7416     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0x0000000c) 0x00000001/r32"  "F - test-convert-get-on-function-argument/7")
 7417     # reclaim c
 7418     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-function-argument/8")
 7419     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-function-argument/9")
 7420     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-function-argument/10")
 7421     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-function-argument/11")
 7422     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-function-argument/12")
 7423     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-function-argument/13")
 7424     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-function-argument/14")
 7425     # . epilogue
 7426     89/<- %esp 5/r32/ebp
 7427     5d/pop-to-ebp
 7428     c3/return
 7429 
 7430 test-convert-get-on-function-argument-with-known-type:
 7431     # . prologue
 7432     55/push-ebp
 7433     89/<- %ebp 4/r32/esp
 7434     # setup
 7435     (clear-stream _test-input-stream)
 7436     (clear-stream $_test-input-buffered-file->buffer)
 7437     (clear-stream _test-output-stream)
 7438     (clear-stream $_test-output-buffered-file->buffer)
 7439     #
 7440     (write _test-input-stream "type t {\n")
 7441     (write _test-input-stream "  x: int\n")
 7442     (write _test-input-stream "  y: int\n")
 7443     (write _test-input-stream "}\n")
 7444     (write _test-input-stream "fn foo a: t {\n")
 7445     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 7446     (write _test-input-stream "}\n")
 7447     # convert
 7448     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7449     (flush _test-output-buffered-file)
 7450 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7456     # check output
 7457     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-function-argument-with-known-type/0")
 7458     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-function-argument-with-known-type/1")
 7459     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-function-argument-with-known-type/2")
 7460     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-function-argument-with-known-type/3")
 7461     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-function-argument-with-known-type/4")
 7462     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-function-argument-with-known-type/5")
 7463     # var c
 7464     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-function-argument-with-known-type/6")
 7465     # get
 7466     (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")
 7467     # reclaim c
 7468     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-function-argument-with-known-type/8")
 7469     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-function-argument-with-known-type/9")
 7470     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-function-argument-with-known-type/10")
 7471     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-function-argument-with-known-type/11")
 7472     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-function-argument-with-known-type/12")
 7473     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-function-argument-with-known-type/13")
 7474     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-function-argument-with-known-type/14")
 7475     # . epilogue
 7476     89/<- %esp 5/r32/ebp
 7477     5d/pop-to-ebp
 7478     c3/return
 7479 
 7480 test-add-with-too-many-inouts:
 7481     # . prologue
 7482     55/push-ebp
 7483     89/<- %ebp 4/r32/esp
 7484     # setup
 7485     (clear-stream _test-input-stream)
 7486     (clear-stream $_test-input-buffered-file->buffer)
 7487     (clear-stream _test-output-stream)
 7488     (clear-stream $_test-output-buffered-file->buffer)
 7489     (clear-stream _test-error-stream)
 7490     (clear-stream $_test-error-buffered-file->buffer)
 7491     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7492     68/push 0/imm32
 7493     68/push 0/imm32
 7494     89/<- %edx 4/r32/esp
 7495     (tailor-exit-descriptor %edx 0x10)
 7496     #
 7497     (write _test-input-stream "fn foo {\n")
 7498     (write _test-input-stream "  var a: int\n")
 7499     (write _test-input-stream "  var b/ecx: int <- add a, 0\n")
 7500     (write _test-input-stream "}\n")
 7501     # convert
 7502     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7503     # registers except esp clobbered at this point
 7504     # restore ed
 7505     89/<- %edx 4/r32/esp
 7506     (flush _test-output-buffered-file)
 7507     (flush _test-error-buffered-file)
 7508 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7514     # check output
 7515     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-inouts: output should be empty")
 7516     (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")
 7517     # check that stop(1) was called
 7518     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-inouts: exit status")
 7519     # don't restore from ebp
 7520     81 0/subop/add %esp 8/imm32
 7521     # . epilogue
 7522     5d/pop-to-ebp
 7523     c3/return
 7524 
 7525 test-add-with-too-many-inouts-2:
 7526     # . prologue
 7527     55/push-ebp
 7528     89/<- %ebp 4/r32/esp
 7529     # setup
 7530     (clear-stream _test-input-stream)
 7531     (clear-stream $_test-input-buffered-file->buffer)
 7532     (clear-stream _test-output-stream)
 7533     (clear-stream $_test-output-buffered-file->buffer)
 7534     (clear-stream _test-error-stream)
 7535     (clear-stream $_test-error-buffered-file->buffer)
 7536     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7537     68/push 0/imm32
 7538     68/push 0/imm32
 7539     89/<- %edx 4/r32/esp
 7540     (tailor-exit-descriptor %edx 0x10)
 7541     #
 7542     (write _test-input-stream "fn foo {\n")
 7543     (write _test-input-stream "  var a: int\n")
 7544     (write _test-input-stream "  add-to a, 0, 1\n")
 7545     (write _test-input-stream "}\n")
 7546     # convert
 7547     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7548     # registers except esp clobbered at this point
 7549     # restore ed
 7550     89/<- %edx 4/r32/esp
 7551     (flush _test-output-buffered-file)
 7552     (flush _test-error-buffered-file)
 7553 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7559     # check output
 7560     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-inouts-2: output should be empty")
 7561     (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")
 7562     # check that stop(1) was called
 7563     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-inouts-2: exit status")
 7564     # don't restore from ebp
 7565     81 0/subop/add %esp 8/imm32
 7566     # . epilogue
 7567     5d/pop-to-ebp
 7568     c3/return
 7569 
 7570 test-add-with-too-many-outputs:
 7571     # . prologue
 7572     55/push-ebp
 7573     89/<- %ebp 4/r32/esp
 7574     # setup
 7575     (clear-stream _test-input-stream)
 7576     (clear-stream $_test-input-buffered-file->buffer)
 7577     (clear-stream _test-output-stream)
 7578     (clear-stream $_test-output-buffered-file->buffer)
 7579     (clear-stream _test-error-stream)
 7580     (clear-stream $_test-error-buffered-file->buffer)
 7581     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7582     68/push 0/imm32
 7583     68/push 0/imm32
 7584     89/<- %edx 4/r32/esp
 7585     (tailor-exit-descriptor %edx 0x10)
 7586     #
 7587     (write _test-input-stream "fn foo {\n")
 7588     (write _test-input-stream "  var a/eax: int <- copy 0\n")
 7589     (write _test-input-stream "  var b/ebx: int <- copy 0\n")
 7590     (write _test-input-stream "  var c/ecx: int <- copy 0\n")
 7591     (write _test-input-stream "  c, b <- add a\n")
 7592     (write _test-input-stream "}\n")
 7593     # convert
 7594     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7595     # registers except esp clobbered at this point
 7596     # restore ed
 7597     89/<- %edx 4/r32/esp
 7598     (flush _test-output-buffered-file)
 7599     (flush _test-error-buffered-file)
 7600 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7606     # check output
 7607     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-outputs: output should be empty")
 7608     (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")
 7609     # check that stop(1) was called
 7610     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-outputs: exit status")
 7611     # don't restore from ebp
 7612     81 0/subop/add %esp 8/imm32
 7613     # . epilogue
 7614     5d/pop-to-ebp
 7615     c3/return
 7616 
 7617 test-add-with-non-number:
 7618     # . prologue
 7619     55/push-ebp
 7620     89/<- %ebp 4/r32/esp
 7621     # setup
 7622     (clear-stream _test-input-stream)
 7623     (clear-stream $_test-input-buffered-file->buffer)
 7624     (clear-stream _test-output-stream)
 7625     (clear-stream $_test-output-buffered-file->buffer)
 7626     (clear-stream _test-error-stream)
 7627     (clear-stream $_test-error-buffered-file->buffer)
 7628     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7629     68/push 0/imm32
 7630     68/push 0/imm32
 7631     89/<- %edx 4/r32/esp
 7632     (tailor-exit-descriptor %edx 0x10)
 7633     #
 7634     (write _test-input-stream "fn foo {\n")
 7635     (write _test-input-stream "  var a: int\n")
 7636     (write _test-input-stream "  var b/ecx: (addr int) <- add a\n")
 7637     (write _test-input-stream "}\n")
 7638     # convert
 7639     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7640     # registers except esp clobbered at this point
 7641     # restore ed
 7642     89/<- %edx 4/r32/esp
 7643     (flush _test-output-buffered-file)
 7644     (flush _test-error-buffered-file)
 7645 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7651     # check output
 7652     (check-stream-equal _test-output-stream  ""  "F - test-add-with-non-number: output should be empty")
 7653     (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")
 7654     # check that stop(1) was called
 7655     (check-ints-equal *(edx+4) 2 "F - test-add-with-non-number: exit status")
 7656     # don't restore from ebp
 7657     81 0/subop/add %esp 8/imm32
 7658     # . epilogue
 7659     5d/pop-to-ebp
 7660     c3/return
 7661 
 7662 test-add-with-addr-dereferenced:
 7663     # . prologue
 7664     55/push-ebp
 7665     89/<- %ebp 4/r32/esp
 7666     # setup
 7667     (clear-stream _test-input-stream)
 7668     (clear-stream $_test-input-buffered-file->buffer)
 7669     (clear-stream _test-output-stream)
 7670     (clear-stream $_test-output-buffered-file->buffer)
 7671     #
 7672     (write _test-input-stream "fn foo {\n")
 7673     (write _test-input-stream "  var a/eax: (addr int) <- copy 0\n")
 7674     (write _test-input-stream "  add-to *a, 1\n")
 7675     (write _test-input-stream "}\n")
 7676     # convert
 7677     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7678     (flush _test-output-buffered-file)
 7679     # no error
 7680     # . epilogue
 7681     89/<- %esp 5/r32/ebp
 7682     5d/pop-to-ebp
 7683     c3/return
 7684 
 7685 test-copy-with-no-inout:
 7686     # . prologue
 7687     55/push-ebp
 7688     89/<- %ebp 4/r32/esp
 7689     # setup
 7690     (clear-stream _test-input-stream)
 7691     (clear-stream $_test-input-buffered-file->buffer)
 7692     (clear-stream _test-output-stream)
 7693     (clear-stream $_test-output-buffered-file->buffer)
 7694     (clear-stream _test-error-stream)
 7695     (clear-stream $_test-error-buffered-file->buffer)
 7696     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7697     68/push 0/imm32
 7698     68/push 0/imm32
 7699     89/<- %edx 4/r32/esp
 7700     (tailor-exit-descriptor %edx 0x10)
 7701     #
 7702     (write _test-input-stream "fn foo {\n")
 7703     (write _test-input-stream "  var x/eax: boolean <- copy\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-with-no-inout: output should be empty")
 7720     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy' expects an inout"  "F - test-copy-with-no-inout: error message")
 7721     # check that stop(1) was called
 7722     (check-ints-equal *(edx+4) 2 "F - test-copy-with-no-inout: 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-with-multiple-inouts:
 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/eax: boolean <- copy 0, 0\n")
 7748     (write _test-input-stream "}\n")
 7749     # convert
 7750     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7751     # registers except esp clobbered at this point
 7752     # restore ed
 7753     89/<- %edx 4/r32/esp
 7754     (flush _test-output-buffered-file)
 7755     (flush _test-error-buffered-file)
 7756 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7762     # check output
 7763     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-multiple-inouts: output should be empty")
 7764     (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")
 7765     # check that stop(1) was called
 7766     (check-ints-equal *(edx+4) 2 "F - test-copy-with-multiple-inouts: exit status")
 7767     # don't restore from ebp
 7768     81 0/subop/add %esp 8/imm32
 7769     # . epilogue
 7770     5d/pop-to-ebp
 7771     c3/return
 7772 
 7773 test-copy-with-no-output:
 7774     # . prologue
 7775     55/push-ebp
 7776     89/<- %ebp 4/r32/esp
 7777     # setup
 7778     (clear-stream _test-input-stream)
 7779     (clear-stream $_test-input-buffered-file->buffer)
 7780     (clear-stream _test-output-stream)
 7781     (clear-stream $_test-output-buffered-file->buffer)
 7782     (clear-stream _test-error-stream)
 7783     (clear-stream $_test-error-buffered-file->buffer)
 7784     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7785     68/push 0/imm32
 7786     68/push 0/imm32
 7787     89/<- %edx 4/r32/esp
 7788     (tailor-exit-descriptor %edx 0x10)
 7789     #
 7790     (write _test-input-stream "fn foo {\n")
 7791     (write _test-input-stream "  copy 0\n")
 7792     (write _test-input-stream "}\n")
 7793     # convert
 7794     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7795     # registers except esp clobbered at this point
 7796     # restore ed
 7797     89/<- %edx 4/r32/esp
 7798     (flush _test-output-buffered-file)
 7799     (flush _test-error-buffered-file)
 7800 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7806     # check output
 7807     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-no-output: output should be empty")
 7808     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy' expects an output"  "F - test-copy-with-no-output: error message")
 7809     # check that stop(1) was called
 7810     (check-ints-equal *(edx+4) 2 "F - test-copy-with-no-output: exit status")
 7811     # don't restore from ebp
 7812     81 0/subop/add %esp 8/imm32
 7813     # . epilogue
 7814     5d/pop-to-ebp
 7815     c3/return
 7816 
 7817 test-copy-with-multiple-outputs:
 7818     # . prologue
 7819     55/push-ebp
 7820     89/<- %ebp 4/r32/esp
 7821     # setup
 7822     (clear-stream _test-input-stream)
 7823     (clear-stream $_test-input-buffered-file->buffer)
 7824     (clear-stream _test-output-stream)
 7825     (clear-stream $_test-output-buffered-file->buffer)
 7826     (clear-stream _test-error-stream)
 7827     (clear-stream $_test-error-buffered-file->buffer)
 7828     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7829     68/push 0/imm32
 7830     68/push 0/imm32
 7831     89/<- %edx 4/r32/esp
 7832     (tailor-exit-descriptor %edx 0x10)
 7833     #
 7834     (write _test-input-stream "fn foo {\n")
 7835     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 7836     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
 7837     (write _test-input-stream "  x, y <- copy 0\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-with-multiple-outputs: output should be empty")
 7854     (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")
 7855     # check that stop(1) was called
 7856     (check-ints-equal *(edx+4) 2 "F - test-copy-with-multiple-outputs: 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-invalid-value-to-address:
 7864     # . prologue
 7865     55/push-ebp
 7866     89/<- %ebp 4/r32/esp
 7867     # setup
 7868     (clear-stream _test-input-stream)
 7869     (clear-stream $_test-input-buffered-file->buffer)
 7870     (clear-stream _test-output-stream)
 7871     (clear-stream $_test-output-buffered-file->buffer)
 7872     (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/eax: int <- copy 0\n")
 7882     (write _test-input-stream "  var y/ecx: (addr int) <- copy 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-invalid-value-to-address: output should be empty")
 7899     (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")
 7900     # check that stop(1) was called
 7901     (check-ints-equal *(edx+4) 2 "F - test-copy-invalid-value-to-address: 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-null-value-to-address:
 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     #
 7918     (write _test-input-stream "fn foo {\n")
 7919     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
 7920     (write _test-input-stream "}\n")
 7921     # convert
 7922     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7923     (flush _test-output-buffered-file)
 7924     # no errors
 7925     # . epilogue
 7926     89/<- %esp 5/r32/ebp
 7927     5d/pop-to-ebp
 7928     c3/return
 7929 
 7930 test-copy-invalid-value-to-offset:
 7931     # . prologue
 7932     55/push-ebp
 7933     89/<- %ebp 4/r32/esp
 7934     # setup
 7935     (clear-stream _test-input-stream)
 7936     (clear-stream $_test-input-buffered-file->buffer)
 7937     (clear-stream _test-output-stream)
 7938     (clear-stream $_test-output-buffered-file->buffer)
 7939     (clear-stream _test-error-stream)
 7940     (clear-stream $_test-error-buffered-file->buffer)
 7941     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7942     68/push 0/imm32
 7943     68/push 0/imm32
 7944     89/<- %edx 4/r32/esp
 7945     (tailor-exit-descriptor %edx 0x10)
 7946     #
 7947     (write _test-input-stream "fn foo {\n")
 7948     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 7949     (write _test-input-stream "  var y/ecx: (offset int) <- copy x\n")
 7950     (write _test-input-stream "}\n")
 7951     # convert
 7952     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7953     # registers except esp clobbered at this point
 7954     # restore ed
 7955     89/<- %edx 4/r32/esp
 7956     (flush _test-output-buffered-file)
 7957     (flush _test-error-buffered-file)
 7958 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7964     # check output
 7965     (check-stream-equal _test-output-stream  ""  "F - test-copy-invalid-value-to-address: output should be empty")
 7966     (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")
 7967     # check that stop(1) was called
 7968     (check-ints-equal *(edx+4) 2 "F - test-copy-invalid-value-to-offset: exit status")
 7969     # don't restore from ebp
 7970     81 0/subop/add %esp 8/imm32
 7971     # . epilogue
 7972     5d/pop-to-ebp
 7973     c3/return
 7974 
 7975 test-copy-null-value-to-offset:
 7976     # . prologue
 7977     55/push-ebp
 7978     89/<- %ebp 4/r32/esp
 7979     # setup
 7980     (clear-stream _test-input-stream)
 7981     (clear-stream $_test-input-buffered-file->buffer)
 7982     (clear-stream _test-output-stream)
 7983     (clear-stream $_test-output-buffered-file->buffer)
 7984     #
 7985     (write _test-input-stream "fn foo {\n")
 7986     (write _test-input-stream "  var y/ecx: (offset int) <- copy 0\n")
 7987     (write _test-input-stream "}\n")
 7988     # convert
 7989     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7990     (flush _test-output-buffered-file)
 7991 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7997     # no errors
 7998     # . epilogue
 7999     89/<- %esp 5/r32/ebp
 8000     5d/pop-to-ebp
 8001     c3/return
 8002 
 8003 test-copy-non-literal-to-byte:
 8004     # . prologue
 8005     55/push-ebp
 8006     89/<- %ebp 4/r32/esp
 8007     # setup
 8008     (clear-stream _test-input-stream)
 8009     (clear-stream $_test-input-buffered-file->buffer)
 8010     (clear-stream _test-output-stream)
 8011     (clear-stream $_test-output-buffered-file->buffer)
 8012     (clear-stream _test-error-stream)
 8013     (clear-stream $_test-error-buffered-file->buffer)
 8014     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8015     68/push 0/imm32
 8016     68/push 0/imm32
 8017     89/<- %edx 4/r32/esp
 8018     (tailor-exit-descriptor %edx 0x10)
 8019     #
 8020     (write _test-input-stream "fn foo {\n")
 8021     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 8022     (write _test-input-stream "  var y/ecx: byte <- copy x\n")
 8023     (write _test-input-stream "}\n")
 8024     # convert
 8025     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8026     # registers except esp clobbered at this point
 8027     # restore ed
 8028     89/<- %edx 4/r32/esp
 8029     (flush _test-output-buffered-file)
 8030     (flush _test-error-buffered-file)
 8031 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8037     # check output
 8038     (check-stream-equal _test-output-stream  ""  "F - test-copy-non-literal-to-byte: output should be empty")
 8039     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy: cannot copy non-literal to 'y' of type byte; use copy-byte"  "F - test-copy-non-literal-to-byte: error message")
 8040     # check that stop(1) was called
 8041     (check-ints-equal *(edx+4) 2 "F - test-copy-non-literal-to-byte: exit status")
 8042     # don't restore from ebp
 8043     81 0/subop/add %esp 8/imm32
 8044     # . epilogue
 8045     5d/pop-to-ebp
 8046     c3/return
 8047 
 8048 test-copy-deref-address:
 8049     # . prologue
 8050     55/push-ebp
 8051     89/<- %ebp 4/r32/esp
 8052     # setup
 8053     (clear-stream _test-input-stream)
 8054     (clear-stream $_test-input-buffered-file->buffer)
 8055     (clear-stream _test-output-stream)
 8056     (clear-stream $_test-output-buffered-file->buffer)
 8057     #
 8058     (write _test-input-stream "fn foo {\n")
 8059     (write _test-input-stream "  var x/eax: (addr addr int) <- copy 0\n")
 8060     (write _test-input-stream "  var y/ecx: (addr int) <- copy *x\n")
 8061     (write _test-input-stream "}\n")
 8062     # convert
 8063     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8064     (flush _test-output-buffered-file)
 8065     # no errors
 8066     # . epilogue
 8067     5d/pop-to-ebp
 8068     c3/return
 8069 
 8070 test-copy-to-non-register:
 8071     # . prologue
 8072     55/push-ebp
 8073     89/<- %ebp 4/r32/esp
 8074     # setup
 8075     (clear-stream _test-input-stream)
 8076     (clear-stream $_test-input-buffered-file->buffer)
 8077     (clear-stream _test-output-stream)
 8078     (clear-stream $_test-output-buffered-file->buffer)
 8079     (clear-stream _test-error-stream)
 8080     (clear-stream $_test-error-buffered-file->buffer)
 8081     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8082     68/push 0/imm32
 8083     68/push 0/imm32
 8084     89/<- %edx 4/r32/esp
 8085     (tailor-exit-descriptor %edx 0x10)
 8086     #
 8087     (write _test-input-stream "fn foo {\n")
 8088     (write _test-input-stream "  var x: int\n")
 8089     (write _test-input-stream "  x <- copy 0\n")
 8090     (write _test-input-stream "}\n")
 8091     # convert
 8092     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8093     # registers except esp clobbered at this point
 8094     # restore ed
 8095     89/<- %edx 4/r32/esp
 8096     (flush _test-output-buffered-file)
 8097     (flush _test-error-buffered-file)
 8098 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8104     # check output
 8105     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-non-register: output should be empty")
 8106     (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")
 8107     # check that stop(1) was called
 8108     (check-ints-equal *(edx+4) 2 "F - test-copy-to-non-register: exit status")
 8109     # don't restore from ebp
 8110     81 0/subop/add %esp 8/imm32
 8111     # . epilogue
 8112     5d/pop-to-ebp
 8113     c3/return
 8114 
 8115 test-copy-from-non-scalar-inout:
 8116     # . prologue
 8117     55/push-ebp
 8118     89/<- %ebp 4/r32/esp
 8119     # setup
 8120     (clear-stream _test-input-stream)
 8121     (clear-stream $_test-input-buffered-file->buffer)
 8122     (clear-stream _test-output-stream)
 8123     (clear-stream $_test-output-buffered-file->buffer)
 8124     (clear-stream _test-error-stream)
 8125     (clear-stream $_test-error-buffered-file->buffer)
 8126     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8127     68/push 0/imm32
 8128     68/push 0/imm32
 8129     89/<- %edx 4/r32/esp
 8130     (tailor-exit-descriptor %edx 0x10)
 8131     #
 8132     (write _test-input-stream "fn foo {\n")
 8133     (write _test-input-stream "  var x: (handle int)\n")
 8134     (write _test-input-stream "  var y/eax: int <- copy x\n")
 8135     (write _test-input-stream "}\n")
 8136     # convert
 8137     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8138     # registers except esp clobbered at this point
 8139     # restore ed
 8140     89/<- %edx 4/r32/esp
 8141     (flush _test-output-buffered-file)
 8142     (flush _test-error-buffered-file)
 8143 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8149     # check output
 8150     (check-stream-equal _test-output-stream  ""  "F - test-copy-from-non-scalar-inout: output should be empty")
 8151     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy: 'x' is too large to fit in a register"  "F - test-copy-from-non-scalar-inout: error message")
 8152     # check that stop(1) was called
 8153     (check-ints-equal *(edx+4) 2 "F - test-copy-from-non-scalar-inout: exit status")
 8154     # don't restore from ebp
 8155     81 0/subop/add %esp 8/imm32
 8156     # . epilogue
 8157     5d/pop-to-ebp
 8158     c3/return
 8159 
 8160 test-copy-to-with-no-inout:
 8161     # . prologue
 8162     55/push-ebp
 8163     89/<- %ebp 4/r32/esp
 8164     # setup
 8165     (clear-stream _test-input-stream)
 8166     (clear-stream $_test-input-buffered-file->buffer)
 8167     (clear-stream _test-output-stream)
 8168     (clear-stream $_test-output-buffered-file->buffer)
 8169     (clear-stream _test-error-stream)
 8170     (clear-stream $_test-error-buffered-file->buffer)
 8171     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8172     68/push 0/imm32
 8173     68/push 0/imm32
 8174     89/<- %edx 4/r32/esp
 8175     (tailor-exit-descriptor %edx 0x10)
 8176     #
 8177     (write _test-input-stream "fn foo {\n")
 8178     (write _test-input-stream "  copy-to\n")
 8179     (write _test-input-stream "}\n")
 8180     # convert
 8181     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8182     # registers except esp clobbered at this point
 8183     # restore ed
 8184     89/<- %edx 4/r32/esp
 8185     (flush _test-output-buffered-file)
 8186     (flush _test-error-buffered-file)
 8187 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8193     # check output
 8194     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-no-inout: output should be empty")
 8195     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-to' must have two inouts"  "F - test-copy-to-with-no-inout: error message")
 8196     # check that stop(1) was called
 8197     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-inout: exit status")
 8198     # don't restore from ebp
 8199     81 0/subop/add %esp 8/imm32
 8200     # . epilogue
 8201     5d/pop-to-ebp
 8202     c3/return
 8203 
 8204 test-copy-to-with-no-source:
 8205     # . prologue
 8206     55/push-ebp
 8207     89/<- %ebp 4/r32/esp
 8208     # setup
 8209     (clear-stream _test-input-stream)
 8210     (clear-stream $_test-input-buffered-file->buffer)
 8211     (clear-stream _test-output-stream)
 8212     (clear-stream $_test-output-buffered-file->buffer)
 8213     (clear-stream _test-error-stream)
 8214     (clear-stream $_test-error-buffered-file->buffer)
 8215     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8216     68/push 0/imm32
 8217     68/push 0/imm32
 8218     89/<- %edx 4/r32/esp
 8219     (tailor-exit-descriptor %edx 0x10)
 8220     #
 8221     (write _test-input-stream "fn foo {\n")
 8222     (write _test-input-stream "  var x: boolean\n")
 8223     (write _test-input-stream "  copy-to x\n")
 8224     (write _test-input-stream "}\n")
 8225     # convert
 8226     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8227     # registers except esp clobbered at this point
 8228     # restore ed
 8229     89/<- %edx 4/r32/esp
 8230     (flush _test-output-buffered-file)
 8231     (flush _test-error-buffered-file)
 8232 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8238     # check output
 8239     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-no-source: output should be empty")
 8240     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-to' must have two inouts"  "F - test-copy-to-with-no-source: error message")
 8241     # check that stop(1) was called
 8242     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-source: exit status")
 8243     # don't restore from ebp
 8244     81 0/subop/add %esp 8/imm32
 8245     # . epilogue
 8246     5d/pop-to-ebp
 8247     c3/return
 8248 
 8249 test-copy-to-with-no-register:
 8250     # . prologue
 8251     55/push-ebp
 8252     89/<- %ebp 4/r32/esp
 8253     # setup
 8254     (clear-stream _test-input-stream)
 8255     (clear-stream $_test-input-buffered-file->buffer)
 8256     (clear-stream _test-output-stream)
 8257     (clear-stream $_test-output-buffered-file->buffer)
 8258     (clear-stream _test-error-stream)
 8259     (clear-stream $_test-error-buffered-file->buffer)
 8260     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8261     68/push 0/imm32
 8262     68/push 0/imm32
 8263     89/<- %edx 4/r32/esp
 8264     (tailor-exit-descriptor %edx 0x10)
 8265     #
 8266     (write _test-input-stream "fn foo {\n")
 8267     (write _test-input-stream "  var x: boolean\n")
 8268     (write _test-input-stream "  copy-to x, x\n")
 8269     (write _test-input-stream "}\n")
 8270     # convert
 8271     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8272     # registers except esp clobbered at this point
 8273     # restore ed
 8274     89/<- %edx 4/r32/esp
 8275     (flush _test-output-buffered-file)
 8276     (flush _test-error-buffered-file)
 8277 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8283     # check output
 8284     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-no-register: output should be empty")
 8285     (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")
 8286     # check that stop(1) was called
 8287     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-register: exit status")
 8288     # don't restore from ebp
 8289     81 0/subop/add %esp 8/imm32
 8290     # . epilogue
 8291     5d/pop-to-ebp
 8292     c3/return
 8293 
 8294 test-copy-to-with-too-many-inouts:
 8295     # . prologue
 8296     55/push-ebp
 8297     89/<- %ebp 4/r32/esp
 8298     # setup
 8299     (clear-stream _test-input-stream)
 8300     (clear-stream $_test-input-buffered-file->buffer)
 8301     (clear-stream _test-output-stream)
 8302     (clear-stream $_test-output-buffered-file->buffer)
 8303     (clear-stream _test-error-stream)
 8304     (clear-stream $_test-error-buffered-file->buffer)
 8305     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8306     68/push 0/imm32
 8307     68/push 0/imm32
 8308     89/<- %edx 4/r32/esp
 8309     (tailor-exit-descriptor %edx 0x10)
 8310     #
 8311     (write _test-input-stream "fn foo {\n")
 8312     (write _test-input-stream "  var x: boolean\n")
 8313     (write _test-input-stream "  copy-to x, 0, 0\n")
 8314     (write _test-input-stream "}\n")
 8315     # convert
 8316     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8317     # registers except esp clobbered at this point
 8318     # restore ed
 8319     89/<- %edx 4/r32/esp
 8320     (flush _test-output-buffered-file)
 8321     (flush _test-error-buffered-file)
 8322 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8328     # check output
 8329     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-too-many-inouts: output should be empty")
 8330     (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")
 8331     # check that stop(1) was called
 8332     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-too-many-inouts: exit status")
 8333     # don't restore from ebp
 8334     81 0/subop/add %esp 8/imm32
 8335     # . epilogue
 8336     5d/pop-to-ebp
 8337     c3/return
 8338 
 8339 test-copy-to-with-output:
 8340     # . prologue
 8341     55/push-ebp
 8342     89/<- %ebp 4/r32/esp
 8343     # setup
 8344     (clear-stream _test-input-stream)
 8345     (clear-stream $_test-input-buffered-file->buffer)
 8346     (clear-stream _test-output-stream)
 8347     (clear-stream $_test-output-buffered-file->buffer)
 8348     (clear-stream _test-error-stream)
 8349     (clear-stream $_test-error-buffered-file->buffer)
 8350     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8351     68/push 0/imm32
 8352     68/push 0/imm32
 8353     89/<- %edx 4/r32/esp
 8354     (tailor-exit-descriptor %edx 0x10)
 8355     #
 8356     (write _test-input-stream "fn foo {\n")
 8357     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 8358     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
 8359     (write _test-input-stream "  x <- copy-to y, 0\n")
 8360     (write _test-input-stream "}\n")
 8361     # convert
 8362     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8363     # registers except esp clobbered at this point
 8364     # restore ed
 8365     89/<- %edx 4/r32/esp
 8366     (flush _test-output-buffered-file)
 8367     (flush _test-error-buffered-file)
 8368 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8374     # check output
 8375     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-output: output should be empty")
 8376     (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")
 8377     # check that stop(1) was called
 8378     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-output: exit status")
 8379     # don't restore from ebp
 8380     81 0/subop/add %esp 8/imm32
 8381     # . epilogue
 8382     5d/pop-to-ebp
 8383     c3/return
 8384 
 8385 test-copy-to-invalid-value-to-address:
 8386     # . prologue
 8387     55/push-ebp
 8388     89/<- %ebp 4/r32/esp
 8389     # setup
 8390     (clear-stream _test-input-stream)
 8391     (clear-stream $_test-input-buffered-file->buffer)
 8392     (clear-stream _test-output-stream)
 8393     (clear-stream $_test-output-buffered-file->buffer)
 8394     (clear-stream _test-error-stream)
 8395     (clear-stream $_test-error-buffered-file->buffer)
 8396     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8397     68/push 0/imm32
 8398     68/push 0/imm32
 8399     89/<- %edx 4/r32/esp
 8400     (tailor-exit-descriptor %edx 0x10)
 8401     #
 8402     (write _test-input-stream "fn foo {\n")
 8403     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 8404     (write _test-input-stream "  var y: (addr int)\n")
 8405     (write _test-input-stream "  copy-to y, x\n")
 8406     (write _test-input-stream "}\n")
 8407     # convert
 8408     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8409     # registers except esp clobbered at this point
 8410     # restore ed
 8411     89/<- %edx 4/r32/esp
 8412     (flush _test-output-buffered-file)
 8413     (flush _test-error-buffered-file)
 8414 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8420     # check output
 8421     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-invalid-value-to-address: output should be empty")
 8422     (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")
 8423     # check that stop(1) was called
 8424     (check-ints-equal *(edx+4) 2 "F - test-copy-to-invalid-value-to-address: exit status")
 8425     # don't restore from ebp
 8426     81 0/subop/add %esp 8/imm32
 8427     # . epilogue
 8428     5d/pop-to-ebp
 8429     c3/return
 8430 
 8431 test-copy-to-null-value-to-address:
 8432     # . prologue
 8433     55/push-ebp
 8434     89/<- %ebp 4/r32/esp
 8435     # setup
 8436     (clear-stream _test-input-stream)
 8437     (clear-stream $_test-input-buffered-file->buffer)
 8438     (clear-stream _test-output-stream)
 8439     (clear-stream $_test-output-buffered-file->buffer)
 8440     #
 8441     (write _test-input-stream "fn foo {\n")
 8442     (write _test-input-stream "  var y: (addr int)\n")
 8443     (write _test-input-stream "  copy-to y, 0\n")
 8444     (write _test-input-stream "}\n")
 8445     # convert
 8446     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8447     (flush _test-output-buffered-file)
 8448     # no errors
 8449     # . epilogue
 8450     89/<- %esp 5/r32/ebp
 8451     5d/pop-to-ebp
 8452     c3/return
 8453 
 8454 test-copy-to-invalid-value-to-offset:
 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/eax: int <- copy 0\n")
 8473     (write _test-input-stream "  var y: (offset int)\n")
 8474     (write _test-input-stream "  copy-to 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-copy-to-invalid-value-to-offset: output should be empty")
 8491     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-to: 'y' must be a non-addr non-offset scalar"  "F - test-copy-to-invalid-value-to-offset: error message")
 8492     # check that stop(1) was called
 8493     (check-ints-equal *(edx+4) 2 "F - test-copy-to-invalid-value-to-offset: exit status")
 8494     # don't restore from ebp
 8495     81 0/subop/add %esp 8/imm32
 8496     # . epilogue
 8497     5d/pop-to-ebp
 8498     c3/return
 8499 
 8500 test-copy-to-null-value-to-offset:
 8501     # . prologue
 8502     55/push-ebp
 8503     89/<- %ebp 4/r32/esp
 8504     # setup
 8505     (clear-stream _test-input-stream)
 8506     (clear-stream $_test-input-buffered-file->buffer)
 8507     (clear-stream _test-output-stream)
 8508     (clear-stream $_test-output-buffered-file->buffer)
 8509     #
 8510     (write _test-input-stream "fn foo {\n")
 8511     (write _test-input-stream "  var y: (offset int)\n")
 8512     (write _test-input-stream "  copy-to y, 0\n")
 8513     (write _test-input-stream "}\n")
 8514     # convert
 8515     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8516     (flush _test-output-buffered-file)
 8517     # no errors
 8518     # . epilogue
 8519     89/<- %esp 5/r32/ebp
 8520     5d/pop-to-ebp
 8521     c3/return
 8522 
 8523 test-copy-to-non-literal-to-byte:
 8524     # . prologue
 8525     55/push-ebp
 8526     89/<- %ebp 4/r32/esp
 8527     # setup
 8528     (clear-stream _test-input-stream)
 8529     (clear-stream $_test-input-buffered-file->buffer)
 8530     (clear-stream _test-output-stream)
 8531     (clear-stream $_test-output-buffered-file->buffer)
 8532     (clear-stream _test-error-stream)
 8533     (clear-stream $_test-error-buffered-file->buffer)
 8534     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8535     68/push 0/imm32
 8536     68/push 0/imm32
 8537     89/<- %edx 4/r32/esp
 8538     (tailor-exit-descriptor %edx 0x10)
 8539     #
 8540     (write _test-input-stream "fn foo {\n")
 8541     (write _test-input-stream "  var x/ecx: byte <- copy 3\n")
 8542     (write _test-input-stream "  var y/eax: (addr byte) <- copy 0\n")
 8543     (write _test-input-stream "  copy-to *y, x\n")
 8544     (write _test-input-stream "}\n")
 8545     # convert
 8546     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8547     # registers except esp clobbered at this point
 8548     # restore ed
 8549     89/<- %edx 4/r32/esp
 8550     (flush _test-output-buffered-file)
 8551     (flush _test-error-buffered-file)
 8552 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8558     # check output
 8559     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-non-literal-to-byte: output should be empty")
 8560     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-to: cannot copy non-literal to type byte; use copy-byte-to"  "F - test-copy-to-non-literal-to-byte: error message")
 8561     # check that stop(1) was called
 8562     (check-ints-equal *(edx+4) 2 "F - test-copy-to-non-literal-to-byte: exit status")
 8563     # don't restore from ebp
 8564     81 0/subop/add %esp 8/imm32
 8565     # . epilogue
 8566     5d/pop-to-ebp
 8567     c3/return
 8568 
 8569 test-copy-to-deref-address:
 8570     # . prologue
 8571     55/push-ebp
 8572     89/<- %ebp 4/r32/esp
 8573     # setup
 8574     (clear-stream _test-input-stream)
 8575     (clear-stream $_test-input-buffered-file->buffer)
 8576     (clear-stream _test-output-stream)
 8577     (clear-stream $_test-output-buffered-file->buffer)
 8578     #
 8579     (write _test-input-stream "fn foo {\n")
 8580     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
 8581     (write _test-input-stream "  var y/ecx: (addr addr int) <- copy 0\n")
 8582     (write _test-input-stream "  copy-to *y, x\n")
 8583     (write _test-input-stream "}\n")
 8584     # convert
 8585     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8586     (flush _test-output-buffered-file)
 8587     # no errors
 8588     # . epilogue
 8589     5d/pop-to-ebp
 8590     c3/return
 8591 
 8592 test-copy-to-from-non-scalar-inout:
 8593     # . prologue
 8594     55/push-ebp
 8595     89/<- %ebp 4/r32/esp
 8596     # setup
 8597     (clear-stream _test-input-stream)
 8598     (clear-stream $_test-input-buffered-file->buffer)
 8599     (clear-stream _test-output-stream)
 8600     (clear-stream $_test-output-buffered-file->buffer)
 8601     (clear-stream _test-error-stream)
 8602     (clear-stream $_test-error-buffered-file->buffer)
 8603     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8604     68/push 0/imm32
 8605     68/push 0/imm32
 8606     89/<- %edx 4/r32/esp
 8607     (tailor-exit-descriptor %edx 0x10)
 8608     #
 8609     (write _test-input-stream "fn foo {\n")
 8610     (write _test-input-stream "  var x: (handle int)\n")
 8611     (write _test-input-stream "  var y: int\n")
 8612     (write _test-input-stream "  copy-to y, x\n")
 8613     (write _test-input-stream "}\n")
 8614     # convert
 8615     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8616     # registers except esp clobbered at this point
 8617     # restore ed
 8618     89/<- %edx 4/r32/esp
 8619     (flush _test-output-buffered-file)
 8620     (flush _test-error-buffered-file)
 8621 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8627     # check output
 8628     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-from-non-scalar-inout: output should be empty")
 8629     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-to: 'x' is too large to copy"  "F - test-copy-to-from-non-scalar-inout: error message")
 8630     # check that stop(1) was called
 8631     (check-ints-equal *(edx+4) 2 "F - test-copy-to-from-non-scalar-inout: exit status")
 8632     # don't restore from ebp
 8633     81 0/subop/add %esp 8/imm32
 8634     # . epilogue
 8635     5d/pop-to-ebp
 8636     c3/return
 8637 
 8638 test-copy-byte-with-no-inout:
 8639     # . prologue
 8640     55/push-ebp
 8641     89/<- %ebp 4/r32/esp
 8642     # setup
 8643     (clear-stream _test-input-stream)
 8644     (clear-stream $_test-input-buffered-file->buffer)
 8645     (clear-stream _test-output-stream)
 8646     (clear-stream $_test-output-buffered-file->buffer)
 8647     (clear-stream _test-error-stream)
 8648     (clear-stream $_test-error-buffered-file->buffer)
 8649     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8650     68/push 0/imm32
 8651     68/push 0/imm32
 8652     89/<- %edx 4/r32/esp
 8653     (tailor-exit-descriptor %edx 0x10)
 8654     #
 8655     (write _test-input-stream "fn foo {\n")
 8656     (write _test-input-stream "  var x/eax: byte <- copy-byte\n")
 8657     (write _test-input-stream "}\n")
 8658     # convert
 8659     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8660     # registers except esp clobbered at this point
 8661     # restore ed
 8662     89/<- %edx 4/r32/esp
 8663     (flush _test-output-buffered-file)
 8664     (flush _test-error-buffered-file)
 8665 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8671     # check output
 8672     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-no-inout: output should be empty")
 8673     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte' expects an inout"  "F - test-copy-byte-with-no-inout: error message")
 8674     # check that stop(1) was called
 8675     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-no-inout: exit status")
 8676     # don't restore from ebp
 8677     81 0/subop/add %esp 8/imm32
 8678     # . epilogue
 8679     5d/pop-to-ebp
 8680     c3/return
 8681 
 8682 test-copy-byte-with-multiple-inouts:
 8683     # . prologue
 8684     55/push-ebp
 8685     89/<- %ebp 4/r32/esp
 8686     # setup
 8687     (clear-stream _test-input-stream)
 8688     (clear-stream $_test-input-buffered-file->buffer)
 8689     (clear-stream _test-output-stream)
 8690     (clear-stream $_test-output-buffered-file->buffer)
 8691     (clear-stream _test-error-stream)
 8692     (clear-stream $_test-error-buffered-file->buffer)
 8693     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8694     68/push 0/imm32
 8695     68/push 0/imm32
 8696     89/<- %edx 4/r32/esp
 8697     (tailor-exit-descriptor %edx 0x10)
 8698     #
 8699     (write _test-input-stream "fn foo {\n")
 8700     (write _test-input-stream "  var x/eax: byte <- copy-byte 0, 0\n")
 8701     (write _test-input-stream "}\n")
 8702     # convert
 8703     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8704     # registers except esp clobbered at this point
 8705     # restore ed
 8706     89/<- %edx 4/r32/esp
 8707     (flush _test-output-buffered-file)
 8708     (flush _test-error-buffered-file)
 8709 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8715     # check output
 8716     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-multiple-inouts: output should be empty")
 8717     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte' must have just one inout"  "F - test-copy-byte-with-multiple-inouts: error message")
 8718     # check that stop(1) was called
 8719     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-multiple-inouts: exit status")
 8720     # don't restore from ebp
 8721     81 0/subop/add %esp 8/imm32
 8722     # . epilogue
 8723     5d/pop-to-ebp
 8724     c3/return
 8725 
 8726 test-copy-byte-with-no-output:
 8727     # . prologue
 8728     55/push-ebp
 8729     89/<- %ebp 4/r32/esp
 8730     # setup
 8731     (clear-stream _test-input-stream)
 8732     (clear-stream $_test-input-buffered-file->buffer)
 8733     (clear-stream _test-output-stream)
 8734     (clear-stream $_test-output-buffered-file->buffer)
 8735     (clear-stream _test-error-stream)
 8736     (clear-stream $_test-error-buffered-file->buffer)
 8737     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8738     68/push 0/imm32
 8739     68/push 0/imm32
 8740     89/<- %edx 4/r32/esp
 8741     (tailor-exit-descriptor %edx 0x10)
 8742     #
 8743     (write _test-input-stream "fn foo {\n")
 8744     (write _test-input-stream "  copy-byte 0\n")
 8745     (write _test-input-stream "}\n")
 8746     # convert
 8747     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8748     # registers except esp clobbered at this point
 8749     # restore ed
 8750     89/<- %edx 4/r32/esp
 8751     (flush _test-output-buffered-file)
 8752     (flush _test-error-buffered-file)
 8753 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8759     # check output
 8760     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-no-output: output should be empty")
 8761     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte' expects an output"  "F - test-copy-byte-with-no-output: error message")
 8762     # check that stop(1) was called
 8763     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-no-output: exit status")
 8764     # don't restore from ebp
 8765     81 0/subop/add %esp 8/imm32
 8766     # . epilogue
 8767     5d/pop-to-ebp
 8768     c3/return
 8769 
 8770 test-copy-byte-with-multiple-outputs:
 8771     # . prologue
 8772     55/push-ebp
 8773     89/<- %ebp 4/r32/esp
 8774     # setup
 8775     (clear-stream _test-input-stream)
 8776     (clear-stream $_test-input-buffered-file->buffer)
 8777     (clear-stream _test-output-stream)
 8778     (clear-stream $_test-output-buffered-file->buffer)
 8779     (clear-stream _test-error-stream)
 8780     (clear-stream $_test-error-buffered-file->buffer)
 8781     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8782     68/push 0/imm32
 8783     68/push 0/imm32
 8784     89/<- %edx 4/r32/esp
 8785     (tailor-exit-descriptor %edx 0x10)
 8786     #
 8787     (write _test-input-stream "fn foo {\n")
 8788     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
 8789     (write _test-input-stream "  var y/ecx: byte <- copy 0\n")
 8790     (write _test-input-stream "  x, y <- copy-byte 0\n")
 8791     (write _test-input-stream "}\n")
 8792     # convert
 8793     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8794     # registers except esp clobbered at this point
 8795     # restore ed
 8796     89/<- %edx 4/r32/esp
 8797     (flush _test-output-buffered-file)
 8798     (flush _test-error-buffered-file)
 8799 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8805     # check output
 8806     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-multiple-outputs: output should be empty")
 8807     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte' must have just one output"  "F - test-copy-byte-with-multiple-outputs: error message")
 8808     # check that stop(1) was called
 8809     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-multiple-outputs: exit status")
 8810     # don't restore from ebp
 8811     81 0/subop/add %esp 8/imm32
 8812     # . epilogue
 8813     5d/pop-to-ebp
 8814     c3/return
 8815 
 8816 test-copy-byte-deref-address:
 8817     # . prologue
 8818     55/push-ebp
 8819     89/<- %ebp 4/r32/esp
 8820     # setup
 8821     (clear-stream _test-input-stream)
 8822     (clear-stream $_test-input-buffered-file->buffer)
 8823     (clear-stream _test-output-stream)
 8824     (clear-stream $_test-output-buffered-file->buffer)
 8825     #
 8826     (write _test-input-stream "fn foo {\n")
 8827     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
 8828     (write _test-input-stream "  var y/ecx: byte <- copy-byte *x\n")
 8829     (write _test-input-stream "}\n")
 8830     # convert
 8831     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8832     (flush _test-output-buffered-file)
 8833 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8839     # not bothering checking output
 8840     (check-next-stream-line-equal _test-error-stream  ""  "F - test-copy-byte-deref-address: error message")
 8841     # . epilogue
 8842     5d/pop-to-ebp
 8843     c3/return
 8844 
 8845 test-copy-byte-with-invalid-output-type:
 8846     # . prologue
 8847     55/push-ebp
 8848     89/<- %ebp 4/r32/esp
 8849     # setup
 8850     (clear-stream _test-input-stream)
 8851     (clear-stream $_test-input-buffered-file->buffer)
 8852     (clear-stream _test-output-stream)
 8853     (clear-stream $_test-output-buffered-file->buffer)
 8854     (clear-stream _test-error-stream)
 8855     (clear-stream $_test-error-buffered-file->buffer)
 8856     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8857     68/push 0/imm32
 8858     68/push 0/imm32
 8859     89/<- %edx 4/r32/esp
 8860     (tailor-exit-descriptor %edx 0x10)
 8861     #
 8862     (write _test-input-stream "fn foo {\n")
 8863     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
 8864     (write _test-input-stream "  var y/eax: int <- copy-byte *x\n")
 8865     (write _test-input-stream "}\n")
 8866     # convert
 8867     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8868     # registers except esp clobbered at this point
 8869     # restore ed
 8870     89/<- %edx 4/r32/esp
 8871     (flush _test-output-buffered-file)
 8872     (flush _test-error-buffered-file)
 8873 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8879     # check output
 8880     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-invalid-output-type: output should be empty")
 8881     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte' must write to output of type byte"  "F - test-copy-byte-with-invalid-output-type: error message")
 8882     # check that stop(1) was called
 8883     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-invalid-output-type: exit status")
 8884     # don't restore from ebp
 8885     81 0/subop/add %esp 8/imm32
 8886     # . epilogue
 8887     5d/pop-to-ebp
 8888     c3/return
 8889 
 8890 test-copy-byte-from-non-scalar-inout:
 8891     # . prologue
 8892     55/push-ebp
 8893     89/<- %ebp 4/r32/esp
 8894     # setup
 8895     (clear-stream _test-input-stream)
 8896     (clear-stream $_test-input-buffered-file->buffer)
 8897     (clear-stream _test-output-stream)
 8898     (clear-stream $_test-output-buffered-file->buffer)
 8899     (clear-stream _test-error-stream)
 8900     (clear-stream $_test-error-buffered-file->buffer)
 8901     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8902     68/push 0/imm32
 8903     68/push 0/imm32
 8904     89/<- %edx 4/r32/esp
 8905     (tailor-exit-descriptor %edx 0x10)
 8906     #
 8907     (write _test-input-stream "fn foo {\n")
 8908     (write _test-input-stream "  var x: (handle int)\n")
 8909     (write _test-input-stream "  var y/eax: byte <- copy-byte x\n")
 8910     (write _test-input-stream "}\n")
 8911     # convert
 8912     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8913     # registers except esp clobbered at this point
 8914     # restore ed
 8915     89/<- %edx 4/r32/esp
 8916     (flush _test-output-buffered-file)
 8917     (flush _test-error-buffered-file)
 8918 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8924     # check output
 8925     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-from-non-scalar-inout: output should be empty")
 8926     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-byte: 'x' is too large to fit in a register"  "F - test-copy-byte-from-non-scalar-inout: error message")
 8927     # check that stop(1) was called
 8928     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-from-non-scalar-inout: exit status")
 8929     # don't restore from ebp
 8930     81 0/subop/add %esp 8/imm32
 8931     # . epilogue
 8932     5d/pop-to-ebp
 8933     c3/return
 8934 
 8935 test-copy-byte-to-with-no-inout:
 8936     # . prologue
 8937     55/push-ebp
 8938     89/<- %ebp 4/r32/esp
 8939     # setup
 8940     (clear-stream _test-input-stream)
 8941     (clear-stream $_test-input-buffered-file->buffer)
 8942     (clear-stream _test-output-stream)
 8943     (clear-stream $_test-output-buffered-file->buffer)
 8944     (clear-stream _test-error-stream)
 8945     (clear-stream $_test-error-buffered-file->buffer)
 8946     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8947     68/push 0/imm32
 8948     68/push 0/imm32
 8949     89/<- %edx 4/r32/esp
 8950     (tailor-exit-descriptor %edx 0x10)
 8951     #
 8952     (write _test-input-stream "fn foo {\n")
 8953     (write _test-input-stream "  copy-byte-to\n")
 8954     (write _test-input-stream "}\n")
 8955     # convert
 8956     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8957     # registers except esp clobbered at this point
 8958     # restore ed
 8959     89/<- %edx 4/r32/esp
 8960     (flush _test-output-buffered-file)
 8961     (flush _test-error-buffered-file)
 8962 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8968     # check output
 8969     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-no-inout: output should be empty")
 8970     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte-to' must have two inouts"  "F - test-copy-byte-to-with-no-inout: error message")
 8971     # check that stop(1) was called
 8972     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-no-inout: exit status")
 8973     # don't restore from ebp
 8974     81 0/subop/add %esp 8/imm32
 8975     # . epilogue
 8976     5d/pop-to-ebp
 8977     c3/return
 8978 
 8979 test-copy-byte-to-with-no-source:
 8980     # . prologue
 8981     55/push-ebp
 8982     89/<- %ebp 4/r32/esp
 8983     # setup
 8984     (clear-stream _test-input-stream)
 8985     (clear-stream $_test-input-buffered-file->buffer)
 8986     (clear-stream _test-output-stream)
 8987     (clear-stream $_test-output-buffered-file->buffer)
 8988     (clear-stream _test-error-stream)
 8989     (clear-stream $_test-error-buffered-file->buffer)
 8990     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8991     68/push 0/imm32
 8992     68/push 0/imm32
 8993     89/<- %edx 4/r32/esp
 8994     (tailor-exit-descriptor %edx 0x10)
 8995     #
 8996     (write _test-input-stream "fn foo {\n")
 8997     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
 8998     (write _test-input-stream "  copy-byte-to *x\n")
 8999     (write _test-input-stream "}\n")
 9000     # convert
 9001     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9002     # registers except esp clobbered at this point
 9003     # restore ed
 9004     89/<- %edx 4/r32/esp
 9005     (flush _test-output-buffered-file)
 9006     (flush _test-error-buffered-file)
 9007 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9013     # check output
 9014     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-no-source: output should be empty")
 9015     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte-to' must have two inouts"  "F - test-copy-byte-to-with-no-source: error message")
 9016     # check that stop(1) was called
 9017     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-no-source: exit status")
 9018     # don't restore from ebp
 9019     81 0/subop/add %esp 8/imm32
 9020     # . epilogue
 9021     5d/pop-to-ebp
 9022     c3/return
 9023 
 9024 test-copy-byte-to-with-too-many-inouts:
 9025     # . prologue
 9026     55/push-ebp
 9027     89/<- %ebp 4/r32/esp
 9028     # setup
 9029     (clear-stream _test-input-stream)
 9030     (clear-stream $_test-input-buffered-file->buffer)
 9031     (clear-stream _test-output-stream)
 9032     (clear-stream $_test-output-buffered-file->buffer)
 9033     (clear-stream _test-error-stream)
 9034     (clear-stream $_test-error-buffered-file->buffer)
 9035     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9036     68/push 0/imm32
 9037     68/push 0/imm32
 9038     89/<- %edx 4/r32/esp
 9039     (tailor-exit-descriptor %edx 0x10)
 9040     #
 9041     (write _test-input-stream "fn foo {\n")
 9042     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
 9043     (write _test-input-stream "  copy-byte-to *x, 0, 0\n")
 9044     (write _test-input-stream "}\n")
 9045     # convert
 9046     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9047     # registers except esp clobbered at this point
 9048     # restore ed
 9049     89/<- %edx 4/r32/esp
 9050     (flush _test-output-buffered-file)
 9051     (flush _test-error-buffered-file)
 9052 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9058     # check output
 9059     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-too-many-inouts: output should be empty")
 9060     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte-to' must have two inouts"  "F - test-copy-byte-to-with-too-many-inouts: error message")
 9061     # check that stop(1) was called
 9062     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-too-many-inouts: exit status")
 9063     # don't restore from ebp
 9064     81 0/subop/add %esp 8/imm32
 9065     # . epilogue
 9066     5d/pop-to-ebp
 9067     c3/return
 9068 
 9069 test-copy-byte-to-with-output:
 9070     # . prologue
 9071     55/push-ebp
 9072     89/<- %ebp 4/r32/esp
 9073     # setup
 9074     (clear-stream _test-input-stream)
 9075     (clear-stream $_test-input-buffered-file->buffer)
 9076     (clear-stream _test-output-stream)
 9077     (clear-stream $_test-output-buffered-file->buffer)
 9078     (clear-stream _test-error-stream)
 9079     (clear-stream $_test-error-buffered-file->buffer)
 9080     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9081     68/push 0/imm32
 9082     68/push 0/imm32
 9083     89/<- %edx 4/r32/esp
 9084     (tailor-exit-descriptor %edx 0x10)
 9085     #
 9086     (write _test-input-stream "fn foo {\n")
 9087     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
 9088     (write _test-input-stream "  var y/ecx: (addr byte) <- copy 0\n")
 9089     (write _test-input-stream "  x <- copy-byte-to *y, 0\n")
 9090     (write _test-input-stream "}\n")
 9091     # convert
 9092     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9093     # registers except esp clobbered at this point
 9094     # restore ed
 9095     89/<- %edx 4/r32/esp
 9096     (flush _test-output-buffered-file)
 9097     (flush _test-error-buffered-file)
 9098 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9104     # check output
 9105     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-output: output should be empty")
 9106     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte-to' must not have any outputs"  "F - test-copy-byte-to-with-output: error message")
 9107     # check that stop(1) was called
 9108     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-output: exit status")
 9109     # don't restore from ebp
 9110     81 0/subop/add %esp 8/imm32
 9111     # . epilogue
 9112     5d/pop-to-ebp
 9113     c3/return
 9114 
 9115 test-copy-byte-to-with-invalid-output-type:
 9116     # . prologue
 9117     55/push-ebp
 9118     89/<- %ebp 4/r32/esp
 9119     # setup
 9120     (clear-stream _test-input-stream)
 9121     (clear-stream $_test-input-buffered-file->buffer)
 9122     (clear-stream _test-output-stream)
 9123     (clear-stream $_test-output-buffered-file->buffer)
 9124     (clear-stream _test-error-stream)
 9125     (clear-stream $_test-error-buffered-file->buffer)
 9126     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9127     68/push 0/imm32
 9128     68/push 0/imm32
 9129     89/<- %edx 4/r32/esp
 9130     (tailor-exit-descriptor %edx 0x10)
 9131     #
 9132     (write _test-input-stream "fn foo {\n")
 9133     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
 9134     (write _test-input-stream "  var y: int\n")
 9135     (write _test-input-stream "  copy-byte-to y, x\n")
 9136     (write _test-input-stream "}\n")
 9137     # convert
 9138     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9139     # registers except esp clobbered at this point
 9140     # restore ed
 9141     89/<- %edx 4/r32/esp
 9142     (flush _test-output-buffered-file)
 9143     (flush _test-error-buffered-file)
 9144 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9150     # check output
 9151     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-invalid-output-type: output should be empty")
 9152     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-byte-to: 'y' must be a byte"  "F - test-copy-byte-to-with-invalid-output-type: error message")
 9153     # check that stop(1) was called
 9154     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-invalid-output-type: exit status")
 9155     # don't restore from ebp
 9156     81 0/subop/add %esp 8/imm32
 9157     # . epilogue
 9158     5d/pop-to-ebp
 9159     c3/return
 9160 
 9161 test-copy-byte-to-with-literal-inout:
 9162     # . prologue
 9163     55/push-ebp
 9164     89/<- %ebp 4/r32/esp
 9165     # setup
 9166     (clear-stream _test-input-stream)
 9167     (clear-stream $_test-input-buffered-file->buffer)
 9168     (clear-stream _test-output-stream)
 9169     (clear-stream $_test-output-buffered-file->buffer)
 9170     (clear-stream _test-error-stream)
 9171     (clear-stream $_test-error-buffered-file->buffer)
 9172     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9173     68/push 0/imm32
 9174     68/push 0/imm32
 9175     89/<- %edx 4/r32/esp
 9176     (tailor-exit-descriptor %edx 0x10)
 9177     #
 9178     (write _test-input-stream "fn foo {\n")
 9179     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
 9180     (write _test-input-stream "  copy-byte-to *x, 0\n")
 9181     (write _test-input-stream "}\n")
 9182     # convert
 9183     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9184     # registers except esp clobbered at this point
 9185     # restore ed
 9186     89/<- %edx 4/r32/esp
 9187     (flush _test-output-buffered-file)
 9188     (flush _test-error-buffered-file)
 9189 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9195     # check output
 9196     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-literal-inout: output should be empty")
 9197     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-byte-to: source (second inout) must be in a register"  "F - test-copy-byte-to-with-literal-inout: error message")
 9198     # check that stop(1) was called
 9199     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-literal-inout: exit status")
 9200     # don't restore from ebp
 9201     81 0/subop/add %esp 8/imm32
 9202     # . epilogue
 9203     5d/pop-to-ebp
 9204     c3/return
 9205 
 9206 test-copy-byte-to-deref-address:
 9207     # . prologue
 9208     55/push-ebp
 9209     89/<- %ebp 4/r32/esp
 9210     # setup
 9211     (clear-stream _test-input-stream)
 9212     (clear-stream $_test-input-buffered-file->buffer)
 9213     (clear-stream _test-output-stream)
 9214     (clear-stream $_test-output-buffered-file->buffer)
 9215     #
 9216     (write _test-input-stream "fn foo {\n")
 9217     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
 9218     (write _test-input-stream "  var y/ecx: (addr byte) <- copy 0\n")
 9219     (write _test-input-stream "  copy-byte-to *y, x\n")
 9220     (write _test-input-stream "}\n")
 9221     # convert
 9222     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9223     (flush _test-output-buffered-file)
 9224     # no errors
 9225     # . epilogue
 9226     5d/pop-to-ebp
 9227     c3/return
 9228 
 9229 test-copy-byte-to-from-non-scalar-inout:
 9230     # . prologue
 9231     55/push-ebp
 9232     89/<- %ebp 4/r32/esp
 9233     # setup
 9234     (clear-stream _test-input-stream)
 9235     (clear-stream $_test-input-buffered-file->buffer)
 9236     (clear-stream _test-output-stream)
 9237     (clear-stream $_test-output-buffered-file->buffer)
 9238     (clear-stream _test-error-stream)
 9239     (clear-stream $_test-error-buffered-file->buffer)
 9240     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9241     68/push 0/imm32
 9242     68/push 0/imm32
 9243     89/<- %edx 4/r32/esp
 9244     (tailor-exit-descriptor %edx 0x10)
 9245     #
 9246     (write _test-input-stream "fn foo {\n")
 9247     (write _test-input-stream "  var x: (handle int)\n")
 9248     (write _test-input-stream "  var y/eax: (addr byte) <- copy 0\n")
 9249     (write _test-input-stream "  copy-byte-to *y, x\n")
 9250     (write _test-input-stream "}\n")
 9251     # convert
 9252     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9253     # registers except esp clobbered at this point
 9254     # restore ed
 9255     89/<- %edx 4/r32/esp
 9256     (flush _test-output-buffered-file)
 9257     (flush _test-error-buffered-file)
 9258 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9264     # check output
 9265     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-from-non-scalar-inout: output should be empty")
 9266     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-byte-to: 'x' is too large to copy"  "F - test-copy-byte-to-from-non-scalar-inout: error message")
 9267     # check that stop(1) was called
 9268     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-from-non-scalar-inout: exit status")
 9269     # don't restore from ebp
 9270     81 0/subop/add %esp 8/imm32
 9271     # . epilogue
 9272     5d/pop-to-ebp
 9273     c3/return
 9274 
 9275 test-compare-with-no-inout:
 9276     # . prologue
 9277     55/push-ebp
 9278     89/<- %ebp 4/r32/esp
 9279     # setup
 9280     (clear-stream _test-input-stream)
 9281     (clear-stream $_test-input-buffered-file->buffer)
 9282     (clear-stream _test-output-stream)
 9283     (clear-stream $_test-output-buffered-file->buffer)
 9284     (clear-stream _test-error-stream)
 9285     (clear-stream $_test-error-buffered-file->buffer)
 9286     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9287     68/push 0/imm32
 9288     68/push 0/imm32
 9289     89/<- %edx 4/r32/esp
 9290     (tailor-exit-descriptor %edx 0x10)
 9291     #
 9292     (write _test-input-stream "fn foo {\n")
 9293     (write _test-input-stream "  var x: boolean\n")
 9294     (write _test-input-stream "  compare\n")
 9295     (write _test-input-stream "}\n")
 9296     # convert
 9297     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9298     # registers except esp clobbered at this point
 9299     # restore ed
 9300     89/<- %edx 4/r32/esp
 9301     (flush _test-output-buffered-file)
 9302     (flush _test-error-buffered-file)
 9303 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9309     # check output
 9310     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-no-inout: output should be empty")
 9311     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must have two inouts"  "F - test-compare-with-no-inout: error message")
 9312     # check that stop(1) was called
 9313     (check-ints-equal *(edx+4) 2 "F - test-compare-with-no-inout: exit status")
 9314     # don't restore from ebp
 9315     81 0/subop/add %esp 8/imm32
 9316     # . epilogue
 9317     5d/pop-to-ebp
 9318     c3/return
 9319 
 9320 test-compare-with-just-one-inout:
 9321     # . prologue
 9322     55/push-ebp
 9323     89/<- %ebp 4/r32/esp
 9324     # setup
 9325     (clear-stream _test-input-stream)
 9326     (clear-stream $_test-input-buffered-file->buffer)
 9327     (clear-stream _test-output-stream)
 9328     (clear-stream $_test-output-buffered-file->buffer)
 9329     (clear-stream _test-error-stream)
 9330     (clear-stream $_test-error-buffered-file->buffer)
 9331     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9332     68/push 0/imm32
 9333     68/push 0/imm32
 9334     89/<- %edx 4/r32/esp
 9335     (tailor-exit-descriptor %edx 0x10)
 9336     #
 9337     (write _test-input-stream "fn foo {\n")
 9338     (write _test-input-stream "  var x: boolean\n")
 9339     (write _test-input-stream "  compare x\n")
 9340     (write _test-input-stream "}\n")
 9341     # convert
 9342     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9343     # registers except esp clobbered at this point
 9344     # restore ed
 9345     89/<- %edx 4/r32/esp
 9346     (flush _test-output-buffered-file)
 9347     (flush _test-error-buffered-file)
 9348 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9354     # check output
 9355     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-just-one-inout: output should be empty")
 9356     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must have two inouts"  "F - test-compare-with-just-one-inout: error message")
 9357     # check that stop(1) was called
 9358     (check-ints-equal *(edx+4) 2 "F - test-compare-with-just-one-inout: exit status")
 9359     # don't restore from ebp
 9360     81 0/subop/add %esp 8/imm32
 9361     # . epilogue
 9362     5d/pop-to-ebp
 9363     c3/return
 9364 
 9365 test-compare-with-too-many-inouts:
 9366     # . prologue
 9367     55/push-ebp
 9368     89/<- %ebp 4/r32/esp
 9369     # setup
 9370     (clear-stream _test-input-stream)
 9371     (clear-stream $_test-input-buffered-file->buffer)
 9372     (clear-stream _test-output-stream)
 9373     (clear-stream $_test-output-buffered-file->buffer)
 9374     (clear-stream _test-error-stream)
 9375     (clear-stream $_test-error-buffered-file->buffer)
 9376     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9377     68/push 0/imm32
 9378     68/push 0/imm32
 9379     89/<- %edx 4/r32/esp
 9380     (tailor-exit-descriptor %edx 0x10)
 9381     #
 9382     (write _test-input-stream "fn foo {\n")
 9383     (write _test-input-stream "  var x: boolean\n")
 9384     (write _test-input-stream "  compare x, 0, 0\n")
 9385     (write _test-input-stream "}\n")
 9386     # convert
 9387     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9388     # registers except esp clobbered at this point
 9389     # restore ed
 9390     89/<- %edx 4/r32/esp
 9391     (flush _test-output-buffered-file)
 9392     (flush _test-error-buffered-file)
 9393 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9399     # check output
 9400     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-too-many-inouts: output should be empty")
 9401     (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")
 9402     # check that stop(1) was called
 9403     (check-ints-equal *(edx+4) 2 "F - test-compare-with-too-many-inouts: exit status")
 9404     # don't restore from ebp
 9405     81 0/subop/add %esp 8/imm32
 9406     # . epilogue
 9407     5d/pop-to-ebp
 9408     c3/return
 9409 
 9410 test-compare-with-output:
 9411     # . prologue
 9412     55/push-ebp
 9413     89/<- %ebp 4/r32/esp
 9414     # setup
 9415     (clear-stream _test-input-stream)
 9416     (clear-stream $_test-input-buffered-file->buffer)
 9417     (clear-stream _test-output-stream)
 9418     (clear-stream $_test-output-buffered-file->buffer)
 9419     (clear-stream _test-error-stream)
 9420     (clear-stream $_test-error-buffered-file->buffer)
 9421     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9422     68/push 0/imm32
 9423     68/push 0/imm32
 9424     89/<- %edx 4/r32/esp
 9425     (tailor-exit-descriptor %edx 0x10)
 9426     #
 9427     (write _test-input-stream "fn foo {\n")
 9428     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 9429     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
 9430     (write _test-input-stream "  x <- compare y, 0\n")
 9431     (write _test-input-stream "}\n")
 9432     # convert
 9433     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9434     # registers except esp clobbered at this point
 9435     # restore ed
 9436     89/<- %edx 4/r32/esp
 9437     (flush _test-output-buffered-file)
 9438     (flush _test-error-buffered-file)
 9439 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9445     # check output
 9446     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-output: output should be empty")
 9447     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must not have any outputs"  "F - test-compare-with-output: error message")
 9448     # check that stop(1) was called
 9449     (check-ints-equal *(edx+4) 2 "F - test-compare-with-output: exit status")
 9450     # don't restore from ebp
 9451     81 0/subop/add %esp 8/imm32
 9452     # . epilogue
 9453     5d/pop-to-ebp
 9454     c3/return
 9455 
 9456 test-compare-invalid-value-to-address:
 9457     # . prologue
 9458     55/push-ebp
 9459     89/<- %ebp 4/r32/esp
 9460     # setup
 9461     (clear-stream _test-input-stream)
 9462     (clear-stream $_test-input-buffered-file->buffer)
 9463     (clear-stream _test-output-stream)
 9464     (clear-stream $_test-output-buffered-file->buffer)
 9465     (clear-stream _test-error-stream)
 9466     (clear-stream $_test-error-buffered-file->buffer)
 9467     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9468     68/push 0/imm32
 9469     68/push 0/imm32
 9470     89/<- %edx 4/r32/esp
 9471     (tailor-exit-descriptor %edx 0x10)
 9472     #
 9473     (write _test-input-stream "fn foo {\n")
 9474     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 9475     (write _test-input-stream "  var y: (addr int)\n")
 9476     (write _test-input-stream "  compare y, x\n")
 9477     (write _test-input-stream "}\n")
 9478     # convert
 9479     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9480     # registers except esp clobbered at this point
 9481     # restore ed
 9482     89/<- %edx 4/r32/esp
 9483     (flush _test-output-buffered-file)
 9484     (flush _test-error-buffered-file)
 9485 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9491     # check output
 9492     (check-stream-equal _test-output-stream  ""  "F - test-compare-invalid-value-to-address: output should be empty")
 9493     (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")
 9494     # check that stop(1) was called
 9495     (check-ints-equal *(edx+4) 2 "F - test-compare-invalid-value-to-address: exit status")
 9496     # don't restore from ebp
 9497     81 0/subop/add %esp 8/imm32
 9498     # . epilogue
 9499     5d/pop-to-ebp
 9500     c3/return
 9501 
 9502 test-compare-address:
 9503     # . prologue
 9504     55/push-ebp
 9505     89/<- %ebp 4/r32/esp
 9506     # setup
 9507     (clear-stream _test-input-stream)
 9508     (clear-stream $_test-input-buffered-file->buffer)
 9509     (clear-stream _test-output-stream)
 9510     (clear-stream $_test-output-buffered-file->buffer)
 9511     #
 9512     (write _test-input-stream "fn foo {\n")
 9513     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
 9514     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
 9515     (write _test-input-stream "  compare y, x\n")
 9516     (write _test-input-stream "}\n")
 9517     # convert
 9518     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9519     (flush _test-output-buffered-file)
 9520     # no errors
 9521     # . epilogue
 9522     5d/pop-to-ebp
 9523     c3/return
 9524 
 9525 test-compare-deref-address:
 9526     # . prologue
 9527     55/push-ebp
 9528     89/<- %ebp 4/r32/esp
 9529     # setup
 9530     (clear-stream _test-input-stream)
 9531     (clear-stream $_test-input-buffered-file->buffer)
 9532     (clear-stream _test-output-stream)
 9533     (clear-stream $_test-output-buffered-file->buffer)
 9534     #
 9535     (write _test-input-stream "fn foo {\n")
 9536     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
 9537     (write _test-input-stream "  var y/ecx: (addr addr int) <- copy 0\n")
 9538     (write _test-input-stream "  compare *y, x\n")
 9539     (write _test-input-stream "}\n")
 9540     # convert
 9541     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9542     (flush _test-output-buffered-file)
 9543     # no errors
 9544     # . epilogue
 9545     5d/pop-to-ebp
 9546     c3/return
 9547 
 9548 test-compare-two-vars-in-memory:
 9549     # . prologue
 9550     55/push-ebp
 9551     89/<- %ebp 4/r32/esp
 9552     # setup
 9553     (clear-stream _test-input-stream)
 9554     (clear-stream $_test-input-buffered-file->buffer)
 9555     (clear-stream _test-output-stream)
 9556     (clear-stream $_test-output-buffered-file->buffer)
 9557     (clear-stream _test-error-stream)
 9558     (clear-stream $_test-error-buffered-file->buffer)
 9559     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9560     68/push 0/imm32
 9561     68/push 0/imm32
 9562     89/<- %edx 4/r32/esp
 9563     (tailor-exit-descriptor %edx 0x10)
 9564     #
 9565     (write _test-input-stream "fn foo {\n")
 9566     (write _test-input-stream "  var x: boolean\n")
 9567     (write _test-input-stream "  compare x, x\n")
 9568     (write _test-input-stream "}\n")
 9569     # convert
 9570     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9571     # registers except esp clobbered at this point
 9572     # restore ed
 9573     89/<- %edx 4/r32/esp
 9574     (flush _test-output-buffered-file)
 9575     (flush _test-error-buffered-file)
 9576 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9582     # check output
 9583     (check-stream-equal _test-output-stream  ""  "F - test-compare-two-vars-in-memory: output should be empty")
 9584     (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")
 9585     # check that stop(1) was called
 9586     (check-ints-equal *(edx+4) 2 "F - test-compare-two-vars-in-memory: exit status")
 9587     # don't restore from ebp
 9588     81 0/subop/add %esp 8/imm32
 9589     # . epilogue
 9590     5d/pop-to-ebp
 9591     c3/return
 9592 
 9593 test-compare-non-scalar:
 9594     # . prologue
 9595     55/push-ebp
 9596     89/<- %ebp 4/r32/esp
 9597     # setup
 9598     (clear-stream _test-input-stream)
 9599     (clear-stream $_test-input-buffered-file->buffer)
 9600     (clear-stream _test-output-stream)
 9601     (clear-stream $_test-output-buffered-file->buffer)
 9602     (clear-stream _test-error-stream)
 9603     (clear-stream $_test-error-buffered-file->buffer)
 9604     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9605     68/push 0/imm32
 9606     68/push 0/imm32
 9607     89/<- %edx 4/r32/esp
 9608     (tailor-exit-descriptor %edx 0x10)
 9609     #
 9610     (write _test-input-stream "fn foo {\n")
 9611     (write _test-input-stream "  var x: (handle int)\n")
 9612     (write _test-input-stream "  var y: int\n")
 9613     (write _test-input-stream "  compare y, x\n")
 9614     (write _test-input-stream "}\n")
 9615     # convert
 9616     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9617     # registers except esp clobbered at this point
 9618     # restore ed
 9619     89/<- %edx 4/r32/esp
 9620     (flush _test-output-buffered-file)
 9621     (flush _test-error-buffered-file)
 9622 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9628     # check output
 9629     (check-stream-equal _test-output-stream  ""  "F - test-compare-non-scalar: output should be empty")
 9630 #?     (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")
 9631     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compare: both inouts are in memory"  "F - test-compare-non-scalar: error message")
 9632     # check that stop(1) was called
 9633     (check-ints-equal *(edx+4) 2 "F - test-compare-non-scalar: exit status")
 9634     # don't restore from ebp
 9635     81 0/subop/add %esp 8/imm32
 9636     # . epilogue
 9637     5d/pop-to-ebp
 9638     c3/return
 9639 
 9640 test-compare-with-string-literal:
 9641     # . prologue
 9642     55/push-ebp
 9643     89/<- %ebp 4/r32/esp
 9644     # setup
 9645     (clear-stream _test-input-stream)
 9646     (clear-stream $_test-input-buffered-file->buffer)
 9647     (clear-stream _test-output-stream)
 9648     (clear-stream $_test-output-buffered-file->buffer)
 9649     (clear-stream _test-error-stream)
 9650     (clear-stream $_test-error-buffered-file->buffer)
 9651     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9652     68/push 0/imm32
 9653     68/push 0/imm32
 9654     89/<- %edx 4/r32/esp
 9655     (tailor-exit-descriptor %edx 0x10)
 9656     #
 9657     (write _test-input-stream "fn foo {\n")
 9658     (write _test-input-stream "  var x/eax: (addr array byte) <- copy 0\n")
 9659     (write _test-input-stream "  compare x, \"abc\"\n")
 9660     (write _test-input-stream "}\n")
 9661     # convert
 9662     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9663     # registers except esp clobbered at this point
 9664     # restore ed
 9665     89/<- %edx 4/r32/esp
 9666     (flush _test-output-buffered-file)
 9667     (flush _test-error-buffered-file)
 9668 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9674     # check output
 9675     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-string-literal: output should be empty")
 9676     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compare: string literal \"abc\" is not supported; use the string-equal? function"  "F - test-compare-with-string-literal: error message")
 9677     # check that stop(1) was called
 9678     (check-ints-equal *(edx+4) 2 "F - test-compare-with-string-literal: exit status")
 9679     # don't restore from ebp
 9680     81 0/subop/add %esp 8/imm32
 9681     # . epilogue
 9682     5d/pop-to-ebp
 9683     c3/return
 9684 
 9685 test-address-with-no-inout:
 9686     # . prologue
 9687     55/push-ebp
 9688     89/<- %ebp 4/r32/esp
 9689     # setup
 9690     (clear-stream _test-input-stream)
 9691     (clear-stream $_test-input-buffered-file->buffer)
 9692     (clear-stream _test-output-stream)
 9693     (clear-stream $_test-output-buffered-file->buffer)
 9694     (clear-stream _test-error-stream)
 9695     (clear-stream $_test-error-buffered-file->buffer)
 9696     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9697     68/push 0/imm32
 9698     68/push 0/imm32
 9699     89/<- %edx 4/r32/esp
 9700     (tailor-exit-descriptor %edx 0x10)
 9701     #
 9702     (write _test-input-stream "fn foo {\n")
 9703     (write _test-input-stream "  var x/eax: boolean <- address\n")
 9704     (write _test-input-stream "}\n")
 9705     # convert
 9706     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9707     # registers except esp clobbered at this point
 9708     # restore ed
 9709     89/<- %edx 4/r32/esp
 9710     (flush _test-output-buffered-file)
 9711     (flush _test-error-buffered-file)
 9712 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9718     # check output
 9719     (check-stream-equal _test-output-stream  ""  "F - test-address-with-no-inout: output should be empty")
 9720     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'address' expects an inout"  "F - test-address-with-no-inout: error message")
 9721     # check that stop(1) was called
 9722     (check-ints-equal *(edx+4) 2 "F - test-address-with-no-inout: exit status")
 9723     # don't restore from ebp
 9724     81 0/subop/add %esp 8/imm32
 9725     # . epilogue
 9726     5d/pop-to-ebp
 9727     c3/return
 9728 
 9729 test-address-with-multiple-inouts:
 9730     # . prologue
 9731     55/push-ebp
 9732     89/<- %ebp 4/r32/esp
 9733     # setup
 9734     (clear-stream _test-input-stream)
 9735     (clear-stream $_test-input-buffered-file->buffer)
 9736     (clear-stream _test-output-stream)
 9737     (clear-stream $_test-output-buffered-file->buffer)
 9738     (clear-stream _test-error-stream)
 9739     (clear-stream $_test-error-buffered-file->buffer)
 9740     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9741     68/push 0/imm32
 9742     68/push 0/imm32
 9743     89/<- %edx 4/r32/esp
 9744     (tailor-exit-descriptor %edx 0x10)
 9745     #
 9746     (write _test-input-stream "fn foo {\n")
 9747     (write _test-input-stream "  var x/eax: boolean <- address 0, 0\n")
 9748     (write _test-input-stream "}\n")
 9749     # convert
 9750     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9751     # registers except esp clobbered at this point
 9752     # restore ed
 9753     89/<- %edx 4/r32/esp
 9754     (flush _test-output-buffered-file)
 9755     (flush _test-error-buffered-file)
 9756 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9762     # check output
 9763     (check-stream-equal _test-output-stream  ""  "F - test-address-with-multiple-inouts: output should be empty")
 9764     (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")
 9765     # check that stop(1) was called
 9766     (check-ints-equal *(edx+4) 2 "F - test-address-with-multiple-inouts: exit status")
 9767     # don't restore from ebp
 9768     81 0/subop/add %esp 8/imm32
 9769     # . epilogue
 9770     5d/pop-to-ebp
 9771     c3/return
 9772 
 9773 test-address-with-no-output:
 9774     # . prologue
 9775     55/push-ebp
 9776     89/<- %ebp 4/r32/esp
 9777     # setup
 9778     (clear-stream _test-input-stream)
 9779     (clear-stream $_test-input-buffered-file->buffer)
 9780     (clear-stream _test-output-stream)
 9781     (clear-stream $_test-output-buffered-file->buffer)
 9782     (clear-stream _test-error-stream)
 9783     (clear-stream $_test-error-buffered-file->buffer)
 9784     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9785     68/push 0/imm32
 9786     68/push 0/imm32
 9787     89/<- %edx 4/r32/esp
 9788     (tailor-exit-descriptor %edx 0x10)
 9789     #
 9790     (write _test-input-stream "fn foo {\n")
 9791     (write _test-input-stream "  address 0\n")
 9792     (write _test-input-stream "}\n")
 9793     # convert
 9794     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9795     # registers except esp clobbered at this point
 9796     # restore ed
 9797     89/<- %edx 4/r32/esp
 9798     (flush _test-output-buffered-file)
 9799     (flush _test-error-buffered-file)
 9800 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9806     # check output
 9807     (check-stream-equal _test-output-stream  ""  "F - test-address-with-no-output: output should be empty")
 9808     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'address' expects an output"  "F - test-address-with-no-output: error message")
 9809     # check that stop(1) was called
 9810     (check-ints-equal *(edx+4) 2 "F - test-address-with-no-output: exit status")
 9811     # don't restore from ebp
 9812     81 0/subop/add %esp 8/imm32
 9813     # . epilogue
 9814     5d/pop-to-ebp
 9815     c3/return
 9816 
 9817 test-address-with-multiple-outputs:
 9818     # . prologue
 9819     55/push-ebp
 9820     89/<- %ebp 4/r32/esp
 9821     # setup
 9822     (clear-stream _test-input-stream)
 9823     (clear-stream $_test-input-buffered-file->buffer)
 9824     (clear-stream _test-output-stream)
 9825     (clear-stream $_test-output-buffered-file->buffer)
 9826     (clear-stream _test-error-stream)
 9827     (clear-stream $_test-error-buffered-file->buffer)
 9828     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9829     68/push 0/imm32
 9830     68/push 0/imm32
 9831     89/<- %edx 4/r32/esp
 9832     (tailor-exit-descriptor %edx 0x10)
 9833     #
 9834     (write _test-input-stream "fn foo {\n")
 9835     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 9836     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
 9837     (write _test-input-stream "  x, y <- address 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-address-with-multiple-outputs: output should be empty")
 9854     (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")
 9855     # check that stop(1) was called
 9856     (check-ints-equal *(edx+4) 2 "F - test-address-with-multiple-outputs: 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 # silly but it works
 9864 test-address-of-deref:
 9865     # . prologue
 9866     55/push-ebp
 9867     89/<- %ebp 4/r32/esp
 9868     # setup
 9869     (clear-stream _test-input-stream)
 9870     (clear-stream $_test-input-buffered-file->buffer)
 9871     (clear-stream _test-output-stream)
 9872     (clear-stream $_test-output-buffered-file->buffer)
 9873     #
 9874     (write _test-input-stream "fn foo {\n")
 9875     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
 9876     (write _test-input-stream "  var y/ecx: (addr int) <- address *x\n")
 9877     (write _test-input-stream "}\n")
 9878     # convert
 9879     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9880     (flush _test-output-buffered-file)
 9881     # no errors
 9882     # . epilogue
 9883     5d/pop-to-ebp
 9884     c3/return
 9885 
 9886 test-address-to-non-register:
 9887     # . prologue
 9888     55/push-ebp
 9889     89/<- %ebp 4/r32/esp
 9890     # setup
 9891     (clear-stream _test-input-stream)
 9892     (clear-stream $_test-input-buffered-file->buffer)
 9893     (clear-stream _test-output-stream)
 9894     (clear-stream $_test-output-buffered-file->buffer)
 9895     (clear-stream _test-error-stream)
 9896     (clear-stream $_test-error-buffered-file->buffer)
 9897     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9898     68/push 0/imm32
 9899     68/push 0/imm32
 9900     89/<- %edx 4/r32/esp
 9901     (tailor-exit-descriptor %edx 0x10)
 9902     #
 9903     (write _test-input-stream "fn foo {\n")
 9904     (write _test-input-stream "  var x: (addr int)\n")
 9905     (write _test-input-stream "  x <- address 0\n")
 9906     (write _test-input-stream "}\n")
 9907     # convert
 9908     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9909     # registers except esp clobbered at this point
 9910     # restore ed
 9911     89/<- %edx 4/r32/esp
 9912     (flush _test-output-buffered-file)
 9913     (flush _test-error-buffered-file)
 9914 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9920     # check output
 9921     (check-stream-equal _test-output-stream  ""  "F - test-address-to-non-register: output should be empty")
 9922     (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")
 9923     # check that stop(1) was called
 9924     (check-ints-equal *(edx+4) 2 "F - test-address-to-non-register: exit status")
 9925     # don't restore from ebp
 9926     81 0/subop/add %esp 8/imm32
 9927     # . epilogue
 9928     5d/pop-to-ebp
 9929     c3/return
 9930 
 9931 test-address-with-wrong-type:
 9932     # . prologue
 9933     55/push-ebp
 9934     89/<- %ebp 4/r32/esp
 9935     # setup
 9936     (clear-stream _test-input-stream)
 9937     (clear-stream $_test-input-buffered-file->buffer)
 9938     (clear-stream _test-output-stream)
 9939     (clear-stream $_test-output-buffered-file->buffer)
 9940     (clear-stream _test-error-stream)
 9941     (clear-stream $_test-error-buffered-file->buffer)
 9942     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9943     68/push 0/imm32
 9944     68/push 0/imm32
 9945     89/<- %edx 4/r32/esp
 9946     (tailor-exit-descriptor %edx 0x10)
 9947     #
 9948     (write _test-input-stream "fn foo {\n")
 9949     (write _test-input-stream "  var x: int\n")
 9950     (write _test-input-stream "  var y/eax: (addr boolean) <- address x\n")
 9951     (write _test-input-stream "}\n")
 9952     # convert
 9953     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9954     # registers except esp clobbered at this point
 9955     # restore ed
 9956     89/<- %edx 4/r32/esp
 9957     (flush _test-output-buffered-file)
 9958     (flush _test-error-buffered-file)
 9959 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9965     # check output
 9966     (check-stream-equal _test-output-stream  ""  "F - test-address-with-wrong-type: output should be empty")
 9967     (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")
 9968     # check that stop(1) was called
 9969     (check-ints-equal *(edx+4) 2 "F - test-address-with-wrong-type: exit status")
 9970     # don't restore from ebp
 9971     81 0/subop/add %esp 8/imm32
 9972     # . epilogue
 9973     5d/pop-to-ebp
 9974     c3/return
 9975 
 9976 test-address-with-right-type-for-array:
 9977     # . prologue
 9978     55/push-ebp
 9979     89/<- %ebp 4/r32/esp
 9980     # setup
 9981     (clear-stream _test-input-stream)
 9982     (clear-stream $_test-input-buffered-file->buffer)
 9983     (clear-stream _test-output-stream)
 9984     (clear-stream $_test-output-buffered-file->buffer)
 9985     #
 9986     (write _test-input-stream "fn foo {\n")
 9987     (write _test-input-stream "  var x: (array int 3)\n")
 9988     (write _test-input-stream "  var y/eax: (addr array int) <- address x\n")
 9989     (write _test-input-stream "}\n")
 9990     # convert
 9991     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9992     (flush _test-output-buffered-file)
 9993     # no errors
 9994     # . epilogue
 9995     89/<- %esp 5/r32/ebp
 9996     5d/pop-to-ebp
 9997     c3/return
 9998 
 9999 test-address-with-right-type-for-stream:
10000     # . prologue
10001     55/push-ebp
10002     89/<- %ebp 4/r32/esp
10003     # setup
10004     (clear-stream _test-input-stream)
10005     (clear-stream $_test-input-buffered-file->buffer)
10006     (clear-stream _test-output-stream)
10007     (clear-stream $_test-output-buffered-file->buffer)
10008     #
10009     (write _test-input-stream "fn foo {\n")
10010     (write _test-input-stream "  var x: (stream int 3)\n")
10011     (write _test-input-stream "  var y/eax: (addr stream int) <- address x\n")
10012     (write _test-input-stream "}\n")
10013     # convert
10014     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10015     (flush _test-output-buffered-file)
10016     # no errors
10017     # . epilogue
10018     89/<- %esp 5/r32/ebp
10019     5d/pop-to-ebp
10020     c3/return
10021 
10022 test-get-with-wrong-field:
10023     # . prologue
10024     55/push-ebp
10025     89/<- %ebp 4/r32/esp
10026     # setup
10027     (clear-stream _test-input-stream)
10028     (clear-stream $_test-input-buffered-file->buffer)
10029     (clear-stream _test-output-stream)
10030     (clear-stream $_test-output-buffered-file->buffer)
10031     (clear-stream _test-error-stream)
10032     (clear-stream $_test-error-buffered-file->buffer)
10033     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10034     68/push 0/imm32
10035     68/push 0/imm32
10036     89/<- %edx 4/r32/esp
10037     (tailor-exit-descriptor %edx 0x10)
10038     #
10039     (write _test-input-stream "fn foo {\n")
10040     (write _test-input-stream "  var a: t\n")
10041     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
10042     (write _test-input-stream "}\n")
10043     (write _test-input-stream "type t {\n")
10044     (write _test-input-stream "  x: int\n")
10045     (write _test-input-stream "}\n")
10046     # convert
10047     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10048     # registers except esp clobbered at this point
10049     # restore ed
10050     89/<- %edx 4/r32/esp
10051     (flush _test-output-buffered-file)
10052     (flush _test-error-buffered-file)
10053 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10059     # check output
10060     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-field: output should be empty")
10061     (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")
10062     # check that stop(1) was called
10063     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-field: exit status")
10064     # don't restore from ebp
10065     81 0/subop/add %esp 8/imm32
10066     # . epilogue
10067     5d/pop-to-ebp
10068     c3/return
10069 
10070 test-get-with-wrong-base-type:
10071     # . prologue
10072     55/push-ebp
10073     89/<- %ebp 4/r32/esp
10074     # setup
10075     (clear-stream _test-input-stream)
10076     (clear-stream $_test-input-buffered-file->buffer)
10077     (clear-stream _test-output-stream)
10078     (clear-stream $_test-output-buffered-file->buffer)
10079     (clear-stream _test-error-stream)
10080     (clear-stream $_test-error-buffered-file->buffer)
10081     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10082     68/push 0/imm32
10083     68/push 0/imm32
10084     89/<- %edx 4/r32/esp
10085     (tailor-exit-descriptor %edx 0x10)
10086     #
10087     (write _test-input-stream "fn foo {\n")
10088     (write _test-input-stream "  var a: int\n")
10089     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
10090     (write _test-input-stream "}\n")
10091     # convert
10092     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10093     # registers except esp clobbered at this point
10094     # restore ed
10095     89/<- %edx 4/r32/esp
10096     (flush _test-output-buffered-file)
10097     (flush _test-error-buffered-file)
10098 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10104     # check output
10105     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type: output should be empty")
10106     (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")
10107     # check that stop(1) was called
10108     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type: exit status")
10109     # don't restore from ebp
10110     81 0/subop/add %esp 8/imm32
10111     # . epilogue
10112     5d/pop-to-ebp
10113     c3/return
10114 
10115 test-get-with-wrong-base-type-2:
10116     # . prologue
10117     55/push-ebp
10118     89/<- %ebp 4/r32/esp
10119     # setup
10120     (clear-stream _test-input-stream)
10121     (clear-stream $_test-input-buffered-file->buffer)
10122     (clear-stream _test-output-stream)
10123     (clear-stream $_test-output-buffered-file->buffer)
10124     (clear-stream _test-error-stream)
10125     (clear-stream $_test-error-buffered-file->buffer)
10126     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10127     68/push 0/imm32
10128     68/push 0/imm32
10129     89/<- %edx 4/r32/esp
10130     (tailor-exit-descriptor %edx 0x10)
10131     #
10132     (write _test-input-stream "fn foo {\n")
10133     (write _test-input-stream "  var a: (addr t)\n")
10134     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
10135     (write _test-input-stream "}\n")
10136     (write _test-input-stream "type t {\n")
10137     (write _test-input-stream "  x: int\n")
10138     (write _test-input-stream "}\n")
10139     # convert
10140     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10141     # registers except esp clobbered at this point
10142     # restore ed
10143     89/<- %edx 4/r32/esp
10144     (flush _test-output-buffered-file)
10145     (flush _test-error-buffered-file)
10146 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10152     # check output
10153     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type-2: output should be empty")
10154     (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")
10155     # check that stop(1) was called
10156     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type-2: exit status")
10157     # don't restore from ebp
10158     81 0/subop/add %esp 8/imm32
10159     # . epilogue
10160     5d/pop-to-ebp
10161     c3/return
10162 
10163 test-get-with-wrong-base-type-3:
10164     # . prologue
10165     55/push-ebp
10166     89/<- %ebp 4/r32/esp
10167     # setup
10168     (clear-stream _test-input-stream)
10169     (clear-stream $_test-input-buffered-file->buffer)
10170     (clear-stream _test-output-stream)
10171     (clear-stream $_test-output-buffered-file->buffer)
10172     (clear-stream _test-error-stream)
10173     (clear-stream $_test-error-buffered-file->buffer)
10174     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10175     68/push 0/imm32
10176     68/push 0/imm32
10177     89/<- %edx 4/r32/esp
10178     (tailor-exit-descriptor %edx 0x10)
10179     #
10180     (write _test-input-stream "fn foo {\n")
10181     (write _test-input-stream "  var a: (handle int)\n")
10182     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
10183     (write _test-input-stream "}\n")
10184     # convert
10185     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10186     # registers except esp clobbered at this point
10187     # restore ed
10188     89/<- %edx 4/r32/esp
10189     (flush _test-output-buffered-file)
10190     (flush _test-error-buffered-file)
10191 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10197     # check output
10198     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type-3: output should be empty")
10199     (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")
10200     # check that stop(1) was called
10201     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type-3: exit status")
10202     # don't restore from ebp
10203     81 0/subop/add %esp 8/imm32
10204     # . epilogue
10205     5d/pop-to-ebp
10206     c3/return
10207 
10208 test-get-with-wrong-offset-type:
10209     # . prologue
10210     55/push-ebp
10211     89/<- %ebp 4/r32/esp
10212     # setup
10213     (clear-stream _test-input-stream)
10214     (clear-stream $_test-input-buffered-file->buffer)
10215     (clear-stream _test-output-stream)
10216     (clear-stream $_test-output-buffered-file->buffer)
10217     (clear-stream _test-error-stream)
10218     (clear-stream $_test-error-buffered-file->buffer)
10219     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10220     68/push 0/imm32
10221     68/push 0/imm32
10222     89/<- %edx 4/r32/esp
10223     (tailor-exit-descriptor %edx 0x10)
10224     #
10225     (write _test-input-stream "fn foo {\n")
10226     (write _test-input-stream "  var a: t\n")
10227     (write _test-input-stream "  var b: int\n")
10228     (write _test-input-stream "  var c/ecx: (addr int) <- get a, b\n")
10229     (write _test-input-stream "}\n")
10230     (write _test-input-stream "type t {\n")
10231     (write _test-input-stream "  x: int\n")
10232     (write _test-input-stream "}\n")
10233     # convert
10234     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10235     # registers except esp clobbered at this point
10236     # restore ed
10237     89/<- %edx 4/r32/esp
10238     (flush _test-output-buffered-file)
10239     (flush _test-error-buffered-file)
10240 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10246     # check output
10247     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-offset-type: output should be empty")
10248     (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")
10249     # check that stop(1) was called
10250     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-offset-type: exit status")
10251     # don't restore from ebp
10252     81 0/subop/add %esp 8/imm32
10253     # . epilogue
10254     5d/pop-to-ebp
10255     c3/return
10256 
10257 test-get-with-wrong-output-type:
10258     # . prologue
10259     55/push-ebp
10260     89/<- %ebp 4/r32/esp
10261     # setup
10262     (clear-stream _test-input-stream)
10263     (clear-stream $_test-input-buffered-file->buffer)
10264     (clear-stream _test-output-stream)
10265     (clear-stream $_test-output-buffered-file->buffer)
10266     (clear-stream _test-error-stream)
10267     (clear-stream $_test-error-buffered-file->buffer)
10268     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10269     68/push 0/imm32
10270     68/push 0/imm32
10271     89/<- %edx 4/r32/esp
10272     (tailor-exit-descriptor %edx 0x10)
10273     #
10274     (write _test-input-stream "fn foo {\n")
10275     (write _test-input-stream "  var a: t\n")
10276     (write _test-input-stream "  var c: (addr int)\n")
10277     (write _test-input-stream "  c <- get a, x\n")
10278     (write _test-input-stream "}\n")
10279     (write _test-input-stream "type t {\n")
10280     (write _test-input-stream "  x: int\n")
10281     (write _test-input-stream "}\n")
10282     # convert
10283     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10284     # registers except esp clobbered at this point
10285     # restore ed
10286     89/<- %edx 4/r32/esp
10287     (flush _test-output-buffered-file)
10288     (flush _test-error-buffered-file)
10289 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10295     # check output
10296     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type: output should be empty")
10297     (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")
10298     # check that stop(1) was called
10299     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type: exit status")
10300     # don't restore from ebp
10301     81 0/subop/add %esp 8/imm32
10302     # . epilogue
10303     5d/pop-to-ebp
10304     c3/return
10305 
10306 test-get-with-wrong-output-type-2:
10307     # . prologue
10308     55/push-ebp
10309     89/<- %ebp 4/r32/esp
10310     # setup
10311     (clear-stream _test-input-stream)
10312     (clear-stream $_test-input-buffered-file->buffer)
10313     (clear-stream _test-output-stream)
10314     (clear-stream $_test-output-buffered-file->buffer)
10315     (clear-stream _test-error-stream)
10316     (clear-stream $_test-error-buffered-file->buffer)
10317     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10318     68/push 0/imm32
10319     68/push 0/imm32
10320     89/<- %edx 4/r32/esp
10321     (tailor-exit-descriptor %edx 0x10)
10322     #
10323     (write _test-input-stream "fn foo {\n")
10324     (write _test-input-stream "  var a: t\n")
10325     (write _test-input-stream "  var c/ecx: int <- get a, x\n")
10326     (write _test-input-stream "}\n")
10327     (write _test-input-stream "type t {\n")
10328     (write _test-input-stream "  x: int\n")
10329     (write _test-input-stream "}\n")
10330     # convert
10331     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10332     # registers except esp clobbered at this point
10333     # restore ed
10334     89/<- %edx 4/r32/esp
10335     (flush _test-output-buffered-file)
10336     (flush _test-error-buffered-file)
10337 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10343     # check output
10344     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-2: output should be empty")
10345     (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")
10346     # check that stop(1) was called
10347     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-2: exit status")
10348     # don't restore from ebp
10349     81 0/subop/add %esp 8/imm32
10350     # . epilogue
10351     5d/pop-to-ebp
10352     c3/return
10353 
10354 test-get-with-wrong-output-type-3:
10355     # . prologue
10356     55/push-ebp
10357     89/<- %ebp 4/r32/esp
10358     # setup
10359     (clear-stream _test-input-stream)
10360     (clear-stream $_test-input-buffered-file->buffer)
10361     (clear-stream _test-output-stream)
10362     (clear-stream $_test-output-buffered-file->buffer)
10363     (clear-stream _test-error-stream)
10364     (clear-stream $_test-error-buffered-file->buffer)
10365     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10366     68/push 0/imm32
10367     68/push 0/imm32
10368     89/<- %edx 4/r32/esp
10369     (tailor-exit-descriptor %edx 0x10)
10370     #
10371     (write _test-input-stream "fn foo {\n")
10372     (write _test-input-stream "  var a: t\n")
10373     (write _test-input-stream "  var c/ecx: (array int) <- get a, x\n")
10374     (write _test-input-stream "}\n")
10375     (write _test-input-stream "type t {\n")
10376     (write _test-input-stream "  x: int\n")
10377     (write _test-input-stream "}\n")
10378     # convert
10379     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10380     # registers except esp clobbered at this point
10381     # restore ed
10382     89/<- %edx 4/r32/esp
10383     (flush _test-output-buffered-file)
10384     (flush _test-error-buffered-file)
10385 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10391     # check output
10392     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-3: output should be empty")
10393     (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")
10394     # check that stop(1) was called
10395     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-3: exit status")
10396     # don't restore from ebp
10397     81 0/subop/add %esp 8/imm32
10398     # . epilogue
10399     5d/pop-to-ebp
10400     c3/return
10401 
10402 test-get-with-wrong-output-type-4:
10403     # . prologue
10404     55/push-ebp
10405     89/<- %ebp 4/r32/esp
10406     # setup
10407     (clear-stream _test-input-stream)
10408     (clear-stream $_test-input-buffered-file->buffer)
10409     (clear-stream _test-output-stream)
10410     (clear-stream $_test-output-buffered-file->buffer)
10411     (clear-stream _test-error-stream)
10412     (clear-stream $_test-error-buffered-file->buffer)
10413     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10414     68/push 0/imm32
10415     68/push 0/imm32
10416     89/<- %edx 4/r32/esp
10417     (tailor-exit-descriptor %edx 0x10)
10418     #
10419     (write _test-input-stream "fn foo {\n")
10420     (write _test-input-stream "  var a: t\n")
10421     (write _test-input-stream "  var c/ecx: (addr boolean) <- get a, x\n")
10422     (write _test-input-stream "}\n")
10423     (write _test-input-stream "type t {\n")
10424     (write _test-input-stream "  x: int\n")
10425     (write _test-input-stream "}\n")
10426     # convert
10427     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10428     # registers except esp clobbered at this point
10429     # restore ed
10430     89/<- %edx 4/r32/esp
10431     (flush _test-output-buffered-file)
10432     (flush _test-error-buffered-file)
10433 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10439     # check output
10440     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-4: output should be empty")
10441     (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")
10442     # check that stop(1) was called
10443     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-4: exit status")
10444     # don't restore from ebp
10445     81 0/subop/add %esp 8/imm32
10446     # . epilogue
10447     5d/pop-to-ebp
10448     c3/return
10449 
10450 test-get-with-wrong-output-type-5:
10451     # . prologue
10452     55/push-ebp
10453     89/<- %ebp 4/r32/esp
10454     # setup
10455     (clear-stream _test-input-stream)
10456     (clear-stream $_test-input-buffered-file->buffer)
10457     (clear-stream _test-output-stream)
10458     (clear-stream $_test-output-buffered-file->buffer)
10459     #
10460     (write _test-input-stream "fn foo {\n")
10461     (write _test-input-stream "  var a: t\n")
10462     (write _test-input-stream "  var c/ecx: (addr handle int) <- get a, x\n")
10463     (write _test-input-stream "}\n")
10464     (write _test-input-stream "type t {\n")
10465     (write _test-input-stream "  x: (handle int)\n")
10466     (write _test-input-stream "}\n")
10467     # convert
10468     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10469     (flush _test-output-buffered-file)
10470     # no errors
10471     # . epilogue
10472     89/<- %esp 5/r32/ebp
10473     5d/pop-to-ebp
10474     c3/return
10475 
10476 test-get-with-too-few-inouts:
10477     # . prologue
10478     55/push-ebp
10479     89/<- %ebp 4/r32/esp
10480     # setup
10481     (clear-stream _test-input-stream)
10482     (clear-stream $_test-input-buffered-file->buffer)
10483     (clear-stream _test-output-stream)
10484     (clear-stream $_test-output-buffered-file->buffer)
10485     (clear-stream _test-error-stream)
10486     (clear-stream $_test-error-buffered-file->buffer)
10487     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10488     68/push 0/imm32
10489     68/push 0/imm32
10490     89/<- %edx 4/r32/esp
10491     (tailor-exit-descriptor %edx 0x10)
10492     #
10493     (write _test-input-stream "fn foo {\n")
10494     (write _test-input-stream "  var a: t\n")
10495     (write _test-input-stream "  var c/ecx: (addr int) <- get a\n")
10496     (write _test-input-stream "}\n")
10497     (write _test-input-stream "type t {\n")
10498     (write _test-input-stream "  x: int\n")
10499     (write _test-input-stream "}\n")
10500     # convert
10501     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10502     # registers except esp clobbered at this point
10503     # restore ed
10504     89/<- %edx 4/r32/esp
10505     (flush _test-output-buffered-file)
10506     (flush _test-error-buffered-file)
10507 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10513     # check output
10514     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-few-inouts: output should be empty")
10515     (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")
10516     # check that stop(1) was called
10517     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-few-inouts: exit status")
10518     # don't restore from ebp
10519     81 0/subop/add %esp 8/imm32
10520     # . epilogue
10521     5d/pop-to-ebp
10522     c3/return
10523 
10524 test-get-with-too-many-inouts:
10525     # . prologue
10526     55/push-ebp
10527     89/<- %ebp 4/r32/esp
10528     # setup
10529     (clear-stream _test-input-stream)
10530     (clear-stream $_test-input-buffered-file->buffer)
10531     (clear-stream _test-output-stream)
10532     (clear-stream $_test-output-buffered-file->buffer)
10533     (clear-stream _test-error-stream)
10534     (clear-stream $_test-error-buffered-file->buffer)
10535     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10536     68/push 0/imm32
10537     68/push 0/imm32
10538     89/<- %edx 4/r32/esp
10539     (tailor-exit-descriptor %edx 0x10)
10540     #
10541     (write _test-input-stream "fn foo {\n")
10542     (write _test-input-stream "  var a: t\n")
10543     (write _test-input-stream "  var c/ecx: (addr int) <- get a, x, 0\n")
10544     (write _test-input-stream "}\n")
10545     (write _test-input-stream "type t {\n")
10546     (write _test-input-stream "  x: int\n")
10547     (write _test-input-stream "}\n")
10548     # convert
10549     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10550     # registers except esp clobbered at this point
10551     # restore ed
10552     89/<- %edx 4/r32/esp
10553     (flush _test-output-buffered-file)
10554     (flush _test-error-buffered-file)
10555 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10561     # check output
10562     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-many-inouts: output should be empty")
10563     (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")
10564     # check that stop(1) was called
10565     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-many-inouts: exit status")
10566     # don't restore from ebp
10567     81 0/subop/add %esp 8/imm32
10568     # . epilogue
10569     5d/pop-to-ebp
10570     c3/return
10571 
10572 test-get-with-no-output:
10573     # . prologue
10574     55/push-ebp
10575     89/<- %ebp 4/r32/esp
10576     # setup
10577     (clear-stream _test-input-stream)
10578     (clear-stream $_test-input-buffered-file->buffer)
10579     (clear-stream _test-output-stream)
10580     (clear-stream $_test-output-buffered-file->buffer)
10581     (clear-stream _test-error-stream)
10582     (clear-stream $_test-error-buffered-file->buffer)
10583     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10584     68/push 0/imm32
10585     68/push 0/imm32
10586     89/<- %edx 4/r32/esp
10587     (tailor-exit-descriptor %edx 0x10)
10588     #
10589     (write _test-input-stream "fn foo {\n")
10590     (write _test-input-stream "  var a: t\n")
10591     (write _test-input-stream "  get a, x\n")
10592     (write _test-input-stream "}\n")
10593     (write _test-input-stream "type t {\n")
10594     (write _test-input-stream "  x: int\n")
10595     (write _test-input-stream "}\n")
10596     # convert
10597     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10598     # registers except esp clobbered at this point
10599     # restore ed
10600     89/<- %edx 4/r32/esp
10601     (flush _test-output-buffered-file)
10602     (flush _test-error-buffered-file)
10603 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10609     # check output
10610     (check-stream-equal _test-output-stream  ""  "F - test-get-with-no-output: output should be empty")
10611     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: must have an output"  "F - test-get-with-no-output: error message")
10612     # check that stop(1) was called
10613     (check-ints-equal *(edx+4) 2 "F - test-get-with-no-output: exit status")
10614     # don't restore from ebp
10615     81 0/subop/add %esp 8/imm32
10616     # . epilogue
10617     5d/pop-to-ebp
10618     c3/return
10619 
10620 test-get-with-too-many-outputs:
10621     # . prologue
10622     55/push-ebp
10623     89/<- %ebp 4/r32/esp
10624     # setup
10625     (clear-stream _test-input-stream)
10626     (clear-stream $_test-input-buffered-file->buffer)
10627     (clear-stream _test-output-stream)
10628     (clear-stream $_test-output-buffered-file->buffer)
10629     (clear-stream _test-error-stream)
10630     (clear-stream $_test-error-buffered-file->buffer)
10631     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10632     68/push 0/imm32
10633     68/push 0/imm32
10634     89/<- %edx 4/r32/esp
10635     (tailor-exit-descriptor %edx 0x10)
10636     #
10637     (write _test-input-stream "fn foo {\n")
10638     (write _test-input-stream "  var a: t\n")
10639     (write _test-input-stream "  var b: int\n")
10640     (write _test-input-stream "  var c/eax: (addr int) <- copy 0\n")
10641     (write _test-input-stream "  c, b <- get a, x\n")
10642     (write _test-input-stream "}\n")
10643     (write _test-input-stream "type t {\n")
10644     (write _test-input-stream "  x: int\n")
10645     (write _test-input-stream "}\n")
10646     # convert
10647     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10648     # registers except esp clobbered at this point
10649     # restore ed
10650     89/<- %edx 4/r32/esp
10651     (flush _test-output-buffered-file)
10652     (flush _test-error-buffered-file)
10653 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10659     # check output
10660     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-many-outputs: output should be empty")
10661     (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")
10662     # check that stop(1) was called
10663     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-many-outputs: exit status")
10664     # don't restore from ebp
10665     81 0/subop/add %esp 8/imm32
10666     # . epilogue
10667     5d/pop-to-ebp
10668     c3/return
10669 
10670 test-convert-array-of-user-defined-types:
10671     # . prologue
10672     55/push-ebp
10673     89/<- %ebp 4/r32/esp
10674     # setup
10675     (clear-stream _test-input-stream)
10676     (clear-stream $_test-input-buffered-file->buffer)
10677     (clear-stream _test-output-stream)
10678     (clear-stream $_test-output-buffered-file->buffer)
10679     #
10680     (write _test-input-stream "type t {\n")  # each t is 8 bytes, which is a power of 2
10681     (write _test-input-stream "  x: int\n")
10682     (write _test-input-stream "  y: int\n")
10683     (write _test-input-stream "}\n")
10684     (write _test-input-stream "fn foo {\n")
10685     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
10686     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
10687     (write _test-input-stream "  var x/eax: (addr t) <- index arr, idx\n")
10688     (write _test-input-stream "}\n")
10689     # convert
10690     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10691     (flush _test-output-buffered-file)
10692 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
10698     # check output
10699     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-array-of-user-defined-types/0")
10700     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-array-of-user-defined-types/1")
10701     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-array-of-user-defined-types/2")
10702     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-array-of-user-defined-types/3")
10703     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-array-of-user-defined-types/4")
10704     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-array-of-user-defined-types/5")
10705     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-array-of-user-defined-types/6")
10706     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-array-of-user-defined-types/7")
10707     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-array-of-user-defined-types/8")
10708     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-array-of-user-defined-types/9")
10709     (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")
10710     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-array-of-user-defined-types/12")
10711     (check-next-stream-line-equal _test-output-stream "    0f 84/jump-if-= __mu-abort-null-index-base-address/disp32"  "F - test-convert-array-of-user-defined-types/13")
10712     (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/14")
10713     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-array-of-user-defined-types/15")
10714     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-array-of-user-defined-types/16")
10715     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-array-of-user-defined-types/17")
10716     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-array-of-user-defined-types/18")
10717     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-array-of-user-defined-types/19")
10718     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-array-of-user-defined-types/20")
10719     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-array-of-user-defined-types/21")
10720     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-array-of-user-defined-types/22")
10721     # . epilogue
10722     89/<- %esp 5/r32/ebp
10723     5d/pop-to-ebp
10724     c3/return
10725 
10726 test-convert-length-of-array-of-user-defined-types-to-eax:
10727     # . prologue
10728     55/push-ebp
10729     89/<- %ebp 4/r32/esp
10730     # setup
10731     (clear-stream _test-input-stream)
10732     (clear-stream $_test-input-buffered-file->buffer)
10733     (clear-stream _test-output-stream)
10734     (clear-stream $_test-output-buffered-file->buffer)
10735     #
10736     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
10737     (write _test-input-stream "  x: int\n")
10738     (write _test-input-stream "  y: int\n")
10739     (write _test-input-stream "  z: int\n")
10740     (write _test-input-stream "}\n")
10741     (write _test-input-stream "fn foo {\n")
10742     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
10743     (write _test-input-stream "  var x/eax: int <- length arr\n")
10744     (write _test-input-stream "}\n")
10745     # convert
10746     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10747     (flush _test-output-buffered-file)
10748 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
10754     # check output
10755     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-eax/0")
10756     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-eax/1")
10757     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-eax/2")
10758     (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")
10759     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-eax/4")
10760     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-eax/5")
10761     # var arr
10762     (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")
10763     (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")
10764     # length instruction
10765     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types-to-eax/8")
10766     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types-to-eax/9")
10767     (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")
10768     (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")
10769     (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")
10770     (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")
10771     (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")
10772     (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")
10773     # reclaim arr
10774     (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")
10775     #
10776     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-eax/17")
10777     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/18")
10778     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-eax/19")
10779     (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")
10780     (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")
10781     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-eax/22")
10782     # . epilogue
10783     89/<- %esp 5/r32/ebp
10784     5d/pop-to-ebp
10785     c3/return
10786 
10787 test-convert-length-of-array-of-user-defined-types-to-ecx:
10788     # . prologue
10789     55/push-ebp
10790     89/<- %ebp 4/r32/esp
10791     # setup
10792     (clear-stream _test-input-stream)
10793     (clear-stream $_test-input-buffered-file->buffer)
10794     (clear-stream _test-output-stream)
10795     (clear-stream $_test-output-buffered-file->buffer)
10796     #
10797     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
10798     (write _test-input-stream "  x: int\n")
10799     (write _test-input-stream "  y: int\n")
10800     (write _test-input-stream "  z: int\n")
10801     (write _test-input-stream "}\n")
10802     (write _test-input-stream "fn foo {\n")
10803     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
10804     (write _test-input-stream "  var x/ecx: int <- length arr\n")
10805     (write _test-input-stream "}\n")
10806     # convert
10807     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10808     (flush _test-output-buffered-file)
10809 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
10815     # check output
10816     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-ecx/0")
10817     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-ecx/1")
10818     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-ecx/2")
10819     (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")
10820     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-ecx/4")
10821     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-ecx/5")
10822     # var a
10823     (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")
10824     (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")
10825     # var x
10826     (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")
10827     # length instruction
10828     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types-to-ecx/9")
10829     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types-to-ecx/10")
10830     (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")
10831     (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")
10832     (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")
10833     (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")
10834     (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")
10835     (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")
10836     (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")
10837     # reclaim x
10838     (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")
10839     # reclaim a
10840     (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")
10841     #
10842     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-ecx/20")
10843     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/21")
10844     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-ecx/22")
10845     (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")
10846     (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")
10847     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-ecx/25")
10848     # . epilogue
10849     89/<- %esp 5/r32/ebp
10850     5d/pop-to-ebp
10851     c3/return
10852 
10853 test-convert-length-of-array-of-user-defined-types-to-edx:
10854     # . prologue
10855     55/push-ebp
10856     89/<- %ebp 4/r32/esp
10857     # setup
10858     (clear-stream _test-input-stream)
10859     (clear-stream $_test-input-buffered-file->buffer)
10860     (clear-stream _test-output-stream)
10861     (clear-stream $_test-output-buffered-file->buffer)
10862     #
10863     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
10864     (write _test-input-stream "  x: int\n")
10865     (write _test-input-stream "  y: int\n")
10866     (write _test-input-stream "  z: int\n")
10867     (write _test-input-stream "}\n")
10868     (write _test-input-stream "fn foo {\n")
10869     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
10870     (write _test-input-stream "  var x/edx: int <- length arr\n")
10871     (write _test-input-stream "}\n")
10872     # convert
10873     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10874     (flush _test-output-buffered-file)
10875 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
10881     # check output
10882     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-edx/0")
10883     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-edx/1")
10884     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-edx/2")
10885     (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")
10886     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-edx/4")
10887     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-edx/5")
10888     # var a
10889     (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")
10890     (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")
10891     # var x
10892     (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")
10893     # length instruction
10894     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types-to-edx/9")
10895     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types-to-edx/10")
10896     (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")
10897     (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")
10898     (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")
10899     (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")
10900     (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")
10901     (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")
10902     (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")
10903     # reclaim x
10904     (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")
10905     # reclaim a
10906     (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")
10907     #
10908     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-edx/20")
10909     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/21")
10910     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-edx/22")
10911     (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")
10912     (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")
10913     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-edx/25")
10914     # . epilogue
10915     89/<- %esp 5/r32/ebp
10916     5d/pop-to-ebp
10917     c3/return
10918 
10919 test-convert-length-of-array-of-user-defined-types:
10920     # . prologue
10921     55/push-ebp
10922     89/<- %ebp 4/r32/esp
10923     # setup
10924     (clear-stream _test-input-stream)
10925     (clear-stream $_test-input-buffered-file->buffer)
10926     (clear-stream _test-output-stream)
10927     (clear-stream $_test-output-buffered-file->buffer)
10928     #
10929     (write _test-input-stream "type t {\n")  # each t is 8 bytes, which is a power of 2
10930     (write _test-input-stream "  x: int\n")
10931     (write _test-input-stream "  y: int\n")
10932     (write _test-input-stream "  z: int\n")
10933     (write _test-input-stream "}\n")
10934     (write _test-input-stream "fn foo {\n")
10935     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
10936     (write _test-input-stream "  var x/ebx: int <- length arr\n")
10937     (write _test-input-stream "}\n")
10938     # convert
10939     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10940     (flush _test-output-buffered-file)
10941 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
10947     # check output
10948     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types/0")
10949     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types/1")
10950     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types/2")
10951     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-user-defined-types/3")
10952     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types/4")
10953     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types/5")
10954     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-of-user-defined-types/6")
10955     (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")
10956     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-length-of-array-of-user-defined-types/8")
10957     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types/9")
10958     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types/10")
10959     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types/11")
10960     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array-of-user-defined-types/12")
10961     (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")
10962     (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")
10963     (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")
10964     (check-next-stream-line-equal _test-output-stream "    89/<- %ebx 0/r32/eax"  "F - test-convert-length-of-array-of-user-defined-types/16")
10965     (check-next-stream-line-equal _test-output-stream "    5a/pop-to-edx"       "F - test-convert-length-of-array-of-user-defined-types/17")
10966     (check-next-stream-line-equal _test-output-stream "    59/pop-to-ecx"       "F - test-convert-length-of-array-of-user-defined-types/18")
10967     (check-next-stream-line-equal _test-output-stream "    58/pop-to-eax"       "F - test-convert-length-of-array-of-user-defined-types/19")
10968     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ebx"  "F - test-convert-length-of-array-of-user-defined-types/20")
10969     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-of-user-defined-types/21")
10970     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types/22")
10971     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types/23")
10972     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types/24")
10973     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-of-user-defined-types/25")
10974     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-of-user-defined-types/26")
10975     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types/27")
10976     # . epilogue
10977     89/<- %esp 5/r32/ebp
10978     5d/pop-to-ebp
10979     c3/return
10980 
10981 test-index-with-non-array-atom-base-type:
10982     # . prologue
10983     55/push-ebp
10984     89/<- %ebp 4/r32/esp
10985     # setup
10986     (clear-stream _test-input-stream)
10987     (clear-stream $_test-input-buffered-file->buffer)
10988     (clear-stream _test-output-stream)
10989     (clear-stream $_test-output-buffered-file->buffer)
10990     (clear-stream _test-error-stream)
10991     (clear-stream $_test-error-buffered-file->buffer)
10992     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10993     68/push 0/imm32
10994     68/push 0/imm32
10995     89/<- %edx 4/r32/esp
10996     (tailor-exit-descriptor %edx 0x10)
10997     #
10998     (write _test-input-stream "fn foo {\n")
10999     (write _test-input-stream "  var a: int\n")
11000     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
11001     (write _test-input-stream "}\n")
11002     # convert
11003     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11004     # registers except esp clobbered at this point
11005     # restore ed
11006     89/<- %edx 4/r32/esp
11007     (flush _test-output-buffered-file)
11008     (flush _test-error-buffered-file)
11009 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11015     # check output
11016     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-atom-base-type: output should be empty")
11017     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: var 'a' is not an array"  "F - test-index-with-non-array-atom-base-type: error message")
11018     # check that stop(1) was called
11019     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-atom-base-type: exit status")
11020     # don't restore from ebp
11021     81 0/subop/add %esp 8/imm32
11022     # . epilogue
11023     5d/pop-to-ebp
11024     c3/return
11025 
11026 test-index-with-non-array-compound-base-type:
11027     # . prologue
11028     55/push-ebp
11029     89/<- %ebp 4/r32/esp
11030     # setup
11031     (clear-stream _test-input-stream)
11032     (clear-stream $_test-input-buffered-file->buffer)
11033     (clear-stream _test-output-stream)
11034     (clear-stream $_test-output-buffered-file->buffer)
11035     (clear-stream _test-error-stream)
11036     (clear-stream $_test-error-buffered-file->buffer)
11037     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11038     68/push 0/imm32
11039     68/push 0/imm32
11040     89/<- %edx 4/r32/esp
11041     (tailor-exit-descriptor %edx 0x10)
11042     #
11043     (write _test-input-stream "fn foo {\n")
11044     (write _test-input-stream "  var a: (handle int)\n")
11045     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
11046     (write _test-input-stream "}\n")
11047     # convert
11048     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11049     # registers except esp clobbered at this point
11050     # restore ed
11051     89/<- %edx 4/r32/esp
11052     (flush _test-output-buffered-file)
11053     (flush _test-error-buffered-file)
11054 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11060     # check output
11061     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-compound-base-type: output should be empty")
11062     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: var 'a' is not an array"  "F - test-index-with-non-array-compound-base-type: error message")
11063     # check that stop(1) was called
11064     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-compound-base-type: exit status")
11065     # don't restore from ebp
11066     81 0/subop/add %esp 8/imm32
11067     # . epilogue
11068     5d/pop-to-ebp
11069     c3/return
11070 
11071 test-index-with-non-array-compound-base-type-2:
11072     # . prologue
11073     55/push-ebp
11074     89/<- %ebp 4/r32/esp
11075     # setup
11076     (clear-stream _test-input-stream)
11077     (clear-stream $_test-input-buffered-file->buffer)
11078     (clear-stream _test-output-stream)
11079     (clear-stream $_test-output-buffered-file->buffer)
11080     (clear-stream _test-error-stream)
11081     (clear-stream $_test-error-buffered-file->buffer)
11082     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11083     68/push 0/imm32
11084     68/push 0/imm32
11085     89/<- %edx 4/r32/esp
11086     (tailor-exit-descriptor %edx 0x10)
11087     #
11088     (write _test-input-stream "fn foo {\n")
11089     (write _test-input-stream "  var a: (addr int)\n")
11090     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
11091     (write _test-input-stream "}\n")
11092     # convert
11093     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11094     # registers except esp clobbered at this point
11095     # restore ed
11096     89/<- %edx 4/r32/esp
11097     (flush _test-output-buffered-file)
11098     (flush _test-error-buffered-file)
11099 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11105     # check output
11106     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-compound-base-type-2: output should be empty")
11107     (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")
11108     # check that stop(1) was called
11109     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-compound-base-type-2: exit status")
11110     # don't restore from ebp
11111     81 0/subop/add %esp 8/imm32
11112     # . epilogue
11113     5d/pop-to-ebp
11114     c3/return
11115 
11116 test-index-with-array-atom-base-type:
11117     # . prologue
11118     55/push-ebp
11119     89/<- %ebp 4/r32/esp
11120     # setup
11121     (clear-stream _test-input-stream)
11122     (clear-stream $_test-input-buffered-file->buffer)
11123     (clear-stream _test-output-stream)
11124     (clear-stream $_test-output-buffered-file->buffer)
11125     (clear-stream _test-error-stream)
11126     (clear-stream $_test-error-buffered-file->buffer)
11127     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11128     68/push 0/imm32
11129     68/push 0/imm32
11130     89/<- %edx 4/r32/esp
11131     (tailor-exit-descriptor %edx 0x10)
11132     #
11133     (write _test-input-stream "fn foo {\n")
11134     (write _test-input-stream "  var a: array\n")
11135     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
11136     (write _test-input-stream "}\n")
11137     # convert
11138     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11139     # registers except esp clobbered at this point
11140     # restore ed
11141     89/<- %edx 4/r32/esp
11142     (flush _test-output-buffered-file)
11143     (flush _test-error-buffered-file)
11144 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11150     # check output
11151     (check-stream-equal _test-output-stream  ""  "F - test-index-with-array-atom-base-type: output should be empty")
11152     (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")
11153     # check that stop(1) was called
11154     (check-ints-equal *(edx+4) 2 "F - test-index-with-array-atom-base-type: exit status")
11155     # don't restore from ebp
11156     81 0/subop/add %esp 8/imm32
11157     # . epilogue
11158     5d/pop-to-ebp
11159     c3/return
11160 
11161 test-index-with-addr-base-on-stack:
11162     # . prologue
11163     55/push-ebp
11164     89/<- %ebp 4/r32/esp
11165     # setup
11166     (clear-stream _test-input-stream)
11167     (clear-stream $_test-input-buffered-file->buffer)
11168     (clear-stream _test-output-stream)
11169     (clear-stream $_test-output-buffered-file->buffer)
11170     (clear-stream _test-error-stream)
11171     (clear-stream $_test-error-buffered-file->buffer)
11172     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11173     68/push 0/imm32
11174     68/push 0/imm32
11175     89/<- %edx 4/r32/esp
11176     (tailor-exit-descriptor %edx 0x10)
11177     #
11178     (write _test-input-stream "fn foo {\n")
11179     (write _test-input-stream "  var a: (addr array int)\n")
11180     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
11181     (write _test-input-stream "}\n")
11182     # convert
11183     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11184     # registers except esp clobbered at this point
11185     # restore ed
11186     89/<- %edx 4/r32/esp
11187     (flush _test-output-buffered-file)
11188     (flush _test-error-buffered-file)
11189 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11195     # check output
11196     (check-stream-equal _test-output-stream  ""  "F - test-index-with-addr-base-on-stack: output should be empty")
11197     (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")
11198     # check that stop(1) was called
11199     (check-ints-equal *(edx+4) 2 "F - test-index-with-addr-base-on-stack: exit status")
11200     # don't restore from ebp
11201     81 0/subop/add %esp 8/imm32
11202     # . epilogue
11203     5d/pop-to-ebp
11204     c3/return
11205 
11206 test-index-with-wrong-index-type:
11207     # . prologue
11208     55/push-ebp
11209     89/<- %ebp 4/r32/esp
11210     # setup
11211     (clear-stream _test-input-stream)
11212     (clear-stream $_test-input-buffered-file->buffer)
11213     (clear-stream _test-output-stream)
11214     (clear-stream $_test-output-buffered-file->buffer)
11215     (clear-stream _test-error-stream)
11216     (clear-stream $_test-error-buffered-file->buffer)
11217     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11218     68/push 0/imm32
11219     68/push 0/imm32
11220     89/<- %edx 4/r32/esp
11221     (tailor-exit-descriptor %edx 0x10)
11222     #
11223     (write _test-input-stream "fn foo {\n")
11224     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
11225     (write _test-input-stream "  var b: boolean\n")
11226     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
11227     (write _test-input-stream "}\n")
11228     # convert
11229     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11230     # registers except esp clobbered at this point
11231     # restore ed
11232     89/<- %edx 4/r32/esp
11233     (flush _test-output-buffered-file)
11234     (flush _test-error-buffered-file)
11235 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11241     # check output
11242     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-index-type: output should be empty")
11243     (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")
11244     # check that stop(1) was called
11245     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-index-type: exit status")
11246     # don't restore from ebp
11247     81 0/subop/add %esp 8/imm32
11248     # . epilogue
11249     5d/pop-to-ebp
11250     c3/return
11251 
11252 test-index-with-offset-atom-index-type:
11253     # . prologue
11254     55/push-ebp
11255     89/<- %ebp 4/r32/esp
11256     # setup
11257     (clear-stream _test-input-stream)
11258     (clear-stream $_test-input-buffered-file->buffer)
11259     (clear-stream _test-output-stream)
11260     (clear-stream $_test-output-buffered-file->buffer)
11261     (clear-stream _test-error-stream)
11262     (clear-stream $_test-error-buffered-file->buffer)
11263     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11264     68/push 0/imm32
11265     68/push 0/imm32
11266     89/<- %edx 4/r32/esp
11267     (tailor-exit-descriptor %edx 0x10)
11268     #
11269     (write _test-input-stream "fn foo {\n")
11270     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
11271     (write _test-input-stream "  var b: offset\n")
11272     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
11273     (write _test-input-stream "}\n")
11274     # convert
11275     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11276     # registers except esp clobbered at this point
11277     # restore ed
11278     89/<- %edx 4/r32/esp
11279     (flush _test-output-buffered-file)
11280     (flush _test-error-buffered-file)
11281 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11287     # check output
11288     (check-stream-equal _test-output-stream  ""  "F - test-index-with-offset-atom-index-type: output should be empty")
11289     (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")
11290     # check that stop(1) was called
11291     (check-ints-equal *(edx+4) 2 "F - test-index-with-offset-atom-index-type: exit status")
11292     # don't restore from ebp
11293     81 0/subop/add %esp 8/imm32
11294     # . epilogue
11295     5d/pop-to-ebp
11296     c3/return
11297 
11298 test-index-with-offset-on-stack:
11299     # . prologue
11300     55/push-ebp
11301     89/<- %ebp 4/r32/esp
11302     # setup
11303     (clear-stream _test-input-stream)
11304     (clear-stream $_test-input-buffered-file->buffer)
11305     (clear-stream _test-output-stream)
11306     (clear-stream $_test-output-buffered-file->buffer)
11307     (clear-stream _test-error-stream)
11308     (clear-stream $_test-error-buffered-file->buffer)
11309     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11310     68/push 0/imm32
11311     68/push 0/imm32
11312     89/<- %edx 4/r32/esp
11313     (tailor-exit-descriptor %edx 0x10)
11314     #
11315     (write _test-input-stream "fn foo {\n")
11316     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
11317     (write _test-input-stream "  var b: int\n")
11318     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
11319     (write _test-input-stream "}\n")
11320     # convert
11321     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11322     # registers except esp clobbered at this point
11323     # restore ed
11324     89/<- %edx 4/r32/esp
11325     (flush _test-output-buffered-file)
11326     (flush _test-error-buffered-file)
11327 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11333     # check output
11334     (check-stream-equal _test-output-stream  ""  "F - test-index-with-offset-on-stack: output should be empty")
11335     (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")
11336     # check that stop(1) was called
11337     (check-ints-equal *(edx+4) 2 "F - test-index-with-offset-on-stack: exit status")
11338     # don't restore from ebp
11339     81 0/subop/add %esp 8/imm32
11340     # . epilogue
11341     5d/pop-to-ebp
11342     c3/return
11343 
11344 test-index-needs-offset-type:
11345     # . prologue
11346     55/push-ebp
11347     89/<- %ebp 4/r32/esp
11348     # setup
11349     (clear-stream _test-input-stream)
11350     (clear-stream $_test-input-buffered-file->buffer)
11351     (clear-stream _test-output-stream)
11352     (clear-stream $_test-output-buffered-file->buffer)
11353     (clear-stream _test-error-stream)
11354     (clear-stream $_test-error-buffered-file->buffer)
11355     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11356     68/push 0/imm32
11357     68/push 0/imm32
11358     89/<- %edx 4/r32/esp
11359     (tailor-exit-descriptor %edx 0x10)
11360     #
11361     (write _test-input-stream "fn foo {\n")
11362     (write _test-input-stream "  var a/eax: (addr array t) <- copy 0\n")
11363     (write _test-input-stream "  var b/ebx: int <- copy 0\n")
11364     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
11365     (write _test-input-stream "}\n")
11366     (write _test-input-stream "type t {\n")  # size 12 is not a power of two
11367     (write _test-input-stream "  x: int\n")
11368     (write _test-input-stream "  y: int\n")
11369     (write _test-input-stream "  z: int\n")
11370     (write _test-input-stream "}\n")
11371     # convert
11372     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11373     # registers except esp clobbered at this point
11374     # restore ed
11375     89/<- %edx 4/r32/esp
11376     (flush _test-output-buffered-file)
11377     (flush _test-error-buffered-file)
11378 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11384     # check output
11385     (check-stream-equal _test-output-stream  ""  "F - test-index-needs-offset-type: output should be empty")
11386     (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")
11387     # check that stop(1) was called
11388     (check-ints-equal *(edx+4) 2 "F - test-index-needs-offset-type: exit status")
11389     # don't restore from ebp
11390     81 0/subop/add %esp 8/imm32
11391     # . epilogue
11392     5d/pop-to-ebp
11393     c3/return
11394 
11395 test-index-with-output-not-address:
11396     # . prologue
11397     55/push-ebp
11398     89/<- %ebp 4/r32/esp
11399     # setup
11400     (clear-stream _test-input-stream)
11401     (clear-stream $_test-input-buffered-file->buffer)
11402     (clear-stream _test-output-stream)
11403     (clear-stream $_test-output-buffered-file->buffer)
11404     (clear-stream _test-error-stream)
11405     (clear-stream $_test-error-buffered-file->buffer)
11406     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11407     68/push 0/imm32
11408     68/push 0/imm32
11409     89/<- %edx 4/r32/esp
11410     (tailor-exit-descriptor %edx 0x10)
11411     #
11412     (write _test-input-stream "fn foo {\n")
11413     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
11414     (write _test-input-stream "  var o/edi: int <- index a, 0\n")
11415     (write _test-input-stream "}\n")
11416     # convert
11417     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11418     # registers except esp clobbered at this point
11419     # restore ed
11420     89/<- %edx 4/r32/esp
11421     (flush _test-output-buffered-file)
11422     (flush _test-error-buffered-file)
11423 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11429     # check output
11430     (check-stream-equal _test-output-stream  ""  "F - test-index-with-output-not-address: output should be empty")
11431     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: output 'o' must be an addr"  "F - test-index-with-output-not-address: error message")
11432     # check that stop(1) was called
11433     (check-ints-equal *(edx+4) 2 "F - test-index-with-output-not-address: exit status")
11434     # don't restore from ebp
11435     81 0/subop/add %esp 8/imm32
11436     # . epilogue
11437     5d/pop-to-ebp
11438     c3/return
11439 
11440 test-index-with-output-not-address-2:
11441     # . prologue
11442     55/push-ebp
11443     89/<- %ebp 4/r32/esp
11444     # setup
11445     (clear-stream _test-input-stream)
11446     (clear-stream $_test-input-buffered-file->buffer)
11447     (clear-stream _test-output-stream)
11448     (clear-stream $_test-output-buffered-file->buffer)
11449     (clear-stream _test-error-stream)
11450     (clear-stream $_test-error-buffered-file->buffer)
11451     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11452     68/push 0/imm32
11453     68/push 0/imm32
11454     89/<- %edx 4/r32/esp
11455     (tailor-exit-descriptor %edx 0x10)
11456     #
11457     (write _test-input-stream "fn foo {\n")
11458     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
11459     (write _test-input-stream "  var o/edi: (int) <- index a, 0\n")
11460     (write _test-input-stream "}\n")
11461     # convert
11462     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11463     # registers except esp clobbered at this point
11464     # restore ed
11465     89/<- %edx 4/r32/esp
11466     (flush _test-output-buffered-file)
11467     (flush _test-error-buffered-file)
11468 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11474     # check output
11475     (check-stream-equal _test-output-stream  ""  "F - test-index-with-output-not-address-2: output should be empty")
11476     (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")
11477     # check that stop(1) was called
11478     (check-ints-equal *(edx+4) 2 "F - test-index-with-output-not-address-2: exit status")
11479     # don't restore from ebp
11480     81 0/subop/add %esp 8/imm32
11481     # . epilogue
11482     5d/pop-to-ebp
11483     c3/return
11484 
11485 test-index-with-wrong-output-type:
11486     # . prologue
11487     55/push-ebp
11488     89/<- %ebp 4/r32/esp
11489     # setup
11490     (clear-stream _test-input-stream)
11491     (clear-stream $_test-input-buffered-file->buffer)
11492     (clear-stream _test-output-stream)
11493     (clear-stream $_test-output-buffered-file->buffer)
11494     (clear-stream _test-error-stream)
11495     (clear-stream $_test-error-buffered-file->buffer)
11496     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11497     68/push 0/imm32
11498     68/push 0/imm32
11499     89/<- %edx 4/r32/esp
11500     (tailor-exit-descriptor %edx 0x10)
11501     #
11502     (write _test-input-stream "fn foo {\n")
11503     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
11504     (write _test-input-stream "  var o/edi: (addr int) <- index a, 0\n")
11505     (write _test-input-stream "}\n")
11506     # convert
11507     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11508     # registers except esp clobbered at this point
11509     # restore ed
11510     89/<- %edx 4/r32/esp
11511     (flush _test-output-buffered-file)
11512     (flush _test-error-buffered-file)
11513 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11519     # check output
11520     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-output-type: output should be empty")
11521     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: output 'o' does not have the right type"  "F - test-index-with-wrong-output-type: error message")
11522     # check that stop(1) was called
11523     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-output-type: exit status")
11524     # don't restore from ebp
11525     81 0/subop/add %esp 8/imm32
11526     # . epilogue
11527     5d/pop-to-ebp
11528     c3/return
11529 
11530 test-index-with-wrong-output-compound-type:
11531     # . prologue
11532     55/push-ebp
11533     89/<- %ebp 4/r32/esp
11534     # setup
11535     (clear-stream _test-input-stream)
11536     (clear-stream $_test-input-buffered-file->buffer)
11537     (clear-stream _test-output-stream)
11538     (clear-stream $_test-output-buffered-file->buffer)
11539     (clear-stream _test-error-stream)
11540     (clear-stream $_test-error-buffered-file->buffer)
11541     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11542     68/push 0/imm32
11543     68/push 0/imm32
11544     89/<- %edx 4/r32/esp
11545     (tailor-exit-descriptor %edx 0x10)
11546     #
11547     (write _test-input-stream "fn foo {\n")
11548     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
11549     (write _test-input-stream "  var o/edi: (addr handle int) <- index a, 0\n")
11550     (write _test-input-stream "}\n")
11551     # convert
11552     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11553     # registers except esp clobbered at this point
11554     # restore ed
11555     89/<- %edx 4/r32/esp
11556     (flush _test-output-buffered-file)
11557     (flush _test-error-buffered-file)
11558 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11564     # check output
11565     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-output-compound-type: output should be empty")
11566     (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")
11567     # check that stop(1) was called
11568     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-output-compound-type: exit status")
11569     # don't restore from ebp
11570     81 0/subop/add %esp 8/imm32
11571     # . epilogue
11572     5d/pop-to-ebp
11573     c3/return
11574 
11575 test-index-with-no-inouts:
11576     # . prologue
11577     55/push-ebp
11578     89/<- %ebp 4/r32/esp
11579     # setup
11580     (clear-stream _test-input-stream)
11581     (clear-stream $_test-input-buffered-file->buffer)
11582     (clear-stream _test-output-stream)
11583     (clear-stream $_test-output-buffered-file->buffer)
11584     (clear-stream _test-error-stream)
11585     (clear-stream $_test-error-buffered-file->buffer)
11586     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11587     68/push 0/imm32
11588     68/push 0/imm32
11589     89/<- %edx 4/r32/esp
11590     (tailor-exit-descriptor %edx 0x10)
11591     #
11592     (write _test-input-stream "fn foo {\n")
11593     (write _test-input-stream "  var c/ecx: (addr int) <- index\n")
11594     (write _test-input-stream "}\n")
11595     # convert
11596     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11597     # registers except esp clobbered at this point
11598     # restore ed
11599     89/<- %edx 4/r32/esp
11600     (flush _test-output-buffered-file)
11601     (flush _test-error-buffered-file)
11602 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11608     # check output
11609     (check-stream-equal _test-output-stream  ""  "F - test-index-with-no-inouts: output should be empty")
11610     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: too few inouts (2 required)"  "F - test-index-with-no-inouts: error message")
11611     # check that stop(1) was called
11612     (check-ints-equal *(edx+4) 2 "F - test-index-with-no-inouts: exit status")
11613     # don't restore from ebp
11614     81 0/subop/add %esp 8/imm32
11615     # . epilogue
11616     5d/pop-to-ebp
11617     c3/return
11618 
11619 test-index-with-too-few-inouts:
11620     # . prologue
11621     55/push-ebp
11622     89/<- %ebp 4/r32/esp
11623     # setup
11624     (clear-stream _test-input-stream)
11625     (clear-stream $_test-input-buffered-file->buffer)
11626     (clear-stream _test-output-stream)
11627     (clear-stream $_test-output-buffered-file->buffer)
11628     (clear-stream _test-error-stream)
11629     (clear-stream $_test-error-buffered-file->buffer)
11630     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11631     68/push 0/imm32
11632     68/push 0/imm32
11633     89/<- %edx 4/r32/esp
11634     (tailor-exit-descriptor %edx 0x10)
11635     #
11636     (write _test-input-stream "fn foo {\n")
11637     (write _test-input-stream "  var a: (array int 3)\n")
11638     (write _test-input-stream "  var c/ecx: (addr int) <- index a\n")
11639     (write _test-input-stream "}\n")
11640     # convert
11641     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11642     # registers except esp clobbered at this point
11643     # restore ed
11644     89/<- %edx 4/r32/esp
11645     (flush _test-output-buffered-file)
11646     (flush _test-error-buffered-file)
11647 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11653     # check output
11654     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-few-inouts: output should be empty")
11655     (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")
11656     # check that stop(1) was called
11657     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-few-inouts: exit status")
11658     # don't restore from ebp
11659     81 0/subop/add %esp 8/imm32
11660     # . epilogue
11661     5d/pop-to-ebp
11662     c3/return
11663 
11664 test-index-with-too-many-inouts:
11665     # . prologue
11666     55/push-ebp
11667     89/<- %ebp 4/r32/esp
11668     # setup
11669     (clear-stream _test-input-stream)
11670     (clear-stream $_test-input-buffered-file->buffer)
11671     (clear-stream _test-output-stream)
11672     (clear-stream $_test-output-buffered-file->buffer)
11673     (clear-stream _test-error-stream)
11674     (clear-stream $_test-error-buffered-file->buffer)
11675     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11676     68/push 0/imm32
11677     68/push 0/imm32
11678     89/<- %edx 4/r32/esp
11679     (tailor-exit-descriptor %edx 0x10)
11680     #
11681     (write _test-input-stream "fn foo {\n")
11682     (write _test-input-stream "  var a: (array int 3)\n")
11683     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0, 0\n")
11684     (write _test-input-stream "}\n")
11685     # convert
11686     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11687     # registers except esp clobbered at this point
11688     # restore ed
11689     89/<- %edx 4/r32/esp
11690     (flush _test-output-buffered-file)
11691     (flush _test-error-buffered-file)
11692 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11698     # check output
11699     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-many-inouts: output should be empty")
11700     (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")
11701     # check that stop(1) was called
11702     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-many-inouts: exit status")
11703     # don't restore from ebp
11704     81 0/subop/add %esp 8/imm32
11705     # . epilogue
11706     5d/pop-to-ebp
11707     c3/return
11708 
11709 test-index-with-no-output:
11710     # . prologue
11711     55/push-ebp
11712     89/<- %ebp 4/r32/esp
11713     # setup
11714     (clear-stream _test-input-stream)
11715     (clear-stream $_test-input-buffered-file->buffer)
11716     (clear-stream _test-output-stream)
11717     (clear-stream $_test-output-buffered-file->buffer)
11718     (clear-stream _test-error-stream)
11719     (clear-stream $_test-error-buffered-file->buffer)
11720     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11721     68/push 0/imm32
11722     68/push 0/imm32
11723     89/<- %edx 4/r32/esp
11724     (tailor-exit-descriptor %edx 0x10)
11725     #
11726     (write _test-input-stream "fn foo {\n")
11727     (write _test-input-stream "  var a: (array int 3)\n")
11728     (write _test-input-stream "  index a, 0\n")
11729     (write _test-input-stream "}\n")
11730     # convert
11731     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11732     # registers except esp clobbered at this point
11733     # restore ed
11734     89/<- %edx 4/r32/esp
11735     (flush _test-output-buffered-file)
11736     (flush _test-error-buffered-file)
11737 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11743     # check output
11744     (check-stream-equal _test-output-stream  ""  "F - test-index-with-no-output: output should be empty")
11745     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: must have an output"  "F - test-index-with-no-output: error message")
11746     # check that stop(1) was called
11747     (check-ints-equal *(edx+4) 2 "F - test-index-with-no-output: exit status")
11748     # don't restore from ebp
11749     81 0/subop/add %esp 8/imm32
11750     # . epilogue
11751     5d/pop-to-ebp
11752     c3/return
11753 
11754 test-index-with-too-many-outputs:
11755     # . prologue
11756     55/push-ebp
11757     89/<- %ebp 4/r32/esp
11758     # setup
11759     (clear-stream _test-input-stream)
11760     (clear-stream $_test-input-buffered-file->buffer)
11761     (clear-stream _test-output-stream)
11762     (clear-stream $_test-output-buffered-file->buffer)
11763     (clear-stream _test-error-stream)
11764     (clear-stream $_test-error-buffered-file->buffer)
11765     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11766     68/push 0/imm32
11767     68/push 0/imm32
11768     89/<- %edx 4/r32/esp
11769     (tailor-exit-descriptor %edx 0x10)
11770     #
11771     (write _test-input-stream "fn foo {\n")
11772     (write _test-input-stream "  var a: (array int 3)\n")
11773     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
11774     (write _test-input-stream "  var c/ecx: (addr int) <- copy 0\n")
11775     (write _test-input-stream "  b, c <- index a, 0\n")
11776     (write _test-input-stream "}\n")
11777     # convert
11778     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11779     # registers except esp clobbered at this point
11780     # restore ed
11781     89/<- %edx 4/r32/esp
11782     (flush _test-output-buffered-file)
11783     (flush _test-error-buffered-file)
11784 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11790     # check output
11791     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-many-outputs: output should be empty")
11792     (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")
11793     # check that stop(1) was called
11794     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-many-outputs: exit status")
11795     # don't restore from ebp
11796     81 0/subop/add %esp 8/imm32
11797     # . epilogue
11798     5d/pop-to-ebp
11799     c3/return
11800 
11801 test-compute-offset-with-non-array-atom-base-type:
11802     # . prologue
11803     55/push-ebp
11804     89/<- %ebp 4/r32/esp
11805     # setup
11806     (clear-stream _test-input-stream)
11807     (clear-stream $_test-input-buffered-file->buffer)
11808     (clear-stream _test-output-stream)
11809     (clear-stream $_test-output-buffered-file->buffer)
11810     (clear-stream _test-error-stream)
11811     (clear-stream $_test-error-buffered-file->buffer)
11812     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11813     68/push 0/imm32
11814     68/push 0/imm32
11815     89/<- %edx 4/r32/esp
11816     (tailor-exit-descriptor %edx 0x10)
11817     #
11818     (write _test-input-stream "fn foo {\n")
11819     (write _test-input-stream "  var a: int\n")
11820     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
11821     (write _test-input-stream "}\n")
11822     # convert
11823     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11824     # registers except esp clobbered at this point
11825     # restore ed
11826     89/<- %edx 4/r32/esp
11827     (flush _test-output-buffered-file)
11828     (flush _test-error-buffered-file)
11829 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11835     # check output
11836     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-atom-base-type: output should be empty")
11837     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: var 'a' is not an array"  "F - test-compute-offset-with-non-array-atom-base-type: error message")
11838     # check that stop(1) was called
11839     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-atom-base-type: exit status")
11840     # don't restore from ebp
11841     81 0/subop/add %esp 8/imm32
11842     # . epilogue
11843     5d/pop-to-ebp
11844     c3/return
11845 
11846 test-compute-offset-with-non-array-compound-base-type:
11847     # . prologue
11848     55/push-ebp
11849     89/<- %ebp 4/r32/esp
11850     # setup
11851     (clear-stream _test-input-stream)
11852     (clear-stream $_test-input-buffered-file->buffer)
11853     (clear-stream _test-output-stream)
11854     (clear-stream $_test-output-buffered-file->buffer)
11855     (clear-stream _test-error-stream)
11856     (clear-stream $_test-error-buffered-file->buffer)
11857     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11858     68/push 0/imm32
11859     68/push 0/imm32
11860     89/<- %edx 4/r32/esp
11861     (tailor-exit-descriptor %edx 0x10)
11862     #
11863     (write _test-input-stream "fn foo {\n")
11864     (write _test-input-stream "  var a: (handle int)\n")
11865     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
11866     (write _test-input-stream "}\n")
11867     # convert
11868     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11869     # registers except esp clobbered at this point
11870     # restore ed
11871     89/<- %edx 4/r32/esp
11872     (flush _test-output-buffered-file)
11873     (flush _test-error-buffered-file)
11874 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11880     # check output
11881     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-compound-base-type: output should be empty")
11882     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: var 'a' is not an array"  "F - test-compute-offset-with-non-array-compound-base-type: error message")
11883     # check that stop(1) was called
11884     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-compound-base-type: exit status")
11885     # don't restore from ebp
11886     81 0/subop/add %esp 8/imm32
11887     # . epilogue
11888     5d/pop-to-ebp
11889     c3/return
11890 
11891 test-compute-offset-with-non-array-compound-base-type-2:
11892     # . prologue
11893     55/push-ebp
11894     89/<- %ebp 4/r32/esp
11895     # setup
11896     (clear-stream _test-input-stream)
11897     (clear-stream $_test-input-buffered-file->buffer)
11898     (clear-stream _test-output-stream)
11899     (clear-stream $_test-output-buffered-file->buffer)
11900     (clear-stream _test-error-stream)
11901     (clear-stream $_test-error-buffered-file->buffer)
11902     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11903     68/push 0/imm32
11904     68/push 0/imm32
11905     89/<- %edx 4/r32/esp
11906     (tailor-exit-descriptor %edx 0x10)
11907     #
11908     (write _test-input-stream "fn foo {\n")
11909     (write _test-input-stream "  var a: (addr int)\n")
11910     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
11911     (write _test-input-stream "}\n")
11912     # convert
11913     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11914     # registers except esp clobbered at this point
11915     # restore ed
11916     89/<- %edx 4/r32/esp
11917     (flush _test-output-buffered-file)
11918     (flush _test-error-buffered-file)
11919 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11925     # check output
11926     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-compound-base-type-2: output should be empty")
11927     (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")
11928     # check that stop(1) was called
11929     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-compound-base-type-2: exit status")
11930     # don't restore from ebp
11931     81 0/subop/add %esp 8/imm32
11932     # . epilogue
11933     5d/pop-to-ebp
11934     c3/return
11935 
11936 test-compute-offset-with-array-atom-base-type:
11937     # . prologue
11938     55/push-ebp
11939     89/<- %ebp 4/r32/esp
11940     # setup
11941     (clear-stream _test-input-stream)
11942     (clear-stream $_test-input-buffered-file->buffer)
11943     (clear-stream _test-output-stream)
11944     (clear-stream $_test-output-buffered-file->buffer)
11945     (clear-stream _test-error-stream)
11946     (clear-stream $_test-error-buffered-file->buffer)
11947     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11948     68/push 0/imm32
11949     68/push 0/imm32
11950     89/<- %edx 4/r32/esp
11951     (tailor-exit-descriptor %edx 0x10)
11952     #
11953     (write _test-input-stream "fn foo {\n")
11954     (write _test-input-stream "  var a: array\n")
11955     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
11956     (write _test-input-stream "}\n")
11957     # convert
11958     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11959     # registers except esp clobbered at this point
11960     # restore ed
11961     89/<- %edx 4/r32/esp
11962     (flush _test-output-buffered-file)
11963     (flush _test-error-buffered-file)
11964 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11970     # check output
11971     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-array-atom-base-type: output should be empty")
11972     (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")
11973     # check that stop(1) was called
11974     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-array-atom-base-type: exit status")
11975     # don't restore from ebp
11976     81 0/subop/add %esp 8/imm32
11977     # . epilogue
11978     5d/pop-to-ebp
11979     c3/return
11980 
11981 test-compute-offset-with-wrong-index-type:
11982     # . prologue
11983     55/push-ebp
11984     89/<- %ebp 4/r32/esp
11985     # setup
11986     (clear-stream _test-input-stream)
11987     (clear-stream $_test-input-buffered-file->buffer)
11988     (clear-stream _test-output-stream)
11989     (clear-stream $_test-output-buffered-file->buffer)
11990     (clear-stream _test-error-stream)
11991     (clear-stream $_test-error-buffered-file->buffer)
11992     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11993     68/push 0/imm32
11994     68/push 0/imm32
11995     89/<- %edx 4/r32/esp
11996     (tailor-exit-descriptor %edx 0x10)
11997     #
11998     (write _test-input-stream "fn foo {\n")
11999     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
12000     (write _test-input-stream "  var b: boolean\n")
12001     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, b\n")
12002     (write _test-input-stream "}\n")
12003     # convert
12004     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12005     # registers except esp clobbered at this point
12006     # restore ed
12007     89/<- %edx 4/r32/esp
12008     (flush _test-output-buffered-file)
12009     (flush _test-error-buffered-file)
12010 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12016     # check output
12017     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-index-type: output should be empty")
12018     (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")
12019     # check that stop(1) was called
12020     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-index-type: exit status")
12021     # don't restore from ebp
12022     81 0/subop/add %esp 8/imm32
12023     # . epilogue
12024     5d/pop-to-ebp
12025     c3/return
12026 
12027 test-compute-offset-with-output-not-offset:
12028     # . prologue
12029     55/push-ebp
12030     89/<- %ebp 4/r32/esp
12031     # setup
12032     (clear-stream _test-input-stream)
12033     (clear-stream $_test-input-buffered-file->buffer)
12034     (clear-stream _test-output-stream)
12035     (clear-stream $_test-output-buffered-file->buffer)
12036     (clear-stream _test-error-stream)
12037     (clear-stream $_test-error-buffered-file->buffer)
12038     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12039     68/push 0/imm32
12040     68/push 0/imm32
12041     89/<- %edx 4/r32/esp
12042     (tailor-exit-descriptor %edx 0x10)
12043     #
12044     (write _test-input-stream "fn foo {\n")
12045     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
12046     (write _test-input-stream "  var o/edi: int <- compute-offset a, 0\n")
12047     (write _test-input-stream "}\n")
12048     # convert
12049     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12050     # registers except esp clobbered at this point
12051     # restore ed
12052     89/<- %edx 4/r32/esp
12053     (flush _test-output-buffered-file)
12054     (flush _test-error-buffered-file)
12055 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12061     # check output
12062     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-output-not-offset: output should be empty")
12063     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: output 'o' must be an offset"  "F - test-compute-offset-with-output-not-offset: error message")
12064     # check that stop(1) was called
12065     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-output-not-offset: exit status")
12066     # don't restore from ebp
12067     81 0/subop/add %esp 8/imm32
12068     # . epilogue
12069     5d/pop-to-ebp
12070     c3/return
12071 
12072 test-compute-offset-with-output-not-address-2:
12073     # . prologue
12074     55/push-ebp
12075     89/<- %ebp 4/r32/esp
12076     # setup
12077     (clear-stream _test-input-stream)
12078     (clear-stream $_test-input-buffered-file->buffer)
12079     (clear-stream _test-output-stream)
12080     (clear-stream $_test-output-buffered-file->buffer)
12081     (clear-stream _test-error-stream)
12082     (clear-stream $_test-error-buffered-file->buffer)
12083     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12084     68/push 0/imm32
12085     68/push 0/imm32
12086     89/<- %edx 4/r32/esp
12087     (tailor-exit-descriptor %edx 0x10)
12088     #
12089     (write _test-input-stream "fn foo {\n")
12090     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
12091     (write _test-input-stream "  var o/edi: (int) <- compute-offset a, 0\n")
12092     (write _test-input-stream "}\n")
12093     # convert
12094     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12095     # registers except esp clobbered at this point
12096     # restore ed
12097     89/<- %edx 4/r32/esp
12098     (flush _test-output-buffered-file)
12099     (flush _test-error-buffered-file)
12100 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12106     # check output
12107     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-output-not-address-2: output should be empty")
12108     (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")
12109     # check that stop(1) was called
12110     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-output-not-address-2: exit status")
12111     # don't restore from ebp
12112     81 0/subop/add %esp 8/imm32
12113     # . epilogue
12114     5d/pop-to-ebp
12115     c3/return
12116 
12117 test-compute-offset-with-wrong-output-type:
12118     # . prologue
12119     55/push-ebp
12120     89/<- %ebp 4/r32/esp
12121     # setup
12122     (clear-stream _test-input-stream)
12123     (clear-stream $_test-input-buffered-file->buffer)
12124     (clear-stream _test-output-stream)
12125     (clear-stream $_test-output-buffered-file->buffer)
12126     (clear-stream _test-error-stream)
12127     (clear-stream $_test-error-buffered-file->buffer)
12128     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12129     68/push 0/imm32
12130     68/push 0/imm32
12131     89/<- %edx 4/r32/esp
12132     (tailor-exit-descriptor %edx 0x10)
12133     #
12134     (write _test-input-stream "fn foo {\n")
12135     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
12136     (write _test-input-stream "  var o/edi: (offset int) <- compute-offset a, 0\n")
12137     (write _test-input-stream "}\n")
12138     # convert
12139     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12140     # registers except esp clobbered at this point
12141     # restore ed
12142     89/<- %edx 4/r32/esp
12143     (flush _test-output-buffered-file)
12144     (flush _test-error-buffered-file)
12145 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12151     # check output
12152     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-output-type: output should be empty")
12153     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: output 'o' does not have the right type"  "F - test-compute-offset-with-wrong-output-type: error message")
12154     # check that stop(1) was called
12155     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-output-type: exit status")
12156     # don't restore from ebp
12157     81 0/subop/add %esp 8/imm32
12158     # . epilogue
12159     5d/pop-to-ebp
12160     c3/return
12161 
12162 test-compute-offset-with-wrong-output-compound-type:
12163     # . prologue
12164     55/push-ebp
12165     89/<- %ebp 4/r32/esp
12166     # setup
12167     (clear-stream _test-input-stream)
12168     (clear-stream $_test-input-buffered-file->buffer)
12169     (clear-stream _test-output-stream)
12170     (clear-stream $_test-output-buffered-file->buffer)
12171     (clear-stream _test-error-stream)
12172     (clear-stream $_test-error-buffered-file->buffer)
12173     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12174     68/push 0/imm32
12175     68/push 0/imm32
12176     89/<- %edx 4/r32/esp
12177     (tailor-exit-descriptor %edx 0x10)
12178     #
12179     (write _test-input-stream "fn foo {\n")
12180     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
12181     (write _test-input-stream "  var o/edi: (offset handle int) <- compute-offset a, 0\n")
12182     (write _test-input-stream "}\n")
12183     # convert
12184     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12185     # registers except esp clobbered at this point
12186     # restore ed
12187     89/<- %edx 4/r32/esp
12188     (flush _test-output-buffered-file)
12189     (flush _test-error-buffered-file)
12190 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12196     # check output
12197     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-output-compound-type: output should be empty")
12198     (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")
12199     # check that stop(1) was called
12200     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-output-compound-type: exit status")
12201     # don't restore from ebp
12202     81 0/subop/add %esp 8/imm32
12203     # . epilogue
12204     5d/pop-to-ebp
12205     c3/return
12206 
12207 test-compute-offset-with-no-inouts:
12208     # . prologue
12209     55/push-ebp
12210     89/<- %ebp 4/r32/esp
12211     # setup
12212     (clear-stream _test-input-stream)
12213     (clear-stream $_test-input-buffered-file->buffer)
12214     (clear-stream _test-output-stream)
12215     (clear-stream $_test-output-buffered-file->buffer)
12216     (clear-stream _test-error-stream)
12217     (clear-stream $_test-error-buffered-file->buffer)
12218     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12219     68/push 0/imm32
12220     68/push 0/imm32
12221     89/<- %edx 4/r32/esp
12222     (tailor-exit-descriptor %edx 0x10)
12223     #
12224     (write _test-input-stream "fn foo {\n")
12225     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset\n")
12226     (write _test-input-stream "}\n")
12227     # convert
12228     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12229     # registers except esp clobbered at this point
12230     # restore ed
12231     89/<- %edx 4/r32/esp
12232     (flush _test-output-buffered-file)
12233     (flush _test-error-buffered-file)
12234 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12240     # check output
12241     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-no-inouts: output should be empty")
12242     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: too few inouts (2 required)"  "F - test-compute-offset-with-no-inouts: error message")
12243     # check that stop(1) was called
12244     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-no-inouts: exit status")
12245     # don't restore from ebp
12246     81 0/subop/add %esp 8/imm32
12247     # . epilogue
12248     5d/pop-to-ebp
12249     c3/return
12250 
12251 test-compute-offset-with-too-few-inouts:
12252     # . prologue
12253     55/push-ebp
12254     89/<- %ebp 4/r32/esp
12255     # setup
12256     (clear-stream _test-input-stream)
12257     (clear-stream $_test-input-buffered-file->buffer)
12258     (clear-stream _test-output-stream)
12259     (clear-stream $_test-output-buffered-file->buffer)
12260     (clear-stream _test-error-stream)
12261     (clear-stream $_test-error-buffered-file->buffer)
12262     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12263     68/push 0/imm32
12264     68/push 0/imm32
12265     89/<- %edx 4/r32/esp
12266     (tailor-exit-descriptor %edx 0x10)
12267     #
12268     (write _test-input-stream "fn foo {\n")
12269     (write _test-input-stream "  var a: (array int 3)\n")
12270     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a\n")
12271     (write _test-input-stream "}\n")
12272     # convert
12273     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12274     # registers except esp clobbered at this point
12275     # restore ed
12276     89/<- %edx 4/r32/esp
12277     (flush _test-output-buffered-file)
12278     (flush _test-error-buffered-file)
12279 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12285     # check output
12286     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-few-inouts: output should be empty")
12287     (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")
12288     # check that stop(1) was called
12289     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-few-inouts: exit status")
12290     # don't restore from ebp
12291     81 0/subop/add %esp 8/imm32
12292     # . epilogue
12293     5d/pop-to-ebp
12294     c3/return
12295 
12296 test-compute-offset-with-too-many-inouts:
12297     # . prologue
12298     55/push-ebp
12299     89/<- %ebp 4/r32/esp
12300     # setup
12301     (clear-stream _test-input-stream)
12302     (clear-stream $_test-input-buffered-file->buffer)
12303     (clear-stream _test-output-stream)
12304     (clear-stream $_test-output-buffered-file->buffer)
12305     (clear-stream _test-error-stream)
12306     (clear-stream $_test-error-buffered-file->buffer)
12307     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12308     68/push 0/imm32
12309     68/push 0/imm32
12310     89/<- %edx 4/r32/esp
12311     (tailor-exit-descriptor %edx 0x10)
12312     #
12313     (write _test-input-stream "fn foo {\n")
12314     (write _test-input-stream "  var a: (array int 3)\n")
12315     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0, 0\n")
12316     (write _test-input-stream "}\n")
12317     # convert
12318     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12319     # registers except esp clobbered at this point
12320     # restore ed
12321     89/<- %edx 4/r32/esp
12322     (flush _test-output-buffered-file)
12323     (flush _test-error-buffered-file)
12324 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12330     # check output
12331     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-many-inouts: output should be empty")
12332     (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")
12333     # check that stop(1) was called
12334     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-many-inouts: exit status")
12335     # don't restore from ebp
12336     81 0/subop/add %esp 8/imm32
12337     # . epilogue
12338     5d/pop-to-ebp
12339     c3/return
12340 
12341 test-compute-offset-with-no-output:
12342     # . prologue
12343     55/push-ebp
12344     89/<- %ebp 4/r32/esp
12345     # setup
12346     (clear-stream _test-input-stream)
12347     (clear-stream $_test-input-buffered-file->buffer)
12348     (clear-stream _test-output-stream)
12349     (clear-stream $_test-output-buffered-file->buffer)
12350     (clear-stream _test-error-stream)
12351     (clear-stream $_test-error-buffered-file->buffer)
12352     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12353     68/push 0/imm32
12354     68/push 0/imm32
12355     89/<- %edx 4/r32/esp
12356     (tailor-exit-descriptor %edx 0x10)
12357     #
12358     (write _test-input-stream "fn foo {\n")
12359     (write _test-input-stream "  var a: (array int 3)\n")
12360     (write _test-input-stream "  compute-offset a, 0\n")
12361     (write _test-input-stream "}\n")
12362     # convert
12363     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12364     # registers except esp clobbered at this point
12365     # restore ed
12366     89/<- %edx 4/r32/esp
12367     (flush _test-output-buffered-file)
12368     (flush _test-error-buffered-file)
12369 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12375     # check output
12376     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-no-output: output should be empty")
12377     (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")
12378     # check that stop(1) was called
12379     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-no-output: 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-compute-offset-with-too-many-outputs:
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: (array int 3)\n")
12405     (write _test-input-stream "  var b/eax: (offset int) <- compute-offset a, 0\n")
12406     (write _test-input-stream "  var c/ecx: (addr int) <- copy 0\n")
12407     (write _test-input-stream "  b, c <- compute-offset a, 0\n")
12408     (write _test-input-stream "}\n")
12409     # convert
12410     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12411     # registers except esp clobbered at this point
12412     # restore ed
12413     89/<- %edx 4/r32/esp
12414     (flush _test-output-buffered-file)
12415     (flush _test-error-buffered-file)
12416 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12422     # check output
12423     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-many-outputs: output should be empty")
12424     (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")
12425     # check that stop(1) was called
12426     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-many-outputs: exit status")
12427     # don't restore from ebp
12428     81 0/subop/add %esp 8/imm32
12429     # . epilogue
12430     5d/pop-to-ebp
12431     c3/return
12432 
12433 test-convert-read-from-stream:
12434     # . prologue
12435     55/push-ebp
12436     89/<- %ebp 4/r32/esp
12437     # setup
12438     (clear-stream _test-input-stream)
12439     (clear-stream $_test-input-buffered-file->buffer)
12440     (clear-stream _test-output-stream)
12441     (clear-stream $_test-output-buffered-file->buffer)
12442     #
12443     (write _test-input-stream "fn foo {\n")
12444     (write _test-input-stream "  var s/esi: (addr stream int) <- copy 0\n")
12445     (write _test-input-stream "  var o/ecx: (addr int) <- copy 0\n")
12446     (write _test-input-stream "  read-from-stream s, o\n")
12447     (write _test-input-stream "}\n")
12448     # convert
12449     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
12450     # registers except esp clobbered at this point
12451     # restore ed
12452     89/<- %edx 4/r32/esp
12453     (flush _test-output-buffered-file)
12454     (flush _test-error-buffered-file)
12455 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
12461     # check output
12462     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-read-from-stream/0")
12463     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-read-from-stream/1")
12464     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-read-from-stream/2")
12465     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-read-from-stream/3")
12466     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-read-from-stream/4")
12467     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-read-from-stream/5")
12468     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-read-from-stream/6")
12469     (check-next-stream-line-equal _test-output-stream "    be/copy-to-esi 0/imm32"      "F - test-convert-read-from-stream/7")
12470     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-read-from-stream/8")
12471     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"      "F - test-convert-read-from-stream/9")
12472     (check-next-stream-line-equal _test-output-stream "    (read-from-stream %esi %ecx 0x00000004)"  "F - test-convert-read-from-stream/10")
12473     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-read-from-stream/11")
12474     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-read-from-stream/12")
12475     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-read-from-stream/13")
12476     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-read-from-stream/14")
12477     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-read-from-stream/15")
12478     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-read-from-stream/16")
12479     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-read-from-stream/17")
12480     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-read-from-stream/18")
12481     # . epilogue
12482     89/<- %esp 5/r32/ebp
12483     5d/pop-to-ebp
12484     c3/return
12485 
12486 test-convert-read-from-stream-with-correct-payload-size:
12487     # . prologue
12488     55/push-ebp
12489     89/<- %ebp 4/r32/esp
12490     # setup
12491     (clear-stream _test-input-stream)
12492     (clear-stream $_test-input-buffered-file->buffer)
12493     (clear-stream _test-output-stream)
12494     (clear-stream $_test-output-buffered-file->buffer)
12495     #
12496     (write _test-input-stream "fn foo {\n")
12497     (write _test-input-stream "  var s/esi: (addr stream handle int) <- copy 0\n")
12498     (write _test-input-stream "  var o/ecx: (addr handle int) <- copy 0\n")
12499     (write _test-input-stream "  read-from-stream s, o\n")
12500     (write _test-input-stream "}\n")
12501     # convert
12502     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
12503     # registers except esp clobbered at this point
12504     # restore ed
12505     89/<- %edx 4/r32/esp
12506     (flush _test-output-buffered-file)
12507     (flush _test-error-buffered-file)
12508 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
12514     # check output
12515     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-read-from-stream-with-correct-payload-size/0")
12516     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-read-from-stream-with-correct-payload-size/1")
12517     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-read-from-stream-with-correct-payload-size/2")
12518     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-read-from-stream-with-correct-payload-size/3")
12519     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-read-from-stream-with-correct-payload-size/4")
12520     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-read-from-stream-with-correct-payload-size/5")
12521     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-read-from-stream-with-correct-payload-size/6")
12522     (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")
12523     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-read-from-stream-with-correct-payload-size/8")
12524     (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")
12525     (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")
12526     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-read-from-stream-with-correct-payload-size/11")
12527     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-read-from-stream-with-correct-payload-size/12")
12528     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-read-from-stream-with-correct-payload-size/13")
12529     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-read-from-stream-with-correct-payload-size/14")
12530     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-read-from-stream-with-correct-payload-size/15")
12531     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-read-from-stream-with-correct-payload-size/16")
12532     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-read-from-stream-with-correct-payload-size/17")
12533     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-read-from-stream-with-correct-payload-size/18")
12534     # . epilogue
12535     89/<- %esp 5/r32/ebp
12536     5d/pop-to-ebp
12537     c3/return
12538 
12539 test-read-from-stream-with-non-stream-atom-base-type:
12540     # . prologue
12541     55/push-ebp
12542     89/<- %ebp 4/r32/esp
12543     # setup
12544     (clear-stream _test-input-stream)
12545     (clear-stream $_test-input-buffered-file->buffer)
12546     (clear-stream _test-output-stream)
12547     (clear-stream $_test-output-buffered-file->buffer)
12548     (clear-stream _test-error-stream)
12549     (clear-stream $_test-error-buffered-file->buffer)
12550     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12551     68/push 0/imm32
12552     68/push 0/imm32
12553     89/<- %edx 4/r32/esp
12554     (tailor-exit-descriptor %edx 0x10)
12555     #
12556     (write _test-input-stream "fn foo {\n")
12557     (write _test-input-stream "  var a: int\n")
12558     (write _test-input-stream "  read-from-stream a, 0\n")
12559     (write _test-input-stream "}\n")
12560     # convert
12561     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12562     # registers except esp clobbered at this point
12563     # restore ed
12564     89/<- %edx 4/r32/esp
12565     (flush _test-output-buffered-file)
12566     (flush _test-error-buffered-file)
12567 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12573     # check output
12574     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-atom-base-type: output should be empty")
12575     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: var 'a' must be an addr to a stream"  "F - test-read-from-stream-with-non-stream-atom-base-type: error message")
12576     # check that stop(1) was called
12577     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-atom-base-type: exit status")
12578     # don't restore from ebp
12579     81 0/subop/add %esp 8/imm32
12580     # . epilogue
12581     5d/pop-to-ebp
12582     c3/return
12583 
12584 test-read-from-stream-with-non-stream-compound-base-type:
12585     # . prologue
12586     55/push-ebp
12587     89/<- %ebp 4/r32/esp
12588     # setup
12589     (clear-stream _test-input-stream)
12590     (clear-stream $_test-input-buffered-file->buffer)
12591     (clear-stream _test-output-stream)
12592     (clear-stream $_test-output-buffered-file->buffer)
12593     (clear-stream _test-error-stream)
12594     (clear-stream $_test-error-buffered-file->buffer)
12595     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12596     68/push 0/imm32
12597     68/push 0/imm32
12598     89/<- %edx 4/r32/esp
12599     (tailor-exit-descriptor %edx 0x10)
12600     #
12601     (write _test-input-stream "fn foo {\n")
12602     (write _test-input-stream "  var a: (handle int)\n")
12603     (write _test-input-stream "  read-from-stream a, 0\n")
12604     (write _test-input-stream "}\n")
12605     # convert
12606     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12607     # registers except esp clobbered at this point
12608     # restore ed
12609     89/<- %edx 4/r32/esp
12610     (flush _test-output-buffered-file)
12611     (flush _test-error-buffered-file)
12612 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12618     # check output
12619     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-compound-base-type: output should be empty")
12620     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: var 'a' must be an addr to a stream"  "F - test-read-from-stream-with-non-stream-compound-base-type: error message")
12621     # check that stop(1) was called
12622     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-compound-base-type: exit status")
12623     # don't restore from ebp
12624     81 0/subop/add %esp 8/imm32
12625     # . epilogue
12626     5d/pop-to-ebp
12627     c3/return
12628 
12629 test-read-from-stream-with-non-stream-compound-base-type-2:
12630     # . prologue
12631     55/push-ebp
12632     89/<- %ebp 4/r32/esp
12633     # setup
12634     (clear-stream _test-input-stream)
12635     (clear-stream $_test-input-buffered-file->buffer)
12636     (clear-stream _test-output-stream)
12637     (clear-stream $_test-output-buffered-file->buffer)
12638     (clear-stream _test-error-stream)
12639     (clear-stream $_test-error-buffered-file->buffer)
12640     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12641     68/push 0/imm32
12642     68/push 0/imm32
12643     89/<- %edx 4/r32/esp
12644     (tailor-exit-descriptor %edx 0x10)
12645     #
12646     (write _test-input-stream "fn foo {\n")
12647     (write _test-input-stream "  var a: (addr int)\n")
12648     (write _test-input-stream "  read-from-stream a, 0\n")
12649     (write _test-input-stream "}\n")
12650     # convert
12651     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12652     # registers except esp clobbered at this point
12653     # restore ed
12654     89/<- %edx 4/r32/esp
12655     (flush _test-output-buffered-file)
12656     (flush _test-error-buffered-file)
12657 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12663     # check output
12664     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-compound-base-type-2: output should be empty")
12665     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: var 'a' must be an addr to a stream"  "F - test-read-from-stream-with-non-stream-compound-base-type-2: error message")
12666     # check that stop(1) was called
12667     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-compound-base-type-2: exit status")
12668     # don't restore from ebp
12669     81 0/subop/add %esp 8/imm32
12670     # . epilogue
12671     5d/pop-to-ebp
12672     c3/return
12673 
12674 test-read-from-stream-with-stream-atom-base-type:
12675     # . prologue
12676     55/push-ebp
12677     89/<- %ebp 4/r32/esp
12678     # setup
12679     (clear-stream _test-input-stream)
12680     (clear-stream $_test-input-buffered-file->buffer)
12681     (clear-stream _test-output-stream)
12682     (clear-stream $_test-output-buffered-file->buffer)
12683     (clear-stream _test-error-stream)
12684     (clear-stream $_test-error-buffered-file->buffer)
12685     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12686     68/push 0/imm32
12687     68/push 0/imm32
12688     89/<- %edx 4/r32/esp
12689     (tailor-exit-descriptor %edx 0x10)
12690     #
12691     (write _test-input-stream "fn foo {\n")
12692     (write _test-input-stream "  var a: stream\n")
12693     (write _test-input-stream "  read-from-stream a, 0\n")
12694     (write _test-input-stream "}\n")
12695     # convert
12696     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12697     # registers except esp clobbered at this point
12698     # restore ed
12699     89/<- %edx 4/r32/esp
12700     (flush _test-output-buffered-file)
12701     (flush _test-error-buffered-file)
12702 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12708     # check output
12709     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-stream-atom-base-type: output should be empty")
12710     (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")
12711     # check that stop(1) was called
12712     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-stream-atom-base-type: exit status")
12713     # don't restore from ebp
12714     81 0/subop/add %esp 8/imm32
12715     # . epilogue
12716     5d/pop-to-ebp
12717     c3/return
12718 
12719 test-read-from-stream-with-wrong-index-type:
12720     # . prologue
12721     55/push-ebp
12722     89/<- %ebp 4/r32/esp
12723     # setup
12724     (clear-stream _test-input-stream)
12725     (clear-stream $_test-input-buffered-file->buffer)
12726     (clear-stream _test-output-stream)
12727     (clear-stream $_test-output-buffered-file->buffer)
12728     (clear-stream _test-error-stream)
12729     (clear-stream $_test-error-buffered-file->buffer)
12730     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12731     68/push 0/imm32
12732     68/push 0/imm32
12733     89/<- %edx 4/r32/esp
12734     (tailor-exit-descriptor %edx 0x10)
12735     #
12736     (write _test-input-stream "fn foo {\n")
12737     (write _test-input-stream "  var a/eax: (addr stream int) <- copy 0\n")
12738     (write _test-input-stream "  var b: boolean\n")
12739     (write _test-input-stream "  read-from-stream a, b\n")
12740     (write _test-input-stream "}\n")
12741     # convert
12742     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12743     # registers except esp clobbered at this point
12744     # restore ed
12745     89/<- %edx 4/r32/esp
12746     (flush _test-output-buffered-file)
12747     (flush _test-error-buffered-file)
12748 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12754     # check output
12755     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-wrong-index-type: output should be empty")
12756     (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")
12757     # check that stop(1) was called
12758     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-wrong-index-type: exit status")
12759     # don't restore from ebp
12760     81 0/subop/add %esp 8/imm32
12761     # . epilogue
12762     5d/pop-to-ebp
12763     c3/return
12764 
12765 test-read-from-stream-with-no-inouts:
12766     # . prologue
12767     55/push-ebp
12768     89/<- %ebp 4/r32/esp
12769     # setup
12770     (clear-stream _test-input-stream)
12771     (clear-stream $_test-input-buffered-file->buffer)
12772     (clear-stream _test-output-stream)
12773     (clear-stream $_test-output-buffered-file->buffer)
12774     (clear-stream _test-error-stream)
12775     (clear-stream $_test-error-buffered-file->buffer)
12776     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12777     68/push 0/imm32
12778     68/push 0/imm32
12779     89/<- %edx 4/r32/esp
12780     (tailor-exit-descriptor %edx 0x10)
12781     #
12782     (write _test-input-stream "fn foo {\n")
12783     (write _test-input-stream "  read-from-stream\n")
12784     (write _test-input-stream "}\n")
12785     # convert
12786     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12787     # registers except esp clobbered at this point
12788     # restore ed
12789     89/<- %edx 4/r32/esp
12790     (flush _test-output-buffered-file)
12791     (flush _test-error-buffered-file)
12792 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12798     # check output
12799     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-no-inouts: output should be empty")
12800     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: too few inouts (2 required)"  "F - test-read-from-stream-with-no-inouts: error message")
12801     # check that stop(1) was called
12802     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-no-inouts: exit status")
12803     # don't restore from ebp
12804     81 0/subop/add %esp 8/imm32
12805     # . epilogue
12806     5d/pop-to-ebp
12807     c3/return
12808 
12809 test-read-from-stream-with-too-few-inouts:
12810     # . prologue
12811     55/push-ebp
12812     89/<- %ebp 4/r32/esp
12813     # setup
12814     (clear-stream _test-input-stream)
12815     (clear-stream $_test-input-buffered-file->buffer)
12816     (clear-stream _test-output-stream)
12817     (clear-stream $_test-output-buffered-file->buffer)
12818     (clear-stream _test-error-stream)
12819     (clear-stream $_test-error-buffered-file->buffer)
12820     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12821     68/push 0/imm32
12822     68/push 0/imm32
12823     89/<- %edx 4/r32/esp
12824     (tailor-exit-descriptor %edx 0x10)
12825     #
12826     (write _test-input-stream "fn foo {\n")
12827     (write _test-input-stream "  var a: (addr stream int)\n")
12828     (write _test-input-stream "  read-from-stream a\n")
12829     (write _test-input-stream "}\n")
12830     # convert
12831     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12832     # registers except esp clobbered at this point
12833     # restore ed
12834     89/<- %edx 4/r32/esp
12835     (flush _test-output-buffered-file)
12836     (flush _test-error-buffered-file)
12837 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12843     # check output
12844     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-too-few-inouts: output should be empty")
12845     (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")
12846     # check that stop(1) was called
12847     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-too-few-inouts: exit status")
12848     # don't restore from ebp
12849     81 0/subop/add %esp 8/imm32
12850     # . epilogue
12851     5d/pop-to-ebp
12852     c3/return
12853 
12854 test-read-from-stream-with-too-many-inouts:
12855     # . prologue
12856     55/push-ebp
12857     89/<- %ebp 4/r32/esp
12858     # setup
12859     (clear-stream _test-input-stream)
12860     (clear-stream $_test-input-buffered-file->buffer)
12861     (clear-stream _test-output-stream)
12862     (clear-stream $_test-output-buffered-file->buffer)
12863     (clear-stream _test-error-stream)
12864     (clear-stream $_test-error-buffered-file->buffer)
12865     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12866     68/push 0/imm32
12867     68/push 0/imm32
12868     89/<- %edx 4/r32/esp
12869     (tailor-exit-descriptor %edx 0x10)
12870     #
12871     (write _test-input-stream "fn foo {\n")
12872     (write _test-input-stream "  var a: (addr stream int)\n")
12873     (write _test-input-stream "  var b: (addr int)\n")
12874     (write _test-input-stream "  read-from-stream a, b, 0\n")
12875     (write _test-input-stream "}\n")
12876     # convert
12877     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12878     # registers except esp clobbered at this point
12879     # restore ed
12880     89/<- %edx 4/r32/esp
12881     (flush _test-output-buffered-file)
12882     (flush _test-error-buffered-file)
12883 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12889     # check output
12890     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-too-many-inouts: output should be empty")
12891     (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")
12892     # check that stop(1) was called
12893     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-too-many-inouts: exit status")
12894     # don't restore from ebp
12895     81 0/subop/add %esp 8/imm32
12896     # . epilogue
12897     5d/pop-to-ebp
12898     c3/return
12899 
12900 test-read-from-stream-with-output:
12901     # . prologue
12902     55/push-ebp
12903     89/<- %ebp 4/r32/esp
12904     # setup
12905     (clear-stream _test-input-stream)
12906     (clear-stream $_test-input-buffered-file->buffer)
12907     (clear-stream _test-output-stream)
12908     (clear-stream $_test-output-buffered-file->buffer)
12909     (clear-stream _test-error-stream)
12910     (clear-stream $_test-error-buffered-file->buffer)
12911     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12912     68/push 0/imm32
12913     68/push 0/imm32
12914     89/<- %edx 4/r32/esp
12915     (tailor-exit-descriptor %edx 0x10)
12916     #
12917     (write _test-input-stream "fn foo {\n")
12918     (write _test-input-stream "  var a: (addr stream int)\n")
12919     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
12920     (write _test-input-stream "  b <- read-from-stream a, b\n")
12921     (write _test-input-stream "}\n")
12922     # convert
12923     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12924     # registers except esp clobbered at this point
12925     # restore ed
12926     89/<- %edx 4/r32/esp
12927     (flush _test-output-buffered-file)
12928     (flush _test-error-buffered-file)
12929 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12935     # check output
12936     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-output: output should be empty")
12937     (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")
12938     # check that stop(1) was called
12939     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-output: exit status")
12940     # don't restore from ebp
12941     81 0/subop/add %esp 8/imm32
12942     # . epilogue
12943     5d/pop-to-ebp
12944     c3/return
12945 
12946 test-convert-write-to-stream:
12947     # . prologue
12948     55/push-ebp
12949     89/<- %ebp 4/r32/esp
12950     # setup
12951     (clear-stream _test-input-stream)
12952     (clear-stream $_test-input-buffered-file->buffer)
12953     (clear-stream _test-output-stream)
12954     (clear-stream $_test-output-buffered-file->buffer)
12955     #
12956     (write _test-input-stream "fn foo {\n")
12957     (write _test-input-stream "  var s/esi: (addr stream int) <- copy 0\n")
12958     (write _test-input-stream "  var o/ecx: (addr int) <- copy 0\n")
12959     (write _test-input-stream "  write-to-stream s, o\n")
12960     (write _test-input-stream "}\n")
12961     # convert
12962     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
12963     # registers except esp clobbered at this point
12964     # restore ed
12965     89/<- %edx 4/r32/esp
12966     (flush _test-output-buffered-file)
12967     (flush _test-error-buffered-file)
12968 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
12974     # check output
12975     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-write-to-stream/0")
12976     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-write-to-stream/1")
12977     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-write-to-stream/2")
12978     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-write-to-stream/3")
12979     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-write-to-stream/4")
12980     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-write-to-stream/5")
12981     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-write-to-stream/6")
12982     (check-next-stream-line-equal _test-output-stream "    be/copy-to-esi 0/imm32"      "F - test-convert-write-to-stream/7")
12983     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-write-to-stream/8")
12984     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"      "F - test-convert-write-to-stream/9")
12985     (check-next-stream-line-equal _test-output-stream "    (write-to-stream %esi %ecx 0x00000004)"  "F - test-convert-write-to-stream/10")
12986     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-write-to-stream/11")
12987     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-write-to-stream/12")
12988     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-write-to-stream/13")
12989     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-write-to-stream/14")
12990     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-write-to-stream/15")
12991     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-write-to-stream/16")
12992     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-write-to-stream/17")
12993     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-write-to-stream/18")
12994     # . epilogue
12995     89/<- %esp 5/r32/ebp
12996     5d/pop-to-ebp
12997     c3/return
12998 
12999 test-convert-write-to-stream-with-correct-payload-size:
13000     # . prologue
13001     55/push-ebp
13002     89/<- %ebp 4/r32/esp
13003     # setup
13004     (clear-stream _test-input-stream)
13005     (clear-stream $_test-input-buffered-file->buffer)
13006     (clear-stream _test-output-stream)
13007     (clear-stream $_test-output-buffered-file->buffer)
13008     #
13009     (write _test-input-stream "fn foo {\n")
13010     (write _test-input-stream "  var s/esi: (addr stream handle int) <- copy 0\n")
13011     (write _test-input-stream "  var o/ecx: (addr handle int) <- copy 0\n")
13012     (write _test-input-stream "  write-to-stream s, o\n")
13013     (write _test-input-stream "}\n")
13014     # convert
13015     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
13016     # registers except esp clobbered at this point
13017     # restore ed
13018     89/<- %edx 4/r32/esp
13019     (flush _test-output-buffered-file)
13020     (flush _test-error-buffered-file)
13021 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
13027     # check output
13028     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-write-to-stream-with-correct-payload-size/0")
13029     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-write-to-stream-with-correct-payload-size/1")
13030     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-write-to-stream-with-correct-payload-size/2")
13031     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-write-to-stream-with-correct-payload-size/3")
13032     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-write-to-stream-with-correct-payload-size/4")
13033     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-write-to-stream-with-correct-payload-size/5")
13034     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-write-to-stream-with-correct-payload-size/6")
13035     (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")
13036     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-write-to-stream-with-correct-payload-size/8")
13037     (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")
13038     (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")
13039     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-write-to-stream-with-correct-payload-size/11")
13040     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-write-to-stream-with-correct-payload-size/12")
13041     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-write-to-stream-with-correct-payload-size/13")
13042     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-write-to-stream-with-correct-payload-size/14")
13043     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-write-to-stream-with-correct-payload-size/15")
13044     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-write-to-stream-with-correct-payload-size/16")
13045     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-write-to-stream-with-correct-payload-size/17")
13046     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-write-to-stream-with-correct-payload-size/18")
13047     # . epilogue
13048     89/<- %esp 5/r32/ebp
13049     5d/pop-to-ebp
13050     c3/return
13051 
13052 test-write-to-stream-with-non-stream-atom-base-type:
13053     # . prologue
13054     55/push-ebp
13055     89/<- %ebp 4/r32/esp
13056     # setup
13057     (clear-stream _test-input-stream)
13058     (clear-stream $_test-input-buffered-file->buffer)
13059     (clear-stream _test-output-stream)
13060     (clear-stream $_test-output-buffered-file->buffer)
13061     (clear-stream _test-error-stream)
13062     (clear-stream $_test-error-buffered-file->buffer)
13063     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13064     68/push 0/imm32
13065     68/push 0/imm32
13066     89/<- %edx 4/r32/esp
13067     (tailor-exit-descriptor %edx 0x10)
13068     #
13069     (write _test-input-stream "fn foo {\n")
13070     (write _test-input-stream "  var a: int\n")
13071     (write _test-input-stream "  write-to-stream a, 0\n")
13072     (write _test-input-stream "}\n")
13073     # convert
13074     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13075     # registers except esp clobbered at this point
13076     # restore ed
13077     89/<- %edx 4/r32/esp
13078     (flush _test-output-buffered-file)
13079     (flush _test-error-buffered-file)
13080 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13086     # check output
13087     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-atom-base-type: output should be empty")
13088     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: var 'a' must be an addr to a stream"  "F - test-write-to-stream-with-non-stream-atom-base-type: error message")
13089     # check that stop(1) was called
13090     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-atom-base-type: exit status")
13091     # don't restore from ebp
13092     81 0/subop/add %esp 8/imm32
13093     # . epilogue
13094     5d/pop-to-ebp
13095     c3/return
13096 
13097 test-write-to-stream-with-non-stream-compound-base-type:
13098     # . prologue
13099     55/push-ebp
13100     89/<- %ebp 4/r32/esp
13101     # setup
13102     (clear-stream _test-input-stream)
13103     (clear-stream $_test-input-buffered-file->buffer)
13104     (clear-stream _test-output-stream)
13105     (clear-stream $_test-output-buffered-file->buffer)
13106     (clear-stream _test-error-stream)
13107     (clear-stream $_test-error-buffered-file->buffer)
13108     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13109     68/push 0/imm32
13110     68/push 0/imm32
13111     89/<- %edx 4/r32/esp
13112     (tailor-exit-descriptor %edx 0x10)
13113     #
13114     (write _test-input-stream "fn foo {\n")
13115     (write _test-input-stream "  var a: (handle int)\n")
13116     (write _test-input-stream "  write-to-stream a, 0\n")
13117     (write _test-input-stream "}\n")
13118     # convert
13119     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13120     # registers except esp clobbered at this point
13121     # restore ed
13122     89/<- %edx 4/r32/esp
13123     (flush _test-output-buffered-file)
13124     (flush _test-error-buffered-file)
13125 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13131     # check output
13132     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-compound-base-type: output should be empty")
13133     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: var 'a' must be an addr to a stream"  "F - test-write-to-stream-with-non-stream-compound-base-type: error message")
13134     # check that stop(1) was called
13135     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-compound-base-type: exit status")
13136     # don't restore from ebp
13137     81 0/subop/add %esp 8/imm32
13138     # . epilogue
13139     5d/pop-to-ebp
13140     c3/return
13141 
13142 test-write-to-stream-with-non-stream-compound-base-type-2:
13143     # . prologue
13144     55/push-ebp
13145     89/<- %ebp 4/r32/esp
13146     # setup
13147     (clear-stream _test-input-stream)
13148     (clear-stream $_test-input-buffered-file->buffer)
13149     (clear-stream _test-output-stream)
13150     (clear-stream $_test-output-buffered-file->buffer)
13151     (clear-stream _test-error-stream)
13152     (clear-stream $_test-error-buffered-file->buffer)
13153     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13154     68/push 0/imm32
13155     68/push 0/imm32
13156     89/<- %edx 4/r32/esp
13157     (tailor-exit-descriptor %edx 0x10)
13158     #
13159     (write _test-input-stream "fn foo {\n")
13160     (write _test-input-stream "  var a: (addr int)\n")
13161     (write _test-input-stream "  write-to-stream a, 0\n")
13162     (write _test-input-stream "}\n")
13163     # convert
13164     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13165     # registers except esp clobbered at this point
13166     # restore ed
13167     89/<- %edx 4/r32/esp
13168     (flush _test-output-buffered-file)
13169     (flush _test-error-buffered-file)
13170 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13176     # check output
13177     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-compound-base-type-2: output should be empty")
13178     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: var 'a' must be an addr to a stream"  "F - test-write-to-stream-with-non-stream-compound-base-type-2: error message")
13179     # check that stop(1) was called
13180     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-compound-base-type-2: exit status")
13181     # don't restore from ebp
13182     81 0/subop/add %esp 8/imm32
13183     # . epilogue
13184     5d/pop-to-ebp
13185     c3/return
13186 
13187 test-write-to-stream-with-stream-atom-base-type:
13188     # . prologue
13189     55/push-ebp
13190     89/<- %ebp 4/r32/esp
13191     # setup
13192     (clear-stream _test-input-stream)
13193     (clear-stream $_test-input-buffered-file->buffer)
13194     (clear-stream _test-output-stream)
13195     (clear-stream $_test-output-buffered-file->buffer)
13196     (clear-stream _test-error-stream)
13197     (clear-stream $_test-error-buffered-file->buffer)
13198     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13199     68/push 0/imm32
13200     68/push 0/imm32
13201     89/<- %edx 4/r32/esp
13202     (tailor-exit-descriptor %edx 0x10)
13203     #
13204     (write _test-input-stream "fn foo {\n")
13205     (write _test-input-stream "  var a: stream\n")
13206     (write _test-input-stream "  write-to-stream a, 0\n")
13207     (write _test-input-stream "}\n")
13208     # convert
13209     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13210     # registers except esp clobbered at this point
13211     # restore ed
13212     89/<- %edx 4/r32/esp
13213     (flush _test-output-buffered-file)
13214     (flush _test-error-buffered-file)
13215 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13221     # check output
13222     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-stream-atom-base-type: output should be empty")
13223     (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")
13224     # check that stop(1) was called
13225     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-stream-atom-base-type: exit status")
13226     # don't restore from ebp
13227     81 0/subop/add %esp 8/imm32
13228     # . epilogue
13229     5d/pop-to-ebp
13230     c3/return
13231 
13232 test-write-to-stream-with-wrong-index-type:
13233     # . prologue
13234     55/push-ebp
13235     89/<- %ebp 4/r32/esp
13236     # setup
13237     (clear-stream _test-input-stream)
13238     (clear-stream $_test-input-buffered-file->buffer)
13239     (clear-stream _test-output-stream)
13240     (clear-stream $_test-output-buffered-file->buffer)
13241     (clear-stream _test-error-stream)
13242     (clear-stream $_test-error-buffered-file->buffer)
13243     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13244     68/push 0/imm32
13245     68/push 0/imm32
13246     89/<- %edx 4/r32/esp
13247     (tailor-exit-descriptor %edx 0x10)
13248     #
13249     (write _test-input-stream "fn foo {\n")
13250     (write _test-input-stream "  var a/eax: (addr stream int) <- copy 0\n")
13251     (write _test-input-stream "  var b: boolean\n")
13252     (write _test-input-stream "  write-to-stream a, b\n")
13253     (write _test-input-stream "}\n")
13254     # convert
13255     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13256     # registers except esp clobbered at this point
13257     # restore ed
13258     89/<- %edx 4/r32/esp
13259     (flush _test-output-buffered-file)
13260     (flush _test-error-buffered-file)
13261 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13267     # check output
13268     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-wrong-index-type: output should be empty")
13269     (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")
13270     # check that stop(1) was called
13271     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-wrong-index-type: exit status")
13272     # don't restore from ebp
13273     81 0/subop/add %esp 8/imm32
13274     # . epilogue
13275     5d/pop-to-ebp
13276     c3/return
13277 
13278 test-write-to-stream-with-no-inouts:
13279     # . prologue
13280     55/push-ebp
13281     89/<- %ebp 4/r32/esp
13282     # setup
13283     (clear-stream _test-input-stream)
13284     (clear-stream $_test-input-buffered-file->buffer)
13285     (clear-stream _test-output-stream)
13286     (clear-stream $_test-output-buffered-file->buffer)
13287     (clear-stream _test-error-stream)
13288     (clear-stream $_test-error-buffered-file->buffer)
13289     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13290     68/push 0/imm32
13291     68/push 0/imm32
13292     89/<- %edx 4/r32/esp
13293     (tailor-exit-descriptor %edx 0x10)
13294     #
13295     (write _test-input-stream "fn foo {\n")
13296     (write _test-input-stream "  write-to-stream\n")
13297     (write _test-input-stream "}\n")
13298     # convert
13299     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13300     # registers except esp clobbered at this point
13301     # restore ed
13302     89/<- %edx 4/r32/esp
13303     (flush _test-output-buffered-file)
13304     (flush _test-error-buffered-file)
13305 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13311     # check output
13312     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-no-inouts: output should be empty")
13313     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: too few inouts (2 required)"  "F - test-write-to-stream-with-no-inouts: error message")
13314     # check that stop(1) was called
13315     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-no-inouts: exit status")
13316     # don't restore from ebp
13317     81 0/subop/add %esp 8/imm32
13318     # . epilogue
13319     5d/pop-to-ebp
13320     c3/return
13321 
13322 test-write-to-stream-with-too-few-inouts:
13323     # . prologue
13324     55/push-ebp
13325     89/<- %ebp 4/r32/esp
13326     # setup
13327     (clear-stream _test-input-stream)
13328     (clear-stream $_test-input-buffered-file->buffer)
13329     (clear-stream _test-output-stream)
13330     (clear-stream $_test-output-buffered-file->buffer)
13331     (clear-stream _test-error-stream)
13332     (clear-stream $_test-error-buffered-file->buffer)
13333     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13334     68/push 0/imm32
13335     68/push 0/imm32
13336     89/<- %edx 4/r32/esp
13337     (tailor-exit-descriptor %edx 0x10)
13338     #
13339     (write _test-input-stream "fn foo {\n")
13340     (write _test-input-stream "  var a: (addr stream int)\n")
13341     (write _test-input-stream "  write-to-stream a\n")
13342     (write _test-input-stream "}\n")
13343     # convert
13344     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13345     # registers except esp clobbered at this point
13346     # restore ed
13347     89/<- %edx 4/r32/esp
13348     (flush _test-output-buffered-file)
13349     (flush _test-error-buffered-file)
13350 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13356     # check output
13357     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-too-few-inouts: output should be empty")
13358     (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")
13359     # check that stop(1) was called
13360     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-too-few-inouts: exit status")
13361     # don't restore from ebp
13362     81 0/subop/add %esp 8/imm32
13363     # . epilogue
13364     5d/pop-to-ebp
13365     c3/return
13366 
13367 test-write-to-stream-with-too-many-inouts:
13368     # . prologue
13369     55/push-ebp
13370     89/<- %ebp 4/r32/esp
13371     # setup
13372     (clear-stream _test-input-stream)
13373     (clear-stream $_test-input-buffered-file->buffer)
13374     (clear-stream _test-output-stream)
13375     (clear-stream $_test-output-buffered-file->buffer)
13376     (clear-stream _test-error-stream)
13377     (clear-stream $_test-error-buffered-file->buffer)
13378     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13379     68/push 0/imm32
13380     68/push 0/imm32
13381     89/<- %edx 4/r32/esp
13382     (tailor-exit-descriptor %edx 0x10)
13383     #
13384     (write _test-input-stream "fn foo {\n")
13385     (write _test-input-stream "  var a: (addr stream int)\n")
13386     (write _test-input-stream "  var b: (addr int)\n")
13387     (write _test-input-stream "  write-to-stream a, b, 0\n")
13388     (write _test-input-stream "}\n")
13389     # convert
13390     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13391     # registers except esp clobbered at this point
13392     # restore ed
13393     89/<- %edx 4/r32/esp
13394     (flush _test-output-buffered-file)
13395     (flush _test-error-buffered-file)
13396 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13402     # check output
13403     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-too-many-inouts: output should be empty")
13404     (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")
13405     # check that stop(1) was called
13406     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-too-many-inouts: exit status")
13407     # don't restore from ebp
13408     81 0/subop/add %esp 8/imm32
13409     # . epilogue
13410     5d/pop-to-ebp
13411     c3/return
13412 
13413 test-write-to-stream-with-output:
13414     # . prologue
13415     55/push-ebp
13416     89/<- %ebp 4/r32/esp
13417     # setup
13418     (clear-stream _test-input-stream)
13419     (clear-stream $_test-input-buffered-file->buffer)
13420     (clear-stream _test-output-stream)
13421     (clear-stream $_test-output-buffered-file->buffer)
13422     (clear-stream _test-error-stream)
13423     (clear-stream $_test-error-buffered-file->buffer)
13424     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13425     68/push 0/imm32
13426     68/push 0/imm32
13427     89/<- %edx 4/r32/esp
13428     (tailor-exit-descriptor %edx 0x10)
13429     #
13430     (write _test-input-stream "fn foo {\n")
13431     (write _test-input-stream "  var a: (addr stream int)\n")
13432     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
13433     (write _test-input-stream "  b <- write-to-stream a, b\n")
13434     (write _test-input-stream "}\n")
13435     # convert
13436     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13437     # registers except esp clobbered at this point
13438     # restore ed
13439     89/<- %edx 4/r32/esp
13440     (flush _test-output-buffered-file)
13441     (flush _test-error-buffered-file)
13442 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13448     # check output
13449     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-output: output should be empty")
13450     (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")
13451     # check that stop(1) was called
13452     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-output: exit status")
13453     # don't restore from ebp
13454     81 0/subop/add %esp 8/imm32
13455     # . epilogue
13456     5d/pop-to-ebp
13457     c3/return
13458 
13459 test-length-with-non-array-atom-base-type:
13460     # . prologue
13461     55/push-ebp
13462     89/<- %ebp 4/r32/esp
13463     # setup
13464     (clear-stream _test-input-stream)
13465     (clear-stream $_test-input-buffered-file->buffer)
13466     (clear-stream _test-output-stream)
13467     (clear-stream $_test-output-buffered-file->buffer)
13468     (clear-stream _test-error-stream)
13469     (clear-stream $_test-error-buffered-file->buffer)
13470     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13471     68/push 0/imm32
13472     68/push 0/imm32
13473     89/<- %edx 4/r32/esp
13474     (tailor-exit-descriptor %edx 0x10)
13475     #
13476     (write _test-input-stream "fn foo {\n")
13477     (write _test-input-stream "  var a: int\n")
13478     (write _test-input-stream "  var c/ecx: int <- length a\n")
13479     (write _test-input-stream "}\n")
13480     # convert
13481     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13482     # registers except esp clobbered at this point
13483     # restore ed
13484     89/<- %edx 4/r32/esp
13485     (flush _test-output-buffered-file)
13486     (flush _test-error-buffered-file)
13487 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13493     # check output
13494     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-atom-base-type: output should be empty")
13495     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: var 'a' is not an array"  "F - test-length-with-non-array-atom-base-type: error message")
13496     # check that stop(1) was called
13497     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-atom-base-type: exit status")
13498     # don't restore from ebp
13499     81 0/subop/add %esp 8/imm32
13500     # . epilogue
13501     5d/pop-to-ebp
13502     c3/return
13503 
13504 test-length-with-non-array-compound-base-type:
13505     # . prologue
13506     55/push-ebp
13507     89/<- %ebp 4/r32/esp
13508     # setup
13509     (clear-stream _test-input-stream)
13510     (clear-stream $_test-input-buffered-file->buffer)
13511     (clear-stream _test-output-stream)
13512     (clear-stream $_test-output-buffered-file->buffer)
13513     (clear-stream _test-error-stream)
13514     (clear-stream $_test-error-buffered-file->buffer)
13515     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13516     68/push 0/imm32
13517     68/push 0/imm32
13518     89/<- %edx 4/r32/esp
13519     (tailor-exit-descriptor %edx 0x10)
13520     #
13521     (write _test-input-stream "fn foo {\n")
13522     (write _test-input-stream "  var a: (handle int)\n")
13523     (write _test-input-stream "  var c/ecx: (addr int) <- length a, 0\n")
13524     (write _test-input-stream "}\n")
13525     # convert
13526     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13527     # registers except esp clobbered at this point
13528     # restore ed
13529     89/<- %edx 4/r32/esp
13530     (flush _test-output-buffered-file)
13531     (flush _test-error-buffered-file)
13532 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13538     # check output
13539     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-compound-base-type: output should be empty")
13540     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: var 'a' is not an array"  "F - test-length-with-non-array-compound-base-type: error message")
13541     # check that stop(1) was called
13542     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-compound-base-type: exit status")
13543     # don't restore from ebp
13544     81 0/subop/add %esp 8/imm32
13545     # . epilogue
13546     5d/pop-to-ebp
13547     c3/return
13548 
13549 test-length-with-non-array-compound-base-type-2:
13550     # . prologue
13551     55/push-ebp
13552     89/<- %ebp 4/r32/esp
13553     # setup
13554     (clear-stream _test-input-stream)
13555     (clear-stream $_test-input-buffered-file->buffer)
13556     (clear-stream _test-output-stream)
13557     (clear-stream $_test-output-buffered-file->buffer)
13558     (clear-stream _test-error-stream)
13559     (clear-stream $_test-error-buffered-file->buffer)
13560     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13561     68/push 0/imm32
13562     68/push 0/imm32
13563     89/<- %edx 4/r32/esp
13564     (tailor-exit-descriptor %edx 0x10)
13565     #
13566     (write _test-input-stream "fn foo {\n")
13567     (write _test-input-stream "  var a: (addr int)\n")
13568     (write _test-input-stream "  var c/ecx: (addr int) <- length a, 0\n")
13569     (write _test-input-stream "}\n")
13570     # convert
13571     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13572     # registers except esp clobbered at this point
13573     # restore ed
13574     89/<- %edx 4/r32/esp
13575     (flush _test-output-buffered-file)
13576     (flush _test-error-buffered-file)
13577 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13583     # check output
13584     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-compound-base-type-2: output should be empty")
13585     (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")
13586     # check that stop(1) was called
13587     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-compound-base-type-2: exit status")
13588     # don't restore from ebp
13589     81 0/subop/add %esp 8/imm32
13590     # . epilogue
13591     5d/pop-to-ebp
13592     c3/return
13593 
13594 test-length-with-array-atom-base-type:
13595     # . prologue
13596     55/push-ebp
13597     89/<- %ebp 4/r32/esp
13598     # setup
13599     (clear-stream _test-input-stream)
13600     (clear-stream $_test-input-buffered-file->buffer)
13601     (clear-stream _test-output-stream)
13602     (clear-stream $_test-output-buffered-file->buffer)
13603     (clear-stream _test-error-stream)
13604     (clear-stream $_test-error-buffered-file->buffer)
13605     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13606     68/push 0/imm32
13607     68/push 0/imm32
13608     89/<- %edx 4/r32/esp
13609     (tailor-exit-descriptor %edx 0x10)
13610     #
13611     (write _test-input-stream "fn foo {\n")
13612     (write _test-input-stream "  var a: array\n")
13613     (write _test-input-stream "  var c/ecx: (addr int) <- length a\n")
13614     (write _test-input-stream "}\n")
13615     # convert
13616     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13617     # registers except esp clobbered at this point
13618     # restore ed
13619     89/<- %edx 4/r32/esp
13620     (flush _test-output-buffered-file)
13621     (flush _test-error-buffered-file)
13622 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13628     # check output
13629     (check-stream-equal _test-output-stream  ""  "F - test-length-with-array-atom-base-type: output should be empty")
13630     (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")
13631     # check that stop(1) was called
13632     (check-ints-equal *(edx+4) 2 "F - test-length-with-array-atom-base-type: exit status")
13633     # don't restore from ebp
13634     81 0/subop/add %esp 8/imm32
13635     # . epilogue
13636     5d/pop-to-ebp
13637     c3/return
13638 
13639 test-length-with-addr-base-on-stack:
13640     # . prologue
13641     55/push-ebp
13642     89/<- %ebp 4/r32/esp
13643     # setup
13644     (clear-stream _test-input-stream)
13645     (clear-stream $_test-input-buffered-file->buffer)
13646     (clear-stream _test-output-stream)
13647     (clear-stream $_test-output-buffered-file->buffer)
13648     (clear-stream _test-error-stream)
13649     (clear-stream $_test-error-buffered-file->buffer)
13650     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13651     68/push 0/imm32
13652     68/push 0/imm32
13653     89/<- %edx 4/r32/esp
13654     (tailor-exit-descriptor %edx 0x10)
13655     #
13656     (write _test-input-stream "fn foo {\n")
13657     (write _test-input-stream "  var a: (addr array int)\n")
13658     (write _test-input-stream "  var c/ecx: (addr int) <- length a\n")
13659     (write _test-input-stream "}\n")
13660     # convert
13661     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13662     # registers except esp clobbered at this point
13663     # restore ed
13664     89/<- %edx 4/r32/esp
13665     (flush _test-output-buffered-file)
13666     (flush _test-error-buffered-file)
13667 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13673     # check output
13674     (check-stream-equal _test-output-stream  ""  "F - test-length-with-addr-base-on-stack: output should be empty")
13675     (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")
13676     # check that stop(1) was called
13677     (check-ints-equal *(edx+4) 2 "F - test-length-with-addr-base-on-stack: exit status")
13678     # don't restore from ebp
13679     81 0/subop/add %esp 8/imm32
13680     # . epilogue
13681     5d/pop-to-ebp
13682     c3/return
13683 
13684 test-length-with-wrong-output-type:
13685     # . prologue
13686     55/push-ebp
13687     89/<- %ebp 4/r32/esp
13688     # setup
13689     (clear-stream _test-input-stream)
13690     (clear-stream $_test-input-buffered-file->buffer)
13691     (clear-stream _test-output-stream)
13692     (clear-stream $_test-output-buffered-file->buffer)
13693     (clear-stream _test-error-stream)
13694     (clear-stream $_test-error-buffered-file->buffer)
13695     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13696     68/push 0/imm32
13697     68/push 0/imm32
13698     89/<- %edx 4/r32/esp
13699     (tailor-exit-descriptor %edx 0x10)
13700     #
13701     (write _test-input-stream "fn foo {\n")
13702     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
13703     (write _test-input-stream "  var o/edi: (addr int) <- length a\n")
13704     (write _test-input-stream "}\n")
13705     # convert
13706     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13707     # registers except esp clobbered at this point
13708     # restore ed
13709     89/<- %edx 4/r32/esp
13710     (flush _test-output-buffered-file)
13711     (flush _test-error-buffered-file)
13712 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13718     # check output
13719     (check-stream-equal _test-output-stream  ""  "F - test-length-with-wrong-output-type: output should be empty")
13720     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: output 'o' does not have the right type"  "F - test-length-with-wrong-output-type: error message")
13721     # check that stop(1) was called
13722     (check-ints-equal *(edx+4) 2 "F - test-length-with-wrong-output-type: exit status")
13723     # don't restore from ebp
13724     81 0/subop/add %esp 8/imm32
13725     # . epilogue
13726     5d/pop-to-ebp
13727     c3/return
13728 
13729 test-length-with-wrong-output-compound-type:
13730     # . prologue
13731     55/push-ebp
13732     89/<- %ebp 4/r32/esp
13733     # setup
13734     (clear-stream _test-input-stream)
13735     (clear-stream $_test-input-buffered-file->buffer)
13736     (clear-stream _test-output-stream)
13737     (clear-stream $_test-output-buffered-file->buffer)
13738     (clear-stream _test-error-stream)
13739     (clear-stream $_test-error-buffered-file->buffer)
13740     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13741     68/push 0/imm32
13742     68/push 0/imm32
13743     89/<- %edx 4/r32/esp
13744     (tailor-exit-descriptor %edx 0x10)
13745     #
13746     (write _test-input-stream "fn foo {\n")
13747     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
13748     (write _test-input-stream "  var o/edi: (addr handle int) <- length a\n")
13749     (write _test-input-stream "}\n")
13750     # convert
13751     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13752     # registers except esp clobbered at this point
13753     # restore ed
13754     89/<- %edx 4/r32/esp
13755     (flush _test-output-buffered-file)
13756     (flush _test-error-buffered-file)
13757 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13763     # check output
13764     (check-stream-equal _test-output-stream  ""  "F - test-length-with-wrong-output-compound-type: output should be empty")
13765     (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")
13766     # check that stop(1) was called
13767     (check-ints-equal *(edx+4) 2 "F - test-length-with-wrong-output-compound-type: exit status")
13768     # don't restore from ebp
13769     81 0/subop/add %esp 8/imm32
13770     # . epilogue
13771     5d/pop-to-ebp
13772     c3/return
13773 
13774 test-length-with-no-inouts:
13775     # . prologue
13776     55/push-ebp
13777     89/<- %ebp 4/r32/esp
13778     # setup
13779     (clear-stream _test-input-stream)
13780     (clear-stream $_test-input-buffered-file->buffer)
13781     (clear-stream _test-output-stream)
13782     (clear-stream $_test-output-buffered-file->buffer)
13783     (clear-stream _test-error-stream)
13784     (clear-stream $_test-error-buffered-file->buffer)
13785     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13786     68/push 0/imm32
13787     68/push 0/imm32
13788     89/<- %edx 4/r32/esp
13789     (tailor-exit-descriptor %edx 0x10)
13790     #
13791     (write _test-input-stream "fn foo {\n")
13792     (write _test-input-stream "  var c/ecx: int <- length\n")
13793     (write _test-input-stream "}\n")
13794     # convert
13795     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13796     # registers except esp clobbered at this point
13797     # restore ed
13798     89/<- %edx 4/r32/esp
13799     (flush _test-output-buffered-file)
13800     (flush _test-error-buffered-file)
13801 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13807     # check output
13808     (check-stream-equal _test-output-stream  ""  "F - test-length-with-no-inouts: output should be empty")
13809     (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")
13810     # check that stop(1) was called
13811     (check-ints-equal *(edx+4) 2 "F - test-length-with-no-inouts: exit status")
13812     # don't restore from ebp
13813     81 0/subop/add %esp 8/imm32
13814     # . epilogue
13815     5d/pop-to-ebp
13816     c3/return
13817 
13818 test-length-with-too-many-inouts:
13819     # . prologue
13820     55/push-ebp
13821     89/<- %ebp 4/r32/esp
13822     # setup
13823     (clear-stream _test-input-stream)
13824     (clear-stream $_test-input-buffered-file->buffer)
13825     (clear-stream _test-output-stream)
13826     (clear-stream $_test-output-buffered-file->buffer)
13827     (clear-stream _test-error-stream)
13828     (clear-stream $_test-error-buffered-file->buffer)
13829     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13830     68/push 0/imm32
13831     68/push 0/imm32
13832     89/<- %edx 4/r32/esp
13833     (tailor-exit-descriptor %edx 0x10)
13834     #
13835     (write _test-input-stream "fn foo {\n")
13836     (write _test-input-stream "  var a: (array int 3)\n")
13837     (write _test-input-stream "  var c/ecx: int <- length a, 0, 0\n")
13838     (write _test-input-stream "}\n")
13839     # convert
13840     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13841     # registers except esp clobbered at this point
13842     # restore ed
13843     89/<- %edx 4/r32/esp
13844     (flush _test-output-buffered-file)
13845     (flush _test-error-buffered-file)
13846 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13852     # check output
13853     (check-stream-equal _test-output-stream  ""  "F - test-length-with-too-many-inouts: output should be empty")
13854     (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")
13855     # check that stop(1) was called
13856     (check-ints-equal *(edx+4) 2 "F - test-length-with-too-many-inouts: exit status")
13857     # don't restore from ebp
13858     81 0/subop/add %esp 8/imm32
13859     # . epilogue
13860     5d/pop-to-ebp
13861     c3/return
13862 
13863 test-length-with-no-output:
13864     # . prologue
13865     55/push-ebp
13866     89/<- %ebp 4/r32/esp
13867     # setup
13868     (clear-stream _test-input-stream)
13869     (clear-stream $_test-input-buffered-file->buffer)
13870     (clear-stream _test-output-stream)
13871     (clear-stream $_test-output-buffered-file->buffer)
13872     (clear-stream _test-error-stream)
13873     (clear-stream $_test-error-buffered-file->buffer)
13874     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13875     68/push 0/imm32
13876     68/push 0/imm32
13877     89/<- %edx 4/r32/esp
13878     (tailor-exit-descriptor %edx 0x10)
13879     #
13880     (write _test-input-stream "fn foo {\n")
13881     (write _test-input-stream "  var a: (array int 3)\n")
13882     (write _test-input-stream "  length a\n")
13883     (write _test-input-stream "}\n")
13884     # convert
13885     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13886     # registers except esp clobbered at this point
13887     # restore ed
13888     89/<- %edx 4/r32/esp
13889     (flush _test-output-buffered-file)
13890     (flush _test-error-buffered-file)
13891 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13897     # check output
13898     (check-stream-equal _test-output-stream  ""  "F - test-length-with-no-output: output should be empty")
13899     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: must have an output"  "F - test-length-with-no-output: error message")
13900     # check that stop(1) was called
13901     (check-ints-equal *(edx+4) 2 "F - test-length-with-no-output: exit status")
13902     # don't restore from ebp
13903     81 0/subop/add %esp 8/imm32
13904     # . epilogue
13905     5d/pop-to-ebp
13906     c3/return
13907 
13908 test-length-with-too-many-outputs:
13909     # . prologue
13910     55/push-ebp
13911     89/<- %ebp 4/r32/esp
13912     # setup
13913     (clear-stream _test-input-stream)
13914     (clear-stream $_test-input-buffered-file->buffer)
13915     (clear-stream _test-output-stream)
13916     (clear-stream $_test-output-buffered-file->buffer)
13917     (clear-stream _test-error-stream)
13918     (clear-stream $_test-error-buffered-file->buffer)
13919     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13920     68/push 0/imm32
13921     68/push 0/imm32
13922     89/<- %edx 4/r32/esp
13923     (tailor-exit-descriptor %edx 0x10)
13924     #
13925     (write _test-input-stream "fn foo {\n")
13926     (write _test-input-stream "  var a: (array int 3)\n")
13927     (write _test-input-stream "  var b/eax: int <- copy 0\n")
13928     (write _test-input-stream "  var c/ecx: int <- copy 0\n")
13929     (write _test-input-stream "  b, c <- length a\n")
13930     (write _test-input-stream "}\n")
13931     # convert
13932     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13933     # registers except esp clobbered at this point
13934     # restore ed
13935     89/<- %edx 4/r32/esp
13936     (flush _test-output-buffered-file)
13937     (flush _test-error-buffered-file)
13938 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13944     # check output
13945     (check-stream-equal _test-output-stream  ""  "F - test-length-with-too-many-outputs: output should be empty")
13946     (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")
13947     # check that stop(1) was called
13948     (check-ints-equal *(edx+4) 2 "F - test-length-with-too-many-outputs: exit status")
13949     # don't restore from ebp
13950     81 0/subop/add %esp 8/imm32
13951     # . epilogue
13952     5d/pop-to-ebp
13953     c3/return
13954 
13955 test-convert-function-with-return-register-and-local:
13956     # . prologue
13957     55/push-ebp
13958     89/<- %ebp 4/r32/esp
13959     # setup
13960     (clear-stream _test-input-stream)
13961     (clear-stream $_test-input-buffered-file->buffer)
13962     (clear-stream _test-output-stream)
13963     (clear-stream $_test-output-buffered-file->buffer)
13964     #
13965     (write _test-input-stream "fn foo -> _/eax: int {\n")
13966     (write _test-input-stream "  var y/eax: int <- copy 3\n")
13967     (write _test-input-stream "  var z/ecx: int <- copy 4\n")
13968     (write _test-input-stream "  return y\n")
13969     (write _test-input-stream "}\n")
13970     # convert
13971     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
13972     (flush _test-output-buffered-file)
13973 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
13979     # check output
13980     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register-and-local/0")
13981     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register-and-local/1")
13982     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register-and-local/2")
13983     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register-and-local/3")
13984     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register-and-local/4")
13985     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register-and-local/5")
13986     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register-and-local/6")
13987     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-convert-function-with-return-register-and-local/7")
13988     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-return-register-and-local/8")
13989     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-convert-function-with-return-register-and-local/9")
13990     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-return-register-and-local/10")
13991     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-function-with-return-register-and-local/11")
13992     (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")
13993     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-register-and-local/13")
13994     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register-and-local/14")
13995     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register-and-local/15")
13996     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register-and-local/16")
13997     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register-and-local/17")
13998     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register-and-local/18")
13999     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register-and-local/19")
14000     # . epilogue
14001     89/<- %esp 5/r32/ebp
14002     5d/pop-to-ebp
14003     c3/return
14004 
14005 test-convert-function-with-return-register-and-local-2:
14006     # . prologue
14007     55/push-ebp
14008     89/<- %ebp 4/r32/esp
14009     # setup
14010     (clear-stream _test-input-stream)
14011     (clear-stream $_test-input-buffered-file->buffer)
14012     (clear-stream _test-output-stream)
14013     (clear-stream $_test-output-buffered-file->buffer)
14014     #
14015     (write _test-input-stream "fn foo -> _/eax: int {\n")
14016     (write _test-input-stream "  var y/eax: int <- copy 3\n")
14017     (write _test-input-stream "  var z/ecx: int <- copy 4\n")
14018     (write _test-input-stream "  return z\n")
14019     (write _test-input-stream "}\n")
14020     # convert
14021     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
14022     (flush _test-output-buffered-file)
14023 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
14029     # check output
14030     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register-and-local-2/0")
14031     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register-and-local-2/1")
14032     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register-and-local-2/2")
14033     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register-and-local-2/3")
14034     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register-and-local-2/4")
14035     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register-and-local-2/5")
14036     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register-and-local-2/6")
14037     (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")
14038     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-return-register-and-local-2/8")
14039     (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")
14040     (check-next-stream-line-equal _test-output-stream "    8b/-> %ecx 0x00000000/r32" "F - test-convert-function-with-return-register-and-local-2/10")
14041     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-function-with-return-register-and-local-2/11")
14042     (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")
14043     (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")
14044     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register-and-local-2/14")
14045     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register-and-local-2/15")
14046     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register-and-local-2/16")
14047     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register-and-local-2/17")
14048     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register-and-local-2/18")
14049     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register-and-local-2/19")
14050     # . epilogue
14051     89/<- %esp 5/r32/ebp
14052     5d/pop-to-ebp
14053     c3/return
14054 
14055 test-convert-function-with-return-float-register-and-local:
14056     # . prologue
14057     55/push-ebp
14058     89/<- %ebp 4/r32/esp
14059     # setup
14060     (clear-stream _test-input-stream)
14061     (clear-stream $_test-input-buffered-file->buffer)
14062     (clear-stream _test-output-stream)
14063     (clear-stream $_test-output-buffered-file->buffer)
14064     #
14065     (write _test-input-stream "fn foo -> _/xmm1: float {\n")
14066     (write _test-input-stream "  var y/eax: int <- copy 3\n")
14067     (write _test-input-stream "  var g/xmm0: float <- convert y\n")
14068     (write _test-input-stream "  var h/xmm1: float <- convert y\n")
14069     (write _test-input-stream "  return g\n")
14070     (write _test-input-stream "}\n")
14071     # convert
14072     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
14073     (flush _test-output-buffered-file)
14074 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
14080     # check output
14081     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-float-register-and-local/0")
14082     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-float-register-and-local/1")
14083     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-float-register-and-local/2")
14084     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-float-register-and-local/3")
14085     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-float-register-and-local/4")
14086     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-float-register-and-local/5")
14087     (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
14088     (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")
14089     (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
14090     (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")
14091     (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")
14092     (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
14093     (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")
14094     (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")
14095     (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
14096     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-floating-point-dereferenced/15")  # reclaim h
14097     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 0/x32"  "F - test-convert-floating-point-dereferenced/16")  # reclaim g
14098     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-floating-point-dereferenced/17")
14099     (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
14100     (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")
14101     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-float-register-and-local/20")
14102     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-float-register-and-local/21")
14103     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-float-register-and-local/22")
14104     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-float-register-and-local/23")
14105     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-float-register-and-local/24")
14106     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-float-register-and-local/25")
14107     # . epilogue
14108     89/<- %esp 5/r32/ebp
14109     5d/pop-to-ebp
14110     c3/return
14111 
14112 test-convert-function-with-return-and-local-vars:
14113     # . prologue
14114     55/push-ebp
14115     89/<- %ebp 4/r32/esp
14116     # setup
14117     (clear-stream _test-input-stream)
14118     (clear-stream $_test-input-buffered-file->buffer)
14119     (clear-stream _test-output-stream)
14120     (clear-stream $_test-output-buffered-file->buffer)
14121     #
14122     (write _test-input-stream "fn foo -> _/eax: int {\n")
14123     (write _test-input-stream "  {\n")
14124     (write _test-input-stream "    var x: int\n")
14125     (write _test-input-stream "    {\n")
14126     (write _test-input-stream "      var y: int\n")
14127     (write _test-input-stream "      return y\n")
14128     (write _test-input-stream "      increment x\n")
14129     (write _test-input-stream "    }\n")
14130     (write _test-input-stream "  }\n")
14131     (write _test-input-stream "  return 0\n")
14132     (write _test-input-stream "}\n")
14133     # convert
14134     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
14135     (flush _test-output-buffered-file)
14136 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
14142     # check output
14143     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-and-local-vars/0")
14144     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-and-local-vars/1")
14145     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-and-local-vars/2")
14146     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-and-local-vars/3")
14147     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-and-local-vars/4")
14148     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-and-local-vars/5")
14149     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-return-and-local-vars/6")
14150     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-return-and-local-vars/7")
14151     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-return-and-local-vars/8")  # var x
14152     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-return-and-local-vars/9")
14153     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-return-and-local-vars/10")
14154     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-return-and-local-vars/11")  # var y
14155     (check-next-stream-line-equal _test-output-stream "        8b/-> *(ebp+0xfffffff8) 0x00000000/r32" "F - test-convert-function-with-return-and-local-vars/12")
14156     (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")
14157     (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")
14158     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-and-local-vars/15")
14159     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-return-and-local-vars/16")
14160     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-return-and-local-vars/17")
14161     (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")
14162     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-return-and-local-vars/19")
14163     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-return-and-local-vars/20")
14164     (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")
14165     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-and-local-vars/21")
14166     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-and-local-vars/21")
14167     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-and-local-vars/22")
14168     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-and-local-vars/23")
14169     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-and-local-vars/24")
14170     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-and-local-vars/25")
14171     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-and-local-vars/26")
14172     # . epilogue
14173     89/<- %esp 5/r32/ebp
14174     5d/pop-to-ebp
14175     c3/return
14176 
14177 test-copy-object-with-no-inout:
14178     # . prologue
14179     55/push-ebp
14180     89/<- %ebp 4/r32/esp
14181     # setup
14182     (clear-stream _test-input-stream)
14183     (clear-stream $_test-input-buffered-file->buffer)
14184     (clear-stream _test-output-stream)
14185     (clear-stream $_test-output-buffered-file->buffer)
14186     (clear-stream _test-error-stream)
14187     (clear-stream $_test-error-buffered-file->buffer)
14188     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14189     68/push 0/imm32
14190     68/push 0/imm32
14191     89/<- %edx 4/r32/esp
14192     (tailor-exit-descriptor %edx 0x10)
14193     #
14194     (write _test-input-stream "fn foo {\n")
14195     (write _test-input-stream "  copy-object\n")
14196     (write _test-input-stream "}\n")
14197     # convert
14198     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14199     # registers except esp clobbered at this point
14200     # restore ed
14201     89/<- %edx 4/r32/esp
14202     (flush _test-output-buffered-file)
14203     (flush _test-error-buffered-file)
14204 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14210     # check output
14211     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-no-inout: output should be empty")
14212     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-object' must have two inouts"  "F - test-copy-object-with-no-inout: error message")
14213     # check that stop(1) was called
14214     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-no-inout: exit status")
14215     # don't restore from ebp
14216     81 0/subop/add %esp 8/imm32
14217     # . epilogue
14218     5d/pop-to-ebp
14219     c3/return
14220 
14221 test-copy-object-with-no-source:
14222     # . prologue
14223     55/push-ebp
14224     89/<- %ebp 4/r32/esp
14225     # setup
14226     (clear-stream _test-input-stream)
14227     (clear-stream $_test-input-buffered-file->buffer)
14228     (clear-stream _test-output-stream)
14229     (clear-stream $_test-output-buffered-file->buffer)
14230     (clear-stream _test-error-stream)
14231     (clear-stream $_test-error-buffered-file->buffer)
14232     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14233     68/push 0/imm32
14234     68/push 0/imm32
14235     89/<- %edx 4/r32/esp
14236     (tailor-exit-descriptor %edx 0x10)
14237     #
14238     (write _test-input-stream "fn foo {\n")
14239     (write _test-input-stream "  var x: (addr int)\n")
14240     (write _test-input-stream "  copy-object x\n")
14241     (write _test-input-stream "}\n")
14242     # convert
14243     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14244     # registers except esp clobbered at this point
14245     # restore ed
14246     89/<- %edx 4/r32/esp
14247     (flush _test-output-buffered-file)
14248     (flush _test-error-buffered-file)
14249 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14255     # check output
14256     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-no-source: output should be empty")
14257     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-object' must have two inouts"  "F - test-copy-object-with-no-source: error message")
14258     # check that stop(1) was called
14259     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-no-source: exit status")
14260     # don't restore from ebp
14261     81 0/subop/add %esp 8/imm32
14262     # . epilogue
14263     5d/pop-to-ebp
14264     c3/return
14265 
14266 test-copy-object-with-too-many-inouts:
14267     # . prologue
14268     55/push-ebp
14269     89/<- %ebp 4/r32/esp
14270     # setup
14271     (clear-stream _test-input-stream)
14272     (clear-stream $_test-input-buffered-file->buffer)
14273     (clear-stream _test-output-stream)
14274     (clear-stream $_test-output-buffered-file->buffer)
14275     (clear-stream _test-error-stream)
14276     (clear-stream $_test-error-buffered-file->buffer)
14277     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14278     68/push 0/imm32
14279     68/push 0/imm32
14280     89/<- %edx 4/r32/esp
14281     (tailor-exit-descriptor %edx 0x10)
14282     #
14283     (write _test-input-stream "fn foo {\n")
14284     (write _test-input-stream "  var x: (addr boolean)\n")
14285     (write _test-input-stream "  copy-object x, x, x\n")
14286     (write _test-input-stream "}\n")
14287     # convert
14288     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14289     # registers except esp clobbered at this point
14290     # restore ed
14291     89/<- %edx 4/r32/esp
14292     (flush _test-output-buffered-file)
14293     (flush _test-error-buffered-file)
14294 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14300     # check output
14301     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-too-many-inouts: output should be empty")
14302     (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")
14303     # check that stop(1) was called
14304     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-too-many-inouts: exit status")
14305     # don't restore from ebp
14306     81 0/subop/add %esp 8/imm32
14307     # . epilogue
14308     5d/pop-to-ebp
14309     c3/return
14310 
14311 test-copy-object-with-output:
14312     # . prologue
14313     55/push-ebp
14314     89/<- %ebp 4/r32/esp
14315     # setup
14316     (clear-stream _test-input-stream)
14317     (clear-stream $_test-input-buffered-file->buffer)
14318     (clear-stream _test-output-stream)
14319     (clear-stream $_test-output-buffered-file->buffer)
14320     (clear-stream _test-error-stream)
14321     (clear-stream $_test-error-buffered-file->buffer)
14322     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14323     68/push 0/imm32
14324     68/push 0/imm32
14325     89/<- %edx 4/r32/esp
14326     (tailor-exit-descriptor %edx 0x10)
14327     #
14328     (write _test-input-stream "fn foo {\n")
14329     (write _test-input-stream "  var x/eax: (addr boolean) <- copy 0\n")
14330     (write _test-input-stream "  var y/ecx: (addr boolean) <- copy 0\n")
14331     (write _test-input-stream "  x <- copy-object x, y\n")
14332     (write _test-input-stream "}\n")
14333     # convert
14334     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14335     # registers except esp clobbered at this point
14336     # restore ed
14337     89/<- %edx 4/r32/esp
14338     (flush _test-output-buffered-file)
14339     (flush _test-error-buffered-file)
14340 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14346     # check output
14347     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-output: output should be empty")
14348     (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")
14349     # check that stop(1) was called
14350     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-output: exit status")
14351     # don't restore from ebp
14352     81 0/subop/add %esp 8/imm32
14353     # . epilogue
14354     5d/pop-to-ebp
14355     c3/return
14356 
14357 test-copy-object-deref-address:
14358     # . prologue
14359     55/push-ebp
14360     89/<- %ebp 4/r32/esp
14361     # setup
14362     (clear-stream _test-input-stream)
14363     (clear-stream $_test-input-buffered-file->buffer)
14364     (clear-stream _test-output-stream)
14365     (clear-stream $_test-output-buffered-file->buffer)
14366     #
14367     (write _test-input-stream "fn foo {\n")
14368     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
14369     (write _test-input-stream "  var y/ecx: (addr addr int) <- copy 0\n")
14370     (write _test-input-stream "  copy-object *y, x\n")
14371     (write _test-input-stream "}\n")
14372     # convert
14373     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
14374     (flush _test-output-buffered-file)
14375     # no errors
14376     # . epilogue
14377     5d/pop-to-ebp
14378     c3/return
14379 
14380 test-copy-object-non-addr:
14381     # . prologue
14382     55/push-ebp
14383     89/<- %ebp 4/r32/esp
14384     # setup
14385     (clear-stream _test-input-stream)
14386     (clear-stream $_test-input-buffered-file->buffer)
14387     (clear-stream _test-output-stream)
14388     (clear-stream $_test-output-buffered-file->buffer)
14389     (clear-stream _test-error-stream)
14390     (clear-stream $_test-error-buffered-file->buffer)
14391     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14392     68/push 0/imm32
14393     68/push 0/imm32
14394     89/<- %edx 4/r32/esp
14395     (tailor-exit-descriptor %edx 0x10)
14396     #
14397     (write _test-input-stream "fn foo {\n")
14398     (write _test-input-stream "  var x: int\n")
14399     (write _test-input-stream "  var y: int\n")
14400     (write _test-input-stream "  copy-object y, x\n")
14401     (write _test-input-stream "}\n")
14402     # convert
14403     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14404     # registers except esp clobbered at this point
14405     # restore ed
14406     89/<- %edx 4/r32/esp
14407     (flush _test-output-buffered-file)
14408     (flush _test-error-buffered-file)
14409 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14415     # check output
14416     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-non-addr: output should be empty")
14417     (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")
14418     # check that stop(1) was called
14419     (check-ints-equal *(edx+4) 2 "F - test-copy-object-non-addr: exit status")
14420     # don't restore from ebp
14421     81 0/subop/add %esp 8/imm32
14422     # . epilogue
14423     5d/pop-to-ebp
14424     c3/return
14425 
14426 test-copy-object-non-equal:
14427     # . prologue
14428     55/push-ebp
14429     89/<- %ebp 4/r32/esp
14430     # setup
14431     (clear-stream _test-input-stream)
14432     (clear-stream $_test-input-buffered-file->buffer)
14433     (clear-stream _test-output-stream)
14434     (clear-stream $_test-output-buffered-file->buffer)
14435     (clear-stream _test-error-stream)
14436     (clear-stream $_test-error-buffered-file->buffer)
14437     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14438     68/push 0/imm32
14439     68/push 0/imm32
14440     89/<- %edx 4/r32/esp
14441     (tailor-exit-descriptor %edx 0x10)
14442     #
14443     (write _test-input-stream "fn foo {\n")
14444     (write _test-input-stream "  var x: (addr int)\n")
14445     (write _test-input-stream "  var y: (addr boolean)\n")
14446     (write _test-input-stream "  copy-object y, x\n")
14447     (write _test-input-stream "}\n")
14448     # convert
14449     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14450     # registers except esp clobbered at this point
14451     # restore ed
14452     89/<- %edx 4/r32/esp
14453     (flush _test-output-buffered-file)
14454     (flush _test-error-buffered-file)
14455 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14461     # check output
14462     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-non-equal: output should be empty")
14463     (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")
14464     # check that stop(1) was called
14465     (check-ints-equal *(edx+4) 2 "F - test-copy-object-non-equal: exit status")
14466     # don't restore from ebp
14467     81 0/subop/add %esp 8/imm32
14468     # . epilogue
14469     5d/pop-to-ebp
14470     c3/return
14471 
14472 test-allocate-with-no-inout:
14473     # . prologue
14474     55/push-ebp
14475     89/<- %ebp 4/r32/esp
14476     # setup
14477     (clear-stream _test-input-stream)
14478     (clear-stream $_test-input-buffered-file->buffer)
14479     (clear-stream _test-output-stream)
14480     (clear-stream $_test-output-buffered-file->buffer)
14481     (clear-stream _test-error-stream)
14482     (clear-stream $_test-error-buffered-file->buffer)
14483     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14484     68/push 0/imm32
14485     68/push 0/imm32
14486     89/<- %edx 4/r32/esp
14487     (tailor-exit-descriptor %edx 0x10)
14488     #
14489     (write _test-input-stream "fn foo {\n")
14490     (write _test-input-stream "  allocate\n")
14491     (write _test-input-stream "}\n")
14492     # convert
14493     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14494     # registers except esp clobbered at this point
14495     # restore ed
14496     89/<- %edx 4/r32/esp
14497     (flush _test-output-buffered-file)
14498     (flush _test-error-buffered-file)
14499 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14505     # check output
14506     (check-stream-equal _test-output-stream  ""  "F - test-allocate-with-no-inout: output should be empty")
14507     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'allocate' must have a single inout"  "F - test-allocate-with-no-inout: error message")
14508     # check that stop(1) was called
14509     (check-ints-equal *(edx+4) 2 "F - test-allocate-with-no-inout: exit status")
14510     # don't restore from ebp
14511     81 0/subop/add %esp 8/imm32
14512     # . epilogue
14513     5d/pop-to-ebp
14514     c3/return
14515 
14516 test-allocate-with-too-many-inouts:
14517     # . prologue
14518     55/push-ebp
14519     89/<- %ebp 4/r32/esp
14520     # setup
14521     (clear-stream _test-input-stream)
14522     (clear-stream $_test-input-buffered-file->buffer)
14523     (clear-stream _test-output-stream)
14524     (clear-stream $_test-output-buffered-file->buffer)
14525     (clear-stream _test-error-stream)
14526     (clear-stream $_test-error-buffered-file->buffer)
14527     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14528     68/push 0/imm32
14529     68/push 0/imm32
14530     89/<- %edx 4/r32/esp
14531     (tailor-exit-descriptor %edx 0x10)
14532     #
14533     (write _test-input-stream "fn foo {\n")
14534     (write _test-input-stream "  var x: (addr handle int)\n")
14535     (write _test-input-stream "  allocate x, 0\n")
14536     (write _test-input-stream "}\n")
14537     # convert
14538     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14539     # registers except esp clobbered at this point
14540     # restore ed
14541     89/<- %edx 4/r32/esp
14542     (flush _test-output-buffered-file)
14543     (flush _test-error-buffered-file)
14544 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14550     # check output
14551     (check-stream-equal _test-output-stream  ""  "F - test-allocate-with-too-many-inouts: output should be empty")
14552     (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")
14553     # check that stop(1) was called
14554     (check-ints-equal *(edx+4) 2 "F - test-allocate-with-too-many-inouts: exit status")
14555     # don't restore from ebp
14556     81 0/subop/add %esp 8/imm32
14557     # . epilogue
14558     5d/pop-to-ebp
14559     c3/return
14560 
14561 test-allocate-with-output:
14562     # . prologue
14563     55/push-ebp
14564     89/<- %ebp 4/r32/esp
14565     # setup
14566     (clear-stream _test-input-stream)
14567     (clear-stream $_test-input-buffered-file->buffer)
14568     (clear-stream _test-output-stream)
14569     (clear-stream $_test-output-buffered-file->buffer)
14570     (clear-stream _test-error-stream)
14571     (clear-stream $_test-error-buffered-file->buffer)
14572     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14573     68/push 0/imm32
14574     68/push 0/imm32
14575     89/<- %edx 4/r32/esp
14576     (tailor-exit-descriptor %edx 0x10)
14577     #
14578     (write _test-input-stream "fn foo {\n")
14579     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
14580     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
14581     (write _test-input-stream "  x <- allocate y\n")
14582     (write _test-input-stream "}\n")
14583     # convert
14584     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14585     # registers except esp clobbered at this point
14586     # restore ed
14587     89/<- %edx 4/r32/esp
14588     (flush _test-output-buffered-file)
14589     (flush _test-error-buffered-file)
14590 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14596     # check output
14597     (check-stream-equal _test-output-stream  ""  "F - test-allocate-with-output: output should be empty")
14598     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'allocate' must not have any outputs"  "F - test-allocate-with-output: error message")
14599     # check that stop(1) was called
14600     (check-ints-equal *(edx+4) 2 "F - test-allocate-with-output: exit status")
14601     # don't restore from ebp
14602     81 0/subop/add %esp 8/imm32
14603     # . epilogue
14604     5d/pop-to-ebp
14605     c3/return
14606 
14607 test-allocate-non-addr:
14608     # . prologue
14609     55/push-ebp
14610     89/<- %ebp 4/r32/esp
14611     # setup
14612     (clear-stream _test-input-stream)
14613     (clear-stream $_test-input-buffered-file->buffer)
14614     (clear-stream _test-output-stream)
14615     (clear-stream $_test-output-buffered-file->buffer)
14616     (clear-stream _test-error-stream)
14617     (clear-stream $_test-error-buffered-file->buffer)
14618     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14619     68/push 0/imm32
14620     68/push 0/imm32
14621     89/<- %edx 4/r32/esp
14622     (tailor-exit-descriptor %edx 0x10)
14623     #
14624     (write _test-input-stream "fn foo {\n")
14625     (write _test-input-stream "  var y: (handle int)\n")
14626     (write _test-input-stream "  allocate y\n")
14627     (write _test-input-stream "}\n")
14628     # convert
14629     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14630     # registers except esp clobbered at this point
14631     # restore ed
14632     89/<- %edx 4/r32/esp
14633     (flush _test-output-buffered-file)
14634     (flush _test-error-buffered-file)
14635 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14641     # check output
14642     (check-stream-equal _test-output-stream  ""  "F - test-allocate-non-addr: output must be empty")
14643     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt allocate: inout 'y' must have type (addr handle ...)"  "F - test-allocate-non-addr: error message")
14644     # check that stop(1) was called
14645     (check-ints-equal *(edx+4) 2 "F - test-allocate-non-addr: exit status")
14646     # don't restore from ebp
14647     81 0/subop/add %esp 8/imm32
14648     # . epilogue
14649     5d/pop-to-ebp
14650     c3/return
14651 
14652 test-allocate-non-addr-handle:
14653     # . prologue
14654     55/push-ebp
14655     89/<- %ebp 4/r32/esp
14656     # setup
14657     (clear-stream _test-input-stream)
14658     (clear-stream $_test-input-buffered-file->buffer)
14659     (clear-stream _test-output-stream)
14660     (clear-stream $_test-output-buffered-file->buffer)
14661     (clear-stream _test-error-stream)
14662     (clear-stream $_test-error-buffered-file->buffer)
14663     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14664     68/push 0/imm32
14665     68/push 0/imm32
14666     89/<- %edx 4/r32/esp
14667     (tailor-exit-descriptor %edx 0x10)
14668     #
14669     (write _test-input-stream "fn foo {\n")
14670     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
14671     (write _test-input-stream "  allocate y\n")
14672     (write _test-input-stream "}\n")
14673     # convert
14674     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14675     # registers except esp clobbered at this point
14676     # restore ed
14677     89/<- %edx 4/r32/esp
14678     (flush _test-output-buffered-file)
14679     (flush _test-error-buffered-file)
14680 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14686     # check output
14687     (check-stream-equal _test-output-stream  ""  "F - test-allocate-non-addr-handle: output should be empty")
14688     (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")
14689     # check that stop(1) was called
14690     (check-ints-equal *(edx+4) 2 "F - test-allocate-non-addr-handle: exit status")
14691     # don't restore from ebp
14692     81 0/subop/add %esp 8/imm32
14693     # . epilogue
14694     5d/pop-to-ebp
14695     c3/return
14696 
14697 test-allocate-deref-address:
14698     # . prologue
14699     55/push-ebp
14700     89/<- %ebp 4/r32/esp
14701     # setup
14702     (clear-stream _test-input-stream)
14703     (clear-stream $_test-input-buffered-file->buffer)
14704     (clear-stream _test-output-stream)
14705     (clear-stream $_test-output-buffered-file->buffer)
14706     #
14707     (write _test-input-stream "fn foo {\n")
14708     (write _test-input-stream "  var y/ecx: (addr addr handle int) <- copy 0\n")
14709     (write _test-input-stream "  allocate *y\n")
14710     (write _test-input-stream "}\n")
14711     # convert
14712     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
14713     (flush _test-output-buffered-file)
14714     # no errors
14715     # . epilogue
14716     5d/pop-to-ebp
14717     c3/return
14718 
14719 test-populate-with-no-inout:
14720     # . prologue
14721     55/push-ebp
14722     89/<- %ebp 4/r32/esp
14723     # setup
14724     (clear-stream _test-input-stream)
14725     (clear-stream $_test-input-buffered-file->buffer)
14726     (clear-stream _test-output-stream)
14727     (clear-stream $_test-output-buffered-file->buffer)
14728     (clear-stream _test-error-stream)
14729     (clear-stream $_test-error-buffered-file->buffer)
14730     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14731     68/push 0/imm32
14732     68/push 0/imm32
14733     89/<- %edx 4/r32/esp
14734     (tailor-exit-descriptor %edx 0x10)
14735     #
14736     (write _test-input-stream "fn foo {\n")
14737     (write _test-input-stream "  populate\n")
14738     (write _test-input-stream "}\n")
14739     # convert
14740     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14741     # registers except esp clobbered at this point
14742     # restore ed
14743     89/<- %edx 4/r32/esp
14744     (flush _test-output-buffered-file)
14745     (flush _test-error-buffered-file)
14746 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14752     # check output
14753     (check-stream-equal _test-output-stream  ""  "F - test-populate-with-no-inout: output should be empty")
14754     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate' must have two inouts"  "F - test-populate-with-no-inout: error message")
14755     # check that stop(1) was called
14756     (check-ints-equal *(edx+4) 2 "F - test-populate-with-no-inout: exit status")
14757     # don't restore from ebp
14758     81 0/subop/add %esp 8/imm32
14759     # . epilogue
14760     5d/pop-to-ebp
14761     c3/return
14762 
14763 test-populate-with-too-many-inouts:
14764     # . prologue
14765     55/push-ebp
14766     89/<- %ebp 4/r32/esp
14767     # setup
14768     (clear-stream _test-input-stream)
14769     (clear-stream $_test-input-buffered-file->buffer)
14770     (clear-stream _test-output-stream)
14771     (clear-stream $_test-output-buffered-file->buffer)
14772     (clear-stream _test-error-stream)
14773     (clear-stream $_test-error-buffered-file->buffer)
14774     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14775     68/push 0/imm32
14776     68/push 0/imm32
14777     89/<- %edx 4/r32/esp
14778     (tailor-exit-descriptor %edx 0x10)
14779     #
14780     (write _test-input-stream "fn foo {\n")
14781     (write _test-input-stream "  var x: (addr handle int)\n")
14782     (write _test-input-stream "  populate x, 3, 0\n")
14783     (write _test-input-stream "}\n")
14784     # convert
14785     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14786     # registers except esp clobbered at this point
14787     # restore ed
14788     89/<- %edx 4/r32/esp
14789     (flush _test-output-buffered-file)
14790     (flush _test-error-buffered-file)
14791 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14797     # check output
14798     (check-stream-equal _test-output-stream  ""  "F - test-populate-with-too-many-inouts: output should be empty")
14799     (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")
14800     # check that stop(1) was called
14801     (check-ints-equal *(edx+4) 2 "F - test-populate-with-too-many-inouts: exit status")
14802     # don't restore from ebp
14803     81 0/subop/add %esp 8/imm32
14804     # . epilogue
14805     5d/pop-to-ebp
14806     c3/return
14807 
14808 test-populate-with-output:
14809     # . prologue
14810     55/push-ebp
14811     89/<- %ebp 4/r32/esp
14812     # setup
14813     (clear-stream _test-input-stream)
14814     (clear-stream $_test-input-buffered-file->buffer)
14815     (clear-stream _test-output-stream)
14816     (clear-stream $_test-output-buffered-file->buffer)
14817     (clear-stream _test-error-stream)
14818     (clear-stream $_test-error-buffered-file->buffer)
14819     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14820     68/push 0/imm32
14821     68/push 0/imm32
14822     89/<- %edx 4/r32/esp
14823     (tailor-exit-descriptor %edx 0x10)
14824     #
14825     (write _test-input-stream "fn foo {\n")
14826     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
14827     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
14828     (write _test-input-stream "  x <- populate y\n")
14829     (write _test-input-stream "}\n")
14830     # convert
14831     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14832     # registers except esp clobbered at this point
14833     # restore ed
14834     89/<- %edx 4/r32/esp
14835     (flush _test-output-buffered-file)
14836     (flush _test-error-buffered-file)
14837 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14843     # check output
14844     (check-stream-equal _test-output-stream  ""  "F - test-populate-with-output: output should be empty")
14845     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate' must not have any outputs"  "F - test-populate-with-output: error message")
14846     # check that stop(1) was called
14847     (check-ints-equal *(edx+4) 2 "F - test-populate-with-output: exit status")
14848     # don't restore from ebp
14849     81 0/subop/add %esp 8/imm32
14850     # . epilogue
14851     5d/pop-to-ebp
14852     c3/return
14853 
14854 test-populate-non-addr:
14855     # . prologue
14856     55/push-ebp
14857     89/<- %ebp 4/r32/esp
14858     # setup
14859     (clear-stream _test-input-stream)
14860     (clear-stream $_test-input-buffered-file->buffer)
14861     (clear-stream _test-output-stream)
14862     (clear-stream $_test-output-buffered-file->buffer)
14863     (clear-stream _test-error-stream)
14864     (clear-stream $_test-error-buffered-file->buffer)
14865     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14866     68/push 0/imm32
14867     68/push 0/imm32
14868     89/<- %edx 4/r32/esp
14869     (tailor-exit-descriptor %edx 0x10)
14870     #
14871     (write _test-input-stream "fn foo {\n")
14872     (write _test-input-stream "  var y: (handle int)\n")
14873     (write _test-input-stream "  populate y, 3\n")
14874     (write _test-input-stream "}\n")
14875     # convert
14876     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14877     # registers except esp clobbered at this point
14878     # restore ed
14879     89/<- %edx 4/r32/esp
14880     (flush _test-output-buffered-file)
14881     (flush _test-error-buffered-file)
14882 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14888     # check output
14889     (check-stream-equal _test-output-stream  ""  "F - test-populate-non-addr: output must be empty")
14890     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt populate: first inout 'y' must have type (addr handle array ...)"  "F - test-populate-non-addr: error message")
14891     # check that stop(1) was called
14892     (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr: exit status")
14893     # don't restore from ebp
14894     81 0/subop/add %esp 8/imm32
14895     # . epilogue
14896     5d/pop-to-ebp
14897     c3/return
14898 
14899 test-populate-non-addr-handle:
14900     # . prologue
14901     55/push-ebp
14902     89/<- %ebp 4/r32/esp
14903     # setup
14904     (clear-stream _test-input-stream)
14905     (clear-stream $_test-input-buffered-file->buffer)
14906     (clear-stream _test-output-stream)
14907     (clear-stream $_test-output-buffered-file->buffer)
14908     (clear-stream _test-error-stream)
14909     (clear-stream $_test-error-buffered-file->buffer)
14910     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14911     68/push 0/imm32
14912     68/push 0/imm32
14913     89/<- %edx 4/r32/esp
14914     (tailor-exit-descriptor %edx 0x10)
14915     #
14916     (write _test-input-stream "fn foo {\n")
14917     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
14918     (write _test-input-stream "  populate y, 3\n")
14919     (write _test-input-stream "}\n")
14920     # convert
14921     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14922     # registers except esp clobbered at this point
14923     # restore ed
14924     89/<- %edx 4/r32/esp
14925     (flush _test-output-buffered-file)
14926     (flush _test-error-buffered-file)
14927 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14933     # check output
14934     (check-stream-equal _test-output-stream  ""  "F - test-populate-non-addr-handle: output should be empty")
14935     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt populate: first inout 'y' must have type (addr handle array ...)"  "F - test-populate-non-addr-handle: error message")
14936     # check that stop(1) was called
14937     (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr-handle: exit status")
14938     # don't restore from ebp
14939     81 0/subop/add %esp 8/imm32
14940     # . epilogue
14941     5d/pop-to-ebp
14942     c3/return
14943 
14944 test-populate-non-addr-handle-array:
14945     # . prologue
14946     55/push-ebp
14947     89/<- %ebp 4/r32/esp
14948     # setup
14949     (clear-stream _test-input-stream)
14950     (clear-stream $_test-input-buffered-file->buffer)
14951     (clear-stream _test-output-stream)
14952     (clear-stream $_test-output-buffered-file->buffer)
14953     (clear-stream _test-error-stream)
14954     (clear-stream $_test-error-buffered-file->buffer)
14955     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14956     68/push 0/imm32
14957     68/push 0/imm32
14958     89/<- %edx 4/r32/esp
14959     (tailor-exit-descriptor %edx 0x10)
14960     #
14961     (write _test-input-stream "fn foo {\n")
14962     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
14963     (write _test-input-stream "  populate y, 3\n")
14964     (write _test-input-stream "}\n")
14965     # convert
14966     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14967     # registers except esp clobbered at this point
14968     # restore ed
14969     89/<- %edx 4/r32/esp
14970     (flush _test-output-buffered-file)
14971     (flush _test-error-buffered-file)
14972 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14978     # check output
14979     (check-stream-equal _test-output-stream  ""  "F - test-populate-non-addr-handle-array: output should be empty")
14980     (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")
14981     # check that stop(1) was called
14982     (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr-handle-array: exit status")
14983     # don't restore from ebp
14984     81 0/subop/add %esp 8/imm32
14985     # . epilogue
14986     5d/pop-to-ebp
14987     c3/return
14988 
14989 test-populate-deref-address:
14990     # . prologue
14991     55/push-ebp
14992     89/<- %ebp 4/r32/esp
14993     # setup
14994     (clear-stream _test-input-stream)
14995     (clear-stream $_test-input-buffered-file->buffer)
14996     (clear-stream _test-output-stream)
14997     (clear-stream $_test-output-buffered-file->buffer)
14998     #
14999     (write _test-input-stream "fn foo {\n")
15000     (write _test-input-stream "  var y/ecx: (addr addr handle array int) <- copy 0\n")
15001     (write _test-input-stream "  populate *y, 3\n")
15002     (write _test-input-stream "}\n")
15003     # convert
15004     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
15005     (flush _test-output-buffered-file)
15006     # no errors
15007     # . epilogue
15008     5d/pop-to-ebp
15009     c3/return
15010 
15011 test-populate-stream-with-no-inout:
15012     # . prologue
15013     55/push-ebp
15014     89/<- %ebp 4/r32/esp
15015     # setup
15016     (clear-stream _test-input-stream)
15017     (clear-stream $_test-input-buffered-file->buffer)
15018     (clear-stream _test-output-stream)
15019     (clear-stream $_test-output-buffered-file->buffer)
15020     (clear-stream _test-error-stream)
15021     (clear-stream $_test-error-buffered-file->buffer)
15022     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15023     68/push 0/imm32
15024     68/push 0/imm32
15025     89/<- %edx 4/r32/esp
15026     (tailor-exit-descriptor %edx 0x10)
15027     #
15028     (write _test-input-stream "fn foo {\n")
15029     (write _test-input-stream "  populate-stream\n")
15030     (write _test-input-stream "}\n")
15031     # convert
15032     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15033     # registers except esp clobbered at this point
15034     # restore ed
15035     89/<- %edx 4/r32/esp
15036     (flush _test-output-buffered-file)
15037     (flush _test-error-buffered-file)
15038 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15044     # check output
15045     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-with-no-inout: output should be empty")
15046     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate-stream' must have two inouts"  "F - test-populate-stream-with-no-inout: error message")
15047     # check that stop(1) was called
15048     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-no-inout: exit status")
15049     # don't restore from ebp
15050     81 0/subop/add %esp 8/imm32
15051     # . epilogue
15052     5d/pop-to-ebp
15053     c3/return
15054 
15055 test-populate-stream-with-too-many-inouts:
15056     # . prologue
15057     55/push-ebp
15058     89/<- %ebp 4/r32/esp
15059     # setup
15060     (clear-stream _test-input-stream)
15061     (clear-stream $_test-input-buffered-file->buffer)
15062     (clear-stream _test-output-stream)
15063     (clear-stream $_test-output-buffered-file->buffer)
15064     (clear-stream _test-error-stream)
15065     (clear-stream $_test-error-buffered-file->buffer)
15066     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15067     68/push 0/imm32
15068     68/push 0/imm32
15069     89/<- %edx 4/r32/esp
15070     (tailor-exit-descriptor %edx 0x10)
15071     #
15072     (write _test-input-stream "fn foo {\n")
15073     (write _test-input-stream "  var x: (addr handle int)\n")
15074     (write _test-input-stream "  populate-stream x, 3, 0\n")
15075     (write _test-input-stream "}\n")
15076     # convert
15077     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15078     # registers except esp clobbered at this point
15079     # restore ed
15080     89/<- %edx 4/r32/esp
15081     (flush _test-output-buffered-file)
15082     (flush _test-error-buffered-file)
15083 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15089     # check output
15090     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-with-too-many-inouts: output should be empty")
15091     (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")
15092     # check that stop(1) was called
15093     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-too-many-inouts: exit status")
15094     # don't restore from ebp
15095     81 0/subop/add %esp 8/imm32
15096     # . epilogue
15097     5d/pop-to-ebp
15098     c3/return
15099 
15100 test-populate-stream-with-output:
15101     # . prologue
15102     55/push-ebp
15103     89/<- %ebp 4/r32/esp
15104     # setup
15105     (clear-stream _test-input-stream)
15106     (clear-stream $_test-input-buffered-file->buffer)
15107     (clear-stream _test-output-stream)
15108     (clear-stream $_test-output-buffered-file->buffer)
15109     (clear-stream _test-error-stream)
15110     (clear-stream $_test-error-buffered-file->buffer)
15111     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15112     68/push 0/imm32
15113     68/push 0/imm32
15114     89/<- %edx 4/r32/esp
15115     (tailor-exit-descriptor %edx 0x10)
15116     #
15117     (write _test-input-stream "fn foo {\n")
15118     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
15119     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
15120     (write _test-input-stream "  x <- populate-stream y\n")
15121     (write _test-input-stream "}\n")
15122     # convert
15123     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15124     # registers except esp clobbered at this point
15125     # restore ed
15126     89/<- %edx 4/r32/esp
15127     (flush _test-output-buffered-file)
15128     (flush _test-error-buffered-file)
15129 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15135     # check output
15136     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-with-output: output should be empty")
15137     (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")
15138     # check that stop(1) was called
15139     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-output: exit status")
15140     # don't restore from ebp
15141     81 0/subop/add %esp 8/imm32
15142     # . epilogue
15143     5d/pop-to-ebp
15144     c3/return
15145 
15146 test-populate-stream-non-addr:
15147     # . prologue
15148     55/push-ebp
15149     89/<- %ebp 4/r32/esp
15150     # setup
15151     (clear-stream _test-input-stream)
15152     (clear-stream $_test-input-buffered-file->buffer)
15153     (clear-stream _test-output-stream)
15154     (clear-stream $_test-output-buffered-file->buffer)
15155     (clear-stream _test-error-stream)
15156     (clear-stream $_test-error-buffered-file->buffer)
15157     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15158     68/push 0/imm32
15159     68/push 0/imm32
15160     89/<- %edx 4/r32/esp
15161     (tailor-exit-descriptor %edx 0x10)
15162     #
15163     (write _test-input-stream "fn foo {\n")
15164     (write _test-input-stream "  var y: (handle int)\n")
15165     (write _test-input-stream "  populate-stream y, 3\n")
15166     (write _test-input-stream "}\n")
15167     # convert
15168     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15169     # registers except esp clobbered at this point
15170     # restore ed
15171     89/<- %edx 4/r32/esp
15172     (flush _test-output-buffered-file)
15173     (flush _test-error-buffered-file)
15174 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15180     # check output
15181     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-non-addr: output must be empty")
15182     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt populate-stream: first inout 'y' must have type (addr handle stream ...)"  "F - test-populate-stream-non-addr: error message")
15183     # check that stop(1) was called
15184     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr: exit status")
15185     # don't restore from ebp
15186     81 0/subop/add %esp 8/imm32
15187     # . epilogue
15188     5d/pop-to-ebp
15189     c3/return
15190 
15191 test-populate-stream-non-addr-handle:
15192     # . prologue
15193     55/push-ebp
15194     89/<- %ebp 4/r32/esp
15195     # setup
15196     (clear-stream _test-input-stream)
15197     (clear-stream $_test-input-buffered-file->buffer)
15198     (clear-stream _test-output-stream)
15199     (clear-stream $_test-output-buffered-file->buffer)
15200     (clear-stream _test-error-stream)
15201     (clear-stream $_test-error-buffered-file->buffer)
15202     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15203     68/push 0/imm32
15204     68/push 0/imm32
15205     89/<- %edx 4/r32/esp
15206     (tailor-exit-descriptor %edx 0x10)
15207     #
15208     (write _test-input-stream "fn foo {\n")
15209     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
15210     (write _test-input-stream "  populate-stream y, 3\n")
15211     (write _test-input-stream "}\n")
15212     # convert
15213     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15214     # registers except esp clobbered at this point
15215     # restore ed
15216     89/<- %edx 4/r32/esp
15217     (flush _test-output-buffered-file)
15218     (flush _test-error-buffered-file)
15219 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15225     # check output
15226     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-non-addr-handle: output should be empty")
15227     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt populate-stream: first inout 'y' must have type (addr handle stream ...)"  "F - test-populate-stream-non-addr-handle: error message")
15228     # check that stop(1) was called
15229     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr-handle: exit status")
15230     # don't restore from ebp
15231     81 0/subop/add %esp 8/imm32
15232     # . epilogue
15233     5d/pop-to-ebp
15234     c3/return
15235 
15236 test-populate-stream-non-addr-handle-stream:
15237     # . prologue
15238     55/push-ebp
15239     89/<- %ebp 4/r32/esp
15240     # setup
15241     (clear-stream _test-input-stream)
15242     (clear-stream $_test-input-buffered-file->buffer)
15243     (clear-stream _test-output-stream)
15244     (clear-stream $_test-output-buffered-file->buffer)
15245     (clear-stream _test-error-stream)
15246     (clear-stream $_test-error-buffered-file->buffer)
15247     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15248     68/push 0/imm32
15249     68/push 0/imm32
15250     89/<- %edx 4/r32/esp
15251     (tailor-exit-descriptor %edx 0x10)
15252     #
15253     (write _test-input-stream "fn foo {\n")
15254     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
15255     (write _test-input-stream "  populate-stream y, 3\n")
15256     (write _test-input-stream "}\n")
15257     # convert
15258     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15259     # registers except esp clobbered at this point
15260     # restore ed
15261     89/<- %edx 4/r32/esp
15262     (flush _test-output-buffered-file)
15263     (flush _test-error-buffered-file)
15264 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15270     # check output
15271     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-non-addr-handle-stream: output should be empty")
15272     (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")
15273     # check that stop(1) was called
15274     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr-handle-stream: exit status")
15275     # don't restore from ebp
15276     81 0/subop/add %esp 8/imm32
15277     # . epilogue
15278     5d/pop-to-ebp
15279     c3/return
15280 
15281 test-populate-stream-deref-address:
15282     # . prologue
15283     55/push-ebp
15284     89/<- %ebp 4/r32/esp
15285     # setup
15286     (clear-stream _test-input-stream)
15287     (clear-stream $_test-input-buffered-file->buffer)
15288     (clear-stream _test-output-stream)
15289     (clear-stream $_test-output-buffered-file->buffer)
15290     #
15291     (write _test-input-stream "fn foo {\n")
15292     (write _test-input-stream "  var y/ecx: (addr addr handle stream int) <- copy 0\n")
15293     (write _test-input-stream "  populate-stream *y, 3\n")
15294     (write _test-input-stream "}\n")
15295     # convert
15296     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
15297     (flush _test-output-buffered-file)
15298     # no errors
15299     # . epilogue
15300     5d/pop-to-ebp
15301     c3/return
15302 
15303 test-convert-with-no-inout:
15304     # . prologue
15305     55/push-ebp
15306     89/<- %ebp 4/r32/esp
15307     # setup
15308     (clear-stream _test-input-stream)
15309     (clear-stream $_test-input-buffered-file->buffer)
15310     (clear-stream _test-output-stream)
15311     (clear-stream $_test-output-buffered-file->buffer)
15312     (clear-stream _test-error-stream)
15313     (clear-stream $_test-error-buffered-file->buffer)
15314     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15315     68/push 0/imm32
15316     68/push 0/imm32
15317     89/<- %edx 4/r32/esp
15318     (tailor-exit-descriptor %edx 0x10)
15319     #
15320     (write _test-input-stream "fn foo {\n")
15321     (write _test-input-stream "  var x/eax: int <- convert\n")
15322     (write _test-input-stream "}\n")
15323     # convert
15324     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15325     # registers except esp clobbered at this point
15326     # restore ed
15327     89/<- %edx 4/r32/esp
15328     (flush _test-output-buffered-file)
15329     (flush _test-error-buffered-file)
15330 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15336     # check output
15337     (check-stream-equal _test-output-stream  ""  "F - test-convert-with-no-inout: output should be empty")
15338     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'convert' expects an inout"  "F - test-convert-with-no-inout: error message")
15339     # check that stop(1) was called
15340     (check-ints-equal *(edx+4) 2 "F - test-convert-with-no-inout: exit status")
15341     # don't restore from ebp
15342     81 0/subop/add %esp 8/imm32
15343     # . epilogue
15344     5d/pop-to-ebp
15345     c3/return
15346 
15347 test-convert-with-multiple-inouts:
15348     # . prologue
15349     55/push-ebp
15350     89/<- %ebp 4/r32/esp
15351     # setup
15352     (clear-stream _test-input-stream)
15353     (clear-stream $_test-input-buffered-file->buffer)
15354     (clear-stream _test-output-stream)
15355     (clear-stream $_test-output-buffered-file->buffer)
15356     (clear-stream _test-error-stream)
15357     (clear-stream $_test-error-buffered-file->buffer)
15358     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15359     68/push 0/imm32
15360     68/push 0/imm32
15361     89/<- %edx 4/r32/esp
15362     (tailor-exit-descriptor %edx 0x10)
15363     #
15364     (write _test-input-stream "fn foo {\n")
15365     (write _test-input-stream "  var x/eax: int <- convert 0, 0\n")
15366     (write _test-input-stream "}\n")
15367     # convert
15368     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15369     # registers except esp clobbered at this point
15370     # restore ed
15371     89/<- %edx 4/r32/esp
15372     (flush _test-output-buffered-file)
15373     (flush _test-error-buffered-file)
15374 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15380     # check output
15381     (check-stream-equal _test-output-stream  ""  "F - test-convert-with-multiple-inouts: output should be empty")
15382     (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")
15383     # check that stop(1) was called
15384     (check-ints-equal *(edx+4) 2 "F - test-convert-with-multiple-inouts: exit status")
15385     # don't restore from ebp
15386     81 0/subop/add %esp 8/imm32
15387     # . epilogue
15388     5d/pop-to-ebp
15389     c3/return
15390 
15391 test-convert-with-no-output:
15392     # . prologue
15393     55/push-ebp
15394     89/<- %ebp 4/r32/esp
15395     # setup
15396     (clear-stream _test-input-stream)
15397     (clear-stream $_test-input-buffered-file->buffer)
15398     (clear-stream _test-output-stream)
15399     (clear-stream $_test-output-buffered-file->buffer)
15400     (clear-stream _test-error-stream)
15401     (clear-stream $_test-error-buffered-file->buffer)
15402     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15403     68/push 0/imm32
15404     68/push 0/imm32
15405     89/<- %edx 4/r32/esp
15406     (tailor-exit-descriptor %edx 0x10)
15407     #
15408     (write _test-input-stream "fn foo {\n")
15409     (write _test-input-stream "  convert 0\n")
15410     (write _test-input-stream "}\n")
15411     # convert
15412     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15413     # registers except esp clobbered at this point
15414     # restore ed
15415     89/<- %edx 4/r32/esp
15416     (flush _test-output-buffered-file)
15417     (flush _test-error-buffered-file)
15418 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15424     # check output
15425     (check-stream-equal _test-output-stream  ""  "F - test-convert-with-no-output: output should be empty")
15426     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'convert' expects an output"  "F - test-convert-with-no-output: error message")
15427     # check that stop(1) was called
15428     (check-ints-equal *(edx+4) 2 "F - test-convert-with-no-output: exit status")
15429     # don't restore from ebp
15430     81 0/subop/add %esp 8/imm32
15431     # . epilogue
15432     5d/pop-to-ebp
15433     c3/return
15434 
15435 test-convert-with-multiple-outputs:
15436     # . prologue
15437     55/push-ebp
15438     89/<- %ebp 4/r32/esp
15439     # setup
15440     (clear-stream _test-input-stream)
15441     (clear-stream $_test-input-buffered-file->buffer)
15442     (clear-stream _test-output-stream)
15443     (clear-stream $_test-output-buffered-file->buffer)
15444     (clear-stream _test-error-stream)
15445     (clear-stream $_test-error-buffered-file->buffer)
15446     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15447     68/push 0/imm32
15448     68/push 0/imm32
15449     89/<- %edx 4/r32/esp
15450     (tailor-exit-descriptor %edx 0x10)
15451     #
15452     (write _test-input-stream "fn foo {\n")
15453     (write _test-input-stream "  var x/eax: int <- copy 0\n")
15454     (write _test-input-stream "  var y/ecx: int <- copy 0\n")
15455     (write _test-input-stream "  x, y <- convert 0\n")
15456     (write _test-input-stream "}\n")
15457     # convert
15458     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15459     # registers except esp clobbered at this point
15460     # restore ed
15461     89/<- %edx 4/r32/esp
15462     (flush _test-output-buffered-file)
15463     (flush _test-error-buffered-file)
15464 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15470     # check output
15471     (check-stream-equal _test-output-stream  ""  "F - test-convert-with-multiple-outputs: output should be empty")
15472     (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")
15473     # check that stop(1) was called
15474     (check-ints-equal *(edx+4) 2 "F - test-convert-with-multiple-outputs: exit status")
15475     # don't restore from ebp
15476     81 0/subop/add %esp 8/imm32
15477     # . epilogue
15478     5d/pop-to-ebp
15479     c3/return
15480 
15481 test-convert-deref-address:
15482     # . prologue
15483     55/push-ebp
15484     89/<- %ebp 4/r32/esp
15485     # setup
15486     (clear-stream _test-input-stream)
15487     (clear-stream $_test-input-buffered-file->buffer)
15488     (clear-stream _test-output-stream)
15489     (clear-stream $_test-output-buffered-file->buffer)
15490     #
15491     (write _test-input-stream "fn foo {\n")
15492     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
15493     (write _test-input-stream "  var y/xmm4: float <- convert *x\n")
15494     (write _test-input-stream "}\n")
15495     # convert
15496     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
15497     (flush _test-output-buffered-file)
15498     # no errors
15499     # . epilogue
15500     5d/pop-to-ebp
15501     c3/return
15502 
15503 test-convert-to-non-register:
15504     # . prologue
15505     55/push-ebp
15506     89/<- %ebp 4/r32/esp
15507     # setup
15508     (clear-stream _test-input-stream)
15509     (clear-stream $_test-input-buffered-file->buffer)
15510     (clear-stream _test-output-stream)
15511     (clear-stream $_test-output-buffered-file->buffer)
15512     (clear-stream _test-error-stream)
15513     (clear-stream $_test-error-buffered-file->buffer)
15514     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15515     68/push 0/imm32
15516     68/push 0/imm32
15517     89/<- %edx 4/r32/esp
15518     (tailor-exit-descriptor %edx 0x10)
15519     #
15520     (write _test-input-stream "fn foo {\n")
15521     (write _test-input-stream "  var x: float\n")
15522     (write _test-input-stream "  var y: int\n")
15523     (write _test-input-stream "  x <- convert y\n")
15524     (write _test-input-stream "}\n")
15525     # convert
15526     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15527     # registers except esp clobbered at this point
15528     # restore ed
15529     89/<- %edx 4/r32/esp
15530     (flush _test-output-buffered-file)
15531     (flush _test-error-buffered-file)
15532 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15538     # check output
15539     (check-stream-equal _test-output-stream  ""  "F - test-convert-to-non-register: output should be empty")
15540     (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")
15541     # check that stop(1) was called
15542     (check-ints-equal *(edx+4) 2 "F - test-convert-to-non-register: exit status")
15543     # don't restore from ebp
15544     81 0/subop/add %esp 8/imm32
15545     # . epilogue
15546     5d/pop-to-ebp
15547     c3/return
15548 
15549 test-convert-invalid-inout-type:
15550     # . prologue
15551     55/push-ebp
15552     89/<- %ebp 4/r32/esp
15553     # setup
15554     (clear-stream _test-input-stream)
15555     (clear-stream $_test-input-buffered-file->buffer)
15556     (clear-stream _test-output-stream)
15557     (clear-stream $_test-output-buffered-file->buffer)
15558     (clear-stream _test-error-stream)
15559     (clear-stream $_test-error-buffered-file->buffer)
15560     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15561     68/push 0/imm32
15562     68/push 0/imm32
15563     89/<- %edx 4/r32/esp
15564     (tailor-exit-descriptor %edx 0x10)
15565     #
15566     (write _test-input-stream "fn foo {\n")
15567     (write _test-input-stream "  var x: boolean\n")
15568     (write _test-input-stream "  var y/xmm1: float <- convert x\n")
15569     (write _test-input-stream "}\n")
15570     # convert
15571     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15572     # registers except esp clobbered at this point
15573     # restore ed
15574     89/<- %edx 4/r32/esp
15575     (flush _test-output-buffered-file)
15576     (flush _test-error-buffered-file)
15577 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15583     # check output
15584     (check-stream-equal _test-output-stream  ""  "F - test-convert-invalid-inout-type: output should be empty")
15585     (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")
15586     # check that stop(1) was called
15587     (check-ints-equal *(edx+4) 2 "F - test-convert-invalid-inout-type: exit status")
15588     # don't restore from ebp
15589     81 0/subop/add %esp 8/imm32
15590     # . epilogue
15591     5d/pop-to-ebp
15592     c3/return
15593 
15594 test-convert-invalid-output-type:
15595     # . prologue
15596     55/push-ebp
15597     89/<- %ebp 4/r32/esp
15598     # setup
15599     (clear-stream _test-input-stream)
15600     (clear-stream $_test-input-buffered-file->buffer)
15601     (clear-stream _test-output-stream)
15602     (clear-stream $_test-output-buffered-file->buffer)
15603     (clear-stream _test-error-stream)
15604     (clear-stream $_test-error-buffered-file->buffer)
15605     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15606     68/push 0/imm32
15607     68/push 0/imm32
15608     89/<- %edx 4/r32/esp
15609     (tailor-exit-descriptor %edx 0x10)
15610     #
15611     (write _test-input-stream "fn foo {\n")
15612     (write _test-input-stream "  var x: float\n")
15613     (write _test-input-stream "  var y/eax: boolean <- convert x\n")
15614     (write _test-input-stream "}\n")
15615     # convert
15616     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15617     # registers except esp clobbered at this point
15618     # restore ed
15619     89/<- %edx 4/r32/esp
15620     (flush _test-output-buffered-file)
15621     (flush _test-error-buffered-file)
15622 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15628     # check output
15629     (check-stream-equal _test-output-stream  ""  "F - test-convert-invalid-output-type: output should be empty")
15630     (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")
15631     # check that stop(1) was called
15632     (check-ints-equal *(edx+4) 2 "F - test-convert-invalid-output-type: exit status")
15633     # don't restore from ebp
15634     81 0/subop/add %esp 8/imm32
15635     # . epilogue
15636     5d/pop-to-ebp
15637     c3/return
15638 
15639 test-convert-int-to-int:
15640     # . prologue
15641     55/push-ebp
15642     89/<- %ebp 4/r32/esp
15643     # setup
15644     (clear-stream _test-input-stream)
15645     (clear-stream $_test-input-buffered-file->buffer)
15646     (clear-stream _test-output-stream)
15647     (clear-stream $_test-output-buffered-file->buffer)
15648     (clear-stream _test-error-stream)
15649     (clear-stream $_test-error-buffered-file->buffer)
15650     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15651     68/push 0/imm32
15652     68/push 0/imm32
15653     89/<- %edx 4/r32/esp
15654     (tailor-exit-descriptor %edx 0x10)
15655     #
15656     (write _test-input-stream "fn foo {\n")
15657     (write _test-input-stream "  var x: int\n")
15658     (write _test-input-stream "  var y/eax: int <- convert x\n")
15659     (write _test-input-stream "}\n")
15660     # convert
15661     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15662     # registers except esp clobbered at this point
15663     # restore ed
15664     89/<- %edx 4/r32/esp
15665     (flush _test-output-buffered-file)
15666     (flush _test-error-buffered-file)
15667 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15673     # check output
15674     (check-stream-equal _test-output-stream  ""  "F - test-convert-int-to-int: output should be empty")
15675     (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")
15676     # check that stop(1) was called
15677     (check-ints-equal *(edx+4) 2 "F - test-convert-int-to-int: exit status")
15678     # don't restore from ebp
15679     81 0/subop/add %esp 8/imm32
15680     # . epilogue
15681     5d/pop-to-ebp
15682     c3/return
15683 
15684 test-convert-float-to-float:
15685     # . prologue
15686     55/push-ebp
15687     89/<- %ebp 4/r32/esp
15688     # setup
15689     (clear-stream _test-input-stream)
15690     (clear-stream $_test-input-buffered-file->buffer)
15691     (clear-stream _test-output-stream)
15692     (clear-stream $_test-output-buffered-file->buffer)
15693     (clear-stream _test-error-stream)
15694     (clear-stream $_test-error-buffered-file->buffer)
15695     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15696     68/push 0/imm32
15697     68/push 0/imm32
15698     89/<- %edx 4/r32/esp
15699     (tailor-exit-descriptor %edx 0x10)
15700     #
15701     (write _test-input-stream "fn foo {\n")
15702     (write _test-input-stream "  var x: float\n")
15703     (write _test-input-stream "  var y/xmm6: float <- convert x\n")
15704     (write _test-input-stream "}\n")
15705     # convert
15706     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15707     # registers except esp clobbered at this point
15708     # restore ed
15709     89/<- %edx 4/r32/esp
15710     (flush _test-output-buffered-file)
15711     (flush _test-error-buffered-file)
15712 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15718     # check output
15719     (check-stream-equal _test-output-stream  ""  "F - test-convert-float-to-float: output should be empty")
15720     (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")
15721     # check that stop(1) was called
15722     (check-ints-equal *(edx+4) 2 "F - test-convert-float-to-float: exit status")
15723     # don't restore from ebp
15724     81 0/subop/add %esp 8/imm32
15725     # . epilogue
15726     5d/pop-to-ebp
15727     c3/return
15728 
15729 #######################################################
15730 # Parsing
15731 #######################################################
15732 
15733 == data
15734 
15735 # Global state added to each var record when parsing a function
15736 Next-block-index:  # (addr int)
15737     1/imm32
15738 
15739 Curr-block-depth:  # (addr int)
15740     1/imm32
15741 
15742 == code
15743 
15744 parse-mu:  # in: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
15745     # pseudocode
15746     #   var curr-function: (addr handle function) = Program->functions
15747     #   var curr-signature: (addr handle function) = Program->signatures
15748     #   var curr-type: (addr handle typeinfo) = Program->types
15749     #   var line: (stream byte 512)
15750     #   var word-slice: slice
15751     #   while true                                  # line loop
15752     #     clear-stream(line)
15753     #     read-line-buffered(in, line)
15754     #     if (line->write == 0) break               # end of file
15755     #     word-slice = next-mu-token(line)
15756     #     if slice-empty?(word-slice)               # end of line
15757     #       continue
15758     #     else if slice-starts-with?(word-slice, "#")  # comment
15759     #       continue                                # end of line
15760     #     else if slice-equal?(word-slice, "fn")
15761     #       var new-function: (handle function) = allocate(function)
15762     #       var vars: (stack live-var 256)
15763     #       populate-mu-function-header(line, new-function, vars)
15764     #       populate-mu-function-body(in, new-function, vars)
15765     #       assert(vars->top == 0)
15766     #       *curr-function = new-function
15767     #       curr-function = &new-function->next
15768     #     else if slice-equal?(word-slice, "sig")
15769     #       var new-function: (handle function) = allocate(function)
15770     #       populate-mu-function-signature(line, new-function)
15771     #       *curr-signature = new-function
15772     #       curr-signature = &new-function->next
15773     #     else if slice-equal?(word-slice, "type")
15774     #       word-slice = next-mu-token(line)
15775     #       type-id = pos-or-insert-slice(Type-id, word-slice)
15776     #       var new-type: (handle typeinfo) = find-or-create-typeinfo(type-id)
15777     #       assert(next-word(line) == "{")
15778     #       populate-mu-type(in, new-type)
15779     #     else
15780     #       abort()
15781     #
15782     # . prologue
15783     55/push-ebp
15784     89/<- %ebp 4/r32/esp
15785     # var curr-signature: (addr handle function) at *(ebp-4)
15786     68/push _Program-signatures/imm32
15787     # . save registers
15788     50/push-eax
15789     51/push-ecx
15790     52/push-edx
15791     53/push-ebx
15792     56/push-esi
15793     57/push-edi
15794     # var line/ecx: (stream byte 512)
15795     81 5/subop/subtract %esp 0x200/imm32
15796     68/push 0x200/imm32/size
15797     68/push 0/imm32/read
15798     68/push 0/imm32/write
15799     89/<- %ecx 4/r32/esp
15800     # var word-slice/edx: slice
15801     68/push 0/imm32/end
15802     68/push 0/imm32/start
15803     89/<- %edx 4/r32/esp
15804     # var curr-function/edi: (addr handle function)
15805     bf/copy-to-edi _Program-functions/imm32
15806     # var vars/ebx: (stack live-var 256)
15807     81 5/subop/subtract %esp 0xc00/imm32
15808     68/push 0xc00/imm32/size
15809     68/push 0/imm32/top
15810     89/<- %ebx 4/r32/esp
15811     {
15812 $parse-mu:line-loop:
15813       (clear-stream %ecx)
15814       (read-line-buffered *(ebp+8) %ecx)
15815       # if (line->write == 0) break
15816       81 7/subop/compare *ecx 0/imm32
15817       0f 84/jump-if-= break/disp32
15818 +--  6 lines: #?       # dump line ------------------------------------------------------------------------------------------------------------------------------------------------------
15824       (next-mu-token %ecx %edx)
15825       # if slice-empty?(word-slice) continue
15826       (slice-empty? %edx)  # => eax
15827       3d/compare-eax-and 0/imm32/false
15828       0f 85/jump-if-!= loop/disp32
15829       # if (*word-slice->start == "#") continue
15830       # . eax = *word-slice->start
15831       8b/-> *edx 0/r32/eax
15832       8a/copy-byte *eax 0/r32/AL
15833       25/and-eax-with 0xff/imm32
15834       # . if (eax == '#') continue
15835       3d/compare-eax-and 0x23/imm32/hash
15836       0f 84/jump-if-= loop/disp32
15837       # if (slice-equal?(word-slice, "fn")) parse a function
15838       {
15839 $parse-mu:fn:
15840         (slice-equal? %edx "fn")  # => eax
15841         3d/compare-eax-and 0/imm32/false
15842         0f 84/jump-if-= break/disp32
15843         # var new-function/esi: (handle function)
15844         68/push 0/imm32
15845         68/push 0/imm32
15846         89/<- %esi 4/r32/esp
15847         # populate-mu-function(line, in, vars, new-function)
15848         (allocate Heap *Function-size %esi)
15849         # var new-function-addr/eax: (addr function)
15850         (lookup *esi *(esi+4))  # => eax
15851         # initialize vars
15852         (clear-stack %ebx)
15853         #
15854         (populate-mu-function-header %ecx %eax %ebx *(ebp+0xc) *(ebp+0x10))
15855         (populate-mu-function-body *(ebp+8) %eax %ebx *(ebp+0xc) *(ebp+0x10))
15856         # *curr-function = new-function
15857         8b/-> *esi 0/r32/eax
15858         89/<- *edi 0/r32/eax
15859         8b/-> *(esi+4) 0/r32/eax
15860         89/<- *(edi+4) 0/r32/eax
15861         # curr-function = &new-function->next
15862         # . var tmp/eax: (addr function) = lookup(new-function)
15863         (lookup *esi *(esi+4))  # => eax
15864         # . curr-function = &tmp->next
15865         8d/copy-address *(eax+0x20) 7/r32/edi  # Function-next
15866         # reclaim new-function
15867         81 0/subop/add %esp 8/imm32
15868         #
15869         e9/jump $parse-mu:line-loop/disp32
15870       }
15871       # if (slice-equal?(word-slice, "sig")) parse a function signature
15872       # Function signatures are for providing types to SubX functions.
15873       {
15874 $parse-mu:sig:
15875         (slice-equal? %edx "sig")  # => eax
15876         3d/compare-eax-and 0/imm32/false
15877         0f 84/jump-if-= break/disp32
15878         # edi = curr-function
15879         57/push-edi
15880         8b/-> *(ebp-4) 7/r32/edi
15881         # var new-function/esi: (handle function)
15882         68/push 0/imm32
15883         68/push 0/imm32
15884         89/<- %esi 4/r32/esp
15885         # populate-mu-function(line, in, vars, new-function)
15886         (allocate Heap *Function-size %esi)
15887         # var new-function-addr/eax: (addr function)
15888         (lookup *esi *(esi+4))  # => eax
15889         #
15890         (populate-mu-function-signature %ecx %eax *(ebp+0xc) *(ebp+0x10))
15891         # *curr-signature = new-function
15892         8b/-> *esi 0/r32/eax
15893         89/<- *edi 0/r32/eax
15894         8b/-> *(esi+4) 0/r32/eax
15895         89/<- *(edi+4) 0/r32/eax
15896         # curr-signature = &new-function->next
15897         # . var tmp/eax: (addr function) = lookup(new-function)
15898         (lookup *esi *(esi+4))  # => eax
15899         # . curr-function = &tmp->next
15900         8d/copy-address *(eax+0x20) 7/r32/edi  # Function-next
15901         # reclaim new-function
15902         81 0/subop/add %esp 8/imm32
15903         # save curr-function
15904         89/<- *(ebp-4) 7/r32/edi
15905         # restore edi
15906         5f/pop-to-edi
15907         #
15908         e9/jump $parse-mu:line-loop/disp32
15909       }
15910       # if (slice-equal?(word-slice, "type")) parse a type (struct/record) definition
15911       {
15912 $parse-mu:type:
15913         (slice-equal? %edx "type")  # => eax
15914         3d/compare-eax-and 0/imm32
15915         0f 84/jump-if-= break/disp32
15916         (next-mu-token %ecx %edx)
15917         # var type-id/eax: int
15918         (pos-or-insert-slice Type-id %edx)  # => eax
15919         # spill
15920         51/push-ecx
15921         # var new-type/ecx: (handle typeinfo)
15922         68/push 0/imm32
15923         68/push 0/imm32
15924         89/<- %ecx 4/r32/esp
15925         (find-or-create-typeinfo %eax %ecx)
15926         #
15927         (lookup *ecx *(ecx+4))  # => eax
15928         # TODO: ensure that 'line' has nothing else but '{'
15929 #? (dump-typeinfos "=== aaa\n")
15930         (populate-mu-type *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10))  # => eax
15931 #? (dump-typeinfos "=== zzz\n")
15932         # reclaim new-type
15933         81 0/subop/add %esp 8/imm32
15934         # restore
15935         59/pop-to-ecx
15936         e9/jump $parse-mu:line-loop/disp32
15937       }
15938       # otherwise abort
15939       e9/jump $parse-mu:error1/disp32
15940     } # end line loop
15941 $parse-mu:end:
15942     # . reclaim locals
15943     81 0/subop/add %esp 0x20c/imm32  # line
15944     81 0/subop/add %esp 0xc08/imm32  # vars
15945     81 0/subop/add %esp 8/imm32
15946     # . restore registers
15947     5f/pop-to-edi
15948     5e/pop-to-esi
15949     5b/pop-to-ebx
15950     5a/pop-to-edx
15951     59/pop-to-ecx
15952     58/pop-to-eax
15953     # . reclaim local
15954     81 0/subop/add %esp 4/imm32
15955     # . epilogue
15956     89/<- %esp 5/r32/ebp
15957     5d/pop-to-ebp
15958     c3/return
15959 
15960 $parse-mu:error1:
15961     # error("unexpected top-level command: " word-slice "\n")
15962     (write-buffered *(ebp+0xc) "unexpected top-level command: ")
15963     (write-slice-buffered *(ebp+0xc) %edx)
15964     (write-buffered *(ebp+0xc) "\n")
15965     (flush *(ebp+0xc))
15966     (stop *(ebp+0x10) 1)
15967     # never gets here
15968 
15969 $parse-mu:error2:
15970     # error(vars->top " vars not reclaimed after fn '" new-function->name "'\n")
15971     (write-int32-hex-buffered *(ebp+0xc) *ebx)
15972     (write-buffered *(ebp+0xc) " vars not reclaimed after fn '")
15973     (write-slice-buffered *(ebp+0xc) *eax)  # Function-name
15974     (write-buffered *(ebp+0xc) "'\n")
15975     (flush *(ebp+0xc))
15976     (stop *(ebp+0x10) 1)
15977     # never gets here
15978 
15979 # scenarios considered:
15980 # ✗ fn foo  # no block
15981 # ✓ fn foo {
15982 # ✗ fn foo { {
15983 # ✗ fn foo { }
15984 # ✗ fn foo { } {
15985 # ✗ fn foo x {
15986 # ✗ fn foo x: {
15987 # ✓ fn foo x: int {
15988 # ✓ fn foo x: int {
15989 # ✓ fn foo x: int -> _/eax: int {
15990 # TODO:
15991 #   disallow outputs of type `(... addr ...)`
15992 #   disallow inputs of type `(... addr ... addr ...)`
15993 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)
15994     # pseudocode:
15995     #   var word-slice: slice
15996     #   next-mu-token(first-line, word-slice)
15997     #   if slice-empty?(word-slice) abort
15998     #   assert(word-slice not in '{' '}' '->')
15999     #   out->name = slice-to-string(word-slice)
16000     #   ## inouts
16001     #   while true
16002     #     word-slice = next-mu-token(first-line)
16003     #     if slice-empty?(word-slice) abort
16004     #     if (word-slice == '{') goto done
16005     #     if (word-slice == '->') break
16006     #     assert(word-slice != '}')
16007     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
16008     #     assert(v->register == null)
16009     #     # v->block-depth is implicitly 0
16010     #     out->inouts = append(v, out->inouts)
16011     #     push(vars, {v, false})
16012     #   ## outputs
16013     #   while true
16014     #     word-slice = next-mu-token(first-line)
16015     #     if slice-empty?(word-slice) abort
16016     #     if (word-slice == '{') break
16017     #     assert(word-slice not in '}' '->')
16018     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
16019     #     assert(v->register != null)
16020     #     assert(v->name == "_")
16021     #     out->outputs = append(v, out->outputs)
16022     #   done:
16023     #
16024     # . prologue
16025     55/push-ebp
16026     89/<- %ebp 4/r32/esp
16027     # . save registers
16028     50/push-eax
16029     51/push-ecx
16030     52/push-edx
16031     53/push-ebx
16032     57/push-edi
16033     # edi = out
16034     8b/-> *(ebp+0xc) 7/r32/edi
16035     # var word-slice/ecx: slice
16036     68/push 0/imm32/end
16037     68/push 0/imm32/start
16038     89/<- %ecx 4/r32/esp
16039     # var v/ebx: (handle var)
16040     68/push 0/imm32
16041     68/push 0/imm32
16042     89/<- %ebx 4/r32/esp
16043     # read function name
16044     (next-mu-token *(ebp+8) %ecx)
16045     # error checking
16046     # if slice-empty?(word-slice) abort
16047     (slice-empty? %ecx)  # => eax
16048     3d/compare-eax-and 0/imm32/false
16049     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
16050     # if (word-slice == '{') abort
16051     (slice-equal? %ecx "{")   # => eax
16052     3d/compare-eax-and 0/imm32/false
16053     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
16054     # if (word-slice == '->') abort
16055     (slice-equal? %ecx "->")   # => eax
16056     3d/compare-eax-and 0/imm32/false
16057     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
16058     # if (word-slice == '}') abort
16059     (slice-equal? %ecx "}")   # => eax
16060     3d/compare-eax-and 0/imm32/false
16061     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
16062     # if word-slice already defined, abort
16063     (function-exists? %ecx)  # => eax
16064     3d/compare-eax-and 0/imm32/false
16065     0f 85/jump-if-!= $populate-mu-function-header:error-duplicate/disp32
16066     #
16067     (slice-starts-with? %ecx "break")  # => eax
16068     3d/compare-eax-and 0/imm32/false
16069     0f 85/jump-if-!= $populate-mu-function-header:error-break/disp32
16070     (slice-starts-with? %ecx "loop")  # => eax
16071     3d/compare-eax-and 0/imm32/false
16072     0f 85/jump-if-!= $populate-mu-function-header:error-loop/disp32
16073     (slice-equal? %ecx "lookup")  # => eax
16074     3d/compare-eax-and 0/imm32/false
16075     0f 85/jump-if-!= $populate-mu-function-header:error-lookup/disp32
16076     # save function name
16077     (slice-to-string Heap %ecx %edi)  # Function-name
16078     # save function inouts
16079     {
16080 $populate-mu-function-header:check-for-inout:
16081       (next-mu-token *(ebp+8) %ecx)
16082       # if slice-empty?(word-slice) abort
16083       (slice-empty? %ecx)  # => eax
16084       3d/compare-eax-and 0/imm32/false
16085       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
16086       # if (word-slice == '{') goto done
16087       (slice-equal? %ecx "{")   # => eax
16088       3d/compare-eax-and 0/imm32/false
16089       0f 85/jump-if-!= $populate-mu-function-header:done/disp32
16090       # if (word-slice == '->') break
16091       (slice-equal? %ecx "->")   # => eax
16092       3d/compare-eax-and 0/imm32/false
16093       0f 85/jump-if-!= break/disp32
16094       # if (word-slice == '}') abort
16095       (slice-equal? %ecx "}")   # => eax
16096       3d/compare-eax-and 0/imm32/false
16097       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
16098       # v = parse-var-with-type(word-slice, first-line)
16099       (lookup *edi *(edi+4))  # Function-name Function-name => eax
16100       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x14) *(ebp+0x18))
16101       # if (v->register != null) abort
16102       # . eax: (addr var) = lookup(v)
16103       (lookup *ebx *(ebx+4))  # => eax
16104       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
16105       0f 85/jump-if-!= $populate-mu-function-header:error2/disp32
16106       # if function name is not "main"
16107       #    and v->type contains an 'addr' anywhere except the start, abort
16108       {
16109         (lookup *edi *(edi+4))  # Function-name Function-name => eax
16110         (string-equal? %eax "main")  # => eax
16111         3d/compare-eax-and 0/imm32/false
16112         75/jump-if-!= break/disp8
16113         (lookup *ebx *(ebx+4))  # => eax
16114         (addr-payload-contains-addr? %eax)  # => eax
16115         3d/compare-eax-and 0/imm32/false
16116         0f 85/jump-if-!= $populate-mu-function-header:error-nested-addr-inout/disp32
16117       }
16118       # v->block-depth is implicitly 0
16119       #
16120       # out->inouts = append(v, out->inouts)
16121       8d/copy-address *(edi+8) 0/r32/eax  # Function-inouts
16122       (append-list Heap  *ebx *(ebx+4)  *(edi+8) *(edi+0xc)  %eax)  # Function-inouts, Function-inouts
16123       # push(vars, {v, false})
16124       (push *(ebp+0x10) *ebx)
16125       (push *(ebp+0x10) *(ebx+4))
16126       (push *(ebp+0x10) 0)  # false
16127       #
16128       e9/jump loop/disp32
16129     }
16130     # save function outputs
16131     {
16132 $populate-mu-function-header:check-for-out:
16133       (next-mu-token *(ebp+8) %ecx)
16134       # if slice-empty?(word-slice) abort
16135       (slice-empty? %ecx)  # => eax
16136       3d/compare-eax-and 0/imm32/false
16137       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
16138       # if (word-slice == '{') break
16139       (slice-equal? %ecx "{")   # => eax
16140       3d/compare-eax-and 0/imm32/false
16141       0f 85/jump-if-!= break/disp32
16142       # if (word-slice == '->') abort
16143       (slice-equal? %ecx "->")   # => eax
16144       3d/compare-eax-and 0/imm32/false
16145       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
16146       # if (word-slice == '}') abort
16147       (slice-equal? %ecx "}")   # => eax
16148       3d/compare-eax-and 0/imm32/false
16149       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
16150       # v = parse-var-with-type(word-slice, first-line)
16151       (lookup *edi *(edi+4))  # Function-name Function-name => eax
16152       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x14) *(ebp+0x18))
16153       # assert(var->register != null)
16154       # . eax: (addr var) = lookup(v)
16155       (lookup *ebx *(ebx+4))  # => eax
16156       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
16157       0f 84/jump-if-= $populate-mu-function-header:error3/disp32
16158       # if (var->name != "_") abort
16159       (lookup *eax *(eax+4))  # Var-name Var-name => eax
16160       (string-equal? %eax "_")  # => eax
16161       3d/compare-eax-and 0/imm32/false
16162       0f 84/jump-if-= $populate-mu-function-header:error4/disp32
16163       # if v->type is an addr, abort
16164       (lookup *ebx *(ebx+4))  # => eax
16165       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
16166       (mu-addr-type? %eax)  # => eax
16167       3d/compare-eax-and 0/imm32/false
16168       0f 85/jump-if-!= $populate-mu-function-header:error-addr-output/disp32
16169       # out->outputs = append(v, out->outputs)
16170       8d/copy-address *(edi+0x10) 0/r32/eax  # Function-outputs
16171       (append-list Heap  *ebx *(ebx+4)  *(edi+0x10) *(edi+0x14)  %eax)  # Function-outputs, Function-outputs
16172       #
16173       e9/jump loop/disp32
16174     }
16175 $populate-mu-function-header:done:
16176     (check-no-tokens-left *(ebp+8))
16177 $populate-mu-function-header:end:
16178     # . reclaim locals
16179     81 0/subop/add %esp 0x10/imm32
16180     # . restore registers
16181     5f/pop-to-edi
16182     5b/pop-to-ebx
16183     5a/pop-to-edx
16184     59/pop-to-ecx
16185     58/pop-to-eax
16186     # . epilogue
16187     89/<- %esp 5/r32/ebp
16188     5d/pop-to-ebp
16189     c3/return
16190 
16191 $populate-mu-function-header:error1:
16192     # error("function header not in form 'fn <name> {'")
16193     (write-buffered *(ebp+0x14) "function header not in form 'fn <name> [inouts] [-> outputs] {' -- '")
16194     (flush *(ebp+0x14))
16195     (rewind-stream *(ebp+8))
16196     (write-stream-data *(ebp+0x14) *(ebp+8))
16197     (write-buffered *(ebp+0x14) "'\n")
16198     (flush *(ebp+0x14))
16199     (stop *(ebp+0x18) 1)
16200     # never gets here
16201 
16202 $populate-mu-function-header:error2:
16203     # error("fn " fn ": function inout '" var "' cannot be in a register")
16204     (write-buffered *(ebp+0x14) "fn ")
16205     50/push-eax
16206     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16207     (write-buffered *(ebp+0x14) %eax)
16208     58/pop-to-eax
16209     (write-buffered *(ebp+0x14) ": function inout '")
16210     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16211     (write-buffered *(ebp+0x14) %eax)
16212     (write-buffered *(ebp+0x14) "' cannot be in a register")
16213     (flush *(ebp+0x14))
16214     (stop *(ebp+0x18) 1)
16215     # never gets here
16216 
16217 $populate-mu-function-header:error3:
16218     # error("fn " fn ": function output '" var "' must be in a register")
16219     (write-buffered *(ebp+0x14) "fn ")
16220     50/push-eax
16221     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16222     (write-buffered *(ebp+0x14) %eax)
16223     58/pop-to-eax
16224     (write-buffered *(ebp+0x14) ": function output '")
16225     (lookup *ebx *(ebx+4))  # => eax
16226     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16227     (write-buffered *(ebp+0x14) %eax)
16228     (write-buffered *(ebp+0x14) "' must be in a register, in instruction '")
16229     (rewind-stream *(ebp+8))
16230     (write-stream-data *(ebp+0x14) *(ebp+8))
16231     (write-buffered *(ebp+0x14) "'\n")
16232     (flush *(ebp+0x14))
16233     (stop *(ebp+0x18) 1)
16234     # never gets here
16235 
16236 $populate-mu-function-header:error4:
16237     # error("fn " fn ": function outputs cannot be named; rename '" var "' in the header to '_'")
16238     (write-buffered *(ebp+0x14) "fn ")
16239     50/push-eax
16240     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16241     (write-buffered *(ebp+0x14) %eax)
16242     58/pop-to-eax
16243     (write-buffered *(ebp+0x14) ": function outputs cannot be named; rename '")
16244     (lookup *ebx *(ebx+4))  # => eax
16245     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16246     (write-buffered *(ebp+0x14) %eax)
16247     (write-buffered *(ebp+0x14) "' in the header to '_'\n")
16248     (flush *(ebp+0x14))
16249     (stop *(ebp+0x18) 1)
16250     # never gets here
16251 
16252 $populate-mu-function-header:error-duplicate:
16253     (write-buffered *(ebp+0x14) "fn ")
16254     (write-slice-buffered *(ebp+0x14) %ecx)
16255     (write-buffered *(ebp+0x14) " defined more than once\n")
16256     (flush *(ebp+0x14))
16257     (stop *(ebp+0x18) 1)
16258     # never gets here
16259 
16260 $populate-mu-function-header:error-break:
16261     (write-buffered *(ebp+0x14) "Sorry, I've reserved all function names starting with 'break' for now. Please contact mu@akkartik.com.\n")
16262     (flush *(ebp+0x14))
16263     (stop *(ebp+0x18) 1)
16264     # never gets here
16265 
16266 $populate-mu-function-header:error-loop:
16267     (write-buffered *(ebp+0x14) "Sorry, I've reserved all function names starting with 'loop' for now. Please contact mu@akkartik.com.\n")
16268     (flush *(ebp+0x14))
16269     (stop *(ebp+0x18) 1)
16270     # never gets here
16271 
16272 $populate-mu-function-header:error-lookup:
16273     (write-buffered *(ebp+0x14) "cannot define a function called 'lookup'\n")
16274     (flush *(ebp+0x14))
16275     (stop *(ebp+0x18) 1)
16276     # never gets here
16277 
16278 $populate-mu-function-header:error-addr-output:
16279     # error("fn " fn ": output cannot have an addr type; that could allow unsafe addresses to escape the function")
16280     (write-buffered *(ebp+0x14) "fn ")
16281     50/push-eax
16282     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16283     (write-buffered *(ebp+0x14) %eax)
16284     58/pop-to-eax
16285     (write-buffered *(ebp+0x14) ": output cannot have an addr type; that could allow unsafe addresses to escape the function\n")
16286     (flush *(ebp+0x14))
16287     (stop *(ebp+0x18) 1)
16288     # never gets here
16289 
16290 $populate-mu-function-header:error-nested-addr-inout:
16291     # 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")
16292     (write-buffered *(ebp+0x14) "fn ")
16293     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16294     (write-buffered *(ebp+0x14) %eax)
16295     (write-buffered *(ebp+0x14) ": inout '")
16296     (lookup *ebx *(ebx+4))  # => eax
16297     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16298     (write-buffered *(ebp+0x14) %eax)
16299     (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")
16300     (flush *(ebp+0x14))
16301     (stop *(ebp+0x18) 1)
16302     # never gets here
16303 
16304 # scenarios considered:
16305 # ✓ fn foo
16306 # ✗ fn foo {
16307 # ✓ fn foo x
16308 # ✓ fn foo x: int
16309 # ✓ fn foo x: int -> _/eax: int
16310 # TODO:
16311 #   disallow outputs of type `(... addr ...)`
16312 #   disallow inputs of type `(... addr ... addr ...)`
16313 populate-mu-function-signature:  # first-line: (addr stream byte), out: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
16314     # pseudocode:
16315     #   var word-slice: slice
16316     #   next-mu-token(first-line, word-slice)
16317     #   assert(word-slice not in '{' '}' '->')
16318     #   out->name = slice-to-string(word-slice)
16319     #   ## inouts
16320     #   while true
16321     #     word-slice = next-mu-token(first-line)
16322     #     if slice-empty?(word-slice) break
16323     #     if (word-slice == '->') break
16324     #     assert(word-slice not in '{' '}')
16325     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
16326     #     assert(v->register == null)
16327     #     # v->block-depth is implicitly 0
16328     #     out->inouts = append(v, out->inouts)
16329     #   ## outputs
16330     #   while true
16331     #     word-slice = next-mu-token(first-line)
16332     #     if slice-empty?(word-slice) break
16333     #     assert(word-slice not in '{' '}' '->')
16334     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
16335     #     assert(v->register != null)
16336     #     out->outputs = append(v, out->outputs)
16337     #
16338     # . prologue
16339     55/push-ebp
16340     89/<- %ebp 4/r32/esp
16341     # . save registers
16342     50/push-eax
16343     51/push-ecx
16344     52/push-edx
16345     53/push-ebx
16346     57/push-edi
16347     # edi = out
16348     8b/-> *(ebp+0xc) 7/r32/edi
16349     # var word-slice/ecx: slice
16350     68/push 0/imm32/end
16351     68/push 0/imm32/start
16352     89/<- %ecx 4/r32/esp
16353     # var v/ebx: (handle var)
16354     68/push 0/imm32
16355     68/push 0/imm32
16356     89/<- %ebx 4/r32/esp
16357     # read function name
16358     (next-mu-token *(ebp+8) %ecx)
16359     # error checking
16360     # if (word-slice == '{') abort
16361     (slice-equal? %ecx "{")   # => eax
16362     3d/compare-eax-and 0/imm32/false
16363     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
16364     # if (word-slice == '->') abort
16365     (slice-equal? %ecx "->")   # => eax
16366     3d/compare-eax-and 0/imm32/false
16367     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
16368     # if (word-slice == '}') abort
16369     (slice-equal? %ecx "}")   # => eax
16370     3d/compare-eax-and 0/imm32/false
16371     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
16372     # if word-slice already defined, abort
16373     (function-exists? %ecx)  # => eax
16374     3d/compare-eax-and 0/imm32/false
16375     0f 85/jump-if-!= $populate-mu-function-signature:error-duplicate/disp32
16376     #
16377     (slice-starts-with? %ecx "break")  # => eax
16378     3d/compare-eax-and 0/imm32/false
16379     0f 85/jump-if-!= $populate-mu-function-signature:error-break/disp32
16380     (slice-starts-with? %ecx "loop")  # => eax
16381     3d/compare-eax-and 0/imm32/false
16382     0f 85/jump-if-!= $populate-mu-function-signature:error-loop/disp32
16383     # save function name
16384     (slice-to-string Heap %ecx %edi)  # Function-name
16385     # save function inouts
16386     {
16387 $populate-mu-function-signature:check-for-inout:
16388       (next-mu-token *(ebp+8) %ecx)
16389       (slice-empty? %ecx)  # => eax
16390       3d/compare-eax-and 0/imm32/false
16391       0f 85/jump-if-!= break/disp32
16392       # if (word-slice == '->') break
16393       (slice-equal? %ecx "->")   # => eax
16394       3d/compare-eax-and 0/imm32/false
16395       0f 85/jump-if-!= break/disp32
16396       # if (word-slice == '{') abort
16397       (slice-equal? %ecx "{")   # => eax
16398       3d/compare-eax-and 0/imm32/false
16399       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
16400       # if (word-slice == '}') abort
16401       (slice-equal? %ecx "}")   # => eax
16402       3d/compare-eax-and 0/imm32/false
16403       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
16404       # v = parse-var-with-type(word-slice, first-line)
16405       (lookup *edi *(edi+4))  # Function-name Function-name => eax
16406       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x10) *(ebp+0x14))
16407       # if (v->register != null) abort
16408       # . eax: (addr var) = lookup(v)
16409       (lookup *ebx *(ebx+4))  # => eax
16410       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
16411       0f 85/jump-if-!= $populate-mu-function-signature:error2/disp32
16412       # if function name is not "main"
16413       #    and v->type contains an 'addr' anywhere except the start, abort
16414       {
16415         (lookup *edi *(edi+4))  # Function-name Function-name => eax
16416         (string-equal? %eax "main")  # => eax
16417         3d/compare-eax-and 0/imm32/false
16418         75/jump-if-!= break/disp8
16419         (lookup *ebx *(ebx+4))  # => eax
16420         (addr-payload-contains-addr? %eax)  # => eax
16421         3d/compare-eax-and 0/imm32/false
16422         0f 85/jump-if-!= $populate-mu-function-signature:error-nested-addr-inout/disp32
16423       }
16424       # assert(v->register == null)
16425       # . eax: (addr var) = lookup(v)
16426       (lookup *ebx *(ebx+4))  # => eax
16427       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
16428       0f 85/jump-if-!= $populate-mu-function-signature:error2/disp32
16429       # v->block-depth is implicitly 0
16430       #
16431       # out->inouts = append(v, out->inouts)
16432       8d/copy-address *(edi+8) 0/r32/eax  # Function-inouts
16433       (append-list Heap  *ebx *(ebx+4)  *(edi+8) *(edi+0xc)  %eax)  # Function-inouts, Function-inouts
16434       #
16435       e9/jump loop/disp32
16436     }
16437     # save function outputs
16438     {
16439 $populate-mu-function-signature:check-for-out:
16440       (next-mu-token *(ebp+8) %ecx)
16441       (slice-empty? %ecx)  # => eax
16442       3d/compare-eax-and 0/imm32/false
16443       0f 85/jump-if-!= break/disp32
16444       # if (word-slice == '{') abort
16445       (slice-equal? %ecx "{")   # => eax
16446       3d/compare-eax-and 0/imm32/false
16447       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
16448       # if (word-slice == '->') abort
16449       (slice-equal? %ecx "->")   # => eax
16450       3d/compare-eax-and 0/imm32/false
16451       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
16452       # if (word-slice == '}') abort
16453       (slice-equal? %ecx "}")   # => eax
16454       3d/compare-eax-and 0/imm32/false
16455       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
16456       # v = parse-var-with-type(word-slice, first-line)
16457       (lookup *edi *(edi+4))  # Function-name Function-name => eax
16458       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x10) *(ebp+0x14))
16459       # assert(var->register != null)
16460       # . eax: (addr var) = lookup(v)
16461       (lookup *ebx *(ebx+4))  # => eax
16462       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
16463       0f 84/jump-if-= $populate-mu-function-signature:error3/disp32
16464       # if (var->name != "_") abort
16465       (lookup *eax *(eax+4))  # Var-name Var-name => eax
16466       (string-equal? %eax "_")  # => eax
16467       3d/compare-eax-and 0/imm32/false
16468       0f 84/jump-if-= $populate-mu-function-signature:error4/disp32
16469       # if function name is not "lookup"
16470       #    and v->type is an addr, abort
16471       {
16472         (lookup *edi *(edi+4))  # Function-name Function-name => eax
16473         (string-equal? %eax "lookup")  # => eax
16474         3d/compare-eax-and 0/imm32/false
16475         75/jump-if-!= break/disp8
16476         (lookup *ebx *(ebx+4))  # => eax
16477         (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
16478         (mu-addr-type? %eax)  # => eax
16479         3d/compare-eax-and 0/imm32/false
16480         0f 85/jump-if-!= $populate-mu-function-signature:error-addr-output/disp32
16481       }
16482       # out->outputs = append(v, out->outputs)
16483       8d/copy-address *(edi+0x10) 0/r32/eax  # Function-outputs
16484       (append-list Heap  *ebx *(ebx+4)  *(edi+0x10) *(edi+0x14)  %eax)  # Function-outputs, Function-outputs
16485       #
16486       e9/jump loop/disp32
16487     }
16488 $populate-mu-function-signature:done:
16489     (check-no-tokens-left *(ebp+8))
16490 $populate-mu-function-signature:end:
16491     # . reclaim locals
16492     81 0/subop/add %esp 0x10/imm32
16493     # . restore registers
16494     5f/pop-to-edi
16495     5b/pop-to-ebx
16496     5a/pop-to-edx
16497     59/pop-to-ecx
16498     58/pop-to-eax
16499     # . epilogue
16500     89/<- %esp 5/r32/ebp
16501     5d/pop-to-ebp
16502     c3/return
16503 
16504 $populate-mu-function-signature:error1:
16505     # error("function signature not in form 'fn <name> {'")
16506     (write-buffered *(ebp+0x10) "function signature not in form 'fn <name> [inouts] [-> outputs] {' -- '")
16507     (flush *(ebp+0x10))
16508     (rewind-stream *(ebp+8))
16509     (write-stream-data *(ebp+0x10) *(ebp+8))
16510     (write-buffered *(ebp+0x10) "'\n")
16511     (flush *(ebp+0x10))
16512     (stop *(ebp+0x14) 1)
16513     # never gets here
16514 
16515 $populate-mu-function-signature:error2:
16516     # error("fn " fn ": function inout '" var "' cannot be in a register")
16517     (write-buffered *(ebp+0x10) "fn ")
16518     50/push-eax
16519     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16520     (write-buffered *(ebp+0x10) %eax)
16521     58/pop-to-eax
16522     (write-buffered *(ebp+0x10) ": function inout '")
16523     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16524     (write-buffered *(ebp+0x10) %eax)
16525     (write-buffered *(ebp+0x10) "' cannot be in a register")
16526     (flush *(ebp+0x10))
16527     (stop *(ebp+0x14) 1)
16528     # never gets here
16529 
16530 $populate-mu-function-signature:error3:
16531     # error("fn " fn ": function output '" var "' must be in a register")
16532     (write-buffered *(ebp+0x10) "fn ")
16533     50/push-eax
16534     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16535     (write-buffered *(ebp+0x10) %eax)
16536     58/pop-to-eax
16537     (write-buffered *(ebp+0x10) ": function output '")
16538     (lookup *ebx *(ebx+4))  # => eax
16539     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16540     (write-buffered *(ebp+0x10) %eax)
16541     (write-buffered *(ebp+0x10) "' must be in a register, in instruction '")
16542     (rewind-stream *(ebp+8))
16543     (write-stream-data *(ebp+0x10) *(ebp+8))
16544     (write-buffered *(ebp+0x10) "'\n")
16545     (flush *(ebp+0x10))
16546     (stop *(ebp+0x14) 1)
16547     # never gets here
16548 
16549 $populate-mu-function-signature:error4:
16550     # error("fn " fn ": function outputs cannot be named; rename '" var "' in the header to '_'")
16551     (write-buffered *(ebp+0x10) "fn ")
16552     50/push-eax
16553     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16554     (write-buffered *(ebp+0x10) %eax)
16555     58/pop-to-eax
16556     (write-buffered *(ebp+0x10) ": function outputs cannot be named; rename '")
16557     (lookup *ebx *(ebx+4))  # => eax
16558     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16559     (write-buffered *(ebp+0x10) %eax)
16560     (write-buffered *(ebp+0x10) "' in the header to '_'\n")
16561     (flush *(ebp+0x10))
16562     (stop *(ebp+0x14) 1)
16563     # never gets here
16564 
16565 $populate-mu-function-signature:error-duplicate:
16566     (write-buffered *(ebp+0x10) "fn ")
16567     (write-slice-buffered *(ebp+0x10) %ecx)
16568     (write-buffered *(ebp+0x10) " defined more than once\n")
16569     (flush *(ebp+0x10))
16570     (stop *(ebp+0x14) 1)
16571     # never gets here
16572 
16573 $populate-mu-function-signature:error-break:
16574     (write-buffered *(ebp+0x10) "Sorry, I've reserved all function names starting with 'break' for now. Please contact mu@akkartik.com.\n")
16575     (flush *(ebp+0x10))
16576     (stop *(ebp+0x14) 1)
16577     # never gets here
16578 
16579 $populate-mu-function-signature:error-loop:
16580     (write-buffered *(ebp+0x10) "Sorry, I've reserved all function names starting with 'loop' for now. Please contact mu@akkartik.com.\n")
16581     (flush *(ebp+0x10))
16582     (stop *(ebp+0x14) 1)
16583     # never gets here
16584 
16585 $populate-mu-function-signature:error-addr-output:
16586     # error("fn " fn ": output cannot have an addr type; that could allow unsafe addresses to escape the function")
16587     (write-buffered *(ebp+0x10) "fn ")
16588     50/push-eax
16589     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16590     (write-buffered *(ebp+0x10) %eax)
16591     58/pop-to-eax
16592     (write-buffered *(ebp+0x10) ": output cannot have an addr type; that could allow unsafe addresses to escape the function\n")
16593     (flush *(ebp+0x10))
16594     (stop *(ebp+0x14) 1)
16595     # never gets here
16596 
16597 $populate-mu-function-signature:error-nested-addr-inout:
16598     # 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")
16599     (write-buffered *(ebp+0x10) "fn ")
16600     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16601     (write-buffered *(ebp+0x10) %eax)
16602     (write-buffered *(ebp+0x10) ": inout '")
16603     (lookup *ebx *(ebx+4))  # => eax
16604     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16605     (write-buffered *(ebp+0x10) %eax)
16606     (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")
16607     (flush *(ebp+0x10))
16608     (stop *(ebp+0x14) 1)
16609     # never gets here
16610 
16611 addr-payload-contains-addr?:  # v: (addr var) -> result/eax: boolean
16612     # . prologue
16613     55/push-ebp
16614     89/<- %ebp 4/r32/esp
16615     # var t/eax: (addr type-tree) = v->type
16616     8b/-> *(ebp+8) 0/r32/eax
16617     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
16618     # if t->right contains addr, return true
16619     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
16620     (type-tree-contains? %eax 2)  # addr => eax
16621     # we don't have to look at t->left as long as it's guaranteed to be an atom
16622 $addr-payload-contains-addr?:end:
16623     # . epilogue
16624     89/<- %esp 5/r32/ebp
16625     5d/pop-to-ebp
16626     c3/return
16627 
16628 type-tree-contains?:  # t: (addr type-tree), n: type-id -> result/eax: boolean
16629     # . prologue
16630     55/push-ebp
16631     89/<- %ebp 4/r32/esp
16632     # . save registers
16633     51/push-ecx
16634     # if t is null, return false
16635     8b/-> *(ebp+8) 0/r32/eax
16636     3d/compare-eax-and 0/imm32
16637     0f 84/jump-if-= $type-tree-contains?:end/disp32  # eax changes type
16638     # if t is an atom, return (t->value == n)
16639     81 7/subop/compare *eax 0/imm32/false
16640     {
16641       74/jump-if-= break/disp8
16642       8b/-> *(ebp+0xc) 1/r32/ecx
16643       39/compare *(eax+4) 1/r32/ecx  # Type-tree-value
16644       0f 94/set-if-= %al
16645       25/and-eax-with 0xff/imm32
16646       eb/jump $type-tree-contains?:end/disp8
16647     }
16648     # if t->left contains n, return true
16649     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
16650     (type-tree-contains? %eax *(ebp+0xc))  # => eax
16651     3d/compare-eax-and 0/imm32/false
16652     75/jump-if-!= $type-tree-contains?:end/disp8
16653     # otherwise return whether t->right contains n
16654     8b/-> *(ebp+8) 0/r32/eax
16655     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
16656     (type-tree-contains? %eax *(ebp+0xc))  # => eax
16657 $type-tree-contains?:end:
16658     # . restore registers
16659     59/pop-to-ecx
16660     # . epilogue
16661     89/<- %esp 5/r32/ebp
16662     5d/pop-to-ebp
16663     c3/return
16664 
16665 function-exists?:  # s: (addr slice) -> result/eax: boolean
16666     # . prologue
16667     55/push-ebp
16668     89/<- %ebp 4/r32/esp
16669     # . save registers
16670     51/push-ecx
16671     # var curr/ecx: (addr function) = functions
16672     (lookup *_Program-functions *_Program-functions->payload)  # => eax
16673     89/<- %ecx 0/r32/eax
16674     {
16675       # if (curr == null) break
16676       81 7/subop/compare %ecx 0/imm32
16677       74/jump-if-= break/disp8
16678       # if (curr->name == s) return true
16679       {
16680         (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
16681         (slice-equal? *(ebp+8) %eax)  # => eax
16682         3d/compare-eax-and 0/imm32/false
16683         74/jump-if-= break/disp8
16684         b8/copy-to-eax 1/imm32/true
16685         e9/jump $function-exists?:end/disp32
16686       }
16687       # curr = curr->next
16688       (lookup *(ecx+0x20) *(ecx+0x24))  # Function-next Function-next => eax
16689       89/<- %ecx 0/r32/eax
16690       #
16691       eb/jump loop/disp8
16692     }
16693     # var curr/ecx: (addr function) = signatures
16694     (lookup *_Program-signatures *_Program-signatures->payload)  # => eax
16695     89/<- %ecx 0/r32/eax
16696     {
16697       # if (curr == null) break
16698       81 7/subop/compare %ecx 0/imm32
16699       74/jump-if-= break/disp8
16700       # if (curr->name == s) return true
16701       {
16702         (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
16703         (slice-equal? *(ebp+8) %eax)  # => eax
16704         3d/compare-eax-and 0/imm32/false
16705         74/jump-if-= break/disp8
16706         b8/copy-to-eax 1/imm32/true
16707         eb/jump $function-exists?:end/disp8
16708       }
16709       # curr = curr->next
16710       (lookup *(ecx+0x20) *(ecx+0x24))  # Function-next Function-next => eax
16711       89/<- %ecx 0/r32/eax
16712       #
16713       eb/jump loop/disp8
16714     }
16715     # return false
16716     b8/copy-to-eax 0/imm32/false
16717 $function-exists?:end:
16718     # . restore registers
16719     59/pop-to-ecx
16720     # . epilogue
16721     89/<- %esp 5/r32/ebp
16722     5d/pop-to-ebp
16723     c3/return
16724 
16725 test-function-header-with-arg:
16726     # . prologue
16727     55/push-ebp
16728     89/<- %ebp 4/r32/esp
16729     # setup
16730     8b/-> *Primitive-type-ids 0/r32/eax
16731     89/<- *Type-id 0/r32/eax  # stream-write
16732     c7 0/subop/copy *_Program-functions 0/imm32
16733     c7 0/subop/copy *_Program-functions->payload 0/imm32
16734     c7 0/subop/copy *_Program-types 0/imm32
16735     c7 0/subop/copy *_Program-types->payload 0/imm32
16736     c7 0/subop/copy *_Program-signatures 0/imm32
16737     c7 0/subop/copy *_Program-signatures->payload 0/imm32
16738     (clear-stream _test-input-stream)
16739     (write _test-input-stream "foo n: int {\n")
16740     # var result/ecx: function
16741     2b/subtract *Function-size 4/r32/esp
16742     89/<- %ecx 4/r32/esp
16743     (zero-out %ecx *Function-size)
16744     # var vars/ebx: (stack live-var 16)
16745     81 5/subop/subtract %esp 0xc0/imm32
16746     68/push 0xc0/imm32/size
16747     68/push 0/imm32/top
16748     89/<- %ebx 4/r32/esp
16749     # convert
16750     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
16751     # check result->name
16752     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
16753     (check-strings-equal %eax "foo" "F - test-function-header-with-arg/name")
16754     # var v/edx: (addr var) = result->inouts->value
16755     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
16756     (lookup *eax *(eax+4))  # List-value List-value => eax
16757     89/<- %edx 0/r32/eax
16758     # check v->name
16759     (lookup *edx *(edx+4))  # Var-name Var-name => eax
16760     (check-strings-equal %eax "n" "F - test-function-header-with-arg/inout:0")
16761     # check v->type
16762     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
16763     (check-ints-equal *eax 1 "F - test-function-header-with-arg/inout:0/type:0")  # Type-tree-is-atom
16764     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-arg/inout:0/type:1")  # Type-tree-value
16765     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-arg/inout:0/type:2")  # Type-tree-right
16766     # . epilogue
16767     89/<- %esp 5/r32/ebp
16768     5d/pop-to-ebp
16769     c3/return
16770 
16771 test-function-header-with-multiple-args:
16772     # . prologue
16773     55/push-ebp
16774     89/<- %ebp 4/r32/esp
16775     # setup
16776     8b/-> *Primitive-type-ids 0/r32/eax
16777     89/<- *Type-id 0/r32/eax  # stream-write
16778     c7 0/subop/copy *_Program-functions 0/imm32
16779     c7 0/subop/copy *_Program-functions->payload 0/imm32
16780     c7 0/subop/copy *_Program-types 0/imm32
16781     c7 0/subop/copy *_Program-types->payload 0/imm32
16782     c7 0/subop/copy *_Program-signatures 0/imm32
16783     c7 0/subop/copy *_Program-signatures->payload 0/imm32
16784     (clear-stream _test-input-stream)
16785     (write _test-input-stream "foo a: int, b: int c: int {\n")
16786     # result/ecx: function
16787     2b/subtract *Function-size 4/r32/esp
16788     89/<- %ecx 4/r32/esp
16789     (zero-out %ecx *Function-size)
16790     # var vars/ebx: (stack live-var 16)
16791     81 5/subop/subtract %esp 0xc0/imm32
16792     68/push 0xc0/imm32/size
16793     68/push 0/imm32/top
16794     89/<- %ebx 4/r32/esp
16795     # convert
16796     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
16797     # check result->name
16798     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
16799     (check-strings-equal %eax "foo" "F - test-function-header-with-multiple-args/name")
16800     # var inouts/edx: (addr list var) = lookup(result->inouts)
16801     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
16802     89/<- %edx 0/r32/eax
16803 $test-function-header-with-multiple-args:inout0:
16804     # var v/ebx: (addr var) = lookup(inouts->value)
16805     (lookup *edx *(edx+4))  # List-value List-value => eax
16806     89/<- %ebx 0/r32/eax
16807     # check v->name
16808     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
16809     (check-strings-equal %eax "a" "F - test-function-header-with-multiple-args/inout:0")  # Var-name
16810     # check v->type
16811     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
16812     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:0/type:0")  # Type-tree-is-atom
16813     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:0/type:1")  # Type-tree-value
16814     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:0/type:2")  # Type-tree-right
16815 $test-function-header-with-multiple-args:inout1:
16816     # inouts = lookup(inouts->next)
16817     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
16818     89/<- %edx 0/r32/eax
16819     # v = lookup(inouts->value)
16820     (lookup *edx *(edx+4))  # List-value List-value => eax
16821     89/<- %ebx 0/r32/eax
16822     # check v->name
16823     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
16824     (check-strings-equal %eax "b" "F - test-function-header-with-multiple-args/inout:1")  # Var-name
16825     # check v->type
16826     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
16827     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:1/type:0")  # Type-tree-is-atom
16828     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:1/type:1")  # Type-tree-value
16829     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:1/type:2")  # Type-tree-right
16830 $test-function-header-with-multiple-args:inout2:
16831     # inouts = lookup(inouts->next)
16832     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
16833     89/<- %edx 0/r32/eax
16834     # v = lookup(inouts->value)
16835     (lookup *edx *(edx+4))  # List-value List-value => eax
16836     89/<- %ebx 0/r32/eax
16837     # check v->name
16838     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
16839     (check-strings-equal %eax "c" "F - test-function-header-with-multiple-args/inout:2")  # Var-name
16840     # check v->type
16841     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
16842     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:2/type:0")  # Type-tree-is-atom
16843     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:2/type:1")  # Type-tree-value
16844     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:2/type:2")  # Type-tree-right
16845     # . epilogue
16846     89/<- %esp 5/r32/ebp
16847     5d/pop-to-ebp
16848     c3/return
16849 
16850 test-function-header-with-multiple-args-and-outputs:
16851     # . prologue
16852     55/push-ebp
16853     89/<- %ebp 4/r32/esp
16854     # setup
16855     8b/-> *Primitive-type-ids 0/r32/eax
16856     89/<- *Type-id 0/r32/eax  # stream-write
16857     c7 0/subop/copy *_Program-functions 0/imm32
16858     c7 0/subop/copy *_Program-functions->payload 0/imm32
16859     c7 0/subop/copy *_Program-types 0/imm32
16860     c7 0/subop/copy *_Program-types->payload 0/imm32
16861     c7 0/subop/copy *_Program-signatures 0/imm32
16862     c7 0/subop/copy *_Program-signatures->payload 0/imm32
16863     (clear-stream _test-input-stream)
16864     (write _test-input-stream "foo a: int, b: int, c: int -> _/ecx: int _/edx: int {\n")
16865     # result/ecx: function
16866     2b/subtract *Function-size 4/r32/esp
16867     89/<- %ecx 4/r32/esp
16868     (zero-out %ecx *Function-size)
16869     # var vars/ebx: (stack live-var 16)
16870     81 5/subop/subtract %esp 0xc0/imm32
16871     68/push 0xc0/imm32/size
16872     68/push 0/imm32/top
16873     89/<- %ebx 4/r32/esp
16874     # convert
16875     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
16876     # check result->name
16877     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
16878     (check-strings-equal %eax "foo" "F - test-function-header-with-multiple-args-and-outputs/name")
16879     # var inouts/edx: (addr list var) = lookup(result->inouts)
16880     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
16881     89/<- %edx 0/r32/eax
16882 $test-function-header-with-multiple-args-and-outputs:inout0:
16883     # var v/ebx: (addr var) = lookup(inouts->value)
16884     (lookup *edx *(edx+4))  # List-value List-value => eax
16885     89/<- %ebx 0/r32/eax
16886     # check v->name
16887     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
16888     (check-strings-equal %eax "a" "F - test-function-header-with-multiple-args-and-outputs/inout:0")
16889     # check v->type
16890     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
16891     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:0")  # Type-tree-is-atom
16892     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:1")  # Type-tree-value
16893     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:2")  # Type-tree-right
16894 $test-function-header-with-multiple-args-and-outputs:inout1:
16895     # inouts = lookup(inouts->next)
16896     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
16897     89/<- %edx 0/r32/eax
16898     # v = lookup(inouts->value)
16899     (lookup *edx *(edx+4))  # List-value List-value => eax
16900     89/<- %ebx 0/r32/eax
16901     # check v->name
16902     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
16903     (check-strings-equal %eax "b" "F - test-function-header-with-multiple-args-and-outputs/inout:1")
16904     # check v->type
16905     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
16906     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:0")  # Type-tree-is-atom
16907     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:1")  # Type-tree-value
16908     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:2")  # Type-tree-right
16909 $test-function-header-with-multiple-args-and-outputs:inout2:
16910     # inouts = lookup(inouts->next)
16911     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
16912     89/<- %edx 0/r32/eax
16913     # v = lookup(inouts->value)
16914     (lookup *edx *(edx+4))  # List-value List-value => eax
16915     89/<- %ebx 0/r32/eax
16916     # check v->name
16917     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
16918     (check-strings-equal %eax "c" "F - test-function-header-with-multiple-args-and-outputs/inout:2")
16919     # check v->type
16920     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
16921     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:0")  # Type-tree-is-atom
16922     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:1")  # Type-tree-value
16923     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:2")  # Type-tree-right
16924 $test-function-header-with-multiple-args-and-outputs:out0:
16925     # var outputs/edx: (addr list var) = lookup(result->outputs)
16926     (lookup *(ecx+0x10) *(ecx+0x14))  # Function-outputs Function-outputs => eax
16927     89/<- %edx 0/r32/eax
16928     # v = lookup(outputs->value)
16929     (lookup *edx *(edx+4))  # List-value List-value => eax
16930     89/<- %ebx 0/r32/eax
16931     # check v->name
16932     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
16933     (check-strings-equal %eax "_" "F - test-function-header-with-multiple-args-and-outputs/output:0")
16934     # check v->register
16935     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
16936     (check-strings-equal %eax "ecx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register")
16937     # check v->type
16938     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
16939     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:0")  # Type-tree-is-atom
16940     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1")  # Type-tree-value
16941     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:2")  # Type-tree-right
16942 $test-function-header-with-multiple-args-and-outputs:out1:
16943     # outputs = lookup(outputs->next)
16944     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
16945     89/<- %edx 0/r32/eax
16946     # v = lookup(inouts->value)
16947     (lookup *edx *(edx+4))  # List-value List-value => eax
16948     89/<- %ebx 0/r32/eax
16949     # check v->name
16950     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
16951     (check-strings-equal %eax "_" "F - test-function-header-with-multiple-args-and-outputs/output:1")
16952     # check v->register
16953     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
16954     (check-strings-equal %eax "edx" "F - test-function-header-with-multiple-args-and-outputs/output:1/register")
16955     # check v->type
16956     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
16957     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:0")  # Type-tree-is-atom
16958     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1")  # Type-tree-value
16959     (check-ints-equal *(eax+0c) 0 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:2")  # Type-tree-right
16960     # . epilogue
16961     89/<- %esp 5/r32/ebp
16962     5d/pop-to-ebp
16963     c3/return
16964 
16965 # format for variables with types
16966 #   x: int
16967 #   x: int,
16968 #   x/eax: int
16969 #   x/eax: int,
16970 # ignores at most one trailing comma
16971 # does not support other, non-register metadata
16972 # WARNING: modifies name
16973 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)
16974     # pseudocode:
16975     #   var s: slice
16976     #   if (!slice-ends-with(name, ":"))
16977     #     abort
16978     #   --name->end to skip ':'
16979     #   next-token-from-slice(name->start, name->end, '/', s)
16980     #   new-var-from-slice(s, out)
16981     #   ## register
16982     #   next-token-from-slice(s->end, name->end, '/', s)
16983     #   if (!slice-empty?(s))
16984     #     out->register = slice-to-string(s)
16985     #   ## type
16986     #   var type: (handle type-tree) = parse-type(first-line)
16987     #   out->type = type
16988     #
16989     # . prologue
16990     55/push-ebp
16991     89/<- %ebp 4/r32/esp
16992     # . save registers
16993     50/push-eax
16994     51/push-ecx
16995     52/push-edx
16996     53/push-ebx
16997     56/push-esi
16998     57/push-edi
16999     # esi = name
17000     8b/-> *(ebp+8) 6/r32/esi
17001     # if (!slice-ends-with?(name, ":")) abort
17002     8b/-> *(esi+4) 1/r32/ecx  # Slice-end
17003     49/decrement-ecx
17004     8a/copy-byte *ecx 1/r32/CL
17005     81 4/subop/and %ecx 0xff/imm32
17006     81 7/subop/compare %ecx 0x3a/imm32/colon
17007     0f 85/jump-if-!= $parse-var-with-type:abort/disp32
17008     # --name->end to skip ':'
17009     ff 1/subop/decrement *(esi+4)
17010     # var s/ecx: slice
17011     68/push 0/imm32/end
17012     68/push 0/imm32/start
17013     89/<- %ecx 4/r32/esp
17014 $parse-var-with-type:parse-name:
17015     (next-token-from-slice *esi *(esi+4) 0x2f %ecx)  # Slice-start, Slice-end, '/'
17016 $parse-var-with-type:create-var:
17017     # new-var-from-slice(s, out)
17018     (new-var-from-slice Heap %ecx *(ebp+0x10))
17019     # save out->register
17020 $parse-var-with-type:save-register:
17021     # . var out-addr/edi: (addr var) = lookup(*out)
17022     8b/-> *(ebp+0x10) 7/r32/edi
17023     (lookup *edi *(edi+4))  # => eax
17024     89/<- %edi 0/r32/eax
17025     # . s = next-token(...)
17026     (next-token-from-slice *(ecx+4) *(esi+4) 0x2f %ecx)  # s->end, name->end, '/'
17027     # . if (!slice-empty?(s)) out->register = slice-to-string(s)
17028     {
17029 $parse-var-with-type:write-register:
17030       (slice-empty? %ecx)  # => eax
17031       3d/compare-eax-and 0/imm32/false
17032       75/jump-if-!= break/disp8
17033       # out->register = slice-to-string(s)
17034       8d/copy-address *(edi+0x18) 0/r32/eax  # Var-register
17035       (slice-to-string Heap %ecx %eax)
17036     }
17037 $parse-var-with-type:save-type:
17038     8d/copy-address *(edi+8) 0/r32/eax  # Var-type
17039     (parse-type Heap *(ebp+0xc) %eax *(ebp+0x18) *(ebp+0x1c))
17040 $parse-var-with-type:check-register:
17041     (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
17042     3d/compare-eax-and 0/imm32
17043     74/jump-if-= $parse-var-with-type:end/disp8
17044     (float-register? %eax)  # => eax
17045     {
17046       3d/compare-eax-and 0/imm32/false
17047       74/jump-if-= break/disp8
17048       # var is in a float register; ensure type is float
17049       (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
17050       (simple-mu-type? %eax 0xf)  # float => eax
17051       3d/compare-eax-and 0/imm32/false
17052       0f 84/jump-if-= $parse-var-with-type:error-non-float-in-floating-point-register/disp32
17053       eb/jump $parse-var-with-type:end/disp8
17054     }
17055     # var is not in a float register; ensure type is not float
17056     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
17057     (simple-mu-type? %eax 0xf)  # float => eax
17058     3d/compare-eax-and 0/imm32/false
17059     0f 85/jump-if-!= $parse-var-with-type:error-float-in-integer-register/disp32
17060 $parse-var-with-type:end:
17061     # . reclaim locals
17062     81 0/subop/add %esp 8/imm32
17063     # . restore registers
17064     5f/pop-to-edi
17065     5e/pop-to-esi
17066     5b/pop-to-ebx
17067     5a/pop-to-edx
17068     59/pop-to-ecx
17069     58/pop-to-eax
17070     # . epilogue
17071     89/<- %esp 5/r32/ebp
17072     5d/pop-to-ebp
17073     c3/return
17074 
17075 $parse-var-with-type:abort:
17076     # error("fn " fn ": var should have form 'name: type' in '" line "'\n")
17077     (write-buffered *(ebp+0x18) "fn ")
17078     (write-buffered *(ebp+0x18) *(ebp+0x14))
17079     (write-buffered *(ebp+0x18) ": var should have form 'name: type' in '")
17080     (flush *(ebp+0x18))
17081     (rewind-stream *(ebp+0xc))
17082     (write-stream-data *(ebp+0x18) *(ebp+0xc))
17083     (write-buffered *(ebp+0x18) "'\n")
17084     (flush *(ebp+0x18))
17085     (stop *(ebp+0x1c) 1)
17086     # never gets here
17087 
17088 $parse-var-with-type:error-float-in-integer-register:
17089     # error("fn " fn ": float var '" var "' should be in a floating-point register\n")
17090     (write-buffered *(ebp+0x18) "fn ")
17091     (write-buffered *(ebp+0x18) *(ebp+0x14))
17092     (write-buffered *(ebp+0x18) ": float var '")
17093     (lookup *edi *(edi+4))  # Var-name Var-name => eax
17094     (write-buffered *(ebp+0x18) %eax)
17095     (write-buffered *(ebp+0x18) "' should be in a floating-point register\n")
17096     (flush *(ebp+0x18))
17097     (stop *(ebp+0x1c) 1)
17098     # never gets here
17099 
17100 $parse-var-with-type:error-non-float-in-floating-point-register:
17101     # error("fn " fn ": non-float var '" var "' should be in an integer register\n")
17102     (write-buffered *(ebp+0x18) "fn ")
17103     (write-buffered *(ebp+0x18) *(ebp+0x14))
17104     (write-buffered *(ebp+0x18) ": non-float var '")
17105     (lookup *edi *(edi+4))  # Var-name Var-name => eax
17106     (write-buffered *(ebp+0x18) %eax)
17107     (write-buffered *(ebp+0x18) "' should be in an integer register\n")
17108     (flush *(ebp+0x18))
17109     (stop *(ebp+0x1c) 1)
17110     # never gets here
17111 
17112 float-register?:  # r: (addr array byte) -> result/eax: boolean
17113     # . prologue
17114     55/push-ebp
17115     89/<- %ebp 4/r32/esp
17116     #
17117     (get Mu-registers-unique *(ebp+8) 0xc "Mu-registers-unique")  # => eax
17118     81 7/subop/compare *eax 8/imm32/start-of-floating-point-registers
17119     0f 9d/set-if->= %al
17120     25/and-eax-with 0xff/imm32
17121 $float-register?:end:
17122     # . epilogue
17123     89/<- %esp 5/r32/ebp
17124     5d/pop-to-ebp
17125     c3/return
17126 
17127 parse-type:  # ad: (addr allocation-descriptor), in: (addr stream byte), out: (addr handle type-tree), err: (addr buffered-file), ed: (addr exit-descriptor)
17128     # pseudocode:
17129     #   var s: slice = next-mu-token(in)
17130     #   assert s != ""
17131     #   assert s != "->"
17132     #   assert s != "{"
17133     #   assert s != "}"
17134     #   if s == ")"
17135     #     return
17136     #   out = allocate(Type-tree)
17137     #   if s != "("
17138     #     HACK: if s is an int, parse and return it
17139     #     out->is-atom? = true
17140     #     if (s[0] == "_")
17141     #       out->value = type-parameter
17142     #       out->parameter-name = slice-to-string(ad, s)
17143     #     else
17144     #       out->value = pos-or-insert-slice(Type-id, s)
17145     #     return
17146     #   out->left = parse-type(ad, in)
17147     #   out->right = parse-type-tree(ad, in)
17148     #
17149     # . prologue
17150     55/push-ebp
17151     89/<- %ebp 4/r32/esp
17152     # . save registers
17153     50/push-eax
17154     51/push-ecx
17155     52/push-edx
17156     # clear out
17157     (zero-out *(ebp+0x10) *Handle-size)
17158     # var s/ecx: slice
17159     68/push 0/imm32
17160     68/push 0/imm32
17161     89/<- %ecx 4/r32/esp
17162     # s = next-mu-token(in)
17163     (next-mu-token *(ebp+0xc) %ecx)
17164 #?     (write-buffered Stderr "tok: ")
17165 #?     (write-slice-buffered Stderr %ecx)
17166 #?     (write-buffered Stderr "$\n")
17167 #?     (flush Stderr)
17168     # assert s != ""
17169     (slice-equal? %ecx "")  # => eax
17170     3d/compare-eax-and 0/imm32/false
17171     0f 85/jump-if-!= $parse-type:abort/disp32
17172     # assert s != "{"
17173     (slice-equal? %ecx "{")  # => eax
17174     3d/compare-eax-and 0/imm32/false
17175     0f 85/jump-if-!= $parse-type:abort/disp32
17176     # assert s != "}"
17177     (slice-equal? %ecx "}")  # => eax
17178     3d/compare-eax-and 0/imm32/false
17179     0f 85/jump-if-!= $parse-type:abort/disp32
17180     # assert s != "->"
17181     (slice-equal? %ecx "->")  # => eax
17182     3d/compare-eax-and 0/imm32/false
17183     0f 85/jump-if-!= $parse-type:abort/disp32
17184     # if (s == ")") return
17185     (slice-equal? %ecx ")")  # => eax
17186     3d/compare-eax-and 0/imm32/false
17187     0f 85/jump-if-!= $parse-type:end/disp32
17188     # out = new tree
17189     (allocate *(ebp+8) *Type-tree-size *(ebp+0x10))
17190     # var out-addr/edx: (addr type-tree) = lookup(*out)
17191     8b/-> *(ebp+0x10) 2/r32/edx
17192     (lookup *edx *(edx+4))  # => eax
17193     89/<- %edx 0/r32/eax
17194     {
17195       # if (s != "(") break
17196       (slice-equal? %ecx "(")  # => eax
17197       3d/compare-eax-and 0/imm32/false
17198       0f 85/jump-if-!= break/disp32
17199       # if s is a number, store it in the type's size field
17200       {
17201 $parse-type:check-for-int:
17202         # var tmp/eax: byte = *s->slice
17203         8b/-> *ecx 0/r32/eax
17204         8a/copy-byte *eax 0/r32/AL
17205         25/and-eax-with 0xff/imm32
17206         # TODO: raise an error on `var x: (array int a)`
17207         (decimal-digit? %eax)  # => eax
17208         3d/compare-eax-and 0/imm32/false
17209         74/jump-if-= break/disp8
17210 $parse-type:int:
17211         # strip out metadata
17212         (next-token-from-slice *ecx *(ecx+4) 0x2f %ecx)
17213         #
17214         (check-mu-hex-int %ecx *(ebp+0x14) *(ebp+0x18))
17215         (parse-hex-int-from-slice %ecx)  # => eax
17216         c7 0/subop/copy *(edx+4) 9/imm32/type-id-array-capacity  # Type-tree-value
17217         89/<- *(edx+8) 0/r32/eax  # Type-tree-value-size
17218         e9/jump $parse-type:end/disp32
17219       }
17220 $parse-type:atom:
17221       # out->is-atom? = true
17222       c7 0/subop/copy *edx 1/imm32/true  # Type-tree-is-atom
17223       {
17224 $parse-type:check-for-type-parameter:
17225         # var tmp/eax: byte = *s->slice
17226         8b/-> *ecx 0/r32/eax
17227         8a/copy-byte *eax 0/r32/AL
17228         25/and-eax-with 0xff/imm32
17229         # if (tmp != '_') break
17230         3d/compare-eax-and 0x5f/imm32/_
17231         75/jump-if-!= break/disp8
17232 $parse-type:type-parameter:
17233         # out->value = type-parameter
17234         c7 0/subop/copy *(edx+4) 0xa/imm32/type-parameter  # Type-tree-value
17235         # out->parameter-name = slice-to-string(ad, s)
17236         8d/copy-address *(edx+8) 0/r32/eax  # Type-tree-parameter-name
17237         (slice-to-string *(ebp+8) %ecx %eax)
17238         e9/jump $parse-type:end/disp32
17239       }
17240 $parse-type:non-type-parameter:
17241       # out->value = pos-or-insert-slice(Type-id, s)
17242       (pos-or-insert-slice Type-id %ecx)  # => eax
17243       89/<- *(edx+4) 0/r32/eax  # Type-tree-value
17244       e9/jump $parse-type:end/disp32
17245     }
17246 $parse-type:non-atom:
17247     # otherwise s == "("
17248     # out->left = parse-type(ad, in)
17249     8d/copy-address *(edx+4) 0/r32/eax  # Type-tree-left
17250     (parse-type *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
17251     # out->right = parse-type-tree(ad, in)
17252     8d/copy-address *(edx+0xc) 0/r32/eax  # Type-tree-right
17253     (parse-type-tree *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
17254 $parse-type:end:
17255     # . reclaim locals
17256     81 0/subop/add %esp 8/imm32
17257     # . restore registers
17258     5a/pop-to-edx
17259     59/pop-to-ecx
17260     58/pop-to-eax
17261     # . epilogue
17262     89/<- %esp 5/r32/ebp
17263     5d/pop-to-ebp
17264     c3/return
17265 
17266 $parse-type:abort:
17267     # error("unexpected token when parsing type: '" s "'\n")
17268     (write-buffered *(ebp+0x14) "unexpected token when parsing type: '")
17269     (write-slice-buffered *(ebp+0x14) %ecx)
17270     (write-buffered *(ebp+0x14) "'\n")
17271     (flush *(ebp+0x14))
17272     (stop *(ebp+0x18) 1)
17273     # never gets here
17274 
17275 parse-type-tree:  # ad: (addr allocation-descriptor), in: (addr stream byte), out: (addr handle type-tree), err: (addr buffered-file), ed: (addr exit-descriptor)
17276     # pseudocode:
17277     #   var tmp: (handle type-tree) = parse-type(ad, in)
17278     #   if tmp == 0
17279     #     return 0
17280     #   out = allocate(Type-tree)
17281     #   out->left = tmp
17282     #   out->right = parse-type-tree(ad, in)
17283     #
17284     # . prologue
17285     55/push-ebp
17286     89/<- %ebp 4/r32/esp
17287     # . save registers
17288     50/push-eax
17289     51/push-ecx
17290     52/push-edx
17291     #
17292     (zero-out *(ebp+0x10) *Handle-size)
17293     # var tmp/ecx: (handle type-tree)
17294     68/push 0/imm32
17295     68/push 0/imm32
17296     89/<- %ecx 4/r32/esp
17297     # tmp = parse-type(ad, in)
17298     (parse-type *(ebp+8) *(ebp+0xc) %ecx *(ebp+0x14) *(ebp+0x18))
17299     # if (tmp == 0) return
17300     81 7/subop/compare *ecx 0/imm32
17301     74/jump-if-= $parse-type-tree:end/disp8
17302     # out = new tree
17303     (allocate *(ebp+8) *Type-tree-size *(ebp+0x10))
17304     # var out-addr/edx: (addr tree) = lookup(*out)
17305     8b/-> *(ebp+0x10) 2/r32/edx
17306     (lookup *edx *(edx+4))  # => eax
17307     89/<- %edx 0/r32/eax
17308     # out->left = tmp
17309     8b/-> *ecx 0/r32/eax
17310     89/<- *(edx+4) 0/r32/eax  # Type-tree-left
17311     8b/-> *(ecx+4) 0/r32/eax
17312     89/<- *(edx+8) 0/r32/eax  # Type-tree-left
17313     # out->right = parse-type-tree(ad, in)
17314     8d/copy-address *(edx+0xc) 0/r32/eax  # Type-tree-right
17315     (parse-type-tree *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
17316 $parse-type-tree:end:
17317     # . reclaim locals
17318     81 0/subop/add %esp 8/imm32
17319     # . restore registers
17320     5a/pop-to-edx
17321     59/pop-to-ecx
17322     58/pop-to-eax
17323     # . epilogue
17324     89/<- %esp 5/r32/ebp
17325     5d/pop-to-ebp
17326     c3/return
17327 
17328 next-mu-token:  # in: (addr stream byte), out: (addr slice)
17329     # pseudocode:
17330     # start:
17331     #   skip-chars-matching-whitespace(in)
17332     #   if in->read >= in->write              # end of in
17333     #     out = {0, 0}
17334     #     return
17335     #   out->start = &in->data[in->read]
17336     #   var curr-byte/eax: byte = in->data[in->read]
17337     #   if curr->byte == ','                  # comment token
17338     #     ++in->read
17339     #     goto start
17340     #   if curr-byte == '#'                   # comment
17341     #     goto done                             # treat as eof
17342     #   if curr-byte == '"'                   # string literal
17343     #     skip-string(in)
17344     #     goto done                           # no metadata
17345     #   if curr-byte == '('
17346     #     ++in->read
17347     #     goto done
17348     #   if curr-byte == ')'
17349     #     ++in->read
17350     #     goto done
17351     #   # read a word
17352     #   while true
17353     #     if in->read >= in->write
17354     #       break
17355     #     curr-byte = in->data[in->read]
17356     #     if curr-byte == ' '
17357     #       break
17358     #     if curr-byte == '\r'
17359     #       break
17360     #     if curr-byte == '\n'
17361     #       break
17362     #     if curr-byte == '('
17363     #       break
17364     #     if curr-byte == ')'
17365     #       break
17366     #     if curr-byte == ','
17367     #       break
17368     #     ++in->read
17369     # done:
17370     #   out->end = &in->data[in->read]
17371     #
17372     # . prologue
17373     55/push-ebp
17374     89/<- %ebp 4/r32/esp
17375     # . save registers
17376     50/push-eax
17377     51/push-ecx
17378     56/push-esi
17379     57/push-edi
17380     # esi = in
17381     8b/-> *(ebp+8) 6/r32/esi
17382     # edi = out
17383     8b/-> *(ebp+0xc) 7/r32/edi
17384 $next-mu-token:start:
17385     (skip-chars-matching-whitespace %esi)
17386 $next-mu-token:check0:
17387     # if (in->read >= in->write) return out = {0, 0}
17388     # . ecx = in->read
17389     8b/-> *(esi+4) 1/r32/ecx
17390     # . if (ecx >= in->write) return out = {0, 0}
17391     3b/compare<- *esi 1/r32/ecx
17392     c7 0/subop/copy *edi 0/imm32
17393     c7 0/subop/copy *(edi+4) 0/imm32
17394     0f 8d/jump-if->= $next-mu-token:end/disp32
17395     # out->start = &in->data[in->read]
17396     8d/copy-address *(esi+ecx+0xc) 0/r32/eax
17397     89/<- *edi 0/r32/eax
17398     # var curr-byte/eax: byte = in->data[in->read]
17399     31/xor-with %eax 0/r32/eax
17400     8a/copy-byte *(esi+ecx+0xc) 0/r32/AL
17401     {
17402 $next-mu-token:check-for-comma:
17403       # if (curr-byte != ',') break
17404       3d/compare-eax-and 0x2c/imm32/comma
17405       75/jump-if-!= break/disp8
17406       # ++in->read
17407       ff 0/subop/increment *(esi+4)
17408       # restart
17409       e9/jump $next-mu-token:start/disp32
17410     }
17411     {
17412 $next-mu-token:check-for-comment:
17413       # if (curr-byte != '#') break
17414       3d/compare-eax-and 0x23/imm32/pound
17415       75/jump-if-!= break/disp8
17416       # return eof
17417       e9/jump $next-mu-token:done/disp32
17418     }
17419     {
17420 $next-mu-token:check-for-string-literal:
17421       # if (curr-byte != '"') break
17422       3d/compare-eax-and 0x22/imm32/dquote
17423       75/jump-if-!= break/disp8
17424       (skip-string %esi)
17425       # return
17426       e9/jump $next-mu-token:done/disp32
17427     }
17428     {
17429 $next-mu-token:check-for-open-paren:
17430       # if (curr-byte != '(') break
17431       3d/compare-eax-and 0x28/imm32/open-paren
17432       75/jump-if-!= break/disp8
17433       # ++in->read
17434       ff 0/subop/increment *(esi+4)
17435       # return
17436       e9/jump $next-mu-token:done/disp32
17437     }
17438     {
17439 $next-mu-token:check-for-close-paren:
17440       # if (curr-byte != ')') break
17441       3d/compare-eax-and 0x29/imm32/close-paren
17442       75/jump-if-!= break/disp8
17443       # ++in->read
17444       ff 0/subop/increment *(esi+4)
17445       # return
17446       e9/jump $next-mu-token:done/disp32
17447     }
17448     {
17449 $next-mu-token:regular-word-without-metadata:
17450       # if (in->read >= in->write) break
17451       # . ecx = in->read
17452       8b/-> *(esi+4) 1/r32/ecx
17453       # . if (ecx >= in->write) break
17454       3b/compare<- *esi 1/r32/ecx
17455       7d/jump-if->= break/disp8
17456       # var c/eax: byte = in->data[in->read]
17457       31/xor-with %eax 0/r32/eax
17458       8a/copy-byte *(esi+ecx+0xc) 0/r32/AL
17459       # if (c == ' ') break
17460       3d/compare-eax-and 0x20/imm32/space
17461       74/jump-if-= break/disp8
17462       # if (c == '\r') break
17463       3d/compare-eax-and 0xd/imm32/carriage-return
17464       74/jump-if-= break/disp8
17465       # if (c == '\n') break
17466       3d/compare-eax-and 0xa/imm32/newline
17467       74/jump-if-= break/disp8
17468       # if (c == '(') break
17469       3d/compare-eax-and 0x28/imm32/open-paren
17470       0f 84/jump-if-= break/disp32
17471       # if (c == ')') break
17472       3d/compare-eax-and 0x29/imm32/close-paren
17473       0f 84/jump-if-= break/disp32
17474       # if (c == ',') break
17475       3d/compare-eax-and 0x2c/imm32/comma
17476       0f 84/jump-if-= break/disp32
17477       # ++in->read
17478       ff 0/subop/increment *(esi+4)
17479       #
17480       e9/jump loop/disp32
17481     }
17482 $next-mu-token:done:
17483     # out->end = &in->data[in->read]
17484     8b/-> *(esi+4) 1/r32/ecx
17485     8d/copy-address *(esi+ecx+0xc) 0/r32/eax
17486     89/<- *(edi+4) 0/r32/eax
17487 $next-mu-token:end:
17488     # . restore registers
17489     5f/pop-to-edi
17490     5e/pop-to-esi
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 pos-or-insert-slice:  # arr: (addr stream (addr array byte)), s: (addr slice) -> index/eax: int
17499     # . prologue
17500     55/push-ebp
17501     89/<- %ebp 4/r32/esp
17502     # if (pos-slice(arr, s) != -1) return it
17503     (pos-slice *(ebp+8) *(ebp+0xc))  # => eax
17504     3d/compare-eax-and -1/imm32
17505     75/jump-if-!= $pos-or-insert-slice:end/disp8
17506 $pos-or-insert-slice:insert:
17507     # var s2/eax: (handle array byte)
17508     68/push 0/imm32
17509     68/push 0/imm32
17510     89/<- %eax 4/r32/esp
17511     (slice-to-string Heap *(ebp+0xc) %eax)
17512     # throw away alloc-id
17513     (lookup *eax *(eax+4))  # => eax
17514     (write-int *(ebp+8) %eax)
17515     (pos-slice *(ebp+8) *(ebp+0xc))  # => eax
17516 $pos-or-insert-slice:end:
17517     # . reclaim locals
17518     81 0/subop/add %esp 8/imm32
17519     # . epilogue
17520     89/<- %esp 5/r32/ebp
17521     5d/pop-to-ebp
17522     c3/return
17523 
17524 # return the index in an array of strings matching 's', -1 if not found
17525 # index is denominated in elements, not bytes
17526 pos-slice:  # arr: (addr stream (addr array byte)), s: (addr slice) -> index/eax: int
17527     # . prologue
17528     55/push-ebp
17529     89/<- %ebp 4/r32/esp
17530     # . save registers
17531     51/push-ecx
17532     52/push-edx
17533     53/push-ebx
17534     56/push-esi
17535 #?     (write-buffered Stderr "pos-slice: ")
17536 #?     (write-slice-buffered Stderr *(ebp+0xc))
17537 #?     (write-buffered Stderr "\n")
17538 #?     (flush Stderr)
17539     # esi = arr
17540     8b/-> *(ebp+8) 6/r32/esi
17541     # var index/ecx: int = 0
17542     b9/copy-to-ecx 0/imm32
17543     # var curr/edx: (addr (addr array byte)) = arr->data
17544     8d/copy-address *(esi+0xc) 2/r32/edx
17545     # var max/ebx: (addr (addr array byte)) = &arr->data[arr->write]
17546     8b/-> *esi 3/r32/ebx
17547     8d/copy-address *(esi+ebx+0xc) 3/r32/ebx
17548     {
17549 #?       (write-buffered Stderr "  ")
17550 #?       (write-int32-hex-buffered Stderr %ecx)
17551 #?       (write-buffered Stderr "\n")
17552 #?       (flush Stderr)
17553       # if (curr >= max) return -1
17554       39/compare %edx 3/r32/ebx
17555       b8/copy-to-eax -1/imm32
17556       73/jump-if-addr>= $pos-slice:end/disp8
17557       # if (slice-equal?(s, *curr)) break
17558       (slice-equal? *(ebp+0xc) *edx)  # => eax
17559       3d/compare-eax-and 0/imm32/false
17560       75/jump-if-!= break/disp8
17561       # ++index
17562       41/increment-ecx
17563       # curr += 4
17564       81 0/subop/add %edx 4/imm32
17565       #
17566       eb/jump loop/disp8
17567     }
17568     # return index
17569     89/<- %eax 1/r32/ecx
17570 $pos-slice:end:
17571 #?     (write-buffered Stderr "=> ")
17572 #?     (write-int32-hex-buffered Stderr %eax)
17573 #?     (write-buffered Stderr "\n")
17574     # . restore registers
17575     5e/pop-to-esi
17576     5b/pop-to-ebx
17577     5a/pop-to-edx
17578     59/pop-to-ecx
17579     # . epilogue
17580     89/<- %esp 5/r32/ebp
17581     5d/pop-to-ebp
17582     c3/return
17583 
17584 test-parse-var-with-type:
17585     # . prologue
17586     55/push-ebp
17587     89/<- %ebp 4/r32/esp
17588     # setup
17589     8b/-> *Primitive-type-ids 0/r32/eax
17590     89/<- *Type-id 0/r32/eax  # stream-write
17591     # (eax..ecx) = "x:"
17592     b8/copy-to-eax "x:"/imm32
17593     8b/-> *eax 1/r32/ecx
17594     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17595     05/add-to-eax 4/imm32
17596     # var slice/ecx: slice = {eax, ecx}
17597     51/push-ecx
17598     50/push-eax
17599     89/<- %ecx 4/r32/esp
17600     # _test-input-stream contains "int"
17601     (clear-stream _test-input-stream)
17602     (write _test-input-stream "int")
17603     # var v/edx: (handle var)
17604     68/push 0/imm32
17605     68/push 0/imm32
17606     89/<- %edx 4/r32/esp
17607     #
17608     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
17609     # var v-addr/edx: (addr var) = lookup(v)
17610     (lookup *edx *(edx+4))  # => eax
17611     89/<- %edx 0/r32/eax
17612     # check v-addr->name
17613     (lookup *edx *(edx+4))  # Var-name Var-name => eax
17614     (check-strings-equal %eax "x" "F - test-parse-var-with-type/name")
17615     # check v-addr->type
17616     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
17617     (check-ints-equal *eax 1 "F - test-parse-var-with-type/type:0")  # Type-tree-is-atom
17618     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-type/type:1")  # Type-tree-value
17619     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-type/type:2")  # Type-tree-right
17620     # . epilogue
17621     89/<- %esp 5/r32/ebp
17622     5d/pop-to-ebp
17623     c3/return
17624 
17625 test-parse-var-with-type-and-register:
17626     # . prologue
17627     55/push-ebp
17628     89/<- %ebp 4/r32/esp
17629     # setup
17630     8b/-> *Primitive-type-ids 0/r32/eax
17631     89/<- *Type-id 0/r32/eax  # stream-write
17632     # (eax..ecx) = "x/eax:"
17633     b8/copy-to-eax "x/eax:"/imm32
17634     8b/-> *eax 1/r32/ecx
17635     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17636     05/add-to-eax 4/imm32
17637     # var slice/ecx: slice = {eax, ecx}
17638     51/push-ecx
17639     50/push-eax
17640     89/<- %ecx 4/r32/esp
17641     # _test-input-stream contains "int"
17642     (clear-stream _test-input-stream)
17643     (write _test-input-stream "int")
17644     # var v/edx: (handle var)
17645     68/push 0/imm32
17646     68/push 0/imm32
17647     89/<- %edx 4/r32/esp
17648     #
17649     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
17650     # var v-addr/edx: (addr var) = lookup(v)
17651     (lookup *edx *(edx+4))  # => eax
17652     89/<- %edx 0/r32/eax
17653     # check v-addr->name
17654     (lookup *edx *(edx+4))  # Var-name Var-name => eax
17655     (check-strings-equal %eax "x" "F - test-parse-var-with-type-and-register/name")
17656     # check v-addr->register
17657     (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
17658     (check-strings-equal %eax "eax" "F - test-parse-var-with-type-and-register/register")
17659     # check v-addr->type
17660     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
17661     (check-ints-equal *eax 1 "F - test-parse-var-with-type-and-register/type:0")  # Type-tree-is-atom
17662     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-type-and-register/type:1")  # Type-tree-left
17663     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-type-and-register/type:2")  # Type-tree-right
17664     # . epilogue
17665     89/<- %esp 5/r32/ebp
17666     5d/pop-to-ebp
17667     c3/return
17668 
17669 test-parse-var-with-trailing-characters:
17670     # . prologue
17671     55/push-ebp
17672     89/<- %ebp 4/r32/esp
17673     # setup
17674     8b/-> *Primitive-type-ids 0/r32/eax
17675     89/<- *Type-id 0/r32/eax  # stream-write
17676     # (eax..ecx) = "x:"
17677     b8/copy-to-eax "x:"/imm32
17678     8b/-> *eax 1/r32/ecx
17679     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17680     05/add-to-eax 4/imm32
17681     # var slice/ecx: slice = {eax, ecx}
17682     51/push-ecx
17683     50/push-eax
17684     89/<- %ecx 4/r32/esp
17685     # _test-input-stream contains "int,"
17686     (clear-stream _test-input-stream)
17687     (write _test-input-stream "int,")
17688     # var v/edx: (handle var)
17689     68/push 0/imm32
17690     68/push 0/imm32
17691     89/<- %edx 4/r32/esp
17692     #
17693     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
17694     # var v-addr/edx: (addr var) = lookup(v)
17695     (lookup *edx *(edx+4))  # => eax
17696     89/<- %edx 0/r32/eax
17697     # check v-addr->name
17698     (lookup *edx *(edx+4))  # Var-name Var-name => eax
17699     (check-strings-equal %eax "x" "F - test-parse-var-with-trailing-characters/name")
17700     # check v-addr->register
17701     (check-ints-equal *(edx+0x18) 0 "F - test-parse-var-with-trailing-characters/register")  # Var-register
17702     # check v-addr->type
17703     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
17704     (check-ints-equal *eax 1 "F - test-parse-var-with-trailing-characters/type:0")  # Type-tree-is-atom
17705     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-trailing-characters/type:1")  # Type-tree-left
17706     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-trailing-characters/type:1")  # Type-tree-right
17707     # . epilogue
17708     89/<- %esp 5/r32/ebp
17709     5d/pop-to-ebp
17710     c3/return
17711 
17712 test-parse-var-with-register-and-trailing-characters:
17713     # . prologue
17714     55/push-ebp
17715     89/<- %ebp 4/r32/esp
17716     # setup
17717     8b/-> *Primitive-type-ids 0/r32/eax
17718     89/<- *Type-id 0/r32/eax  # stream-write
17719     # (eax..ecx) = "x/eax:"
17720     b8/copy-to-eax "x/eax:"/imm32
17721     8b/-> *eax 1/r32/ecx
17722     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17723     05/add-to-eax 4/imm32
17724     # var slice/ecx: slice = {eax, ecx}
17725     51/push-ecx
17726     50/push-eax
17727     89/<- %ecx 4/r32/esp
17728     # _test-input-stream contains "int,"
17729     (clear-stream _test-input-stream)
17730     (write _test-input-stream "int,")
17731     # var v/edx: (handle var)
17732     68/push 0/imm32
17733     68/push 0/imm32
17734     89/<- %edx 4/r32/esp
17735     #
17736     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
17737     # var v-addr/edx: (addr var) = lookup(v)
17738     (lookup *edx *(edx+4))  # => eax
17739     89/<- %edx 0/r32/eax
17740     # check v-addr->name
17741     (lookup *edx *(edx+4))  # Var-name Var-name => eax
17742     (check-strings-equal %eax "x" "F - test-parse-var-with-register-and-trailing-characters/name")
17743     # check v-addr->register
17744     (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
17745     (check-strings-equal %eax "eax" "F - test-parse-var-with-register-and-trailing-characters/register")
17746     # check v-addr->type
17747     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
17748     (check-ints-equal *eax 1 "F - test-parse-var-with-register-and-trailing-characters/type:0")  # Type-tree-is-atom
17749     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-register-and-trailing-characters/type:1")  # Type-tree-left
17750     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-register-and-trailing-characters/type:2")  # Type-tree-right
17751     # . epilogue
17752     89/<- %esp 5/r32/ebp
17753     5d/pop-to-ebp
17754     c3/return
17755 
17756 test-parse-var-with-compound-type:
17757     # . prologue
17758     55/push-ebp
17759     89/<- %ebp 4/r32/esp
17760     # setup
17761     8b/-> *Primitive-type-ids 0/r32/eax
17762     89/<- *Type-id 0/r32/eax  # stream-write
17763     # (eax..ecx) = "x:"
17764     b8/copy-to-eax "x:"/imm32
17765     8b/-> *eax 1/r32/ecx
17766     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17767     05/add-to-eax 4/imm32
17768     # var slice/ecx: slice = {eax, ecx}
17769     51/push-ecx
17770     50/push-eax
17771     89/<- %ecx 4/r32/esp
17772     # _test-input-stream contains "(addr int)"
17773     (clear-stream _test-input-stream)
17774     (write _test-input-stream "(addr int)")
17775     # var v/edx: (handle var)
17776     68/push 0/imm32
17777     68/push 0/imm32
17778     89/<- %edx 4/r32/esp
17779     #
17780     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
17781     # var v-addr/edx: (addr var) = lookup(v)
17782     (lookup *edx *(edx+4))  # => eax
17783     89/<- %edx 0/r32/eax
17784     # check v-addr->name
17785     (lookup *edx *(edx+4))  # Var-name Var-name => eax
17786     (check-strings-equal %eax "x" "F - test-parse-var-with-compound-type/name")
17787     # check v-addr->register
17788     (check-ints-equal *(edx+0x18) 0 "F - test-parse-var-with-compound-type/register")  # Var-register
17789     # - check v-addr->type
17790     # var type/edx: (addr type-tree) = var->type
17791     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
17792     89/<- %edx 0/r32/eax
17793     # type is a non-atom
17794     (check-ints-equal *edx 0 "F - test-parse-var-with-compound-type/type:0")  # Type-tree-is-atom
17795     # type->left == atom(addr)
17796     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
17797     (check-ints-equal *eax 1 "F - test-parse-var-with-compound-type/type:1")  # Type-tree-is-atom
17798     (check-ints-equal *(eax+4) 2 "F - test-parse-var-with-compound-type/type:2")  # Type-tree-value
17799     # type->right->left == atom(int)
17800     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
17801     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
17802     (check-ints-equal *eax 1 "F - test-parse-var-with-compound-type/type:3")  # Type-tree-is-atom
17803     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-compound-type/type:4")  # Type-tree-value
17804     # type->right->right == null
17805     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-compound-type/type:5")  # Type-tree-right
17806     # . epilogue
17807     89/<- %esp 5/r32/ebp
17808     5d/pop-to-ebp
17809     c3/return
17810 
17811 # identifier starts with a letter or '$' or '_'
17812 # no constraints at the moment on later letters
17813 # all we really want to do so far is exclude '{', '}' and '->'
17814 identifier?:  # in: (addr slice) -> result/eax: boolean
17815     # . prologue
17816     55/push-ebp
17817     89/<- %ebp 4/r32/esp
17818     # if (slice-empty?(in)) return false
17819     (slice-empty? *(ebp+8))  # => eax
17820     3d/compare-eax-and 0/imm32/false
17821     75/jump-if-!= $identifier?:false/disp8
17822     # var c/eax: byte = *in->start
17823     8b/-> *(ebp+8) 0/r32/eax
17824     8b/-> *eax 0/r32/eax
17825     8a/copy-byte *eax 0/r32/AL
17826     25/and-eax-with 0xff/imm32
17827     # if (c == '$') return true
17828     3d/compare-eax-and 0x24/imm32/$
17829     74/jump-if-= $identifier?:true/disp8
17830     # if (c == '_') return true
17831     3d/compare-eax-and 0x5f/imm32/_
17832     74/jump-if-= $identifier?:true/disp8
17833     # drop case
17834     25/and-eax-with 0x5f/imm32
17835     # if (c < 'A') return false
17836     3d/compare-eax-and 0x41/imm32/A
17837     7c/jump-if-< $identifier?:false/disp8
17838     # if (c > 'Z') return false
17839     3d/compare-eax-and 0x5a/imm32/Z
17840     7f/jump-if-> $identifier?:false/disp8
17841     # otherwise return true
17842 $identifier?:true:
17843     b8/copy-to-eax 1/imm32/true
17844     eb/jump $identifier?:end/disp8
17845 $identifier?:false:
17846     b8/copy-to-eax 0/imm32/false
17847 $identifier?:end:
17848     # . epilogue
17849     89/<- %esp 5/r32/ebp
17850     5d/pop-to-ebp
17851     c3/return
17852 
17853 test-is-identifier-dollar:
17854     # . prologue
17855     55/push-ebp
17856     89/<- %ebp 4/r32/esp
17857     # (eax..ecx) = "$a"
17858     b8/copy-to-eax "$a"/imm32
17859     8b/-> *eax 1/r32/ecx
17860     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17861     05/add-to-eax 4/imm32
17862     # var slice/ecx: slice = {eax, ecx}
17863     51/push-ecx
17864     50/push-eax
17865     89/<- %ecx 4/r32/esp
17866     #
17867     (identifier? %ecx)
17868     (check-ints-equal %eax 1 "F - test-is-identifier-dollar")
17869     # . epilogue
17870     89/<- %esp 5/r32/ebp
17871     5d/pop-to-ebp
17872     c3/return
17873 
17874 test-is-identifier-underscore:
17875     # . prologue
17876     55/push-ebp
17877     89/<- %ebp 4/r32/esp
17878     # (eax..ecx) = "_a"
17879     b8/copy-to-eax "_a"/imm32
17880     8b/-> *eax 1/r32/ecx
17881     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17882     05/add-to-eax 4/imm32
17883     # var slice/ecx: slice = {eax, ecx}
17884     51/push-ecx
17885     50/push-eax
17886     89/<- %ecx 4/r32/esp
17887     #
17888     (identifier? %ecx)
17889     (check-ints-equal %eax 1 "F - test-is-identifier-underscore")
17890     # . epilogue
17891     89/<- %esp 5/r32/ebp
17892     5d/pop-to-ebp
17893     c3/return
17894 
17895 test-is-identifier-a:
17896     # . prologue
17897     55/push-ebp
17898     89/<- %ebp 4/r32/esp
17899     # (eax..ecx) = "a$"
17900     b8/copy-to-eax "a$"/imm32
17901     8b/-> *eax 1/r32/ecx
17902     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17903     05/add-to-eax 4/imm32
17904     # var slice/ecx: slice = {eax, ecx}
17905     51/push-ecx
17906     50/push-eax
17907     89/<- %ecx 4/r32/esp
17908     #
17909     (identifier? %ecx)
17910     (check-ints-equal %eax 1 "F - test-is-identifier-a")
17911     # . epilogue
17912     89/<- %esp 5/r32/ebp
17913     5d/pop-to-ebp
17914     c3/return
17915 
17916 test-is-identifier-z:
17917     # . prologue
17918     55/push-ebp
17919     89/<- %ebp 4/r32/esp
17920     # (eax..ecx) = "z$"
17921     b8/copy-to-eax "z$"/imm32
17922     8b/-> *eax 1/r32/ecx
17923     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17924     05/add-to-eax 4/imm32
17925     # var slice/ecx: slice = {eax, ecx}
17926     51/push-ecx
17927     50/push-eax
17928     89/<- %ecx 4/r32/esp
17929     #
17930     (identifier? %ecx)
17931     (check-ints-equal %eax 1 "F - test-is-identifier-z")
17932     # . epilogue
17933     89/<- %esp 5/r32/ebp
17934     5d/pop-to-ebp
17935     c3/return
17936 
17937 test-is-identifier-A:
17938     # . prologue
17939     55/push-ebp
17940     89/<- %ebp 4/r32/esp
17941     # (eax..ecx) = "A$"
17942     b8/copy-to-eax "A$"/imm32
17943     8b/-> *eax 1/r32/ecx
17944     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17945     05/add-to-eax 4/imm32
17946     # var slice/ecx: slice = {eax, ecx}
17947     51/push-ecx
17948     50/push-eax
17949     89/<- %ecx 4/r32/esp
17950     #
17951     (identifier? %ecx)
17952     (check-ints-equal %eax 1 "F - test-is-identifier-A")
17953     # . epilogue
17954     89/<- %esp 5/r32/ebp
17955     5d/pop-to-ebp
17956     c3/return
17957 
17958 test-is-identifier-Z:
17959     # . prologue
17960     55/push-ebp
17961     89/<- %ebp 4/r32/esp
17962     # (eax..ecx) = "Z$"
17963     b8/copy-to-eax "Z$"/imm32
17964     8b/-> *eax 1/r32/ecx
17965     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17966     05/add-to-eax 4/imm32
17967     # var slice/ecx: slice = {eax, ecx}
17968     51/push-ecx
17969     50/push-eax
17970     89/<- %ecx 4/r32/esp
17971     #
17972     (identifier? %ecx)
17973     (check-ints-equal %eax 1 "F - test-is-identifier-Z")
17974     # . epilogue
17975     89/<- %esp 5/r32/ebp
17976     5d/pop-to-ebp
17977     c3/return
17978 
17979 test-is-identifier-at:
17980     # character before 'A' is invalid
17981     # . prologue
17982     55/push-ebp
17983     89/<- %ebp 4/r32/esp
17984     # (eax..ecx) = "@a"
17985     b8/copy-to-eax "@a"/imm32
17986     8b/-> *eax 1/r32/ecx
17987     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17988     05/add-to-eax 4/imm32
17989     # var slice/ecx: slice = {eax, ecx}
17990     51/push-ecx
17991     50/push-eax
17992     89/<- %ecx 4/r32/esp
17993     #
17994     (identifier? %ecx)
17995     (check-ints-equal %eax 0 "F - test-is-identifier-@")
17996     # . epilogue
17997     89/<- %esp 5/r32/ebp
17998     5d/pop-to-ebp
17999     c3/return
18000 
18001 test-is-identifier-square-bracket:
18002     # character after 'Z' is invalid
18003     # . prologue
18004     55/push-ebp
18005     89/<- %ebp 4/r32/esp
18006     # (eax..ecx) = "[a"
18007     b8/copy-to-eax "[a"/imm32
18008     8b/-> *eax 1/r32/ecx
18009     8d/copy-address *(eax+ecx+4) 1/r32/ecx
18010     05/add-to-eax 4/imm32
18011     # var slice/ecx: slice = {eax, ecx}
18012     51/push-ecx
18013     50/push-eax
18014     89/<- %ecx 4/r32/esp
18015     #
18016     (identifier? %ecx)
18017     (check-ints-equal %eax 0 "F - test-is-identifier-@")
18018     # . epilogue
18019     89/<- %esp 5/r32/ebp
18020     5d/pop-to-ebp
18021     c3/return
18022 
18023 test-is-identifier-backtick:
18024     # character before 'a' is invalid
18025     # . prologue
18026     55/push-ebp
18027     89/<- %ebp 4/r32/esp
18028     # (eax..ecx) = "`a"
18029     b8/copy-to-eax "`a"/imm32
18030     8b/-> *eax 1/r32/ecx
18031     8d/copy-address *(eax+ecx+4) 1/r32/ecx
18032     05/add-to-eax 4/imm32
18033     # var slice/ecx: slice = {eax, ecx}
18034     51/push-ecx
18035     50/push-eax
18036     89/<- %ecx 4/r32/esp
18037     #
18038     (identifier? %ecx)
18039     (check-ints-equal %eax 0 "F - test-is-identifier-backtick")
18040     # . epilogue
18041     89/<- %esp 5/r32/ebp
18042     5d/pop-to-ebp
18043     c3/return
18044 
18045 test-is-identifier-curly-brace-open:
18046     # character after 'z' is invalid; also used for blocks
18047     # . prologue
18048     55/push-ebp
18049     89/<- %ebp 4/r32/esp
18050     # (eax..ecx) = "{a"
18051     b8/copy-to-eax "{a"/imm32
18052     8b/-> *eax 1/r32/ecx
18053     8d/copy-address *(eax+ecx+4) 1/r32/ecx
18054     05/add-to-eax 4/imm32
18055     # var slice/ecx: slice = {eax, ecx}
18056     51/push-ecx
18057     50/push-eax
18058     89/<- %ecx 4/r32/esp
18059     #
18060     (identifier? %ecx)
18061     (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-open")
18062     # . epilogue
18063     89/<- %esp 5/r32/ebp
18064     5d/pop-to-ebp
18065     c3/return
18066 
18067 test-is-identifier-curly-brace-close:
18068     # . prologue
18069     55/push-ebp
18070     89/<- %ebp 4/r32/esp
18071     # (eax..ecx) = "}a"
18072     b8/copy-to-eax "}a"/imm32
18073     8b/-> *eax 1/r32/ecx
18074     8d/copy-address *(eax+ecx+4) 1/r32/ecx
18075     05/add-to-eax 4/imm32
18076     # var slice/ecx: slice = {eax, ecx}
18077     51/push-ecx
18078     50/push-eax
18079     89/<- %ecx 4/r32/esp
18080     #
18081     (identifier? %ecx)
18082     (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-close")
18083     # . epilogue
18084     89/<- %esp 5/r32/ebp
18085     5d/pop-to-ebp
18086     c3/return
18087 
18088 test-is-identifier-hyphen:
18089     # disallow leading '-' since '->' has special meaning
18090     # . prologue
18091     55/push-ebp
18092     89/<- %ebp 4/r32/esp
18093     # (eax..ecx) = "-a"
18094     b8/copy-to-eax "-a"/imm32
18095     8b/-> *eax 1/r32/ecx
18096     8d/copy-address *(eax+ecx+4) 1/r32/ecx
18097     05/add-to-eax 4/imm32
18098     # var slice/ecx: slice = {eax, ecx}
18099     51/push-ecx
18100     50/push-eax
18101     89/<- %ecx 4/r32/esp
18102     #
18103     (identifier? %ecx)
18104     (check-ints-equal %eax 0 "F - test-is-identifier-hyphen")
18105     # . epilogue
18106     89/<- %esp 5/r32/ebp
18107     5d/pop-to-ebp
18108     c3/return
18109 
18110 populate-mu-function-body:  # in: (addr buffered-file), out: (addr function), vars: (addr stack live-var), err: (addr buffered-file), ed: (addr exit-descriptor)
18111     # . prologue
18112     55/push-ebp
18113     89/<- %ebp 4/r32/esp
18114     # . save registers
18115     50/push-eax
18116     56/push-esi
18117     57/push-edi
18118     # esi = in
18119     8b/-> *(ebp+8) 6/r32/esi
18120     # edi = out
18121     8b/-> *(ebp+0xc) 7/r32/edi
18122     # initialize some global state
18123     c7 0/subop/copy *Curr-block-depth 1/imm32
18124     # parse-mu-block(in, vars, out, out->body)
18125     8d/copy-address *(edi+0x18) 0/r32/eax  # Function-body
18126     (parse-mu-block %esi *(ebp+0x10) %edi %eax *(ebp+0x14) *(ebp+0x18))
18127 $populate-mu-function-body:end:
18128     # . restore registers
18129     5f/pop-to-edi
18130     5e/pop-to-esi
18131     58/pop-to-eax
18132     # . epilogue
18133     89/<- %esp 5/r32/ebp
18134     5d/pop-to-ebp
18135     c3/return
18136 
18137 # parses a block, assuming that the leading '{' has already been read by the caller
18138 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)
18139     # pseudocode:
18140     #   var line: (stream byte 512)
18141     #   var word-slice: slice
18142     #   allocate(Heap, Stmt-size, out)
18143     #   var out-addr: (addr block) = lookup(*out)
18144     #   out-addr->tag = 0/block
18145     #   out-addr->var = some unique name
18146     #   push(vars, {out-addr->var, false})
18147     #   while true                                  # line loop
18148     #     clear-stream(line)
18149     #     read-line-buffered(in, line)
18150     #     if (line->write == 0) break               # end of file
18151     #     word-slice = next-mu-token(line)
18152     #     if slice-empty?(word-slice)               # end of line
18153     #       continue
18154     #     else if slice-starts-with?(word-slice, "#")
18155     #       continue
18156     #     else if slice-equal?(word-slice, "{")
18157     #       assert(no-tokens-in(line))
18158     #       block = parse-mu-block(in, vars, fn)
18159     #       append-to-block(out-addr, block)
18160     #     else if slice-equal?(word-slice, "}")
18161     #       break
18162     #     else if slice-ends-with?(word-slice, ":")
18163     #       # TODO: error-check the rest of 'line'
18164     #       --word-slice->end to skip ':'
18165     #       named-block = parse-mu-named-block(word-slice, in, vars, fn)
18166     #       append-to-block(out-addr, named-block)
18167     #     else if slice-equal?(word-slice, "var")
18168     #       var-def = parse-mu-var-def(line, vars, fn)
18169     #       append-to-block(out-addr, var-def)
18170     #     else
18171     #       stmt = parse-mu-stmt(line, vars, fn)
18172     #       append-to-block(out-addr, stmt)
18173     #   pop(vars)
18174     #
18175     # . prologue
18176     55/push-ebp
18177     89/<- %ebp 4/r32/esp
18178     # . save registers
18179     50/push-eax
18180     51/push-ecx
18181     52/push-edx
18182     53/push-ebx
18183     57/push-edi
18184     # var line/ecx: (stream byte 512)
18185     81 5/subop/subtract %esp 0x200/imm32
18186     68/push 0x200/imm32/size
18187     68/push 0/imm32/read
18188     68/push 0/imm32/write
18189     89/<- %ecx 4/r32/esp
18190     # var word-slice/edx: slice
18191     68/push 0/imm32/end
18192     68/push 0/imm32/start
18193     89/<- %edx 4/r32/esp
18194     # allocate into out
18195     (allocate Heap *Stmt-size *(ebp+0x14))
18196     # var out-addr/edi: (addr block) = lookup(*out)
18197     8b/-> *(ebp+0x14) 7/r32/edi
18198     (lookup *edi *(edi+4))  # => eax
18199     89/<- %edi 0/r32/eax
18200     # out-addr->tag is 0 (block) by default
18201     # set out-addr->var
18202     8d/copy-address *(edi+0xc) 0/r32/eax  # Block-var
18203     (new-block-name *(ebp+0x10) %eax)
18204     # push(vars, out-addr->var)
18205     (push *(ebp+0xc) *(edi+0xc))  # Block-var
18206     (push *(ebp+0xc) *(edi+0x10))  # Block-var
18207     (push *(ebp+0xc) 0)  # false
18208     # increment *Curr-block-depth
18209     ff 0/subop/increment *Curr-block-depth
18210     {
18211 $parse-mu-block:line-loop:
18212       # line = read-line-buffered(in)
18213       (clear-stream %ecx)
18214       (read-line-buffered *(ebp+8) %ecx)
18215 #?       (write-buffered Stderr "line: ")
18216 #?       (write-stream-data Stderr %ecx)
18217 #? #?       (write-buffered Stderr Newline)  # line has its own newline
18218 #?       (flush Stderr)
18219 #?       (rewind-stream %ecx)
18220       # if (line->write == 0) break
18221       81 7/subop/compare *ecx 0/imm32
18222       0f 84/jump-if-= break/disp32
18223 #?       (write-buffered Stderr "vars:\n")
18224 #?       (dump-vars *(ebp+0xc))
18225       # word-slice = next-mu-token(line)
18226       (next-mu-token %ecx %edx)
18227 #?       (write-buffered Stderr "word: ")
18228 #?       (write-slice-buffered Stderr %edx)
18229 #?       (write-buffered Stderr Newline)
18230 #?       (flush Stderr)
18231       # if slice-empty?(word-slice) continue
18232       (slice-empty? %edx)
18233       3d/compare-eax-and 0/imm32/false
18234       0f 85/jump-if-!= loop/disp32
18235       # if (slice-starts-with?(word-slice, '#') continue
18236       # . eax = *word-slice->start
18237       8b/-> *edx 0/r32/eax
18238       8a/copy-byte *eax 0/r32/AL
18239       25/and-eax-with 0xff/imm32
18240       # . if (eax == '#') continue
18241       3d/compare-eax-and 0x23/imm32/hash
18242       0f 84/jump-if-= loop/disp32
18243       # if slice-equal?(word-slice, "{")
18244       {
18245 $parse-mu-block:check-for-block:
18246         (slice-equal? %edx "{")
18247         3d/compare-eax-and 0/imm32/false
18248         74/jump-if-= break/disp8
18249         (check-no-tokens-left %ecx)
18250         # parse new block and append
18251         # . var tmp/eax: (handle block)
18252         68/push 0/imm32
18253         68/push 0/imm32
18254         89/<- %eax 4/r32/esp
18255         # .
18256         (parse-mu-block *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
18257         (append-to-block Heap %edi  *eax *(eax+4))
18258         # . reclaim tmp
18259         81 0/subop/add %esp 8/imm32
18260         # .
18261         e9/jump $parse-mu-block:line-loop/disp32
18262       }
18263       # if slice-equal?(word-slice, "}") break
18264 $parse-mu-block:check-for-end:
18265       (slice-equal? %edx "}")
18266       3d/compare-eax-and 0/imm32/false
18267       0f 85/jump-if-!= break/disp32
18268       # if slice-ends-with?(word-slice, ":") parse named block and append
18269       {
18270 $parse-mu-block:check-for-named-block:
18271         # . eax = *(word-slice->end-1)
18272         8b/-> *(edx+4) 0/r32/eax
18273         48/decrement-eax
18274         8a/copy-byte *eax 0/r32/AL
18275         25/and-eax-with 0xff/imm32
18276         # . if (eax != ':') break
18277         3d/compare-eax-and 0x3a/imm32/colon
18278         0f 85/jump-if-!= break/disp32
18279         # TODO: error-check the rest of 'line'
18280         #
18281         # skip ':'
18282         ff 1/subop/decrement *(edx+4)  # Slice-end
18283         # var tmp/eax: (handle block)
18284         68/push 0/imm32
18285         68/push 0/imm32
18286         89/<- %eax 4/r32/esp
18287         #
18288         (parse-mu-named-block %edx *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
18289         (append-to-block Heap %edi  *eax *(eax+4))
18290         # reclaim tmp
18291         81 0/subop/add %esp 8/imm32
18292         #
18293         e9/jump $parse-mu-block:line-loop/disp32
18294       }
18295       # if slice-equal?(word-slice, "var")
18296       {
18297 $parse-mu-block:check-for-var:
18298         (slice-equal? %edx "var")
18299         3d/compare-eax-and 0/imm32/false
18300         74/jump-if-= break/disp8
18301         # var tmp/eax: (handle block)
18302         68/push 0/imm32
18303         68/push 0/imm32
18304         89/<- %eax 4/r32/esp
18305         #
18306         (parse-mu-var-def %ecx *(ebp+0xc) %eax *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
18307         (append-to-block Heap %edi  *eax *(eax+4))
18308         # reclaim tmp
18309         81 0/subop/add %esp 8/imm32
18310         #
18311         e9/jump $parse-mu-block:line-loop/disp32
18312       }
18313 $parse-mu-block:regular-stmt:
18314       # otherwise
18315       # var tmp/eax: (handle block)
18316       68/push 0/imm32
18317       68/push 0/imm32
18318       89/<- %eax 4/r32/esp
18319       #
18320       (parse-mu-stmt %ecx *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
18321       (append-to-block Heap %edi  *eax *(eax+4))
18322       # reclaim tmp
18323       81 0/subop/add %esp 8/imm32
18324       #
18325       e9/jump loop/disp32
18326     } # end line loop
18327     (clean-up-blocks *(ebp+0xc) *Curr-block-depth *(ebp+0x10))
18328     # decrement *Curr-block-depth
18329     ff 1/subop/decrement *Curr-block-depth
18330     # pop(vars)
18331     (pop *(ebp+0xc))  # => eax
18332     (pop *(ebp+0xc))  # => eax
18333     (pop *(ebp+0xc))  # => eax
18334 $parse-mu-block:end:
18335     # . reclaim locals
18336     81 0/subop/add %esp 0x214/imm32
18337     # . restore registers
18338     5f/pop-to-edi
18339     5b/pop-to-ebx
18340     5a/pop-to-edx
18341     59/pop-to-ecx
18342     58/pop-to-eax
18343     # . epilogue
18344     89/<- %esp 5/r32/ebp
18345     5d/pop-to-ebp
18346     c3/return
18347 
18348 $parse-mu-block:abort:
18349     # error("'{' or '}' should be on its own line, but got '")
18350     (write-buffered *(ebp+0x18) "'{' or '}' should be on its own line, but got '")
18351     (rewind-stream %ecx)
18352     (write-stream-data *(ebp+0x18) %ecx)
18353     (write-buffered *(ebp+0x18) "'\n")
18354     (flush *(ebp+0x18))
18355     (stop *(ebp+0x1c) 1)
18356     # never gets here
18357 
18358 new-block-name:  # fn: (addr function), out: (addr handle var)
18359     # . prologue
18360     55/push-ebp
18361     89/<- %ebp 4/r32/esp
18362     # . save registers
18363     50/push-eax
18364     51/push-ecx
18365     52/push-edx
18366     # var n/ecx: int = len(fn->name) + 10 for an int + 2 for '$:'
18367     8b/-> *(ebp+8) 0/r32/eax
18368     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18369     8b/-> *eax 0/r32/eax  # String-size
18370     05/add-to-eax 0xd/imm32  # 10 + 2 for '$:'
18371     89/<- %ecx 0/r32/eax
18372     # var name/edx: (stream byte n)
18373     29/subtract-from %esp 1/r32/ecx
18374     ff 6/subop/push %ecx
18375     68/push 0/imm32/read
18376     68/push 0/imm32/write
18377     89/<- %edx 4/r32/esp
18378     (clear-stream %edx)
18379     # eax = fn->name
18380     8b/-> *(ebp+8) 0/r32/eax
18381     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18382     # construct result using Next-block-index (and increment it)
18383     (write %edx "$")
18384     (write %edx %eax)
18385     (write %edx ":")
18386     (write-int32-hex %edx *Next-block-index)
18387     ff 0/subop/increment *Next-block-index
18388     # var s/eax: slice = {name->data, name->data + name->write}  (clobbering edx)
18389     # . eax = name->write
18390     8b/-> *edx 0/r32/eax
18391     # . edx = name->data
18392     8d/copy-address *(edx+0xc) 2/r32/edx
18393     # . eax = name->write + name->data
18394     01/add-to %eax 2/r32/edx
18395     # . push {edx, eax}
18396     ff 6/subop/push %eax
18397     ff 6/subop/push %edx
18398     89/<- %eax 4/r32/esp
18399     # out = new literal(s)
18400     (new-literal Heap %eax *(ebp+0xc))
18401 #?     8b/-> *(ebp+0xc) 0/r32/eax
18402 #?     (write-buffered Stderr "type allocid in caller after new-literal: ")
18403 #?     (write-int32-hex-buffered Stderr *(eax+8))
18404 #?     (write-buffered Stderr " for var ")
18405 #?     (write-int32-hex-buffered Stderr %eax)
18406 #?     (write-buffered Stderr Newline)
18407 #?     (flush Stderr)
18408 $new-block-name:end:
18409     # . reclaim locals
18410     81 0/subop/add %ecx 0xc/imm32  # name.{read/write/len}
18411     81 0/subop/add %ecx 8/imm32  # slice
18412     01/add-to %esp 1/r32/ecx
18413     # . restore registers
18414     5a/pop-to-edx
18415     59/pop-to-ecx
18416     58/pop-to-eax
18417     # . epilogue
18418     89/<- %esp 5/r32/ebp
18419     5d/pop-to-ebp
18420     c3/return
18421 
18422 check-no-tokens-left:  # line: (addr stream byte)
18423     # . prologue
18424     55/push-ebp
18425     89/<- %ebp 4/r32/esp
18426     # . save registers
18427     50/push-eax
18428     51/push-ecx
18429     # var s/ecx: slice
18430     68/push 0/imm32/end
18431     68/push 0/imm32/start
18432     89/<- %ecx 4/r32/esp
18433     #
18434     (next-mu-token *(ebp+8) %ecx)
18435     # if slice-empty?(s) return
18436     (slice-empty? %ecx)
18437     3d/compare-eax-and 0/imm32/false
18438     75/jump-if-!= $check-no-tokens-left:end/disp8
18439     # if (slice-starts-with?(s, '#') return
18440     # . eax = *s->start
18441     8b/-> *edx 0/r32/eax
18442     8a/copy-byte *eax 0/r32/AL
18443     25/and-eax-with 0xff/imm32
18444     # . if (eax == '#') continue
18445     3d/compare-eax-and 0x23/imm32/hash
18446     74/jump-if-= $check-no-tokens-left:end/disp8
18447     # abort
18448     (write-buffered Stderr "'{' or '}' should be on its own line, but got '")
18449     (rewind-stream %ecx)
18450     (write-stream 2 %ecx)
18451     (write-buffered Stderr "'\n")
18452     (flush Stderr)
18453     # . syscall(exit, 1)
18454     bb/copy-to-ebx  1/imm32
18455     e8/call syscall_exit/disp32
18456     # never gets here
18457 $check-no-tokens-left:end:
18458     # . reclaim locals
18459     81 0/subop/add %esp 8/imm32
18460     # . restore registers
18461     59/pop-to-ecx
18462     58/pop-to-eax
18463     # . epilogue
18464     89/<- %esp 5/r32/ebp
18465     5d/pop-to-ebp
18466     c3/return
18467 
18468 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)
18469     # pseudocode:
18470     #   var v: (handle var)
18471     #   new-literal(name, v)
18472     #   push(vars, {v, false})
18473     #   parse-mu-block(in, vars, fn, out)
18474     #   pop(vars)
18475     #   out->tag = block
18476     #   out->var = v
18477     #
18478     # . prologue
18479     55/push-ebp
18480     89/<- %ebp 4/r32/esp
18481     # . save registers
18482     50/push-eax
18483     51/push-ecx
18484     57/push-edi
18485     # var v/ecx: (handle var)
18486     68/push 0/imm32
18487     68/push 0/imm32
18488     89/<- %ecx 4/r32/esp
18489     #
18490     (new-literal Heap *(ebp+8) %ecx)
18491     # push(vars, v)
18492     (push *(ebp+0x10) *ecx)
18493     (push *(ebp+0x10) *(ecx+4))
18494     (push *(ebp+0x10) 0)  # false
18495     #
18496     (parse-mu-block *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c) *(ebp+0x20))
18497     # pop v off vars
18498     (pop *(ebp+0x10))  # => eax
18499     (pop *(ebp+0x10))  # => eax
18500     (pop *(ebp+0x10))  # => eax
18501     # var out-addr/edi: (addr stmt) = lookup(*out)
18502     8b/-> *(ebp+0x18) 7/r32/edi
18503     (lookup *edi *(edi+4))  # => eax
18504     89/<- %edi 0/r32/eax
18505     # out-addr->tag = named-block
18506     c7 0/subop/copy *edi 0/imm32/block  # Stmt-tag
18507     # out-addr->var = v
18508     8b/-> *ecx 0/r32/eax
18509     89/<- *(edi+0xc) 0/r32/eax  # Block-var
18510     8b/-> *(ecx+4) 0/r32/eax
18511     89/<- *(edi+0x10) 0/r32/eax  # Block-var
18512 $parse-mu-named-block:end:
18513     # . reclaim locals
18514     81 0/subop/add %esp 8/imm32
18515     # . restore registers
18516     5f/pop-to-edi
18517     59/pop-to-ecx
18518     58/pop-to-eax
18519     # . epilogue
18520     89/<- %esp 5/r32/ebp
18521     5d/pop-to-ebp
18522     c3/return
18523 
18524 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)
18525     # . prologue
18526     55/push-ebp
18527     89/<- %ebp 4/r32/esp
18528     # . save registers
18529     50/push-eax
18530     51/push-ecx
18531     52/push-edx
18532     56/push-esi
18533     57/push-edi
18534     # edi = out
18535     8b/-> *(ebp+0x10) 7/r32/edi
18536     # var word-slice/ecx: slice
18537     68/push 0/imm32/end
18538     68/push 0/imm32/start
18539     89/<- %ecx 4/r32/esp
18540     # var v/edx: (handle var)
18541     68/push 0/imm32
18542     68/push 0/imm32
18543     89/<- %edx 4/r32/esp
18544     # v = parse-var-with-type(next-mu-token(line))
18545     (next-mu-token *(ebp+8) %ecx)
18546     {
18547       # just for tests, support null fn
18548       8b/-> *(ebp+0x14) 0/r32/eax
18549       3d/compare-eax-and 0/imm32
18550       74/jump-if-= break/disp8
18551       (lookup *eax *(eax+4))  # Var-name Var-name => eax
18552     }
18553     (parse-var-with-type %ecx *(ebp+8) %edx %eax *(ebp+0x18) *(ebp+0x1c))
18554     # var v-addr/esi: (addr var)
18555     (lookup *edx *(edx+4))  # => eax
18556     89/<- %esi 0/r32/eax
18557     # v->block-depth = *Curr-block-depth
18558     8b/-> *Curr-block-depth 0/r32/eax
18559     89/<- *(esi+0x10) 0/r32/eax  # Var-block-depth
18560     # either v has no register and there's no more to this line
18561     81 7/subop/compare *(esi+0x18) 0/imm32
18562     {
18563       75/jump-if-!= break/disp8
18564       # if v-addr->type == byte, abort
18565       (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
18566       (simple-mu-type? %eax 8)  # byte => eax
18567       3d/compare-eax-and 0/imm32/false
18568       0f 85/jump-if-!= $parse-mu-var-def:error-byte-on-stack/disp32
18569       # ensure that there's nothing else on this line
18570       (next-mu-token *(ebp+8) %ecx)
18571       (slice-empty? %ecx)  # => eax
18572       3d/compare-eax-and 0/imm32/false
18573       0f 84/jump-if-= $parse-mu-var-def:error2/disp32
18574       #
18575       (new-var-def Heap  *edx *(edx+4)  %edi)
18576       e9/jump $parse-mu-var-def:update-vars/disp32
18577     }
18578     # or v has a register and there's more to this line
18579     {
18580       0f 84/jump-if-= break/disp32
18581       # if v-addr->type == byte, check for unsupported registers
18582       {
18583         (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
18584         (simple-mu-type? %eax 8)  # byte => eax
18585         3d/compare-eax-and 0/imm32/false
18586         74/jump-if-= break/disp8
18587         (lookup *(esi+0x18) *(esi+0x1c))  # => eax
18588         (string-equal? %eax "esi")  # => eax
18589         3d/compare-eax-and 0/imm32/false
18590         0f 85/jump-if-!= $parse-mu-var-def:error-byte-registers/disp32
18591         (lookup *(esi+0x18) *(esi+0x1c))  # => eax
18592         (string-equal? %eax "edi")  # => eax
18593         3d/compare-eax-and 0/imm32/false
18594         0f 85/jump-if-!= $parse-mu-var-def:error-byte-registers/disp32
18595       }
18596       # TODO: vars of type 'byte' should only be initialized by clearing to 0
18597       # ensure that the next word is '<-'
18598       (next-mu-token *(ebp+8) %ecx)
18599       (slice-equal? %ecx "<-")  # => eax
18600       3d/compare-eax-and 0/imm32/false
18601       0f 84/jump-if-= $parse-mu-var-def:error1/disp32
18602       #
18603       (new-reg-var-def Heap  *edx *(edx+4)  %edi)
18604       (lookup *edi *(edi+4))  # => eax
18605       (add-operation-and-inputs-to-stmt %eax *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
18606     }
18607 $parse-mu-var-def:update-vars:
18608     # push 'v' at end of function
18609     (push *(ebp+0xc) *edx)
18610     (push *(ebp+0xc) *(edx+4))
18611     (push *(ebp+0xc) 0)  # Live-var-register-spilled is unused during parsing
18612 $parse-mu-var-def:end:
18613     # . reclaim locals
18614     81 0/subop/add %esp 0x10/imm32
18615     # . restore registers
18616     5f/pop-to-edi
18617     5e/pop-to-esi
18618     5a/pop-to-edx
18619     59/pop-to-ecx
18620     58/pop-to-eax
18621     # . epilogue
18622     89/<- %esp 5/r32/ebp
18623     5d/pop-to-ebp
18624     c3/return
18625 
18626 $parse-mu-var-def:error1:
18627     (rewind-stream *(ebp+8))
18628     # error("register variable requires a valid instruction to initialize but got '" line "'\n")
18629     (write-buffered *(ebp+0x18) "register variable requires a valid instruction to initialize but got '")
18630     (flush *(ebp+0x18))
18631     (write-stream-data *(ebp+0x18) *(ebp+8))
18632     (write-buffered *(ebp+0x18) "'\n")
18633     (flush *(ebp+0x18))
18634     (stop *(ebp+0x1c) 1)
18635     # never gets here
18636 
18637 $parse-mu-var-def:error2:
18638     # error("fn " fn ": var " var ": variables on the stack can't take an initializer\n")
18639     (write-buffered *(ebp+0x18) "fn ")
18640     8b/-> *(ebp+0x14) 0/r32/eax
18641     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18642     (write-buffered *(ebp+0x18) %eax)
18643     (write-buffered *(ebp+0x18) ": var ")
18644     # var v-addr/eax: (addr var) = lookup(v)
18645     (lookup *edx *(edx+4))  # => eax
18646     (lookup *eax *(eax+4))  # Var-name Var-name => eax
18647     (write-buffered *(ebp+0x18) %eax)
18648     (write-buffered *(ebp+0x18) ": variables on the stack can't take an initializer\n")
18649     (flush *(ebp+0x18))
18650     (stop *(ebp+0x1c) 1)
18651     # never gets here
18652 
18653 $parse-mu-var-def:error-byte-on-stack:
18654     # error("fn " fn ": var '" var "' of type 'byte' cannot be on the stack\n")
18655     (write-buffered *(ebp+0x18) "fn ")
18656     8b/-> *(ebp+0x14) 0/r32/eax
18657     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18658     (write-buffered *(ebp+0x18) %eax)
18659     (write-buffered *(ebp+0x18) ": var '")
18660     # var v-addr/eax: (addr var) = lookup(v)
18661     (lookup *edx *(edx+4))  # => eax
18662     (lookup *eax *(eax+4))  # Var-name Var-name => eax
18663     (write-buffered *(ebp+0x18) %eax)
18664     (write-buffered *(ebp+0x18) "' of type 'byte' cannot be on the stack\n")
18665     (flush *(ebp+0x18))
18666     (stop *(ebp+0x1c) 1)
18667     # never gets here
18668 
18669 $parse-mu-var-def:error-byte-registers:
18670     # error("fn " fn ": var '" var "' of type 'byte' cannot be in esi or edi\n")
18671     (write-buffered *(ebp+0x18) "fn ")
18672     8b/-> *(ebp+0x14) 0/r32/eax
18673     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18674     (write-buffered *(ebp+0x18) %eax)
18675     (write-buffered *(ebp+0x18) ": var '")
18676     # var v-addr/eax: (addr var) = lookup(v)
18677     (lookup *edx *(edx+4))  # => eax
18678     (lookup *eax *(eax+4))  # Var-name Var-name => eax
18679     (write-buffered *(ebp+0x18) %eax)
18680     (write-buffered *(ebp+0x18) "' of type 'byte' cannot be in esi or edi\n")
18681     (flush *(ebp+0x18))
18682     (stop *(ebp+0x1c) 1)
18683     # never gets here
18684 
18685 test-parse-mu-var-def:
18686     # 'var n: int'
18687     # . prologue
18688     55/push-ebp
18689     89/<- %ebp 4/r32/esp
18690     # setup
18691     8b/-> *Primitive-type-ids 0/r32/eax
18692     89/<- *Type-id 0/r32/eax  # stream-write
18693     (clear-stream _test-input-stream)
18694     (write _test-input-stream "n: int\n")  # caller has consumed the 'var'
18695     c7 0/subop/copy *Curr-block-depth 1/imm32
18696     # var out/esi: (handle stmt)
18697     68/push 0/imm32
18698     68/push 0/imm32
18699     89/<- %esi 4/r32/esp
18700     # var vars/ecx: (stack (addr var) 16)
18701     81 5/subop/subtract %esp 0xc0/imm32
18702     68/push 0xc0/imm32/size
18703     68/push 0/imm32/top
18704     89/<- %ecx 4/r32/esp
18705     (clear-stack %ecx)
18706     # convert
18707     (parse-mu-var-def _test-input-stream %ecx %esi 0 Stderr 0)
18708     # var out-addr/esi: (addr stmt)
18709     (lookup *esi *(esi+4))  # => eax
18710     89/<- %esi 0/r32/eax
18711     #
18712     (check-ints-equal *esi 2 "F - test-parse-mu-var-def/tag")  # Stmt-tag is var-def
18713     # var v/ecx: (addr var) = lookup(out->var)
18714     (lookup *(esi+4) *(esi+8))  # Vardef-var Vardef-var => eax
18715     89/<- %ecx 0/r32/eax
18716     # v->name
18717     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
18718     (check-strings-equal %eax "n" "F - test-parse-mu-var-def/var-name")
18719     # v->register
18720     (check-ints-equal *(ecx+0x18) 0 "F - test-parse-mu-var-def/var-register")  # Var-register
18721     # v->block-depth
18722     (check-ints-equal *(ecx+0x10) 1 "F - test-parse-mu-var-def/output-block-depth")  # Var-block-depth
18723     # v->type == int
18724     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
18725     (check-ints-equal *eax 1 "F - test-parse-mu-var-def/var-type:0")  # Type-tree-is-atom
18726     (check-ints-equal *(eax+4) 1 "F - test-parse-mu-var-def/var-type:1")  # Type-tree-value
18727     (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-var-def/var-type:2")  # Type-tree-right
18728     # . epilogue
18729     89/<- %esp 5/r32/ebp
18730     5d/pop-to-ebp
18731     c3/return
18732 
18733 test-parse-mu-reg-var-def:
18734     # 'var n/eax: int <- copy 0'
18735     # . prologue
18736     55/push-ebp
18737     89/<- %ebp 4/r32/esp
18738     # setup
18739     8b/-> *Primitive-type-ids 0/r32/eax
18740     89/<- *Type-id 0/r32/eax  # stream-write
18741     (clear-stream _test-input-stream)
18742     (write _test-input-stream "n/eax: int <- copy 0\n")  # caller has consumed the 'var'
18743     c7 0/subop/copy *Curr-block-depth 1/imm32
18744     # var out/esi: (handle stmt)
18745     68/push 0/imm32
18746     68/push 0/imm32
18747     89/<- %esi 4/r32/esp
18748     # var vars/ecx: (stack (addr var) 16)
18749     81 5/subop/subtract %esp 0xc0/imm32
18750     68/push 0xc0/imm32/size
18751     68/push 0/imm32/top
18752     89/<- %ecx 4/r32/esp
18753     (clear-stack %ecx)
18754     # convert
18755     (parse-mu-var-def _test-input-stream %ecx %esi 0 Stderr 0)
18756     # var out-addr/esi: (addr stmt)
18757     (lookup *esi *(esi+4))  # => eax
18758     89/<- %esi 0/r32/eax
18759     #
18760     (check-ints-equal *esi 3 "F - test-parse-mu-reg-var-def/tag")  # Stmt-tag is reg-var-def
18761     # var v/ecx: (addr var) = lookup(out->outputs->value)
18762     # . eax: (addr stmt-var) = lookup(out->outputs)
18763     (lookup *(esi+0x14) *(esi+0x18))  # Regvardef-outputs Regvardef-outputs => eax
18764     # .
18765     (check-ints-equal *(eax+8) 0 "F - test-parse-mu-reg-var-def/single-output")  # Stmt-var-next
18766     # . eax: (addr var) = lookup(eax->value)
18767     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
18768     # . ecx = eax
18769     89/<- %ecx 0/r32/eax
18770     # v->name
18771     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
18772     (check-strings-equal %eax "n" "F - test-parse-mu-reg-var-def/output-name")  # Var-name
18773     # v->register
18774     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
18775     (check-strings-equal %eax "eax" "F - test-parse-mu-reg-var-def/output-register")
18776     # v->block-depth
18777     (check-ints-equal *(ecx+0x10) 1 "F - test-parse-mu-reg-var-def/output-block-depth")  # Var-block-depth
18778     # v->type == int
18779     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
18780     (check-ints-equal *eax 1 "F - test-parse-mu-reg-var-def/output-type:0")  # Type-tree-is-atom
18781     (check-ints-equal *(eax+4) 1 "F - test-parse-mu-reg-var-def/output-type:1")  # Type-tree-value
18782     (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-reg-var-def/output-type:2")  # Type-tree-right
18783     # . epilogue
18784     89/<- %esp 5/r32/ebp
18785     5d/pop-to-ebp
18786     c3/return
18787 
18788 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)
18789     # pseudocode:
18790     #   var name: slice
18791     #   allocate(Heap, Stmt-size, out)
18792     #   var out-addr: (addr stmt) = lookup(*out)
18793     #   out-addr->tag = stmt
18794     #   if stmt-has-outputs?(line)
18795     #     while true
18796     #       name = next-mu-token(line)
18797     #       if (name == '<-') break
18798     #       assert(identifier?(name))
18799     #       var v: (handle var) = lookup-var(name, vars)
18800     #       out-addr->outputs = append(v, out-addr->outputs)
18801     #   add-operation-and-inputs-to-stmt(out-addr, line, vars)
18802     #
18803     # . prologue
18804     55/push-ebp
18805     89/<- %ebp 4/r32/esp
18806     # . save registers
18807     50/push-eax
18808     51/push-ecx
18809     52/push-edx
18810     53/push-ebx
18811     57/push-edi
18812     # var name/ecx: slice
18813     68/push 0/imm32/end
18814     68/push 0/imm32/start
18815     89/<- %ecx 4/r32/esp
18816     # var is-deref?/edx: boolean = false
18817     ba/copy-to-edx 0/imm32/false
18818     # var v: (handle var)
18819     68/push 0/imm32
18820     68/push 0/imm32
18821     89/<- %ebx 4/r32/esp
18822     #
18823     (allocate Heap *Stmt-size *(ebp+0x14))
18824     # var out-addr/edi: (addr stmt) = lookup(*out)
18825     8b/-> *(ebp+0x14) 7/r32/edi
18826     (lookup *edi *(edi+4))  # => eax
18827     89/<- %edi 0/r32/eax
18828     # out-addr->tag = 1/stmt
18829     c7 0/subop/copy *edi 1/imm32/stmt1  # Stmt-tag
18830     {
18831       (stmt-has-outputs? *(ebp+8))
18832       3d/compare-eax-and 0/imm32/false
18833       0f 84/jump-if-= break/disp32
18834       {
18835 $parse-mu-stmt:read-outputs:
18836         # name = next-mu-token(line)
18837         (next-mu-token *(ebp+8) %ecx)
18838         # if slice-empty?(word-slice) break
18839         (slice-empty? %ecx)  # => eax
18840         3d/compare-eax-and 0/imm32/false
18841         0f 85/jump-if-!= break/disp32
18842         # if (name == "<-") break
18843         (slice-equal? %ecx "<-")  # => eax
18844         3d/compare-eax-and 0/imm32/false
18845         0f 85/jump-if-!= break/disp32
18846         # if slice-starts-with?(name, "*") abort
18847         8b/-> *ecx 0/r32/eax  # Slice-start
18848         8a/copy-byte *eax 0/r32/AL
18849         25/and-eax-with 0xff/imm32
18850         3d/compare-eax-and 0x2a/imm32/asterisk
18851         0f 84/jump-if-= $parse-mu-stmt:error-output-dereferenced/disp32
18852         # assert(identifier?(name))
18853         (identifier? %ecx)  # => eax
18854         3d/compare-eax-and 0/imm32/false
18855         0f 84/jump-if-= $parse-mu-stmt:abort/disp32
18856         #
18857         (lookup-var %ecx *(ebp+0xc) %ebx *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
18858         8d/copy-address *(edi+0x14) 0/r32/eax  # Stmt1-outputs
18859         (append-stmt-var Heap  *ebx *(ebx+4)  *(edi+0x14) *(edi+0x18)  0  %eax)  # Stmt1-outputs
18860         #
18861         e9/jump loop/disp32
18862       }
18863     }
18864     (add-operation-and-inputs-to-stmt %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
18865 $parse-mu-stmt:end:
18866     # . reclaim locals
18867     81 0/subop/add %esp 0x10/imm32
18868     # . restore registers
18869     5f/pop-to-edi
18870     5b/pop-to-ebx
18871     5a/pop-to-edx
18872     59/pop-to-ecx
18873     58/pop-to-eax
18874     # . epilogue
18875     89/<- %esp 5/r32/ebp
18876     5d/pop-to-ebp
18877     c3/return
18878 
18879 $parse-mu-stmt:abort:
18880     # error("invalid identifier '" name "'\n")
18881     (write-buffered *(ebp+0x18) "fn ")
18882     8b/-> *(ebp+0x10) 0/r32/eax
18883     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18884     (write-buffered *(ebp+0x18) %eax)
18885     (write-buffered *(ebp+0x18) ": invalid identifier '")
18886     (write-slice-buffered *(ebp+0x18) %ecx)
18887     (write-buffered *(ebp+0x18) "'\n")
18888     (flush *(ebp+0x18))
18889     (stop *(ebp+0x1c) 1)
18890     # never gets here
18891 
18892 $parse-mu-stmt:error-output-dereferenced:
18893     # error("invalid identifier '" name "'\n")
18894     (write-buffered *(ebp+0x18) "fn ")
18895     8b/-> *(ebp+0x10) 0/r32/eax
18896     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18897     (write-buffered *(ebp+0x18) %eax)
18898     (write-buffered *(ebp+0x18) ": output '")
18899     (write-slice-buffered *(ebp+0x18) %ecx)
18900     (write-buffered *(ebp+0x18) "' should write to a register, and therefore cannot be dereferenced\n")
18901     (flush *(ebp+0x18))
18902     (stop *(ebp+0x1c) 1)
18903     # never gets here
18904 
18905 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)
18906     # pseudocode:
18907     #   stmt->name = slice-to-string(next-mu-token(line))
18908     #   while true
18909     #     name = next-mu-token(line)
18910     #     v = lookup-var-or-literal(name)
18911     #     stmt->inouts = append(v, stmt->inouts)
18912     #
18913     # . prologue
18914     55/push-ebp
18915     89/<- %ebp 4/r32/esp
18916     # . save registers
18917     50/push-eax
18918     51/push-ecx
18919     52/push-edx
18920     53/push-ebx
18921     56/push-esi
18922     57/push-edi
18923     # edi = stmt
18924     8b/-> *(ebp+8) 7/r32/edi
18925     # var name/ecx: slice
18926     68/push 0/imm32/end
18927     68/push 0/imm32/start
18928     89/<- %ecx 4/r32/esp
18929     # var is-deref?/edx: boolean = false
18930     ba/copy-to-edx 0/imm32/false
18931     # var v/esi: (handle var)
18932     68/push 0/imm32
18933     68/push 0/imm32
18934     89/<- %esi 4/r32/esp
18935 $add-operation-and-inputs-to-stmt:read-operation:
18936     (next-mu-token *(ebp+0xc) %ecx)
18937     8d/copy-address *(edi+4) 0/r32/eax  # Stmt1-operation or Regvardef-operationStmt1-operation or Regvardef-operation
18938     (slice-to-string Heap %ecx %eax)
18939     # var is-get?/ebx: boolean = (name == "get")
18940     (slice-equal? %ecx "get")  # => eax
18941     89/<- %ebx 0/r32/eax
18942     {
18943 $add-operation-and-inputs-to-stmt:read-inouts:
18944       # name = next-mu-token(line)
18945       (next-mu-token *(ebp+0xc) %ecx)
18946       # if slice-empty?(word-slice) break
18947       (slice-empty? %ecx)  # => eax
18948       3d/compare-eax-and 0/imm32/false
18949       0f 85/jump-if-!= break/disp32
18950       # if (name == "<-") abort
18951       (slice-equal? %ecx "<-")
18952       3d/compare-eax-and 0/imm32/false
18953       0f 85/jump-if-!= $add-operation-and-inputs-to-stmt:abort/disp32
18954       # if (get? && second operand) lookup or create offset
18955       {
18956         81 7/subop/compare %ebx 0/imm32/false
18957         74/jump-if-= break/disp8
18958         (lookup *(edi+0xc) *(edi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
18959         3d/compare-eax-and 0/imm32
18960         74/jump-if-= break/disp8
18961         (lookup-or-create-constant %eax %ecx %esi)
18962 #?         (lookup *esi *(esi+4))
18963 #?         (write-buffered Stderr "creating new output var ")
18964 #?         (write-int32-hex-buffered Stderr %eax)
18965 #?         (write-buffered Stderr " for field called ")
18966 #?         (write-slice-buffered Stderr %ecx)
18967 #?         (write-buffered Stderr "; var name ")
18968 #?         (lookup *eax *(eax+4))  # Var-name
18969 #?         (write-buffered Stderr %eax)
18970 #?         (write-buffered Stderr Newline)
18971 #?         (flush Stderr)
18972         e9/jump $add-operation-and-inputs-to-stmt:save-var/disp32
18973       }
18974       # is-deref? = false
18975       ba/copy-to-edx 0/imm32/false
18976       # if (slice-starts-with?(name, '*')) ++name->start and set is-deref?
18977       8b/-> *ecx 0/r32/eax  # Slice-start
18978       8a/copy-byte *eax 0/r32/AL
18979       25/and-eax-with 0xff/imm32
18980       3d/compare-eax-and 0x2a/imm32/asterisk
18981       {
18982         75/jump-if-!= break/disp8
18983 $add-operation-and-inputs-to-stmt:inout-is-deref:
18984         ff 0/subop/increment *ecx
18985         ba/copy-to-edx 1/imm32/true
18986       }
18987       (lookup-var-or-literal %ecx *(ebp+0x10) %esi *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
18988       # if (deref?) some additional checks
18989       81 7/subop/compare %edx 0/imm32/false
18990       {
18991         74/jump-if-= break/disp8
18992         # if var is not in register, abort
18993         (lookup *esi *(esi+4))  # => eax
18994         81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
18995         0f 84/jump-if-= $add-operation-and-inputs-to-stmt:error-deref-on-stack/disp32
18996         # if var is not an address, abort
18997         (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
18998         (mu-addr-type? %eax)  # => eax
18999         3d/compare-eax-and 0/imm32/false
19000         0f 84/jump-if-= $add-operation-and-inputs-to-stmt:error-deref-non-addr/disp32
19001       }
19002 $add-operation-and-inputs-to-stmt:save-var:
19003       8d/copy-address *(edi+0xc) 0/r32/eax
19004       (append-stmt-var Heap  *esi *(esi+4)  *(edi+0xc) *(edi+0x10)  %edx  %eax)  # Stmt1-inouts or Regvardef-inouts
19005       #
19006       e9/jump loop/disp32
19007     }
19008 $add-operation-and-inputs-to-stmt:end:
19009     # . reclaim locals
19010     81 0/subop/add %esp 0x10/imm32
19011     # . restore registers
19012     5f/pop-to-edi
19013     5e/pop-to-esi
19014     5b/pop-to-ebx
19015     5a/pop-to-edx
19016     59/pop-to-ecx
19017     58/pop-to-eax
19018     # . epilogue
19019     89/<- %esp 5/r32/ebp
19020     5d/pop-to-ebp
19021     c3/return
19022 
19023 $add-operation-and-inputs-to-stmt:abort:
19024     # error("fn ___: invalid identifier in '" line "'\n")
19025     (write-buffered *(ebp+0x18) "fn ")
19026     8b/-> *(ebp+0x14) 0/r32/eax
19027     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19028     (write-buffered *(ebp+0x18) %eax)
19029     (rewind-stream *(ebp+0xc))
19030     (write-buffered *(ebp+0x18) ": invalid identifier in '")
19031     (write-stream-data *(ebp+0x18) *(ebp+0xc))
19032     (write-buffered *(ebp+0x18) "'\n")
19033     (flush *(ebp+0x18))
19034     (stop *(ebp+0x1c) 1)
19035     # never gets here
19036 
19037 $add-operation-and-inputs-to-stmt:error-deref-on-stack:
19038     # error("fn ___: cannot dereference var ___ on stack\n")
19039     (write-buffered *(ebp+0x18) "fn ")
19040     8b/-> *(ebp+0x14) 0/r32/eax
19041     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19042     (write-buffered *(ebp+0x18) %eax)
19043     (rewind-stream *(ebp+0xc))
19044     (write-buffered *(ebp+0x18) ": cannot dereference var '")
19045     (lookup *esi *(esi+4))  # => eax
19046     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19047     (write-buffered *(ebp+0x18) %eax)
19048     (write-buffered *(ebp+0x18) "' on stack\n")
19049     (flush *(ebp+0x18))
19050     (stop *(ebp+0x1c) 1)
19051     # never gets here
19052 
19053 $add-operation-and-inputs-to-stmt:error-deref-non-addr:
19054     # error("fn ___: cannot dereference non-addr var ___\n")
19055     (write-buffered *(ebp+0x18) "fn ")
19056     8b/-> *(ebp+0x14) 0/r32/eax
19057     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19058     (write-buffered *(ebp+0x18) %eax)
19059     (rewind-stream *(ebp+0xc))
19060     (write-buffered *(ebp+0x18) ": cannot dereference non-addr var '")
19061     (lookup *esi *(esi+4))  # => eax
19062     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19063     (write-buffered *(ebp+0x18) %eax)
19064     (write-buffered *(ebp+0x18) "'\n")
19065     (flush *(ebp+0x18))
19066     (stop *(ebp+0x1c) 1)
19067     # never gets here
19068 
19069 stmt-has-outputs?:  # line: (addr stream byte) -> result/eax: boolean
19070     # . prologue
19071     55/push-ebp
19072     89/<- %ebp 4/r32/esp
19073     # . save registers
19074     51/push-ecx
19075     # var word-slice/ecx: slice
19076     68/push 0/imm32/end
19077     68/push 0/imm32/start
19078     89/<- %ecx 4/r32/esp
19079     # result = false
19080     b8/copy-to-eax 0/imm32/false
19081     (rewind-stream *(ebp+8))
19082     {
19083       (next-mu-token *(ebp+8) %ecx)
19084       # if slice-empty?(word-slice) break
19085       (slice-empty? %ecx)
19086       3d/compare-eax-and 0/imm32/false
19087       b8/copy-to-eax 0/imm32/false/result  # restore result (if we're here it's still false)
19088       0f 85/jump-if-!= break/disp32
19089       # if slice-starts-with?(word-slice, '#') break
19090       # . eax = *word-slice->start
19091       8b/-> *ecx 0/r32/eax
19092       8a/copy-byte *eax 0/r32/AL
19093       25/and-eax-with 0xff/imm32
19094       # . if (eax == '#') break
19095       3d/compare-eax-and 0x23/imm32/hash
19096       b8/copy-to-eax 0/imm32/false/result  # restore result (if we're here it's still false)
19097       0f 84/jump-if-= break/disp32
19098       # if slice-equal?(word-slice, '<-') return true
19099       (slice-equal? %ecx "<-")
19100       3d/compare-eax-and 0/imm32/false
19101       74/jump-if-= loop/disp8
19102       b8/copy-to-eax 1/imm32/true
19103     }
19104 $stmt-has-outputs:end:
19105     (rewind-stream *(ebp+8))
19106     # . reclaim locals
19107     81 0/subop/add %esp 8/imm32
19108     # . restore registers
19109     59/pop-to-ecx
19110     # . epilogue
19111     89/<- %esp 5/r32/ebp
19112     5d/pop-to-ebp
19113     c3/return
19114 
19115 # if 'name' starts with a digit, create a new literal var for it
19116 # otherwise return first 'name' from the top (back) of 'vars' and abort if not found
19117 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)
19118     # . prologue
19119     55/push-ebp
19120     89/<- %ebp 4/r32/esp
19121     # . save registers
19122     50/push-eax
19123     51/push-ecx
19124     56/push-esi
19125     # esi = name
19126     8b/-> *(ebp+8) 6/r32/esi
19127     # if slice-empty?(name) abort
19128     (slice-empty? %esi)  # => eax
19129     3d/compare-eax-and 0/imm32/false
19130     0f 85/jump-if-!= $lookup-var-or-literal:abort/disp32
19131     # var c/ecx: byte = *name->start
19132     8b/-> *esi 1/r32/ecx
19133     8a/copy-byte *ecx 1/r32/CL
19134     81 4/subop/and %ecx 0xff/imm32
19135     # if (decimal-digit?(c) || c == '-') return new var(name)
19136     {
19137       81 7/subop/compare %ecx 0x2d/imm32/dash
19138       74/jump-if-= $lookup-var-or-literal:literal/disp8
19139       (decimal-digit? %ecx)  # => eax
19140       3d/compare-eax-and 0/imm32/false
19141       74/jump-if-= break/disp8
19142 $lookup-var-or-literal:literal:
19143       (new-literal-integer Heap %esi *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
19144       eb/jump $lookup-var-or-literal:end/disp8
19145     }
19146     # else if (c == '"') return new var(name)
19147     {
19148       81 7/subop/compare %ecx 0x22/imm32/dquote
19149       75/jump-if-!= break/disp8
19150 $lookup-var-or-literal:literal-string:
19151       (new-literal-string Heap %esi *(ebp+0x10))
19152       eb/jump $lookup-var-or-literal:end/disp8
19153     }
19154     # otherwise return lookup-var(name, vars)
19155     {
19156 $lookup-var-or-literal:var:
19157       (lookup-var %esi *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
19158     }
19159 $lookup-var-or-literal:end:
19160     # . restore registers
19161     5e/pop-to-esi
19162     59/pop-to-ecx
19163     58/pop-to-eax
19164     # . epilogue
19165     89/<- %esp 5/r32/ebp
19166     5d/pop-to-ebp
19167     c3/return
19168 
19169 $lookup-var-or-literal:abort:
19170     (write-buffered *(ebp+0x18) "fn ")
19171     8b/-> *(ebp+0x14) 0/r32/eax
19172     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19173     (write-buffered *(ebp+0x18) %eax)
19174     (write-buffered *(ebp+0x18) ": empty variable!")
19175     (flush *(ebp+0x18))
19176     (stop *(ebp+0x1c) 1)
19177     # never gets here
19178 
19179 # return first 'name' from the top (back) of 'vars' and abort if not found
19180 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)
19181     # . prologue
19182     55/push-ebp
19183     89/<- %ebp 4/r32/esp
19184     # . save registers
19185     50/push-eax
19186     #
19187     (lookup-var-helper *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
19188     # if (*out == 0) abort
19189     8b/-> *(ebp+0x10) 0/r32/eax
19190     81 7/subop/compare *eax 0/imm32
19191     74/jump-if-= $lookup-var:abort/disp8
19192 $lookup-var:end:
19193     # . restore registers
19194     58/pop-to-eax
19195     # . epilogue
19196     89/<- %esp 5/r32/ebp
19197     5d/pop-to-ebp
19198     c3/return
19199 
19200 $lookup-var:abort:
19201     (write-buffered *(ebp+0x18) "fn ")
19202     8b/-> *(ebp+0x14) 0/r32/eax
19203     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19204     (write-buffered *(ebp+0x18) %eax)
19205     (write-buffered *(ebp+0x18) ": unknown variable '")
19206     (write-slice-buffered *(ebp+0x18) *(ebp+8))
19207     (write-buffered *(ebp+0x18) "'\n")
19208     (flush *(ebp+0x18))
19209     (stop *(ebp+0x1c) 1)
19210     # never gets here
19211 
19212 # return first 'name' from the top (back) of 'vars', and 0/null if not found
19213 # ensure that 'name' if in a register is the topmost variable in that register
19214 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)
19215     # pseudocode:
19216     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
19217     #   var min = vars->data
19218     #   while curr >= min
19219     #     var v: (handle var) = *curr
19220     #     if v->name == name
19221     #       return
19222     #     curr -= 12
19223     #
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     53/push-ebx
19232     56/push-esi
19233     57/push-edi
19234     # clear out
19235     (zero-out *(ebp+0x10) *Handle-size)
19236     # esi = vars
19237     8b/-> *(ebp+0xc) 6/r32/esi
19238     # ebx = vars->top
19239     8b/-> *esi 3/r32/ebx
19240     # if (vars->top > vars->size) abort
19241     3b/compare<- *(esi+4) 0/r32/eax
19242     0f 8f/jump-if-> $lookup-var-helper:error1/disp32
19243     # var min/edx: (addr handle var) = vars->data
19244     8d/copy-address *(esi+8) 2/r32/edx
19245     # var curr/ebx: (addr handle var) = &vars->data[vars->top - 12]
19246     8d/copy-address *(esi+ebx-4) 3/r32/ebx  # vars + 8 + vars->type - 12
19247     # var var-in-reg/edi: 16 addrs
19248     68/push 0/imm32
19249     68/push 0/imm32
19250     68/push 0/imm32
19251     68/push 0/imm32
19252     68/push 0/imm32
19253     68/push 0/imm32
19254     68/push 0/imm32
19255     68/push 0/imm32
19256     68/push 0/imm32
19257     68/push 0/imm32
19258     68/push 0/imm32
19259     68/push 0/imm32
19260     68/push 0/imm32
19261     68/push 0/imm32
19262     68/push 0/imm32
19263     68/push 0/imm32
19264     89/<- %edi 4/r32/esp
19265     {
19266 $lookup-var-helper:loop:
19267       # if (curr < min) return
19268       39/compare %ebx 2/r32/edx
19269       0f 82/jump-if-addr< break/disp32
19270       # var v/ecx: (addr var) = lookup(*curr)
19271       (lookup *ebx *(ebx+4))  # => eax
19272       89/<- %ecx 0/r32/eax
19273       # var vn/eax: (addr array byte) = lookup(v->name)
19274       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
19275       # if (vn == name) return curr
19276       (slice-equal? *(ebp+8) %eax)  # => eax
19277       3d/compare-eax-and 0/imm32/false
19278       {
19279         74/jump-if-= break/disp8
19280 $lookup-var-helper:found:
19281         # var vr/eax: (addr array byte) = lookup(v->register)
19282         (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
19283         3d/compare-eax-and 0/imm32
19284         {
19285           74/jump-if-= break/disp8
19286 $lookup-var-helper:found-register:
19287           # var reg/eax: int = get(Registers, vr)
19288           (get Mu-registers-unique %eax 0xc "Mu-registers-unique")  # => eax
19289           8b/-> *eax 0/r32/eax
19290           # if (var-in-reg[reg]) error
19291           8b/-> *(edi+eax<<2) 0/r32/eax
19292           3d/compare-eax-and 0/imm32
19293           0f 85/jump-if-!= $lookup-var-helper:error2/disp32
19294         }
19295 $lookup-var-helper:return:
19296         # esi = out
19297         8b/-> *(ebp+0x10) 6/r32/esi
19298         # *out = *curr
19299         8b/-> *ebx 0/r32/eax
19300         89/<- *esi 0/r32/eax
19301         8b/-> *(ebx+4) 0/r32/eax
19302         89/<- *(esi+4) 0/r32/eax
19303         # return
19304         eb/jump $lookup-var-helper:end/disp8
19305       }
19306       # 'name' not yet found; update var-in-reg if v in register
19307       # . var vr/eax: (addr array byte) = lookup(v->register)
19308       (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
19309       # . if (vr == 0) continue
19310       3d/compare-eax-and 0/imm32
19311       74/jump-if-= $lookup-var-helper:continue/disp8
19312       # . var reg/eax: int = get(Registers, vr)
19313       (get Mu-registers-unique %eax 0xc "Mu-registers-unique")  # => eax
19314       8b/-> *eax 0/r32/eax
19315       # . var-in-reg[reg] = v
19316       89/<- *(edi+eax<<2) 1/r32/ecx
19317 $lookup-var-helper:continue:
19318       # curr -= 12
19319       81 5/subop/subtract %ebx 0xc/imm32
19320       e9/jump loop/disp32
19321     }
19322 $lookup-var-helper:end:
19323     # . reclaim locals
19324     81 0/subop/add %esp 0x40/imm32
19325     # . restore registers
19326     5f/pop-to-edi
19327     5e/pop-to-esi
19328     5b/pop-to-ebx
19329     5a/pop-to-edx
19330     59/pop-to-ecx
19331     58/pop-to-eax
19332     # . epilogue
19333     89/<- %esp 5/r32/ebp
19334     5d/pop-to-ebp
19335     c3/return
19336 
19337 $lookup-var-helper:error1:
19338     (write-buffered *(ebp+0x18) "fn ")
19339     8b/-> *(ebp+0x14) 0/r32/eax
19340     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19341     (write-buffered *(ebp+0x18) %eax)
19342     (write-buffered *(ebp+0x18) ": malformed stack when looking up '")
19343     (write-slice-buffered *(ebp+0x18) *(ebp+8))
19344     (write-buffered *(ebp+0x18) "'\n")
19345     (flush *(ebp+0x18))
19346     (stop *(ebp+0x1c) 1)
19347     # never gets here
19348 
19349 $lookup-var-helper:error2:
19350     # eax contains the conflicting var at this point
19351     (write-buffered *(ebp+0x18) "fn ")
19352     50/push-eax
19353     8b/-> *(ebp+0x14) 0/r32/eax
19354     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19355     (write-buffered *(ebp+0x18) %eax)
19356     58/pop-eax
19357     (write-buffered *(ebp+0x18) ": register ")
19358     50/push-eax
19359     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
19360     (write-buffered *(ebp+0x18) %eax)
19361     58/pop-to-eax
19362     (write-buffered *(ebp+0x18) " reads var '")
19363     (write-slice-buffered *(ebp+0x18) *(ebp+8))
19364     (write-buffered *(ebp+0x18) "' after writing var '")
19365     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19366     (write-buffered *(ebp+0x18) %eax)
19367     (write-buffered *(ebp+0x18) "'\n")
19368     (flush *(ebp+0x18))
19369     (stop *(ebp+0x1c) 1)
19370     # never gets here
19371 
19372 dump-vars:  # vars: (addr stack live-var)
19373     # pseudocode:
19374     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
19375     #   var min = vars->data
19376     #   while curr >= min
19377     #     var v: (handle var) = *curr
19378     #     print v
19379     #     curr -= 12
19380     #
19381     # . prologue
19382     55/push-ebp
19383     89/<- %ebp 4/r32/esp
19384     # . save registers
19385     52/push-edx
19386     53/push-ebx
19387     56/push-esi
19388     # esi = vars
19389     8b/-> *(ebp+8) 6/r32/esi
19390     # ebx = vars->top
19391     8b/-> *esi 3/r32/ebx
19392     # var min/edx: (addr handle var) = vars->data
19393     8d/copy-address *(esi+8) 2/r32/edx
19394     # var curr/ebx: (addr handle var) = &vars->data[vars->top - 12]
19395     8d/copy-address *(esi+ebx-4) 3/r32/ebx  # vars + 8 + vars->type - 12
19396     {
19397 $dump-vars:loop:
19398       # if (curr < min) return
19399       39/compare %ebx 2/r32/edx
19400       0f 82/jump-if-addr< break/disp32
19401       #
19402       (write-buffered Stderr "  var@")
19403       (dump-var 2 %ebx)
19404       # curr -= 12
19405       81 5/subop/subtract %ebx 0xc/imm32
19406       e9/jump loop/disp32
19407     }
19408 $dump-vars:end:
19409     # . restore registers
19410     5e/pop-to-esi
19411     5b/pop-to-ebx
19412     5a/pop-to-edx
19413     # . epilogue
19414     89/<- %esp 5/r32/ebp
19415     5d/pop-to-ebp
19416     c3/return
19417 
19418 == data
19419 # Like Registers, but no esp or ebp
19420 Mu-registers:  # (addr stream {(handle array byte), int})
19421   # a table is a stream
19422   0xa8/imm32/write
19423   0/imm32/read
19424   0xa8/imm32/length
19425   # data
19426   # general-purpose registers
19427   # it is perfectly ok to use fake alloc-ids -- as long as you never try to reclaim them
19428   0x11/imm32/alloc-id $Mu-register-eax/imm32 0/imm32
19429   0x11/imm32/alloc-id $Mu-register-ecx/imm32 1/imm32
19430   0x11/imm32/alloc-id $Mu-register-edx/imm32 2/imm32
19431   0x11/imm32/alloc-id $Mu-register-ebx/imm32 3/imm32
19432   0x11/imm32/alloc-id $Mu-register-esi/imm32 6/imm32
19433   0x11/imm32/alloc-id $Mu-register-edi/imm32 7/imm32
19434   # floating-point registers
19435   0x11/imm32/alloc-id $Mu-register-xmm0/imm32 0/imm32
19436   0x11/imm32/alloc-id $Mu-register-xmm1/imm32 1/imm32
19437   0x11/imm32/alloc-id $Mu-register-xmm2/imm32 2/imm32
19438   0x11/imm32/alloc-id $Mu-register-xmm3/imm32 3/imm32
19439   0x11/imm32/alloc-id $Mu-register-xmm4/imm32 4/imm32
19440   0x11/imm32/alloc-id $Mu-register-xmm5/imm32 5/imm32
19441   0x11/imm32/alloc-id $Mu-register-xmm6/imm32 6/imm32
19442   0x11/imm32/alloc-id $Mu-register-xmm7/imm32 7/imm32
19443 
19444 # Like Mu-registers, but with unique codes for integer and floating-point
19445 # registers.
19446 # Don't use this for code-generation, only for checking.
19447 Mu-registers-unique:  # (addr stream {(handle array byte), int})
19448   # a table is a stream
19449   0xa8/imm32/write
19450   0/imm32/read
19451   0xa8/imm32/length
19452   # data
19453   # general-purpose registers
19454   0x11/imm32/alloc-id $Mu-register-eax/imm32 0/imm32
19455   0x11/imm32/alloc-id $Mu-register-ecx/imm32 1/imm32
19456   0x11/imm32/alloc-id $Mu-register-edx/imm32 2/imm32
19457   0x11/imm32/alloc-id $Mu-register-ebx/imm32 3/imm32
19458   0x11/imm32/alloc-id $Mu-register-esi/imm32 6/imm32
19459   0x11/imm32/alloc-id $Mu-register-edi/imm32 7/imm32
19460   # floating-point registers
19461   0x11/imm32/alloc-id $Mu-register-xmm0/imm32 8/imm32
19462   0x11/imm32/alloc-id $Mu-register-xmm1/imm32 9/imm32
19463   0x11/imm32/alloc-id $Mu-register-xmm2/imm32 0xa/imm32
19464   0x11/imm32/alloc-id $Mu-register-xmm3/imm32 0xb/imm32
19465   0x11/imm32/alloc-id $Mu-register-xmm4/imm32 0xc/imm32
19466   0x11/imm32/alloc-id $Mu-register-xmm5/imm32 0xd/imm32
19467   0x11/imm32/alloc-id $Mu-register-xmm6/imm32 0xe/imm32
19468   0x11/imm32/alloc-id $Mu-register-xmm7/imm32 0xf/imm32
19469 
19470 $Mu-register-eax:
19471   0x11/imm32/alloc-id
19472   3/imm32/size
19473   0x65/e 0x61/a 0x78/x
19474 
19475 $Mu-register-ecx:
19476   0x11/imm32/alloc-id
19477   3/imm32/size
19478   0x65/e 0x63/c 0x78/x
19479 
19480 $Mu-register-edx:
19481   0x11/imm32/alloc-id
19482   3/imm32/size
19483   0x65/e 0x64/d 0x78/x
19484 
19485 $Mu-register-ebx:
19486   0x11/imm32/alloc-id
19487   3/imm32/size
19488   0x65/e 0x62/b 0x78/x
19489 
19490 $Mu-register-esi:
19491   0x11/imm32/alloc-id
19492   3/imm32/size
19493   0x65/e 0x73/s 0x69/i
19494 
19495 $Mu-register-edi:
19496   0x11/imm32/alloc-id
19497   3/imm32/size
19498   0x65/e 0x64/d 0x69/i
19499 
19500 $Mu-register-xmm0:
19501   0x11/imm32/alloc-id:fake:payload
19502   # "xmm0"
19503   0x4/imm32/size
19504   0x78/x 0x6d/m 0x6d/m 0x30/0
19505 
19506 $Mu-register-xmm1:
19507   0x11/imm32/alloc-id:fake:payload
19508   # "xmm1"
19509   0x4/imm32/size
19510   0x78/x 0x6d/m 0x6d/m 0x31/1
19511 
19512 $Mu-register-xmm2:
19513   0x11/imm32/alloc-id:fake:payload
19514   # "xmm2"
19515   0x4/imm32/size
19516   0x78/x 0x6d/m 0x6d/m 0x32/2
19517 
19518 $Mu-register-xmm3:
19519   0x11/imm32/alloc-id:fake:payload
19520   # "xmm3"
19521   0x4/imm32/size
19522   0x78/x 0x6d/m 0x6d/m 0x33/3
19523 
19524 $Mu-register-xmm4:
19525   0x11/imm32/alloc-id:fake:payload
19526   # "xmm4"
19527   0x4/imm32/size
19528   0x78/x 0x6d/m 0x6d/m 0x34/4
19529 
19530 $Mu-register-xmm5:
19531   0x11/imm32/alloc-id:fake:payload
19532   # "xmm5"
19533   0x4/imm32/size
19534   0x78/x 0x6d/m 0x6d/m 0x35/5
19535 
19536 $Mu-register-xmm6:
19537   0x11/imm32/alloc-id:fake:payload
19538   # "xmm6"
19539   0x4/imm32/size
19540   0x78/x 0x6d/m 0x6d/m 0x36/6
19541 
19542 $Mu-register-xmm7:
19543   0x11/imm32/alloc-id:fake:payload
19544   # "xmm7"
19545   0x4/imm32/size
19546   0x78/x 0x6d/m 0x6d/m 0x37/7
19547 
19548 == code
19549 
19550 # push 'out' to 'vars' if not already there; it's assumed to be a fn output
19551 maybe-define-var:  # out: (handle var), vars: (addr stack live-var)
19552     # . prologue
19553     55/push-ebp
19554     89/<- %ebp 4/r32/esp
19555     # . save registers
19556     50/push-eax
19557     # var out-addr/eax: (addr var)
19558     (lookup *(ebp+8) *(ebp+0xc))  # => eax
19559     #
19560     (binding-exists? %eax *(ebp+0x10))  # => eax
19561     3d/compare-eax-and 0/imm32/false
19562     75/jump-if-!= $maybe-define-var:end/disp8
19563     # otherwise update vars
19564     (push *(ebp+0x10) *(ebp+8))
19565     (push *(ebp+0x10) *(ebp+0xc))
19566     (push *(ebp+0x10) 0)  # 'out' is always a fn output; never spill it
19567 $maybe-define-var:end:
19568     # . restore registers
19569     58/pop-to-eax
19570     # . epilogue
19571     89/<- %esp 5/r32/ebp
19572     5d/pop-to-ebp
19573     c3/return
19574 
19575 # simpler version of lookup-var-helper
19576 binding-exists?:  # target: (addr var), vars: (addr stack live-var) -> result/eax: boolean
19577     # pseudocode:
19578     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
19579     #   var min = vars->data
19580     #   while curr >= min
19581     #     var v: (handle var) = *curr
19582     #     if v->name == target->name
19583     #       return true
19584     #     curr -= 12
19585     #   return false
19586     #
19587     # . prologue
19588     55/push-ebp
19589     89/<- %ebp 4/r32/esp
19590     # . save registers
19591     51/push-ecx
19592     52/push-edx
19593     56/push-esi
19594     # var target-name/ecx: (addr array byte) = lookup(target->name)
19595     8b/-> *(ebp+8) 0/r32/eax
19596     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19597     89/<- %ecx 0/r32/eax
19598     # esi = vars
19599     8b/-> *(ebp+0xc) 6/r32/esi
19600     # eax = vars->top
19601     8b/-> *esi 0/r32/eax
19602     # var min/edx: (addr handle var) = vars->data
19603     8d/copy-address *(esi+8) 2/r32/edx
19604     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
19605     8d/copy-address *(esi+eax-4) 6/r32/esi  # vars + 8 + vars->type - 12
19606     {
19607 $binding-exists?:loop:
19608       # if (curr < min) return
19609       39/compare %esi 2/r32/edx
19610       0f 82/jump-if-addr< break/disp32
19611       # var v/eax: (addr var) = lookup(*curr)
19612       (lookup *esi *(esi+4))  # => eax
19613       # var vn/eax: (addr array byte) = lookup(v->name)
19614       (lookup *eax *(eax+4))  # Var-name Var-name => eax
19615       # if (vn == target-name) return true
19616       (string-equal? %ecx %eax)  # => eax
19617       3d/compare-eax-and 0/imm32/false
19618       75/jump-if-!= $binding-exists?:end/disp8  # eax already contains true
19619       # curr -= 12
19620       81 5/subop/subtract %esi 0xc/imm32
19621       e9/jump loop/disp32
19622     }
19623     b8/copy-to-eax 0/imm32/false
19624 $binding-exists?:end:
19625     # . restore registers
19626     5e/pop-to-esi
19627     5a/pop-to-edx
19628     59/pop-to-ecx
19629     # . epilogue
19630     89/<- %esp 5/r32/ebp
19631     5d/pop-to-ebp
19632     c3/return
19633 
19634 test-parse-mu-stmt:
19635     # . prologue
19636     55/push-ebp
19637     89/<- %ebp 4/r32/esp
19638     # setup
19639     8b/-> *Primitive-type-ids 0/r32/eax
19640     89/<- *Type-id 0/r32/eax  # stream-write
19641     (clear-stream _test-input-stream)
19642     (write _test-input-stream "increment n\n")
19643     # var vars/ecx: (stack (addr var) 16)
19644     81 5/subop/subtract %esp 0xc0/imm32
19645     68/push 0xc0/imm32/size
19646     68/push 0/imm32/top
19647     89/<- %ecx 4/r32/esp
19648     (clear-stack %ecx)
19649     # var v/edx: (handle var)
19650     68/push 0/imm32
19651     68/push 0/imm32
19652     89/<- %edx 4/r32/esp
19653     # var s/eax: (handle array byte)
19654     68/push 0/imm32
19655     68/push 0/imm32
19656     89/<- %eax 4/r32/esp
19657     # v = new var("n")
19658     (copy-array Heap "n" %eax)
19659     (new-var Heap *eax *(eax+4) %edx)
19660     #
19661     (push %ecx *edx)
19662     (push %ecx *(edx+4))
19663     (push %ecx 0)
19664     # var out/eax: (handle stmt)
19665     68/push 0/imm32
19666     68/push 0/imm32
19667     89/<- %eax 4/r32/esp
19668     # convert
19669     (parse-mu-stmt _test-input-stream %ecx 0 %eax Stderr 0)
19670     # var out-addr/edx: (addr stmt) = lookup(*out)
19671     (lookup *eax *(eax+4))  # => eax
19672     89/<- %edx 0/r32/eax
19673     # out->tag
19674     (check-ints-equal *edx 1 "F - test-parse-mu-stmt/tag")  # Stmt-tag is Stmt1
19675     # out->operation
19676     (lookup *(edx+4) *(edx+8))  # Stmt1-operation Stmt1-operation => eax
19677     (check-strings-equal %eax "increment" "F - test-parse-mu-stmt/name")  # Stmt1-operation
19678     # out->inouts->value->name
19679     # . eax = out->inouts
19680     (lookup *(edx+0xc) *(edx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
19681     # . eax = out->inouts->value
19682     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
19683     # . eax = out->inouts->value->name
19684     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19685     # .
19686     (check-strings-equal %eax "n" "F - test-parse-mu-stmt/inout:0")
19687     # . epilogue
19688     89/<- %esp 5/r32/ebp
19689     5d/pop-to-ebp
19690     c3/return
19691 
19692 test-parse-mu-stmt-with-comma:
19693     # . prologue
19694     55/push-ebp
19695     89/<- %ebp 4/r32/esp
19696     # setup
19697     8b/-> *Primitive-type-ids 0/r32/eax
19698     89/<- *Type-id 0/r32/eax  # stream-write
19699     (clear-stream _test-input-stream)
19700     (write _test-input-stream "copy-to n, 3\n")
19701     # var vars/ecx: (stack (addr var) 16)
19702     81 5/subop/subtract %esp 0xc0/imm32
19703     68/push 0xc0/imm32/size
19704     68/push 0/imm32/top
19705     89/<- %ecx 4/r32/esp
19706     (clear-stack %ecx)
19707     # var v/edx: (handle var)
19708     68/push 0/imm32
19709     68/push 0/imm32
19710     89/<- %edx 4/r32/esp
19711     # var s/eax: (handle array byte)
19712     68/push 0/imm32
19713     68/push 0/imm32
19714     89/<- %eax 4/r32/esp
19715     # v = new var("n")
19716     (copy-array Heap "n" %eax)
19717     (new-var Heap *eax *(eax+4) %edx)
19718     #
19719     (push %ecx *edx)
19720     (push %ecx *(edx+4))
19721     (push %ecx 0)
19722     # var out/eax: (handle stmt)
19723     68/push 0/imm32
19724     68/push 0/imm32
19725     89/<- %eax 4/r32/esp
19726     # convert
19727     (parse-mu-stmt _test-input-stream %ecx 0 %eax Stderr 0)
19728     # var out-addr/edx: (addr stmt) = lookup(*out)
19729     (lookup *eax *(eax+4))  # => eax
19730     89/<- %edx 0/r32/eax
19731     # out->tag
19732     (check-ints-equal *edx 1 "F - test-parse-mu-stmt-with-comma/tag")  # Stmt-tag is Stmt1
19733     # out->operation
19734     (lookup *(edx+4) *(edx+8))  # Stmt1-operation Stmt1-operation => eax
19735     (check-strings-equal %eax "copy-to" "F - test-parse-mu-stmt-with-comma/name")  # Stmt1-operation
19736     # out->inouts->value->name
19737     # . eax = out->inouts
19738     (lookup *(edx+0xc) *(edx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
19739     # . eax = out->inouts->value
19740     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
19741     # . eax = out->inouts->value->name
19742     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19743     # .
19744     (check-strings-equal %eax "n" "F - test-parse-mu-stmt-with-comma/inout:0")
19745     # . epilogue
19746     89/<- %esp 5/r32/ebp
19747     5d/pop-to-ebp
19748     c3/return
19749 
19750 new-var:  # ad: (addr allocation-descriptor), name: (handle array byte), out: (addr handle var)
19751     # . prologue
19752     55/push-ebp
19753     89/<- %ebp 4/r32/esp
19754     # . save registers
19755     50/push-eax
19756     51/push-ecx
19757     # ecx = out
19758     8b/-> *(ebp+0x14) 1/r32/ecx
19759     #
19760     (allocate *(ebp+8) *Var-size %ecx)
19761     # var out-addr/eax: (addr var)
19762     (lookup *ecx *(ecx+4))  # => eax
19763     # out-addr->name = name
19764     8b/-> *(ebp+0xc) 1/r32/ecx
19765     89/<- *eax 1/r32/ecx  # Var-name
19766     8b/-> *(ebp+0x10) 1/r32/ecx
19767     89/<- *(eax+4) 1/r32/ecx  # Var-name
19768 #?     (write-buffered Stderr "var ")
19769 #?     (lookup *(ebp+0xc) *(ebp+0x10))
19770 #?     (write-buffered Stderr %eax)
19771 #?     (write-buffered Stderr " at ")
19772 #?     8b/-> *(ebp+0x14) 1/r32/ecx
19773 #?     (lookup *ecx *(ecx+4))  # => eax
19774 #?     (write-int32-hex-buffered Stderr %eax)
19775 #?     (write-buffered Stderr Newline)
19776 #?     (flush Stderr)
19777 $new-var:end:
19778     # . restore registers
19779     59/pop-to-ecx
19780     58/pop-to-eax
19781     # . epilogue
19782     89/<- %esp 5/r32/ebp
19783     5d/pop-to-ebp
19784     c3/return
19785 
19786 # WARNING: modifies name
19787 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)
19788     # . prologue
19789     55/push-ebp
19790     89/<- %ebp 4/r32/esp
19791     # . save registers
19792     50/push-eax
19793     51/push-ecx
19794     # first strip out metadata
19795     8b/-> *(ebp+0xc) 1/r32/ecx
19796     (next-token-from-slice *ecx *(ecx+4) 0x2f *(ebp+0xc))
19797     # if (!is-hex-int?(name)) abort
19798     (hex-int? *(ebp+0xc))  # => eax
19799     3d/compare-eax-and 0/imm32/false
19800     0f 84/jump-if-= $new-literal-integer:abort/disp32
19801     # a little more error-checking
19802     (check-mu-hex-int *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
19803     # out = new var(s)
19804     (new-var-from-slice *(ebp+8) *(ebp+0xc) *(ebp+0x10))
19805     # var out-addr/ecx: (addr var) = lookup(*out)
19806     8b/-> *(ebp+0x10) 0/r32/eax
19807     (lookup *eax *(eax+4))  # => eax
19808     89/<- %ecx 0/r32/eax
19809     # out-addr->block-depth = *Curr-block-depth
19810     8b/-> *Curr-block-depth 0/r32/eax
19811     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
19812     # out-addr->type = new tree()
19813     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
19814     (allocate *(ebp+8) *Type-tree-size %eax)
19815     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
19816     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
19817     # nothing else to do; default type is 'literal'
19818 $new-literal-integer:end:
19819     # . reclaim locals
19820     81 0/subop/add %esp 8/imm32
19821     # . restore registers
19822     59/pop-to-ecx
19823     58/pop-to-eax
19824     # . epilogue
19825     89/<- %esp 5/r32/ebp
19826     5d/pop-to-ebp
19827     c3/return
19828 
19829 $new-literal-integer:abort:
19830     (write-buffered *(ebp+0x18) "fn ")
19831     8b/-> *(ebp+0x14) 0/r32/eax
19832     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19833     (write-buffered *(ebp+0x18) %eax)
19834     (write-buffered *(ebp+0x18) ": variable '")
19835     (write-slice-buffered *(ebp+0x18) *(ebp+0xc))
19836     (write-buffered *(ebp+0x18) "' cannot begin with a digit (or do you have a typo in a number?)\n")
19837     (flush *(ebp+0x18))
19838     (stop *(ebp+0x1c) 1)
19839     # never gets here
19840 
19841 # precondition: name is a valid hex integer; require a '0x' prefix
19842 check-mu-hex-int:  # name: (addr slice), err: (addr buffered-file), ed: (addr exit-descriptor)
19843     # . prologue
19844     55/push-ebp
19845     89/<- %ebp 4/r32/esp
19846     # . save registers
19847     50/push-eax
19848     51/push-ecx
19849     52/push-edx
19850     # ecx = name
19851     8b/-> *(ebp+8) 1/r32/ecx
19852     # var start/edx: (addr byte) = name->start
19853     8b/-> *ecx 2/r32/edx
19854     # if (*start == '-') ++start
19855     b8/copy-to-eax 0/imm32
19856     8a/copy-byte *edx 0/r32/AL
19857     3d/compare-eax-and 0x2d/imm32/dash
19858     {
19859       75/jump-if-!= break/disp8
19860       42/increment-edx
19861     }
19862     # var end/ecx: (addr byte) = name->end
19863     8b/-> *(ecx+4) 1/r32/ecx
19864     # var len/eax: int = name->end - name->start
19865     89/<- %eax 1/r32/ecx
19866     29/subtract-from %eax 2/r32/edx
19867     # if (len <= 1) return
19868     3d/compare-eax-with 1/imm32
19869     0f 8e/jump-if-<= $check-mu-hex-int:end/disp32
19870 $check-mu-hex-int:length->-1:
19871     # if slice-starts-with?({start, end}, "0x") return
19872     # . var tmp = {start, end}
19873     51/push-ecx
19874     52/push-edx
19875     89/<- %eax 4/r32/esp
19876     # .
19877     (slice-starts-with? %eax "0x")  # => eax
19878     # . reclaim tmp
19879     81 0/subop/add %esp 8/imm32
19880     # .
19881     3d/compare-eax-with 0/imm32/false
19882     75/jump-if-!= $check-mu-hex-int:end/disp8
19883 $check-mu-hex-int:abort:
19884     # otherwise abort
19885     (write-buffered *(ebp+0xc) "literal integers are always hex in Mu; start '")
19886     (write-slice-buffered *(ebp+0xc) *(ebp+8))
19887     (write-buffered *(ebp+0xc) "' with a '0x' to be unambiguous, converting it to hexadecimal as necessary.\n")
19888     (flush *(ebp+0xc))
19889     (stop *(ebp+0x10) 1)
19890 $check-mu-hex-int:end:
19891     # . restore registers
19892     5a/pop-to-edx
19893     59/pop-to-ecx
19894     58/pop-to-eax
19895     # . epilogue
19896     89/<- %esp 5/r32/ebp
19897     5d/pop-to-ebp
19898     c3/return
19899 
19900 new-literal:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
19901     # . prologue
19902     55/push-ebp
19903     89/<- %ebp 4/r32/esp
19904     # . save registers
19905     50/push-eax
19906     51/push-ecx
19907     # var s/ecx: (handle array byte)
19908     68/push 0/imm32
19909     68/push 0/imm32
19910     89/<- %ecx 4/r32/esp
19911     # s = slice-to-string(name)
19912     (slice-to-string Heap *(ebp+0xc) %ecx)
19913     # allocate to out
19914     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
19915     # var out-addr/ecx: (addr var) = lookup(*out)
19916     8b/-> *(ebp+0x10) 1/r32/ecx
19917     (lookup *ecx *(ecx+4))  # => eax
19918     89/<- %ecx 0/r32/eax
19919     # out-addr->block-depth = *Curr-block-depth
19920     8b/-> *Curr-block-depth 0/r32/eax
19921     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
19922     # out-addr->type/eax = new type
19923     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
19924     (allocate *(ebp+8) *Type-tree-size %eax)
19925     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
19926     # nothing else to do; default type is 'literal'
19927     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
19928 $new-literal:end:
19929     # . reclaim locals
19930     81 0/subop/add %esp 8/imm32
19931     # . restore registers
19932     59/pop-to-ecx
19933     58/pop-to-eax
19934     # . epilogue
19935     89/<- %esp 5/r32/ebp
19936     5d/pop-to-ebp
19937     c3/return
19938 
19939 new-literal-string:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
19940     # . prologue
19941     55/push-ebp
19942     89/<- %ebp 4/r32/esp
19943     # . save registers
19944     50/push-eax
19945     51/push-ecx
19946     # var s/ecx: (handle array byte)
19947     68/push 0/imm32
19948     68/push 0/imm32
19949     89/<- %ecx 4/r32/esp
19950     # s = slice-to-string(name)
19951     (slice-to-string Heap *(ebp+0xc) %ecx)
19952     # allocate to out
19953     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
19954     # var out-addr/ecx: (addr var) = lookup(*out)
19955     8b/-> *(ebp+0x10) 1/r32/ecx
19956     (lookup *ecx *(ecx+4))  # => eax
19957     89/<- %ecx 0/r32/eax
19958     # out-addr->block-depth = *Curr-block-depth
19959     8b/-> *Curr-block-depth 0/r32/eax
19960     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
19961     # out-addr->type/eax = new type
19962     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
19963     (allocate *(ebp+8) *Type-tree-size %eax)
19964     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
19965     # out-addr->type->value = literal-string
19966     c7 0/subop/copy *(eax+4) 0x10/imm32/type-id-string-literal  # Type-tree-value
19967     # out-addr->type->is-atom? = true
19968     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
19969 $new-literal-string:end:
19970     # . reclaim locals
19971     81 0/subop/add %esp 8/imm32
19972     # . restore registers
19973     59/pop-to-ecx
19974     58/pop-to-eax
19975     # . epilogue
19976     89/<- %esp 5/r32/ebp
19977     5d/pop-to-ebp
19978     c3/return
19979 
19980 new-var-from-slice:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
19981     # . prologue
19982     55/push-ebp
19983     89/<- %ebp 4/r32/esp
19984     # . save registers
19985     51/push-ecx
19986     # var tmp/ecx: (handle array byte)
19987     68/push 0/imm32
19988     68/push 0/imm32
19989     89/<- %ecx 4/r32/esp
19990     # tmp = slice-to-string(name)
19991     (slice-to-string Heap *(ebp+0xc) %ecx)
19992     # out = new-var(tmp)
19993     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
19994 $new-var-from-slice:end:
19995     # . reclaim locals
19996     81 0/subop/add %esp 8/imm32
19997     # . restore registers
19998     59/pop-to-ecx
19999     # . epilogue
20000     89/<- %esp 5/r32/ebp
20001     5d/pop-to-ebp
20002     c3/return
20003 
20004 new-var-def:  # ad: (addr allocation-descriptor), var: (handle var), out: (addr handle stmt)
20005     # . prologue
20006     55/push-ebp
20007     89/<- %ebp 4/r32/esp
20008     # . save registers
20009     50/push-eax
20010     51/push-ecx
20011     #
20012     (allocate *(ebp+8) *Stmt-size *(ebp+0x14))
20013     # var out-addr/eax: (addr stmt) = lookup(*out)
20014     8b/-> *(ebp+0x14) 0/r32/eax
20015     (lookup *eax *(eax+4))  # => eax
20016     # out-addr->tag = stmt
20017     c7 0/subop/copy *eax 2/imm32/tag/var-on-stack  # Stmt-tag
20018     # result->var = var
20019     8b/-> *(ebp+0xc) 1/r32/ecx
20020     89/<- *(eax+4) 1/r32/ecx  # Vardef-var
20021     8b/-> *(ebp+0x10) 1/r32/ecx
20022     89/<- *(eax+8) 1/r32/ecx  # Vardef-var
20023 $new-var-def:end:
20024     # . restore registers
20025     59/pop-to-ecx
20026     58/pop-to-eax
20027     # . epilogue
20028     89/<- %esp 5/r32/ebp
20029     5d/pop-to-ebp
20030     c3/return
20031 
20032 new-reg-var-def:  # ad: (addr allocation-descriptor), var: (handle var), out: (addr handle stmt)
20033     # . prologue
20034     55/push-ebp
20035     89/<- %ebp 4/r32/esp
20036     # . save registers
20037     50/push-eax
20038     # eax = out
20039     8b/-> *(ebp+0x14) 0/r32/eax
20040     #
20041     (allocate *(ebp+8) *Stmt-size %eax)
20042     # var out-addr/eax: (addr stmt) = lookup(*out)
20043     (lookup *eax *(eax+4))  # => eax
20044     # set tag
20045     c7 0/subop/copy *eax 3/imm32/tag/var-in-register  # Stmt-tag
20046     # set output
20047     8d/copy-address *(eax+0x14) 0/r32/eax  # Regvardef-outputs
20048     (append-stmt-var Heap  *(ebp+0xc) *(ebp+0x10)  0 0  0  %eax)
20049 $new-reg-var-def:end:
20050     # . restore registers
20051     58/pop-to-eax
20052     # . epilogue
20053     89/<- %esp 5/r32/ebp
20054     5d/pop-to-ebp
20055     c3/return
20056 
20057 append-list:  # ad: (addr allocation-descriptor), value: (handle _type), list: (handle list _type), out: (addr handle list _type)
20058     # . prologue
20059     55/push-ebp
20060     89/<- %ebp 4/r32/esp
20061     # . save registers
20062     50/push-eax
20063     51/push-ecx
20064     57/push-edi
20065     # edi = out
20066     8b/-> *(ebp+0x1c) 7/r32/edi
20067     # *out = new list
20068     (allocate *(ebp+8) *List-size %edi)
20069     # var out-addr/edi: (addr list _type) = lookup(*out)
20070     (lookup *edi *(edi+4))  # => eax
20071     89/<- %edi 0/r32/eax
20072     # out-addr->value = value
20073     8b/-> *(ebp+0xc) 0/r32/eax
20074     89/<- *edi 0/r32/eax  # List-value
20075     8b/-> *(ebp+0x10) 0/r32/eax
20076     89/<- *(edi+4) 0/r32/eax  # List-value
20077     # if (list == null) return
20078     81 7/subop/compare *(ebp+0x14) 0/imm32
20079     74/jump-if-= $append-list:end/disp8
20080     # otherwise append
20081 $append-list:non-empty-list:
20082     # var curr/eax: (addr list _type) = lookup(list)
20083     (lookup *(ebp+0x14) *(ebp+0x18))  # => eax
20084     # while (curr->next != null) curr = curr->next
20085     {
20086       81 7/subop/compare *(eax+8) 0/imm32  # List-next
20087       74/jump-if-= break/disp8
20088       # curr = lookup(curr->next)
20089       (lookup *(eax+8) *(eax+0xc))  # List-next, List-next => eax
20090       #
20091       eb/jump loop/disp8
20092     }
20093     # edi = out
20094     8b/-> *(ebp+0x1c) 7/r32/edi
20095     # curr->next = out
20096     8b/-> *edi 1/r32/ecx
20097     89/<- *(eax+8) 1/r32/ecx  # List-next
20098     8b/-> *(edi+4) 1/r32/ecx
20099     89/<- *(eax+0xc) 1/r32/ecx  # List-next
20100     # out = list
20101     8b/-> *(ebp+0x14) 1/r32/ecx
20102     89/<- *edi 1/r32/ecx
20103     8b/-> *(ebp+0x18) 1/r32/ecx
20104     89/<- *(edi+4) 1/r32/ecx
20105 $append-list:end:
20106     # . restore registers
20107     5f/pop-to-edi
20108     59/pop-to-ecx
20109     58/pop-to-eax
20110     # . epilogue
20111     89/<- %esp 5/r32/ebp
20112     5d/pop-to-ebp
20113     c3/return
20114 
20115 append-stmt-var:  # ad: (addr allocation-descriptor), v: (handle var), vars: (handle stmt-var), is-deref?: boolean, out: (addr handle stmt-var)
20116     # . prologue
20117     55/push-ebp
20118     89/<- %ebp 4/r32/esp
20119     # . save registers
20120     50/push-eax
20121     51/push-ecx
20122     57/push-edi
20123     # edi = out
20124     8b/-> *(ebp+0x20) 7/r32/edi
20125     # out = new stmt-var
20126     (allocate *(ebp+8) *Stmt-var-size %edi)
20127     # var out-addr/ecx: (addr stmt-var) = lookup(*out)
20128     (lookup *edi *(edi+4))  # => eax
20129     89/<- %ecx 0/r32/eax
20130     # out-addr->value = v
20131     8b/-> *(ebp+0xc) 0/r32/eax
20132     89/<- *ecx 0/r32/eax  # Stmt-var-value
20133     8b/-> *(ebp+0x10) 0/r32/eax
20134     89/<- *(ecx+4) 0/r32/eax  # Stmt-var-value
20135     # out-addr->is-deref? = is-deref?
20136     8b/-> *(ebp+0x1c) 0/r32/eax
20137     89/<- *(ecx+0x10) 0/r32/eax  # Stmt-var-is-deref
20138     # if (vars == null) return result
20139     81 7/subop/compare *(ebp+0x14) 0/imm32/null
20140     74/jump-if-= $append-stmt-var:end/disp8
20141     # otherwise append
20142     # var curr/eax: (addr stmt-var) = lookup(vars)
20143     (lookup *(ebp+0x14) *(ebp+0x18))  # => eax
20144     # while (curr->next != null) curr = curr->next
20145     {
20146       81 7/subop/compare *(eax+8) 0/imm32  # Stmt-var-next
20147       74/jump-if-= break/disp8
20148       # curr = lookup(curr->next)
20149       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next, Stmt-var-next => eax
20150       #
20151       eb/jump loop/disp8
20152     }
20153     # curr->next = out
20154     8b/-> *edi 1/r32/ecx
20155     89/<- *(eax+8) 1/r32/ecx  # Stmt-var-next
20156     8b/-> *(edi+4) 1/r32/ecx
20157     89/<- *(eax+0xc) 1/r32/ecx  # Stmt-var-next
20158     # out = vars
20159     8b/-> *(ebp+0x14) 1/r32/ecx
20160     89/<- *edi 1/r32/ecx
20161     8b/-> *(ebp+0x18) 1/r32/ecx
20162     89/<- *(edi+4) 1/r32/ecx
20163 $append-stmt-var:end:
20164     # . restore registers
20165     5f/pop-to-edi
20166     59/pop-to-ecx
20167     58/pop-to-eax
20168     # . epilogue
20169     89/<- %esp 5/r32/ebp
20170     5d/pop-to-ebp
20171     c3/return
20172 
20173 append-to-block:  # ad: (addr allocation-descriptor), block: (addr block), x: (handle stmt)
20174     # . prologue
20175     55/push-ebp
20176     89/<- %ebp 4/r32/esp
20177     # . save registers
20178     50/push-eax
20179     56/push-esi
20180     # esi = block
20181     8b/-> *(ebp+0xc) 6/r32/esi
20182     # block->stmts = append(x, block->stmts)
20183     8d/copy-address *(esi+4) 0/r32/eax  # Block-stmts
20184     (append-list *(ebp+8)  *(ebp+0x10) *(ebp+0x14)  *(esi+4) *(esi+8)  %eax)  # ad, x, x, Block-stmts, Block-stmts
20185 $append-to-block:end:
20186     # . restore registers
20187     5e/pop-to-esi
20188     58/pop-to-eax
20189     # . epilogue
20190     89/<- %esp 5/r32/ebp
20191     5d/pop-to-ebp
20192     c3/return
20193 
20194 ## Parsing types
20195 # We need to create metadata on user-defined types, and we need to use this
20196 # metadata as we parse instructions.
20197 # However, we also want to allow types to be used before their definitions.
20198 # This means we can't ever assume any type data structures exist.
20199 
20200 lookup-or-create-constant:  # container: (addr stmt-var), field-name: (addr slice), out: (addr handle var)
20201     # . prologue
20202     55/push-ebp
20203     89/<- %ebp 4/r32/esp
20204     # . save registers
20205     50/push-eax
20206     56/push-esi
20207     # var container-type/esi: type-id
20208     (container-type *(ebp+8))  # => eax
20209     89/<- %esi 0/r32/eax
20210     # var tmp/eax: (handle typeinfo) = find-or-create-typeinfo(container-type)
20211     68/push 0/imm32
20212     68/push 0/imm32
20213     89/<- %eax 4/r32/esp
20214     (find-or-create-typeinfo %esi %eax)
20215     # var tmp-addr/eax: (addr typeinfo) = lookup(tmp)
20216     (lookup *eax *(eax+4))  # => eax
20217     # result = find-or-create-typeinfo-output-var(typeinfo, field-name)
20218 #?     (write-buffered Stderr "constant: ")
20219 #?     (write-slice-buffered Stderr *(ebp+0xc))
20220 #?     (write-buffered Stderr Newline)
20221 #?     (flush Stderr)
20222     (find-or-create-typeinfo-output-var %eax *(ebp+0xc) *(ebp+0x10))
20223 #?     8b/-> *(ebp+0x10) 0/r32/eax
20224 #?     (write-buffered Stderr "@")
20225 #?     (lookup *eax *(eax+4))
20226 #?     (write-int32-hex-buffered Stderr %eax)
20227 #?     (lookup *eax *(eax+4))
20228 #?     (write-buffered Stderr %eax)
20229 #?     (write-buffered Stderr Newline)
20230 #?     (flush Stderr)
20231 #?     (write-buffered Stderr "offset: ")
20232 #?     8b/-> *(eax+0x14) 0/r32/eax
20233 #?     (write-int32-hex-buffered Stderr %eax)
20234 #?     (write-buffered Stderr Newline)
20235 #?     (flush Stderr)
20236 $lookup-or-create-constant:end:
20237     # . reclaim locals
20238     81 0/subop/add %esp 8/imm32
20239     # . restore registers
20240     5e/pop-to-esi
20241     58/pop-to-eax
20242     # . epilogue
20243     89/<- %esp 5/r32/ebp
20244     5d/pop-to-ebp
20245     c3/return
20246 
20247 # if addr var:
20248 #   container->var->type->right->left->value
20249 # otherwise
20250 #   container->var->type->value
20251 container-type:  # container: (addr stmt-var) -> result/eax: type-id
20252     # . prologue
20253     55/push-ebp
20254     89/<- %ebp 4/r32/esp
20255     #
20256     8b/-> *(ebp+8) 0/r32/eax
20257     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
20258     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20259     {
20260       81 7/subop/compare *(eax+8) 0/imm32  # Type-tree-right
20261       74/jump-if-= break/disp8
20262       (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
20263       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20264     }
20265     8b/-> *(eax+4) 0/r32/eax  # Type-tree-value
20266 $container-type:end:
20267     # . epilogue
20268     89/<- %esp 5/r32/ebp
20269     5d/pop-to-ebp
20270     c3/return
20271 
20272 container?:  # t: type-id -> result/eax: boolean
20273     # . prologue
20274     55/push-ebp
20275     89/<- %ebp 4/r32/esp
20276     #
20277     8b/-> *(ebp+8) 0/r32/eax
20278     c1/shift 4/subop/left %eax 2/imm8
20279     3b/compare 0/r32/eax *Primitive-type-ids
20280     0f 9d/set-if->= %al
20281     25/and-eax-with 0xff/imm32
20282 $container?:end:
20283     # . epilogue
20284     89/<- %esp 5/r32/ebp
20285     5d/pop-to-ebp
20286     c3/return
20287 
20288 find-or-create-typeinfo:  # t: type-id, out: (addr handle typeinfo)
20289     # . prologue
20290     55/push-ebp
20291     89/<- %ebp 4/r32/esp
20292     # . save registers
20293     50/push-eax
20294     51/push-ecx
20295     52/push-edx
20296     57/push-edi
20297     # edi = out
20298     8b/-> *(ebp+0xc) 7/r32/edi
20299     # var fields/ecx: (handle table (handle array byte) (handle typeinfo-entry))
20300     68/push 0/imm32
20301     68/push 0/imm32
20302     89/<- %ecx 4/r32/esp
20303     # find-typeinfo(t, out)
20304     (find-typeinfo *(ebp+8) %edi)
20305     {
20306       # if (*out != 0) break
20307       81 7/subop/compare *edi 0/imm32
20308       0f 85/jump-if-!= break/disp32
20309 $find-or-create-typeinfo:create:
20310       # *out = allocate
20311       (allocate Heap *Typeinfo-size %edi)
20312       # var tmp/eax: (addr typeinfo) = lookup(*out)
20313       (lookup *edi *(edi+4))  # => eax
20314 #?     (write-buffered Stderr "created typeinfo at ")
20315 #?     (write-int32-hex-buffered Stderr %eax)
20316 #?     (write-buffered Stderr " for type-id ")
20317 #?     (write-int32-hex-buffered Stderr *(ebp+8))
20318 #?     (write-buffered Stderr Newline)
20319 #?     (flush Stderr)
20320       # tmp->id = t
20321       8b/-> *(ebp+8) 2/r32/edx
20322       89/<- *eax 2/r32/edx  # Typeinfo-id
20323       # tmp->fields = new table
20324       # . fields = new table
20325       (new-stream Heap 0x40 *Typeinfo-fields-row-size %ecx)
20326       # . tmp->fields = fields
20327       8b/-> *ecx 2/r32/edx
20328       89/<- *(eax+4) 2/r32/edx  # Typeinfo-fields
20329       8b/-> *(ecx+4) 2/r32/edx
20330       89/<- *(eax+8) 2/r32/edx  # Typeinfo-fields
20331       # tmp->next = Program->types
20332       8b/-> *_Program-types 1/r32/ecx
20333       89/<- *(eax+0x10) 1/r32/ecx  # Typeinfo-next
20334       8b/-> *_Program-types->payload 1/r32/ecx
20335       89/<- *(eax+0x14) 1/r32/ecx  # Typeinfo-next
20336       # Program->types = out
20337       8b/-> *edi 1/r32/ecx
20338       89/<- *_Program-types 1/r32/ecx
20339       8b/-> *(edi+4) 1/r32/ecx
20340       89/<- *_Program-types->payload 1/r32/ecx
20341     }
20342 $find-or-create-typeinfo:end:
20343     # . reclaim locals
20344     81 0/subop/add %esp 8/imm32
20345     # . restore registers
20346     5f/pop-to-edi
20347     5a/pop-to-edx
20348     59/pop-to-ecx
20349     58/pop-to-eax
20350     # . epilogue
20351     89/<- %esp 5/r32/ebp
20352     5d/pop-to-ebp
20353     c3/return
20354 
20355 find-typeinfo:  # t: type-id, out: (addr handle typeinfo)
20356     # . prologue
20357     55/push-ebp
20358     89/<- %ebp 4/r32/esp
20359     # . save registers
20360     50/push-eax
20361     51/push-ecx
20362     52/push-edx
20363     57/push-edi
20364     # ecx = t
20365     8b/-> *(ebp+8) 1/r32/ecx
20366     # edi = out
20367     8b/-> *(ebp+0xc) 7/r32/edi
20368     # *out = Program->types
20369     8b/-> *_Program-types 0/r32/eax
20370     89/<- *edi 0/r32/eax
20371     8b/-> *_Program-types->payload 0/r32/eax
20372     89/<- *(edi+4) 0/r32/eax
20373     {
20374 $find-typeinfo:loop:
20375       # if (*out == 0) break
20376       81 7/subop/compare *edi 0/imm32
20377       74/jump-if-= break/disp8
20378 $find-typeinfo:check:
20379       # var tmp/eax: (addr typeinfo) = lookup(*out)
20380       (lookup *edi *(edi+4))  # => eax
20381       # if (tmp->id == t) break
20382       39/compare *eax 1/r32/ecx  # Typeinfo-id
20383       74/jump-if-= break/disp8
20384 $find-typeinfo:continue:
20385       # *out = tmp->next
20386       8b/-> *(eax+0x10) 2/r32/edx  # Typeinfo-next
20387       89/<- *edi 2/r32/edx
20388       8b/-> *(eax+0x14) 2/r32/edx  # Typeinfo-next
20389       89/<- *(edi+4) 2/r32/edx
20390       #
20391       eb/jump loop/disp8
20392     }
20393 $find-typeinfo:end:
20394     # . restore registers
20395     5f/pop-to-edi
20396     5a/pop-to-edx
20397     59/pop-to-ecx
20398     58/pop-to-eax
20399     # . epilogue
20400     89/<- %esp 5/r32/ebp
20401     5d/pop-to-ebp
20402     c3/return
20403 
20404 find-or-create-typeinfo-output-var:  # T: (addr typeinfo), f: (addr slice), out: (addr handle var)
20405     # . prologue
20406     55/push-ebp
20407     89/<- %ebp 4/r32/esp
20408     # . save registers
20409     50/push-eax
20410     52/push-edx
20411     57/push-edi
20412     # var dest/edi: (handle typeinfo-entry)
20413     68/push 0/imm32
20414     68/push 0/imm32
20415     89/<- %edi 4/r32/esp
20416     # find-or-create-typeinfo-fields(T, f, dest)
20417     (find-or-create-typeinfo-fields *(ebp+8) *(ebp+0xc) %edi)
20418     # var dest-addr/edi: (addr typeinfo-entry) = lookup(dest)
20419     (lookup *edi *(edi+4))  # => eax
20420     89/<- %edi 0/r32/eax
20421     # if dest-addr->output-var doesn't exist, create it
20422     {
20423       81 7/subop/compare *(edi+0xc) 0/imm32  # Typeinfo-entry-output-var
20424       0f 85/jump-if-!= break/disp32
20425       # dest-addr->output-var = new var(dummy name, type, -1 offset)
20426       # . var name/eax: (handle array byte) = "field"
20427       68/push 0/imm32
20428       68/push 0/imm32
20429       89/<- %eax 4/r32/esp
20430       (slice-to-string Heap *(ebp+0xc) %eax)
20431       # . new var
20432       8d/copy-address *(edi+0xc) 2/r32/edx
20433       (new-var Heap  *eax *(eax+4)  %edx)
20434       # . reclaim name
20435       81 0/subop/add %esp 8/imm32
20436       # var result/edx: (addr var) = lookup(dest-addr->output-var)
20437       (lookup *(edi+0xc) *(edi+0x10))  # => eax
20438       89/<- %edx 0/r32/eax
20439       # result->type = new constant type
20440       8d/copy-address *(edx+8) 0/r32/eax  # Var-type
20441       (allocate Heap *Type-tree-size %eax)
20442       (lookup *(edx+8) *(edx+0xc))  # => eax
20443       c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
20444       c7 0/subop/copy *(eax+4) 6/imm32/constant  # Type-tree-value
20445       c7 0/subop/copy *(eax+8) 0/imm32  # Type-tree-left
20446       c7 0/subop/copy *(eax+0xc) 0/imm32  # Type-tree-right
20447       c7 0/subop/copy *(eax+0x10) 0/imm32  # Type-tree-right
20448       # result->offset isn't filled out yet
20449       c7 0/subop/copy *(edx+0x14) -1/imm32/uninitialized  # Var-offset
20450     }
20451     # out = dest-addr->output-var
20452     8b/-> *(ebp+0x10) 2/r32/edx
20453     8b/-> *(edi+0xc) 0/r32/eax  # Typeinfo-entry-output-var
20454     89/<- *edx 0/r32/eax
20455     8b/-> *(edi+0x10) 0/r32/eax  # Typeinfo-entry-output-var
20456     89/<- *(edx+4) 0/r32/eax
20457 $find-or-create-typeinfo-output-var:end:
20458     # . reclaim locals
20459     81 0/subop/add %esp 8/imm32
20460     # . restore registers
20461     5f/pop-to-edi
20462     5a/pop-to-edx
20463     58/pop-to-eax
20464     # . epilogue
20465     89/<- %esp 5/r32/ebp
20466     5d/pop-to-ebp
20467     c3/return
20468 
20469 find-or-create-typeinfo-fields:  # T: (addr typeinfo), f: (addr slice), out: (addr handle typeinfo-entry)
20470     # . prologue
20471     55/push-ebp
20472     89/<- %ebp 4/r32/esp
20473     # . save registers
20474     50/push-eax
20475     56/push-esi
20476     57/push-edi
20477     # eax = lookup(T->fields)
20478     8b/-> *(ebp+8) 0/r32/eax
20479     (lookup *(eax+4) *(eax+8))  # Typeinfo-fields Typeinfo-fields => eax
20480     # edi = out
20481     8b/-> *(ebp+0x10) 7/r32/edi
20482     # var src/esi: (addr handle typeinfo-entry) = get-or-insert-slice(T->fields, f)
20483     (get-or-insert-slice %eax *(ebp+0xc) *Typeinfo-fields-row-size Heap)  # => eax
20484     89/<- %esi 0/r32/eax
20485     # if src doesn't exist, allocate it
20486     {
20487       81 7/subop/compare *esi 0/imm32
20488       75/jump-if-!= break/disp8
20489       (allocate Heap *Typeinfo-entry-size %esi)
20490 #?       (write-buffered Stderr "handle at ")
20491 #?       (write-int32-hex-buffered Stderr %esi)
20492 #?       (write-buffered Stderr ": ")
20493 #?       (write-int32-hex-buffered Stderr *esi)
20494 #?       (write-buffered Stderr " ")
20495 #?       (write-int32-hex-buffered Stderr *(esi+4))
20496 #?       (write-buffered Stderr Newline)
20497 #?       (flush Stderr)
20498 #?       (lookup *esi *(esi+4))
20499 #?       (write-buffered Stderr "created typeinfo fields at ")
20500 #?       (write-int32-hex-buffered Stderr %esi)
20501 #?       (write-buffered Stderr " for ")
20502 #?       (write-int32-hex-buffered Stderr *(ebp+8))
20503 #?       (write-buffered Stderr Newline)
20504 #?       (flush Stderr)
20505     }
20506     # *out = src
20507     # . *edi = *src
20508     8b/-> *esi 0/r32/eax
20509     89/<- *edi 0/r32/eax
20510     8b/-> *(esi+4) 0/r32/eax
20511     89/<- *(edi+4) 0/r32/eax
20512 $find-or-create-typeinfo-fields:end:
20513     # . restore registers
20514     5f/pop-to-edi
20515     5e/pop-to-esi
20516     58/pop-to-eax
20517     # . epilogue
20518     89/<- %esp 5/r32/ebp
20519     5d/pop-to-ebp
20520     c3/return
20521 
20522 populate-mu-type:  # in: (addr stream byte), t: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
20523     # pseudocode:
20524     #   var line: (stream byte 512)
20525     #   curr-index = 0
20526     #   while true
20527     #     clear-stream(line)
20528     #     read-line-buffered(in, line)
20529     #     if line->write == 0
20530     #       abort
20531     #     word-slice = next-mu-token(line)
20532     #     if slice-empty?(word-slice)               # end of line
20533     #       continue
20534     #     if slice-equal?(word-slice, "}")
20535     #       break
20536     #     var v: (handle var) = parse-var-with-type(word-slice, line)
20537     #     var r: (handle typeinfo-fields) = find-or-create-typeinfo-fields(t, word-slice/v->name)
20538     #     TODO: ensure that r->first is null
20539     #     r->index = curr-index
20540     #     curr-index++
20541     #     r->input-var = v
20542     #     if r->output-var == 0
20543     #       r->output-var = new literal
20544     #     TODO: ensure nothing else in line
20545     # t->total-size-in-bytes = -2 (not yet initialized)
20546     #
20547     # . prologue
20548     55/push-ebp
20549     89/<- %ebp 4/r32/esp
20550     # var curr-index: int at *(ebp-4)
20551     68/push 0/imm32
20552     # . save registers
20553     50/push-eax
20554     51/push-ecx
20555     52/push-edx
20556     53/push-ebx
20557     56/push-esi
20558     57/push-edi
20559     # edi = t
20560     8b/-> *(ebp+0xc) 7/r32/edi
20561     # var line/ecx: (stream byte 512)
20562     81 5/subop/subtract %esp 0x200/imm32
20563     68/push 0x200/imm32/size
20564     68/push 0/imm32/read
20565     68/push 0/imm32/write
20566     89/<- %ecx 4/r32/esp
20567     # var word-slice/edx: slice
20568     68/push 0/imm32/end
20569     68/push 0/imm32/start
20570     89/<- %edx 4/r32/esp
20571     # var v/esi: (handle var)
20572     68/push 0/imm32
20573     68/push 0/imm32
20574     89/<- %esi 4/r32/esp
20575     # var r/ebx: (handle typeinfo-entry)
20576     68/push 0/imm32
20577     68/push 0/imm32
20578     89/<- %ebx 4/r32/esp
20579     {
20580 $populate-mu-type:line-loop:
20581       (clear-stream %ecx)
20582       (read-line-buffered *(ebp+8) %ecx)
20583       # if (line->write == 0) abort
20584       81 7/subop/compare *ecx 0/imm32
20585       0f 84/jump-if-= $populate-mu-type:error1/disp32
20586 +--  6 lines: #?       # dump line ------------------------------------------------------------------------------------------------------------------------------------------------------
20592       (next-mu-token %ecx %edx)
20593       # if slice-empty?(word-slice) continue
20594       (slice-empty? %edx)  # => eax
20595       3d/compare-eax-and 0/imm32
20596       0f 85/jump-if-!= loop/disp32
20597       # if slice-equal?(word-slice, "}") break
20598       (slice-equal? %edx "}")
20599       3d/compare-eax-and 0/imm32
20600       0f 85/jump-if-!= break/disp32
20601 $populate-mu-type:parse-element:
20602       # v = parse-var-with-type(word-slice, first-line)
20603       # must do this first to strip the trailing ':' from word-slice before
20604       # using it in find-or-create-typeinfo-fields below
20605       # TODO: clean up that mutation in parse-var-with-type
20606       (type-name *edi)  # Typeinfo-id => eax
20607       (parse-var-with-type %edx %ecx %esi %eax *(ebp+0x10) *(ebp+0x14))
20608       # if v is an addr, abort
20609       (lookup *esi *(esi+4))  # => eax
20610       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20611       (mu-addr-type? %eax)  # => eax
20612       3d/compare-eax-and 0/imm32/false
20613       0f 85/jump-if-!= $populate-mu-type:error2/disp32
20614       # if v is an array, abort  (we could support it, but initialization gets complex)
20615       (lookup *esi *(esi+4))  # => eax
20616       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20617       (mu-array-type? %eax)  # => eax
20618       3d/compare-eax-and 0/imm32/false
20619       0f 85/jump-if-!= $populate-mu-type:error3/disp32
20620       # if v is a byte, abort
20621       (lookup *esi *(esi+4))  # => eax
20622       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20623       (simple-mu-type? %eax 8)  # byte => eax
20624       3d/compare-eax-and 0/imm32/false
20625       0f 85/jump-if-!= $populate-mu-type:error4/disp32
20626       # if v is a slice, abort
20627       (lookup *esi *(esi+4))  # => eax
20628       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20629       (simple-mu-type? %eax 0xc)  # slice => eax
20630       3d/compare-eax-and 0/imm32/false
20631       0f 85/jump-if-!= $populate-mu-type:error5/disp32
20632       # if v is a stream, abort  (we could support it, but initialization gets even more complex)
20633       (lookup *esi *(esi+4))  # => eax
20634       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20635       (mu-stream-type? %eax)  # => eax
20636       3d/compare-eax-and 0/imm32/false
20637       0f 85/jump-if-!= $populate-mu-type:error6/disp32
20638       # var tmp/ecx
20639       51/push-ecx
20640 $populate-mu-type:create-typeinfo-fields:
20641       # var r/ebx: (handle typeinfo-entry)
20642       (find-or-create-typeinfo-fields %edi %edx %ebx)
20643       # r->index = curr-index
20644       (lookup *ebx *(ebx+4))  # => eax
20645       8b/-> *(ebp-4) 1/r32/ecx
20646 #?       (write-buffered Stderr "saving index ")
20647 #?       (write-int32-hex-buffered Stderr %ecx)
20648 #?       (write-buffered Stderr " at ")
20649 #?       (write-int32-hex-buffered Stderr %edi)
20650 #?       (write-buffered Stderr Newline)
20651 #?       (flush Stderr)
20652       89/<- *(eax+8) 1/r32/ecx  # Typeinfo-entry-index
20653       # ++curr-index
20654       ff 0/subop/increment *(ebp-4)
20655 $populate-mu-type:set-input-type:
20656       # r->input-var = v
20657       8b/-> *esi 1/r32/ecx
20658       89/<- *eax 1/r32/ecx  # Typeinfo-entry-input-var
20659       8b/-> *(esi+4) 1/r32/ecx
20660       89/<- *(eax+4) 1/r32/ecx  # Typeinfo-entry-input-var
20661       # restore line
20662       59/pop-to-ecx
20663       {
20664 $populate-mu-type:create-output-type:
20665         # if (r->output-var == 0) create a new var with some placeholder data
20666         81 7/subop/compare *(eax+0xc) 0/imm32  # Typeinfo-entry-output-var
20667         75/jump-if-!= break/disp8
20668         8d/copy-address *(eax+0xc) 0/r32/eax  # Typeinfo-entry-output-var
20669         (new-literal Heap %edx %eax)
20670       }
20671       e9/jump loop/disp32
20672     }
20673 $populate-mu-type:invalidate-total-size-in-bytes:
20674     # Offsets and total size may not be accurate here since we may not yet
20675     # have encountered the element types.
20676     # We'll recompute them separately after parsing the entire program.
20677     c7 0/subop/copy *(edi+0xc) -2/imm32/uninitialized  # Typeinfo-total-size-in-bytes
20678 $populate-mu-type:end:
20679     # . reclaim locals
20680     81 0/subop/add %esp 0x224/imm32
20681     # . restore registers
20682     5f/pop-to-edi
20683     5e/pop-to-esi
20684     5b/pop-to-ebx
20685     5a/pop-to-edx
20686     59/pop-to-ecx
20687     58/pop-to-eax
20688     # reclaim curr-index
20689     81 0/subop/add %esp 4/imm32
20690     # . epilogue
20691     89/<- %esp 5/r32/ebp
20692     5d/pop-to-ebp
20693     c3/return
20694 
20695 $populate-mu-type:error1:
20696     # error("incomplete type definition '" t->name "'\n")
20697     (write-buffered *(ebp+0x10) "incomplete type definition '")
20698     (type-name *edi)  # Typeinfo-id => eax
20699     (write-buffered *(ebp+0x10) %eax)
20700     (write-buffered *(ebp+0x10) "\n")
20701     (flush *(ebp+0x10))
20702     (stop *(ebp+0x14) 1)
20703     # never gets here
20704 
20705 $populate-mu-type:error2:
20706     (write-buffered *(ebp+0x10) "type ")
20707     (type-name *edi)  # Typeinfo-id => eax
20708     (write-buffered *(ebp+0x10) %eax)
20709     (write-buffered *(ebp+0x10) ": 'addr' elements not allowed\n")
20710     (flush *(ebp+0x10))
20711     (stop *(ebp+0x14) 1)
20712     # never gets here
20713 
20714 $populate-mu-type:error3:
20715     (write-buffered *(ebp+0x10) "type ")
20716     (type-name *edi)  # Typeinfo-id => eax
20717     (write-buffered *(ebp+0x10) %eax)
20718     (write-buffered *(ebp+0x10) ": 'array' elements not allowed for now\n")
20719     (flush *(ebp+0x10))
20720     (stop *(ebp+0x14) 1)
20721     # never gets here
20722 
20723 $populate-mu-type:error4:
20724     (write-buffered *(ebp+0x10) "type ")
20725     (type-name *edi)  # Typeinfo-id => eax
20726     (write-buffered *(ebp+0x10) %eax)
20727     (write-buffered *(ebp+0x10) ": 'byte' elements not allowed\n")
20728     (flush *(ebp+0x10))
20729     (stop *(ebp+0x14) 1)
20730     # never gets here
20731 
20732 $populate-mu-type:error5:
20733     (write-buffered *(ebp+0x10) "type ")
20734     (type-name *edi)  # Typeinfo-id => eax
20735     (write-buffered *(ebp+0x10) %eax)
20736     (write-buffered *(ebp+0x10) ": 'slice' elements not allowed\n")
20737     (flush *(ebp+0x10))
20738     (stop *(ebp+0x14) 1)
20739     # never gets here
20740 
20741 $populate-mu-type:error6:
20742     (write-buffered *(ebp+0x10) "type ")
20743     (type-name *edi)  # Typeinfo-id => eax
20744     (write-buffered *(ebp+0x10) %eax)
20745     (write-buffered *(ebp+0x10) ": 'stream' elements not allowed for now\n")
20746     (flush *(ebp+0x10))
20747     (stop *(ebp+0x14) 1)
20748     # never gets here
20749 
20750 type-name:  # index: int -> result/eax: (addr array byte)
20751     # . prologue
20752     55/push-ebp
20753     89/<- %ebp 4/r32/esp
20754     #
20755     (index Type-id *(ebp+8))
20756 $type-name:end:
20757     # . epilogue
20758     89/<- %esp 5/r32/ebp
20759     5d/pop-to-ebp
20760     c3/return
20761 
20762 index:  # arr: (addr stream (handle array byte)), index: int -> result/eax: (addr array byte)
20763     # . prologue
20764     55/push-ebp
20765     89/<- %ebp 4/r32/esp
20766     # . save registers
20767     56/push-esi
20768     # TODO: bounds-check index
20769     # esi = arr
20770     8b/-> *(ebp+8) 6/r32/esi
20771     # eax = index
20772     8b/-> *(ebp+0xc) 0/r32/eax
20773     # eax = *(arr + 12 + index)
20774     8b/-> *(esi+eax<<2+0xc) 0/r32/eax
20775 $index:end:
20776     # . restore registers
20777     5e/pop-to-esi
20778     # . epilogue
20779     89/<- %esp 5/r32/ebp
20780     5d/pop-to-ebp
20781     c3/return
20782 
20783 #######################################################
20784 # Compute type sizes
20785 #######################################################
20786 
20787 # Compute the sizes of all user-defined types.
20788 # We'll need the sizes of their elements, which may be other user-defined
20789 # types, which we will compute as needed.
20790 
20791 # Initially, all user-defined types have their sizes set to -2 (invalid)
20792 populate-mu-type-sizes:  # err: (addr buffered-file), ed: (addr exit-descriptor)
20793     # . prologue
20794     55/push-ebp
20795     89/<- %ebp 4/r32/esp
20796 $populate-mu-type-sizes:total-sizes:
20797     # var curr/eax: (addr typeinfo) = lookup(Program->types)
20798     (lookup *_Program-types *_Program-types->payload)  # => eax
20799     {
20800       # if (curr == null) break
20801       3d/compare-eax-and 0/imm32/null
20802       74/jump-if-= break/disp8
20803       (populate-mu-type-sizes-in-type %eax *(ebp+8) *(ebp+0xc))
20804       # curr = lookup(curr->next)
20805       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
20806       eb/jump loop/disp8
20807     }
20808 $populate-mu-type-sizes:offsets:
20809     # curr = *Program->types
20810     (lookup *_Program-types *_Program-types->payload)  # => eax
20811     {
20812       # if (curr == null) break
20813       3d/compare-eax-and 0/imm32/null
20814       74/jump-if-= break/disp8
20815       (populate-mu-type-offsets %eax *(ebp+8) *(ebp+0xc))
20816       # curr = curr->next
20817       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
20818       eb/jump loop/disp8
20819     }
20820 $populate-mu-type-sizes:end:
20821     # . epilogue
20822     89/<- %esp 5/r32/ebp
20823     5d/pop-to-ebp
20824     c3/return
20825 
20826 # compute sizes of all fields, recursing as necessary
20827 # sum up all their sizes to arrive at total size
20828 # fields may be out of order, but that doesn't affect the answer
20829 populate-mu-type-sizes-in-type:  # T: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
20830     # . prologue
20831     55/push-ebp
20832     89/<- %ebp 4/r32/esp
20833     # . save registers
20834     50/push-eax
20835     51/push-ecx
20836     52/push-edx
20837     56/push-esi
20838     57/push-edi
20839     # esi = T
20840     8b/-> *(ebp+8) 6/r32/esi
20841     # if T is already computed, return
20842     81 7/subop/compare *(esi+0xc) 0/imm32  # Typeinfo-total-size-in-bytes
20843     0f 8d/jump-if->= $populate-mu-type-sizes-in-type:end/disp32
20844     # if T is being computed, abort
20845     81 7/subop/compare *(esi+0xc) -1/imm32/being-computed  # Typeinfo-total-size-in-bytes
20846     0f 84/jump-if-= $populate-mu-type-sizes-in-type:abort/disp32
20847     # tag T (-2 to -1) to avoid infinite recursion
20848     c7 0/subop/copy *(esi+0xc) -1/imm32/being-computed  # Typeinfo-total-size-in-bytes
20849     # var total-size/edi: int = 0
20850     bf/copy-to-edi 0/imm32
20851     # - for every field, if it's a user-defined type, compute its size
20852     # var table/ecx: (addr table (handle array byte) (handle typeinfo-entry)) = lookup(T->fields)
20853     (lookup *(esi+4) *(esi+8))  # Typeinfo-fields Typeinfo-fields => eax
20854     89/<- %ecx 0/r32/eax
20855     # var table-size/edx: int = table->write
20856     8b/-> *ecx 2/r32/edx  # stream-write
20857     # var curr/ecx: (addr table_row) = table->data
20858     8d/copy-address *(ecx+0xc) 1/r32/ecx
20859     # var max/edx: (addr table_row) = table->data + table->write
20860     8d/copy-address *(ecx+edx) 2/r32/edx
20861     {
20862 $populate-mu-type-sizes-in-type:loop:
20863       # if (curr >= max) break
20864       39/compare %ecx 2/r32/edx
20865       73/jump-if-addr>= break/disp8
20866       # var t/eax: (addr typeinfo-entry) = lookup(curr->value)
20867       (lookup *(ecx+8) *(ecx+0xc))  # => eax
20868       # if (t->input-var == 0) silently ignore it; we'll emit a nice error message while type-checking
20869       81 7/subop/compare *eax 0/imm32  # Typeinfo-entry-input-var
20870       74/jump-if-= $populate-mu-type-sizes-in-type:end/disp8
20871       # compute size of t->input-var
20872       (lookup *eax *(eax+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
20873       (compute-size-of-var %eax *(ebp+0xc) *(ebp+0x10))  # => eax
20874       # result += eax
20875       01/add-to %edi 0/r32/eax
20876       # curr += row-size
20877       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-fields-row-size
20878       #
20879       eb/jump loop/disp8
20880     }
20881     # - save result
20882     89/<- *(esi+0xc) 7/r32/edi  # Typeinfo-total-size-in-bytes
20883 $populate-mu-type-sizes-in-type:end:
20884     # . restore registers
20885     5f/pop-to-edi
20886     5e/pop-to-esi
20887     5a/pop-to-edx
20888     59/pop-to-ecx
20889     58/pop-to-eax
20890     # . epilogue
20891     89/<- %esp 5/r32/ebp
20892     5d/pop-to-ebp
20893     c3/return
20894 
20895 $populate-mu-type-sizes-in-type:abort:
20896     (write-buffered *(ebp+0xc) "cycle in type definitions\n")
20897     (flush *(ebp+0xc))
20898     (stop *(ebp+0x10) 1)
20899     # never gets here
20900 
20901 # Analogous to size-of, except we need to compute what size-of can just read
20902 # off the right data structures.
20903 compute-size-of-var:  # in: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
20904     # . prologue
20905     55/push-ebp
20906     89/<- %ebp 4/r32/esp
20907     # . push registers
20908     51/push-ecx
20909     # var t/ecx: (addr type-tree) = lookup(v->type)
20910     8b/-> *(ebp+8) 1/r32/ecx
20911     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
20912     89/<- %ecx 0/r32/eax
20913     # if (t->is-atom == false) t = lookup(t->left)
20914     {
20915       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
20916       75/jump-if-!= break/disp8
20917       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
20918       89/<- %ecx 0/r32/eax
20919     }
20920     # TODO: ensure t is an atom
20921     (compute-size-of-type-id *(ecx+4) *(ebp+0xc) *(ebp+0x10))  # Type-tree-value => eax
20922 $compute-size-of-var:end:
20923     # . restore registers
20924     59/pop-to-ecx
20925     # . epilogue
20926     89/<- %esp 5/r32/ebp
20927     5d/pop-to-ebp
20928     c3/return
20929 
20930 compute-size-of-type-id:  # t: type-id, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
20931     # . prologue
20932     55/push-ebp
20933     89/<- %ebp 4/r32/esp
20934     # . save registers
20935     51/push-ecx
20936     # var out/ecx: (handle typeinfo)
20937     68/push 0/imm32
20938     68/push 0/imm32
20939     89/<- %ecx 4/r32/esp
20940     # eax = t
20941     8b/-> *(ebp+8) 0/r32/eax
20942     # if t is a literal, return 0
20943     3d/compare-eax-and 0/imm32/literal
20944     0f 84/jump-if-= $compute-size-of-type-id:end/disp32  # eax changes type from type-id to int
20945     # if t is a byte, return 4 (because we don't really support non-multiples of 4)
20946     3d/compare-eax-and 8/imm32/byte
20947     {
20948       75/jump-if-!= break/disp8
20949       b8/copy-to-eax 4/imm32
20950       eb/jump $compute-size-of-type-id:end/disp8
20951     }
20952     # if t is a handle, return 8
20953     3d/compare-eax-and 4/imm32/handle
20954     {
20955       75/jump-if-!= break/disp8
20956       b8/copy-to-eax 8/imm32
20957       eb/jump $compute-size-of-type-id:end/disp8  # eax changes type from type-id to int
20958     }
20959     # if t is a slice, return 8
20960     3d/compare-eax-and 0xc/imm32/slice
20961     {
20962       75/jump-if-!= break/disp8
20963       b8/copy-to-eax 8/imm32
20964       eb/jump $compute-size-of-type-id:end/disp8  # eax changes type from type-id to int
20965     }
20966     # if t is a user-defined type, compute its size
20967     # TODO: support non-atom type
20968     (find-typeinfo %eax %ecx)
20969     {
20970       81 7/subop/compare *ecx 0/imm32
20971       74/jump-if-= break/disp8
20972 $compute-size-of-type-id:user-defined:
20973       (lookup *ecx *(ecx+4))  # => eax
20974       (populate-mu-type-sizes-in-type %eax *(ebp+0xc) *(ebp+0x10))
20975       8b/-> *(eax+0xc) 0/r32/eax  # Typeinfo-total-size-in-bytes
20976       eb/jump $compute-size-of-type-id:end/disp8
20977     }
20978     # otherwise return the word size
20979     b8/copy-to-eax 4/imm32
20980 $compute-size-of-type-id:end:
20981     # . reclaim locals
20982     81 0/subop/add %esp 8/imm32
20983     # . restore registers
20984     59/pop-to-ecx
20985     # . epilogue
20986     89/<- %esp 5/r32/ebp
20987     5d/pop-to-ebp
20988     c3/return
20989 
20990 # at this point we have total sizes for all user-defined types
20991 # compute offsets for each element
20992 # complication: fields may be out of order
20993 populate-mu-type-offsets:  # in: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
20994     # . prologue
20995     55/push-ebp
20996     89/<- %ebp 4/r32/esp
20997     # . save registers
20998     50/push-eax
20999     51/push-ecx
21000     52/push-edx
21001     53/push-ebx
21002     56/push-esi
21003     57/push-edi
21004 #?     (dump-typeinfos "aaa\n")
21005     # var curr-offset/edi: int = 0
21006     bf/copy-to-edi 0/imm32
21007     # var table/ecx: (addr table string_key (handle typeinfo-entry)) = lookup(in->fields)
21008     8b/-> *(ebp+8) 1/r32/ecx
21009     (lookup *(ecx+4) *(ecx+8))  # Typeinfo-fields Typeinfo-fields => eax
21010     89/<- %ecx 0/r32/eax
21011     # var num-elems/edx: int = table->write / Typeinfo-fields-row-size
21012     8b/-> *ecx 2/r32/edx  # stream-write
21013     c1 5/subop/shift-right-logical  %edx 4/imm8
21014     # var i/ebx: int = 0
21015     bb/copy-to-ebx 0/imm32
21016     {
21017 $populate-mu-type-offsets:loop:
21018       39/compare %ebx 2/r32/edx
21019       0f 8d/jump-if->= break/disp32
21020 #?       (write-buffered Stderr "looking up index ")
21021 #?       (write-int32-hex-buffered Stderr %ebx)
21022 #?       (write-buffered Stderr " in ")
21023 #?       (write-int32-hex-buffered Stderr *(ebp+8))
21024 #?       (write-buffered Stderr Newline)
21025 #?       (flush Stderr)
21026       # var v/esi: (addr typeinfo-entry)
21027       (locate-typeinfo-entry-with-index %ecx %ebx *(ebp+0xc) *(ebp+0x10))  # => eax
21028       89/<- %esi 0/r32/eax
21029       # if v is null, silently move on; we'll emit a nice error message while type-checking
21030       81 7/subop/compare %esi 0/imm32  # Typeinfo-entry-input-var
21031       74/jump-if-= $populate-mu-type-offsets:end/disp8
21032       # if (v->input-var == 0) silently ignore v; we'll emit a nice error message while type-checking
21033       81 7/subop/compare *esi 0/imm32  # Typeinfo-entry-input-var
21034       74/jump-if-= $populate-mu-type-offsets:end/disp8
21035       # v->output-var->offset = curr-offset
21036       # . eax: (addr var)
21037       (lookup *(esi+0xc) *(esi+0x10))  # Typeinfo-entry-output-var Typeinfo-entry-output-var => eax
21038       89/<- *(eax+0x14) 7/r32/edi  # Var-offset
21039       # curr-offset += size-of(v->input-var)
21040       (lookup *esi *(esi+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
21041       (size-of %eax)  # => eax
21042       01/add-to %edi 0/r32/eax
21043       # ++i
21044       43/increment-ebx
21045       e9/jump loop/disp32
21046     }
21047 $populate-mu-type-offsets:end:
21048     # . restore registers
21049     5f/pop-to-edi
21050     5e/pop-to-esi
21051     5b/pop-to-ebx
21052     5a/pop-to-edx
21053     59/pop-to-ecx
21054     58/pop-to-eax
21055     # . epilogue
21056     89/<- %esp 5/r32/ebp
21057     5d/pop-to-ebp
21058     c3/return
21059 
21060 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)
21061     # . prologue
21062     55/push-ebp
21063     89/<- %ebp 4/r32/esp
21064     # . save registers
21065     51/push-ecx
21066     52/push-edx
21067     53/push-ebx
21068     56/push-esi
21069     57/push-edi
21070     # esi = table
21071     8b/-> *(ebp+8) 6/r32/esi
21072     # var curr/ecx: (addr row (handle array byte) (handle typeinfo-entry)) = table->data
21073     8d/copy-address *(esi+0xc) 1/r32/ecx
21074     # var max/edx: (addr byte) = &table->data[table->write]
21075     8b/-> *esi 2/r32/edx
21076     8d/copy-address *(ecx+edx) 2/r32/edx
21077     {
21078 $locate-typeinfo-entry-with-index:loop:
21079       39/compare %ecx 2/r32/edx
21080       73/jump-if-addr>= break/disp8
21081       # var v/eax: (addr typeinfo-entry)
21082       (lookup *(ecx+8) *(ecx+0xc))  # => eax
21083       # if (v->index == idx) return v
21084       8b/-> *(eax+8) 3/r32/ebx  # Typeinfo-entry-index
21085 #?       (write-buffered Stderr "comparing ")
21086 #?       (write-int32-hex-buffered Stderr %ebx)
21087 #?       (write-buffered Stderr " and ")
21088 #?       (write-int32-hex-buffered Stderr *(ebp+0xc))
21089 #?       (write-buffered Stderr Newline)
21090 #?       (flush Stderr)
21091       39/compare *(ebp+0xc) 3/r32/ebx
21092       74/jump-if-= $locate-typeinfo-entry-with-index:end/disp8
21093       # curr += Typeinfo-entry-size
21094       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-entry-size
21095       #
21096       eb/jump loop/disp8
21097     }
21098     # return 0
21099     b8/copy-to-eax 0/imm32
21100 $locate-typeinfo-entry-with-index:end:
21101 #?     (write-buffered Stderr "returning ")
21102 #?     (write-int32-hex-buffered Stderr %eax)
21103 #?     (write-buffered Stderr Newline)
21104 #?     (flush Stderr)
21105     # . restore registers
21106     5f/pop-to-edi
21107     5e/pop-to-esi
21108     5b/pop-to-ebx
21109     5a/pop-to-edx
21110     59/pop-to-ecx
21111     # . epilogue
21112     89/<- %esp 5/r32/ebp
21113     5d/pop-to-ebp
21114     c3/return
21115 
21116 dump-typeinfos:  # hdr: (addr array byte)
21117     # . prologue
21118     55/push-ebp
21119     89/<- %ebp 4/r32/esp
21120     # . save registers
21121     50/push-eax
21122     #
21123     (write-buffered Stderr *(ebp+8))
21124     (flush Stderr)
21125     # var curr/eax: (addr typeinfo) = lookup(Program->types)
21126     (lookup *_Program-types *_Program-types->payload)  # => eax
21127     {
21128       # if (curr == null) break
21129       3d/compare-eax-and 0/imm32
21130       74/jump-if-= break/disp8
21131       (write-buffered Stderr "---\n")
21132       (flush Stderr)
21133       (dump-typeinfo %eax)
21134       # curr = lookup(curr->next)
21135       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
21136       eb/jump loop/disp8
21137     }
21138 $dump-typeinfos:end:
21139     # . restore registers
21140     58/pop-to-eax
21141     # . epilogue
21142     89/<- %esp 5/r32/ebp
21143     5d/pop-to-ebp
21144     c3/return
21145 
21146 dump-typeinfo:  # in: (addr typeinfo)
21147     # . prologue
21148     55/push-ebp
21149     89/<- %ebp 4/r32/esp
21150     # . save registers
21151     50/push-eax
21152     51/push-ecx
21153     52/push-edx
21154     53/push-ebx
21155     56/push-esi
21156     57/push-edi
21157     # esi = in
21158     8b/-> *(ebp+8) 6/r32/esi
21159     # var table/ecx: (addr table (handle array byte) (handle typeinfo-entry)) = lookup(T->fields)
21160     (lookup *(esi+4) *(esi+8))  # Typeinfo-fields Typeinfo-fields => eax
21161     89/<- %ecx 0/r32/eax
21162     (write-buffered Stderr "id:")
21163     (write-int32-hex-buffered Stderr *esi)
21164     (write-buffered Stderr "\n")
21165     (write-buffered Stderr "fields @ ")
21166     (write-int32-hex-buffered Stderr %ecx)
21167     (write-buffered Stderr Newline)
21168     (flush Stderr)
21169     (write-buffered Stderr "  write: ")
21170     (write-int32-hex-buffered Stderr *ecx)
21171     (write-buffered Stderr Newline)
21172     (flush Stderr)
21173     (write-buffered Stderr "  read: ")
21174     (write-int32-hex-buffered Stderr *(ecx+4))
21175     (write-buffered Stderr Newline)
21176     (flush Stderr)
21177     (write-buffered Stderr "  size: ")
21178     (write-int32-hex-buffered Stderr *(ecx+8))
21179     (write-buffered Stderr Newline)
21180     (flush Stderr)
21181     # var table-size/edx: int = table->write
21182     8b/-> *ecx 2/r32/edx  # stream-write
21183     # var curr/ecx: (addr table_row) = table->data
21184     8d/copy-address *(ecx+0xc) 1/r32/ecx
21185     # var max/edx: (addr table_row) = table->data + table->write
21186     8d/copy-address *(ecx+edx) 2/r32/edx
21187     {
21188 $dump-typeinfo:loop:
21189       # if (curr >= max) break
21190       39/compare %ecx 2/r32/edx
21191       0f 83/jump-if-addr>= break/disp32
21192       (write-buffered Stderr "  row:\n")
21193       (write-buffered Stderr "    key: ")
21194       (write-int32-hex-buffered Stderr *ecx)
21195       (write-buffered Stderr ",")
21196       (write-int32-hex-buffered Stderr *(ecx+4))
21197       (write-buffered Stderr " = '")
21198       (lookup *ecx *(ecx+4))
21199       (write-buffered Stderr %eax)
21200       (write-buffered Stderr "' @ ")
21201       (write-int32-hex-buffered Stderr %eax)
21202       (write-buffered Stderr Newline)
21203       (flush Stderr)
21204       (write-buffered Stderr "    value: ")
21205       (write-int32-hex-buffered Stderr *(ecx+8))
21206       (write-buffered Stderr ",")
21207       (write-int32-hex-buffered Stderr *(ecx+0xc))
21208       (write-buffered Stderr " = typeinfo-entry@")
21209       (lookup *(ecx+8) *(ecx+0xc))
21210       (write-int32-hex-buffered Stderr %eax)
21211       (write-buffered Stderr Newline)
21212       (flush Stderr)
21213       (write-buffered Stderr "        input var@")
21214       (dump-var 5 %eax)
21215       (lookup *(ecx+8) *(ecx+0xc))
21216       (write-buffered Stderr "        index: ")
21217       (write-int32-hex-buffered Stderr *(eax+8))
21218       (write-buffered Stderr Newline)
21219       (flush Stderr)
21220       (write-buffered Stderr "        output var@")
21221       8d/copy-address *(eax+0xc) 0/r32/eax  # Typeinfo-entry-output-var
21222       (dump-var 5 %eax)
21223       (flush Stderr)
21224       # curr += row-size
21225       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-fields-row-size
21226       #
21227       e9/jump loop/disp32
21228     }
21229 $dump-typeinfo:end:
21230     # . restore registers
21231     5f/pop-to-edi
21232     5e/pop-to-esi
21233     5b/pop-to-ebx
21234     5a/pop-to-edx
21235     59/pop-to-ecx
21236     58/pop-to-eax
21237     # . epilogue
21238     89/<- %esp 5/r32/ebp
21239     5d/pop-to-ebp
21240     c3/return
21241 
21242 dump-var:  # indent: int, v: (addr handle var)
21243     # . prologue
21244     55/push-ebp
21245     89/<- %ebp 4/r32/esp
21246     # . save registers
21247     50/push-eax
21248     53/push-ebx
21249     # eax = v
21250     8b/-> *(ebp+0xc) 0/r32/eax
21251     #
21252     (write-int32-hex-buffered Stderr *eax)
21253     (write-buffered Stderr ",")
21254     (write-int32-hex-buffered Stderr *(eax+4))
21255     (write-buffered Stderr "->")
21256     (lookup *eax *(eax+4))
21257     (write-int32-hex-buffered Stderr %eax)
21258     (write-buffered Stderr Newline)
21259     (flush Stderr)
21260     {
21261       3d/compare-eax-and 0/imm32
21262       0f 84/jump-if-= break/disp32
21263       (emit-indent Stderr *(ebp+8))
21264       (write-buffered Stderr "name: ")
21265       89/<- %ebx 0/r32/eax
21266       (write-int32-hex-buffered Stderr *ebx)  # Var-name
21267       (write-buffered Stderr ",")
21268       (write-int32-hex-buffered Stderr *(ebx+4))  # Var-name
21269       (write-buffered Stderr "->")
21270       (lookup *ebx *(ebx+4))  # Var-name
21271       (write-int32-hex-buffered Stderr %eax)
21272       {
21273         3d/compare-eax-and 0/imm32
21274         74/jump-if-= break/disp8
21275         (write-buffered Stderr Space)
21276         (write-buffered Stderr %eax)
21277       }
21278       (write-buffered Stderr Newline)
21279       (flush Stderr)
21280       (emit-indent Stderr *(ebp+8))
21281       (write-buffered Stderr "block depth: ")
21282       (write-int32-hex-buffered Stderr *(ebx+0x10))  # Var-block-depth
21283       (write-buffered Stderr Newline)
21284       (flush Stderr)
21285       (emit-indent Stderr *(ebp+8))
21286       (write-buffered Stderr "stack offset: ")
21287       (write-int32-hex-buffered Stderr *(ebx+0x14))  # Var-offset
21288       (write-buffered Stderr Newline)
21289       (flush Stderr)
21290       (emit-indent Stderr *(ebp+8))
21291       (write-buffered Stderr "reg: ")
21292       (write-int32-hex-buffered Stderr *(ebx+0x18))  # Var-register
21293       (write-buffered Stderr ",")
21294       (write-int32-hex-buffered Stderr *(ebx+0x1c))  # Var-register
21295       (write-buffered Stderr "->")
21296       (flush Stderr)
21297       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register
21298       (write-int32-hex-buffered Stderr %eax)
21299       {
21300         3d/compare-eax-and 0/imm32
21301         74/jump-if-= break/disp8
21302         (write-buffered Stderr Space)
21303         (write-buffered Stderr %eax)
21304       }
21305       (write-buffered Stderr Newline)
21306       (flush Stderr)
21307     }
21308 $dump-var:end:
21309     # . restore registers
21310     5b/pop-to-ebx
21311     58/pop-to-eax
21312     # . epilogue
21313     89/<- %esp 5/r32/ebp
21314     5d/pop-to-ebp
21315     c3/return
21316 
21317 #######################################################
21318 # Type-checking
21319 #######################################################
21320 
21321 check-mu-types:  # err: (addr buffered-file), ed: (addr exit-descriptor)
21322     # . prologue
21323     55/push-ebp
21324     89/<- %ebp 4/r32/esp
21325     # . save registers
21326     50/push-eax
21327     # var curr/eax: (addr function) = lookup(Program->functions)
21328     (lookup *_Program-functions *_Program-functions->payload)  # => eax
21329     {
21330 $check-mu-types:loop:
21331       # if (curr == null) break
21332       3d/compare-eax-and 0/imm32
21333       0f 84/jump-if-= break/disp32
21334 +--  8 lines: #?       # dump curr->name ------------------------------------------------------------------------------------------------------------------------------------------------
21342       (check-mu-function %eax *(ebp+8) *(ebp+0xc))
21343       # curr = lookup(curr->next)
21344       (lookup *(eax+0x20) *(eax+0x24))  # Function-next Function-next => eax
21345       e9/jump loop/disp32
21346     }
21347 $check-mu-types:end:
21348     # . restore registers
21349     58/pop-to-eax
21350     # . epilogue
21351     89/<- %esp 5/r32/ebp
21352     5d/pop-to-ebp
21353     c3/return
21354 
21355 check-mu-function:  # fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21356     # . prologue
21357     55/push-ebp
21358     89/<- %ebp 4/r32/esp
21359     # . save registers
21360     50/push-eax
21361     56/push-esi
21362     # esi = f
21363     8b/-> *(ebp+8) 6/r32/esi
21364     # outputs
21365     (lookup *(esi+0x10) *(esi+0x14))  # Function-outputs Function-outputs => eax
21366     (check-all-unique-registers %eax %esi *(ebp+0xc) *(ebp+0x10))
21367     # body
21368     (lookup *(esi+0x18) *(esi+0x1c))  # Function-body Function-body => eax
21369     (check-mu-block %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10))
21370     # if function has no outputs, we're done
21371     81 7/subop/compare *(esi+0x10) 0/imm32
21372     74/jump-if-= $check-mu-function:end/disp8
21373     # some final checks on body
21374     (check-final-stmt-is-return %eax %esi *(ebp+0xc) *(ebp+0x10))
21375     (check-no-breaks %eax %esi *(ebp+0xc) *(ebp+0x10))
21376 $check-mu-function:end:
21377     # . restore registers
21378     5e/pop-to-esi
21379     58/pop-to-eax
21380     # . epilogue
21381     89/<- %esp 5/r32/ebp
21382     5d/pop-to-ebp
21383     c3/return
21384 
21385 check-mu-block:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21386     # . prologue
21387     55/push-ebp
21388     89/<- %ebp 4/r32/esp
21389     # . save registers
21390     50/push-eax
21391     # eax = block
21392     8b/-> *(ebp+8) 0/r32/eax
21393     # var stmts/eax: (addr list stmt) = lookup(block->statements)
21394     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
21395     #
21396     {
21397 $check-mu-block:check-empty:
21398       3d/compare-eax-and 0/imm32
21399       0f 84/jump-if-= break/disp32
21400       # emit block->statements
21401       (check-mu-stmt-list %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21402     }
21403 $check-mu-block:end:
21404     # . restore registers
21405     58/pop-to-eax
21406     # . epilogue
21407     89/<- %esp 5/r32/ebp
21408     5d/pop-to-ebp
21409     c3/return
21410 
21411 check-mu-stmt-list:  # stmts: (addr list stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21412     # . prologue
21413     55/push-ebp
21414     89/<- %ebp 4/r32/esp
21415     # . save registers
21416     50/push-eax
21417     56/push-esi
21418     # esi = stmts
21419     8b/-> *(ebp+8) 6/r32/esi
21420     {
21421 $check-mu-stmt-list:loop:
21422       81 7/subop/compare %esi 0/imm32
21423       0f 84/jump-if-= break/disp32
21424       # var curr-stmt/eax: (addr stmt) = lookup(stmts->value)
21425       (lookup *esi *(esi+4))  # List-value List-value => eax
21426       {
21427 $check-mu-stmt-list:check-for-block:
21428         81 7/subop/compare *eax 0/imm32/block  # Stmt-tag
21429         75/jump-if-!= break/disp8
21430 $check-mu-stmt-list:block:
21431         (check-mu-block %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21432         eb/jump $check-mu-stmt-list:continue/disp8
21433       }
21434       {
21435 $check-mu-stmt-list:check-for-stmt1:
21436         81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
21437         0f 85/jump-if-!= break/disp32
21438 $check-mu-stmt-list:stmt1:
21439         (check-mu-stmt %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21440         eb/jump $check-mu-stmt-list:continue/disp8
21441       }
21442       {
21443 $check-mu-stmt-list:check-for-reg-var-def:
21444         81 7/subop/compare *eax 3/imm32/reg-var-def  # Stmt-tag
21445         0f 85/jump-if-!= break/disp32
21446 $check-mu-stmt-list:reg-var-def:
21447         (check-mu-stmt %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21448         eb/jump $check-mu-stmt-list:continue/disp8
21449       }
21450 $check-mu-stmt-list:continue:
21451       # TODO: raise an error on unrecognized Stmt-tag
21452       (lookup *(esi+8) *(esi+0xc))  # List-next List-next => eax
21453       89/<- %esi 0/r32/eax
21454       e9/jump loop/disp32
21455     }
21456 $check-mu-stmt-list:end:
21457     # . restore registers
21458     5e/pop-to-esi
21459     58/pop-to-eax
21460     # . epilogue
21461     89/<- %esp 5/r32/ebp
21462     5d/pop-to-ebp
21463     c3/return
21464 
21465 check-mu-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21466     # . prologue
21467     55/push-ebp
21468     89/<- %ebp 4/r32/esp
21469     # . save registers
21470     50/push-eax
21471     # - if stmt's operation matches a primitive, check against it
21472     (has-primitive-name? *(ebp+8))  # => eax
21473     3d/compare-eax-and 0/imm32/false
21474     {
21475       74/jump-if-= break/disp8
21476       (check-mu-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21477       e9/jump $check-mu-stmt:end/disp32
21478     }
21479     # - otherwise find a function to check against
21480     # var f/eax: (addr function) = lookup(*Program->functions)
21481     (lookup *_Program-functions *_Program-functions->payload)  # => eax
21482     (find-matching-function %eax *(ebp+8))  # => eax
21483     3d/compare-eax-and 0/imm32
21484     {
21485       74/jump-if-= break/disp8
21486       (check-mu-call *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21487       eb/jump $check-mu-stmt:end/disp8
21488     }
21489     # var f/eax: (addr function) = lookup(*Program->signatures)
21490     (lookup *_Program-signatures *_Program-signatures->payload)  # => eax
21491     (find-matching-function %eax *(ebp+8))  # => eax
21492     3d/compare-eax-and 0/imm32
21493     {
21494       74/jump-if-= break/disp8
21495       (check-mu-call *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21496       eb/jump $check-mu-stmt:end/disp8
21497     }
21498     # - otherwise abort
21499     e9/jump $check-mu-stmt:unknown-call/disp32
21500 $check-mu-stmt:end:
21501     # . restore registers
21502     58/pop-to-eax
21503     # . epilogue
21504     89/<- %esp 5/r32/ebp
21505     5d/pop-to-ebp
21506     c3/return
21507 
21508 $check-mu-stmt:unknown-call:
21509     (write-buffered *(ebp+0x10) "unknown function '")
21510     8b/-> *(ebp+8) 0/r32/eax
21511     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
21512     (write-buffered *(ebp+0x10) %eax)
21513     (write-buffered *(ebp+0x10) "'\n")
21514     (flush *(ebp+0x10))
21515     (stop *(ebp+0x14) 1)
21516     # never gets here
21517 
21518 has-primitive-name?:  # stmt: (addr stmt) -> result/eax: boolean
21519     # . prologue
21520     55/push-ebp
21521     89/<- %ebp 4/r32/esp
21522     # . save registers
21523     51/push-ecx
21524     56/push-esi
21525     # var name/esi: (addr array byte) = lookup(stmt->operation)
21526     8b/-> *(ebp+8) 6/r32/esi
21527     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
21528     89/<- %esi 0/r32/eax
21529     # if (name == "return") return true
21530     (string-equal? %esi "return")  # => eax
21531     3d/compare-eax-and 0/imm32/false
21532     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21533     # if (name == "get") return true
21534     (string-equal? %esi "get")  # => eax
21535     3d/compare-eax-and 0/imm32/false
21536     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21537     # if (name == "index") return true
21538     (string-equal? %esi "index")  # => eax
21539     3d/compare-eax-and 0/imm32/false
21540     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21541     # if (name == "length") return true
21542     (string-equal? %esi "length")  # => eax
21543     3d/compare-eax-and 0/imm32/false
21544     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21545     # if (name == "compute-offset") return true
21546     (string-equal? %esi "compute-offset")  # => eax
21547     3d/compare-eax-and 0/imm32/false
21548     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21549     # if (name == "copy-object") return true
21550     (string-equal? %esi "copy-object")  # => eax
21551     3d/compare-eax-and 0/imm32/false
21552     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21553     # if (name == "clear-object") return true
21554     (string-equal? %esi "clear-object")  # => eax
21555     3d/compare-eax-and 0/imm32/false
21556     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21557     # if (name == "allocate") return true
21558     (string-equal? %esi "allocate")  # => eax
21559     3d/compare-eax-and 0/imm32/false
21560     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21561     # if (name == "populate") return true
21562     (string-equal? %esi "populate")  # => eax
21563     3d/compare-eax-and 0/imm32/false
21564     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21565     # if (name == "populate-stream") return true
21566     (string-equal? %esi "populate-stream")  # => eax
21567     3d/compare-eax-and 0/imm32/false
21568     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21569     # if (name == "read-from-stream") return true
21570     (string-equal? %esi "read-from-stream")  # => eax
21571     3d/compare-eax-and 0/imm32/false
21572     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21573     # if (name == "write-to-stream") return true
21574     (string-equal? %esi "write-to-stream")  # => eax
21575     3d/compare-eax-and 0/imm32/false
21576     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21577     # var curr/ecx: (addr primitive) = Primitives
21578     b9/copy-to-ecx Primitives/imm32
21579     {
21580 $has-primitive-name?:loop:
21581       # if (curr == null) break
21582       81 7/subop/compare %ecx 0/imm32
21583       74/jump-if-= break/disp8
21584       # if (primitive->name == name) return true
21585       (lookup *ecx *(ecx+4))  # Primitive-name Primitive-name => eax
21586 #?       (write-buffered Stderr %eax)
21587 #?       (write-buffered Stderr Newline)
21588 #?       (flush Stderr)
21589       (string-equal? %esi %eax)  # => eax
21590       3d/compare-eax-and 0/imm32/false
21591       75/jump-if-!= $has-primitive-name?:end/disp8
21592 $has-primitive-name?:next-primitive:
21593       # curr = curr->next
21594       (lookup *(ecx+0x3c) *(ecx+0x40))  # Primitive-next Primitive-next => eax
21595       89/<- %ecx 0/r32/eax
21596       #
21597       e9/jump loop/disp32
21598     }
21599     # return null
21600     b8/copy-to-eax 0/imm32
21601 $has-primitive-name?:end:
21602     # . restore registers
21603     5e/pop-to-esi
21604     59/pop-to-ecx
21605     # . epilogue
21606     89/<- %esp 5/r32/ebp
21607     5d/pop-to-ebp
21608     c3/return
21609 
21610 check-mu-primitive:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21611     # . prologue
21612     55/push-ebp
21613     89/<- %ebp 4/r32/esp
21614     # . save registers
21615     50/push-eax
21616     51/push-ecx
21617     # var op/ecx: (addr array byte) = lookup(stmt->operation)
21618     8b/-> *(ebp+8) 0/r32/eax
21619     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
21620     89/<- %ecx 0/r32/eax
21621     # if (op == "copy") check-mu-copy-stmt
21622     {
21623       (string-equal? %ecx "copy")  # => eax
21624       3d/compare-eax-and 0/imm32/false
21625       74/jump-if-= break/disp8
21626       (check-mu-copy-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21627       e9/jump $check-mu-primitive:end/disp32
21628     }
21629     # if (op == "copy-to") check-mu-copy-to-stmt
21630     {
21631       (string-equal? %ecx "copy-to")  # => eax
21632       3d/compare-eax-and 0/imm32/false
21633       74/jump-if-= break/disp8
21634       (check-mu-copy-to-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21635       e9/jump $check-mu-primitive:end/disp32
21636     }
21637     # if (op == "copy-byte") check-mu-copy-byte-stmt
21638     {
21639       (string-equal? %ecx "copy-byte")  # => eax
21640       3d/compare-eax-and 0/imm32/false
21641       74/jump-if-= break/disp8
21642       (check-mu-copy-byte-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21643       e9/jump $check-mu-primitive:end/disp32
21644     }
21645     # if (op == "copy-byte-to") check-mu-copy-byte-to-stmt
21646     {
21647       (string-equal? %ecx "copy-byte-to")  # => eax
21648       3d/compare-eax-and 0/imm32/false
21649       74/jump-if-= break/disp8
21650       (check-mu-copy-byte-to-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21651       e9/jump $check-mu-primitive:end/disp32
21652     }
21653     # if (op == "compare") check-mu-compare-stmt
21654     {
21655       (string-equal? %ecx "compare")  # => eax
21656       3d/compare-eax-and 0/imm32/false
21657       74/jump-if-= break/disp8
21658       (check-mu-compare-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21659       e9/jump $check-mu-primitive:end/disp32
21660     }
21661     # if (op == "address") check-mu-address-stmt
21662     {
21663       (string-equal? %ecx "address")  # => eax
21664       3d/compare-eax-and 0/imm32/false
21665       74/jump-if-= break/disp8
21666       (check-mu-address-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21667       e9/jump $check-mu-primitive:end/disp32
21668     }
21669     # if (op == "return") check-mu-return-stmt
21670     {
21671       (string-equal? %ecx "return")  # => eax
21672       3d/compare-eax-and 0/imm32/false
21673       74/jump-if-= break/disp8
21674       (check-mu-return-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21675       e9/jump $check-mu-primitive:end/disp32
21676     }
21677     # if (op == "get") check-mu-get-stmt
21678     {
21679       (string-equal? %ecx "get")  # => eax
21680       3d/compare-eax-and 0/imm32/false
21681       74/jump-if-= break/disp8
21682       (check-mu-get-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21683       e9/jump $check-mu-primitive:end/disp32
21684     }
21685     # if (op == "index") check-mu-index-stmt
21686     {
21687       (string-equal? %ecx "index")  # => eax
21688       3d/compare-eax-and 0/imm32/false
21689       74/jump-if-= break/disp8
21690       (check-mu-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21691       e9/jump $check-mu-primitive:end/disp32
21692     }
21693     # if (op == "length") check-mu-length-stmt
21694     {
21695       (string-equal? %ecx "length")  # => eax
21696       3d/compare-eax-and 0/imm32/false
21697       74/jump-if-= break/disp8
21698       (check-mu-length-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21699       e9/jump $check-mu-primitive:end/disp32
21700     }
21701     # if (op == "compute-offset") check-mu-compute-offset-stmt
21702     {
21703       (string-equal? %ecx "compute-offset")  # => eax
21704       3d/compare-eax-and 0/imm32/false
21705       74/jump-if-= break/disp8
21706       (check-mu-compute-offset-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21707       e9/jump $check-mu-primitive:end/disp32
21708     }
21709     # if (op == "copy-object") check-mu-copy-object-stmt
21710     {
21711       (string-equal? %ecx "copy-object")  # => eax
21712       3d/compare-eax-and 0/imm32/false
21713       74/jump-if-= break/disp8
21714       (check-mu-copy-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21715       e9/jump $check-mu-primitive:end/disp32
21716     }
21717     # if (op == "clear-object") check-mu-clear-object-stmt
21718     {
21719       (string-equal? %ecx "clear-object")  # => eax
21720       3d/compare-eax-and 0/imm32/false
21721       74/jump-if-= break/disp8
21722       (check-mu-clear-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21723       e9/jump $check-mu-primitive:end/disp32
21724     }
21725     # if (op == "allocate") check-mu-allocate-stmt
21726     {
21727       (string-equal? %ecx "allocate")  # => eax
21728       3d/compare-eax-and 0/imm32/false
21729       74/jump-if-= break/disp8
21730       (check-mu-allocate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21731       e9/jump $check-mu-primitive:end/disp32
21732     }
21733     # if (op == "populate") check-mu-populate-stmt
21734     {
21735       (string-equal? %ecx "populate")  # => eax
21736       3d/compare-eax-and 0/imm32/false
21737       74/jump-if-= break/disp8
21738       (check-mu-populate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21739       e9/jump $check-mu-primitive:end/disp32
21740     }
21741     # if (op == "populate-stream") check-mu-populate-stream-stmt
21742     {
21743       (string-equal? %ecx "populate-stream")  # => eax
21744       3d/compare-eax-and 0/imm32/false
21745       74/jump-if-= break/disp8
21746       (check-mu-populate-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21747       e9/jump $check-mu-primitive:end/disp32
21748     }
21749     # if (op == "read-from-stream") check-mu-read-from-stream-stmt
21750     {
21751       (string-equal? %ecx "read-from-stream")  # => eax
21752       3d/compare-eax-and 0/imm32/false
21753       74/jump-if-= break/disp8
21754       (check-mu-read-from-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21755       e9/jump $check-mu-primitive:end/disp32
21756     }
21757     # if (op == "write-to-stream") check-mu-write-to-stream-stmt
21758     {
21759       (string-equal? %ecx "write-to-stream")  # => eax
21760       3d/compare-eax-and 0/imm32/false
21761       74/jump-if-= break/disp8
21762       (check-mu-write-to-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21763       e9/jump $check-mu-primitive:end/disp32
21764     }
21765     # if (op == "convert") check-mu-convert-stmt
21766     {
21767       (string-equal? %ecx "convert")  # => eax
21768       3d/compare-eax-and 0/imm32/false
21769       74/jump-if-= break/disp8
21770       (check-mu-convert-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21771       e9/jump $check-mu-primitive:end/disp32
21772     }
21773     # otherwise check-numberlike-stmt
21774     (check-mu-numberlike-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21775 $check-mu-primitive:end:
21776     # . restore registers
21777     59/pop-to-ecx
21778     58/pop-to-eax
21779     # . epilogue
21780     89/<- %esp 5/r32/ebp
21781     5d/pop-to-ebp
21782     c3/return
21783 
21784 # by default, Mu primitives should only operate on 'number-like' types
21785 check-mu-numberlike-primitive:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21786     # . prologue
21787     55/push-ebp
21788     89/<- %ebp 4/r32/esp
21789     # . save registers
21790     50/push-eax
21791     51/push-ecx
21792     56/push-esi
21793     # esi = stmt
21794     8b/-> *(ebp+8) 6/r32/esi
21795     # var gas/ecx: int = 2
21796     b9/copy-to-ecx 2/imm32
21797     # - check at most 1 output
21798     # var output/eax: (addr stmt-var) = stmt->outputs
21799     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
21800     {
21801       3d/compare-eax-and 0/imm32
21802       74/jump-if-= break/disp8
21803 $check-mu-numberlike-primitive:output:
21804       (check-mu-numberlike-output %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21805       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
21806       3d/compare-eax-and 0/imm32
21807       0f 85/jump-if-!= $check-mu-numberlike-primitive:error-too-many-outputs/disp32
21808       # check output is in a register
21809       # --gas
21810       49/decrement-ecx
21811     }
21812     # - check first inout
21813     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21814     {
21815       3d/compare-eax-and 0/imm32
21816       0f 84/jump-if-= $check-mu-numberlike-primitive:end/disp32
21817 $check-mu-numberlike-primitive:first-inout:
21818       (check-mu-numberlike-arg %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21819       # --gas
21820       49/decrement-ecx
21821     }
21822     # - check second inout
21823     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
21824     {
21825       3d/compare-eax-and 0/imm32
21826       74/jump-if-= $check-mu-numberlike-primitive:end/disp8
21827 $check-mu-numberlike-primitive:second-inout:
21828       # is a second inout allowed?
21829       81 7/subop/compare %ecx 0/imm32
21830       0f 84/jump-if-= $check-mu-numberlike-primitive:error-too-many-inouts/disp32
21831 $check-mu-numberlike-primitive:second-inout-permitted:
21832       (check-mu-numberlike-arg %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21833     }
21834 $check-mu-numberlike-primitive:third-inout:
21835     # if there's a third arg, raise an error
21836     81 7/subop/compare *(eax+8) 0/imm32  # Stmt-var-next
21837     0f 85/jump-if-!= $check-mu-numberlike-primitive:error-too-many-inouts/disp32
21838 $check-mu-numberlike-primitive:end:
21839     # . restore registers
21840     5e/pop-to-esi
21841     59/pop-to-ecx
21842     58/pop-to-eax
21843     # . epilogue
21844     89/<- %esp 5/r32/ebp
21845     5d/pop-to-ebp
21846     c3/return
21847 
21848 $check-mu-numberlike-primitive:error-too-many-inouts:
21849     (write-buffered *(ebp+0x10) "fn ")
21850     8b/-> *(ebp+0xc) 0/r32/eax
21851     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21852     (write-buffered *(ebp+0x10) %eax)
21853     (write-buffered *(ebp+0x10) ": stmt ")
21854     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
21855     (write-buffered *(ebp+0x10) %eax)
21856     (write-buffered *(ebp+0x10) ": too many inouts; most primitives support at most two arguments, across inouts and outputs\n")
21857     (flush *(ebp+0x10))
21858     (stop *(ebp+0x14) 1)
21859     # never gets here
21860 
21861 $check-mu-numberlike-primitive:error-too-many-outputs:
21862     (write-buffered *(ebp+0x10) "fn ")
21863     8b/-> *(ebp+0xc) 0/r32/eax
21864     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21865     (write-buffered *(ebp+0x10) %eax)
21866     (write-buffered *(ebp+0x10) ": stmt ")
21867     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
21868     (write-buffered *(ebp+0x10) %eax)
21869     (write-buffered *(ebp+0x10) ": too many outputs; most primitives support at most one output\n")
21870     (flush *(ebp+0x10))
21871     (stop *(ebp+0x14) 1)
21872     # never gets here
21873 
21874 check-mu-numberlike-arg:  # v: (addr stmt-var), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21875     # . prologue
21876     55/push-ebp
21877     89/<- %ebp 4/r32/esp
21878     # . save registers
21879     50/push-eax
21880     56/push-esi
21881     # var t/esi: (addr type-tree) = lookup(v->value->type)
21882     8b/-> *(ebp+8) 0/r32/eax
21883     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21884     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21885     89/<- %esi 0/r32/eax
21886 $check-mu-numberlike-arg:check-literal:
21887     # if t is an int, return
21888     (simple-mu-type? %esi 0)  # literal => eax
21889     3d/compare-eax-and 0/imm32/false
21890     0f 85/jump-if-!= $check-mu-numberlike-arg:end/disp32
21891 $check-mu-numberlike-arg:check-addr:
21892     # if t is an addr and v is dereferenced, return whether t->payload is an addr
21893     {
21894       (mu-addr-type? %esi)  # => eax
21895       3d/compare-eax-and 0/imm32/false
21896       74/jump-if-= break/disp8
21897       8b/-> *(ebp+8) 0/r32/eax
21898       8b/-> *(eax+0x10) 0/r32/eax  # Stmt-var-is-deref
21899       3d/compare-eax-and 0/imm32/false
21900       {
21901         74/jump-if-= break/disp8
21902         (lookup *(esi+0xc) *(esi+0x10))  # Type-tree-right Type-tree-right => eax
21903         # if t->right is null, t = t->left
21904         81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
21905         {
21906           75/jump-if-!= break/disp8
21907           (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21908         }
21909         (mu-addr-type? %eax)  # => eax
21910         3d/compare-eax-and 0/imm32/false
21911         74/jump-if-= $check-mu-numberlike-arg:end/disp8
21912       }
21913     }
21914 $check-mu-numberlike-arg:output-checks:
21915     (check-mu-numberlike-output *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18))
21916 $check-mu-numberlike-arg:end:
21917     # . restore registers
21918     5e/pop-to-esi
21919     58/pop-to-eax
21920     # . epilogue
21921     89/<- %esp 5/r32/ebp
21922     5d/pop-to-ebp
21923     c3/return
21924 
21925 check-mu-numberlike-output:  # v: (addr stmt-var), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21926     # . prologue
21927     55/push-ebp
21928     89/<- %ebp 4/r32/esp
21929     # . save registers
21930     50/push-eax
21931     #
21932     (mu-numberlike-output-var? *(ebp+8))  # => eax
21933     3d/compare-eax-and 0/imm32/false
21934     0f 84/jump-if-= $check-mu-numberlike-output:fail/disp32
21935 $check-mu-numberlike-output:end:
21936     # . restore registers
21937     58/pop-to-eax
21938     # . epilogue
21939     89/<- %esp 5/r32/ebp
21940     5d/pop-to-ebp
21941     c3/return
21942 
21943 $check-mu-numberlike-output:fail:
21944     # otherwise raise an error
21945     (write-buffered *(ebp+0x14) "fn ")
21946     8b/-> *(ebp+0x10) 0/r32/eax
21947     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21948     (write-buffered *(ebp+0x14) %eax)
21949     (write-buffered *(ebp+0x14) ": stmt ")
21950     8b/-> *(ebp+0xc) 0/r32/eax
21951     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
21952     (write-buffered *(ebp+0x14) %eax)
21953     (write-buffered *(ebp+0x14) ": '")
21954     8b/-> *(ebp+8) 0/r32/eax
21955     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21956     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21957     (write-buffered *(ebp+0x14) %eax)
21958     (write-buffered *(ebp+0x14) "' must be a non-addr non-offset scalar\n")
21959     (flush *(ebp+0x14))
21960     (stop *(ebp+0x18) 1)
21961     # never gets here
21962 
21963 mu-numberlike-output-var?:  # v: (addr stmt-var) -> result/eax: boolean
21964     # . prologue
21965     55/push-ebp
21966     89/<- %ebp 4/r32/esp
21967     #
21968     8b/-> *(ebp+8) 0/r32/eax
21969     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21970     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21971     (mu-numberlike-output? %eax)  # => eax
21972 $mu-numberlike-output-var?:end:
21973     # . epilogue
21974     89/<- %esp 5/r32/ebp
21975     5d/pop-to-ebp
21976     c3/return
21977 
21978 mu-numberlike-output?:  # v: (addr type-tree) -> result/eax: boolean
21979     # . prologue
21980     55/push-ebp
21981     89/<- %ebp 4/r32/esp
21982     # . save registers
21983     56/push-esi
21984     # var t/esi: (addr type-tree) = lookup(v->value->type)
21985     8b/-> *(ebp+8) 6/r32/esi
21986 $mu-numberlike-output?:check-int:
21987     # if t is an int, return
21988     (simple-mu-type? %esi 1)  # int => eax
21989     3d/compare-eax-and 0/imm32/false
21990     0f 85/jump-if-!= $mu-numberlike-output?:return-true/disp32
21991 $mu-numberlike-output?:check-float:
21992     # if t is a float, return
21993     (simple-mu-type? %esi 0xf)  # float => eax
21994     3d/compare-eax-and 0/imm32/false
21995     75/jump-if-!= $mu-numberlike-output?:return-true/disp8
21996 $mu-numberlike-output?:check-boolean:
21997     # if t is a boolean, return
21998     (simple-mu-type? %esi 5)  # boolean => eax
21999     3d/compare-eax-and 0/imm32/false
22000     75/jump-if-!= $mu-numberlike-output?:return-true/disp8
22001 $mu-numberlike-output?:check-byte:
22002     # if t is a byte, return
22003     (simple-mu-type? %esi 8)  # byte => eax
22004     3d/compare-eax-and 0/imm32/false
22005     75/jump-if-!= $mu-numberlike-output?:return-true/disp8
22006 $mu-numberlike-output?:check-code-point:
22007     # if t is a code-point, return
22008     (simple-mu-type? %esi 0xd)  # code-point => eax
22009     3d/compare-eax-and 0/imm32/false
22010     75/jump-if-!= $mu-numberlike-output?:return-true/disp8
22011 $mu-numberlike-output?:check-grapheme:
22012     # if t is a grapheme, return
22013     (simple-mu-type? %esi 0xe)  # grapheme => eax
22014     3d/compare-eax-and 0/imm32/false
22015     75/jump-if-!= $mu-numberlike-output?:return-true/disp8
22016 $mu-numberlike-output?:return-false:
22017     b8/copy-to-eax 0/imm32/false
22018     eb/jump $mu-numberlike-output?:end/disp8
22019 $mu-numberlike-output?:return-true:
22020     b8/copy-to-eax 1/imm32/true
22021 $mu-numberlike-output?:end:
22022     # . restore registers
22023     5e/pop-to-esi
22024     # . epilogue
22025     89/<- %esp 5/r32/ebp
22026     5d/pop-to-ebp
22027     c3/return
22028 
22029 check-mu-copy-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22030     # . prologue
22031     55/push-ebp
22032     89/<- %ebp 4/r32/esp
22033     # . save registers
22034     50/push-eax
22035     51/push-ecx
22036     52/push-edx
22037     56/push-esi
22038     57/push-edi
22039     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
22040     81 5/subop/subtract %esp 0x60/imm32
22041     68/push 0x60/imm32/size
22042     68/push 0/imm32/read
22043     68/push 0/imm32/write
22044     89/<- %edx 4/r32/esp
22045 $check-mu-copy-stmt:get-output:
22046     # esi = stmt
22047     8b/-> *(ebp+8) 6/r32/esi
22048     # var output/edi: (addr stmt-var) = stmt->outputs
22049     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22050     89/<- %edi 0/r32/eax
22051     # zero outputs
22052     3d/compare-eax-and 0/imm32
22053     0f 84/jump-if-= $check-mu-copy-stmt:error-no-output/disp32
22054     # > 1 output
22055     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
22056     3d/compare-eax-and 0/imm32
22057     0f 85/jump-if-!= $check-mu-copy-stmt:error-too-many-outputs/disp32
22058 $check-mu-copy-stmt:get-inout:
22059     # var inout/esi: (addr stmt-var) = stmt->inouts
22060     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22061     89/<- %esi 0/r32/eax
22062     # zero inouts
22063     3d/compare-eax-and 0/imm32
22064     0f 84/jump-if-= $check-mu-copy-stmt:error-no-inout/disp32
22065     # > 1 inout
22066     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
22067     3d/compare-eax-and 0/imm32
22068     0f 85/jump-if-!= $check-mu-copy-stmt:error-too-many-inouts/disp32
22069 $check-mu-copy-stmt:types:
22070     # if inout is not a scalar, abort
22071     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22072     (size-of %eax)  # => eax
22073     3d/compare-eax-and 4/imm32
22074     0f 8f/jump-if-> $check-mu-copy-stmt:error-inout-too-large/disp32
22075     # var inout-type/ecx: (addr type-tree) = inout->value->type
22076     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22077     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22078     89/<- %ecx 0/r32/eax
22079     # if (inout->is-deref?) inout-type = inout-type->payload
22080     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
22081     3d/compare-eax-and 0/imm32/false
22082     {
22083       74/jump-if-= break/disp8
22084       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
22085       # if inout-type->right is null, t = inout-type->left
22086       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
22087       {
22088         75/jump-if-!= break/disp8
22089         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22090       }
22091       89/<- %ecx 0/r32/eax
22092     }
22093     # if output not in register, abort
22094     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22095     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
22096     3d/compare-eax-and 0/imm32
22097     0f 84/jump-if-= $check-mu-copy-stmt:error-output-not-in-register/disp32
22098     # var output-type/eax: (addr type-tree) = output->value->type
22099     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22100     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22101     # if (inout-type == output-type) return
22102     (type-match? %eax %ecx %edx)  # => eax
22103     3d/compare-eax-and 0/imm32
22104     0f 85/jump-if-!= $check-mu-copy-stmt:end/disp32
22105     # if output is an addr and inout is 0, return
22106     {
22107       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22108       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22109       (mu-addr-type? %eax)  # => eax
22110       3d/compare-eax-and 0/imm32/false
22111       74/jump-if-= break/disp8
22112       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22113       (lookup *eax *(eax+4))  # Var-name Var-name => eax
22114       (string-equal? %eax "0")  # => eax
22115       3d/compare-eax-and 0/imm32/false
22116       74/jump-if-= break/disp8
22117       e9/jump $check-mu-copy-stmt:end/disp32
22118     }
22119     # if output is an offset and inout is 0, return
22120     {
22121       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22122       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22123       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
22124       75/jump-if-!= break/disp8
22125       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22126       (simple-mu-type? %eax 7)  # offset => eax
22127       3d/compare-eax-and 0/imm32/false
22128       74/jump-if-= break/disp8
22129       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22130       (lookup *eax *(eax+4))  # Var-name Var-name => eax
22131       (string-equal? %eax "0")  # => eax
22132       3d/compare-eax-and 0/imm32/false
22133       74/jump-if-= break/disp8
22134       e9/jump $check-mu-copy-stmt:end/disp32
22135     }
22136     # if output is a byte, abort if inout is not a literal. Otherwise return.
22137     {
22138       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22139       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22140       (simple-mu-type? %eax 8)  # byte => eax
22141       3d/compare-eax-and 0/imm32/false
22142       74/jump-if-= break/disp8
22143       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22144       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22145       (simple-mu-type? %eax 0)  # literal => eax
22146       3d/compare-eax-and 0/imm32/false
22147       0f 84/jump-if-= $check-mu-copy-stmt:error-non-literal-to-byte/disp32
22148       eb/jump $check-mu-copy-stmt:end/disp8
22149     }
22150     # if output is not number-like, abort
22151     (check-mu-numberlike-output %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
22152 $check-mu-copy-stmt:end:
22153     # . reclaim locals
22154     81 0/subop/add %esp 0x6c/imm32
22155     # . restore registers
22156     5f/pop-to-edi
22157     5e/pop-to-esi
22158     5a/pop-to-edx
22159     59/pop-to-ecx
22160     58/pop-to-eax
22161     # . epilogue
22162     89/<- %esp 5/r32/ebp
22163     5d/pop-to-ebp
22164     c3/return
22165 
22166 $check-mu-copy-stmt:error-no-inout:
22167     (write-buffered *(ebp+0x10) "fn ")
22168     8b/-> *(ebp+0xc) 0/r32/eax
22169     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22170     (write-buffered *(ebp+0x10) %eax)
22171     (write-buffered *(ebp+0x10) ": stmt 'copy' expects an inout\n")
22172     (flush *(ebp+0x10))
22173     (stop *(ebp+0x14) 1)
22174     # never gets here
22175 
22176 $check-mu-copy-stmt:error-too-many-inouts:
22177     (write-buffered *(ebp+0x10) "fn ")
22178     8b/-> *(ebp+0xc) 0/r32/eax
22179     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22180     (write-buffered *(ebp+0x10) %eax)
22181     (write-buffered *(ebp+0x10) ": stmt 'copy' must have just one inout\n")
22182     (flush *(ebp+0x10))
22183     (stop *(ebp+0x14) 1)
22184     # never gets here
22185 
22186 $check-mu-copy-stmt:error-no-output:
22187     (write-buffered *(ebp+0x10) "fn ")
22188     8b/-> *(ebp+0xc) 0/r32/eax
22189     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22190     (write-buffered *(ebp+0x10) %eax)
22191     (write-buffered *(ebp+0x10) ": stmt 'copy' expects an output\n")
22192     (flush *(ebp+0x10))
22193     (stop *(ebp+0x14) 1)
22194     # never gets here
22195 
22196 $check-mu-copy-stmt:error-output-not-in-register:
22197     (write-buffered *(ebp+0x10) "fn ")
22198     8b/-> *(ebp+0xc) 0/r32/eax
22199     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22200     (write-buffered *(ebp+0x10) %eax)
22201     (write-buffered *(ebp+0x10) ": stmt copy: output '")
22202     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22203     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22204     (write-buffered *(ebp+0x10) %eax)
22205     (write-buffered *(ebp+0x10) "' not in a register\n")
22206     (flush *(ebp+0x10))
22207     (stop *(ebp+0x14) 1)
22208     # never gets here
22209 
22210 $check-mu-copy-stmt:error-too-many-outputs:
22211     (write-buffered *(ebp+0x10) "fn ")
22212     8b/-> *(ebp+0xc) 0/r32/eax
22213     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22214     (write-buffered *(ebp+0x10) %eax)
22215     (write-buffered *(ebp+0x10) ": stmt 'copy' must have just one output\n")
22216     (flush *(ebp+0x10))
22217     (stop *(ebp+0x14) 1)
22218     # never gets here
22219 
22220 $check-mu-copy-stmt:error-inout-too-large:
22221     (write-buffered *(ebp+0x10) "fn ")
22222     8b/-> *(ebp+0xc) 0/r32/eax
22223     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22224     (write-buffered *(ebp+0x10) %eax)
22225     (write-buffered *(ebp+0x10) ": stmt copy: '")
22226     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22227     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22228     (write-buffered *(ebp+0x10) %eax)
22229     (write-buffered *(ebp+0x10) "' is too large to fit in a register\n")
22230     (flush *(ebp+0x10))
22231     (stop *(ebp+0x14) 1)
22232     # never gets here
22233 
22234 $check-mu-copy-stmt:error-non-literal-to-byte:
22235     (write-buffered *(ebp+0x10) "fn ")
22236     8b/-> *(ebp+0xc) 0/r32/eax
22237     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22238     (write-buffered *(ebp+0x10) %eax)
22239     (write-buffered *(ebp+0x10) ": stmt copy: cannot copy non-literal to '")
22240     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22241     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22242     (write-buffered *(ebp+0x10) %eax)
22243     (write-buffered *(ebp+0x10) "' of type byte; use copy-byte\n")
22244     (flush *(ebp+0x10))
22245     (stop *(ebp+0x14) 1)
22246     # never gets here
22247 
22248 check-mu-copy-to-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22249     # . prologue
22250     55/push-ebp
22251     89/<- %ebp 4/r32/esp
22252     # . save registers
22253     50/push-eax
22254     51/push-ecx
22255     52/push-edx
22256     53/push-ebx
22257     56/push-esi
22258     57/push-edi
22259     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
22260     81 5/subop/subtract %esp 0x60/imm32
22261     68/push 0x60/imm32/size
22262     68/push 0/imm32/read
22263     68/push 0/imm32/write
22264     89/<- %edx 4/r32/esp
22265     # esi = stmt
22266     8b/-> *(ebp+8) 6/r32/esi
22267 $check-mu-copy-to-stmt:check-for-output:
22268     # if stmt->outputs abort
22269     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22270     3d/compare-eax-and 0/imm32
22271     0f 85/jump-if-!= $check-mu-copy-to-stmt:error-too-many-outputs/disp32
22272 $check-mu-copy-to-stmt:get-dest:
22273     # var dest/edi: (addr stmt-var) = stmt->inouts
22274     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22275     89/<- %edi 0/r32/eax
22276     # zero inouts
22277     3d/compare-eax-and 0/imm32
22278     0f 84/jump-if-= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32
22279 $check-mu-copy-to-stmt:get-src:
22280     # var src/esi: (addr stmt-var) = dest->next
22281     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
22282     89/<- %esi 0/r32/eax
22283     # 1 inout
22284     3d/compare-eax-and 0/imm32
22285     0f 84/jump-if-= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32
22286     # > 2 inouts
22287     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
22288     3d/compare-eax-and 0/imm32
22289     0f 85/jump-if-!= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32
22290 $check-mu-copy-to-stmt:types:
22291     # if src is not a scalar, abort
22292     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22293     (size-of %eax)  # => eax
22294     3d/compare-eax-and 4/imm32
22295     0f 8f/jump-if-> $check-mu-copy-to-stmt:error-src-too-large/disp32
22296     # var src-type/ecx: (addr type-tree) = src->value->type
22297     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22298     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22299     89/<- %ecx 0/r32/eax
22300     # if src not in register or literal, abort
22301     # (we can't use stack-offset because it hasn't been computed yet)
22302     {
22303       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22304       (lookup *(eax+0x8) *(eax+0xc))  # Var-type Var-type => eax
22305       (simple-mu-type? %eax 0)  # => eax
22306       3d/compare-eax-and 0/imm32
22307       75/jump-if-!= break/disp8
22308       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22309       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
22310       3d/compare-eax-and 0/imm32
22311       75/jump-if-!= break/disp8
22312       e9/jump $check-mu-copy-to-stmt:error-src-not-literal-or-in-register/disp32
22313     }
22314     # var dest-type/ebx: (addr type-tree) = dest->value->type
22315     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22316     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22317     89/<- %ebx 0/r32/eax
22318     # if (dest->is-deref?) dest-type = dest-type->payload
22319 $check-mu-copy-to-stmt:check-dest-deref:
22320     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
22321     3d/compare-eax-and 0/imm32/false
22322     {
22323       74/jump-if-= break/disp8
22324       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22325 $check-mu-copy-to-stmt:dest-is-deref:
22326       # if dest-type->right is null, dest-type = dest-type->left
22327       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
22328       {
22329         75/jump-if-!= break/disp8
22330 $check-mu-copy-to-stmt:dest-is-deref2:
22331         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22332       }
22333       89/<- %ebx 0/r32/eax
22334     }
22335     # if dest is a byte and src is not a literal, abort
22336     {
22337 $check-mu-copy-to-stmt:final-check-byte:
22338       (simple-mu-type? %ebx 8)  # byte => eax
22339       3d/compare-eax-and 0/imm32/false
22340       74/jump-if-= break/disp8
22341       (simple-mu-type? %ecx 0)  # literal => eax
22342       3d/compare-eax-and 0/imm32/false
22343       0f 84/jump-if-= $check-mu-copy-to-stmt:error-non-literal-to-byte/disp32
22344     }
22345     # if (src-type == dest-type) return
22346     (type-match? %ebx %ecx %edx)  # => eax
22347     3d/compare-eax-and 0/imm32
22348     0f 85/jump-if-!= $check-mu-copy-to-stmt:end/disp32
22349     # if dest is an addr and src is 0, return
22350     {
22351 $check-mu-copy-to-stmt:final-check-addr:
22352       (mu-addr-type? %ebx)  # => eax
22353       3d/compare-eax-and 0/imm32/false
22354       74/jump-if-= break/disp8
22355       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22356       (lookup *eax *(eax+4))  # Var-name Var-name => eax
22357       (string-equal? %eax "0")  # => eax
22358       3d/compare-eax-and 0/imm32/false
22359       74/jump-if-= break/disp8
22360       e9/jump $check-mu-copy-to-stmt:end/disp32
22361     }
22362     # if dest is an offset and src is 0, return
22363     {
22364 $check-mu-copy-to-stmt:final-check-offset:
22365       81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
22366       75/jump-if-!= break/disp8
22367       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22368       (simple-mu-type? %eax 7)  # offset => eax
22369       3d/compare-eax-and 0/imm32/false
22370       74/jump-if-= break/disp8
22371       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22372       (lookup *eax *(eax+4))  # Var-name Var-name => eax
22373       (string-equal? %eax "0")  # => eax
22374       3d/compare-eax-and 0/imm32/false
22375       74/jump-if-= break/disp8
22376       e9/jump $check-mu-copy-to-stmt:end/disp32
22377     }
22378     # if dest is not number-like, abort
22379     (check-mu-numberlike-arg %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
22380 $check-mu-copy-to-stmt:end:
22381     # . reclaim locals
22382     81 0/subop/add %esp 0x6c/imm32
22383     # . restore registers
22384     5f/pop-to-edi
22385     5e/pop-to-esi
22386     5b/pop-to-ebx
22387     5a/pop-to-edx
22388     59/pop-to-ecx
22389     58/pop-to-eax
22390     # . epilogue
22391     89/<- %esp 5/r32/ebp
22392     5d/pop-to-ebp
22393     c3/return
22394 
22395 $check-mu-copy-to-stmt:error-incorrect-inouts:
22396     (write-buffered *(ebp+0x10) "fn ")
22397     8b/-> *(ebp+0xc) 0/r32/eax
22398     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22399     (write-buffered *(ebp+0x10) %eax)
22400     (write-buffered *(ebp+0x10) ": stmt 'copy-to' must have two inouts\n")
22401     (flush *(ebp+0x10))
22402     (stop *(ebp+0x14) 1)
22403     # never gets here
22404 
22405 $check-mu-copy-to-stmt:error-too-many-outputs:
22406     (write-buffered *(ebp+0x10) "fn ")
22407     8b/-> *(ebp+0xc) 0/r32/eax
22408     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22409     (write-buffered *(ebp+0x10) %eax)
22410     (write-buffered *(ebp+0x10) ": stmt 'copy-to' must not have any outputs\n")
22411     (flush *(ebp+0x10))
22412     (stop *(ebp+0x14) 1)
22413     # never gets here
22414 
22415 $check-mu-copy-to-stmt:error-src-not-literal-or-in-register:
22416     (write-buffered *(ebp+0x10) "fn ")
22417     8b/-> *(ebp+0xc) 0/r32/eax
22418     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22419     (write-buffered *(ebp+0x10) %eax)
22420     (write-buffered *(ebp+0x10) ": stmt copy-to: source (second inout) is in memory\n")
22421     (flush *(ebp+0x10))
22422     (stop *(ebp+0x14) 1)
22423     # never gets here
22424 
22425 $check-mu-copy-to-stmt:error-src-too-large:
22426     (write-buffered *(ebp+0x10) "fn ")
22427     8b/-> *(ebp+0xc) 0/r32/eax
22428     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22429     (write-buffered *(ebp+0x10) %eax)
22430     (write-buffered *(ebp+0x10) ": stmt copy-to: '")
22431     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22432     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22433     (write-buffered *(ebp+0x10) %eax)
22434     (write-buffered *(ebp+0x10) "' is too large to copy\n")
22435     (flush *(ebp+0x10))
22436     (stop *(ebp+0x14) 1)
22437     # never gets here
22438 
22439 $check-mu-copy-to-stmt:error-non-literal-to-byte:
22440     (write-buffered *(ebp+0x10) "fn ")
22441     8b/-> *(ebp+0xc) 0/r32/eax
22442     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22443     (write-buffered *(ebp+0x10) %eax)
22444     (write-buffered *(ebp+0x10) ": stmt copy-to: cannot copy non-literal to type byte; use copy-byte-to\n")
22445     (flush *(ebp+0x10))
22446     (stop *(ebp+0x14) 1)
22447     # never gets here
22448 
22449 check-mu-copy-byte-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22450     # . prologue
22451     55/push-ebp
22452     89/<- %ebp 4/r32/esp
22453     # . save registers
22454     50/push-eax
22455     51/push-ecx
22456     52/push-edx
22457     56/push-esi
22458     57/push-edi
22459     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
22460     81 5/subop/subtract %esp 0x60/imm32
22461     68/push 0x60/imm32/size
22462     68/push 0/imm32/read
22463     68/push 0/imm32/write
22464     89/<- %edx 4/r32/esp
22465 $check-mu-copy-byte-stmt:get-output:
22466     # esi = stmt
22467     8b/-> *(ebp+8) 6/r32/esi
22468     # var output/edi: (addr stmt-var) = stmt->outputs
22469     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22470     89/<- %edi 0/r32/eax
22471     # zero outputs
22472     3d/compare-eax-and 0/imm32
22473     0f 84/jump-if-= $check-mu-copy-byte-stmt:error-no-output/disp32
22474     # > 1 output
22475     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
22476     3d/compare-eax-and 0/imm32
22477     0f 85/jump-if-!= $check-mu-copy-byte-stmt:error-too-many-outputs/disp32
22478 $check-mu-copy-byte-stmt:get-inout:
22479     # var inout/esi: (addr stmt-var) = stmt->inouts
22480     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22481     89/<- %esi 0/r32/eax
22482     # zero inouts
22483     3d/compare-eax-and 0/imm32
22484     0f 84/jump-if-= $check-mu-copy-byte-stmt:error-no-inout/disp32
22485     # > 1 inout
22486     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
22487     3d/compare-eax-and 0/imm32
22488     0f 85/jump-if-!= $check-mu-copy-byte-stmt:error-too-many-inouts/disp32
22489 $check-mu-copy-byte-stmt:types:
22490     # if inout is not a scalar, abort
22491     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22492     (size-of %eax)  # => eax
22493     3d/compare-eax-and 4/imm32
22494     0f 8f/jump-if-> $check-mu-copy-byte-stmt:error-inout-too-large/disp32
22495     # var inout-type/ecx: (addr type-tree) = inout->value->type
22496     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22497     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22498     89/<- %ecx 0/r32/eax
22499 $check-mu-copy-byte-stmt:check-inout-deref:
22500     # if (inout->is-deref?) inout-type = inout-type->payload
22501     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
22502     3d/compare-eax-and 0/imm32/false
22503     {
22504       74/jump-if-= break/disp8
22505 $check-mu-copy-byte-stmt:inout-is-deref:
22506       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
22507       # if inout-type->right is null, t = inout-type->left
22508       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
22509       {
22510         75/jump-if-!= break/disp8
22511 $check-mu-copy-byte-stmt:inout-is-deref2:
22512         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22513       }
22514       89/<- %ecx 0/r32/eax
22515     }
22516     # if output not in register, abort
22517     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22518     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
22519     3d/compare-eax-and 0/imm32
22520     0f 84/jump-if-= $check-mu-copy-byte-stmt:error-output-not-in-register/disp32
22521     # var output-type/eax: (addr type-tree) = output->value->type
22522     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22523     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22524     # if output is not of type byte, abort
22525     (simple-mu-type? %eax 8)  # byte => eax
22526     3d/compare-eax-and 0/imm32
22527     0f 84/jump-if-= $check-mu-copy-byte-stmt:error-invalid-output-type/disp32
22528 $check-mu-copy-byte-stmt:end:
22529     # . reclaim locals
22530     81 0/subop/add %esp 0x6c/imm32
22531     # . restore registers
22532     5f/pop-to-edi
22533     5e/pop-to-esi
22534     5a/pop-to-edx
22535     59/pop-to-ecx
22536     58/pop-to-eax
22537     # . epilogue
22538     89/<- %esp 5/r32/ebp
22539     5d/pop-to-ebp
22540     c3/return
22541 
22542 $check-mu-copy-byte-stmt:error-no-inout:
22543     (write-buffered *(ebp+0x10) "fn ")
22544     8b/-> *(ebp+0xc) 0/r32/eax
22545     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22546     (write-buffered *(ebp+0x10) %eax)
22547     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' expects an inout\n")
22548     (flush *(ebp+0x10))
22549     (stop *(ebp+0x14) 1)
22550     # never gets here
22551 
22552 $check-mu-copy-byte-stmt:error-too-many-inouts:
22553     (write-buffered *(ebp+0x10) "fn ")
22554     8b/-> *(ebp+0xc) 0/r32/eax
22555     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22556     (write-buffered *(ebp+0x10) %eax)
22557     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' must have just one inout\n")
22558     (flush *(ebp+0x10))
22559     (stop *(ebp+0x14) 1)
22560     # never gets here
22561 
22562 $check-mu-copy-byte-stmt:error-no-output:
22563     (write-buffered *(ebp+0x10) "fn ")
22564     8b/-> *(ebp+0xc) 0/r32/eax
22565     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22566     (write-buffered *(ebp+0x10) %eax)
22567     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' expects an output\n")
22568     (flush *(ebp+0x10))
22569     (stop *(ebp+0x14) 1)
22570     # never gets here
22571 
22572 $check-mu-copy-byte-stmt:error-output-not-in-register:
22573     (write-buffered *(ebp+0x10) "fn ")
22574     8b/-> *(ebp+0xc) 0/r32/eax
22575     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22576     (write-buffered *(ebp+0x10) %eax)
22577     (write-buffered *(ebp+0x10) ": stmt copy-byte: output '")
22578     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22579     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22580     (write-buffered *(ebp+0x10) %eax)
22581     (write-buffered *(ebp+0x10) "' not in a register\n")
22582     (flush *(ebp+0x10))
22583     (stop *(ebp+0x14) 1)
22584     # never gets here
22585 
22586 $check-mu-copy-byte-stmt:error-too-many-outputs:
22587     (write-buffered *(ebp+0x10) "fn ")
22588     8b/-> *(ebp+0xc) 0/r32/eax
22589     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22590     (write-buffered *(ebp+0x10) %eax)
22591     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' must have just one output\n")
22592     (flush *(ebp+0x10))
22593     (stop *(ebp+0x14) 1)
22594     # never gets here
22595 
22596 $check-mu-copy-byte-stmt:error-invalid-output-type:
22597     (write-buffered *(ebp+0x10) "fn ")
22598     8b/-> *(ebp+0xc) 0/r32/eax
22599     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22600     (write-buffered *(ebp+0x10) %eax)
22601     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' must write to output of type byte\n")
22602     (flush *(ebp+0x10))
22603     (stop *(ebp+0x14) 1)
22604     # never gets here
22605 
22606 $check-mu-copy-byte-stmt:error-inout-too-large:
22607     (write-buffered *(ebp+0x10) "fn ")
22608     8b/-> *(ebp+0xc) 0/r32/eax
22609     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22610     (write-buffered *(ebp+0x10) %eax)
22611     (write-buffered *(ebp+0x10) ": stmt copy-byte: '")
22612     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22613     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22614     (write-buffered *(ebp+0x10) %eax)
22615     (write-buffered *(ebp+0x10) "' is too large to fit in a register\n")
22616     (flush *(ebp+0x10))
22617     (stop *(ebp+0x14) 1)
22618     # never gets here
22619 
22620 check-mu-copy-byte-to-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22621     # . prologue
22622     55/push-ebp
22623     89/<- %ebp 4/r32/esp
22624     # . save registers
22625     50/push-eax
22626     52/push-edx
22627     53/push-ebx
22628     56/push-esi
22629     57/push-edi
22630     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
22631     81 5/subop/subtract %esp 0x60/imm32
22632     68/push 0x60/imm32/size
22633     68/push 0/imm32/read
22634     68/push 0/imm32/write
22635     89/<- %edx 4/r32/esp
22636     # esi = stmt
22637     8b/-> *(ebp+8) 6/r32/esi
22638 $check-mu-copy-byte-to-stmt:check-for-output:
22639     # if stmt->outputs abort
22640     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22641     3d/compare-eax-and 0/imm32
22642     0f 85/jump-if-!= $check-mu-copy-byte-to-stmt:error-too-many-outputs/disp32
22643 $check-mu-copy-byte-to-stmt:get-dest:
22644     # var dest/edi: (addr stmt-var) = stmt->inouts
22645     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22646     89/<- %edi 0/r32/eax
22647     # zero inouts
22648     3d/compare-eax-and 0/imm32
22649     0f 84/jump-if-= $check-mu-copy-byte-to-stmt:error-incorrect-inouts/disp32
22650 $check-mu-copy-byte-to-stmt:get-src:
22651     # var src/esi: (addr stmt-var) = dest->next
22652     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
22653     89/<- %esi 0/r32/eax
22654     # 1 inout
22655     3d/compare-eax-and 0/imm32
22656     0f 84/jump-if-= $check-mu-copy-byte-to-stmt:error-incorrect-inouts/disp32
22657     # > 2 inouts
22658     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
22659     3d/compare-eax-and 0/imm32
22660     0f 85/jump-if-!= $check-mu-copy-byte-to-stmt:error-incorrect-inouts/disp32
22661 $check-mu-copy-byte-to-stmt:types:
22662     # if src is not a scalar, abort
22663     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22664     (size-of %eax)  # => eax
22665     3d/compare-eax-and 4/imm32
22666     0f 8f/jump-if-> $check-mu-copy-byte-to-stmt:error-src-too-large/disp32
22667     # if src not in register, abort
22668     {
22669       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22670       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
22671       3d/compare-eax-and 0/imm32
22672       75/jump-if-!= break/disp8
22673       e9/jump $check-mu-copy-byte-to-stmt:error-src-not-in-register/disp32
22674     }
22675     # var dest-type/ebx: (addr type-tree) = dest->value->type
22676     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22677     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22678     89/<- %ebx 0/r32/eax
22679     # if (dest->is-deref?) dest-type = dest-type->payload
22680 $check-mu-copy-byte-to-stmt:check-dest-deref:
22681     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
22682     3d/compare-eax-and 0/imm32/false
22683     {
22684       74/jump-if-= break/disp8
22685       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22686 $check-mu-copy-byte-to-stmt:dest-is-deref:
22687       # if dest-type->right is null, dest-type = dest-type->left
22688       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
22689       {
22690         75/jump-if-!= break/disp8
22691 $check-mu-copy-byte-to-stmt:dest-is-deref2:
22692         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22693       }
22694       89/<- %ebx 0/r32/eax
22695     }
22696     # if dest is not a byte, abort
22697     (simple-mu-type? %ebx 8)  # byte => eax
22698     3d/compare-eax-and 0/imm32/false
22699     0f 84/jump-if-= $check-mu-copy-byte-to-stmt:error-invalid-dest-type/disp32
22700 $check-mu-copy-byte-to-stmt:end:
22701     # . reclaim locals
22702     81 0/subop/add %esp 0x6c/imm32
22703     # . restore registers
22704     5f/pop-to-edi
22705     5e/pop-to-esi
22706     5b/pop-to-ebx
22707     5a/pop-to-edx
22708     58/pop-to-eax
22709     # . epilogue
22710     89/<- %esp 5/r32/ebp
22711     5d/pop-to-ebp
22712     c3/return
22713 
22714 $check-mu-copy-byte-to-stmt:error-incorrect-inouts:
22715     (write-buffered *(ebp+0x10) "fn ")
22716     8b/-> *(ebp+0xc) 0/r32/eax
22717     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22718     (write-buffered *(ebp+0x10) %eax)
22719     (write-buffered *(ebp+0x10) ": stmt 'copy-byte-to' must have two inouts\n")
22720     (flush *(ebp+0x10))
22721     (stop *(ebp+0x14) 1)
22722     # never gets here
22723 
22724 $check-mu-copy-byte-to-stmt:error-too-many-outputs:
22725     (write-buffered *(ebp+0x10) "fn ")
22726     8b/-> *(ebp+0xc) 0/r32/eax
22727     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22728     (write-buffered *(ebp+0x10) %eax)
22729     (write-buffered *(ebp+0x10) ": stmt 'copy-byte-to' must not have any outputs\n")
22730     (flush *(ebp+0x10))
22731     (stop *(ebp+0x14) 1)
22732     # never gets here
22733 
22734 $check-mu-copy-byte-to-stmt:error-src-not-in-register:
22735     (write-buffered *(ebp+0x10) "fn ")
22736     8b/-> *(ebp+0xc) 0/r32/eax
22737     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22738     (write-buffered *(ebp+0x10) %eax)
22739     (write-buffered *(ebp+0x10) ": stmt copy-byte-to: source (second inout) must be in a register\n")
22740     (flush *(ebp+0x10))
22741     (stop *(ebp+0x14) 1)
22742     # never gets here
22743 
22744 $check-mu-copy-byte-to-stmt:error-invalid-dest-type:
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 copy-byte-to: '")
22750     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22751     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22752     (write-buffered *(ebp+0x10) %eax)
22753     (write-buffered *(ebp+0x10) "' must be a byte\n")
22754     (flush *(ebp+0x10))
22755     (stop *(ebp+0x14) 1)
22756     # never gets here
22757 
22758 $check-mu-copy-byte-to-stmt:error-src-too-large:
22759     (write-buffered *(ebp+0x10) "fn ")
22760     8b/-> *(ebp+0xc) 0/r32/eax
22761     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22762     (write-buffered *(ebp+0x10) %eax)
22763     (write-buffered *(ebp+0x10) ": stmt copy-byte-to: '")
22764     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22765     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22766     (write-buffered *(ebp+0x10) %eax)
22767     (write-buffered *(ebp+0x10) "' is too large to copy\n")
22768     (flush *(ebp+0x10))
22769     (stop *(ebp+0x14) 1)
22770     # never gets here
22771 
22772 check-mu-compare-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22773     # . prologue
22774     55/push-ebp
22775     89/<- %ebp 4/r32/esp
22776     # . save registers
22777     50/push-eax
22778     51/push-ecx
22779     52/push-edx
22780     53/push-ebx
22781     56/push-esi
22782     57/push-edi
22783     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
22784     81 5/subop/subtract %esp 0x60/imm32
22785     68/push 0x60/imm32/size
22786     68/push 0/imm32/read
22787     68/push 0/imm32/write
22788     89/<- %edx 4/r32/esp
22789     # esi = stmt
22790     8b/-> *(ebp+8) 6/r32/esi
22791 $check-mu-compare-stmt:check-for-output:
22792     # if stmt->outputs abort
22793     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22794     3d/compare-eax-and 0/imm32
22795     0f 85/jump-if-!= $check-mu-compare-stmt:error-too-many-outputs/disp32
22796 $check-mu-compare-stmt:get-left:
22797     # var left/edi: (addr stmt-var) = stmt->inouts
22798     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22799     89/<- %edi 0/r32/eax
22800     # zero inouts
22801     3d/compare-eax-and 0/imm32
22802     0f 84/jump-if-= $check-mu-compare-stmt:error-incorrect-inouts/disp32
22803 $check-mu-compare-stmt:get-right:
22804     # var right/esi: (addr stmt-var) = left->next
22805     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
22806     89/<- %esi 0/r32/eax
22807     # 1 inout
22808     3d/compare-eax-and 0/imm32
22809     0f 84/jump-if-= $check-mu-compare-stmt:error-incorrect-inouts/disp32
22810     # > 2 inouts
22811     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
22812     3d/compare-eax-and 0/imm32
22813     0f 85/jump-if-!= $check-mu-compare-stmt:error-incorrect-inouts/disp32
22814     # if both inouts are in memory, abort
22815     {
22816 $check-mu-compare-stmt:both-in-mem:
22817       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22818       (lookup *(eax+0x8) *(eax+0xc))  # Var-type Var-type => eax
22819       (simple-mu-type? %eax 0)  # => eax
22820       3d/compare-eax-and 0/imm32
22821       0f 85/jump-if-!= break/disp32
22822       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22823       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
22824       3d/compare-eax-and 0/imm32
22825       75/jump-if-!= break/disp8
22826       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22827       (lookup *(eax+0x8) *(eax+0xc))  # Var-type Var-type => eax
22828       (simple-mu-type? %eax 0)  # => eax
22829       3d/compare-eax-and 0/imm32
22830       75/jump-if-!= break/disp8
22831       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22832       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
22833       3d/compare-eax-and 0/imm32
22834       75/jump-if-!= break/disp8
22835       e9/jump $check-mu-compare-stmt:error-both-in-memory/disp32
22836     }
22837 $check-mu-compare-stmt:types:
22838     # var right-type/ecx: (addr type-tree) = right->value->type
22839     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22840     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22841     89/<- %ecx 0/r32/eax
22842     # if (right->is-deref?) right-type = right-type->payload
22843     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
22844     3d/compare-eax-and 0/imm32/false
22845     {
22846       74/jump-if-= break/disp8
22847       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
22848       # if right-type->right is null, right-type = right-type->left
22849       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
22850       {
22851         75/jump-if-!= break/disp8
22852         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22853       }
22854       89/<- %ecx 0/r32/eax
22855     }
22856     # if right-type is a literal string, abort
22857     (simple-mu-type? %ecx 0x10)  # string-literal => eax
22858     3d/compare-eax-and 0/imm32/false
22859     0f 85/jump-if-!= $check-mu-compare-stmt:error-right-string-literal/disp32
22860     # if right is not a scalar, abort
22861     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22862     (size-of %eax)  # => eax
22863     3d/compare-eax-and 4/imm32
22864     0f 8f/jump-if-> $check-mu-compare-stmt:error-right-too-large/disp32
22865     # if left is not a scalar, abort
22866     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22867     (size-of %eax)  # => eax
22868     3d/compare-eax-and 4/imm32
22869     0f 8f/jump-if-> $check-mu-compare-stmt:error-left-too-large/disp32
22870     # var left-type/ebx: (addr type-tree) = left->value->type
22871     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22872     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22873     89/<- %ebx 0/r32/eax
22874     # if (left->is-deref?) left-type = left-type->payload
22875     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
22876     3d/compare-eax-and 0/imm32/false
22877     {
22878       74/jump-if-= break/disp8
22879       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22880       # if left-type->right is null, left-type = left-type->left
22881       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
22882       {
22883         75/jump-if-!= break/disp8
22884         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22885       }
22886       89/<- %ebx 0/r32/eax
22887     }
22888     # if (left-type == right-type) return
22889     (type-match? %ebx %ecx %edx)  # => eax
22890     3d/compare-eax-and 0/imm32
22891     0f 85/jump-if-!= $check-mu-compare-stmt:end/disp32
22892     # if left is an addr and right is 0, return
22893     {
22894       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22895       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22896       (mu-addr-type? %eax)  # => eax
22897       3d/compare-eax-and 0/imm32/false
22898       74/jump-if-= break/disp8
22899       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22900       (lookup *eax *(eax+4))  # Var-name Var-name => eax
22901       (string-equal? %eax "0")  # => eax
22902       3d/compare-eax-and 0/imm32/false
22903       74/jump-if-= break/disp8
22904       eb/jump $check-mu-compare-stmt:end/disp8
22905     }
22906     # if left is not number-like, abort
22907     (check-mu-numberlike-arg %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
22908 $check-mu-compare-stmt:end:
22909     # . reclaim locals
22910     81 0/subop/add %esp 0x6c/imm32
22911     # . restore registers
22912     5f/pop-to-edi
22913     5e/pop-to-esi
22914     5b/pop-to-ebx
22915     5a/pop-to-edx
22916     59/pop-to-ecx
22917     58/pop-to-eax
22918     # . epilogue
22919     89/<- %esp 5/r32/ebp
22920     5d/pop-to-ebp
22921     c3/return
22922 
22923 $check-mu-compare-stmt:error-incorrect-inouts:
22924     (write-buffered *(ebp+0x10) "fn ")
22925     8b/-> *(ebp+0xc) 0/r32/eax
22926     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22927     (write-buffered *(ebp+0x10) %eax)
22928     (write-buffered *(ebp+0x10) ": stmt 'compare' must have two inouts\n")
22929     (flush *(ebp+0x10))
22930     (stop *(ebp+0x14) 1)
22931     # never gets here
22932 
22933 $check-mu-compare-stmt:error-too-many-outputs:
22934     (write-buffered *(ebp+0x10) "fn ")
22935     8b/-> *(ebp+0xc) 0/r32/eax
22936     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22937     (write-buffered *(ebp+0x10) %eax)
22938     (write-buffered *(ebp+0x10) ": stmt 'compare' must not have any outputs\n")
22939     (flush *(ebp+0x10))
22940     (stop *(ebp+0x14) 1)
22941     # never gets here
22942 
22943 $check-mu-compare-stmt:error-both-in-memory:
22944     (write-buffered *(ebp+0x10) "fn ")
22945     8b/-> *(ebp+0xc) 0/r32/eax
22946     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22947     (write-buffered *(ebp+0x10) %eax)
22948     (write-buffered *(ebp+0x10) ": stmt compare: both inouts are in memory\n")
22949     (flush *(ebp+0x10))
22950     (stop *(ebp+0x14) 1)
22951     # never gets here
22952 
22953 $check-mu-compare-stmt:error-left-too-large:
22954     (write-buffered *(ebp+0x10) "fn ")
22955     8b/-> *(ebp+0xc) 0/r32/eax
22956     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22957     (write-buffered *(ebp+0x10) %eax)
22958     (write-buffered *(ebp+0x10) ": stmt compare: '")
22959     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22960     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22961     (write-buffered *(ebp+0x10) %eax)
22962     (write-buffered *(ebp+0x10) "' is too large to compare\n")
22963     (flush *(ebp+0x10))
22964     (stop *(ebp+0x14) 1)
22965     # never gets here
22966 
22967 $check-mu-compare-stmt:error-right-too-large:
22968     (write-buffered *(ebp+0x10) "fn ")
22969     8b/-> *(ebp+0xc) 0/r32/eax
22970     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22971     (write-buffered *(ebp+0x10) %eax)
22972     (write-buffered *(ebp+0x10) ": stmt compare: '")
22973     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22974     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22975     (write-buffered *(ebp+0x10) %eax)
22976     (write-buffered *(ebp+0x10) "' is too large to compare\n")
22977     (flush *(ebp+0x10))
22978     (stop *(ebp+0x14) 1)
22979     # never gets here
22980 
22981 $check-mu-compare-stmt:error-right-string-literal:
22982     (write-buffered *(ebp+0x10) "fn ")
22983     8b/-> *(ebp+0xc) 0/r32/eax
22984     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22985     (write-buffered *(ebp+0x10) %eax)
22986     (write-buffered *(ebp+0x10) ": stmt compare: string literal ")
22987     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22988     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22989     (write-buffered *(ebp+0x10) %eax)
22990     (write-buffered *(ebp+0x10) " is not supported; use the string-equal? function\n")
22991     (flush *(ebp+0x10))
22992     (stop *(ebp+0x14) 1)
22993     # never gets here
22994 
22995 check-mu-address-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22996     # . prologue
22997     55/push-ebp
22998     89/<- %ebp 4/r32/esp
22999     # . save registers
23000     50/push-eax
23001     51/push-ecx
23002     52/push-edx
23003     56/push-esi
23004     57/push-edi
23005 $check-mu-address-stmt:get-output:
23006     # esi = stmt
23007     8b/-> *(ebp+8) 6/r32/esi
23008     # var output/edi: (addr stmt-var) = stmt->outputs
23009     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
23010     89/<- %edi 0/r32/eax
23011     # zero outputs
23012     3d/compare-eax-and 0/imm32
23013     0f 84/jump-if-= $check-mu-address-stmt:error-no-output/disp32
23014     # > 1 output
23015     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
23016     3d/compare-eax-and 0/imm32
23017     0f 85/jump-if-!= $check-mu-address-stmt:error-too-many-outputs/disp32
23018 $check-mu-address-stmt:get-inout:
23019     # var inout/esi: (addr stmt-var) = stmt->inouts
23020     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23021     89/<- %esi 0/r32/eax
23022     # zero inouts
23023     3d/compare-eax-and 0/imm32
23024     0f 84/jump-if-= $check-mu-address-stmt:error-no-inout/disp32
23025     # > 1 inout
23026     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
23027     3d/compare-eax-and 0/imm32
23028     0f 85/jump-if-!= $check-mu-address-stmt:error-too-many-inouts/disp32
23029 $check-mu-address-stmt:types:
23030     # if output not in register, abort
23031     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23032     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
23033     3d/compare-eax-and 0/imm32
23034     0f 84/jump-if-= $check-mu-address-stmt:error-output-not-in-register/disp32
23035     # var output-type/edx: (addr type-tree) = output->value->type
23036     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23037     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23038     89/<- %edx 0/r32/eax
23039     # if output-type not an addr, abort
23040     (mu-addr-type? %edx)  # => eax
23041     3d/compare-eax-and 0/imm32/false
23042     0f 84/jump-if-= $check-mu-address-stmt:error-output-not-address/disp32
23043     # output-type = output-type->right
23044     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
23045     # if output-type->right is null, output-type = output-type->left
23046     81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
23047     {
23048       75/jump-if-!= break/disp8
23049       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23050     }
23051     89/<- %edx 0/r32/eax
23052     # var inout-type/ecx: (addr type-tree) = inout->value->type
23053     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
23054     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23055     89/<- %ecx 0/r32/eax
23056     # if (inout->is-deref?) inout-type = inout-type->payload
23057     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
23058     3d/compare-eax-and 0/imm32/false
23059     {
23060       74/jump-if-= break/disp8
23061       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
23062       # if inout-type->right is null, t = inout-type->left
23063       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
23064       {
23065         75/jump-if-!= break/disp8
23066         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23067       }
23068       89/<- %ecx 0/r32/eax
23069     }
23070     # if (inout-type != output-type) abort
23071     (type-equal-ignoring-capacity? %edx %ecx)  # => eax
23072     3d/compare-eax-and 0/imm32
23073     0f 84/jump-if-= $check-mu-address-stmt:error-type-mismatch/disp32
23074 $check-mu-address-stmt:end:
23075     # . restore registers
23076     5f/pop-to-edi
23077     5e/pop-to-esi
23078     5a/pop-to-edx
23079     59/pop-to-ecx
23080     58/pop-to-eax
23081     # . epilogue
23082     89/<- %esp 5/r32/ebp
23083     5d/pop-to-ebp
23084     c3/return
23085 
23086 $check-mu-address-stmt:error-no-inout:
23087     (write-buffered *(ebp+0x10) "fn ")
23088     8b/-> *(ebp+0xc) 0/r32/eax
23089     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23090     (write-buffered *(ebp+0x10) %eax)
23091     (write-buffered *(ebp+0x10) ": stmt 'address' expects an inout\n")
23092     (flush *(ebp+0x10))
23093     (stop *(ebp+0x14) 1)
23094     # never gets here
23095 
23096 $check-mu-address-stmt:error-too-many-inouts:
23097     (write-buffered *(ebp+0x10) "fn ")
23098     8b/-> *(ebp+0xc) 0/r32/eax
23099     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23100     (write-buffered *(ebp+0x10) %eax)
23101     (write-buffered *(ebp+0x10) ": stmt 'address' must have just one inout\n")
23102     (flush *(ebp+0x10))
23103     (stop *(ebp+0x14) 1)
23104     # never gets here
23105 
23106 $check-mu-address-stmt:error-no-output:
23107     (write-buffered *(ebp+0x10) "fn ")
23108     8b/-> *(ebp+0xc) 0/r32/eax
23109     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23110     (write-buffered *(ebp+0x10) %eax)
23111     (write-buffered *(ebp+0x10) ": stmt 'address' expects an output\n")
23112     (flush *(ebp+0x10))
23113     (stop *(ebp+0x14) 1)
23114     # never gets here
23115 
23116 $check-mu-address-stmt:error-output-not-in-register:
23117     (write-buffered *(ebp+0x10) "fn ")
23118     8b/-> *(ebp+0xc) 0/r32/eax
23119     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23120     (write-buffered *(ebp+0x10) %eax)
23121     (write-buffered *(ebp+0x10) ": stmt address: output '")
23122     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23123     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23124     (write-buffered *(ebp+0x10) %eax)
23125     (write-buffered *(ebp+0x10) "' not in a register\n")
23126     (flush *(ebp+0x10))
23127     (stop *(ebp+0x14) 1)
23128     # never gets here
23129 
23130 $check-mu-address-stmt:error-too-many-outputs:
23131     (write-buffered *(ebp+0x10) "fn ")
23132     8b/-> *(ebp+0xc) 0/r32/eax
23133     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23134     (write-buffered *(ebp+0x10) %eax)
23135     (write-buffered *(ebp+0x10) ": stmt 'address' must have just one output\n")
23136     (flush *(ebp+0x10))
23137     (stop *(ebp+0x14) 1)
23138     # never gets here
23139 
23140 $check-mu-address-stmt:error-output-not-address:
23141     (write-buffered *(ebp+0x10) "fn ")
23142     8b/-> *(ebp+0xc) 0/r32/eax
23143     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23144     (write-buffered *(ebp+0x10) %eax)
23145     (write-buffered *(ebp+0x10) ": stmt address: output '")
23146     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23147     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23148     (write-buffered *(ebp+0x10) %eax)
23149     (write-buffered *(ebp+0x10) "' is not an addr\n")
23150     (flush *(ebp+0x10))
23151     (stop *(ebp+0x14) 1)
23152     # never gets here
23153 
23154 $check-mu-address-stmt:error-type-mismatch:
23155     (write-buffered *(ebp+0x10) "fn ")
23156     8b/-> *(ebp+0xc) 0/r32/eax
23157     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23158     (write-buffered *(ebp+0x10) %eax)
23159     (write-buffered *(ebp+0x10) ": stmt address: output '")
23160     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23161     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23162     (write-buffered *(ebp+0x10) %eax)
23163     (write-buffered *(ebp+0x10) "' cannot hold address of '")
23164     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
23165     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23166     (write-buffered *(ebp+0x10) %eax)
23167     (write-buffered *(ebp+0x10) "'\n")
23168     (flush *(ebp+0x10))
23169     (stop *(ebp+0x14) 1)
23170     # never gets here
23171 
23172 type-equal-ignoring-capacity?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
23173     # . prologue
23174     55/push-ebp
23175     89/<- %ebp 4/r32/esp
23176     # . save registers
23177     51/push-ecx
23178     52/push-edx
23179     53/push-ebx
23180     # var curr-a/ecx: (addr type-tree) = a
23181     8b/-> *(ebp+8) 1/r32/ecx
23182     # var curr-b/ebx: (addr type-tree) = b
23183     8b/-> *(ebp+0xc) 3/r32/ebx
23184     # if (curr-a->is-atom?) fall back to regular equality
23185     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
23186     0f 85/jump-if-!= $type-equal-ignoring-capacity?:base-case/disp32
23187     # if (curr-a->left != curr-b->left) return false
23188     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
23189     89/<- %edx 0/r32/eax
23190     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
23191     (type-equal? %edx %eax)  # => eax
23192     3d/compare-eax-and 0/imm32/false
23193     0f 84/jump-if-= $type-equal-ignoring-capacity?:end/disp32  # eax switches meaning
23194     # if (curr-a->left == "array") curr-a = curr-a->element-type
23195     {
23196       (mu-array? %edx)  # => eax
23197       3d/compare-eax-and 0/imm32/false
23198       75/jump-if-!= break/disp8
23199 $type-equal-ignoring-capacity?:array:
23200       # curr-a = curr-a->right->left
23201       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
23202       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23203       89/<- %ecx 0/r32/eax
23204       # curr-b = curr-b->right->left
23205       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23206       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23207       89/<- %ebx 0/r32/eax
23208       eb/jump $type-equal-ignoring-capacity?:base-case/disp8
23209     }
23210     # if (curr-a->left == "stream") curr-a = curr-a->element-type
23211     {
23212       (mu-stream? %edx)  # => eax
23213       3d/compare-eax-and 0/imm32/false
23214       75/jump-if-!= break/disp8
23215 $type-equal-ignoring-capacity?:stream:
23216       # curr-a = curr-a->right->left
23217       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
23218       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23219       89/<- %ecx 0/r32/eax
23220       # curr-b = curr-b->right->left
23221       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23222       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23223       89/<- %ebx 0/r32/eax
23224       eb/jump $type-equal-ignoring-capacity?:base-case/disp8
23225     }
23226 $type-equal-ignoring-capacity?:base-case:
23227     # return type-equal?(curr-a, curr-b)
23228     (type-equal? %ecx %ebx)  # => eax
23229 $type-equal-ignoring-capacity?:end:
23230     # . restore registers
23231     5b/pop-to-ebx
23232     5a/pop-to-edx
23233     59/pop-to-ecx
23234     # . epilogue
23235     89/<- %esp 5/r32/ebp
23236     5d/pop-to-ebp
23237     c3/return
23238 
23239 check-mu-return-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23240     # . prologue
23241     55/push-ebp
23242     89/<- %ebp 4/r32/esp
23243     # . save registers
23244     50/push-eax
23245     51/push-ecx
23246     52/push-edx
23247     53/push-ebx
23248     56/push-esi
23249     57/push-edi
23250     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
23251     81 5/subop/subtract %esp 0x60/imm32
23252     68/push 0x60/imm32/size
23253     68/push 0/imm32/read
23254     68/push 0/imm32/write
23255     89/<- %edx 4/r32/esp
23256     # var template/esi: (addr list var) = fn->outputs
23257     8b/-> *(ebp+0xc) 0/r32/eax
23258     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
23259     89/<- %esi 0/r32/eax
23260     # var curr-template/ebx: (addr list var) = fn->outputs
23261     89/<- %ebx 0/r32/eax
23262     # var curr/edi: (addr stmt-var) = stmt->inouts
23263     8b/-> *(ebp+8) 0/r32/eax
23264     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23265     89/<- %edi 0/r32/eax
23266     {
23267       # if template is null, break
23268       81 7/subop/compare %ebx 0/imm32
23269       0f 84/jump-if-= break/disp32
23270       # if curr is null, abort
23271       81 7/subop/compare %edi 0/imm32
23272       0f 84/jump-if-= $check-mu-return-stmt:error-too-few-inouts/disp32
23273       # var template-type/ecx: (addr type-tree) = template->value->type
23274       (lookup *ebx *(ebx+4))  # List-value List-value => eax
23275       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23276       89/<- %ecx 0/r32/eax
23277       # var curr-type/eax: (addr type-tree) = curr->value->type
23278       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23279       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23280       # if (curr->is-deref?) curr-type = payload of curr-type
23281       81 7/subop/compare *(edi+0x10) 0/imm32/false  # Stmt-var-is-deref
23282       {
23283         74/jump-if-= break/disp8
23284         (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
23285         # if t->right is null, t = t->left
23286         81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
23287         75/jump-if-!= break/disp8
23288         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23289       }
23290       # if curr-type is literal and template-type is float, abort
23291       50/push-eax
23292       {
23293         (simple-mu-type? %eax 0)  # literal => eax
23294         3d/compare-eax-and 0/imm32/false
23295         74/jump-if-= break/disp8
23296         (simple-mu-type? %ecx 0xf)  # float => eax
23297         3d/compare-eax-and 0/imm32/false
23298         0f 85/jump-if-!= $check-mu-return-stmt:error-literal-to-float/disp32
23299       }
23300       58/pop-to-eax
23301       # if (curr-type != template-type) abort
23302       (type-match? %ecx %eax %edx)  # => eax
23303       3d/compare-eax-and 0/imm32/false
23304       0f 84/jump-if-= $check-mu-return-stmt:error1/disp32
23305       # if register-within-list-with-conflict?(curr, original template, curr-template, stmt) abort
23306       (register-within-list-with-conflict? %edi %esi %ebx *(ebp+8))  # => eax
23307       3d/compare-eax-and 0/imm32/false
23308       0f 85/jump-if-!= $check-mu-return-stmt:error2/disp32
23309       # template = template->next
23310       (lookup *(ebx+8) *(ebx+0xc))  # List-next List-next => eax
23311       89/<- %ebx 0/r32/eax
23312       # curr = curr->next
23313       (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
23314       89/<- %edi 0/r32/eax
23315       #
23316       e9/jump loop/disp32
23317     }
23318     # if curr is not null, abort
23319     81 7/subop/compare %edi 0/imm32
23320     0f 85/jump-if-!= $check-mu-return-stmt:error-too-many-inouts/disp32
23321 $check-mu-return-stmt:end:
23322     # . reclaim locals
23323     81 0/subop/add %esp 0x6c/imm32
23324     # . restore registers
23325     5f/pop-to-edi
23326     5e/pop-to-esi
23327     5b/pop-to-ebx
23328     5a/pop-to-edx
23329     59/pop-to-ecx
23330     58/pop-to-eax
23331     # . epilogue
23332     89/<- %esp 5/r32/ebp
23333     5d/pop-to-ebp
23334     c3/return
23335 
23336 $check-mu-return-stmt:error1:
23337     (write-buffered *(ebp+0x10) "fn ")
23338     8b/-> *(ebp+0xc) 0/r32/eax
23339     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23340     (write-buffered *(ebp+0x10) %eax)
23341     (write-buffered *(ebp+0x10) ": return: '")
23342     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23343     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23344     (write-buffered *(ebp+0x10) %eax)
23345     (write-buffered *(ebp+0x10) "' has the wrong type\n")
23346     (flush *(ebp+0x10))
23347     (stop *(ebp+0x14) 1)
23348     # never gets here
23349 
23350 $check-mu-return-stmt:error2:
23351     (write-buffered *(ebp+0x10) "fn ")
23352     8b/-> *(ebp+0xc) 0/r32/eax
23353     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23354     (write-buffered *(ebp+0x10) %eax)
23355     (write-buffered *(ebp+0x10) ": return: '")
23356     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23357     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23358     (write-buffered *(ebp+0x10) %eax)
23359     (write-buffered *(ebp+0x10) "' is no longer available\n")
23360     (flush *(ebp+0x10))
23361     (stop *(ebp+0x14) 1)
23362     # never gets here
23363 
23364 $check-mu-return-stmt:error-literal-to-float:
23365     (write-buffered *(ebp+0x10) "fn ")
23366     8b/-> *(ebp+0xc) 0/r32/eax
23367     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23368     (write-buffered *(ebp+0x10) %eax)
23369     (write-buffered *(ebp+0x10) ": return: cannot copy literal '")
23370     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23371     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23372     (write-buffered *(ebp+0x10) %eax)
23373     (write-buffered *(ebp+0x10) "' to float\n")
23374     (flush *(ebp+0x10))
23375     (stop *(ebp+0x14) 1)
23376     # never gets here
23377 
23378 $check-mu-return-stmt:error-too-few-inouts:
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) ": return: too few inouts\n")
23384     (flush *(ebp+0x10))
23385     (stop *(ebp+0x14) 1)
23386     # never gets here
23387 
23388 $check-mu-return-stmt:error-too-many-inouts:
23389     (write-buffered *(ebp+0x10) "fn ")
23390     8b/-> *(ebp+0xc) 0/r32/eax
23391     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23392     (write-buffered *(ebp+0x10) %eax)
23393     (write-buffered *(ebp+0x10) ": return: too many inouts\n")
23394     (flush *(ebp+0x10))
23395     (stop *(ebp+0x14) 1)
23396     # never gets here
23397 
23398 check-all-unique-registers:  # outputs: (addr list var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23399     # . prologue
23400     55/push-ebp
23401     89/<- %ebp 4/r32/esp
23402     # . save registers
23403     50/push-eax
23404     51/push-ecx
23405     56/push-esi
23406     # var table/esi: (addr table (handle array byte) int 8)
23407     81 5/subop/subtract %esp 0x60/imm32
23408     68/push 0x60/imm32/size
23409     68/push 0/imm32/read
23410     68/push 0/imm32/write
23411     89/<- %esi 4/r32/esp
23412     # var curr/ecx: (addr list var) = outputs
23413     8b/-> *(ebp+8) 1/r32/ecx
23414     {
23415       # if (curr == 0) break
23416       81 7/subop/compare %ecx 0/imm32
23417       0f 84/jump-if-= break/disp32
23418       # var reg/eax: (addr array byte) = curr->value->register  # guaranteed to exist
23419       (lookup *ecx *(ecx+4))  # List-value List-value => eax
23420       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
23421       # if reg exists in table, abort
23422       (maybe-get %esi %eax 0xc)  # => eax
23423       3d/compare-eax-and 0/imm32
23424       0f 85/jump-if-!= $check-all-unique-registers:abort/disp32
23425       # insert reg in table
23426       (lookup *ecx *(ecx+4))  # List-value List-value => eax
23427       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
23428       (get-or-insert %esi %eax 0xc Heap)
23429       # curr = curr->next
23430       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
23431       89/<- %ecx 0/r32/eax
23432       e9/jump loop/disp32
23433     }
23434 $check-all-unique-registers:end:
23435     # . reclaim locals
23436     81 0/subop/add %esp 0x6c/imm32
23437     # . restore registers
23438     5e/pop-to-esi
23439     59/pop-to-ecx
23440     58/pop-to-eax
23441     # . epilogue
23442     89/<- %esp 5/r32/ebp
23443     5d/pop-to-ebp
23444     c3/return
23445 
23446 $check-all-unique-registers:abort:
23447     (write-buffered *(ebp+0x10) "fn ")
23448     8b/-> *(ebp+0xc) 0/r32/eax
23449     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23450     (write-buffered *(ebp+0x10) %eax)
23451     (write-buffered *(ebp+0x10) ": outputs must be in unique registers\n")
23452     (flush *(ebp+0x10))
23453     (stop *(ebp+0x14) 1)
23454     # never gets here
23455 
23456 # return false if s's register is not between start (inclusive) and end (exclusive)
23457 # return false if the positionally corresponding register in stmt->inouts (where s comes from) is also s's register
23458 # otherwise return true
23459 register-within-list-with-conflict?:  # s: (addr stmt-var), start: (addr list var), end: (addr list var), stmt: (addr stmt) -> result/eax: boolean
23460     # . prologue
23461     55/push-ebp
23462     89/<- %ebp 4/r32/esp
23463     # . save registers
23464     51/push-ecx
23465     52/push-edx
23466     53/push-ebx
23467     56/push-esi
23468     57/push-edi
23469     # var target/ebx: (addr array byte) = s->value->register
23470     8b/-> *(ebp+8) 0/r32/eax
23471     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23472     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
23473 #?     (write-buffered Stderr "AA: ")
23474 #?     (write-buffered Stderr %eax)
23475 #?     (write-buffered Stderr Newline)
23476 #?     (flush Stderr)
23477     # if (var->register == 0) return false
23478     3d/compare-eax-and 0/imm32
23479     0f 84/jump-if-= $register-within-list-with-conflict?:end/disp32  # eax turns into result
23480     89/<- %ebx 0/r32/eax
23481     # var curr/ecx: (addr list var) = start
23482     8b/-> *(ebp+0xc) 1/r32/ecx
23483     # edx = end
23484     8b/-> *(ebp+0x10) 2/r32/edx
23485     {
23486       # if (curr == 0) break
23487       81 7/subop/compare %edi 0/imm32
23488       0f 84/jump-if-= break/disp32
23489       # if (curr == end) break
23490       39/compare %ecx 2/r32/edx
23491       0f 84/jump-if-= break/disp32
23492       # var curr-reg/eax: (addr array byte) = curr->value->register
23493       (lookup *ecx *(ecx+4))  # List-value List-value => eax
23494       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
23495       # if (curr-reg == 0) continue
23496       3d/compare-eax-and 0/imm32
23497       74/jump-if-= $register-within-list-with-conflict?:continue/disp8
23498       # if (curr-reg == target) check for conflict
23499       (string-equal? %eax %ebx)  # => eax
23500       3d/compare-eax-and 0/imm32/false
23501       {
23502         74/jump-if-= break/disp8
23503 #?         (write-buffered Stderr "conflict?\n")
23504 #?         (flush Stderr)
23505         # var return-inouts/eax: (addr stmt-var) = stmt->inouts
23506         8b/-> *(ebp+0x14) 0/r32/eax
23507         (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23508         (register-conflict? %ebx %eax *(ebp+0xc))  # => eax
23509         eb/jump $register-within-list-with-conflict?:end/disp8
23510       }
23511 $register-within-list-with-conflict?:continue:
23512       # curr = curr->next
23513       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
23514       89/<- %ecx 0/r32/eax
23515       e9/jump loop/disp32
23516     }
23517     # return false
23518     b8/copy-to-eax 0/imm32/false
23519 $register-within-list-with-conflict?:end:
23520     # . restore registers
23521     5f/pop-to-edi
23522     5e/pop-to-esi
23523     5b/pop-to-ebx
23524     5a/pop-to-edx
23525     59/pop-to-ecx
23526     # . epilogue
23527     89/<- %esp 5/r32/ebp
23528     5d/pop-to-ebp
23529     c3/return
23530 
23531 # At the first occurrence of register 'reg' in fn-outputs,
23532 # check if the corresponding element of return-inouts has a different register.
23533 # This hacky helper is intended to be called in one specific place. Don't
23534 # reuse it as is.
23535 register-conflict?:  # reg: (addr array byte), return-inouts: (addr stmt-var), fn-outputs: (addr list var) => result/eax: boolean
23536     # . prologue
23537     55/push-ebp
23538     89/<- %ebp 4/r32/esp
23539     # . save registers
23540     51/push-ecx
23541     52/push-edx
23542     53/push-ebx
23543     56/push-esi
23544     57/push-edi
23545 #?     (write-buffered Stderr "BB: ")
23546 #?     (write-buffered Stderr *(ebp+8))
23547 #?     (write-buffered Stderr Newline)
23548 #?     (flush Stderr)
23549     # var curr-output/edi: (addr list var) = fn-outputs
23550     8b/-> *(ebp+0x10) 7/r32/edi
23551     # var curr-inout/esi: (addr stmt-var) = return-inouts
23552     8b/-> *(ebp+0xc) 6/r32/esi
23553     {
23554       # if (curr-output == 0) abort
23555       81 7/subop/compare %edi 0/imm32
23556       0f 84/jump-if-= break/disp32
23557       # if (curr-output->value->register != reg) continue
23558       (lookup *edi *(edi+4))  # List-value List-value => eax
23559       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
23560       (string-equal? %eax *(ebp+8))  # => eax
23561       3d/compare-eax-and 0/imm32/false
23562       0f 84/jump-if= $register-conflict?:continue/disp32
23563 #?       (write-buffered Stderr "rescan\n")
23564 #?       (flush Stderr)
23565       # var curr-reg/eax: (addr array byte) = curr-inout->value->register
23566       (lookup *esi *(esi+4))  # List-value List-value => eax
23567       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
23568       # if (curr-reg == 0) return true
23569       3d/compare-eax-and 0/imm32
23570       {
23571         75/jump-if-!= break/disp8
23572 #?         (write-buffered Stderr "no register\n")
23573 #?         (flush Stderr)
23574         b8/copy-to-eax 1/imm32/true
23575         e9/jump $register-conflict?:end/disp32
23576       }
23577       # return (curr-reg != reg)
23578       (string-equal? %eax *(ebp+8))  # => eax
23579       3d/compare-eax-and 0/imm32/false
23580       0f 94/set-if-= %al
23581 #?       (write-buffered Stderr "final: ")
23582 #?       (write-int32-hex-buffered Stderr %eax)
23583 #?       (write-buffered Stderr Newline)
23584 #?       (flush Stderr)
23585       eb/jump $register-conflict?:end/disp8
23586 $register-conflict?:continue:
23587       # curr-output = curr-output->next
23588       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
23589       89/<- %edi 0/r32/eax
23590       # curr-inout = curr-inout->next
23591       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
23592       89/<- %esi 0/r32/eax
23593       e9/jump loop/disp32
23594     }
23595     # should never get here
23596     (write-buffered Stderr "register-conflict? misused\n")
23597     (flush Stderr)
23598     e8/call syscall_exit/disp32
23599 $register-conflict?:end:
23600     # . restore registers
23601     5f/pop-to-edi
23602     5e/pop-to-esi
23603     5b/pop-to-ebx
23604     5a/pop-to-edx
23605     59/pop-to-ecx
23606     # . epilogue
23607     89/<- %esp 5/r32/ebp
23608     5d/pop-to-ebp
23609     c3/return
23610 
23611 check-final-stmt-is-return:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23612     # . prologue
23613     55/push-ebp
23614     89/<- %ebp 4/r32/esp
23615     # . save registers
23616     50/push-eax
23617     51/push-ecx
23618     # var curr/ecx: (addr list stmt) = block->stmts
23619     8b/-> *(ebp+8) 0/r32/eax
23620     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
23621     3d/compare-eax-and 0/imm32
23622     74/jump-if-= $check-final-stmt-is-return:error/disp8
23623     89/<- %ecx 0/r32/eax
23624     {
23625       # if curr->next == 0, break
23626       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
23627       3d/compare-eax-and 0/imm32
23628       74/jump-if-= break/disp8
23629       # curr = curr->next
23630       89/<- %ecx 0/r32/eax
23631       e9/jump loop/disp32
23632     }
23633 $check-final-stmt-is-return:check-tag:
23634     # if curr->value->tag != Stmt1, abort
23635     (lookup *ecx *(ecx+4))  # List-value List-value => eax
23636     81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
23637     75/jump-if-!= $check-final-stmt-is-return:error/disp8
23638 $check-final-stmt-is-return:check-operation:
23639     # if curr->operation != "return", abort
23640     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
23641     (string-equal? %eax "return")
23642     3d/compare-eax-and 0/imm32/false
23643     74/jump-if-= $check-final-stmt-is-return:error/disp8
23644 $check-final-stmt-is-return:end:
23645     # . restore registers
23646     59/pop-to-ecx
23647     58/pop-to-eax
23648     # . epilogue
23649     89/<- %esp 5/r32/ebp
23650     5d/pop-to-ebp
23651     c3/return
23652 
23653 $check-final-stmt-is-return:error:
23654     (write-buffered *(ebp+0x10) "fn ")
23655     8b/-> *(ebp+0xc) 0/r32/eax
23656     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23657     (write-buffered *(ebp+0x10) %eax)
23658     (write-buffered *(ebp+0x10) ": final statement should be a 'return'\n")
23659     (flush *(ebp+0x10))
23660     (stop *(ebp+0x14) 1)
23661     # never gets here
23662 
23663 check-no-breaks:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23664     # . prologue
23665     55/push-ebp
23666     89/<- %ebp 4/r32/esp
23667     # . save registers
23668     50/push-eax
23669     51/push-ecx
23670     # var curr/ecx: (addr list stmt) = block->stmts
23671     8b/-> *(ebp+8) 0/r32/eax
23672     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
23673     3d/compare-eax-and 0/imm32
23674     0f 84/jump-if-= $check-no-breaks:end/disp32
23675     89/<- %ecx 0/r32/eax
23676     {
23677       # if curr->next == 0, break
23678       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
23679       3d/compare-eax-and 0/imm32
23680       74/jump-if-= break/disp8
23681       # if curr->value->tag != Stmt1, continue
23682       (lookup *ecx *(ecx+4))  # List-value List-value => eax
23683       81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
23684       75/jump-if-!= $check-no-breaks:continue/disp8
23685       # if curr->value->operation starts with "break", abort
23686       (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
23687       (string-starts-with? %eax "break")  # => eax
23688       3d/compare-eax-and 0/imm32/false
23689       75/jump-if-!= $check-no-breaks:error/disp8
23690 $check-no-breaks:continue:
23691       # curr = curr->next
23692       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
23693       89/<- %ecx 0/r32/eax
23694       e9/jump loop/disp32
23695     }
23696 $check-no-breaks:end:
23697     # . restore registers
23698     59/pop-to-ecx
23699     58/pop-to-eax
23700     # . epilogue
23701     89/<- %esp 5/r32/ebp
23702     5d/pop-to-ebp
23703     c3/return
23704 
23705 $check-no-breaks:error:
23706     (write-buffered *(ebp+0x10) "fn ")
23707     8b/-> *(ebp+0xc) 0/r32/eax
23708     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23709     (write-buffered *(ebp+0x10) %eax)
23710     (write-buffered *(ebp+0x10) " has outputs, so you cannot 'break' out of the outermost block. Use 'return'.\n")
23711     (flush *(ebp+0x10))
23712     (stop *(ebp+0x14) 1)
23713     # never gets here
23714 
23715 check-mu-get-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23716     # . prologue
23717     55/push-ebp
23718     89/<- %ebp 4/r32/esp
23719     # . save registers
23720     50/push-eax
23721     51/push-ecx
23722     52/push-edx
23723     53/push-ebx
23724     56/push-esi
23725     57/push-edi
23726     # esi = stmt
23727     8b/-> *(ebp+8) 6/r32/esi
23728     # - check for 0 inouts
23729     # var base/ecx: (addr var) = stmt->inouts->value
23730     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23731     3d/compare-eax-and 0/imm32/false
23732     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-inouts/disp32
23733     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23734     89/<- %ecx 0/r32/eax
23735 $check-mu-get-stmt:check-base:
23736     # - check base type
23737     # if it's an 'addr', check that it's in a register
23738     # var base-type/ebx: (addr type-tree) = lookup(base->type)
23739     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
23740     89/<- %ebx 0/r32/eax
23741     {
23742       81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
23743       0f 85/jump-if-!= break/disp32
23744 $check-mu-get-stmt:base-is-compound:
23745       # if (type->left != addr) break
23746       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
23747       (simple-mu-type? %eax 2)  # addr => eax
23748       3d/compare-eax-and 0/imm32/false
23749       74/jump-if-= break/disp8
23750 $check-mu-get-stmt:base-is-addr:
23751       # now check for register
23752       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
23753       0f 84/jump-if-= $check-mu-get-stmt:error-base-type-addr-but-not-register/disp32
23754 $check-mu-get-stmt:base-is-addr-in-register:
23755       # type->left is now an addr; skip it
23756       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23757       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
23758       0f 85/jump-if-!= $check-mu-get-stmt:error-bad-base/disp32
23759 $check-mu-get-stmt:base-is-addr-to-atom-in-register:
23760       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23761       89/<- %ebx 0/r32/eax
23762     }
23763 $check-mu-get-stmt:check-base-typeinfo:
23764     # ensure type is a container
23765     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
23766     {
23767       75/jump-if-!= break/disp8
23768       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
23769       89/<- %ebx 0/r32/eax
23770     }
23771     # var base-type-id/ebx: type-id = base-type->value
23772     8b/-> *(ebx+4) 3/r32/ebx  # Type-tree-value
23773     (container? %ebx)  # => eax
23774     3d/compare-eax-and 0/imm32/false
23775     0f 84/jump-if-= $check-mu-get-stmt:error-bad-base/disp32
23776     # var base-typeinfo/edx: (addr typeinfo) = find-typeinfo(base-type-id)
23777     # . var container/ecx: (handle typeinfo)
23778     68/push 0/imm32
23779     68/push 0/imm32
23780     89/<- %ecx 4/r32/esp
23781     # .
23782     (find-typeinfo %ebx %ecx)
23783     (lookup *ecx *(ecx+4))  # => eax
23784     # . reclaim container
23785     81 0/subop/add %esp 8/imm32
23786     # .
23787     89/<- %edx 0/r32/eax
23788     # var offset/ecx: (addr stmt-var) = stmt->inouts->next
23789     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23790     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
23791     89/<- %ecx 0/r32/eax
23792     # - check for 1 inout
23793     3d/compare-eax-and 0/imm32/false
23794     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-inouts/disp32
23795     # var offset/ecx: (addr var) = lookup(offset->value)
23796     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
23797     89/<- %ecx 0/r32/eax
23798     # - check for valid field
23799     81 7/subop/compare *(ecx+0x14) -1/imm32/uninitialized  # Var-offset
23800     0f 84/jump-if-= $check-mu-get-stmt:error-bad-field/disp32
23801     # - check for too many inouts
23802     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23803     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
23804     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
23805     3d/compare-eax-and 0/imm32/false
23806     0f 85/jump-if-!= $check-mu-get-stmt:error-too-many-inouts/disp32
23807     # var output/edi: (addr var) = stmt->outputs->value
23808     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
23809     # - check for 0 outputs
23810     3d/compare-eax-and 0/imm32/false
23811     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-outputs/disp32
23812     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23813     89/<- %edi 0/r32/eax
23814 $check-mu-get-stmt:check-output-type:
23815     # - check output type
23816     # must be in register
23817     (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
23818     3d/compare-eax-and 0/imm32
23819     0f 84/jump-if-= $check-mu-get-stmt:error-output-not-in-register/disp32
23820     # must have a non-atomic type
23821     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
23822     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
23823     0f 85/jump-if-!= $check-mu-get-stmt:error-output-type-not-address/disp32
23824     # type must start with (addr ...)
23825     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23826     (simple-mu-type? %eax 2)  # => eax
23827     3d/compare-eax-and 0/imm32/false
23828     0f 84/jump-if-= $check-mu-get-stmt:error-output-type-not-address/disp32
23829 $check-mu-get-stmt:check-output-type-match:
23830     # payload of addr type must match 'type' definition
23831     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
23832     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
23833     # if (payload->right == null) payload = payload->left
23834     81 7/subop/compare *(eax+0xc) 0/imm32/null  # Type-tree-right
23835     {
23836       75/jump-if-!= break/disp8
23837       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23838     }
23839     89/<- %edi 0/r32/eax
23840     # . var output-name/ecx: (addr array byte)
23841     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
23842     89/<- %ecx 0/r32/eax
23843     # . var base-typeinfo-entry/eax: (addr handle typeinfo-entry)
23844     (lookup *(edx+4) *(edx+8))  # Typeinfo-fields Typeinfo-fields => eax
23845     (get %eax %ecx 0x10)  # => eax
23846     # .
23847     (lookup *eax *(eax+4))  # => eax
23848     (lookup *eax *(eax+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
23849     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23850     # .
23851     (type-equal? %edi %eax)  # => eax
23852     3d/compare-eax-and 0/imm32/false
23853     0f 84/jump-if-= $check-mu-get-stmt:error-bad-output-type/disp32
23854     # - check for too many outputs
23855     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
23856     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
23857     3d/compare-eax-and 0/imm32/false
23858     0f 85/jump-if-!= $check-mu-get-stmt:error-too-many-outputs/disp32
23859 $check-mu-get-stmt:end:
23860     # . restore registers
23861     5f/pop-to-edi
23862     5e/pop-to-esi
23863     5b/pop-to-ebx
23864     5a/pop-to-edx
23865     59/pop-to-ecx
23866     58/pop-to-eax
23867     # . epilogue
23868     89/<- %esp 5/r32/ebp
23869     5d/pop-to-ebp
23870     c3/return
23871 
23872 $check-mu-get-stmt:error-too-few-inouts:
23873     (write-buffered *(ebp+0x10) "fn ")
23874     8b/-> *(ebp+0xc) 0/r32/eax
23875     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23876     (write-buffered *(ebp+0x10) %eax)
23877     (write-buffered *(ebp+0x10) ": stmt get: too few inouts (2 required)\n")
23878     (flush *(ebp+0x10))
23879     (stop *(ebp+0x14) 1)
23880     # never gets here
23881 
23882 $check-mu-get-stmt:error-too-many-inouts:
23883     (write-buffered *(ebp+0x10) "fn ")
23884     8b/-> *(ebp+0xc) 0/r32/eax
23885     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23886     (write-buffered *(ebp+0x10) %eax)
23887     (write-buffered *(ebp+0x10) ": stmt get: too many inouts (2 required)\n")
23888     (flush *(ebp+0x10))
23889     (stop *(ebp+0x14) 1)
23890     # never gets here
23891 
23892 $check-mu-get-stmt:error-too-few-outputs:
23893     (write-buffered *(ebp+0x10) "fn ")
23894     8b/-> *(ebp+0xc) 0/r32/eax
23895     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23896     (write-buffered *(ebp+0x10) %eax)
23897     (write-buffered *(ebp+0x10) ": stmt get: must have an output\n")
23898     (flush *(ebp+0x10))
23899     (stop *(ebp+0x14) 1)
23900     # never gets here
23901 
23902 $check-mu-get-stmt:error-too-many-outputs:
23903     (write-buffered *(ebp+0x10) "fn ")
23904     8b/-> *(ebp+0xc) 0/r32/eax
23905     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23906     (write-buffered *(ebp+0x10) %eax)
23907     (write-buffered *(ebp+0x10) ": stmt get: too many outputs (1 required)\n")
23908     (flush *(ebp+0x10))
23909     (stop *(ebp+0x14) 1)
23910     # never gets here
23911 
23912 $check-mu-get-stmt:error-bad-base:
23913     # error("fn " fn ": stmt get: var '" base->name "' must have a 'type' definition\n")
23914     (write-buffered *(ebp+0x10) "fn ")
23915     8b/-> *(ebp+0xc) 0/r32/eax
23916     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23917     (write-buffered *(ebp+0x10) %eax)
23918     (write-buffered *(ebp+0x10) ": stmt get: var '")
23919     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23920     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23921     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23922     (write-buffered *(ebp+0x10) %eax)
23923     (write-buffered *(ebp+0x10) "' must have a 'type' definition\n")
23924     (flush *(ebp+0x10))
23925     (stop *(ebp+0x14) 1)
23926     # never gets here
23927 
23928 $check-mu-get-stmt:error-base-type-addr-but-not-register:
23929     (write-buffered *(ebp+0x10) "fn ")
23930     8b/-> *(ebp+0xc) 0/r32/eax
23931     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23932     (write-buffered *(ebp+0x10) %eax)
23933     (write-buffered *(ebp+0x10) ": stmt get: var '")
23934     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23935     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23936     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23937     (write-buffered *(ebp+0x10) %eax)
23938     (write-buffered *(ebp+0x10) "' is an 'addr' type, and so must live in a register\n")
23939     (flush *(ebp+0x10))
23940     (stop *(ebp+0x14) 1)
23941     # never gets here
23942 
23943 $check-mu-get-stmt:error-bad-field:
23944     # error("fn " fn ": stmt get: type " type " has no member called '" curr->name "'\n")
23945     (write-buffered *(ebp+0x10) "fn ")
23946     8b/-> *(ebp+0xc) 0/r32/eax
23947     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23948     (write-buffered *(ebp+0x10) %eax)
23949     (write-buffered *(ebp+0x10) ": stmt get: type '")
23950     # . write(Type-id->data[tmp])
23951     bf/copy-to-edi Type-id/imm32
23952     8b/-> *(edi+ebx<<2+0xc) 6/r32/esi
23953     {
23954       81 7/subop/compare %esi 0/imm32
23955       74/jump-if-= break/disp8
23956       (write-buffered *(ebp+0x10) %esi)
23957     }
23958     # .
23959     (write-buffered *(ebp+0x10) "' has no member called '")
23960     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
23961     (write-buffered *(ebp+0x10) %eax)
23962     (write-buffered *(ebp+0x10) "'\n")
23963     (flush *(ebp+0x10))
23964     (stop *(ebp+0x14) 1)
23965     # never gets here
23966 
23967 $check-mu-get-stmt:error-output-not-in-register:
23968     (write-buffered *(ebp+0x10) "fn ")
23969     8b/-> *(ebp+0xc) 0/r32/eax
23970     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23971     (write-buffered *(ebp+0x10) %eax)
23972     (write-buffered *(ebp+0x10) ": stmt get: output '")
23973     (lookup *edi *(edi+4))  # Var-name Var-name => eax
23974     (write-buffered *(ebp+0x10) %eax)
23975     (write-buffered *(ebp+0x10) "' is not in a register\n")
23976     (flush *(ebp+0x10))
23977     (stop *(ebp+0x14) 1)
23978     # never gets here
23979 
23980 $check-mu-get-stmt:error-output-type-not-address:
23981     (write-buffered *(ebp+0x10) "fn ")
23982     8b/-> *(ebp+0xc) 0/r32/eax
23983     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23984     (write-buffered *(ebp+0x10) %eax)
23985     (write-buffered *(ebp+0x10) ": stmt get: output must be an addr\n")
23986     (flush *(ebp+0x10))
23987     (stop *(ebp+0x14) 1)
23988     # never gets here
23989 
23990 $check-mu-get-stmt:error-bad-output-type:
23991     (write-buffered *(ebp+0x10) "fn ")
23992     8b/-> *(ebp+0xc) 0/r32/eax
23993     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23994     (write-buffered *(ebp+0x10) %eax)
23995     (write-buffered *(ebp+0x10) ": stmt get: wrong output type for member '")
23996     (write-buffered *(ebp+0x10) %ecx)
23997     (write-buffered *(ebp+0x10) "' of type '")
23998     bf/copy-to-edi Type-id/imm32
23999     8b/-> *(edi+ebx<<2+0xc) 6/r32/esi
24000     {
24001       81 7/subop/compare %esi 0/imm32
24002       74/jump-if-= break/disp8
24003       (write-buffered *(ebp+0x10) %esi)
24004     }
24005     (write-buffered *(ebp+0x10) "'\n")
24006     (flush *(ebp+0x10))
24007     (stop *(ebp+0x14) 1)
24008     # never gets here
24009 
24010 check-mu-index-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
24011     # . prologue
24012     55/push-ebp
24013     89/<- %ebp 4/r32/esp
24014     # . save registers
24015     50/push-eax
24016     51/push-ecx
24017     52/push-edx
24018     53/push-ebx
24019     56/push-esi
24020     57/push-edi
24021     # esi = stmt
24022     8b/-> *(ebp+8) 6/r32/esi
24023     # - check for 0 inouts
24024     # var base/ecx: (addr var) = stmt->inouts->value
24025     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24026 $check-mu-index-stmt:check-no-inouts:
24027     3d/compare-eax-and 0/imm32
24028     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-inouts/disp32
24029     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24030     89/<- %ecx 0/r32/eax
24031     # - check base type is either (addr array ...) in register or (array ...) on stack
24032     # var base-type/ebx: (addr type-tree) = lookup(base->type)
24033     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
24034     89/<- %ebx 0/r32/eax
24035     # if base-type is an atom, abort with a precise error
24036     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
24037     {
24038       74/jump-if-= break/disp8
24039       (simple-mu-type? %ebx 3)  # array => eax
24040       3d/compare-eax-and 0/imm32/false
24041       0f 85/jump-if-!= $check-mu-index-stmt:error-base-array-atom-type/disp32
24042       0f 84/jump-if-= $check-mu-index-stmt:error-base-non-array-type/disp32
24043     }
24044 $check-mu-index-stmt:base-is-compound:
24045     # if type->left not addr or array, abort
24046     {
24047       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24048       (simple-mu-type? %eax 2)  # addr => eax
24049       3d/compare-eax-and 0/imm32/false
24050       75/jump-if-!= break/disp8
24051       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24052       (simple-mu-type? %eax 3)  # array => eax
24053       3d/compare-eax-and 0/imm32/false
24054       75/jump-if-!= break/disp8
24055       e9/jump $check-mu-index-stmt:error-base-non-array-type/disp32
24056     }
24057     # if (type->left == addr) ensure type->right->left == array and type->register exists
24058     {
24059       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24060       (simple-mu-type? %eax 2)  # addr => eax
24061       3d/compare-eax-and 0/imm32/false
24062       74/jump-if-= break/disp8
24063 $check-mu-index-stmt:base-is-addr:
24064       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
24065       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
24066       (simple-mu-type? %eax 3)  # array => eax
24067       3d/compare-eax-and 0/imm32/false
24068       0f 84/jump-if-= $check-mu-index-stmt:error-base-non-array-type/disp32
24069 $check-mu-index-stmt:check-base-addr-is-register:
24070       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
24071       0f 84/jump-if-= $check-mu-index-stmt:error-base-address-array-type-on-stack/disp32
24072     }
24073     # if (type->left == array) ensure type->register doesn't exist
24074     {
24075       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24076       (simple-mu-type? %eax 3)  # array => eax
24077       3d/compare-eax-and 0/imm32/false
24078       74/jump-if-= break/disp8
24079 $check-mu-index-stmt:base-is-array:
24080       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
24081       0f 85/jump-if-!= $check-mu-index-stmt:error-base-array-type-in-register/disp32
24082     }
24083     # if (base-type->left == addr) base-type = base-type->right
24084     {
24085       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24086       (simple-mu-type? %eax 2)  # addr => eax
24087       3d/compare-eax-and 0/imm32/false
24088       74/jump-if-= break/disp8
24089       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
24090       89/<- %ebx 0/r32/eax
24091     }
24092     # - check for 1 inout
24093     # var index/ecx: (addr stmt-var) = stmt->inouts->next->value
24094     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24095     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24096 $check-mu-index-stmt:check-single-inout:
24097     3d/compare-eax-and 0/imm32
24098     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-inouts/disp32
24099     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24100     89/<- %ecx 0/r32/eax
24101     # - check index is either a literal or register
24102     # var index-type/edx: (addr type-tree)
24103     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
24104     89/<- %edx 0/r32/eax
24105     # if index type is an atom, it must be a literal or int
24106     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
24107     {
24108       74/jump-if-= break/disp8
24109 $check-mu-index-stmt:index-type-is-atom:
24110       (simple-mu-type? %edx 0)  # literal => eax
24111       3d/compare-eax-and 0/imm32/false
24112       75/jump-if-!= $check-mu-index-stmt:index-type-done/disp8
24113       (simple-mu-type? %edx 1)  # int => eax
24114       3d/compare-eax-and 0/imm32/false
24115       75/jump-if-!= $check-mu-index-stmt:index-type-done/disp8
24116       (simple-mu-type? %edx 7)  # offset => eax
24117       3d/compare-eax-and 0/imm32/false
24118       0f 85/jump-if-!= $check-mu-index-stmt:error-index-offset-atom-type/disp32
24119       e9/jump $check-mu-index-stmt:error-invalid-index-type/disp32
24120     }
24121     # if index type is a non-atom: it must be an offset
24122     {
24123       75/jump-if-!= break/disp8
24124 $check-mu-index-stmt:index-type-is-non-atom:
24125       (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
24126       (simple-mu-type? %eax 7)  # offset => eax
24127       3d/compare-eax-and 0/imm32/false
24128       0f 84/jump-if-= $check-mu-index-stmt:error-invalid-index-type/disp32
24129     }
24130 $check-mu-index-stmt:index-type-done:
24131     # check index is either a literal or in a register
24132     {
24133       (simple-mu-type? %edx 0)  # literal => eax
24134       3d/compare-eax-and 0/imm32/false
24135       75/jump-if-!= break/disp8
24136 $check-mu-index-stmt:check-index-in-register:
24137       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
24138       0f 84/jump-if-= $check-mu-index-stmt:error-index-on-stack/disp32
24139     }
24140     # - if index is an 'int', check that element type of base has size 1, 2, 4 or 8 bytes.
24141     {
24142       (simple-mu-type? %edx 1)  # int => eax
24143       3d/compare-eax-and 0/imm32/false
24144       74/jump-if-= break/disp8
24145 $check-mu-index-stmt:check-index-can-be-int:
24146       (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24147       (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24148       (array-element-size %eax)  # => eax
24149       3d/compare-eax-and 1/imm32
24150       74/jump-if-= break/disp8
24151       3d/compare-eax-and 2/imm32
24152       74/jump-if-= break/disp8
24153       3d/compare-eax-and 4/imm32
24154       74/jump-if-= break/disp8
24155       3d/compare-eax-and 8/imm32
24156       74/jump-if-= break/disp8
24157       e9/jump $check-mu-index-stmt:error-index-needs-offset/disp32
24158     }
24159     # - check for too many inouts
24160     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24161     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24162     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24163     3d/compare-eax-and 0/imm32/false
24164     0f 85/jump-if-!= $check-mu-index-stmt:error-too-many-inouts/disp32
24165     # - check for 0 outputs
24166     # var output/edi: (addr var) = stmt->outputs->value
24167     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24168     3d/compare-eax-and 0/imm32/false
24169     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-outputs/disp32
24170     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24171     89/<- %edi 0/r32/eax
24172     # - check output type
24173     # must have a non-atomic type
24174     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
24175     89/<- %edx 0/r32/eax
24176     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
24177     0f 85/jump-if-!= $check-mu-index-stmt:error-output-type-not-address/disp32
24178     # type must start with (addr ...)
24179     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
24180     (simple-mu-type? %eax 2)  # addr => eax
24181     3d/compare-eax-and 0/imm32/false
24182     0f 84/jump-if-= $check-mu-index-stmt:error-output-type-not-address/disp32
24183     # if tail(base-type) != tail(output-type) abort
24184     (type-tail %ebx)  # => eax
24185     89/<- %ebx 0/r32/eax
24186     (type-tail %edx)  # => eax
24187     (type-equal? %ebx %eax)  # => eax
24188     3d/compare-eax-and 0/imm32/false
24189     0f 84/jump-if-= $check-mu-index-stmt:error-bad-output-type/disp32
24190     # - check for too many outputs
24191     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24192     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24193     3d/compare-eax-and 0/imm32/false
24194     0f 85/jump-if-!= $check-mu-index-stmt:error-too-many-outputs/disp32
24195 $check-mu-index-stmt:end:
24196     # . restore registers
24197     5f/pop-to-edi
24198     5e/pop-to-esi
24199     5b/pop-to-ebx
24200     5a/pop-to-edx
24201     59/pop-to-ecx
24202     58/pop-to-eax
24203     # . epilogue
24204     89/<- %esp 5/r32/ebp
24205     5d/pop-to-ebp
24206     c3/return
24207 
24208 $check-mu-index-stmt:error-base-non-array-type:
24209     (write-buffered *(ebp+0x10) "fn ")
24210     8b/-> *(ebp+0xc) 0/r32/eax
24211     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24212     (write-buffered *(ebp+0x10) %eax)
24213     (write-buffered *(ebp+0x10) ": stmt index: var '")
24214     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24215     (write-buffered *(ebp+0x10) %eax)
24216     (write-buffered *(ebp+0x10) "' is not an array\n")
24217     (flush *(ebp+0x10))
24218     (stop *(ebp+0x14) 1)
24219     # never gets here
24220 
24221 $check-mu-index-stmt:error-base-array-atom-type:
24222     (write-buffered *(ebp+0x10) "fn ")
24223     8b/-> *(ebp+0xc) 0/r32/eax
24224     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24225     (write-buffered *(ebp+0x10) %eax)
24226     (write-buffered *(ebp+0x10) ": stmt index: array '")
24227     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24228     (write-buffered *(ebp+0x10) %eax)
24229     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
24230     (flush *(ebp+0x10))
24231     (stop *(ebp+0x14) 1)
24232     # never gets here
24233 
24234 $check-mu-index-stmt:error-base-address-array-type-on-stack:
24235     (write-buffered *(ebp+0x10) "fn ")
24236     8b/-> *(ebp+0xc) 0/r32/eax
24237     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24238     (write-buffered *(ebp+0x10) %eax)
24239     (write-buffered *(ebp+0x10) ": stmt index: var '")
24240     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24241     (write-buffered *(ebp+0x10) %eax)
24242     (write-buffered *(ebp+0x10) "' is an addr to an array, and so must live in a register\n")
24243     (flush *(ebp+0x10))
24244     (stop *(ebp+0x14) 1)
24245     # never gets here
24246 
24247 $check-mu-index-stmt:error-base-array-type-in-register:
24248     (write-buffered *(ebp+0x10) "fn ")
24249     8b/-> *(ebp+0xc) 0/r32/eax
24250     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24251     (write-buffered *(ebp+0x10) %eax)
24252     (write-buffered *(ebp+0x10) ": stmt index: var '")
24253     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24254     (write-buffered *(ebp+0x10) %eax)
24255     (write-buffered *(ebp+0x10) "' is an array, and so must live on the stack\n")
24256     (flush *(ebp+0x10))
24257     (stop *(ebp+0x14) 1)
24258     # never gets here
24259 
24260 $check-mu-index-stmt:error-too-few-inouts:
24261     (write-buffered *(ebp+0x10) "fn ")
24262     8b/-> *(ebp+0xc) 0/r32/eax
24263     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24264     (write-buffered *(ebp+0x10) %eax)
24265     (write-buffered *(ebp+0x10) ": stmt index: too few inouts (2 required)\n")
24266     (flush *(ebp+0x10))
24267     (stop *(ebp+0x14) 1)
24268     # never gets here
24269 
24270 $check-mu-index-stmt:error-invalid-index-type:
24271     (write-buffered *(ebp+0x10) "fn ")
24272     8b/-> *(ebp+0xc) 0/r32/eax
24273     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24274     (write-buffered *(ebp+0x10) %eax)
24275     (write-buffered *(ebp+0x10) ": stmt index: second argument '")
24276     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24277     (write-buffered *(ebp+0x10) %eax)
24278     (write-buffered *(ebp+0x10) "' must be an int or offset\n")
24279     (flush *(ebp+0x10))
24280     (stop *(ebp+0x14) 1)
24281     # never gets here
24282 
24283 $check-mu-index-stmt:error-index-offset-atom-type:
24284     (write-buffered *(ebp+0x10) "fn ")
24285     8b/-> *(ebp+0xc) 0/r32/eax
24286     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24287     (write-buffered *(ebp+0x10) %eax)
24288     (write-buffered *(ebp+0x10) ": stmt index: offset '")
24289     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24290     (write-buffered *(ebp+0x10) %eax)
24291     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
24292     (flush *(ebp+0x10))
24293     (stop *(ebp+0x14) 1)
24294     # never gets here
24295 
24296 $check-mu-index-stmt:error-index-on-stack:
24297     (write-buffered *(ebp+0x10) "fn ")
24298     8b/-> *(ebp+0xc) 0/r32/eax
24299     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24300     (write-buffered *(ebp+0x10) %eax)
24301     (write-buffered *(ebp+0x10) ": stmt index: second argument '")
24302     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24303     (write-buffered *(ebp+0x10) %eax)
24304     (write-buffered *(ebp+0x10) "' must be in a register\n")
24305     (flush *(ebp+0x10))
24306     (stop *(ebp+0x14) 1)
24307     # never gets here
24308 
24309 $check-mu-index-stmt:error-index-needs-offset:
24310     (write-buffered *(ebp+0x10) "fn ")
24311     8b/-> *(ebp+0xc) 0/r32/eax
24312     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24313     (write-buffered *(ebp+0x10) %eax)
24314     (write-buffered *(ebp+0x10) ": stmt index: cannot take an int for array '")
24315     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24316     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24317     (lookup *eax *(eax+4))  # Var-name Var-name => eax
24318     (write-buffered *(ebp+0x10) %eax)
24319     (write-buffered *(ebp+0x10) "'; create an offset instead. See mu.md for details.\n")
24320     (flush *(ebp+0x10))
24321     (stop *(ebp+0x14) 1)
24322     # never gets here
24323 
24324 $check-mu-index-stmt:error-too-many-inouts:
24325     (write-buffered *(ebp+0x10) "fn ")
24326     8b/-> *(ebp+0xc) 0/r32/eax
24327     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24328     (write-buffered *(ebp+0x10) %eax)
24329     (write-buffered *(ebp+0x10) ": stmt index: too many inouts (2 required)\n")
24330     (flush *(ebp+0x10))
24331     (stop *(ebp+0x14) 1)
24332     # never gets here
24333 
24334 $check-mu-index-stmt:error-too-few-outputs:
24335     (write-buffered *(ebp+0x10) "fn ")
24336     8b/-> *(ebp+0xc) 0/r32/eax
24337     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24338     (write-buffered *(ebp+0x10) %eax)
24339     (write-buffered *(ebp+0x10) ": stmt index: must have an output\n")
24340     (flush *(ebp+0x10))
24341     (stop *(ebp+0x14) 1)
24342     # never gets here
24343 
24344 $check-mu-index-stmt:error-too-many-outputs:
24345     (write-buffered *(ebp+0x10) "fn ")
24346     8b/-> *(ebp+0xc) 0/r32/eax
24347     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24348     (write-buffered *(ebp+0x10) %eax)
24349     (write-buffered *(ebp+0x10) ": stmt index: too many outputs (1 required)\n")
24350     (flush *(ebp+0x10))
24351     (stop *(ebp+0x14) 1)
24352     # never gets here
24353 
24354 $check-mu-index-stmt:error-output-not-in-register:
24355     (write-buffered *(ebp+0x10) "fn ")
24356     8b/-> *(ebp+0xc) 0/r32/eax
24357     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24358     (write-buffered *(ebp+0x10) %eax)
24359     (write-buffered *(ebp+0x10) ": stmt index: output '")
24360     (lookup *edi *(edi+4))  # Var-name Var-name => eax
24361     (write-buffered *(ebp+0x10) %eax)
24362     (write-buffered *(ebp+0x10) "' is not in a register\n")
24363     (flush *(ebp+0x10))
24364     (stop *(ebp+0x14) 1)
24365     # never gets here
24366 
24367 $check-mu-index-stmt:error-output-type-not-address:
24368     (write-buffered *(ebp+0x10) "fn ")
24369     8b/-> *(ebp+0xc) 0/r32/eax
24370     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24371     (write-buffered *(ebp+0x10) %eax)
24372     (write-buffered *(ebp+0x10) ": stmt index: output '")
24373     (lookup *edi *(edi+4))  # Var-name Var-name => eax
24374     (write-buffered *(ebp+0x10) %eax)
24375     (write-buffered *(ebp+0x10) "' must be an addr\n")
24376     (flush *(ebp+0x10))
24377     (stop *(ebp+0x14) 1)
24378     # never gets here
24379 
24380 $check-mu-index-stmt:error-bad-output-type:
24381     (write-buffered *(ebp+0x10) "fn ")
24382     8b/-> *(ebp+0xc) 0/r32/eax
24383     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24384     (write-buffered *(ebp+0x10) %eax)
24385     (write-buffered *(ebp+0x10) ": stmt index: output '")
24386     (lookup *edi *(edi+4))  # Var-name Var-name => eax
24387     (write-buffered *(ebp+0x10) %eax)
24388     (write-buffered *(ebp+0x10) "' does not have the right type\n")
24389     (flush *(ebp+0x10))
24390     (stop *(ebp+0x14) 1)
24391     # never gets here
24392 
24393 check-mu-length-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
24394     # . prologue
24395     55/push-ebp
24396     89/<- %ebp 4/r32/esp
24397     # . save registers
24398     50/push-eax
24399     51/push-ecx
24400     52/push-edx
24401     53/push-ebx
24402     56/push-esi
24403     57/push-edi
24404     # esi = stmt
24405     8b/-> *(ebp+8) 6/r32/esi
24406     # - check for 0 inouts
24407     # var base/ecx: (addr var) = stmt->inouts->value
24408     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24409 $check-mu-length-stmt:check-no-inouts:
24410     3d/compare-eax-and 0/imm32
24411     0f 84/jump-if-= $check-mu-length-stmt:error-too-few-inouts/disp32
24412     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24413     89/<- %ecx 0/r32/eax
24414     # - check base type is either (addr array ...) in register or (array ...) on stack
24415     # var base-type/ebx: (addr type-tree) = lookup(base->type)
24416     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
24417     89/<- %ebx 0/r32/eax
24418     # if base-type is an atom, abort with a precise error
24419     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
24420     {
24421       74/jump-if-= break/disp8
24422       (simple-mu-type? %ebx 3)  # array => eax
24423       3d/compare-eax-and 0/imm32/false
24424       0f 85/jump-if-!= $check-mu-length-stmt:error-base-array-atom-type/disp32
24425       0f 84/jump-if-= $check-mu-length-stmt:error-base-non-array-type/disp32
24426     }
24427 $check-mu-length-stmt:base-is-compound:
24428     # if type->left not addr or array, abort
24429     {
24430       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24431       (simple-mu-type? %eax 2)  # addr => eax
24432       3d/compare-eax-and 0/imm32/false
24433       75/jump-if-!= break/disp8
24434       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24435       (simple-mu-type? %eax 3)  # array => eax
24436       3d/compare-eax-and 0/imm32/false
24437       75/jump-if-!= break/disp8
24438       e9/jump $check-mu-length-stmt:error-base-non-array-type/disp32
24439     }
24440     # if (type->left == addr) ensure type->right->left == array and type->register exists
24441     {
24442       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24443       (simple-mu-type? %eax 2)  # addr => eax
24444       3d/compare-eax-and 0/imm32/false
24445       74/jump-if-= break/disp8
24446 $check-mu-length-stmt:base-is-addr:
24447       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
24448       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
24449       (simple-mu-type? %eax 3)  # array => eax
24450       3d/compare-eax-and 0/imm32/false
24451       0f 84/jump-if-= $check-mu-length-stmt:error-base-non-array-type/disp32
24452 $check-mu-length-stmt:check-base-addr-is-register:
24453       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
24454       0f 84/jump-if-= $check-mu-length-stmt:error-base-address-array-type-on-stack/disp32
24455     }
24456     # if (type->left == array) ensure type->register doesn't exist
24457     {
24458       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24459       (simple-mu-type? %eax 3)  # array => eax
24460       3d/compare-eax-and 0/imm32/false
24461       74/jump-if-= break/disp8
24462 $check-mu-length-stmt:base-is-array:
24463       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
24464       0f 85/jump-if-!= $check-mu-length-stmt:error-base-array-type-in-register/disp32
24465     }
24466     # if (base-type->left == addr) base-type = base-type->right
24467     {
24468       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24469       (simple-mu-type? %eax 2)  # addr => eax
24470       3d/compare-eax-and 0/imm32/false
24471       74/jump-if-= break/disp8
24472       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
24473       89/<- %ebx 0/r32/eax
24474     }
24475     # - check for too many inouts
24476     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24477     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24478     3d/compare-eax-and 0/imm32/false
24479     0f 85/jump-if-!= $check-mu-length-stmt:error-too-many-inouts/disp32
24480     # - check for 0 outputs
24481     # var output/edi: (addr var) = stmt->outputs->value
24482     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24483     3d/compare-eax-and 0/imm32/false
24484     0f 84/jump-if-= $check-mu-length-stmt:error-too-few-outputs/disp32
24485     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24486     89/<- %edi 0/r32/eax
24487     # - check output type
24488     # must have a non-atomic type
24489     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
24490     (simple-mu-type? %eax 1)  # int => eax
24491     3d/compare-eax-and 0/imm32/false
24492     0f 84/jump-if-= $check-mu-length-stmt:error-invalid-output-type/disp32
24493     # - check for too many outputs
24494     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24495     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24496     3d/compare-eax-and 0/imm32/false
24497     0f 85/jump-if-!= $check-mu-length-stmt:error-too-many-outputs/disp32
24498 $check-mu-length-stmt:end:
24499     # . restore registers
24500     5f/pop-to-edi
24501     5e/pop-to-esi
24502     5b/pop-to-ebx
24503     5a/pop-to-edx
24504     59/pop-to-ecx
24505     58/pop-to-eax
24506     # . epilogue
24507     89/<- %esp 5/r32/ebp
24508     5d/pop-to-ebp
24509     c3/return
24510 
24511 $check-mu-length-stmt:error-base-non-array-type:
24512     (write-buffered *(ebp+0x10) "fn ")
24513     8b/-> *(ebp+0xc) 0/r32/eax
24514     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24515     (write-buffered *(ebp+0x10) %eax)
24516     (write-buffered *(ebp+0x10) ": stmt length: var '")
24517     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24518     (write-buffered *(ebp+0x10) %eax)
24519     (write-buffered *(ebp+0x10) "' is not an array\n")
24520     (flush *(ebp+0x10))
24521     (stop *(ebp+0x14) 1)
24522     # never gets here
24523 
24524 $check-mu-length-stmt:error-base-array-atom-type:
24525     (write-buffered *(ebp+0x10) "fn ")
24526     8b/-> *(ebp+0xc) 0/r32/eax
24527     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24528     (write-buffered *(ebp+0x10) %eax)
24529     (write-buffered *(ebp+0x10) ": stmt length: array '")
24530     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24531     (write-buffered *(ebp+0x10) %eax)
24532     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
24533     (flush *(ebp+0x10))
24534     (stop *(ebp+0x14) 1)
24535     # never gets here
24536 
24537 $check-mu-length-stmt:error-base-address-array-type-on-stack:
24538     (write-buffered *(ebp+0x10) "fn ")
24539     8b/-> *(ebp+0xc) 0/r32/eax
24540     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24541     (write-buffered *(ebp+0x10) %eax)
24542     (write-buffered *(ebp+0x10) ": stmt length: var '")
24543     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24544     (write-buffered *(ebp+0x10) %eax)
24545     (write-buffered *(ebp+0x10) "' is an addr to an array, and so must live in a register\n")
24546     (flush *(ebp+0x10))
24547     (stop *(ebp+0x14) 1)
24548     # never gets here
24549 
24550 $check-mu-length-stmt:error-base-array-type-in-register:
24551     (write-buffered *(ebp+0x10) "fn ")
24552     8b/-> *(ebp+0xc) 0/r32/eax
24553     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24554     (write-buffered *(ebp+0x10) %eax)
24555     (write-buffered *(ebp+0x10) ": stmt length: var '")
24556     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24557     (write-buffered *(ebp+0x10) %eax)
24558     (write-buffered *(ebp+0x10) "' is an array, and so must live on the stack\n")
24559     (flush *(ebp+0x10))
24560     (stop *(ebp+0x14) 1)
24561     # never gets here
24562 
24563 $check-mu-length-stmt:error-too-few-inouts:
24564     (write-buffered *(ebp+0x10) "fn ")
24565     8b/-> *(ebp+0xc) 0/r32/eax
24566     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24567     (write-buffered *(ebp+0x10) %eax)
24568     (write-buffered *(ebp+0x10) ": stmt length: too few inouts (1 required)\n")
24569     (flush *(ebp+0x10))
24570     (stop *(ebp+0x14) 1)
24571     # never gets here
24572 
24573 $check-mu-length-stmt:error-invalid-index-type:
24574     (write-buffered *(ebp+0x10) "fn ")
24575     8b/-> *(ebp+0xc) 0/r32/eax
24576     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24577     (write-buffered *(ebp+0x10) %eax)
24578     (write-buffered *(ebp+0x10) ": stmt length: second argument '")
24579     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24580     (write-buffered *(ebp+0x10) %eax)
24581     (write-buffered *(ebp+0x10) "' must be an int or offset\n")
24582     (flush *(ebp+0x10))
24583     (stop *(ebp+0x14) 1)
24584     # never gets here
24585 
24586 $check-mu-length-stmt:error-index-offset-atom-type:
24587     (write-buffered *(ebp+0x10) "fn ")
24588     8b/-> *(ebp+0xc) 0/r32/eax
24589     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24590     (write-buffered *(ebp+0x10) %eax)
24591     (write-buffered *(ebp+0x10) ": stmt length: offset '")
24592     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24593     (write-buffered *(ebp+0x10) %eax)
24594     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
24595     (flush *(ebp+0x10))
24596     (stop *(ebp+0x14) 1)
24597     # never gets here
24598 
24599 $check-mu-length-stmt:error-index-on-stack:
24600     (write-buffered *(ebp+0x10) "fn ")
24601     8b/-> *(ebp+0xc) 0/r32/eax
24602     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24603     (write-buffered *(ebp+0x10) %eax)
24604     (write-buffered *(ebp+0x10) ": stmt length: second argument '")
24605     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24606     (write-buffered *(ebp+0x10) %eax)
24607     (write-buffered *(ebp+0x10) "' must be in a register\n")
24608     (flush *(ebp+0x10))
24609     (stop *(ebp+0x14) 1)
24610     # never gets here
24611 
24612 $check-mu-length-stmt:error-index-needs-offset:
24613     (write-buffered *(ebp+0x10) "fn ")
24614     8b/-> *(ebp+0xc) 0/r32/eax
24615     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24616     (write-buffered *(ebp+0x10) %eax)
24617     (write-buffered *(ebp+0x10) ": stmt length: cannot take an int for array '")
24618     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24619     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24620     (lookup *eax *(eax+4))  # Var-name Var-name => eax
24621     (write-buffered *(ebp+0x10) %eax)
24622     (write-buffered *(ebp+0x10) "'; create an offset instead. See mu.md for details.\n")
24623     (flush *(ebp+0x10))
24624     (stop *(ebp+0x14) 1)
24625     # never gets here
24626 
24627 $check-mu-length-stmt:error-too-many-inouts:
24628     (write-buffered *(ebp+0x10) "fn ")
24629     8b/-> *(ebp+0xc) 0/r32/eax
24630     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24631     (write-buffered *(ebp+0x10) %eax)
24632     (write-buffered *(ebp+0x10) ": stmt length: too many inouts (1 required)\n")
24633     (flush *(ebp+0x10))
24634     (stop *(ebp+0x14) 1)
24635     # never gets here
24636 
24637 $check-mu-length-stmt:error-too-few-outputs:
24638     (write-buffered *(ebp+0x10) "fn ")
24639     8b/-> *(ebp+0xc) 0/r32/eax
24640     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24641     (write-buffered *(ebp+0x10) %eax)
24642     (write-buffered *(ebp+0x10) ": stmt length: must have an output\n")
24643     (flush *(ebp+0x10))
24644     (stop *(ebp+0x14) 1)
24645     # never gets here
24646 
24647 $check-mu-length-stmt:error-too-many-outputs:
24648     (write-buffered *(ebp+0x10) "fn ")
24649     8b/-> *(ebp+0xc) 0/r32/eax
24650     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24651     (write-buffered *(ebp+0x10) %eax)
24652     (write-buffered *(ebp+0x10) ": stmt length: too many outputs (1 required)\n")
24653     (flush *(ebp+0x10))
24654     (stop *(ebp+0x14) 1)
24655     # never gets here
24656 
24657 $check-mu-length-stmt:error-output-not-in-register:
24658     (write-buffered *(ebp+0x10) "fn ")
24659     8b/-> *(ebp+0xc) 0/r32/eax
24660     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24661     (write-buffered *(ebp+0x10) %eax)
24662     (write-buffered *(ebp+0x10) ": stmt length: output '")
24663     (lookup *edi *(edi+4))  # Var-name Var-name => eax
24664     (write-buffered *(ebp+0x10) %eax)
24665     (write-buffered *(ebp+0x10) "' is not in a register\n")
24666     (flush *(ebp+0x10))
24667     (stop *(ebp+0x14) 1)
24668     # never gets here
24669 
24670 $check-mu-length-stmt:error-invalid-output-type:
24671     (write-buffered *(ebp+0x10) "fn ")
24672     8b/-> *(ebp+0xc) 0/r32/eax
24673     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24674     (write-buffered *(ebp+0x10) %eax)
24675     (write-buffered *(ebp+0x10) ": stmt length: output '")
24676     (lookup *edi *(edi+4))  # Var-name Var-name => eax
24677     (write-buffered *(ebp+0x10) %eax)
24678     (write-buffered *(ebp+0x10) "' does not have the right type\n")
24679     (flush *(ebp+0x10))
24680     (stop *(ebp+0x14) 1)
24681     # never gets here
24682 
24683 check-mu-compute-offset-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
24684     # . prologue
24685     55/push-ebp
24686     89/<- %ebp 4/r32/esp
24687     # . save registers
24688     50/push-eax
24689     51/push-ecx
24690     52/push-edx
24691     53/push-ebx
24692     56/push-esi
24693     57/push-edi
24694     # esi = stmt
24695     8b/-> *(ebp+8) 6/r32/esi
24696     # - check for 0 inouts
24697     # var base/ecx: (addr var) = stmt->inouts->value
24698     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24699 $check-mu-compute-offset-stmt:check-no-inouts:
24700     3d/compare-eax-and 0/imm32
24701     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-inouts/disp32
24702     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24703     89/<- %ecx 0/r32/eax
24704     # - check base type is either (addr array ...) in register or (array ...) on stack
24705     # var base-type/ebx: (addr type-tree) = lookup(base->type)
24706     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
24707     89/<- %ebx 0/r32/eax
24708     # if base-type is an atom, abort with a precise error
24709     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
24710     {
24711       74/jump-if-= break/disp8
24712       (simple-mu-type? %ebx 3)  # array => eax
24713       3d/compare-eax-and 0/imm32/false
24714       0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-base-array-atom-type/disp32
24715       0f 84/jump-if-= $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
24716     }
24717 $check-mu-compute-offset-stmt:base-is-compound:
24718     # if type->left not addr or array, abort
24719     {
24720       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24721       (simple-mu-type? %eax 2)  # addr => eax
24722       3d/compare-eax-and 0/imm32/false
24723       75/jump-if-!= break/disp8
24724       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24725       (simple-mu-type? %eax 3)  # array => eax
24726       3d/compare-eax-and 0/imm32/false
24727       75/jump-if-!= break/disp8
24728       e9/jump $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
24729     }
24730     # if (type->left == addr) ensure type->right->left == array and type->register exists
24731     {
24732       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24733       (simple-mu-type? %eax 2)  # addr => eax
24734       3d/compare-eax-and 0/imm32/false
24735       74/jump-if-= break/disp8
24736 $check-mu-compute-offset-stmt:base-is-addr:
24737       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
24738       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
24739       (simple-mu-type? %eax 3)  # array => eax
24740       3d/compare-eax-and 0/imm32/false
24741       0f 84/jump-if-= $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
24742     }
24743     # if (base-type->left == addr) base-type = base-type->right
24744     {
24745       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24746       (simple-mu-type? %eax 2)  # addr => eax
24747       3d/compare-eax-and 0/imm32/false
24748       74/jump-if-= break/disp8
24749       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
24750       89/<- %ebx 0/r32/eax
24751     }
24752     # - check for 1 inout
24753     # var index/ecx: (addr stmt-var) = stmt->inouts->next->value
24754     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24755     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24756 $check-mu-compute-offset-stmt:check-single-inout:
24757     3d/compare-eax-and 0/imm32
24758     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-inouts/disp32
24759     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24760     89/<- %ecx 0/r32/eax
24761     # - check index is either a literal or register
24762     # var index-type/edx: (addr type-tree)
24763     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
24764     89/<- %edx 0/r32/eax
24765     # index type must be a literal or int
24766     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
24767     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-invalid-index-type/disp32
24768     {
24769 $check-mu-compute-offset-stmt:index-type-is-atom:
24770       (simple-mu-type? %edx 0)  # literal => eax
24771       3d/compare-eax-and 0/imm32/false
24772       75/jump-if-!= break/disp8
24773       (simple-mu-type? %edx 1)  # int => eax
24774       3d/compare-eax-and 0/imm32/false
24775       75/jump-if-!= break/disp8
24776       e9/jump $check-mu-compute-offset-stmt:error-invalid-index-type/disp32
24777     }
24778     # - check for too many inouts
24779     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24780     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24781     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24782     3d/compare-eax-and 0/imm32/false
24783     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-too-many-inouts/disp32
24784     # - check for 0 outputs
24785     # var output/edi: (addr var) = stmt->outputs->value
24786     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24787     3d/compare-eax-and 0/imm32/false
24788     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-outputs/disp32
24789     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24790     89/<- %edi 0/r32/eax
24791     # - check output type
24792     # must have a non-atomic type
24793     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
24794     89/<- %edx 0/r32/eax
24795     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
24796     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-output-type-not-offset/disp32
24797     # type must start with (offset ...)
24798     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
24799     (simple-mu-type? %eax 7)  # offset => eax
24800     3d/compare-eax-and 0/imm32/false
24801     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-output-type-not-offset/disp32
24802     # if tail(base-type) != tail(output-type) abort
24803     (type-tail %ebx)  # => eax
24804     89/<- %ebx 0/r32/eax
24805     (type-tail %edx)  # => eax
24806     (type-equal? %ebx %eax)  # => eax
24807     3d/compare-eax-and 0/imm32/false
24808     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-bad-output-type/disp32
24809     # - check for too many outputs
24810     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24811     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24812     3d/compare-eax-and 0/imm32/false
24813     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-too-many-outputs/disp32
24814 $check-mu-compute-offset-stmt:end:
24815     # . restore registers
24816     5f/pop-to-edi
24817     5e/pop-to-esi
24818     5b/pop-to-ebx
24819     5a/pop-to-edx
24820     59/pop-to-ecx
24821     58/pop-to-eax
24822     # . epilogue
24823     89/<- %esp 5/r32/ebp
24824     5d/pop-to-ebp
24825     c3/return
24826 
24827 $check-mu-compute-offset-stmt:error-base-non-array-type:
24828     (write-buffered *(ebp+0x10) "fn ")
24829     8b/-> *(ebp+0xc) 0/r32/eax
24830     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24831     (write-buffered *(ebp+0x10) %eax)
24832     (write-buffered *(ebp+0x10) ": stmt compute-offset: var '")
24833     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24834     (write-buffered *(ebp+0x10) %eax)
24835     (write-buffered *(ebp+0x10) "' is not an array\n")
24836     (flush *(ebp+0x10))
24837     (stop *(ebp+0x14) 1)
24838     # never gets here
24839 
24840 $check-mu-compute-offset-stmt:error-base-array-atom-type:
24841     (write-buffered *(ebp+0x10) "fn ")
24842     8b/-> *(ebp+0xc) 0/r32/eax
24843     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24844     (write-buffered *(ebp+0x10) %eax)
24845     (write-buffered *(ebp+0x10) ": stmt compute-offset: array '")
24846     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24847     (write-buffered *(ebp+0x10) %eax)
24848     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
24849     (flush *(ebp+0x10))
24850     (stop *(ebp+0x14) 1)
24851     # never gets here
24852 
24853 $check-mu-compute-offset-stmt:error-too-few-inouts:
24854     (write-buffered *(ebp+0x10) "fn ")
24855     8b/-> *(ebp+0xc) 0/r32/eax
24856     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24857     (write-buffered *(ebp+0x10) %eax)
24858     (write-buffered *(ebp+0x10) ": stmt compute-offset: too few inouts (2 required)\n")
24859     (flush *(ebp+0x10))
24860     (stop *(ebp+0x14) 1)
24861     # never gets here
24862 
24863 $check-mu-compute-offset-stmt:error-invalid-index-type:
24864     (write-buffered *(ebp+0x10) "fn ")
24865     8b/-> *(ebp+0xc) 0/r32/eax
24866     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24867     (write-buffered *(ebp+0x10) %eax)
24868     (write-buffered *(ebp+0x10) ": stmt compute-offset: second argument '")
24869     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24870     (write-buffered *(ebp+0x10) %eax)
24871     (write-buffered *(ebp+0x10) "' must be an int\n")
24872     (flush *(ebp+0x10))
24873     (stop *(ebp+0x14) 1)
24874     # never gets here
24875 
24876 $check-mu-compute-offset-stmt:error-index-offset-atom-type:
24877     (write-buffered *(ebp+0x10) "fn ")
24878     8b/-> *(ebp+0xc) 0/r32/eax
24879     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24880     (write-buffered *(ebp+0x10) %eax)
24881     (write-buffered *(ebp+0x10) ": stmt compute-offset: offset '")
24882     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24883     (write-buffered *(ebp+0x10) %eax)
24884     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
24885     (flush *(ebp+0x10))
24886     (stop *(ebp+0x14) 1)
24887     # never gets here
24888 
24889 $check-mu-compute-offset-stmt:error-index-on-stack:
24890     (write-buffered *(ebp+0x10) "fn ")
24891     8b/-> *(ebp+0xc) 0/r32/eax
24892     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24893     (write-buffered *(ebp+0x10) %eax)
24894     (write-buffered *(ebp+0x10) ": stmt compute-offset: second argument '")
24895     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24896     (write-buffered *(ebp+0x10) %eax)
24897     (write-buffered *(ebp+0x10) "' must be in a register\n")
24898     (flush *(ebp+0x10))
24899     (stop *(ebp+0x14) 1)
24900     # never gets here
24901 
24902 $check-mu-compute-offset-stmt:error-too-many-inouts:
24903     (write-buffered *(ebp+0x10) "fn ")
24904     8b/-> *(ebp+0xc) 0/r32/eax
24905     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24906     (write-buffered *(ebp+0x10) %eax)
24907     (write-buffered *(ebp+0x10) ": stmt compute-offset: too many inouts (2 required)\n")
24908     (flush *(ebp+0x10))
24909     (stop *(ebp+0x14) 1)
24910     # never gets here
24911 
24912 $check-mu-compute-offset-stmt:error-too-few-outputs:
24913     (write-buffered *(ebp+0x10) "fn ")
24914     8b/-> *(ebp+0xc) 0/r32/eax
24915     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24916     (write-buffered *(ebp+0x10) %eax)
24917     (write-buffered *(ebp+0x10) ": stmt compute-offset: must have an output\n")
24918     (flush *(ebp+0x10))
24919     (stop *(ebp+0x14) 1)
24920     # never gets here
24921 
24922 $check-mu-compute-offset-stmt:error-too-many-outputs:
24923     (write-buffered *(ebp+0x10) "fn ")
24924     8b/-> *(ebp+0xc) 0/r32/eax
24925     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24926     (write-buffered *(ebp+0x10) %eax)
24927     (write-buffered *(ebp+0x10) ": stmt compute-offset: too many outputs (1 required)\n")
24928     (flush *(ebp+0x10))
24929     (stop *(ebp+0x14) 1)
24930     # never gets here
24931 
24932 $check-mu-compute-offset-stmt:error-output-not-in-register:
24933     (write-buffered *(ebp+0x10) "fn ")
24934     8b/-> *(ebp+0xc) 0/r32/eax
24935     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24936     (write-buffered *(ebp+0x10) %eax)
24937     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
24938     (lookup *edi *(edi+4))  # Var-name Var-name => eax
24939     (write-buffered *(ebp+0x10) %eax)
24940     (write-buffered *(ebp+0x10) "' is not in a register\n")
24941     (flush *(ebp+0x10))
24942     (stop *(ebp+0x14) 1)
24943     # never gets here
24944 
24945 $check-mu-compute-offset-stmt:error-output-type-not-offset:
24946     (write-buffered *(ebp+0x10) "fn ")
24947     8b/-> *(ebp+0xc) 0/r32/eax
24948     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24949     (write-buffered *(ebp+0x10) %eax)
24950     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
24951     (lookup *edi *(edi+4))  # Var-name Var-name => eax
24952     (write-buffered *(ebp+0x10) %eax)
24953     (write-buffered *(ebp+0x10) "' must be an offset\n")
24954     (flush *(ebp+0x10))
24955     (stop *(ebp+0x14) 1)
24956     # never gets here
24957 
24958 $check-mu-compute-offset-stmt:error-bad-output-type:
24959     (write-buffered *(ebp+0x10) "fn ")
24960     8b/-> *(ebp+0xc) 0/r32/eax
24961     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24962     (write-buffered *(ebp+0x10) %eax)
24963     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
24964     (lookup *edi *(edi+4))  # Var-name Var-name => eax
24965     (write-buffered *(ebp+0x10) %eax)
24966     (write-buffered *(ebp+0x10) "' does not have the right type\n")
24967     (flush *(ebp+0x10))
24968     (stop *(ebp+0x14) 1)
24969     # never gets here
24970 
24971 check-mu-copy-object-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
24972     # . prologue
24973     55/push-ebp
24974     89/<- %ebp 4/r32/esp
24975     # . save registers
24976     50/push-eax
24977     51/push-ecx
24978     53/push-ebx
24979     56/push-esi
24980     57/push-edi
24981     # esi = stmt
24982     8b/-> *(ebp+8) 6/r32/esi
24983 $check-mu-copy-object-stmt:check-for-output:
24984     # if stmt->outputs abort
24985     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24986     3d/compare-eax-and 0/imm32
24987     0f 85/jump-if-!= $check-mu-copy-object-stmt:error-too-many-outputs/disp32
24988 $check-mu-copy-object-stmt:get-left:
24989     # var dest/edi: (addr stmt-var) = stmt->inouts
24990     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24991     89/<- %edi 0/r32/eax
24992     # zero inouts
24993     3d/compare-eax-and 0/imm32
24994     0f 84/jump-if-= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
24995 $check-mu-copy-object-stmt:get-src:
24996     # var src/esi: (addr stmt-var) = dest->next
24997     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
24998     89/<- %esi 0/r32/eax
24999     # 1 inout
25000     3d/compare-eax-and 0/imm32
25001     0f 84/jump-if-= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
25002     # > 2 inouts
25003     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
25004     3d/compare-eax-and 0/imm32
25005     0f 85/jump-if-!= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
25006 $check-mu-copy-object-stmt:types:
25007     # var src-type/ecx: (addr type-tree) = src->value->type
25008     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
25009     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25010     89/<- %ecx 0/r32/eax
25011     # if (src->is-deref?) src-type = src-type->payload
25012     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
25013     3d/compare-eax-and 0/imm32/false
25014     {
25015       74/jump-if-= break/disp8
25016       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
25017       # if src-type->right is null, src-type = src-type->left
25018       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
25019       {
25020         75/jump-if-!= break/disp8
25021         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25022       }
25023       89/<- %ecx 0/r32/eax
25024     }
25025     # if src-type is not addr, abort
25026     (mu-addr-type? %ecx)  # => eax
25027     3d/compare-eax-and 0/imm32/false
25028     0f 84/jump-if-= $check-mu-copy-object-stmt:error-invalid-types/disp32
25029     # var dest-type/ebx: (addr type-tree) = dest->value->type
25030     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25031     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25032     89/<- %ebx 0/r32/eax
25033     # if (dest->is-deref?) dest-type = dest-type->payload
25034     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
25035     3d/compare-eax-and 0/imm32/false
25036     {
25037       74/jump-if-= break/disp8
25038       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25039       # if dest-type->right is null, dest-type = dest-type->left
25040       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
25041       {
25042         75/jump-if-!= break/disp8
25043         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25044       }
25045       89/<- %ebx 0/r32/eax
25046     }
25047     # if (dest-type != src-type) abort
25048     (type-equal? %ecx %ebx)  # => eax
25049     3d/compare-eax-and 0/imm32
25050     0f 84/jump-if-= $check-mu-copy-object-stmt:error-invalid-types/disp32
25051 $check-mu-copy-object-stmt:end:
25052     # . restore registers
25053     5f/pop-to-edi
25054     5e/pop-to-esi
25055     5b/pop-to-ebx
25056     59/pop-to-ecx
25057     58/pop-to-eax
25058     # . epilogue
25059     89/<- %esp 5/r32/ebp
25060     5d/pop-to-ebp
25061     c3/return
25062 
25063 $check-mu-copy-object-stmt:error-incorrect-inouts:
25064     (write-buffered *(ebp+0x10) "fn ")
25065     8b/-> *(ebp+0xc) 0/r32/eax
25066     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25067     (write-buffered *(ebp+0x10) %eax)
25068     (write-buffered *(ebp+0x10) ": stmt 'copy-object' must have two inouts\n")
25069     (flush *(ebp+0x10))
25070     (stop *(ebp+0x14) 1)
25071     # never gets here
25072 
25073 $check-mu-copy-object-stmt:error-too-many-outputs:
25074     (write-buffered *(ebp+0x10) "fn ")
25075     8b/-> *(ebp+0xc) 0/r32/eax
25076     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25077     (write-buffered *(ebp+0x10) %eax)
25078     (write-buffered *(ebp+0x10) ": stmt 'copy-object' must not have any outputs\n")
25079     (flush *(ebp+0x10))
25080     (stop *(ebp+0x14) 1)
25081     # never gets here
25082 
25083 $check-mu-copy-object-stmt:error-invalid-types:
25084     (write-buffered *(ebp+0x10) "fn ")
25085     8b/-> *(ebp+0xc) 0/r32/eax
25086     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25087     (write-buffered *(ebp+0x10) %eax)
25088     (write-buffered *(ebp+0x10) ": stmt copy-object: two inouts with identical addr types expected\n")
25089     (flush *(ebp+0x10))
25090     (stop *(ebp+0x14) 1)
25091     # never gets here
25092 
25093 check-mu-clear-object-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
25094     # . prologue
25095     55/push-ebp
25096     89/<- %ebp 4/r32/esp
25097     # . save registers
25098     50/push-eax
25099     51/push-ecx
25100     53/push-ebx
25101     56/push-esi
25102     57/push-edi
25103     # esi = stmt
25104     8b/-> *(ebp+8) 6/r32/esi
25105 $check-mu-clear-object-stmt:check-for-output:
25106     # if stmt->outputs abort
25107     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
25108     3d/compare-eax-and 0/imm32
25109     0f 85/jump-if-!= $check-mu-clear-object-stmt:error-too-many-outputs/disp32
25110 $check-mu-clear-object-stmt:get-left:
25111     # var dest/edi: (addr stmt-var) = stmt->inouts
25112     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25113     89/<- %edi 0/r32/eax
25114     # zero inouts
25115     3d/compare-eax-and 0/imm32
25116     0f 84/jump-if-= $check-mu-clear-object-stmt:error-incorrect-inouts/disp32
25117 $check-mu-clear-object-stmt:get-src:
25118     # > 1 inout
25119     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
25120     3d/compare-eax-and 0/imm32
25121     0f 85/jump-if-!= $check-mu-clear-object-stmt:error-incorrect-inouts/disp32
25122 $check-mu-clear-object-stmt:types:
25123     # var src-type/ecx: (addr type-tree) = src->value->type
25124     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25125     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25126     89/<- %ecx 0/r32/eax
25127     # if (src->is-deref?) src-type = src-type->payload
25128     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
25129     3d/compare-eax-and 0/imm32/false
25130     {
25131       74/jump-if-= break/disp8
25132       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
25133       # if src-type->right is null, src-type = src-type->left
25134       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
25135       {
25136         75/jump-if-!= break/disp8
25137         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25138       }
25139       89/<- %ecx 0/r32/eax
25140     }
25141     # if src-type is not addr, abort
25142     (mu-addr-type? %ecx)  # => eax
25143     3d/compare-eax-and 0/imm32/false
25144     0f 84/jump-if-= $check-mu-clear-object-stmt:error-invalid-type/disp32
25145 $check-mu-clear-object-stmt:end:
25146     # . restore registers
25147     5f/pop-to-edi
25148     5e/pop-to-esi
25149     5b/pop-to-ebx
25150     59/pop-to-ecx
25151     58/pop-to-eax
25152     # . epilogue
25153     89/<- %esp 5/r32/ebp
25154     5d/pop-to-ebp
25155     c3/return
25156 
25157 $check-mu-clear-object-stmt:error-incorrect-inouts:
25158     (write-buffered *(ebp+0x10) "fn ")
25159     8b/-> *(ebp+0xc) 0/r32/eax
25160     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25161     (write-buffered *(ebp+0x10) %eax)
25162     (write-buffered *(ebp+0x10) ": stmt 'clear-object' must have a single inout\n")
25163     (flush *(ebp+0x10))
25164     (stop *(ebp+0x14) 1)
25165     # never gets here
25166 
25167 $check-mu-clear-object-stmt:error-too-many-outputs:
25168     (write-buffered *(ebp+0x10) "fn ")
25169     8b/-> *(ebp+0xc) 0/r32/eax
25170     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25171     (write-buffered *(ebp+0x10) %eax)
25172     (write-buffered *(ebp+0x10) ": stmt 'clear-object' must not have any outputs\n")
25173     (flush *(ebp+0x10))
25174     (stop *(ebp+0x14) 1)
25175     # never gets here
25176 
25177 $check-mu-clear-object-stmt:error-invalid-type:
25178     (write-buffered *(ebp+0x10) "fn ")
25179     8b/-> *(ebp+0xc) 0/r32/eax
25180     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25181     (write-buffered *(ebp+0x10) %eax)
25182     (write-buffered *(ebp+0x10) ": stmt clear-object: inout must have an addr type\n")
25183     (flush *(ebp+0x10))
25184     (stop *(ebp+0x14) 1)
25185     # never gets here
25186 
25187 check-mu-allocate-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
25188     # . prologue
25189     55/push-ebp
25190     89/<- %ebp 4/r32/esp
25191     # . save registers
25192     50/push-eax
25193     53/push-ebx
25194     56/push-esi
25195     57/push-edi
25196     # esi = stmt
25197     8b/-> *(ebp+8) 6/r32/esi
25198 $check-mu-allocate-stmt:check-for-output:
25199     # if stmt->outputs abort
25200     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
25201     3d/compare-eax-and 0/imm32
25202     0f 85/jump-if-!= $check-mu-allocate-stmt:error-too-many-outputs/disp32
25203 $check-mu-allocate-stmt:get-target:
25204     # var target/edi: (addr stmt-var) = stmt->inouts
25205     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25206     89/<- %edi 0/r32/eax
25207     # zero inouts
25208     3d/compare-eax-and 0/imm32
25209     0f 84/jump-if-= $check-mu-allocate-stmt:error-incorrect-inouts/disp32
25210     # > 1 inouts
25211     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
25212     3d/compare-eax-and 0/imm32
25213     0f 85/jump-if-!= $check-mu-allocate-stmt:error-incorrect-inouts/disp32
25214 $check-mu-allocate-stmt:check-type:
25215     # var target-type/ebx: (addr type-tree) = target->value->type
25216     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25217     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25218     89/<- %ebx 0/r32/eax
25219     # if (target->is-deref?) target-type = target-type->payload
25220     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
25221     3d/compare-eax-and 0/imm32/false
25222     {
25223       74/jump-if-= break/disp8
25224       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25225       # if target-type->right is null, target-type = target-type->left
25226       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
25227       {
25228         75/jump-if-!= break/disp8
25229         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25230       }
25231       89/<- %ebx 0/r32/eax
25232     }
25233     # if target-type is not addr, abort
25234     (mu-addr-type? %ebx)  # => eax
25235     3d/compare-eax-and 0/imm32/false
25236     0f 84/jump-if-= $check-mu-allocate-stmt:error-invalid-type/disp32
25237     # if target-type->right is an atom, abort
25238     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25239     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
25240     0f 85/jump-if-!= $check-mu-allocate-stmt:error-invalid-type/disp32
25241     # if target-type->right->left is not handle, abort
25242     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25243     (simple-mu-type? %eax 4)  # handle => eax
25244     3d/compare-eax-and 0/imm32/false
25245     0f 84/jump-if-= $check-mu-allocate-stmt:error-invalid-type/disp32
25246 $check-mu-allocate-stmt:end:
25247     # . restore registers
25248     5f/pop-to-edi
25249     5e/pop-to-esi
25250     5b/pop-to-ebx
25251     58/pop-to-eax
25252     # . epilogue
25253     89/<- %esp 5/r32/ebp
25254     5d/pop-to-ebp
25255     c3/return
25256 
25257 $check-mu-allocate-stmt:error-incorrect-inouts:
25258     (write-buffered *(ebp+0x10) "fn ")
25259     8b/-> *(ebp+0xc) 0/r32/eax
25260     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25261     (write-buffered *(ebp+0x10) %eax)
25262     (write-buffered *(ebp+0x10) ": stmt 'allocate' must have a single inout\n")
25263     (flush *(ebp+0x10))
25264     (stop *(ebp+0x14) 1)
25265     # never gets here
25266 
25267 $check-mu-allocate-stmt:error-too-many-outputs:
25268     (write-buffered *(ebp+0x10) "fn ")
25269     8b/-> *(ebp+0xc) 0/r32/eax
25270     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25271     (write-buffered *(ebp+0x10) %eax)
25272     (write-buffered *(ebp+0x10) ": stmt 'allocate' must not have any outputs\n")
25273     (flush *(ebp+0x10))
25274     (stop *(ebp+0x14) 1)
25275     # never gets here
25276 
25277 $check-mu-allocate-stmt:error-invalid-type:
25278     (write-buffered *(ebp+0x10) "fn ")
25279     8b/-> *(ebp+0xc) 0/r32/eax
25280     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25281     (write-buffered *(ebp+0x10) %eax)
25282     (write-buffered *(ebp+0x10) ": stmt allocate: inout '")
25283     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25284     (lookup *eax *(eax+4))  # Var-name Var-name => eax
25285     (write-buffered *(ebp+0x10) %eax)
25286     (write-buffered *(ebp+0x10) "' must have type (addr handle ...)\n")
25287     (flush *(ebp+0x10))
25288     (stop *(ebp+0x14) 1)
25289     # never gets here
25290 
25291 check-mu-populate-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
25292     # . prologue
25293     55/push-ebp
25294     89/<- %ebp 4/r32/esp
25295     # . save registers
25296     50/push-eax
25297     53/push-ebx
25298     56/push-esi
25299     57/push-edi
25300     # esi = stmt
25301     8b/-> *(ebp+8) 6/r32/esi
25302 $check-mu-populate-stmt:check-for-output:
25303     # if stmt->outputs abort
25304     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
25305     3d/compare-eax-and 0/imm32
25306     0f 85/jump-if-!= $check-mu-populate-stmt:error-too-many-outputs/disp32
25307 $check-mu-populate-stmt:get-target:
25308     # var target/edi: (addr stmt-var) = stmt->inouts
25309     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25310     89/<- %edi 0/r32/eax
25311     # zero inouts
25312     3d/compare-eax-and 0/imm32
25313     0f 84/jump-if-= $check-mu-populate-stmt:error-incorrect-inouts/disp32
25314 $check-mu-populate-stmt:get-length:
25315     # var length/esi: (addr stmt-var) = dest->next
25316     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
25317     89/<- %esi 0/r32/eax
25318     # 1 inout
25319     3d/compare-eax-and 0/imm32
25320     0f 84/jump-if-= $check-mu-populate-stmt:error-incorrect-inouts/disp32
25321     # > 2 inouts
25322     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
25323     3d/compare-eax-and 0/imm32
25324     0f 85/jump-if-!= $check-mu-populate-stmt:error-incorrect-inouts/disp32
25325 $check-mu-populate-stmt:check-target-type:
25326     # var target-type/ebx: (addr type-tree) = target->value->type
25327     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25328     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25329     89/<- %ebx 0/r32/eax
25330 $check-mu-populate-stmt:check-target-type-deref:
25331     # if (target->is-deref?) target-type = target-type->payload
25332     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
25333     3d/compare-eax-and 0/imm32/false
25334     {
25335       74/jump-if-= break/disp8
25336       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25337       # if target-type->right is null, target-type = target-type->left
25338       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
25339       {
25340         75/jump-if-!= break/disp8
25341         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25342       }
25343       89/<- %ebx 0/r32/eax
25344     }
25345 $check-mu-populate-stmt:check-target-type-addr:
25346     # if target-type is not addr, abort
25347     (mu-addr-type? %ebx)  # => eax
25348     3d/compare-eax-and 0/imm32/false
25349     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32
25350     # if target-type->right is an atom, abort
25351     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25352     89/<- %ebx 0/r32/eax
25353     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
25354     0f 85/jump-if-!= $check-mu-populate-stmt:error-invalid-target-type/disp32
25355 $check-mu-populate-stmt:check-target-type-handle:
25356     # if target-type->right->left is not handle, abort
25357     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
25358     (simple-mu-type? %eax 4)  # handle => eax
25359     3d/compare-eax-and 0/imm32/false
25360     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32
25361     # if target-type->right->right is an atom, abort
25362     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25363     89/<- %ebx 0/r32/eax
25364     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
25365     0f 85/jump-if-!= $check-mu-populate-stmt:error-invalid-target-type/disp32
25366 $check-mu-populate-stmt:check-target-type-array:
25367     # if target-type->right->right->left is not array, abort
25368     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
25369     (simple-mu-type? %eax 3)  # array => eax
25370     3d/compare-eax-and 0/imm32/false
25371     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32
25372 $check-mu-populate-stmt:check-length-type:
25373     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
25374     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25375     89/<- %ebx 0/r32/eax
25376     (simple-mu-type? %ebx 0)  # literal => eax
25377     3d/compare-eax-and 0/imm32/false
25378     75/jump-if-!= $check-mu-populate-stmt:end/disp8
25379     (simple-mu-type? %ebx 1)  # int => eax
25380     3d/compare-eax-and 0/imm32/false
25381     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-length-type/disp32
25382 $check-mu-populate-stmt:end:
25383     # . restore registers
25384     5f/pop-to-edi
25385     5e/pop-to-esi
25386     5b/pop-to-ebx
25387     58/pop-to-eax
25388     # . epilogue
25389     89/<- %esp 5/r32/ebp
25390     5d/pop-to-ebp
25391     c3/return
25392 
25393 $check-mu-populate-stmt:error-incorrect-inouts:
25394     (write-buffered *(ebp+0x10) "fn ")
25395     8b/-> *(ebp+0xc) 0/r32/eax
25396     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25397     (write-buffered *(ebp+0x10) %eax)
25398     (write-buffered *(ebp+0x10) ": stmt 'populate' must have two inouts\n")
25399     (flush *(ebp+0x10))
25400     (stop *(ebp+0x14) 1)
25401     # never gets here
25402 
25403 $check-mu-populate-stmt:error-too-many-outputs:
25404     (write-buffered *(ebp+0x10) "fn ")
25405     8b/-> *(ebp+0xc) 0/r32/eax
25406     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25407     (write-buffered *(ebp+0x10) %eax)
25408     (write-buffered *(ebp+0x10) ": stmt 'populate' must not have any outputs\n")
25409     (flush *(ebp+0x10))
25410     (stop *(ebp+0x14) 1)
25411     # never gets here
25412 
25413 $check-mu-populate-stmt:error-invalid-target-type:
25414     (write-buffered *(ebp+0x10) "fn ")
25415     8b/-> *(ebp+0xc) 0/r32/eax
25416     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25417     (write-buffered *(ebp+0x10) %eax)
25418     (write-buffered *(ebp+0x10) ": stmt populate: first inout '")
25419     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25420     (lookup *eax *(eax+4))  # Var-name Var-name => eax
25421     (write-buffered *(ebp+0x10) %eax)
25422     (write-buffered *(ebp+0x10) "' must have type (addr handle array ...)\n")
25423     (flush *(ebp+0x10))
25424     (stop *(ebp+0x14) 1)
25425     # never gets here
25426 
25427 $check-mu-populate-stmt:error-invalid-length-type:
25428     (write-buffered *(ebp+0x10) "fn ")
25429     8b/-> *(ebp+0xc) 0/r32/eax
25430     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25431     (write-buffered *(ebp+0x10) %eax)
25432     (write-buffered *(ebp+0x10) ": stmt populate: second inout '")
25433     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
25434     (lookup *eax *(eax+4))  # Var-name Var-name => eax
25435     (write-buffered *(ebp+0x10) %eax)
25436     (write-buffered *(ebp+0x10) "' must be an int\n")
25437     (flush *(ebp+0x10))
25438     (stop *(ebp+0x14) 1)
25439     # never gets here
25440 
25441 check-mu-populate-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
25442     # . prologue
25443     55/push-ebp
25444     89/<- %ebp 4/r32/esp
25445     # . save registers
25446     50/push-eax
25447     53/push-ebx
25448     56/push-esi
25449     57/push-edi
25450     # esi = stmt
25451     8b/-> *(ebp+8) 6/r32/esi
25452 $check-mu-populate-stream-stmt:check-for-output:
25453     # if stmt->outputs abort
25454     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
25455     3d/compare-eax-and 0/imm32
25456     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-too-many-outputs/disp32
25457 $check-mu-populate-stream-stmt:get-target:
25458     # var target/edi: (addr stmt-var) = stmt->inouts
25459     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25460     89/<- %edi 0/r32/eax
25461     # zero inouts
25462     3d/compare-eax-and 0/imm32
25463     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32
25464 $check-mu-populate-stream-stmt:get-length:
25465     # var length/esi: (addr stmt-var) = dest->next
25466     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
25467     89/<- %esi 0/r32/eax
25468     # 1 inout
25469     3d/compare-eax-and 0/imm32
25470     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32
25471     # > 2 inouts
25472     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
25473     3d/compare-eax-and 0/imm32
25474     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32
25475 $check-mu-populate-stream-stmt:check-target-type:
25476     # var target-type/ebx: (addr type-tree) = target->value->type
25477     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25478     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25479     89/<- %ebx 0/r32/eax
25480 $check-mu-populate-stream-stmt:check-target-type-deref:
25481     # if (target->is-deref?) target-type = target-type->payload
25482     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
25483     3d/compare-eax-and 0/imm32/false
25484     {
25485       74/jump-if-= break/disp8
25486       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25487       # if target-type->right is null, target-type = target-type->left
25488       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
25489       {
25490         75/jump-if-!= break/disp8
25491         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25492       }
25493       89/<- %ebx 0/r32/eax
25494     }
25495 $check-mu-populate-stream-stmt:check-target-type-addr:
25496     # if target-type is not addr, abort
25497     (mu-addr-type? %ebx)  # => eax
25498     3d/compare-eax-and 0/imm32/false
25499     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
25500     # if target-type->right is an atom, abort
25501     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25502     89/<- %ebx 0/r32/eax
25503     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
25504     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
25505 $check-mu-populate-stream-stmt:check-target-type-handle:
25506     # if target-type->right->left is not handle, abort
25507     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
25508     (simple-mu-type? %eax 4)  # handle => eax
25509     3d/compare-eax-and 0/imm32/false
25510     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
25511     # if target-type->right->right is an atom, abort
25512     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25513     89/<- %ebx 0/r32/eax
25514     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
25515     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
25516 $check-mu-populate-stream-stmt:check-target-type-stream:
25517     # if target-type->right->right->left is not stream, abort
25518     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
25519     (simple-mu-type? %eax 0xb)  # stream => eax
25520     3d/compare-eax-and 0/imm32/false
25521     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
25522 $check-mu-populate-stream-stmt:check-length-type:
25523     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
25524     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25525     89/<- %ebx 0/r32/eax
25526     (simple-mu-type? %ebx 0)  # literal => eax
25527     3d/compare-eax-and 0/imm32/false
25528     75/jump-if-!= $check-mu-populate-stream-stmt:end/disp8
25529     (simple-mu-type? %ebx 1)  # int => eax
25530     3d/compare-eax-and 0/imm32/false
25531     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-length-type/disp32
25532 $check-mu-populate-stream-stmt:end:
25533     # . restore registers
25534     5f/pop-to-edi
25535     5e/pop-to-esi
25536     5b/pop-to-ebx
25537     58/pop-to-eax
25538     # . epilogue
25539     89/<- %esp 5/r32/ebp
25540     5d/pop-to-ebp
25541     c3/return
25542 
25543 $check-mu-populate-stream-stmt:error-incorrect-inouts:
25544     (write-buffered *(ebp+0x10) "fn ")
25545     8b/-> *(ebp+0xc) 0/r32/eax
25546     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25547     (write-buffered *(ebp+0x10) %eax)
25548     (write-buffered *(ebp+0x10) ": stmt 'populate-stream' must have two inouts\n")
25549     (flush *(ebp+0x10))
25550     (stop *(ebp+0x14) 1)
25551     # never gets here
25552 
25553 $check-mu-populate-stream-stmt:error-too-many-outputs:
25554     (write-buffered *(ebp+0x10) "fn ")
25555     8b/-> *(ebp+0xc) 0/r32/eax
25556     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25557     (write-buffered *(ebp+0x10) %eax)
25558     (write-buffered *(ebp+0x10) ": stmt 'populate-stream' must not have any outputs\n")
25559     (flush *(ebp+0x10))
25560     (stop *(ebp+0x14) 1)
25561     # never gets here
25562 
25563 $check-mu-populate-stream-stmt:error-invalid-target-type:
25564     (write-buffered *(ebp+0x10) "fn ")
25565     8b/-> *(ebp+0xc) 0/r32/eax
25566     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25567     (write-buffered *(ebp+0x10) %eax)
25568     (write-buffered *(ebp+0x10) ": stmt populate-stream: first inout '")
25569     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25570     (lookup *eax *(eax+4))  # Var-name Var-name => eax
25571     (write-buffered *(ebp+0x10) %eax)
25572     (write-buffered *(ebp+0x10) "' must have type (addr handle stream ...)\n")
25573     (flush *(ebp+0x10))
25574     (stop *(ebp+0x14) 1)
25575     # never gets here
25576 
25577 $check-mu-populate-stream-stmt:error-invalid-length-type:
25578     (write-buffered *(ebp+0x10) "fn ")
25579     8b/-> *(ebp+0xc) 0/r32/eax
25580     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25581     (write-buffered *(ebp+0x10) %eax)
25582     (write-buffered *(ebp+0x10) ": stmt populate-stream: second inout '")
25583     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
25584     (lookup *eax *(eax+4))  # Var-name Var-name => eax
25585     (write-buffered *(ebp+0x10) %eax)
25586     (write-buffered *(ebp+0x10) "' must be an int\n")
25587     (flush *(ebp+0x10))
25588     (stop *(ebp+0x14) 1)
25589     # never gets here
25590 
25591 check-mu-read-from-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
25592     # . prologue
25593     55/push-ebp
25594     89/<- %ebp 4/r32/esp
25595     # . save registers
25596     50/push-eax
25597     51/push-ecx
25598     52/push-edx
25599     53/push-ebx
25600     56/push-esi
25601     57/push-edi
25602     # esi = stmt
25603     8b/-> *(ebp+8) 6/r32/esi
25604     # - check for 0 inouts
25605     # var base/ecx: (addr var) = stmt->inouts->value
25606     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25607 $check-mu-read-from-stream-stmt:check-no-inouts:
25608     3d/compare-eax-and 0/imm32
25609     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-too-few-inouts/disp32
25610     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25611     89/<- %ecx 0/r32/eax
25612     # - check base type is (addr stream T)
25613     # var base-type/ebx: (addr type-tree) = lookup(base->type)
25614     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
25615     89/<- %ebx 0/r32/eax
25616 $check-mu-read-from-stream-stmt:check-base-is-compound:
25617     # if base-type is an atom, abort
25618     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
25619     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
25620 $check-mu-read-from-stream-stmt:check-base-is-addr:
25621     # if type->left not addr, abort
25622     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
25623     (simple-mu-type? %eax 2)  # addr => eax
25624     3d/compare-eax-and 0/imm32/false
25625     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
25626 $check-mu-read-from-stream-stmt:check-base-is-addr-to-stream:
25627     # base-type = base-type->right
25628     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25629     89/<- %ebx 0/r32/eax
25630     # ensure base-type->left == stream
25631     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25632     (simple-mu-type? %eax 0xb)  # stream => eax
25633     3d/compare-eax-and 0/imm32/false
25634     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
25635     # - check target type is (addr T)
25636     # var target/ecx: (addr stmt-var) = stmt->inouts->next->value
25637     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25638     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
25639 $check-mu-read-from-stream-stmt:check-single-inout:
25640     3d/compare-eax-and 0/imm32
25641     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-too-few-inouts/disp32
25642     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25643     89/<- %ecx 0/r32/eax
25644     # var target-type/edx: (addr type-tree)
25645     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
25646     89/<- %edx 0/r32/eax
25647     # if target-type is an atom, it must be a literal or int
25648 $check-mu-read-from-stream-stmt:check-target-is-compound:
25649     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
25650     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-target-type-not-address/disp32
25651 $check-mu-read-from-stream-stmt:check-target-type:
25652     # target type must start with (addr ...)
25653     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
25654     (simple-mu-type? %eax 2)  # addr => eax
25655     3d/compare-eax-and 0/imm32/false
25656     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-target-type-not-address/disp32
25657     # if tail(base-type) != tail(target-type) abort
25658     (type-tail %ebx)  # => eax
25659     89/<- %ebx 0/r32/eax
25660     (type-tail %edx)  # => eax
25661     (type-equal? %ebx %eax)  # => eax
25662     3d/compare-eax-and 0/imm32/false
25663     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-target-type/disp32
25664 $check-mu-read-from-stream-stmt:check-too-many-inouts:
25665     # - check for too many inouts
25666     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25667     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
25668     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
25669     3d/compare-eax-and 0/imm32/false
25670     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-too-many-inouts/disp32
25671 $check-mu-read-from-stream-stmt:check-unexpected-output:
25672     # - check for any output
25673     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
25674     3d/compare-eax-and 0/imm32/false
25675     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-unexpected-output/disp32
25676 $check-mu-read-from-stream-stmt:end:
25677     # . restore registers
25678     5f/pop-to-edi
25679     5e/pop-to-esi
25680     5b/pop-to-ebx
25681     5a/pop-to-edx
25682     59/pop-to-ecx
25683     58/pop-to-eax
25684     # . epilogue
25685     89/<- %esp 5/r32/ebp
25686     5d/pop-to-ebp
25687     c3/return
25688 
25689 $check-mu-read-from-stream-stmt:error-invalid-base-type:
25690     (write-buffered *(ebp+0x10) "fn ")
25691     8b/-> *(ebp+0xc) 0/r32/eax
25692     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25693     (write-buffered *(ebp+0x10) %eax)
25694     (write-buffered *(ebp+0x10) ": stmt read-from-stream: var '")
25695     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
25696     (write-buffered *(ebp+0x10) %eax)
25697     (write-buffered *(ebp+0x10) "' must be an addr to a stream\n")
25698     (flush *(ebp+0x10))
25699     (stop *(ebp+0x14) 1)
25700     # never gets here
25701 
25702 $check-mu-read-from-stream-stmt:error-too-few-inouts:
25703     (write-buffered *(ebp+0x10) "fn ")
25704     8b/-> *(ebp+0xc) 0/r32/eax
25705     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25706     (write-buffered *(ebp+0x10) %eax)
25707     (write-buffered *(ebp+0x10) ": stmt read-from-stream: too few inouts (2 required)\n")
25708     (flush *(ebp+0x10))
25709     (stop *(ebp+0x14) 1)
25710     # never gets here
25711 
25712 $check-mu-read-from-stream-stmt:error-target-type-not-address:
25713     (write-buffered *(ebp+0x10) "fn ")
25714     8b/-> *(ebp+0xc) 0/r32/eax
25715     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25716     (write-buffered *(ebp+0x10) %eax)
25717     (write-buffered *(ebp+0x10) ": stmt read-from-stream: target '")
25718     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
25719     (write-buffered *(ebp+0x10) %eax)
25720     (write-buffered *(ebp+0x10) "' must be an addr\n")
25721     (flush *(ebp+0x10))
25722     (stop *(ebp+0x14) 1)
25723     # never gets here
25724 
25725 $check-mu-read-from-stream-stmt:error-invalid-target-type:
25726     (write-buffered *(ebp+0x10) "fn ")
25727     8b/-> *(ebp+0xc) 0/r32/eax
25728     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25729     (write-buffered *(ebp+0x10) %eax)
25730     (write-buffered *(ebp+0x10) ": stmt read-from-stream: second inout '")
25731     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
25732     (write-buffered *(ebp+0x10) %eax)
25733     (write-buffered *(ebp+0x10) "' does not have the right type\n")
25734     (flush *(ebp+0x10))
25735     (stop *(ebp+0x14) 1)
25736     # never gets here
25737 
25738 $check-mu-read-from-stream-stmt:error-too-many-inouts:
25739     (write-buffered *(ebp+0x10) "fn ")
25740     8b/-> *(ebp+0xc) 0/r32/eax
25741     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25742     (write-buffered *(ebp+0x10) %eax)
25743     (write-buffered *(ebp+0x10) ": stmt read-from-stream: too many inouts (2 required)\n")
25744     (flush *(ebp+0x10))
25745     (stop *(ebp+0x14) 1)
25746     # never gets here
25747 
25748 $check-mu-read-from-stream-stmt:error-unexpected-output:
25749     (write-buffered *(ebp+0x10) "fn ")
25750     8b/-> *(ebp+0xc) 0/r32/eax
25751     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25752     (write-buffered *(ebp+0x10) %eax)
25753     (write-buffered *(ebp+0x10) ": stmt read-from-stream: unexpected output\n")
25754     (flush *(ebp+0x10))
25755     (stop *(ebp+0x14) 1)
25756     # never gets here
25757 
25758 check-mu-write-to-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
25759     # . prologue
25760     55/push-ebp
25761     89/<- %ebp 4/r32/esp
25762     # . save registers
25763     50/push-eax
25764     51/push-ecx
25765     52/push-edx
25766     53/push-ebx
25767     56/push-esi
25768     57/push-edi
25769     # esi = stmt
25770     8b/-> *(ebp+8) 6/r32/esi
25771     # - check for 0 inouts
25772     # var base/ecx: (addr var) = stmt->inouts->value
25773     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25774 $check-mu-write-to-stream-stmt:check-no-inouts:
25775     3d/compare-eax-and 0/imm32
25776     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-too-few-inouts/disp32
25777     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25778     89/<- %ecx 0/r32/eax
25779     # - check base type is (addr stream T)
25780     # var base-type/ebx: (addr type-tree) = lookup(base->type)
25781     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
25782     89/<- %ebx 0/r32/eax
25783 $check-mu-write-to-stream-stmt:check-base-is-compound:
25784     # if base-type is an atom, abort
25785     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
25786     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
25787 $check-mu-write-to-stream-stmt:check-base-is-addr:
25788     # if type->left not addr, abort
25789     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
25790     (simple-mu-type? %eax 2)  # addr => eax
25791     3d/compare-eax-and 0/imm32/false
25792     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
25793 $check-mu-write-to-stream-stmt:check-base-is-addr-to-stream:
25794     # base-type = base-type->right
25795     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25796     89/<- %ebx 0/r32/eax
25797     # ensure base-type->left == stream
25798     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25799     (simple-mu-type? %eax 0xb)  # stream => eax
25800     3d/compare-eax-and 0/imm32/false
25801     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
25802     # - check target type is (addr T)
25803     # var target/ecx: (addr stmt-var) = stmt->inouts->next->value
25804     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25805     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
25806 $check-mu-write-to-stream-stmt:check-single-inout:
25807     3d/compare-eax-and 0/imm32
25808     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-too-few-inouts/disp32
25809     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25810     89/<- %ecx 0/r32/eax
25811     # var target-type/edx: (addr type-tree)
25812     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
25813     89/<- %edx 0/r32/eax
25814     # if target-type is an atom, it must be a literal or int
25815 $check-mu-write-to-stream-stmt:check-target-is-compound:
25816     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
25817     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-target-type-not-address/disp32
25818 $check-mu-write-to-stream-stmt:check-target-type:
25819     # target type must start with (addr ...)
25820     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
25821     (simple-mu-type? %eax 2)  # addr => eax
25822     3d/compare-eax-and 0/imm32/false
25823     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-target-type-not-address/disp32
25824     # if tail(base-type) != tail(target-type) abort
25825     (type-tail %ebx)  # => eax
25826     89/<- %ebx 0/r32/eax
25827     (type-tail %edx)  # => eax
25828     (type-equal? %ebx %eax)  # => eax
25829     3d/compare-eax-and 0/imm32/false
25830     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-target-type/disp32
25831 $check-mu-write-to-stream-stmt:check-too-many-inouts:
25832     # - check for too many inouts
25833     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25834     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
25835     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
25836     3d/compare-eax-and 0/imm32/false
25837     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-too-many-inouts/disp32
25838 $check-mu-write-to-stream-stmt:check-unexpected-output:
25839     # - check for any output
25840     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
25841     3d/compare-eax-and 0/imm32/false
25842     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-unexpected-output/disp32
25843 $check-mu-write-to-stream-stmt:end:
25844     # . restore registers
25845     5f/pop-to-edi
25846     5e/pop-to-esi
25847     5b/pop-to-ebx
25848     5a/pop-to-edx
25849     59/pop-to-ecx
25850     58/pop-to-eax
25851     # . epilogue
25852     89/<- %esp 5/r32/ebp
25853     5d/pop-to-ebp
25854     c3/return
25855 
25856 $check-mu-write-to-stream-stmt:error-invalid-base-type:
25857     (write-buffered *(ebp+0x10) "fn ")
25858     8b/-> *(ebp+0xc) 0/r32/eax
25859     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25860     (write-buffered *(ebp+0x10) %eax)
25861     (write-buffered *(ebp+0x10) ": stmt write-to-stream: var '")
25862     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
25863     (write-buffered *(ebp+0x10) %eax)
25864     (write-buffered *(ebp+0x10) "' must be an addr to a stream\n")
25865     (flush *(ebp+0x10))
25866     (stop *(ebp+0x14) 1)
25867     # never gets here
25868 
25869 $check-mu-write-to-stream-stmt:error-too-few-inouts:
25870     (write-buffered *(ebp+0x10) "fn ")
25871     8b/-> *(ebp+0xc) 0/r32/eax
25872     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25873     (write-buffered *(ebp+0x10) %eax)
25874     (write-buffered *(ebp+0x10) ": stmt write-to-stream: too few inouts (2 required)\n")
25875     (flush *(ebp+0x10))
25876     (stop *(ebp+0x14) 1)
25877     # never gets here
25878 
25879 $check-mu-write-to-stream-stmt:error-target-type-not-address:
25880     (write-buffered *(ebp+0x10) "fn ")
25881     8b/-> *(ebp+0xc) 0/r32/eax
25882     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25883     (write-buffered *(ebp+0x10) %eax)
25884     (write-buffered *(ebp+0x10) ": stmt write-to-stream: target '")
25885     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
25886     (write-buffered *(ebp+0x10) %eax)
25887     (write-buffered *(ebp+0x10) "' must be an addr\n")
25888     (flush *(ebp+0x10))
25889     (stop *(ebp+0x14) 1)
25890     # never gets here
25891 
25892 $check-mu-write-to-stream-stmt:error-invalid-target-type:
25893     (write-buffered *(ebp+0x10) "fn ")
25894     8b/-> *(ebp+0xc) 0/r32/eax
25895     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25896     (write-buffered *(ebp+0x10) %eax)
25897     (write-buffered *(ebp+0x10) ": stmt write-to-stream: second inout '")
25898     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
25899     (write-buffered *(ebp+0x10) %eax)
25900     (write-buffered *(ebp+0x10) "' does not have the right type\n")
25901     (flush *(ebp+0x10))
25902     (stop *(ebp+0x14) 1)
25903     # never gets here
25904 
25905 $check-mu-write-to-stream-stmt:error-too-many-inouts:
25906     (write-buffered *(ebp+0x10) "fn ")
25907     8b/-> *(ebp+0xc) 0/r32/eax
25908     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25909     (write-buffered *(ebp+0x10) %eax)
25910     (write-buffered *(ebp+0x10) ": stmt write-to-stream: too many inouts (2 required)\n")
25911     (flush *(ebp+0x10))
25912     (stop *(ebp+0x14) 1)
25913     # never gets here
25914 
25915 $check-mu-write-to-stream-stmt:error-unexpected-output:
25916     (write-buffered *(ebp+0x10) "fn ")
25917     8b/-> *(ebp+0xc) 0/r32/eax
25918     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25919     (write-buffered *(ebp+0x10) %eax)
25920     (write-buffered *(ebp+0x10) ": stmt write-to-stream: unexpected output\n")
25921     (flush *(ebp+0x10))
25922     (stop *(ebp+0x14) 1)
25923     # never gets here
25924 
25925 check-mu-convert-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
25926     # . prologue
25927     55/push-ebp
25928     89/<- %ebp 4/r32/esp
25929     # . save registers
25930     50/push-eax
25931     51/push-ecx
25932     52/push-edx
25933     56/push-esi
25934     57/push-edi
25935 $check-mu-convert-stmt:get-output:
25936     # esi = stmt
25937     8b/-> *(ebp+8) 6/r32/esi
25938     # var output/edi: (addr stmt-var) = stmt->outputs
25939     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
25940     89/<- %edi 0/r32/eax
25941     # zero outputs
25942     3d/compare-eax-and 0/imm32
25943     0f 84/jump-if-= $check-mu-convert-stmt:error-no-output/disp32
25944     # > 1 output
25945     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
25946     3d/compare-eax-and 0/imm32
25947     0f 85/jump-if-!= $check-mu-convert-stmt:error-too-many-outputs/disp32
25948 $check-mu-convert-stmt:get-inout:
25949     # var inout/esi: (addr stmt-var) = stmt->inouts
25950     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25951     89/<- %esi 0/r32/eax
25952     # zero inouts
25953     3d/compare-eax-and 0/imm32
25954     0f 84/jump-if-= $check-mu-convert-stmt:error-no-inout/disp32
25955     # > 1 inout
25956     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
25957     3d/compare-eax-and 0/imm32
25958     0f 85/jump-if-!= $check-mu-convert-stmt:error-too-many-inouts/disp32
25959 $check-mu-convert-stmt:types:
25960     # var inout-type/ecx: (addr type-tree) = inout->value->type
25961     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
25962     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25963     89/<- %ecx 0/r32/eax
25964     # if (inout->is-deref?) inout-type = inout-type->payload
25965     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
25966     3d/compare-eax-and 0/imm32/false
25967     {
25968       74/jump-if-= break/disp8
25969       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
25970       # if inout-type->right is null, t = inout-type->left
25971       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
25972       {
25973         75/jump-if-!= break/disp8
25974         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25975       }
25976       89/<- %ecx 0/r32/eax
25977     }
25978     # if input is not int or float, abort
25979     {
25980       (simple-mu-type? %ecx 1)  # int => eax
25981       3d/compare-eax-and 0/imm32/false
25982       75/jump-if-!= break/disp8
25983       (simple-mu-type? %ecx 0xf)  # float => eax
25984       3d/compare-eax-and 0/imm32/false
25985       75/jump-if-!= break/disp8
25986       e9/jump $check-mu-convert-stmt:error-invalid-inout-type/disp32
25987     }
25988     # if output not in register, abort
25989     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25990     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
25991     3d/compare-eax-and 0/imm32
25992     0f 84/jump-if-= $check-mu-convert-stmt:error-output-not-in-register/disp32
25993     # var output-type/edx: (addr type-tree) = output->value->type
25994     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25995     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25996     89/<- %edx 0/r32/eax
25997     # if output is not int or float, abort
25998     {
25999       (simple-mu-type? %edx 1)  # int => eax
26000       3d/compare-eax-and 0/imm32/false
26001       75/jump-if-!= break/disp8
26002       (simple-mu-type? %edx 0xf)  # float => eax
26003       3d/compare-eax-and 0/imm32/false
26004       75/jump-if-!= break/disp8
26005       e9/jump $check-mu-convert-stmt:error-invalid-output-type/disp32
26006     }
26007     # if both are ints, abort
26008     {
26009       (simple-mu-type? %edx 1)  # int => eax
26010       3d/compare-eax-and 0/imm32/false
26011       74/jump-if-= break/disp8
26012       (simple-mu-type? %ecx 1)  # int => eax
26013       3d/compare-eax-and 0/imm32/false
26014       74/jump-if-= break/disp8
26015       e9/jump $check-mu-convert-stmt:error-int-to-int/disp32
26016     }
26017     # if both are floats, abort
26018     {
26019       (simple-mu-type? %edx 0xf)  # float => eax
26020       3d/compare-eax-and 0/imm32/false
26021       74/jump-if-= break/disp8
26022       (simple-mu-type? %ecx 0xf)  # float => eax
26023       3d/compare-eax-and 0/imm32/false
26024       74/jump-if-= break/disp8
26025       e9/jump $check-mu-convert-stmt:error-float-to-float/disp32
26026     }
26027 $check-mu-convert-stmt:end:
26028     # . restore registers
26029     5f/pop-to-edi
26030     5e/pop-to-esi
26031     5a/pop-to-edx
26032     59/pop-to-ecx
26033     58/pop-to-eax
26034     # . epilogue
26035     89/<- %esp 5/r32/ebp
26036     5d/pop-to-ebp
26037     c3/return
26038 
26039 $check-mu-convert-stmt:error-no-inout:
26040     (write-buffered *(ebp+0x10) "fn ")
26041     8b/-> *(ebp+0xc) 0/r32/eax
26042     (lookup *eax *(eax+4))  # Function-name Function-name => eax
26043     (write-buffered *(ebp+0x10) %eax)
26044     (write-buffered *(ebp+0x10) ": stmt 'convert' expects an inout\n")
26045     (flush *(ebp+0x10))
26046     (stop *(ebp+0x14) 1)
26047     # never gets here
26048 
26049 $check-mu-convert-stmt:error-too-many-inouts:
26050     (write-buffered *(ebp+0x10) "fn ")
26051     8b/-> *(ebp+0xc) 0/r32/eax
26052     (lookup *eax *(eax+4))  # Function-name Function-name => eax
26053     (write-buffered *(ebp+0x10) %eax)
26054     (write-buffered *(ebp+0x10) ": stmt 'convert' must have just one inout\n")
26055     (flush *(ebp+0x10))
26056     (stop *(ebp+0x14) 1)
26057     # never gets here
26058 
26059 $check-mu-convert-stmt:error-no-output:
26060     (write-buffered *(ebp+0x10) "fn ")
26061     8b/-> *(ebp+0xc) 0/r32/eax
26062     (lookup *eax *(eax+4))  # Function-name Function-name => eax
26063     (write-buffered *(ebp+0x10) %eax)
26064     (write-buffered *(ebp+0x10) ": stmt 'convert' expects an output\n")
26065     (flush *(ebp+0x10))
26066     (stop *(ebp+0x14) 1)
26067     # never gets here
26068 
26069 $check-mu-convert-stmt:error-output-not-in-register:
26070     (write-buffered *(ebp+0x10) "fn ")
26071     8b/-> *(ebp+0xc) 0/r32/eax
26072     (lookup *eax *(eax+4))  # Function-name Function-name => eax
26073     (write-buffered *(ebp+0x10) %eax)
26074     (write-buffered *(ebp+0x10) ": stmt convert: output '")
26075     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
26076     (lookup *eax *(eax+4))  # Var-name Var-name => eax
26077     (write-buffered *(ebp+0x10) %eax)
26078     (write-buffered *(ebp+0x10) "' not in a register\n")
26079     (flush *(ebp+0x10))
26080     (stop *(ebp+0x14) 1)
26081     # never gets here
26082 
26083 $check-mu-convert-stmt:error-too-many-outputs:
26084     (write-buffered *(ebp+0x10) "fn ")
26085     8b/-> *(ebp+0xc) 0/r32/eax
26086     (lookup *eax *(eax+4))  # Function-name Function-name => eax
26087     (write-buffered *(ebp+0x10) %eax)
26088     (write-buffered *(ebp+0x10) ": stmt 'convert' must have just one output\n")
26089     (flush *(ebp+0x10))
26090     (stop *(ebp+0x14) 1)
26091     # never gets here
26092 
26093 $check-mu-convert-stmt:error-invalid-inout-type:
26094     (write-buffered *(ebp+0x10) "fn ")
26095     8b/-> *(ebp+0xc) 0/r32/eax
26096     (lookup *eax *(eax+4))  # Function-name Function-name => eax
26097     (write-buffered *(ebp+0x10) %eax)
26098     (write-buffered *(ebp+0x10) ": stmt convert: inout '")
26099     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
26100     (lookup *eax *(eax+4))  # Var-name Var-name => eax
26101     (write-buffered *(ebp+0x10) %eax)
26102     (write-buffered *(ebp+0x10) "' must be an int or float\n")
26103     (flush *(ebp+0x10))
26104     (stop *(ebp+0x14) 1)
26105     # never gets here
26106 
26107 $check-mu-convert-stmt:error-invalid-output-type:
26108     (write-buffered *(ebp+0x10) "fn ")
26109     8b/-> *(ebp+0xc) 0/r32/eax
26110     (lookup *eax *(eax+4))  # Function-name Function-name => eax
26111     (write-buffered *(ebp+0x10) %eax)
26112     (write-buffered *(ebp+0x10) ": stmt convert: output '")
26113     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
26114     (lookup *eax *(eax+4))  # Var-name Var-name => eax
26115     (write-buffered *(ebp+0x10) %eax)
26116     (write-buffered *(ebp+0x10) "' must be an int or float\n")
26117     (flush *(ebp+0x10))
26118     (stop *(ebp+0x14) 1)
26119     # never gets here
26120 
26121 $check-mu-convert-stmt:error-int-to-int:
26122     (write-buffered *(ebp+0x10) "fn ")
26123     8b/-> *(ebp+0xc) 0/r32/eax
26124     (lookup *eax *(eax+4))  # Function-name Function-name => eax
26125     (write-buffered *(ebp+0x10) %eax)
26126     (write-buffered *(ebp+0x10) ": stmt convert: no need to convert int to int\n")
26127     (flush *(ebp+0x10))
26128     (stop *(ebp+0x14) 1)
26129     # never gets here
26130 
26131 $check-mu-convert-stmt:error-float-to-float:
26132     (write-buffered *(ebp+0x10) "fn ")
26133     8b/-> *(ebp+0xc) 0/r32/eax
26134     (lookup *eax *(eax+4))  # Function-name Function-name => eax
26135     (write-buffered *(ebp+0x10) %eax)
26136     (write-buffered *(ebp+0x10) ": stmt convert: no need to convert float to float\n")
26137     (flush *(ebp+0x10))
26138     (stop *(ebp+0x14) 1)
26139     # never gets here
26140 
26141 check-mu-call:  # stmt: (addr stmt), callee: (addr function), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
26142     # . prologue
26143     55/push-ebp
26144     89/<- %ebp 4/r32/esp
26145     # var type-parameters: (addr table (handle array byte) (addr type-tree) 8)
26146     68/push 0/imm32
26147     # var type-parameters-storage: (table (handle array byte) (addr type-tree) 8)
26148     81 5/subop/subtract %esp 0x60/imm32
26149     68/push 0x60/imm32/size
26150     68/push 0/imm32/read
26151     68/push 0/imm32/write
26152     # save a pointer to type-parameters-storage at type-parameters
26153     89/<- *(ebp-4) 4/r32/esp
26154     (clear-stream *(ebp-4))
26155     # . save registers
26156     50/push-eax
26157     51/push-ecx
26158     52/push-edx
26159     53/push-ebx
26160     56/push-esi
26161     57/push-edi
26162     # esi = stmt
26163     8b/-> *(ebp+8) 6/r32/esi
26164     # edi = callee
26165     8b/-> *(ebp+0xc) 7/r32/edi
26166     # var inouts/ecx: (addr stmt-var) = lookup(stmt->inouts)
26167     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
26168     89/<- %ecx 0/r32/eax
26169     # var expected/edx: (addr list var) = lookup(f->inouts)
26170     (lookup *(edi+8) *(edi+0xc))  # Function-inouts Function-inouts => eax
26171     89/<- %edx 0/r32/eax
26172     {
26173 $check-mu-call:check-for-inouts:
26174       # if (inouts == 0) break
26175       81 7/subop/compare %ecx 0/imm32
26176       0f 84/jump-if-= break/disp32
26177       # if (expected == 0) error
26178       81 7/subop/compare %edx 0/imm32
26179       0f 84/jump-if-= break/disp32
26180 $check-mu-call:check-null-addr:
26181       # if (inouts->value->name == "0") continue
26182       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26183       (lookup *eax *(eax+4))  # Var-name Var-name => eax
26184       (string-equal? %eax "0")  # => eax
26185       3d/compare-eax-and 0/imm32/false
26186       0f 85/jump-if-!= $check-mu-call:continue-to-next-inout/disp32
26187 $check-mu-call:check-inout-type:
26188       # var t/ebx: (addr type-tree) = inouts->value->type
26189       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26190       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
26191       89/<- %ebx 0/r32/eax
26192       # if (inouts->is-deref?) t = t->right
26193       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
26194       {
26195         74/jump-if-= break/disp8
26196         (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
26197         89/<- %ebx 0/r32/eax
26198         # if t->right is null, t = t->left
26199         81 7/subop/compare *(ebx+0xc) 0/imm32  # Type-tree-right
26200         75/jump-if-!= break/disp8
26201         (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
26202         89/<- %ebx 0/r32/eax
26203       }
26204       # var v2/eax: (addr v) = lookup(expected->value)
26205       (lookup *edx *(edx+4))  # List-value List-value => eax
26206       # var t2/eax: (addr type-tree) = lookup(v2->type)
26207       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
26208       # if (t != t2) error
26209       (type-match? %eax %ebx *(ebp-4))  # => eax
26210       3d/compare-eax-and 0/imm32/false
26211       {
26212         0f 85/jump-if-!= break/disp32
26213         (write-buffered *(ebp+0x14) "fn ")
26214         8b/-> *(ebp+0x10) 0/r32/eax
26215         (lookup *eax *(eax+4))  # Function-name Function-name => eax
26216         (write-buffered *(ebp+0x14) %eax)
26217         (write-buffered *(ebp+0x14) ": call ")
26218         (lookup *edi *(edi+4))  # Function-name Function-name => eax
26219         (write-buffered *(ebp+0x14) %eax)
26220         (write-buffered *(ebp+0x14) ": type for inout '")
26221         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26222         (lookup *eax *(eax+4))  # Var-name Var-name => eax
26223         (write-buffered *(ebp+0x14) %eax)
26224         (write-buffered *(ebp+0x14) "' is not right\n")
26225         (flush *(ebp+0x14))
26226         (stop *(ebp+0x18) 1)
26227       }
26228 $check-mu-call:continue-to-next-inout:
26229       # inouts = lookup(inouts->next)
26230       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
26231       89/<- %ecx 0/r32/eax
26232       # expected = lookup(expected->next)
26233       (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
26234       89/<- %edx 0/r32/eax
26235       #
26236       e9/jump loop/disp32
26237     }
26238 $check-mu-call:check-inout-count:
26239     # if (inouts == expected) proceed
26240     39/compare %ecx 2/r32/edx
26241     {
26242       0f 84/jump-if-= break/disp32
26243       # exactly one of the two is null
26244       # if (inouts == 0) error("too many inouts")
26245       {
26246         81 7/subop/compare %ecx 0/imm32
26247         0f 84/jump-if-= break/disp32
26248         (write-buffered *(ebp+0x14) "fn ")
26249         8b/-> *(ebp+0x10) 0/r32/eax
26250         (lookup *eax *(eax+4))  # Function-name Function-name => eax
26251         (write-buffered *(ebp+0x14) %eax)
26252         (write-buffered *(ebp+0x14) ": call ")
26253         (lookup *edi *(edi+4))  # Function-name Function-name => eax
26254         (write-buffered *(ebp+0x14) %eax)
26255         (write-buffered *(ebp+0x14) ": too many inouts\n")
26256         (flush *(ebp+0x14))
26257         (stop *(ebp+0x18) 1)
26258       }
26259       # if (expected == 0) error("too few inouts")
26260       {
26261         81 7/subop/compare %edx 0/imm32
26262         0f 84/jump-if-= break/disp32
26263         (write-buffered *(ebp+0x14) "fn ")
26264         8b/-> *(ebp+0x10) 0/r32/eax
26265         (lookup *eax *(eax+4))  # Function-name Function-name => eax
26266         (write-buffered *(ebp+0x14) %eax)
26267         (write-buffered *(ebp+0x14) ": call ")
26268         (lookup *edi *(edi+4))  # Function-name Function-name => eax
26269         (write-buffered *(ebp+0x14) %eax)
26270         (write-buffered *(ebp+0x14) ": too few inouts\n")
26271         (flush *(ebp+0x14))
26272         (stop *(ebp+0x18) 1)
26273       }
26274     }
26275 $check-mu-call:check-outputs:
26276     # var outputs/ecx: (addr stmt-var) = lookup(stmt->outputs)
26277     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
26278     89/<- %ecx 0/r32/eax
26279     # var expected/edx: (addr list var) = lookup(f->outputs)
26280     (lookup *(edi+0x10) *(edi+0x14))  # Function-outputs Function-outputs => eax
26281     89/<- %edx 0/r32/eax
26282     {
26283 $check-mu-call:check-for-outputs:
26284       # if (outputs == 0) break
26285       81 7/subop/compare %ecx 0/imm32
26286       0f 84/jump-if-= break/disp32
26287       # if (expected == 0) error
26288       81 7/subop/compare %edx 0/imm32
26289       0f 84/jump-if-= break/disp32
26290 $check-mu-call:check-output-type:
26291       # var v/eax: (addr v) = lookup(outputs->value)
26292       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26293       # var t/ebx: (addr type-tree) = lookup(v->type)
26294       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
26295       89/<- %ebx 0/r32/eax
26296       # if (outputs->is-deref?) t = t->right  # TODO: check that t->left is an addr
26297       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
26298       {
26299         74/jump-if-= break/disp8
26300         (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
26301         89/<- %ebx 0/r32/eax
26302       }
26303       # var v2/eax: (addr v) = lookup(expected->value)
26304       (lookup *edx *(edx+4))  # List-value List-value => eax
26305       # var t2/eax: (addr type-tree) = lookup(v2->type)
26306       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
26307       # if (t != t2) error
26308       (type-match? %eax %ebx *(ebp-4))  # => eax
26309       3d/compare-eax-and 0/imm32/false
26310       {
26311         0f 85/jump-if-!= break/disp32
26312         (write-buffered *(ebp+0x14) "fn ")
26313         8b/-> *(ebp+0x10) 0/r32/eax
26314         (lookup *eax *(eax+4))  # Function-name Function-name => eax
26315         (write-buffered *(ebp+0x14) %eax)
26316         (write-buffered *(ebp+0x14) ": call ")
26317         (lookup *edi *(edi+4))  # Function-name Function-name => eax
26318         (write-buffered *(ebp+0x14) %eax)
26319         (write-buffered *(ebp+0x14) ": type for output '")
26320         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26321         (lookup *eax *(eax+4))  # Var-name Var-name => eax
26322         (write-buffered *(ebp+0x14) %eax)
26323         (write-buffered *(ebp+0x14) "' is not right\n")
26324         (flush *(ebp+0x14))
26325         (stop *(ebp+0x18) 1)
26326       }
26327 $check-mu-call:check-output-register:
26328       # var v/eax: (addr v) = lookup(outputs->value)
26329       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26330       # var r/ebx: (addr array byte) = lookup(v->register)
26331       (lookup *(eax+18) *(eax+0x1c))  # Var-register Var-register => eax
26332       89/<- %ebx 0/r32/eax
26333       # if (r == 0) error
26334       3d/compare-eax-and 0/imm32
26335       {
26336         0f 85/jump-if-!= break/disp32
26337         (write-buffered *(ebp+0x14) "fn ")
26338         8b/-> *(ebp+0x10) 0/r32/eax
26339         (lookup *eax *(eax+4))  # Function-name Function-name => eax
26340         (write-buffered *(ebp+0x14) %eax)
26341         (write-buffered *(ebp+0x14) ": call ")
26342         (lookup *edi *(edi+4))  # Function-name Function-name => eax
26343         (write-buffered *(ebp+0x14) %eax)
26344         (write-buffered *(ebp+0x14) ": output '")
26345         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26346         (lookup *eax *(eax+4))  # Var-name Var-name => eax
26347         (write-buffered *(ebp+0x14) %eax)
26348         (write-buffered *(ebp+0x14) "' is not in a register\n")
26349         (flush *(ebp+0x14))
26350         (stop *(ebp+0x18) 1)
26351       }
26352       # var v2/eax: (addr v) = lookup(expected->value)
26353       (lookup *edx *(edx+4))  # Stmt-var-value Stmt-var-value => eax
26354       # var r2/eax: (addr array byte) = lookup(v2->register)
26355       (lookup *(eax+18) *(eax+0x1c))  # Var-register Var-register => eax
26356       # if (r != r2) error
26357       (string-equal? %eax %ebx)  # => eax
26358       3d/compare-eax-and 0/imm32/false
26359       {
26360         0f 85/jump-if-!= break/disp32
26361         (write-buffered *(ebp+0x14) "fn ")
26362         8b/-> *(ebp+0x10) 0/r32/eax
26363         (lookup *eax *(eax+4))  # Function-name Function-name => eax
26364         (write-buffered *(ebp+0x14) %eax)
26365         (write-buffered *(ebp+0x14) ": call ")
26366         (lookup *edi *(edi+4))  # Function-name Function-name => eax
26367         (write-buffered *(ebp+0x14) %eax)
26368         (write-buffered *(ebp+0x14) ": register for output '")
26369         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26370         (lookup *eax *(eax+4))  # Var-name Var-name => eax
26371         (write-buffered *(ebp+0x14) %eax)
26372         (write-buffered *(ebp+0x14) "' is not right\n")
26373         (flush *(ebp+0x14))
26374         (stop *(ebp+0x18) 1)
26375       }
26376 $check-mu-call:continue-to-next-output:
26377       # outputs = lookup(outputs->next)
26378       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
26379       89/<- %ecx 0/r32/eax
26380       # expected = lookup(expected->next)
26381       (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
26382       89/<- %edx 0/r32/eax
26383       #
26384       e9/jump loop/disp32
26385     }
26386 $check-mu-call:check-output-count:
26387     # if (outputs == expected) proceed
26388     39/compare %ecx 2/r32/edx
26389     {
26390       0f 84/jump-if-= break/disp32
26391       # exactly one of the two is null
26392       # if (outputs == 0) error("too many outputs")
26393       {
26394         81 7/subop/compare %ecx 0/imm32
26395         0f 84/jump-if-= break/disp32
26396         (write-buffered *(ebp+0x14) "fn ")
26397         8b/-> *(ebp+0x10) 0/r32/eax
26398         (lookup *eax *(eax+4))  # Function-name Function-name => eax
26399         (write-buffered *(ebp+0x14) %eax)
26400         (write-buffered *(ebp+0x14) ": call ")
26401         (lookup *edi *(edi+4))  # Function-name Function-name => eax
26402         (write-buffered *(ebp+0x14) %eax)
26403         (write-buffered *(ebp+0x14) ": too many outputs\n")
26404         (flush *(ebp+0x14))
26405         (stop *(ebp+0x18) 1)
26406       }
26407       # if (expected == 0) error("too few outputs")
26408       {
26409         81 7/subop/compare %edx 0/imm32
26410         0f 84/jump-if-= break/disp32
26411         (write-buffered *(ebp+0x14) "fn ")
26412         8b/-> *(ebp+0x10) 0/r32/eax
26413         (lookup *eax *(eax+4))  # Function-name Function-name => eax
26414         (write-buffered *(ebp+0x14) %eax)
26415         (write-buffered *(ebp+0x14) ": call ")
26416         (lookup *edi *(edi+4))  # Function-name Function-name => eax
26417         (write-buffered *(ebp+0x14) %eax)
26418         (write-buffered *(ebp+0x14) ": too few outputs\n")
26419         (flush *(ebp+0x14))
26420         (stop *(ebp+0x18) 1)
26421       }
26422     }
26423 $check-mu-call:end:
26424     # . restore registers
26425     5f/pop-to-edi
26426     5e/pop-to-esi
26427     5b/pop-to-ebx
26428     5a/pop-to-edx
26429     59/pop-to-ecx
26430     58/pop-to-eax
26431     # . reclaim locals exclusively on the stack
26432     81 0/subop/add %esp 0x70/imm32
26433     # . epilogue
26434     89/<- %esp 5/r32/ebp
26435     5d/pop-to-ebp
26436     c3/return
26437 
26438 # like type-equal? but takes literals type parameters into account
26439 type-match?:  # def: (addr type-tree), call: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean
26440     # . prologue
26441     55/push-ebp
26442     89/<- %ebp 4/r32/esp
26443     # if call is literal and def is numberlike, return true
26444     {
26445 $type-match?:check-literal-int:
26446       (simple-mu-type? *(ebp+0xc) 0)  # literal => eax
26447       3d/compare-eax-and 0/imm32/false
26448       74/jump-if-= break/disp8
26449       (mu-numberlike-output? *(ebp+8))  # => eax
26450       3d/compare-eax-and 0/imm32/false
26451       74/jump-if-= break/disp8
26452       b8/copy-to-eax 1/imm32/true
26453       e9/jump $type-match?:end/disp32
26454     }
26455     # if call is literal-string, match against (addr array byte)
26456     {
26457 $type-match?:check-literal-string:
26458       (simple-mu-type? *(ebp+0xc) 0x10)  # literal-string => eax
26459       3d/compare-eax-and 0/imm32/false
26460       74/jump-if-= break/disp8
26461       (type-component-match? *(ebp+8) Addr-type-string *(ebp+0x10))  # => eax
26462       e9/jump $type-match?:end/disp32
26463     }
26464 $type-match?:baseline:
26465     # otherwise fall back
26466     (type-component-match? *(ebp+8) *(ebp+0xc) *(ebp+0x10))  # => eax
26467 $type-match?:end:
26468     # . epilogue
26469     89/<- %esp 5/r32/ebp
26470     5d/pop-to-ebp
26471     c3/return
26472 
26473 type-component-match?:  # def: (addr type-tree), call: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean
26474     # . prologue
26475     55/push-ebp
26476     89/<- %ebp 4/r32/esp
26477     # . save registers
26478     51/push-ecx
26479     52/push-edx
26480     53/push-ebx
26481     # ecx = def
26482     8b/-> *(ebp+8) 1/r32/ecx
26483     # edx = call
26484     8b/-> *(ebp+0xc) 2/r32/edx
26485 $type-component-match?:compare-addr:
26486     # if (def == call) return true
26487     8b/-> %ecx 0/r32/eax  # Var-type
26488     39/compare %edx 0/r32/eax  # Var-type
26489     b8/copy-to-eax 1/imm32/true
26490     0f 84/jump-if-= $type-component-match?:end/disp32
26491     # if (def == 0) return false
26492     b8/copy-to-eax 0/imm32/false
26493     81 7/subop/compare %ecx 0/imm32  # Type-tree-is-atom
26494     0f 84/jump-if-= $type-component-match?:end/disp32
26495     # if (call == 0) return false
26496     81 7/subop/compare %edx 0/imm32  # Type-tree-is-atom
26497     0f 84/jump-if-= $type-component-match?:end/disp32
26498     # if def is a type parameter, just check in type-parameters
26499     {
26500 $type-component-match?:check-type-parameter:
26501       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
26502       74/jump-if-= break/disp8
26503       81 7/subop/compare *(ecx+4) 0xa/imm32/type-parameter  # Type-tree-value
26504       75/jump-if-!= break/disp8
26505 $type-component-match?:type-parameter:
26506       (type-parameter-match? *(ecx+8) *(ecx+0xc)  %edx  *(ebp+0x10))  # => eax
26507       e9/jump $type-component-match?:end/disp32
26508     }
26509     # if def is a list containing just a type parameter, just check in type-parameters
26510     {
26511 $type-component-match?:check-list-type-parameter:
26512       # if def is a list..
26513       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
26514       75/jump-if-!= break/disp8
26515       #   ..that's a singleton
26516       81 7/subop/compare *(ecx+0xc) 0/imm32  # Type-tree-left
26517       75/jump-if-!= break/disp8
26518       #   ..and whose head is a type parameter
26519       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26520       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
26521       74/jump-if-= break/disp8
26522       81 7/subop/compare *(eax+4) 0xa/imm32/type-parameter  # Type-tree-value
26523       75/jump-if-!= break/disp8
26524 $type-component-match?:list-type-parameter:
26525       (type-parameter-match? *(eax+8) *(eax+0xc)  %edx  *(ebp+0x10))  # => eax
26526       e9/jump $type-component-match?:end/disp32
26527     }
26528 $type-component-match?:compare-atom-state:
26529     # if (def->is-atom? != call->is-atom?) return false
26530     8b/-> *ecx 3/r32/ebx  # Type-tree-is-atom
26531     39/compare *edx 3/r32/ebx  # Type-tree-is-atom
26532     b8/copy-to-eax 0/imm32/false
26533     0f 85/jump-if-!= $type-component-match?:end/disp32
26534     # if def->is-atom? return (def->value == call->value)
26535     {
26536 $type-component-match?:check-atom:
26537       81 7/subop/compare %ebx 0/imm32/false
26538       74/jump-if-= break/disp8
26539 $type-component-match?:is-atom:
26540       8b/-> *(ecx+4) 0/r32/eax  # Type-tree-value
26541       39/compare *(edx+4) 0/r32/eax  # Type-tree-value
26542       0f 94/set-if-= %al
26543       25/and-eax-with 0xff/imm32
26544       e9/jump $type-component-match?:end/disp32
26545     }
26546 $type-component-match?:check-left:
26547     # if (!type-component-match?(def->left, call->left)) return false
26548     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26549     89/<- %ebx 0/r32/eax
26550     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
26551     (type-component-match? %ebx %eax *(ebp+0x10))  # => eax
26552     3d/compare-eax-and 0/imm32/false
26553     74/jump-if-= $type-component-match?:end/disp8
26554 $type-component-match?:check-right:
26555     # return type-component-match?(def->right, call->right)
26556     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
26557     89/<- %ebx 0/r32/eax
26558     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
26559     (type-component-match? %ebx %eax *(ebp+0x10))  # => eax
26560 $type-component-match?:end:
26561     # . restore registers
26562     5b/pop-to-ebx
26563     5a/pop-to-edx
26564     59/pop-to-ecx
26565     # . epilogue
26566     89/<- %esp 5/r32/ebp
26567     5d/pop-to-ebp
26568     c3/return
26569 
26570 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
26571     # . prologue
26572     55/push-ebp
26573     89/<- %ebp 4/r32/esp
26574     # . save registers
26575     51/push-ecx
26576     #
26577     (get-or-insert-handle *(ebp+0x14)  *(ebp+8) *(ebp+0xc)  0xc)  # => eax
26578     # if parameter wasn't saved, save it
26579     {
26580       81 7/subop/compare *eax 0/imm32
26581       75/jump-if-!= break/disp8
26582       8b/-> *(ebp+0x10) 1/r32/ecx
26583       89/<- *eax 1/r32/ecx
26584     }
26585     #
26586     (type-equal? *(ebp+0x10) *eax)  # => eax
26587 $type-parameter-match?:end:
26588     # . restore registers
26589     59/pop-to-ecx
26590     # . epilogue
26591     89/<- %esp 5/r32/ebp
26592     5d/pop-to-ebp
26593     c3/return
26594 
26595 size-of:  # v: (addr var) -> result/eax: int
26596     # . prologue
26597     55/push-ebp
26598     89/<- %ebp 4/r32/esp
26599     # . save registers
26600     51/push-ecx
26601     # var t/ecx: (addr type-tree) = lookup(v->type)
26602     8b/-> *(ebp+8) 1/r32/ecx
26603 #?     (write-buffered Stderr "size-of ")
26604 #?     (write-int32-hex-buffered Stderr %ecx)
26605 #?     (write-buffered Stderr Newline)
26606 #?     (write-buffered Stderr "type allocid: ")
26607 #?     (write-int32-hex-buffered Stderr *(ecx+8))
26608 #?     (write-buffered Stderr Newline)
26609 #?     (flush Stderr)
26610     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
26611     89/<- %ecx 0/r32/eax
26612     # if mu-array?(t) return size-of-array(t)
26613     {
26614       (mu-array? %ecx)  # => eax
26615       3d/compare-eax-and 0/imm32/false
26616       74/jump-if-= break/disp8
26617       (size-of-array %ecx)  # => eax
26618       eb/jump $size-of:end/disp8
26619     }
26620     # if mu-stream?(t) return size-of-stream(t)
26621     {
26622       (mu-stream? %ecx)  # => eax
26623       3d/compare-eax-and 0/imm32/false
26624       74/jump-if-= break/disp8
26625       (size-of-stream %ecx)  # => eax
26626       eb/jump $size-of:end/disp8
26627     }
26628     # if (!t->is-atom?) t = lookup(t->left)
26629     {
26630       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
26631       75/jump-if-!= break/disp8
26632       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26633       89/<- %ecx 0/r32/eax
26634     }
26635     # TODO: assert t->is-atom?
26636     (size-of-type-id *(ecx+4))  # Type-tree-value => eax
26637 $size-of:end:
26638     # . restore registers
26639     59/pop-to-ecx
26640     # . epilogue
26641     89/<- %esp 5/r32/ebp
26642     5d/pop-to-ebp
26643     c3/return
26644 
26645 size-of-deref:  # v: (addr var) -> result/eax: int
26646     # . prologue
26647     55/push-ebp
26648     89/<- %ebp 4/r32/esp
26649     # . save registers
26650     51/push-ecx
26651     # var t/ecx: (addr type-tree) = lookup(v->type)
26652     8b/-> *(ebp+8) 1/r32/ecx
26653     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
26654     89/<- %ecx 0/r32/eax
26655     # TODO: assert(t is an addr)
26656     # t = lookup(t->right)
26657     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
26658     89/<- %ecx 0/r32/eax
26659     # if mu-array?(t) return size-of-array(t)
26660     {
26661       (mu-array? %ecx)  # => eax
26662       3d/compare-eax-and 0/imm32/false
26663       74/jump-if-= break/disp8
26664       (size-of-array %ecx)  # => eax
26665       eb/jump $size-of-deref:end/disp8
26666     }
26667     # if mu-stream?(t) return size-of-stream(t)
26668     {
26669       (mu-stream? %ecx)  # => eax
26670       3d/compare-eax-and 0/imm32/false
26671       74/jump-if-= break/disp8
26672       (size-of-stream %ecx)  # => eax
26673       eb/jump $size-of-deref:end/disp8
26674     }
26675     # if (!t->is-atom?) t = lookup(t->left)
26676     {
26677       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
26678       75/jump-if-!= break/disp8
26679       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26680       89/<- %ecx 0/r32/eax
26681     }
26682     # TODO: assert t->is-atom?
26683     (size-of-type-id *(ecx+4))  # Type-tree-value => eax
26684 $size-of-deref:end:
26685     # . restore registers
26686     59/pop-to-ecx
26687     # . epilogue
26688     89/<- %esp 5/r32/ebp
26689     5d/pop-to-ebp
26690     c3/return
26691 
26692 mu-array?:  # t: (addr type-tree) -> result/eax: boolean
26693     # . prologue
26694     55/push-ebp
26695     89/<- %ebp 4/r32/esp
26696     # . save registers
26697     51/push-ecx
26698     # ecx = t
26699     8b/-> *(ebp+8) 1/r32/ecx
26700     # if t->is-atom?, return false
26701     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
26702     75/jump-if-!= $mu-array?:return-false/disp8
26703     # if !t->left->is-atom?, return false
26704     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26705     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
26706     74/jump-if-= $mu-array?:return-false/disp8
26707     # return t->left->value == array
26708     81 7/subop/compare *(eax+4) 3/imm32/array-type-id  # Type-tree-value
26709     0f 94/set-if-= %al
26710     25/and-eax-with 0xff/imm32
26711     eb/jump $mu-array?:end/disp8
26712 $mu-array?:return-false:
26713     b8/copy-to-eax 0/imm32/false
26714 $mu-array?:end:
26715     # . restore registers
26716     59/pop-to-ecx
26717     # . epilogue
26718     89/<- %esp 5/r32/ebp
26719     5d/pop-to-ebp
26720     c3/return
26721 
26722 # size of a statically allocated array where the size is part of the type expression
26723 size-of-array:  # a: (addr type-tree) -> result/eax: int
26724     # . prologue
26725     55/push-ebp
26726     89/<- %ebp 4/r32/esp
26727     # . save registers
26728     51/push-ecx
26729     52/push-edx
26730     #
26731     8b/-> *(ebp+8) 1/r32/ecx
26732     # TODO: assert that a->left is 'array'
26733     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
26734     89/<- %ecx 0/r32/eax
26735     # var elem-type/edx: type-id = a->right->left->value
26736     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26737     8b/-> *(eax+4) 2/r32/edx  # Type-tree-value
26738     # TODO: assert that a->right->right->left->value == size
26739     # var array-size/ecx: int = a->right->right->left->value-size
26740     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
26741     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
26742     8b/-> *(eax+8) 1/r32/ecx  # Type-tree-value-size
26743     # return 4 + array-size * size-of(elem-type)
26744     (size-of-type-id-as-array-element %edx)  # => eax
26745     f7 4/subop/multiply-into-edx-eax %ecx
26746     05/add-to-eax 4/imm32  # for array size
26747     # TODO: check edx for overflow
26748 $size-of-array:end:
26749     # . restore registers
26750     5a/pop-to-edx
26751     59/pop-to-ecx
26752     # . epilogue
26753     89/<- %esp 5/r32/ebp
26754     5d/pop-to-ebp
26755     c3/return
26756 
26757 mu-stream?:  # t: (addr type-tree) -> result/eax: boolean
26758     # . prologue
26759     55/push-ebp
26760     89/<- %ebp 4/r32/esp
26761     # . save registers
26762     51/push-ecx
26763     # ecx = t
26764     8b/-> *(ebp+8) 1/r32/ecx
26765     # if t->is-atom?, return false
26766     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
26767     75/jump-if-!= $mu-stream?:return-false/disp8
26768     # if !t->left->is-atom?, return false
26769     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26770     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
26771     74/jump-if-= $mu-stream?:return-false/disp8
26772     # return t->left->value == stream
26773     81 7/subop/compare *(eax+4) 0xb/imm32/stream-type-id  # Type-tree-value
26774     0f 94/set-if-= %al
26775     25/and-eax-with 0xff/imm32
26776     eb/jump $mu-stream?:end/disp8
26777 $mu-stream?:return-false:
26778     b8/copy-to-eax 0/imm32/false
26779 $mu-stream?:end:
26780     # . restore registers
26781     59/pop-to-ecx
26782     # . epilogue
26783     89/<- %esp 5/r32/ebp
26784     5d/pop-to-ebp
26785     c3/return
26786 
26787 # size of a statically allocated stream where the size is part of the type expression
26788 size-of-stream:  # a: (addr type-tree) -> result/eax: int
26789     # . prologue
26790     55/push-ebp
26791     89/<- %ebp 4/r32/esp
26792     #
26793     (size-of-array *(ebp+8))  # assumes we ignore the actual type name 'array' in the type
26794     05/add-to-eax 8/imm32  # for read/write pointers
26795 $size-of-stream:end:
26796     # . epilogue
26797     89/<- %esp 5/r32/ebp
26798     5d/pop-to-ebp
26799     c3/return
26800 
26801 size-of-type-id:  # t: type-id -> result/eax: int
26802     # . prologue
26803     55/push-ebp
26804     89/<- %ebp 4/r32/esp
26805     # . save registers
26806     51/push-ecx
26807     # var out/ecx: (handle typeinfo)
26808     68/push 0/imm32
26809     68/push 0/imm32
26810     89/<- %ecx 4/r32/esp
26811     # eax = t
26812     8b/-> *(ebp+8) 0/r32/eax
26813     # if t is a literal, return 0
26814     3d/compare-eax-and 0/imm32
26815     0f 84/jump-if-= $size-of-type-id:end/disp32  # eax changes type from type-id to int
26816     # if t is a byte, return 4 (because we don't really support non-multiples of 4)
26817     3d/compare-eax-and 8/imm32/byte
26818     {
26819       75/jump-if-!= break/disp8
26820       b8/copy-to-eax 4/imm32
26821       eb/jump $size-of-type-id:end/disp8
26822     }
26823     # if t is a handle, return 8
26824     3d/compare-eax-and 4/imm32/handle
26825     {
26826       75/jump-if-!= break/disp8
26827       b8/copy-to-eax 8/imm32
26828       eb/jump $size-of-type-id:end/disp8  # eax changes type from type-id to int
26829     }
26830     # if t is a slice, return 8
26831     3d/compare-eax-and 0xc/imm32/slice
26832     {
26833       75/jump-if-!= break/disp8
26834       b8/copy-to-eax 8/imm32
26835       eb/jump $size-of-type-id:end/disp8  # eax changes type from type-id to int
26836     }
26837     # if t is a user-defined type, return its size
26838     # TODO: support non-atom type
26839     (find-typeinfo %eax %ecx)
26840     {
26841       81 7/subop/compare *ecx 0/imm32
26842       74/jump-if-= break/disp8
26843 $size-of-type-id:user-defined:
26844       (lookup *ecx *(ecx+4))  # => eax
26845       8b/-> *(eax+0xc) 0/r32/eax  # Typeinfo-total-size-in-bytes
26846       eb/jump $size-of-type-id:end/disp8
26847     }
26848     # otherwise return the word size
26849     b8/copy-to-eax 4/imm32
26850 $size-of-type-id:end:
26851     # . reclaim locals
26852     81 0/subop/add %esp 8/imm32
26853     # . restore registers
26854     59/pop-to-ecx
26855     # . epilogue
26856     89/<- %esp 5/r32/ebp
26857     5d/pop-to-ebp
26858     c3/return
26859 
26860 # Minor violation of our type system since it returns an addr. But we could
26861 # replace it with a handle some time.
26862 # Returns null if t is an atom.
26863 type-tail:  # t: (addr type-tree) -> out/eax: (addr type-tree)
26864     # . prologue
26865     55/push-ebp
26866     89/<- %ebp 4/r32/esp
26867     # . save registers
26868     51/push-ecx
26869     # eax = 0
26870     b8/copy-to-eax 0/imm32
26871     # ecx = t
26872     8b/-> *(ebp+8) 1/r32/ecx
26873 $type-tail:check-atom:
26874     # if t->is-atom? return 0
26875     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
26876     0f 85/jump-if-!= $type-tail:end/disp32
26877     # var tail = t->right
26878     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
26879     89/<- %ecx 0/r32/eax
26880 $type-tail:check-singleton:
26881     # if (tail->right == 0) return tail->left
26882     {
26883       81 7/subop/compare *(ecx+0xc) 0/imm32  # Type-tree-right
26884       75/jump-if-!= break/disp8
26885       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26886       e9/jump $type-tail:end/disp32
26887     }
26888     # if tail->right->left is an array-capacity, return tail->left
26889     {
26890 $type-tail:check-array-capacity:
26891       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
26892       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
26893       75/jump-if-!= break/disp8
26894 $type-tail:check-array-capacity-1:
26895       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
26896       3d/compare-eax-and 0/imm32
26897       74/jump-if-= break/disp8
26898 $type-tail:check-array-capacity-2:
26899       (simple-mu-type? %eax 9)  # array-capacity => eax
26900       3d/compare-eax-and 0/imm32/false
26901       74/jump-if-= break/disp8
26902 $type-tail:array-capacity:
26903       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26904       eb/jump $type-tail:end/disp8
26905     }
26906 $type-tail:check-compound-left:
26907     # if !tail->left->is-atom? return tail->left
26908     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26909     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
26910     74/jump-if-= $type-tail:end/disp8
26911 $type-tail:return-tail:
26912     # return tail
26913     89/<- %eax 1/r32/ecx
26914 $type-tail:end:
26915     # . restore registers
26916     59/pop-to-ecx
26917     # . epilogue
26918     89/<- %esp 5/r32/ebp
26919     5d/pop-to-ebp
26920     c3/return
26921 
26922 type-equal?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
26923     # . prologue
26924     55/push-ebp
26925     89/<- %ebp 4/r32/esp
26926     # . save registers
26927     51/push-ecx
26928     52/push-edx
26929     53/push-ebx
26930     # ecx = a
26931     8b/-> *(ebp+8) 1/r32/ecx
26932     # edx = b
26933     8b/-> *(ebp+0xc) 2/r32/edx
26934 $type-equal?:compare-addr:
26935     # if (a == b) return true
26936     8b/-> %ecx 0/r32/eax  # Var-type
26937     39/compare %edx 0/r32/eax  # Var-type
26938     b8/copy-to-eax 1/imm32/true
26939     0f 84/jump-if-= $type-equal?:end/disp32
26940 $type-equal?:compare-null-a:
26941     # if (a == 0) return false
26942     b8/copy-to-eax 0/imm32/false
26943     81 7/subop/compare %ecx 0/imm32
26944     0f 84/jump-if-= $type-equal?:end/disp32
26945 $type-equal?:compare-null-b:
26946     # if (b == 0) return false
26947     81 7/subop/compare %edx 0/imm32
26948     0f 84/jump-if-= $type-equal?:end/disp32
26949 $type-equal?:compare-atom-state:
26950     # if (a->is-atom? != b->is-atom?) return false
26951     8b/-> *ecx 3/r32/ebx  # Type-tree-is-atom
26952     39/compare *edx 3/r32/ebx  # Type-tree-is-atom
26953     b8/copy-to-eax 0/imm32/false
26954     0f 85/jump-if-!= $type-equal?:end/disp32
26955     # if a->is-atom? return (a->value == b->value)
26956     {
26957 $type-equal?:check-atom:
26958       81 7/subop/compare %ebx 0/imm32/false
26959       74/jump-if-= break/disp8
26960 $type-equal?:is-atom:
26961       8b/-> *(ecx+4) 0/r32/eax  # Type-tree-value
26962       39/compare *(edx+4) 0/r32/eax  # Type-tree-value
26963       0f 94/set-if-= %al
26964       25/and-eax-with 0xff/imm32
26965       e9/jump $type-equal?:end/disp32
26966     }
26967 $type-equal?:check-left:
26968     # if (!type-equal?(a->left, b->left)) return false
26969     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26970     89/<- %ebx 0/r32/eax
26971     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
26972     (type-equal? %eax %ebx)  # => eax
26973     3d/compare-eax-and 0/imm32/false
26974     74/jump-if-= $type-equal?:end/disp8
26975 $type-equal?:check-right:
26976     # return type-equal?(a->right, b->right)
26977     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
26978     89/<- %ebx 0/r32/eax
26979     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
26980     (type-equal? %eax %ebx)  # => eax
26981 $type-equal?:end:
26982     # . restore registers
26983     5b/pop-to-ebx
26984     5a/pop-to-edx
26985     59/pop-to-ecx
26986     # . epilogue
26987     89/<- %esp 5/r32/ebp
26988     5d/pop-to-ebp
26989     c3/return
26990 
26991 #######################################################
26992 # Code-generation
26993 #######################################################
26994 
26995 == data
26996 
26997 # Global state added to each var record when performing code-generation.
26998 Curr-local-stack-offset:  # (addr int)
26999     0/imm32
27000 
27001 == code
27002 
27003 # We may not need to pass err/ed everywhere here. I think they're relics of Mu
27004 # getting type checks later in life.
27005 # But we do need them for runtime checks, particularly array index bounds checks.
27006 # So perhaps it's not worth taking them out. They're a safety net.
27007 
27008 emit-subx:  # out: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
27009     # . prologue
27010     55/push-ebp
27011     89/<- %ebp 4/r32/esp
27012     # . save registers
27013     50/push-eax
27014     # var curr/eax: (addr function) = *Program->functions
27015     (lookup *_Program-functions *_Program-functions->payload)  # => eax
27016     {
27017       # if (curr == null) break
27018       3d/compare-eax-and 0/imm32
27019       0f 84/jump-if-= break/disp32
27020       (emit-subx-function *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10))
27021       # curr = lookup(curr->next)
27022       (lookup *(eax+0x20) *(eax+0x24))  # Function-next Function-next => eax
27023       e9/jump loop/disp32
27024     }
27025 $emit-subx:end:
27026     # . restore registers
27027     58/pop-to-eax
27028     # . epilogue
27029     89/<- %esp 5/r32/ebp
27030     5d/pop-to-ebp
27031     c3/return
27032 
27033 emit-subx-function:  # out: (addr buffered-file), f: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
27034     # . prologue
27035     55/push-ebp
27036     89/<- %ebp 4/r32/esp
27037     # some preprocessing
27038     (populate-mu-type-offsets-in-inouts *(ebp+0xc))
27039     # . save registers
27040     50/push-eax
27041     51/push-ecx
27042     52/push-edx
27043     # initialize some global state
27044     c7 0/subop/copy *Curr-block-depth 1/imm32  # Important: keep this in sync with the parse phase
27045     c7 0/subop/copy *Curr-local-stack-offset 0/imm32
27046     # ecx = f
27047     8b/-> *(ebp+0xc) 1/r32/ecx
27048     # var vars/edx: (stack (addr var) 256)
27049     81 5/subop/subtract %esp 0xc00/imm32
27050     68/push 0xc00/imm32/size
27051     68/push 0/imm32/top
27052     89/<- %edx 4/r32/esp
27053     # var name/eax: (addr array byte) = lookup(f->name)
27054     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
27055     #
27056     (write-buffered *(ebp+8) %eax)
27057     (write-buffered *(ebp+8) ":\n")
27058     (emit-subx-prologue *(ebp+8))
27059     # var body/eax: (addr block) = lookup(f->body)
27060     (lookup *(ecx+0x18) *(ecx+0x1c))  # Function-body Function-body => eax
27061     #
27062     (emit-subx-block *(ebp+8) %eax %edx *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
27063     (emit-subx-epilogue *(ebp+8))
27064     # TODO: validate that *Curr-block-depth and *Curr-local-stack-offset have
27065     # been cleaned up
27066 $emit-subx-function:end:
27067     # . reclaim locals
27068     81 0/subop/add %esp 0xc08/imm32
27069     # . restore registers
27070     5a/pop-to-edx
27071     59/pop-to-ecx
27072     58/pop-to-eax
27073     # . epilogue
27074     89/<- %esp 5/r32/ebp
27075     5d/pop-to-ebp
27076     c3/return
27077 
27078 populate-mu-type-offsets-in-inouts:  # f: (addr function)
27079     # . prologue
27080     55/push-ebp
27081     89/<- %ebp 4/r32/esp
27082     # . save registers
27083     50/push-eax
27084     51/push-ecx
27085     52/push-edx
27086     53/push-ebx
27087     57/push-edi
27088     # var next-offset/edx: int = 8
27089     ba/copy-to-edx 8/imm32
27090     # var curr/ecx: (addr list var) = lookup(f->inouts)
27091     8b/-> *(ebp+8) 1/r32/ecx
27092     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
27093     89/<- %ecx 0/r32/eax
27094     {
27095 $populate-mu-type-offsets-in-inouts:loop:
27096       81 7/subop/compare %ecx 0/imm32
27097       74/jump-if-= break/disp8
27098       # var v/ebx: (addr var) = lookup(curr->value)
27099       (lookup *ecx *(ecx+4))  # List-value List-value => eax
27100       89/<- %ebx 0/r32/eax
27101 #?       (lookup *ebx *(ebx+4))
27102 #?       (write-buffered Stderr "setting offset of fn inout ")
27103 #?       (write-buffered Stderr %eax)
27104 #?       (write-buffered Stderr "@")
27105 #?       (write-int32-hex-buffered Stderr %ebx)
27106 #?       (write-buffered Stderr " to ")
27107 #?       (write-int32-hex-buffered Stderr %edx)
27108 #?       (write-buffered Stderr Newline)
27109 #?       (flush Stderr)
27110       # v->offset = next-offset
27111       89/<- *(ebx+0x14) 2/r32/edx  # Var-offset
27112       # next-offset += size-of(v)
27113       (size-of %ebx)  # => eax
27114       01/add-to %edx 0/r32/eax
27115       # curr = lookup(curr->next)
27116       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
27117       89/<- %ecx 0/r32/eax
27118       #
27119       eb/jump loop/disp8
27120     }
27121 $populate-mu-type-offsets-in-inouts:end:
27122     # . restore registers
27123     5f/pop-to-edi
27124     5b/pop-to-ebx
27125     5a/pop-to-edx
27126     59/pop-to-ecx
27127     58/pop-to-eax
27128     # . epilogue
27129     89/<- %esp 5/r32/ebp
27130     5d/pop-to-ebp
27131     c3/return
27132 
27133 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)
27134     # . prologue
27135     55/push-ebp
27136     89/<- %ebp 4/r32/esp
27137     # . save registers
27138     50/push-eax
27139     51/push-ecx
27140     53/push-ebx
27141     56/push-esi
27142     # esi = stmts
27143     8b/-> *(ebp+0xc) 6/r32/esi
27144     #
27145     {
27146 $emit-subx-stmt-list:loop:
27147       81 7/subop/compare %esi 0/imm32
27148       0f 84/jump-if-= break/disp32
27149       # var curr-stmt/ecx: (addr stmt) = lookup(stmts->value)
27150       (lookup *esi *(esi+4))  # List-value List-value => eax
27151       89/<- %ecx 0/r32/eax
27152       {
27153 $emit-subx-stmt-list:check-for-block:
27154         81 7/subop/compare *ecx 0/imm32/block  # Stmt-tag
27155         75/jump-if-!= break/disp8
27156 $emit-subx-stmt-list:block:
27157         (emit-subx-block *(ebp+8) %ecx *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
27158       }
27159       {
27160 $emit-subx-stmt-list:check-for-stmt:
27161         81 7/subop/compare *ecx 1/imm32/stmt1  # Stmt-tag
27162         0f 85/jump-if-!= break/disp32
27163 $emit-subx-stmt-list:stmt1:
27164         {
27165           (mu-branch? %ecx)  # => eax
27166           3d/compare-eax-and 0/imm32/false
27167           0f 84/jump-if-= break/disp32
27168 $emit-subx-stmt-list:branch-stmt:
27169 +-- 25 lines: # unconditional return ----------------------------------------------------------------------------------------------------------------------------------------------------
27194 +-- 27 lines: # unconditional loops -----------------------------------------------------------------------------------------------------------------------------------------------------
27221 +-- 16 lines: # unconditional breaks ----------------------------------------------------------------------------------------------------------------------------------------------------
27237 +-- 38 lines: # simple conditional branches without a target ----------------------------------------------------------------------------------------------------------------------------
27275 +-- 19 lines: # conditional branches with an explicit target ----------------------------------------------------------------------------------------------------------------------------
27294         }
27295 $emit-subx-stmt-list:1-to-1:
27296         (emit-subx-stmt *(ebp+8) %ecx Primitives *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
27297         e9/jump $emit-subx-stmt-list:continue/disp32
27298       }
27299       {
27300 $emit-subx-stmt-list:check-for-var-def:
27301         81 7/subop/compare *ecx 2/imm32/var-def  # Stmt-tag
27302         75/jump-if-!= break/disp8
27303 $emit-subx-stmt-list:var-def:
27304         (emit-subx-var-def *(ebp+8) %ecx *(ebp+0x18) *(ebp+0x1c))
27305         (push *(ebp+0x10) *(ecx+4))  # Vardef-var
27306         (push *(ebp+0x10) *(ecx+8))  # Vardef-var
27307         (push *(ebp+0x10) 0)  # Live-var-register-spilled = 0 for vars on the stack
27308         #
27309         eb/jump $emit-subx-stmt-list:continue/disp8
27310       }
27311       {
27312 $emit-subx-stmt-list:check-for-reg-var-def:
27313         81 7/subop/compare *ecx 3/imm32/reg-var-def  # Stmt-tag
27314         0f 85/jump-if-!= break/disp32
27315 $emit-subx-stmt-list:reg-var-def:
27316         # TODO: ensure that there's exactly one output
27317         (push-output-and-maybe-emit-spill *(ebp+8) %ecx *(ebp+0x10) %esi *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
27318         # emit the instruction as usual
27319         (emit-subx-stmt *(ebp+8) %ecx Primitives *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
27320         #
27321         eb/jump $emit-subx-stmt-list:continue/disp8
27322       }
27323 $emit-subx-stmt-list:continue:
27324       # TODO: raise an error on unrecognized Stmt-tag
27325       (lookup *(esi+8) *(esi+0xc))  # List-next List-next => eax
27326       89/<- %esi 0/r32/eax
27327       e9/jump loop/disp32
27328     }
27329 $emit-subx-stmt-list:emit-cleanup:
27330     (emit-cleanup-code-until-depth *(ebp+8) *(ebp+0x10) *Curr-block-depth)
27331 $emit-subx-stmt-list:clean-up:
27332     (clean-up-stack-offset-state *(ebp+0x10) *Curr-block-depth)
27333     (clean-up-blocks *(ebp+0x10) *Curr-block-depth *(ebp+0x14))
27334 $emit-subx-stmt-list:end:
27335     # . restore registers
27336     5e/pop-to-esi
27337     5b/pop-to-ebx
27338     59/pop-to-ecx
27339     58/pop-to-eax
27340     # . epilogue
27341     89/<- %esp 5/r32/ebp
27342     5d/pop-to-ebp
27343     c3/return
27344 
27345 # 'later-stmts' includes 'stmt', but will behave the same even without it; reg-var-def stmts are guaranteed not to write to function outputs.
27346 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)
27347     # . prologue
27348     55/push-ebp
27349     89/<- %ebp 4/r32/esp
27350     # . save registers
27351     50/push-eax
27352     51/push-ecx
27353     52/push-edx
27354     # ecx = stmt
27355     8b/-> *(ebp+0xc) 1/r32/ecx
27356     # var sv/eax: (addr stmt-var) = lookup(curr-stmt->outputs)
27357     (lookup *(ecx+0x14) *(ecx+0x18))  # Regvardef-outputs Regvardef-outputs => eax
27358     # TODO: assert !sv->is-deref?
27359     # var v/ecx: (addr var) = lookup(sv->value)
27360     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27361     89/<- %ecx 0/r32/eax
27362     # v->block-depth = *Curr-block-depth
27363     8b/-> *Curr-block-depth 0/r32/eax
27364     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
27365 #?     (write-buffered Stderr "var ")
27366 #?     (lookup *ecx *(ecx+4))
27367 #?     (write-buffered Stderr %eax)
27368 #?     (write-buffered Stderr " at depth ")
27369 #?     (write-int32-hex-buffered Stderr *(ecx+0x10))
27370 #?     (write-buffered Stderr Newline)
27371 #?     (flush Stderr)
27372     # ensure that v is in a register
27373     81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
27374     0f 84/jump-if-= $push-output-and-maybe-emit-spill:abort/disp32
27375     # var emit-spill?/edx: boolean = not-yet-spilled-this-block? && will-not-write-some-register?(fn)
27376     (not-yet-spilled-this-block? %ecx *(ebp+0x10))  # => eax
27377     89/<- %edx 0/r32/eax
27378     3d/compare-eax-and 0/imm32/false
27379     0f 84/jump-if-= $push-output-and-maybe-emit-spill:push/disp32
27380     (will-not-write-some-register? %ecx *(ebp+0x14) *(ebp+0x18))  # => eax
27381     89/<- %edx 0/r32/eax
27382     # check emit-spill?
27383     3d/compare-eax-and 0/imm32/false
27384     0f 84/jump-if-= $push-output-and-maybe-emit-spill:push/disp32
27385     # TODO: assert(size-of(output) == 4)
27386     # *Curr-local-stack-offset -= 4
27387     81 5/subop/subtract *Curr-local-stack-offset 4/imm32
27388     # emit spill
27389     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
27390     (emit-push-register *(ebp+8) %eax)
27391 $push-output-and-maybe-emit-spill:push:
27392     8b/-> *(ebp+0xc) 1/r32/ecx
27393     (lookup *(ecx+0x14) *(ecx+0x18))  # Regvardef-outputs Regvardef-outputs => eax
27394     # push(vars, {sv->value, emit-spill?})
27395     (push *(ebp+0x10) *eax)  # Stmt-var-value
27396     (push *(ebp+0x10) *(eax+4))  # Stmt-var-value
27397     (push *(ebp+0x10) %edx)
27398 $push-output-and-maybe-emit-spill:end:
27399     # . restore registers
27400     5a/pop-to-edx
27401     59/pop-to-ecx
27402     58/pop-to-eax
27403     # . epilogue
27404     89/<- %esp 5/r32/ebp
27405     5d/pop-to-ebp
27406     c3/return
27407 
27408 $push-output-and-maybe-emit-spill:abort:
27409     # error("var '" var->name "' initialized from an instruction must live in a register\n")
27410     (write-buffered *(ebp+0x1c) "var '")
27411     (write-buffered *(ebp+0x1c) *eax)  # Var-name
27412     (write-buffered *(ebp+0x1c) "' initialized from an instruction must live in a register\n")
27413     (flush *(ebp+0x1c))
27414     (stop *(ebp+0x20) 1)
27415     # never gets here
27416 
27417 emit-subx-cleanup-and-unconditional-nonlocal-branch:  # out: (addr buffered-file), stmt: (addr stmt1), vars: (addr stack live-var)
27418     # . prologue
27419     55/push-ebp
27420     89/<- %ebp 4/r32/esp
27421     # . save registers
27422     50/push-eax
27423     51/push-ecx
27424     # ecx = stmt
27425     8b/-> *(ebp+0xc) 1/r32/ecx
27426     # var target/eax: (addr array byte) = curr-stmt->inouts->value->name
27427     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27428     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27429     (lookup *eax *(eax+4))  # Var-name Var-name => eax
27430     # clean up until target block
27431     (emit-cleanup-code-until-target *(ebp+8) *(ebp+0x10) %eax)
27432     # emit jump to target block
27433     (emit-indent *(ebp+8) *Curr-block-depth)
27434     (write-buffered *(ebp+8) "e9/jump ")
27435     (write-buffered *(ebp+8) %eax)
27436     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
27437     (string-starts-with? %eax "break")
27438     3d/compare-eax-and 0/imm32/false
27439     {
27440       74/jump-if-= break/disp8
27441       (write-buffered *(ebp+8) ":break/disp32\n")
27442       eb/jump $emit-subx-cleanup-and-unconditional-nonlocal-branch:end/disp8
27443     }
27444     (write-buffered *(ebp+8) ":loop/disp32\n")
27445 $emit-subx-cleanup-and-unconditional-nonlocal-branch:end:
27446     # . restore registers
27447     59/pop-to-ecx
27448     58/pop-to-eax
27449     # . epilogue
27450     89/<- %esp 5/r32/ebp
27451     5d/pop-to-ebp
27452     c3/return
27453 
27454 emit-outputs:  # out: (addr buffered-file), return-stmt: (addr stmt1), fn: (addr function)
27455     # . prologue
27456     55/push-ebp
27457     89/<- %ebp 4/r32/esp
27458     # . save registers
27459     50/push-eax
27460     51/push-ecx
27461     56/push-esi
27462     57/push-edi
27463     # var curr-inout/esi: (addr stmt-var) = return-stmt->inouts
27464     8b/-> *(ebp+0xc) 0/r32/eax
27465     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27466     89/<- %esi 0/r32/eax
27467     # var curr-output/edi: (addr list var) = fn->outputs
27468     8b/-> *(ebp+0x10) 0/r32/eax
27469     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
27470     89/<- %edi 0/r32/eax
27471     {
27472 $emit-outputs:loop:
27473       81 7/subop/compare %esi 0/imm32
27474       0f 84/jump-if-= break/disp32
27475       # emit copy to output register
27476       # var curr-output-register/ecx: (addr array byte) = curr-output->value->register
27477       (lookup *edi *(edi+4))  # List-value List-value => eax
27478       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
27479       89/<- %ecx 0/r32/eax
27480       # if curr-output-register starts with "x", emit a floating-point copy
27481       8a/copy-byte *(ecx+4) 0/r32/AL
27482       25/and-eax-with 0xff/imm32
27483       3d/compare-eax-and 0x78/imm32/x
27484       {
27485         75/jump-if-!= break/disp8
27486         (emit-float-output *(ebp+8) %esi %ecx)
27487         eb/jump $emit-outputs:continue/disp8
27488       }
27489       # otherwise emit an int copy
27490       (emit-int-output *(ebp+8) %esi %ecx)
27491 $emit-outputs:continue:
27492       # curr-inout = curr-inout->next
27493       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
27494       89/<- %esi 0/r32/eax
27495       # curr-output = curr-output->next
27496       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
27497       89/<- %edi 0/r32/eax
27498       #
27499       e9/jump loop/disp32
27500     }
27501 $emit-outputs:end:
27502     # . restore registers
27503     5f/pop-to-edi
27504     5e/pop-to-esi
27505     59/pop-to-ecx
27506     58/pop-to-eax
27507     # . epilogue
27508     89/<- %esp 5/r32/ebp
27509     5d/pop-to-ebp
27510     c3/return
27511 
27512 emit-int-output:  # out: (addr buffered-file), return-var: (addr stmt-var), dest-reg: (addr array byte)
27513     # . prologue
27514     55/push-ebp
27515     89/<- %ebp 4/r32/esp
27516     # . save registers
27517     50/push-eax
27518     51/push-ecx
27519     # ecx = return-var->value
27520     8b/-> *(ebp+0xc) 0/r32/eax
27521     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27522     89/<- %ecx 0/r32/eax
27523     # if curr-var is a literal, emit copy of a literal to the output
27524     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
27525     (simple-mu-type? %eax 0)  # literal => eax
27526     {
27527       3d/compare-eax-and 0/imm32/false
27528       0f 84/jump-if-= break/disp32
27529       (emit-indent *(ebp+8) *Curr-block-depth)
27530       (write-buffered *(ebp+8) "c7 0/subop/copy %")
27531       (write-buffered *(ebp+8) *(ebp+0x10))
27532       (write-buffered *(ebp+8) " ")
27533       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
27534       (write-buffered *(ebp+8) %eax)
27535       (write-buffered *(ebp+8) "/imm32\n")
27536       e9/jump $emit-int-output:end/disp32
27537     }
27538     # otherwise emit an integer copy
27539     (emit-indent *(ebp+8) *Curr-block-depth)
27540     (write-buffered *(ebp+8) "8b/->")
27541     (emit-subx-var-as-rm32 *(ebp+8) *(ebp+0xc))
27542     (write-buffered *(ebp+8) " ")
27543     (get Mu-registers *(ebp+0x10) 0xc "Mu-registers")  # => eax
27544     (write-int32-hex-buffered *(ebp+8) *eax)
27545     (write-buffered *(ebp+8) "/r32\n")
27546 $emit-int-output:end:
27547     # . restore registers
27548     59/pop-to-ecx
27549     58/pop-to-eax
27550     # . epilogue
27551     89/<- %esp 5/r32/ebp
27552     5d/pop-to-ebp
27553     c3/return
27554 
27555 emit-float-output:  # out: (addr buffered-file), return-var: (addr stmt-var), dest-reg: (addr array byte)
27556     # . prologue
27557     55/push-ebp
27558     89/<- %ebp 4/r32/esp
27559     # . save registers
27560     50/push-eax
27561     #
27562     (emit-indent *(ebp+8) *Curr-block-depth)
27563     (write-buffered *(ebp+8) "f3 0f 10/->")
27564     (emit-subx-var-as-rm32 *(ebp+8) *(ebp+0xc))
27565     (write-buffered *(ebp+8) " ")
27566     (get Mu-registers *(ebp+0x10) 0xc "Mu-registers")  # => eax
27567     (write-int32-hex-buffered *(ebp+8) *eax)
27568     (write-buffered *(ebp+8) "/x32\n")
27569 $emit-float-output:end:
27570     # . restore registers
27571     58/pop-to-eax
27572     # . epilogue
27573     89/<- %esp 5/r32/ebp
27574     5d/pop-to-ebp
27575     c3/return
27576 
27577 mu-branch?:  # stmt: (addr stmt1) -> result/eax: boolean
27578     # . prologue
27579     55/push-ebp
27580     89/<- %ebp 4/r32/esp
27581     # . save registers
27582     51/push-ecx
27583     # ecx = lookup(stmt->operation)
27584     8b/-> *(ebp+8) 1/r32/ecx
27585     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
27586     89/<- %ecx 0/r32/eax
27587     # if (stmt->operation starts with "loop") return true
27588     (string-starts-with? %ecx "loop")  # => eax
27589     3d/compare-eax-and 0/imm32/false
27590     75/jump-if-not-equal $mu-branch?:end/disp8
27591     # if (stmt->operation starts with "break") return true
27592     (string-starts-with? %ecx "break")  # => eax
27593     3d/compare-eax-and 0/imm32/false
27594     75/jump-if-not-equal $mu-branch?:end/disp8
27595     # otherwise return (stmt->operation starts with "return")
27596     (string-starts-with? %ecx "return")  # => eax
27597 $mu-branch?:end:
27598     # . restore registers
27599     59/pop-to-ecx
27600     # . epilogue
27601     89/<- %esp 5/r32/ebp
27602     5d/pop-to-ebp
27603     c3/return
27604 
27605 emit-reverse-break:  # out: (addr buffered-file), stmt: (addr stmt1)
27606     # . prologue
27607     55/push-ebp
27608     89/<- %ebp 4/r32/esp
27609     # . save registers
27610     50/push-eax
27611     # eax = stmt
27612     8b/-> *(ebp+0xc) 0/r32/eax
27613     #
27614     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
27615     (get Reverse-branch %eax 0x10 "reverse-branch: ")  # => eax: (addr handle array byte)
27616     (emit-indent *(ebp+8) *Curr-block-depth)
27617     (lookup *eax *(eax+4))  # => eax
27618     (write-buffered *(ebp+8) %eax)
27619     (write-buffered *(ebp+8) " break/disp32\n")
27620 $emit-reverse-break:end:
27621     # . restore registers
27622     58/pop-to-eax
27623     # . epilogue
27624     89/<- %esp 5/r32/ebp
27625     5d/pop-to-ebp
27626     c3/return
27627 
27628 == data
27629 
27630 # Table from Mu branch instructions to the reverse SubX opcodes for them.
27631 Reverse-branch:  # (table (handle array byte) (handle array byte))
27632   # a table is a stream
27633   0x240/imm32/write
27634   0/imm32/read
27635   0x240/imm32/size
27636   # data
27637   0x11/imm32/alloc-id   _string-break-if-=/imm32                0x11/imm32/alloc-id   _string_0f_85_jump_label/imm32
27638   0x11/imm32/alloc-id   _string-loop-if-=/imm32                 0x11/imm32/alloc-id   _string_0f_85_jump_label/imm32
27639   0x11/imm32/alloc-id   _string-break-if-!=/imm32               0x11/imm32/alloc-id   _string_0f_84_jump_label/imm32
27640   0x11/imm32/alloc-id   _string-loop-if-!=/imm32                0x11/imm32/alloc-id   _string_0f_84_jump_label/imm32
27641   0x11/imm32/alloc-id   _string-break-if-</imm32                0x11/imm32/alloc-id   _string_0f_8d_jump_label/imm32
27642   0x11/imm32/alloc-id   _string-loop-if-</imm32                 0x11/imm32/alloc-id   _string_0f_8d_jump_label/imm32
27643   0x11/imm32/alloc-id   _string-break-if->/imm32                0x11/imm32/alloc-id   _string_0f_8e_jump_label/imm32
27644   0x11/imm32/alloc-id   _string-loop-if->/imm32                 0x11/imm32/alloc-id   _string_0f_8e_jump_label/imm32
27645   0x11/imm32/alloc-id   _string-break-if-<=/imm32               0x11/imm32/alloc-id   _string_0f_8f_jump_label/imm32
27646   0x11/imm32/alloc-id   _string-loop-if-<=/imm32                0x11/imm32/alloc-id   _string_0f_8f_jump_label/imm32
27647   0x11/imm32/alloc-id   _string-break-if->=/imm32               0x11/imm32/alloc-id   _string_0f_8c_jump_label/imm32
27648   0x11/imm32/alloc-id   _string-loop-if->=/imm32                0x11/imm32/alloc-id   _string_0f_8c_jump_label/imm32
27649   0x11/imm32/alloc-id   _string-break-if-addr</imm32            0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
27650   0x11/imm32/alloc-id   _string-loop-if-addr</imm32             0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
27651   0x11/imm32/alloc-id   _string-break-if-addr>/imm32            0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
27652   0x11/imm32/alloc-id   _string-loop-if-addr>/imm32             0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
27653   0x11/imm32/alloc-id   _string-break-if-addr<=/imm32           0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
27654   0x11/imm32/alloc-id   _string-loop-if-addr<=/imm32            0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
27655   0x11/imm32/alloc-id   _string-break-if-addr>=/imm32           0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
27656   0x11/imm32/alloc-id   _string-loop-if-addr>=/imm32            0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
27657   0x11/imm32/alloc-id   _string-break-if-float</imm32           0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
27658   0x11/imm32/alloc-id   _string-loop-if-float</imm32            0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
27659   0x11/imm32/alloc-id   _string-break-if-float>/imm32           0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
27660   0x11/imm32/alloc-id   _string-loop-if-float>/imm32            0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
27661   0x11/imm32/alloc-id   _string-break-if-float<=/imm32          0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
27662   0x11/imm32/alloc-id   _string-loop-if-float<=/imm32           0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
27663   0x11/imm32/alloc-id   _string-break-if-float>=/imm32          0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
27664   0x11/imm32/alloc-id   _string-loop-if-float>=/imm32           0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
27665   0x11/imm32/alloc-id   _string-break-if-carry/imm32            0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
27666   0x11/imm32/alloc-id   _string-loop-if-carry/imm32             0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
27667   0x11/imm32/alloc-id   _string-break-if-not-carry/imm32        0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
27668   0x11/imm32/alloc-id   _string-loop-if-not-carry/imm32         0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
27669   0x11/imm32/alloc-id   _string-break-if-overflow/imm32         0x11/imm32/alloc-id   _string_0f_81_jump_label/imm32
27670   0x11/imm32/alloc-id   _string-loop-if-overflow/imm32          0x11/imm32/alloc-id   _string_0f_81_jump_label/imm32
27671   0x11/imm32/alloc-id   _string-break-if-not-overflow/imm32     0x11/imm32/alloc-id   _string_0f_80_jump_label/imm32
27672   0x11/imm32/alloc-id   _string-loop-if-not-overflow/imm32      0x11/imm32/alloc-id   _string_0f_80_jump_label/imm32
27673 
27674 == code
27675 
27676 emit-unconditional-jump-to-depth:  # out: (addr buffered-file), vars: (addr stack live-var), depth: int, label-suffix: (addr array byte)
27677     # . prologue
27678     55/push-ebp
27679     89/<- %ebp 4/r32/esp
27680     # . save registers
27681     50/push-eax
27682     51/push-ecx
27683     52/push-edx
27684     53/push-ebx
27685     56/push-esi
27686     # ecx = vars
27687     8b/-> *(ebp+0xc) 1/r32/ecx
27688     # var eax: int = vars->top
27689     8b/-> *ecx 0/r32/eax
27690     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
27691     8d/copy-address *(ecx+eax-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
27692     # var min/ecx: (addr handle var) = vars->data
27693     8d/copy-address *(ecx+8) 1/r32/ecx
27694     # edx = depth
27695     8b/-> *(ebp+0x10) 2/r32/edx
27696     {
27697 $emit-unconditional-jump-to-depth:loop:
27698       # if (curr < min) break
27699       39/compare %esi 1/r32/ecx
27700       0f 82/jump-if-addr< break/disp32
27701       # var v/ebx: (addr var) = lookup(*curr)
27702       (lookup *esi *(esi+4))  # => eax
27703       89/<- %ebx 0/r32/eax
27704       # if (v->block-depth < until-block-depth) break
27705       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
27706       0f 8c/jump-if-< break/disp32
27707       {
27708 $emit-unconditional-jump-to-depth:check:
27709         # if v->block-depth != until-block-depth, continue
27710         39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
27711         0f 85/jump-if-!= break/disp32
27712 $emit-unconditional-jump-to-depth:depth-found:
27713         # if v is not a literal, continue
27714         (size-of %ebx)  # => eax
27715         3d/compare-eax-and 0/imm32
27716         0f 85/jump-if-!= break/disp32
27717 $emit-unconditional-jump-to-depth:label-found:
27718         # emit unconditional jump, then return
27719         (emit-indent *(ebp+8) *Curr-block-depth)
27720         (write-buffered *(ebp+8) "e9/jump ")
27721         (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
27722         (write-buffered *(ebp+8) %eax)
27723         (write-buffered *(ebp+8) ":")
27724         (write-buffered *(ebp+8) *(ebp+0x14))
27725         (write-buffered *(ebp+8) "/disp32\n")
27726         eb/jump $emit-unconditional-jump-to-depth:end/disp8
27727       }
27728       # curr -= 12
27729       81 5/subop/subtract %esi 0xc/imm32
27730       e9/jump loop/disp32
27731     }
27732     # TODO: error if no label at 'depth' was found
27733 $emit-unconditional-jump-to-depth:end:
27734     # . restore registers
27735     5e/pop-to-esi
27736     5b/pop-to-ebx
27737     5a/pop-to-edx
27738     59/pop-to-ecx
27739     58/pop-to-eax
27740     # . epilogue
27741     89/<- %esp 5/r32/ebp
27742     5d/pop-to-ebp
27743     c3/return
27744 
27745 # emit clean-up code for 'vars' until some block depth
27746 # doesn't actually modify 'vars' so we need traverse manually inside the stack
27747 emit-cleanup-code-until-depth:  # out: (addr buffered-file), vars: (addr stack live-var), until-block-depth: int
27748     # . prologue
27749     55/push-ebp
27750     89/<- %ebp 4/r32/esp
27751     # . save registers
27752     50/push-eax
27753     51/push-ecx
27754     52/push-edx
27755     53/push-ebx
27756     56/push-esi
27757 #?     (write-buffered Stderr "--- cleanup\n")
27758 #?     (flush Stderr)
27759     # ecx = vars
27760     8b/-> *(ebp+0xc) 1/r32/ecx
27761     # var esi: int = vars->top
27762     8b/-> *ecx 6/r32/esi
27763     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
27764     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
27765     # var min/ecx: (addr handle var) = vars->data
27766     81 0/subop/add %ecx 8/imm32
27767     # edx = until-block-depth
27768     8b/-> *(ebp+0x10) 2/r32/edx
27769     {
27770 $emit-cleanup-code-until-depth:loop:
27771       # if (curr < min) break
27772       39/compare %esi 1/r32/ecx
27773       0f 82/jump-if-addr< break/disp32
27774       # var v/ebx: (addr var) = lookup(*curr)
27775       (lookup *esi *(esi+4))  # => eax
27776       89/<- %ebx 0/r32/eax
27777 #?       (lookup *ebx *(ebx+4))  # Var-name
27778 #?       (write-buffered Stderr "var ")
27779 #?       (write-buffered Stderr %eax)
27780 #?       (write-buffered Stderr Newline)
27781 #?       (flush Stderr)
27782       # if (v->block-depth < until-block-depth) break
27783       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
27784       0f 8c/jump-if-< break/disp32
27785       # if v is in a register
27786       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
27787       {
27788         0f 84/jump-if-= break/disp32
27789         {
27790 $emit-cleanup-code-until-depth:check-for-previous-spill:
27791           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
27792           3d/compare-eax-and 0/imm32/false
27793           74/jump-if-= break/disp8
27794 $emit-cleanup-code-until-depth:reclaim-var-in-register:
27795           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
27796           (emit-pop-register *(ebp+8) %eax)
27797         }
27798         eb/jump $emit-cleanup-code-until-depth:continue/disp8
27799       }
27800       # otherwise v is on the stack
27801       {
27802         75/jump-if-!= break/disp8
27803 $emit-cleanup-code-until-depth:var-on-stack:
27804         (size-of %ebx)  # => eax
27805         # don't emit code for labels
27806         3d/compare-eax-and 0/imm32
27807         74/jump-if-= break/disp8
27808 $emit-cleanup-code-until-depth:reclaim-var-on-stack:
27809         (emit-indent *(ebp+8) *Curr-block-depth)
27810         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
27811         (write-int32-hex-buffered *(ebp+8) %eax)
27812         (write-buffered *(ebp+8) "/imm32\n")
27813       }
27814 $emit-cleanup-code-until-depth:continue:
27815       # curr -= 12
27816       81 5/subop/subtract %esi 0xc/imm32
27817       e9/jump loop/disp32
27818     }
27819 $emit-cleanup-code-until-depth:end:
27820     # . restore registers
27821     5e/pop-to-esi
27822     5b/pop-to-ebx
27823     5a/pop-to-edx
27824     59/pop-to-ecx
27825     58/pop-to-eax
27826     # . epilogue
27827     89/<- %esp 5/r32/ebp
27828     5d/pop-to-ebp
27829     c3/return
27830 
27831 # emit clean-up code for 'vars' that don't conflict with output registers
27832 # doesn't actually modify 'vars' so we need traverse manually inside the stack
27833 emit-cleanup-code-for-non-outputs:  # out: (addr buffered-file), vars: (addr stack live-var), fn: (addr function)
27834     # . prologue
27835     55/push-ebp
27836     89/<- %ebp 4/r32/esp
27837     # . save registers
27838     50/push-eax
27839     51/push-ecx
27840     52/push-edx
27841     53/push-ebx
27842     56/push-esi
27843     57/push-edi
27844     # ecx = vars
27845     8b/-> *(ebp+0xc) 1/r32/ecx
27846     # var esi: int = vars->top
27847     8b/-> *ecx 6/r32/esi
27848     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
27849     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
27850     # var min/ecx: (addr handle var) = vars->data
27851     81 0/subop/add %ecx 8/imm32
27852     {
27853 $emit-cleanup-code-for-non-outputs:loop:
27854       # if (curr < min) break
27855       39/compare %esi 1/r32/ecx
27856       0f 82/jump-if-addr< break/disp32
27857       # var v/ebx: (addr var) = lookup(*curr)
27858       (lookup *esi *(esi+4))  # => eax
27859       89/<- %ebx 0/r32/eax
27860       # if v is in a register
27861       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
27862       {
27863         0f 84/jump-if-= break/disp32
27864         {
27865 $emit-cleanup-code-for-non-outputs:check-for-previous-spill:
27866           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
27867           3d/compare-eax-and 0/imm32/false
27868           0f 84/jump-if-= break/disp32
27869 $emit-cleanup-code-for-non-outputs:reclaim-var-in-register:
27870           # var reg/edi: (addr array name) = v->register
27871           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
27872           89/<- %edi 0/r32/eax
27873           # if reg is not in function outputs, emit a pop
27874           (reg-in-function-outputs? *(ebp+0x10) %edi)  # => eax
27875           3d/compare-eax-and 0/imm32/false
27876           {
27877             75/jump-if-!= break/disp8
27878             (emit-pop-register *(ebp+8) %edi)
27879             eb/jump $emit-cleanup-code-for-non-outputs:reclaim-var-in-register-done/disp8
27880           }
27881           # otherwise just drop it from the stack
27882           (emit-indent *(ebp+8) *Curr-block-depth)
27883           (write-buffered *(ebp+8) "81 0/subop/add %esp 4/imm32\n")
27884         }
27885 $emit-cleanup-code-for-non-outputs:reclaim-var-in-register-done:
27886         eb/jump $emit-cleanup-code-for-non-outputs:continue/disp8
27887       }
27888       # otherwise v is on the stack
27889       {
27890         75/jump-if-!= break/disp8
27891 $emit-cleanup-code-for-non-outputs:var-on-stack:
27892         (size-of %ebx)  # => eax
27893         # don't emit code for labels
27894         3d/compare-eax-and 0/imm32
27895         74/jump-if-= break/disp8
27896 $emit-cleanup-code-for-non-outputs:reclaim-var-on-stack:
27897         (emit-indent *(ebp+8) *Curr-block-depth)
27898         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
27899         (write-int32-hex-buffered *(ebp+8) %eax)
27900         (write-buffered *(ebp+8) "/imm32\n")
27901       }
27902 $emit-cleanup-code-for-non-outputs:continue:
27903       # curr -= 12
27904       81 5/subop/subtract %esi 0xc/imm32
27905       e9/jump loop/disp32
27906     }
27907 $emit-cleanup-code-for-non-outputs:end:
27908     # . restore registers
27909     5f/pop-to-edi
27910     5e/pop-to-esi
27911     5b/pop-to-ebx
27912     5a/pop-to-edx
27913     59/pop-to-ecx
27914     58/pop-to-eax
27915     # . epilogue
27916     89/<- %esp 5/r32/ebp
27917     5d/pop-to-ebp
27918     c3/return
27919 
27920 emit-push-register:  # out: (addr buffered-file), reg: (addr array byte)
27921     # . prologue
27922     55/push-ebp
27923     89/<- %ebp 4/r32/esp
27924     # eax = reg
27925     8b/-> *(ebp+0xc) 0/r32/eax
27926     # var prefix/eax: byte = reg->data[0]
27927     8a/copy-byte *(eax+4) 0/r32/AL
27928     25/and-eax-with 0xff/imm32
27929     # if (prefix == 'x') push xmm register
27930     {
27931       3d/compare-eax-and 0x78/imm32/x
27932       0f 85/jump-if-!= break/disp32
27933       # TODO validate register
27934       (emit-indent *(ebp+8) *Curr-block-depth)
27935       (write-buffered *(ebp+8) "81 5/subop/subtract %esp 4/imm32\n")
27936       (emit-indent *(ebp+8) *Curr-block-depth)
27937       (write-buffered *(ebp+8) "f3 0f 11/<- *esp ")
27938       # var prefix/eax: byte = reg->data[3]
27939       8b/-> *(ebp+0xc) 0/r32/eax
27940       8a/copy-byte *(eax+7) 0/r32/AL
27941       25/and-eax-with 0xff/imm32
27942       (write-byte-buffered *(ebp+8) %eax)
27943       (write-buffered *(ebp+8) "/x32\n")
27944       e9/jump $emit-push-register:end/disp32
27945     }
27946     # otherwise push gp register
27947     (emit-indent *(ebp+8) *Curr-block-depth)
27948     (write-buffered *(ebp+8) "ff 6/subop/push %")
27949     (write-buffered *(ebp+8) *(ebp+0xc))
27950     (write-buffered *(ebp+8) Newline)
27951 $emit-push-register:end:
27952     # . epilogue
27953     89/<- %esp 5/r32/ebp
27954     5d/pop-to-ebp
27955     c3/return
27956 
27957 emit-pop-register:  # out: (addr buffered-file), reg: (addr array byte)
27958     # . prologue
27959     55/push-ebp
27960     89/<- %ebp 4/r32/esp
27961     # . save registers
27962     50/push-eax
27963     # eax = reg
27964     8b/-> *(ebp+0xc) 0/r32/eax
27965     # var prefix/eax: byte = reg->data[0]
27966     8a/copy-byte *(eax+4) 0/r32/AL
27967     25/and-eax-with 0xff/imm32
27968     # if (prefix == 'x') pop to xmm register
27969     {
27970       3d/compare-eax-and 0x78/imm32/x
27971       0f 85/jump-if-!= break/disp32
27972       # TODO validate register
27973       (emit-indent *(ebp+8) *Curr-block-depth)
27974       (write-buffered *(ebp+8) "f3 0f 10/-> *esp ")
27975       # var prefix/eax: byte = reg->data[3]
27976       8b/-> *(ebp+0xc) 0/r32/eax
27977       8a/copy-byte *(eax+7) 0/r32/AL
27978       25/and-eax-with 0xff/imm32
27979       (write-byte-buffered *(ebp+8) %eax)
27980       (write-buffered *(ebp+8) "/x32\n")
27981       (emit-indent *(ebp+8) *Curr-block-depth)
27982       (write-buffered *(ebp+8) "81 0/subop/add %esp 4/imm32\n")
27983       e9/jump $emit-pop-register:end/disp32
27984     }
27985     # otherwise pop to gp register
27986     (emit-indent *(ebp+8) *Curr-block-depth)
27987     (write-buffered *(ebp+8) "8f 0/subop/pop %")
27988     (write-buffered *(ebp+8) *(ebp+0xc))
27989     (write-buffered *(ebp+8) Newline)
27990 $emit-pop-register:end:
27991     # . restore registers
27992     58/pop-to-eax
27993     # . epilogue
27994     89/<- %esp 5/r32/ebp
27995     5d/pop-to-ebp
27996     c3/return
27997 
27998 # emit clean-up code for 'vars' until a given label is encountered
27999 # doesn't actually modify 'vars' so we need traverse manually inside the stack
28000 emit-cleanup-code-until-target:  # out: (addr buffered-file), vars: (addr stack live-var), until-block-label: (addr array byte)
28001     # . prologue
28002     55/push-ebp
28003     89/<- %ebp 4/r32/esp
28004     # . save registers
28005     50/push-eax
28006     51/push-ecx
28007     52/push-edx
28008     53/push-ebx
28009     # ecx = vars
28010     8b/-> *(ebp+0xc) 1/r32/ecx
28011     # var eax: int = vars->top
28012     8b/-> *ecx 0/r32/eax
28013     # var curr/edx: (addr handle var) = &vars->data[vars->top - 12]
28014     8d/copy-address *(ecx+eax-4) 2/r32/edx  # vars + 8 + vars->top - 12/Live-var-size
28015     # var min/ecx: (addr handle var) = vars->data
28016     81 0/subop/add %ecx 8/imm32
28017     {
28018 $emit-cleanup-code-until-target:loop:
28019       # if (curr < min) break
28020       39/compare %edx 1/r32/ecx
28021       0f 82/jump-if-addr< break/disp32
28022       # var v/ebx: (handle var) = lookup(*curr)
28023       (lookup *edx *(edx+4))  # => eax
28024       89/<- %ebx 0/r32/eax
28025       # if (v->name == until-block-label) break
28026       (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
28027       (string-equal? %eax *(ebp+0x10))  # => eax
28028       3d/compare-eax-and 0/imm32/false
28029       0f 85/jump-if-!= break/disp32
28030       # if v is in a register
28031       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
28032       {
28033         0f 84/jump-if-= break/disp32
28034         {
28035 $emit-cleanup-code-until-target:check-for-previous-spill:
28036           8b/-> *(edx+8) 0/r32/eax  # Live-var-register-spilled
28037           3d/compare-eax-and 0/imm32/false
28038           74/jump-if-= break/disp8
28039 $emit-cleanup-code-until-target:reclaim-var-in-register:
28040           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
28041           (emit-pop-register *(ebp+8) %eax)
28042         }
28043         eb/jump $emit-cleanup-code-until-target:continue/disp8
28044       }
28045       # otherwise v is on the stack
28046       {
28047         75/jump-if-!= break/disp8
28048 $emit-cleanup-code-until-target:reclaim-var-on-stack:
28049         (size-of %ebx)  # => eax
28050         # don't emit code for labels
28051         3d/compare-eax-and 0/imm32
28052         74/jump-if-= break/disp8
28053         #
28054         (emit-indent *(ebp+8) *Curr-block-depth)
28055         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
28056         (write-int32-hex-buffered *(ebp+8) %eax)
28057         (write-buffered *(ebp+8) "/imm32\n")
28058       }
28059 $emit-cleanup-code-until-target:continue:
28060       # curr -= 12
28061       81 5/subop/subtract %edx 0xc/imm32
28062       e9/jump loop/disp32
28063     }
28064 $emit-cleanup-code-until-target:end:
28065     # . restore registers
28066     5b/pop-to-ebx
28067     5a/pop-to-edx
28068     59/pop-to-ecx
28069     58/pop-to-eax
28070     # . epilogue
28071     89/<- %esp 5/r32/ebp
28072     5d/pop-to-ebp
28073     c3/return
28074 
28075 # update Curr-local-stack-offset assuming vars until some block depth are popped
28076 # doesn't actually modify 'vars', so we need traverse manually inside the stack
28077 clean-up-stack-offset-state:  # vars: (addr stack live-var), until-block-depth: int
28078     # . prologue
28079     55/push-ebp
28080     89/<- %ebp 4/r32/esp
28081     # . save registers
28082     50/push-eax
28083     51/push-ecx
28084     52/push-edx
28085     53/push-ebx
28086     56/push-esi
28087     # ecx = vars
28088     8b/-> *(ebp+8) 1/r32/ecx
28089     # var esi: int = vars->top
28090     8b/-> *ecx 6/r32/esi
28091     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
28092     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
28093     # var min/ecx: (addr handle var) = vars->data
28094     81 0/subop/add %ecx 8/imm32
28095     # edx = until-block-depth
28096     8b/-> *(ebp+0xc) 2/r32/edx
28097     {
28098 $clean-up-stack-offset-state:loop:
28099       # if (curr < min) break
28100       39/compare %esi 1/r32/ecx
28101       0f 82/jump-if-addr< break/disp32
28102       # var v/ebx: (addr var) = lookup(*curr)
28103       (lookup *esi *(esi+4))  # => eax
28104       89/<- %ebx 0/r32/eax
28105       # if (v->block-depth < until-block-depth) break
28106       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
28107       0f 8c/jump-if-< break/disp32
28108       # if v is in a register
28109       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
28110       {
28111         0f 84/jump-if-= break/disp32
28112         {
28113 $clean-up-stack-offset-state:check-for-previous-spill:
28114           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
28115           3d/compare-eax-and 0/imm32/false
28116           74/jump-if-= break/disp8
28117 $clean-up-stack-offset-state:reclaim-var-in-register:
28118           81 0/subop/add *Curr-local-stack-offset 4/imm32
28119         }
28120         eb/jump $clean-up-stack-offset-state:continue/disp8
28121       }
28122       # otherwise v is on the stack
28123       {
28124         75/jump-if-!= break/disp8
28125 $clean-up-stack-offset-state:var-on-stack:
28126         (size-of %ebx)  # => eax
28127         01/add-to *Curr-local-stack-offset 0/r32/eax
28128       }
28129 $clean-up-stack-offset-state:continue:
28130       # curr -= 12
28131       81 5/subop/subtract %esi 0xc/imm32
28132       e9/jump loop/disp32
28133     }
28134 $clean-up-stack-offset-state:end:
28135     # . restore registers
28136     5e/pop-to-esi
28137     5b/pop-to-ebx
28138     5a/pop-to-edx
28139     59/pop-to-ecx
28140     58/pop-to-eax
28141     # . epilogue
28142     89/<- %esp 5/r32/ebp
28143     5d/pop-to-ebp
28144     c3/return
28145 
28146 # Return true if there isn't a variable in 'vars' with the same block-depth
28147 # and register as 'v'.
28148 # 'v' is guaranteed not to be within 'vars'.
28149 not-yet-spilled-this-block?:  # v: (addr var), vars: (addr stack live-var) -> result/eax: boolean
28150     # . prologue
28151     55/push-ebp
28152     89/<- %ebp 4/r32/esp
28153     # . save registers
28154     51/push-ecx
28155     52/push-edx
28156     53/push-ebx
28157     56/push-esi
28158     57/push-edi
28159     # ecx = vars
28160     8b/-> *(ebp+0xc) 1/r32/ecx
28161     # var eax: int = vars->top
28162     8b/-> *ecx 0/r32/eax
28163     # var curr/edx: (addr handle var) = &vars->data[vars->top - 12]
28164     8d/copy-address *(ecx+eax-4) 2/r32/edx  # vars + 8 + vars->top - 12/Live-var-size
28165     # var min/ecx: (addr handle var) = vars->data
28166     8d/copy-address *(ecx+8) 1/r32/ecx
28167     # var depth/ebx: int = v->block-depth
28168     8b/-> *(ebp+8) 3/r32/ebx
28169     8b/-> *(ebx+0x10) 3/r32/ebx  # Var-block-depth
28170     # var needle/esi: (addr array byte) = v->register
28171     8b/-> *(ebp+8) 6/r32/esi
28172     (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
28173     89/<- %esi 0/r32/eax
28174     {
28175 $not-yet-spilled-this-block?:loop:
28176       # if (curr < min) break
28177       39/compare %edx 1/r32/ecx
28178       0f 82/jump-if-addr< break/disp32
28179       # var cand/edi: (addr var) = lookup(*curr)
28180       (lookup *edx *(edx+4))  # => eax
28181       89/<- %edi 0/r32/eax
28182       # if (cand->block-depth < depth) break
28183       39/compare *(edi+0x10) 3/r32/ebx  # Var-block-depth
28184       0f 8c/jump-if-< break/disp32
28185       # var cand-reg/edi: (array array byte) = cand->reg
28186       (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
28187       89/<- %edi 0/r32/eax
28188       # if (cand-reg == null) continue
28189       {
28190 $not-yet-spilled-this-block?:check-reg:
28191         81 7/subop/compare %edi 0/imm32
28192         0f 84/jump-if-= break/disp32
28193         # if (cand-reg == needle) return true
28194         (string-equal? %esi %edi)  # => eax
28195         3d/compare-eax-and 0/imm32/false
28196         74/jump-if-= break/disp8
28197 $not-yet-spilled-this-block?:return-false:
28198         b8/copy-to-eax 0/imm32/false
28199         eb/jump $not-yet-spilled-this-block?:end/disp8
28200       }
28201 $not-yet-spilled-this-block?:continue:
28202       # curr -= 12
28203       81 5/subop/subtract %edx 0xc/imm32
28204       e9/jump loop/disp32
28205     }
28206 $not-yet-spilled-this-block?:return-true:
28207     # return true
28208     b8/copy-to-eax 1/imm32/true
28209 $not-yet-spilled-this-block?:end:
28210     # . restore registers
28211     5f/pop-to-edi
28212     5e/pop-to-esi
28213     5b/pop-to-ebx
28214     5a/pop-to-edx
28215     59/pop-to-ecx
28216     # . epilogue
28217     89/<- %esp 5/r32/ebp
28218     5d/pop-to-ebp
28219     c3/return
28220 
28221 # could the register of 'v' ever be written to by one of the vars in fn-outputs?
28222 will-not-write-some-register?:  # v: (addr var), stmts: (addr list stmt), fn: (addr function) -> result/eax: boolean
28223     # . prologue
28224     55/push-ebp
28225     89/<- %ebp 4/r32/esp
28226     # eax = v
28227     8b/-> *(ebp+8) 0/r32/eax
28228     # var reg/eax: (addr array byte) = lookup(v->register)
28229     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
28230     # var target/eax: (addr var) = find-register(fn-outputs, reg)
28231     (find-register *(ebp+0x10) %eax)  # => eax
28232     # if (target == 0) return true
28233     {
28234       3d/compare-eax-and 0/imm32
28235       75/jump-if-!= break/disp8
28236       b8/copy-to-eax 1/imm32/true
28237       eb/jump $will-not-write-some-register?:end/disp8
28238     }
28239     # return !assigns-in-stmts?(stmts, target)
28240     (assigns-in-stmts? *(ebp+0xc) %eax)  # => eax
28241     3d/compare-eax-and 0/imm32/false
28242     # assume: true = 1, so no need to mask with 0x000000ff
28243     0f 94/set-if-= %al
28244 $will-not-write-some-register?:end:
28245     # . epilogue
28246     89/<- %esp 5/r32/ebp
28247     5d/pop-to-ebp
28248     c3/return
28249 
28250 # return fn output with matching register
28251 # always returns false if 'reg' is null
28252 find-register:  # fn: (addr function), reg: (addr array byte) -> result/eax: (addr var)
28253     # . prologue
28254     55/push-ebp
28255     89/<- %ebp 4/r32/esp
28256     # . save registers
28257     51/push-ecx
28258     # var curr/ecx: (addr list var) = lookup(fn->outputs)
28259     8b/-> *(ebp+8) 1/r32/ecx
28260     (lookup *(ecx+0x10) *(ecx+0x14))  # Function-outputs Function-outputs => eax
28261     89/<- %ecx 0/r32/eax
28262     {
28263 $find-register:loop:
28264       # if (curr == 0) break
28265       81 7/subop/compare %ecx 0/imm32
28266       74/jump-if-= break/disp8
28267       # eax = curr->value->register
28268       (lookup *ecx *(ecx+4))  # List-value List-value => eax
28269       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
28270       # if (eax == reg) return curr->value
28271 $find-register:compare:
28272       (string-equal? *(ebp+0xc) %eax)  # => eax
28273       {
28274         3d/compare-eax-and 0/imm32/false
28275         74/jump-if-= break/disp8
28276 $find-register:found:
28277         (lookup *ecx *(ecx+4))  # List-value List-value => eax
28278         eb/jump $find-register:end/disp8
28279       }
28280       # curr = lookup(curr->next)
28281       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
28282       89/<- %ecx 0/r32/eax
28283       #
28284       eb/jump loop/disp8
28285     }
28286 $find-register:end:
28287     # . restore registers
28288     59/pop-to-ecx
28289     # . epilogue
28290     89/<- %esp 5/r32/ebp
28291     5d/pop-to-ebp
28292     c3/return
28293 
28294 assigns-in-stmts?:  # stmts: (addr list stmt), v: (addr var) -> result/eax: boolean
28295     # . prologue
28296     55/push-ebp
28297     89/<- %ebp 4/r32/esp
28298     # . save registers
28299     51/push-ecx
28300     # var curr/ecx: (addr list stmt) = stmts
28301     8b/-> *(ebp+8) 1/r32/ecx
28302     {
28303       # if (curr == 0) break
28304       81 7/subop/compare %ecx 0/imm32
28305       74/jump-if-= break/disp8
28306       # if assigns-in-stmt?(curr->value, v) return true
28307       (lookup *ecx *(ecx+4))  # List-value List-value => eax
28308       (assigns-in-stmt? %eax *(ebp+0xc))  # => eax
28309       3d/compare-eax-and 0/imm32/false
28310       75/jump-if-!= break/disp8
28311       # curr = lookup(curr->next)
28312       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
28313       89/<- %ecx 0/r32/eax
28314       #
28315       eb/jump loop/disp8
28316     }
28317 $assigns-in-stmts?:end:
28318     # . restore registers
28319     59/pop-to-ecx
28320     # . epilogue
28321     89/<- %esp 5/r32/ebp
28322     5d/pop-to-ebp
28323     c3/return
28324 
28325 assigns-in-stmt?:  # stmt: (addr stmt), v: (addr var) -> result/eax: boolean
28326     # . prologue
28327     55/push-ebp
28328     89/<- %ebp 4/r32/esp
28329     # . save registers
28330     51/push-ecx
28331     # ecx = stmt
28332     8b/-> *(ebp+8) 1/r32/ecx
28333     # if stmt is a stmt1, return assigns-in-stmt-vars?(stmt->outputs, v)
28334     {
28335       81 7/subop/compare *ecx 1/imm32/stmt1  # Stmt-tag
28336       75/jump-if-!= break/disp8
28337       (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
28338       (assigns-in-stmt-vars? %eax *(ebp+0xc))  # => eax
28339       eb/jump $assigns-in-stmt?:end/disp8
28340     }
28341     # if stmt is a block, return assigns-in-stmts?(stmt->stmts, v)
28342     {
28343       81 7/subop/compare *ecx 0/imm32/block  # Stmt-tag
28344       75/jump-if-!= break/disp8
28345       (lookup *(ecx+4) *(ecx+8))  # Block-stmts Block-stmts => eax
28346       (assigns-in-stmts? %eax *(ebp+0xc))  # => eax
28347       eb/jump $assigns-in-stmt?:end/disp8
28348     }
28349     # otherwise return false
28350     b8/copy 0/imm32/false
28351 $assigns-in-stmt?:end:
28352     # . restore registers
28353     59/pop-to-ecx
28354     # . epilogue
28355     89/<- %esp 5/r32/ebp
28356     5d/pop-to-ebp
28357     c3/return
28358 
28359 assigns-in-stmt-vars?:  # stmt-var: (addr stmt-var), v: (addr var) -> result/eax: boolean
28360     # . prologue
28361     55/push-ebp
28362     89/<- %ebp 4/r32/esp
28363     # . save registers
28364     51/push-ecx
28365     # var curr/ecx: (addr stmt-var) = stmt-var
28366     8b/-> *(ebp+8) 1/r32/ecx
28367     {
28368       # if (curr == 0) break
28369       81 7/subop/compare %ecx 0/imm32
28370       74/jump-if-= break/disp8
28371       # eax = lookup(curr->value)
28372       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
28373       # if (eax == v  &&  curr->is-deref? == false) return true
28374       {
28375         39/compare *(ebp+0xc) 0/r32/eax
28376         75/jump-if-!= break/disp8
28377         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
28378         75/jump-if-!= break/disp8
28379         b8/copy-to-eax 1/imm32/true
28380         eb/jump $assigns-in-stmt-vars?:end/disp8
28381       }
28382       # curr = lookup(curr->next)
28383       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
28384       89/<- %ecx 0/r32/eax
28385       #
28386       eb/jump loop/disp8
28387     }
28388 $assigns-in-stmt-vars?:end:
28389     # . restore registers
28390     59/pop-to-ecx
28391     # . epilogue
28392     89/<- %esp 5/r32/ebp
28393     5d/pop-to-ebp
28394     c3/return
28395 
28396 # is there a var before 'v' with the same block-depth and register on the 'vars' stack?
28397 # v is guaranteed to be within vars
28398 # 'start' is provided as an optimization, a pointer within vars
28399 # *start == v
28400 same-register-spilled-before?:  # v: (addr var), vars: (addr stack (handle var)), start: (addr var) -> result/eax: boolean
28401     # . prologue
28402     55/push-ebp
28403     89/<- %ebp 4/r32/esp
28404     # . save registers
28405     51/push-ecx
28406     52/push-edx
28407     53/push-ebx
28408     56/push-esi
28409     57/push-edi
28410     # ecx = v
28411     8b/-> *(ebp+8) 1/r32/ecx
28412     # var reg/edx: (addr array byte) = lookup(v->register)
28413     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
28414     89/<- %edx 0/r32/eax
28415     # var depth/ebx: int = v->block-depth
28416     8b/-> *(ecx+0x10) 3/r32/ebx  # Var-block-depth
28417     # var min/ecx: (addr handle var) = vars->data
28418     8b/-> *(ebp+0xc) 1/r32/ecx
28419     81 0/subop/add %ecx 8/imm32
28420     # TODO: check that start >= min and start < &vars->data[top]
28421     # TODO: check that *start == v
28422     # var curr/esi: (addr handle var) = start
28423     8b/-> *(ebp+0x10) 6/r32/esi
28424     # curr -= 8
28425     81 5/subop/subtract %esi 8/imm32
28426     {
28427 $same-register-spilled-before?:loop:
28428       # if (curr < min) break
28429       39/compare %esi 1/r32/ecx
28430       0f 82/jump-if-addr< break/disp32
28431       # var x/eax: (addr var) = lookup(*curr)
28432       (lookup *esi *(esi+4))  # => eax
28433       # if (x->block-depth < depth) break
28434       39/compare *(eax+0x10) 3/r32/ebx  # Var-block-depth
28435       0f 8c/jump-if-< break/disp32
28436       # if (x->register == 0) continue
28437       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
28438       74/jump-if-= $same-register-spilled-before?:continue/disp8
28439       # if (x->register == reg) return true
28440       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
28441       (string-equal? %eax %edx)  # => eax
28442       3d/compare-eax-and 0/imm32/false
28443       b8/copy-to-eax 1/imm32/true
28444       75/jump-if-!= $same-register-spilled-before?:end/disp8
28445 $same-register-spilled-before?:continue:
28446       # curr -= 8
28447       81 5/subop/subtract %esi 8/imm32
28448       e9/jump loop/disp32
28449     }
28450 $same-register-spilled-before?:false:
28451     b8/copy-to-eax 0/imm32/false
28452 $same-register-spilled-before?:end:
28453     # . restore registers
28454     5f/pop-to-edi
28455     5e/pop-to-esi
28456     5b/pop-to-ebx
28457     5a/pop-to-edx
28458     59/pop-to-ecx
28459     # . epilogue
28460     89/<- %esp 5/r32/ebp
28461     5d/pop-to-ebp
28462     c3/return
28463 
28464 # clean up global state for 'vars' until some block depth (inclusive)
28465 clean-up-blocks:  # vars: (addr stack live-var), until-block-depth: int, fn: (addr function)
28466     # . prologue
28467     55/push-ebp
28468     89/<- %ebp 4/r32/esp
28469     # . save registers
28470     50/push-eax
28471     51/push-ecx
28472     56/push-esi
28473     # esi = vars
28474     8b/-> *(ebp+8) 6/r32/esi
28475     # ecx = until-block-depth
28476     8b/-> *(ebp+0xc) 1/r32/ecx
28477     {
28478 $clean-up-blocks:reclaim-loop:
28479       # if (vars->top <= 0) break
28480       8b/-> *esi 0/r32/eax  # Stack-top
28481       3d/compare-eax-and 0/imm32
28482       0f 8e/jump-if-<= break/disp32
28483       # var v/eax: (addr var) = lookup(vars[vars->top-12])
28484       (lookup *(esi+eax-4) *(esi+eax))  # vars + 8 + vars->top - 12 => eax
28485       # if (v->block-depth < until-block-depth) break
28486       39/compare *(eax+0x10) 1/r32/ecx  # Var-block-depth
28487       0f 8c/jump-if-< break/disp32
28488       (pop %esi)  # => eax
28489       (pop %esi)  # => eax
28490       (pop %esi)  # => eax
28491       e9/jump loop/disp32
28492     }
28493 $clean-up-blocks:end:
28494     # . restore registers
28495     5e/pop-to-esi
28496     59/pop-to-ecx
28497     58/pop-to-eax
28498     # . epilogue
28499     89/<- %esp 5/r32/ebp
28500     5d/pop-to-ebp
28501     c3/return
28502 
28503 reg-in-function-outputs?:  # fn: (addr function), target: (addr array byte) -> result/eax: boolean
28504     # . prologue
28505     55/push-ebp
28506     89/<- %ebp 4/r32/esp
28507     # . save registers
28508     51/push-ecx
28509     # var curr/ecx: (addr list var) = lookup(fn->outputs)
28510     8b/-> *(ebp+8) 0/r32/eax
28511     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
28512     89/<- %ecx 0/r32/eax
28513     # while curr != null
28514     {
28515       81 7/subop/compare %ecx 0/imm32
28516       74/jump-if-= break/disp8
28517       # var v/eax: (addr var) = lookup(curr->value)
28518       (lookup *ecx *(ecx+4))  # List-value List-value => eax
28519       # var reg/eax: (addr array byte) = lookup(v->register)
28520       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
28521       # if (reg == target) return true
28522       (string-equal? %eax *(ebp+0xc))  # => eax
28523       3d/compare-eax-and 0/imm32/false
28524       75/jump-if-!= $reg-in-function-outputs?:end/disp8
28525       # curr = curr->next
28526       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
28527       89/<- %ecx 0/r32/eax
28528       #
28529       eb/jump loop/disp8
28530     }
28531     # return false
28532     b8/copy-to-eax 0/imm32
28533 $reg-in-function-outputs?:end:
28534     # . restore registers
28535     59/pop-to-ecx
28536     # . epilogue
28537     89/<- %esp 5/r32/ebp
28538     5d/pop-to-ebp
28539     c3/return
28540 
28541 emit-subx-var-def:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
28542     # . prologue
28543     55/push-ebp
28544     89/<- %ebp 4/r32/esp
28545     # . save registers
28546     50/push-eax
28547     51/push-ecx
28548     52/push-edx
28549     # eax = stmt
28550     8b/-> *(ebp+0xc) 0/r32/eax
28551     # var v/ecx: (addr var)
28552     (lookup *(eax+4) *(eax+8))  # Vardef-var Vardef-var => eax
28553     89/<- %ecx 0/r32/eax
28554     # v->block-depth = *Curr-block-depth
28555     8b/-> *Curr-block-depth 0/r32/eax
28556     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
28557     # var n/edx: int = size-of(stmt->var)
28558     (size-of %ecx)  # => eax
28559     89/<- %edx 0/r32/eax
28560     # *Curr-local-stack-offset -= n
28561     29/subtract-from *Curr-local-stack-offset 2/r32/edx
28562     # v->offset = *Curr-local-stack-offset
28563     8b/-> *Curr-local-stack-offset 0/r32/eax
28564     89/<- *(ecx+0x14) 0/r32/eax  # Var-offset
28565     # if v is an array, do something special to initialize it
28566     {
28567       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
28568       (mu-array? %eax)  # => eax
28569       3d/compare-eax-and 0/imm32/false
28570       0f 84/jump-if-= break/disp32
28571       # var array-size-without-size/edx: int = n-4
28572       81 5/subop/subtract %edx 4/imm32
28573       #
28574       (emit-array-data-initialization *(ebp+8) %edx)
28575       e9/jump $emit-subx-var-def:end/disp32
28576     }
28577     # another special-case for initializing streams
28578     # a stream is an array with 2 extra pointers
28579     {
28580       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
28581       (mu-stream? %eax)  # => eax
28582       3d/compare-eax-and 0/imm32/false
28583       0f 84/jump-if-= break/disp32
28584       # var array-size-without-size/edx: int = n-12
28585       81 5/subop/subtract %edx 0xc/imm32
28586       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
28587       (emit-stream-data-initialization *(ebp+8) %edx %eax *(ebp+0x10) *(ebp+0x14))
28588       # emit read and write pointers
28589       (emit-indent *(ebp+8) *Curr-block-depth)
28590       (write-buffered *(ebp+8) "68/push 0/imm32\n")
28591       (emit-indent *(ebp+8) *Curr-block-depth)
28592       (write-buffered *(ebp+8) "68/push 0/imm32\n")
28593       #
28594       eb/jump $emit-subx-var-def:end/disp8
28595     }
28596     # while n > 0
28597     {
28598       81 7/subop/compare %edx 0/imm32
28599       7e/jump-if-<= break/disp8
28600       (emit-indent *(ebp+8) *Curr-block-depth)
28601       (write-buffered *(ebp+8) "68/push 0/imm32\n")
28602       # n -= 4
28603       81 5/subop/subtract %edx 4/imm32
28604       #
28605       eb/jump loop/disp8
28606     }
28607 $emit-subx-var-def:end:
28608     # . restore registers
28609     5a/pop-to-edx
28610     59/pop-to-ecx
28611     58/pop-to-eax
28612     # . epilogue
28613     89/<- %esp 5/r32/ebp
28614     5d/pop-to-ebp
28615     c3/return
28616 
28617 emit-array-data-initialization:  # out: (addr buffered-file), n: int
28618     # . prologue
28619     55/push-ebp
28620     89/<- %ebp 4/r32/esp
28621     #
28622     (emit-indent *(ebp+8) *Curr-block-depth)
28623     (write-buffered *(ebp+8) "(push-n-zero-bytes ")
28624     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
28625     (write-buffered *(ebp+8) ")\n")
28626     (emit-indent *(ebp+8) *Curr-block-depth)
28627     (write-buffered *(ebp+8) "68/push ")
28628     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
28629     (write-buffered *(ebp+8) "/imm32\n")
28630 $emit-array-data-initialization:end:
28631     # . epilogue
28632     89/<- %esp 5/r32/ebp
28633     5d/pop-to-ebp
28634     c3/return
28635 
28636 emit-stream-data-initialization:  # out: (addr buffered-file), n: int, type: (addr type-tree), err: (addr buffered-file), ed: (addr exit-descriptor)
28637     # . prologue
28638     55/push-ebp
28639     89/<- %ebp 4/r32/esp
28640     # . save registers
28641     50/push-eax
28642     # Optimization: if it's a stream of bytes, don't initialize.
28643     #
28644     # We often construct large temporary streams on the stack for 'trace'
28645     # statements. Initializing such streams can significantly slow programs
28646     # down.
28647     #
28648     # Mu doesn't really depend on initializing stream contents for type- or
28649     # memory-safety; we're mostly doing so to make it easy to debug unsafe
28650     # SubX code that misuses stream objects by manipulating read/write
28651     # pointers. But you can't _really_ protect from unsafe SubX, so I think we
28652     # don't give up much safety or security here.
28653     {
28654       (stream-element-type-id *(ebp+0x10) *(ebp+0x14) *(ebp+0x18))  # => eax
28655       3d/compare-eax-and 8/imm32/byte
28656       75/jump-if-!= break/disp8
28657       (emit-indent *(ebp+8) *Curr-block-depth)
28658       (write-buffered *(ebp+8) "81 5/subop/subtract %esp ")
28659       (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
28660       (write-buffered *(ebp+8) "/imm32\n")
28661       eb/jump $emit-stream-data-initialization:emit-length/disp8
28662     }
28663     (emit-indent *(ebp+8) *Curr-block-depth)
28664     (write-buffered *(ebp+8) "(push-n-zero-bytes ")
28665     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
28666     (write-buffered *(ebp+8) ")\n")
28667 $emit-stream-data-initialization:emit-length:
28668     (emit-indent *(ebp+8) *Curr-block-depth)
28669     (write-buffered *(ebp+8) "68/push ")
28670     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
28671     (write-buffered *(ebp+8) "/imm32\n")
28672 $emit-stream-data-initialization:end:
28673     # . restore registers
28674     58/pop-to-eax
28675     # . epilogue
28676     89/<- %esp 5/r32/ebp
28677     5d/pop-to-ebp
28678     c3/return
28679 
28680 emit-subx-stmt:  # out: (addr buffered-file), stmt: (addr stmt), primitives: (addr primitive), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
28681     # . prologue
28682     55/push-ebp
28683     89/<- %ebp 4/r32/esp
28684     # . save registers
28685     50/push-eax
28686     51/push-ecx
28687     # - some special-case primitives that don't actually use the 'primitives' data structure
28688     # var op/ecx: (addr array byte) = lookup(stmt->operation)
28689     8b/-> *(ebp+0xc) 1/r32/ecx
28690     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
28691     89/<- %ecx 0/r32/eax
28692     # copy byte (can be a primitive except we need to emit a second instruction)
28693     {
28694       # if (!string-equal?(stmt->operation, "copy-byte")) break
28695       (string-equal? %ecx "copy-byte")  # => eax
28696       3d/compare-eax-and 0/imm32/false
28697       0f 84/jump-if-= break/disp32
28698       (translate-mu-copy-byte-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28699       e9/jump $emit-subx-stmt:end/disp32
28700     }
28701     # copy-byte-to can be a primitive; writes to memory don't need to clear surrounding bytes
28702     # array size
28703     {
28704       # if (!string-equal?(stmt->operation, "length")) break
28705       (string-equal? %ecx "length")  # => eax
28706       3d/compare-eax-and 0/imm32/false
28707       0f 84/jump-if-= break/disp32
28708       (translate-mu-length-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28709       e9/jump $emit-subx-stmt:end/disp32
28710     }
28711     # index into array
28712     {
28713       # if (!string-equal?(stmt->operation, "index")) break
28714       (string-equal? %ecx "index")  # => eax
28715       3d/compare-eax-and 0/imm32/false
28716       0f 84/jump-if-= break/disp32
28717       (translate-mu-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
28718       e9/jump $emit-subx-stmt:end/disp32
28719     }
28720     # compute-offset for index into array
28721     {
28722       # if (!string-equal?(stmt->operation, "compute-offset")) break
28723       (string-equal? %ecx "compute-offset")  # => eax
28724       3d/compare-eax-and 0/imm32/false
28725       0f 84/jump-if-= break/disp32
28726       (translate-mu-compute-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28727       e9/jump $emit-subx-stmt:end/disp32
28728     }
28729     # get field from record
28730     {
28731       # if (!string-equal?(stmt->operation, "get")) break
28732       (string-equal? %ecx "get")  # => eax
28733       3d/compare-eax-and 0/imm32/false
28734       0f 84/jump-if-= break/disp32
28735       (translate-mu-get-stmt *(ebp+8) *(ebp+0xc))
28736       e9/jump $emit-subx-stmt:end/disp32
28737     }
28738     # allocate scalar
28739     {
28740       # if (!string-equal?(stmt->operation, "allocate")) break
28741       (string-equal? %ecx "allocate")  # => eax
28742       3d/compare-eax-and 0/imm32/false
28743       0f 84/jump-if-= break/disp32
28744       (translate-mu-allocate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28745       e9/jump $emit-subx-stmt:end/disp32
28746     }
28747     # copy-object
28748     {
28749       # if (!string-equal?(stmt->operation, "copy-object")) break
28750       (string-equal? %ecx "copy-object")  # => eax
28751       3d/compare-eax-and 0/imm32/false
28752       0f 84/jump-if-= break/disp32
28753       (translate-mu-copy-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28754       e9/jump $emit-subx-stmt:end/disp32
28755     }
28756     # clear-object
28757     {
28758       # if (!string-equal?(stmt->operation, "clear-object")) break
28759       (string-equal? %ecx "clear-object")  # => eax
28760       3d/compare-eax-and 0/imm32/false
28761       0f 84/jump-if-= break/disp32
28762       (translate-mu-clear-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28763       e9/jump $emit-subx-stmt:end/disp32
28764     }
28765     # allocate array
28766     {
28767       # if (!string-equal?(stmt->operation, "populate")) break
28768       (string-equal? %ecx "populate")  # => eax
28769       3d/compare-eax-and 0/imm32/false
28770       0f 84/jump-if-= break/disp32
28771       (translate-mu-populate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28772       e9/jump $emit-subx-stmt:end/disp32
28773     }
28774     # allocate stream
28775     {
28776       # if (!string-equal?(stmt->operation, "populate-stream")) break
28777       (string-equal? %ecx "populate-stream")  # => eax
28778       3d/compare-eax-and 0/imm32/false
28779       0f 84/jump-if-= break/disp32
28780       (translate-mu-populate-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28781       e9/jump $emit-subx-stmt:end/disp32
28782     }
28783     # read from stream
28784     {
28785       # if (!string-equal?(stmt->operation, "read-from-stream")) break
28786       (string-equal? %ecx "read-from-stream")  # => eax
28787       3d/compare-eax-and 0/imm32/false
28788       0f 84/jump-if-= break/disp32
28789       (translate-mu-read-from-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28790       e9/jump $emit-subx-stmt:end/disp32
28791     }
28792     # write to stream
28793     {
28794       # if (!string-equal?(stmt->operation, "write-to-stream")) break
28795       (string-equal? %ecx "write-to-stream")  # => eax
28796       3d/compare-eax-and 0/imm32/false
28797       0f 84/jump-if-= break/disp32
28798       (translate-mu-write-to-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28799       e9/jump $emit-subx-stmt:end/disp32
28800     }
28801     # - optimizations
28802     # if copy instruction has same register in source and destination, emit nothing
28803     (redundant-copy? *(ebp+0xc))  # => eax
28804     3d/compare-eax-and 0/imm32/false
28805     75/jump-if-!= $emit-subx-stmt:end/disp8
28806     # - if stmt matches a primitive, emit it
28807     {
28808 $emit-subx-stmt:check-for-primitive:
28809       # var curr/eax: (addr primitive)
28810       (find-matching-primitive *(ebp+0x10) *(ebp+0xc))  # primitives, stmt => eax
28811       3d/compare-eax-and 0/imm32
28812       74/jump-if-= break/disp8
28813 $emit-subx-stmt:primitive:
28814       (emit-subx-primitive *(ebp+8) *(ebp+0xc) %eax)  # out, stmt, curr
28815       e9/jump $emit-subx-stmt:end/disp32
28816     }
28817     # - otherwise emit a call
28818 $emit-subx-stmt:call:
28819     (emit-call *(ebp+8) *(ebp+0xc))
28820 $emit-subx-stmt:end:
28821     # . restore registers
28822     59/pop-to-ecx
28823     58/pop-to-eax
28824     # . epilogue
28825     89/<- %esp 5/r32/ebp
28826     5d/pop-to-ebp
28827     c3/return
28828 
28829 redundant-copy?:  # stmt: (addr stmt) -> result/eax: boolean
28830     # . prologue
28831     55/push-ebp
28832     89/<- %ebp 4/r32/esp
28833     # . save registers
28834     56/push-esi
28835     57/push-edi
28836     # esi = stmt
28837     8b/-> *(ebp+8) 6/r32/esi
28838     # if stmt->operation != "copy" return false
28839     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
28840     (string-equal? %eax "copy")  # => eax
28841     3d/compare-eax-and 0/imm32/false
28842     0f 84/jump-if-= $redundant-copy?:end/disp32
28843     # var output-reg/edi: (addr stmt-var) = stmt->outputs->value->register
28844     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
28845     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
28846     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
28847     # . if output-reg == null, return false
28848     3d/compare-eax-and 0/imm32
28849     74/jump-if-= $redundant-copy?:end/disp8
28850     89/<- %edi 0/r32/eax
28851     # return (inout->value->register == output->value->register)
28852     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
28853     # . if inout->is-deref return false
28854     81 7/subop/compare *(eax+0x10) 0/imm32/false  # Stmt-var-is-deref
28855     {
28856       74/jump-if-= break/disp8
28857       b8/copy-to-eax 0/imm32/false
28858       e9/jump $redundant-copy?:end/disp32
28859     }
28860     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
28861     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
28862     # . if inout-reg == null, return false
28863     3d/compare-eax-and 0/imm32
28864     74/jump-if-= $redundant-copy?:end/disp8
28865     (string-equal? %eax %edi)  # => eax
28866 $redundant-copy?:end:
28867     # . restore registers
28868     5f/pop-to-edi
28869     5e/pop-to-esi
28870     # . epilogue
28871     89/<- %esp 5/r32/ebp
28872     5d/pop-to-ebp
28873     c3/return
28874 
28875 translate-mu-length-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
28876     # . prologue
28877     55/push-ebp
28878     89/<- %ebp 4/r32/esp
28879     # . save registers
28880     50/push-eax
28881     51/push-ecx
28882     52/push-edx
28883     53/push-ebx
28884     56/push-esi
28885     # esi = stmt
28886     8b/-> *(ebp+0xc) 6/r32/esi
28887     # var base/ebx: (addr var) = stmt->inouts[0]->value
28888     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
28889     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
28890     89/<- %ebx 0/r32/eax
28891     # var elemsize/ecx: int = array-element-size(base)
28892     (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
28893     89/<- %ecx 0/r32/eax
28894     # var outreg/edx: (addr array byte) = stmt->outputs[0]->value->register
28895     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
28896     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
28897     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
28898     89/<- %edx 0/r32/eax
28899     # if elemsize == 1
28900     {
28901       81 7/subop/compare %ecx 1/imm32
28902       75/jump-if-!= break/disp8
28903 $translate-mu-length-stmt:size-1:
28904       (emit-save-size-to *(ebp+8) %ebx %edx)
28905       e9/jump $translate-mu-length-stmt:end/disp32
28906     }
28907     # if elemsize is a power of 2 less than 256
28908     {
28909       (power-of-2? %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
28910       3d/compare-eax-and 0/imm32/false
28911       74/jump-if-= break/disp8
28912       81 7/subop/compare %ecx 0xff/imm32
28913       7f/jump-if-> break/disp8
28914 $translate-mu-length-stmt:size-power-of-2:
28915       (emit-save-size-to *(ebp+8) %ebx %edx)
28916       (emit-divide-by-shift-right *(ebp+8) %edx %ecx)
28917       e9/jump $translate-mu-length-stmt:end/disp32
28918     }
28919     # otherwise, the complex case
28920     # . emit register spills
28921     {
28922 $translate-mu-length-stmt:complex:
28923       (string-equal? %edx "eax")  # => eax
28924       3d/compare-eax-and 0/imm32/false
28925       75/break-if-!= break/disp8
28926       (emit-indent *(ebp+8) *Curr-block-depth)
28927       (write-buffered *(ebp+8) "50/push-eax\n")
28928     }
28929     {
28930       (string-equal? %edx "ecx")  # => eax
28931       3d/compare-eax-and 0/imm32/false
28932       75/break-if-!= break/disp8
28933       (emit-indent *(ebp+8) *Curr-block-depth)
28934       (write-buffered *(ebp+8) "51/push-ecx\n")
28935     }
28936     {
28937       (string-equal? %edx "edx")  # => eax
28938       3d/compare-eax-and 0/imm32/false
28939       75/break-if-!= break/disp8
28940       (emit-indent *(ebp+8) *Curr-block-depth)
28941       (write-buffered *(ebp+8) "52/push-edx\n")
28942     }
28943     # .
28944     (emit-save-size-to *(ebp+8) %ebx "eax")
28945     (emit-indent *(ebp+8) *Curr-block-depth)
28946     (write-buffered *(ebp+8) "31/xor %edx 2/r32/edx\n")
28947     (emit-indent *(ebp+8) *Curr-block-depth)
28948     (write-buffered *(ebp+8) "b9/copy-to-ecx ")
28949     (write-int32-hex-buffered *(ebp+8) %ecx)
28950     (write-buffered *(ebp+8) "/imm32\n")
28951     (emit-indent *(ebp+8) *Curr-block-depth)
28952     (write-buffered *(ebp+8) "f7 7/subop/idiv-eax-edx-by %ecx\n")
28953     {
28954       (string-equal? %edx "eax")  # => eax
28955       3d/compare-eax-and 0/imm32/false
28956       75/break-if-!= break/disp8
28957       (emit-indent *(ebp+8) *Curr-block-depth)
28958       (write-buffered *(ebp+8) "89/<- %")
28959       (write-buffered *(ebp+8) %edx)
28960       (write-buffered *(ebp+8) " 0/r32/eax\n")
28961     }
28962     # . emit register restores
28963     {
28964       (string-equal? %edx "edx")  # => eax
28965       3d/compare-eax-and 0/imm32/false
28966       75/break-if-!= break/disp8
28967       (emit-indent *(ebp+8) *Curr-block-depth)
28968       (write-buffered *(ebp+8) "5a/pop-to-edx\n")
28969     }
28970     {
28971       (string-equal? %edx "ecx")  # => eax
28972       3d/compare-eax-and 0/imm32/false
28973       75/break-if-!= break/disp8
28974       (emit-indent *(ebp+8) *Curr-block-depth)
28975       (write-buffered *(ebp+8) "59/pop-to-ecx\n")
28976     }
28977     {
28978       (string-equal? %edx "eax")  # => eax
28979       3d/compare-eax-and 0/imm32/false
28980       75/break-if-!= break/disp8
28981       (emit-indent *(ebp+8) *Curr-block-depth)
28982       (write-buffered *(ebp+8) "58/pop-to-eax\n")
28983     }
28984 $translate-mu-length-stmt:end:
28985     # . restore registers
28986     5e/pop-to-esi
28987     5b/pop-to-ebx
28988     5a/pop-to-edx
28989     59/pop-to-ecx
28990     58/pop-to-eax
28991     # . epilogue
28992     89/<- %esp 5/r32/ebp
28993     5d/pop-to-ebp
28994     c3/return
28995 
28996 array-element-size:  # arr: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
28997     # . prologue
28998     55/push-ebp
28999     89/<- %ebp 4/r32/esp
29000     #
29001     (array-element-type-id *(ebp+8) *(ebp+0xc) *(ebp+0x10))  # => eax
29002     (size-of-type-id-as-array-element %eax)  # => eax
29003 $array-element-size:end:
29004     # . epilogue
29005     89/<- %esp 5/r32/ebp
29006     5d/pop-to-ebp
29007     c3/return
29008 
29009 array-element-type-id:  # v: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: type-id
29010     # precondition: n is positive
29011     # . prologue
29012     55/push-ebp
29013     89/<- %ebp 4/r32/esp
29014     #
29015     8b/-> *(ebp+8) 0/r32/eax
29016     # var t/eax: (addr type-tree)
29017     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
29018     # if t == 0 abort
29019     3d/compare-eax-with 0/imm32
29020     0f 84/jump-if-== $array-element-type-id:error0/disp32
29021     # if t->is-atom? abort
29022     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
29023     0f 85/jump-if-!= $array-element-type-id:error1/disp32
29024     # if (t->left == addr) t = t->right
29025     {
29026       50/push-eax
29027       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29028       (simple-mu-type? %eax 2)  # addr => eax
29029       3d/compare-eax-with 0/imm32/false
29030       58/pop-to-eax
29031       74/jump-if-= break/disp8
29032 $array-element-type-id:skip-addr:
29033       (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
29034     }
29035     # if t == 0 abort
29036     3d/compare-eax-with 0/imm32
29037     0f 84/jump-if-= $array-element-type-id:error2/disp32
29038     # if t->is-atom? abort
29039     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
29040     0f 85/jump-if-!= $array-element-type-id:error2/disp32
29041     # if t->left != array abort
29042     {
29043       50/push-eax
29044       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29045       (simple-mu-type? %eax 3)  # array => eax
29046       3d/compare-eax-with 0/imm32/false
29047       58/pop-to-eax
29048 $array-element-type-id:no-array:
29049       0f 84/jump-if-= $array-element-type-id:error2/disp32
29050     }
29051 $array-element-type-id:skip-array:
29052     # t = t->right
29053     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
29054     # if t == 0 abort
29055     3d/compare-eax-with 0/imm32
29056     0f 84/jump-if-= $array-element-type-id:error2/disp32
29057     # if t->is-atom? abort
29058     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
29059     0f 85/jump-if-!= $array-element-type-id:error2/disp32
29060     # t = t->left
29061     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29062     # if (!t->is-atom?) t = t->left     # TODO: assumes array element size can be determined from just first word of array element type
29063     # if (t->is-atom == false) t = lookup(t->left)
29064     {
29065       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
29066       75/jump-if-!= break/disp8
29067       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29068     }
29069     # return t->value
29070     8b/-> *(eax+4) 0/r32/eax  # Type-tree-value
29071 $array-element-type-id:end:
29072     # . epilogue
29073     89/<- %esp 5/r32/ebp
29074     5d/pop-to-ebp
29075     c3/return
29076 
29077 $array-element-type-id:error0:
29078     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
29079     50/push-eax
29080     8b/-> *(ebp+8) 0/r32/eax
29081     (lookup *eax *(eax+4))  # Var-name Var-name => eax
29082     (write-buffered *(ebp+0xc) %eax)
29083     58/pop-to-eax
29084     (write-buffered *(ebp+0xc) "' has no type\n")
29085     (flush *(ebp+0xc))
29086     (stop *(ebp+0x10) 1)
29087     # never gets here
29088 
29089 $array-element-type-id:error1:
29090     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
29091     50/push-eax
29092     8b/-> *(ebp+8) 0/r32/eax
29093     (lookup *eax *(eax+4))  # Var-name Var-name => eax
29094     (write-buffered *(ebp+0xc) %eax)
29095     58/pop-to-eax
29096     (write-buffered *(ebp+0xc) "' has atomic type ")
29097     (write-int32-hex-buffered *(ebp+0xc) *(eax+4))  # Type-tree-value
29098     (write-buffered *(ebp+0xc) Newline)
29099     (flush *(ebp+0xc))
29100     (stop *(ebp+0x10) 1)
29101     # never gets here
29102 
29103 $array-element-type-id:error2:
29104     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
29105     50/push-eax
29106     8b/-> *(ebp+8) 0/r32/eax
29107     (lookup *eax *(eax+4))  # Var-name Var-name => eax
29108     (write-buffered *(ebp+0xc) %eax)
29109     58/pop-to-eax
29110     (write-buffered *(ebp+0xc) "' has non-array type\n")
29111     (flush *(ebp+0xc))
29112     (stop *(ebp+0x10) 1)
29113     # never gets here
29114 
29115 size-of-type-id-as-array-element:  # t: type-id -> result/eax: int
29116     # . prologue
29117     55/push-ebp
29118     89/<- %ebp 4/r32/esp
29119     # eax = t
29120     8b/-> *(ebp+8) 0/r32/eax
29121     # if t is 'byte', size is 1
29122     3d/compare-eax-and 8/imm32/byte
29123     {
29124       75/jump-if-!= break/disp8
29125       b8/copy-to-eax 1/imm32
29126       eb/jump $size-of-type-id-as-array-element:end/disp8
29127     }
29128     # otherwise proceed as usual
29129     (size-of-type-id %eax)  # => eax
29130 $size-of-type-id-as-array-element:end:
29131     # . epilogue
29132     89/<- %esp 5/r32/ebp
29133     5d/pop-to-ebp
29134     c3/return
29135 
29136 stream-element-type-id:  # type: (addr type-tree), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: type-id
29137     # precondition: n is positive
29138     # . prologue
29139     55/push-ebp
29140     89/<- %ebp 4/r32/esp
29141     # eax = type
29142     8b/-> *(ebp+8) 0/r32/eax
29143     # if type == 0 abort
29144     3d/compare-eax-with 0/imm32
29145     0f 84/jump-if-== $stream-element-type-id:error0/disp32
29146     # if type->is-atom? abort
29147     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
29148     0f 85/jump-if-!= $stream-element-type-id:error1/disp32
29149     # if (type->left == addr) type = type->right
29150     {
29151       50/push-eax
29152       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29153       (simple-mu-type? %eax 2)  # addr => eax
29154       3d/compare-eax-with 0/imm32/false
29155       58/pop-to-eax
29156       74/jump-if-= break/disp8
29157 $stream-element-type-id:skip-addr:
29158       (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
29159     }
29160     # if type == 0 abort
29161     3d/compare-eax-with 0/imm32
29162     0f 84/jump-if-= $stream-element-type-id:error2/disp32
29163     # if type->is-atom? abort
29164     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
29165     0f 85/jump-if-!= $stream-element-type-id:error2/disp32
29166     # if type->left != stream abort
29167     {
29168       50/push-eax
29169       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29170       (simple-mu-type? %eax 0xb)  # stream => eax
29171       3d/compare-eax-with 0/imm32/false
29172       58/pop-to-eax
29173 $stream-element-type-id:no-stream:
29174       0f 84/jump-if-= $stream-element-type-id:error2/disp32
29175     }
29176 $stream-element-type-id:skip-stream:
29177     # type = type->right
29178     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
29179     # if type == 0 abort
29180     3d/compare-eax-with 0/imm32
29181     0f 84/jump-if-= $stream-element-type-id:error2/disp32
29182     # if type->is-atom? abort
29183     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
29184     0f 85/jump-if-!= $stream-element-type-id:error2/disp32
29185     # t = type->left
29186     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29187     # if (!type->is-atom?) type = type->left     # TODO: assumes stream element size can be determined from just first word of stream element type
29188     {
29189       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
29190       75/jump-if-!= break/disp8
29191       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29192     }
29193     # return type->value
29194     8b/-> *(eax+4) 0/r32/eax  # Type-tree-value
29195 $stream-element-type-id:end:
29196     # . epilogue
29197     89/<- %esp 5/r32/ebp
29198     5d/pop-to-ebp
29199     c3/return
29200 
29201 $stream-element-type-id:error0:
29202     (write-buffered *(ebp+0xc) "stream-element-type-id: var '")
29203     50/push-eax
29204     8b/-> *(ebp+8) 0/r32/eax
29205     (lookup *eax *(eax+4))  # Var-name Var-name => eax
29206     (write-buffered *(ebp+0xc) %eax)
29207     58/pop-to-eax
29208     (write-buffered *(ebp+0xc) "' has no type\n")
29209     (flush *(ebp+0xc))
29210     (stop *(ebp+0x10) 1)
29211     # never gets here
29212 
29213 $stream-element-type-id:error1:
29214     (write-buffered *(ebp+0xc) "stream-element-type-id: var '")
29215     50/push-eax
29216     8b/-> *(ebp+8) 0/r32/eax
29217     (lookup *eax *(eax+4))  # Var-name Var-name => eax
29218     (write-buffered *(ebp+0xc) %eax)
29219     58/pop-to-eax
29220     (write-buffered *(ebp+0xc) "' has atomic type ")
29221     (write-int32-hex-buffered *(ebp+0xc) *(eax+4))  # Type-tree-value
29222     (write-buffered *(ebp+0xc) Newline)
29223     (flush *(ebp+0xc))
29224     (stop *(ebp+0x10) 1)
29225     # never gets here
29226 
29227 $stream-element-type-id:error2:
29228     (write-buffered *(ebp+0xc) "stream-element-type-id: var '")
29229     50/push-eax
29230     8b/-> *(ebp+8) 0/r32/eax
29231     (lookup *eax *(eax+4))  # Var-name Var-name => eax
29232     (write-buffered *(ebp+0xc) %eax)
29233     58/pop-to-eax
29234     (write-buffered *(ebp+0xc) "' has non-stream type\n")
29235     (flush *(ebp+0xc))
29236     (stop *(ebp+0x10) 1)
29237     # never gets here
29238 
29239 emit-save-size-to:  # out: (addr buffered-file), base: (addr var), outreg: (addr array byte)
29240     # . prologue
29241     55/push-ebp
29242     89/<- %ebp 4/r32/esp
29243     # . save registers
29244     50/push-eax
29245     53/push-ebx
29246     # ebx = base
29247     8b/-> *(ebp+0xc) 3/r32/ebx
29248     (emit-indent *(ebp+8) *Curr-block-depth)
29249     (write-buffered *(ebp+8) "8b/-> *")
29250     # if base is an (addr array ...) in a register
29251     {
29252       81 7/subop/compare *(ebx+0x18)) 0/imm32  # Var-register
29253       74/jump-if-= break/disp8
29254 $emit-save-size-to:emit-base-from-register:
29255       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
29256       (write-buffered *(ebp+8) %eax)
29257       eb/jump $emit-save-size-to:emit-output/disp8
29258     }
29259     # otherwise if base is an (array ...) on the stack
29260     {
29261       81 7/subop/compare *(ebx+0x14)) 0/imm32  # Var-offset
29262       74/jump-if-= break/disp8
29263 $emit-save-size-to:emit-base-from-stack:
29264       (write-buffered *(ebp+8) "(ebp+")
29265       (write-int32-hex-buffered *(ebp+8) *(ebx+0x14))  # Var-offset
29266       (write-buffered *(ebp+8) ")")
29267     }
29268 $emit-save-size-to:emit-output:
29269     (write-buffered *(ebp+8) " ")
29270     (get Mu-registers *(ebp+0x10) 0xc "Mu-registers")  # => eax
29271     (write-int32-hex-buffered *(ebp+8) *eax)
29272     (write-buffered *(ebp+8) "/r32\n")
29273 $emit-save-size-to:end:
29274     # . restore registers
29275     5b/pop-to-ebx
29276     58/pop-to-eax
29277     # . epilogue
29278     89/<- %esp 5/r32/ebp
29279     5d/pop-to-ebp
29280     c3/return
29281 
29282 emit-divide-by-shift-right:  # out: (addr buffered-file), reg: (addr array byte), size: int
29283     # . prologue
29284     55/push-ebp
29285     89/<- %ebp 4/r32/esp
29286     # . save registers
29287     50/push-eax
29288     #
29289     (emit-indent *(ebp+8) *Curr-block-depth)
29290     (write-buffered *(ebp+8) "c1/shift 5/subop/>> %")
29291     (write-buffered *(ebp+8) *(ebp+0xc))
29292     (write-buffered *(ebp+8) Space)
29293     (num-shift-rights *(ebp+0x10))  # => eax
29294     (write-int32-hex-buffered *(ebp+8) %eax)
29295     (write-buffered *(ebp+8) "/imm8\n")
29296 $emit-divide-by-shift-right:end:
29297     # . restore registers
29298     58/pop-to-eax
29299     # . epilogue
29300     89/<- %esp 5/r32/ebp
29301     5d/pop-to-ebp
29302     c3/return
29303 
29304 translate-mu-copy-byte-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29305     # . prologue
29306     55/push-ebp
29307     89/<- %ebp 4/r32/esp
29308     # . save registers
29309     50/push-eax
29310     56/push-esi
29311     # esi = stmt
29312     8b/-> *(ebp+0xc) 6/r32/esi
29313     #
29314     (emit-indent *(ebp+8) *Curr-block-depth)
29315     (write-buffered *(ebp+8) "8a/byte->")
29316     # emit stmt->inouts[0]
29317     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29318     (emit-subx-var-as-rm32 *(ebp+8) %eax)
29319     # emit /r32 for stmt->outputs[0]->register
29320     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
29321     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29322     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
29323     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
29324     (write-buffered *(ebp+8) Space)
29325     (write-int32-hex-buffered *(ebp+8) *eax)
29326     (write-buffered *(ebp+8) "/r32\n")
29327     # clear rest of register
29328     (emit-indent *(ebp+8) *Curr-block-depth)
29329     (write-buffered *(ebp+8) "81 4/subop/and %")
29330     8b/-> *(ebp+0xc) 0/r32/eax
29331     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
29332     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29333     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
29334     (write-buffered *(ebp+8) %eax)
29335     (write-buffered *(ebp+8) " 0xff/imm32\n")
29336 $translate-mu-copy-byte-stmt:end:
29337     # . restore registers
29338     5e/pop-to-esi
29339     58/pop-to-eax
29340     # . epilogue
29341     89/<- %esp 5/r32/ebp
29342     5d/pop-to-ebp
29343     c3/return
29344 
29345 # a little different from other translate- functions; notice the extra 'fn' argument
29346 translate-mu-index-stmt:  # out: (addr buffered-file), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
29347     # . prologue
29348     55/push-ebp
29349     89/<- %ebp 4/r32/esp
29350     # . save registers
29351     53/push-ebx
29352     # ebx = stmt
29353     8b/-> *(ebp+0xc) 3/r32/ebx
29354     # var base/ebx: (addr var) = stmt->inouts[0]
29355     (lookup *(ebx+0xc) *(ebx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29356     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29357     89/<- %ebx 0/r32/eax
29358     # emit bounds-check
29359     (emit-mu-index-bounds-check *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18))
29360     # if (var->register) do one thing
29361     {
29362       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
29363       74/jump-if-= break/disp8
29364       # TODO: ensure there's no dereference
29365       (translate-mu-index-stmt-with-array-in-register *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
29366       eb/jump $translate-mu-index-stmt:end/disp8
29367     }
29368     # if (var->offset) do a different thing
29369     {
29370       81 7/subop/compare *(ebx+0x14) 0/imm32  # Var-offset
29371       74/jump-if-= break/disp8
29372       # TODO: ensure there's no dereference
29373       (translate-mu-index-stmt-with-array-on-stack *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
29374       eb/jump $translate-mu-index-stmt:end/disp8
29375     }
29376 $translate-mu-index-stmt:end:
29377     # . restore registers
29378     5b/pop-to-ebx
29379     # . epilogue
29380     89/<- %esp 5/r32/ebp
29381     5d/pop-to-ebp
29382     c3/return
29383 
29384 $translate-mu-index-stmt:error1:
29385     (write-buffered *(ebp+0x14) "couldn't translate an index instruction. second (index) input must either lie in a register or be a literal\n")
29386     (flush *(ebp+0x14))
29387     (stop *(ebp+0x18) 1)
29388     # never gets here
29389 
29390 $translate-mu-index-stmt:error2:
29391     (write-buffered *(ebp+0x14) "couldn't translate an index instruction. second (index) input when in a register must be an int or offset\n")
29392     (flush *(ebp+0x14))
29393     (stop *(ebp+0x18) 1)
29394     # never gets here
29395 
29396 emit-mu-index-bounds-check:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29397     # . prologue
29398     55/push-ebp
29399     89/<- %ebp 4/r32/esp
29400     # . save registers
29401     50/push-eax
29402     51/push-ecx
29403     52/push-edx
29404     53/push-ebx
29405     # ecx = stmt
29406     8b/-> *(ebp+0xc) 1/r32/ecx
29407     #
29408     (emit-indent *(ebp+8) *Curr-block-depth)
29409     (write-buffered *(ebp+8) "(__check-mu-array-bounds ")
29410 $emit-mu-index-bounds-check:compute-base:
29411     # var base/ebx: (addr var) = inouts[0]
29412     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29413     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29414     89/<- %ebx 0/r32/eax
29415 $emit-mu-index-bounds-check:emit-index:
29416     # var index/edx: (addr var) = inouts[1]
29417     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29418     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
29419     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29420     89/<- %edx 0/r32/eax
29421     # if index->register, print its code
29422     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
29423     {
29424       0f 84/jump-if-= break/disp32
29425 $emit-mu-index-bounds-check:emit-register-index:
29426       (write-buffered *(ebp+8) "%")
29427       (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
29428       (write-buffered *(ebp+8) %eax)
29429       eb/jump $emit-mu-index-bounds-check:index-done/disp8
29430     }
29431     # otherwise if index is a literal, print it
29432 $emit-mu-index-bounds-check:emit-literal-index:
29433     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29434     (simple-mu-type? %eax 0)  # => eax
29435     3d/compare-eax-and 0/imm32/false
29436     {
29437       0f 84/jump-if-= break/disp32
29438       (lookup *edx *(edx+4))  # Var-name Var-name => eax
29439       (write-buffered *(ebp+8) %eax)
29440     }
29441 $emit-mu-index-bounds-check:index-done:
29442     (write-buffered *(ebp+8) " ")
29443 $emit-mu-index-bounds-check:emit-element-size:
29444     # if index is a literal or int, print size of array element
29445     {
29446       {
29447         (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29448         (simple-mu-type? %eax 0)  # literal => eax
29449         3d/compare-eax-and 0/imm32/false
29450         75/jump-if-!= break/disp8
29451         (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29452         (simple-mu-type? %eax 1)  # int => eax
29453         3d/compare-eax-and 0/imm32/false
29454         75/jump-if-!= break/disp8
29455         eb/jump $emit-mu-index-bounds-check:emit-element-size-offset/disp8
29456       }
29457 $emit-mu-index-bounds-check:emit-int-register-index:
29458       (array-element-size %ebx *(ebp+0x14) *(ebp+0x18))  # => eax
29459       (write-int32-hex-buffered *(ebp+8) %eax)
29460       e9/jump $emit-mu-index-bounds-check:emit-base/disp32
29461     }
29462 $emit-mu-index-bounds-check:emit-element-size-offset:
29463     # if index has type (offset ...), print "1"
29464     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29465     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
29466     {
29467       75/jump-if-!= break/disp8
29468       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29469       (simple-mu-type? %eax 7)  # => eax
29470       3d/compare-eax-and 0/imm32/false
29471       {
29472         0f 84/jump-if-= break/disp32
29473 $emit-mu-index-bounds-check:emit-offset-register-index:
29474         (write-buffered *(ebp+8) "1")
29475       }
29476     }
29477 $emit-mu-index-bounds-check:emit-base:
29478     # if base is in a register, print " *" base->register
29479     81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
29480     {
29481       74/jump-if-= break/disp8
29482       (write-buffered *(ebp+8) " *")
29483       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
29484       (write-buffered *(ebp+8) %eax)
29485       e9/jump $emit-mu-index-bounds-check:emit-function-name/disp32
29486     }
29487     # otherwise print " *(ebp+" base->offset ")"
29488     (write-buffered *(ebp+8) " *(ebp+")
29489     (write-int32-hex-buffered *(ebp+8) *(ebx+0x14))  # Var-offset
29490     (write-buffered *(ebp+8) ")")
29491 $emit-mu-index-bounds-check:emit-function-name:
29492     # " \"" function-name "\""
29493     (write-buffered *(ebp+8) " \"")
29494     8b/-> *(ebp+0x10) 1/r32/ecx
29495     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
29496     (write-buffered *(ebp+8) %eax)
29497     (write-buffered *(ebp+8) "\"")
29498 $emit-mu-index-bounds-check:emit-array-name:
29499     # " \"" base->name "\""
29500     (write-buffered *(ebp+8) " \"")
29501     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
29502     (write-buffered *(ebp+8) %eax)
29503     (write-buffered *(ebp+8) "\")\n")
29504 $emit-mu-index-bounds-check:end:
29505     # . restore registers
29506     5b/pop-to-ebx
29507     5a/pop-to-edx
29508     59/pop-to-ecx
29509     58/pop-to-eax
29510     # . epilogue
29511     89/<- %esp 5/r32/ebp
29512     5d/pop-to-ebp
29513     c3/return
29514 
29515 translate-mu-index-stmt-with-array-in-register:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29516     # . prologue
29517     55/push-ebp
29518     89/<- %ebp 4/r32/esp
29519     # . save registers
29520     50/push-eax
29521     51/push-ecx
29522     52/push-edx
29523     53/push-ebx
29524     # ecx = stmt
29525     8b/-> *(ebp+0xc) 1/r32/ecx
29526     # var base/ebx: (addr var) = inouts[0]
29527     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29528     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29529     89/<- %ebx 0/r32/eax
29530     # emit null check
29531     (emit-indent *(ebp+8) *Curr-block-depth)
29532     (write-buffered *(ebp+8) "81 7/subop/compare %")
29533     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
29534     (write-buffered *(ebp+8) %eax)
29535     (write-buffered *(ebp+8) " 0/imm32\n")
29536     (emit-indent *(ebp+8) *Curr-block-depth)
29537     (write-buffered *(ebp+8) "0f 84/jump-if-= __mu-abort-null-index-base-address/disp32\n")
29538     #
29539     (emit-indent *(ebp+8) *Curr-block-depth)
29540     (write-buffered *(ebp+8) "8d/copy-address *(")
29541     # TODO: ensure inouts[0] is in a register and not dereferenced
29542 $translate-mu-index-stmt-with-array-in-register:emit-base:
29543     # print base->register " + "
29544     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
29545     (write-buffered *(ebp+8) %eax)
29546     (write-buffered *(ebp+8) " + ")
29547     # var index/edx: (addr var) = inouts[1]
29548     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29549     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
29550     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29551     89/<- %edx 0/r32/eax
29552     # if index->register
29553     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
29554     {
29555       0f 84/jump-if-= break/disp32
29556 $translate-mu-index-stmt-with-array-in-register:emit-register-index:
29557       # if index is an int
29558       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29559       (simple-mu-type? %eax 1)  # int => eax
29560       3d/compare-eax-and 0/imm32/false
29561       {
29562         0f 84/jump-if-= break/disp32
29563 $translate-mu-index-stmt-with-array-in-register:emit-int-register-index:
29564         # print index->register "<<" log2(array-element-size(base)) " + 4) "
29565         # . index->register "<<"
29566         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
29567         (write-buffered *(ebp+8) %eax)
29568         (write-buffered *(ebp+8) "<<")
29569         # . log2(array-element-size(base->type))
29570         # we know size is a power of 2
29571         (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
29572         (num-shift-rights %eax)  # => eax
29573         (write-int32-hex-buffered *(ebp+8) %eax)
29574         e9/jump $translate-mu-index-stmt-with-array-in-register:emit-register-index-done/disp32
29575       }
29576       # if index->type is any other atom, abort
29577       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29578       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
29579       0f 85/jump-if-!= $translate-mu-index-stmt:error2/disp32
29580       # if index has type (offset ...)
29581       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29582       (simple-mu-type? %eax 7)  # => eax
29583       3d/compare-eax-and 0/imm32/false
29584       {
29585         0f 84/jump-if-= break/disp32
29586         # print index->register
29587 $translate-mu-index-stmt-with-array-in-register:emit-offset-register-index:
29588         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
29589         (write-buffered *(ebp+8) %eax)
29590       }
29591 $translate-mu-index-stmt-with-array-in-register:emit-register-index-done:
29592       (write-buffered *(ebp+8) " + 4) ")
29593       e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32
29594     }
29595     # otherwise if index is a literal
29596     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29597     (simple-mu-type? %eax 0)  # => eax
29598     3d/compare-eax-and 0/imm32/false
29599     {
29600       0f 84/jump-if-= break/disp32
29601 $translate-mu-index-stmt-with-array-in-register:emit-literal-index:
29602       # var index-value/edx: int = parse-hex-int(index->name)
29603       (lookup *edx *(edx+4))  # Var-name Var-name => eax
29604       (parse-hex-int %eax)  # => eax
29605       89/<- %edx 0/r32/eax
29606       # offset = idx-value * array-element-size(base->type)
29607       (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
29608       f7 4/subop/multiply-into-edx-eax %edx  # clobbers edx
29609       # offset += 4 for array size
29610       05/add-to-eax 4/imm32
29611       # TODO: check edx for overflow
29612       # print offset
29613       (write-int32-hex-buffered *(ebp+8) %eax)
29614       (write-buffered *(ebp+8) ") ")
29615       e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32
29616     }
29617     # otherwise abort
29618     e9/jump $translate-mu-index-stmt:error1/disp32
29619 $translate-mu-index-stmt-with-array-in-register:emit-output:
29620     # outputs[0] "/r32"
29621     8b/-> *(ebp+0xc) 1/r32/ecx
29622     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
29623     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29624     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
29625     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
29626     (write-int32-hex-buffered *(ebp+8) *eax)
29627     (write-buffered *(ebp+8) "/r32\n")
29628 $translate-mu-index-stmt-with-array-in-register:end:
29629     # . restore registers
29630     5b/pop-to-ebx
29631     5a/pop-to-edx
29632     59/pop-to-ecx
29633     58/pop-to-eax
29634     # . epilogue
29635     89/<- %esp 5/r32/ebp
29636     5d/pop-to-ebp
29637     c3/return
29638 
29639 translate-mu-index-stmt-with-array-on-stack:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29640     # . prologue
29641     55/push-ebp
29642     89/<- %ebp 4/r32/esp
29643     # . save registers
29644     50/push-eax
29645     51/push-ecx
29646     52/push-edx
29647     53/push-ebx
29648     #
29649     (emit-indent *(ebp+8) *Curr-block-depth)
29650     (write-buffered *(ebp+8) "8d/copy-address *(ebp + ")
29651     # var curr/edx: (addr stmt-var) = lookup(stmt->inouts)
29652     8b/-> *(ebp+0xc) 0/r32/eax
29653     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29654     89/<- %edx 0/r32/eax
29655     # var base/ecx: (addr var) = lookup(curr->value)
29656     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29657     89/<- %ecx 0/r32/eax
29658     # var curr2/eax: (addr stmt-var) = lookup(curr->next)
29659     (lookup *(edx+8) *(edx+0xc))  # Stmt-var-next Stmt-var-next => eax
29660     # var index/edx: (handle var) = curr2->value
29661     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29662     89/<- %edx 0/r32/eax
29663     # if index->register
29664     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
29665     {
29666       0f 84/jump-if-= break/disp32
29667 $translate-mu-index-stmt-with-array-on-stack:emit-register-index:
29668       # if index is an int
29669       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29670       (simple-mu-type? %eax 1)  # int => eax
29671       3d/compare-eax-and 0/imm32/false
29672       {
29673         0f 84/jump-if-= break/disp32
29674 $translate-mu-index-stmt-with-array-on-stack:emit-int-register-index:
29675         # print index->register "<<" log2(array-element-size(base)) " + " base->offset+4
29676         # . inouts[1]->register "<<"
29677         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
29678         (write-buffered *(ebp+8) %eax)
29679         (write-buffered *(ebp+8) "<<")
29680         # . log2(array-element-size(base))
29681         # TODO: ensure size is a power of 2
29682         (array-element-size %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
29683         (num-shift-rights %eax)  # => eax
29684         (write-int32-hex-buffered *(ebp+8) %eax)
29685         #
29686         (write-buffered *(ebp+8) " + ")
29687         #
29688         8b/-> *(ecx+0x14) 0/r32/eax  # Var-offset
29689         05/add-to-eax 4/imm32  # for array length
29690         (write-int32-hex-buffered *(ebp+8) %eax)
29691         e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done/disp32
29692       }
29693       # if index->type is any other atom, abort
29694       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29695       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
29696       0f 85/jump-if-!= $translate-mu-index-stmt:error2/disp32
29697       # if index has type (offset ...)
29698       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29699       (simple-mu-type? %eax 7)  # => eax
29700       3d/compare-eax-and 0/imm32/false
29701       {
29702         0f 84/jump-if-= break/disp32
29703         # print index->register
29704 $translate-mu-index-stmt-with-array-on-stack:emit-offset-register-index:
29705         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
29706         (write-buffered *(ebp+8) %eax)
29707       }
29708 $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done:
29709       (write-buffered *(ebp+8) ") ")
29710       e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32
29711     }
29712     # otherwise if index is a literal
29713     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29714     (simple-mu-type? %eax 0)  # => eax
29715     3d/compare-eax-and 0/imm32/false
29716     {
29717       0f 84/jump-if-= break/disp32
29718 $translate-mu-index-stmt-with-array-on-stack:emit-literal-index:
29719       # var idx-value/edx: int = parse-hex-int(index->name)
29720       (lookup *edx *(edx+4))  # Var-name Var-name => eax
29721       (parse-hex-int %eax)  # Var-name => eax
29722       89/<- %edx 0/r32/eax
29723       # offset = idx-value * array-element-size(base)
29724       (array-element-size %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
29725       f7 4/subop/multiply-into-edx-eax %edx  # clobbers edx
29726       # offset += base->offset
29727       03/add *(ecx+0x14) 0/r32/eax  # Var-offset
29728       # offset += 4 for array size
29729       05/add-to-eax 4/imm32
29730       # TODO: check edx for overflow
29731       # print offset
29732       (write-int32-hex-buffered *(ebp+8) %eax)
29733       (write-buffered *(ebp+8) ") ")
29734       e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32
29735     }
29736     # otherwise abort
29737     e9/jump $translate-mu-index-stmt:error1/disp32
29738 $translate-mu-index-stmt-with-array-on-stack:emit-output:
29739     # outputs[0] "/r32"
29740     8b/-> *(ebp+0xc) 0/r32/eax
29741     (lookup *(eax+0x14) *(eax+0x18))  # Stmt1-outputs Stmt1-outputs => eax
29742     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29743     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
29744     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
29745     (write-int32-hex-buffered *(ebp+8) *eax)
29746     (write-buffered *(ebp+8) "/r32\n")
29747 $translate-mu-index-stmt-with-array-on-stack:end:
29748     # . restore registers
29749     5b/pop-to-ebx
29750     5a/pop-to-edx
29751     59/pop-to-ecx
29752     58/pop-to-eax
29753     # . epilogue
29754     89/<- %esp 5/r32/ebp
29755     5d/pop-to-ebp
29756     c3/return
29757 
29758 translate-mu-compute-index-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29759     # . prologue
29760     55/push-ebp
29761     89/<- %ebp 4/r32/esp
29762     # . save registers
29763     50/push-eax
29764     51/push-ecx
29765     52/push-edx
29766     53/push-ebx
29767     #
29768     (emit-indent *(ebp+8) *Curr-block-depth)
29769     (write-buffered *(ebp+8) "69/multiply")
29770     # ecx = stmt
29771     8b/-> *(ebp+0xc) 1/r32/ecx
29772     # var first-inout/ebx: (addr stmt-var) = stmt->inouts[0]
29773     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29774     89/<- %ebx 0/r32/eax
29775 $translate-mu-compute-index-stmt:emit-index:
29776     (lookup *(ebx+8) *(ebx+0xc))  # Stmt-var-next Stmt-var-next => eax
29777     (emit-subx-var-as-rm32 *(ebp+8) %eax)
29778     (write-buffered *(ebp+8) Space)
29779 $translate-mu-compute-index-stmt:emit-elem-size:
29780     # var base/ebx: (addr var)
29781     (lookup *ebx *(ebx+4))  # Stmt-var-value Stmt-var-value => eax
29782     89/<- %ebx 0/r32/eax
29783     # print array-element-size(base)
29784     (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
29785     (write-int32-hex-buffered *(ebp+8) %eax)
29786     (write-buffered *(ebp+8) "/imm32 ")
29787 $translate-mu-compute-index-stmt:emit-output:
29788     # outputs[0] "/r32"
29789     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
29790     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29791     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
29792     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
29793     (write-int32-hex-buffered *(ebp+8) *eax)
29794     (write-buffered *(ebp+8) "/r32\n")
29795 $translate-mu-compute-index-stmt:end:
29796     # . restore registers
29797     5b/pop-to-ebx
29798     5a/pop-to-edx
29799     59/pop-to-ecx
29800     58/pop-to-eax
29801     # . epilogue
29802     89/<- %esp 5/r32/ebp
29803     5d/pop-to-ebp
29804     c3/return
29805 
29806 translate-mu-get-stmt:  # out: (addr buffered-file), stmt: (addr stmt)
29807     # . prologue
29808     55/push-ebp
29809     89/<- %ebp 4/r32/esp
29810     # . save registers
29811     50/push-eax
29812     51/push-ecx
29813     52/push-edx
29814     # ecx = stmt
29815     8b/-> *(ebp+0xc) 1/r32/ecx
29816     # var base/eax: (addr var) = stmt->inouts->value
29817     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29818     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29819     # if base is in a register, insert a null check
29820     81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
29821     {
29822       0f 84/jump-if-= break/disp32
29823 $translate-mu-get-stmt:emit-null-check-for-register-input:
29824       # emit "81 7/subop/compare %" base->register " 0/imm32\n"
29825       (emit-indent *(ebp+8) *Curr-block-depth)
29826       (write-buffered *(ebp+8) "81 7/subop/compare %")
29827       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
29828       (write-buffered *(ebp+8) %eax)
29829       (write-buffered *(ebp+8) " 0/imm32\n")
29830       #
29831       (emit-indent *(ebp+8) *Curr-block-depth)
29832       (write-buffered *(ebp+8) "0f 84/jump-if-= __mu-abort-null-get-base-address/disp32\n")
29833     }
29834     # var offset/edx: int = get offset of stmt
29835     (mu-get-offset %ecx)  # => eax
29836     89/<- %edx 0/r32/eax
29837     # var base/eax: (addr var) = stmt->inouts->value
29838     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29839     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29840     #
29841     (emit-indent *(ebp+8) *Curr-block-depth)
29842     (write-buffered *(ebp+8) "8d/copy-address ")
29843     # if base is in a register
29844     81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
29845     {
29846       0f 84/jump-if-= break/disp32
29847 $translate-mu-get-stmt:emit-register-input:
29848       # emit "*(" base->register " + " offset ") "
29849       (write-buffered *(ebp+8) "*(")
29850       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
29851       (write-buffered *(ebp+8) %eax)
29852       (write-buffered *(ebp+8) " + ")
29853       (write-int32-hex-buffered *(ebp+8) %edx)
29854       (write-buffered *(ebp+8) ") ")
29855       e9/jump $translate-mu-get-stmt:emit-output/disp32
29856     }
29857     # otherwise base is on the stack
29858     {
29859 $translate-mu-get-stmt:emit-stack-input:
29860       # emit "*(ebp + " inouts[0]->stack-offset + offset ") "
29861       (write-buffered *(ebp+8) "*(ebp+")
29862       03/add *(eax+0x14) 2/r32/edx  # Var-offset
29863       (write-int32-hex-buffered *(ebp+8) %edx)
29864       (write-buffered *(ebp+8) ") ")
29865       eb/jump $translate-mu-get-stmt:emit-output/disp8
29866     }
29867 $translate-mu-get-stmt:emit-output:
29868     # var output/eax: (addr var) = stmt->outputs->value
29869     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
29870     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29871     # emit offset->register "/r32"
29872     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
29873     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
29874     (write-int32-hex-buffered *(ebp+8) *eax)
29875     (write-buffered *(ebp+8) "/r32\n")
29876 $translate-mu-get-stmt:end:
29877     # . restore registers
29878     5a/pop-to-edx
29879     59/pop-to-ecx
29880     58/pop-to-eax
29881     # . epilogue
29882     89/<- %esp 5/r32/ebp
29883     5d/pop-to-ebp
29884     c3/return
29885 
29886 translate-mu-copy-object-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29887     # . prologue
29888     55/push-ebp
29889     89/<- %ebp 4/r32/esp
29890     # . save registers
29891     50/push-eax
29892     #
29893     (emit-indent *(ebp+8) *Curr-block-depth)
29894     (write-buffered *(ebp+8) "(copy-bytes")
29895     # eax = stmt
29896     8b/-> *(ebp+0xc) 0/r32/eax
29897     # var first-inout/eax: (addr stmt-var) = stmt->inouts[0]
29898     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29899     (emit-subx-call-operand *(ebp+8) %eax)
29900     # var second-inout/eax: (addr stmt-var) = stmt->inouts[1]
29901     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
29902     (emit-subx-call-operand *(ebp+8) %eax)
29903     # emit size of inouts
29904     (write-buffered *(ebp+8) Space)
29905     (addr-payload-size %eax *(ebp+0x10) *(ebp+0x14))  # => eax
29906     (write-int32-hex-buffered *(ebp+8) %eax)
29907     (write-buffered *(ebp+8) ")\n")
29908 $translate-mu-copy-object-stmt:end:
29909     # . restore registers
29910     58/pop-to-eax
29911     # . epilogue
29912     89/<- %esp 5/r32/ebp
29913     5d/pop-to-ebp
29914     c3/return
29915 
29916 translate-mu-clear-object-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29917     # . prologue
29918     55/push-ebp
29919     89/<- %ebp 4/r32/esp
29920     # . save registers
29921     50/push-eax
29922     #
29923     (emit-indent *(ebp+8) *Curr-block-depth)
29924     (write-buffered *(ebp+8) "(zero-out")
29925     # eax = stmt
29926     8b/-> *(ebp+0xc) 0/r32/eax
29927     # var dest/eax: (addr stmt-var) = stmt->inouts[0]
29928     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29929     #
29930     (emit-subx-call-operand *(ebp+8) %eax)
29931     (write-buffered *(ebp+8) Space)
29932     (addr-payload-size %eax *(ebp+0x10) *(ebp+0x14))  # => eax
29933     (write-int32-hex-buffered *(ebp+8) %eax)
29934     (write-buffered *(ebp+8) ")\n")
29935 $translate-mu-clear-object-stmt:end:
29936     # . restore registers
29937     58/pop-to-eax
29938     # . epilogue
29939     89/<- %esp 5/r32/ebp
29940     5d/pop-to-ebp
29941     c3/return
29942 
29943 translate-mu-allocate-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29944     # . prologue
29945     55/push-ebp
29946     89/<- %ebp 4/r32/esp
29947     # . save registers
29948     50/push-eax
29949     56/push-esi
29950     57/push-edi
29951     # esi = stmt
29952     8b/-> *(ebp+0xc) 6/r32/esi
29953     # var target/edi: (addr stmt-var) = stmt->inouts[0]
29954     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29955     89/<- %edi 0/r32/eax
29956     #
29957     (emit-indent *(ebp+8) *Curr-block-depth)
29958     (write-buffered *(ebp+8) "(allocate Heap ")
29959     (addr-handle-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
29960     (write-int32-hex-buffered *(ebp+8) %eax)
29961     (emit-subx-call-operand *(ebp+8) %edi)
29962     (write-buffered *(ebp+8) ")\n")
29963 $translate-mu-allocate-stmt:end:
29964     # . restore registers
29965     5f/pop-to-edi
29966     5e/pop-to-esi
29967     58/pop-to-eax
29968     # . epilogue
29969     89/<- %esp 5/r32/ebp
29970     5d/pop-to-ebp
29971     c3/return
29972 
29973 addr-handle-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
29974     # . prologue
29975     55/push-ebp
29976     89/<- %ebp 4/r32/esp
29977     # var t/eax: (addr type-tree) = s->value->type
29978     8b/-> *(ebp+8) 0/r32/eax
29979     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29980     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
29981     # TODO: check eax != 0
29982     # TODO: check !t->is-atom?
29983     # TODO: check t->left == addr
29984     # t = t->right
29985 $addr-handle-payload-size:skip-addr:
29986     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
29987     # TODO: check eax != 0
29988     # TODO: check !t->is-atom?
29989     # TODO: check t->left == handle
29990     # t = t->right
29991 $addr-handle-payload-size:skip-handle:
29992     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
29993     # TODO: check eax != 0
29994     # if !t->is-atom? t = t->left
29995     81 7/subop/compare *eax 0/imm32/false
29996     {
29997       75/jump-if-!= break/disp8
29998       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29999     }
30000     # TODO: check t->is-atom?
30001     # return size(t->value)
30002     (size-of-type-id *(eax+4))  # Type-tree-value => eax
30003 $addr-handle-payload-size:end:
30004     # . epilogue
30005     89/<- %esp 5/r32/ebp
30006     5d/pop-to-ebp
30007     c3/return
30008 
30009 addr-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
30010     # . prologue
30011     55/push-ebp
30012     89/<- %ebp 4/r32/esp
30013     # var t/eax: (addr type-tree) = s->value->type
30014     8b/-> *(ebp+8) 0/r32/eax
30015     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
30016     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
30017     # TODO: check eax != 0
30018     # TODO: check !t->is-atom?
30019     # TODO: check t->left == addr
30020     # t = t->right
30021 $addr-payload-size:skip-addr:
30022     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
30023     # TODO: check eax != 0
30024     # if !t->is-atom? t = t->left
30025     81 7/subop/compare *eax 0/imm32/false
30026     {
30027       75/jump-if-!= break/disp8
30028       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
30029     }
30030     # TODO: check t->is-atom?
30031     # return size(t->value)
30032     (size-of-type-id *(eax+4))  # Type-tree-value => eax
30033 $addr-payload-size:end:
30034     # . epilogue
30035     89/<- %esp 5/r32/ebp
30036     5d/pop-to-ebp
30037     c3/return
30038 
30039 translate-mu-populate-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
30040     # . prologue
30041     55/push-ebp
30042     89/<- %ebp 4/r32/esp
30043     # . save registers
30044     50/push-eax
30045     51/push-ecx
30046     56/push-esi
30047     57/push-edi
30048     # esi = stmt
30049     8b/-> *(ebp+0xc) 6/r32/esi
30050     # var target/edi: (addr stmt-var) = stmt->inouts[0]
30051     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
30052     89/<- %edi 0/r32/eax
30053     # var len/ecx: (addr stmt-var) = stmt->inouts[1]
30054     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
30055     89/<- %ecx 0/r32/eax
30056     #
30057     (emit-indent *(ebp+8) *Curr-block-depth)
30058     (write-buffered *(ebp+8) "(allocate-array2 Heap ")
30059     (addr-handle-array-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
30060     (write-int32-hex-buffered *(ebp+8) %eax)
30061     (emit-subx-call-operand *(ebp+8) %ecx)
30062     (emit-subx-call-operand *(ebp+8) %edi)
30063     (write-buffered *(ebp+8) ")\n")
30064 $translate-mu-populate-stmt:end:
30065     # . restore registers
30066     5f/pop-to-edi
30067     5e/pop-to-esi
30068     59/pop-to-ecx
30069     58/pop-to-eax
30070     # . epilogue
30071     89/<- %esp 5/r32/ebp
30072     5d/pop-to-ebp
30073     c3/return
30074 
30075 translate-mu-populate-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
30076     # . prologue
30077     55/push-ebp
30078     89/<- %ebp 4/r32/esp
30079     # . save registers
30080     50/push-eax
30081     51/push-ecx
30082     56/push-esi
30083     57/push-edi
30084     # esi = stmt
30085     8b/-> *(ebp+0xc) 6/r32/esi
30086     # var target/edi: (addr stmt-var) = stmt->inouts[0]
30087     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
30088     89/<- %edi 0/r32/eax
30089     # var len/ecx: (addr stmt-var) = stmt->inouts[1]
30090     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
30091     89/<- %ecx 0/r32/eax
30092     #
30093     (emit-indent *(ebp+8) *Curr-block-depth)
30094     (write-buffered *(ebp+8) "(new-stream Heap ")
30095     (addr-handle-stream-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
30096     (write-int32-hex-buffered *(ebp+8) %eax)
30097     (emit-subx-call-operand *(ebp+8) %ecx)
30098     (emit-subx-call-operand *(ebp+8) %edi)
30099     (write-buffered *(ebp+8) ")\n")
30100 $translate-mu-populate-stream-stmt:end:
30101     # . restore registers
30102     5f/pop-to-edi
30103     5e/pop-to-esi
30104     59/pop-to-ecx
30105     58/pop-to-eax
30106     # . epilogue
30107     89/<- %esp 5/r32/ebp
30108     5d/pop-to-ebp
30109     c3/return
30110 
30111 translate-mu-read-from-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
30112     # . prologue
30113     55/push-ebp
30114     89/<- %ebp 4/r32/esp
30115     # . save registers
30116     50/push-eax
30117     51/push-ecx
30118     56/push-esi
30119     57/push-edi
30120     # esi = stmt
30121     8b/-> *(ebp+0xc) 6/r32/esi
30122     # var stream/ecx: (addr stmt-var) = stmt->inouts[0]
30123     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
30124     89/<- %ecx 0/r32/eax
30125     # var target/edi: (addr stmt-var) = stmt->inouts[1]
30126     (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
30127     89/<- %edi 0/r32/eax
30128     #
30129     (emit-indent *(ebp+8) *Curr-block-depth)
30130     (write-buffered *(ebp+8) "(read-from-stream")
30131     (emit-subx-call-operand *(ebp+8) %ecx)
30132     (emit-subx-call-operand *(ebp+8) %edi)
30133     (write-buffered *(ebp+8) Space)
30134     (addr-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
30135     (write-int32-hex-buffered *(ebp+8) %eax)
30136     (write-buffered *(ebp+8) ")\n")
30137 $translate-mu-read-from-stream-stmt:end:
30138     # . restore registers
30139     5f/pop-to-edi
30140     5e/pop-to-esi
30141     59/pop-to-ecx
30142     58/pop-to-eax
30143     # . epilogue
30144     89/<- %esp 5/r32/ebp
30145     5d/pop-to-ebp
30146     c3/return
30147 
30148 translate-mu-write-to-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
30149     # . prologue
30150     55/push-ebp
30151     89/<- %ebp 4/r32/esp
30152     # . save registers
30153     50/push-eax
30154     51/push-ecx
30155     56/push-esi
30156     57/push-edi
30157     # esi = stmt
30158     8b/-> *(ebp+0xc) 6/r32/esi
30159     # var stream/ecx: (addr stmt-var) = stmt->inouts[0]
30160     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
30161     89/<- %ecx 0/r32/eax
30162     # var target/edi: (addr stmt-var) = stmt->inouts[1]
30163     (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
30164     89/<- %edi 0/r32/eax
30165     #
30166     (emit-indent *(ebp+8) *Curr-block-depth)
30167     (write-buffered *(ebp+8) "(write-to-stream")
30168     (emit-subx-call-operand *(ebp+8) %ecx)
30169     (flush *(ebp+8))
30170     (emit-subx-call-operand *(ebp+8) %edi)
30171     (flush *(ebp+8))
30172     (write-buffered *(ebp+8) Space)
30173     (flush *(ebp+8))
30174     (addr-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
30175     (write-int32-hex-buffered *(ebp+8) %eax)
30176     (write-buffered *(ebp+8) ")\n")
30177 $translate-mu-write-to-stream-stmt:end:
30178     # . restore registers
30179     5f/pop-to-edi
30180     5e/pop-to-esi
30181     59/pop-to-ecx
30182     58/pop-to-eax
30183     # . epilogue
30184     89/<- %esp 5/r32/ebp
30185     5d/pop-to-ebp
30186     c3/return
30187 
30188 addr-handle-array-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
30189     # . prologue
30190     55/push-ebp
30191     89/<- %ebp 4/r32/esp
30192     # var t/eax: (addr type-tree) = s->value->type
30193     8b/-> *(ebp+8) 0/r32/eax
30194     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
30195     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
30196     # TODO: check eax != 0
30197     # TODO: check !t->is-atom?
30198     # TODO: check t->left == addr
30199     # t = t->right
30200 $addr-handle-array-payload-size:skip-addr:
30201     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
30202     # TODO: check eax != 0
30203     # TODO: check !t->is-atom?
30204     # TODO: check t->left == handle
30205     # t = t->right
30206 $addr-handle-array-payload-size:skip-handle:
30207     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
30208     # TODO: check eax != 0
30209     # TODO: check !t->is-atom?
30210     # TODO: check t->left == array
30211     # t = t->right
30212 $addr-handle-array-payload-size:skip-array:
30213     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
30214     # TODO: check eax != 0
30215     # if !t->is-atom? t = t->left
30216     81 7/subop/compare *eax 0/imm32/false
30217     {
30218       75/jump-if-!= break/disp8
30219       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
30220     }
30221 $addr-handle-array-payload-size:compute-size:
30222     # TODO: check t->is-atom?
30223     # return size(t->value)
30224     (size-of-type-id-as-array-element *(eax+4))  # Type-tree-value => eax
30225 $addr-handle-array-payload-size:end:
30226     # . epilogue
30227     89/<- %esp 5/r32/ebp
30228     5d/pop-to-ebp
30229     c3/return
30230 
30231 addr-handle-stream-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
30232     # . prologue
30233     55/push-ebp
30234     89/<- %ebp 4/r32/esp
30235     # var t/eax: (addr type-tree) = s->value->type
30236     8b/-> *(ebp+8) 0/r32/eax
30237     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
30238     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
30239     # TODO: check eax != 0
30240     # TODO: check !t->is-atom?
30241     # TODO: check t->left == addr
30242     # t = t->right
30243 $addr-handle-stream-payload-size:skip-addr:
30244     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
30245     # TODO: check eax != 0
30246     # TODO: check !t->is-atom?
30247     # TODO: check t->left == handle
30248     # t = t->right
30249 $addr-handle-stream-payload-size:skip-handle:
30250     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
30251     # TODO: check eax != 0
30252     # TODO: check !t->is-atom?
30253     # TODO: check t->left == stream
30254     # t = t->right
30255 $addr-handle-stream-payload-size:skip-stream:
30256     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
30257     # TODO: check eax != 0
30258     # if !t->is-atom? t = t->left
30259     81 7/subop/compare *eax 0/imm32/false
30260     {
30261       75/jump-if-!= break/disp8
30262       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
30263     }
30264 $addr-handle-stream-payload-size:compute-size:
30265     # TODO: check t->is-atom?
30266     # return size(t->value)
30267     (size-of-type-id-as-array-element *(eax+4))  # Type-tree-value => eax
30268 $addr-handle-stream-payload-size:end:
30269     # . epilogue
30270     89/<- %esp 5/r32/ebp
30271     5d/pop-to-ebp
30272     c3/return
30273 
30274 power-of-2?:  # n: int, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: boolean
30275     # precondition: n is positive
30276     # . prologue
30277     55/push-ebp
30278     89/<- %ebp 4/r32/esp
30279     # eax = n
30280     8b/-> *(ebp+8) 0/r32/eax
30281     # if (n < 0) abort
30282     3d/compare-eax-with 0/imm32
30283     0f 8c/jump-if-< $power-of-2?:abort/disp32
30284     # var tmp/eax: int = n-1
30285     48/decrement-eax
30286     # var tmp2/eax: int = n & tmp
30287     23/and-> *(ebp+8) 0/r32/eax
30288     # return (tmp2 == 0)
30289     3d/compare-eax-and 0/imm32
30290     0f 94/set-byte-if-= %al
30291     25/and-eax-with 0xff/imm32
30292 $power-of-2?:end:
30293     # . epilogue
30294     89/<- %esp 5/r32/ebp
30295     5d/pop-to-ebp
30296     c3/return
30297 
30298 $power-of-2?:abort:
30299     (write-buffered *(ebp+0xc) "power-of-2?: negative number\n")
30300     (flush *(ebp+0xc))
30301     (stop *(ebp+0x10) 1)
30302     # never gets here
30303 
30304 num-shift-rights:  # n: int -> result/eax: int
30305     # precondition: n is a positive power of 2
30306     # . prologue
30307     55/push-ebp
30308     89/<- %ebp 4/r32/esp
30309     # . save registers
30310     51/push-ecx
30311     # var curr/ecx: int = n
30312     8b/-> *(ebp+8) 1/r32/ecx
30313     # result = 0
30314     b8/copy-to-eax 0/imm32
30315     {
30316       # if (curr <= 1) break
30317       81 7/subop/compare %ecx 1/imm32
30318       7e/jump-if-<= break/disp8
30319       40/increment-eax
30320       c1/shift 5/subop/arithmetic-right %ecx 1/imm8
30321       eb/jump loop/disp8
30322     }
30323 $num-shift-rights:end:
30324     # . restore registers
30325     59/pop-to-ecx
30326     # . epilogue
30327     89/<- %esp 5/r32/ebp
30328     5d/pop-to-ebp
30329     c3/return
30330 
30331 mu-get-offset:  # stmt: (addr stmt) -> result/eax: int
30332     # . prologue
30333     55/push-ebp
30334     89/<- %ebp 4/r32/esp
30335     # var second-inout/eax: (addr stmt-var) = stmt->inouts->next
30336     8b/-> *(ebp+8) 0/r32/eax
30337     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
30338     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
30339     # var output-var/eax: (addr var) = second-inout->value
30340     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
30341 #?     (write-buffered Stderr "mu-get-offset: ")
30342 #?     (write-int32-hex-buffered Stderr %eax)
30343 #?     (write-buffered Stderr " name: ")
30344 #?     50/push-eax
30345 #?     (lookup *eax *(eax+4))  # Var-name
30346 #?     (write-buffered Stderr %eax)
30347 #?     58/pop-to-eax
30348 #?     (write-buffered Stderr Newline)
30349 #?     (flush Stderr)
30350     # return output-var->stack-offset
30351     8b/-> *(eax+0x14) 0/r32/eax  # Var-offset
30352 #?     (write-buffered Stderr "=> ")
30353 #?     (write-int32-hex-buffered Stderr %eax)
30354 #?     (write-buffered Stderr Newline)
30355 #?     (flush Stderr)
30356 $emit-get-offset:end:
30357     # . epilogue
30358     89/<- %esp 5/r32/ebp
30359     5d/pop-to-ebp
30360     c3/return
30361 
30362 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)
30363     # . prologue
30364     55/push-ebp
30365     89/<- %ebp 4/r32/esp
30366     # . save registers
30367     50/push-eax
30368     51/push-ecx
30369     56/push-esi
30370     # esi = block
30371     8b/-> *(ebp+0xc) 6/r32/esi
30372     # block->var->block-depth = *Curr-block-depth
30373     (lookup *(esi+0xc) *(esi+0x10))  # Block-var Block-var => eax
30374     8b/-> *Curr-block-depth 1/r32/ecx
30375     89/<- *(eax+0x10) 1/r32/ecx  # Var-block-depth
30376     # var stmts/eax: (addr list stmt) = lookup(block->statements)
30377     (lookup *(esi+4) *(esi+8))  # Block-stmts Block-stmts => eax
30378     #
30379     {
30380 $emit-subx-block:check-empty:
30381       3d/compare-eax-and 0/imm32
30382       0f 84/jump-if-= break/disp32
30383       (emit-indent *(ebp+8) *Curr-block-depth)
30384       (write-buffered *(ebp+8) "{\n")
30385       # var v/ecx: (addr var) = lookup(block->var)
30386       (lookup *(esi+0xc) *(esi+0x10))  # Block-var Block-var => eax
30387       89/<- %ecx 0/r32/eax
30388       #
30389       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
30390       (write-buffered *(ebp+8) %eax)
30391       (write-buffered *(ebp+8) ":loop:\n")
30392       ff 0/subop/increment *Curr-block-depth
30393       (push *(ebp+0x10) *(esi+0xc))  # Block-var
30394       (push *(ebp+0x10) *(esi+0x10))  # Block-var
30395       (push *(ebp+0x10) 0)  # false
30396       # emit block->statements
30397       (lookup *(esi+4) *(esi+8))  # Block-stmts Block-stmts => eax
30398       (emit-subx-stmt-list *(ebp+8) %eax *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
30399       (pop *(ebp+0x10))  # => eax
30400       (pop *(ebp+0x10))  # => eax
30401       (pop *(ebp+0x10))  # => eax
30402       ff 1/subop/decrement *Curr-block-depth
30403       (emit-indent *(ebp+8) *Curr-block-depth)
30404       (write-buffered *(ebp+8) "}\n")
30405       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
30406       (write-buffered *(ebp+8) %eax)
30407       (write-buffered *(ebp+8) ":break:\n")
30408     }
30409 $emit-subx-block:end:
30410     # . restore registers
30411     5e/pop-to-esi
30412     59/pop-to-ecx
30413     58/pop-to-eax
30414     # . epilogue
30415     89/<- %esp 5/r32/ebp
30416     5d/pop-to-ebp
30417     c3/return
30418 
30419 # Primitives supported
30420 # See mu_instructions for a summary of this linked-list data structure.
30421 #
30422 # For each operation, put variants with hard-coded registers before flexible ones.
30423 #
30424 # Unfortunately, our restrictions on addresses require that various fields in
30425 # primitives be handles, which complicates these definitions.
30426 #   - we need to insert dummy fields all over the place for fake alloc-ids
30427 #   - we can't use our syntax sugar of quoted literals for string fields
30428 #
30429 # Fake alloc-ids are needed because our type definitions up top require
30430 # handles but it's clearer to statically allocate these long-lived objects.
30431 # Fake alloc-ids are perfectly safe, but they can't be reclaimed.
30432 #
30433 # Every 'object' below starts with a fake alloc-id. It may also contain other
30434 # fake alloc-ids for various handle fields.
30435 #
30436 # I think of objects starting with a fake alloc-id as having type 'payload'.
30437 # It's not really intended to be created dynamically; for that use `allocate`
30438 # as usual.
30439 #
30440 # Idea for a notation to simplify such definitions:
30441 #   _Primitive-increment-eax:  # (payload primitive)
30442 #     0x11/alloc-id:fake:payload
30443 #     0x11 @(0x11 "increment")  # name
30444 #     0 0                       # inouts
30445 #     0x11 @(0x11/payload
30446 #            0x11 @(0x11/payload  # List-value
30447 #                   0 0             # Var-name
30448 #                   0x11 @(0x11     # Var-type
30449 #                          1/is-atom
30450 #                          1/value 0/unused   # Type-tree-left
30451 #                          0 0                # Type-tree-right
30452 #                         )
30453 #                   1               # block-depth
30454 #                   0               # stack-offset
30455 #                   0x11 @(0x11 "eax")  # Var-register
30456 #                  )
30457 #            0 0)                 # List-next
30458 #     ...
30459 #     _Primitive-increment-ecx/imm32/next
30460 #   ...
30461 # Awfully complex and non-obvious. But also clearly signals there's something
30462 # to learn here, so may be worth trying.
30463 #
30464 # '@' is just an initial thought. Punctuation used so far in Mu: () * % # / "
30465 #
30466 # For now we'll continue to just use comments and manually ensure they stay up
30467 # to date.
30468 == data
30469 Primitives:  # (addr primitive)
30470 # - increment/decrement
30471 _Primitive-increment-eax:  # (addr primitive)
30472     # var/eax <- increment => 40/increment-eax
30473     0x11/imm32/alloc-id:fake
30474     _string-increment/imm32/name
30475     0/imm32/no-inouts
30476     0/imm32/no-inouts
30477     0x11/imm32/alloc-id:fake
30478     Single-int-var-in-eax/imm32/outputs
30479     0x11/imm32/alloc-id:fake
30480     _string_40_increment_eax/imm32/subx-name
30481     0/imm32/no-rm32
30482     0/imm32/no-r32
30483     0/imm32/no-imm32
30484     0/imm32/no-imm8
30485     0/imm32/no-disp32
30486     0/imm32/no-xm32
30487     0/imm32/no-x32
30488     0x11/imm32/alloc-id:fake
30489     _Primitive-increment-ecx/imm32/next
30490 _Primitive-increment-ecx:  # (payload primitive)
30491     0x11/imm32/alloc-id:fake:payload
30492     # var/ecx <- increment => 41/increment-ecx
30493     0x11/imm32/alloc-id:fake
30494     _string-increment/imm32/name
30495     0/imm32/no-inouts
30496     0/imm32/no-inouts
30497     0x11/imm32/alloc-id:fake
30498     Single-int-var-in-ecx/imm32/outputs
30499     0x11/imm32/alloc-id:fake
30500     _string_41_increment_ecx/imm32/subx-name
30501     0/imm32/no-rm32
30502     0/imm32/no-r32
30503     0/imm32/no-imm32
30504     0/imm32/no-imm8
30505     0/imm32/no-disp32
30506     0/imm32/no-xm32
30507     0/imm32/no-x32
30508     0x11/imm32/alloc-id:fake
30509     _Primitive-increment-edx/imm32/next
30510 _Primitive-increment-edx:  # (payload primitive)
30511     0x11/imm32/alloc-id:fake:payload
30512     # var/edx <- increment => 42/increment-edx
30513     0x11/imm32/alloc-id:fake
30514     _string-increment/imm32/name
30515     0/imm32/no-inouts
30516     0/imm32/no-inouts
30517     0x11/imm32/alloc-id:fake
30518     Single-int-var-in-edx/imm32/outputs
30519     0x11/imm32/alloc-id:fake
30520     _string_42_increment_edx/imm32/subx-name
30521     0/imm32/no-rm32
30522     0/imm32/no-r32
30523     0/imm32/no-imm32
30524     0/imm32/no-imm8
30525     0/imm32/no-disp32
30526     0/imm32/no-xm32
30527     0/imm32/no-x32
30528     0x11/imm32/alloc-id:fake
30529     _Primitive-increment-ebx/imm32/next
30530 _Primitive-increment-ebx:  # (payload primitive)
30531     0x11/imm32/alloc-id:fake:payload
30532     # var/ebx <- increment => 43/increment-ebx
30533     0x11/imm32/alloc-id:fake
30534     _string-increment/imm32/name
30535     0/imm32/no-inouts
30536     0/imm32/no-inouts
30537     0x11/imm32/alloc-id:fake
30538     Single-int-var-in-ebx/imm32/outputs
30539     0x11/imm32/alloc-id:fake
30540     _string_43_increment_ebx/imm32/subx-name
30541     0/imm32/no-rm32
30542     0/imm32/no-r32
30543     0/imm32/no-imm32
30544     0/imm32/no-imm8
30545     0/imm32/no-disp32
30546     0/imm32/no-xm32
30547     0/imm32/no-x32
30548     0x11/imm32/alloc-id:fake
30549     _Primitive-increment-esi/imm32/next
30550 _Primitive-increment-esi:  # (payload primitive)
30551     0x11/imm32/alloc-id:fake:payload
30552     # var/esi <- increment => 46/increment-esi
30553     0x11/imm32/alloc-id:fake
30554     _string-increment/imm32/name
30555     0/imm32/no-inouts
30556     0/imm32/no-inouts
30557     0x11/imm32/alloc-id:fake
30558     Single-int-var-in-esi/imm32/outputs
30559     0x11/imm32/alloc-id:fake
30560     _string_46_increment_esi/imm32/subx-name
30561     0/imm32/no-rm32
30562     0/imm32/no-r32
30563     0/imm32/no-imm32
30564     0/imm32/no-imm8
30565     0/imm32/no-disp32
30566     0/imm32/no-xm32
30567     0/imm32/no-x32
30568     0x11/imm32/alloc-id:fake
30569     _Primitive-increment-edi/imm32/next
30570 _Primitive-increment-edi:  # (payload primitive)
30571     0x11/imm32/alloc-id:fake:payload
30572     # var/edi <- increment => 47/increment-edi
30573     0x11/imm32/alloc-id:fake
30574     _string-increment/imm32/name
30575     0/imm32/no-inouts
30576     0/imm32/no-inouts
30577     0x11/imm32/alloc-id:fake
30578     Single-int-var-in-edi/imm32/outputs
30579     0x11/imm32/alloc-id:fake
30580     _string_47_increment_edi/imm32/subx-name
30581     0/imm32/no-rm32
30582     0/imm32/no-r32
30583     0/imm32/no-imm32
30584     0/imm32/no-imm8
30585     0/imm32/no-disp32
30586     0/imm32/no-xm32
30587     0/imm32/no-x32
30588     0x11/imm32/alloc-id:fake
30589     _Primitive-decrement-eax/imm32/next
30590 _Primitive-decrement-eax:  # (payload primitive)
30591     0x11/imm32/alloc-id:fake:payload
30592     # var/eax <- decrement => 48/decrement-eax
30593     0x11/imm32/alloc-id:fake
30594     _string-decrement/imm32/name
30595     0/imm32/no-inouts
30596     0/imm32/no-inouts
30597     0x11/imm32/alloc-id:fake
30598     Single-int-var-in-eax/imm32/outputs
30599     0x11/imm32/alloc-id:fake
30600     _string_48_decrement_eax/imm32/subx-name
30601     0/imm32/no-rm32
30602     0/imm32/no-r32
30603     0/imm32/no-imm32
30604     0/imm32/no-imm8
30605     0/imm32/no-disp32
30606     0/imm32/no-xm32
30607     0/imm32/no-x32
30608     0x11/imm32/alloc-id:fake
30609     _Primitive-decrement-ecx/imm32/next
30610 _Primitive-decrement-ecx:  # (payload primitive)
30611     0x11/imm32/alloc-id:fake:payload
30612     # var/ecx <- decrement => 49/decrement-ecx
30613     0x11/imm32/alloc-id:fake
30614     _string-decrement/imm32/name
30615     0/imm32/no-inouts
30616     0/imm32/no-inouts
30617     0x11/imm32/alloc-id:fake
30618     Single-int-var-in-ecx/imm32/outputs
30619     0x11/imm32/alloc-id:fake
30620     _string_49_decrement_ecx/imm32/subx-name
30621     0/imm32/no-rm32
30622     0/imm32/no-r32
30623     0/imm32/no-imm32
30624     0/imm32/no-imm8
30625     0/imm32/no-disp32
30626     0/imm32/no-xm32
30627     0/imm32/no-x32
30628     0x11/imm32/alloc-id:fake
30629     _Primitive-decrement-edx/imm32/next
30630 _Primitive-decrement-edx:  # (payload primitive)
30631     0x11/imm32/alloc-id:fake:payload
30632     # var/edx <- decrement => 4a/decrement-edx
30633     0x11/imm32/alloc-id:fake
30634     _string-decrement/imm32/name
30635     0/imm32/no-inouts
30636     0/imm32/no-inouts
30637     0x11/imm32/alloc-id:fake
30638     Single-int-var-in-edx/imm32/outputs
30639     0x11/imm32/alloc-id:fake
30640     _string_4a_decrement_edx/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     0/imm32/no-xm32
30647     0/imm32/no-x32
30648     0x11/imm32/alloc-id:fake
30649     _Primitive-decrement-ebx/imm32/next
30650 _Primitive-decrement-ebx:  # (payload primitive)
30651     0x11/imm32/alloc-id:fake:payload
30652     # var/ebx <- decrement => 4b/decrement-ebx
30653     0x11/imm32/alloc-id:fake
30654     _string-decrement/imm32/name
30655     0/imm32/no-inouts
30656     0/imm32/no-inouts
30657     0x11/imm32/alloc-id:fake
30658     Single-int-var-in-ebx/imm32/outputs
30659     0x11/imm32/alloc-id:fake
30660     _string_4b_decrement_ebx/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     0/imm32/no-xm32
30667     0/imm32/no-x32
30668     0x11/imm32/alloc-id:fake
30669     _Primitive-decrement-esi/imm32/next
30670 _Primitive-decrement-esi:  # (payload primitive)
30671     0x11/imm32/alloc-id:fake:payload
30672     # var/esi <- decrement => 4e/decrement-esi
30673     0x11/imm32/alloc-id:fake
30674     _string-decrement/imm32/name
30675     0/imm32/no-inouts
30676     0/imm32/no-inouts
30677     0x11/imm32/alloc-id:fake
30678     Single-int-var-in-esi/imm32/outputs
30679     0x11/imm32/alloc-id:fake
30680     _string_4e_decrement_esi/imm32/subx-name
30681     0/imm32/no-rm32
30682     0/imm32/no-r32
30683     0/imm32/no-imm32
30684     0/imm32/no-imm8
30685     0/imm32/no-disp32
30686     0/imm32/no-xm32
30687     0/imm32/no-x32
30688     0x11/imm32/alloc-id:fake
30689     _Primitive-decrement-edi/imm32/next
30690 _Primitive-decrement-edi:  # (payload primitive)
30691     0x11/imm32/alloc-id:fake:payload
30692     # var/edi <- decrement => 4f/decrement-edi
30693     0x11/imm32/alloc-id:fake
30694     _string-decrement/imm32/name
30695     0/imm32/no-inouts
30696     0/imm32/no-inouts
30697     0x11/imm32/alloc-id:fake
30698     Single-int-var-in-edi/imm32/outputs
30699     0x11/imm32/alloc-id:fake
30700     _string_4f_decrement_edi/imm32/subx-name
30701     0/imm32/no-rm32
30702     0/imm32/no-r32
30703     0/imm32/no-imm32
30704     0/imm32/no-imm8
30705     0/imm32/no-disp32
30706     0/imm32/no-xm32
30707     0/imm32/no-x32
30708     0x11/imm32/alloc-id:fake
30709     _Primitive-increment-mem/imm32/next
30710 _Primitive-increment-mem:  # (payload primitive)
30711     0x11/imm32/alloc-id:fake:payload
30712     # increment var => ff 0/subop/increment *(ebp+__)
30713     0x11/imm32/alloc-id:fake
30714     _string-increment/imm32/name
30715     0x11/imm32/alloc-id:fake
30716     Single-int-var-in-mem/imm32/inouts
30717     0/imm32/no-outputs
30718     0/imm32/no-outputs
30719     0x11/imm32/alloc-id:fake
30720     _string_ff_subop_increment/imm32/subx-name
30721     1/imm32/rm32-is-first-inout
30722     0/imm32/no-r32
30723     0/imm32/no-imm32
30724     0/imm32/no-imm8
30725     0/imm32/no-disp32
30726     0/imm32/no-xm32
30727     0/imm32/no-x32
30728     0x11/imm32/alloc-id:fake
30729     _Primitive-increment-reg/imm32/next
30730 _Primitive-increment-reg:  # (payload primitive)
30731     0x11/imm32/alloc-id:fake:payload
30732     # var/reg <- increment => ff 0/subop/increment %__
30733     0x11/imm32/alloc-id:fake
30734     _string-increment/imm32/name
30735     0/imm32/no-inouts
30736     0/imm32/no-inouts
30737     0x11/imm32/alloc-id:fake
30738     Single-int-var-in-some-register/imm32/outputs
30739     0x11/imm32/alloc-id:fake
30740     _string_ff_subop_increment/imm32/subx-name
30741     3/imm32/rm32-is-first-output
30742     0/imm32/no-r32
30743     0/imm32/no-imm32
30744     0/imm32/no-imm8
30745     0/imm32/no-disp32
30746     0/imm32/no-xm32
30747     0/imm32/no-x32
30748     0x11/imm32/alloc-id:fake
30749     _Primitive-decrement-mem/imm32/next
30750 _Primitive-decrement-mem:  # (payload primitive)
30751     0x11/imm32/alloc-id:fake:payload
30752     # decrement var => ff 1/subop/decrement *(ebp+__)
30753     0x11/imm32/alloc-id:fake
30754     _string-decrement/imm32/name
30755     0x11/imm32/alloc-id:fake
30756     Single-int-var-in-mem/imm32/inouts
30757     0/imm32/no-outputs
30758     0/imm32/no-outputs
30759     0x11/imm32/alloc-id:fake
30760     _string_ff_subop_decrement/imm32/subx-name
30761     1/imm32/rm32-is-first-inout
30762     0/imm32/no-r32
30763     0/imm32/no-imm32
30764     0/imm32/no-imm8
30765     0/imm32/no-disp32
30766     0/imm32/no-xm32
30767     0/imm32/no-x32
30768     0x11/imm32/alloc-id:fake
30769     _Primitive-decrement-reg/imm32/next
30770 _Primitive-decrement-reg:  # (payload primitive)
30771     0x11/imm32/alloc-id:fake:payload
30772     # var/reg <- decrement => ff 1/subop/decrement %__
30773     0x11/imm32/alloc-id:fake
30774     _string-decrement/imm32/name
30775     0/imm32/no-inouts
30776     0/imm32/no-inouts
30777     0x11/imm32/alloc-id:fake
30778     Single-int-var-in-some-register/imm32/outputs
30779     0x11/imm32/alloc-id:fake
30780     _string_ff_subop_decrement/imm32/subx-name
30781     3/imm32/rm32-is-first-output
30782     0/imm32/no-r32
30783     0/imm32/no-imm32
30784     0/imm32/no-imm8
30785     0/imm32/no-disp32
30786     0/imm32/no-xm32
30787     0/imm32/no-x32
30788     0x11/imm32/alloc-id:fake
30789     _Primitive-add-to-eax/imm32/next
30790 # - add
30791 _Primitive-add-to-eax:  # (payload primitive)
30792     0x11/imm32/alloc-id:fake:payload
30793     # var/eax <- add lit => 05/add-to-eax lit/imm32
30794     0x11/imm32/alloc-id:fake
30795     _string-add/imm32/name
30796     0x11/imm32/alloc-id:fake
30797     Single-lit-var/imm32/inouts
30798     0x11/imm32/alloc-id:fake
30799     Single-int-var-in-eax/imm32/outputs
30800     0x11/imm32/alloc-id:fake
30801     _string_05_add_to_eax/imm32/subx-name
30802     0/imm32/no-rm32
30803     0/imm32/no-r32
30804     1/imm32/imm32-is-first-inout
30805     0/imm32/no-imm8
30806     0/imm32/no-disp32
30807     0/imm32/no-xm32
30808     0/imm32/no-x32
30809     0x11/imm32/alloc-id:fake
30810     _Primitive-add-reg-to-reg/imm32/next
30811 _Primitive-add-reg-to-reg:  # (payload primitive)
30812     0x11/imm32/alloc-id:fake:payload
30813     # var1/reg <- add var2/reg => 01/add-to var1/rm32 var2/r32
30814     0x11/imm32/alloc-id:fake
30815     _string-add/imm32/name
30816     0x11/imm32/alloc-id:fake
30817     Single-int-var-in-some-register/imm32/inouts
30818     0x11/imm32/alloc-id:fake
30819     Single-int-var-in-some-register/imm32/outputs
30820     0x11/imm32/alloc-id:fake
30821     _string_01_add_to/imm32/subx-name
30822     3/imm32/rm32-is-first-output
30823     1/imm32/r32-is-first-inout
30824     0/imm32/no-imm32
30825     0/imm32/no-imm8
30826     0/imm32/no-disp32
30827     0/imm32/no-xm32
30828     0/imm32/no-x32
30829     0x11/imm32/alloc-id:fake
30830     _Primitive-add-reg-to-mem/imm32/next
30831 _Primitive-add-reg-to-mem:  # (payload primitive)
30832     0x11/imm32/alloc-id:fake:payload
30833     # add-to var1 var2/reg => 01/add-to var1 var2/r32
30834     0x11/imm32/alloc-id:fake
30835     _string-add-to/imm32/name
30836     0x11/imm32/alloc-id:fake
30837     Two-args-int-stack-int-reg/imm32/inouts
30838     0/imm32/no-outputs
30839     0/imm32/no-outputs
30840     0x11/imm32/alloc-id:fake
30841     _string_01_add_to/imm32/subx-name
30842     1/imm32/rm32-is-first-inout
30843     2/imm32/r32-is-second-inout
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-add-mem-to-reg/imm32/next
30851 _Primitive-add-mem-to-reg:  # (payload primitive)
30852     0x11/imm32/alloc-id:fake:payload
30853     # var1/reg <- add var2 => 03/add var2/rm32 var1/r32
30854     0x11/imm32/alloc-id:fake
30855     _string-add/imm32/name
30856     0x11/imm32/alloc-id:fake
30857     Single-int-var-in-mem/imm32/inouts
30858     0x11/imm32/alloc-id:fake
30859     Single-int-var-in-some-register/imm32/outputs
30860     0x11/imm32/alloc-id:fake
30861     _string_03_add/imm32/subx-name
30862     1/imm32/rm32-is-first-inout
30863     3/imm32/r32-is-first-output
30864     0/imm32/no-imm32
30865     0/imm32/no-imm8
30866     0/imm32/no-disp32
30867     0/imm32/no-xm32
30868     0/imm32/no-x32
30869     0x11/imm32/alloc-id:fake
30870     _Primitive-add-lit-to-reg/imm32/next
30871 _Primitive-add-lit-to-reg:  # (payload primitive)
30872     0x11/imm32/alloc-id:fake:payload
30873     # var1/reg <- add lit => 81 0/subop/add var1/rm32 lit/imm32
30874     0x11/imm32/alloc-id:fake
30875     _string-add/imm32/name
30876     0x11/imm32/alloc-id:fake
30877     Single-lit-var/imm32/inouts
30878     0x11/imm32/alloc-id:fake
30879     Single-int-var-in-some-register/imm32/outputs
30880     0x11/imm32/alloc-id:fake
30881     _string_81_subop_add/imm32/subx-name
30882     3/imm32/rm32-is-first-output
30883     0/imm32/no-r32
30884     1/imm32/imm32-is-first-inout
30885     0/imm32/no-imm8
30886     0/imm32/no-disp32
30887     0/imm32/no-xm32
30888     0/imm32/no-x32
30889     0x11/imm32/alloc-id:fake
30890     _Primitive-add-lit-to-mem/imm32/next
30891 _Primitive-add-lit-to-mem:  # (payload primitive)
30892     0x11/imm32/alloc-id:fake:payload
30893     # add-to var1, lit => 81 0/subop/add var1/rm32 lit/imm32
30894     0x11/imm32/alloc-id:fake
30895     _string-add-to/imm32/name
30896     0x11/imm32/alloc-id:fake
30897     Int-var-and-literal/imm32/inouts
30898     0/imm32/no-outputs
30899     0/imm32/no-outputs
30900     0x11/imm32/alloc-id:fake
30901     _string_81_subop_add/imm32/subx-name
30902     1/imm32/rm32-is-first-inout
30903     0/imm32/no-r32
30904     2/imm32/imm32-is-second-inout
30905     0/imm32/no-imm8
30906     0/imm32/no-disp32
30907     0/imm32/no-xm32
30908     0/imm32/no-x32
30909     0x11/imm32/alloc-id:fake
30910     _Primitive-subtract-from-eax/imm32/next
30911 # - subtract
30912 _Primitive-subtract-from-eax:  # (payload primitive)
30913     0x11/imm32/alloc-id:fake:payload
30914     # var/eax <- subtract lit => 2d/subtract-from-eax lit/imm32
30915     0x11/imm32/alloc-id:fake
30916     _string-subtract/imm32/name
30917     0x11/imm32/alloc-id:fake
30918     Single-lit-var/imm32/inouts
30919     0x11/imm32/alloc-id:fake
30920     Single-int-var-in-eax/imm32/outputs
30921     0x11/imm32/alloc-id:fake
30922     _string_2d_subtract_from_eax/imm32/subx-name
30923     0/imm32/no-rm32
30924     0/imm32/no-r32
30925     1/imm32/imm32-is-first-inout
30926     0/imm32/no-imm8
30927     0/imm32/no-disp32
30928     0/imm32/no-xm32
30929     0/imm32/no-x32
30930     0x11/imm32/alloc-id:fake
30931     _Primitive-subtract-reg-from-reg/imm32/next
30932 _Primitive-subtract-reg-from-reg:  # (payload primitive)
30933     0x11/imm32/alloc-id:fake:payload
30934     # var1/reg <- subtract var2/reg => 29/subtract-from var1/rm32 var2/r32
30935     0x11/imm32/alloc-id:fake
30936     _string-subtract/imm32/name
30937     0x11/imm32/alloc-id:fake
30938     Single-int-var-in-some-register/imm32/inouts
30939     0x11/imm32/alloc-id:fake
30940     Single-int-var-in-some-register/imm32/outputs
30941     0x11/imm32/alloc-id:fake
30942     _string_29_subtract_from/imm32/subx-name
30943     3/imm32/rm32-is-first-output
30944     1/imm32/r32-is-first-inout
30945     0/imm32/no-imm32
30946     0/imm32/no-imm8
30947     0/imm32/no-disp32
30948     0/imm32/no-xm32
30949     0/imm32/no-x32
30950     0x11/imm32/alloc-id:fake
30951     _Primitive-subtract-reg-from-mem/imm32/next
30952 _Primitive-subtract-reg-from-mem:  # (payload primitive)
30953     0x11/imm32/alloc-id:fake:payload
30954     # subtract-from var1 var2/reg => 29/subtract-from var1 var2/r32
30955     0x11/imm32/alloc-id:fake
30956     _string-subtract-from/imm32/name
30957     0x11/imm32/alloc-id:fake
30958     Two-args-int-stack-int-reg/imm32/inouts
30959     0/imm32/no-outputs
30960     0/imm32/no-outputs
30961     0x11/imm32/alloc-id:fake
30962     _string_29_subtract_from/imm32/subx-name
30963     1/imm32/rm32-is-first-inout
30964     2/imm32/r32-is-second-inout
30965     0/imm32/no-imm32
30966     0/imm32/no-imm8
30967     0/imm32/no-disp32
30968     0/imm32/no-xm32
30969     0/imm32/no-x32
30970     0x11/imm32/alloc-id:fake
30971     _Primitive-subtract-mem-from-reg/imm32/next
30972 _Primitive-subtract-mem-from-reg:  # (payload primitive)
30973     0x11/imm32/alloc-id:fake:payload
30974     # var1/reg <- subtract var2 => 2b/subtract var2/rm32 var1/r32
30975     0x11/imm32/alloc-id:fake
30976     _string-subtract/imm32/name
30977     0x11/imm32/alloc-id:fake
30978     Single-int-var-in-mem/imm32/inouts
30979     0x11/imm32/alloc-id:fake
30980     Single-int-var-in-some-register/imm32/outputs
30981     0x11/imm32/alloc-id:fake
30982     _string_2b_subtract/imm32/subx-name
30983     1/imm32/rm32-is-first-inout
30984     3/imm32/r32-is-first-output
30985     0/imm32/no-imm32
30986     0/imm32/no-imm8
30987     0/imm32/no-disp32
30988     0/imm32/no-xm32
30989     0/imm32/no-x32
30990     0x11/imm32/alloc-id:fake
30991     _Primitive-subtract-lit-from-reg/imm32/next
30992 _Primitive-subtract-lit-from-reg:  # (payload primitive)
30993     0x11/imm32/alloc-id:fake:payload
30994     # var1/reg <- subtract lit => 81 5/subop/subtract var1/rm32 lit/imm32
30995     0x11/imm32/alloc-id:fake
30996     _string-subtract/imm32/name
30997     0x11/imm32/alloc-id:fake
30998     Single-lit-var/imm32/inouts
30999     0x11/imm32/alloc-id:fake
31000     Single-int-var-in-some-register/imm32/outputs
31001     0x11/imm32/alloc-id:fake
31002     _string_81_subop_subtract/imm32/subx-name
31003     3/imm32/rm32-is-first-output
31004     0/imm32/no-r32
31005     1/imm32/imm32-is-first-inout
31006     0/imm32/no-imm8
31007     0/imm32/no-disp32
31008     0/imm32/no-xm32
31009     0/imm32/no-x32
31010     0x11/imm32/alloc-id:fake
31011     _Primitive-subtract-lit-from-mem/imm32/next
31012 _Primitive-subtract-lit-from-mem:  # (payload primitive)
31013     0x11/imm32/alloc-id:fake:payload
31014     # subtract-from var1, lit => 81 5/subop/subtract var1/rm32 lit/imm32
31015     0x11/imm32/alloc-id:fake
31016     _string-subtract-from/imm32/name
31017     0x11/imm32/alloc-id:fake
31018     Int-var-and-literal/imm32/inouts
31019     0/imm32/no-outputs
31020     0/imm32/no-outputs
31021     0x11/imm32/alloc-id:fake
31022     _string_81_subop_subtract/imm32/subx-name
31023     1/imm32/rm32-is-first-inout
31024     0/imm32/no-r32
31025     2/imm32/imm32-is-second-inout
31026     0/imm32/no-imm8
31027     0/imm32/no-disp32
31028     0/imm32/no-xm32
31029     0/imm32/no-x32
31030     0x11/imm32/alloc-id:fake
31031     _Primitive-and-with-eax/imm32/next
31032 # - and
31033 _Primitive-and-with-eax:  # (payload primitive)
31034     0x11/imm32/alloc-id:fake:payload
31035     # var/eax <- and lit => 25/and-with-eax lit/imm32
31036     0x11/imm32/alloc-id:fake
31037     _string-and/imm32/name
31038     0x11/imm32/alloc-id:fake
31039     Single-lit-var/imm32/inouts
31040     0x11/imm32/alloc-id:fake
31041     Single-int-var-in-eax/imm32/outputs
31042     0x11/imm32/alloc-id:fake
31043     _string_25_and_with_eax/imm32/subx-name
31044     0/imm32/no-rm32
31045     0/imm32/no-r32
31046     1/imm32/imm32-is-first-inout
31047     0/imm32/no-imm8
31048     0/imm32/no-disp32
31049     0/imm32/no-xm32
31050     0/imm32/no-x32
31051     0x11/imm32/alloc-id:fake
31052     _Primitive-and-reg-with-reg/imm32/next
31053 _Primitive-and-reg-with-reg:  # (payload primitive)
31054     0x11/imm32/alloc-id:fake:payload
31055     # var1/reg <- and var2/reg => 21/and-with var1/rm32 var2/r32
31056     0x11/imm32/alloc-id:fake
31057     _string-and/imm32/name
31058     0x11/imm32/alloc-id:fake
31059     Single-int-var-in-some-register/imm32/inouts
31060     0x11/imm32/alloc-id:fake
31061     Single-int-var-in-some-register/imm32/outputs
31062     0x11/imm32/alloc-id:fake
31063     _string_21_and_with/imm32/subx-name
31064     3/imm32/rm32-is-first-output
31065     1/imm32/r32-is-first-inout
31066     0/imm32/no-imm32
31067     0/imm32/no-imm8
31068     0/imm32/no-disp32
31069     0/imm32/no-xm32
31070     0/imm32/no-x32
31071     0x11/imm32/alloc-id:fake
31072     _Primitive-and-reg-with-mem/imm32/next
31073 _Primitive-and-reg-with-mem:  # (payload primitive)
31074     0x11/imm32/alloc-id:fake:payload
31075     # and-with var1 var2/reg => 21/and-with var1 var2/r32
31076     0x11/imm32/alloc-id:fake
31077     _string-and-with/imm32/name
31078     0x11/imm32/alloc-id:fake
31079     Two-args-int-stack-int-reg/imm32/inouts
31080     0/imm32/no-outputs
31081     0/imm32/no-outputs
31082     0x11/imm32/alloc-id:fake
31083     _string_21_and_with/imm32/subx-name
31084     1/imm32/rm32-is-first-inout
31085     2/imm32/r32-is-second-inout
31086     0/imm32/no-imm32
31087     0/imm32/no-imm8
31088     0/imm32/no-disp32
31089     0/imm32/no-xm32
31090     0/imm32/no-x32
31091     0x11/imm32/alloc-id:fake
31092     _Primitive-and-mem-with-reg/imm32/next
31093 _Primitive-and-mem-with-reg:  # (payload primitive)
31094     0x11/imm32/alloc-id:fake:payload
31095     # var1/reg <- and var2 => 23/and var2/rm32 var1/r32
31096     0x11/imm32/alloc-id:fake
31097     _string-and/imm32/name
31098     0x11/imm32/alloc-id:fake
31099     Single-int-var-in-mem/imm32/inouts
31100     0x11/imm32/alloc-id:fake
31101     Single-int-var-in-some-register/imm32/outputs
31102     0x11/imm32/alloc-id:fake
31103     _string_23_and/imm32/subx-name
31104     1/imm32/rm32-is-first-inout
31105     3/imm32/r32-is-first-output
31106     0/imm32/no-imm32
31107     0/imm32/no-imm8
31108     0/imm32/no-disp32
31109     0/imm32/no-xm32
31110     0/imm32/no-x32
31111     0x11/imm32/alloc-id:fake
31112     _Primitive-and-lit-with-reg/imm32/next
31113 _Primitive-and-lit-with-reg:  # (payload primitive)
31114     0x11/imm32/alloc-id:fake:payload
31115     # var1/reg <- and lit => 81 4/subop/and var1/rm32 lit/imm32
31116     0x11/imm32/alloc-id:fake
31117     _string-and/imm32/name
31118     0x11/imm32/alloc-id:fake
31119     Single-lit-var/imm32/inouts
31120     0x11/imm32/alloc-id:fake
31121     Single-int-var-in-some-register/imm32/outputs
31122     0x11/imm32/alloc-id:fake
31123     _string_81_subop_and/imm32/subx-name
31124     3/imm32/rm32-is-first-output
31125     0/imm32/no-r32
31126     1/imm32/imm32-is-first-inout
31127     0/imm32/no-imm8
31128     0/imm32/no-disp32
31129     0/imm32/no-xm32
31130     0/imm32/no-x32
31131     0x11/imm32/alloc-id:fake
31132     _Primitive-and-lit-with-mem/imm32/next
31133 _Primitive-and-lit-with-mem:  # (payload primitive)
31134     0x11/imm32/alloc-id:fake:payload
31135     # and-with var1, lit => 81 4/subop/and var1/rm32 lit/imm32
31136     0x11/imm32/alloc-id:fake
31137     _string-and-with/imm32/name
31138     0x11/imm32/alloc-id:fake
31139     Int-var-and-literal/imm32/inouts
31140     0/imm32/no-outputs
31141     0/imm32/no-outputs
31142     0x11/imm32/alloc-id:fake
31143     _string_81_subop_and/imm32/subx-name
31144     1/imm32/rm32-is-first-inout
31145     0/imm32/no-r32
31146     2/imm32/imm32-is-second-inout
31147     0/imm32/no-imm8
31148     0/imm32/no-disp32
31149     0/imm32/no-xm32
31150     0/imm32/no-x32
31151     0x11/imm32/alloc-id:fake
31152     _Primitive-or-with-eax/imm32/next
31153 # - or
31154 _Primitive-or-with-eax:  # (payload primitive)
31155     0x11/imm32/alloc-id:fake:payload
31156     # var/eax <- or lit => 0d/or-with-eax lit/imm32
31157     0x11/imm32/alloc-id:fake
31158     _string-or/imm32/name
31159     0x11/imm32/alloc-id:fake
31160     Single-lit-var/imm32/inouts
31161     0x11/imm32/alloc-id:fake
31162     Single-int-var-in-eax/imm32/outputs
31163     0x11/imm32/alloc-id:fake
31164     _string_0d_or_with_eax/imm32/subx-name
31165     0/imm32/no-rm32
31166     0/imm32/no-r32
31167     1/imm32/imm32-is-first-inout
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-or-reg-with-reg/imm32/next
31174 _Primitive-or-reg-with-reg:  # (payload primitive)
31175     0x11/imm32/alloc-id:fake:payload
31176     # var1/reg <- or var2/reg => 09/or-with var1/rm32 var2/r32
31177     0x11/imm32/alloc-id:fake
31178     _string-or/imm32/name
31179     0x11/imm32/alloc-id:fake
31180     Single-int-var-in-some-register/imm32/inouts
31181     0x11/imm32/alloc-id:fake
31182     Single-int-var-in-some-register/imm32/outputs
31183     0x11/imm32/alloc-id:fake
31184     _string_09_or_with/imm32/subx-name
31185     3/imm32/rm32-is-first-output
31186     1/imm32/r32-is-first-inout
31187     0/imm32/no-imm32
31188     0/imm32/no-imm8
31189     0/imm32/no-disp32
31190     0/imm32/no-xm32
31191     0/imm32/no-x32
31192     0x11/imm32/alloc-id:fake
31193     _Primitive-or-reg-with-mem/imm32/next
31194 _Primitive-or-reg-with-mem:  # (payload primitive)
31195     0x11/imm32/alloc-id:fake:payload
31196     # or-with var1 var2/reg => 09/or-with var1 var2/r32
31197     0x11/imm32/alloc-id:fake
31198     _string-or-with/imm32/name
31199     0x11/imm32/alloc-id:fake
31200     Two-args-int-stack-int-reg/imm32/inouts
31201     0/imm32/no-outputs
31202     0/imm32/no-outputs
31203     0x11/imm32/alloc-id:fake
31204     _string_09_or_with/imm32/subx-name
31205     1/imm32/rm32-is-first-inout
31206     2/imm32/r32-is-second-inout
31207     0/imm32/no-imm32
31208     0/imm32/no-imm8
31209     0/imm32/no-disp32
31210     0/imm32/no-xm32
31211     0/imm32/no-x32
31212     0x11/imm32/alloc-id:fake
31213     _Primitive-or-mem-with-reg/imm32/next
31214 _Primitive-or-mem-with-reg:  # (payload primitive)
31215     0x11/imm32/alloc-id:fake:payload
31216     # var1/reg <- or var2 => 0b/or var2/rm32 var1/r32
31217     0x11/imm32/alloc-id:fake
31218     _string-or/imm32/name
31219     0x11/imm32/alloc-id:fake
31220     Single-int-var-in-mem/imm32/inouts
31221     0x11/imm32/alloc-id:fake
31222     Single-int-var-in-some-register/imm32/outputs
31223     0x11/imm32/alloc-id:fake
31224     _string_0b_or/imm32/subx-name
31225     1/imm32/rm32-is-first-inout
31226     3/imm32/r32-is-first-output
31227     0/imm32/no-imm32
31228     0/imm32/no-imm8
31229     0/imm32/no-disp32
31230     0/imm32/no-xm32
31231     0/imm32/no-x32
31232     0x11/imm32/alloc-id:fake
31233     _Primitive-or-lit-with-reg/imm32/next
31234 _Primitive-or-lit-with-reg:  # (payload primitive)
31235     0x11/imm32/alloc-id:fake:payload
31236     # var1/reg <- or lit => 81 1/subop/or var1/rm32 lit/imm32
31237     0x11/imm32/alloc-id:fake
31238     _string-or/imm32/name
31239     0x11/imm32/alloc-id:fake
31240     Single-lit-var/imm32/inouts
31241     0x11/imm32/alloc-id:fake
31242     Single-int-var-in-some-register/imm32/outputs
31243     0x11/imm32/alloc-id:fake
31244     _string_81_subop_or/imm32/subx-name
31245     3/imm32/rm32-is-first-output
31246     0/imm32/no-r32
31247     1/imm32/imm32-is-first-inout
31248     0/imm32/no-imm8
31249     0/imm32/no-disp32
31250     0/imm32/no-xm32
31251     0/imm32/no-x32
31252     0x11/imm32/alloc-id:fake
31253     _Primitive-or-lit-with-mem/imm32/next
31254 _Primitive-or-lit-with-mem:  # (payload primitive)
31255     0x11/imm32/alloc-id:fake:payload
31256     # or-with var1, lit => 81 1/subop/or var1/rm32 lit/imm32
31257     0x11/imm32/alloc-id:fake
31258     _string-or-with/imm32/name
31259     0x11/imm32/alloc-id:fake
31260     Int-var-and-literal/imm32/inouts
31261     0/imm32/no-outputs
31262     0/imm32/no-outputs
31263     0x11/imm32/alloc-id:fake
31264     _string_81_subop_or/imm32/subx-name
31265     1/imm32/rm32-is-first-inout
31266     0/imm32/no-r32
31267     2/imm32/imm32-is-second-inout
31268     0/imm32/no-imm8
31269     0/imm32/no-disp32
31270     0/imm32/no-xm32
31271     0/imm32/no-x32
31272     0x11/imm32/alloc-id:fake
31273     _Primitive-not-reg/imm32/next
31274 # - not
31275 _Primitive-not-reg:  # (payload primitive)
31276     0x11/imm32/alloc-id:fake:payload
31277     # var1/reg <- not => f7 2/subop/not var1/rm32
31278     0x11/imm32/alloc-id:fake
31279     _string-not/imm32/name
31280     0/imm32/no-inouts
31281     0/imm32/no-inouts
31282     0x11/imm32/alloc-id:fake
31283     Single-int-var-in-some-register/imm32/outputs
31284     0x11/imm32/alloc-id:fake
31285     _string_f7_subop_not/imm32/subx-name
31286     3/imm32/rm32-is-first-output
31287     0/imm32/no-r32
31288     0/imm32/no-imm32
31289     0/imm32/no-imm8
31290     0/imm32/no-disp32
31291     0/imm32/no-xm32
31292     0/imm32/no-x32
31293     0x11/imm32/alloc-id:fake
31294     _Primitive-not-mem/imm32/next
31295 _Primitive-not-mem:  # (payload primitive)
31296     0x11/imm32/alloc-id:fake:payload
31297     # not var1 => f7 2/subop/not var1/rm32
31298     0x11/imm32/alloc-id:fake
31299     _string-not/imm32/name
31300     0x11/imm32/alloc-id:fake
31301     Single-int-var-in-mem/imm32/inouts
31302     0/imm32/no-outputs
31303     0/imm32/no-outputs
31304     0x11/imm32/alloc-id:fake
31305     _string_f7_subop_not/imm32/subx-name
31306     1/imm32/rm32-is-first-inout
31307     0/imm32/no-r32
31308     0/imm32/no-imm32
31309     0/imm32/no-imm8
31310     0/imm32/no-disp32
31311     0/imm32/no-xm32
31312     0/imm32/no-x32
31313     0x11/imm32/alloc-id:fake
31314     _Primitive-xor-with-eax/imm32/next
31315 # - xor
31316 _Primitive-xor-with-eax:  # (payload primitive)
31317     0x11/imm32/alloc-id:fake:payload
31318     # var/eax <- xor lit => 35/xor-with-eax lit/imm32
31319     0x11/imm32/alloc-id:fake
31320     _string-xor/imm32/name
31321     0x11/imm32/alloc-id:fake
31322     Single-lit-var/imm32/inouts
31323     0x11/imm32/alloc-id:fake
31324     Single-int-var-in-eax/imm32/outputs
31325     0x11/imm32/alloc-id:fake
31326     _string_35_xor_with_eax/imm32/subx-name
31327     0/imm32/no-rm32
31328     0/imm32/no-r32
31329     1/imm32/imm32-is-first-inout
31330     0/imm32/no-imm8
31331     0/imm32/no-disp32
31332     0/imm32/no-xm32
31333     0/imm32/no-x32
31334     0x11/imm32/alloc-id:fake
31335     _Primitive-xor-reg-with-reg/imm32/next
31336 _Primitive-xor-reg-with-reg:  # (payload primitive)
31337     0x11/imm32/alloc-id:fake:payload
31338     # var1/reg <- xor var2/reg => 31/xor-with var1/rm32 var2/r32
31339     0x11/imm32/alloc-id:fake
31340     _string-xor/imm32/name
31341     0x11/imm32/alloc-id:fake
31342     Single-int-var-in-some-register/imm32/inouts
31343     0x11/imm32/alloc-id:fake
31344     Single-int-var-in-some-register/imm32/outputs
31345     0x11/imm32/alloc-id:fake
31346     _string_31_xor_with/imm32/subx-name
31347     3/imm32/rm32-is-first-output
31348     1/imm32/r32-is-first-inout
31349     0/imm32/no-imm32
31350     0/imm32/no-imm8
31351     0/imm32/no-disp32
31352     0/imm32/no-xm32
31353     0/imm32/no-x32
31354     0x11/imm32/alloc-id:fake
31355     _Primitive-xor-reg-with-mem/imm32/next
31356 _Primitive-xor-reg-with-mem:  # (payload primitive)
31357     0x11/imm32/alloc-id:fake:payload
31358     # xor-with var1 var2/reg => 31/xor-with var1 var2/r32
31359     0x11/imm32/alloc-id:fake
31360     _string-xor-with/imm32/name
31361     0x11/imm32/alloc-id:fake
31362     Two-args-int-stack-int-reg/imm32/inouts
31363     0/imm32/no-outputs
31364     0/imm32/no-outputs
31365     0x11/imm32/alloc-id:fake
31366     _string_31_xor_with/imm32/subx-name
31367     1/imm32/rm32-is-first-inout
31368     2/imm32/r32-is-second-inout
31369     0/imm32/no-imm32
31370     0/imm32/no-imm8
31371     0/imm32/no-disp32
31372     0/imm32/no-xm32
31373     0/imm32/no-x32
31374     0x11/imm32/alloc-id:fake
31375     _Primitive-xor-mem-with-reg/imm32/next
31376 _Primitive-xor-mem-with-reg:  # (payload primitive)
31377     0x11/imm32/alloc-id:fake:payload
31378     # var1/reg <- xor var2 => 33/xor var2/rm32 var1/r32
31379     0x11/imm32/alloc-id:fake
31380     _string-xor/imm32/name
31381     0x11/imm32/alloc-id:fake
31382     Single-int-var-in-mem/imm32/inouts
31383     0x11/imm32/alloc-id:fake
31384     Single-int-var-in-some-register/imm32/outputs
31385     0x11/imm32/alloc-id:fake
31386     _string_33_xor/imm32/subx-name
31387     1/imm32/rm32-is-first-inout
31388     3/imm32/r32-is-first-output
31389     0/imm32/no-imm32
31390     0/imm32/no-imm8
31391     0/imm32/no-disp32
31392     0/imm32/no-xm32
31393     0/imm32/no-x32
31394     0x11/imm32/alloc-id:fake
31395     _Primitive-xor-lit-with-reg/imm32/next
31396 _Primitive-xor-lit-with-reg:  # (payload primitive)
31397     0x11/imm32/alloc-id:fake:payload
31398     # var1/reg <- xor lit => 81 6/subop/xor var1/rm32 lit/imm32
31399     0x11/imm32/alloc-id:fake
31400     _string-xor/imm32/name
31401     0x11/imm32/alloc-id:fake
31402     Single-lit-var/imm32/inouts
31403     0x11/imm32/alloc-id:fake
31404     Single-int-var-in-some-register/imm32/outputs
31405     0x11/imm32/alloc-id:fake
31406     _string_81_subop_xor/imm32/subx-name
31407     3/imm32/rm32-is-first-output
31408     0/imm32/no-r32
31409     1/imm32/imm32-is-first-inout
31410     0/imm32/no-imm8
31411     0/imm32/no-disp32
31412     0/imm32/no-xm32
31413     0/imm32/no-x32
31414     0x11/imm32/alloc-id:fake
31415     _Primitive-xor-lit-with-mem/imm32/next
31416 _Primitive-xor-lit-with-mem:  # (payload primitive)
31417     0x11/imm32/alloc-id:fake:payload
31418     # xor-with var1, lit => 81 6/subop/xor var1/rm32 lit/imm32
31419     0x11/imm32/alloc-id:fake
31420     _string-xor-with/imm32/name
31421     0x11/imm32/alloc-id:fake
31422     Int-var-and-literal/imm32/inouts
31423     0/imm32/no-outputs
31424     0/imm32/no-outputs
31425     0x11/imm32/alloc-id:fake
31426     _string_81_subop_xor/imm32/subx-name
31427     1/imm32/rm32-is-first-inout
31428     0/imm32/no-r32
31429     2/imm32/imm32-is-second-inout
31430     0/imm32/no-imm8
31431     0/imm32/no-disp32
31432     0/imm32/no-xm32
31433     0/imm32/no-x32
31434     0x11/imm32/alloc-id:fake
31435     _Primitive-shift-reg-left-by-lit/imm32/next
31436 _Primitive-shift-reg-left-by-lit:  # (payload primitive)
31437     0x11/imm32/alloc-id:fake:payload
31438     # var1/reg <- shift-left lit => c1/shift 4/subop/left var1/rm32 lit/imm32
31439     0x11/imm32/alloc-id:fake
31440     _string-shift-left/imm32/name
31441     0x11/imm32/alloc-id:fake
31442     Single-lit-var/imm32/inouts
31443     0x11/imm32/alloc-id:fake
31444     Single-int-var-in-some-register/imm32/outputs
31445     0x11/imm32/alloc-id:fake
31446     _string_c1_subop_shift_left/imm32/subx-name
31447     3/imm32/rm32-is-first-output
31448     0/imm32/no-r32
31449     0/imm32/no-imm32
31450     1/imm32/imm8-is-first-inout
31451     0/imm32/no-disp32
31452     0/imm32/no-xm32
31453     0/imm32/no-x32
31454     0x11/imm32/alloc-id:fake
31455     _Primitive-shift-reg-right-by-lit/imm32/next
31456 _Primitive-shift-reg-right-by-lit:  # (payload primitive)
31457     0x11/imm32/alloc-id:fake:payload
31458     # var1/reg <- shift-right lit => c1/shift 5/subop/right var1/rm32 lit/imm32
31459     0x11/imm32/alloc-id:fake
31460     _string-shift-right/imm32/name
31461     0x11/imm32/alloc-id:fake
31462     Single-lit-var/imm32/inouts
31463     0x11/imm32/alloc-id:fake
31464     Single-int-var-in-some-register/imm32/outputs
31465     0x11/imm32/alloc-id:fake
31466     _string_c1_subop_shift_right_padding_zeroes/imm32/subx-name
31467     3/imm32/rm32-is-first-output
31468     0/imm32/no-r32
31469     0/imm32/no-imm32
31470     1/imm32/imm8-is-first-inout
31471     0/imm32/no-disp32
31472     0/imm32/no-xm32
31473     0/imm32/no-x32
31474     0x11/imm32/alloc-id:fake
31475     _Primitive-shift-reg-right-signed-by-lit/imm32/next
31476 _Primitive-shift-reg-right-signed-by-lit:  # (payload primitive)
31477     0x11/imm32/alloc-id:fake:payload
31478     # var1/reg <- shift-right-signed lit => c1/shift 7/subop/right-preserving-sign var1/rm32 lit/imm32
31479     0x11/imm32/alloc-id:fake
31480     _string-shift-right-signed/imm32/name
31481     0x11/imm32/alloc-id:fake
31482     Single-lit-var/imm32/inouts
31483     0x11/imm32/alloc-id:fake
31484     Single-int-var-in-some-register/imm32/outputs
31485     0x11/imm32/alloc-id:fake
31486     _string_c1_subop_shift_right_preserving_sign/imm32/subx-name
31487     3/imm32/rm32-is-first-output
31488     0/imm32/no-r32
31489     0/imm32/no-imm32
31490     1/imm32/imm8-is-first-inout
31491     0/imm32/no-disp32
31492     0/imm32/no-xm32
31493     0/imm32/no-x32
31494     0x11/imm32/alloc-id:fake
31495     _Primitive-shift-mem-left-by-lit/imm32/next
31496 _Primitive-shift-mem-left-by-lit:  # (payload primitive)
31497     0x11/imm32/alloc-id:fake:payload
31498     # shift-left var1, lit => c1/shift 4/subop/left var1/rm32 lit/imm32
31499     0x11/imm32/alloc-id:fake
31500     _string-shift-left/imm32/name
31501     0x11/imm32/alloc-id:fake
31502     Int-var-and-literal/imm32/inouts
31503     0/imm32/no-outputs
31504     0/imm32/no-outputs
31505     0x11/imm32/alloc-id:fake
31506     _string_c1_subop_shift_left/imm32/subx-name
31507     1/imm32/rm32-is-first-inout
31508     0/imm32/no-r32
31509     0/imm32/no-imm32
31510     2/imm32/imm8-is-second-inout
31511     0/imm32/no-disp32
31512     0/imm32/no-xm32
31513     0/imm32/no-x32
31514     0x11/imm32/alloc-id:fake
31515     _Primitive-shift-mem-right-by-lit/imm32/next
31516 _Primitive-shift-mem-right-by-lit:  # (payload primitive)
31517     0x11/imm32/alloc-id:fake:payload
31518     # shift-right var1, lit => c1/shift 5/subop/right var1/rm32 lit/imm32
31519     0x11/imm32/alloc-id:fake
31520     _string-shift-right/imm32/name
31521     0x11/imm32/alloc-id:fake
31522     Int-var-and-literal/imm32/inouts
31523     0/imm32/no-outputs
31524     0/imm32/no-outputs
31525     0x11/imm32/alloc-id:fake
31526     _string_c1_subop_shift_right_padding_zeroes/imm32/subx-name
31527     1/imm32/rm32-is-first-inout
31528     0/imm32/no-r32
31529     0/imm32/no-imm32
31530     2/imm32/imm8-is-second-inout
31531     0/imm32/no-disp32
31532     0/imm32/no-xm32
31533     0/imm32/no-x32
31534     0x11/imm32/alloc-id:fake
31535     _Primitive-shift-mem-right-signed-by-lit/imm32/next
31536 _Primitive-shift-mem-right-signed-by-lit:  # (payload primitive)
31537     0x11/imm32/alloc-id:fake:payload
31538     # shift-right-signed var1, lit => c1/shift 7/subop/right-preserving-sign var1/rm32 lit/imm32
31539     0x11/imm32/alloc-id:fake
31540     _string-shift-right-signed/imm32/name
31541     0x11/imm32/alloc-id:fake
31542     Int-var-and-literal/imm32/inouts
31543     0/imm32/no-outputs
31544     0/imm32/no-outputs
31545     0x11/imm32/alloc-id:fake
31546     _string_c1_subop_shift_right_preserving_sign/imm32/subx-name
31547     1/imm32/rm32-is-first-inout
31548     0/imm32/no-r32
31549     0/imm32/no-imm32
31550     2/imm32/imm8-is-second-inout
31551     0/imm32/no-disp32
31552     0/imm32/no-xm32
31553     0/imm32/no-x32
31554     0x11/imm32/alloc-id:fake
31555     _Primitive-copy-to-eax/imm32/next
31556 # - copy
31557 _Primitive-copy-to-eax:  # (payload primitive)
31558     0x11/imm32/alloc-id:fake:payload
31559     # var/eax <- copy lit => b8/copy-to-eax lit/imm32
31560     0x11/imm32/alloc-id:fake
31561     _string-copy/imm32/name
31562     0x11/imm32/alloc-id:fake
31563     Single-lit-var/imm32/inouts
31564     0x11/imm32/alloc-id:fake
31565     Single-int-var-in-eax/imm32/outputs
31566     0x11/imm32/alloc-id:fake
31567     _string_b8_copy_to_eax/imm32/subx-name
31568     0/imm32/no-rm32
31569     0/imm32/no-r32
31570     1/imm32/imm32-is-first-inout
31571     0/imm32/no-imm8
31572     0/imm32/no-disp32
31573     0/imm32/no-xm32
31574     0/imm32/no-x32
31575     0x11/imm32/alloc-id:fake
31576     _Primitive-copy-to-ecx/imm32/next
31577 _Primitive-copy-to-ecx:  # (payload primitive)
31578     0x11/imm32/alloc-id:fake:payload
31579     # var/ecx <- copy lit => b9/copy-to-ecx lit/imm32
31580     0x11/imm32/alloc-id:fake
31581     _string-copy/imm32/name
31582     0x11/imm32/alloc-id:fake
31583     Single-lit-var/imm32/inouts
31584     0x11/imm32/alloc-id:fake
31585     Single-int-var-in-ecx/imm32/outputs
31586     0x11/imm32/alloc-id:fake
31587     _string_b9_copy_to_ecx/imm32/subx-name
31588     0/imm32/no-rm32
31589     0/imm32/no-r32
31590     1/imm32/imm32-is-first-inout
31591     0/imm32/no-imm8
31592     0/imm32/no-disp32
31593     0/imm32/no-xm32
31594     0/imm32/no-x32
31595     0x11/imm32/alloc-id:fake
31596     _Primitive-copy-to-edx/imm32/next
31597 _Primitive-copy-to-edx:  # (payload primitive)
31598     0x11/imm32/alloc-id:fake:payload
31599     # var/edx <- copy lit => ba/copy-to-edx lit/imm32
31600     0x11/imm32/alloc-id:fake
31601     _string-copy/imm32/name
31602     0x11/imm32/alloc-id:fake
31603     Single-lit-var/imm32/inouts
31604     0x11/imm32/alloc-id:fake
31605     Single-int-var-in-edx/imm32/outputs
31606     0x11/imm32/alloc-id:fake
31607     _string_ba_copy_to_edx/imm32/subx-name
31608     0/imm32/no-rm32
31609     0/imm32/no-r32
31610     1/imm32/imm32-is-first-inout
31611     0/imm32/no-imm8
31612     0/imm32/no-disp32
31613     0/imm32/no-xm32
31614     0/imm32/no-x32
31615     0x11/imm32/alloc-id:fake
31616     _Primitive-copy-to-ebx/imm32/next
31617 _Primitive-copy-to-ebx:  # (payload primitive)
31618     0x11/imm32/alloc-id:fake:payload
31619     # var/ebx <- copy lit => bb/copy-to-ebx lit/imm32
31620     0x11/imm32/alloc-id:fake
31621     _string-copy/imm32/name
31622     0x11/imm32/alloc-id:fake
31623     Single-lit-var/imm32/inouts
31624     0x11/imm32/alloc-id:fake
31625     Single-int-var-in-ebx/imm32/outputs
31626     0x11/imm32/alloc-id:fake
31627     _string_bb_copy_to_ebx/imm32/subx-name
31628     0/imm32/no-rm32
31629     0/imm32/no-r32
31630     1/imm32/imm32-is-first-inout
31631     0/imm32/no-imm8
31632     0/imm32/no-disp32
31633     0/imm32/no-xm32
31634     0/imm32/no-x32
31635     0x11/imm32/alloc-id:fake
31636     _Primitive-copy-to-esi/imm32/next
31637 _Primitive-copy-to-esi:  # (payload primitive)
31638     0x11/imm32/alloc-id:fake:payload
31639     # var/esi <- copy lit => be/copy-to-esi lit/imm32
31640     0x11/imm32/alloc-id:fake
31641     _string-copy/imm32/name
31642     0x11/imm32/alloc-id:fake
31643     Single-lit-var/imm32/inouts
31644     0x11/imm32/alloc-id:fake
31645     Single-int-var-in-esi/imm32/outputs
31646     0x11/imm32/alloc-id:fake
31647     _string_be_copy_to_esi/imm32/subx-name
31648     0/imm32/no-rm32
31649     0/imm32/no-r32
31650     1/imm32/imm32-is-first-inout
31651     0/imm32/no-imm8
31652     0/imm32/no-disp32
31653     0/imm32/no-xm32
31654     0/imm32/no-x32
31655     0x11/imm32/alloc-id:fake
31656     _Primitive-copy-to-edi/imm32/next
31657 _Primitive-copy-to-edi:  # (payload primitive)
31658     0x11/imm32/alloc-id:fake:payload
31659     # var/edi <- copy lit => bf/copy-to-edi lit/imm32
31660     0x11/imm32/alloc-id:fake
31661     _string-copy/imm32/name
31662     0x11/imm32/alloc-id:fake
31663     Single-lit-var/imm32/inouts
31664     0x11/imm32/alloc-id:fake
31665     Single-int-var-in-edi/imm32/outputs
31666     0x11/imm32/alloc-id:fake
31667     _string_bf_copy_to_edi/imm32/subx-name
31668     0/imm32/no-rm32
31669     0/imm32/no-r32
31670     1/imm32/imm32-is-first-inout
31671     0/imm32/no-imm8
31672     0/imm32/no-disp32
31673     0/imm32/no-xm32
31674     0/imm32/no-x32
31675     0x11/imm32/alloc-id:fake
31676     _Primitive-copy-reg-to-reg/imm32/next
31677 _Primitive-copy-reg-to-reg:  # (payload primitive)
31678     0x11/imm32/alloc-id:fake:payload
31679     # var1/reg <- copy var2/reg => 89/<- var1/rm32 var2/r32
31680     0x11/imm32/alloc-id:fake
31681     _string-copy/imm32/name
31682     0x11/imm32/alloc-id:fake
31683     Single-int-var-in-some-register/imm32/inouts
31684     0x11/imm32/alloc-id:fake
31685     Single-int-var-in-some-register/imm32/outputs
31686     0x11/imm32/alloc-id:fake
31687     _string_89_<-/imm32/subx-name
31688     3/imm32/rm32-is-first-output
31689     1/imm32/r32-is-first-inout
31690     0/imm32/no-imm32
31691     0/imm32/no-imm8
31692     0/imm32/no-disp32
31693     0/imm32/no-xm32
31694     0/imm32/no-x32
31695     0x11/imm32/alloc-id:fake
31696     _Primitive-copy-reg-to-mem/imm32/next
31697 _Primitive-copy-reg-to-mem:  # (payload primitive)
31698     0x11/imm32/alloc-id:fake:payload
31699     # copy-to var1 var2/reg => 89/<- var1 var2/r32
31700     0x11/imm32/alloc-id:fake
31701     _string-copy-to/imm32/name
31702     0x11/imm32/alloc-id:fake
31703     Two-args-int-stack-int-reg/imm32/inouts
31704     0/imm32/no-outputs
31705     0/imm32/no-outputs
31706     0x11/imm32/alloc-id:fake
31707     _string_89_<-/imm32/subx-name
31708     1/imm32/rm32-is-first-inout
31709     2/imm32/r32-is-second-inout
31710     0/imm32/no-imm32
31711     0/imm32/no-imm8
31712     0/imm32/no-disp32
31713     0/imm32/no-xm32
31714     0/imm32/no-x32
31715     0x11/imm32/alloc-id:fake
31716     _Primitive-copy-mem-to-reg/imm32/next
31717 _Primitive-copy-mem-to-reg:  # (payload primitive)
31718     0x11/imm32/alloc-id:fake:payload
31719     # var1/reg <- copy var2 => 8b/-> var2/rm32 var1/r32
31720     0x11/imm32/alloc-id:fake
31721     _string-copy/imm32/name
31722     0x11/imm32/alloc-id:fake
31723     Single-int-var-in-mem/imm32/inouts
31724     0x11/imm32/alloc-id:fake
31725     Single-int-var-in-some-register/imm32/outputs
31726     0x11/imm32/alloc-id:fake
31727     _string_8b_->/imm32/subx-name
31728     1/imm32/rm32-is-first-inout
31729     3/imm32/r32-is-first-output
31730     0/imm32/no-imm32
31731     0/imm32/no-imm8
31732     0/imm32/no-disp32
31733     0/imm32/no-xm32
31734     0/imm32/no-x32
31735     0x11/imm32/alloc-id:fake
31736     _Primitive-copy-lit-to-reg/imm32/next
31737 _Primitive-copy-lit-to-reg:  # (payload primitive)
31738     0x11/imm32/alloc-id:fake:payload
31739     # var1/reg <- copy lit => c7 0/subop/copy var1/rm32 lit/imm32
31740     0x11/imm32/alloc-id:fake
31741     _string-copy/imm32/name
31742     0x11/imm32/alloc-id:fake
31743     Single-lit-var/imm32/inouts
31744     0x11/imm32/alloc-id:fake
31745     Single-int-var-in-some-register/imm32/outputs
31746     0x11/imm32/alloc-id:fake
31747     _string_c7_subop_copy/imm32/subx-name
31748     3/imm32/rm32-is-first-output
31749     0/imm32/no-r32
31750     1/imm32/imm32-is-first-inout
31751     0/imm32/no-imm8
31752     0/imm32/no-disp32
31753     0/imm32/no-xm32
31754     0/imm32/no-x32
31755     0x11/imm32/alloc-id:fake
31756     _Primitive-copy-lit-to-mem/imm32/next
31757 _Primitive-copy-lit-to-mem:  # (payload primitive)
31758     0x11/imm32/alloc-id:fake:payload
31759     # copy-to var1, lit => c7 0/subop/copy var1/rm32 lit/imm32
31760     0x11/imm32/alloc-id:fake
31761     _string-copy-to/imm32/name
31762     0x11/imm32/alloc-id:fake
31763     Int-var-and-literal/imm32/inouts
31764     0/imm32/no-outputs
31765     0/imm32/no-outputs
31766     0x11/imm32/alloc-id:fake
31767     _string_c7_subop_copy/imm32/subx-name
31768     1/imm32/rm32-is-first-inout
31769     0/imm32/no-r32
31770     2/imm32/imm32-is-second-inout
31771     0/imm32/no-imm8
31772     0/imm32/no-disp32
31773     0/imm32/no-xm32
31774     0/imm32/no-x32
31775     0x11/imm32/alloc-id:fake
31776     _Primitive-copy-byte-from-reg/imm32/next
31777 # - copy byte
31778 _Primitive-copy-byte-from-reg:
31779     0x11/imm32/alloc-id:fake:payload
31780     # var/reg <- copy-byte var2/reg2 => 8a/byte-> %var2 var/r32
31781     0x11/imm32/alloc-id:fake
31782     _string-copy-byte/imm32/name
31783     0x11/imm32/alloc-id:fake
31784     Single-byte-var-in-some-register/imm32/inouts
31785     0x11/imm32/alloc-id:fake
31786     Single-byte-var-in-some-register/imm32/outputs
31787     0x11/imm32/alloc-id:fake
31788     _string_8a_copy_byte/imm32/subx-name
31789     1/imm32/rm32-is-first-inout
31790     3/imm32/r32-is-first-output
31791     0/imm32/no-imm32
31792     0/imm32/no-imm8
31793     0/imm32/no-disp32
31794     0/imm32/no-xm32
31795     0/imm32/no-x32
31796     0x11/imm32/alloc-id:fake
31797     _Primitive-copy-byte-from-mem/imm32/next
31798 _Primitive-copy-byte-from-mem:
31799     0x11/imm32/alloc-id:fake:payload
31800     # var/reg <- copy-byte *var2/reg2 => 8a/byte-> *var2 var/r32
31801     0x11/imm32/alloc-id:fake
31802     _string-copy-byte/imm32/name
31803     0x11/imm32/alloc-id:fake
31804     Single-byte-var-in-mem/imm32/inouts
31805     0x11/imm32/alloc-id:fake
31806     Single-byte-var-in-some-register/imm32/outputs
31807     0x11/imm32/alloc-id:fake
31808     _string_8a_copy_byte/imm32/subx-name
31809     1/imm32/rm32-is-first-inout
31810     3/imm32/r32-is-first-output
31811     0/imm32/no-imm32
31812     0/imm32/no-imm8
31813     0/imm32/no-disp32
31814     0/imm32/no-xm32
31815     0/imm32/no-x32
31816     0x11/imm32/alloc-id:fake
31817     _Primitive-copy-byte-to-mem/imm32/next
31818 _Primitive-copy-byte-to-mem:
31819     0x11/imm32/alloc-id:fake:payload
31820     # copy-byte-to *var1/reg1, var2/reg2 => 88/byte<- *reg1 reg2/r32
31821     0x11/imm32/alloc-id:fake
31822     _string-copy-byte-to/imm32/name
31823     0x11/imm32/alloc-id:fake
31824     Two-args-byte-stack-byte-reg/imm32/inouts
31825     0/imm32/no-outputs
31826     0/imm32/no-outputs
31827     0x11/imm32/alloc-id:fake
31828     _string_88_copy_byte/imm32/subx-name
31829     1/imm32/rm32-is-first-inout
31830     2/imm32/r32-is-second-inout
31831     0/imm32/no-imm32
31832     0/imm32/no-imm8
31833     0/imm32/no-disp32
31834     0/imm32/no-xm32
31835     0/imm32/no-x32
31836     0x11/imm32/alloc-id:fake
31837     _Primitive-address/imm32/next
31838 # - address
31839 _Primitive-address:  # (payload primitive)
31840     0x11/imm32/alloc-id:fake:payload
31841     # var1/reg <- address var2 => 8d/copy-address var2/rm32 var1/r32
31842     0x11/imm32/alloc-id:fake
31843     _string-address/imm32/name
31844     0x11/imm32/alloc-id:fake
31845     Single-int-var-in-mem/imm32/inouts
31846     0x11/imm32/alloc-id:fake
31847     Single-addr-var-in-some-register/imm32/outputs
31848     0x11/imm32/alloc-id:fake
31849     _string_8d_copy_address/imm32/subx-name
31850     1/imm32/rm32-is-first-inout
31851     3/imm32/r32-is-first-output
31852     0/imm32/no-imm32
31853     0/imm32/no-imm8
31854     0/imm32/no-disp32
31855     0/imm32/no-xm32
31856     0/imm32/no-x32
31857     0x11/imm32/alloc-id:fake
31858     _Primitive-compare-reg-with-reg/imm32/next
31859 # - compare
31860 _Primitive-compare-reg-with-reg:  # (payload primitive)
31861     0x11/imm32/alloc-id:fake:payload
31862     # compare var1/reg1 var2/reg2 => 39/compare var1/rm32 var2/r32
31863     0x11/imm32/alloc-id:fake
31864     _string-compare/imm32/name
31865     0x11/imm32/alloc-id:fake
31866     Two-int-args-in-regs/imm32/inouts
31867     0/imm32/no-outputs
31868     0/imm32/no-outputs
31869     0x11/imm32/alloc-id:fake
31870     _string_39_compare->/imm32/subx-name
31871     1/imm32/rm32-is-first-inout
31872     2/imm32/r32-is-second-inout
31873     0/imm32/no-imm32
31874     0/imm32/no-imm8
31875     0/imm32/no-disp32
31876     0/imm32/no-xm32
31877     0/imm32/no-x32
31878     0x11/imm32/alloc-id:fake
31879     _Primitive-compare-mem-with-reg/imm32/next
31880 _Primitive-compare-mem-with-reg:  # (payload primitive)
31881     0x11/imm32/alloc-id:fake:payload
31882     # compare var1 var2/reg => 39/compare var1/rm32 var2/r32
31883     0x11/imm32/alloc-id:fake
31884     _string-compare/imm32/name
31885     0x11/imm32/alloc-id:fake
31886     Two-args-int-stack-int-reg/imm32/inouts
31887     0/imm32/no-outputs
31888     0/imm32/no-outputs
31889     0x11/imm32/alloc-id:fake
31890     _string_39_compare->/imm32/subx-name
31891     1/imm32/rm32-is-first-inout
31892     2/imm32/r32-is-second-inout
31893     0/imm32/no-imm32
31894     0/imm32/no-imm8
31895     0/imm32/no-disp32
31896     0/imm32/no-xm32
31897     0/imm32/no-x32
31898     0x11/imm32/alloc-id:fake
31899     _Primitive-compare-reg-with-mem/imm32/next
31900 _Primitive-compare-reg-with-mem:  # (payload primitive)
31901     0x11/imm32/alloc-id:fake:payload
31902     # compare var1/reg var2 => 3b/compare<- var2/rm32 var1/r32
31903     0x11/imm32/alloc-id:fake
31904     _string-compare/imm32/name
31905     0x11/imm32/alloc-id:fake
31906     Two-args-int-reg-int-stack/imm32/inouts
31907     0/imm32/no-outputs
31908     0/imm32/no-outputs
31909     0x11/imm32/alloc-id:fake
31910     _string_3b_compare<-/imm32/subx-name
31911     2/imm32/rm32-is-second-inout
31912     1/imm32/r32-is-first-inout
31913     0/imm32/no-imm32
31914     0/imm32/no-imm8
31915     0/imm32/no-disp32
31916     0/imm32/no-xm32
31917     0/imm32/no-x32
31918     0x11/imm32/alloc-id:fake
31919     _Primitive-compare-eax-with-literal/imm32/next
31920 _Primitive-compare-eax-with-literal:  # (payload primitive)
31921     0x11/imm32/alloc-id:fake:payload
31922     # compare var1/eax n => 3d/compare-eax-with n/imm32
31923     0x11/imm32/alloc-id:fake
31924     _string-compare/imm32/name
31925     0x11/imm32/alloc-id:fake
31926     Two-args-int-eax-int-literal/imm32/inouts
31927     0/imm32/no-outputs
31928     0/imm32/no-outputs
31929     0x11/imm32/alloc-id:fake
31930     _string_3d_compare_eax_with/imm32/subx-name
31931     0/imm32/no-rm32
31932     0/imm32/no-r32
31933     2/imm32/imm32-is-second-inout
31934     0/imm32/no-imm8
31935     0/imm32/no-disp32
31936     0/imm32/no-xm32
31937     0/imm32/no-x32
31938     0x11/imm32/alloc-id:fake
31939     _Primitive-compare-reg-with-literal/imm32/next
31940 _Primitive-compare-reg-with-literal:  # (payload primitive)
31941     0x11/imm32/alloc-id:fake:payload
31942     # compare var1/reg n => 81 7/subop/compare %reg n/imm32
31943     0x11/imm32/alloc-id:fake
31944     _string-compare/imm32/name
31945     0x11/imm32/alloc-id:fake
31946     Int-var-in-register-and-literal/imm32/inouts
31947     0/imm32/no-outputs
31948     0/imm32/no-outputs
31949     0x11/imm32/alloc-id:fake
31950     _string_81_subop_compare/imm32/subx-name
31951     1/imm32/rm32-is-first-inout
31952     0/imm32/no-r32
31953     2/imm32/imm32-is-second-inout
31954     0/imm32/no-imm8
31955     0/imm32/no-disp32
31956     0/imm32/no-xm32
31957     0/imm32/no-x32
31958     0x11/imm32/alloc-id:fake
31959     _Primitive-compare-mem-with-literal/imm32/next
31960 _Primitive-compare-mem-with-literal:  # (payload primitive)
31961     0x11/imm32/alloc-id:fake:payload
31962     # compare var1 n => 81 7/subop/compare *(ebp+___) n/imm32
31963     0x11/imm32/alloc-id:fake
31964     _string-compare/imm32/name
31965     0x11/imm32/alloc-id:fake
31966     Int-var-and-literal/imm32/inouts
31967     0/imm32/no-outputs
31968     0/imm32/no-outputs
31969     0x11/imm32/alloc-id:fake
31970     _string_81_subop_compare/imm32/subx-name
31971     1/imm32/rm32-is-first-inout
31972     0/imm32/no-r32
31973     2/imm32/imm32-is-second-inout
31974     0/imm32/no-imm8
31975     0/imm32/no-disp32
31976     0/imm32/no-xm32
31977     0/imm32/no-x32
31978     0x11/imm32/alloc-id:fake
31979     _Primitive-negate-reg/imm32/next
31980 # - negate
31981 _Primitive-negate-reg:  # (payload primitive)
31982     0x11/imm32/alloc-id:fake:payload
31983     # var1/reg <- negate => f7 3/subop/negate var1/rm32
31984     0x11/imm32/alloc-id:fake
31985     _string-negate/imm32/name
31986     0/imm32/no-inouts
31987     0/imm32/no-inouts
31988     0x11/imm32/alloc-id:fake
31989     Single-int-var-in-some-register/imm32/outputs
31990     0x11/imm32/alloc-id:fake
31991     _string_f7_subop_negate/imm32/subx-name
31992     3/imm32/rm32-is-first-output
31993     0/imm32/no-r32
31994     0/imm32/no-imm32
31995     0/imm32/no-imm8
31996     0/imm32/no-disp32
31997     0/imm32/no-xm32
31998     0/imm32/no-x32
31999     0x11/imm32/alloc-id:fake
32000     _Primitive-negate-mem/imm32/next
32001 _Primitive-negate-mem:  # (payload primitive)
32002     0x11/imm32/alloc-id:fake:payload
32003     # negate var1 => f7 3/subop/negate var1/rm32
32004     0x11/imm32/alloc-id:fake
32005     _string-negate/imm32/name
32006     0x11/imm32/alloc-id:fake
32007     Single-int-var-in-mem/imm32/inouts
32008     0/imm32/no-outputs
32009     0/imm32/no-outputs
32010     0x11/imm32/alloc-id:fake
32011     _string_f7_subop_negate/imm32/subx-name
32012     1/imm32/rm32-is-first-inout
32013     0/imm32/no-r32
32014     0/imm32/no-imm32
32015     0/imm32/no-imm8
32016     0/imm32/no-disp32
32017     0/imm32/no-xm32
32018     0/imm32/no-x32
32019     0x11/imm32/alloc-id:fake
32020     _Primitive-multiply-reg-by-reg/imm32/next
32021 # - multiply
32022 _Primitive-multiply-reg-by-reg:  # (payload primitive)
32023     0x11/imm32/alloc-id:fake:payload
32024     # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32
32025     0x11/imm32/alloc-id:fake
32026     _string-multiply/imm32/name
32027     0x11/imm32/alloc-id:fake
32028     Single-int-var-in-some-register/imm32/inouts
32029     0x11/imm32/alloc-id:fake
32030     Single-int-var-in-some-register/imm32/outputs
32031     0x11/imm32/alloc-id:fake
32032     _string_0f_af_multiply/imm32/subx-name
32033     1/imm32/rm32-is-first-inout
32034     3/imm32/r32-is-first-output
32035     0/imm32/no-imm32
32036     0/imm32/no-imm8
32037     0/imm32/no-disp32
32038     0/imm32/no-xm32
32039     0/imm32/no-x32
32040     0x11/imm32/alloc-id:fake
32041     _Primitive-multiply-reg-by-mem/imm32/next
32042 _Primitive-multiply-reg-by-mem:  # (payload primitive)
32043     0x11/imm32/alloc-id:fake:payload
32044     # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32
32045     0x11/imm32/alloc-id:fake
32046     _string-multiply/imm32/name
32047     0x11/imm32/alloc-id:fake
32048     Single-int-var-in-mem/imm32/inouts
32049     0x11/imm32/alloc-id:fake
32050     Single-int-var-in-some-register/imm32/outputs
32051     0x11/imm32/alloc-id:fake
32052     _string_0f_af_multiply/imm32/subx-name
32053     1/imm32/rm32-is-first-inout
32054     3/imm32/r32-is-first-output
32055     0/imm32/no-imm32
32056     0/imm32/no-imm8
32057     0/imm32/no-disp32
32058     0/imm32/no-xm32
32059     0/imm32/no-x32
32060     0x11/imm32/alloc-id:fake
32061     _Primitive-convert-mem-to-xreg/imm32/next
32062 # - convert int to floating point
32063 _Primitive-convert-mem-to-xreg:  # (payload primitive)
32064     0x11/imm32/alloc-id:fake:payload
32065     # var1/xreg <- convert var2 => f3 0f 2a/convert-to-float var2/rm32 var1/x32
32066     0x11/imm32/alloc-id:fake
32067     _string-convert/imm32/name
32068     0x11/imm32/alloc-id:fake
32069     Single-int-var-in-mem/imm32/inouts
32070     0x11/imm32/alloc-id:fake
32071     Single-float-var-in-some-register/imm32/outputs
32072     0x11/imm32/alloc-id:fake
32073     _string_f3_0f_2a_convert_to_float/imm32/subx-name
32074     1/imm32/rm32-is-first-inout
32075     0/imm32/no-r32
32076     0/imm32/no-imm32
32077     0/imm32/no-imm8
32078     0/imm32/no-disp32
32079     0/imm32/no-xm32
32080     3/imm32/x32-is-first-output
32081     0x11/imm32/alloc-id:fake
32082     _Primitive-convert-reg-to-xreg/imm32/next
32083 _Primitive-convert-reg-to-xreg:  # (payload primitive)
32084     0x11/imm32/alloc-id:fake:payload
32085     # var1/xreg <- convert var2/reg => f3 0f 2a/convert-to-float var2/rm32 var1/x32
32086     0x11/imm32/alloc-id:fake
32087     _string-convert/imm32/name
32088     0x11/imm32/alloc-id:fake
32089     Single-int-var-in-some-register/imm32/inouts
32090     0x11/imm32/alloc-id:fake
32091     Single-float-var-in-some-register/imm32/outputs
32092     0x11/imm32/alloc-id:fake
32093     _string_f3_0f_2a_convert_to_float/imm32/subx-name
32094     1/imm32/rm32-is-first-inout
32095     0/imm32/no-r32
32096     0/imm32/no-imm32
32097     0/imm32/no-imm8
32098     0/imm32/no-disp32
32099     0/imm32/no-xm32
32100     3/imm32/x32-is-first-output
32101     0x11/imm32/alloc-id:fake
32102     _Primitive-convert-xmem-to-reg/imm32/next
32103 # - convert floating point to int
32104 _Primitive-convert-xmem-to-reg:  # (payload primitive)
32105     0x11/imm32/alloc-id:fake:payload
32106     # var1/reg <- convert var2 => f3 0f 2d/convert-to-int var2/xm32 var1/r32
32107     0x11/imm32/alloc-id:fake
32108     _string-convert/imm32/name
32109     0x11/imm32/alloc-id:fake
32110     Single-float-var-in-mem/imm32/inouts
32111     0x11/imm32/alloc-id:fake
32112     Single-int-var-in-some-register/imm32/outputs
32113     0x11/imm32/alloc-id:fake
32114     _string_f3_0f_2d_convert_to_int/imm32/subx-name
32115     0/imm32/no-rm32
32116     3/imm32/r32-is-first-output
32117     0/imm32/no-imm32
32118     0/imm32/no-imm8
32119     0/imm32/no-disp32
32120     1/imm32/xm32-is-first-inout
32121     0/imm32/no-x32
32122     0x11/imm32/alloc-id:fake
32123     _Primitive-convert-xreg-to-reg/imm32/next
32124 _Primitive-convert-xreg-to-reg:  # (payload primitive)
32125     0x11/imm32/alloc-id:fake:payload
32126     # var1/reg <- convert var2/xreg => f3 0f 2d/convert-to-int var2/xm32 var1/r32
32127     0x11/imm32/alloc-id:fake
32128     _string-convert/imm32/name
32129     0x11/imm32/alloc-id:fake
32130     Single-float-var-in-some-register/imm32/inouts
32131     0x11/imm32/alloc-id:fake
32132     Single-int-var-in-some-register/imm32/outputs
32133     0x11/imm32/alloc-id:fake
32134     _string_f3_0f_2d_convert_to_int/imm32/subx-name
32135     0/imm32/no-rm32
32136     3/imm32/r32-is-first-output
32137     0/imm32/no-imm32
32138     0/imm32/no-imm8
32139     0/imm32/no-disp32
32140     1/imm32/xm32-is-first-inout
32141     0/imm32/no-x32
32142     0x11/imm32/alloc-id:fake
32143     _Primitive-truncate-xmem-to-reg/imm32/next
32144 _Primitive-truncate-xmem-to-reg:  # (payload primitive)
32145     0x11/imm32/alloc-id:fake:payload
32146     # var1/reg <- truncate var2 => f3 0f 2c/truncate-to-int var2/xm32 var1/r32
32147     0x11/imm32/alloc-id:fake
32148     _string-truncate/imm32/name
32149     0x11/imm32/alloc-id:fake
32150     Single-float-var-in-mem/imm32/inouts
32151     0x11/imm32/alloc-id:fake
32152     Single-int-var-in-some-register/imm32/outputs
32153     0x11/imm32/alloc-id:fake
32154     _string_f3_0f_2c_truncate_to_int/imm32/subx-name
32155     0/imm32/no-rm32
32156     3/imm32/r32-is-first-output
32157     0/imm32/no-imm32
32158     0/imm32/no-imm8
32159     0/imm32/no-disp32
32160     1/imm32/xm32-is-first-inout
32161     0/imm32/no-x32
32162     0x11/imm32/alloc-id:fake
32163     _Primitive-truncate-xreg-to-reg/imm32/next
32164 _Primitive-truncate-xreg-to-reg:  # (payload primitive)
32165     0x11/imm32/alloc-id:fake:payload
32166     # var1/reg <- truncate var2/xreg => f3 0f 2c/truncate-to-int var2/xm32 var1/r32
32167     0x11/imm32/alloc-id:fake
32168     _string-truncate/imm32/name
32169     0x11/imm32/alloc-id:fake
32170     Single-float-var-in-some-register/imm32/inouts
32171     0x11/imm32/alloc-id:fake
32172     Single-int-var-in-some-register/imm32/outputs
32173     0x11/imm32/alloc-id:fake
32174     _string_f3_0f_2c_truncate_to_int/imm32/subx-name
32175     0/imm32/no-rm32
32176     3/imm32/r32-is-first-output
32177     0/imm32/no-imm32
32178     0/imm32/no-imm8
32179     0/imm32/no-disp32
32180     1/imm32/xm32-is-first-inout
32181     0/imm32/no-x32
32182     0x11/imm32/alloc-id:fake
32183     _Primitive-reinterpret-xmem-as-reg/imm32/next
32184 # - reinterpret bytes (just for debugging)
32185 _Primitive-reinterpret-xmem-as-reg:  # (payload primitive)
32186     0x11/imm32/alloc-id:fake:payload
32187     # var1/reg <- reinterpret var2 => 8b/-> var2/xm32 var1/r32
32188     0x11/imm32/alloc-id:fake
32189     _string-reinterpret/imm32/name
32190     0x11/imm32/alloc-id:fake
32191     Single-float-var-in-mem/imm32/inouts
32192     0x11/imm32/alloc-id:fake
32193     Single-int-var-in-some-register/imm32/outputs
32194     0x11/imm32/alloc-id:fake
32195     _string_8b_->/imm32/subx-name
32196     0/imm32/no-rm32
32197     3/imm32/r32-is-first-output
32198     0/imm32/no-imm32
32199     0/imm32/no-imm8
32200     0/imm32/no-disp32
32201     1/imm32/xm32-is-first-inout
32202     0/imm32/no-x32
32203     0x11/imm32/alloc-id:fake
32204     _Primitive-reinterpret-mem-as-xreg/imm32/next
32205 _Primitive-reinterpret-mem-as-xreg:  # (payload primitive)
32206     0x11/imm32/alloc-id:fake:payload
32207     # var1/xreg <- reinterpret var2 => f3 0f 10/-> var2/rm32 var1/x32
32208     0x11/imm32/alloc-id:fake
32209     _string-reinterpret/imm32/name
32210     0x11/imm32/alloc-id:fake
32211     Single-int-var-in-mem/imm32/inouts
32212     0x11/imm32/alloc-id:fake
32213     Single-float-var-in-some-register/imm32/outputs
32214     0x11/imm32/alloc-id:fake
32215     _string_f3_0f_10_copy/imm32/subx-name
32216     1/imm32/rm32-is-first-inout
32217     0/imm32/no-r32
32218     0/imm32/no-imm32
32219     0/imm32/no-imm8
32220     0/imm32/no-disp32
32221     0/imm32/no-xm32
32222     3/imm32/x32-is-first-output
32223     0x11/imm32/alloc-id:fake
32224     _Primitive-copy-xreg-to-xreg/imm32/next
32225 # - floating-point copy
32226 _Primitive-copy-xreg-to-xreg:  # (payload primitive)
32227     0x11/imm32/alloc-id:fake:payload
32228     # var1/xreg <- copy var2/xreg => f3 0f 11/<- var1/xm32 var2/x32
32229     0x11/imm32/alloc-id:fake
32230     _string-copy/imm32/name
32231     0x11/imm32/alloc-id:fake
32232     Single-float-var-in-some-register/imm32/inouts
32233     0x11/imm32/alloc-id:fake
32234     Single-float-var-in-some-register/imm32/outputs
32235     0x11/imm32/alloc-id:fake
32236     _string_f3_0f_11_copy/imm32/subx-name
32237     0/imm32/no-rm32
32238     0/imm32/no-r32
32239     0/imm32/no-imm32
32240     0/imm32/no-imm8
32241     0/imm32/no-disp32
32242     3/imm32/xm32-is-first-output
32243     1/imm32/x32-is-first-inout
32244     0x11/imm32/alloc-id:fake
32245     _Primitive-copy-xreg-to-mem/imm32/next
32246 _Primitive-copy-xreg-to-mem:  # (payload primitive)
32247     0x11/imm32/alloc-id:fake:payload
32248     # copy-to var1 var2/xreg => f3 0f 11/<- var1 var2/x32
32249     0x11/imm32/alloc-id:fake
32250     _string-copy-to/imm32/name
32251     0x11/imm32/alloc-id:fake
32252     Two-args-float-stack-float-reg/imm32/inouts
32253     0/imm32/no-outputs
32254     0/imm32/no-outputs
32255     0x11/imm32/alloc-id:fake
32256     _string_f3_0f_11_copy/imm32/subx-name
32257     0/imm32/no-rm32
32258     0/imm32/no-r32
32259     0/imm32/no-imm32
32260     0/imm32/no-imm8
32261     0/imm32/no-disp32
32262     1/imm32/xm32-is-first-inout
32263     2/imm32/x32-is-second-inout
32264     0x11/imm32/alloc-id:fake
32265     _Primitive-copy-mem-to-xreg/imm32/next
32266 _Primitive-copy-mem-to-xreg:  # (payload primitive)
32267     0x11/imm32/alloc-id:fake:payload
32268     # var1/xreg <- copy var2 => f3 0f 10/-> var2/rm32 var1/x32
32269     0x11/imm32/alloc-id:fake
32270     _string-copy/imm32/name
32271     0x11/imm32/alloc-id:fake
32272     Single-float-var-in-mem/imm32/inouts
32273     0x11/imm32/alloc-id:fake
32274     Single-float-var-in-some-register/imm32/outputs
32275     0x11/imm32/alloc-id:fake
32276     _string_f3_0f_10_copy/imm32/subx-name
32277     0/imm32/no-rm32
32278     0/imm32/no-r32
32279     0/imm32/no-imm32
32280     0/imm32/no-imm8
32281     0/imm32/no-disp32
32282     1/imm32/xm32-is-first-inout
32283     3/imm32/x32-is-first-output
32284     0x11/imm32/alloc-id:fake
32285     _Primitive-address-of-xmem/imm32/next
32286 # - floating-point-address
32287 _Primitive-address-of-xmem:  # (payload primitive)
32288     0x11/imm32/alloc-id:fake:payload
32289     # var1/reg <- address var2 => 8d/copy-address var2/rm32 var1/r32
32290     0x11/imm32/alloc-id:fake
32291     _string-address/imm32/name
32292     0x11/imm32/alloc-id:fake
32293     Single-float-var-in-mem/imm32/inouts
32294     0x11/imm32/alloc-id:fake
32295     Single-addr-var-in-some-register/imm32/outputs
32296     0x11/imm32/alloc-id:fake
32297     _string_8d_copy_address/imm32/subx-name
32298     1/imm32/rm32-is-first-inout
32299     3/imm32/r32-is-first-output
32300     0/imm32/no-imm32
32301     0/imm32/no-imm8
32302     0/imm32/no-disp32
32303     0/imm32/no-xm32
32304     0/imm32/no-x32
32305     0x11/imm32/alloc-id:fake
32306     _Primitive-add-xreg-to-xreg/imm32/next
32307 # - floating-point add
32308 _Primitive-add-xreg-to-xreg:  # (payload primitive)
32309     0x11/imm32/alloc-id:fake:payload
32310     # var1/xreg <- add var2/xreg => f3 0f 58/add var1/xm32 var2/x32
32311     0x11/imm32/alloc-id:fake
32312     _string-add/imm32/name
32313     0x11/imm32/alloc-id:fake
32314     Single-float-var-in-some-register/imm32/inouts
32315     0x11/imm32/alloc-id:fake
32316     Single-float-var-in-some-register/imm32/outputs
32317     0x11/imm32/alloc-id:fake
32318     _string_f3_0f_58_add/imm32/subx-name
32319     0/imm32/no-rm32
32320     0/imm32/no-r32
32321     0/imm32/no-imm32
32322     0/imm32/no-imm8
32323     0/imm32/no-disp32
32324     1/imm32/xm32-is-first-inout
32325     3/imm32/x32-is-first-output
32326     0x11/imm32/alloc-id:fake
32327     _Primitive-add-mem-to-xreg/imm32/next
32328 _Primitive-add-mem-to-xreg:  # (payload primitive)
32329     0x11/imm32/alloc-id:fake:payload
32330     # var1/xreg <- add var2 => f3 0f 58/add var2/xm32 var1/x32
32331     0x11/imm32/alloc-id:fake
32332     _string-add/imm32/name
32333     0x11/imm32/alloc-id:fake
32334     Single-float-var-in-mem/imm32/inouts
32335     0x11/imm32/alloc-id:fake
32336     Single-float-var-in-some-register/imm32/outputs
32337     0x11/imm32/alloc-id:fake
32338     _string_f3_0f_58_add/imm32/subx-name
32339     0/imm32/no-rm32
32340     0/imm32/no-r32
32341     0/imm32/no-imm32
32342     0/imm32/no-imm8
32343     0/imm32/no-disp32
32344     1/imm32/xm32-is-first-inout
32345     3/imm32/x32-is-first-output
32346     0x11/imm32/alloc-id:fake
32347     _Primitive-subtract-xreg-from-xreg/imm32/next
32348 # - floating-point subtract
32349 _Primitive-subtract-xreg-from-xreg:  # (payload primitive)
32350     0x11/imm32/alloc-id:fake:payload
32351     # var1/xreg <- subtract var2/xreg => f3 0f 5c/subtract var1/xm32 var2/x32
32352     0x11/imm32/alloc-id:fake
32353     _string-subtract/imm32/name
32354     0x11/imm32/alloc-id:fake
32355     Single-float-var-in-some-register/imm32/inouts
32356     0x11/imm32/alloc-id:fake
32357     Single-float-var-in-some-register/imm32/outputs
32358     0x11/imm32/alloc-id:fake
32359     _string_f3_0f_5c_subtract/imm32/subx-name
32360     0/imm32/no-rm32
32361     0/imm32/no-r32
32362     0/imm32/no-imm32
32363     0/imm32/no-imm8
32364     0/imm32/no-disp32
32365     1/imm32/xm32-is-first-inout
32366     3/imm32/x32-is-first-output
32367     0x11/imm32/alloc-id:fake
32368     _Primitive-subtract-mem-from-xreg/imm32/next
32369 _Primitive-subtract-mem-from-xreg:  # (payload primitive)
32370     0x11/imm32/alloc-id:fake:payload
32371     # var1/xreg <- subtract var2 => f3 0f 5c/subtract var2/xm32 var1/x32
32372     0x11/imm32/alloc-id:fake
32373     _string-subtract/imm32/name
32374     0x11/imm32/alloc-id:fake
32375     Single-float-var-in-mem/imm32/inouts
32376     0x11/imm32/alloc-id:fake
32377     Single-float-var-in-some-register/imm32/outputs
32378     0x11/imm32/alloc-id:fake
32379     _string_f3_0f_5c_subtract/imm32/subx-name
32380     0/imm32/no-rm32
32381     0/imm32/no-r32
32382     0/imm32/no-imm32
32383     0/imm32/no-imm8
32384     0/imm32/no-disp32
32385     1/imm32/xm32-is-first-inout
32386     3/imm32/x32-is-first-output
32387     0x11/imm32/alloc-id:fake
32388     _Primitive-multiply-xreg-by-xreg/imm32/next
32389 # - floating-point multiply
32390 _Primitive-multiply-xreg-by-xreg:  # (payload primitive)
32391     0x11/imm32/alloc-id:fake:payload
32392     # var1/xreg <- multiply var2 => f3 0f 59/multiply var2/xm32 var1/x32
32393     0x11/imm32/alloc-id:fake
32394     _string-multiply/imm32/name
32395     0x11/imm32/alloc-id:fake
32396     Single-float-var-in-some-register/imm32/inouts
32397     0x11/imm32/alloc-id:fake
32398     Single-float-var-in-some-register/imm32/outputs
32399     0x11/imm32/alloc-id:fake
32400     _string_f3_0f_59_multiply/imm32/subx-name
32401     0/imm32/no-rm32
32402     0/imm32/no-r32
32403     0/imm32/no-imm32
32404     0/imm32/no-imm8
32405     0/imm32/no-disp32
32406     1/imm32/xm32-is-first-inout
32407     3/imm32/x32-is-first-output
32408     0x11/imm32/alloc-id:fake
32409     _Primitive-multiply-xreg-by-mem/imm32/next
32410 _Primitive-multiply-xreg-by-mem:  # (payload primitive)
32411     0x11/imm32/alloc-id:fake:payload
32412     # var1/xreg <- multiply var2 => 53 0f 59/multiply var2/xm32 var1/x32
32413     0x11/imm32/alloc-id:fake
32414     _string-multiply/imm32/name
32415     0x11/imm32/alloc-id:fake
32416     Single-float-var-in-mem/imm32/inouts
32417     0x11/imm32/alloc-id:fake
32418     Single-float-var-in-some-register/imm32/outputs
32419     0x11/imm32/alloc-id:fake
32420     _string_f3_0f_59_multiply/imm32/subx-name
32421     0/imm32/no-rm32
32422     0/imm32/no-r32
32423     0/imm32/no-imm32
32424     0/imm32/no-imm8
32425     0/imm32/no-disp32
32426     1/imm32/xm32-is-first-inout
32427     3/imm32/x32-is-first-output
32428     0x11/imm32/alloc-id:fake
32429     _Primitive-divide-xreg-by-xreg/imm32/next
32430 # - floating-point divide
32431 _Primitive-divide-xreg-by-xreg:  # (payload primitive)
32432     0x11/imm32/alloc-id:fake:payload
32433     # var1/xreg <- divide var2 => f3 0f 5e/divide var2/xm32 var1/x32
32434     0x11/imm32/alloc-id:fake
32435     _string-divide/imm32/name
32436     0x11/imm32/alloc-id:fake
32437     Single-float-var-in-some-register/imm32/inouts
32438     0x11/imm32/alloc-id:fake
32439     Single-float-var-in-some-register/imm32/outputs
32440     0x11/imm32/alloc-id:fake
32441     _string_f3_0f_5e_divide/imm32/subx-name
32442     0/imm32/no-rm32
32443     0/imm32/no-r32
32444     0/imm32/no-imm32
32445     0/imm32/no-imm8
32446     0/imm32/no-disp32
32447     1/imm32/xm32-is-first-inout
32448     3/imm32/x32-is-first-output
32449     0x11/imm32/alloc-id:fake
32450     _Primitive-divide-xreg-by-mem/imm32/next
32451 _Primitive-divide-xreg-by-mem:  # (payload primitive)
32452     0x11/imm32/alloc-id:fake:payload
32453     # var1/xreg <- divide var2 => f3 0f 5e/divide var2/xm32 var1/x32
32454     0x11/imm32/alloc-id:fake
32455     _string-divide/imm32/name
32456     0x11/imm32/alloc-id:fake
32457     Single-float-var-in-mem/imm32/inouts
32458     0x11/imm32/alloc-id:fake
32459     Single-float-var-in-some-register/imm32/outputs
32460     0x11/imm32/alloc-id:fake
32461     _string_f3_0f_5e_divide/imm32/subx-name
32462     0/imm32/no-rm32
32463     0/imm32/no-r32
32464     0/imm32/no-imm32
32465     0/imm32/no-imm8
32466     0/imm32/no-disp32
32467     1/imm32/xm32-is-first-inout
32468     3/imm32/x32-is-first-output
32469     0x11/imm32/alloc-id:fake
32470     _Primitive-max-xreg-with-xreg/imm32/next
32471 # - floating-point maximum
32472 _Primitive-max-xreg-with-xreg:  # (payload primitive)
32473     0x11/imm32/alloc-id:fake:payload
32474     # var1/xreg <- max var2 => f3 0f 5f/max var2/xm32 var1/x32
32475     0x11/imm32/alloc-id:fake
32476     _string-max/imm32/name
32477     0x11/imm32/alloc-id:fake
32478     Single-float-var-in-some-register/imm32/inouts
32479     0x11/imm32/alloc-id:fake
32480     Single-float-var-in-some-register/imm32/outputs
32481     0x11/imm32/alloc-id:fake
32482     _string_f3_0f_5f_max/imm32/subx-name
32483     0/imm32/no-rm32
32484     0/imm32/no-r32
32485     0/imm32/no-imm32
32486     0/imm32/no-imm8
32487     0/imm32/no-disp32
32488     1/imm32/xm32-is-first-inout
32489     3/imm32/x32-is-first-output
32490     0x11/imm32/alloc-id:fake
32491     _Primitive-max-xreg-with-mem/imm32/next
32492 _Primitive-max-xreg-with-mem:  # (payload primitive)
32493     0x11/imm32/alloc-id:fake:payload
32494     # var1/xreg <- divide var2 => f3 0f 5f/max var2/xm32 var1/x32
32495     0x11/imm32/alloc-id:fake
32496     _string-max/imm32/name
32497     0x11/imm32/alloc-id:fake
32498     Single-float-var-in-mem/imm32/inouts
32499     0x11/imm32/alloc-id:fake
32500     Single-float-var-in-some-register/imm32/outputs
32501     0x11/imm32/alloc-id:fake
32502     _string_f3_0f_5f_max/imm32/subx-name
32503     0/imm32/no-rm32
32504     0/imm32/no-r32
32505     0/imm32/no-imm32
32506     0/imm32/no-imm8
32507     0/imm32/no-disp32
32508     1/imm32/xm32-is-first-inout
32509     3/imm32/x32-is-first-output
32510     0x11/imm32/alloc-id:fake
32511     _Primitive-min-xreg-with-xreg/imm32/next
32512 # - floating-point minimum
32513 _Primitive-min-xreg-with-xreg:  # (payload primitive)
32514     0x11/imm32/alloc-id:fake:payload
32515     # var1/xreg <- divide var2 => f3 0f 5d/min var2/xm32 var1/x32
32516     0x11/imm32/alloc-id:fake
32517     _string-min/imm32/name
32518     0x11/imm32/alloc-id:fake
32519     Single-float-var-in-some-register/imm32/inouts
32520     0x11/imm32/alloc-id:fake
32521     Single-float-var-in-some-register/imm32/outputs
32522     0x11/imm32/alloc-id:fake
32523     _string_f3_0f_5d_min/imm32/subx-name
32524     0/imm32/no-rm32
32525     0/imm32/no-r32
32526     0/imm32/no-imm32
32527     0/imm32/no-imm8
32528     0/imm32/no-disp32
32529     1/imm32/xm32-is-first-inout
32530     3/imm32/x32-is-first-output
32531     0x11/imm32/alloc-id:fake
32532     _Primitive-min-xreg-with-mem/imm32/next
32533 _Primitive-min-xreg-with-mem:  # (payload primitive)
32534     0x11/imm32/alloc-id:fake:payload
32535     # var1/xreg <- divide var2 => f3 0f 5d/min var2/xm32 var1/x32
32536     0x11/imm32/alloc-id:fake
32537     _string-min/imm32/name
32538     0x11/imm32/alloc-id:fake
32539     Single-float-var-in-mem/imm32/inouts
32540     0x11/imm32/alloc-id:fake
32541     Single-float-var-in-some-register/imm32/outputs
32542     0x11/imm32/alloc-id:fake
32543     _string_f3_0f_5d_min/imm32/subx-name
32544     0/imm32/no-rm32
32545     0/imm32/no-r32
32546     0/imm32/no-imm32
32547     0/imm32/no-imm8
32548     0/imm32/no-disp32
32549     1/imm32/xm32-is-first-inout
32550     3/imm32/x32-is-first-output
32551     0x11/imm32/alloc-id:fake
32552     _Primitive-reciprocal-xreg-to-xreg/imm32/next
32553 # - floating-point reciprocal
32554 _Primitive-reciprocal-xreg-to-xreg:  # (payload primitive)
32555     0x11/imm32/alloc-id:fake:payload
32556     # var1/xreg <- reciprocal var2 => f3 0f 53/reciprocal var2/xm32 var1/x32
32557     0x11/imm32/alloc-id:fake
32558     _string-reciprocal/imm32/name
32559     0x11/imm32/alloc-id:fake
32560     Single-float-var-in-some-register/imm32/inouts
32561     0x11/imm32/alloc-id:fake
32562     Single-float-var-in-some-register/imm32/outputs
32563     0x11/imm32/alloc-id:fake
32564     _string_f3_0f_53_reciprocal/imm32/subx-name
32565     0/imm32/no-rm32
32566     0/imm32/no-r32
32567     0/imm32/no-imm32
32568     0/imm32/no-imm8
32569     0/imm32/no-disp32
32570     1/imm32/xm32-is-first-inout
32571     3/imm32/x32-is-first-output
32572     0x11/imm32/alloc-id:fake
32573     _Primitive-reciprocal-mem-to-xreg/imm32/next
32574 _Primitive-reciprocal-mem-to-xreg:  # (payload primitive)
32575     0x11/imm32/alloc-id:fake:payload
32576     # var1/xreg <- divide var2 => f3 0f 53/reciprocal var2/xm32 var1/x32
32577     0x11/imm32/alloc-id:fake
32578     _string-reciprocal/imm32/name
32579     0x11/imm32/alloc-id:fake
32580     Single-float-var-in-mem/imm32/inouts
32581     0x11/imm32/alloc-id:fake
32582     Single-float-var-in-some-register/imm32/outputs
32583     0x11/imm32/alloc-id:fake
32584     _string_f3_0f_53_reciprocal/imm32/subx-name
32585     0/imm32/no-rm32
32586     0/imm32/no-r32
32587     0/imm32/no-imm32
32588     0/imm32/no-imm8
32589     0/imm32/no-disp32
32590     1/imm32/xm32-is-first-inout
32591     3/imm32/x32-is-first-output
32592     0x11/imm32/alloc-id:fake
32593     _Primitive-square-root-xreg-to-xreg/imm32/next
32594 # - floating-point square root
32595 _Primitive-square-root-xreg-to-xreg:  # (payload primitive)
32596     0x11/imm32/alloc-id:fake:payload
32597     # var1/xreg <- square-root var2 => f3 0f 51/square-root var2/xm32 var1/x32
32598     0x11/imm32/alloc-id:fake
32599     _string-square-root/imm32/name
32600     0x11/imm32/alloc-id:fake
32601     Single-float-var-in-some-register/imm32/inouts
32602     0x11/imm32/alloc-id:fake
32603     Single-float-var-in-some-register/imm32/outputs
32604     0x11/imm32/alloc-id:fake
32605     _string_f3_0f_51_square_root/imm32/subx-name
32606     0/imm32/no-rm32
32607     0/imm32/no-r32
32608     0/imm32/no-imm32
32609     0/imm32/no-imm8
32610     0/imm32/no-disp32
32611     1/imm32/xm32-is-first-inout
32612     3/imm32/x32-is-first-output
32613     0x11/imm32/alloc-id:fake
32614     _Primitive-square-root-mem-to-xreg/imm32/next
32615 _Primitive-square-root-mem-to-xreg:  # (payload primitive)
32616     0x11/imm32/alloc-id:fake:payload
32617     # var1/xreg <- divide var2 => f3 0f 51/square-root var2/xm32 var1/x32
32618     0x11/imm32/alloc-id:fake
32619     _string-square-root/imm32/name
32620     0x11/imm32/alloc-id:fake
32621     Single-float-var-in-mem/imm32/inouts
32622     0x11/imm32/alloc-id:fake
32623     Single-float-var-in-some-register/imm32/outputs
32624     0x11/imm32/alloc-id:fake
32625     _string_f3_0f_51_square_root/imm32/subx-name
32626     0/imm32/no-rm32
32627     0/imm32/no-r32
32628     0/imm32/no-imm32
32629     0/imm32/no-imm8
32630     0/imm32/no-disp32
32631     1/imm32/xm32-is-first-inout
32632     3/imm32/x32-is-first-output
32633     0x11/imm32/alloc-id:fake
32634     _Primitive-inverse-square-root-xreg-to-xreg/imm32/next
32635 # - floating-point inverse square root 1/sqrt(x)
32636 _Primitive-inverse-square-root-xreg-to-xreg:  # (payload primitive)
32637     0x11/imm32/alloc-id:fake:payload
32638     # var1/xreg <- reciprocal var2 => f3 0f 52/inverse-square-root var2/xm32 var1/x32
32639     0x11/imm32/alloc-id:fake
32640     _string-inverse-square-root/imm32/name
32641     0x11/imm32/alloc-id:fake
32642     Single-float-var-in-some-register/imm32/inouts
32643     0x11/imm32/alloc-id:fake
32644     Single-float-var-in-some-register/imm32/outputs
32645     0x11/imm32/alloc-id:fake
32646     _string_f3_0f_52_inverse_square_root/imm32/subx-name
32647     0/imm32/no-rm32
32648     0/imm32/no-r32
32649     0/imm32/no-imm32
32650     0/imm32/no-imm8
32651     0/imm32/no-disp32
32652     1/imm32/xm32-is-first-inout
32653     3/imm32/x32-is-first-output
32654     0x11/imm32/alloc-id:fake
32655     _Primitive-inverse-square-root-mem-to-xreg/imm32/next
32656 _Primitive-inverse-square-root-mem-to-xreg:  # (payload primitive)
32657     0x11/imm32/alloc-id:fake:payload
32658     # var1/xreg <- divide var2 => f3 0f 52/inverse-square-root var2/xm32 var1/x32
32659     0x11/imm32/alloc-id:fake
32660     _string-inverse-square-root/imm32/name
32661     0x11/imm32/alloc-id:fake
32662     Single-float-var-in-mem/imm32/inouts
32663     0x11/imm32/alloc-id:fake
32664     Single-float-var-in-some-register/imm32/outputs
32665     0x11/imm32/alloc-id:fake
32666     _string_f3_0f_52_inverse_square_root/imm32/subx-name
32667     0/imm32/no-rm32
32668     0/imm32/no-r32
32669     0/imm32/no-imm32
32670     0/imm32/no-imm8
32671     0/imm32/no-disp32
32672     1/imm32/xm32-is-first-inout
32673     3/imm32/x32-is-first-output
32674     0x11/imm32/alloc-id:fake
32675     _Primitive-compare-xreg-with-xreg/imm32/next
32676 # - floating-point compare
32677 _Primitive-compare-xreg-with-xreg:  # (payload primitive)
32678     0x11/imm32/alloc-id:fake:payload
32679     # compare var1/reg1 var2/reg2 => 0f 2f/compare var2/x32 var1/xm32
32680     0x11/imm32/alloc-id:fake
32681     _string-compare/imm32/name
32682     0x11/imm32/alloc-id:fake
32683     Two-float-args-in-regs/imm32/inouts
32684     0/imm32/no-outputs
32685     0/imm32/no-outputs
32686     0x11/imm32/alloc-id:fake
32687     _string_0f_2f_compare/imm32/subx-name
32688     0/imm32/no-rm32
32689     0/imm32/no-r32
32690     0/imm32/no-imm32
32691     0/imm32/no-imm8
32692     0/imm32/no-disp32
32693     2/imm32/xm32-is-second-inout
32694     1/imm32/x32-is-first-inout
32695     0x11/imm32/alloc-id:fake
32696     _Primitive-compare-xreg-with-mem/imm32/next
32697 _Primitive-compare-xreg-with-mem:  # (payload primitive)
32698     0x11/imm32/alloc-id:fake:payload
32699     # compare var1/xreg var2 => 0f 2f/compare var1/x32 var2/xm32
32700     0x11/imm32/alloc-id:fake
32701     _string-compare/imm32/name
32702     0x11/imm32/alloc-id:fake
32703     Two-args-float-reg-float-stack/imm32/inouts
32704     0/imm32/no-outputs
32705     0/imm32/no-outputs
32706     0x11/imm32/alloc-id:fake
32707     _string_0f_2f_compare/imm32/subx-name
32708     0/imm32/no-rm32
32709     0/imm32/no-r32
32710     0/imm32/no-imm32
32711     0/imm32/no-imm8
32712     0/imm32/no-disp32
32713     2/imm32/xm32-is-second-inout
32714     1/imm32/x32-is-first-inout
32715     0x11/imm32/alloc-id:fake
32716     _Primitive-break-if-addr</imm32/next
32717 # - branches
32718 _Primitive-break-if-addr<:  # (payload primitive)
32719     0x11/imm32/alloc-id:fake:payload
32720     0x11/imm32/alloc-id:fake
32721     _string-break-if-addr</imm32/name
32722     0/imm32/no-inouts
32723     0/imm32/no-inouts
32724     0/imm32/no-outputs
32725     0/imm32/no-outputs
32726     0x11/imm32/alloc-id:fake
32727     _string_0f_82_jump_break/imm32/subx-name
32728     0/imm32/no-rm32
32729     0/imm32/no-r32
32730     0/imm32/no-imm32
32731     0/imm32/no-imm8
32732     0/imm32/no-disp32
32733     0/imm32/no-xm32
32734     0/imm32/no-x32
32735     0x11/imm32/alloc-id:fake
32736     _Primitive-break-if-addr>=/imm32/next
32737 _Primitive-break-if-addr>=:  # (payload primitive)
32738     0x11/imm32/alloc-id:fake:payload
32739     0x11/imm32/alloc-id:fake
32740     _string-break-if-addr>=/imm32/name
32741     0/imm32/no-inouts
32742     0/imm32/no-inouts
32743     0/imm32/no-outputs
32744     0/imm32/no-outputs
32745     0x11/imm32/alloc-id:fake
32746     _string_0f_83_jump_break/imm32/subx-name
32747     0/imm32/no-rm32
32748     0/imm32/no-r32
32749     0/imm32/no-imm32
32750     0/imm32/no-imm8
32751     0/imm32/no-disp32
32752     0/imm32/no-xm32
32753     0/imm32/no-x32
32754     0x11/imm32/alloc-id:fake
32755     _Primitive-break-if-=/imm32/next
32756 _Primitive-break-if-=:  # (payload primitive)
32757     0x11/imm32/alloc-id:fake:payload
32758     0x11/imm32/alloc-id:fake
32759     _string-break-if-=/imm32/name
32760     0/imm32/no-inouts
32761     0/imm32/no-inouts
32762     0/imm32/no-outputs
32763     0/imm32/no-outputs
32764     0x11/imm32/alloc-id:fake
32765     _string_0f_84_jump_break/imm32/subx-name
32766     0/imm32/no-rm32
32767     0/imm32/no-r32
32768     0/imm32/no-imm32
32769     0/imm32/no-imm8
32770     0/imm32/no-disp32
32771     0/imm32/no-xm32
32772     0/imm32/no-x32
32773     0x11/imm32/alloc-id:fake
32774     _Primitive-break-if-!=/imm32/next
32775 _Primitive-break-if-!=:  # (payload primitive)
32776     0x11/imm32/alloc-id:fake:payload
32777     0x11/imm32/alloc-id:fake
32778     _string-break-if-!=/imm32/name
32779     0/imm32/no-inouts
32780     0/imm32/no-inouts
32781     0/imm32/no-outputs
32782     0/imm32/no-outputs
32783     0x11/imm32/alloc-id:fake
32784     _string_0f_85_jump_break/imm32/subx-name
32785     0/imm32/no-rm32
32786     0/imm32/no-r32
32787     0/imm32/no-imm32
32788     0/imm32/no-imm8
32789     0/imm32/no-disp32
32790     0/imm32/no-xm32
32791     0/imm32/no-x32
32792     0x11/imm32/alloc-id:fake
32793     _Primitive-break-if-addr<=/imm32/next
32794 _Primitive-break-if-addr<=:  # (payload primitive)
32795     0x11/imm32/alloc-id:fake:payload
32796     0x11/imm32/alloc-id:fake
32797     _string-break-if-addr<=/imm32/name
32798     0/imm32/no-inouts
32799     0/imm32/no-inouts
32800     0/imm32/no-outputs
32801     0/imm32/no-outputs
32802     0x11/imm32/alloc-id:fake
32803     _string_0f_86_jump_break/imm32/subx-name
32804     0/imm32/no-rm32
32805     0/imm32/no-r32
32806     0/imm32/no-imm32
32807     0/imm32/no-imm8
32808     0/imm32/no-disp32
32809     0/imm32/no-xm32
32810     0/imm32/no-x32
32811     0x11/imm32/alloc-id:fake
32812     _Primitive-break-if-addr>/imm32/next
32813 _Primitive-break-if-addr>:  # (payload primitive)
32814     0x11/imm32/alloc-id:fake:payload
32815     0x11/imm32/alloc-id:fake
32816     _string-break-if-addr>/imm32/name
32817     0/imm32/no-inouts
32818     0/imm32/no-inouts
32819     0/imm32/no-outputs
32820     0/imm32/no-outputs
32821     0x11/imm32/alloc-id:fake
32822     _string_0f_87_jump_break/imm32/subx-name
32823     0/imm32/no-rm32
32824     0/imm32/no-r32
32825     0/imm32/no-imm32
32826     0/imm32/no-imm8
32827     0/imm32/no-disp32
32828     0/imm32/no-xm32
32829     0/imm32/no-x32
32830     0x11/imm32/alloc-id:fake
32831     _Primitive-break-if-</imm32/next
32832 _Primitive-break-if-<:  # (payload primitive)
32833     0x11/imm32/alloc-id:fake:payload
32834     0x11/imm32/alloc-id:fake
32835     _string-break-if-</imm32/name
32836     0/imm32/no-inouts
32837     0/imm32/no-inouts
32838     0/imm32/no-outputs
32839     0/imm32/no-outputs
32840     0x11/imm32/alloc-id:fake
32841     _string_0f_8c_jump_break/imm32/subx-name
32842     0/imm32/no-rm32
32843     0/imm32/no-r32
32844     0/imm32/no-imm32
32845     0/imm32/no-imm8
32846     0/imm32/no-disp32
32847     0/imm32/no-xm32
32848     0/imm32/no-x32
32849     0x11/imm32/alloc-id:fake
32850     _Primitive-break-if->=/imm32/next
32851 _Primitive-break-if->=:  # (payload primitive)
32852     0x11/imm32/alloc-id:fake:payload
32853     0x11/imm32/alloc-id:fake
32854     _string-break-if->=/imm32/name
32855     0/imm32/no-inouts
32856     0/imm32/no-inouts
32857     0/imm32/no-outputs
32858     0/imm32/no-outputs
32859     0x11/imm32/alloc-id:fake
32860     _string_0f_8d_jump_break/imm32/subx-name
32861     0/imm32/no-rm32
32862     0/imm32/no-r32
32863     0/imm32/no-imm32
32864     0/imm32/no-imm8
32865     0/imm32/no-disp32
32866     0/imm32/no-xm32
32867     0/imm32/no-x32
32868     0x11/imm32/alloc-id:fake
32869     _Primitive-break-if-<=/imm32/next
32870 _Primitive-break-if-<=:  # (payload primitive)
32871     0x11/imm32/alloc-id:fake:payload
32872     0x11/imm32/alloc-id:fake
32873     _string-break-if-<=/imm32/name
32874     0/imm32/no-inouts
32875     0/imm32/no-inouts
32876     0/imm32/no-outputs
32877     0/imm32/no-outputs
32878     0x11/imm32/alloc-id:fake
32879     _string_0f_8e_jump_break/imm32/subx-name
32880     0/imm32/no-rm32
32881     0/imm32/no-r32
32882     0/imm32/no-imm32
32883     0/imm32/no-imm8
32884     0/imm32/no-disp32
32885     0/imm32/no-xm32
32886     0/imm32/no-x32
32887     0x11/imm32/alloc-id:fake
32888     _Primitive-break-if->/imm32/next
32889 _Primitive-break-if->:  # (payload primitive)
32890     0x11/imm32/alloc-id:fake:payload
32891     0x11/imm32/alloc-id:fake
32892     _string-break-if->/imm32/name
32893     0/imm32/no-inouts
32894     0/imm32/no-inouts
32895     0/imm32/no-outputs
32896     0/imm32/no-outputs
32897     0x11/imm32/alloc-id:fake
32898     _string_0f_8f_jump_break/imm32/subx-name
32899     0/imm32/no-rm32
32900     0/imm32/no-r32
32901     0/imm32/no-imm32
32902     0/imm32/no-imm8
32903     0/imm32/no-disp32
32904     0/imm32/no-xm32
32905     0/imm32/no-x32
32906     0x11/imm32/alloc-id:fake
32907     _Primitive-break-if-carry/imm32/next
32908 _Primitive-break-if-carry:  # (payload primitive)
32909     0x11/imm32/alloc-id:fake:payload
32910     0x11/imm32/alloc-id:fake
32911     _string-break-if-carry/imm32/name
32912     0/imm32/no-inouts
32913     0/imm32/no-inouts
32914     0/imm32/no-outputs
32915     0/imm32/no-outputs
32916     0x11/imm32/alloc-id:fake
32917     _string_0f_82_jump_break/imm32/subx-name
32918     0/imm32/no-rm32
32919     0/imm32/no-r32
32920     0/imm32/no-imm32
32921     0/imm32/no-imm8
32922     0/imm32/no-disp32
32923     0/imm32/no-xm32
32924     0/imm32/no-x32
32925     0x11/imm32/alloc-id:fake
32926     _Primitive-break-if-not-carry/imm32/next
32927 _Primitive-break-if-not-carry:  # (payload primitive)
32928     0x11/imm32/alloc-id:fake:payload
32929     0x11/imm32/alloc-id:fake
32930     _string-break-if-not-carry/imm32/name
32931     0/imm32/no-inouts
32932     0/imm32/no-inouts
32933     0/imm32/no-outputs
32934     0/imm32/no-outputs
32935     0x11/imm32/alloc-id:fake
32936     _string_0f_83_jump_break/imm32/subx-name
32937     0/imm32/no-rm32
32938     0/imm32/no-r32
32939     0/imm32/no-imm32
32940     0/imm32/no-imm8
32941     0/imm32/no-disp32
32942     0/imm32/no-xm32
32943     0/imm32/no-x32
32944     0x11/imm32/alloc-id:fake
32945     _Primitive-break-if-overflow/imm32/next
32946 _Primitive-break-if-overflow:  # (payload primitive)
32947     0x11/imm32/alloc-id:fake:payload
32948     0x11/imm32/alloc-id:fake
32949     _string-break-if-overflow/imm32/name
32950     0/imm32/no-inouts
32951     0/imm32/no-inouts
32952     0/imm32/no-outputs
32953     0/imm32/no-outputs
32954     0x11/imm32/alloc-id:fake
32955     _string_0f_80_jump_break/imm32/subx-name
32956     0/imm32/no-rm32
32957     0/imm32/no-r32
32958     0/imm32/no-imm32
32959     0/imm32/no-imm8
32960     0/imm32/no-disp32
32961     0/imm32/no-xm32
32962     0/imm32/no-x32
32963     0x11/imm32/alloc-id:fake
32964     _Primitive-break-if-not-overflow/imm32/next
32965 _Primitive-break-if-not-overflow:  # (payload primitive)
32966     0x11/imm32/alloc-id:fake:payload
32967     0x11/imm32/alloc-id:fake
32968     _string-break-if-not-overflow/imm32/name
32969     0/imm32/no-inouts
32970     0/imm32/no-inouts
32971     0/imm32/no-outputs
32972     0/imm32/no-outputs
32973     0x11/imm32/alloc-id:fake
32974     _string_0f_81_jump_break/imm32/subx-name
32975     0/imm32/no-rm32
32976     0/imm32/no-r32
32977     0/imm32/no-imm32
32978     0/imm32/no-imm8
32979     0/imm32/no-disp32
32980     0/imm32/no-xm32
32981     0/imm32/no-x32
32982     0x11/imm32/alloc-id:fake
32983     _Primitive-break/imm32/next
32984 _Primitive-break:  # (payload primitive)
32985     0x11/imm32/alloc-id:fake:payload
32986     0x11/imm32/alloc-id:fake
32987     _string-break/imm32/name
32988     0/imm32/no-inouts
32989     0/imm32/no-inouts
32990     0/imm32/no-outputs
32991     0/imm32/no-outputs
32992     0x11/imm32/alloc-id:fake
32993     _string_e9_jump_break/imm32/subx-name
32994     0/imm32/no-rm32
32995     0/imm32/no-r32
32996     0/imm32/no-imm32
32997     0/imm32/no-imm8
32998     0/imm32/no-disp32
32999     0/imm32/no-xm32
33000     0/imm32/no-x32
33001     0x11/imm32/alloc-id:fake
33002     _Primitive-loop-if-addr</imm32/next
33003 _Primitive-loop-if-addr<:  # (payload primitive)
33004     0x11/imm32/alloc-id:fake:payload
33005     0x11/imm32/alloc-id:fake
33006     _string-loop-if-addr</imm32/name
33007     0/imm32/no-inouts
33008     0/imm32/no-inouts
33009     0/imm32/no-outputs
33010     0/imm32/no-outputs
33011     0x11/imm32/alloc-id:fake
33012     _string_0f_82_jump_loop/imm32/subx-name
33013     0/imm32/no-rm32
33014     0/imm32/no-r32
33015     0/imm32/no-imm32
33016     0/imm32/no-imm8
33017     0/imm32/no-disp32
33018     0/imm32/no-xm32
33019     0/imm32/no-x32
33020     0x11/imm32/alloc-id:fake
33021     _Primitive-loop-if-addr>=/imm32/next
33022 _Primitive-loop-if-addr>=:  # (payload primitive)
33023     0x11/imm32/alloc-id:fake:payload
33024     0x11/imm32/alloc-id:fake
33025     _string-loop-if-addr>=/imm32/name
33026     0/imm32/no-inouts
33027     0/imm32/no-inouts
33028     0/imm32/no-outputs
33029     0/imm32/no-outputs
33030     0x11/imm32/alloc-id:fake
33031     _string_0f_83_jump_loop/imm32/subx-name
33032     0/imm32/no-rm32
33033     0/imm32/no-r32
33034     0/imm32/no-imm32
33035     0/imm32/no-imm8
33036     0/imm32/no-disp32
33037     0/imm32/no-xm32
33038     0/imm32/no-x32
33039     0x11/imm32/alloc-id:fake
33040     _Primitive-loop-if-=/imm32/next
33041 _Primitive-loop-if-=:  # (payload primitive)
33042     0x11/imm32/alloc-id:fake:payload
33043     0x11/imm32/alloc-id:fake
33044     _string-loop-if-=/imm32/name
33045     0/imm32/no-inouts
33046     0/imm32/no-inouts
33047     0/imm32/no-outputs
33048     0/imm32/no-outputs
33049     0x11/imm32/alloc-id:fake
33050     _string_0f_84_jump_loop/imm32/subx-name
33051     0/imm32/no-rm32
33052     0/imm32/no-r32
33053     0/imm32/no-imm32
33054     0/imm32/no-imm8
33055     0/imm32/no-disp32
33056     0/imm32/no-xm32
33057     0/imm32/no-x32
33058     0x11/imm32/alloc-id:fake
33059     _Primitive-loop-if-!=/imm32/next
33060 _Primitive-loop-if-!=:  # (payload primitive)
33061     0x11/imm32/alloc-id:fake:payload
33062     0x11/imm32/alloc-id:fake
33063     _string-loop-if-!=/imm32/name
33064     0/imm32/no-inouts
33065     0/imm32/no-inouts
33066     0/imm32/no-outputs
33067     0/imm32/no-outputs
33068     0x11/imm32/alloc-id:fake
33069     _string_0f_85_jump_loop/imm32/subx-name
33070     0/imm32/no-rm32
33071     0/imm32/no-r32
33072     0/imm32/no-imm32
33073     0/imm32/no-imm8
33074     0/imm32/no-disp32
33075     0/imm32/no-xm32
33076     0/imm32/no-x32
33077     0x11/imm32/alloc-id:fake
33078     _Primitive-loop-if-addr<=/imm32/next
33079 _Primitive-loop-if-addr<=:  # (payload primitive)
33080     0x11/imm32/alloc-id:fake:payload
33081     0x11/imm32/alloc-id:fake
33082     _string-loop-if-addr<=/imm32/name
33083     0/imm32/no-inouts
33084     0/imm32/no-inouts
33085     0/imm32/no-outputs
33086     0/imm32/no-outputs
33087     0x11/imm32/alloc-id:fake
33088     _string_0f_86_jump_loop/imm32/subx-name
33089     0/imm32/no-rm32
33090     0/imm32/no-r32
33091     0/imm32/no-imm32
33092     0/imm32/no-imm8
33093     0/imm32/no-disp32
33094     0/imm32/no-xm32
33095     0/imm32/no-x32
33096     0x11/imm32/alloc-id:fake
33097     _Primitive-loop-if-addr>/imm32/next
33098 _Primitive-loop-if-addr>:  # (payload primitive)
33099     0x11/imm32/alloc-id:fake:payload
33100     0x11/imm32/alloc-id:fake
33101     _string-loop-if-addr>/imm32/name
33102     0/imm32/no-inouts
33103     0/imm32/no-inouts
33104     0/imm32/no-outputs
33105     0/imm32/no-outputs
33106     0x11/imm32/alloc-id:fake
33107     _string_0f_87_jump_loop/imm32/subx-name
33108     0/imm32/no-rm32
33109     0/imm32/no-r32
33110     0/imm32/no-imm32
33111     0/imm32/no-imm8
33112     0/imm32/no-disp32
33113     0/imm32/no-xm32
33114     0/imm32/no-x32
33115     0x11/imm32/alloc-id:fake
33116     _Primitive-loop-if-</imm32/next
33117 _Primitive-loop-if-<:  # (payload primitive)
33118     0x11/imm32/alloc-id:fake:payload
33119     0x11/imm32/alloc-id:fake
33120     _string-loop-if-</imm32/name
33121     0/imm32/no-inouts
33122     0/imm32/no-inouts
33123     0/imm32/no-outputs
33124     0/imm32/no-outputs
33125     0x11/imm32/alloc-id:fake
33126     _string_0f_8c_jump_loop/imm32/subx-name
33127     0/imm32/no-rm32
33128     0/imm32/no-r32
33129     0/imm32/no-imm32
33130     0/imm32/no-imm8
33131     0/imm32/no-disp32
33132     0/imm32/no-xm32
33133     0/imm32/no-x32
33134     0x11/imm32/alloc-id:fake
33135     _Primitive-loop-if->=/imm32/next
33136 _Primitive-loop-if->=:  # (payload primitive)
33137     0x11/imm32/alloc-id:fake:payload
33138     0x11/imm32/alloc-id:fake
33139     _string-loop-if->=/imm32/name
33140     0/imm32/no-inouts
33141     0/imm32/no-inouts
33142     0/imm32/no-outputs
33143     0/imm32/no-outputs
33144     0x11/imm32/alloc-id:fake
33145     _string_0f_8d_jump_loop/imm32/subx-name
33146     0/imm32/no-rm32
33147     0/imm32/no-r32
33148     0/imm32/no-imm32
33149     0/imm32/no-imm8
33150     0/imm32/no-disp32
33151     0/imm32/no-xm32
33152     0/imm32/no-x32
33153     0x11/imm32/alloc-id:fake
33154     _Primitive-loop-if-<=/imm32/next
33155 _Primitive-loop-if-<=:  # (payload primitive)
33156     0x11/imm32/alloc-id:fake:payload
33157     0x11/imm32/alloc-id:fake
33158     _string-loop-if-<=/imm32/name
33159     0/imm32/no-inouts
33160     0/imm32/no-inouts
33161     0/imm32/no-outputs
33162     0/imm32/no-outputs
33163     0x11/imm32/alloc-id:fake
33164     _string_0f_8e_jump_loop/imm32/subx-name
33165     0/imm32/no-rm32
33166     0/imm32/no-r32
33167     0/imm32/no-imm32
33168     0/imm32/no-imm8
33169     0/imm32/no-disp32
33170     0/imm32/no-xm32
33171     0/imm32/no-x32
33172     0x11/imm32/alloc-id:fake
33173     _Primitive-loop-if->/imm32/next
33174 _Primitive-loop-if->:  # (payload primitive)
33175     0x11/imm32/alloc-id:fake:payload
33176     0x11/imm32/alloc-id:fake
33177     _string-loop-if->/imm32/name
33178     0/imm32/no-inouts
33179     0/imm32/no-inouts
33180     0/imm32/no-outputs
33181     0/imm32/no-outputs
33182     0x11/imm32/alloc-id:fake
33183     _string_0f_8f_jump_loop/imm32/subx-name
33184     0/imm32/no-rm32
33185     0/imm32/no-r32
33186     0/imm32/no-imm32
33187     0/imm32/no-imm8
33188     0/imm32/no-disp32
33189     0/imm32/no-xm32
33190     0/imm32/no-x32
33191     0x11/imm32/alloc-id:fake
33192     _Primitive-loop-if-carry/imm32/next
33193 _Primitive-loop-if-carry:  # (payload primitive)
33194     0x11/imm32/alloc-id:fake:payload
33195     0x11/imm32/alloc-id:fake
33196     _string-loop-if-carry/imm32/name
33197     0/imm32/no-inouts
33198     0/imm32/no-inouts
33199     0/imm32/no-outputs
33200     0/imm32/no-outputs
33201     0x11/imm32/alloc-id:fake
33202     _string_0f_82_jump_loop/imm32/subx-name
33203     0/imm32/no-rm32
33204     0/imm32/no-r32
33205     0/imm32/no-imm32
33206     0/imm32/no-imm8
33207     0/imm32/no-disp32
33208     0/imm32/no-xm32
33209     0/imm32/no-x32
33210     0x11/imm32/alloc-id:fake
33211     _Primitive-loop-if-not-carry/imm32/next
33212 _Primitive-loop-if-not-carry:  # (payload primitive)
33213     0x11/imm32/alloc-id:fake:payload
33214     0x11/imm32/alloc-id:fake
33215     _string-loop-if-not-carry/imm32/name
33216     0/imm32/no-inouts
33217     0/imm32/no-inouts
33218     0/imm32/no-outputs
33219     0/imm32/no-outputs
33220     0x11/imm32/alloc-id:fake
33221     _string_0f_83_jump_loop/imm32/subx-name
33222     0/imm32/no-rm32
33223     0/imm32/no-r32
33224     0/imm32/no-imm32
33225     0/imm32/no-imm8
33226     0/imm32/no-disp32
33227     0/imm32/no-xm32
33228     0/imm32/no-x32
33229     0x11/imm32/alloc-id:fake
33230     _Primitive-loop-if-overflow/imm32/next
33231 _Primitive-loop-if-overflow:  # (payload primitive)
33232     0x11/imm32/alloc-id:fake:payload
33233     0x11/imm32/alloc-id:fake
33234     _string-loop-if-overflow/imm32/name
33235     0/imm32/no-inouts
33236     0/imm32/no-inouts
33237     0/imm32/no-outputs
33238     0/imm32/no-outputs
33239     0x11/imm32/alloc-id:fake
33240     _string_0f_80_jump_loop/imm32/subx-name
33241     0/imm32/no-rm32
33242     0/imm32/no-r32
33243     0/imm32/no-imm32
33244     0/imm32/no-imm8
33245     0/imm32/no-disp32
33246     0/imm32/no-xm32
33247     0/imm32/no-x32
33248     0x11/imm32/alloc-id:fake
33249     _Primitive-loop-if-not-overflow/imm32/next
33250 _Primitive-loop-if-not-overflow:  # (payload primitive)
33251     0x11/imm32/alloc-id:fake:payload
33252     0x11/imm32/alloc-id:fake
33253     _string-loop-if-not-overflow/imm32/name
33254     0/imm32/no-inouts
33255     0/imm32/no-inouts
33256     0/imm32/no-outputs
33257     0/imm32/no-outputs
33258     0x11/imm32/alloc-id:fake
33259     _string_0f_81_jump_loop/imm32/subx-name
33260     0/imm32/no-rm32
33261     0/imm32/no-r32
33262     0/imm32/no-imm32
33263     0/imm32/no-imm8
33264     0/imm32/no-disp32
33265     0/imm32/no-xm32
33266     0/imm32/no-x32
33267     0x11/imm32/alloc-id:fake
33268     _Primitive-loop/imm32/next  # we probably don't need an unconditional break
33269 _Primitive-loop:  # (payload primitive)
33270     0x11/imm32/alloc-id:fake:payload
33271     0x11/imm32/alloc-id:fake
33272     _string-loop/imm32/name
33273     0/imm32/no-inouts
33274     0/imm32/no-inouts
33275     0/imm32/no-outputs
33276     0/imm32/no-outputs
33277     0x11/imm32/alloc-id:fake
33278     _string_e9_jump_loop/imm32/subx-name
33279     0/imm32/no-rm32
33280     0/imm32/no-r32
33281     0/imm32/no-imm32
33282     0/imm32/no-imm8
33283     0/imm32/no-disp32
33284     0/imm32/no-xm32
33285     0/imm32/no-x32
33286     0x11/imm32/alloc-id:fake
33287     _Primitive-break-if-addr<-named/imm32/next
33288 # - branches to named blocks
33289 _Primitive-break-if-addr<-named:  # (payload primitive)
33290     0x11/imm32/alloc-id:fake:payload
33291     0x11/imm32/alloc-id:fake
33292     _string-break-if-addr</imm32/name
33293     0x11/imm32/alloc-id:fake
33294     Single-lit-var/imm32/inouts
33295     0/imm32/no-outputs
33296     0/imm32/no-outputs
33297     0x11/imm32/alloc-id:fake
33298     _string_0f_82_jump_label/imm32/subx-name
33299     0/imm32/no-rm32
33300     0/imm32/no-r32
33301     0/imm32/no-imm32
33302     0/imm32/no-imm8
33303     1/imm32/disp32-is-first-inout
33304     0/imm32/no-xm32
33305     0/imm32/no-x32
33306     0x11/imm32/alloc-id:fake
33307     _Primitive-break-if-addr>=-named/imm32/next
33308 _Primitive-break-if-addr>=-named:  # (payload primitive)
33309     0x11/imm32/alloc-id:fake:payload
33310     0x11/imm32/alloc-id:fake
33311     _string-break-if-addr>=/imm32/name
33312     0x11/imm32/alloc-id:fake
33313     Single-lit-var/imm32/inouts
33314     0/imm32/no-outputs
33315     0/imm32/no-outputs
33316     0x11/imm32/alloc-id:fake
33317     _string_0f_83_jump_label/imm32/subx-name
33318     0/imm32/no-rm32
33319     0/imm32/no-r32
33320     0/imm32/no-imm32
33321     0/imm32/no-imm8
33322     1/imm32/disp32-is-first-inout
33323     0/imm32/no-xm32
33324     0/imm32/no-x32
33325     0x11/imm32/alloc-id:fake
33326     _Primitive-break-if-=-named/imm32/next
33327 _Primitive-break-if-=-named:  # (payload primitive)
33328     0x11/imm32/alloc-id:fake:payload
33329     0x11/imm32/alloc-id:fake
33330     _string-break-if-=/imm32/name
33331     0x11/imm32/alloc-id:fake
33332     Single-lit-var/imm32/inouts
33333     0/imm32/no-outputs
33334     0/imm32/no-outputs
33335     0x11/imm32/alloc-id:fake
33336     _string_0f_84_jump_label/imm32/subx-name
33337     0/imm32/no-rm32
33338     0/imm32/no-r32
33339     0/imm32/no-imm32
33340     0/imm32/no-imm8
33341     1/imm32/disp32-is-first-inout
33342     0/imm32/no-xm32
33343     0/imm32/no-x32
33344     0x11/imm32/alloc-id:fake
33345     _Primitive-break-if-!=-named/imm32/next
33346 _Primitive-break-if-!=-named:  # (payload primitive)
33347     0x11/imm32/alloc-id:fake:payload
33348     0x11/imm32/alloc-id:fake
33349     _string-break-if-!=/imm32/name
33350     0x11/imm32/alloc-id:fake
33351     Single-lit-var/imm32/inouts
33352     0/imm32/no-outputs
33353     0/imm32/no-outputs
33354     0x11/imm32/alloc-id:fake
33355     _string_0f_85_jump_label/imm32/subx-name
33356     0/imm32/no-rm32
33357     0/imm32/no-r32
33358     0/imm32/no-imm32
33359     0/imm32/no-imm8
33360     1/imm32/disp32-is-first-inout
33361     0/imm32/no-xm32
33362     0/imm32/no-x32
33363     0x11/imm32/alloc-id:fake
33364     _Primitive-break-if-addr<=-named/imm32/next
33365 _Primitive-break-if-addr<=-named:  # (payload primitive)
33366     0x11/imm32/alloc-id:fake:payload
33367     0x11/imm32/alloc-id:fake
33368     _string-break-if-addr<=/imm32/name
33369     0x11/imm32/alloc-id:fake
33370     Single-lit-var/imm32/inouts
33371     0/imm32/no-outputs
33372     0/imm32/no-outputs
33373     0x11/imm32/alloc-id:fake
33374     _string_0f_86_jump_label/imm32/subx-name
33375     0/imm32/no-rm32
33376     0/imm32/no-r32
33377     0/imm32/no-imm32
33378     0/imm32/no-imm8
33379     1/imm32/disp32-is-first-inout
33380     0/imm32/no-xm32
33381     0/imm32/no-x32
33382     0x11/imm32/alloc-id:fake
33383     _Primitive-break-if-addr>-named/imm32/next
33384 _Primitive-break-if-addr>-named:  # (payload primitive)
33385     0x11/imm32/alloc-id:fake:payload
33386     0x11/imm32/alloc-id:fake
33387     _string-break-if-addr>/imm32/name
33388     0x11/imm32/alloc-id:fake
33389     Single-lit-var/imm32/inouts
33390     0/imm32/no-outputs
33391     0/imm32/no-outputs
33392     0x11/imm32/alloc-id:fake
33393     _string_0f_87_jump_label/imm32/subx-name
33394     0/imm32/no-rm32
33395     0/imm32/no-r32
33396     0/imm32/no-imm32
33397     0/imm32/no-imm8
33398     1/imm32/disp32-is-first-inout
33399     0/imm32/no-xm32
33400     0/imm32/no-x32
33401     0x11/imm32/alloc-id:fake
33402     _Primitive-break-if-<-named/imm32/next
33403 _Primitive-break-if-<-named:  # (payload primitive)
33404     0x11/imm32/alloc-id:fake:payload
33405     0x11/imm32/alloc-id:fake
33406     _string-break-if-</imm32/name
33407     0x11/imm32/alloc-id:fake
33408     Single-lit-var/imm32/inouts
33409     0/imm32/no-outputs
33410     0/imm32/no-outputs
33411     0x11/imm32/alloc-id:fake
33412     _string_0f_8c_jump_label/imm32/subx-name
33413     0/imm32/no-rm32
33414     0/imm32/no-r32
33415     0/imm32/no-imm32
33416     0/imm32/no-imm8
33417     1/imm32/disp32-is-first-inout
33418     0/imm32/no-xm32
33419     0/imm32/no-x32
33420     0x11/imm32/alloc-id:fake
33421     _Primitive-break-if->=-named/imm32/next
33422 _Primitive-break-if->=-named:  # (payload primitive)
33423     0x11/imm32/alloc-id:fake:payload
33424     0x11/imm32/alloc-id:fake
33425     _string-break-if->=/imm32/name
33426     0x11/imm32/alloc-id:fake
33427     Single-lit-var/imm32/inouts
33428     0/imm32/no-outputs
33429     0/imm32/no-outputs
33430     0x11/imm32/alloc-id:fake
33431     _string_0f_8d_jump_label/imm32/subx-name
33432     0/imm32/no-rm32
33433     0/imm32/no-r32
33434     0/imm32/no-imm32
33435     0/imm32/no-imm8
33436     1/imm32/disp32-is-first-inout
33437     0/imm32/no-xm32
33438     0/imm32/no-x32
33439     0x11/imm32/alloc-id:fake
33440     _Primitive-break-if-<=-named/imm32/next
33441 _Primitive-break-if-<=-named:  # (payload primitive)
33442     0x11/imm32/alloc-id:fake:payload
33443     0x11/imm32/alloc-id:fake
33444     _string-break-if-<=/imm32/name
33445     0x11/imm32/alloc-id:fake
33446     Single-lit-var/imm32/inouts
33447     0/imm32/no-outputs
33448     0/imm32/no-outputs
33449     0x11/imm32/alloc-id:fake
33450     _string_0f_8e_jump_label/imm32/subx-name
33451     0/imm32/no-rm32
33452     0/imm32/no-r32
33453     0/imm32/no-imm32
33454     0/imm32/no-imm8
33455     1/imm32/disp32-is-first-inout
33456     0/imm32/no-xm32
33457     0/imm32/no-x32
33458     0x11/imm32/alloc-id:fake
33459     _Primitive-break-if->-named/imm32/next
33460 _Primitive-break-if->-named:  # (payload primitive)
33461     0x11/imm32/alloc-id:fake:payload
33462     0x11/imm32/alloc-id:fake
33463     _string-break-if->/imm32/name
33464     0x11/imm32/alloc-id:fake
33465     Single-lit-var/imm32/inouts
33466     0/imm32/no-outputs
33467     0/imm32/no-outputs
33468     0x11/imm32/alloc-id:fake
33469     _string_0f_8f_jump_label/imm32/subx-name
33470     0/imm32/no-rm32
33471     0/imm32/no-r32
33472     0/imm32/no-imm32
33473     0/imm32/no-imm8
33474     1/imm32/disp32-is-first-inout
33475     0/imm32/no-xm32
33476     0/imm32/no-x32
33477     0x11/imm32/alloc-id:fake
33478     _Primitive-break-named/imm32/next
33479 _Primitive-break-named:  # (payload primitive)
33480     0x11/imm32/alloc-id:fake:payload
33481     0x11/imm32/alloc-id:fake
33482     _string-break/imm32/name
33483     0x11/imm32/alloc-id:fake
33484     Single-lit-var/imm32/inouts
33485     0/imm32/no-outputs
33486     0/imm32/no-outputs
33487     0x11/imm32/alloc-id:fake
33488     _string_e9_jump_label/imm32/subx-name
33489     0/imm32/no-rm32
33490     0/imm32/no-r32
33491     0/imm32/no-imm32
33492     0/imm32/no-imm8
33493     1/imm32/disp32-is-first-inout
33494     0/imm32/no-xm32
33495     0/imm32/no-x32
33496     0x11/imm32/alloc-id:fake
33497     _Primitive-loop-if-addr<-named/imm32/next
33498 _Primitive-loop-if-addr<-named:  # (payload primitive)
33499     0x11/imm32/alloc-id:fake:payload
33500     0x11/imm32/alloc-id:fake
33501     _string-loop-if-addr</imm32/name
33502     0x11/imm32/alloc-id:fake
33503     Single-lit-var/imm32/inouts
33504     0/imm32/no-outputs
33505     0/imm32/no-outputs
33506     0x11/imm32/alloc-id:fake
33507     _string_0f_82_jump_label/imm32/subx-name
33508     0/imm32/no-rm32
33509     0/imm32/no-r32
33510     0/imm32/no-imm32
33511     0/imm32/no-imm8
33512     1/imm32/disp32-is-first-inout
33513     0/imm32/no-xm32
33514     0/imm32/no-x32
33515     0x11/imm32/alloc-id:fake
33516     _Primitive-loop-if-addr>=-named/imm32/next
33517 _Primitive-loop-if-addr>=-named:  # (payload primitive)
33518     0x11/imm32/alloc-id:fake:payload
33519     0x11/imm32/alloc-id:fake
33520     _string-loop-if-addr>=/imm32/name
33521     0x11/imm32/alloc-id:fake
33522     Single-lit-var/imm32/inouts
33523     0/imm32/no-outputs
33524     0/imm32/no-outputs
33525     0x11/imm32/alloc-id:fake
33526     _string_0f_83_jump_label/imm32/subx-name
33527     0/imm32/no-rm32
33528     0/imm32/no-r32
33529     0/imm32/no-imm32
33530     0/imm32/no-imm8
33531     1/imm32/disp32-is-first-inout
33532     0/imm32/no-xm32
33533     0/imm32/no-x32
33534     0x11/imm32/alloc-id:fake
33535     _Primitive-loop-if-=-named/imm32/next
33536 _Primitive-loop-if-=-named:  # (payload primitive)
33537     0x11/imm32/alloc-id:fake:payload
33538     0x11/imm32/alloc-id:fake
33539     _string-loop-if-=/imm32/name
33540     0x11/imm32/alloc-id:fake
33541     Single-lit-var/imm32/inouts
33542     0/imm32/no-outputs
33543     0/imm32/no-outputs
33544     0x11/imm32/alloc-id:fake
33545     _string_0f_84_jump_label/imm32/subx-name
33546     0/imm32/no-rm32
33547     0/imm32/no-r32
33548     0/imm32/no-imm32
33549     0/imm32/no-imm8
33550     1/imm32/disp32-is-first-inout
33551     0/imm32/no-xm32
33552     0/imm32/no-x32
33553     0x11/imm32/alloc-id:fake
33554     _Primitive-loop-if-!=-named/imm32/next
33555 _Primitive-loop-if-!=-named:  # (payload primitive)
33556     0x11/imm32/alloc-id:fake:payload
33557     0x11/imm32/alloc-id:fake
33558     _string-loop-if-!=/imm32/name
33559     0x11/imm32/alloc-id:fake
33560     Single-lit-var/imm32/inouts
33561     0/imm32/no-outputs
33562     0/imm32/no-outputs
33563     0x11/imm32/alloc-id:fake
33564     _string_0f_85_jump_label/imm32/subx-name
33565     0/imm32/no-rm32
33566     0/imm32/no-r32
33567     0/imm32/no-imm32
33568     0/imm32/no-imm8
33569     1/imm32/disp32-is-first-inout
33570     0/imm32/no-xm32
33571     0/imm32/no-x32
33572     0x11/imm32/alloc-id:fake
33573     _Primitive-loop-if-addr<=-named/imm32/next
33574 _Primitive-loop-if-addr<=-named:  # (payload primitive)
33575     0x11/imm32/alloc-id:fake:payload
33576     0x11/imm32/alloc-id:fake
33577     _string-loop-if-addr<=/imm32/name
33578     0x11/imm32/alloc-id:fake
33579     Single-lit-var/imm32/inouts
33580     0/imm32/no-outputs
33581     0/imm32/no-outputs
33582     0x11/imm32/alloc-id:fake
33583     _string_0f_86_jump_label/imm32/subx-name
33584     0/imm32/no-rm32
33585     0/imm32/no-r32
33586     0/imm32/no-imm32
33587     0/imm32/no-imm8
33588     1/imm32/disp32-is-first-inout
33589     0/imm32/no-xm32
33590     0/imm32/no-x32
33591     0x11/imm32/alloc-id:fake
33592     _Primitive-loop-if-addr>-named/imm32/next
33593 _Primitive-loop-if-addr>-named:  # (payload primitive)
33594     0x11/imm32/alloc-id:fake:payload
33595     0x11/imm32/alloc-id:fake
33596     _string-loop-if-addr>/imm32/name
33597     0x11/imm32/alloc-id:fake
33598     Single-lit-var/imm32/inouts
33599     0/imm32/no-outputs
33600     0/imm32/no-outputs
33601     0x11/imm32/alloc-id:fake
33602     _string_0f_87_jump_label/imm32/subx-name
33603     0/imm32/no-rm32
33604     0/imm32/no-r32
33605     0/imm32/no-imm32
33606     0/imm32/no-imm8
33607     1/imm32/disp32-is-first-inout
33608     0/imm32/no-xm32
33609     0/imm32/no-x32
33610     0x11/imm32/alloc-id:fake
33611     _Primitive-loop-if-<-named/imm32/next
33612 _Primitive-loop-if-<-named:  # (payload primitive)
33613     0x11/imm32/alloc-id:fake:payload
33614     0x11/imm32/alloc-id:fake
33615     _string-loop-if-</imm32/name
33616     0x11/imm32/alloc-id:fake
33617     Single-lit-var/imm32/inouts
33618     0/imm32/no-outputs
33619     0/imm32/no-outputs
33620     0x11/imm32/alloc-id:fake
33621     _string_0f_8c_jump_label/imm32/subx-name
33622     0/imm32/no-rm32
33623     0/imm32/no-r32
33624     0/imm32/no-imm32
33625     0/imm32/no-imm8
33626     1/imm32/disp32-is-first-inout
33627     0/imm32/no-xm32
33628     0/imm32/no-x32
33629     0x11/imm32/alloc-id:fake
33630     _Primitive-loop-if->=-named/imm32/next
33631 _Primitive-loop-if->=-named:  # (payload primitive)
33632     0x11/imm32/alloc-id:fake:payload
33633     0x11/imm32/alloc-id:fake
33634     _string-loop-if->=/imm32/name
33635     0x11/imm32/alloc-id:fake
33636     Single-lit-var/imm32/inouts
33637     0/imm32/no-outputs
33638     0/imm32/no-outputs
33639     0x11/imm32/alloc-id:fake
33640     _string_0f_8d_jump_label/imm32/subx-name
33641     0/imm32/no-rm32
33642     0/imm32/no-r32
33643     0/imm32/no-imm32
33644     0/imm32/no-imm8
33645     1/imm32/disp32-is-first-inout
33646     0/imm32/no-xm32
33647     0/imm32/no-x32
33648     0x11/imm32/alloc-id:fake
33649     _Primitive-loop-if-<=-named/imm32/next
33650 _Primitive-loop-if-<=-named:  # (payload primitive)
33651     0x11/imm32/alloc-id:fake:payload
33652     0x11/imm32/alloc-id:fake
33653     _string-loop-if-<=/imm32/name
33654     0x11/imm32/alloc-id:fake
33655     Single-lit-var/imm32/inouts
33656     0/imm32/no-outputs
33657     0/imm32/no-outputs
33658     0x11/imm32/alloc-id:fake
33659     _string_0f_8e_jump_label/imm32/subx-name
33660     0/imm32/no-rm32
33661     0/imm32/no-r32
33662     0/imm32/no-imm32
33663     0/imm32/no-imm8
33664     1/imm32/disp32-is-first-inout
33665     0/imm32/no-xm32
33666     0/imm32/no-x32
33667     0x11/imm32/alloc-id:fake
33668     _Primitive-loop-if->-named/imm32/next
33669 _Primitive-loop-if->-named:  # (payload primitive)
33670     0x11/imm32/alloc-id:fake:payload
33671     0x11/imm32/alloc-id:fake
33672     _string-loop-if->/imm32/name
33673     0x11/imm32/alloc-id:fake
33674     Single-lit-var/imm32/inouts
33675     0/imm32/no-outputs
33676     0/imm32/no-outputs
33677     0x11/imm32/alloc-id:fake
33678     _string_0f_8f_jump_label/imm32/subx-name
33679     0/imm32/no-rm32
33680     0/imm32/no-r32
33681     0/imm32/no-imm32
33682     0/imm32/no-imm8
33683     1/imm32/disp32-is-first-inout
33684     0/imm32/no-xm32
33685     0/imm32/no-x32
33686     0x11/imm32/alloc-id:fake
33687     _Primitive-loop-named/imm32/next  # we probably don't need an unconditional break
33688 _Primitive-loop-named:  # (payload primitive)
33689     0x11/imm32/alloc-id:fake:payload
33690     0x11/imm32/alloc-id:fake
33691     _string-loop/imm32/name
33692     0x11/imm32/alloc-id:fake
33693     Single-lit-var/imm32/inouts
33694     0/imm32/no-outputs
33695     0/imm32/no-outputs
33696     0x11/imm32/alloc-id:fake
33697     _string_e9_jump_label/imm32/subx-name
33698     0/imm32/no-rm32
33699     0/imm32/no-r32
33700     0/imm32/no-imm32
33701     0/imm32/no-imm8
33702     1/imm32/disp32-is-first-inout
33703     0/imm32/no-xm32
33704     0/imm32/no-x32
33705     0x11/imm32/alloc-id:fake
33706     _Primitive-break-if-float</imm32/next
33707 # - branches based on floating-point comparisons
33708 _Primitive-break-if-float<:  # (payload primitive)
33709     0x11/imm32/alloc-id:fake:payload
33710     0x11/imm32/alloc-id:fake
33711     _string-break-if-float</imm32/name
33712     0/imm32/no-inouts
33713     0/imm32/no-inouts
33714     0/imm32/no-outputs
33715     0/imm32/no-outputs
33716     0x11/imm32/alloc-id:fake
33717     _string_0f_82_jump_break/imm32/subx-name
33718     0/imm32/no-rm32
33719     0/imm32/no-r32
33720     0/imm32/no-imm32
33721     0/imm32/no-imm8
33722     0/imm32/no-disp32
33723     0/imm32/no-xm32
33724     0/imm32/no-x32
33725     0x11/imm32/alloc-id:fake
33726     _Primitive-break-if-float>=/imm32/next
33727 _Primitive-break-if-float>=:  # (payload primitive)
33728     0x11/imm32/alloc-id:fake:payload
33729     0x11/imm32/alloc-id:fake
33730     _string-break-if-float>=/imm32/name
33731     0/imm32/no-inouts
33732     0/imm32/no-inouts
33733     0/imm32/no-outputs
33734     0/imm32/no-outputs
33735     0x11/imm32/alloc-id:fake
33736     _string_0f_83_jump_break/imm32/subx-name
33737     0/imm32/no-rm32
33738     0/imm32/no-r32
33739     0/imm32/no-imm32
33740     0/imm32/no-imm8
33741     0/imm32/no-disp32
33742     0/imm32/no-xm32
33743     0/imm32/no-x32
33744     0x11/imm32/alloc-id:fake
33745     _Primitive-break-if-float<=/imm32/next
33746 _Primitive-break-if-float<=:  # (payload primitive)
33747     0x11/imm32/alloc-id:fake:payload
33748     0x11/imm32/alloc-id:fake
33749     _string-break-if-float<=/imm32/name
33750     0/imm32/no-inouts
33751     0/imm32/no-inouts
33752     0/imm32/no-outputs
33753     0/imm32/no-outputs
33754     0x11/imm32/alloc-id:fake
33755     _string_0f_86_jump_break/imm32/subx-name
33756     0/imm32/no-rm32
33757     0/imm32/no-r32
33758     0/imm32/no-imm32
33759     0/imm32/no-imm8
33760     0/imm32/no-disp32
33761     0/imm32/no-xm32
33762     0/imm32/no-x32
33763     0x11/imm32/alloc-id:fake
33764     _Primitive-break-if-float>/imm32/next
33765 _Primitive-break-if-float>:  # (payload primitive)
33766     0x11/imm32/alloc-id:fake:payload
33767     0x11/imm32/alloc-id:fake
33768     _string-break-if-float>/imm32/name
33769     0/imm32/no-inouts
33770     0/imm32/no-inouts
33771     0/imm32/no-outputs
33772     0/imm32/no-outputs
33773     0x11/imm32/alloc-id:fake
33774     _string_0f_87_jump_break/imm32/subx-name
33775     0/imm32/no-rm32
33776     0/imm32/no-r32
33777     0/imm32/no-imm32
33778     0/imm32/no-imm8
33779     0/imm32/no-disp32
33780     0/imm32/no-xm32
33781     0/imm32/no-x32
33782     0x11/imm32/alloc-id:fake
33783     _Primitive-loop-if-float</imm32/next
33784 _Primitive-loop-if-float<:  # (payload primitive)
33785     0x11/imm32/alloc-id:fake:payload
33786     0x11/imm32/alloc-id:fake
33787     _string-loop-if-float</imm32/name
33788     0/imm32/no-inouts
33789     0/imm32/no-inouts
33790     0/imm32/no-outputs
33791     0/imm32/no-outputs
33792     0x11/imm32/alloc-id:fake
33793     _string_0f_82_jump_loop/imm32/subx-name
33794     0/imm32/no-rm32
33795     0/imm32/no-r32
33796     0/imm32/no-imm32
33797     0/imm32/no-imm8
33798     0/imm32/no-disp32
33799     0/imm32/no-xm32
33800     0/imm32/no-x32
33801     0x11/imm32/alloc-id:fake
33802     _Primitive-loop-if-float>=/imm32/next
33803 _Primitive-loop-if-float>=:  # (payload primitive)
33804     0x11/imm32/alloc-id:fake:payload
33805     0x11/imm32/alloc-id:fake
33806     _string-loop-if-float>=/imm32/name
33807     0/imm32/no-inouts
33808     0/imm32/no-inouts
33809     0/imm32/no-outputs
33810     0/imm32/no-outputs
33811     0x11/imm32/alloc-id:fake
33812     _string_0f_83_jump_loop/imm32/subx-name
33813     0/imm32/no-rm32
33814     0/imm32/no-r32
33815     0/imm32/no-imm32
33816     0/imm32/no-imm8
33817     0/imm32/no-disp32
33818     0/imm32/no-xm32
33819     0/imm32/no-x32
33820     0x11/imm32/alloc-id:fake
33821     _Primitive-loop-if-float<=/imm32/next
33822 _Primitive-loop-if-float<=:  # (payload primitive)
33823     0x11/imm32/alloc-id:fake:payload
33824     0x11/imm32/alloc-id:fake
33825     _string-loop-if-float<=/imm32/name
33826     0/imm32/no-inouts
33827     0/imm32/no-inouts
33828     0/imm32/no-outputs
33829     0/imm32/no-outputs
33830     0x11/imm32/alloc-id:fake
33831     _string_0f_86_jump_loop/imm32/subx-name
33832     0/imm32/no-rm32
33833     0/imm32/no-r32
33834     0/imm32/no-imm32
33835     0/imm32/no-imm8
33836     0/imm32/no-disp32
33837     0/imm32/no-xm32
33838     0/imm32/no-x32
33839     0x11/imm32/alloc-id:fake
33840     _Primitive-loop-if-float>/imm32/next
33841 _Primitive-loop-if-float>:  # (payload primitive)
33842     0x11/imm32/alloc-id:fake:payload
33843     0x11/imm32/alloc-id:fake
33844     _string-loop-if-float>/imm32/name
33845     0/imm32/no-inouts
33846     0/imm32/no-inouts
33847     0/imm32/no-outputs
33848     0/imm32/no-outputs
33849     0x11/imm32/alloc-id:fake
33850     _string_0f_87_jump_loop/imm32/subx-name
33851     0/imm32/no-rm32
33852     0/imm32/no-r32
33853     0/imm32/no-imm32
33854     0/imm32/no-imm8
33855     0/imm32/no-disp32
33856     0/imm32/no-xm32
33857     0/imm32/no-x32
33858     0x11/imm32/alloc-id:fake
33859     _Primitive-break-if-float<-named/imm32/next
33860 _Primitive-break-if-float<-named:  # (payload primitive)
33861     0x11/imm32/alloc-id:fake:payload
33862     0x11/imm32/alloc-id:fake
33863     _string-break-if-float</imm32/name
33864     0x11/imm32/alloc-id:fake
33865     Single-lit-var/imm32/inouts
33866     0/imm32/no-outputs
33867     0/imm32/no-outputs
33868     0x11/imm32/alloc-id:fake
33869     _string_0f_82_jump_label/imm32/subx-name
33870     0/imm32/no-rm32
33871     0/imm32/no-r32
33872     0/imm32/no-imm32
33873     0/imm32/no-imm8
33874     1/imm32/disp32-is-first-inout
33875     0/imm32/no-xm32
33876     0/imm32/no-x32
33877     0x11/imm32/alloc-id:fake
33878     _Primitive-break-if-float>=-named/imm32/next
33879 _Primitive-break-if-float>=-named:  # (payload primitive)
33880     0x11/imm32/alloc-id:fake:payload
33881     0x11/imm32/alloc-id:fake
33882     _string-break-if-float>=/imm32/name
33883     0x11/imm32/alloc-id:fake
33884     Single-lit-var/imm32/inouts
33885     0/imm32/no-outputs
33886     0/imm32/no-outputs
33887     0x11/imm32/alloc-id:fake
33888     _string_0f_83_jump_label/imm32/subx-name
33889     0/imm32/no-rm32
33890     0/imm32/no-r32
33891     0/imm32/no-imm32
33892     0/imm32/no-imm8
33893     1/imm32/disp32-is-first-inout
33894     0/imm32/no-xm32
33895     0/imm32/no-x32
33896     0x11/imm32/alloc-id:fake
33897     _Primitive-break-if-float<=-named/imm32/next
33898 _Primitive-break-if-float<=-named:  # (payload primitive)
33899     0x11/imm32/alloc-id:fake:payload
33900     0x11/imm32/alloc-id:fake
33901     _string-break-if-float<=/imm32/name
33902     0x11/imm32/alloc-id:fake
33903     Single-lit-var/imm32/inouts
33904     0/imm32/no-outputs
33905     0/imm32/no-outputs
33906     0x11/imm32/alloc-id:fake
33907     _string_0f_86_jump_label/imm32/subx-name
33908     0/imm32/no-rm32
33909     0/imm32/no-r32
33910     0/imm32/no-imm32
33911     0/imm32/no-imm8
33912     1/imm32/disp32-is-first-inout
33913     0/imm32/no-xm32
33914     0/imm32/no-x32
33915     0x11/imm32/alloc-id:fake
33916     _Primitive-break-if-float>-named/imm32/next
33917 _Primitive-break-if-float>-named:  # (payload primitive)
33918     0x11/imm32/alloc-id:fake:payload
33919     0x11/imm32/alloc-id:fake
33920     _string-break-if-float>/imm32/name
33921     0x11/imm32/alloc-id:fake
33922     Single-lit-var/imm32/inouts
33923     0/imm32/no-outputs
33924     0/imm32/no-outputs
33925     0x11/imm32/alloc-id:fake
33926     _string_0f_87_jump_label/imm32/subx-name
33927     0/imm32/no-rm32
33928     0/imm32/no-r32
33929     0/imm32/no-imm32
33930     0/imm32/no-imm8
33931     1/imm32/disp32-is-first-inout
33932     0/imm32/no-xm32
33933     0/imm32/no-x32
33934     0x11/imm32/alloc-id:fake
33935     _Primitive-loop-if-float<-named/imm32/next
33936 _Primitive-loop-if-float<-named:  # (payload primitive)
33937     0x11/imm32/alloc-id:fake:payload
33938     0x11/imm32/alloc-id:fake
33939     _string-loop-if-float</imm32/name
33940     0x11/imm32/alloc-id:fake
33941     Single-lit-var/imm32/inouts
33942     0/imm32/no-outputs
33943     0/imm32/no-outputs
33944     0x11/imm32/alloc-id:fake
33945     _string_0f_82_jump_label/imm32/subx-name
33946     0/imm32/no-rm32
33947     0/imm32/no-r32
33948     0/imm32/no-imm32
33949     0/imm32/no-imm8
33950     1/imm32/disp32-is-first-inout
33951     0/imm32/no-xm32
33952     0/imm32/no-x32
33953     0x11/imm32/alloc-id:fake
33954     _Primitive-loop-if-float>=-named/imm32/next
33955 _Primitive-loop-if-float>=-named:  # (payload primitive)
33956     0x11/imm32/alloc-id:fake:payload
33957     0x11/imm32/alloc-id:fake
33958     _string-loop-if-float>=/imm32/name
33959     0x11/imm32/alloc-id:fake
33960     Single-lit-var/imm32/inouts
33961     0/imm32/no-outputs
33962     0/imm32/no-outputs
33963     0x11/imm32/alloc-id:fake
33964     _string_0f_83_jump_label/imm32/subx-name
33965     0/imm32/no-rm32
33966     0/imm32/no-r32
33967     0/imm32/no-imm32
33968     0/imm32/no-imm8
33969     1/imm32/disp32-is-first-inout
33970     0/imm32/no-xm32
33971     0/imm32/no-x32
33972     0x11/imm32/alloc-id:fake
33973     _Primitive-loop-if-float<=-named/imm32/next
33974 _Primitive-loop-if-float<=-named:  # (payload primitive)
33975     0x11/imm32/alloc-id:fake:payload
33976     0x11/imm32/alloc-id:fake
33977     _string-loop-if-float<=/imm32/name
33978     0x11/imm32/alloc-id:fake
33979     Single-lit-var/imm32/inouts
33980     0/imm32/no-outputs
33981     0/imm32/no-outputs
33982     0x11/imm32/alloc-id:fake
33983     _string_0f_86_jump_label/imm32/subx-name
33984     0/imm32/no-rm32
33985     0/imm32/no-r32
33986     0/imm32/no-imm32
33987     0/imm32/no-imm8
33988     1/imm32/disp32-is-first-inout
33989     0/imm32/no-xm32
33990     0/imm32/no-x32
33991     0x11/imm32/alloc-id:fake
33992     _Primitive-loop-if-float>-named/imm32/next
33993 _Primitive-loop-if-float>-named:  # (payload primitive)
33994     0x11/imm32/alloc-id:fake:payload
33995     0x11/imm32/alloc-id:fake
33996     _string-loop-if-float>/imm32/name
33997     0x11/imm32/alloc-id:fake
33998     Single-lit-var/imm32/inouts
33999     0/imm32/no-outputs
34000     0/imm32/no-outputs
34001     0x11/imm32/alloc-id:fake
34002     _string_0f_87_jump_label/imm32/subx-name
34003     0/imm32/no-rm32
34004     0/imm32/no-r32
34005     0/imm32/no-imm32
34006     0/imm32/no-imm8
34007     1/imm32/disp32-is-first-inout
34008     0/imm32/no-xm32
34009     0/imm32/no-x32
34010     0/imm32/next
34011     0/imm32/next
34012 
34013 # string literals for Mu instructions
34014 _string-add:  # (payload array byte)
34015     0x11/imm32/alloc-id:fake:payload
34016     # "add"
34017     0x3/imm32/size
34018     0x61/a 0x64/d 0x64/d
34019 _string-address:  # (payload array byte)
34020     0x11/imm32/alloc-id:fake:payload
34021     # "address"
34022     0x7/imm32/size
34023     0x61/a 0x64/d 0x64/d 0x72/r 0x65/e 0x73/s 0x73/s
34024 _string-add-to:  # (payload array byte)
34025     0x11/imm32/alloc-id:fake:payload
34026     # "add-to"
34027     0x6/imm32/size
34028     0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o
34029 _string-and:  # (payload array byte)
34030     0x11/imm32/alloc-id:fake:payload
34031     # "and"
34032     0x3/imm32/size
34033     0x61/a 0x6e/n 0x64/d
34034 _string-and-with:  # (payload array byte)
34035     0x11/imm32/alloc-id:fake:payload
34036     # "and-with"
34037     0x8/imm32/size
34038     0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
34039 _string-break:  # (payload array byte)
34040     0x11/imm32/alloc-id:fake:payload
34041     # "break"
34042     0x5/imm32/size
34043     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k
34044 _string-break-if-<:  # (payload array byte)
34045     0x11/imm32/alloc-id:fake:payload
34046     # "break-if-<"
34047     0xa/imm32/size
34048     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/<
34049 _string-break-if-<=:  # (payload array byte)
34050     0x11/imm32/alloc-id:fake:payload
34051     # "break-if-<="
34052     0xb/imm32/size
34053     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/=
34054 _string-break-if-=:  # (payload array byte)
34055     0x11/imm32/alloc-id:fake:payload
34056     # "break-if-="
34057     0xa/imm32/size
34058     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/=
34059 _string-break-if->:  # (payload array byte)
34060     0x11/imm32/alloc-id:fake:payload
34061     # "break-if->"
34062     0xa/imm32/size
34063     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/>
34064 _string-break-if->=:  # (payload array byte)
34065     0x11/imm32/alloc-id:fake:payload
34066     # "break-if->="
34067     0xb/imm32/size
34068     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/=
34069 _string-break-if-!=:  # (payload array byte)
34070     0x11/imm32/alloc-id:fake:payload
34071     # "break-if-!="
34072     0xb/imm32/size
34073     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/=
34074 _string-break-if-addr<:  # (payload array byte)
34075     0x11/imm32/alloc-id:fake:payload
34076     # "break-if-addr<"
34077     0xe/imm32/size
34078     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/<
34079 _string-break-if-addr<=:  # (payload array byte)
34080     0x11/imm32/alloc-id:fake:payload
34081     # "break-if-addr<="
34082     0xf/imm32/size
34083     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/=
34084 _string-break-if-addr>:  # (payload array byte)
34085     0x11/imm32/alloc-id:fake:payload
34086     # "break-if-addr>"
34087     0xe/imm32/size
34088     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/>
34089 _string-break-if-addr>=:  # (payload array byte)
34090     0x11/imm32/alloc-id:fake:payload
34091     # "break-if-addr>="
34092     0xf/imm32/size
34093     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/=
34094 _string-break-if-float<:  # (payload array byte)
34095     0x11/imm32/alloc-id:fake:payload
34096     # "break-if-float<"
34097     0xf/imm32/size
34098     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/<
34099 _string-break-if-float<=:  # (payload array byte)
34100     0x11/imm32/alloc-id:fake:payload
34101     # "break-if-float<="
34102     0x10/imm32/size
34103     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/=
34104 _string-break-if-float>:  # (payload array byte)
34105     0x11/imm32/alloc-id:fake:payload
34106     # "break-if-float>"
34107     0xf/imm32/size
34108     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/>
34109 _string-break-if-float>=:  # (payload array byte)
34110     0x11/imm32/alloc-id:fake:payload
34111     # "break-if-float>="
34112     0x10/imm32/size
34113     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/=
34114 _string-break-if-carry:  # (payload array byte)
34115     0x11/imm32/alloc-id:fake:payload
34116     # "break-if-carry"
34117     0xe/imm32/size
34118     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x63/c 0x61/a 0x72/r 0x72/r 0x79/y
34119 _string-break-if-not-carry:  # (payload array byte)
34120     0x11/imm32/alloc-id:fake:payload
34121     # "break-if-not-carry"
34122     0x12/imm32/size
34123     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6e/n 0x6f/o 0x74/t 0x2d/dash 0x63/c 0x61/a 0x72/r 0x72/r 0x79/y
34124 _string-break-if-overflow:  # (payload array byte)
34125     0x11/imm32/alloc-id:fake:payload
34126     # "break-if-overflow"
34127     0x11/imm32/size
34128     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w
34129 _string-break-if-not-overflow:  # (payload array byte)
34130     0x11/imm32/alloc-id:fake:payload
34131     # "break-if-not-overflow"
34132     0x15/imm32/size
34133     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6e/n 0x6f/o 0x74/t 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w
34134 _string-compare:  # (payload array byte)
34135     0x11/imm32/alloc-id:fake:payload
34136     # "compare"
34137     0x7/imm32/size
34138     0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e
34139 _string-copy:  # (payload array byte)
34140     0x11/imm32/alloc-id:fake:payload
34141     # "copy"
34142     0x4/imm32/size
34143     0x63/c 0x6f/o 0x70/p 0x79/y
34144 _string-copy-to:  # (payload array byte)
34145     0x11/imm32/alloc-id:fake:payload
34146     # "copy-to"
34147     0x7/imm32/size
34148     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o
34149 _string-copy-byte:
34150     0x11/imm32/alloc-id:fake:payload
34151     # "copy-byte"
34152     0x9/imm32/size
34153     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x62/b 0x79/y 0x74/t 0x65/e
34154 _string-copy-byte-to:
34155     0x11/imm32/alloc-id:fake:payload
34156     # "copy-byte-to"
34157     0xc/imm32/size
34158     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x62/b 0x79/y 0x74/t 0x65/e 0x2d/dash 0x74/t 0x6f/o
34159 _string-decrement:  # (payload array byte)
34160     0x11/imm32/alloc-id:fake:payload
34161     # "decrement"
34162     0x9/imm32/size
34163     0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t
34164 _string-increment:  # (payload array byte)
34165     0x11/imm32/alloc-id:fake:payload
34166     # "increment"
34167     0x9/imm32/size
34168     0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t
34169 _string-loop:  # (payload array byte)
34170     0x11/imm32/alloc-id:fake:payload
34171     # "loop"
34172     0x4/imm32/size
34173     0x6c/l 0x6f/o 0x6f/o 0x70/p
34174 _string-loop-if-<:  # (payload array byte)
34175     0x11/imm32/alloc-id:fake:payload
34176     # "loop-if-<"
34177     0x9/imm32/size
34178     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/<
34179 _string-loop-if-<=:  # (payload array byte)
34180     0x11/imm32/alloc-id:fake:payload
34181     # "loop-if-<="
34182     0xa/imm32/size
34183     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/=
34184 _string-loop-if-=:  # (payload array byte)
34185     0x11/imm32/alloc-id:fake:payload
34186     # "loop-if-="
34187     0x9/imm32/size
34188     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/=
34189 _string-loop-if->:  # (payload array byte)
34190     0x11/imm32/alloc-id:fake:payload
34191     # "loop-if->"
34192     0x9/imm32/size
34193     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/>
34194 _string-loop-if->=:  # (payload array byte)
34195     0x11/imm32/alloc-id:fake:payload
34196     # "loop-if->="
34197     0xa/imm32/size
34198     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/=
34199 _string-loop-if-!=:  # (payload array byte)
34200     0x11/imm32/alloc-id:fake:payload
34201     # "loop-if-!="
34202     0xa/imm32/size
34203     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/=
34204 _string-loop-if-addr<:  # (payload array byte)
34205     0x11/imm32/alloc-id:fake:payload
34206     # "loop-if-addr<"
34207     0xd/imm32/size
34208     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/<
34209 _string-loop-if-addr<=:  # (payload array byte)
34210     0x11/imm32/alloc-id:fake:payload
34211     # "loop-if-addr<="
34212     0xe/imm32/size
34213     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/=
34214 _string-loop-if-addr>:  # (payload array byte)
34215     0x11/imm32/alloc-id:fake:payload
34216     # "loop-if-addr>"
34217     0xd/imm32/size
34218     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/>
34219 _string-loop-if-addr>=:  # (payload array byte)
34220     0x11/imm32/alloc-id:fake:payload
34221     # "loop-if-addr>="
34222     0xe/imm32/size
34223     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/=
34224 _string-loop-if-float<:  # (payload array byte)
34225     0x11/imm32/alloc-id:fake:payload
34226     # "loop-if-float<"
34227     0xe/imm32/size
34228     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/<
34229 _string-loop-if-float<=:  # (payload array byte)
34230     0x11/imm32/alloc-id:fake:payload
34231     # "loop-if-float<="
34232     0xf/imm32/size
34233     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/=
34234 _string-loop-if-float>:  # (payload array byte)
34235     0x11/imm32/alloc-id:fake:payload
34236     # "loop-if-float>"
34237     0xe/imm32/size
34238     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/>
34239 _string-loop-if-float>=:  # (payload array byte)
34240     0x11/imm32/alloc-id:fake:payload
34241     # "loop-if-float>="
34242     0xf/imm32/size
34243     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/=
34244 _string-loop-if-carry:  # (payload array byte)
34245     0x11/imm32/alloc-id:fake:payload
34246     # "loop-if-carry"
34247     0xd/imm32/size
34248     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x63/c 0x61/a 0x72/r 0x72/r 0x79/y
34249 _string-loop-if-not-carry:  # (payload array byte)
34250     0x11/imm32/alloc-id:fake:payload
34251     # "loop-if-not-carry"
34252     0x11/imm32/size
34253     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6e/n 0x6f/o 0x74/t 0x2d/dash 0x63/c 0x61/a 0x72/r 0x72/r 0x79/y
34254 _string-loop-if-overflow:  # (payload array byte)
34255     0x11/imm32/alloc-id:fake:payload
34256     # "loop-if-overflow"
34257     0x10/imm32/size
34258     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w
34259 _string-loop-if-not-overflow:  # (payload array byte)
34260     0x11/imm32/alloc-id:fake:payload
34261     # "loop-if-not-overflow"
34262     0x14/imm32/size
34263     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6e/n 0x6f/o 0x74/t 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w
34264 _string-multiply:  # (payload array byte)
34265     0x11/imm32/alloc-id:fake:payload
34266     # "multiply"
34267     0x8/imm32/size
34268     0x6d/m 0x75/u 0x6c/l 0x74/t 0x69/i 0x70/p 0x6c/l 0x79/y
34269 _string-convert:  # (payload array byte)
34270     0x11/imm32/alloc-id:fake:payload
34271     # "convert"
34272     0x7/imm32/size
34273     0x63/c 0x6f/o 0x6e/n 0x76/v 0x65/e 0x72/r 0x74/t
34274 _string-truncate:  # (payload array byte)
34275     0x11/imm32/alloc-id:fake:payload
34276     # "truncate"
34277     0x8/imm32/size
34278     0x74/t 0x72/r 0x75/u 0x6e/n 0x63/c 0x61/a 0x74/t 0x65/e
34279 _string-reinterpret:  # (payload array byte)
34280     0x11/imm32/alloc-id:fake:payload
34281     # "reinterpret"
34282     0xb/imm32/size
34283     0x72/r 0x65/e 0x69/i 0x6e/n 0x74/t 0x65/e 0x72/r 0x70/p 0x72/r 0x65/e 0x74/t
34284 _string-divide:
34285     0x11/imm32/alloc-id:fake:payload
34286     # "divide"
34287     0x6/imm32/size
34288     0x64/d 0x69/i 0x76/v 0x69/i 0x64/d 0x65/e
34289 _string-max:
34290     0x11/imm32/alloc-id:fake:payload
34291     # "max"
34292     0x3/imm32/size
34293     0x6d/m 0x61/a 0x78/x
34294 _string-min:
34295     0x11/imm32/alloc-id:fake:payload
34296     # "min"
34297     0x3/imm32/size
34298     0x6d/m 0x69/i 0x6e/n
34299 _string-reciprocal:
34300     0x11/imm32/alloc-id:fake:payload
34301     # "reciprocal"
34302     0xa/imm32/size
34303     0x72/r 0x65/e 0x63/c 0x69/i 0x70/p 0x72/r 0x6f/o 0x63/c 0x61/a 0x6c/l
34304 _string-square-root:
34305     0x11/imm32/alloc-id:fake:payload
34306     # "square-root"
34307     0xb/imm32/size
34308     0x73/s 0x71/q 0x75/u 0x61/a 0x72/r 0x65/e 0x2d/dash 0x72/r 0x6f/o 0x6f/o 0x74/t
34309 _string-inverse-square-root:
34310     0x11/imm32/alloc-id:fake:payload
34311     # "inverse-square-root"
34312     0x13/imm32/size
34313     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
34314 _string-negate:  # (payload array byte)
34315     0x11/imm32/alloc-id:fake:payload
34316     # "negate"
34317     0x6/imm32/size
34318     0x6e/n 0x65/e 0x67/g 0x61/a 0x74/t 0x65/e
34319 _string-not:  # (payload array byte)
34320     0x11/imm32/alloc-id:fake:payload
34321     # "not"
34322     0x3/imm32/size
34323     0x6e/n 0x6f/o 0x74/t
34324 _string-or:  # (payload array byte)
34325     0x11/imm32/alloc-id:fake:payload
34326     # "or"
34327     0x2/imm32/size
34328     0x6f/o 0x72/r
34329 _string-or-with:  # (payload array byte)
34330     0x11/imm32/alloc-id:fake:payload
34331     # "or-with"
34332     0x7/imm32/size
34333     0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
34334 _string-subtract:  # (payload array byte)
34335     0x11/imm32/alloc-id:fake:payload
34336     # "subtract"
34337     0x8/imm32/size
34338     0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t
34339 _string-subtract-from:  # (payload array byte)
34340     0x11/imm32/alloc-id:fake:payload
34341     # "subtract-from"
34342     0xd/imm32/size
34343     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
34344 _string-xor:  # (payload array byte)
34345     0x11/imm32/alloc-id:fake:payload
34346     # "xor"
34347     0x3/imm32/size
34348     0x78/x 0x6f/o 0x72/r
34349 _string-xor-with:  # (payload array byte)
34350     0x11/imm32/alloc-id:fake:payload
34351     # "xor-with"
34352     0x8/imm32/size
34353     0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
34354 _string-shift-left:  # (payload array byte)
34355     0x11/imm32/alloc-id:fake:payload
34356     # "shift-left"
34357     0xa/imm32/size
34358     0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x6c/l 0x65/e 0x66/f 0x74/t
34359 _string-shift-right:  # (payload array byte)
34360     0x11/imm32/alloc-id:fake:payload
34361     # "shift-right"
34362     0xb/imm32/size
34363     0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x72/r 0x69/i 0x67/g 0x68/h 0x74/t
34364 _string-shift-right-signed:  # (payload array byte)
34365     0x11/imm32/alloc-id:fake:payload
34366     # "shift-right-signed"
34367     0x12/imm32/size
34368     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
34369 
34370 # string literals for SubX instructions
34371 _string_01_add_to:  # (payload array byte)
34372     0x11/imm32/alloc-id:fake:payload
34373     # "01/add-to"
34374     0x9/imm32/size
34375     0x30/0 0x31/1 0x2f/slash 0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o
34376 _string_03_add:  # (payload array byte)
34377     0x11/imm32/alloc-id:fake:payload
34378     # "03/add"
34379     0x6/imm32/size
34380     0x30/0 0x33/3 0x2f/slash 0x61/a 0x64/d 0x64/d
34381 _string_05_add_to_eax:  # (payload array byte)
34382     0x11/imm32/alloc-id:fake:payload
34383     # "05/add-to-eax"
34384     0xd/imm32/size
34385     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
34386 _string_09_or_with:  # (payload array byte)
34387     0x11/imm32/alloc-id:fake:payload
34388     # "09/or-with"
34389     0xa/imm32/size
34390     0x30/0 0x39/9 0x2f/slash 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
34391 _string_0b_or:  # (payload array byte)
34392     0x11/imm32/alloc-id:fake:payload
34393     # "0b/or"
34394     0x5/imm32/size
34395     0x30/0 0x62/b 0x2f/slash 0x6f/o 0x72/r
34396 _string_0d_or_with_eax:  # (payload array byte)
34397     0x11/imm32/alloc-id:fake:payload
34398     # "0d/or-with-eax"
34399     0xe/imm32/size
34400     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
34401 _string_0f_80_jump_label:  # (payload array byte)
34402     0x11/imm32/alloc-id:fake:payload
34403     # "0f 80/jump-if-overflow"
34404     0x16/imm32/size
34405     0x30/0 0x66/f 0x20/space 0x38/8 0x30/0 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w
34406 _string_0f_80_jump_break:  # (payload array byte)
34407     0x11/imm32/alloc-id:fake:payload
34408     # "0f 80/jump-if-overflow break/disp32"
34409     0x23/imm32/size
34410     0x30/0 0x66/f 0x20/space 0x38/8 0x30/0 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w 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
34411 _string_0f_80_jump_loop:  # (payload array byte)
34412     0x11/imm32/alloc-id:fake:payload
34413     # "0f 80/jump-if-overflow loop/disp32"
34414     0x22/imm32/size
34415     0x30/0 0x66/f 0x20/space 0x38/8 0x30/0 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
34416 _string_0f_81_jump_label:  # (payload array byte)
34417     0x11/imm32/alloc-id:fake:payload
34418     # "0f 81/jump-if-not-overflow"
34419     0x1a/imm32/size
34420     0x30/0 0x66/f 0x20/space 0x38/8 0x31/1 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6e/n 0x6f/o 0x74/t 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w
34421 _string_0f_81_jump_break:  # (payload array byte)
34422     0x11/imm32/alloc-id:fake:payload
34423     # "0f 81/jump-if-not-overflow break/disp32"
34424     0x27/imm32/size
34425     0x30/0 0x66/f 0x20/space 0x38/8 0x31/1 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6e/n 0x6f/o 0x74/t 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w 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
34426 _string_0f_81_jump_loop:  # (payload array byte)
34427     0x11/imm32/alloc-id:fake:payload
34428     # "0f 81/jump-if-not-overflow loop/disp32"
34429     0x26/imm32/size
34430     0x30/0 0x66/f 0x20/space 0x38/8 0x31/1 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6e/n 0x6f/o 0x74/t 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
34431 _string_0f_82_jump_label:  # (payload array byte)
34432     0x11/imm32/alloc-id:fake:payload
34433     # "0f 82/jump-if-addr<"
34434     0x13/imm32/size
34435     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/<
34436 _string_0f_82_jump_break:  # (payload array byte)
34437     0x11/imm32/alloc-id:fake:payload
34438     # "0f 82/jump-if-addr< break/disp32"
34439     0x20/imm32/size
34440     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
34441 _string_0f_82_jump_loop:  # (payload array byte)
34442     0x11/imm32/alloc-id:fake:payload
34443     # "0f 82/jump-if-addr< loop/disp32"
34444     0x1f/imm32/size
34445     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
34446 _string_0f_83_jump_label:  # (payload array byte)
34447     0x11/imm32/alloc-id:fake:payload
34448     # "0f 83/jump-if-addr>="
34449     0x14/imm32/size
34450     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/=
34451 _string_0f_83_jump_break:  # (payload array byte)
34452     0x11/imm32/alloc-id:fake:payload
34453     # "0f 83/jump-if-addr>= break/disp32"
34454     0x21/imm32/size
34455     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
34456 _string_0f_83_jump_loop:  # (payload array byte)
34457     0x11/imm32/alloc-id:fake:payload
34458     # "0f 83/jump-if-addr>= loop/disp32"
34459     0x20/imm32/size
34460     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
34461 _string_0f_84_jump_label:  # (payload array byte)
34462     0x11/imm32/alloc-id:fake:payload
34463     # "0f 84/jump-if-="
34464     0xf/imm32/size
34465     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/=
34466 _string_0f_84_jump_break:  # (payload array byte)
34467     0x11/imm32/alloc-id:fake:payload
34468     # "0f 84/jump-if-= break/disp32"
34469     0x1c/imm32/size
34470     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
34471 _string_0f_84_jump_loop:  # (payload array byte)
34472     0x11/imm32/alloc-id:fake:payload
34473     # "0f 84/jump-if-= loop/disp32"
34474     0x1a/imm32/size
34475     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
34476 _string_0f_85_jump_label:  # (payload array byte)
34477     0x11/imm32/alloc-id:fake:payload
34478     # "0f 85/jump-if-!="
34479     0x10/imm32/size
34480     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/=
34481 _string_0f_85_jump_break:  # (payload array byte)
34482     0x11/imm32/alloc-id:fake:payload
34483     # "0f 85/jump-if-!= break/disp32"
34484     0x1d/imm32/size
34485     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
34486 _string_0f_85_jump_loop:  # (payload array byte)
34487     0x11/imm32/alloc-id:fake:payload
34488     # "0f 85/jump-if-!= loop/disp32"
34489     0x1c/imm32/size
34490     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
34491 _string_0f_86_jump_label:  # (payload array byte)
34492     0x11/imm32/alloc-id:fake:payload
34493     # "0f 86/jump-if-addr<="
34494     0x14/imm32/size
34495     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/=
34496 _string_0f_86_jump_break:  # (payload array byte)
34497     0x11/imm32/alloc-id:fake:payload
34498     # "0f 86/jump-if-addr<= break/disp32"
34499     0x21/imm32/size
34500     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
34501 _string_0f_86_jump_loop:  # (payload array byte)
34502     0x11/imm32/alloc-id:fake:payload
34503     # "0f 86/jump-if-addr<= loop/disp32"
34504     0x20/imm32/size
34505     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
34506 _string_0f_87_jump_label:  # (payload array byte)
34507     0x11/imm32/alloc-id:fake:payload
34508     # "0f 87/jump-if-addr>"
34509     0x13/imm32/size
34510     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/>
34511 _string_0f_87_jump_break:  # (payload array byte)
34512     0x11/imm32/alloc-id:fake:payload
34513     # "0f 87/jump-if-addr> break/disp32"
34514     0x20/imm32/size
34515     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
34516 _string_0f_87_jump_loop:  # (payload array byte)
34517     0x11/imm32/alloc-id:fake:payload
34518     # "0f 87/jump-if-addr> loop/disp32"
34519     0x1f/imm32/size
34520     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
34521 _string_0f_8c_jump_label:  # (payload array byte)
34522     0x11/imm32/alloc-id:fake:payload
34523     # "0f 8c/jump-if-<"
34524     0xf/imm32/size
34525     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/<
34526 _string_0f_8c_jump_break:  # (payload array byte)
34527     0x11/imm32/alloc-id:fake:payload
34528     # "0f 8c/jump-if-< break/disp32"
34529     0x1c/imm32/size
34530     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
34531 _string_0f_8c_jump_loop:  # (payload array byte)
34532     0x11/imm32/alloc-id:fake:payload
34533     # "0f 8c/jump-if-< loop/disp32"
34534     0x1b/imm32/size
34535     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
34536 _string_0f_8d_jump_label:  # (payload array byte)
34537     0x11/imm32/alloc-id:fake:payload
34538     # "0f 8d/jump-if->="
34539     0x10/imm32/size
34540     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/=
34541 _string_0f_8d_jump_break:  # (payload array byte)
34542     0x11/imm32/alloc-id:fake:payload
34543     # "0f 8d/jump-if->= break/disp32"
34544     0x1d/imm32/size
34545     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
34546 _string_0f_8d_jump_loop:  # (payload array byte)
34547     0x11/imm32/alloc-id:fake:payload
34548     # "0f 8d/jump-if->= loop/disp32"
34549     0x1c/imm32/size
34550     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
34551 _string_0f_8e_jump_label:  # (payload array byte)
34552     0x11/imm32/alloc-id:fake:payload
34553     # "0f 8e/jump-if-<="
34554     0x10/imm32/size
34555     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/=
34556 _string_0f_8e_jump_break:  # (payload array byte)
34557     0x11/imm32/alloc-id:fake:payload
34558     # "0f 8e/jump-if-<= break/disp32"
34559     0x1d/imm32/size
34560     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
34561 _string_0f_8e_jump_loop:  # (payload array byte)
34562     0x11/imm32/alloc-id:fake:payload
34563     # "0f 8e/jump-if-<= loop/disp32"
34564     0x1c/imm32/size
34565     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
34566 _string_0f_8f_jump_label:  # (payload array byte)
34567     0x11/imm32/alloc-id:fake:payload
34568     # "0f 8f/jump-if->"
34569     0xf/imm32/size
34570     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/>
34571 _string_0f_8f_jump_break:  # (payload array byte)
34572     0x11/imm32/alloc-id:fake:payload
34573     # "0f 8f/jump-if-> break/disp32"
34574     0x1c/imm32/size
34575     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
34576 _string_0f_8f_jump_loop:  # (payload array byte)
34577     0x11/imm32/alloc-id:fake:payload
34578     # "0f 8f/jump-if-> loop/disp32"
34579     0x1b/imm32/size
34580     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
34581 _string_0f_af_multiply:  # (payload array byte)
34582     0x11/imm32/alloc-id:fake:payload
34583     # "0f af/multiply"
34584     0xe/imm32/size
34585     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
34586 _string_f3_0f_2a_convert_to_float:
34587     0x11/imm32/alloc-id:fake:payload
34588     # "f3 0f 2a/convert-to-float"
34589     0x19/imm32/size
34590     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
34591 _string_f3_0f_2d_convert_to_int:
34592     0x11/imm32/alloc-id:fake:payload
34593     # "f3 0f 2d/convert-to-int"
34594     0x17/imm32/size
34595     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
34596 _string_f3_0f_2c_truncate_to_int:
34597     0x11/imm32/alloc-id:fake:payload
34598     # "f3 0f 2c/truncate-to-int"
34599     0x18/imm32/size
34600     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
34601 _string_f3_0f_58_add:
34602     0x11/imm32/alloc-id:fake:payload
34603     # "f3 0f 58/add"
34604     0xc/imm32/size
34605     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x38/8 0x2f/slash 0x61/a 0x64/d 0x64/d
34606 _string_f3_0f_5c_subtract:
34607     0x11/imm32/alloc-id:fake:payload
34608     # "f3 0f 5c/subtract"
34609     0x11/imm32/size
34610     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
34611 _string_f3_0f_59_multiply:
34612     0x11/imm32/alloc-id:fake:payload
34613     # "f3 0f 59/multiply"
34614     0x11/imm32/size
34615     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
34616 _string_f3_0f_5e_divide:
34617     0x11/imm32/alloc-id:fake:payload
34618     # "f3 0f 5e/divide"
34619     0xf/imm32/size
34620     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
34621 _string_f3_0f_53_reciprocal:
34622     0x11/imm32/alloc-id:fake:payload
34623     # "f3 0f 53/reciprocal"
34624     0x13/imm32/size
34625     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
34626 _string_f3_0f_51_square_root:
34627     0x11/imm32/alloc-id:fake:payload
34628     # "f3 0f 51/square-root"
34629     0x14/imm32/size
34630     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
34631 _string_f3_0f_52_inverse_square_root:
34632     0x11/imm32/alloc-id:fake:payload
34633     # "f3 0f 52/inverse-square-root"
34634     0x1c/imm32/size
34635     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
34636 _string_f3_0f_5d_min:
34637     0x11/imm32/alloc-id:fake:payload
34638     # "f3 0f 5d/min"
34639     0xc/imm32/size
34640     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x64/d 0x2f/slash 0x6d/m 0x69/i 0x6e/n
34641 _string_f3_0f_5f_max:
34642     0x11/imm32/alloc-id:fake:payload
34643     # "f3 0f 5f/max"
34644     0xc/imm32/size
34645     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x66/f 0x2f/slash 0x6d/m 0x61/a 0x78/x
34646 _string_f3_0f_10_copy:
34647     0x11/imm32/alloc-id:fake:payload
34648     # "f3 0f 10/copy"
34649     0xd/imm32/size
34650     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
34651 _string_f3_0f_11_copy:
34652     0x11/imm32/alloc-id:fake:payload
34653     # "f3 0f 11/copy"
34654     0xd/imm32/size
34655     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
34656 _string_0f_2f_compare:
34657     0x11/imm32/alloc-id:fake:payload
34658     # "0f 2f/compare"
34659     0xd/imm32/size
34660     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
34661 _string_21_and_with:  # (payload array byte)
34662     0x11/imm32/alloc-id:fake:payload
34663     # "21/and-with"
34664     0xb/imm32/size
34665     0x32/2 0x31/1 0x2f/slash 0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
34666 _string_23_and:  # (payload array byte)
34667     0x11/imm32/alloc-id:fake:payload
34668     # "23/and"
34669     0x6/imm32/size
34670     0x32/2 0x33/3 0x2f/slash 0x61/a 0x6e/n 0x64/d
34671 _string_25_and_with_eax:  # (payload array byte)
34672     0x11/imm32/alloc-id:fake:payload
34673     # "25/and-with-eax"
34674     0xf/imm32/size
34675     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
34676 _string_29_subtract_from:  # (payload array byte)
34677     0x11/imm32/alloc-id:fake:payload
34678     # "29/subtract-from"
34679     0x10/imm32/size
34680     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
34681 _string_2b_subtract:  # (payload array byte)
34682     0x11/imm32/alloc-id:fake:payload
34683     # "2b/subtract"
34684     0xb/imm32/size
34685     0x32/2 0x62/b 0x2f/slash 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t
34686 _string_2d_subtract_from_eax:  # (payload array byte)
34687     0x11/imm32/alloc-id:fake:payload
34688     # "2d/subtract-from-eax"
34689     0x14/imm32/size
34690     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
34691 _string_31_xor_with:  # (payload array byte)
34692     0x11/imm32/alloc-id:fake:payload
34693     # "31/xor-with"
34694     0xb/imm32/size
34695     0x33/3 0x31/1 0x2f/slash 0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
34696 _string_33_xor:  # (payload array byte)
34697     0x11/imm32/alloc-id:fake:payload
34698     # "33/xor"
34699     0x6/imm32/size
34700     0x33/3 0x33/3 0x2f/slash 0x78/x 0x6f/o 0x72/r
34701 _string_35_xor_with_eax:  # (payload array byte)
34702     0x11/imm32/alloc-id:fake:payload
34703     # "35/xor-with-eax"
34704     0xf/imm32/size
34705     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
34706 _string_39_compare->:  # (payload array byte)
34707     0x11/imm32/alloc-id:fake:payload
34708     # "39/compare->"
34709     0xc/imm32/size
34710     0x33/3 0x39/9 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x2d/dash 0x3e/>
34711 _string_3b_compare<-:  # (payload array byte)
34712     0x11/imm32/alloc-id:fake:payload
34713     # "3b/compare<-"
34714     0xc/imm32/size
34715     0x33/3 0x62/b 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x3c/< 0x2d/dash
34716 _string_3d_compare_eax_with:  # (payload array byte)
34717     0x11/imm32/alloc-id:fake:payload
34718     # "3d/compare-eax-with"
34719     0x13/imm32/size
34720     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
34721 _string_40_increment_eax:  # (payload array byte)
34722     0x11/imm32/alloc-id:fake:payload
34723     # "40/increment-eax"
34724     0x10/imm32/size
34725     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
34726 _string_41_increment_ecx:  # (payload array byte)
34727     0x11/imm32/alloc-id:fake:payload
34728     # "41/increment-ecx"
34729     0x10/imm32/size
34730     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
34731 _string_42_increment_edx:  # (payload array byte)
34732     0x11/imm32/alloc-id:fake:payload
34733     # "42/increment-edx"
34734     0x10/imm32/size
34735     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
34736 _string_43_increment_ebx:  # (payload array byte)
34737     0x11/imm32/alloc-id:fake:payload
34738     # "43/increment-ebx"
34739     0x10/imm32/size
34740     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
34741 _string_46_increment_esi:  # (payload array byte)
34742     0x11/imm32/alloc-id:fake:payload
34743     # "46/increment-esi"
34744     0x10/imm32/size
34745     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
34746 _string_47_increment_edi:  # (payload array byte)
34747     0x11/imm32/alloc-id:fake:payload
34748     # "47/increment-edi"
34749     0x10/imm32/size
34750     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
34751 _string_48_decrement_eax:  # (payload array byte)
34752     0x11/imm32/alloc-id:fake:payload
34753     # "48/decrement-eax"
34754     0x10/imm32/size
34755     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
34756 _string_49_decrement_ecx:  # (payload array byte)
34757     0x11/imm32/alloc-id:fake:payload
34758     # "49/decrement-ecx"
34759     0x10/imm32/size
34760     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
34761 _string_4a_decrement_edx:  # (payload array byte)
34762     0x11/imm32/alloc-id:fake:payload
34763     # "4a/decrement-edx"
34764     0x10/imm32/size
34765     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
34766 _string_4b_decrement_ebx:  # (payload array byte)
34767     0x11/imm32/alloc-id:fake:payload
34768     # "4b/decrement-ebx"
34769     0x10/imm32/size
34770     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
34771 _string_4e_decrement_esi:  # (payload array byte)
34772     0x11/imm32/alloc-id:fake:payload
34773     # "4e/decrement-esi"
34774     0x10/imm32/size
34775     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
34776 _string_4f_decrement_edi:  # (payload array byte)
34777     0x11/imm32/alloc-id:fake:payload
34778     # "4f/decrement-edi"
34779     0x10/imm32/size
34780     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
34781 _string_81_subop_add:  # (payload array byte)
34782     0x11/imm32/alloc-id:fake:payload
34783     # "81 0/subop/add"
34784     0xe/imm32/size
34785     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
34786 _string_81_subop_or:  # (payload array byte)
34787     0x11/imm32/alloc-id:fake:payload
34788     # "81 1/subop/or"
34789     0xd/imm32/size
34790     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
34791 _string_81_subop_and:  # (payload array byte)
34792     0x11/imm32/alloc-id:fake:payload
34793     # "81 4/subop/and"
34794     0xe/imm32/size
34795     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
34796 _string_81_subop_subtract:  # (payload array byte)
34797     0x11/imm32/alloc-id:fake:payload
34798     # "81 5/subop/subtract"
34799     0x13/imm32/size
34800     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
34801 _string_81_subop_xor:  # (payload array byte)
34802     0x11/imm32/alloc-id:fake:payload
34803     # "81 6/subop/xor"
34804     0xe/imm32/size
34805     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
34806 _string_81_subop_compare:  # (payload array byte)
34807     0x11/imm32/alloc-id:fake:payload
34808     # "81 7/subop/compare"
34809     0x12/imm32/size
34810     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
34811 _string_89_<-:  # (payload array byte)
34812     0x11/imm32/alloc-id:fake:payload
34813     # "89/<-"
34814     0x5/imm32/size
34815     0x38/8 0x39/9 0x2f/slash 0x3c/< 0x2d/dash
34816 _string_8b_->:  # (payload array byte)
34817     0x11/imm32/alloc-id:fake:payload
34818     # "8b/->"
34819     0x5/imm32/size
34820     0x38/8 0x62/b 0x2f/slash 0x2d/dash 0x3e/>
34821 _string_8a_copy_byte:
34822     0x11/imm32/alloc-id:fake:payload
34823     # "8a/byte->"
34824     0x9/imm32/size
34825     0x38/8 0x61/a 0x2f/slash 0x62/b 0x79/y 0x74/t 0x65/e 0x2d/dash 0x3e/>
34826 _string_88_copy_byte:
34827     0x11/imm32/alloc-id:fake:payload
34828     # "88/byte<-"
34829     0x9/imm32/size
34830     0x38/8 0x38/8 0x2f/slash 0x62/b 0x79/y 0x74/t 0x65/e 0x3c/< 0x2d/-
34831 _string_8d_copy_address:  # (payload array byte)
34832     0x11/imm32/alloc-id:fake:payload
34833     # "8d/copy-address"
34834     0xf/imm32/size
34835     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
34836 _string_b8_copy_to_eax:  # (payload array byte)
34837     0x11/imm32/alloc-id:fake:payload
34838     # "b8/copy-to-eax"
34839     0xe/imm32/size
34840     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
34841 _string_b9_copy_to_ecx:  # (payload array byte)
34842     0x11/imm32/alloc-id:fake:payload
34843     # "b9/copy-to-ecx"
34844     0xe/imm32/size
34845     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
34846 _string_ba_copy_to_edx:  # (payload array byte)
34847     0x11/imm32/alloc-id:fake:payload
34848     # "ba/copy-to-edx"
34849     0xe/imm32/size
34850     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
34851 _string_bb_copy_to_ebx:  # (payload array byte)
34852     0x11/imm32/alloc-id:fake:payload
34853     # "bb/copy-to-ebx"
34854     0xe/imm32/size
34855     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
34856 _string_be_copy_to_esi:  # (payload array byte)
34857     0x11/imm32/alloc-id:fake:payload
34858     # "be/copy-to-esi"
34859     0xe/imm32/size
34860     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
34861 _string_bf_copy_to_edi:  # (payload array byte)
34862     0x11/imm32/alloc-id:fake:payload
34863     # "bf/copy-to-edi"
34864     0xe/imm32/size
34865     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
34866 _string_c7_subop_copy:  # (payload array byte)
34867     0x11/imm32/alloc-id:fake:payload
34868     # "c7 0/subop/copy"
34869     0xf/imm32/size
34870     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
34871 _string_e9_jump_label:  # (payload array byte)
34872     0x11/imm32/alloc-id:fake:payload
34873     # "e9/jump"
34874     0x7/imm32/size
34875     0x65/e 0x39/9 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p
34876 _string_e9_jump_break:  # (payload array byte)
34877     0x11/imm32/alloc-id:fake:payload
34878     # "e9/jump break/disp32"
34879     0x14/imm32/size
34880     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
34881 _string_e9_jump_loop:  # (payload array byte)
34882     0x11/imm32/alloc-id:fake:payload
34883     # "e9/jump loop/disp32"
34884     0x13/imm32/size
34885     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
34886 _string_f7_subop_negate:
34887     0x11/imm32/alloc-id:fake:payload
34888     # "f7 3/subop/negate"
34889     0x11/imm32/size
34890     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
34891 _string_f7_subop_not:
34892     0x11/imm32/alloc-id:fake:payload
34893     # "f7 2/subop/not"
34894     0xe/imm32/size
34895     0x66/f 0x37/7 0x20/space 0x32/2 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x6e/n 0x6f/o 0x74/t
34896 _string_ff_subop_increment:  # (payload array byte)
34897     0x11/imm32/alloc-id:fake:payload
34898     # "ff 0/subop/increment"
34899     0x14/imm32/size
34900     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
34901 _string_ff_subop_decrement:  # (payload array byte)
34902     0x11/imm32/alloc-id:fake:payload
34903     # "ff 1/subop/decrement"
34904     0x14/imm32/size
34905     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
34906 _string_c1_subop_shift_left:  # (payload array byte)
34907     0x11/imm32/alloc-id:fake:payload
34908     # "c1/shift 4/subop/left"
34909     0x15/imm32/size
34910     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
34911 _string_c1_subop_shift_right_padding_zeroes:  # (payload array byte)
34912     0x11/imm32/alloc-id:fake:payload
34913     # "c1/shift 5/subop/right-padding-zeroes"
34914     0x25/imm32/size
34915     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
34916 _string_c1_subop_shift_right_preserving_sign:  # (payload array byte)
34917     0x11/imm32/alloc-id:fake:payload
34918     # "c1/shift 7/subop/right-preserving-sign"
34919     0x26/imm32/size
34920     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
34921 
34922 Single-int-var-in-mem:  # (payload list var)
34923     0x11/imm32/alloc-id:fake:payload
34924     0x11/imm32/alloc-id:fake
34925     Int-var-in-mem/imm32
34926     0/imm32/next
34927     0/imm32/next
34928 
34929 Int-var-in-mem:  # (payload var)
34930     0x11/imm32/alloc-id:fake:payload
34931     0/imm32/name
34932     0/imm32/name
34933     0x11/imm32/alloc-id:fake
34934     Type-int/imm32
34935     1/imm32/some-block-depth
34936     1/imm32/some-stack-offset
34937     0/imm32/no-register
34938     0/imm32/no-register
34939 
34940 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
34941 Single-byte-var-in-mem:  # (payload list var)
34942     0x11/imm32/alloc-id:fake:payload
34943     0x11/imm32/alloc-id:fake
34944     Byte-var-in-mem/imm32
34945     0/imm32/next
34946     0/imm32/next
34947 
34948 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
34949 Byte-var-in-mem:  # (payload var)
34950     0x11/imm32/alloc-id:fake:payload
34951     0/imm32/name
34952     0/imm32/name
34953     0x11/imm32/alloc-id:fake
34954     Type-byte/imm32
34955     1/imm32/some-block-depth
34956     1/imm32/some-stack-offset
34957     0/imm32/no-register
34958     0/imm32/no-register
34959 
34960 Two-args-int-stack-int-reg:  # (payload list var)
34961     0x11/imm32/alloc-id:fake:payload
34962     0x11/imm32/alloc-id:fake
34963     Int-var-in-mem/imm32
34964     0x11/imm32/alloc-id:fake
34965     Single-int-var-in-some-register/imm32/next
34966 
34967 Two-int-args-in-regs:  # (payload list var)
34968     0x11/imm32/alloc-id:fake:payload
34969     0x11/imm32/alloc-id:fake
34970     Int-var-in-some-register/imm32
34971     0x11/imm32/alloc-id:fake
34972     Single-int-var-in-some-register/imm32/next
34973 
34974 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
34975 Two-args-byte-stack-byte-reg:  # (payload list var)
34976     0x11/imm32/alloc-id:fake:payload
34977     0x11/imm32/alloc-id:fake
34978     Byte-var-in-mem/imm32
34979     0x11/imm32/alloc-id:fake
34980     Single-byte-var-in-some-register/imm32/next
34981 
34982 Two-args-int-reg-int-stack:  # (payload list var)
34983     0x11/imm32/alloc-id:fake:payload
34984     0x11/imm32/alloc-id:fake
34985     Int-var-in-some-register/imm32
34986     0x11/imm32/alloc-id:fake
34987     Single-int-var-in-mem/imm32/next
34988 
34989 Two-args-int-eax-int-literal:  # (payload list var)
34990     0x11/imm32/alloc-id:fake:payload
34991     0x11/imm32/alloc-id:fake
34992     Int-var-in-eax/imm32
34993     0x11/imm32/alloc-id:fake
34994     Single-lit-var/imm32/next
34995 
34996 Int-var-and-literal:  # (payload list var)
34997     0x11/imm32/alloc-id:fake:payload
34998     0x11/imm32/alloc-id:fake
34999     Int-var-in-mem/imm32
35000     0x11/imm32/alloc-id:fake
35001     Single-lit-var/imm32/next
35002 
35003 Int-var-in-register-and-literal:  # (payload list var)
35004     0x11/imm32/alloc-id:fake:payload
35005     0x11/imm32/alloc-id:fake
35006     Int-var-in-some-register/imm32
35007     0x11/imm32/alloc-id:fake
35008     Single-lit-var/imm32/next
35009 
35010 Two-float-args-in-regs:  # (payload list var)
35011     0x11/imm32/alloc-id:fake:payload
35012     0x11/imm32/alloc-id:fake
35013     Float-var-in-some-register/imm32
35014     0x11/imm32/alloc-id:fake
35015     Single-float-var-in-some-register/imm32/next
35016 
35017 Two-args-float-reg-float-stack:  # (payload list var)
35018     0x11/imm32/alloc-id:fake:payload
35019     0x11/imm32/alloc-id:fake
35020     Float-var-in-some-register/imm32
35021     0x11/imm32/alloc-id:fake
35022     Single-float-var-in-mem/imm32/next
35023 
35024 Two-args-float-stack-float-reg:  # (payload list var)
35025     0x11/imm32/alloc-id:fake:payload
35026     0x11/imm32/alloc-id:fake
35027     Float-var-in-mem/imm32
35028     0x11/imm32/alloc-id:fake
35029     Single-float-var-in-some-register/imm32/next
35030 
35031 Single-int-var-in-some-register:  # (payload list var)
35032     0x11/imm32/alloc-id:fake:payload
35033     0x11/imm32/alloc-id:fake
35034     Int-var-in-some-register/imm32
35035     0/imm32/next
35036     0/imm32/next
35037 
35038 Single-addr-var-in-some-register:  # (payload list var)
35039     0x11/imm32/alloc-id:fake:payload
35040     0x11/imm32/alloc-id:fake
35041     Addr-var-in-some-register/imm32
35042     0/imm32/next
35043     0/imm32/next
35044 
35045 Single-byte-var-in-some-register:  # (payload list var)
35046     0x11/imm32/alloc-id:fake:payload
35047     0x11/imm32/alloc-id:fake
35048     Byte-var-in-some-register/imm32
35049     0/imm32/next
35050     0/imm32/next
35051 
35052 Int-var-in-some-register:  # (payload var)
35053     0x11/imm32/alloc-id:fake:payload
35054     0/imm32/name
35055     0/imm32/name
35056     0x11/imm32/alloc-id:fake
35057     Type-int/imm32
35058     1/imm32/some-block-depth
35059     0/imm32/no-stack-offset
35060     0x11/imm32/alloc-id:fake
35061     Any-register/imm32
35062 
35063 Any-register:  # (payload array byte)
35064     0x11/imm32/alloc-id:fake:payload
35065     1/imm32/size
35066     # data
35067     2a/asterisk
35068 
35069 Addr-var-in-some-register:  # (payload var)
35070     0x11/imm32/alloc-id:fake:payload
35071     0/imm32/name
35072     0/imm32/name
35073     0x11/imm32/alloc-id:fake
35074     Type-addr/imm32
35075     1/imm32/some-block-depth
35076     0/imm32/no-stack-offset
35077     0x11/imm32/alloc-id:fake
35078     Any-register/imm32
35079 
35080 Byte-var-in-some-register:  # (payload var)
35081     0x11/imm32/alloc-id:fake:payload
35082     0/imm32/name
35083     0/imm32/name
35084     0x11/imm32/alloc-id:fake
35085     Type-byte/imm32
35086     1/imm32/some-block-depth
35087     0/imm32/no-stack-offset
35088     0x11/imm32/alloc-id:fake
35089     Any-register/imm32
35090 
35091 Single-int-var-in-eax:  # (payload list var)
35092     0x11/imm32/alloc-id:fake:payload
35093     0x11/imm32/alloc-id:fake
35094     Int-var-in-eax/imm32
35095     0/imm32/next
35096     0/imm32/next
35097 
35098 Int-var-in-eax:
35099     0x11/imm32/alloc-id:fake:payload
35100     0/imm32/name
35101     0/imm32/name
35102     0x11/imm32/alloc-id:fake
35103     Type-int/imm32
35104     1/imm32/some-block-depth
35105     0/imm32/no-stack-offset
35106     0x11/imm32/alloc-id:fake
35107     $Mu-register-eax/imm32  # can't use Register-eax only to keep our buggy tools/treeshake.cc happy (TODO)
35108 
35109 Single-int-var-in-ecx:  # (payload list var)
35110     0x11/imm32/alloc-id:fake:payload
35111     0x11/imm32/alloc-id:fake
35112     Int-var-in-ecx/imm32
35113     0/imm32/next
35114     0/imm32/next
35115 
35116 Int-var-in-ecx:
35117     0x11/imm32/alloc-id:fake:payload
35118     0/imm32/name
35119     0/imm32/name
35120     0x11/imm32/alloc-id:fake
35121     Type-int/imm32
35122     1/imm32/some-block-depth
35123     0/imm32/no-stack-offset
35124     0x11/imm32/alloc-id:fake
35125     $Register-ecx/imm32/register
35126 
35127 Single-int-var-in-edx:  # (payload list var)
35128     0x11/imm32/alloc-id:fake:payload
35129     0x11/imm32/alloc-id:fake
35130     Int-var-in-edx/imm32
35131     0/imm32/next
35132     0/imm32/next
35133 
35134 Int-var-in-edx:  # (payload list var)
35135     0x11/imm32/alloc-id:fake:payload
35136     0/imm32/name
35137     0/imm32/name
35138     0x11/imm32/alloc-id:fake
35139     Type-int/imm32
35140     1/imm32/some-block-depth
35141     0/imm32/no-stack-offset
35142     0x11/imm32/alloc-id:fake
35143     $Register-edx/imm32/register
35144 
35145 Single-int-var-in-ebx:  # (payload list var)
35146     0x11/imm32/alloc-id:fake:payload
35147     0x11/imm32/alloc-id:fake
35148     Int-var-in-ebx/imm32
35149     0/imm32/next
35150     0/imm32/next
35151 
35152 Int-var-in-ebx:  # (payload list var)
35153     0x11/imm32/alloc-id:fake:payload
35154     0/imm32/name
35155     0/imm32/name
35156     0x11/imm32/alloc-id:fake
35157     Type-int/imm32
35158     1/imm32/some-block-depth
35159     0/imm32/no-stack-offset
35160     0x11/imm32/alloc-id:fake
35161     $Register-ebx/imm32/register
35162 
35163 Single-int-var-in-esi:  # (payload list var)
35164     0x11/imm32/alloc-id:fake:payload
35165     0x11/imm32/alloc-id:fake
35166     Int-var-in-esi/imm32
35167     0/imm32/next
35168     0/imm32/next
35169 
35170 Int-var-in-esi:  # (payload list var)
35171     0x11/imm32/alloc-id:fake:payload
35172     0/imm32/name
35173     0/imm32/name
35174     0x11/imm32/alloc-id:fake
35175     Type-int/imm32
35176     1/imm32/some-block-depth
35177     0/imm32/no-stack-offset
35178     0x11/imm32/alloc-id:fake
35179     $Register-esi/imm32/register
35180 
35181 Single-int-var-in-edi:  # (payload list var)
35182     0x11/imm32/alloc-id:fake:payload
35183     0x11/imm32/alloc-id:fake
35184     Int-var-in-edi/imm32
35185     0/imm32/next
35186     0/imm32/next
35187 
35188 Int-var-in-edi:  # (payload list var)
35189     0x11/imm32/alloc-id:fake:payload
35190     0/imm32/name
35191     0/imm32/name
35192     0x11/imm32/alloc-id:fake
35193     Type-int/imm32
35194     1/imm32/some-block-depth
35195     0/imm32/no-stack-offset
35196     0x11/imm32/alloc-id:fake
35197     $Register-edi/imm32/register
35198 
35199 Single-lit-var:  # (payload list var)
35200     0x11/imm32/alloc-id:fake:payload
35201     0x11/imm32/alloc-id:fake
35202     Lit-var/imm32
35203     0/imm32/next
35204     0/imm32/next
35205 
35206 Lit-var:  # (payload var)
35207     0x11/imm32/alloc-id:fake:payload
35208     0/imm32/name
35209     0/imm32/name
35210     0x11/imm32/alloc-id:fake
35211     Type-literal/imm32
35212     1/imm32/some-block-depth
35213     0/imm32/no-stack-offset
35214     0/imm32/no-register
35215     0/imm32/no-register
35216 
35217 Single-float-var-in-mem:  # (payload list var)
35218     0x11/imm32/alloc-id:fake:payload
35219     0x11/imm32/alloc-id:fake
35220     Float-var-in-mem/imm32
35221     0/imm32/next
35222     0/imm32/next
35223 
35224 Float-var-in-mem:  # (payload var)
35225     0x11/imm32/alloc-id:fake:payload
35226     0/imm32/name
35227     0/imm32/name
35228     0x11/imm32/alloc-id:fake
35229     Type-float/imm32
35230     1/imm32/some-block-depth
35231     1/imm32/some-stack-offset
35232     0/imm32/no-register
35233     0/imm32/no-register
35234 
35235 Single-float-var-in-some-register:  # (payload list var)
35236     0x11/imm32/alloc-id:fake:payload
35237     0x11/imm32/alloc-id:fake
35238     Float-var-in-some-register/imm32
35239     0/imm32/next
35240     0/imm32/next
35241 
35242 Float-var-in-some-register:  # (payload var)
35243     0x11/imm32/alloc-id:fake:payload
35244     0/imm32/name
35245     0/imm32/name
35246     0x11/imm32/alloc-id:fake
35247     Type-float/imm32
35248     1/imm32/some-block-depth
35249     0/imm32/no-stack-offset
35250     0x11/imm32/alloc-id:fake
35251     Any-register/imm32
35252 
35253 Type-int:  # (payload type-tree)
35254     0x11/imm32/alloc-id:fake:payload
35255     1/imm32/is-atom
35256     1/imm32/value:int
35257     0/imm32/left:unused
35258     0/imm32/right:null
35259     0/imm32/right:null
35260 
35261 Type-literal:  # (payload type-tree)
35262     0x11/imm32/alloc-id:fake:payload
35263     1/imm32/is-atom
35264     0/imm32/value:literal
35265     0/imm32/left:unused
35266     0/imm32/right:null
35267     0/imm32/right:null
35268 
35269 Type-addr:  # (payload type-tree)
35270     0x11/imm32/alloc-id:fake:payload
35271     1/imm32/is-atom
35272     2/imm32/value:addr
35273     0/imm32/left:unused
35274     0/imm32/right:null
35275     0/imm32/right:null
35276 
35277 Type-array:  # (payload type-tree)
35278     0x11/imm32/alloc-id:fake:payload
35279     1/imm32/is-atom
35280     3/imm32/value:array
35281     0/imm32/left:unused
35282     0/imm32/right:null
35283     0/imm32/right:null
35284 
35285 Type-byte:  # (payload type-tree)
35286     0x11/imm32/alloc-id:fake:payload
35287     1/imm32/is-atom
35288     8/imm32/value:byte
35289     0/imm32/left:unused
35290     0/imm32/right:null
35291     0/imm32/right:null
35292 
35293 Type-float:  # (payload type-tree)
35294     0x11/imm32/alloc-id:fake:payload
35295     1/imm32/is-atom
35296     0xf/imm32/value:float
35297     0/imm32/left:unused
35298     0/imm32/right:null
35299     0/imm32/right:null
35300 
35301 Addr-type-string:  # (addr type-tree)
35302   0/imm32/not-atom
35303   0x11/imm32/alloc-id:fake
35304   Type-addr/imm32/left
35305   0x11/imm32/alloc-id:fake
35306   _Addr-type-string:array/imm32/right
35307 _Addr-type-string:array:  # (payload type-tree)
35308   0x11/imm32/alloc-id:fake:payload
35309   0/imm32/not-atom
35310   0x11/imm32/alloc-id:fake
35311   Type-array/imm32/left
35312   0x11/imm32/alloc-id:fake
35313   _Addr-type-string:byte/imm32/right
35314 _Addr-type-string:byte:  # (payload type-tree)
35315   0x11/imm32/alloc-id:fake:payload
35316   0/imm32/not-atom
35317   0x11/imm32/alloc-id:fake
35318   Type-byte/imm32/left
35319   0/imm32/right:null
35320   0/imm32/right:null
35321 
35322 == code
35323 emit-subx-primitive:  # out: (addr buffered-file), stmt: (addr stmt), primitive: (addr primitive), err: (addr buffered-file), ed: (addr exit-descriptor)
35324     # . prologue
35325     55/push-ebp
35326     89/<- %ebp 4/r32/esp
35327     # . save registers
35328     50/push-eax
35329     51/push-ecx
35330     # ecx = primitive
35331     8b/-> *(ebp+0x10) 1/r32/ecx
35332     # emit primitive name
35333     (emit-indent *(ebp+8) *Curr-block-depth)
35334     (lookup *(ecx+0x18) *(ecx+0x1c))  # Primitive-subx-name Primitive-subx-name => eax
35335     (write-buffered *(ebp+8) %eax)
35336     # emit rm32 if necessary
35337     (emit-subx-rm32 *(ebp+8) *(ecx+0x20) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-rm32
35338     # emit xm32 if necessary
35339     (emit-subx-rm32 *(ebp+8) *(ecx+0x34) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-xm32
35340     # emit r32 if necessary
35341     (emit-subx-r32 *(ebp+8) *(ecx+0x24) *(ebp+0xc))  # Primitive-subx-r32
35342     # emit x32 if necessary
35343     (emit-subx-x32 *(ebp+8) *(ecx+0x38) *(ebp+0xc))  # Primitive-subx-x32
35344     # emit imm32 if necessary
35345     (emit-subx-imm32 *(ebp+8) *(ecx+0x28) *(ebp+0xc))  # Primitive-subx-imm32
35346     # emit imm8 if necessary
35347     (emit-subx-imm8 *(ebp+8) *(ecx+0x2c) *(ebp+0xc))  # Primitive-subx-imm8
35348     # emit disp32 if necessary
35349     (emit-subx-disp32 *(ebp+8) *(ecx+0x30) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-disp32
35350     (write-buffered *(ebp+8) Newline)
35351 $emit-subx-primitive:end:
35352     # . restore registers
35353     59/pop-to-ecx
35354     58/pop-to-eax
35355     # . epilogue
35356     89/<- %esp 5/r32/ebp
35357     5d/pop-to-ebp
35358     c3/return
35359 
35360 emit-subx-rm32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
35361     # . prologue
35362     55/push-ebp
35363     89/<- %ebp 4/r32/esp
35364     # . save registers
35365     50/push-eax
35366     # if (l == 0) return
35367     81 7/subop/compare *(ebp+0xc) 0/imm32
35368     74/jump-if-= $emit-subx-rm32:end/disp8
35369     # var v/eax: (addr stmt-var)
35370     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # => eax
35371     (emit-subx-var-as-rm32 *(ebp+8) %eax)
35372 $emit-subx-rm32:end:
35373     # . restore registers
35374     58/pop-to-eax
35375     # . epilogue
35376     89/<- %esp 5/r32/ebp
35377     5d/pop-to-ebp
35378     c3/return
35379 
35380 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)
35381     # . prologue
35382     55/push-ebp
35383     89/<- %ebp 4/r32/esp
35384     # . save registers
35385     51/push-ecx
35386     # eax = l
35387     8b/-> *(ebp+0xc) 0/r32/eax
35388     # ecx = stmt
35389     8b/-> *(ebp+8) 1/r32/ecx
35390     # if (l == 1) return stmt->inouts
35391     {
35392       3d/compare-eax-and 1/imm32
35393       75/jump-if-!= break/disp8
35394 $get-stmt-operand-from-arg-location:1:
35395       (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
35396       eb/jump $get-stmt-operand-from-arg-location:end/disp8
35397     }
35398     # if (l == 2) return stmt->inouts->next
35399     {
35400       3d/compare-eax-and 2/imm32
35401       75/jump-if-!= break/disp8
35402 $get-stmt-operand-from-arg-location:2:
35403       (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
35404       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
35405       eb/jump $get-stmt-operand-from-arg-location:end/disp8
35406     }
35407     # if (l == 3) return stmt->outputs
35408     {
35409       3d/compare-eax-and 3/imm32
35410       75/jump-if-!= break/disp8
35411 $get-stmt-operand-from-arg-location:3:
35412       (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
35413       eb/jump $get-stmt-operand-from-arg-location:end/disp8
35414     }
35415     # abort
35416     e9/jump $get-stmt-operand-from-arg-location:abort/disp32
35417 $get-stmt-operand-from-arg-location:end:
35418     # . restore registers
35419     59/pop-to-ecx
35420     # . epilogue
35421     89/<- %esp 5/r32/ebp
35422     5d/pop-to-ebp
35423     c3/return
35424 
35425 $get-stmt-operand-from-arg-location:abort:
35426     # error("invalid arg-location " eax)
35427     (write-buffered *(ebp+0x10) "invalid arg-location ")
35428     (write-int32-hex-buffered *(ebp+0x10) %eax)
35429     (write-buffered *(ebp+0x10) Newline)
35430     (flush *(ebp+0x10))
35431     (stop *(ebp+0x14) 1)
35432     # never gets here
35433 
35434 emit-subx-r32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
35435     # . prologue
35436     55/push-ebp
35437     89/<- %ebp 4/r32/esp
35438     # . save registers
35439     50/push-eax
35440     51/push-ecx
35441     # if (l == 0) return
35442     81 7/subop/compare *(ebp+0xc) 0/imm32
35443     0f 84/jump-if-= $emit-subx-r32:end/disp32
35444     # var v/eax: (addr stmt-var)
35445     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
35446     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
35447     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
35448 #?     (write-buffered Stderr "looking up ")
35449 #?     (write-buffered Stderr %eax)
35450 #?     (write-buffered Stderr Newline)
35451 #?     (flush Stderr)
35452     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
35453     (write-buffered *(ebp+8) Space)
35454     (write-int32-hex-buffered *(ebp+8) *eax)
35455     (write-buffered *(ebp+8) "/r32")
35456 $emit-subx-r32:end:
35457     # . restore registers
35458     59/pop-to-ecx
35459     58/pop-to-eax
35460     # . epilogue
35461     89/<- %esp 5/r32/ebp
35462     5d/pop-to-ebp
35463     c3/return
35464 
35465 emit-subx-x32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
35466     # . prologue
35467     55/push-ebp
35468     89/<- %ebp 4/r32/esp
35469     # . save registers
35470     50/push-eax
35471     51/push-ecx
35472     # if (l == 0) return
35473     81 7/subop/compare *(ebp+0xc) 0/imm32
35474     0f 84/jump-if-= $emit-subx-x32:end/disp32
35475     # var v/eax: (addr stmt-var)
35476     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
35477     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
35478     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
35479 #?     (write-buffered Stderr "looking up ")
35480 #?     (write-buffered Stderr %eax)
35481 #?     (write-buffered Stderr Newline)
35482 #?     (flush Stderr)
35483     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
35484     (write-buffered *(ebp+8) Space)
35485     (write-int32-hex-buffered *(ebp+8) *eax)
35486     (write-buffered *(ebp+8) "/x32")
35487 $emit-subx-x32:end:
35488     # . restore registers
35489     59/pop-to-ecx
35490     58/pop-to-eax
35491     # . epilogue
35492     89/<- %esp 5/r32/ebp
35493     5d/pop-to-ebp
35494     c3/return
35495 
35496 emit-subx-imm32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
35497     # . prologue
35498     55/push-ebp
35499     89/<- %ebp 4/r32/esp
35500     # . save registers
35501     50/push-eax
35502     51/push-ecx
35503     # if (l == 0) return
35504     81 7/subop/compare *(ebp+0xc) 0/imm32
35505     0f 84/jump-if-= $emit-subx-imm32:end/disp32
35506     # var v/eax: (handle var)
35507     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
35508     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
35509     (lookup *eax *(eax+4))  # Var-name Var-name => eax
35510     (write-buffered *(ebp+8) Space)
35511     (write-buffered *(ebp+8) %eax)
35512     (write-buffered *(ebp+8) "/imm32")
35513 $emit-subx-imm32:end:
35514     # . restore registers
35515     59/pop-to-ecx
35516     58/pop-to-eax
35517     # . epilogue
35518     89/<- %esp 5/r32/ebp
35519     5d/pop-to-ebp
35520     c3/return
35521 
35522 emit-subx-imm8:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
35523     # . prologue
35524     55/push-ebp
35525     89/<- %ebp 4/r32/esp
35526     # . save registers
35527     50/push-eax
35528     51/push-ecx
35529     # if (l == 0) return
35530     81 7/subop/compare *(ebp+0xc) 0/imm32
35531     0f 84/jump-if-= $emit-subx-imm32:end/disp32
35532     # var v/eax: (handle var)
35533     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
35534     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
35535     (lookup *eax *(eax+4))  # Var-name Var-name => eax
35536     (write-buffered *(ebp+8) Space)
35537     (write-buffered *(ebp+8) %eax)
35538     (write-buffered *(ebp+8) "/imm8")
35539 $emit-subx-imm8:end:
35540     # . restore registers
35541     59/pop-to-ecx
35542     58/pop-to-eax
35543     # . epilogue
35544     89/<- %esp 5/r32/ebp
35545     5d/pop-to-ebp
35546     c3/return
35547 
35548 emit-subx-disp32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
35549     # . prologue
35550     55/push-ebp
35551     89/<- %ebp 4/r32/esp
35552     # . save registers
35553     50/push-eax
35554     51/push-ecx
35555     # if (location == 0) return
35556     81 7/subop/compare *(ebp+0xc) 0/imm32
35557     0f 84/jump-if-= $emit-subx-disp32:end/disp32
35558     # var v/eax: (addr stmt-var)
35559     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # => eax
35560     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
35561     (lookup *eax *(eax+4))  # Var-name Var-name => eax
35562     (write-buffered *(ebp+8) Space)
35563     (write-buffered *(ebp+8) %eax)
35564     # hack: if instruction operation starts with "break", emit ":break"
35565     # var name/ecx: (addr array byte) = lookup(stmt->operation)
35566     8b/-> *(ebp+0x10) 0/r32/eax
35567     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
35568     89/<- %ecx 0/r32/eax
35569     {
35570       (string-starts-with? %ecx "break")  # => eax
35571       3d/compare-eax-and 0/imm32/false
35572       74/jump-if-= break/disp8
35573       (write-buffered *(ebp+8) ":break")
35574     }
35575     # hack: if instruction operation starts with "loop", emit ":loop"
35576     {
35577       (string-starts-with? %ecx "loop")  # => eax
35578       3d/compare-eax-and 0/imm32/false
35579       74/jump-if-= break/disp8
35580       (write-buffered *(ebp+8) ":loop")
35581     }
35582     (write-buffered *(ebp+8) "/disp32")
35583 $emit-subx-disp32:end:
35584     # . restore registers
35585     59/pop-to-ecx
35586     58/pop-to-eax
35587     # . epilogue
35588     89/<- %esp 5/r32/ebp
35589     5d/pop-to-ebp
35590     c3/return
35591 
35592 emit-call:  # out: (addr buffered-file), stmt: (addr stmt)
35593     # . prologue
35594     55/push-ebp
35595     89/<- %ebp 4/r32/esp
35596     # . save registers
35597     50/push-eax
35598     51/push-ecx
35599     #
35600     (emit-indent *(ebp+8) *Curr-block-depth)
35601     (write-buffered *(ebp+8) "(")
35602     # ecx = stmt
35603     8b/-> *(ebp+0xc) 1/r32/ecx
35604     # - emit function name
35605     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
35606     (write-buffered *(ebp+8) %eax)
35607     # - emit arguments
35608     # var curr/eax: (addr stmt-var) = lookup(stmt->inouts)
35609     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
35610     {
35611       # if (curr == null) break
35612       3d/compare-eax-and 0/imm32
35613       74/jump-if-= break/disp8
35614       #
35615       (emit-subx-call-operand *(ebp+8) %eax)
35616       # curr = lookup(curr->next)
35617       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
35618       eb/jump loop/disp8
35619     }
35620     #
35621     (write-buffered *(ebp+8) ")\n")
35622 $emit-call:end:
35623     # . restore registers
35624     59/pop-to-ecx
35625     58/pop-to-eax
35626     # . epilogue
35627     89/<- %esp 5/r32/ebp
35628     5d/pop-to-ebp
35629     c3/return
35630 
35631 emit-subx-call-operand:  # out: (addr buffered-file), s: (addr stmt-var)
35632     # shares code with emit-subx-var-as-rm32
35633     # . prologue
35634     55/push-ebp
35635     89/<- %ebp 4/r32/esp
35636     # . save registers
35637     50/push-eax
35638     51/push-ecx
35639     56/push-esi
35640     # ecx = s
35641     8b/-> *(ebp+0xc) 1/r32/ecx
35642     # var operand/esi: (addr var) = lookup(s->value)
35643     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
35644     89/<- %esi 0/r32/eax
35645     # if (operand->register && !s->is-deref?) emit "%__"
35646     {
35647 $emit-subx-call-operand:check-for-register-direct:
35648       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
35649       74/jump-if-= break/disp8
35650       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
35651       75/jump-if-!= break/disp8
35652 $emit-subx-call-operand:register-direct:
35653       (write-buffered *(ebp+8) " %")
35654       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
35655       (write-buffered *(ebp+8) %eax)
35656       e9/jump $emit-subx-call-operand:end/disp32
35657     }
35658     # else if (operand->register && s->is-deref?) emit "*__"
35659     {
35660 $emit-subx-call-operand:check-for-register-indirect:
35661       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
35662       74/jump-if-= break/disp8
35663       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
35664       74/jump-if-= break/disp8
35665 $emit-subx-call-operand:register-indirect:
35666       (emit-subx-call-operand-register-indirect *(ebp+8) %esi)
35667       e9/jump $emit-subx-call-operand:end/disp32
35668     }
35669     # else if (operand->stack-offset) emit "*(ebp+__)"
35670     {
35671       81 7/subop/compare *(esi+0x14) 0/imm32  # Var-offset
35672       74/jump-if-= break/disp8
35673 $emit-subx-call-operand:stack:
35674       (emit-subx-call-operand-stack *(ebp+8) %esi)
35675       e9/jump $emit-subx-call-operand:end/disp32
35676     }
35677     # else if (operand->type == literal) emit "__"
35678     {
35679       (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
35680       81 7/subop/compare *(eax+4) 0/imm32  # Type-tree-value
35681       75/jump-if-!= break/disp8
35682 $emit-subx-call-operand:literal:
35683       (write-buffered *(ebp+8) Space)
35684       (lookup *esi *(esi+4))  # Var-name Var-name => eax
35685       (write-buffered *(ebp+8) %eax)
35686       e9/jump $emit-subx-call-operand:end/disp32
35687     }
35688     # else if (operand->type == literal-string) emit "__"
35689     {
35690       (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
35691       81 7/subop/compare *(eax+4) 0x10/imm32  # Type-tree-value
35692       75/jump-if-!= break/disp8
35693 $emit-subx-call-operand:literal-string:
35694       (write-buffered *(ebp+8) Space)
35695       (lookup *esi *(esi+4))  # Var-name Var-name => eax
35696       (write-buffered *(ebp+8) %eax)
35697     }
35698 $emit-subx-call-operand:end:
35699     # . restore registers
35700     5e/pop-to-esi
35701     59/pop-to-ecx
35702     58/pop-to-eax
35703     # . epilogue
35704     89/<- %esp 5/r32/ebp
35705     5d/pop-to-ebp
35706     c3/return
35707 
35708 emit-subx-call-operand-register-indirect:  # out: (addr buffered-file), v: (addr var)
35709     # . prologue
35710     55/push-ebp
35711     89/<- %ebp 4/r32/esp
35712     # . save registers
35713     50/push-eax
35714     51/push-ecx
35715     56/push-esi
35716     # esi = v
35717     8b/-> *(ebp+0xc) 6/r32/esi
35718     # var size/ecx: int = size-of-deref(v)
35719     (size-of-deref %esi)  # => eax
35720     89/<- %ecx 0/r32/eax
35721     # var reg-name/esi: (addr array byte) = lookup(v->register)
35722     (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
35723     89/<- %esi 0/r32/eax
35724     # TODO: assert size is a multiple of 4
35725     # var i/eax: int = 0
35726     b8/copy-to-eax 0/imm32
35727     {
35728 $emit-subx-call-operand-register-indirect:loop:
35729       # if (i >= size) break
35730       39/compare %eax 1/r32/ecx
35731       7d/jump-if->= break/disp8
35732       # emit " *(" v->register "+" i ")"
35733       (write-buffered *(ebp+8) " *(")
35734       (write-buffered *(ebp+8) %esi)
35735       (write-buffered *(ebp+8) "+")
35736       (write-int32-hex-buffered *(ebp+8) %eax)
35737       (write-buffered *(ebp+8) ")")
35738       # i += 4
35739       05/add-to-eax 4/imm32
35740       #
35741       eb/jump loop/disp8
35742     }
35743 $emit-subx-call-operand-register-indirect:end:
35744     # . restore registers
35745     5e/pop-to-esi
35746     59/pop-to-ecx
35747     58/pop-to-eax
35748     # . epilogue
35749     89/<- %esp 5/r32/ebp
35750     5d/pop-to-ebp
35751     c3/return
35752 
35753 emit-subx-call-operand-stack:  # out: (addr buffered-file), v: (addr var)
35754     # . prologue
35755     55/push-ebp
35756     89/<- %ebp 4/r32/esp
35757     # . save registers
35758     50/push-eax
35759     51/push-ecx
35760     56/push-esi
35761     # esi = v
35762     8b/-> *(ebp+0xc) 6/r32/esi
35763     # var curr/ecx: int = v->offset
35764     8b/-> *(esi+0x14) 1/r32/ecx  # Var-offset
35765     # var max/eax: int = v->offset + size-of(v)
35766     (size-of %esi)  # => eax
35767     # TODO: assert size is a multiple of 4
35768     01/add-to %eax 1/r32/ecx
35769     {
35770 $emit-subx-call-operand-stack:loop:
35771       # if (curr >= max) break
35772       39/compare %ecx 0/r32/eax
35773       7d/jump-if->= break/disp8
35774       # emit " *(ebp+" curr ")"
35775       (write-buffered *(ebp+8) " *(ebp+")
35776       (write-int32-hex-buffered *(ebp+8) %ecx)
35777       (write-buffered *(ebp+8) ")")
35778       # i += 4
35779       81 0/subop/add %ecx 4/imm32
35780       #
35781       eb/jump loop/disp8
35782     }
35783 $emit-subx-call-operand-stack:end:
35784     # . restore registers
35785     5e/pop-to-esi
35786     59/pop-to-ecx
35787     58/pop-to-eax
35788     # . epilogue
35789     89/<- %esp 5/r32/ebp
35790     5d/pop-to-ebp
35791     c3/return
35792 
35793 emit-subx-var-as-rm32:  # out: (addr buffered-file), s: (addr stmt-var)
35794     # . prologue
35795     55/push-ebp
35796     89/<- %ebp 4/r32/esp
35797     # . save registers
35798     50/push-eax
35799     51/push-ecx
35800     56/push-esi
35801     # ecx = s
35802     8b/-> *(ebp+0xc) 1/r32/ecx
35803     # var operand/esi: (addr var) = lookup(s->value)
35804     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
35805     89/<- %esi 0/r32/eax
35806     # if (operand->register && s->is-deref?) emit "*__"
35807     {
35808 $emit-subx-var-as-rm32:check-for-register-indirect:
35809       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
35810       74/jump-if-= break/disp8
35811       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
35812       74/jump-if-= break/disp8
35813 $emit-subx-var-as-rm32:register-indirect:
35814       (write-buffered *(ebp+8) " *")
35815       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
35816       (write-buffered *(ebp+8) %eax)
35817       e9/jump $emit-subx-var-as-rm32:end/disp32
35818     }
35819     # if (operand->register && !s->is-deref?) emit "%__"
35820     {
35821 $emit-subx-var-as-rm32:check-for-register-direct:
35822       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
35823       74/jump-if-= break/disp8
35824       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
35825       75/jump-if-!= break/disp8
35826 $emit-subx-var-as-rm32:register-direct:
35827       (write-buffered *(ebp+8) " %")
35828       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
35829       (write-buffered *(ebp+8) %eax)
35830       e9/jump $emit-subx-var-as-rm32:end/disp32
35831     }
35832     # else if (operand->stack-offset) emit "*(ebp+__)"
35833     {
35834       81 7/subop/compare *(esi+0x14) 0/imm32  # Var-offset
35835       74/jump-if-= break/disp8
35836 $emit-subx-var-as-rm32:stack:
35837       (write-buffered *(ebp+8) Space)
35838       (write-buffered *(ebp+8) "*(ebp+")
35839       (write-int32-hex-buffered *(ebp+8) *(esi+0x14))  # Var-offset
35840       (write-buffered *(ebp+8) ")")
35841     }
35842 $emit-subx-var-as-rm32:end:
35843     # . restore registers
35844     5e/pop-to-esi
35845     59/pop-to-ecx
35846     58/pop-to-eax
35847     # . epilogue
35848     89/<- %esp 5/r32/ebp
35849     5d/pop-to-ebp
35850     c3/return
35851 
35852 find-matching-primitive:  # primitives: (addr primitive), stmt: (addr stmt) -> result/eax: (addr primitive)
35853     # . prologue
35854     55/push-ebp
35855     89/<- %ebp 4/r32/esp
35856     # . save registers
35857     51/push-ecx
35858     # var curr/ecx: (addr primitive) = primitives
35859     8b/-> *(ebp+8) 1/r32/ecx
35860     {
35861 $find-matching-primitive:loop:
35862       # if (curr == null) break
35863       81 7/subop/compare %ecx 0/imm32
35864       74/jump-if-= break/disp8
35865       # if match(curr, stmt) return curr
35866       {
35867         (mu-stmt-matches-primitive? *(ebp+0xc) %ecx)  # => eax
35868         3d/compare-eax-and 0/imm32/false
35869         74/jump-if-= break/disp8
35870         89/<- %eax 1/r32/ecx
35871         eb/jump $find-matching-primitive:end/disp8
35872       }
35873 $find-matching-primitive:next-primitive:
35874       # curr = curr->next
35875       (lookup *(ecx+0x3c) *(ecx+0x40))  # Primitive-next Primitive-next => eax
35876       89/<- %ecx 0/r32/eax
35877       #
35878       e9/jump loop/disp32
35879     }
35880     # return null
35881     b8/copy-to-eax 0/imm32
35882 $find-matching-primitive:end:
35883     # . restore registers
35884     59/pop-to-ecx
35885     # . epilogue
35886     89/<- %esp 5/r32/ebp
35887     5d/pop-to-ebp
35888     c3/return
35889 
35890 mu-stmt-matches-primitive?:  # stmt: (addr stmt), primitive: (addr primitive) -> result/eax: boolean
35891     # A mu stmt matches a primitive if the name matches, all the inout vars
35892     # match, and all the output vars match.
35893     # Vars match if types match and registers match.
35894     # In addition, a stmt output matches a primitive's output if types match
35895     # and the primitive has a wildcard register.
35896     # . prologue
35897     55/push-ebp
35898     89/<- %ebp 4/r32/esp
35899     # . save registers
35900     51/push-ecx
35901     52/push-edx
35902     53/push-ebx
35903     56/push-esi
35904     57/push-edi
35905     # ecx = stmt
35906     8b/-> *(ebp+8) 1/r32/ecx
35907     # edx = primitive
35908     8b/-> *(ebp+0xc) 2/r32/edx
35909     {
35910 $mu-stmt-matches-primitive?:check-name:
35911       # if (primitive->name != stmt->operation) return false
35912       # . var esi: (addr array byte) = lookup(stmt->operation)
35913       (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
35914       89/<- %esi 0/r32/eax
35915       # . var edi: (addr array byte) = lookup(primitive->name)
35916       (lookup *edx *(edx+4))  # Primitive-name Primitive-name => eax
35917 #?       (write-buffered Stderr %eax)
35918 #?       (write-buffered Stderr Newline)
35919 #?       (flush Stderr)
35920       89/<- %edi 0/r32/eax
35921       (string-equal? %esi %edi)  # => eax
35922       3d/compare-eax-and 0/imm32/false
35923       75/jump-if-!= break/disp8
35924       b8/copy-to-eax 0/imm32
35925       e9/jump $mu-stmt-matches-primitive?:end/disp32
35926     }
35927     # var curr/esi: (addr stmt-var) = lookup(stmt->inouts)
35928     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
35929     89/<- %esi 0/r32/eax
35930     # var curr2/edi: (addr list var) = lookup(primitive->inouts)
35931     (lookup *(edx+8) *(edx+0xc))  # Primitive-inouts Primitive-inouts => eax
35932     89/<- %edi 0/r32/eax
35933     {
35934 $mu-stmt-matches-primitive?:inouts-loop:
35935       # if (curr == 0 && curr2 == 0) move on to check outputs
35936       {
35937 $mu-stmt-matches-primitive?:check-both-inouts-null:
35938         81 7/subop/compare %esi 0/imm32
35939         75/jump-if-!= break/disp8
35940 $mu-stmt-matches-primitive?:stmt-inout-null:
35941         81 7/subop/compare %edi 0/imm32
35942         0f 84/jump-if-= $mu-stmt-matches-primitive?:check-outputs/disp32
35943 $mu-stmt-matches-primitive?:stmt-inout-null-and-prim-inout-not-null:
35944         # return false
35945         b8/copy-to-eax 0/imm32/false
35946         e9/jump $mu-stmt-matches-primitive?:end/disp32
35947       }
35948       # if (curr2 == 0) return false
35949       {
35950 $mu-stmt-matches-primitive?:check-prim-inout-null:
35951         81 7/subop/compare %edi 0/imm32
35952         75/jump-if-!= break/disp8
35953 $mu-stmt-matches-primitive?:prim-inout-null:
35954         b8/copy-to-eax 0/imm32/false
35955         e9/jump $mu-stmt-matches-primitive?:end/disp32
35956       }
35957       # if (curr != curr2) return false
35958       {
35959 $mu-stmt-matches-primitive?:check-inouts-match:
35960         (lookup *edi *(edi+4))  # List-value List-value => eax
35961         (operand-matches-primitive? %esi %eax)  # => eax
35962         3d/compare-eax-and 0/imm32/false
35963         75/jump-if-!= break/disp8
35964 $mu-stmt-matches-primitive?:inouts-match:
35965         b8/copy-to-eax 0/imm32/false
35966         e9/jump $mu-stmt-matches-primitive?:end/disp32
35967       }
35968 $mu-stmt-matches-primitive?:next-inout:
35969       # curr = lookup(curr->next)
35970       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
35971       89/<- %esi 0/r32/eax
35972       # curr2 = lookup(curr2->next)
35973       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
35974       89/<- %edi 0/r32/eax
35975       #
35976       e9/jump loop/disp32
35977     }
35978 $mu-stmt-matches-primitive?:check-outputs:
35979     # var curr/esi: (addr stmt-var) = lookup(stmt->outputs)
35980     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
35981     89/<- %esi 0/r32/eax
35982     # var curr2/edi: (addr list var) = lookup(primitive->outputs)
35983     (lookup *(edx+0x10) *(edx+0x14))  # Primitive-outputs Primitive-outputs => eax
35984     89/<- %edi 0/r32/eax
35985     {
35986 $mu-stmt-matches-primitive?:outputs-loop:
35987       # if (curr == 0) return (curr2 == 0)
35988       {
35989 $mu-stmt-matches-primitive?:check-both-outputs-null:
35990         81 7/subop/compare %esi 0/imm32
35991         75/jump-if-!= break/disp8
35992         {
35993 $mu-stmt-matches-primitive?:stmt-output-null:
35994           81 7/subop/compare %edi 0/imm32
35995           75/jump-if-!= break/disp8
35996 $mu-stmt-matches-primitive?:both-outputs-null:
35997           # return true
35998           b8/copy-to-eax 1/imm32
35999           e9/jump $mu-stmt-matches-primitive?:end/disp32
36000         }
36001 $mu-stmt-matches-primitive?:stmt-output-null-and-prim-output-not-null:
36002         # return false
36003         b8/copy-to-eax 0/imm32
36004         e9/jump $mu-stmt-matches-primitive?:end/disp32
36005       }
36006       # if (curr2 == 0) return false
36007       {
36008 $mu-stmt-matches-primitive?:check-prim-output-null:
36009         81 7/subop/compare %edi 0/imm32
36010         75/jump-if-!= break/disp8
36011 $mu-stmt-matches-primitive?:prim-output-is-null:
36012         b8/copy-to-eax 0/imm32
36013         e9/jump $mu-stmt-matches-primitive?:end/disp32
36014       }
36015       # if (curr != curr2) return false
36016       {
36017 $mu-stmt-matches-primitive?:check-outputs-match:
36018         (lookup *edi *(edi+4))  # List-value List-value => eax
36019         (operand-matches-primitive? %esi %eax)  # => eax
36020         3d/compare-eax-and 0/imm32/false
36021         75/jump-if-!= break/disp8
36022 $mu-stmt-matches-primitive?:outputs-match:
36023         b8/copy-to-eax 0/imm32
36024         e9/jump $mu-stmt-matches-primitive?:end/disp32
36025       }
36026 $mu-stmt-matches-primitive?:next-output:
36027       # curr = lookup(curr->next)
36028       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
36029       89/<- %esi 0/r32/eax
36030       # curr2 = lookup(curr2->next)
36031       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
36032       89/<- %edi 0/r32/eax
36033       #
36034       e9/jump loop/disp32
36035     }
36036 $mu-stmt-matches-primitive?:return-true:
36037     b8/copy-to-eax 1/imm32
36038 $mu-stmt-matches-primitive?:end:
36039     # . restore registers
36040     5f/pop-to-edi
36041     5e/pop-to-esi
36042     5b/pop-to-ebx
36043     5a/pop-to-edx
36044     59/pop-to-ecx
36045     # . epilogue
36046     89/<- %esp 5/r32/ebp
36047     5d/pop-to-ebp
36048     c3/return
36049 
36050 operand-matches-primitive?:  # s: (addr stmt-var), prim-var: (addr var) -> result/eax: boolean
36051     # . prologue
36052     55/push-ebp
36053     89/<- %ebp 4/r32/esp
36054     # . save registers
36055     51/push-ecx
36056     52/push-edx
36057     53/push-ebx
36058     56/push-esi
36059     57/push-edi
36060     # ecx = s
36061     8b/-> *(ebp+8) 1/r32/ecx
36062     # var var/esi: (addr var) = lookup(s->value)
36063     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
36064     89/<- %esi 0/r32/eax
36065     # edi = prim-var
36066     8b/-> *(ebp+0xc) 7/r32/edi
36067 $operand-matches-primitive?:check-type:
36068     # if !category-match?(var->type, prim-var->type) return false
36069     # . var vtype/ebx: (addr type-tree) = lookup(var->type)
36070     (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
36071     89/<- %ebx 0/r32/eax
36072     # . if s is deref, vtype = vtype->right
36073     {
36074       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
36075       74/jump-if-= break/disp8
36076 $operand-matches-primitive?:is-deref:
36077       # . var t/eax: (addr type)
36078       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
36079       # . if !t->is-atom? t = t->left
36080       81 7/subop/compare *eax 0/imm32/false
36081       {
36082         75/jump-if-!= break/disp8
36083         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
36084       }
36085       # .
36086       89/<- %ebx 0/r32/eax
36087     }
36088     # . var ptype/eax: (addr type-tree) = lookup(prim-var->type)
36089     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
36090     (subx-type-category-match? %ebx %eax)  # => eax
36091     3d/compare-eax-and 0/imm32/false
36092     0f 84/jump-if-= $operand-matches-primitive?:return-false/disp32
36093     {
36094 $operand-matches-primitive?:check-register:
36095       # if prim-var is in memory and var is in register but dereference, match
36096       {
36097         81 7/subop/compare *(edi+0x18) 0/imm32  # Var-register
36098         0f 85/jump-if-!= break/disp32
36099         81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
36100         74/jump-if-= break/disp8
36101         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
36102         74/jump-if-= break/disp8
36103 $operand-matches-primitive?:var-deref-match:
36104         e9/jump $operand-matches-primitive?:return-true/disp32
36105       }
36106       # if prim-var is in register and var is in register but dereference, no match
36107       {
36108         81 7/subop/compare *(edi+0x18) 0/imm32  # Var-register
36109         0f 84/jump-if-= break/disp32
36110         81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
36111         0f 84/jump-if-= break/disp32
36112         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
36113         74/jump-if-= break/disp8
36114 $operand-matches-primitive?:var-deref-no-match:
36115         e9/jump $operand-matches-primitive?:return-false/disp32
36116       }
36117       # return false if var->register doesn't match prim-var->register
36118       {
36119         # if register addresses are equal, it's a match
36120         # var vreg/ebx: (addr array byte) = lookup(var->register)
36121         (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
36122         89/<- %ebx 0/r32/eax
36123         # var preg/ecx: (addr array byte) = lookup(prim-var->register)
36124         (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
36125         89/<- %ecx 0/r32/eax
36126         # if (vreg == preg) break
36127         39/compare %ecx 3/r32/ebx
36128         74/jump-if-= break/disp8
36129 $operand-matches-primitive?:var-register-no-match:
36130         # if either address is 0, return false
36131         81 7/subop/compare %ebx 0/imm32
36132         74/jump-if-=  $operand-matches-primitive?:return-false/disp8
36133         81 7/subop/compare %ecx 0/imm32
36134         74/jump-if-=  $operand-matches-primitive?:return-false/disp8
36135         # if prim-var->register is wildcard, it's a match
36136         (string-equal? %ecx "*")  # Any-register => eax
36137         3d/compare-eax-and 0/imm32/false
36138         75/jump-if-!= break/disp8
36139 $operand-matches-primitive?:wildcard-no-match:
36140         # if string contents aren't equal, return false
36141         (string-equal? %ecx %ebx)  # => eax
36142         3d/compare-eax-and 0/imm32/false
36143         74/jump-if-= $operand-matches-primitive?:return-false/disp8
36144       }
36145     }
36146 $operand-matches-primitive?:return-true:
36147     b8/copy-to-eax 1/imm32/true
36148     eb/jump $operand-matches-primitive?:end/disp8
36149 $operand-matches-primitive?:return-false:
36150     b8/copy-to-eax 0/imm32/false
36151 $operand-matches-primitive?:end:
36152     # . restore registers
36153     5f/pop-to-edi
36154     5e/pop-to-esi
36155     5b/pop-to-ebx
36156     5a/pop-to-edx
36157     59/pop-to-ecx
36158     # . epilogue
36159     89/<- %esp 5/r32/ebp
36160     5d/pop-to-ebp
36161     c3/return
36162 
36163 find-matching-function:  # functions: (addr function), stmt: (addr stmt) -> result/eax: (addr function)
36164     # . prologue
36165     55/push-ebp
36166     89/<- %ebp 4/r32/esp
36167     # . save registers
36168     51/push-ecx
36169     # var curr/ecx: (handle function) = functions
36170     8b/-> *(ebp+8) 1/r32/ecx
36171     {
36172       # if (curr == null) break
36173       81 7/subop/compare %ecx 0/imm32
36174       74/jump-if-= break/disp8
36175 #?       (write-buffered Stderr "iter\n")
36176 #?       (flush Stderr)
36177       # if match(stmt, curr) return curr
36178       {
36179         (mu-stmt-matches-function? *(ebp+0xc) %ecx)  # => eax
36180         3d/compare-eax-and 0/imm32/false
36181         74/jump-if-= break/disp8
36182         89/<- %eax 1/r32/ecx
36183         eb/jump $find-matching-function:end/disp8
36184       }
36185       # curr = curr->next
36186       (lookup *(ecx+0x20) *(ecx+0x24))  # Function-next Function-next => eax
36187       89/<- %ecx 0/r32/eax
36188       #
36189       eb/jump loop/disp8
36190     }
36191     # return null
36192     b8/copy-to-eax 0/imm32
36193 $find-matching-function:end:
36194     # . restore registers
36195     59/pop-to-ecx
36196     # . epilogue
36197     89/<- %esp 5/r32/ebp
36198     5d/pop-to-ebp
36199     c3/return
36200 
36201 # Just compare names; user-defined functions don't support overloading yet.
36202 mu-stmt-matches-function?:  # stmt: (addr stmt1), function: (addr function) -> result/eax: boolean
36203     # . prologue
36204     55/push-ebp
36205     89/<- %ebp 4/r32/esp
36206     # . save registers
36207     51/push-ecx
36208     # return function->name == stmt->operation
36209     # ecx = lookup(stmt->operation)
36210     8b/-> *(ebp+8) 0/r32/eax
36211     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
36212     89/<- %ecx 0/r32/eax
36213     # eax = lookup(function->name)
36214     8b/-> *(ebp+0xc) 0/r32/eax
36215     (lookup *eax *(eax+4))  # Function-name Function-name => eax
36216     (string-equal? %eax %ecx)  # => eax
36217 $mu-stmt-matches-function?:end:
36218     # . restore registers
36219     59/pop-to-ecx
36220     # . epilogue
36221     89/<- %esp 5/r32/ebp
36222     5d/pop-to-ebp
36223     c3/return
36224 
36225 # Type-checking happens elsewhere. This method is for selecting between
36226 # primitives.
36227 subx-type-category-match?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
36228     # . prologue
36229     55/push-ebp
36230     89/<- %ebp 4/r32/esp
36231     # . save registers
36232     51/push-ecx
36233     # var cata/ecx: int = type-category(a)
36234     (type-category *(ebp+8))  # => eax
36235     89/<- %ecx 0/r32/eax
36236     # var catb/eax: int = type-category(b)
36237     (type-category *(ebp+0xc))  # => eax
36238     # return cata == catb
36239     39/compare %eax 1/r32/ecx
36240     0f 94/set-byte-if-= %al
36241     25/and-eax-with 0xff/imm32
36242 $subx-type-category-match?:end:
36243     # . restore registers
36244     59/pop-to-ecx
36245     # . epilogue
36246     89/<- %esp 5/r32/ebp
36247     5d/pop-to-ebp
36248     c3/return
36249 
36250 type-category:  # a: (addr type-tree) -> result/eax: int
36251     # . prologue
36252     55/push-ebp
36253     89/<- %ebp 4/r32/esp
36254     # . save registers
36255     51/push-ecx
36256     # var lit?/ecx: boolean = literal-type?(a)
36257     (simple-mu-type? *(ebp+8) 0)  # literal => eax
36258     89/<- %ecx 0/r32/eax
36259     # var float?/eax: int = float?(a)
36260     (simple-mu-type? *(ebp+8) 0xf)  # => eax
36261     # set bits for lit? and float?
36262     c1/shift 4/subop/left %ecx 1/imm8
36263     09/or %eax 1/r32/ecx
36264 $type-category:end:
36265     # . restore registers
36266     59/pop-to-ecx
36267     # . epilogue
36268     89/<- %esp 5/r32/ebp
36269     5d/pop-to-ebp
36270     c3/return
36271 
36272 simple-mu-type?:  # a: (addr type-tree), n: type-id -> result/eax: boolean
36273     # . prologue
36274     55/push-ebp
36275     89/<- %ebp 4/r32/esp
36276     # . save registers
36277     51/push-ecx
36278     # ecx = n
36279     8b/-> *(ebp+0xc) 1/r32/ecx
36280     # return (a->value == n)
36281     8b/-> *(ebp+8) 0/r32/eax
36282     39/compare *(eax+4) 1/r32/ecx  # Type-tree-value
36283     0f 94/set-byte-if-= %al
36284     25/and-eax-with 0xff/imm32
36285 $simple-mu-type?:end:
36286     # . restore registers
36287     59/pop-to-ecx
36288     # . epilogue
36289     89/<- %esp 5/r32/ebp
36290     5d/pop-to-ebp
36291     c3/return
36292 
36293 mu-addr-type?:  # a: (addr type-tree) -> result/eax: boolean
36294     # . prologue
36295     55/push-ebp
36296     89/<- %ebp 4/r32/esp
36297     # eax = a
36298     8b/-> *(ebp+8) 0/r32/eax
36299     # if (!a->is-atom?) a = a->left
36300     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
36301     {
36302       75/jump-if-!= break/disp8
36303       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
36304     }
36305     # return (a->value == addr)
36306     81 7/subop/compare *(eax+4) 2/imm32/addr  # Type-tree-value
36307     0f 94/set-byte-if-= %al
36308     25/and-eax-with 0xff/imm32
36309 $mu-addr-type?:end:
36310     # . epilogue
36311     89/<- %esp 5/r32/ebp
36312     5d/pop-to-ebp
36313     c3/return
36314 
36315 mu-array-type?:  # a: (addr type-tree) -> result/eax: boolean
36316     # . prologue
36317     55/push-ebp
36318     89/<- %ebp 4/r32/esp
36319     # eax = a
36320     8b/-> *(ebp+8) 0/r32/eax
36321     # if (!a->is-atom?) a = a->left
36322     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
36323     {
36324       75/jump-if-!= break/disp8
36325       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
36326     }
36327     # return (a->value == array)
36328     81 7/subop/compare *(eax+4) 3/imm32/array  # Type-tree-value
36329     0f 94/set-byte-if-= %al
36330     25/and-eax-with 0xff/imm32
36331 $mu-array-type?:end:
36332     # . epilogue
36333     89/<- %esp 5/r32/ebp
36334     5d/pop-to-ebp
36335     c3/return
36336 
36337 mu-string-type?:  # a: (addr type-tree) -> result/eax: boolean
36338     # . prologue
36339     55/push-ebp
36340     89/<- %ebp 4/r32/esp
36341     # . save registers
36342     56/push-esi
36343     # esi = a
36344     8b/-> *(ebp+8) 6/r32/esi
36345     # if (a->is-atom?) return false
36346     81 7/subop/compare *esi 0/imm32/false  # Type-tree-is-atom
36347     0f 85/jump-if-!= $mu-string-type?:return-false/disp32
36348     # if a is not an addr, return false
36349     (mu-addr-type? %esi)  # => eax
36350     3d/compare-eax-with 0/imm32/false
36351     0f 84/jump-if-= $mu-string-type?:end/disp32  # eax changes var
36352     # if a is not an array, return false
36353     (lookup *(esi+0xc) *(esi+0x10))  # Type-tree-right Type-tree-right => eax
36354     (mu-array-type? %eax)  # => eax
36355     3d/compare-eax-with 0/imm32/false
36356     74/jump-if-= $mu-string-type?:end/disp8  # eax changes var
36357     # var p/eax: (addr type-tree) = payload of a
36358     (lookup *(esi+0xc) *(esi+0x10))  # Type-tree-right Type-tree-right => eax
36359     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
36360     # if p is an atom, return false
36361     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
36362     75/jump-if-!= $mu-string-type?:return-false/disp8
36363     # return (p == byte)
36364     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
36365     (simple-mu-type? %eax 8)  # byte => eax
36366     eb/jump $mu-string-type?:end/disp8
36367 $mu-string-type?:return-false:
36368     b8/copy-to-eax 0/imm32/false
36369 $mu-string-type?:end:
36370     # . restore registers
36371     5e/pop-to-esi
36372     # . epilogue
36373     89/<- %esp 5/r32/ebp
36374     5d/pop-to-ebp
36375     c3/return
36376 
36377 mu-stream-type?:  # a: (addr type-tree) -> result/eax: boolean
36378     # . prologue
36379     55/push-ebp
36380     89/<- %ebp 4/r32/esp
36381     # eax = a
36382     8b/-> *(ebp+8) 0/r32/eax
36383     # if (!a->is-atom?) a = a->left
36384     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
36385     {
36386       75/jump-if-!= break/disp8
36387       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
36388     }
36389     # return (a->value == stream)
36390     81 7/subop/compare *(eax+4) 0xb/imm32/stream  # Type-tree-value
36391     0f 94/set-byte-if-= %al
36392     25/and-eax-with 0xff/imm32
36393 $mu-stream-type?:end:
36394     # . epilogue
36395     89/<- %esp 5/r32/ebp
36396     5d/pop-to-ebp
36397     c3/return
36398 
36399 test-emit-subx-stmt-primitive:
36400     # Primitive operation on a variable on the stack.
36401     #   increment foo
36402     # =>
36403     #   ff 0/subop/increment *(ebp-8)
36404     #
36405     # There's a variable on the var stack as follows:
36406     #   name: 'foo'
36407     #   type: int
36408     #   stack-offset: -8
36409     #
36410     # There's a primitive with this info:
36411     #   name: 'increment'
36412     #   inouts: int/mem
36413     #   value: 'ff 0/subop/increment'
36414     #
36415     # . prologue
36416     55/push-ebp
36417     89/<- %ebp 4/r32/esp
36418     # setup
36419     (clear-stream _test-output-stream)
36420     (clear-stream $_test-output-buffered-file->buffer)
36421     # simulate allocated payloads starting with an initial fake alloc-id (0x11)
36422 $test-emit-subx-stmt-primitive:initialize-type:
36423     # var type/ecx: (payload type-tree) = int
36424     68/push 0/imm32/right:null
36425     68/push 0/imm32/right:null
36426     68/push 0/imm32/left:unused
36427     68/push 1/imm32/value:int
36428     68/push 1/imm32/is-atom?:true
36429     68/push 0x11/imm32/alloc-id:fake:payload
36430     89/<- %ecx 4/r32/esp
36431 $test-emit-subx-stmt-primitive:initialize-var:
36432     # var var-foo/ecx: (payload var) = var(type)
36433     68/push 0/imm32/no-register
36434     68/push 0/imm32/no-register
36435     68/push -8/imm32/stack-offset
36436     68/push 1/imm32/block-depth
36437     51/push-ecx/type
36438     68/push 0x11/imm32/alloc-id:fake
36439     68/push 0/imm32/name
36440     68/push 0/imm32/name
36441     68/push 0x11/imm32/alloc-id:fake:payload
36442     89/<- %ecx 4/r32/esp
36443 $test-emit-subx-stmt-primitive:initialize-var-name:
36444     # var-foo->name = "foo"
36445     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
36446     (copy-array Heap "foo" %eax)
36447 $test-emit-subx-stmt-primitive:initialize-stmt-var:
36448     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
36449     68/push 0/imm32/is-deref:false
36450     68/push 0/imm32/next
36451     68/push 0/imm32/next
36452     51/push-ecx/var-foo
36453     68/push 0x11/imm32/alloc-id:fake
36454     68/push 0x11/imm32/alloc-id:fake:payload
36455     89/<- %ebx 4/r32/esp
36456 $test-emit-subx-stmt-primitive:initialize-stmt:
36457     # var stmt/esi: (addr statement)
36458     68/push 0/imm32/no-outputs
36459     68/push 0/imm32/no-outputs
36460     53/push-ebx/inouts
36461     68/push 0x11/imm32/alloc-id:fake
36462     68/push 0/imm32/operation
36463     68/push 0/imm32/operation
36464     68/push 1/imm32/tag
36465     89/<- %esi 4/r32/esp
36466 $test-emit-subx-stmt-primitive:initialize-stmt-operation:
36467     # stmt->operation = "increment"
36468     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
36469     (copy-array Heap "increment" %eax)
36470 $test-emit-subx-stmt-primitive:initialize-primitive:
36471     # var primitives/ebx: (addr primitive)
36472     68/push 0/imm32/next
36473     68/push 0/imm32/next
36474     68/push 0/imm32/no-x32
36475     68/push 0/imm32/no-xm32
36476     68/push 0/imm32/no-disp32
36477     68/push 0/imm32/no-imm8
36478     68/push 0/imm32/no-imm32
36479     68/push 0/imm32/no-r32
36480     68/push 1/imm32/rm32-is-first-inout
36481     68/push 0/imm32/subx-name
36482     68/push 0/imm32/subx-name
36483     68/push 0/imm32/no-outputs
36484     68/push 0/imm32/no-outputs
36485     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
36486     68/push 0x11/imm32/alloc-id:fake
36487     68/push 0/imm32/name
36488     68/push 0/imm32/name
36489     89/<- %ebx 4/r32/esp
36490 $test-emit-subx-stmt-primitive:initialize-primitive-name:
36491     # primitives->name = "increment"
36492     (copy-array Heap "increment" %ebx)  # Primitive-name
36493 $test-emit-subx-stmt-primitive:initialize-primitive-subx-name:
36494     # primitives->subx-name = "ff 0/subop/increment"
36495     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
36496     (copy-array Heap "ff 0/subop/increment" %eax)
36497     # convert
36498     c7 0/subop/copy *Curr-block-depth 0/imm32
36499     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
36500     (flush _test-output-buffered-file)
36501 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
36507     # check output
36508     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-stmt-primitive")
36509     # . epilogue
36510     89/<- %esp 5/r32/ebp
36511     5d/pop-to-ebp
36512     c3/return
36513 
36514 test-emit-subx-stmt-primitive-register:
36515     # Primitive operation on a variable in a register.
36516     #   foo <- increment
36517     # =>
36518     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
36519     #
36520     # There's a variable on the var stack as follows:
36521     #   name: 'foo'
36522     #   type: int
36523     #   register: 'eax'
36524     #
36525     # There's a primitive with this info:
36526     #   name: 'increment'
36527     #   out: int/reg
36528     #   value: 'ff 0/subop/increment'
36529     #
36530     # . prologue
36531     55/push-ebp
36532     89/<- %ebp 4/r32/esp
36533     # setup
36534     (clear-stream _test-output-stream)
36535     (clear-stream $_test-output-buffered-file->buffer)
36536 $test-emit-subx-stmt-primitive-register:initialize-type:
36537     # var type/ecx: (payload type-tree) = int
36538     68/push 0/imm32/right:null
36539     68/push 0/imm32/right:null
36540     68/push 0/imm32/left:unused
36541     68/push 1/imm32/value:int
36542     68/push 1/imm32/is-atom?:true
36543     68/push 0x11/imm32/alloc-id:fake:payload
36544     89/<- %ecx 4/r32/esp
36545 $test-emit-subx-stmt-primitive-register:initialize-var:
36546     # var var-foo/ecx: (payload var)
36547     68/push 0/imm32/register
36548     68/push 0/imm32/register
36549     68/push 0/imm32/no-stack-offset
36550     68/push 1/imm32/block-depth
36551     51/push-ecx
36552     68/push 0x11/imm32/alloc-id:fake
36553     68/push 0/imm32/name
36554     68/push 0/imm32/name
36555     68/push 0x11/imm32/alloc-id:fake:payload
36556     89/<- %ecx 4/r32/esp
36557 $test-emit-subx-stmt-primitive-register:initialize-var-name:
36558     # var-foo->name = "foo"
36559     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
36560     (copy-array Heap "foo" %eax)
36561 $test-emit-subx-stmt-primitive-register:initialize-var-register:
36562     # var-foo->register = "eax"
36563     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
36564     (copy-array Heap "eax" %eax)
36565 $test-emit-subx-stmt-primitive-register:initialize-stmt-var:
36566     # var operand/ebx: (payload stmt-var)
36567     68/push 0/imm32/is-deref:false
36568     68/push 0/imm32/next
36569     68/push 0/imm32/next
36570     51/push-ecx/var-foo
36571     68/push 0x11/imm32/alloc-id:fake
36572     68/push 0x11/imm32/alloc-id:fake:payload
36573     89/<- %ebx 4/r32/esp
36574 $test-emit-subx-stmt-primitive-register:initialize-stmt:
36575     # var stmt/esi: (addr statement)
36576     53/push-ebx/outputs
36577     68/push 0x11/imm32/alloc-id:fake
36578     68/push 0/imm32/no-inouts
36579     68/push 0/imm32/no-inouts
36580     68/push 0/imm32/operation
36581     68/push 0/imm32/operation
36582     68/push 1/imm32
36583     89/<- %esi 4/r32/esp
36584 $test-emit-subx-stmt-primitive-register:initialize-stmt-operation:
36585     # stmt->operation = "increment"
36586     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
36587     (copy-array Heap "increment" %eax)
36588 $test-emit-subx-stmt-primitive-register:initialize-formal-var:
36589     # var formal-var/ebx: (payload var)
36590     68/push 0/imm32/register
36591     68/push 0/imm32/register
36592     68/push 0/imm32/no-stack-offset
36593     68/push 1/imm32/block-depth
36594     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
36595     68/push 0x11/imm32/alloc-id:fake
36596     68/push 0/imm32/name
36597     68/push 0/imm32/name
36598     68/push 0x11/imm32/alloc-id:fake:payload
36599     89/<- %ebx 4/r32/esp
36600 $test-emit-subx-stmt-primitive-register:initialize-formal-var-name:
36601     # formal-var->name = "dummy"
36602     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
36603     (copy-array Heap "dummy" %eax)
36604 $test-emit-subx-stmt-primitive-register:initialize-formal-register:
36605     # formal-var->register = "*"
36606     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
36607     (copy-array Heap "*" %eax)  # Any-register
36608 $test-emit-subx-stmt-primitive-register:initialize-var-list:
36609     # var formal-outputs/ebx: (payload list var)
36610     68/push 0/imm32/next
36611     68/push 0/imm32/next
36612     53/push-ebx/formal-var
36613     68/push 0x11/imm32/alloc-id:fake
36614     68/push 0x11/imm32/alloc-id:fake:payload
36615     89/<- %ebx 4/r32/esp
36616 $test-emit-subx-stmt-primitive-register:initialize-primitive:
36617     # var primitives/ebx: (addr primitive)
36618     68/push 0/imm32/next
36619     68/push 0/imm32/next
36620     68/push 0/imm32/no-x32
36621     68/push 0/imm32/no-xm32
36622     68/push 0/imm32/no-disp32
36623     68/push 0/imm32/no-imm8
36624     68/push 0/imm32/no-imm32
36625     68/push 0/imm32/no-r32
36626     68/push 3/imm32/rm32-is-first-output
36627     68/push 0/imm32/subx-name
36628     68/push 0/imm32/subx-name
36629     53/push-ebx/outputs
36630     68/push 0x11/imm32/alloc-id:fake
36631     68/push 0/imm32/no-inouts
36632     68/push 0/imm32/no-inouts
36633     68/push 0/imm32/name
36634     68/push 0/imm32/name
36635     89/<- %ebx 4/r32/esp
36636 $test-emit-subx-stmt-primitive-register:initialize-primitive-name:
36637     # primitives->name = "increment"
36638     (copy-array Heap "increment" %ebx)  # Primitive-name
36639 $test-emit-subx-stmt-primitive-register:initialize-primitive-subx-name:
36640     # primitives->subx-name = "ff 0/subop/increment"
36641     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
36642     (copy-array Heap "ff 0/subop/increment" %eax)
36643     # convert
36644     c7 0/subop/copy *Curr-block-depth 0/imm32
36645     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
36646     (flush _test-output-buffered-file)
36647 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
36653     # check output
36654     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-primitive-register")
36655     # . epilogue
36656     89/<- %esp 5/r32/ebp
36657     5d/pop-to-ebp
36658     c3/return
36659 
36660 test-emit-subx-stmt-select-primitive:
36661     # Select the right primitive between overloads.
36662     #   foo <- increment
36663     # =>
36664     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
36665     #
36666     # There's a variable on the var stack as follows:
36667     #   name: 'foo'
36668     #   type: int
36669     #   register: 'eax'
36670     #
36671     # There's two primitives, as follows:
36672     #   - name: 'increment'
36673     #     out: int/reg
36674     #     value: 'ff 0/subop/increment'
36675     #   - name: 'increment'
36676     #     inout: int/mem
36677     #     value: 'ff 0/subop/increment'
36678     #
36679     # . prologue
36680     55/push-ebp
36681     89/<- %ebp 4/r32/esp
36682     # setup
36683     (clear-stream _test-output-stream)
36684     (clear-stream $_test-output-buffered-file->buffer)
36685 $test-emit-subx-stmt-select-primitive:initialize-type:
36686     # var type/ecx: (payload type-tree) = int
36687     68/push 0/imm32/right:null
36688     68/push 0/imm32/right:null
36689     68/push 0/imm32/left:unused
36690     68/push 1/imm32/value:int
36691     68/push 1/imm32/is-atom?:true
36692     68/push 0x11/imm32/alloc-id:fake:payload
36693     89/<- %ecx 4/r32/esp
36694 $test-emit-subx-stmt-select-primitive:initialize-var:
36695     # var var-foo/ecx: (payload var)
36696     68/push 0/imm32/register
36697     68/push 0/imm32/register
36698     68/push 0/imm32/no-stack-offset
36699     68/push 1/imm32/block-depth
36700     51/push-ecx
36701     68/push 0x11/imm32/alloc-id:fake
36702     68/push 0/imm32/name
36703     68/push 0/imm32/name
36704     68/push 0x11/imm32/alloc-id:fake:payload
36705     89/<- %ecx 4/r32/esp
36706 $test-emit-subx-stmt-select-primitive:initialize-var-name:
36707     # var-foo->name = "foo"
36708     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
36709     (copy-array Heap "foo" %eax)
36710 $test-emit-subx-stmt-select-primitive:initialize-var-register:
36711     # var-foo->register = "eax"
36712     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
36713     (copy-array Heap "eax" %eax)
36714 $test-emit-subx-stmt-select-primitive:initialize-stmt-var:
36715     # var operand/ebx: (payload stmt-var)
36716     68/push 0/imm32/is-deref:false
36717     68/push 0/imm32/next
36718     68/push 0/imm32/next
36719     51/push-ecx/var-foo
36720     68/push 0x11/imm32/alloc-id:fake
36721     68/push 0x11/imm32/alloc-id:fake:payload
36722     89/<- %ebx 4/r32/esp
36723 $test-emit-subx-stmt-select-primitive:initialize-stmt:
36724     # var stmt/esi: (addr statement)
36725     53/push-ebx/outputs
36726     68/push 0x11/imm32/alloc-id:fake
36727     68/push 0/imm32/no-inouts
36728     68/push 0/imm32/no-inouts
36729     68/push 0/imm32/operation
36730     68/push 0/imm32/operation
36731     68/push 1/imm32
36732     89/<- %esi 4/r32/esp
36733 $test-emit-subx-stmt-select-primitive:initialize-stmt-operation:
36734     # stmt->operation = "increment"
36735     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
36736     (copy-array Heap "increment" %eax)
36737 $test-emit-subx-stmt-select-primitive:initialize-formal-var:
36738     # var formal-var/ebx: (payload var)
36739     68/push 0/imm32/register
36740     68/push 0/imm32/register
36741     68/push 0/imm32/no-stack-offset
36742     68/push 1/imm32/block-depth
36743     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
36744     68/push 0x11/imm32/alloc-id:fake
36745     68/push 0/imm32/name
36746     68/push 0/imm32/name
36747     68/push 0x11/imm32/alloc-id:fake:payload
36748     89/<- %ebx 4/r32/esp
36749 $test-emit-subx-stmt-select-primitive:initialize-formal-var-name:
36750     # formal-var->name = "dummy"
36751     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
36752     (copy-array Heap "dummy" %eax)
36753 $test-emit-subx-stmt-select-primitive:initialize-formal-register:
36754     # formal-var->register = "*"
36755     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
36756     (copy-array Heap "*" %eax)  # Any-register
36757 $test-emit-subx-stmt-select-primitive:initialize-var-list:
36758     # var formal-outputs/ebx: (payload list var)
36759     68/push 0/imm32/next
36760     68/push 0/imm32/next
36761     53/push-ebx/formal-var
36762     68/push 0x11/imm32/alloc-id:fake
36763     68/push 0x11/imm32/alloc-id:fake:payload
36764     89/<- %ebx 4/r32/esp
36765 $test-emit-subx-stmt-select-primitive:initialize-primitive2:
36766     # var primitive2/edi: (payload primitive)
36767     68/push 0/imm32/next
36768     68/push 0/imm32/next
36769     68/push 0/imm32/no-x32
36770     68/push 0/imm32/no-xm32
36771     68/push 0/imm32/no-disp32
36772     68/push 0/imm32/no-imm8
36773     68/push 0/imm32/no-imm32
36774     68/push 0/imm32/no-r32
36775     68/push 3/imm32/rm32-is-first-output
36776     68/push 0/imm32/subx-name
36777     68/push 0/imm32/subx-name
36778     53/push-ebx/outputs
36779     68/push 0x11/imm32/alloc-id:fake
36780     68/push 0/imm32/no-inouts
36781     68/push 0/imm32/no-inouts
36782     68/push 0/imm32/name
36783     68/push 0/imm32/name
36784     68/push 0x11/imm32/alloc-id:fake:payload
36785     89/<- %edi 4/r32/esp
36786 $test-emit-subx-stmt-select-primitive:initialize-primitive2-name:
36787     # primitives->name = "increment"
36788     8d/copy-address *(edi+4) 0/r32/eax  # Primitive-name + 4
36789     (copy-array Heap "increment" %eax)
36790 $test-emit-subx-stmt-select-primitive:initialize-primitive2-subx-name:
36791     # primitives->subx-name = "ff 0/subop/increment"
36792     8d/copy-address *(edi+0x1c) 0/r32/eax  # Primitive-subx-name + 4
36793     (copy-array Heap "ff 0/subop/increment" %eax)
36794 $test-emit-subx-stmt-select-primitive:initialize-primitive:
36795     # var primitives/ebx: (addr primitive)
36796     57/push-edi
36797     68/push 0x11/imm32/alloc-id:fake
36798     68/push 0/imm32/no-x32
36799     68/push 0/imm32/no-xm32
36800     68/push 0/imm32/no-disp32
36801     68/push 0/imm32/no-imm8
36802     68/push 0/imm32/no-imm32
36803     68/push 0/imm32/no-r32
36804     68/push 1/imm32/rm32-is-first-inout
36805     68/push 0/imm32/subx-name
36806     68/push 0/imm32/subx-name
36807     68/push 0/imm32/no-outputs
36808     68/push 0/imm32/no-outputs
36809     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
36810     68/push 0x11/imm32/alloc-id:fake
36811     68/push 0/imm32/name
36812     68/push 0/imm32/name
36813     89/<- %ebx 4/r32/esp
36814 $test-emit-subx-stmt-select-primitive:initialize-primitive-name:
36815     # primitives->name = "increment"
36816     (copy-array Heap "increment" %ebx)  # Primitive-name
36817 $test-emit-subx-stmt-select-primitive:initialize-primitive-subx-name:
36818     # primitives->subx-name = "ff 0/subop/increment"
36819     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
36820     (copy-array Heap "ff 0/subop/increment" %eax)
36821     # convert
36822     c7 0/subop/copy *Curr-block-depth 0/imm32
36823     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
36824     (flush _test-output-buffered-file)
36825 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
36831     # check output
36832     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive")
36833     # . epilogue
36834     89/<- %esp 5/r32/ebp
36835     5d/pop-to-ebp
36836     c3/return
36837 
36838 test-emit-subx-stmt-select-primitive-2:
36839     # Select the right primitive between overloads.
36840     #   increment foo
36841     # =>
36842     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
36843     #
36844     # There's a variable on the var stack as follows:
36845     #   name: 'foo'
36846     #   type: int
36847     #   register: 'eax'
36848     #
36849     # There's two primitives, as follows:
36850     #   - name: 'increment'
36851     #     out: int/reg
36852     #     value: 'ff 0/subop/increment'
36853     #   - name: 'increment'
36854     #     inout: int/mem
36855     #     value: 'ff 0/subop/increment'
36856     #
36857     # . prologue
36858     55/push-ebp
36859     89/<- %ebp 4/r32/esp
36860     # setup
36861     (clear-stream _test-output-stream)
36862     (clear-stream $_test-output-buffered-file->buffer)
36863 $test-emit-subx-stmt-select-primitive-2:initialize-type:
36864     # var type/ecx: (payload type-tree) = int
36865     68/push 0/imm32/right:null
36866     68/push 0/imm32/right:null
36867     68/push 0/imm32/left:unused
36868     68/push 1/imm32/value:int
36869     68/push 1/imm32/is-atom?:true
36870     68/push 0x11/imm32/alloc-id:fake:payload
36871     89/<- %ecx 4/r32/esp
36872 $test-emit-subx-stmt-select-primitive-2:initialize-var:
36873     # var var-foo/ecx: (payload var)
36874     68/push 0/imm32/register
36875     68/push 0/imm32/register
36876     68/push 0/imm32/no-stack-offset
36877     68/push 1/imm32/block-depth
36878     51/push-ecx
36879     68/push 0x11/imm32/alloc-id:fake
36880     68/push 0/imm32/name
36881     68/push 0/imm32/name
36882     68/push 0x11/imm32/alloc-id:fake:payload
36883     89/<- %ecx 4/r32/esp
36884 $test-emit-subx-stmt-select-primitive-2:initialize-var-name:
36885     # var-foo->name = "foo"
36886     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
36887     (copy-array Heap "foo" %eax)
36888 $test-emit-subx-stmt-select-primitive-2:initialize-var-register:
36889     # var-foo->register = "eax"
36890     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
36891     (copy-array Heap "eax" %eax)
36892 $test-emit-subx-stmt-select-primitive-2:initialize-stmt-var:
36893     # var operand/ebx: (payload stmt-var)
36894     68/push 0/imm32/is-deref:false
36895     68/push 0/imm32/next
36896     68/push 0/imm32/next
36897     51/push-ecx/var-foo
36898     68/push 0x11/imm32/alloc-id:fake
36899     68/push 0x11/imm32/alloc-id:fake:payload
36900     89/<- %ebx 4/r32/esp
36901 $test-emit-subx-stmt-select-primitive-2:initialize-stmt:
36902     # var stmt/esi: (addr statement)
36903     68/push 0/imm32/no-outputs
36904     68/push 0/imm32/no-outputs
36905     53/push-ebx/inouts
36906     68/push 0x11/imm32/alloc-id:fake
36907     68/push 0/imm32/operation
36908     68/push 0/imm32/operation
36909     68/push 1/imm32
36910     89/<- %esi 4/r32/esp
36911 $test-emit-subx-stmt-select-primitive-2:initialize-stmt-operation:
36912     # stmt->operation = "increment"
36913     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
36914     (copy-array Heap "increment" %eax)
36915 $test-emit-subx-stmt-select-primitive-2:initialize-formal-var:
36916     # var formal-var/ebx: (payload var)
36917     68/push 0/imm32/register
36918     68/push 0/imm32/register
36919     68/push 0/imm32/no-stack-offset
36920     68/push 1/imm32/block-depth
36921     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
36922     68/push 0x11/imm32/alloc-id:fake
36923     68/push 0/imm32/name
36924     68/push 0/imm32/name
36925     68/push 0x11/imm32/alloc-id:fake:payload
36926     89/<- %ebx 4/r32/esp
36927 $test-emit-subx-stmt-select-primitive-2:initialize-formal-var-name:
36928     # formal-var->name = "dummy"
36929     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
36930     (copy-array Heap "dummy" %eax)
36931 $test-emit-subx-stmt-select-primitive-2:initialize-formal-register:
36932     # formal-var->register = "*"
36933     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
36934     (copy-array Heap "*" %eax)  # Any-register
36935 $test-emit-subx-stmt-select-primitive-2:initialize-var-list:
36936     # var formal-outputs/ebx: (payload list stmt-var)
36937     68/push 0/imm32/next
36938     68/push 0/imm32/next
36939     53/push-ebx/formal-var
36940     68/push 0x11/imm32/alloc-id:fake
36941     68/push 0x11/imm32/alloc-id:fake:payload
36942     89/<- %ebx 4/r32/esp
36943 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2:
36944     # var primitive2/edi: (payload primitive)
36945     68/push 0/imm32/next
36946     68/push 0/imm32/next
36947     68/push 0/imm32/no-x32
36948     68/push 0/imm32/no-xm32
36949     68/push 0/imm32/no-disp32
36950     68/push 0/imm32/no-imm8
36951     68/push 0/imm32/no-imm32
36952     68/push 0/imm32/no-r32
36953     68/push 3/imm32/rm32-is-first-output
36954     68/push 0/imm32/subx-name
36955     68/push 0/imm32/subx-name
36956     53/push-ebx/outputs
36957     68/push 0x11/imm32/alloc-id:fake
36958     68/push 0/imm32/no-inouts
36959     68/push 0/imm32/no-inouts
36960     68/push 0/imm32/name
36961     68/push 0/imm32/name
36962     68/push 0x11/imm32/alloc-id:fake:payload
36963     89/<- %edi 4/r32/esp
36964 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2-name:
36965     # primitives->name = "increment"
36966     8d/copy-address *(edi+4) 0/r32/eax  # Primitive-name + 4
36967     (copy-array Heap "increment" %eax)
36968 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2-subx-name:
36969     # primitives->subx-name = "ff 0/subop/increment"
36970     8d/copy-address *(edi+0x1c) 0/r32/eax  # Primitive-subx-name + 4
36971     (copy-array Heap "ff 0/subop/increment" %eax)
36972 $test-emit-subx-stmt-select-primitive-2:initialize-primitive:
36973     # var primitives/ebx: (addr primitive)
36974     57/push-edi
36975     68/push 0x11/imm32/alloc-id:fake
36976     68/push 0/imm32/no-x32
36977     68/push 0/imm32/no-xm32
36978     68/push 0/imm32/no-disp32
36979     68/push 0/imm32/no-imm8
36980     68/push 0/imm32/no-imm32
36981     68/push 0/imm32/no-r32
36982     68/push 1/imm32/rm32-is-first-inout
36983     68/push 0/imm32/subx-name
36984     68/push 0/imm32/subx-name
36985     68/push 0/imm32/no-outputs
36986     68/push 0/imm32/no-outputs
36987     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
36988     68/push 0x11/imm32/alloc-id:fake
36989     68/push 0/imm32/name
36990     68/push 0/imm32/name
36991     89/<- %ebx 4/r32/esp
36992 $test-emit-subx-stmt-select-primitive-2:initialize-primitive-name:
36993     # primitives->name = "increment"
36994     (copy-array Heap "increment" %ebx)  # Primitive-name
36995 $test-emit-subx-stmt-select-primitive-2:initialize-primitive-subx-name:
36996     # primitives->subx-name = "ff 0/subop/increment"
36997     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
36998     (copy-array Heap "ff 0/subop/increment" %eax)
36999     # convert
37000     c7 0/subop/copy *Curr-block-depth 0/imm32
37001     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
37002     (flush _test-output-buffered-file)
37003 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37009     # check output
37010     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive-2")
37011     # . epilogue
37012     89/<- %esp 5/r32/ebp
37013     5d/pop-to-ebp
37014     c3/return
37015 
37016 test-increment-register:
37017     # Select the right register between overloads.
37018     #   foo <- increment
37019     # =>
37020     #   50/increment-eax
37021     #
37022     # There's a variable on the var stack as follows:
37023     #   name: 'foo'
37024     #   type: int
37025     #   register: 'eax'
37026     #
37027     # Primitives are the global definitions.
37028     #
37029     # . prologue
37030     55/push-ebp
37031     89/<- %ebp 4/r32/esp
37032     # setup
37033     (clear-stream _test-output-stream)
37034     (clear-stream $_test-output-buffered-file->buffer)
37035 $test-increment-register:initialize-type:
37036     # var type/ecx: (payload type-tree) = int
37037     68/push 0/imm32/right:null
37038     68/push 0/imm32/right:null
37039     68/push 0/imm32/left:unused
37040     68/push 1/imm32/value:int
37041     68/push 1/imm32/is-atom?:true
37042     68/push 0x11/imm32/alloc-id:fake:payload
37043     89/<- %ecx 4/r32/esp
37044 $test-increment-register:initialize-var:
37045     # var var-foo/ecx: (payload var)
37046     68/push 0/imm32/register
37047     68/push 0/imm32/register
37048     68/push 0/imm32/no-stack-offset
37049     68/push 1/imm32/block-depth
37050     51/push-ecx
37051     68/push 0x11/imm32/alloc-id:fake
37052     68/push 0/imm32/name
37053     68/push 0/imm32/name
37054     68/push 0x11/imm32/alloc-id:fake:payload
37055     89/<- %ecx 4/r32/esp
37056 $test-increment-register:initialize-var-name:
37057     # var-foo->name = "foo"
37058     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37059     (copy-array Heap "foo" %eax)
37060 $test-increment-register:initialize-var-register:
37061     # var-foo->register = "eax"
37062     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
37063     (copy-array Heap "eax" %eax)
37064 $test-increment-register:initialize-stmt-var:
37065     # var operand/ebx: (payload stmt-var)
37066     68/push 0/imm32/is-deref:false
37067     68/push 0/imm32/next
37068     68/push 0/imm32/next
37069     51/push-ecx/var-foo
37070     68/push 0x11/imm32/alloc-id:fake
37071     68/push 0x11/imm32/alloc-id:fake:payload
37072     89/<- %ebx 4/r32/esp
37073 $test-increment-register:initialize-stmt:
37074     # var stmt/esi: (addr statement)
37075     53/push-ebx/outputs
37076     68/push 0x11/imm32/alloc-id:fake
37077     68/push 0/imm32/no-inouts
37078     68/push 0/imm32/no-inouts
37079     68/push 0/imm32/operation
37080     68/push 0/imm32/operation
37081     68/push 1/imm32
37082     89/<- %esi 4/r32/esp
37083 $test-increment-register:initialize-stmt-operation:
37084     # stmt->operation = "increment"
37085     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37086     (copy-array Heap "increment" %eax)
37087     # convert
37088     c7 0/subop/copy *Curr-block-depth 0/imm32
37089     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37090     (flush _test-output-buffered-file)
37091 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37097     # check output
37098     (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-register")
37099     # . epilogue
37100     89/<- %esp 5/r32/ebp
37101     5d/pop-to-ebp
37102     c3/return
37103 
37104 test-add-reg-to-reg:
37105     #   var1/reg <- add var2/reg
37106     # =>
37107     #   01/add-to %var1 var2
37108     #
37109     # . prologue
37110     55/push-ebp
37111     89/<- %ebp 4/r32/esp
37112     # setup
37113     (clear-stream _test-output-stream)
37114     (clear-stream $_test-output-buffered-file->buffer)
37115 $test-add-reg-to-reg:initialize-type:
37116     # var type/ecx: (payload type-tree) = int
37117     68/push 0/imm32/right:null
37118     68/push 0/imm32/right:null
37119     68/push 0/imm32/left:unused
37120     68/push 1/imm32/value:int
37121     68/push 1/imm32/is-atom?:true
37122     68/push 0x11/imm32/alloc-id:fake:payload
37123     89/<- %ecx 4/r32/esp
37124 $test-add-reg-to-reg:initialize-var1:
37125     # var var1/ecx: (payload var)
37126     68/push 0/imm32/register
37127     68/push 0/imm32/register
37128     68/push 0/imm32/no-stack-offset
37129     68/push 1/imm32/block-depth
37130     51/push-ecx
37131     68/push 0x11/imm32/alloc-id:fake
37132     68/push 0/imm32/name
37133     68/push 0/imm32/name
37134     68/push 0x11/imm32/alloc-id:fake:payload
37135     89/<- %ecx 4/r32/esp
37136 $test-add-reg-to-reg:initialize-var1-name:
37137     # var1->name = "var1"
37138     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37139     (copy-array Heap "var1" %eax)
37140 $test-add-reg-to-reg:initialize-var1-register:
37141     # var1->register = "eax"
37142     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
37143     (copy-array Heap "eax" %eax)
37144 $test-add-reg-to-reg:initialize-var2:
37145     # var var2/edx: (payload var)
37146     68/push 0/imm32/register
37147     68/push 0/imm32/register
37148     68/push 0/imm32/no-stack-offset
37149     68/push 1/imm32/block-depth
37150     ff 6/subop/push *(ecx+0x10)
37151     68/push 0x11/imm32/alloc-id:fake
37152     68/push 0/imm32/name
37153     68/push 0/imm32/name
37154     68/push 0x11/imm32/alloc-id:fake:payload
37155     89/<- %edx 4/r32/esp
37156 $test-add-reg-to-reg:initialize-var2-name:
37157     # var2->name = "var2"
37158     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
37159     (copy-array Heap "var2" %eax)
37160 $test-add-reg-to-reg:initialize-var2-register:
37161     # var2->register = "ecx"
37162     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
37163     (copy-array Heap "ecx" %eax)
37164 $test-add-reg-to-reg:initialize-inouts:
37165     # var inouts/esi: (payload stmt-var) = [var2]
37166     68/push 0/imm32/is-deref:false
37167     68/push 0/imm32/next
37168     68/push 0/imm32/next
37169     52/push-edx/var2
37170     68/push 0x11/imm32/alloc-id:fake
37171     68/push 0x11/imm32/alloc-id:fake:payload
37172     89/<- %esi 4/r32/esp
37173 $test-add-reg-to-reg:initialize-outputs:
37174     # var outputs/edi: (payload stmt-var) = [var1]
37175     68/push 0/imm32/is-deref:false
37176     68/push 0/imm32/next
37177     68/push 0/imm32/next
37178     51/push-ecx/var1
37179     68/push 0x11/imm32/alloc-id:fake
37180     68/push 0x11/imm32/alloc-id:fake:payload
37181     89/<- %edi 4/r32/esp
37182 $test-add-reg-to-reg:initialize-stmt:
37183     # var stmt/esi: (addr statement)
37184     68/push 0/imm32/next
37185     68/push 0/imm32/next
37186     57/push-edi/outputs
37187     68/push 0x11/imm32/alloc-id:fake
37188     56/push-esi/inouts
37189     68/push 0x11/imm32/alloc-id:fake
37190     68/push 0/imm32/operation
37191     68/push 0/imm32/operation
37192     68/push 1/imm32/tag:stmt1
37193     89/<- %esi 4/r32/esp
37194 $test-add-reg-to-reg:initialize-stmt-operation:
37195     # stmt->operation = "add"
37196     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37197     (copy-array Heap "add" %eax)
37198     # convert
37199     c7 0/subop/copy *Curr-block-depth 0/imm32
37200     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37201     (flush _test-output-buffered-file)
37202 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37208     # check output
37209     (check-next-stream-line-equal _test-output-stream "01/add-to %eax 0x00000001/r32" "F - test-add-reg-to-reg")
37210     # . epilogue
37211     89/<- %esp 5/r32/ebp
37212     5d/pop-to-ebp
37213     c3/return
37214 
37215 test-add-reg-to-mem:
37216     #   add-to var1 var2/reg
37217     # =>
37218     #   01/add-to *(ebp+__) var2
37219     #
37220     # . prologue
37221     55/push-ebp
37222     89/<- %ebp 4/r32/esp
37223     # setup
37224     (clear-stream _test-output-stream)
37225     (clear-stream $_test-output-buffered-file->buffer)
37226 $test-add-reg-to-mem:initialize-type:
37227     # var type/ecx: (payload type-tree) = int
37228     68/push 0/imm32/right:null
37229     68/push 0/imm32/right:null
37230     68/push 0/imm32/left:unused
37231     68/push 1/imm32/value:int
37232     68/push 1/imm32/is-atom?:true
37233     68/push 0x11/imm32/alloc-id:fake:payload
37234     89/<- %ecx 4/r32/esp
37235 $test-add-reg-to-mem:initialize-var1:
37236     # var var1/ecx: (payload var)
37237     68/push 0/imm32/register
37238     68/push 0/imm32/register
37239     68/push 8/imm32/stack-offset
37240     68/push 1/imm32/block-depth
37241     51/push-ecx
37242     68/push 0x11/imm32/alloc-id:fake
37243     68/push 0/imm32/name
37244     68/push 0/imm32/name
37245     68/push 0x11/imm32/alloc-id:fake:payload
37246     89/<- %ecx 4/r32/esp
37247 $test-add-reg-to-mem:initialize-var1-name:
37248     # var1->name = "var1"
37249     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37250     (copy-array Heap "var1" %eax)
37251 $test-add-reg-to-mem:initialize-var2:
37252     # var var2/edx: (payload var)
37253     68/push 0/imm32/register
37254     68/push 0/imm32/register
37255     68/push 0/imm32/no-stack-offset
37256     68/push 1/imm32/block-depth
37257     ff 6/subop/push *(ecx+0x10)
37258     68/push 0x11/imm32/alloc-id:fake
37259     68/push 0/imm32/name
37260     68/push 0/imm32/name
37261     68/push 0x11/imm32/alloc-id:fake:payload
37262     89/<- %edx 4/r32/esp
37263 $test-add-reg-to-mem:initialize-var2-name:
37264     # var2->name = "var2"
37265     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
37266     (copy-array Heap "var2" %eax)
37267 $test-add-reg-to-mem:initialize-var2-register:
37268     # var2->register = "ecx"
37269     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
37270     (copy-array Heap "ecx" %eax)
37271 $test-add-reg-to-mem:initialize-inouts:
37272     # var inouts/esi: (payload stmt-var) = [var2]
37273     68/push 0/imm32/is-deref:false
37274     68/push 0/imm32/next
37275     68/push 0/imm32/next
37276     52/push-edx/var2
37277     68/push 0x11/imm32/alloc-id:fake
37278     68/push 0x11/imm32/alloc-id:fake:payload
37279     89/<- %esi 4/r32/esp
37280     # inouts = [var1, var2]
37281     68/push 0/imm32/is-deref:false
37282     56/push-esi/next
37283     68/push 0x11/imm32/alloc-id:fake
37284     51/push-ecx/var1
37285     68/push 0x11/imm32/alloc-id:fake
37286     68/push 0x11/imm32/alloc-id:fake:payload
37287     89/<- %esi 4/r32/esp
37288 $test-add-reg-to-mem:initialize-stmt:
37289     # var stmt/esi: (addr statement)
37290     68/push 0/imm32/next
37291     68/push 0/imm32/next
37292     68/push 0/imm32/outputs
37293     68/push 0/imm32/outputs
37294     56/push-esi/inouts
37295     68/push 0x11/imm32/alloc-id:fake
37296     68/push 0/imm32/operation
37297     68/push 0/imm32/operation
37298     68/push 1/imm32/tag:stmt1
37299     89/<- %esi 4/r32/esp
37300 $test-add-reg-to-mem:initialize-stmt-operation:
37301     # stmt->operation = "add-to"
37302     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37303     (copy-array Heap "add-to" %eax)
37304     # convert
37305     c7 0/subop/copy *Curr-block-depth 0/imm32
37306     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37307     (flush _test-output-buffered-file)
37308 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37314     # check output
37315     (check-next-stream-line-equal _test-output-stream "01/add-to *(ebp+0x00000008) 0x00000001/r32" "F - test-add-reg-to-mem")
37316     # . epilogue
37317     89/<- %esp 5/r32/ebp
37318     5d/pop-to-ebp
37319     c3/return
37320 
37321 test-add-mem-to-reg:
37322     #   var1/reg <- add var2
37323     # =>
37324     #   03/add *(ebp+__) var1
37325     #
37326     # . prologue
37327     55/push-ebp
37328     89/<- %ebp 4/r32/esp
37329     # setup
37330     (clear-stream _test-output-stream)
37331     (clear-stream $_test-output-buffered-file->buffer)
37332 $test-add-mem-to-reg:initialize-type:
37333     # var type/ecx: (payload type-tree) = int
37334     68/push 0/imm32/right:null
37335     68/push 0/imm32/right:null
37336     68/push 0/imm32/left:unused
37337     68/push 1/imm32/value:int
37338     68/push 1/imm32/is-atom?:true
37339     68/push 0x11/imm32/alloc-id:fake:payload
37340     89/<- %ecx 4/r32/esp
37341 $test-add-mem-to-reg:initialize-var:
37342     # var var1/ecx: (payload var)
37343     68/push 0/imm32/register
37344     68/push 0/imm32/register
37345     68/push 0/imm32/no-stack-offset
37346     68/push 1/imm32/block-depth
37347     51/push-ecx
37348     68/push 0x11/imm32/alloc-id:fake
37349     68/push 0/imm32/name
37350     68/push 0/imm32/name
37351     68/push 0x11/imm32/alloc-id:fake:payload
37352     89/<- %ecx 4/r32/esp
37353 $test-add-mem-to-reg:initialize-var-name:
37354     # var1->name = "foo"
37355     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37356     (copy-array Heap "var1" %eax)
37357 $test-add-mem-to-reg:initialize-var-register:
37358     # var1->register = "eax"
37359     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
37360     (copy-array Heap "eax" %eax)
37361 $test-add-mem-to-reg:initialize-var2:
37362     # var var2/edx: (payload var)
37363     68/push 0/imm32/register
37364     68/push 0/imm32/register
37365     68/push 8/imm32/stack-offset
37366     68/push 1/imm32/block-depth
37367     ff 6/subop/push *(ecx+0x10)
37368     68/push 0x11/imm32/alloc-id:fake
37369     68/push 0/imm32/name
37370     68/push 0/imm32/name
37371     68/push 0x11/imm32/alloc-id:fake:payload
37372     89/<- %edx 4/r32/esp
37373 $test-add-mem-to-reg:initialize-var2-name:
37374     # var2->name = "var2"
37375     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
37376     (copy-array Heap "var2" %eax)
37377 $test-add-mem-to-reg:initialize-inouts:
37378     # var inouts/esi: (payload stmt-var) = [var2]
37379     68/push 0/imm32/is-deref:false
37380     68/push 0/imm32/next
37381     68/push 0/imm32/next
37382     52/push-edx/var2
37383     68/push 0x11/imm32/alloc-id:fake
37384     68/push 0x11/imm32/alloc-id:fake:payload
37385     89/<- %esi 4/r32/esp
37386 $test-add-mem-to-reg:initialize-outputs:
37387     # var outputs/edi: (payload stmt-var) = [var1]
37388     68/push 0/imm32/is-deref:false
37389     68/push 0/imm32/next
37390     68/push 0/imm32/next
37391     51/push-ecx/var1
37392     68/push 0x11/imm32/alloc-id:fake
37393     68/push 0x11/imm32/alloc-id:fake:payload
37394     89/<- %edi 4/r32/esp
37395 $test-add-mem-to-reg:initialize-stmt:
37396     # var stmt/esi: (addr statement)
37397     68/push 0/imm32/next
37398     68/push 0/imm32/next
37399     57/push-edi/outputs
37400     68/push 0x11/imm32/alloc-id:fake
37401     56/push-esi/inouts
37402     68/push 0x11/imm32/alloc-id:fake
37403     68/push 0/imm32/operation
37404     68/push 0/imm32/operation
37405     68/push 1/imm32/tag:stmt1
37406     89/<- %esi 4/r32/esp
37407 $test-add-mem-to-reg:initialize-stmt-operation:
37408     # stmt->operation = "add"
37409     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37410     (copy-array Heap "add" %eax)
37411     # convert
37412     c7 0/subop/copy *Curr-block-depth 0/imm32
37413     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37414     (flush _test-output-buffered-file)
37415 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37421     # check output
37422     (check-next-stream-line-equal _test-output-stream "03/add *(ebp+0x00000008) 0x00000000/r32" "F - test-add-mem-to-reg")
37423     # . epilogue
37424     89/<- %esp 5/r32/ebp
37425     5d/pop-to-ebp
37426     c3/return
37427 
37428 test-add-literal-to-eax:
37429     #   var1/eax <- add 0x34
37430     # =>
37431     #   05/add-to-eax 0x34/imm32
37432     #
37433     # . prologue
37434     55/push-ebp
37435     89/<- %ebp 4/r32/esp
37436     # setup
37437     (clear-stream _test-output-stream)
37438     (clear-stream $_test-output-buffered-file->buffer)
37439 $test-add-literal-to-eax:initialize-var-type:
37440     # var type/ecx: (payload type-tree) = int
37441     68/push 0/imm32/right:null
37442     68/push 0/imm32/right:null
37443     68/push 0/imm32/left:unused
37444     68/push 1/imm32/value:int
37445     68/push 1/imm32/is-atom?:true
37446     68/push 0x11/imm32/alloc-id:fake:payload
37447     89/<- %ecx 4/r32/esp
37448 $test-add-literal-to-eax:initialize-var:
37449     # var v/ecx: (payload var)
37450     68/push 0/imm32/register
37451     68/push 0/imm32/register
37452     68/push 0/imm32/no-stack-offset
37453     68/push 1/imm32/block-depth
37454     51/push-ecx
37455     68/push 0x11/imm32/alloc-id:fake
37456     68/push 0/imm32/name
37457     68/push 0/imm32/name
37458     68/push 0x11/imm32/alloc-id:fake:payload
37459     89/<- %ecx 4/r32/esp
37460 $test-add-literal-to-eax:initialize-var-name:
37461     # v->name = "v"
37462     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37463     (copy-array Heap "v" %eax)
37464 $test-add-literal-to-eax:initialize-var-register:
37465     # v->register = "eax"
37466     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
37467     (copy-array Heap "eax" %eax)
37468 $test-add-literal-to-eax:initialize-literal-type:
37469     # var type/edx: (payload type-tree) = literal
37470     68/push 0/imm32/right:null
37471     68/push 0/imm32/right:null
37472     68/push 0/imm32/left:unused
37473     68/push 0/imm32/value:literal
37474     68/push 1/imm32/is-atom?:true
37475     68/push 0x11/imm32/alloc-id:fake:payload
37476     89/<- %edx 4/r32/esp
37477 $test-add-literal-to-eax:initialize-literal:
37478     # var l/edx: (payload var)
37479     68/push 0/imm32/register
37480     68/push 0/imm32/register
37481     68/push 0/imm32/no-stack-offset
37482     68/push 1/imm32/block-depth
37483     52/push-edx
37484     68/push 0x11/imm32/alloc-id:fake
37485     68/push 0/imm32/name
37486     68/push 0/imm32/name
37487     68/push 0x11/imm32/alloc-id:fake:payload
37488     89/<- %edx 4/r32/esp
37489 $test-add-literal-to-eax:initialize-literal-value:
37490     # l->name = "0x34"
37491     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
37492     (copy-array Heap "0x34" %eax)
37493 $test-add-literal-to-eax:initialize-inouts:
37494     # var inouts/esi: (payload stmt-var) = [l]
37495     68/push 0/imm32/is-deref:false
37496     68/push 0/imm32/next
37497     68/push 0/imm32/next
37498     52/push-edx/l
37499     68/push 0x11/imm32/alloc-id:fake
37500     68/push 0x11/imm32/alloc-id:fake:payload
37501     89/<- %esi 4/r32/esp
37502 $test-add-literal-to-eax:initialize-outputs:
37503     # var outputs/edi: (payload stmt-var) = [v]
37504     68/push 0/imm32/is-deref:false
37505     68/push 0/imm32/next
37506     68/push 0/imm32/next
37507     51/push-ecx/v
37508     68/push 0x11/imm32/alloc-id:fake
37509     68/push 0x11/imm32/alloc-id:fake:payload
37510     89/<- %edi 4/r32/esp
37511 $test-add-literal-to-eax:initialize-stmt:
37512     # var stmt/esi: (addr statement)
37513     68/push 0/imm32/next
37514     68/push 0/imm32/next
37515     57/push-edi/outputs
37516     68/push 0x11/imm32/alloc-id:fake
37517     56/push-esi/inouts
37518     68/push 0x11/imm32/alloc-id:fake
37519     68/push 0/imm32/operation
37520     68/push 0/imm32/operation
37521     68/push 1/imm32/tag:stmt1
37522     89/<- %esi 4/r32/esp
37523 $test-add-literal-to-eax:initialize-stmt-operation:
37524     # stmt->operation = "add"
37525     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37526     (copy-array Heap "add" %eax)
37527     # convert
37528     c7 0/subop/copy *Curr-block-depth 0/imm32
37529     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37530     (flush _test-output-buffered-file)
37531 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37537     # check output
37538     (check-next-stream-line-equal _test-output-stream "05/add-to-eax 0x34/imm32" "F - test-add-literal-to-eax")
37539     # . epilogue
37540     89/<- %esp 5/r32/ebp
37541     5d/pop-to-ebp
37542     c3/return
37543 
37544 test-add-literal-to-reg:
37545     #   var1/ecx <- add 0x34
37546     # =>
37547     #   81 0/subop/add %ecx 0x34/imm32
37548     #
37549     # . prologue
37550     55/push-ebp
37551     89/<- %ebp 4/r32/esp
37552     # setup
37553     (clear-stream _test-output-stream)
37554     (clear-stream $_test-output-buffered-file->buffer)
37555 $test-add-literal-to-reg:initialize-var-type:
37556     # var type/ecx: (payload type-tree) = int
37557     68/push 0/imm32/right:null
37558     68/push 0/imm32/right:null
37559     68/push 0/imm32/left:unused
37560     68/push 1/imm32/value:int
37561     68/push 1/imm32/is-atom?:true
37562     68/push 0x11/imm32/alloc-id:fake:payload
37563     89/<- %ecx 4/r32/esp
37564 $test-add-literal-to-reg:initialize-var:
37565     # var v/ecx: (payload var)
37566     68/push 0/imm32/register
37567     68/push 0/imm32/register
37568     68/push 0/imm32/no-stack-offset
37569     68/push 1/imm32/block-depth
37570     51/push-ecx
37571     68/push 0x11/imm32/alloc-id:fake
37572     68/push 0/imm32/name
37573     68/push 0/imm32/name
37574     68/push 0x11/imm32/alloc-id:fake:payload
37575     89/<- %ecx 4/r32/esp
37576 $test-add-literal-to-reg:initialize-var-name:
37577     # v->name = "v"
37578     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37579     (copy-array Heap "v" %eax)
37580 $test-add-literal-to-reg:initialize-var-register:
37581     # v->register = "ecx"
37582     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
37583     (copy-array Heap "ecx" %eax)
37584 $test-add-literal-to-reg:initialize-literal-type:
37585     # var type/edx: (payload type-tree) = literal
37586     68/push 0/imm32/right:null
37587     68/push 0/imm32/right:null
37588     68/push 0/imm32/left:unused
37589     68/push 0/imm32/value:literal
37590     68/push 1/imm32/is-atom?:true
37591     68/push 0x11/imm32/alloc-id:fake:payload
37592     89/<- %edx 4/r32/esp
37593 $test-add-literal-to-reg:initialize-literal:
37594     # var l/edx: (payload var)
37595     68/push 0/imm32/register
37596     68/push 0/imm32/register
37597     68/push 0/imm32/no-stack-offset
37598     68/push 1/imm32/block-depth
37599     52/push-edx
37600     68/push 0x11/imm32/alloc-id:fake
37601     68/push 0/imm32/name
37602     68/push 0/imm32/name
37603     68/push 0x11/imm32/alloc-id:fake:payload
37604     89/<- %edx 4/r32/esp
37605 $test-add-literal-to-reg:initialize-literal-value:
37606     # l->name = "0x34"
37607     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
37608     (copy-array Heap "0x34" %eax)
37609 $test-add-literal-to-reg:initialize-inouts:
37610     # var inouts/esi: (payload stmt-var) = [l]
37611     68/push 0/imm32/is-deref:false
37612     68/push 0/imm32/next
37613     68/push 0/imm32/next
37614     52/push-edx/l
37615     68/push 0x11/imm32/alloc-id:fake
37616     68/push 0x11/imm32/alloc-id:fake:payload
37617     89/<- %esi 4/r32/esp
37618 $test-add-literal-to-reg:initialize-outputs:
37619     # var outputs/edi: (payload stmt-var) = [v]
37620     68/push 0/imm32/is-deref:false
37621     68/push 0/imm32/next
37622     68/push 0/imm32/next
37623     51/push-ecx/v
37624     68/push 0x11/imm32/alloc-id:fake
37625     68/push 0x11/imm32/alloc-id:fake:payload
37626     89/<- %edi 4/r32/esp
37627 $test-add-literal-to-reg:initialize-stmt:
37628     # var stmt/esi: (addr statement)
37629     68/push 0/imm32/next
37630     68/push 0/imm32/next
37631     57/push-edi/outputs
37632     68/push 0x11/imm32/alloc-id:fake
37633     56/push-esi/inouts
37634     68/push 0x11/imm32/alloc-id:fake
37635     68/push 0/imm32/operation
37636     68/push 0/imm32/operation
37637     68/push 1/imm32/tag:stmt1
37638     89/<- %esi 4/r32/esp
37639 $test-add-literal-to-reg:initialize-stmt-operation:
37640     # stmt->operation = "add"
37641     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37642     (copy-array Heap "add" %eax)
37643     # convert
37644     c7 0/subop/copy *Curr-block-depth 0/imm32
37645     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37646     (flush _test-output-buffered-file)
37647 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37653     # check output
37654     (check-next-stream-line-equal _test-output-stream "81 0/subop/add %ecx 0x34/imm32" "F - test-add-literal-to-reg")
37655     # . epilogue
37656     89/<- %esp 5/r32/ebp
37657     5d/pop-to-ebp
37658     c3/return
37659 
37660 test-add-literal-to-mem:
37661     #   add-to var1, 0x34
37662     # =>
37663     #   81 0/subop/add %eax 0x34/imm32
37664     #
37665     # . prologue
37666     55/push-ebp
37667     89/<- %ebp 4/r32/esp
37668     # setup
37669     (clear-stream _test-output-stream)
37670     (clear-stream $_test-output-buffered-file->buffer)
37671 $test-add-literal-to-mem:initialize-type:
37672     # var type/ecx: (payload type-tree) = int
37673     68/push 0/imm32/right:null
37674     68/push 0/imm32/right:null
37675     68/push 0/imm32/left:unused
37676     68/push 1/imm32/value:int
37677     68/push 1/imm32/is-atom?:true
37678     68/push 0x11/imm32/alloc-id:fake:payload
37679     89/<- %ecx 4/r32/esp
37680 $test-add-literal-to-mem:initialize-var1:
37681     # var var1/ecx: (payload var)
37682     68/push 0/imm32/register
37683     68/push 0/imm32/register
37684     68/push 8/imm32/stack-offset
37685     68/push 1/imm32/block-depth
37686     51/push-ecx
37687     68/push 0x11/imm32/alloc-id:fake
37688     68/push 0/imm32/name
37689     68/push 0/imm32/name
37690     68/push 0x11/imm32/alloc-id:fake:payload
37691     89/<- %ecx 4/r32/esp
37692 $test-add-literal-to-mem:initialize-var1-name:
37693     # var1->name = "var1"
37694     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37695     (copy-array Heap "var1" %eax)
37696 $test-add-literal-to-mem:initialize-literal-type:
37697     # var type/edx: (payload type-tree) = literal
37698     68/push 0/imm32/right:null
37699     68/push 0/imm32/right:null
37700     68/push 0/imm32/left:unused
37701     68/push 0/imm32/value:literal
37702     68/push 1/imm32/is-atom?:true
37703     68/push 0x11/imm32/alloc-id:fake:payload
37704     89/<- %edx 4/r32/esp
37705 $test-add-literal-to-mem:initialize-literal:
37706     # var l/edx: (payload var)
37707     68/push 0/imm32/register
37708     68/push 0/imm32/register
37709     68/push 0/imm32/no-stack-offset
37710     68/push 1/imm32/block-depth
37711     52/push-edx
37712     68/push 0x11/imm32/alloc-id:fake
37713     68/push 0/imm32/name
37714     68/push 0/imm32/name
37715     68/push 0x11/imm32/alloc-id:fake:payload
37716     89/<- %edx 4/r32/esp
37717 $test-add-literal-to-mem:initialize-literal-value:
37718     # l->name = "0x34"
37719     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
37720     (copy-array Heap "0x34" %eax)
37721 $test-add-literal-to-mem:initialize-inouts:
37722     # var inouts/esi: (payload stmt-var) = [l]
37723     68/push 0/imm32/is-deref:false
37724     68/push 0/imm32/next
37725     68/push 0/imm32/next
37726     52/push-edx/l
37727     68/push 0x11/imm32/alloc-id:fake
37728     68/push 0x11/imm32/alloc-id:fake:payload
37729     89/<- %esi 4/r32/esp
37730     # var inouts = (handle stmt-var) = [var1, var2]
37731     68/push 0/imm32/is-deref:false
37732     56/push-esi/next
37733     68/push 0x11/imm32/alloc-id:fake
37734     51/push-ecx/var1
37735     68/push 0x11/imm32/alloc-id:fake
37736     68/push 0x11/imm32/alloc-id:fake:payload
37737     89/<- %esi 4/r32/esp
37738 $test-add-literal-to-mem:initialize-stmt:
37739     # var stmt/esi: (addr statement)
37740     68/push 0/imm32/next
37741     68/push 0/imm32/next
37742     68/push 0/imm32/outputs
37743     68/push 0/imm32/outputs
37744     56/push-esi/inouts
37745     68/push 0x11/imm32/alloc-id:fake
37746     68/push 0/imm32/operation
37747     68/push 0/imm32/operation
37748     68/push 1/imm32/tag:stmt1
37749     89/<- %esi 4/r32/esp
37750 $test-add-literal-to-mem:initialize-stmt-operation:
37751     # stmt->operation = "add-to"
37752     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37753     (copy-array Heap "add-to" %eax)
37754     # convert
37755     c7 0/subop/copy *Curr-block-depth 0/imm32
37756     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37757     (flush _test-output-buffered-file)
37758 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37764     # check output
37765     (check-next-stream-line-equal _test-output-stream "81 0/subop/add *(ebp+0x00000008) 0x34/imm32" "F - test-add-literal-to-mem")
37766     # . epilogue
37767     89/<- %esp 5/r32/ebp
37768     5d/pop-to-ebp
37769     c3/return
37770 
37771 test-shift-reg-by-literal:
37772     #   var1/ecx <- shift-left 2
37773     # =>
37774     #   c1/shift 4/subop/left %ecx 2/imm8
37775     #
37776     # . prologue
37777     55/push-ebp
37778     89/<- %ebp 4/r32/esp
37779     # setup
37780     (clear-stream _test-output-stream)
37781     (clear-stream $_test-output-buffered-file->buffer)
37782 $test-shift-reg-by-literal:initialize-var-type:
37783     # var type/ecx: (payload type-tree) = int
37784     68/push 0/imm32/right:null
37785     68/push 0/imm32/right:null
37786     68/push 0/imm32/left:unused
37787     68/push 1/imm32/value:int
37788     68/push 1/imm32/is-atom?:true
37789     68/push 0x11/imm32/alloc-id:fake:payload
37790     89/<- %ecx 4/r32/esp
37791 $test-shift-reg-by-literal:initialize-var:
37792     # var v/ecx: (payload var)
37793     68/push 0/imm32/register
37794     68/push 0/imm32/register
37795     68/push 0/imm32/no-stack-offset
37796     68/push 1/imm32/block-depth
37797     51/push-ecx
37798     68/push 0x11/imm32/alloc-id:fake
37799     68/push 0/imm32/name
37800     68/push 0/imm32/name
37801     68/push 0x11/imm32/alloc-id:fake:payload
37802     89/<- %ecx 4/r32/esp
37803 $test-shift-reg-by-literal:initialize-var-name:
37804     # v->name = "v"
37805     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37806     (copy-array Heap "v" %eax)
37807 $test-shift-reg-by-literal:initialize-var-register:
37808     # v->register = "ecx"
37809     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
37810     (copy-array Heap "ecx" %eax)
37811 $test-shift-reg-by-literal:initialize-literal-type:
37812     # var type/edx: (payload type-tree) = literal
37813     68/push 0/imm32/right:null
37814     68/push 0/imm32/right:null
37815     68/push 0/imm32/left:unused
37816     68/push 0/imm32/value:literal
37817     68/push 1/imm32/is-atom?:true
37818     68/push 0x11/imm32/alloc-id:fake:payload
37819     89/<- %edx 4/r32/esp
37820 $test-shift-reg-by-literal:initialize-literal:
37821     # var l/edx: (payload var)
37822     68/push 0/imm32/register
37823     68/push 0/imm32/register
37824     68/push 0/imm32/no-stack-offset
37825     68/push 1/imm32/block-depth
37826     52/push-edx
37827     68/push 0x11/imm32/alloc-id:fake
37828     68/push 0/imm32/name
37829     68/push 0/imm32/name
37830     68/push 0x11/imm32/alloc-id:fake:payload
37831     89/<- %edx 4/r32/esp
37832 $test-shift-reg-by-literal:initialize-literal-value:
37833     # l->name = "2"
37834     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
37835     (copy-array Heap "2" %eax)
37836 $test-shift-reg-by-literal:initialize-inouts:
37837     # var inouts/esi: (payload stmt-var) = [l]
37838     68/push 0/imm32/is-deref:false
37839     68/push 0/imm32/next
37840     68/push 0/imm32/next
37841     52/push-edx/l
37842     68/push 0x11/imm32/alloc-id:fake
37843     68/push 0x11/imm32/alloc-id:fake:payload
37844     89/<- %esi 4/r32/esp
37845 $test-shift-reg-by-literal:initialize-outputs:
37846     # var outputs/edi: (payload stmt-var) = [v]
37847     68/push 0/imm32/is-deref:false
37848     68/push 0/imm32/next
37849     68/push 0/imm32/next
37850     51/push-ecx/v
37851     68/push 0x11/imm32/alloc-id:fake
37852     68/push 0x11/imm32/alloc-id:fake:payload
37853     89/<- %edi 4/r32/esp
37854 $test-shift-reg-by-literal:initialize-stmt:
37855     # var stmt/esi: (addr statement)
37856     68/push 0/imm32/next
37857     68/push 0/imm32/next
37858     57/push-edi/outputs
37859     68/push 0x11/imm32/alloc-id:fake
37860     56/push-esi/inouts
37861     68/push 0x11/imm32/alloc-id:fake
37862     68/push 0/imm32/operation
37863     68/push 0/imm32/operation
37864     68/push 1/imm32/tag:stmt1
37865     89/<- %esi 4/r32/esp
37866 $test-shift-reg-by-literal:initialize-stmt-operation:
37867     # stmt->operation = "shift-left"
37868     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37869     (copy-array Heap "shift-left" %eax)
37870     # convert
37871     c7 0/subop/copy *Curr-block-depth 0/imm32
37872     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37873     (flush _test-output-buffered-file)
37874 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37880     # check output
37881     (check-next-stream-line-equal _test-output-stream "c1/shift 4/subop/left %ecx 2/imm8" "F - test-shift-reg-by-literal")
37882     # . epilogue
37883     89/<- %esp 5/r32/ebp
37884     5d/pop-to-ebp
37885     c3/return
37886 
37887 test-shift-mem-by-literal:
37888     #   shift-left var 3
37889     # =>
37890     #   c1/shift 4/subop/left *(ebp+8) 3/imm8
37891     #
37892     # . prologue
37893     55/push-ebp
37894     89/<- %ebp 4/r32/esp
37895     # setup
37896     (clear-stream _test-output-stream)
37897     (clear-stream $_test-output-buffered-file->buffer)
37898 $test-shift-mem-by-literal:initialize-type:
37899     # var type/ecx: (payload type-tree) = int
37900     68/push 0/imm32/right:null
37901     68/push 0/imm32/right:null
37902     68/push 0/imm32/left:unused
37903     68/push 1/imm32/value:int
37904     68/push 1/imm32/is-atom?:true
37905     68/push 0x11/imm32/alloc-id:fake:payload
37906     89/<- %ecx 4/r32/esp
37907 $test-shift-mem-by-literal:initialize-var1:
37908     # var var1/ecx: (payload var)
37909     68/push 0/imm32/register
37910     68/push 0/imm32/register
37911     68/push 8/imm32/stack-offset
37912     68/push 1/imm32/block-depth
37913     51/push-ecx
37914     68/push 0x11/imm32/alloc-id:fake
37915     68/push 0/imm32/name
37916     68/push 0/imm32/name
37917     68/push 0x11/imm32/alloc-id:fake:payload
37918     89/<- %ecx 4/r32/esp
37919 $test-shift-mem-by-literal:initialize-var1-name:
37920     # var1->name = "var1"
37921     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37922     (copy-array Heap "var1" %eax)
37923 $test-shift-mem-by-literal:initialize-literal-type:
37924     # var type/edx: (payload type-tree) = literal
37925     68/push 0/imm32/right:null
37926     68/push 0/imm32/right:null
37927     68/push 0/imm32/left:unused
37928     68/push 0/imm32/value:literal
37929     68/push 1/imm32/is-atom?:true
37930     68/push 0x11/imm32/alloc-id:fake:payload
37931     89/<- %edx 4/r32/esp
37932 $test-shift-mem-by-literal:initialize-literal:
37933     # var l/edx: (payload var)
37934     68/push 0/imm32/register
37935     68/push 0/imm32/register
37936     68/push 0/imm32/no-stack-offset
37937     68/push 1/imm32/block-depth
37938     52/push-edx
37939     68/push 0x11/imm32/alloc-id:fake
37940     68/push 0/imm32/name
37941     68/push 0/imm32/name
37942     68/push 0x11/imm32/alloc-id:fake:payload
37943     89/<- %edx 4/r32/esp
37944 $test-shift-mem-by-literal:initialize-literal-value:
37945     # l->name = "3"
37946     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
37947     (copy-array Heap "3" %eax)
37948 $test-shift-mem-by-literal:initialize-inouts:
37949     # var inouts/esi: (payload stmt-var) = [l]
37950     68/push 0/imm32/is-deref:false
37951     68/push 0/imm32/next
37952     68/push 0/imm32/next
37953     52/push-edx/l
37954     68/push 0x11/imm32/alloc-id:fake
37955     68/push 0x11/imm32/alloc-id:fake:payload
37956     89/<- %esi 4/r32/esp
37957     # var inouts = (handle stmt-var) = [var1, var2]
37958     68/push 0/imm32/is-deref:false
37959     56/push-esi/next
37960     68/push 0x11/imm32/alloc-id:fake
37961     51/push-ecx/var1
37962     68/push 0x11/imm32/alloc-id:fake
37963     68/push 0x11/imm32/alloc-id:fake:payload
37964     89/<- %esi 4/r32/esp
37965 $test-shift-mem-by-literal:initialize-stmt:
37966     # var stmt/esi: (addr statement)
37967     68/push 0/imm32/next
37968     68/push 0/imm32/next
37969     68/push 0/imm32/outputs
37970     68/push 0/imm32/outputs
37971     56/push-esi/inouts
37972     68/push 0x11/imm32/alloc-id:fake
37973     68/push 0/imm32/operation
37974     68/push 0/imm32/operation
37975     68/push 1/imm32/tag:stmt1
37976     89/<- %esi 4/r32/esp
37977 $test-shift-mem-by-literal:initialize-stmt-operation:
37978     # stmt->operation = "shift-left"
37979     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37980     (copy-array Heap "shift-left" %eax)
37981     # convert
37982     c7 0/subop/copy *Curr-block-depth 0/imm32
37983     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37984     (flush _test-output-buffered-file)
37985 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37991     # check output
37992     (check-next-stream-line-equal _test-output-stream "c1/shift 4/subop/left *(ebp+0x00000008) 3/imm8" "F - test-shift-mem-by-literal")
37993     # . epilogue
37994     89/<- %esp 5/r32/ebp
37995     5d/pop-to-ebp
37996     c3/return
37997 
37998 test-compare-reg-with-reg:
37999     #   compare var1/ecx, var2/eax
38000     # =>
38001     #   39/compare %ecx 0/r32/eax
38002     #
38003     # . prologue
38004     55/push-ebp
38005     89/<- %ebp 4/r32/esp
38006     # setup
38007     (clear-stream _test-output-stream)
38008     (clear-stream $_test-output-buffered-file->buffer)
38009 $test-compare-reg-with-reg:initialize-type:
38010     # var type/ecx: (payload type-tree) = int
38011     68/push 0/imm32/right:null
38012     68/push 0/imm32/right:null
38013     68/push 0/imm32/left:unused
38014     68/push 1/imm32/value:int
38015     68/push 1/imm32/is-atom?:true
38016     68/push 0x11/imm32/alloc-id:fake:payload
38017     89/<- %ecx 4/r32/esp
38018 $test-compare-reg-with-reg:initialize-var1:
38019     # var var1/ecx: (payload var)
38020     68/push 0/imm32/register
38021     68/push 0/imm32/register
38022     68/push 0/imm32/no-stack-offset
38023     68/push 1/imm32/block-depth
38024     51/push-ecx
38025     68/push 0x11/imm32/alloc-id:fake
38026     68/push 0/imm32/name
38027     68/push 0/imm32/name
38028     68/push 0x11/imm32/alloc-id:fake:payload
38029     89/<- %ecx 4/r32/esp
38030 $test-compare-reg-with-reg:initialize-var1-name:
38031     # var1->name = "var1"
38032     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
38033     (copy-array Heap "var1" %eax)
38034 $test-compare-reg-with-reg:initialize-var1-register:
38035     # var1->register = "ecx"
38036     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
38037     (copy-array Heap "ecx" %eax)
38038 $test-compare-reg-with-reg:initialize-var2:
38039     # var var2/edx: (payload var)
38040     68/push 0/imm32/register
38041     68/push 0/imm32/register
38042     68/push 0/imm32/no-stack-offset
38043     68/push 1/imm32/block-depth
38044     ff 6/subop/push *(ecx+0x10)
38045     68/push 0x11/imm32/alloc-id:fake
38046     68/push 0/imm32/name
38047     68/push 0/imm32/name
38048     68/push 0x11/imm32/alloc-id:fake:payload
38049     89/<- %edx 4/r32/esp
38050 $test-compare-reg-with-reg:initialize-var2-name:
38051     # var2->name = "var2"
38052     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
38053     (copy-array Heap "var2" %eax)
38054 $test-compare-reg-with-reg:initialize-var2-register:
38055     # var2->register = "eax"
38056     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
38057     (copy-array Heap "eax" %eax)
38058 $test-compare-reg-with-reg:initialize-inouts:
38059     # var inouts/esi: (payload stmt-var) = [var2]
38060     68/push 0/imm32/is-deref:false
38061     68/push 0/imm32/next
38062     68/push 0/imm32/next
38063     52/push-edx/var2
38064     68/push 0x11/imm32/alloc-id:fake
38065     68/push 0x11/imm32/alloc-id:fake:payload
38066     89/<- %esi 4/r32/esp
38067     # inouts = [var1, var2]
38068     68/push 0/imm32/is-deref:false
38069     56/push-esi/next
38070     68/push 0x11/imm32/alloc-id:fake
38071     51/push-ecx/var1
38072     68/push 0x11/imm32/alloc-id:fake
38073     68/push 0x11/imm32/alloc-id:fake:payload
38074     89/<- %esi 4/r32/esp
38075 $test-compare-reg-with-reg:initialize-stmt:
38076     # var stmt/esi: (addr statement)
38077     68/push 0/imm32/next
38078     68/push 0/imm32/next
38079     68/push 0/imm32/outputs
38080     68/push 0/imm32/outputs
38081     56/push-esi/inouts
38082     68/push 0x11/imm32/alloc-id:fake
38083     68/push 0/imm32/operation
38084     68/push 0/imm32/operation
38085     68/push 1/imm32/tag:stmt1
38086     89/<- %esi 4/r32/esp
38087 $test-compare-reg-with-reg:initialize-stmt-operation:
38088     # stmt->operation = "compare"
38089     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
38090     (copy-array Heap "compare" %eax)
38091     # convert
38092     c7 0/subop/copy *Curr-block-depth 0/imm32
38093     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
38094     (flush _test-output-buffered-file)
38095 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
38101     # check output
38102     (check-next-stream-line-equal _test-output-stream "39/compare-> %ecx 0x00000000/r32" "F - test-compare-reg-with-reg")
38103     # . epilogue
38104     89/<- %esp 5/r32/ebp
38105     5d/pop-to-ebp
38106     c3/return
38107 
38108 test-compare-mem-with-reg:
38109     #   compare var1, var2/eax
38110     # =>
38111     #   39/compare *(ebp+___) 0/r32/eax
38112     #
38113     # . prologue
38114     55/push-ebp
38115     89/<- %ebp 4/r32/esp
38116     # setup
38117     (clear-stream _test-output-stream)
38118     (clear-stream $_test-output-buffered-file->buffer)
38119 $test-compare-mem-with-reg:initialize-type:
38120     # var type/ecx: (payload type-tree) = int
38121     68/push 0/imm32/right:null
38122     68/push 0/imm32/right:null
38123     68/push 0/imm32/left:unused
38124     68/push 1/imm32/value:int
38125     68/push 1/imm32/is-atom?:true
38126     68/push 0x11/imm32/alloc-id:fake:payload
38127     89/<- %ecx 4/r32/esp
38128 $test-compare-mem-with-reg:initialize-var1:
38129     # var var1/ecx: (payload var)
38130     68/push 0/imm32/register
38131     68/push 0/imm32/register
38132     68/push 8/imm32/stack-offset
38133     68/push 1/imm32/block-depth
38134     51/push-ecx
38135     68/push 0x11/imm32/alloc-id:fake
38136     68/push 0/imm32/name
38137     68/push 0/imm32/name
38138     68/push 0x11/imm32/alloc-id:fake:payload
38139     89/<- %ecx 4/r32/esp
38140 $test-compare-mem-with-reg:initialize-var1-name:
38141     # var1->name = "var1"
38142     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
38143     (copy-array Heap "var1" %eax)
38144 $test-compare-mem-with-reg:initialize-var2:
38145     # var var2/edx: (payload var)
38146     68/push 0/imm32/register
38147     68/push 0/imm32/register
38148     68/push 0/imm32/no-stack-offset
38149     68/push 1/imm32/block-depth
38150     ff 6/subop/push *(ecx+0x10)
38151     68/push 0x11/imm32/alloc-id:fake
38152     68/push 0/imm32/name
38153     68/push 0/imm32/name
38154     68/push 0x11/imm32/alloc-id:fake:payload
38155     89/<- %edx 4/r32/esp
38156 $test-compare-mem-with-reg:initialize-var2-name:
38157     # var2->name = "var2"
38158     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
38159     (copy-array Heap "var2" %eax)
38160 $test-compare-mem-with-reg:initialize-var2-register:
38161     # var2->register = "eax"
38162     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
38163     (copy-array Heap "eax" %eax)
38164 $test-compare-mem-with-reg:initialize-inouts:
38165     # var inouts/esi: (payload stmt-var) = [var2]
38166     68/push 0/imm32/is-deref:false
38167     68/push 0/imm32/next
38168     68/push 0/imm32/next
38169     52/push-edx/var2
38170     68/push 0x11/imm32/alloc-id:fake
38171     68/push 0x11/imm32/alloc-id:fake:payload
38172     89/<- %esi 4/r32/esp
38173     # inouts = [var1, var2]
38174     68/push 0/imm32/is-deref:false
38175     56/push-esi/next
38176     68/push 0x11/imm32/alloc-id:fake
38177     51/push-ecx/var1
38178     68/push 0x11/imm32/alloc-id:fake
38179     68/push 0x11/imm32/alloc-id:fake:payload
38180     89/<- %esi 4/r32/esp
38181 $test-compare-mem-with-reg:initialize-stmt:
38182     # var stmt/esi: (addr statement)
38183     68/push 0/imm32/next
38184     68/push 0/imm32/next
38185     68/push 0/imm32/outputs
38186     68/push 0/imm32/outputs
38187     56/push-esi/inouts
38188     68/push 0x11/imm32/alloc-id:fake
38189     68/push 0/imm32/operation
38190     68/push 0/imm32/operation
38191     68/push 1/imm32/tag:stmt1
38192     89/<- %esi 4/r32/esp
38193 $test-compare-mem-with-reg:initialize-stmt-operation:
38194     # stmt->operation = "compare"
38195     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
38196     (copy-array Heap "compare" %eax)
38197     # convert
38198     c7 0/subop/copy *Curr-block-depth 0/imm32
38199     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
38200     (flush _test-output-buffered-file)
38201 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
38207     # check output
38208     (check-next-stream-line-equal _test-output-stream "39/compare-> *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-mem-with-reg")
38209     # . epilogue
38210     89/<- %esp 5/r32/ebp
38211     5d/pop-to-ebp
38212     c3/return
38213 
38214 test-compare-reg-with-mem:
38215     #   compare var1/eax, var2
38216     # =>
38217     #   3b/compare<- *(ebp+___) 0/r32/eax
38218     #
38219     # . prologue
38220     55/push-ebp
38221     89/<- %ebp 4/r32/esp
38222     # setup
38223     (clear-stream _test-output-stream)
38224     (clear-stream $_test-output-buffered-file->buffer)
38225 $test-compare-reg-with-mem:initialize-type:
38226     # var type/ecx: (payload type-tree) = int
38227     68/push 0/imm32/right:null
38228     68/push 0/imm32/right:null
38229     68/push 0/imm32/left:unused
38230     68/push 1/imm32/value:int
38231     68/push 1/imm32/is-atom?:true
38232     68/push 0x11/imm32/alloc-id:fake:payload
38233     89/<- %ecx 4/r32/esp
38234 $test-compare-reg-with-mem:initialize-var1:
38235     # var var1/ecx: (payload var)
38236     68/push 0/imm32/register
38237     68/push 0/imm32/register
38238     68/push 0/imm32/no-stack-offset
38239     68/push 1/imm32/block-depth
38240     51/push-ecx
38241     68/push 0x11/imm32/alloc-id:fake
38242     68/push 0/imm32/name
38243     68/push 0/imm32/name
38244     68/push 0x11/imm32/alloc-id:fake:payload
38245     89/<- %ecx 4/r32/esp
38246 $test-compare-reg-with-mem:initialize-var1-name:
38247     # var1->name = "var1"
38248     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
38249     (copy-array Heap "var1" %eax)
38250 $test-compare-reg-with-mem:initialize-var1-register:
38251     # var1->register = "eax"
38252     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
38253     (copy-array Heap "eax" %eax)
38254 $test-compare-reg-with-mem:initialize-var2:
38255     # var var2/edx: (payload var)
38256     68/push 0/imm32/register
38257     68/push 0/imm32/register
38258     68/push 8/imm32/stack-offset
38259     68/push 1/imm32/block-depth
38260     ff 6/subop/push *(ecx+0x10)
38261     68/push 0x11/imm32/alloc-id:fake
38262     68/push 0/imm32/name
38263     68/push 0/imm32/name
38264     68/push 0x11/imm32/alloc-id:fake:payload
38265     89/<- %edx 4/r32/esp
38266 $test-compare-reg-with-mem:initialize-var2-name:
38267     # var2->name = "var2"
38268     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
38269     (copy-array Heap "var2" %eax)
38270 $test-compare-reg-with-mem:initialize-inouts:
38271     # var inouts/esi: (payload stmt-var) = [var2]
38272     68/push 0/imm32/is-deref:false
38273     68/push 0/imm32/next
38274     68/push 0/imm32/next
38275     52/push-edx/var2
38276     68/push 0x11/imm32/alloc-id:fake
38277     68/push 0x11/imm32/alloc-id:fake:payload
38278     89/<- %esi 4/r32/esp
38279     # inouts = [var1, var2]
38280     68/push 0/imm32/is-deref:false
38281     56/push-esi/next
38282     68/push 0x11/imm32/alloc-id:fake
38283     51/push-ecx/var1
38284     68/push 0x11/imm32/alloc-id:fake
38285     68/push 0x11/imm32/alloc-id:fake:payload
38286     89/<- %esi 4/r32/esp
38287 $test-compare-reg-with-mem:initialize-stmt:
38288     # var stmt/esi: (addr statement)
38289     68/push 0/imm32/next
38290     68/push 0/imm32/next
38291     68/push 0/imm32/outputs
38292     68/push 0/imm32/outputs
38293     56/push-esi/inouts
38294     68/push 0x11/imm32/alloc-id:fake
38295     68/push 0/imm32/operation
38296     68/push 0/imm32/operation
38297     68/push 1/imm32/tag:stmt1
38298     89/<- %esi 4/r32/esp
38299 $test-compare-reg-with-mem:initialize-stmt-operation:
38300     # stmt->operation = "compare"
38301     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
38302     (copy-array Heap "compare" %eax)
38303     # convert
38304     c7 0/subop/copy *Curr-block-depth 0/imm32
38305     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
38306     (flush _test-output-buffered-file)
38307 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
38313     # check output
38314     (check-next-stream-line-equal _test-output-stream "3b/compare<- *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-reg-with-mem")
38315     # . epilogue
38316     89/<- %esp 5/r32/ebp
38317     5d/pop-to-ebp
38318     c3/return
38319 
38320 test-compare-mem-with-literal:
38321     #   compare var1, 0x34
38322     # =>
38323     #   81 7/subop/compare *(ebp+___) 0x34/imm32
38324     #
38325     # . prologue
38326     55/push-ebp
38327     89/<- %ebp 4/r32/esp
38328     # setup
38329     (clear-stream _test-output-stream)
38330     (clear-stream $_test-output-buffered-file->buffer)
38331 $test-compare-mem-with-literal:initialize-type:
38332     # var type/ecx: (payload type-tree) = int
38333     68/push 0/imm32/right:null
38334     68/push 0/imm32/right:null
38335     68/push 0/imm32/left:unused
38336     68/push 1/imm32/value:int
38337     68/push 1/imm32/is-atom?:true
38338     68/push 0x11/imm32/alloc-id:fake:payload
38339     89/<- %ecx 4/r32/esp
38340 $test-compare-mem-with-literal:initialize-var1:
38341     # var var1/ecx: (payload var)
38342     68/push 0/imm32/register
38343     68/push 0/imm32/register
38344     68/push 8/imm32/stack-offset
38345     68/push 1/imm32/block-depth
38346     51/push-ecx
38347     68/push 0x11/imm32/alloc-id:fake
38348     68/push 0/imm32/name
38349     68/push 0/imm32/name
38350     68/push 0x11/imm32/alloc-id:fake:payload
38351     89/<- %ecx 4/r32/esp
38352 $test-compare-mem-with-literal:initialize-var1-name:
38353     # var1->name = "var1"
38354     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
38355     (copy-array Heap "var1" %eax)
38356 $test-compare-mem-with-literal:initialize-literal-type:
38357     # var type/edx: (payload type-tree) = literal
38358     68/push 0/imm32/right:null
38359     68/push 0/imm32/right:null
38360     68/push 0/imm32/left:unused
38361     68/push 0/imm32/value:literal
38362     68/push 1/imm32/is-atom?:true
38363     68/push 0x11/imm32/alloc-id:fake:payload
38364     89/<- %edx 4/r32/esp
38365 $test-compare-mem-with-literal:initialize-literal:
38366     # var l/edx: (payload var)
38367     68/push 0/imm32/register
38368     68/push 0/imm32/register
38369     68/push 0/imm32/no-stack-offset
38370     68/push 1/imm32/block-depth
38371     52/push-edx
38372     68/push 0x11/imm32/alloc-id:fake
38373     68/push 0/imm32/name
38374     68/push 0/imm32/name
38375     68/push 0x11/imm32/alloc-id:fake:payload
38376     89/<- %edx 4/r32/esp
38377 $test-compare-mem-with-literal:initialize-literal-value:
38378     # l->name = "0x34"
38379     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
38380     (copy-array Heap "0x34" %eax)
38381 $test-compare-mem-with-literal:initialize-inouts:
38382     # var inouts/esi: (payload stmt-var) = [l]
38383     68/push 0/imm32/is-deref:false
38384     68/push 0/imm32/next
38385     68/push 0/imm32/next
38386     52/push-edx/l
38387     68/push 0x11/imm32/alloc-id:fake
38388     68/push 0x11/imm32/alloc-id:fake:payload
38389     89/<- %esi 4/r32/esp
38390     # var inouts = (handle stmt-var) = [var1, var2]
38391     68/push 0/imm32/is-deref:false
38392     56/push-esi/next
38393     68/push 0x11/imm32/alloc-id:fake
38394     51/push-ecx/var1
38395     68/push 0x11/imm32/alloc-id:fake
38396     68/push 0x11/imm32/alloc-id:fake:payload
38397     89/<- %esi 4/r32/esp
38398 $test-compare-mem-with-literal:initialize-stmt:
38399     # var stmt/esi: (addr statement)
38400     68/push 0/imm32/next
38401     68/push 0/imm32/next
38402     68/push 0/imm32/outputs
38403     68/push 0/imm32/outputs
38404     56/push-esi/inouts
38405     68/push 0x11/imm32/alloc-id:fake
38406     68/push 0/imm32/operation
38407     68/push 0/imm32/operation
38408     68/push 1/imm32/tag:stmt1
38409     89/<- %esi 4/r32/esp
38410 $test-compare-mem-with-literal:initialize-stmt-operation:
38411     # stmt->operation = "compare"
38412     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
38413     (copy-array Heap "compare" %eax)
38414     # convert
38415     c7 0/subop/copy *Curr-block-depth 0/imm32
38416     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
38417     (flush _test-output-buffered-file)
38418 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
38424     # check output
38425     (check-next-stream-line-equal _test-output-stream "81 7/subop/compare *(ebp+0x00000008) 0x34/imm32" "F - test-compare-mem-with-literal")
38426     # . epilogue
38427     89/<- %esp 5/r32/ebp
38428     5d/pop-to-ebp
38429     c3/return
38430 
38431 test-compare-eax-with-literal:
38432     #   compare var1/eax 0x34
38433     # =>
38434     #   3d/compare-eax-with 0x34/imm32
38435     #
38436     # . prologue
38437     55/push-ebp
38438     89/<- %ebp 4/r32/esp
38439     # setup
38440     (clear-stream _test-output-stream)
38441     (clear-stream $_test-output-buffered-file->buffer)
38442 $test-compare-eax-with-literal:initialize-type:
38443     # var type/ecx: (payload type-tree) = int
38444     68/push 0/imm32/right:null
38445     68/push 0/imm32/right:null
38446     68/push 0/imm32/left:unused
38447     68/push 1/imm32/value:int
38448     68/push 1/imm32/is-atom?:true
38449     68/push 0x11/imm32/alloc-id:fake:payload
38450     89/<- %ecx 4/r32/esp
38451 $test-compare-eax-with-literal:initialize-var1:
38452     # var var1/ecx: (payload var)
38453     68/push 0/imm32/register
38454     68/push 0/imm32/register
38455     68/push 0/imm32/no-stack-offset
38456     68/push 1/imm32/block-depth
38457     51/push-ecx
38458     68/push 0x11/imm32/alloc-id:fake
38459     68/push 0/imm32/name
38460     68/push 0/imm32/name
38461     68/push 0x11/imm32/alloc-id:fake:payload
38462     89/<- %ecx 4/r32/esp
38463 $test-compare-eax-with-literal:initialize-var1-name:
38464     # var1->name = "var1"
38465     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
38466     (copy-array Heap "var1" %eax)
38467 $test-compare-eax-with-literal:initialize-var1-register:
38468     # v->register = "eax"
38469     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
38470     (copy-array Heap "eax" %eax)
38471 $test-compare-eax-with-literal:initialize-literal-type:
38472     # var type/edx: (payload type-tree) = literal
38473     68/push 0/imm32/right:null
38474     68/push 0/imm32/right:null
38475     68/push 0/imm32/left:unused
38476     68/push 0/imm32/value:literal
38477     68/push 1/imm32/is-atom?:true
38478     68/push 0x11/imm32/alloc-id:fake:payload
38479     89/<- %edx 4/r32/esp
38480 $test-compare-eax-with-literal:initialize-literal:
38481     # var l/edx: (payload var)
38482     68/push 0/imm32/register
38483     68/push 0/imm32/register
38484     68/push 0/imm32/no-stack-offset
38485     68/push 1/imm32/block-depth
38486     52/push-edx
38487     68/push 0x11/imm32/alloc-id:fake
38488     68/push 0/imm32/name
38489     68/push 0/imm32/name
38490     68/push 0x11/imm32/alloc-id:fake:payload
38491     89/<- %edx 4/r32/esp
38492 $test-compare-eax-with-literal:initialize-literal-value:
38493     # l->name = "0x34"
38494     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
38495     (copy-array Heap "0x34" %eax)
38496 $test-compare-eax-with-literal:initialize-inouts:
38497     # var inouts/esi: (payload stmt-var) = [l]
38498     68/push 0/imm32/is-deref:false
38499     68/push 0/imm32/next
38500     68/push 0/imm32/next
38501     52/push-edx/l
38502     68/push 0x11/imm32/alloc-id:fake
38503     68/push 0x11/imm32/alloc-id:fake:payload
38504     89/<- %esi 4/r32/esp
38505     # var inouts = (handle stmt-var) = [var1, var2]
38506     68/push 0/imm32/is-deref:false
38507     56/push-esi/next
38508     68/push 0x11/imm32/alloc-id:fake
38509     51/push-ecx/var1
38510     68/push 0x11/imm32/alloc-id:fake
38511     68/push 0x11/imm32/alloc-id:fake:payload
38512     89/<- %esi 4/r32/esp
38513 $test-compare-eax-with-literal:initialize-stmt:
38514     # var stmt/esi: (addr statement)
38515     68/push 0/imm32/next
38516     68/push 0/imm32/next
38517     68/push 0/imm32/outputs
38518     68/push 0/imm32/outputs
38519     56/push-esi/inouts
38520     68/push 0x11/imm32/alloc-id:fake
38521     68/push 0/imm32/operation
38522     68/push 0/imm32/operation
38523     68/push 1/imm32/tag:stmt1
38524     89/<- %esi 4/r32/esp
38525 $test-compare-eax-with-literal:initialize-stmt-operation:
38526     # stmt->operation = "compare"
38527     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
38528     (copy-array Heap "compare" %eax)
38529     # convert
38530     c7 0/subop/copy *Curr-block-depth 0/imm32
38531     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
38532     (flush _test-output-buffered-file)
38533 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
38539     # check output
38540     (check-next-stream-line-equal _test-output-stream "3d/compare-eax-with 0x34/imm32" "F - test-compare-eax-with-literal")
38541     # . epilogue
38542     89/<- %esp 5/r32/ebp
38543     5d/pop-to-ebp
38544     c3/return
38545 
38546 test-compare-reg-with-literal:
38547     #   compare var1/ecx 0x34
38548     # =>
38549     #   81 7/subop/compare %ecx 0x34/imm32
38550     #
38551     # . prologue
38552     55/push-ebp
38553     89/<- %ebp 4/r32/esp
38554     # setup
38555     (clear-stream _test-output-stream)
38556     (clear-stream $_test-output-buffered-file->buffer)
38557 $test-compare-reg-with-literal:initialize-type:
38558     # var type/ecx: (payload type-tree) = int
38559     68/push 0/imm32/right:null
38560     68/push 0/imm32/right:null
38561     68/push 0/imm32/left:unused
38562     68/push 1/imm32/value:int
38563     68/push 1/imm32/is-atom?:true
38564     68/push 0x11/imm32/alloc-id:fake:payload
38565     89/<- %ecx 4/r32/esp
38566 $test-compare-reg-with-literal:initialize-var1:
38567     # var var1/ecx: (payload var)
38568     68/push 0/imm32/register
38569     68/push 0/imm32/register
38570     68/push 0/imm32/no-stack-offset
38571     68/push 1/imm32/block-depth
38572     51/push-ecx
38573     68/push 0x11/imm32/alloc-id:fake
38574     68/push 0/imm32/name
38575     68/push 0/imm32/name
38576     68/push 0x11/imm32/alloc-id:fake:payload
38577     89/<- %ecx 4/r32/esp
38578 $test-compare-reg-with-literal:initialize-var1-name:
38579     # var1->name = "var1"
38580     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
38581     (copy-array Heap "var1" %eax)
38582 $test-compare-reg-with-literal:initialize-var1-register:
38583     # v->register = "ecx"
38584     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
38585     (copy-array Heap "ecx" %eax)
38586 $test-compare-reg-with-literal:initialize-literal-type:
38587     # var type/edx: (payload type-tree) = literal
38588     68/push 0/imm32/right:null
38589     68/push 0/imm32/right:null
38590     68/push 0/imm32/left:unused
38591     68/push 0/imm32/value:literal
38592     68/push 1/imm32/is-atom?:true
38593     68/push 0x11/imm32/alloc-id:fake:payload
38594     89/<- %edx 4/r32/esp
38595 $test-compare-reg-with-literal:initialize-literal:
38596     # var l/edx: (payload var)
38597     68/push 0/imm32/register
38598     68/push 0/imm32/register
38599     68/push 0/imm32/no-stack-offset
38600     68/push 1/imm32/block-depth
38601     52/push-edx
38602     68/push 0x11/imm32/alloc-id:fake
38603     68/push 0/imm32/name
38604     68/push 0/imm32/name
38605     68/push 0x11/imm32/alloc-id:fake:payload
38606     89/<- %edx 4/r32/esp
38607 $test-compare-reg-with-literal:initialize-literal-value:
38608     # l->name = "0x34"
38609     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
38610     (copy-array Heap "0x34" %eax)
38611 $test-compare-reg-with-literal:initialize-inouts:
38612     # var inouts/esi: (payload stmt-var) = [l]
38613     68/push 0/imm32/is-deref:false
38614     68/push 0/imm32/next
38615     68/push 0/imm32/next
38616     52/push-edx/l
38617     68/push 0x11/imm32/alloc-id:fake
38618     68/push 0x11/imm32/alloc-id:fake:payload
38619     89/<- %esi 4/r32/esp
38620     # var inouts = (handle stmt-var) = [var1, var2]
38621     68/push 0/imm32/is-deref:false
38622     56/push-esi/next
38623     68/push 0x11/imm32/alloc-id:fake
38624     51/push-ecx/var1
38625     68/push 0x11/imm32/alloc-id:fake
38626     68/push 0x11/imm32/alloc-id:fake:payload
38627     89/<- %esi 4/r32/esp
38628 $test-compare-reg-with-literal:initialize-stmt:
38629     # var stmt/esi: (addr statement)
38630     68/push 0/imm32/next
38631     68/push 0/imm32/next
38632     68/push 0/imm32/outputs
38633     68/push 0/imm32/outputs
38634     56/push-esi/inouts
38635     68/push 0x11/imm32/alloc-id:fake
38636     68/push 0/imm32/operation
38637     68/push 0/imm32/operation
38638     68/push 1/imm32/tag:stmt1
38639     89/<- %esi 4/r32/esp
38640 $test-compare-reg-with-literal:initialize-stmt-operation:
38641     # stmt->operation = "compare"
38642     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
38643     (copy-array Heap "compare" %eax)
38644     # convert
38645     c7 0/subop/copy *Curr-block-depth 0/imm32
38646     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
38647     (flush _test-output-buffered-file)
38648 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
38654     # check output
38655     (check-next-stream-line-equal _test-output-stream "81 7/subop/compare %ecx 0x34/imm32" "F - test-compare-reg-with-literal")
38656     # . epilogue
38657     89/<- %esp 5/r32/ebp
38658     5d/pop-to-ebp
38659     c3/return
38660 
38661 test-emit-subx-stmt-function-call:
38662     # Call a function on a variable on the stack.
38663     #   f foo
38664     # =>
38665     #   (f *(ebp-8))
38666     # (Changing the function name supports overloading in general, but here it
38667     # just serves to help disambiguate things.)
38668     #
38669     # There's a variable on the var stack as follows:
38670     #   name: 'foo'
38671     #   type: int
38672     #   stack-offset: -8
38673     #
38674     # There's nothing in primitives.
38675     #
38676     # We don't perform any checking here on the type of 'f'.
38677     #
38678     # . prologue
38679     55/push-ebp
38680     89/<- %ebp 4/r32/esp
38681     # setup
38682     (clear-stream _test-output-stream)
38683     (clear-stream $_test-output-buffered-file->buffer)
38684 $test-emit-subx-function-call:initialize-type:
38685     # var type/ecx: (payload type-tree) = int
38686     68/push 0/imm32/right:null
38687     68/push 0/imm32/right:null
38688     68/push 0/imm32/left:unused
38689     68/push 1/imm32/value:int
38690     68/push 1/imm32/is-atom?:true
38691     68/push 0x11/imm32/alloc-id:fake:payload
38692     89/<- %ecx 4/r32/esp
38693 $test-emit-subx-function-call:initialize-var:
38694     # var var-foo/ecx: (payload var) = var(type)
38695     68/push 0/imm32/no-register
38696     68/push 0/imm32/no-register
38697     68/push -8/imm32/stack-offset
38698     68/push 1/imm32/block-depth
38699     51/push-ecx/type
38700     68/push 0x11/imm32/alloc-id:fake
38701     68/push 0/imm32/name
38702     68/push 0/imm32/name
38703     68/push 0x11/imm32/alloc-id:fake:payload
38704     89/<- %ecx 4/r32/esp
38705 $test-emit-subx-function-call:initialize-var-name:
38706     # var-foo->name = "foo"
38707     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
38708     (copy-array Heap "foo" %eax)
38709 $test-emit-subx-function-call:initialize-stmt-var:
38710     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
38711     68/push 0/imm32/is-deref:false
38712     68/push 0/imm32/next
38713     68/push 0/imm32/next
38714     51/push-ecx/var-foo
38715     68/push 0x11/imm32/alloc-id:fake
38716     68/push 0x11/imm32/alloc-id:fake:payload
38717     89/<- %ebx 4/r32/esp
38718 $test-emit-subx-function-call:initialize-stmt:
38719     # var stmt/esi: (addr statement)
38720     68/push 0/imm32/no-outputs
38721     68/push 0/imm32/no-outputs
38722     53/push-ebx/inouts
38723     68/push 0x11/imm32/alloc-id:fake
38724     68/push 0/imm32/operation
38725     68/push 0/imm32/operation
38726     68/push 1/imm32/tag
38727     89/<- %esi 4/r32/esp
38728 $test-emit-subx-function-call:initialize-stmt-operation:
38729     # stmt->operation = "f"
38730     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
38731     (copy-array Heap "f" %eax)
38732     # convert
38733     c7 0/subop/copy *Curr-block-depth 0/imm32
38734     (emit-subx-stmt _test-output-buffered-file %esi 0 0 Stderr 0)
38735     (flush _test-output-buffered-file)
38736 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
38742     # check output
38743     (check-next-stream-line-equal _test-output-stream "(f *(ebp+0xfffffff8))" "F - test-emit-subx-stmt-function-call")
38744     # . epilogue
38745     89/<- %esp 5/r32/ebp
38746     5d/pop-to-ebp
38747     c3/return
38748 
38749 test-emit-subx-stmt-function-call-with-literal-arg:
38750     # Call a function on a literal.
38751     #   f 0x34
38752     # =>
38753     #   (f2 0x34)
38754     #
38755     # . prologue
38756     55/push-ebp
38757     89/<- %ebp 4/r32/esp
38758     # setup
38759     (clear-stream _test-output-stream)
38760     (clear-stream $_test-output-buffered-file->buffer)
38761 $test-emit-subx-function-call-with-literal-arg:initialize-type:
38762     # var type/ecx: (payload type-tree) = int
38763     68/push 0/imm32/right:null
38764     68/push 0/imm32/right:null
38765     68/push 0/imm32/left:unused
38766     68/push 0/imm32/value:literal
38767     68/push 1/imm32/is-atom?:true
38768     68/push 0x11/imm32/alloc-id:fake:payload
38769     89/<- %ecx 4/r32/esp
38770 $test-emit-subx-function-call-with-literal-arg:initialize-var:
38771     # var var-foo/ecx: (payload var) = var(lit)
38772     68/push 0/imm32/no-register
38773     68/push 0/imm32/no-register
38774     68/push 0/imm32/no-stack-offset
38775     68/push 1/imm32/block-depth
38776     51/push-ecx/type
38777     68/push 0x11/imm32/alloc-id:fake
38778     68/push 0/imm32/name
38779     68/push 0/imm32/name
38780     68/push 0x11/imm32/alloc-id:fake:payload
38781     89/<- %ecx 4/r32/esp
38782 $test-emit-subx-function-call-with-literal-arg:initialize-var-name:
38783     # var-foo->name = "0x34"
38784     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
38785     (copy-array Heap "0x34" %eax)
38786 $test-emit-subx-function-call-with-literal-arg:initialize-stmt-var:
38787     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
38788     68/push 0/imm32/is-deref:false
38789     68/push 0/imm32/next
38790     68/push 0/imm32/next
38791     51/push-ecx/var-foo
38792     68/push 0x11/imm32/alloc-id:fake
38793     68/push 0x11/imm32/alloc-id:fake:payload
38794     89/<- %ebx 4/r32/esp
38795 $test-emit-subx-function-call-with-literal-arg:initialize-stmt:
38796     # var stmt/esi: (addr statement)
38797     68/push 0/imm32/no-outputs
38798     68/push 0/imm32/no-outputs
38799     53/push-ebx/inouts
38800     68/push 0x11/imm32/alloc-id:fake
38801     68/push 0/imm32/operation
38802     68/push 0/imm32/operation
38803     68/push 1/imm32/tag
38804     89/<- %esi 4/r32/esp
38805 $test-emit-subx-function-call-with-literal-arg:initialize-stmt-operation:
38806     # stmt->operation = "f"
38807     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
38808     (copy-array Heap "f" %eax)
38809     # convert
38810     c7 0/subop/copy *Curr-block-depth 0/imm32
38811     (emit-subx-stmt _test-output-buffered-file %esi 0 %ebx 0 Stderr 0)
38812     (flush _test-output-buffered-file)
38813 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
38819     # check output
38820     (check-next-stream-line-equal _test-output-stream "(f 0x34)" "F - test-emit-subx-stmt-function-call-with-literal-arg")
38821     # . epilogue
38822     89/<- %esp 5/r32/ebp
38823     5d/pop-to-ebp
38824     c3/return
38825 
38826 emit-indent:  # out: (addr buffered-file), n: int
38827     # . prologue
38828     55/push-ebp
38829     89/<- %ebp 4/r32/esp
38830     # . save registers
38831     50/push-eax
38832     # var i/eax: int = n
38833     8b/-> *(ebp+0xc) 0/r32/eax
38834     {
38835       # if (i <= 0) break
38836       3d/compare-eax-with 0/imm32
38837       7e/jump-if-<= break/disp8
38838       (write-buffered *(ebp+8) "  ")
38839       48/decrement-eax
38840       eb/jump loop/disp8
38841     }
38842 $emit-indent:end:
38843     # . restore registers
38844     58/pop-to-eax
38845     # . epilogue
38846     89/<- %esp 5/r32/ebp
38847     5d/pop-to-ebp
38848     c3/return
38849 
38850 emit-subx-prologue:  # out: (addr buffered-file)
38851     # . prologue
38852     55/push-ebp
38853     89/<- %ebp 4/r32/esp
38854     #
38855     (write-buffered *(ebp+8) "  # . prologue\n")
38856     (write-buffered *(ebp+8) "  55/push-ebp\n")
38857     (write-buffered *(ebp+8) "  89/<- %ebp 4/r32/esp\n")
38858 $emit-subx-prologue:end:
38859     # . epilogue
38860     89/<- %esp 5/r32/ebp
38861     5d/pop-to-ebp
38862     c3/return
38863 
38864 emit-subx-epilogue:  # out: (addr buffered-file)
38865     # . prologue
38866     55/push-ebp
38867     89/<- %ebp 4/r32/esp
38868     #
38869     (write-buffered *(ebp+8) "  # . epilogue\n")
38870     (write-buffered *(ebp+8) "  89/<- %esp 5/r32/ebp\n")
38871     (write-buffered *(ebp+8) "  5d/pop-to-ebp\n")
38872     (write-buffered *(ebp+8) "  c3/return\n")
38873 $emit-subx-epilogue:end:
38874     # . epilogue
38875     89/<- %esp 5/r32/ebp
38876     5d/pop-to-ebp
38877     c3/return