https://github.com/akkartik/mu/blob/master/apps/mu.subx
    1 # The Mu computer's level-2 language, also called Mu.
    2 # http://akkartik.name/post/mu-2019-2
    3 #
    4 # To run:
    5 #   $ ./translate_subx init.linux [0-9]*.subx apps/mu.subx
    6 #   $ ./a.elf < prog.mu > prog.elf
    7 
    8 # == Goals
    9 # 1. Be memory safe. It should be impossible to corrupt the heap, or to create
   10 # a bad pointer. (Requires strong type safety.)
   11 # 2. Do as little as possible to achieve goal 1. The translator should be
   12 # implementable in machine code.
   13 #   - minimize impedance mismatch between source language and SubX target
   14 #     (e.g. programmer manages registers manually)
   15 #   - checks over syntax
   16 #     (e.g. programmer's register allocation is checked)
   17 #   - runtime checks to avoid complex static analysis
   18 #     (e.g. array indexing always checks bounds)
   19 
   20 # == Language description
   21 # A program is a sequence of function and type definitions.
   22 #
   23 # Function example:
   24 #   fn foo n: int -> _/eax: int {
   25 #     ...
   26 #   }
   27 #
   28 # Functions consist of a name, optional inputs, optional outputs and a block.
   29 #
   30 # Function inputs and outputs are variables. All variables have a type and
   31 # storage specifier. They can be placed either in memory (on the stack) or in
   32 # one of 6 named registers.
   33 #   eax ecx edx ebx esi edi
   34 # Variables in registers must be primitive 32-bit types.
   35 # Variables not explicitly placed in a register are on the stack.
   36 #
   37 # Function inputs are always passed in memory (on the stack), while outputs
   38 # are always returned in registers. Outputs can't be named; they use the
   39 # dummy value '_'.
   40 #
   41 # Blocks mostly consist of statements.
   42 #
   43 # Statements mostly consist of a name, optional inputs and optional outputs.
   44 #
   45 # Statement inputs are variables or literals. Variables need to specify type
   46 # (and storage) the first time they're mentioned but not later.
   47 #
   48 # Statement outputs, like function outputs, must be variables in registers.
   49 #
   50 # Statement names must be either primitives or user-defined functions.
   51 #
   52 # Primitives can write to any register.
   53 # User-defined functions only write to hard-coded registers. Outputs of each
   54 # call must have the same registers as in the function definition.
   55 #
   56 # There are some other statement types:
   57 #   - blocks. Multiple statements surrounded by '{...}' and optionally
   58 #     prefixed with a label name and ':'
   59 #       - {
   60 #           ...
   61 #         }
   62 #       - foo: {
   63 #           ...
   64 #         }
   65 #
   66 #   - variable definitions on the stack. E.g.:
   67 #       - var foo: int
   68 #       - var bar: (array int 3)
   69 #     There's no initializer; variables are automatically initialized.
   70 #     The type of a local variable is either word-length (4 bytes) or starts with 'ref'.
   71 #
   72 #   - variables definitions in a register. E.g.:
   73 #       - var foo/eax: int <- add bar 1
   74 #     The initializer is mandatory and must be a valid instruction that writes
   75 #     a single output to the right register. In practice registers will
   76 #     usually be either initialized by primitives or copied from eax.
   77 #       - var eax: int <- foo bar quux
   78 #         var floo/ecx: int <- copy eax
   79 #
   80 # Still todo:
   81 #   global variables
   82 #   union types
   83 #
   84 # Formal types:
   85 #   A program is a linked list of functions
   86 #   A function contains:
   87 #     name: (handle array byte)
   88 #     inouts: linked list of vars  <-- 'inouts' is more precise than 'inputs'
   89 #       data: (handle var)
   90 #       next: (handle list)
   91 #     outputs: linked list of vars
   92 #       data: (handle var)
   93 #       next: (handle list)
   94 #     body: (handle block)
   95 #   A var-type contains:
   96 #     name: (handle array byte)
   97 #     type: (handle type-tree)
   98 #
   99 #   A statement can be:
  100 #     tag 0: a block
  101 #     tag 1: a simple statement (stmt1)
  102 #     tag 2: a variable defined on the stack
  103 #     tag 3: a variable defined in a register
  104 #
  105 #   A block contains:
  106 #     tag: 0
  107 #     statements: (handle list stmt)
  108 #     name: (handle array byte) -- starting with '$'
  109 #
  110 #   A regular statement contains:
  111 #     tag: 1
  112 #     operation: (handle array byte)
  113 #     inouts: (handle list operand)
  114 #     outputs: (handle list var)
  115 #
  116 #   A variable defined on the stack contains:
  117 #     tag: 2
  118 #     name: (handle array byte)
  119 #     type: (handle type-tree)
  120 #
  121 #   A variable defined in a register contains:
  122 #     tag: 3
  123 #     name: (handle array byte)
  124 #     type: (handle type-tree)
  125 #     reg: (handle array byte)
  126 
  127 # == Translation: managing the stack
  128 # Now that we know what the language looks like in the large, let's think
  129 # about how translation happens from the bottom up. One crucial piece of the
  130 # puzzle is how Mu will clean up variables defined on the stack for you.
  131 #
  132 # Assume that we maintain a 'functions' list while parsing source code. And a
  133 # 'primitives' list is a global constant. Both these contain enough information
  134 # to perform type-checking on function calls or primitive statements, respectively.
  135 #
  136 # Defining variables pushes them on a stack with the current block depth and
  137 # enough information about their location (stack offset or register).
  138 # Starting a block increments the current block id.
  139 # Each statement now has enough information to emit code for it.
  140 # Ending a block is where the magic happens:
  141 #   pop all variables at the current block depth
  142 #   emit code to restore all register variables introduced at the current depth
  143 #   emit code to clean up all stack variables at the current depth (just increment esp)
  144 #   decrement the current block depth
  145 #
  146 # Formal types:
  147 #   live-vars: stack of vars
  148 #   var:
  149 #     name: (handle array byte)
  150 #     type: (handle type-tree)
  151 #     block: int
  152 #     stack-offset: int  (added to ebp)
  153 #     register: (handle array byte)
  154 #       either usual register names
  155 #       or '*' to indicate any register
  156 #   At most one of stack-offset or register-index must be non-zero.
  157 #   A register of '*' designates a variable _template_. Only legal in formal
  158 #   parameters for primitives.
  159 
  160 # == Translating a single function call
  161 # This one's easy. Assuming we've already checked things, we just drop the
  162 # outputs (which use hard-coded registers) and emit inputs in a standard format.
  163 #
  164 # out1, out2, out3, ... <- name inout1, inout2, inout3, ...
  165 # =>
  166 # (name inout1 inout2 inout3)
  167 #
  168 # Formal types:
  169 #   functions: linked list of info
  170 #     name: (handle array byte)
  171 #     inouts: linked list of vars
  172 #     outputs: linked list of vars
  173 #     body: block (linked list of statements)
  174 
  175 # == Translating a single primitive instruction
  176 # A second crucial piece of the puzzle is how Mu converts fairly regular
  177 # primitives with their uniform syntax to SubX instructions with their gnarly
  178 # x86 details.
  179 #
  180 # Mu instructions have inputs and outputs. Primitives can have up to 2 of
  181 # them.
  182 # SubX instructions have rm32 and r32 operands.
  183 # The translation between them covers almost all the possibilities.
  184 #   Instructions with 1 inout may turn into ones with 1 rm32
  185 #     (e.g. incrementing a var on the stack)
  186 #   Instructions with 1 output may turn into ones with 1 rm32
  187 #     (e.g. incrementing a var in a register)
  188 #   1 inout and 1 output may turn into 1 rm32 and 1 r32
  189 #     (e.g. adding a var to a reg)
  190 #   2 inouts may turn into 1 rm32 and 1 r32
  191 #     (e.g. adding a reg to a var)
  192 #   1 inout and 1 literal may turn into 1 rm32 and 1 imm32
  193 #     (e.g. adding a constant to a var)
  194 #   1 output and 1 literal may turn into 1 rm32 and 1 imm32
  195 #     (e.g. adding a constant to a reg)
  196 #   2 outputs to hardcoded registers and 1 inout may turn into 1 rm32
  197 #     (special-case: divide edx:eax by a var or reg)
  198 # Observations:
  199 #   We always emit rm32. It may be the first inout or the first output.
  200 #   We may emit r32 or imm32 or neither.
  201 #   When we emit r32 it may come from first inout or second inout or first output.
  202 #
  203 # Accordingly, the formal data structure for a primitive looks like this:
  204 #   primitives: linked list of info
  205 #     name: (handle array byte)
  206 #     mu-inouts: linked list of vars to check
  207 #     mu-outputs: linked list of vars to check; at most a singleton
  208 #     subx-name: (handle array byte)
  209 #     subx-rm32: enum arg-location
  210 #     subx-r32: enum arg-location
  211 #     subx-imm32: enum arg-location
  212 #     subx-imm8: enum arg-location
  213 #     subx-disp32: enum arg-location
  214 #     subx-xm32: enum arg-location
  215 #     subx-x32: enum arg-location
  216 #   arg-location: enum
  217 #     0 means none
  218 #     1 means first inout
  219 #     2 means second inout
  220 #     3 means first output
  221 
  222 # == Translating a block
  223 # Emit block name if necessary
  224 # Emit '{'
  225 # When you encounter a statement, emit it as above
  226 # When you encounter a variable declaration
  227 #   emit any code needed for it (bzeros)
  228 #   push it on the var stack
  229 #   update register dict if necessary
  230 # When you encounter '}'
  231 #   While popping variables off the var stack until block id changes
  232 #     Emit code needed to clean up the stack
  233 #       either increment esp
  234 #       or pop into appropriate register
  235 
  236 # The rest is straightforward.
  237 
  238 == data
  239 
  240 Program:
  241 _Program-functions:  # (handle function)
  242   0/imm32
  243 _Program-functions->payload:
  244   0/imm32
  245 _Program-types:  # (handle typeinfo)
  246   0/imm32
  247 _Program-types->payload:
  248   0/imm32
  249 _Program-signatures:  # (handle function)
  250   0/imm32
  251 _Program-signatures->payload:
  252   0/imm32
  253 
  254 # Some constants for simulating the data structures described above.
  255 # Many constants here come with a type in a comment.
  256 #
  257 # Sometimes the type is of the value at that offset for the given type. For
  258 # example, if you start at a function record and move forward Function-inouts
  259 # bytes, you'll find a (handle list var).
  260 #
  261 # At other times, the type is of the constant itself. For example, the type of
  262 # the constant Function-size is (addr int). To get the size of a function,
  263 # look in *Function-size.
  264 
  265 Function-name:  # (handle array byte)
  266   0/imm32
  267 Function-inouts:  # (handle list var)
  268   8/imm32
  269 Function-outputs:  # (handle list var)
  270   0x10/imm32
  271 Function-body:  # (handle block)
  272   0x18/imm32
  273 Function-next:  # (handle function)
  274   0x20/imm32
  275 Function-size:  # (addr int)
  276   0x28/imm32/40
  277 
  278 Primitive-name:  # (handle array byte)
  279   0/imm32
  280 Primitive-inouts:  # (handle list var)
  281   8/imm32
  282 Primitive-outputs:  # (handle list var)
  283   0x10/imm32
  284 Primitive-subx-name:  # (handle array byte)
  285   0x18/imm32
  286 Primitive-subx-rm32:  # enum arg-location
  287   0x20/imm32
  288 Primitive-subx-r32:  # enum arg-location
  289   0x24/imm32
  290 Primitive-subx-imm32:  # enum arg-location
  291   0x28/imm32
  292 Primitive-subx-imm8:  # enum arg-location  -- only for bit shifts
  293   0x2c/imm32
  294 Primitive-subx-disp32:  # enum arg-location  -- only for branches
  295   0x30/imm32
  296 Primitive-subx-xm32:  # enum arg-location
  297   0x34/imm32
  298 Primitive-subx-x32:  # enum arg-location
  299   0x38/imm32
  300 Primitive-next:  # (handle function)
  301   0x3c/imm32
  302 Primitive-size:  # (addr int)
  303   0x44/imm32/68
  304 
  305 Stmt-tag:  # int
  306   0/imm32
  307 
  308 Block-stmts:  # (handle list stmt)
  309   4/imm32
  310 Block-var:  # (handle var)
  311   0xc/imm32
  312 
  313 Stmt1-operation:  # (handle array byte)
  314   4/imm32
  315 Stmt1-inouts:  # (handle stmt-var)
  316   0xc/imm32
  317 Stmt1-outputs:  # (handle stmt-var)
  318   0x14/imm32
  319 
  320 Vardef-var:  # (handle var)
  321   4/imm32
  322 
  323 Regvardef-operation:  # (handle array byte)
  324   4/imm32
  325 Regvardef-inouts:  # (handle stmt-var)
  326   0xc/imm32
  327 Regvardef-outputs:  # (handle stmt-var)  # will have exactly one element
  328   0x14/imm32
  329 
  330 Stmt-size:  # (addr int)
  331   0x1c/imm32
  332 
  333 Var-name:  # (handle array byte)
  334   0/imm32
  335 Var-type:  # (handle type-tree)
  336   8/imm32
  337 Var-block-depth:  # int -- not available until code-generation time
  338   0x10/imm32
  339 Var-offset:  # int -- not available until code-generation time
  340   0x14/imm32
  341 Var-register:  # (handle array byte) -- name of a register
  342   0x18/imm32
  343 Var-size:  # (addr int)
  344   0x20/imm32
  345 
  346 List-value:  # (handle _)
  347   0/imm32
  348 List-next:  # (handle list _)
  349   8/imm32
  350 List-size:  # (addr int)
  351   0x10/imm32
  352 
  353 # A stmt-var is like a list of vars with call-site specific metadata
  354 Stmt-var-value:  # (handle var)
  355   0/imm32
  356 Stmt-var-next:  # (handle stmt-var)
  357   8/imm32
  358 Stmt-var-is-deref:  # boolean
  359   0x10/imm32
  360 Stmt-var-size:  # (addr int)
  361   0x14/imm32
  362 
  363 # A live-var is a var augmented with information needed for tracking live
  364 # variables.
  365 Live-var-value:  # (handle var)
  366   0/imm32
  367 Live-var-register-spilled:  # boolean; only used if value is in a register, and only during code-gen
  368   8/imm32
  369 Live-var-size:  # (addr int)
  370   0xc/imm32
  371 
  372 # Types are expressed as trees (s-expressions) of type-ids (ints).
  373 
  374 Type-tree-is-atom:  # boolean
  375   0/imm32
  376 # if is-atom?
  377 Type-tree-value:  # type-id
  378   4/imm32
  379 Type-tree-value-size:  # int (for static data structure sizes)
  380   8/imm32
  381 Type-tree-parameter-name:  # (handle array byte) for type parameters
  382   8/imm32
  383 # unless is-atom?
  384 Type-tree-left:  # (addr type-tree)
  385   4/imm32
  386 Type-tree-right:  # (addr type-tree)
  387   0xc/imm32
  388 #
  389 Type-tree-size:  # (addr int)
  390   0x14/imm32
  391 
  392 # Types
  393 
  394 # TODO: Turn this data structure into valid Mu, with (fake) handles rather than addrs.
  395 Type-id:  # (stream (addr array byte))
  396   0/imm32/write  # initialized later from Primitive-type-ids
  397   0/imm32/read
  398   0x100/imm32/size
  399   # data
  400   0/imm32  # 0 reserved for literals; value is just the name
  401            # Not to be used directly, so we don't include a name here.
  402   "int"/imm32  # 1
  403   "addr"/imm32  # 2
  404   "array"/imm32  # 3
  405   "handle"/imm32  # 4
  406   "boolean"/imm32  # 5
  407   0/imm32  # 6 reserved for constants; they're like literals, but value is an int in Var-offset
  408            # Not to be used directly, so we don't include a name here.
  409   "offset"/imm32  # 7: (offset T) is guaranteed to be a 32-bit multiple of size-of(T)
  410   # 0x20
  411   "byte"/imm32  # 8
  412   0/imm32  # 9 reserved for array-capacity; value is in Type-tree-size.
  413            # Not to be used directly, so we don't include a name here.
  414   0/imm32  # 10 reserved for type parameters; value is (address array byte) in Type-tree-value2.
  415            # Not to be used directly, so we don't include a name here.
  416   "stream"/imm32  # 11
  417   "slice"/imm32  # 12
  418   "code-point"/imm32  # 13; smallest scannable unit from a text stream
  419   "grapheme"/imm32  # 14; smallest printable unit; will eventually be composed of multiple code-points, but currently corresponds 1:1
  420                     # only 4-byte graphemes in utf-8 are currently supported;
  421                     # unclear how we should deal with larger clusters.
  422   "float"/imm32     # 15
  423   # 0x40
  424   0/imm32  # 16 reserved for literal strings; value is just the name
  425            # Not to be used directly, so we don't include a name here.
  426            # TODO: move this up next to literal ints
  427   # Keep Primitive-type-ids in sync if you add types here.
  428           0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  429   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  430   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  431   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  432   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  433   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  434 
  435 Primitive-type-ids:  # (addr int)
  436   0x44
  437 
  438 # == Type definitions
  439 # Program->types contains some typeinfo for each type definition.
  440 # Types contain vars with types, but can't specify registers.
  441 Typeinfo-id:  # type-id
  442   0/imm32
  443 Typeinfo-fields:  # (handle table (handle array byte) (handle typeinfo-entry))
  444   4/imm32
  445 # Total size must be >= 0
  446 # During parsing it may take on two additional values:
  447 #   -2: not yet initialized
  448 #   -1: in process of being computed
  449 # See populate-mu-type-sizes for details.
  450 Typeinfo-total-size-in-bytes:  # int
  451   0xc/imm32
  452 Typeinfo-next:  # (handle typeinfo)
  453   0x10/imm32
  454 Typeinfo-size:  # (addr int)
  455   0x18/imm32
  456 
  457 # Each entry in the typeinfo->fields table has a pointer to a string and a
  458 # pointer to a typeinfo-entry.
  459 Typeinfo-fields-row-size:  # (addr int)
  460   0x10/imm32
  461 
  462 # typeinfo-entry objects have information about a field in a single record type
  463 #
  464 # each field of a type is represented using two var's:
  465 #   1. the input var: expected type of the field; convenient for creating using parse-var-with-type
  466 #   2. the output var: a constant containing the byte offset; convenient for code-generation
  467 # computing the output happens after parsing; in the meantime we preserve the
  468 # order of fields in the 'index' field.
  469 Typeinfo-entry-input-var:  # (handle var)
  470   0/imm32
  471 Typeinfo-entry-index:  # int
  472   8/imm32
  473 Typeinfo-entry-output-var:  # (handle var)
  474   0xc/imm32
  475 Typeinfo-entry-size:  # (addr int)
  476   0x14/imm32
  477 
  478 == code
  479 
  480 Entry:
  481     # . prologue
  482     89/<- %ebp 4/r32/esp
  483     (new-segment *Heap-size Heap)
  484     # if (argv[1] == "test') run-tests()
  485     {
  486       # if (argc <= 1) break
  487       81 7/subop/compare *ebp 1/imm32
  488       7e/jump-if-<= break/disp8
  489       # if (argv[1] != "test") break
  490       (kernel-string-equal? *(ebp+8) "test")  # => eax
  491       3d/compare-eax-and 0/imm32/false
  492       74/jump-if-= break/disp8
  493       #
  494       (run-tests)
  495       # syscall(exit, *Num-test-failures)
  496       8b/-> *Num-test-failures 3/r32/ebx
  497       eb/jump $mu-main:end/disp8
  498     }
  499     # otherwise convert Stdin
  500     (convert-mu Stdin Stdout Stderr 0)
  501     (flush Stdout)
  502     # syscall(exit, 0)
  503     bb/copy-to-ebx 0/imm32
  504 $mu-main:end:
  505     e8/call syscall_exit/disp32
  506 
  507 convert-mu:  # in: (addr buffered-file), out: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
  508     # . prologue
  509     55/push-ebp
  510     89/<- %ebp 4/r32/esp
  511     # . save registers
  512     50/push-eax
  513     # initialize global data structures
  514     c7 0/subop/copy *Next-block-index 1/imm32
  515     8b/-> *Primitive-type-ids 0/r32/eax
  516     89/<- *Type-id 0/r32/eax  # stream-write
  517     c7 0/subop/copy *_Program-functions 0/imm32
  518     c7 0/subop/copy *_Program-functions->payload 0/imm32
  519     c7 0/subop/copy *_Program-types 0/imm32
  520     c7 0/subop/copy *_Program-types->payload 0/imm32
  521     c7 0/subop/copy *_Program-signatures 0/imm32
  522     c7 0/subop/copy *_Program-signatures->payload 0/imm32
  523     #
  524     (parse-mu *(ebp+8) *(ebp+0x10) *(ebp+0x14))
  525     (populate-mu-type-sizes *(ebp+0x10) *(ebp+0x14))
  526 #?     (dump-typeinfos "=== typeinfos\n")
  527     (check-mu-types *(ebp+0x10) *(ebp+0x14))
  528     (emit-subx *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
  529 $convert-mu:end:
  530     # . restore registers
  531     58/pop-to-eax
  532     # . epilogue
  533     89/<- %esp 5/r32/ebp
  534     5d/pop-to-ebp
  535     c3/return
  536 
  537 test-convert-empty-input:
  538     # empty input => empty output
  539     # . prologue
  540     55/push-ebp
  541     89/<- %ebp 4/r32/esp
  542     # setup
  543     (clear-stream _test-input-stream)
  544     (clear-stream $_test-input-buffered-file->buffer)
  545     (clear-stream _test-output-stream)
  546     (clear-stream $_test-output-buffered-file->buffer)
  547     #
  548     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  549     (flush _test-output-buffered-file)
  550     (check-stream-equal _test-output-stream "" "F - test-convert-empty-input")
  551     # . epilogue
  552     89/<- %esp 5/r32/ebp
  553     5d/pop-to-ebp
  554     c3/return
  555 
  556 test-convert-function-skeleton:
  557     # . prologue
  558     55/push-ebp
  559     89/<- %ebp 4/r32/esp
  560     # setup
  561     (clear-stream _test-input-stream)
  562     (clear-stream $_test-input-buffered-file->buffer)
  563     (clear-stream _test-output-stream)
  564     (clear-stream $_test-output-buffered-file->buffer)
  565     #
  566     (write _test-input-stream "fn foo {\n")
  567     (write _test-input-stream "}\n")
  568     # convert
  569     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  570     (flush _test-output-buffered-file)
  571 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
  577     # check output
  578     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-skeleton/0")
  579     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-skeleton/1")
  580     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-skeleton/2")
  581     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-skeleton/3")
  582     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-skeleton/4")
  583     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-skeleton/5")
  584     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-skeleton/6")
  585     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-skeleton/7")
  586     # . epilogue
  587     89/<- %esp 5/r32/ebp
  588     5d/pop-to-ebp
  589     c3/return
  590 
  591 test-convert-multiple-function-skeletons:
  592     # . prologue
  593     55/push-ebp
  594     89/<- %ebp 4/r32/esp
  595     # setup
  596     (clear-stream _test-input-stream)
  597     (clear-stream $_test-input-buffered-file->buffer)
  598     (clear-stream _test-output-stream)
  599     (clear-stream $_test-output-buffered-file->buffer)
  600     #
  601     (write _test-input-stream "fn foo {\n")
  602     (write _test-input-stream "}\n")
  603     (write _test-input-stream "fn bar {\n")
  604     (write _test-input-stream "}\n")
  605     # convert
  606     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  607     (flush _test-output-buffered-file)
  608 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
  614     # check first function
  615     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-multiple-function-skeletons/0")
  616     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-multiple-function-skeletons/1")
  617     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-multiple-function-skeletons/2")
  618     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-multiple-function-skeletons/3")
  619     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-multiple-function-skeletons/4")
  620     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-multiple-function-skeletons/5")
  621     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-multiple-function-skeletons/6")
  622     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-multiple-function-skeletons/7")
  623     # check second function
  624     (check-next-stream-line-equal _test-output-stream "bar:"                    "F - test-convert-multiple-function-skeletons/10")
  625     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-multiple-function-skeletons/11")
  626     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-multiple-function-skeletons/12")
  627     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-multiple-function-skeletons/13")
  628     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-multiple-function-skeletons/14")
  629     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-multiple-function-skeletons/15")
  630     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-multiple-function-skeletons/16")
  631     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-multiple-function-skeletons/17")
  632     # . epilogue
  633     89/<- %esp 5/r32/ebp
  634     5d/pop-to-ebp
  635     c3/return
  636 
  637 test-convert-function-with-arg:
  638     # . prologue
  639     55/push-ebp
  640     89/<- %ebp 4/r32/esp
  641     # setup
  642     (clear-stream _test-input-stream)
  643     (clear-stream $_test-input-buffered-file->buffer)
  644     (clear-stream _test-output-stream)
  645     (clear-stream $_test-output-buffered-file->buffer)
  646     #
  647     (write _test-input-stream "fn foo n: int {\n")
  648     (write _test-input-stream "}\n")
  649     # convert
  650     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  651     (flush _test-output-buffered-file)
  652 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
  658     # check output
  659     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-arg/0")
  660     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-arg/1")
  661     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-arg/2")
  662     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-arg/3")
  663     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-arg/4")
  664     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-arg/5")
  665     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-arg/6")
  666     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-arg/7")
  667     # . epilogue
  668     89/<- %esp 5/r32/ebp
  669     5d/pop-to-ebp
  670     c3/return
  671 
  672 test-function-with-redefined-name:
  673     # . prologue
  674     55/push-ebp
  675     89/<- %ebp 4/r32/esp
  676     # setup
  677     (clear-stream _test-input-stream)
  678     (clear-stream $_test-input-buffered-file->buffer)
  679     (clear-stream _test-output-stream)
  680     (clear-stream $_test-output-buffered-file->buffer)
  681     (clear-stream _test-error-stream)
  682     (clear-stream $_test-error-buffered-file->buffer)
  683     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  684     68/push 0/imm32
  685     68/push 0/imm32
  686     89/<- %edx 4/r32/esp
  687     (tailor-exit-descriptor %edx 0x10)
  688     #
  689     (write _test-input-stream "fn foo {\n")
  690     (write _test-input-stream "}\n")
  691     (write _test-input-stream "fn foo {\n")
  692     (write _test-input-stream "}\n")
  693     # convert
  694     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  695     # registers except esp clobbered at this point
  696     # restore ed
  697     89/<- %edx 4/r32/esp
  698     (flush _test-output-buffered-file)
  699     (flush _test-error-buffered-file)
  700 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
  706     # check output
  707     (check-stream-equal _test-output-stream  ""  "F - test-function-with-redefined-name: output should be empty")
  708     (check-next-stream-line-equal _test-error-stream  "fn foo defined more than once"  "F - test-function-with-redefined-name: error message")
  709     # check that stop(1) was called
  710     (check-ints-equal *(edx+4) 2 "F - test-function-with-redefined-name: exit status")
  711     # don't restore from ebp
  712     81 0/subop/add %esp 8/imm32
  713     # . epilogue
  714     5d/pop-to-ebp
  715     c3/return
  716 
  717 test-function-with-redefined-name-2:
  718     # . prologue
  719     55/push-ebp
  720     89/<- %ebp 4/r32/esp
  721     # setup
  722     (clear-stream _test-input-stream)
  723     (clear-stream $_test-input-buffered-file->buffer)
  724     (clear-stream _test-output-stream)
  725     (clear-stream $_test-output-buffered-file->buffer)
  726     (clear-stream _test-error-stream)
  727     (clear-stream $_test-error-buffered-file->buffer)
  728     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  729     68/push 0/imm32
  730     68/push 0/imm32
  731     89/<- %edx 4/r32/esp
  732     (tailor-exit-descriptor %edx 0x10)
  733     #
  734     (write _test-input-stream "fn foo {\n")
  735     (write _test-input-stream "}\n")
  736     (write _test-input-stream "sig foo\n")
  737     # convert
  738     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  739     # registers except esp clobbered at this point
  740     # restore ed
  741     89/<- %edx 4/r32/esp
  742     (flush _test-output-buffered-file)
  743     (flush _test-error-buffered-file)
  744 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
  750     # check output
  751     (check-stream-equal _test-output-stream  ""  "F - test-function-with-redefined-name-2: output should be empty")
  752     (check-next-stream-line-equal _test-error-stream  "fn foo defined more than once"  "F - test-function-with-redefined-name-2: error message")
  753     # check that stop(1) was called
  754     (check-ints-equal *(edx+4) 2 "F - test-function-with-redefined-name-2: exit status")
  755     # don't restore from ebp
  756     81 0/subop/add %esp 8/imm32
  757     # . epilogue
  758     5d/pop-to-ebp
  759     c3/return
  760 
  761 test-function-with-redefined-name-3:
  762     # . prologue
  763     55/push-ebp
  764     89/<- %ebp 4/r32/esp
  765     # setup
  766     (clear-stream _test-input-stream)
  767     (clear-stream $_test-input-buffered-file->buffer)
  768     (clear-stream _test-output-stream)
  769     (clear-stream $_test-output-buffered-file->buffer)
  770     (clear-stream _test-error-stream)
  771     (clear-stream $_test-error-buffered-file->buffer)
  772     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  773     68/push 0/imm32
  774     68/push 0/imm32
  775     89/<- %edx 4/r32/esp
  776     (tailor-exit-descriptor %edx 0x10)
  777     #
  778     (write _test-input-stream "sig foo\n")
  779     (write _test-input-stream "fn foo {\n")
  780     (write _test-input-stream "}\n")
  781     # convert
  782     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  783     # registers except esp clobbered at this point
  784     # restore ed
  785     89/<- %edx 4/r32/esp
  786     (flush _test-output-buffered-file)
  787     (flush _test-error-buffered-file)
  788 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
  794     # check output
  795     (check-stream-equal _test-output-stream  ""  "F - test-function-with-redefined-name-3: output should be empty")
  796     (check-next-stream-line-equal _test-error-stream  "fn foo defined more than once"  "F - test-function-with-redefined-name-3: error message")
  797     # check that stop(1) was called
  798     (check-ints-equal *(edx+4) 2 "F - test-function-with-redefined-name-3: exit status")
  799     # don't restore from ebp
  800     81 0/subop/add %esp 8/imm32
  801     # . epilogue
  802     5d/pop-to-ebp
  803     c3/return
  804 
  805 test-function-with-inout-in-register:
  806     # . prologue
  807     55/push-ebp
  808     89/<- %ebp 4/r32/esp
  809     # setup
  810     (clear-stream _test-input-stream)
  811     (clear-stream $_test-input-buffered-file->buffer)
  812     (clear-stream _test-output-stream)
  813     (clear-stream $_test-output-buffered-file->buffer)
  814     (clear-stream _test-error-stream)
  815     (clear-stream $_test-error-buffered-file->buffer)
  816     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  817     68/push 0/imm32
  818     68/push 0/imm32
  819     89/<- %edx 4/r32/esp
  820     (tailor-exit-descriptor %edx 0x10)
  821     #
  822     (write _test-input-stream "fn foo x/eax: int {\n")
  823     (write _test-input-stream "}\n")
  824     # convert
  825     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  826     # registers except esp clobbered at this point
  827     # restore ed
  828     89/<- %edx 4/r32/esp
  829     (flush _test-output-buffered-file)
  830     (flush _test-error-buffered-file)
  831 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
  837     # check output
  838     (check-stream-equal _test-output-stream  ""  "F - test-function-with-inout-in-register: output should be empty")
  839     (check-next-stream-line-equal _test-error-stream  "fn foo: function inout 'x' cannot be in a register"  "F - test-function-with-inout-in-register: error message")
  840     # check that stop(1) was called
  841     (check-ints-equal *(edx+4) 2 "F - test-function-with-inout-in-register: exit status")
  842     # don't restore from ebp
  843     81 0/subop/add %esp 8/imm32
  844     # . epilogue
  845     5d/pop-to-ebp
  846     c3/return
  847 
  848 test-function-with-addr-output:
  849     # . prologue
  850     55/push-ebp
  851     89/<- %ebp 4/r32/esp
  852     # setup
  853     (clear-stream _test-input-stream)
  854     (clear-stream $_test-input-buffered-file->buffer)
  855     (clear-stream _test-output-stream)
  856     (clear-stream $_test-output-buffered-file->buffer)
  857     (clear-stream _test-error-stream)
  858     (clear-stream $_test-error-buffered-file->buffer)
  859     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  860     68/push 0/imm32
  861     68/push 0/imm32
  862     89/<- %edx 4/r32/esp
  863     (tailor-exit-descriptor %edx 0x10)
  864     #
  865     (write _test-input-stream "fn foo -> _/eax: (addr int) {\n")
  866     (write _test-input-stream "}\n")
  867     # convert
  868     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  869     # registers except esp clobbered at this point
  870     # restore ed
  871     89/<- %edx 4/r32/esp
  872     (flush _test-output-buffered-file)
  873     (flush _test-error-buffered-file)
  874 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
  880     # check output
  881     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-output: output should be empty")
  882     (check-next-stream-line-equal _test-error-stream  "fn foo: output cannot have an addr type; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-output: error message")
  883     # check that stop(1) was called
  884     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-output: exit status")
  885     # don't restore from ebp
  886     81 0/subop/add %esp 8/imm32
  887     # . epilogue
  888     5d/pop-to-ebp
  889     c3/return
  890 
  891 test-function-with-addr-inout:
  892     # . prologue
  893     55/push-ebp
  894     89/<- %ebp 4/r32/esp
  895     # setup
  896     (clear-stream _test-input-stream)
  897     (clear-stream $_test-input-buffered-file->buffer)
  898     (clear-stream _test-output-stream)
  899     (clear-stream $_test-output-buffered-file->buffer)
  900     (clear-stream _test-error-stream)
  901     (clear-stream $_test-error-buffered-file->buffer)
  902     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  903     68/push 0/imm32
  904     68/push 0/imm32
  905     89/<- %edx 4/r32/esp
  906     (tailor-exit-descriptor %edx 0x10)
  907     #
  908     (write _test-input-stream "fn foo a: (addr addr int) {\n")
  909     (write _test-input-stream "}\n")
  910     # convert
  911     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  912     # registers except esp clobbered at this point
  913     # restore ed
  914     89/<- %edx 4/r32/esp
  915     (flush _test-output-buffered-file)
  916     (flush _test-error-buffered-file)
  917 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
  923     # check output
  924     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout: output should be empty")
  925     (check-next-stream-line-equal _test-error-stream  "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-inout: error message")
  926     # check that stop(1) was called
  927     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout: exit status")
  928     # don't restore from ebp
  929     81 0/subop/add %esp 8/imm32
  930     # . epilogue
  931     5d/pop-to-ebp
  932     c3/return
  933 
  934 test-function-with-addr-inout-2:
  935     # . prologue
  936     55/push-ebp
  937     89/<- %ebp 4/r32/esp
  938     # setup
  939     (clear-stream _test-input-stream)
  940     (clear-stream $_test-input-buffered-file->buffer)
  941     (clear-stream _test-output-stream)
  942     (clear-stream $_test-output-buffered-file->buffer)
  943     (clear-stream _test-error-stream)
  944     (clear-stream $_test-error-buffered-file->buffer)
  945     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  946     68/push 0/imm32
  947     68/push 0/imm32
  948     89/<- %edx 4/r32/esp
  949     (tailor-exit-descriptor %edx 0x10)
  950     #
  951     (write _test-input-stream "fn foo a: (addr array addr int) {\n")
  952     (write _test-input-stream "}\n")
  953     # convert
  954     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  955     # registers except esp clobbered at this point
  956     # restore ed
  957     89/<- %edx 4/r32/esp
  958     (flush _test-output-buffered-file)
  959     (flush _test-error-buffered-file)
  960 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
  966     # check output
  967     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout-2: output should be empty")
  968     (check-next-stream-line-equal _test-error-stream  "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-inout-2: error message")
  969     # check that stop(1) was called
  970     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout-2: exit status")
  971     # don't restore from ebp
  972     81 0/subop/add %esp 8/imm32
  973     # . epilogue
  974     5d/pop-to-ebp
  975     c3/return
  976 
  977 test-function-with-addr-inout-3:
  978     # . prologue
  979     55/push-ebp
  980     89/<- %ebp 4/r32/esp
  981     # setup
  982     (clear-stream _test-input-stream)
  983     (clear-stream $_test-input-buffered-file->buffer)
  984     (clear-stream _test-output-stream)
  985     (clear-stream $_test-output-buffered-file->buffer)
  986     (clear-stream _test-error-stream)
  987     (clear-stream $_test-error-buffered-file->buffer)
  988     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  989     68/push 0/imm32
  990     68/push 0/imm32
  991     89/<- %edx 4/r32/esp
  992     (tailor-exit-descriptor %edx 0x10)
  993     #
  994     (write _test-input-stream "fn foo a: (addr array (addr int) 3) {\n")
  995     (write _test-input-stream "}\n")
  996     # convert
  997     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  998     # registers except esp clobbered at this point
  999     # restore ed
 1000     89/<- %edx 4/r32/esp
 1001     (flush _test-output-buffered-file)
 1002     (flush _test-error-buffered-file)
 1003 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1009     # check output
 1010     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout-3: output should be empty")
 1011     (check-next-stream-line-equal _test-error-stream  "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-inout-3: error message")
 1012     # check that stop(1) was called
 1013     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout-3: exit status")
 1014     # don't restore from ebp
 1015     81 0/subop/add %esp 8/imm32
 1016     # . epilogue
 1017     5d/pop-to-ebp
 1018     c3/return
 1019 
 1020 test-function-with-addr-inout-4:
 1021     # . prologue
 1022     55/push-ebp
 1023     89/<- %ebp 4/r32/esp
 1024     # setup
 1025     (clear-stream _test-input-stream)
 1026     (clear-stream $_test-input-buffered-file->buffer)
 1027     (clear-stream _test-output-stream)
 1028     (clear-stream $_test-output-buffered-file->buffer)
 1029     (clear-stream _test-error-stream)
 1030     (clear-stream $_test-error-buffered-file->buffer)
 1031     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1032     68/push 0/imm32
 1033     68/push 0/imm32
 1034     89/<- %edx 4/r32/esp
 1035     (tailor-exit-descriptor %edx 0x10)
 1036     #
 1037     (write _test-input-stream "fn foo a: (array (addr int) 3) {\n")
 1038     (write _test-input-stream "}\n")
 1039     # convert
 1040     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1041     # registers except esp clobbered at this point
 1042     # restore ed
 1043     89/<- %edx 4/r32/esp
 1044     (flush _test-output-buffered-file)
 1045     (flush _test-error-buffered-file)
 1046 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1052     # check output
 1053     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout-4: output should be empty")
 1054     (check-next-stream-line-equal _test-error-stream  "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-inout-4: error message")
 1055     # check that stop(1) was called
 1056     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout-4: exit status")
 1057     # don't restore from ebp
 1058     81 0/subop/add %esp 8/imm32
 1059     # . epilogue
 1060     5d/pop-to-ebp
 1061     c3/return
 1062 
 1063 # 'main' is an exception
 1064 test-function-main-with-addr-inout:
 1065     # . prologue
 1066     55/push-ebp
 1067     89/<- %ebp 4/r32/esp
 1068     # setup
 1069     (clear-stream _test-input-stream)
 1070     (clear-stream $_test-input-buffered-file->buffer)
 1071     (clear-stream _test-output-stream)
 1072     (clear-stream $_test-output-buffered-file->buffer)
 1073     #
 1074     (write _test-input-stream "fn main a: (addr addr int) {\n")
 1075     (write _test-input-stream "}\n")
 1076     # convert
 1077     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1078     (flush _test-output-buffered-file)
 1079     # no errors
 1080     # . epilogue
 1081     89/<- %esp 5/r32/ebp
 1082     5d/pop-to-ebp
 1083     c3/return
 1084 
 1085 # 'lookup' is an exception, but only in signatures
 1086 test-signature-lookup-with-addr-inout:
 1087     # . prologue
 1088     55/push-ebp
 1089     89/<- %ebp 4/r32/esp
 1090     # setup
 1091     (clear-stream _test-input-stream)
 1092     (clear-stream $_test-input-buffered-file->buffer)
 1093     (clear-stream _test-output-stream)
 1094     (clear-stream $_test-output-buffered-file->buffer)
 1095     #
 1096     (write _test-input-stream "sig lookup h: (handle _T) -> _/eax: (addr _T)\n")
 1097     # convert
 1098     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1099     (flush _test-output-buffered-file)
 1100     # no errors
 1101     # . epilogue
 1102     89/<- %esp 5/r32/ebp
 1103     5d/pop-to-ebp
 1104     c3/return
 1105 
 1106 test-convert-function-with-arg-and-body:
 1107     # . prologue
 1108     55/push-ebp
 1109     89/<- %ebp 4/r32/esp
 1110     # setup
 1111     (clear-stream _test-input-stream)
 1112     (clear-stream $_test-input-buffered-file->buffer)
 1113     (clear-stream _test-output-stream)
 1114     (clear-stream $_test-output-buffered-file->buffer)
 1115     #
 1116     (write _test-input-stream "fn foo n: int {\n")
 1117     (write _test-input-stream "  increment n\n")
 1118     (write _test-input-stream "}\n")
 1119     # convert
 1120     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1121     (flush _test-output-buffered-file)
 1122 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1128     # check output
 1129     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-arg-and-body/0")
 1130     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-arg-and-body/1")
 1131     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-arg-and-body/2")
 1132     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-arg-and-body/3")
 1133     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-arg-and-body/4")
 1134     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-arg-and-body/5")
 1135     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-arg-and-body/6")
 1136     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-arg-and-body/7")
 1137     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-arg-and-body/8")
 1138     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-arg-and-body/9")
 1139     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-arg-and-body/10")
 1140     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-arg-and-body/11")
 1141     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-arg-and-body/12")
 1142     # . epilogue
 1143     89/<- %esp 5/r32/ebp
 1144     5d/pop-to-ebp
 1145     c3/return
 1146 
 1147 test-convert-function-distinguishes-args:
 1148     # . prologue
 1149     55/push-ebp
 1150     89/<- %ebp 4/r32/esp
 1151     # setup
 1152     (clear-stream _test-input-stream)
 1153     (clear-stream $_test-input-buffered-file->buffer)
 1154     (clear-stream _test-output-stream)
 1155     (clear-stream $_test-output-buffered-file->buffer)
 1156     #
 1157     (write _test-input-stream "fn foo a: int, b: int {\n")
 1158     (write _test-input-stream "  increment b\n")
 1159     (write _test-input-stream "}\n")
 1160     # convert
 1161     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1162     (flush _test-output-buffered-file)
 1163 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1169     # check output
 1170     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-distinguishes-args/0")
 1171     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-distinguishes-args/1")
 1172     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-distinguishes-args/2")
 1173     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-distinguishes-args/3")
 1174     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-distinguishes-args/4")
 1175     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-distinguishes-args/5")
 1176     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0x0000000c)"  "F - test-convert-function-distinguishes-args/6")
 1177     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-distinguishes-args/7")
 1178     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-distinguishes-args/8")
 1179     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-distinguishes-args/9")
 1180     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-distinguishes-args/10")
 1181     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-distinguishes-args/11")
 1182     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-distinguishes-args/12")
 1183     # . epilogue
 1184     89/<- %esp 5/r32/ebp
 1185     5d/pop-to-ebp
 1186     c3/return
 1187 
 1188 test-convert-function-with-return-literal:
 1189     # . prologue
 1190     55/push-ebp
 1191     89/<- %ebp 4/r32/esp
 1192     # setup
 1193     (clear-stream _test-input-stream)
 1194     (clear-stream $_test-input-buffered-file->buffer)
 1195     (clear-stream _test-output-stream)
 1196     (clear-stream $_test-output-buffered-file->buffer)
 1197     #
 1198     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1199     (write _test-input-stream "  return 0\n")
 1200     (write _test-input-stream "}\n")
 1201     # convert
 1202     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1203     (flush _test-output-buffered-file)
 1204 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1210     # check output
 1211     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-literal/0")
 1212     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-literal/1")
 1213     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-literal/2")
 1214     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-literal/3")
 1215     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-literal/4")
 1216     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-literal/5")
 1217     (check-next-stream-line-equal _test-output-stream "    c7 0/subop/copy %eax 0/imm32"  "F - test-convert-function-with-return-literal/6")
 1218     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-literal/7")
 1219     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-literal/8")
 1220     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-literal/9")
 1221     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-literal/10")
 1222     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-literal/11")
 1223     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-literal/12")
 1224     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-literal/13")
 1225     # . epilogue
 1226     89/<- %esp 5/r32/ebp
 1227     5d/pop-to-ebp
 1228     c3/return
 1229 
 1230 test-convert-function-with-return:
 1231     # . prologue
 1232     55/push-ebp
 1233     89/<- %ebp 4/r32/esp
 1234     # setup
 1235     (clear-stream _test-input-stream)
 1236     (clear-stream $_test-input-buffered-file->buffer)
 1237     (clear-stream _test-output-stream)
 1238     (clear-stream $_test-output-buffered-file->buffer)
 1239     #
 1240     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1241     (write _test-input-stream "  var y: int\n")
 1242     (write _test-input-stream "  return y\n")
 1243     (write _test-input-stream "}\n")
 1244     # convert
 1245     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1246     (flush _test-output-buffered-file)
 1247 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1253     # check output
 1254     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return/0")
 1255     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return/1")
 1256     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return/2")
 1257     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return/3")
 1258     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return/4")
 1259     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return/5")
 1260     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-return/6")  # y
 1261     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0xfffffffc) 0x00000000/r32" "F - test-convert-function-with-return/7")
 1262     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-return/8")
 1263     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return/9")
 1264     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return/10")
 1265     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return/11")
 1266     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return/12")
 1267     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return/13")
 1268     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return/14")
 1269     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return/15")
 1270     # . epilogue
 1271     89/<- %esp 5/r32/ebp
 1272     5d/pop-to-ebp
 1273     c3/return
 1274 
 1275 test-convert-function-with-return-register:
 1276     # . prologue
 1277     55/push-ebp
 1278     89/<- %ebp 4/r32/esp
 1279     # setup
 1280     (clear-stream _test-input-stream)
 1281     (clear-stream $_test-input-buffered-file->buffer)
 1282     (clear-stream _test-output-stream)
 1283     (clear-stream $_test-output-buffered-file->buffer)
 1284     #
 1285     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1286     (write _test-input-stream "  var y/eax: int <- copy 3\n")
 1287     (write _test-input-stream "  return y\n")
 1288     (write _test-input-stream "}\n")
 1289     # convert
 1290     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1291     (flush _test-output-buffered-file)
 1292 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1298     # check output
 1299     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register/0")
 1300     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register/1")
 1301     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register/2")
 1302     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register/3")
 1303     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register/4")
 1304     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register/5")
 1305     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register/6")
 1306     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-convert-function-with-return-register/7")
 1307     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-return-register/8")
 1308     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-return-register/9")
 1309     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-register/10")
 1310     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register/11")
 1311     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register/12")
 1312     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register/13")
 1313     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register/14")
 1314     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register/15")
 1315     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register/16")
 1316     # . epilogue
 1317     89/<- %esp 5/r32/ebp
 1318     5d/pop-to-ebp
 1319     c3/return
 1320 
 1321 test-function-with-output-without-register:
 1322     # . prologue
 1323     55/push-ebp
 1324     89/<- %ebp 4/r32/esp
 1325     # setup
 1326     (clear-stream _test-input-stream)
 1327     (clear-stream $_test-input-buffered-file->buffer)
 1328     (clear-stream _test-output-stream)
 1329     (clear-stream $_test-output-buffered-file->buffer)
 1330     (clear-stream _test-error-stream)
 1331     (clear-stream $_test-error-buffered-file->buffer)
 1332     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1333     68/push 0/imm32
 1334     68/push 0/imm32
 1335     89/<- %edx 4/r32/esp
 1336     (tailor-exit-descriptor %edx 0x10)
 1337     #
 1338     (write _test-input-stream "fn foo -> _: int {\n")
 1339     (write _test-input-stream "}\n")
 1340     # convert
 1341     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1342     # registers except esp clobbered at this point
 1343     # restore ed
 1344     89/<- %edx 4/r32/esp
 1345     (flush _test-output-buffered-file)
 1346     (flush _test-error-buffered-file)
 1347 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1353     # check output
 1354     (check-stream-equal _test-output-stream  ""  "F - test-function-with-output-without-register: output should be empty")
 1355     (check-next-stream-line-equal _test-error-stream  "fn foo: function output '_' must be in a register, in instruction 'fn foo -> _: int {"  "F - test-function-with-output-without-register: error message")
 1356     # check that stop(1) was called
 1357     (check-ints-equal *(edx+4) 2 "F - test-function-with-output-without-register: exit status")
 1358     # don't restore from ebp
 1359     81 0/subop/add %esp 8/imm32
 1360     # . epilogue
 1361     5d/pop-to-ebp
 1362     c3/return
 1363 
 1364 test-function-with-outputs-in-conflicting-registers:
 1365     # . prologue
 1366     55/push-ebp
 1367     89/<- %ebp 4/r32/esp
 1368     # setup
 1369     (clear-stream _test-input-stream)
 1370     (clear-stream $_test-input-buffered-file->buffer)
 1371     (clear-stream _test-output-stream)
 1372     (clear-stream $_test-output-buffered-file->buffer)
 1373     (clear-stream _test-error-stream)
 1374     (clear-stream $_test-error-buffered-file->buffer)
 1375     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1376     68/push 0/imm32
 1377     68/push 0/imm32
 1378     89/<- %edx 4/r32/esp
 1379     (tailor-exit-descriptor %edx 0x10)
 1380     #
 1381     (write _test-input-stream "fn foo -> _/eax: int, _/eax: int {\n")
 1382     (write _test-input-stream "}\n")
 1383     # convert
 1384     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1385     # registers except esp clobbered at this point
 1386     # restore ed
 1387     89/<- %edx 4/r32/esp
 1388     (flush _test-output-buffered-file)
 1389     (flush _test-error-buffered-file)
 1390 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1396     # check output
 1397     (check-stream-equal _test-output-stream  ""  "F - test-function-with-outputs-in-conflicting-registers: output should be empty")
 1398     (check-next-stream-line-equal _test-error-stream  "fn foo: outputs must be in unique registers"  "F - test-function-with-outputs-in-conflicting-registers: error message")
 1399     # check that stop(1) was called
 1400     (check-ints-equal *(edx+4) 2 "F - test-function-with-outputs-in-conflicting-registers: exit status")
 1401     # don't restore from ebp
 1402     81 0/subop/add %esp 8/imm32
 1403     # . epilogue
 1404     5d/pop-to-ebp
 1405     c3/return
 1406 
 1407 test-function-with-named-output:
 1408     # . prologue
 1409     55/push-ebp
 1410     89/<- %ebp 4/r32/esp
 1411     # setup
 1412     (clear-stream _test-input-stream)
 1413     (clear-stream $_test-input-buffered-file->buffer)
 1414     (clear-stream _test-output-stream)
 1415     (clear-stream $_test-output-buffered-file->buffer)
 1416     (clear-stream _test-error-stream)
 1417     (clear-stream $_test-error-buffered-file->buffer)
 1418     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1419     68/push 0/imm32
 1420     68/push 0/imm32
 1421     89/<- %edx 4/r32/esp
 1422     (tailor-exit-descriptor %edx 0x10)
 1423     #
 1424     (write _test-input-stream "fn foo -> x/eax: int {\n")
 1425     (write _test-input-stream "  return 0\n")
 1426     (write _test-input-stream "}\n")
 1427     # convert
 1428     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1429     # registers except esp clobbered at this point
 1430     # restore ed
 1431     89/<- %edx 4/r32/esp
 1432     (flush _test-output-buffered-file)
 1433     (flush _test-error-buffered-file)
 1434 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1440     # check output
 1441     (check-stream-equal _test-output-stream  ""  "F - test-function-with-named-output: output should be empty")
 1442     (check-next-stream-line-equal _test-error-stream  "fn foo: function outputs cannot be named; rename 'x' in the header to '_'"  "F - test-function-with-named-output: error message")
 1443     # check that stop(1) was called
 1444     (check-ints-equal *(edx+4) 2 "F - test-function-with-named-output: exit status")
 1445     # don't restore from ebp
 1446     81 0/subop/add %esp 8/imm32
 1447     # . epilogue
 1448     5d/pop-to-ebp
 1449     c3/return
 1450 
 1451 test-return-with-wrong-type:
 1452     # . prologue
 1453     55/push-ebp
 1454     89/<- %ebp 4/r32/esp
 1455     # setup
 1456     (clear-stream _test-input-stream)
 1457     (clear-stream $_test-input-buffered-file->buffer)
 1458     (clear-stream _test-output-stream)
 1459     (clear-stream $_test-output-buffered-file->buffer)
 1460     (clear-stream _test-error-stream)
 1461     (clear-stream $_test-error-buffered-file->buffer)
 1462     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1463     68/push 0/imm32
 1464     68/push 0/imm32
 1465     89/<- %edx 4/r32/esp
 1466     (tailor-exit-descriptor %edx 0x10)
 1467     #
 1468     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1469     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 1470     (write _test-input-stream "  return x\n")
 1471     (write _test-input-stream "}\n")
 1472     # convert
 1473     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1474     # registers except esp clobbered at this point
 1475     # restore ed
 1476     89/<- %edx 4/r32/esp
 1477     (flush _test-output-buffered-file)
 1478     (flush _test-error-buffered-file)
 1479 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1485     # check output
 1486     (check-stream-equal _test-output-stream  ""  "F - test-return-with-wrong-type: output should be empty")
 1487     (check-next-stream-line-equal _test-error-stream  "fn foo: return: 'x' has the wrong type"  "F - test-return-with-wrong-type: error message")
 1488     # check that stop(1) was called
 1489     (check-ints-equal *(edx+4) 2 "F - test-return-with-wrong-type: exit status")
 1490     # don't restore from ebp
 1491     81 0/subop/add %esp 8/imm32
 1492     # . epilogue
 1493     5d/pop-to-ebp
 1494     c3/return
 1495 
 1496 test-missing-return:
 1497     # . prologue
 1498     55/push-ebp
 1499     89/<- %ebp 4/r32/esp
 1500     # setup
 1501     (clear-stream _test-input-stream)
 1502     (clear-stream $_test-input-buffered-file->buffer)
 1503     (clear-stream _test-output-stream)
 1504     (clear-stream $_test-output-buffered-file->buffer)
 1505     (clear-stream _test-error-stream)
 1506     (clear-stream $_test-error-buffered-file->buffer)
 1507     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1508     68/push 0/imm32
 1509     68/push 0/imm32
 1510     89/<- %edx 4/r32/esp
 1511     (tailor-exit-descriptor %edx 0x10)
 1512     #
 1513     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1514     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 1515     (write _test-input-stream "}\n")
 1516     # convert
 1517     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1518     # registers except esp clobbered at this point
 1519     # restore ed
 1520     89/<- %edx 4/r32/esp
 1521     (flush _test-output-buffered-file)
 1522     (flush _test-error-buffered-file)
 1523 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1529     # check output
 1530     (check-stream-equal _test-output-stream  ""  "F - test-missing-return: output should be empty")
 1531     (check-next-stream-line-equal _test-error-stream  "fn foo: final statement should be a 'return'"  "F - test-missing-return: error message")
 1532     # check that stop(1) was called
 1533     (check-ints-equal *(edx+4) 2 "F - test-missing-return: exit status")
 1534     # don't restore from ebp
 1535     81 0/subop/add %esp 8/imm32
 1536     # . epilogue
 1537     5d/pop-to-ebp
 1538     c3/return
 1539 
 1540 test-early-exit-without-return:
 1541     # . prologue
 1542     55/push-ebp
 1543     89/<- %ebp 4/r32/esp
 1544     # setup
 1545     (clear-stream _test-input-stream)
 1546     (clear-stream $_test-input-buffered-file->buffer)
 1547     (clear-stream _test-output-stream)
 1548     (clear-stream $_test-output-buffered-file->buffer)
 1549     (clear-stream _test-error-stream)
 1550     (clear-stream $_test-error-buffered-file->buffer)
 1551     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1552     68/push 0/imm32
 1553     68/push 0/imm32
 1554     89/<- %edx 4/r32/esp
 1555     (tailor-exit-descriptor %edx 0x10)
 1556     #
 1557     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1558     (write _test-input-stream "  break\n")
 1559     (write _test-input-stream "  return 0\n")
 1560     (write _test-input-stream "}\n")
 1561     # convert
 1562     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1563     # registers except esp clobbered at this point
 1564     # restore ed
 1565     89/<- %edx 4/r32/esp
 1566     (flush _test-output-buffered-file)
 1567     (flush _test-error-buffered-file)
 1568 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1574     # check output
 1575     (check-stream-equal _test-output-stream  ""  "F - test-early-exit-without-return: output should be empty")
 1576     (check-next-stream-line-equal _test-error-stream  "fn foo has outputs, so you cannot 'break' out of the outermost block. Use 'return'."  "F - test-early-exit-without-return: error message")
 1577     # check that stop(1) was called
 1578     (check-ints-equal *(edx+4) 2 "F - test-early-exit-without-return: exit status")
 1579     # don't restore from ebp
 1580     81 0/subop/add %esp 8/imm32
 1581     # . epilogue
 1582     5d/pop-to-ebp
 1583     c3/return
 1584 
 1585 test-return-with-too-few-inouts:
 1586     # . prologue
 1587     55/push-ebp
 1588     89/<- %ebp 4/r32/esp
 1589     # setup
 1590     (clear-stream _test-input-stream)
 1591     (clear-stream $_test-input-buffered-file->buffer)
 1592     (clear-stream _test-output-stream)
 1593     (clear-stream $_test-output-buffered-file->buffer)
 1594     (clear-stream _test-error-stream)
 1595     (clear-stream $_test-error-buffered-file->buffer)
 1596     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1597     68/push 0/imm32
 1598     68/push 0/imm32
 1599     89/<- %edx 4/r32/esp
 1600     (tailor-exit-descriptor %edx 0x10)
 1601     #
 1602     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1603     (write _test-input-stream "  return\n")
 1604     (write _test-input-stream "}\n")
 1605     # convert
 1606     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1607     # registers except esp clobbered at this point
 1608     # restore ed
 1609     89/<- %edx 4/r32/esp
 1610     (flush _test-output-buffered-file)
 1611     (flush _test-error-buffered-file)
 1612 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1618     # check output
 1619     (check-stream-equal _test-output-stream  ""  "F - test-return-with-too-few-inouts: output should be empty")
 1620     (check-next-stream-line-equal _test-error-stream  "fn foo: return: too few inouts"  "F - test-return-with-too-few-inouts: error message")
 1621     # check that stop(1) was called
 1622     (check-ints-equal *(edx+4) 2 "F - test-return-with-too-few-inouts: exit status")
 1623     # don't restore from ebp
 1624     81 0/subop/add %esp 8/imm32
 1625     # . epilogue
 1626     5d/pop-to-ebp
 1627     c3/return
 1628 
 1629 test-return-with-too-many-inouts:
 1630     # . prologue
 1631     55/push-ebp
 1632     89/<- %ebp 4/r32/esp
 1633     # setup
 1634     (clear-stream _test-input-stream)
 1635     (clear-stream $_test-input-buffered-file->buffer)
 1636     (clear-stream _test-output-stream)
 1637     (clear-stream $_test-output-buffered-file->buffer)
 1638     (clear-stream _test-error-stream)
 1639     (clear-stream $_test-error-buffered-file->buffer)
 1640     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1641     68/push 0/imm32
 1642     68/push 0/imm32
 1643     89/<- %edx 4/r32/esp
 1644     (tailor-exit-descriptor %edx 0x10)
 1645     #
 1646     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1647     (write _test-input-stream "  return 0, 0\n")
 1648     (write _test-input-stream "}\n")
 1649     # convert
 1650     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1651     # registers except esp clobbered at this point
 1652     # restore ed
 1653     89/<- %edx 4/r32/esp
 1654     (flush _test-output-buffered-file)
 1655     (flush _test-error-buffered-file)
 1656 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1662     # check output
 1663     (check-stream-equal _test-output-stream  ""  "F - test-return-with-too-many-inouts: output should be empty")
 1664     (check-next-stream-line-equal _test-error-stream  "fn foo: return: too many inouts"  "F - test-return-with-too-many-inouts: error message")
 1665     # check that stop(1) was called
 1666     (check-ints-equal *(edx+4) 2 "F - test-return-with-too-many-inouts: exit status")
 1667     # don't restore from ebp
 1668     81 0/subop/add %esp 8/imm32
 1669     # . epilogue
 1670     5d/pop-to-ebp
 1671     c3/return
 1672 
 1673 test-return-unavailable-value:
 1674     # . prologue
 1675     55/push-ebp
 1676     89/<- %ebp 4/r32/esp
 1677     # setup
 1678     (clear-stream _test-input-stream)
 1679     (clear-stream $_test-input-buffered-file->buffer)
 1680     (clear-stream _test-output-stream)
 1681     (clear-stream $_test-output-buffered-file->buffer)
 1682     (clear-stream _test-error-stream)
 1683     (clear-stream $_test-error-buffered-file->buffer)
 1684     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1685     68/push 0/imm32
 1686     68/push 0/imm32
 1687     89/<- %edx 4/r32/esp
 1688     (tailor-exit-descriptor %edx 0x10)
 1689     #
 1690     (write _test-input-stream "fn foo -> _/eax: int, _/ecx: int {\n")
 1691     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 1692     (write _test-input-stream "  var y/ecx: int <- copy 0\n")
 1693     (write _test-input-stream "  return y, x\n")
 1694     (write _test-input-stream "}\n")
 1695     # convert
 1696     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1697     # registers except esp clobbered at this point
 1698     # restore ed
 1699     89/<- %edx 4/r32/esp
 1700     (flush _test-output-buffered-file)
 1701     (flush _test-error-buffered-file)
 1702 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1708     # check output
 1709     (check-stream-equal _test-output-stream  ""  "F - test-return-unavailable-value: output should be empty")
 1710     (check-next-stream-line-equal _test-error-stream  "fn foo: return: 'x' is no longer available"  "F - test-return-unavailable-value: error message")
 1711     # check that stop(1) was called
 1712     (check-ints-equal *(edx+4) 2 "F - test-return-unavailable-value: exit status")
 1713     # don't restore from ebp
 1714     81 0/subop/add %esp 8/imm32
 1715     # . epilogue
 1716     5d/pop-to-ebp
 1717     c3/return
 1718 
 1719 test-convert-return-with-duplicate-values:
 1720     # . prologue
 1721     55/push-ebp
 1722     89/<- %ebp 4/r32/esp
 1723     # setup
 1724     (clear-stream _test-input-stream)
 1725     (clear-stream $_test-input-buffered-file->buffer)
 1726     (clear-stream _test-output-stream)
 1727     (clear-stream $_test-output-buffered-file->buffer)
 1728     #
 1729     (write _test-input-stream "fn foo -> _/eax: int, _/ecx: int {\n")
 1730     (write _test-input-stream "  var x/eax: int <- copy 0x34\n")
 1731     (write _test-input-stream "  return x, x\n")
 1732     (write _test-input-stream "}\n")
 1733     # convert
 1734     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1735     (flush _test-output-buffered-file)
 1736 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1742     # check output
 1743     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-return-with-duplicate-values/0")
 1744     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-return-with-duplicate-values/1")
 1745     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-return-with-duplicate-values/2")
 1746     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-return-with-duplicate-values/3")
 1747     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-return-with-duplicate-values/4")
 1748     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-return-with-duplicate-values/5")
 1749     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-return-with-duplicate-values/6")
 1750     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0x34/imm32"  "F - test-convert-return-with-duplicate-values/7")
 1751     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32"  "F - test-convert-return-with-duplicate-values/8")
 1752     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000001/r32"  "F - test-convert-return-with-duplicate-values/9")
 1753     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-return-with-duplicate-values/10")
 1754     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-return-with-duplicate-values/11")
 1755     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-return-with-duplicate-values/12")
 1756     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-return-with-duplicate-values/13")
 1757     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-return-with-duplicate-values/14")
 1758     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-return-with-duplicate-values/15")
 1759     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-return-with-duplicate-values/16")
 1760     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-return-with-duplicate-values/17")
 1761     # . epilogue
 1762     89/<- %esp 5/r32/ebp
 1763     5d/pop-to-ebp
 1764     c3/return
 1765 
 1766 test-convert-return-with-duplicate-values-2:
 1767     # . prologue
 1768     55/push-ebp
 1769     89/<- %ebp 4/r32/esp
 1770     # setup
 1771     (clear-stream _test-input-stream)
 1772     (clear-stream $_test-input-buffered-file->buffer)
 1773     (clear-stream _test-output-stream)
 1774     (clear-stream $_test-output-buffered-file->buffer)
 1775     #
 1776     (write _test-input-stream "fn foo -> _/eax: int, _/ecx: int {\n")
 1777     (write _test-input-stream "  var x/ecx: int <- copy 0x34\n")
 1778     (write _test-input-stream "  return x, x\n")
 1779     (write _test-input-stream "}\n")
 1780     # convert
 1781     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1782     (flush _test-output-buffered-file)
 1783 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1789     # check output
 1790     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-return-with-duplicate-values-2/0")
 1791     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-return-with-duplicate-values-2/1")
 1792     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-return-with-duplicate-values-2/2")
 1793     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-return-with-duplicate-values-2/3")
 1794     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-return-with-duplicate-values-2/4")
 1795     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-return-with-duplicate-values-2/5")
 1796     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-return-with-duplicate-values-2/6")
 1797     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0x34/imm32"  "F - test-convert-return-with-duplicate-values-2/7")
 1798     (check-next-stream-line-equal _test-output-stream "    8b/-> %ecx 0x00000000/r32"  "F - test-convert-return-with-duplicate-values-2/8")
 1799     (check-next-stream-line-equal _test-output-stream "    8b/-> %ecx 0x00000001/r32"  "F - test-convert-return-with-duplicate-values-2/9")
 1800     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-return-with-duplicate-values-2/10")
 1801     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-return-with-duplicate-values-2/11")
 1802     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-return-with-duplicate-values-2/12")
 1803     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-return-with-duplicate-values-2/13")
 1804     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-return-with-duplicate-values-2/14")
 1805     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-return-with-duplicate-values-2/15")
 1806     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-return-with-duplicate-values-2/16")
 1807     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-return-with-duplicate-values-2/17")
 1808     # . epilogue
 1809     89/<- %esp 5/r32/ebp
 1810     5d/pop-to-ebp
 1811     c3/return
 1812 
 1813 test-stmt-with-unknown-var:
 1814     # . prologue
 1815     55/push-ebp
 1816     89/<- %ebp 4/r32/esp
 1817     # setup
 1818     (clear-stream _test-input-stream)
 1819     (clear-stream $_test-input-buffered-file->buffer)
 1820     (clear-stream _test-output-stream)
 1821     (clear-stream $_test-output-buffered-file->buffer)
 1822     (clear-stream _test-error-stream)
 1823     (clear-stream $_test-error-buffered-file->buffer)
 1824     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1825     68/push 0/imm32
 1826     68/push 0/imm32
 1827     89/<- %edx 4/r32/esp
 1828     (tailor-exit-descriptor %edx 0x10)
 1829     #
 1830     (write _test-input-stream "fn foo {\n")
 1831     (write _test-input-stream "  x <- copy 0x34\n")
 1832     (write _test-input-stream "}\n")
 1833     # convert
 1834     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1835     # registers except esp clobbered at this point
 1836     # restore ed
 1837     89/<- %edx 4/r32/esp
 1838     (flush _test-output-buffered-file)
 1839     (flush _test-error-buffered-file)
 1840 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1846     # check output
 1847     (check-stream-equal _test-output-stream  ""  "F - test-stmt-with-unknown-var: output should be empty")
 1848     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-stmt-with-unknown-var: error message")
 1849     # check that stop(1) was called
 1850     (check-ints-equal *(edx+4) 2 "F - test-stmt-with-unknown-var: exit status")
 1851     # don't restore from ebp
 1852     81 0/subop/add %esp 8/imm32
 1853     # . epilogue
 1854     5d/pop-to-ebp
 1855     c3/return
 1856 
 1857 test-stmt-with-invalid-identifier:
 1858     # . prologue
 1859     55/push-ebp
 1860     89/<- %ebp 4/r32/esp
 1861     # setup
 1862     (clear-stream _test-input-stream)
 1863     (clear-stream $_test-input-buffered-file->buffer)
 1864     (clear-stream _test-output-stream)
 1865     (clear-stream $_test-output-buffered-file->buffer)
 1866     (clear-stream _test-error-stream)
 1867     (clear-stream $_test-error-buffered-file->buffer)
 1868     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1869     68/push 0/imm32
 1870     68/push 0/imm32
 1871     89/<- %edx 4/r32/esp
 1872     (tailor-exit-descriptor %edx 0x10)
 1873     #
 1874     (write _test-input-stream "fn foo {\n")
 1875     (write _test-input-stream "  1 <- copy 0x34\n")
 1876     (write _test-input-stream "}\n")
 1877     # convert
 1878     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1879     # registers except esp clobbered at this point
 1880     # restore ed
 1881     89/<- %edx 4/r32/esp
 1882     (flush _test-output-buffered-file)
 1883     (flush _test-error-buffered-file)
 1884 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1890     # check output
 1891     (check-stream-equal _test-output-stream  ""  "F - test-stmt-with-invalid-identifier: output should be empty")
 1892     (check-next-stream-line-equal _test-error-stream  "fn foo: invalid identifier '1'"  "F - test-stmt-with-invalid-identifier: error message")
 1893     # check that stop(1) was called
 1894     (check-ints-equal *(edx+4) 2 "F - test-stmt-with-invalid-identifier: exit status")
 1895     # don't restore from ebp
 1896     81 0/subop/add %esp 8/imm32
 1897     # . epilogue
 1898     5d/pop-to-ebp
 1899     c3/return
 1900 
 1901 test-stmt-with-deref-var:
 1902     # . prologue
 1903     55/push-ebp
 1904     89/<- %ebp 4/r32/esp
 1905     # setup
 1906     (clear-stream _test-input-stream)
 1907     (clear-stream $_test-input-buffered-file->buffer)
 1908     (clear-stream _test-output-stream)
 1909     (clear-stream $_test-output-buffered-file->buffer)
 1910     (clear-stream _test-error-stream)
 1911     (clear-stream $_test-error-buffered-file->buffer)
 1912     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1913     68/push 0/imm32
 1914     68/push 0/imm32
 1915     89/<- %edx 4/r32/esp
 1916     (tailor-exit-descriptor %edx 0x10)
 1917     #
 1918     (write _test-input-stream "fn foo {\n")
 1919     (write _test-input-stream "  *x <- copy 0x34\n")
 1920     (write _test-input-stream "}\n")
 1921     # convert
 1922     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1923     # registers except esp clobbered at this point
 1924     # restore ed
 1925     89/<- %edx 4/r32/esp
 1926     (flush _test-output-buffered-file)
 1927     (flush _test-error-buffered-file)
 1928 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1934     # check output
 1935     (check-stream-equal _test-output-stream  ""  "F - test-stmt-with-deref-var: output should be empty")
 1936     (check-next-stream-line-equal _test-error-stream  "fn foo: output '*x' should write to a register, and therefore cannot be dereferenced"  "F - test-stmt-with-deref-var: error message")
 1937     # check that stop(1) was called
 1938     (check-ints-equal *(edx+4) 2 "F - test-stmt-with-deref-var: exit status")
 1939     # don't restore from ebp
 1940     81 0/subop/add %esp 8/imm32
 1941     # . epilogue
 1942     5d/pop-to-ebp
 1943     c3/return
 1944 
 1945 test-convert-function-with-literal-arg:
 1946     # . prologue
 1947     55/push-ebp
 1948     89/<- %ebp 4/r32/esp
 1949     # setup
 1950     (clear-stream _test-input-stream)
 1951     (clear-stream $_test-input-buffered-file->buffer)
 1952     (clear-stream _test-output-stream)
 1953     (clear-stream $_test-output-buffered-file->buffer)
 1954     #
 1955     (write _test-input-stream "fn foo a: int, b: int -> _/eax: int {\n")
 1956     (write _test-input-stream "  var result/eax: int <- copy a\n")
 1957     (write _test-input-stream "  result <- add 1\n")
 1958     (write _test-input-stream "  return result\n")
 1959     (write _test-input-stream "}\n")
 1960     # convert
 1961     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1962     (flush _test-output-buffered-file)
 1963 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1969     # check output
 1970     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-literal-arg/0")
 1971     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-literal-arg/1")
 1972     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-literal-arg/2")
 1973     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-literal-arg/3")
 1974     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-literal-arg/4")
 1975     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-literal-arg/5")
 1976     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-literal-arg/6")
 1977     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-with-literal-arg/7")
 1978     (check-next-stream-line-equal _test-output-stream "    05/add-to-eax 1/imm32"  "F - test-convert-function-with-literal-arg/8")
 1979     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-literal-arg/9")
 1980     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-literal-arg/10")
 1981     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-literal-arg/11")
 1982     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-literal-arg/12")
 1983     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-literal-arg/13")
 1984     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-literal-arg/14")
 1985     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-literal-arg/15")
 1986     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-literal-arg/16")
 1987     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-literal-arg/17")
 1988     # . epilogue
 1989     89/<- %esp 5/r32/ebp
 1990     5d/pop-to-ebp
 1991     c3/return
 1992 
 1993 test-convert-function-with-literal-arg-2:
 1994     # . prologue
 1995     55/push-ebp
 1996     89/<- %ebp 4/r32/esp
 1997     # setup
 1998     (clear-stream _test-input-stream)
 1999     (clear-stream $_test-input-buffered-file->buffer)
 2000     (clear-stream _test-output-stream)
 2001     (clear-stream $_test-output-buffered-file->buffer)
 2002     #
 2003     (write _test-input-stream "fn foo a: int, b: int -> _/ebx: int {\n")
 2004     (write _test-input-stream "  var result/ebx: int <- copy a\n")
 2005     (write _test-input-stream "  result <- add 1\n")
 2006     (write _test-input-stream "  return result\n")
 2007     (write _test-input-stream "}\n")
 2008     # convert
 2009     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2010     (flush _test-output-buffered-file)
 2011 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2017     # check output
 2018     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-literal-arg-2/0")
 2019     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-literal-arg-2/1")
 2020     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-literal-arg-2/2")
 2021     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-literal-arg-2/3")
 2022     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-literal-arg-2/4")
 2023     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-literal-arg-2/5")
 2024     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-with-literal-arg-2/6")
 2025     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000003/r32"  "F - test-convert-function-with-literal-arg-2/7")
 2026     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %ebx 1/imm32"  "F - test-convert-function-with-literal-arg-2/8")
 2027     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-with-literal-arg-2/9")
 2028     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-literal-arg-2/10")
 2029     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-literal-arg-2/11")
 2030     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-literal-arg-2/12")
 2031     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-literal-arg-2/13")
 2032     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-literal-arg-2/14")
 2033     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-literal-arg-2/15")
 2034     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-literal-arg-2/16")
 2035     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-literal-arg-2/17")
 2036     # . epilogue
 2037     89/<- %esp 5/r32/ebp
 2038     5d/pop-to-ebp
 2039     c3/return
 2040 
 2041 test-convert-function-call-with-literal-arg:
 2042     # . prologue
 2043     55/push-ebp
 2044     89/<- %ebp 4/r32/esp
 2045     # setup
 2046     (clear-stream _test-input-stream)
 2047     (clear-stream $_test-input-buffered-file->buffer)
 2048     (clear-stream _test-output-stream)
 2049     (clear-stream $_test-output-buffered-file->buffer)
 2050     #
 2051     (write _test-input-stream "fn main -> _/ebx: int {\n")
 2052     (write _test-input-stream "  var result/eax: int <- do-add 3 4\n")
 2053     (write _test-input-stream "  return result\n")
 2054     (write _test-input-stream "}\n")
 2055     (write _test-input-stream "fn do-add a: int, b: int -> _/eax: int {\n")
 2056     (write _test-input-stream "  var result/eax: int <- copy a\n")
 2057     (write _test-input-stream "  result <- add b\n")
 2058     (write _test-input-stream "  return result\n")
 2059     (write _test-input-stream "}\n")
 2060     # convert
 2061     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2062     (flush _test-output-buffered-file)
 2063 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2069     # check output
 2070     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call-with-literal-arg/0")
 2071     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-literal-arg/1")
 2072     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-literal-arg/2")
 2073     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-literal-arg/3")
 2074     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-literal-arg/4")
 2075     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call-with-literal-arg/5")
 2076     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/6")
 2077     (check-next-stream-line-equal _test-output-stream "    (do-add 3 4)"        "F - test-convert-function-call-with-literal-arg/7")
 2078     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 2079     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-with-local-var-in-reg/9")
 2080     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 2081     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-literal-arg/11")
 2082     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call-with-literal-arg/12")
 2083     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-literal-arg/13")
 2084     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-literal-arg/14")
 2085     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-literal-arg/15")
 2086     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-literal-arg/16")
 2087     (check-next-stream-line-equal _test-output-stream "do-add:"                 "F - test-convert-function-call-with-literal-arg/17")
 2088     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-literal-arg/18")
 2089     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-literal-arg/19")
 2090     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-literal-arg/20")
 2091     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-literal-arg/21")
 2092     (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:loop:"  "F - test-convert-function-call-with-literal-arg/22")
 2093     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/23")
 2094     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-call-with-literal-arg/24")
 2095     (check-next-stream-line-equal _test-output-stream "    03/add *(ebp+0x0000000c) 0x00000000/r32"  "F - test-convert-function-call-with-literal-arg/25")
 2096     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-call-with-literal-arg/26")
 2097     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
 2098     (check-next-stream-line-equal _test-output-stream "    e9/jump $do-add:0x00000002:break/disp32"  "F - test-convert-function-call-with-literal-arg/28")
 2099     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-literal-arg/29")
 2100     (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:break:"  "F - test-convert-function-call-with-literal-arg/30")
 2101     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-literal-arg/31")
 2102     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-literal-arg/32")
 2103     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-literal-arg/33")
 2104     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-literal-arg/34")
 2105     # . epilogue
 2106     89/<- %esp 5/r32/ebp
 2107     5d/pop-to-ebp
 2108     c3/return
 2109 
 2110 test-convert-function-call-with-literal-string-arg:
 2111     # . prologue
 2112     55/push-ebp
 2113     89/<- %ebp 4/r32/esp
 2114     # setup
 2115     (clear-stream _test-input-stream)
 2116     (clear-stream $_test-input-buffered-file->buffer)
 2117     (clear-stream _test-output-stream)
 2118     (clear-stream $_test-output-buffered-file->buffer)
 2119     #
 2120     (write _test-input-stream "fn foo {\n")
 2121     (write _test-input-stream "  string-func \"abc\"\n")
 2122     (write _test-input-stream "}\n")
 2123     (write _test-input-stream "sig string-func in: (addr array byte)\n")
 2124     # convert
 2125     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2126     # no errors
 2127     # not bothering checking output
 2128     # . epilogue
 2129     89/<- %esp 5/r32/ebp
 2130     5d/pop-to-ebp
 2131     c3/return
 2132 
 2133 test-convert-function-call-with-null-addr:
 2134     # . prologue
 2135     55/push-ebp
 2136     89/<- %ebp 4/r32/esp
 2137     # setup
 2138     (clear-stream _test-input-stream)
 2139     (clear-stream $_test-input-buffered-file->buffer)
 2140     (clear-stream _test-output-stream)
 2141     (clear-stream $_test-output-buffered-file->buffer)
 2142     #
 2143     (write _test-input-stream "fn foo {\n")
 2144     (write _test-input-stream "  bar 0\n")
 2145     (write _test-input-stream "}\n")
 2146     (write _test-input-stream "sig bar in: (addr int)\n")
 2147     # convert
 2148     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2149     # no errors
 2150     # not bothering checking output
 2151     # . epilogue
 2152     89/<- %esp 5/r32/ebp
 2153     5d/pop-to-ebp
 2154     c3/return
 2155 
 2156 test-convert-function-call-with-signature:
 2157     # . prologue
 2158     55/push-ebp
 2159     89/<- %ebp 4/r32/esp
 2160     # setup
 2161     (clear-stream _test-input-stream)
 2162     (clear-stream $_test-input-buffered-file->buffer)
 2163     (clear-stream _test-output-stream)
 2164     (clear-stream $_test-output-buffered-file->buffer)
 2165     #
 2166     (write _test-input-stream "fn main -> _/ebx: int {\n")
 2167     (write _test-input-stream "  var result/eax: int <- do-add 3 4\n")
 2168     (write _test-input-stream "  return result\n")
 2169     (write _test-input-stream "}\n")
 2170     (write _test-input-stream "sig do-add a: int, b: int -> _/eax: int\n")
 2171     # convert
 2172     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2173     (flush _test-output-buffered-file)
 2174 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2180     # check output
 2181     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call-with-signature/0")
 2182     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-signature/1")
 2183     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-signature/2")
 2184     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-signature/3")
 2185     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-signature/4")
 2186     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call-with-signature/5")
 2187     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/6")
 2188     (check-next-stream-line-equal _test-output-stream "    (do-add 3 4)"        "F - test-convert-function-call-with-signature/6")
 2189     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 2190     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-with-local-var-in-reg/9")
 2191     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 2192     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-signature/7")
 2193     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call-with-signature/8")
 2194     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-signature/9")
 2195     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-signature/10")
 2196     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-signature/11")
 2197     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-signature/12")
 2198     # . epilogue
 2199     89/<- %esp 5/r32/ebp
 2200     5d/pop-to-ebp
 2201     c3/return
 2202 
 2203 test-convert-function-with-local-var-in-mem:
 2204     # . prologue
 2205     55/push-ebp
 2206     89/<- %ebp 4/r32/esp
 2207     # setup
 2208     (clear-stream _test-input-stream)
 2209     (clear-stream $_test-input-buffered-file->buffer)
 2210     (clear-stream _test-output-stream)
 2211     (clear-stream $_test-output-buffered-file->buffer)
 2212     #
 2213     (write _test-input-stream "fn foo {\n")
 2214     (write _test-input-stream "  var x: int\n")
 2215     (write _test-input-stream "  increment x\n")
 2216     (write _test-input-stream "}\n")
 2217     # convert
 2218     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2219     (flush _test-output-buffered-file)
 2220 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2226     # check output
 2227     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-mem/0")
 2228     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-mem/1")
 2229     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-mem/2")
 2230     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-mem/3")
 2231     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-mem/4")
 2232     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-mem/5")
 2233     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-in-mem/6")
 2234     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-local-var-in-mem/7")
 2235     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-local-var-in-mem/8")
 2236     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-mem/9")
 2237     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-mem/10")
 2238     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-mem/11")
 2239     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-mem/12")
 2240     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-mem/13")
 2241     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-mem/14")
 2242     # . epilogue
 2243     89/<- %esp 5/r32/ebp
 2244     5d/pop-to-ebp
 2245     c3/return
 2246 
 2247 test-convert-invalid-literal:
 2248     # . prologue
 2249     55/push-ebp
 2250     89/<- %ebp 4/r32/esp
 2251     # setup
 2252     (clear-stream _test-input-stream)
 2253     (clear-stream $_test-input-buffered-file->buffer)
 2254     (clear-stream _test-output-stream)
 2255     (clear-stream $_test-output-buffered-file->buffer)
 2256     (clear-stream _test-error-stream)
 2257     (clear-stream $_test-error-buffered-file->buffer)
 2258     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2259     68/push 0/imm32
 2260     68/push 0/imm32
 2261     89/<- %edx 4/r32/esp
 2262     (tailor-exit-descriptor %edx 0x10)
 2263     #
 2264     (write _test-input-stream "fn foo {\n")
 2265     (write _test-input-stream "  increment 1n\n")
 2266     (write _test-input-stream "}\n")
 2267     # convert
 2268     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2269     # registers except esp clobbered at this point
 2270     # restore ed
 2271     89/<- %edx 4/r32/esp
 2272     (flush _test-output-buffered-file)
 2273     (flush _test-error-buffered-file)
 2274 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2280     # check output
 2281     (check-stream-equal _test-output-stream  ""  "F - test-convert-invalid-literal: output should be empty")
 2282     (check-next-stream-line-equal _test-error-stream  "fn foo: variable '1n' cannot begin with a digit (or do you have a typo in a number?)"  "F - test-convert-invalid-literal: error message")
 2283     # check that stop(1) was called
 2284     (check-ints-equal *(edx+4) 2 "F - test-convert-invalid-literal: exit status")
 2285     # don't restore from ebp
 2286     81 0/subop/add %esp 8/imm32
 2287     # . epilogue
 2288     5d/pop-to-ebp
 2289     c3/return
 2290 
 2291 test-local-var-in-mem-has-no-initializer:
 2292     # . prologue
 2293     55/push-ebp
 2294     89/<- %ebp 4/r32/esp
 2295     # setup
 2296     (clear-stream _test-input-stream)
 2297     (clear-stream $_test-input-buffered-file->buffer)
 2298     (clear-stream _test-output-stream)
 2299     (clear-stream $_test-output-buffered-file->buffer)
 2300     (clear-stream _test-error-stream)
 2301     (clear-stream $_test-error-buffered-file->buffer)
 2302     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2303     68/push 0/imm32
 2304     68/push 0/imm32
 2305     89/<- %edx 4/r32/esp
 2306     (tailor-exit-descriptor %edx 0x10)
 2307     #
 2308     (write _test-input-stream "fn foo {\n")
 2309     (write _test-input-stream "  var x: int <- copy 0\n")
 2310     (write _test-input-stream "  increment x\n")
 2311     (write _test-input-stream "}\n")
 2312     # convert
 2313     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2314     # registers except esp clobbered at this point
 2315     # restore ed
 2316     89/<- %edx 4/r32/esp
 2317     (flush _test-output-buffered-file)
 2318     (flush _test-error-buffered-file)
 2319 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2325     # check output
 2326     (check-stream-equal _test-output-stream  ""  "F - test-var-in-mem-has-no-initializer: output should be empty")
 2327     (check-next-stream-line-equal _test-error-stream  "fn foo: var x: variables on the stack can't take an initializer"  "F - test-var-in-mem-has-no-initializer: error message")
 2328     # check that stop(1) was called
 2329     (check-ints-equal *(edx+4) 2 "F - test-var-in-mem-has-no-initializer: exit status")
 2330     # don't restore from ebp
 2331     81 0/subop/add %esp 8/imm32
 2332     # . epilogue
 2333     5d/pop-to-ebp
 2334     c3/return
 2335 
 2336 test-convert-function-with-local-var-with-compound-type-in-mem:
 2337     # . prologue
 2338     55/push-ebp
 2339     89/<- %ebp 4/r32/esp
 2340     # setup
 2341     (clear-stream _test-input-stream)
 2342     (clear-stream $_test-input-buffered-file->buffer)
 2343     (clear-stream _test-output-stream)
 2344     (clear-stream $_test-output-buffered-file->buffer)
 2345     #
 2346     (write _test-input-stream "fn foo {\n")
 2347     (write _test-input-stream "  var x: (addr int)\n")
 2348     (write _test-input-stream "  copy-to x, 0\n")
 2349     (write _test-input-stream "}\n")
 2350     # convert
 2351     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2352     (flush _test-output-buffered-file)
 2353 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2359     # check output
 2360     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-with-compound-type-in-mem/0")
 2361     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-with-compound-type-in-mem/1")
 2362     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-with-compound-type-in-mem/2")
 2363     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-with-compound-type-in-mem/3")
 2364     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-compound-type-in-mem/4")
 2365     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-with-compound-type-in-mem/5")
 2366     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-compound-type-in-mem/6")
 2367     (check-next-stream-line-equal _test-output-stream "    c7 0/subop/copy *(ebp+0xfffffffc) 0/imm32"  "F - test-convert-function-with-local-var-with-compound-type-in-mem/7")
 2368     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-local-var-with-compound-type-in-mem/8")
 2369     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-compound-type-in-mem/9")
 2370     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-with-compound-type-in-mem/10")
 2371     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-with-compound-type-in-mem/11")
 2372     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-with-compound-type-in-mem/12")
 2373     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-with-compound-type-in-mem/13")
 2374     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-with-compound-type-in-mem/14")
 2375     # . epilogue
 2376     89/<- %esp 5/r32/ebp
 2377     5d/pop-to-ebp
 2378     c3/return
 2379 
 2380 test-convert-function-with-local-var-in-reg:
 2381     # . prologue
 2382     55/push-ebp
 2383     89/<- %ebp 4/r32/esp
 2384     # setup
 2385     (clear-stream _test-input-stream)
 2386     (clear-stream $_test-input-buffered-file->buffer)
 2387     (clear-stream _test-output-stream)
 2388     (clear-stream $_test-output-buffered-file->buffer)
 2389     #
 2390     (write _test-input-stream "fn foo {\n")
 2391     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2392     (write _test-input-stream "  x <- increment\n")
 2393     (write _test-input-stream "}\n")
 2394     # convert
 2395     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2396     (flush _test-output-buffered-file)
 2397 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2403     # check output
 2404     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-reg/0")
 2405     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-reg/1")
 2406     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-reg/2")
 2407     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-reg/3")
 2408     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-reg/4")
 2409     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-reg/5")
 2410     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-in-reg/6")
 2411     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-convert-function-with-local-var-in-reg/7")
 2412     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-convert-function-with-local-var-in-reg/8")
 2413     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-in-reg/9")
 2414     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-reg/10")
 2415     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-reg/11")
 2416     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-reg/12")
 2417     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-reg/13")
 2418     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-reg/14")
 2419     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-reg/15")
 2420     # . epilogue
 2421     89/<- %esp 5/r32/ebp
 2422     5d/pop-to-ebp
 2423     c3/return
 2424 
 2425 test-float-var-in-wrong-register:
 2426     # . prologue
 2427     55/push-ebp
 2428     89/<- %ebp 4/r32/esp
 2429     # setup
 2430     (clear-stream _test-input-stream)
 2431     (clear-stream $_test-input-buffered-file->buffer)
 2432     (clear-stream _test-output-stream)
 2433     (clear-stream $_test-output-buffered-file->buffer)
 2434     (clear-stream _test-error-stream)
 2435     (clear-stream $_test-error-buffered-file->buffer)
 2436     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2437     68/push 0/imm32
 2438     68/push 0/imm32
 2439     89/<- %edx 4/r32/esp
 2440     (tailor-exit-descriptor %edx 0x10)
 2441     #
 2442     (write _test-input-stream "fn foo {\n")
 2443     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 2444     (write _test-input-stream "  var y/eax: float <- convert x\n")
 2445     (write _test-input-stream "}\n")
 2446     # convert
 2447     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2448     # registers except esp clobbered at this point
 2449     # restore ed
 2450     89/<- %edx 4/r32/esp
 2451     (flush _test-output-buffered-file)
 2452     (flush _test-error-buffered-file)
 2453 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2459     # check output
 2460     (check-stream-equal _test-output-stream  ""  "F - test-float-var-in-wrong-register: output should be empty")
 2461     (check-next-stream-line-equal _test-error-stream  "fn foo: float var 'y' should be in a floating-point register"  "F - test-float-var-in-wrong-register: error message")
 2462     # check that stop(1) was called
 2463     (check-ints-equal *(edx+4) 2 "F - test-float-var-in-wrong-register: exit status")
 2464     # don't restore from ebp
 2465     81 0/subop/add %esp 8/imm32
 2466     # . epilogue
 2467     5d/pop-to-ebp
 2468     c3/return
 2469 
 2470 test-non-float-var-in-wrong-register:
 2471     # . prologue
 2472     55/push-ebp
 2473     89/<- %ebp 4/r32/esp
 2474     # setup
 2475     (clear-stream _test-input-stream)
 2476     (clear-stream $_test-input-buffered-file->buffer)
 2477     (clear-stream _test-output-stream)
 2478     (clear-stream $_test-output-buffered-file->buffer)
 2479     (clear-stream _test-error-stream)
 2480     (clear-stream $_test-error-buffered-file->buffer)
 2481     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2482     68/push 0/imm32
 2483     68/push 0/imm32
 2484     89/<- %edx 4/r32/esp
 2485     (tailor-exit-descriptor %edx 0x10)
 2486     #
 2487     (write _test-input-stream "fn foo {\n")
 2488     (write _test-input-stream "  var x/xmm5: int <- copy 0\n")
 2489     (write _test-input-stream "}\n")
 2490     # convert
 2491     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2492     # registers except esp clobbered at this point
 2493     # restore ed
 2494     89/<- %edx 4/r32/esp
 2495     (flush _test-output-buffered-file)
 2496     (flush _test-error-buffered-file)
 2497 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2503     # check output
 2504     (check-stream-equal _test-output-stream  ""  "F - test-non-float-var-in-wrong-register: output should be empty")
 2505     (check-next-stream-line-equal _test-error-stream  "fn foo: non-float var 'x' should be in an integer register"  "F - test-non-float-var-in-wrong-register: error message")
 2506     # check that stop(1) was called
 2507     (check-ints-equal *(edx+4) 2 "F - test-non-float-var-in-wrong-register: exit status")
 2508     # don't restore from ebp
 2509     81 0/subop/add %esp 8/imm32
 2510     # . epilogue
 2511     5d/pop-to-ebp
 2512     c3/return
 2513 
 2514 test-convert-function-with-allocate:
 2515     # . prologue
 2516     55/push-ebp
 2517     89/<- %ebp 4/r32/esp
 2518     # setup
 2519     (clear-stream _test-input-stream)
 2520     (clear-stream $_test-input-buffered-file->buffer)
 2521     (clear-stream _test-output-stream)
 2522     (clear-stream $_test-output-buffered-file->buffer)
 2523     #
 2524     (write _test-input-stream "fn foo {\n")
 2525     (write _test-input-stream "  var x/ecx: (addr handle int) <- copy 0\n")
 2526     (write _test-input-stream "  allocate x\n")
 2527     (write _test-input-stream "}\n")
 2528     # convert
 2529     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2530     (flush _test-output-buffered-file)
 2531 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2537     # check output
 2538     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-allocate/0")
 2539     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-allocate/1")
 2540     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-allocate/2")
 2541     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-allocate/3")
 2542     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-allocate/4")
 2543     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-allocate/5")
 2544     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-allocate/6")
 2545     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-allocate/7")
 2546     (check-next-stream-line-equal _test-output-stream "    (allocate Heap 0x00000004 %ecx)"  "F - test-convert-function-with-allocate/8")  # 4 = size-of(int)
 2547     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-allocate/9")
 2548     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-allocate/10")
 2549     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-allocate/11")
 2550     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-allocate/12")
 2551     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-allocate/13")
 2552     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-allocate/14")
 2553     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-allocate/15")
 2554     # . epilogue
 2555     89/<- %esp 5/r32/ebp
 2556     5d/pop-to-ebp
 2557     c3/return
 2558 
 2559 test-initializer-in-hex:
 2560     # . prologue
 2561     55/push-ebp
 2562     89/<- %ebp 4/r32/esp
 2563     # setup
 2564     (clear-stream _test-input-stream)
 2565     (clear-stream $_test-input-buffered-file->buffer)
 2566     (clear-stream _test-output-stream)
 2567     (clear-stream $_test-output-buffered-file->buffer)
 2568     (clear-stream _test-error-stream)
 2569     (clear-stream $_test-error-buffered-file->buffer)
 2570     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2571     68/push 0/imm32
 2572     68/push 0/imm32
 2573     89/<- %edx 4/r32/esp
 2574     (tailor-exit-descriptor %edx 0x10)
 2575     #
 2576     (write _test-input-stream "fn foo {\n")
 2577     (write _test-input-stream "  var x/ecx: int <- copy 10\n")
 2578     (write _test-input-stream "}\n")
 2579     # convert
 2580     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2581     # registers except esp clobbered at this point
 2582     # restore ed
 2583     89/<- %edx 4/r32/esp
 2584     (flush _test-output-buffered-file)
 2585     (flush _test-error-buffered-file)
 2586 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2592     # check output
 2593     (check-stream-equal _test-output-stream  ""  "F - test-initializer-in-hex: output should be empty")
 2594     (check-next-stream-line-equal _test-error-stream  "literal integers are always hex in Mu; start '10' with a '0x' to be unambiguous, converting it to hexadecimal as necessary."  "F - test-initializer-in-hex: error message")
 2595     # check that stop(1) was called
 2596     (check-ints-equal *(edx+4) 2 "F - test-initializer-in-hex: exit status")
 2597     # don't restore from ebp
 2598     81 0/subop/add %esp 8/imm32
 2599     # . epilogue
 2600     5d/pop-to-ebp
 2601     c3/return
 2602 
 2603 test-convert-function-with-second-local-var-in-same-reg:
 2604     # . prologue
 2605     55/push-ebp
 2606     89/<- %ebp 4/r32/esp
 2607     # setup
 2608     (clear-stream _test-input-stream)
 2609     (clear-stream $_test-input-buffered-file->buffer)
 2610     (clear-stream _test-output-stream)
 2611     (clear-stream $_test-output-buffered-file->buffer)
 2612     #
 2613     (write _test-input-stream "fn foo {\n")
 2614     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2615     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 2616     (write _test-input-stream "  y <- increment\n")
 2617     (write _test-input-stream "}\n")
 2618     # convert
 2619     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2620     (flush _test-output-buffered-file)
 2621 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2627     # check output
 2628     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-second-local-var-in-same-reg/0")
 2629     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-second-local-var-in-same-reg/1")
 2630     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-second-local-var-in-same-reg/2")
 2631     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-second-local-var-in-same-reg/3")
 2632     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-second-local-var-in-same-reg/4")
 2633     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-second-local-var-in-same-reg/5")
 2634     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-second-local-var-in-same-reg/6")
 2635     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-convert-function-with-second-local-var-in-same-reg/7")
 2636     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-convert-function-with-second-local-var-in-same-reg/8")
 2637     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-convert-function-with-second-local-var-in-same-reg/9")
 2638     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-second-local-var-in-same-reg/10")
 2639     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-second-local-var-in-same-reg/11")
 2640     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-second-local-var-in-same-reg/12")
 2641     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-second-local-var-in-same-reg/13")
 2642     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-second-local-var-in-same-reg/14")
 2643     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-second-local-var-in-same-reg/15")
 2644     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-second-local-var-in-same-reg/16")
 2645     # . epilogue
 2646     89/<- %esp 5/r32/ebp
 2647     5d/pop-to-ebp
 2648     c3/return
 2649 
 2650 test-read-clobbered-reg-var:
 2651     # . prologue
 2652     55/push-ebp
 2653     89/<- %ebp 4/r32/esp
 2654     # setup
 2655     (clear-stream _test-input-stream)
 2656     (clear-stream $_test-input-buffered-file->buffer)
 2657     (clear-stream _test-output-stream)
 2658     (clear-stream $_test-output-buffered-file->buffer)
 2659     (clear-stream _test-error-stream)
 2660     (clear-stream $_test-error-buffered-file->buffer)
 2661     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
 2662     68/push 0/imm32
 2663     68/push 0/imm32
 2664     89/<- %edx 4/r32/esp
 2665     (tailor-exit-descriptor %edx 0x10)
 2666     #
 2667     (write _test-input-stream "fn foo {\n")
 2668     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2669     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 2670     (write _test-input-stream "  x <- increment\n")
 2671     (write _test-input-stream "}\n")
 2672     # convert
 2673     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2674     # registers except esp clobbered at this point
 2675     # restore ed
 2676     89/<- %edx 4/r32/esp
 2677     (flush _test-output-buffered-file)
 2678     (flush _test-error-buffered-file)
 2679 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2685     # check output
 2686     (check-stream-equal _test-output-stream  ""  "F - test-read-clobbered-reg-var: output should be empty")
 2687     (check-next-stream-line-equal _test-error-stream  "fn foo: register ecx reads var 'x' after writing var 'y'"  "F - test-read-clobbered-reg-var: error message")
 2688     # check that stop(1) was called
 2689     (check-ints-equal *(edx+4) 2 "F - test-read-clobbered-reg-var: exit status")
 2690     # don't restore from ebp
 2691     81 0/subop/add %esp 8/imm32
 2692     # . epilogue
 2693     5d/pop-to-ebp
 2694     c3/return
 2695 
 2696 test-overlapping-int-fp-registers:
 2697     # . prologue
 2698     55/push-ebp
 2699     89/<- %ebp 4/r32/esp
 2700     # setup
 2701     (clear-stream _test-input-stream)
 2702     (clear-stream $_test-input-buffered-file->buffer)
 2703     (clear-stream _test-output-stream)
 2704     (clear-stream $_test-output-buffered-file->buffer)
 2705     (clear-stream _test-error-stream)
 2706     (clear-stream $_test-error-buffered-file->buffer)
 2707     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
 2708     68/push 0/imm32
 2709     68/push 0/imm32
 2710     89/<- %edx 4/r32/esp
 2711     (tailor-exit-descriptor %edx 0x10)
 2712     #
 2713     (write _test-input-stream "fn foo {\n")
 2714     (write _test-input-stream "  var x/eax: int <- copy 3\n")
 2715     (write _test-input-stream "  var y/xmm0: float <- convert x\n")
 2716     (write _test-input-stream "  x <- increment\n")
 2717     (write _test-input-stream "}\n")
 2718     # convert
 2719     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2720     # registers except esp clobbered at this point
 2721     # restore ed
 2722     89/<- %edx 4/r32/esp
 2723     (flush _test-output-buffered-file)
 2724     (flush _test-error-buffered-file)
 2725 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2731     # no errors
 2732     (check-next-stream-line-equal _test-error-stream  ""  "F - test-overlapping-int-fp-registers: error message")
 2733     # don't bother checking the generated code
 2734     # don't restore from ebp
 2735     81 0/subop/add %esp 8/imm32
 2736     # . epilogue
 2737     5d/pop-to-ebp
 2738     c3/return
 2739 
 2740 test-convert-function-call:
 2741     # . prologue
 2742     55/push-ebp
 2743     89/<- %ebp 4/r32/esp
 2744     # setup
 2745     (clear-stream _test-input-stream)
 2746     (clear-stream $_test-input-buffered-file->buffer)
 2747     (clear-stream _test-output-stream)
 2748     (clear-stream $_test-output-buffered-file->buffer)
 2749     #
 2750     (write _test-input-stream "fn main -> _/ebx: int {\n")
 2751     (write _test-input-stream "  var result/ebx: int <- foo\n")
 2752     (write _test-input-stream "  return result\n")
 2753     (write _test-input-stream "}\n")
 2754     (write _test-input-stream "fn foo -> _/ebx: int {\n")
 2755     (write _test-input-stream "  var result/ebx: int <- copy 3\n")
 2756     (write _test-input-stream "  return result\n")
 2757     (write _test-input-stream "}\n")
 2758     # convert
 2759     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2760     (flush _test-output-buffered-file)
 2761 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2767     # check output
 2768     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call/0")
 2769     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call/1")
 2770     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call/2")
 2771     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call/3")
 2772     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call/4")
 2773     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call/5")
 2774     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-call-with-literal-arg/6")
 2775     (check-next-stream-line-equal _test-output-stream "    (foo)"               "F - test-convert-function-call/6")
 2776     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 2777     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
 2778     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 2779     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call/7")
 2780     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call/8")
 2781     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call/9")
 2782     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call/10")
 2783     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call/11")
 2784     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call/12")
 2785     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call/13")
 2786     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call/14")
 2787     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call/15")
 2788     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call/16")
 2789     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call/17")
 2790     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"  "F - test-convert-function-call/18")
 2791     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-call-with-literal-arg/6")
 2792     (check-next-stream-line-equal _test-output-stream "    bb/copy-to-ebx 3/imm32"  "F - test-convert-function-call/19")
 2793     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 2794     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
 2795     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 2796     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call/20")
 2797     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-call/21")
 2798     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call/22")
 2799     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call/23")
 2800     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call/24")
 2801     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call/25")
 2802     # . epilogue
 2803     89/<- %esp 5/r32/ebp
 2804     5d/pop-to-ebp
 2805     c3/return
 2806 
 2807 test-convert-function-call-with-inout-with-compound-type:
 2808     # . prologue
 2809     55/push-ebp
 2810     89/<- %ebp 4/r32/esp
 2811     # setup
 2812     (clear-stream _test-input-stream)
 2813     (clear-stream $_test-input-buffered-file->buffer)
 2814     (clear-stream _test-output-stream)
 2815     (clear-stream $_test-output-buffered-file->buffer)
 2816     #
 2817     (write _test-input-stream "fn f {\n")
 2818     (write _test-input-stream "  var x: (addr int)\n")
 2819     (write _test-input-stream "  g x\n")
 2820     (write _test-input-stream "}\n")
 2821     (write _test-input-stream "fn g a: (addr int) {\n")
 2822     (write _test-input-stream "}\n")
 2823     # convert
 2824     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2825     (flush _test-output-buffered-file)
 2826 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2832     # check output
 2833     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-inout-with-compound-type/0")
 2834     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-inout-with-compound-type/1")
 2835     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-inout-with-compound-type/2")
 2836     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-inout-with-compound-type/3")
 2837     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-inout-with-compound-type/4")
 2838     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-inout-with-compound-type/5")
 2839     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-inout-with-compound-type/6")
 2840     (check-next-stream-line-equal _test-output-stream "    (g *(ebp+0xfffffffc))"  "F - test-convert-function-call-with-inout-with-compound-type/7")
 2841     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-call-with-inout-with-compound-type/8")
 2842     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-inout-with-compound-type/9")
 2843     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-inout-with-compound-type/10")
 2844     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-inout-with-compound-type/11")
 2845     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-inout-with-compound-type/12")
 2846     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-inout-with-compound-type/13")
 2847     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-inout-with-compound-type/14")
 2848     (check-next-stream-line-equal _test-output-stream "g:"                      "F - test-convert-function-call-with-inout-with-compound-type/15")
 2849     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-inout-with-compound-type/16")
 2850     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-inout-with-compound-type/17")
 2851     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-inout-with-compound-type/18")
 2852     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-inout-with-compound-type/19")
 2853     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-inout-with-compound-type/20")
 2854     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-inout-with-compound-type/21")
 2855     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-inout-with-compound-type/22")
 2856     # . epilogue
 2857     89/<- %esp 5/r32/ebp
 2858     5d/pop-to-ebp
 2859     c3/return
 2860 
 2861 test-convert-function-call-with-inout-with-type-parameter:
 2862     # . prologue
 2863     55/push-ebp
 2864     89/<- %ebp 4/r32/esp
 2865     # setup
 2866     (clear-stream _test-input-stream)
 2867     (clear-stream $_test-input-buffered-file->buffer)
 2868     (clear-stream _test-output-stream)
 2869     (clear-stream $_test-output-buffered-file->buffer)
 2870     (clear-stream _test-error-stream)
 2871     (clear-stream $_test-error-buffered-file->buffer)
 2872     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2873     68/push 0/imm32
 2874     68/push 0/imm32
 2875     89/<- %edx 4/r32/esp
 2876     (tailor-exit-descriptor %edx 0x10)
 2877     #
 2878     (write _test-input-stream "fn f {\n")
 2879     (write _test-input-stream "  var x: (addr int)\n")
 2880     (write _test-input-stream "  g x\n")
 2881     (write _test-input-stream "}\n")
 2882     (write _test-input-stream "fn g a: (addr _) {\n")
 2883     (write _test-input-stream "}\n")
 2884     # convert
 2885     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2886     # registers except esp clobbered at this point
 2887     # restore ed
 2888     89/<- %edx 4/r32/esp
 2889     (flush _test-output-buffered-file)
 2890     (flush _test-error-buffered-file)
 2891 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2897     # no error; types matched
 2898     (check-stream-equal _test-error-stream  ""  "F - test-convert-function-call-with-inout-with-type-parameter: error stream should be empty")
 2899     # don't bother checking the generated code; that's in the test 'test-local-clobbered-by-fn-output' below
 2900     # don't restore from ebp
 2901     81 0/subop/add %esp 8/imm32
 2902     # . epilogue
 2903     5d/pop-to-ebp
 2904     c3/return
 2905 
 2906 test-convert-function-call-with-incorrect-inout-type:
 2907     # . prologue
 2908     55/push-ebp
 2909     89/<- %ebp 4/r32/esp
 2910     # setup
 2911     (clear-stream _test-input-stream)
 2912     (clear-stream $_test-input-buffered-file->buffer)
 2913     (clear-stream _test-output-stream)
 2914     (clear-stream $_test-output-buffered-file->buffer)
 2915     (clear-stream _test-error-stream)
 2916     (clear-stream $_test-error-buffered-file->buffer)
 2917     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2918     68/push 0/imm32
 2919     68/push 0/imm32
 2920     89/<- %edx 4/r32/esp
 2921     (tailor-exit-descriptor %edx 0x10)
 2922     #
 2923     (write _test-input-stream "fn f {\n")
 2924     (write _test-input-stream "  var x: int\n")
 2925     (write _test-input-stream "  g x\n")
 2926     (write _test-input-stream "}\n")
 2927     (write _test-input-stream "fn g a: foo {\n")
 2928     (write _test-input-stream "}\n")
 2929     # convert
 2930     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2931     # registers except esp clobbered at this point
 2932     # restore ed
 2933     89/<- %edx 4/r32/esp
 2934     (flush _test-output-buffered-file)
 2935     (flush _test-error-buffered-file)
 2936 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2942     # check output
 2943     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-inout-type: output should be empty")
 2944     (check-next-stream-line-equal _test-error-stream  "fn f: call g: type for inout 'x' is not right"  "F - test-convert-function-call-with-incorrect-inout-type: error message")
 2945     # check that stop(1) was called
 2946     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-inout-type: exit status")
 2947     # don't restore from ebp
 2948     81 0/subop/add %esp 8/imm32
 2949     5d/pop-to-ebp
 2950     c3/return
 2951 
 2952 test-convert-function-call-with-inout-with-incorrect-compound-type:
 2953     # . prologue
 2954     55/push-ebp
 2955     89/<- %ebp 4/r32/esp
 2956     # setup
 2957     (clear-stream _test-input-stream)
 2958     (clear-stream $_test-input-buffered-file->buffer)
 2959     (clear-stream _test-output-stream)
 2960     (clear-stream $_test-output-buffered-file->buffer)
 2961     (clear-stream _test-error-stream)
 2962     (clear-stream $_test-error-buffered-file->buffer)
 2963     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2964     68/push 0/imm32
 2965     68/push 0/imm32
 2966     89/<- %edx 4/r32/esp
 2967     (tailor-exit-descriptor %edx 0x10)
 2968     #
 2969     (write _test-input-stream "fn f {\n")
 2970     (write _test-input-stream "  var x: (addr int)\n")
 2971     (write _test-input-stream "  g x\n")
 2972     (write _test-input-stream "}\n")
 2973     (write _test-input-stream "fn g a: (addr bool) {\n")
 2974     (write _test-input-stream "}\n")
 2975     # convert
 2976     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2977     # registers except esp clobbered at this point
 2978     # restore ed
 2979     89/<- %edx 4/r32/esp
 2980     (flush _test-output-buffered-file)
 2981     (flush _test-error-buffered-file)
 2982 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2988     # check output
 2989     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-inout-with-incorrect-compound-type: output should be empty")
 2990     (check-next-stream-line-equal _test-error-stream  "fn f: call g: type for inout 'x' is not right"  "F - test-convert-function-call-with-inout-with-incorrect-compound-type: error message")
 2991     # don't restore from ebp
 2992     81 0/subop/add %esp 8/imm32
 2993     # . epilogue
 2994     5d/pop-to-ebp
 2995     c3/return
 2996 
 2997 test-convert-function-call-with-inout-with-multiple-type-parameters:
 2998     # . prologue
 2999     55/push-ebp
 3000     89/<- %ebp 4/r32/esp
 3001     # setup
 3002     (clear-stream _test-input-stream)
 3003     (clear-stream $_test-input-buffered-file->buffer)
 3004     (clear-stream _test-output-stream)
 3005     (clear-stream $_test-output-buffered-file->buffer)
 3006     (clear-stream _test-error-stream)
 3007     (clear-stream $_test-error-buffered-file->buffer)
 3008     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3009     68/push 0/imm32
 3010     68/push 0/imm32
 3011     89/<- %edx 4/r32/esp
 3012     (tailor-exit-descriptor %edx 0x10)
 3013     #
 3014     (write _test-input-stream "fn f {\n")
 3015     (write _test-input-stream "  var x: (addr int)\n")
 3016     (write _test-input-stream "  var y: (addr int)\n")
 3017     (write _test-input-stream "  g x, y\n")
 3018     (write _test-input-stream "}\n")
 3019     (write _test-input-stream "fn g a: (addr _), b: (addr _) {\n")
 3020     (write _test-input-stream "}\n")
 3021     # convert
 3022     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3023     # registers except esp clobbered at this point
 3024     # restore ed
 3025     89/<- %edx 4/r32/esp
 3026     (flush _test-output-buffered-file)
 3027     (flush _test-error-buffered-file)
 3028 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3034     # no errors
 3035     (check-stream-equal _test-error-stream  ""  "F - test-convert-function-call-with-inout-with-multiple-type-parameters: error stream should be empty")
 3036     # don't bother checking the generated code
 3037     # don't restore from ebp
 3038     81 0/subop/add %esp 8/imm32
 3039     # . epilogue
 3040     5d/pop-to-ebp
 3041     c3/return
 3042 
 3043 test-type-parameter-matches-rest-of-type:
 3044     # . prologue
 3045     55/push-ebp
 3046     89/<- %ebp 4/r32/esp
 3047     # setup
 3048     (clear-stream _test-input-stream)
 3049     (clear-stream $_test-input-buffered-file->buffer)
 3050     (clear-stream _test-output-stream)
 3051     (clear-stream $_test-output-buffered-file->buffer)
 3052     (clear-stream _test-error-stream)
 3053     (clear-stream $_test-error-buffered-file->buffer)
 3054     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3055     68/push 0/imm32
 3056     68/push 0/imm32
 3057     89/<- %edx 4/r32/esp
 3058     (tailor-exit-descriptor %edx 0x10)
 3059     #
 3060     (write _test-input-stream "fn f {\n")
 3061     (write _test-input-stream "  var x: (addr array int)\n")
 3062     (write _test-input-stream "  g x\n")
 3063     (write _test-input-stream "}\n")
 3064     (write _test-input-stream "fn g a: (addr _) {\n")
 3065     (write _test-input-stream "}\n")
 3066     # convert
 3067     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3068     # registers except esp clobbered at this point
 3069     # restore ed
 3070     89/<- %edx 4/r32/esp
 3071     (flush _test-output-buffered-file)
 3072     (flush _test-error-buffered-file)
 3073 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3079     # no errors
 3080     (check-stream-equal _test-error-stream  ""  "F - test-type-parameter-matches-rest-of-type: error stream should be empty")
 3081     # don't bother checking the generated code
 3082     # don't restore from ebp
 3083     81 0/subop/add %esp 8/imm32
 3084     # . epilogue
 3085     5d/pop-to-ebp
 3086     c3/return
 3087 
 3088 test-convert-function-call-with-inout-with-incompatible-type-parameters:
 3089     # . prologue
 3090     55/push-ebp
 3091     89/<- %ebp 4/r32/esp
 3092     # setup
 3093     (clear-stream _test-input-stream)
 3094     (clear-stream $_test-input-buffered-file->buffer)
 3095     (clear-stream _test-output-stream)
 3096     (clear-stream $_test-output-buffered-file->buffer)
 3097     (clear-stream _test-error-stream)
 3098     (clear-stream $_test-error-buffered-file->buffer)
 3099     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3100     68/push 0/imm32
 3101     68/push 0/imm32
 3102     89/<- %edx 4/r32/esp
 3103     (tailor-exit-descriptor %edx 0x10)
 3104     #
 3105     (write _test-input-stream "fn f {\n")
 3106     (write _test-input-stream "  var x: (addr int)\n")
 3107     (write _test-input-stream "  var y: (addr boolean)\n")
 3108     (write _test-input-stream "  g x, y\n")
 3109     (write _test-input-stream "}\n")
 3110     (write _test-input-stream "fn g a: (addr _T), b: (addr _T) {\n")
 3111     (write _test-input-stream "}\n")
 3112     # convert
 3113     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3114     # registers except esp clobbered at this point
 3115     # restore ed
 3116     89/<- %edx 4/r32/esp
 3117     (flush _test-output-buffered-file)
 3118     (flush _test-error-buffered-file)
 3119 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3125     # check output
 3126     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-inout-with-incompatible-type-parameters: output should be empty")
 3127     (check-next-stream-line-equal _test-error-stream  "fn f: call g: type for inout 'y' is not right"  "F - test-convert-function-call-with-inout-with-incompatible-type-parameters: error message")
 3128     # don't restore from ebp
 3129     81 0/subop/add %esp 8/imm32
 3130     # . epilogue
 3131     5d/pop-to-ebp
 3132     c3/return
 3133 
 3134 test-convert-function-call-with-too-few-inouts:
 3135     # . prologue
 3136     55/push-ebp
 3137     89/<- %ebp 4/r32/esp
 3138     # setup
 3139     (clear-stream _test-input-stream)
 3140     (clear-stream $_test-input-buffered-file->buffer)
 3141     (clear-stream _test-output-stream)
 3142     (clear-stream $_test-output-buffered-file->buffer)
 3143     (clear-stream _test-error-stream)
 3144     (clear-stream $_test-error-buffered-file->buffer)
 3145     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3146     68/push 0/imm32
 3147     68/push 0/imm32
 3148     89/<- %edx 4/r32/esp
 3149     (tailor-exit-descriptor %edx 0x10)
 3150     #
 3151     (write _test-input-stream "fn f {\n")
 3152     (write _test-input-stream "  g\n")
 3153     (write _test-input-stream "}\n")
 3154     (write _test-input-stream "fn g a: int {\n")
 3155     (write _test-input-stream "}\n")
 3156     # convert
 3157     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3158     # registers except esp clobbered at this point
 3159     # restore ed
 3160     89/<- %edx 4/r32/esp
 3161     (flush _test-output-buffered-file)
 3162     (flush _test-error-buffered-file)
 3163 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3169     # check output
 3170     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-few-inouts: output should be empty")
 3171     (check-next-stream-line-equal _test-error-stream  "fn f: call g: too few inouts"  "F - test-convert-function-call-with-too-few-inouts: error message")
 3172     # check that stop(1) was called
 3173     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-few-inouts: exit status")
 3174     # don't restore from ebp
 3175     81 0/subop/add %esp 8/imm32
 3176     5d/pop-to-ebp
 3177     c3/return
 3178 
 3179 test-convert-function-call-with-too-many-inouts:
 3180     # . prologue
 3181     55/push-ebp
 3182     89/<- %ebp 4/r32/esp
 3183     # setup
 3184     (clear-stream _test-input-stream)
 3185     (clear-stream $_test-input-buffered-file->buffer)
 3186     (clear-stream _test-output-stream)
 3187     (clear-stream $_test-output-buffered-file->buffer)
 3188     (clear-stream _test-error-stream)
 3189     (clear-stream $_test-error-buffered-file->buffer)
 3190     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3191     68/push 0/imm32
 3192     68/push 0/imm32
 3193     89/<- %edx 4/r32/esp
 3194     (tailor-exit-descriptor %edx 0x10)
 3195     #
 3196     (write _test-input-stream "fn f {\n")
 3197     (write _test-input-stream "  var x: int\n")
 3198     (write _test-input-stream "  g x\n")
 3199     (write _test-input-stream "}\n")
 3200     (write _test-input-stream "fn g {\n")
 3201     (write _test-input-stream "}\n")
 3202     # convert
 3203     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3204     # registers except esp clobbered at this point
 3205     # restore ed
 3206     89/<- %edx 4/r32/esp
 3207     (flush _test-output-buffered-file)
 3208     (flush _test-error-buffered-file)
 3209 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3215     # check output
 3216     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-many-inouts: output should be empty")
 3217     (check-next-stream-line-equal _test-error-stream  "fn f: call g: too many inouts"  "F - test-convert-function-call-with-too-many-inouts: error message")
 3218     # check that stop(1) was called
 3219     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-many-inouts: exit status")
 3220     # don't restore from ebp
 3221     81 0/subop/add %esp 8/imm32
 3222     5d/pop-to-ebp
 3223     c3/return
 3224 
 3225 test-convert-function-call-with-incorrect-output-type:
 3226     # . prologue
 3227     55/push-ebp
 3228     89/<- %ebp 4/r32/esp
 3229     # setup
 3230     (clear-stream _test-input-stream)
 3231     (clear-stream $_test-input-buffered-file->buffer)
 3232     (clear-stream _test-output-stream)
 3233     (clear-stream $_test-output-buffered-file->buffer)
 3234     (clear-stream _test-error-stream)
 3235     (clear-stream $_test-error-buffered-file->buffer)
 3236     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3237     68/push 0/imm32
 3238     68/push 0/imm32
 3239     89/<- %edx 4/r32/esp
 3240     (tailor-exit-descriptor %edx 0x10)
 3241     #
 3242     (write _test-input-stream "fn f {\n")
 3243     (write _test-input-stream "  var x/eax: int <- g\n")
 3244     (write _test-input-stream "}\n")
 3245     (write _test-input-stream "fn g -> _/eax: foo {\n")
 3246     (write _test-input-stream "}\n")
 3247     # convert
 3248     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3249     # registers except esp clobbered at this point
 3250     # restore ed
 3251     89/<- %edx 4/r32/esp
 3252     (flush _test-output-buffered-file)
 3253     (flush _test-error-buffered-file)
 3254 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3260     # check output
 3261     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-output-type: output should be empty")
 3262     (check-next-stream-line-equal _test-error-stream  "fn f: call g: type for output 'x' is not right"  "F - test-convert-function-call-with-incorrect-output-type: error message")
 3263     # check that stop(1) was called
 3264     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-output-type: exit status")
 3265     # don't restore from ebp
 3266     81 0/subop/add %esp 8/imm32
 3267     5d/pop-to-ebp
 3268     c3/return
 3269 
 3270 test-convert-function-call-with-too-few-outputs:
 3271     # . prologue
 3272     55/push-ebp
 3273     89/<- %ebp 4/r32/esp
 3274     # setup
 3275     (clear-stream _test-input-stream)
 3276     (clear-stream $_test-input-buffered-file->buffer)
 3277     (clear-stream _test-output-stream)
 3278     (clear-stream $_test-output-buffered-file->buffer)
 3279     (clear-stream _test-error-stream)
 3280     (clear-stream $_test-error-buffered-file->buffer)
 3281     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3282     68/push 0/imm32
 3283     68/push 0/imm32
 3284     89/<- %edx 4/r32/esp
 3285     (tailor-exit-descriptor %edx 0x10)
 3286     #
 3287     (write _test-input-stream "fn f {\n")
 3288     (write _test-input-stream "  g\n")
 3289     (write _test-input-stream "}\n")
 3290     (write _test-input-stream "fn g -> _/eax: int {\n")
 3291     (write _test-input-stream "}\n")
 3292     # convert
 3293     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3294     # registers except esp clobbered at this point
 3295     # restore ed
 3296     89/<- %edx 4/r32/esp
 3297     (flush _test-output-buffered-file)
 3298     (flush _test-error-buffered-file)
 3299 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3305     # check output
 3306     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-few-outputs: output should be empty")
 3307     (check-next-stream-line-equal _test-error-stream  "fn f: call g: too few outputs"  "F - test-convert-function-call-with-too-few-outputs: error message")
 3308     # check that stop(1) was called
 3309     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-few-outputs: exit status")
 3310     # don't restore from ebp
 3311     81 0/subop/add %esp 8/imm32
 3312     5d/pop-to-ebp
 3313     c3/return
 3314 
 3315 test-convert-function-call-with-too-many-outputs:
 3316     # . prologue
 3317     55/push-ebp
 3318     89/<- %ebp 4/r32/esp
 3319     # setup
 3320     (clear-stream _test-input-stream)
 3321     (clear-stream $_test-input-buffered-file->buffer)
 3322     (clear-stream _test-output-stream)
 3323     (clear-stream $_test-output-buffered-file->buffer)
 3324     (clear-stream _test-error-stream)
 3325     (clear-stream $_test-error-buffered-file->buffer)
 3326     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3327     68/push 0/imm32
 3328     68/push 0/imm32
 3329     89/<- %edx 4/r32/esp
 3330     (tailor-exit-descriptor %edx 0x10)
 3331     #
 3332     (write _test-input-stream "fn f {\n")
 3333     (write _test-input-stream "  var x/eax: int <- g\n")
 3334     (write _test-input-stream "}\n")
 3335     (write _test-input-stream "fn g {\n")
 3336     (write _test-input-stream "}\n")
 3337     # convert
 3338     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3339     # registers except esp clobbered at this point
 3340     # restore ed
 3341     89/<- %edx 4/r32/esp
 3342     (flush _test-output-buffered-file)
 3343     (flush _test-error-buffered-file)
 3344 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3350     # check output
 3351     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-many-outputs: output should be empty")
 3352     (check-next-stream-line-equal _test-error-stream  "fn f: call g: too many outputs"  "F - test-convert-function-call-with-too-many-outputs: error message")
 3353     # check that stop(1) was called
 3354     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-many-outputs: exit status")
 3355     # don't restore from ebp
 3356     81 0/subop/add %esp 8/imm32
 3357     5d/pop-to-ebp
 3358     c3/return
 3359 
 3360 test-convert-function-call-with-missing-output-register:
 3361     # . prologue
 3362     55/push-ebp
 3363     89/<- %ebp 4/r32/esp
 3364     # setup
 3365     (clear-stream _test-input-stream)
 3366     (clear-stream $_test-input-buffered-file->buffer)
 3367     (clear-stream _test-output-stream)
 3368     (clear-stream $_test-output-buffered-file->buffer)
 3369     (clear-stream _test-error-stream)
 3370     (clear-stream $_test-error-buffered-file->buffer)
 3371     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3372     68/push 0/imm32
 3373     68/push 0/imm32
 3374     89/<- %edx 4/r32/esp
 3375     (tailor-exit-descriptor %edx 0x10)
 3376     #
 3377     (write _test-input-stream "fn f {\n")
 3378     (write _test-input-stream "  var x: int\n")
 3379     (write _test-input-stream "  x <- g\n")
 3380     (write _test-input-stream "}\n")
 3381     (write _test-input-stream "fn g -> _/eax: int {\n")
 3382     (write _test-input-stream "}\n")
 3383     # convert
 3384     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3385     # registers except esp clobbered at this point
 3386     # restore ed
 3387     89/<- %edx 4/r32/esp
 3388     (flush _test-output-buffered-file)
 3389     (flush _test-error-buffered-file)
 3390 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3396     # check output
 3397     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-missing-output-register: output should be empty")
 3398     (check-next-stream-line-equal _test-error-stream  "fn f: call g: output 'x' is not in a register"  "F - test-convert-function-call-with-missing-output-register: error message")
 3399     # check that stop(1) was called
 3400     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-missing-output-register: exit status")
 3401     # don't restore from ebp
 3402     81 0/subop/add %esp 8/imm32
 3403     5d/pop-to-ebp
 3404     c3/return
 3405 
 3406 test-convert-function-call-with-incorrect-output-register:
 3407     # . prologue
 3408     55/push-ebp
 3409     89/<- %ebp 4/r32/esp
 3410     # setup
 3411     (clear-stream _test-input-stream)
 3412     (clear-stream $_test-input-buffered-file->buffer)
 3413     (clear-stream _test-output-stream)
 3414     (clear-stream $_test-output-buffered-file->buffer)
 3415     (clear-stream _test-error-stream)
 3416     (clear-stream $_test-error-buffered-file->buffer)
 3417     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3418     68/push 0/imm32
 3419     68/push 0/imm32
 3420     89/<- %edx 4/r32/esp
 3421     (tailor-exit-descriptor %edx 0x10)
 3422     #
 3423     (write _test-input-stream "fn f {\n")
 3424     (write _test-input-stream "  var x/ecx: int <- g\n")
 3425     (write _test-input-stream "}\n")
 3426     (write _test-input-stream "fn g -> _/eax: int {\n")
 3427     (write _test-input-stream "}\n")
 3428     # convert
 3429     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3430     # registers except esp clobbered at this point
 3431     # restore ed
 3432     89/<- %edx 4/r32/esp
 3433     (flush _test-output-buffered-file)
 3434     (flush _test-error-buffered-file)
 3435 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3441     # check output
 3442     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-output-register: output should be empty")
 3443     (check-next-stream-line-equal _test-error-stream  "fn f: call g: register for output 'x' is not right"  "F - test-convert-function-call-with-incorrect-output-register: error message")
 3444     # check that stop(1) was called
 3445     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-output-register: exit status")
 3446     # don't restore from ebp
 3447     81 0/subop/add %esp 8/imm32
 3448     5d/pop-to-ebp
 3449     c3/return
 3450 
 3451 test-convert-function-with-local-var-dereferenced:
 3452     # . prologue
 3453     55/push-ebp
 3454     89/<- %ebp 4/r32/esp
 3455     # setup
 3456     (clear-stream _test-input-stream)
 3457     (clear-stream $_test-input-buffered-file->buffer)
 3458     (clear-stream _test-output-stream)
 3459     (clear-stream $_test-output-buffered-file->buffer)
 3460     #
 3461     (write _test-input-stream "fn foo {\n")
 3462     (write _test-input-stream "  var x/ecx: (addr int) <- copy 0\n")
 3463     (write _test-input-stream "  increment *x\n")
 3464     (write _test-input-stream "}\n")
 3465     # convert
 3466     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3467     (flush _test-output-buffered-file)
 3468 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3474     # check output
 3475     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-dereferenced/0")
 3476     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-dereferenced/1")
 3477     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-dereferenced/2")
 3478     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-dereferenced/3")
 3479     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-dereferenced/4")
 3480     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-dereferenced/5")
 3481     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-dereferenced/6")
 3482     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-local-var-dereferenced/7")
 3483     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *ecx"  "F - test-convert-function-with-local-var-dereferenced/8")
 3484     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-dereferenced/9")
 3485     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-dereferenced/10")
 3486     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-dereferenced/11")
 3487     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-dereferenced/12")
 3488     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-dereferenced/13")
 3489     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-dereferenced/14")
 3490     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-dereferenced/15")
 3491     # . epilogue
 3492     89/<- %esp 5/r32/ebp
 3493     5d/pop-to-ebp
 3494     c3/return
 3495 
 3496 test-dereference-of-var-on-stack:
 3497     # . prologue
 3498     55/push-ebp
 3499     89/<- %ebp 4/r32/esp
 3500     # setup
 3501     (clear-stream _test-input-stream)
 3502     (clear-stream $_test-input-buffered-file->buffer)
 3503     (clear-stream _test-output-stream)
 3504     (clear-stream $_test-output-buffered-file->buffer)
 3505     (clear-stream _test-error-stream)
 3506     (clear-stream $_test-error-buffered-file->buffer)
 3507     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3508     68/push 0/imm32
 3509     68/push 0/imm32
 3510     89/<- %edx 4/r32/esp
 3511     (tailor-exit-descriptor %edx 0x10)
 3512     #
 3513     (write _test-input-stream "fn foo {\n")
 3514     (write _test-input-stream "  var x: (addr int)\n")
 3515     (write _test-input-stream "  increment *x\n")
 3516     (write _test-input-stream "}\n")
 3517     # convert
 3518     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3519     # registers except esp clobbered at this point
 3520     # restore ed
 3521     89/<- %edx 4/r32/esp
 3522     (flush _test-output-buffered-file)
 3523     (flush _test-error-buffered-file)
 3524 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3530     # check output
 3531     (check-stream-equal _test-output-stream  ""  "F - test-dereference-of-var-on-stack: output should be empty")
 3532     (check-next-stream-line-equal _test-error-stream  "fn foo: cannot dereference var 'x' on stack"  "F - test-dereference-of-var-on-stack: error message")
 3533     # check that stop(1) was called
 3534     (check-ints-equal *(edx+4) 2 "F - test-dereference-of-var-on-stack: exit status")
 3535     # don't restore from ebp
 3536     81 0/subop/add %esp 8/imm32
 3537     # . epilogue
 3538     5d/pop-to-ebp
 3539     c3/return
 3540 
 3541 test-convert-function-with-byte-operations:
 3542     # . prologue
 3543     55/push-ebp
 3544     89/<- %ebp 4/r32/esp
 3545     # setup
 3546     (clear-stream _test-input-stream)
 3547     (clear-stream $_test-input-buffered-file->buffer)
 3548     (clear-stream _test-output-stream)
 3549     (clear-stream $_test-output-buffered-file->buffer)
 3550     #
 3551     (write _test-input-stream "fn foo {\n")
 3552     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
 3553     (write _test-input-stream "  var y/ecx: byte <- copy 0\n")
 3554     (write _test-input-stream "  y <- copy-byte x\n")
 3555     (write _test-input-stream "  var z/edx: (addr byte) <- copy 0\n")
 3556     (write _test-input-stream "  y <- copy-byte *z\n")
 3557     (write _test-input-stream "  copy-byte-to *z, x\n")
 3558     (write _test-input-stream "}\n")
 3559     # convert
 3560     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3561     (flush _test-output-buffered-file)
 3562 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3568     # check output
 3569     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-function-with-byte-operations/0")
 3570     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-function-with-byte-operations/1")
 3571     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-function-with-byte-operations/2")
 3572     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-function-with-byte-operations/3")
 3573     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-function-with-byte-operations/4")
 3574     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-function-with-byte-operations/5")
 3575     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-function-with-byte-operations/6")
 3576     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-function-with-byte-operations/7")
 3577     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-function-with-byte-operations/8")
 3578     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"                  "F - test-convert-function-with-byte-operations/9")
 3579     (check-next-stream-line-equal _test-output-stream "    8a/byte-> %eax 0x00000001/r32"           "F - test-convert-function-with-byte-operations/10")
 3580     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %edx"                    "F - test-convert-function-with-byte-operations/11")
 3581     (check-next-stream-line-equal _test-output-stream "    ba/copy-to-edx 0/imm32"                  "F - test-convert-function-with-byte-operations/12")
 3582     (check-next-stream-line-equal _test-output-stream "    8a/byte-> *edx 0x00000001/r32"           "F - test-convert-function-with-byte-operations/13")
 3583     (check-next-stream-line-equal _test-output-stream "    88/byte<- *edx 0x00000000/r32"           "F - test-convert-function-with-byte-operations/14")
 3584     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %edx"                     "F - test-convert-function-with-byte-operations/15")
 3585     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-function-with-byte-operations/16")
 3586     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-function-with-byte-operations/17")
 3587     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-function-with-byte-operations/18")
 3588     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-function-with-byte-operations/19")
 3589     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-function-with-byte-operations/20")
 3590     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-function-with-byte-operations/21")
 3591     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-function-with-byte-operations/22")
 3592     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-function-with-byte-operations/23")
 3593     # . epilogue
 3594     89/<- %esp 5/r32/ebp
 3595     5d/pop-to-ebp
 3596     c3/return
 3597 
 3598 # variables of type 'byte' are not allowed on the stack
 3599 test-byte-values-on-stack:
 3600     # . prologue
 3601     55/push-ebp
 3602     89/<- %ebp 4/r32/esp
 3603     # setup
 3604     (clear-stream _test-input-stream)
 3605     (clear-stream $_test-input-buffered-file->buffer)
 3606     (clear-stream _test-output-stream)
 3607     (clear-stream $_test-output-buffered-file->buffer)
 3608     (clear-stream _test-error-stream)
 3609     (clear-stream $_test-error-buffered-file->buffer)
 3610     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3611     68/push 0/imm32
 3612     68/push 0/imm32
 3613     89/<- %edx 4/r32/esp
 3614     (tailor-exit-descriptor %edx 0x10)
 3615     #
 3616     (write _test-input-stream "fn foo {\n")
 3617     (write _test-input-stream "  var x: byte\n")
 3618     (write _test-input-stream "}\n")
 3619     # convert
 3620     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3621     # registers except esp clobbered at this point
 3622     # restore ed
 3623     89/<- %edx 4/r32/esp
 3624     (flush _test-output-buffered-file)
 3625     (flush _test-error-buffered-file)
 3626 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3632     # check output
 3633     (check-stream-equal _test-output-stream  ""  "F - test-byte-values-on-stack: output should be empty")
 3634     (check-next-stream-line-equal _test-error-stream  "fn foo: var 'x' of type 'byte' cannot be on the stack"  "F - test-byte-values-on-stack: error message")
 3635     # check that stop(1) was called
 3636     (check-ints-equal *(edx+4) 2 "F - test-byte-values-on-stack: exit status")
 3637     # don't restore from ebp
 3638     81 0/subop/add %esp 8/imm32
 3639     # . epilogue
 3640     5d/pop-to-ebp
 3641     c3/return
 3642 
 3643 # variables of type 'byte' are not allowed in esi or edi
 3644 test-byte-values-in-unsupported-registers:
 3645     # . prologue
 3646     55/push-ebp
 3647     89/<- %ebp 4/r32/esp
 3648     # setup
 3649     (clear-stream _test-input-stream)
 3650     (clear-stream $_test-input-buffered-file->buffer)
 3651     (clear-stream _test-output-stream)
 3652     (clear-stream $_test-output-buffered-file->buffer)
 3653     (clear-stream _test-error-stream)
 3654     (clear-stream $_test-error-buffered-file->buffer)
 3655     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3656     68/push 0/imm32
 3657     68/push 0/imm32
 3658     89/<- %edx 4/r32/esp
 3659     (tailor-exit-descriptor %edx 0x10)
 3660     #
 3661     (write _test-input-stream "fn foo {\n")
 3662     (write _test-input-stream "  var x/esi: byte <- copy 0\n")
 3663     (write _test-input-stream "}\n")
 3664     # convert
 3665     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3666     # registers except esp clobbered at this point
 3667     # restore ed
 3668     89/<- %edx 4/r32/esp
 3669     (flush _test-output-buffered-file)
 3670     (flush _test-error-buffered-file)
 3671 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3677     # check output
 3678     (check-stream-equal _test-output-stream  ""  "F - test-byte-values-in-unsupported-registers: output should be empty")
 3679     (check-next-stream-line-equal _test-error-stream  "fn foo: var 'x' of type 'byte' cannot be in esi or edi"  "F - test-byte-values-in-unsupported-registers: error message")
 3680     # check that stop(1) was called
 3681     (check-ints-equal *(edx+4) 2 "F - test-byte-values-in-unsupported-registers: exit status")
 3682     # don't restore from ebp
 3683     81 0/subop/add %esp 8/imm32
 3684     # . epilogue
 3685     5d/pop-to-ebp
 3686     c3/return
 3687 
 3688 # variables of type 'byte' _can_ be function args. They then occupy 4 bytes.
 3689 test-copy-byte-var-from-fn-arg:
 3690     # . prologue
 3691     55/push-ebp
 3692     89/<- %ebp 4/r32/esp
 3693     # setup
 3694     (clear-stream _test-input-stream)
 3695     (clear-stream $_test-input-buffered-file->buffer)
 3696     (clear-stream _test-output-stream)
 3697     (clear-stream $_test-output-buffered-file->buffer)
 3698     #
 3699     (write _test-input-stream "fn foo x: byte, y: int {\n")
 3700     (write _test-input-stream "  var a/eax: byte <- copy x\n")
 3701     (write _test-input-stream "  var b/eax: int <- copy y\n")
 3702     (write _test-input-stream "}\n")
 3703     # convert
 3704     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3705     (flush _test-output-buffered-file)
 3706 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3712     # check output
 3713     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-copy-byte-from-fn-arg/0")
 3714     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-copy-byte-from-fn-arg/1")
 3715     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-copy-byte-from-fn-arg/2")
 3716     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-copy-byte-from-fn-arg/3")
 3717     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-copy-byte-from-fn-arg/4")
 3718     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-copy-byte-from-fn-arg/5")
 3719     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-copy-byte-from-fn-arg/6")
 3720     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-copy-byte-from-fn-arg/7")
 3721     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x0000000c) 0x00000000/r32"  "F - test-copy-byte-from-fn-arg/8")
 3722     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"   "F - test-copy-byte-from-fn-arg/9")
 3723     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-copy-byte-from-fn-arg/10")
 3724     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-copy-byte-from-fn-arg/11")
 3725     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-copy-byte-from-fn-arg/12")
 3726     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-copy-byte-from-fn-arg/13")
 3727     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-copy-byte-from-fn-arg/14")
 3728     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-copy-byte-from-fn-arg/15")
 3729     # . epilogue
 3730     89/<- %esp 5/r32/ebp
 3731     5d/pop-to-ebp
 3732     c3/return
 3733 
 3734 test-convert-compare-register-with-literal:
 3735     # . prologue
 3736     55/push-ebp
 3737     89/<- %ebp 4/r32/esp
 3738     # setup
 3739     (clear-stream _test-input-stream)
 3740     (clear-stream $_test-input-buffered-file->buffer)
 3741     (clear-stream _test-output-stream)
 3742     (clear-stream $_test-output-buffered-file->buffer)
 3743     #
 3744     (write _test-input-stream "fn foo {\n")
 3745     (write _test-input-stream "  var x/ecx: int <- copy 0\n")
 3746     (write _test-input-stream "  compare x, 0\n")
 3747     (write _test-input-stream "}\n")
 3748     # convert
 3749     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3750     (flush _test-output-buffered-file)
 3751 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3757     # check output
 3758     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-compare-register-with-literal/0")
 3759     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-compare-register-with-literal/1")
 3760     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-compare-register-with-literal/2")
 3761     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-compare-register-with-literal/3")
 3762     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-compare-register-with-literal/4")
 3763     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-compare-register-with-literal/5")
 3764     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-compare-register-with-literal/6")
 3765     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-compare-register-with-literal/7")
 3766     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %ecx 0/imm32"  "F - test-convert-compare-register-with-literal/8")
 3767     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-compare-register-with-literal/9")
 3768     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-compare-register-with-literal/10")
 3769     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-compare-register-with-literal/11")
 3770     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-compare-register-with-literal/12")
 3771     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-compare-register-with-literal/13")
 3772     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-compare-register-with-literal/14")
 3773     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-compare-register-with-literal/15")
 3774     # . epilogue
 3775     89/<- %esp 5/r32/ebp
 3776     5d/pop-to-ebp
 3777     c3/return
 3778 
 3779 test-unknown-variable:
 3780     # . prologue
 3781     55/push-ebp
 3782     89/<- %ebp 4/r32/esp
 3783     # setup
 3784     (clear-stream _test-input-stream)
 3785     (clear-stream $_test-input-buffered-file->buffer)
 3786     (clear-stream _test-output-stream)
 3787     (clear-stream $_test-output-buffered-file->buffer)
 3788     (clear-stream _test-error-stream)
 3789     (clear-stream $_test-error-buffered-file->buffer)
 3790     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3791     68/push 0/imm32
 3792     68/push 0/imm32
 3793     89/<- %edx 4/r32/esp
 3794     (tailor-exit-descriptor %edx 0x10)
 3795     #
 3796     (write _test-input-stream "fn foo {\n")
 3797     (write _test-input-stream "  compare x, 0\n")
 3798     (write _test-input-stream "}\n")
 3799     # convert
 3800     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3801     # registers except esp clobbered at this point
 3802     # restore ed
 3803     89/<- %edx 4/r32/esp
 3804     (flush _test-output-buffered-file)
 3805     (flush _test-error-buffered-file)
 3806 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3812     # check output
 3813     (check-stream-equal _test-output-stream  ""  "F - test-unknown-variable: output should be empty")
 3814     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-unknown-variable: error message")
 3815     # check that stop(1) was called
 3816     (check-ints-equal *(edx+4) 2 "F - test-unknown-variable: exit status")
 3817     # don't restore from ebp
 3818     81 0/subop/add %esp 8/imm32
 3819     # . epilogue
 3820     5d/pop-to-ebp
 3821     c3/return
 3822 
 3823 test-convert-function-with-local-var-in-block:
 3824     # . prologue
 3825     55/push-ebp
 3826     89/<- %ebp 4/r32/esp
 3827     # setup
 3828     (clear-stream _test-input-stream)
 3829     (clear-stream $_test-input-buffered-file->buffer)
 3830     (clear-stream _test-output-stream)
 3831     (clear-stream $_test-output-buffered-file->buffer)
 3832     #
 3833     (write _test-input-stream "fn foo {\n")
 3834     (write _test-input-stream "  {\n")
 3835     (write _test-input-stream "    var x: int\n")
 3836     (write _test-input-stream "    increment x\n")
 3837     (write _test-input-stream "  }\n")
 3838     (write _test-input-stream "}\n")
 3839     # convert
 3840     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3841     (flush _test-output-buffered-file)
 3842 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3848     # check output
 3849     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-block/0")
 3850     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-block/1")
 3851     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-block/2")
 3852     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-block/3")
 3853     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-block/4")
 3854     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-block/5")
 3855     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-block/6")
 3856     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-local-var-in-block/7")
 3857     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-block/8")
 3858     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-local-var-in-block/9")
 3859     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-local-var-in-block/10")
 3860     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-block/11")
 3861     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-local-var-in-block/12")
 3862     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-block/13")
 3863     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-block/14")
 3864     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-block/15")
 3865     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-block/16")
 3866     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-block/17")
 3867     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-block/18")
 3868     # . epilogue
 3869     89/<- %esp 5/r32/ebp
 3870     5d/pop-to-ebp
 3871     c3/return
 3872 
 3873 test-convert-function-with-local-var-in-mem-after-block:
 3874     # . prologue
 3875     55/push-ebp
 3876     89/<- %ebp 4/r32/esp
 3877     # setup
 3878     (clear-stream _test-input-stream)
 3879     (clear-stream $_test-input-buffered-file->buffer)
 3880     (clear-stream _test-output-stream)
 3881     (clear-stream $_test-output-buffered-file->buffer)
 3882     #
 3883     (write _test-input-stream "fn foo {\n")
 3884     (write _test-input-stream "  {\n")
 3885     (write _test-input-stream "    var y: int\n")
 3886     (write _test-input-stream "  }\n")
 3887     (write _test-input-stream "  var x: int\n")
 3888     (write _test-input-stream "  increment x\n")
 3889     (write _test-input-stream "}\n")
 3890     # convert
 3891     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3892     (flush _test-output-buffered-file)
 3893 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3899     # check output
 3900     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-mem-after-block/0")
 3901     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-mem-after-block/1")
 3902     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-mem-after-block/2")
 3903     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-mem-after-block/3")
 3904     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-mem-after-block/4")
 3905     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-mem-after-block/5")
 3906     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-mem-after-block/6")
 3907     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-local-var-in-mem-after-block/7")
 3908     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-mem-after-block/8")
 3909     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-local-var-in-mem-after-block/9")
 3910     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-mem-after-block/10")
 3911     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-local-var-in-mem-after-block/11")
 3912     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-in-mem-after-block/12")
 3913     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-local-var-in-mem-after-block/13")
 3914     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-local-var-in-mem-after-block/14")
 3915     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-mem-after-block/15")
 3916     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-mem-after-block/16")
 3917     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-mem-after-block/17")
 3918     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-mem-after-block/18")
 3919     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-mem-after-block/19")
 3920     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-mem-after-block/20")
 3921     # . epilogue
 3922     89/<- %esp 5/r32/ebp
 3923     5d/pop-to-ebp
 3924     c3/return
 3925 
 3926 test-convert-function-with-local-var-in-named-block:
 3927     # . prologue
 3928     55/push-ebp
 3929     89/<- %ebp 4/r32/esp
 3930     # setup
 3931     (clear-stream _test-input-stream)
 3932     (clear-stream $_test-input-buffered-file->buffer)
 3933     (clear-stream _test-output-stream)
 3934     (clear-stream $_test-output-buffered-file->buffer)
 3935     #
 3936     (write _test-input-stream "fn foo {\n")
 3937     (write _test-input-stream "  $bar: {\n")
 3938     (write _test-input-stream "    var x: int\n")
 3939     (write _test-input-stream "    increment x\n")
 3940     (write _test-input-stream "  }\n")
 3941     (write _test-input-stream "}\n")
 3942     # convert
 3943     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3944     (flush _test-output-buffered-file)
 3945 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3951     # check output
 3952     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-named-block/0")
 3953     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-named-block/1")
 3954     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-named-block/2")
 3955     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-named-block/3")
 3956     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-named-block/4")
 3957     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-named-block/5")
 3958     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-named-block/6")
 3959     (check-next-stream-line-equal _test-output-stream "$bar:loop:"              "F - test-convert-function-with-local-var-in-named-block/7")
 3960     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-named-block/8")
 3961     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-local-var-in-named-block/9")
 3962     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-local-var-in-named-block/10")
 3963     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-named-block/11")
 3964     (check-next-stream-line-equal _test-output-stream "$bar:break:"             "F - test-convert-function-with-local-var-in-named-block/12")
 3965     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-named-block/13")
 3966     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-named-block/14")
 3967     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-named-block/15")
 3968     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-named-block/16")
 3969     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-named-block/17")
 3970     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-named-block/18")
 3971     # . epilogue
 3972     89/<- %esp 5/r32/ebp
 3973     5d/pop-to-ebp
 3974     c3/return
 3975 
 3976 test-unknown-variable-in-named-block:
 3977     # . prologue
 3978     55/push-ebp
 3979     89/<- %ebp 4/r32/esp
 3980     # setup
 3981     (clear-stream _test-input-stream)
 3982     (clear-stream $_test-input-buffered-file->buffer)
 3983     (clear-stream _test-output-stream)
 3984     (clear-stream $_test-output-buffered-file->buffer)
 3985     (clear-stream _test-error-stream)
 3986     (clear-stream $_test-error-buffered-file->buffer)
 3987     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3988     68/push 0/imm32
 3989     68/push 0/imm32
 3990     89/<- %edx 4/r32/esp
 3991     (tailor-exit-descriptor %edx 0x10)
 3992     #
 3993     (write _test-input-stream "fn foo {\n")
 3994     (write _test-input-stream "  $a: {\n")
 3995     (write _test-input-stream "    compare x, 0\n")
 3996     (write _test-input-stream "  }\n")
 3997     (write _test-input-stream "}\n")
 3998     # convert
 3999     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 4000     # registers except esp clobbered at this point
 4001     # restore ed
 4002     89/<- %edx 4/r32/esp
 4003     (flush _test-output-buffered-file)
 4004     (flush _test-error-buffered-file)
 4005 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4011     # check output
 4012     (check-stream-equal _test-output-stream  ""  "F - test-unknown-variable-in-named-block: output should be empty")
 4013     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-unknown-variable-in-named-block: error message")
 4014     # check that stop(1) was called
 4015     (check-ints-equal *(edx+4) 2 "F - test-unknown-variable-in-named-block: exit status")
 4016     # don't restore from ebp
 4017     81 0/subop/add %esp 8/imm32
 4018     # . epilogue
 4019     5d/pop-to-ebp
 4020     c3/return
 4021 
 4022 test-always-shadow-outermost-reg-vars-in-function:
 4023     # . prologue
 4024     55/push-ebp
 4025     89/<- %ebp 4/r32/esp
 4026     # setup
 4027     (clear-stream _test-input-stream)
 4028     (clear-stream $_test-input-buffered-file->buffer)
 4029     (clear-stream _test-output-stream)
 4030     (clear-stream $_test-output-buffered-file->buffer)
 4031     #
 4032     (write _test-input-stream "fn foo {\n")
 4033     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4034     (write _test-input-stream "}\n")
 4035     # convert
 4036     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4037     (flush _test-output-buffered-file)
 4038 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4044     # check output
 4045     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-always-shadow-outermost-reg-vars-in-function/0")
 4046     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-always-shadow-outermost-reg-vars-in-function/1")
 4047     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-always-shadow-outermost-reg-vars-in-function/2")
 4048     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-always-shadow-outermost-reg-vars-in-function/3")
 4049     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-always-shadow-outermost-reg-vars-in-function/4")
 4050     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-always-shadow-outermost-reg-vars-in-function/5")
 4051     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-compare-register-with-literal/6")
 4052     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-always-shadow-outermost-reg-vars-in-function/8")
 4053     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-compare-register-with-literal/9")
 4054     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-always-shadow-outermost-reg-vars-in-function/12")
 4055     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-always-shadow-outermost-reg-vars-in-function/13")
 4056     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-always-shadow-outermost-reg-vars-in-function/14")
 4057     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-always-shadow-outermost-reg-vars-in-function/15")
 4058     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-always-shadow-outermost-reg-vars-in-function/16")
 4059     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-always-shadow-outermost-reg-vars-in-function/17")
 4060     # . epilogue
 4061     89/<- %esp 5/r32/ebp
 4062     5d/pop-to-ebp
 4063     c3/return
 4064 
 4065 test-shadow-local:
 4066     # . prologue
 4067     55/push-ebp
 4068     89/<- %ebp 4/r32/esp
 4069     # setup
 4070     (clear-stream _test-input-stream)
 4071     (clear-stream $_test-input-buffered-file->buffer)
 4072     (clear-stream _test-output-stream)
 4073     (clear-stream $_test-output-buffered-file->buffer)
 4074     #
 4075     (write _test-input-stream "fn foo {\n")
 4076     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4077     (write _test-input-stream "  {\n")
 4078     (write _test-input-stream "    var y/ecx: int <- copy 4\n")
 4079     (write _test-input-stream "  }\n")
 4080     (write _test-input-stream "  x <- increment\n")
 4081     (write _test-input-stream "}\n")
 4082     # convert
 4083     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4084     (flush _test-output-buffered-file)
 4085 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4091     # check output
 4092     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-local/0")
 4093     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-local/1")
 4094     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-local/2")
 4095     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-local/3")
 4096     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-local/4")
 4097     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-local/5")
 4098     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-local/6")
 4099     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-local/7")
 4100     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-local/8")
 4101     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-local/9")
 4102     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %ecx"  "F - test-shadow-local/10")
 4103     (check-next-stream-line-equal _test-output-stream "      b9/copy-to-ecx 4/imm32"  "F - test-shadow-local/11")
 4104     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %ecx" "F - test-shadow-local/12")
 4105     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-local/13")
 4106     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-local/14")
 4107     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-local/15")
 4108     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-local/16")
 4109     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-local/17")
 4110     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-local/18")
 4111     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-local/19")
 4112     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-local/20")
 4113     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-local/21")
 4114     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-local/22")
 4115     # . epilogue
 4116     89/<- %esp 5/r32/ebp
 4117     5d/pop-to-ebp
 4118     c3/return
 4119 
 4120 test-shadow-name:
 4121     # . prologue
 4122     55/push-ebp
 4123     89/<- %ebp 4/r32/esp
 4124     # setup
 4125     (clear-stream _test-input-stream)
 4126     (clear-stream $_test-input-buffered-file->buffer)
 4127     (clear-stream _test-output-stream)
 4128     (clear-stream $_test-output-buffered-file->buffer)
 4129     #
 4130     (write _test-input-stream "fn foo {\n")
 4131     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4132     (write _test-input-stream "  {\n")
 4133     (write _test-input-stream "    var x/edx: int <- copy 4\n")
 4134     (write _test-input-stream "  }\n")
 4135     (write _test-input-stream "  x <- increment\n")
 4136     (write _test-input-stream "}\n")
 4137     # convert
 4138     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4139     (flush _test-output-buffered-file)
 4140 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4146     # check output
 4147     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-name/0")
 4148     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-name/1")
 4149     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-name/2")
 4150     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-name/3")
 4151     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-name/4")
 4152     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-name/5")
 4153     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-name/6")
 4154     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-name/7")
 4155     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-name/8")
 4156     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-name/9")
 4157     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %edx"  "F - test-shadow-name/10")
 4158     (check-next-stream-line-equal _test-output-stream "      ba/copy-to-edx 4/imm32"  "F - test-shadow-name/11")
 4159     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %edx" "F - test-shadow-name/12")
 4160     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-name/13")
 4161     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-name/14")
 4162     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-name/15")
 4163     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-name/16")
 4164     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-name/17")
 4165     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-name/18")
 4166     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-name/19")
 4167     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-name/20")
 4168     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-name/21")
 4169     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-name/22")
 4170     # . epilogue
 4171     89/<- %esp 5/r32/ebp
 4172     5d/pop-to-ebp
 4173     c3/return
 4174 
 4175 test-shadow-name-2:
 4176     # . prologue
 4177     55/push-ebp
 4178     89/<- %ebp 4/r32/esp
 4179     # setup
 4180     (clear-stream _test-input-stream)
 4181     (clear-stream $_test-input-buffered-file->buffer)
 4182     (clear-stream _test-output-stream)
 4183     (clear-stream $_test-output-buffered-file->buffer)
 4184     #
 4185     (write _test-input-stream "fn foo {\n")
 4186     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4187     (write _test-input-stream "  {\n")
 4188     (write _test-input-stream "    var x/edx: int <- copy 4\n")
 4189     (write _test-input-stream "    var y/ecx: int <- copy 5\n")
 4190     (write _test-input-stream "  }\n")
 4191     (write _test-input-stream "  x <- increment\n")
 4192     (write _test-input-stream "}\n")
 4193     # convert
 4194     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4195     (flush _test-output-buffered-file)
 4196 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4202     # check output
 4203     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-name-2/0")
 4204     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-name-2/1")
 4205     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-name-2/2")
 4206     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-name-2/3")
 4207     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-name-2/4")
 4208     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-name-2/5")
 4209     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-name-2/6")
 4210     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-name-2/7")
 4211     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-name-2/8")
 4212     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-name-2/9")
 4213     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %edx"  "F - test-shadow-name-2/10")
 4214     (check-next-stream-line-equal _test-output-stream "      ba/copy-to-edx 4/imm32"  "F - test-shadow-name-2/11")
 4215     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %ecx"  "F - test-shadow-name-2/12")
 4216     (check-next-stream-line-equal _test-output-stream "      b9/copy-to-ecx 5/imm32"  "F - test-shadow-name-2/13")
 4217     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %ecx" "F - test-shadow-name-2/14")
 4218     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %edx" "F - test-shadow-name-2/15")
 4219     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-name-2/16")
 4220     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-name-2/17")
 4221     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-name-2/18")
 4222     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-name-2/19")
 4223     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-name-2/20")
 4224     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-name-2/21")
 4225     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-name-2/22")
 4226     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-name-2/23")
 4227     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-name-2/24")
 4228     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-name-2/25")
 4229     # . epilogue
 4230     89/<- %esp 5/r32/ebp
 4231     5d/pop-to-ebp
 4232     c3/return
 4233 
 4234 test-do-not-spill-same-register-in-block:
 4235     # . prologue
 4236     55/push-ebp
 4237     89/<- %ebp 4/r32/esp
 4238     # setup
 4239     (clear-stream _test-input-stream)
 4240     (clear-stream $_test-input-buffered-file->buffer)
 4241     (clear-stream _test-output-stream)
 4242     (clear-stream $_test-output-buffered-file->buffer)
 4243     #
 4244     (write _test-input-stream "fn foo {\n")
 4245     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4246     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 4247     (write _test-input-stream "  y <- increment\n")
 4248     (write _test-input-stream "}\n")
 4249     # convert
 4250     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4251     (flush _test-output-buffered-file)
 4252 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4258     # check output
 4259     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-do-not-spill-same-register-in-block/0")
 4260     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-do-not-spill-same-register-in-block/1")
 4261     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-do-not-spill-same-register-in-block/2")
 4262     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-do-not-spill-same-register-in-block/3")
 4263     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-do-not-spill-same-register-in-block/4")
 4264     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-do-not-spill-same-register-in-block/5")
 4265     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-do-not-spill-same-register-in-block/6")
 4266     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-do-not-spill-same-register-in-block/7")
 4267     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-do-not-spill-same-register-in-block/8")
 4268     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-do-not-spill-same-register-in-block/9")
 4269     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-do-not-spill-same-register-in-block/10")
 4270     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-do-not-spill-same-register-in-block/11")
 4271     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-do-not-spill-same-register-in-block/12")
 4272     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-do-not-spill-same-register-in-block/13")
 4273     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-do-not-spill-same-register-in-block/14")
 4274     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-do-not-spill-same-register-in-block/15")
 4275     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-do-not-spill-same-register-in-block/16")
 4276     # . epilogue
 4277     89/<- %esp 5/r32/ebp
 4278     5d/pop-to-ebp
 4279     c3/return
 4280 
 4281 test-spill-different-register-in-block:
 4282     # . prologue
 4283     55/push-ebp
 4284     89/<- %ebp 4/r32/esp
 4285     # setup
 4286     (clear-stream _test-input-stream)
 4287     (clear-stream $_test-input-buffered-file->buffer)
 4288     (clear-stream _test-output-stream)
 4289     (clear-stream $_test-output-buffered-file->buffer)
 4290     #
 4291     (write _test-input-stream "fn foo {\n")
 4292     (write _test-input-stream "  var x/eax: int <- copy 3\n")
 4293     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 4294     (write _test-input-stream "  y <- increment\n")
 4295     (write _test-input-stream "}\n")
 4296     # convert
 4297     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4298     (flush _test-output-buffered-file)
 4299 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4305     # check output
 4306     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-spill-different-register-in-block/0")
 4307     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-spill-different-register-in-block/1")
 4308     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-spill-different-register-in-block/2")
 4309     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-spill-different-register-in-block/3")
 4310     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-spill-different-register-in-block/4")
 4311     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-spill-different-register-in-block/5")
 4312     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-spill-different-register-in-block/6")
 4313     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-spill-different-register-in-block/7")
 4314     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-spill-different-register-in-block/8")
 4315     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-spill-different-register-in-block/9")
 4316     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-spill-different-register-in-block/10")
 4317     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-spill-different-register-in-block/11")
 4318     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-spill-different-register-in-block/12")
 4319     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-spill-different-register-in-block/13")
 4320     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-spill-different-register-in-block/14")
 4321     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-spill-different-register-in-block/15")
 4322     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-spill-different-register-in-block/16")
 4323     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-spill-different-register-in-block/17")
 4324     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-spill-different-register-in-block/18")
 4325     # . epilogue
 4326     89/<- %esp 5/r32/ebp
 4327     5d/pop-to-ebp
 4328     c3/return
 4329 
 4330 test-convert-function-with-branches-in-block:
 4331     # . prologue
 4332     55/push-ebp
 4333     89/<- %ebp 4/r32/esp
 4334     # setup
 4335     (clear-stream _test-input-stream)
 4336     (clear-stream $_test-input-buffered-file->buffer)
 4337     (clear-stream _test-output-stream)
 4338     (clear-stream $_test-output-buffered-file->buffer)
 4339     #
 4340     (write _test-input-stream "fn foo x: int {\n")
 4341     (write _test-input-stream "  {\n")
 4342     (write _test-input-stream "    break-if->=\n")
 4343     (write _test-input-stream "    loop-if-addr<\n")
 4344     (write _test-input-stream "    increment x\n")
 4345     (write _test-input-stream "    loop\n")
 4346     (write _test-input-stream "  }\n")
 4347     (write _test-input-stream "}\n")
 4348     # convert
 4349     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4350     (flush _test-output-buffered-file)
 4351 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4357     # check output
 4358     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-block/0")
 4359     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-block/1")
 4360     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-block/2")
 4361     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-block/3")
 4362     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-block/4")
 4363     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-block/5")
 4364     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-block/6")
 4365     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-in-block/7")
 4366     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/8")
 4367     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-block/9")
 4368     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-in-block/10")
 4369     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/11")
 4370     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/12")
 4371     (check-next-stream-line-equal _test-output-stream "        0f 83/jump-if-addr>= break/disp32"  "F - test-convert-function-with-branches-in-block/13")
 4372     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:loop/disp32"  "F - test-convert-function-with-branches-in-block/14")
 4373     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/15")
 4374     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-block/16")
 4375     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-in-block/17")
 4376     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-block/18")
 4377     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-in-block/19")
 4378     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-block/20")
 4379     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-block/21")
 4380     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-block/22")
 4381     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-block/23")
 4382     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-block/24")
 4383     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-block/25")
 4384     # . epilogue
 4385     89/<- %esp 5/r32/ebp
 4386     5d/pop-to-ebp
 4387     c3/return
 4388 
 4389 test-convert-function-with-branches-in-block-2:
 4390     # . prologue
 4391     55/push-ebp
 4392     89/<- %ebp 4/r32/esp
 4393     # setup
 4394     (clear-stream _test-input-stream)
 4395     (clear-stream $_test-input-buffered-file->buffer)
 4396     (clear-stream _test-output-stream)
 4397     (clear-stream $_test-output-buffered-file->buffer)
 4398     #
 4399     (write _test-input-stream "fn foo x: int {\n")
 4400     (write _test-input-stream "  {\n")
 4401     (write _test-input-stream "    break-if->=\n")
 4402     (write _test-input-stream "    loop-if-float<\n")
 4403     (write _test-input-stream "    increment x\n")
 4404     (write _test-input-stream "    loop\n")
 4405     (write _test-input-stream "  }\n")
 4406     (write _test-input-stream "}\n")
 4407     # convert
 4408     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4409     (flush _test-output-buffered-file)
 4410 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4416     # check output
 4417     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-block/0")
 4418     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-block/1")
 4419     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-block/2")
 4420     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-block/3")
 4421     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-block/4")
 4422     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-block/5")
 4423     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-block/6")
 4424     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-in-block/7")
 4425     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/8")
 4426     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-block/9")
 4427     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-in-block/10")
 4428     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/11")
 4429     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/12")
 4430     (check-next-stream-line-equal _test-output-stream "        0f 83/jump-if-addr>= break/disp32"  "F - test-convert-function-with-branches-in-block/13")
 4431     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:loop/disp32"  "F - test-convert-function-with-branches-in-block/14")
 4432     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/15")
 4433     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-block/16")
 4434     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-in-block/17")
 4435     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-block/18")
 4436     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-in-block/19")
 4437     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-block/20")
 4438     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-block/21")
 4439     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-block/22")
 4440     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-block/23")
 4441     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-block/24")
 4442     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-block/25")
 4443     # . epilogue
 4444     89/<- %esp 5/r32/ebp
 4445     5d/pop-to-ebp
 4446     c3/return
 4447 
 4448 test-convert-function-with-branches-in-named-block:
 4449     # . prologue
 4450     55/push-ebp
 4451     89/<- %ebp 4/r32/esp
 4452     # setup
 4453     (clear-stream _test-input-stream)
 4454     (clear-stream $_test-input-buffered-file->buffer)
 4455     (clear-stream _test-output-stream)
 4456     (clear-stream $_test-output-buffered-file->buffer)
 4457     #
 4458     (write _test-input-stream "fn foo x: int {\n")
 4459     (write _test-input-stream "  $bar: {\n")
 4460     (write _test-input-stream "    break-if->= $bar\n")
 4461     (write _test-input-stream "    loop-if-addr< $bar\n")
 4462     (write _test-input-stream "    increment x\n")
 4463     (write _test-input-stream "    loop\n")
 4464     (write _test-input-stream "  }\n")
 4465     (write _test-input-stream "}\n")
 4466     # convert
 4467     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4468     (flush _test-output-buffered-file)
 4469 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4475     # check output
 4476     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-named-block/0")
 4477     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-named-block/1")
 4478     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-named-block/2")
 4479     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-named-block/3")
 4480     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-named-block/4")
 4481     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-named-block/5")
 4482     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-named-block/6")
 4483     (check-next-stream-line-equal _test-output-stream "$bar:loop:"              "F - test-convert-function-with-branches-in-named-block/7")
 4484     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-named-block/8")
 4485     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-named-block/9")
 4486     (check-next-stream-line-equal _test-output-stream "        e9/jump $bar:break/disp32"  "F - test-convert-function-with-branches-in-named-block/10")
 4487     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-named-block/11")
 4488     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-named-block/12")
 4489     (check-next-stream-line-equal _test-output-stream "        0f 83/jump-if-addr>= break/disp32"  "F - test-convert-function-with-branches-in-named-block/13")
 4490     (check-next-stream-line-equal _test-output-stream "        e9/jump $bar:loop/disp32"  "F - test-convert-function-with-branches-in-named-block/14")
 4491     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-named-block/15")
 4492     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-named-block/16")
 4493     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"   "F - test-convert-function-with-branches-in-named-block/17")
 4494     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-named-block/18")
 4495     (check-next-stream-line-equal _test-output-stream "$bar:break:"             "F - test-convert-function-with-branches-in-named-block/19")
 4496     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-named-block/20")
 4497     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-named-block/21")
 4498     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-named-block/22")
 4499     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-named-block/23")
 4500     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-named-block/24")
 4501     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-named-block/25")
 4502     # . epilogue
 4503     89/<- %esp 5/r32/ebp
 4504     5d/pop-to-ebp
 4505     c3/return
 4506 
 4507 test-convert-function-with-var-in-nested-block:
 4508     # . prologue
 4509     55/push-ebp
 4510     89/<- %ebp 4/r32/esp
 4511     # setup
 4512     (clear-stream _test-input-stream)
 4513     (clear-stream $_test-input-buffered-file->buffer)
 4514     (clear-stream _test-output-stream)
 4515     (clear-stream $_test-output-buffered-file->buffer)
 4516     #
 4517     (write _test-input-stream "fn foo x: int {\n")
 4518     (write _test-input-stream "  {\n")
 4519     (write _test-input-stream "    {\n")
 4520     (write _test-input-stream "      var x: int\n")
 4521     (write _test-input-stream "      increment x\n")
 4522     (write _test-input-stream "    }\n")
 4523     (write _test-input-stream "  }\n")
 4524     (write _test-input-stream "}\n")
 4525     # convert
 4526     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4527     (flush _test-output-buffered-file)
 4528 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4534     # check output
 4535     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-var-in-nested-block/0")
 4536     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-var-in-nested-block/1")
 4537     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-var-in-nested-block/2")
 4538     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-var-in-nested-block/3")
 4539     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-var-in-nested-block/4")
 4540     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-var-in-nested-block/5")
 4541     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-var-in-nested-block/6")
 4542     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-var-in-nested-block/7")
 4543     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-var-in-nested-block/8")
 4544     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-var-in-nested-block/9")
 4545     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-var-in-nested-block/10")
 4546     (check-next-stream-line-equal _test-output-stream "        ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-var-in-nested-block/11")
 4547     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-var-in-nested-block/12")
 4548     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-var-in-nested-block/13")
 4549     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-var-in-nested-block/14")
 4550     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-var-in-nested-block/15")
 4551     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-var-in-nested-block/16")
 4552     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-var-in-nested-block/17")
 4553     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-var-in-nested-block/18")
 4554     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-var-in-nested-block/19")
 4555     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-var-in-nested-block/20")
 4556     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-var-in-nested-block/21")
 4557     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-var-in-nested-block/22")
 4558     # . epilogue
 4559     89/<- %esp 5/r32/ebp
 4560     5d/pop-to-ebp
 4561     c3/return
 4562 
 4563 test-convert-function-with-multiple-vars-in-nested-blocks:
 4564     # . prologue
 4565     55/push-ebp
 4566     89/<- %ebp 4/r32/esp
 4567     # setup
 4568     (clear-stream _test-input-stream)
 4569     (clear-stream $_test-input-buffered-file->buffer)
 4570     (clear-stream _test-output-stream)
 4571     (clear-stream $_test-output-buffered-file->buffer)
 4572     #
 4573     (write _test-input-stream "fn foo x: int {\n")
 4574     (write _test-input-stream "  {\n")
 4575     (write _test-input-stream "    var x/eax: int <- copy 0\n")
 4576     (write _test-input-stream "    {\n")
 4577     (write _test-input-stream "      var y: int\n")
 4578     (write _test-input-stream "      x <- add y\n")
 4579     (write _test-input-stream "    }\n")
 4580     (write _test-input-stream "  }\n")
 4581     (write _test-input-stream "}\n")
 4582     # convert
 4583     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4584     (flush _test-output-buffered-file)
 4585 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4591     # check output
 4592     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-multiple-vars-in-nested-blocks/0")
 4593     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-multiple-vars-in-nested-blocks/1")
 4594     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-multiple-vars-in-nested-blocks/2")
 4595     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/3")
 4596     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-multiple-vars-in-nested-blocks/4")
 4597     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/5")
 4598     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-multiple-vars-in-nested-blocks/6")
 4599     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/7")
 4600     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %eax"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/8")
 4601     (check-next-stream-line-equal _test-output-stream "      b8/copy-to-eax 0/imm32"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/9")
 4602     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-multiple-vars-in-nested-blocks/10")
 4603     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/11")
 4604     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-multiple-vars-in-nested-blocks/12")
 4605     (check-next-stream-line-equal _test-output-stream "        03/add *(ebp+0xfffffff8) 0x00000000/r32"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/13")
 4606     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/14")
 4607     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-multiple-vars-in-nested-blocks/15")
 4608     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/16")
 4609     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %eax"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/17")
 4610     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-multiple-vars-in-nested-blocks/18")
 4611     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/19")
 4612     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-multiple-vars-in-nested-blocks/20")
 4613     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/21")
 4614     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-multiple-vars-in-nested-blocks/22")
 4615     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/23")
 4616     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-multiple-vars-in-nested-blocks/24")
 4617     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-multiple-vars-in-nested-blocks/25")
 4618     # . epilogue
 4619     89/<- %esp 5/r32/ebp
 4620     5d/pop-to-ebp
 4621     c3/return
 4622 
 4623 test-convert-function-with-branches-and-local-vars:
 4624     # A conditional 'break' after a 'var' in a block is converted into a
 4625     # nested block that performs all necessary cleanup before jumping. This
 4626     # results in some ugly code duplication.
 4627     # . prologue
 4628     55/push-ebp
 4629     89/<- %ebp 4/r32/esp
 4630     # setup
 4631     (clear-stream _test-input-stream)
 4632     (clear-stream $_test-input-buffered-file->buffer)
 4633     (clear-stream _test-output-stream)
 4634     (clear-stream $_test-output-buffered-file->buffer)
 4635     #
 4636     (write _test-input-stream "fn foo {\n")
 4637     (write _test-input-stream "  {\n")
 4638     (write _test-input-stream "    var x: int\n")
 4639     (write _test-input-stream "    break-if->=\n")
 4640     (write _test-input-stream "    increment x\n")
 4641     (write _test-input-stream "  }\n")
 4642     (write _test-input-stream "}\n")
 4643     # convert
 4644     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4645     (flush _test-output-buffered-file)
 4646 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4652     # check output
 4653     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-and-local-vars/0")
 4654     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-and-local-vars/1")
 4655     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-and-local-vars/2")
 4656     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-and-local-vars/3")
 4657     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-and-local-vars/4")
 4658     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-and-local-vars/5")
 4659     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-and-local-vars/6")
 4660     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-and-local-vars/7")
 4661     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-branches-and-local-vars/8")
 4662     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-and-local-vars/9")
 4663     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-and-local-vars/10")
 4664     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-branches-and-local-vars/11")
 4665     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-and-local-vars/12")
 4666     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-and-local-vars/13")
 4667     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-branches-and-local-vars/14")
 4668     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-branches-and-local-vars/15")
 4669     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-and-local-vars/16")
 4670     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-and-local-vars/17")
 4671     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-and-local-vars/18")
 4672     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-and-local-vars/19")
 4673     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-and-local-vars/20")
 4674     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-and-local-vars/21")
 4675     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-and-local-vars/22")
 4676     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-and-local-vars/23")
 4677     # . epilogue
 4678     89/<- %esp 5/r32/ebp
 4679     5d/pop-to-ebp
 4680     c3/return
 4681 
 4682 test-convert-function-with-conditional-loops-and-local-vars:
 4683     # A conditional 'loop' after a 'var' in a block is converted into a nested
 4684     # block that performs all necessary cleanup before jumping. This results
 4685     # in some ugly code duplication.
 4686     # . prologue
 4687     55/push-ebp
 4688     89/<- %ebp 4/r32/esp
 4689     # setup
 4690     (clear-stream _test-input-stream)
 4691     (clear-stream $_test-input-buffered-file->buffer)
 4692     (clear-stream _test-output-stream)
 4693     (clear-stream $_test-output-buffered-file->buffer)
 4694     #
 4695     (write _test-input-stream "fn foo {\n")
 4696     (write _test-input-stream "  {\n")
 4697     (write _test-input-stream "    var x: int\n")
 4698     (write _test-input-stream "    loop-if->=\n")
 4699     (write _test-input-stream "    increment x\n")
 4700     (write _test-input-stream "  }\n")
 4701     (write _test-input-stream "}\n")
 4702     # convert
 4703     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4704     (flush _test-output-buffered-file)
 4705 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4711     # check output
 4712     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-conditional-loops-and-local-vars/0")
 4713     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-conditional-loops-and-local-vars/1")
 4714     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-conditional-loops-and-local-vars/2")
 4715     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-conditional-loops-and-local-vars/3")
 4716     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-conditional-loops-and-local-vars/4")
 4717     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-conditional-loops-and-local-vars/5")
 4718     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-conditional-loops-and-local-vars/6")
 4719     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-conditional-loops-and-local-vars/7")
 4720     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-conditional-loops-and-local-vars/8")
 4721     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-conditional-loops-and-local-vars/9")
 4722     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-conditional-loops-and-local-vars/10")
 4723     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-conditional-loops-and-local-vars/11")
 4724     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:loop/disp32"  "F - test-convert-function-with-conditional-loops-and-local-vars/12")
 4725     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-conditional-loops-and-local-vars/13")
 4726     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-conditional-loops-and-local-vars/14")
 4727     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-conditional-loops-and-local-vars/15")
 4728     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-conditional-loops-and-local-vars/16")
 4729     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-conditional-loops-and-local-vars/17")
 4730     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-conditional-loops-and-local-vars/18")
 4731     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-conditional-loops-and-local-vars/19")
 4732     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-conditional-loops-and-local-vars/20")
 4733     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-conditional-loops-and-local-vars/21")
 4734     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-conditional-loops-and-local-vars/22")
 4735     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-conditional-loops-and-local-vars/23")
 4736     # . epilogue
 4737     89/<- %esp 5/r32/ebp
 4738     5d/pop-to-ebp
 4739     c3/return
 4740 
 4741 test-convert-function-with-unconditional-loops-and-local-vars:
 4742     # An unconditional 'loop' after a 'var' in a block is emitted _after_ the
 4743     # regular block cleanup. Any instructions after 'loop' are dead and
 4744     # therefore skipped.
 4745     # . prologue
 4746     55/push-ebp
 4747     89/<- %ebp 4/r32/esp
 4748     # setup
 4749     (clear-stream _test-input-stream)
 4750     (clear-stream $_test-input-buffered-file->buffer)
 4751     (clear-stream _test-output-stream)
 4752     (clear-stream $_test-output-buffered-file->buffer)
 4753     #
 4754     (write _test-input-stream "fn foo {\n")
 4755     (write _test-input-stream "  {\n")
 4756     (write _test-input-stream "    var x: int\n")
 4757     (write _test-input-stream "    loop\n")
 4758     (write _test-input-stream "    increment x\n")
 4759     (write _test-input-stream "  }\n")
 4760     (write _test-input-stream "}\n")
 4761     # convert
 4762     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4763     (flush _test-output-buffered-file)
 4764 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4770     # check output
 4771     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-unconditional-loops-and-local-vars/0")
 4772     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-unconditional-loops-and-local-vars/1")
 4773     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-unconditional-loops-and-local-vars/2")
 4774     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-unconditional-loops-and-local-vars/3")
 4775     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-unconditional-loops-and-local-vars/4")
 4776     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-unconditional-loops-and-local-vars/5")
 4777     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-unconditional-loops-and-local-vars/6")
 4778     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-unconditional-loops-and-local-vars/7")
 4779     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-unconditional-loops-and-local-vars/8")
 4780     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-unconditional-loops-and-local-vars/9")
 4781     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-unconditional-loops-and-local-vars/10")
 4782     # not emitted:                                           ff 0/subop/increment *(ebp+0xfffffffc)
 4783     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-unconditional-loops-and-local-vars/11")
 4784     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-unconditional-loops-and-local-vars/12")
 4785     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-unconditional-loops-and-local-vars/13")
 4786     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-unconditional-loops-and-local-vars/14")
 4787     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-unconditional-loops-and-local-vars/15")
 4788     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-unconditional-loops-and-local-vars/16")
 4789     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-unconditional-loops-and-local-vars/17")
 4790     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-unconditional-loops-and-local-vars/18")
 4791     # . epilogue
 4792     89/<- %esp 5/r32/ebp
 4793     5d/pop-to-ebp
 4794     c3/return
 4795 
 4796 test-convert-function-with-branches-and-loops-and-local-vars:
 4797     # . prologue
 4798     55/push-ebp
 4799     89/<- %ebp 4/r32/esp
 4800     # setup
 4801     (clear-stream _test-input-stream)
 4802     (clear-stream $_test-input-buffered-file->buffer)
 4803     (clear-stream _test-output-stream)
 4804     (clear-stream $_test-output-buffered-file->buffer)
 4805     #
 4806     (write _test-input-stream "fn foo {\n")
 4807     (write _test-input-stream "  {\n")
 4808     (write _test-input-stream "    var x: int\n")
 4809     (write _test-input-stream "    break-if->=\n")
 4810     (write _test-input-stream "    increment x\n")
 4811     (write _test-input-stream "    loop\n")
 4812     (write _test-input-stream "  }\n")
 4813     (write _test-input-stream "}\n")
 4814     # convert
 4815     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4816     (flush _test-output-buffered-file)
 4817 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4823     # check output
 4824     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-and-loops-and-local-vars/0")
 4825     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-and-loops-and-local-vars/1")
 4826     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-and-loops-and-local-vars/2")
 4827     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-and-loops-and-local-vars/3")
 4828     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-and-loops-and-local-vars/4")
 4829     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-and-loops-and-local-vars/5")
 4830     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-and-loops-and-local-vars/6")
 4831     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-and-loops-and-local-vars/7")
 4832     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-branches-and-loops-and-local-vars/8")
 4833     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-and-loops-and-local-vars/9")
 4834     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-and-loops-and-local-vars/10")
 4835     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-branches-and-loops-and-local-vars/11")
 4836     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-and-loops-and-local-vars/12")
 4837     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-and-loops-and-local-vars/13")
 4838     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-branches-and-loops-and-local-vars/14")
 4839     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-branches-and-loops-and-local-vars/15")
 4840     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-and-loops-and-local-vars/16")
 4841     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-and-loops-and-local-vars/17")
 4842     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-and-loops-and-local-vars/18")
 4843     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-and-loops-and-local-vars/19")
 4844     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-and-loops-and-local-vars/20")
 4845     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-and-loops-and-local-vars/21")
 4846     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-and-loops-and-local-vars/22")
 4847     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-and-loops-and-local-vars/23")
 4848     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-and-loops-and-local-vars/24")
 4849     # . epilogue
 4850     89/<- %esp 5/r32/ebp
 4851     5d/pop-to-ebp
 4852     c3/return
 4853 
 4854 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars:
 4855     # . prologue
 4856     55/push-ebp
 4857     89/<- %ebp 4/r32/esp
 4858     # setup
 4859     (clear-stream _test-input-stream)
 4860     (clear-stream $_test-input-buffered-file->buffer)
 4861     (clear-stream _test-output-stream)
 4862     (clear-stream $_test-output-buffered-file->buffer)
 4863     #
 4864     (write _test-input-stream "fn foo {\n")
 4865     (write _test-input-stream "  a: {\n")
 4866     (write _test-input-stream "    var x: int\n")
 4867     (write _test-input-stream "    {\n")
 4868     (write _test-input-stream "      var y: int\n")
 4869     (write _test-input-stream "      break-if->= a\n")
 4870     (write _test-input-stream "      increment x\n")
 4871     (write _test-input-stream "      loop\n")
 4872     (write _test-input-stream "    }\n")
 4873     (write _test-input-stream "  }\n")
 4874     (write _test-input-stream "}\n")
 4875     # convert
 4876     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4877     (flush _test-output-buffered-file)
 4878 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4884     # check output
 4885     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/0")
 4886     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/1")
 4887     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/2")
 4888     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/3")
 4889     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/4")
 4890     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/5")
 4891     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/6")
 4892     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/7")
 4893     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/8")
 4894     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/9")
 4895     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/10")
 4896     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/11")
 4897     (check-next-stream-line-equal _test-output-stream "        {"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/12")
 4898     (check-next-stream-line-equal _test-output-stream "          0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/13")
 4899     (check-next-stream-line-equal _test-output-stream "          81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/14")
 4900     (check-next-stream-line-equal _test-output-stream "          81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/15")
 4901     (check-next-stream-line-equal _test-output-stream "          e9/jump a:break/disp32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/16")
 4902     (check-next-stream-line-equal _test-output-stream "        }"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/17")
 4903     (check-next-stream-line-equal _test-output-stream "        ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/18")
 4904     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/19")
 4905     (check-next-stream-line-equal _test-output-stream "        e9/jump loop/disp32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/20")
 4906     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/21")
 4907     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/22")
 4908     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/23")
 4909     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/24")
 4910     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/25")
 4911     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/26")
 4912     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/27")
 4913     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/28")
 4914     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/29")
 4915     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/30")
 4916     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/31")
 4917     # . epilogue
 4918     89/<- %esp 5/r32/ebp
 4919     5d/pop-to-ebp
 4920     c3/return
 4921 
 4922 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2:
 4923     # . prologue
 4924     55/push-ebp
 4925     89/<- %ebp 4/r32/esp
 4926     # setup
 4927     (clear-stream _test-input-stream)
 4928     (clear-stream $_test-input-buffered-file->buffer)
 4929     (clear-stream _test-output-stream)
 4930     (clear-stream $_test-output-buffered-file->buffer)
 4931     # non-local conditional branch from a block without a local variable,
 4932     # unwinding a local on the stack
 4933     (write _test-input-stream "fn foo {\n")
 4934     (write _test-input-stream "  a: {\n")
 4935     (write _test-input-stream "    var x: int\n")
 4936     (write _test-input-stream "    {\n")
 4937     (write _test-input-stream "      break-if->= a\n")
 4938     (write _test-input-stream "    }\n")
 4939     (write _test-input-stream "  }\n")
 4940     (write _test-input-stream "}\n")
 4941     # convert
 4942     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4943     (flush _test-output-buffered-file)
 4944 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4950     # check output
 4951     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/0")
 4952     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/1")
 4953     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/2")
 4954     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/3")
 4955     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/4")
 4956     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/5")
 4957     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/6")
 4958     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/7")
 4959     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/8")
 4960     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/9")
 4961     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/10")
 4962     (check-next-stream-line-equal _test-output-stream "        {"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/11")
 4963     (check-next-stream-line-equal _test-output-stream "          0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/12")
 4964     (check-next-stream-line-equal _test-output-stream "          81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/13")
 4965     (check-next-stream-line-equal _test-output-stream "          e9/jump a:break/disp32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/14")
 4966     (check-next-stream-line-equal _test-output-stream "        }"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/15")
 4967     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/16")
 4968     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/17")
 4969     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/18")
 4970     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/19")
 4971     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/20")
 4972     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/21")
 4973     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/22")
 4974     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/23")
 4975     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/24")
 4976     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/25")
 4977     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/26")
 4978     # . epilogue
 4979     89/<- %esp 5/r32/ebp
 4980     5d/pop-to-ebp
 4981     c3/return
 4982 
 4983 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3:
 4984     # . prologue
 4985     55/push-ebp
 4986     89/<- %ebp 4/r32/esp
 4987     # setup
 4988     (clear-stream _test-input-stream)
 4989     (clear-stream $_test-input-buffered-file->buffer)
 4990     (clear-stream _test-output-stream)
 4991     (clear-stream $_test-output-buffered-file->buffer)
 4992     # non-local unconditional branch from a block without a local variable,
 4993     # unwinding a local on the stack
 4994     (write _test-input-stream "fn foo {\n")
 4995     (write _test-input-stream "  a: {\n")
 4996     (write _test-input-stream "    var x: int\n")
 4997     (write _test-input-stream "    {\n")
 4998     (write _test-input-stream "      break a\n")
 4999     (write _test-input-stream "    }\n")
 5000     (write _test-input-stream "  }\n")
 5001     (write _test-input-stream "}\n")
 5002     # convert
 5003     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5004     (flush _test-output-buffered-file)
 5005 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5011     # check output
 5012     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/0")
 5013     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/1")
 5014     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/2")
 5015     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/3")
 5016     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/4")
 5017     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/5")
 5018     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/6")
 5019     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/7")
 5020     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/8")
 5021     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/9")
 5022     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/10")
 5023     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/11")
 5024     (check-next-stream-line-equal _test-output-stream "        e9/jump a:break/disp32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/12")
 5025     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/14")
 5026     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/15")
 5027     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/16")
 5028     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/17")
 5029     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/18")
 5030     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/19")
 5031     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/20")
 5032     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/21")
 5033     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/22")
 5034     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/23")
 5035     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/24")
 5036     # . epilogue
 5037     89/<- %esp 5/r32/ebp
 5038     5d/pop-to-ebp
 5039     c3/return
 5040 
 5041 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4:
 5042     # . prologue
 5043     55/push-ebp
 5044     89/<- %ebp 4/r32/esp
 5045     # setup
 5046     (clear-stream _test-input-stream)
 5047     (clear-stream $_test-input-buffered-file->buffer)
 5048     (clear-stream _test-output-stream)
 5049     (clear-stream $_test-output-buffered-file->buffer)
 5050     #
 5051     (write _test-input-stream "fn foo {\n")
 5052     (write _test-input-stream "  a: {\n")
 5053     (write _test-input-stream "    var x/esi: int <- copy 0\n")
 5054     (write _test-input-stream "    {\n")
 5055     (write _test-input-stream "      break a\n")
 5056     (write _test-input-stream "    }\n")
 5057     (write _test-input-stream "  }\n")
 5058     (write _test-input-stream "}\n")
 5059     # convert
 5060     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5061     (flush _test-output-buffered-file)
 5062 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5068     # check output
 5069     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/0")
 5070     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/1")
 5071     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/2")
 5072     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/3")
 5073     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/4")
 5074     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/5")
 5075     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/6")
 5076     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/7")
 5077     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %esi"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/8")
 5078     (check-next-stream-line-equal _test-output-stream "      be/copy-to-esi 0/imm32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/9")
 5079     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/10")
 5080     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/11")
 5081     (check-next-stream-line-equal _test-output-stream "        8f 0/subop/pop %esi"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/12")
 5082     (check-next-stream-line-equal _test-output-stream "        e9/jump a:break/disp32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/13")
 5083     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/14")
 5084     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/15")
 5085     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %esi"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/16")
 5086     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/17")
 5087     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/18")
 5088     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/19")
 5089     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/20")
 5090     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/21")
 5091     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/22")
 5092     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/23")
 5093     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/24")
 5094     # . epilogue
 5095     89/<- %esp 5/r32/ebp
 5096     5d/pop-to-ebp
 5097     c3/return
 5098 
 5099 test-convert-function-with-nonlocal-unconditional-break-and-local-vars:
 5100     # . prologue
 5101     55/push-ebp
 5102     89/<- %ebp 4/r32/esp
 5103     # setup
 5104     (clear-stream _test-input-stream)
 5105     (clear-stream $_test-input-buffered-file->buffer)
 5106     (clear-stream _test-output-stream)
 5107     (clear-stream $_test-output-buffered-file->buffer)
 5108     #
 5109     (write _test-input-stream "fn foo {\n")
 5110     (write _test-input-stream "  a: {\n")
 5111     (write _test-input-stream "    var x: int\n")
 5112     (write _test-input-stream "    {\n")
 5113     (write _test-input-stream "      var y: int\n")
 5114     (write _test-input-stream "      break a\n")
 5115     (write _test-input-stream "      increment x\n")
 5116     (write _test-input-stream "    }\n")
 5117     (write _test-input-stream "  }\n")
 5118     (write _test-input-stream "}\n")
 5119     # convert
 5120     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5121     (flush _test-output-buffered-file)
 5122 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5128     # check output
 5129     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/0")
 5130     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/1")
 5131     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/2")
 5132     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/3")
 5133     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/4")
 5134     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/5")
 5135     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/6")
 5136     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/7")
 5137     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/8")
 5138     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/9")
 5139     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/10")
 5140     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/11")
 5141     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/12")
 5142     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/13")
 5143     (check-next-stream-line-equal _test-output-stream "        e9/jump a:break/disp32"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/14")
 5144     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/15")
 5145     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/16")
 5146     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/17")
 5147     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/18")
 5148     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/19")
 5149     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/20")
 5150     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/21")
 5151     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/22")
 5152     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/23")
 5153     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/24")
 5154     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/25")
 5155     # . epilogue
 5156     89/<- %esp 5/r32/ebp
 5157     5d/pop-to-ebp
 5158     c3/return
 5159 
 5160 test-convert-function-with-unconditional-break-and-local-vars:
 5161     # . prologue
 5162     55/push-ebp
 5163     89/<- %ebp 4/r32/esp
 5164     # setup
 5165     (clear-stream _test-input-stream)
 5166     (clear-stream $_test-input-buffered-file->buffer)
 5167     (clear-stream _test-output-stream)
 5168     (clear-stream $_test-output-buffered-file->buffer)
 5169     #
 5170     (write _test-input-stream "fn foo {\n")
 5171     (write _test-input-stream "  {\n")
 5172     (write _test-input-stream "    var x: int\n")
 5173     (write _test-input-stream "    {\n")
 5174     (write _test-input-stream "      var y: int\n")
 5175     (write _test-input-stream "      break\n")
 5176     (write _test-input-stream "      increment x\n")
 5177     (write _test-input-stream "    }\n")
 5178     (write _test-input-stream "  }\n")
 5179     (write _test-input-stream "}\n")
 5180     # convert
 5181     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5182     (flush _test-output-buffered-file)
 5183 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5189     # check output
 5190     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-unconditional-break-and-local-vars/0")
 5191     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-unconditional-break-and-local-vars/1")
 5192     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-unconditional-break-and-local-vars/2")
 5193     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-unconditional-break-and-local-vars/3")
 5194     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-unconditional-break-and-local-vars/4")
 5195     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/5")
 5196     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-unconditional-break-and-local-vars/6")
 5197     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/7")
 5198     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-unconditional-break-and-local-vars/8")
 5199     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-unconditional-break-and-local-vars/9")
 5200     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/10")
 5201     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-unconditional-break-and-local-vars/11")
 5202     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-unconditional-break-and-local-vars/12")
 5203     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-unconditional-break-and-local-vars/13")
 5204     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/14")
 5205     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-unconditional-break-and-local-vars/15")
 5206     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-unconditional-break-and-local-vars/16")
 5207     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/17")
 5208     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-unconditional-break-and-local-vars/18")
 5209     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/19")
 5210     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-unconditional-break-and-local-vars/20")
 5211     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-unconditional-break-and-local-vars/21")
 5212     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-unconditional-break-and-local-vars/22")
 5213     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-unconditional-break-and-local-vars/23")
 5214     # . epilogue
 5215     89/<- %esp 5/r32/ebp
 5216     5d/pop-to-ebp
 5217     c3/return
 5218 
 5219 test-convert-function-with-nonlocal-unconditional-loop-and-local-vars:
 5220     # . prologue
 5221     55/push-ebp
 5222     89/<- %ebp 4/r32/esp
 5223     # setup
 5224     (clear-stream _test-input-stream)
 5225     (clear-stream $_test-input-buffered-file->buffer)
 5226     (clear-stream _test-output-stream)
 5227     (clear-stream $_test-output-buffered-file->buffer)
 5228     #
 5229     (write _test-input-stream "fn foo {\n")
 5230     (write _test-input-stream "  a: {\n")
 5231     (write _test-input-stream "    var x: int\n")
 5232     (write _test-input-stream "    {\n")
 5233     (write _test-input-stream "      var y: int\n")
 5234     (write _test-input-stream "      loop a\n")
 5235     (write _test-input-stream "      increment x\n")
 5236     (write _test-input-stream "    }\n")
 5237     (write _test-input-stream "  }\n")
 5238     (write _test-input-stream "}\n")
 5239     # convert
 5240     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5241     (flush _test-output-buffered-file)
 5242 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5248     # check output
 5249     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/0")
 5250     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/1")
 5251     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/2")
 5252     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/3")
 5253     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/4")
 5254     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/5")
 5255     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/6")
 5256     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/7")
 5257     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/8")
 5258     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/9")
 5259     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/10")
 5260     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/11")
 5261     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/12")
 5262     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/13")
 5263     (check-next-stream-line-equal _test-output-stream "        e9/jump a:loop/disp32"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/14")
 5264     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/15")
 5265     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/16")
 5266     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/17")
 5267     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/18")
 5268     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/19")
 5269     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/20")
 5270     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/21")
 5271     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/22")
 5272     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/23")
 5273     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/24")
 5274     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/25")
 5275     # . epilogue
 5276     89/<- %esp 5/r32/ebp
 5277     5d/pop-to-ebp
 5278     c3/return
 5279 
 5280 test-convert-function-with-local-array-var-in-mem:
 5281     # . prologue
 5282     55/push-ebp
 5283     89/<- %ebp 4/r32/esp
 5284     # setup
 5285     (clear-stream _test-input-stream)
 5286     (clear-stream $_test-input-buffered-file->buffer)
 5287     (clear-stream _test-output-stream)
 5288     (clear-stream $_test-output-buffered-file->buffer)
 5289     #
 5290     (write _test-input-stream "fn foo {\n")
 5291     (write _test-input-stream "  var x: (array int 3)\n")
 5292     (write _test-input-stream "}\n")
 5293     # convert
 5294     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5295     (flush _test-output-buffered-file)
 5296 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5302     # check output
 5303     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-array-var-in-mem/0")
 5304     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-array-var-in-mem/1")
 5305     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-array-var-in-mem/2")
 5306     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-array-var-in-mem/3")
 5307     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-array-var-in-mem/4")
 5308     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-array-var-in-mem/5")
 5309     # define x
 5310     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"  "F - test-convert-function-with-local-array-var-in-mem/7")
 5311     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"  "F - test-convert-function-with-local-array-var-in-mem/8")
 5312     # reclaim x
 5313     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"  "F - test-convert-function-with-local-array-var-in-mem/9")
 5314     #
 5315     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-array-var-in-mem/10")
 5316     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-array-var-in-mem/11")
 5317     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-array-var-in-mem/12")
 5318     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-array-var-in-mem/13")
 5319     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-array-var-in-mem/14")
 5320     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-array-var-in-mem/15")
 5321     # . epilogue
 5322     89/<- %esp 5/r32/ebp
 5323     5d/pop-to-ebp
 5324     c3/return
 5325 
 5326 test-array-size-in-hex:
 5327     # . prologue
 5328     55/push-ebp
 5329     89/<- %ebp 4/r32/esp
 5330     # setup
 5331     (clear-stream _test-input-stream)
 5332     (clear-stream $_test-input-buffered-file->buffer)
 5333     (clear-stream _test-output-stream)
 5334     (clear-stream $_test-output-buffered-file->buffer)
 5335     (clear-stream _test-error-stream)
 5336     (clear-stream $_test-error-buffered-file->buffer)
 5337     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 5338     68/push 0/imm32
 5339     68/push 0/imm32
 5340     89/<- %edx 4/r32/esp
 5341     (tailor-exit-descriptor %edx 0x10)
 5342     #
 5343     (write _test-input-stream "fn foo {\n")
 5344     (write _test-input-stream "  var x: (array int 10)\n")
 5345     (write _test-input-stream "}\n")
 5346     # convert
 5347     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 5348     # registers except esp clobbered at this point
 5349     # restore ed
 5350     89/<- %edx 4/r32/esp
 5351     (flush _test-output-buffered-file)
 5352     (flush _test-error-buffered-file)
 5353 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5359     # check output
 5360     (check-stream-equal _test-output-stream  ""  "F - test-array-size-in-hex: output should be empty")
 5361     (check-next-stream-line-equal _test-error-stream  "literal integers are always hex in Mu; start '10' with a '0x' to be unambiguous, converting it to hexadecimal as necessary."  "F - test-array-size-in-hex: error message")
 5362     # check that stop(1) was called
 5363     (check-ints-equal *(edx+4) 2 "F - test-array-size-in-hex: exit status")
 5364     # don't restore from ebp
 5365     81 0/subop/add %esp 8/imm32
 5366     # . epilogue
 5367     5d/pop-to-ebp
 5368     c3/return
 5369 
 5370 test-convert-function-with-populate:
 5371     # . prologue
 5372     55/push-ebp
 5373     89/<- %ebp 4/r32/esp
 5374     # setup
 5375     (clear-stream _test-input-stream)
 5376     (clear-stream $_test-input-buffered-file->buffer)
 5377     (clear-stream _test-output-stream)
 5378     (clear-stream $_test-output-buffered-file->buffer)
 5379     #
 5380     (write _test-input-stream "fn foo {\n")
 5381     (write _test-input-stream "  var x/ecx: (addr handle array int) <- copy 0\n")
 5382     (write _test-input-stream "  populate x, 7\n")
 5383     (write _test-input-stream "}\n")
 5384     # convert
 5385     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5386     (flush _test-output-buffered-file)
 5387 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5393     # check output
 5394     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-populate/0")
 5395     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-populate/1")
 5396     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-populate/2")
 5397     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-populate/3")
 5398     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-populate/4")
 5399     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-populate/5")
 5400     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-populate/6")
 5401     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-populate/7")
 5402     (check-next-stream-line-equal _test-output-stream "    (allocate-array2 Heap 0x00000004 7 %ecx)"  "F - test-convert-function-with-populate/8")  # 4 = size-of(int)
 5403     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-populate/9")
 5404     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-populate/10")
 5405     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-populate/11")
 5406     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-populate/12")
 5407     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-populate/13")
 5408     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-populate/14")
 5409     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-populate/15")
 5410     # . epilogue
 5411     89/<- %esp 5/r32/ebp
 5412     5d/pop-to-ebp
 5413     c3/return
 5414 
 5415 # special-case for size(byte) when allocating array
 5416 test-convert-function-with-local-array-of-bytes-in-mem:
 5417     # . prologue
 5418     55/push-ebp
 5419     89/<- %ebp 4/r32/esp
 5420     # setup
 5421     (clear-stream _test-input-stream)
 5422     (clear-stream $_test-input-buffered-file->buffer)
 5423     (clear-stream _test-output-stream)
 5424     (clear-stream $_test-output-buffered-file->buffer)
 5425     #
 5426     (write _test-input-stream "fn foo {\n")
 5427     (write _test-input-stream "  var x: (array byte 3)\n")
 5428     (write _test-input-stream "}\n")
 5429     # convert
 5430     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5431     (flush _test-output-buffered-file)
 5432 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5438     # check output
 5439     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-array-of-bytes-in-mem/0")
 5440     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-array-of-bytes-in-mem/1")
 5441     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-array-of-bytes-in-mem/2")
 5442     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-array-of-bytes-in-mem/3")
 5443     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-array-of-bytes-in-mem/4")
 5444     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-array-of-bytes-in-mem/5")
 5445     # define x
 5446     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x00000003)"  "F - test-convert-function-with-local-array-of-bytes-in-mem/7")
 5447     (check-next-stream-line-equal _test-output-stream "    68/push 0x00000003/imm32"  "F - test-convert-function-with-local-array-of-bytes-in-mem/8")
 5448     # reclaim x
 5449     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000007/imm32"  "F - test-convert-function-with-local-array-of-bytes-in-mem/9")
 5450     #
 5451     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-array-of-bytes-in-mem/10")
 5452     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-array-of-bytes-in-mem/11")
 5453     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-array-of-bytes-in-mem/12")
 5454     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-array-of-bytes-in-mem/13")
 5455     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-array-of-bytes-in-mem/14")
 5456     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-array-of-bytes-in-mem/15")
 5457     # . epilogue
 5458     89/<- %esp 5/r32/ebp
 5459     5d/pop-to-ebp
 5460     c3/return
 5461 
 5462 test-convert-address:
 5463     # . prologue
 5464     55/push-ebp
 5465     89/<- %ebp 4/r32/esp
 5466     # setup
 5467     (clear-stream _test-input-stream)
 5468     (clear-stream $_test-input-buffered-file->buffer)
 5469     (clear-stream _test-output-stream)
 5470     (clear-stream $_test-output-buffered-file->buffer)
 5471     #
 5472     (write _test-input-stream "fn foo {\n")
 5473     (write _test-input-stream "  var a: int\n")
 5474     (write _test-input-stream "  var b/eax: (addr int) <- address a\n")
 5475     (write _test-input-stream "}\n")
 5476     # convert
 5477     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5478     (flush _test-output-buffered-file)
 5479 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5485     # check output
 5486     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-address/0")
 5487     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-address/1")
 5488     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-address/2")
 5489     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-address/3")
 5490     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-address/4")
 5491     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-address/5")
 5492     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-address/6")
 5493     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-address/7")
 5494     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0xfffffffc) 0x00000000/r32"  "F - test-convert-address/8")
 5495     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-address/9")
 5496     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-address/10")
 5497     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-address/11")
 5498     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-address/12")
 5499     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-address/13")
 5500     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-address/14")
 5501     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-address/15")
 5502     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-address/16")
 5503     # . epilogue
 5504     89/<- %esp 5/r32/ebp
 5505     5d/pop-to-ebp
 5506     c3/return
 5507 
 5508 test-convert-floating-point-convert:
 5509     # . prologue
 5510     55/push-ebp
 5511     89/<- %ebp 4/r32/esp
 5512     # setup
 5513     (clear-stream _test-input-stream)
 5514     (clear-stream $_test-input-buffered-file->buffer)
 5515     (clear-stream _test-output-stream)
 5516     (clear-stream $_test-output-buffered-file->buffer)
 5517     #
 5518     (write _test-input-stream "fn foo {\n")
 5519     (write _test-input-stream "  var a/eax: int <- copy 0\n")
 5520     (write _test-input-stream "  var b/xmm1: float <- convert a\n")
 5521     (write _test-input-stream "}\n")
 5522     # convert
 5523     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5524     (flush _test-output-buffered-file)
 5525 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5531     # check output
 5532     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-floating-point-convert/0")
 5533     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-floating-point-convert/1")
 5534     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-floating-point-convert/2")
 5535     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-floating-point-convert/3")
 5536     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-floating-point-convert/4")
 5537     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-floating-point-convert/5")
 5538     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-floating-point-convert/6")
 5539     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-floating-point-convert/7")
 5540     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"  "F - test-convert-floating-point-convert/8")
 5541     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"  "F - test-convert-floating-point-convert/9")
 5542     (check-next-stream-line-equal _test-output-stream "    f3 0f 2a/convert-to-float %eax 0x00000001/x32"  "F - test-convert-floating-point-convert/10")
 5543     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"  "F - test-convert-floating-point-convert/11")
 5544     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-floating-point-convert/12")
 5545     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-floating-point-convert/13")
 5546     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-floating-point-convert/14")
 5547     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-floating-point-convert/15")
 5548     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-floating-point-convert/16")
 5549     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-floating-point-convert/17")
 5550     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-floating-point-convert/18")
 5551     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-floating-point-convert/19")
 5552     # . epilogue
 5553     89/<- %esp 5/r32/ebp
 5554     5d/pop-to-ebp
 5555     c3/return
 5556 
 5557 test-convert-floating-point-convert-2:
 5558     # . prologue
 5559     55/push-ebp
 5560     89/<- %ebp 4/r32/esp
 5561     # setup
 5562     (clear-stream _test-input-stream)
 5563     (clear-stream $_test-input-buffered-file->buffer)
 5564     (clear-stream _test-output-stream)
 5565     (clear-stream $_test-output-buffered-file->buffer)
 5566     #
 5567     (write _test-input-stream "fn foo {\n")
 5568     (write _test-input-stream "  var a/eax: int <- copy 0\n")
 5569     (write _test-input-stream "  var b/xmm1: float <- convert a\n")
 5570     (write _test-input-stream "  a <- convert b\n")
 5571     (write _test-input-stream "}\n")
 5572     # convert
 5573     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5574     (flush _test-output-buffered-file)
 5575 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5581     # check output
 5582     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-floating-point-convert-2/0")
 5583     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-floating-point-convert-2/1")
 5584     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-floating-point-convert-2/2")
 5585     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-floating-point-convert-2/3")
 5586     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-floating-point-convert-2/4")
 5587     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-floating-point-convert-2/5")
 5588     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-floating-point-convert-2/6")
 5589     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-floating-point-convert-2/7")
 5590     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"  "F - test-convert-floating-point-convert-2/8")
 5591     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"  "F - test-convert-floating-point-convert-2/9")
 5592     (check-next-stream-line-equal _test-output-stream "    f3 0f 2a/convert-to-float %eax 0x00000001/x32"  "F - test-convert-floating-point-convert-2/10")
 5593     (check-next-stream-line-equal _test-output-stream "    f3 0f 2d/convert-to-int %xmm1 0x00000000/r32"  "F - test-convert-floating-point-convert-2/11")
 5594     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"  "F - test-convert-floating-point-convert-2/12")
 5595     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-floating-point-convert-2/13")
 5596     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-floating-point-convert-2/14")
 5597     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-floating-point-convert-2/15")
 5598     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-floating-point-convert-2/16")
 5599     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-floating-point-convert-2/17")
 5600     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-floating-point-convert-2/18")
 5601     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-floating-point-convert-2/19")
 5602     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-floating-point-convert-2/20")
 5603     # . epilogue
 5604     89/<- %esp 5/r32/ebp
 5605     5d/pop-to-ebp
 5606     c3/return
 5607 
 5608 test-convert-floating-point-operation:
 5609     # . prologue
 5610     55/push-ebp
 5611     89/<- %ebp 4/r32/esp
 5612     # setup
 5613     (clear-stream _test-input-stream)
 5614     (clear-stream $_test-input-buffered-file->buffer)
 5615     (clear-stream _test-output-stream)
 5616     (clear-stream $_test-output-buffered-file->buffer)
 5617     #
 5618     (write _test-input-stream "fn f {\n")
 5619     (write _test-input-stream "  var m: float\n")
 5620     (write _test-input-stream "  var x/xmm1: float <- copy m\n")
 5621     (write _test-input-stream "  var y/xmm5: float <- copy m\n")
 5622     (write _test-input-stream "  x <- copy y\n")
 5623     (write _test-input-stream "  copy-to m, y\n")
 5624     (write _test-input-stream "  x <- add y\n")
 5625     (write _test-input-stream "  x <- add m\n")
 5626     (write _test-input-stream "  x <- subtract y\n")
 5627     (write _test-input-stream "  x <- subtract m\n")
 5628     (write _test-input-stream "  x <- multiply y\n")
 5629     (write _test-input-stream "  x <- multiply m\n")
 5630     (write _test-input-stream "  x <- divide y\n")
 5631     (write _test-input-stream "  x <- divide m\n")
 5632     (write _test-input-stream "  x <- reciprocal y\n")
 5633     (write _test-input-stream "  x <- reciprocal m\n")
 5634     (write _test-input-stream "  x <- square-root y\n")
 5635     (write _test-input-stream "  x <- square-root m\n")
 5636     (write _test-input-stream "  x <- inverse-square-root y\n")
 5637     (write _test-input-stream "  x <- inverse-square-root m\n")
 5638     (write _test-input-stream "  x <- max y\n")
 5639     (write _test-input-stream "  x <- max m\n")
 5640     (write _test-input-stream "  x <- min y\n")
 5641     (write _test-input-stream "  x <- min m\n")
 5642     (write _test-input-stream "  compare x, y\n")
 5643     (write _test-input-stream "  compare x, m\n")
 5644     (write _test-input-stream "}\n")
 5645     # convert
 5646     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5647     (flush _test-output-buffered-file)
 5648 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5654     # check output
 5655     (check-next-stream-line-equal _test-output-stream "f:"                                                                     "F - test-convert-floating-point-operation/0")
 5656     (check-next-stream-line-equal _test-output-stream "  # . prologue"                                                         "F - test-convert-floating-point-operation/1")
 5657     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                                                          "F - test-convert-floating-point-operation/2")
 5658     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                                                 "F - test-convert-floating-point-operation/3")
 5659     (check-next-stream-line-equal _test-output-stream "  {"                                                                    "F - test-convert-floating-point-operation/4")
 5660     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"                                                    "F - test-convert-floating-point-operation/5")
 5661     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                                                    "F - test-convert-floating-point-operation/6")
 5662     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-operation/7")
 5663     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"                                             "F - test-convert-floating-point-operation/8")
 5664     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-operation/9")
 5665     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-operation/10")
 5666     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 5/x32"                                             "F - test-convert-floating-point-operation/11")
 5667     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000005/x32"                     "F - test-convert-floating-point-operation/12")
 5668     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/copy %xmm1 0x00000005/x32"                                 "F - test-convert-floating-point-operation/13")
 5669     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/copy *(ebp+0xfffffffc) 0x00000005/x32"                     "F - test-convert-floating-point-operation/14")
 5670     (check-next-stream-line-equal _test-output-stream "    f3 0f 58/add %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/15")
 5671     (check-next-stream-line-equal _test-output-stream "    f3 0f 58/add *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/16")
 5672     (check-next-stream-line-equal _test-output-stream "    f3 0f 5c/subtract %xmm5 0x00000001/x32"                             "F - test-convert-floating-point-operation/17")
 5673     (check-next-stream-line-equal _test-output-stream "    f3 0f 5c/subtract *(ebp+0xfffffffc) 0x00000001/x32"                 "F - test-convert-floating-point-operation/18")
 5674     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply %xmm5 0x00000001/x32"                             "F - test-convert-floating-point-operation/19")
 5675     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply *(ebp+0xfffffffc) 0x00000001/x32"                 "F - test-convert-floating-point-operation/20")
 5676     (check-next-stream-line-equal _test-output-stream "    f3 0f 5e/divide %xmm5 0x00000001/x32"                               "F - test-convert-floating-point-operation/21")
 5677     (check-next-stream-line-equal _test-output-stream "    f3 0f 5e/divide *(ebp+0xfffffffc) 0x00000001/x32"                   "F - test-convert-floating-point-operation/22")
 5678     (check-next-stream-line-equal _test-output-stream "    f3 0f 53/reciprocal %xmm5 0x00000001/x32"                           "F - test-convert-floating-point-operation/23")
 5679     (check-next-stream-line-equal _test-output-stream "    f3 0f 53/reciprocal *(ebp+0xfffffffc) 0x00000001/x32"               "F - test-convert-floating-point-operation/24")
 5680     (check-next-stream-line-equal _test-output-stream "    f3 0f 51/square-root %xmm5 0x00000001/x32"                          "F - test-convert-floating-point-operation/25")
 5681     (check-next-stream-line-equal _test-output-stream "    f3 0f 51/square-root *(ebp+0xfffffffc) 0x00000001/x32"              "F - test-convert-floating-point-operation/26")
 5682     (check-next-stream-line-equal _test-output-stream "    f3 0f 52/inverse-square-root %xmm5 0x00000001/x32"                  "F - test-convert-floating-point-operation/27")
 5683     (check-next-stream-line-equal _test-output-stream "    f3 0f 52/inverse-square-root *(ebp+0xfffffffc) 0x00000001/x32"      "F - test-convert-floating-point-operation/28")
 5684     (check-next-stream-line-equal _test-output-stream "    f3 0f 5f/max %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/29")
 5685     (check-next-stream-line-equal _test-output-stream "    f3 0f 5f/max *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/30")
 5686     (check-next-stream-line-equal _test-output-stream "    f3 0f 5d/min %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/31")
 5687     (check-next-stream-line-equal _test-output-stream "    f3 0f 5d/min *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/32")
 5688     (check-next-stream-line-equal _test-output-stream "    0f 2f/compare %xmm1 0x00000005/x32"                                 "F - test-convert-floating-point-operation/33")
 5689     (check-next-stream-line-equal _test-output-stream "    0f 2f/compare *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-operation/34")
 5690     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 5/x32"                                             "F - test-convert-floating-point-operation/35")
 5691     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-operation/36")
 5692     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"                                             "F - test-convert-floating-point-operation/37")
 5693     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-operation/38")
 5694     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"                               "F - test-convert-floating-point-operation/39")
 5695     (check-next-stream-line-equal _test-output-stream "  }"                                                                    "F - test-convert-floating-point-operation/40")
 5696     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"                                                   "F - test-convert-floating-point-operation/41")
 5697     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                                                         "F - test-convert-floating-point-operation/42")
 5698     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                                                 "F - test-convert-floating-point-operation/43")
 5699     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                                                        "F - test-convert-floating-point-operation/44")
 5700     (check-next-stream-line-equal _test-output-stream "  c3/return"                                                            "F - test-convert-floating-point-operation/45")
 5701     # . epilogue
 5702     89/<- %esp 5/r32/ebp
 5703     5d/pop-to-ebp
 5704     c3/return
 5705 
 5706 test-convert-floating-point-dereferenced:
 5707     # . prologue
 5708     55/push-ebp
 5709     89/<- %ebp 4/r32/esp
 5710     # setup
 5711     (clear-stream _test-input-stream)
 5712     (clear-stream $_test-input-buffered-file->buffer)
 5713     (clear-stream _test-output-stream)
 5714     (clear-stream $_test-output-buffered-file->buffer)
 5715     #
 5716     (write _test-input-stream "fn f {\n")
 5717     (write _test-input-stream "  var m: float\n")
 5718     (write _test-input-stream "  var x/xmm1: float <- copy m\n")
 5719     (write _test-input-stream "  var y/eax: (addr float) <- copy 0\n")
 5720     (write _test-input-stream "  x <- multiply *y\n")
 5721     (write _test-input-stream "}\n")
 5722     # convert
 5723     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5724     (flush _test-output-buffered-file)
 5725 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5731     # check output
 5732     (check-next-stream-line-equal _test-output-stream "f:"                                                                     "F - test-convert-floating-point-dereferenced/0")
 5733     (check-next-stream-line-equal _test-output-stream "  # . prologue"                                                         "F - test-convert-floating-point-dereferenced/1")
 5734     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                                                          "F - test-convert-floating-point-dereferenced/2")
 5735     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                                                 "F - test-convert-floating-point-dereferenced/3")
 5736     (check-next-stream-line-equal _test-output-stream "  {"                                                                    "F - test-convert-floating-point-dereferenced/4")
 5737     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"                                                    "F - test-convert-floating-point-dereferenced/5")
 5738     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                                                    "F - test-convert-floating-point-dereferenced/6")
 5739     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-dereferenced/7")
 5740     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"                                             "F - test-convert-floating-point-dereferenced/8")
 5741     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-dereferenced/9")
 5742     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                                               "F - test-convert-floating-point-dereferenced/10")
 5743     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                                             "F - test-convert-floating-point-dereferenced/11")
 5744     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply *eax 0x00000001/x32"                              "F - test-convert-floating-point-dereferenced/12")
 5745     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                                                "F - test-convert-floating-point-dereferenced/13")
 5746     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"                                             "F - test-convert-floating-point-dereferenced/14")
 5747     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-dereferenced/15")
 5748     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"                               "F - test-convert-floating-point-dereferenced/16")
 5749     (check-next-stream-line-equal _test-output-stream "  }"                                                                    "F - test-convert-floating-point-dereferenced/17")
 5750     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"                                                   "F - test-convert-floating-point-dereferenced/18")
 5751     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                                                         "F - test-convert-floating-point-dereferenced/19")
 5752     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                                                 "F - test-convert-floating-point-dereferenced/20")
 5753     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                                                        "F - test-convert-floating-point-dereferenced/21")
 5754     (check-next-stream-line-equal _test-output-stream "  c3/return"                                                            "F - test-convert-floating-point-dereferenced/22")
 5755     # . epilogue
 5756     89/<- %esp 5/r32/ebp
 5757     5d/pop-to-ebp
 5758     c3/return
 5759 
 5760 test-convert-length-of-array:
 5761     # . prologue
 5762     55/push-ebp
 5763     89/<- %ebp 4/r32/esp
 5764     # setup
 5765     (clear-stream _test-input-stream)
 5766     (clear-stream $_test-input-buffered-file->buffer)
 5767     (clear-stream _test-output-stream)
 5768     (clear-stream $_test-output-buffered-file->buffer)
 5769     #
 5770     (write _test-input-stream "fn foo a: (addr array int) {\n")
 5771     (write _test-input-stream "  var b/eax: (addr array int) <- copy a\n")
 5772     (write _test-input-stream "  var c/eax: int <- length b\n")
 5773     (write _test-input-stream "}\n")
 5774     # convert
 5775     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5776     (flush _test-output-buffered-file)
 5777 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5783     # check output
 5784     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array/0")
 5785     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array/1")
 5786     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array/2")
 5787     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array/3")
 5788     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array/4")
 5789     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array/5")
 5790     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array/6")
 5791     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-length-of-array/7")
 5792     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array/8")
 5793     (check-next-stream-line-equal _test-output-stream "    c1/shift 5/subop/>> %eax 0x00000002/imm8"  "F - test-convert-length-of-array/9")
 5794     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array/10")
 5795     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array/11")
 5796     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array/12")
 5797     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array/13")
 5798     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array/14")
 5799     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array/15")
 5800     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array/16")
 5801     # . epilogue
 5802     89/<- %esp 5/r32/ebp
 5803     5d/pop-to-ebp
 5804     c3/return
 5805 
 5806 # special-case for size(byte) when computing array length
 5807 test-convert-length-of-array-of-bytes:
 5808     # . prologue
 5809     55/push-ebp
 5810     89/<- %ebp 4/r32/esp
 5811     # setup
 5812     (clear-stream _test-input-stream)
 5813     (clear-stream $_test-input-buffered-file->buffer)
 5814     (clear-stream _test-output-stream)
 5815     (clear-stream $_test-output-buffered-file->buffer)
 5816     #
 5817     (write _test-input-stream "fn foo a: (addr array byte) {\n")
 5818     (write _test-input-stream "  var b/eax: (addr array byte) <- copy a\n")
 5819     (write _test-input-stream "  var c/eax: int <- length b\n")
 5820     (write _test-input-stream "}\n")
 5821     # convert
 5822     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5823     (flush _test-output-buffered-file)
 5824 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5830     # check output
 5831     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-bytes/0")
 5832     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-bytes/1")
 5833     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-bytes/2")
 5834     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-bytes/3")
 5835     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-bytes/4")
 5836     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-bytes/5")
 5837     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-of-bytes/6")
 5838     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-length-of-array-of-bytes/7")
 5839     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array-of-bytes/8")
 5840     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-of-bytes/9")
 5841     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-bytes/10")
 5842     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-bytes/11")
 5843     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-bytes/12")
 5844     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-of-bytes/13")
 5845     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-of-bytes/14")
 5846     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-bytes/15")
 5847     # . epilogue
 5848     89/<- %esp 5/r32/ebp
 5849     5d/pop-to-ebp
 5850     c3/return
 5851 
 5852 test-convert-length-of-array-on-stack:
 5853     # . prologue
 5854     55/push-ebp
 5855     89/<- %ebp 4/r32/esp
 5856     # setup
 5857     (clear-stream _test-input-stream)
 5858     (clear-stream $_test-input-buffered-file->buffer)
 5859     (clear-stream _test-output-stream)
 5860     (clear-stream $_test-output-buffered-file->buffer)
 5861     #
 5862     (write _test-input-stream "fn foo {\n")
 5863     (write _test-input-stream "  var a: (array int 3)\n")
 5864     (write _test-input-stream "  var b/eax: int <- length a\n")
 5865     (write _test-input-stream "}\n")
 5866     # convert
 5867     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5868     (flush _test-output-buffered-file)
 5869 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5875     # check output
 5876     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-on-stack/0")
 5877     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-on-stack/1")
 5878     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-on-stack/2")
 5879     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-on-stack/3")
 5880     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-on-stack/4")
 5881     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-on-stack/5")
 5882     # define x
 5883     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"  "F - test-convert-length-of-array-on-stack/6")
 5884     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"  "F - test-convert-length-of-array-on-stack/7")
 5885     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-on-stack/8")
 5886     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0xfffffff0) 0x00000000/r32"  "F - test-convert-length-of-array-on-stack/9")
 5887     (check-next-stream-line-equal _test-output-stream "    c1/shift 5/subop/>> %eax 0x00000002/imm8"  "F - test-convert-length-of-array-on-stack/10")
 5888     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-on-stack/11")
 5889     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"  "F - test-convert-length-of-array-on-stack/12")
 5890     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-on-stack/13")
 5891     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-on-stack/14")
 5892     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-on-stack/15")
 5893     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-on-stack/16")
 5894     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-on-stack/17")
 5895     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-on-stack/18")
 5896     # . epilogue
 5897     89/<- %esp 5/r32/ebp
 5898     5d/pop-to-ebp
 5899     c3/return
 5900 
 5901 test-reg-var-def-with-read-of-same-register:
 5902     # . prologue
 5903     55/push-ebp
 5904     89/<- %ebp 4/r32/esp
 5905     # setup
 5906     (clear-stream _test-input-stream)
 5907     (clear-stream $_test-input-buffered-file->buffer)
 5908     (clear-stream _test-output-stream)
 5909     (clear-stream $_test-output-buffered-file->buffer)
 5910     (clear-stream _test-error-stream)
 5911     (clear-stream $_test-error-buffered-file->buffer)
 5912     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
 5913     68/push 0/imm32
 5914     68/push 0/imm32
 5915     89/<- %edx 4/r32/esp
 5916     (tailor-exit-descriptor %edx 0x10)
 5917     #
 5918     (write _test-input-stream "fn foo {\n")
 5919     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 5920     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 5921     (write _test-input-stream "  var x/eax: (addr int) <- index arr, idx\n")
 5922     (write _test-input-stream "}\n")
 5923     # convert
 5924     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 5925     # registers except esp could be clobbered at this point (though they shouldn't be)
 5926     # restore ed
 5927     89/<- %edx 4/r32/esp
 5928     (flush _test-output-buffered-file)
 5929     (flush _test-error-buffered-file)
 5930 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5936 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5942     (check-stream-equal _test-error-stream  ""  "F - test-reg-var-def-with-read-of-same-register: error stream should be empty")
 5943     # check output
 5944     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-reg-var-def-with-read-of-same-register/0")
 5945     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-reg-var-def-with-read-of-same-register/1")
 5946     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-reg-var-def-with-read-of-same-register/2")
 5947     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-reg-var-def-with-read-of-same-register/3")
 5948     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-reg-var-def-with-read-of-same-register/4")
 5949     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-reg-var-def-with-read-of-same-register/5")
 5950     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-reg-var-def-with-read-of-same-register/6")
 5951     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-reg-var-def-with-read-of-same-register/7")
 5952     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-reg-var-def-with-read-of-same-register/8")
 5953     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-reg-var-def-with-read-of-same-register/9")
 5954     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx<<0x00000002 + 4) 0x00000000/r32"  "F - test-reg-var-def-with-read-of-same-register/11")
 5955     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-reg-var-def-with-read-of-same-register/13")
 5956     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-reg-var-def-with-read-of-same-register/14")
 5957     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-reg-var-def-with-read-of-same-register/15")
 5958     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-reg-var-def-with-read-of-same-register/16")
 5959     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-reg-var-def-with-read-of-same-register/17")
 5960     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-reg-var-def-with-read-of-same-register/18")
 5961     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-reg-var-def-with-read-of-same-register/19")
 5962     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-reg-var-def-with-read-of-same-register/20")
 5963     # don't restore from ebp
 5964     81 0/subop/add %esp 8/imm32
 5965     # . epilogue
 5966     5d/pop-to-ebp
 5967     c3/return
 5968 
 5969 test-convert-index-into-array:
 5970     # . prologue
 5971     55/push-ebp
 5972     89/<- %ebp 4/r32/esp
 5973     # setup
 5974     (clear-stream _test-input-stream)
 5975     (clear-stream $_test-input-buffered-file->buffer)
 5976     (clear-stream _test-output-stream)
 5977     (clear-stream $_test-output-buffered-file->buffer)
 5978     #
 5979     (write _test-input-stream "fn foo {\n")
 5980     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 5981     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 5982     (write _test-input-stream "  var x/eax: (addr int) <- index arr, idx\n")
 5983     (write _test-input-stream "}\n")
 5984     # convert
 5985     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5986     (flush _test-output-buffered-file)
 5987 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5993     # check output
 5994     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array/0")
 5995     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array/1")
 5996     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array/2")
 5997     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array/3")
 5998     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array/4")
 5999     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array/5")
 6000     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array/6")
 6001     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array/7")
 6002     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array/8")
 6003     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array/9")
 6004     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx<<0x00000002 + 4) 0x00000000/r32"  "F - test-convert-index-into-array/10")
 6005     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array/11")
 6006     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array/12")
 6007     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array/13")
 6008     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array/14")
 6009     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array/15")
 6010     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array/16")
 6011     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array/17")
 6012     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array/18")
 6013     # . epilogue
 6014     89/<- %esp 5/r32/ebp
 6015     5d/pop-to-ebp
 6016     c3/return
 6017 
 6018 test-convert-index-into-array-of-bytes:
 6019     # . prologue
 6020     55/push-ebp
 6021     89/<- %ebp 4/r32/esp
 6022     # setup
 6023     (clear-stream _test-input-stream)
 6024     (clear-stream $_test-input-buffered-file->buffer)
 6025     (clear-stream _test-output-stream)
 6026     (clear-stream $_test-output-buffered-file->buffer)
 6027     #
 6028     (write _test-input-stream "fn foo {\n")
 6029     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 6030     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 6031     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, idx\n")
 6032     (write _test-input-stream "}\n")
 6033     # convert
 6034     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6035     (flush _test-output-buffered-file)
 6036 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6042     # check output
 6043     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes/0")
 6044     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes/1")
 6045     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes/2")
 6046     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes/3")
 6047     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes/4")
 6048     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes/5")
 6049     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes/6")
 6050     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-of-bytes/7")
 6051     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-of-bytes/8")
 6052     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array-of-bytes/9")
 6053     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx<<0x00000000 + 4) 0x00000000/r32"  "F - test-convert-index-into-array-of-bytes/11")
 6054     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes/13")
 6055     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes/14")
 6056     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes/15")
 6057     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes/16")
 6058     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes/17")
 6059     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes/18")
 6060     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes/19")
 6061     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes/20")
 6062     # . epilogue
 6063     89/<- %esp 5/r32/ebp
 6064     5d/pop-to-ebp
 6065     c3/return
 6066 
 6067 test-convert-index-into-array-with-literal:
 6068     # . prologue
 6069     55/push-ebp
 6070     89/<- %ebp 4/r32/esp
 6071     # setup
 6072     (clear-stream _test-input-stream)
 6073     (clear-stream $_test-input-buffered-file->buffer)
 6074     (clear-stream _test-output-stream)
 6075     (clear-stream $_test-output-buffered-file->buffer)
 6076     #
 6077     (write _test-input-stream "fn foo {\n")
 6078     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 6079     (write _test-input-stream "  var x/eax: (addr int) <- index arr, 2\n")
 6080     (write _test-input-stream "}\n")
 6081     # convert
 6082     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6083     (flush _test-output-buffered-file)
 6084 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6090     # check output
 6091     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-with-literal/0")
 6092     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-with-literal/1")
 6093     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-with-literal/2")
 6094     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-with-literal/3")
 6095     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-with-literal/4")
 6096     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-with-literal/5")
 6097     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-with-literal/6")
 6098     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-with-literal/7")
 6099                                                                                  # 2 * 4 bytes/elem + 4 bytes for size = offset 12
 6100     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x0000000c) 0x00000000/r32"  "F - test-convert-index-into-array-with-literal/8")
 6101     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-with-literal/9")
 6102     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-with-literal/10")
 6103     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-with-literal/11")
 6104     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-with-literal/12")
 6105     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-with-literal/13")
 6106     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-with-literal/14")
 6107     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-with-literal/15")
 6108     # . epilogue
 6109     89/<- %esp 5/r32/ebp
 6110     5d/pop-to-ebp
 6111     c3/return
 6112 
 6113 test-convert-index-into-array-of-bytes-with-literal:
 6114     # . prologue
 6115     55/push-ebp
 6116     89/<- %ebp 4/r32/esp
 6117     # setup
 6118     (clear-stream _test-input-stream)
 6119     (clear-stream $_test-input-buffered-file->buffer)
 6120     (clear-stream _test-output-stream)
 6121     (clear-stream $_test-output-buffered-file->buffer)
 6122     #
 6123     (write _test-input-stream "fn foo {\n")
 6124     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 6125     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, 2\n")
 6126     (write _test-input-stream "}\n")
 6127     # convert
 6128     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6129     (flush _test-output-buffered-file)
 6130 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6136     # check output
 6137     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-with-literal/0")
 6138     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-with-literal/1")
 6139     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-with-literal/2")
 6140     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes-with-literal/3")
 6141     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-with-literal/4")
 6142     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-with-literal/5")
 6143     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes-with-literal/6")
 6144     (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")
 6145                                                                                  # 2 * 1 byte/elem + 4 bytes for size = offset 6
 6146     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x00000006) 0x00000000/r32"  "F - test-convert-index-into-array-of-bytes-with-literal/8")
 6147     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-with-literal/9")
 6148     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-with-literal/10")
 6149     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-with-literal/11")
 6150     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-with-literal/12")
 6151     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-with-literal/13")
 6152     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-with-literal/14")
 6153     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-with-literal/15")
 6154     # . epilogue
 6155     89/<- %esp 5/r32/ebp
 6156     5d/pop-to-ebp
 6157     c3/return
 6158 
 6159 test-convert-index-into-array-on-stack:
 6160     # . prologue
 6161     55/push-ebp
 6162     89/<- %ebp 4/r32/esp
 6163     # setup
 6164     (clear-stream _test-input-stream)
 6165     (clear-stream $_test-input-buffered-file->buffer)
 6166     (clear-stream _test-output-stream)
 6167     (clear-stream $_test-output-buffered-file->buffer)
 6168     #
 6169     (write _test-input-stream "fn foo {\n")
 6170     (write _test-input-stream "  var arr: (array int 3)\n")
 6171     (write _test-input-stream "  var idx/eax: int <- copy 2\n")
 6172     (write _test-input-stream "  var x/eax: (addr int) <- index arr, idx\n")
 6173     (write _test-input-stream "}\n")
 6174     # convert
 6175     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6176     (flush _test-output-buffered-file)
 6177 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6183     # check output
 6184     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-on-stack/0")
 6185     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-on-stack/1")
 6186     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-on-stack/2")
 6187     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-on-stack/3")
 6188     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-on-stack/4")
 6189     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-on-stack/5")
 6190     # var arr
 6191     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"          "F - test-convert-index-into-array-on-stack/6")
 6192     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"                "F - test-convert-index-into-array-on-stack/7")
 6193     # var idx
 6194     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-on-stack/8")
 6195     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 2/imm32"                  "F - test-convert-index-into-array-on-stack/9")
 6196     # var x is at (ebp-0x10) + idx<<2 + 4 = ebp + idx<<2 - 0xc
 6197     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp + eax<<0x00000002 + 0xfffffff4) 0x00000000/r32"  "F - test-convert-index-into-array-on-stack/10")
 6198     # reclaim idx
 6199     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-on-stack/11")
 6200     # reclaim arr
 6201     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"    "F - test-convert-index-into-array-on-stack/12")
 6202     #
 6203     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-on-stack/13")
 6204     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-on-stack/14")
 6205     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-on-stack/15")
 6206     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-on-stack/16")
 6207     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-on-stack/17")
 6208     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-on-stack/18")
 6209     # . epilogue
 6210     89/<- %esp 5/r32/ebp
 6211     5d/pop-to-ebp
 6212     c3/return
 6213 
 6214 test-convert-index-into-array-on-stack-with-literal:
 6215     # . prologue
 6216     55/push-ebp
 6217     89/<- %ebp 4/r32/esp
 6218     # setup
 6219     (clear-stream _test-input-stream)
 6220     (clear-stream $_test-input-buffered-file->buffer)
 6221     (clear-stream _test-output-stream)
 6222     (clear-stream $_test-output-buffered-file->buffer)
 6223     #
 6224     (write _test-input-stream "fn foo {\n")
 6225     (write _test-input-stream "  var arr: (array int 3)\n")
 6226     (write _test-input-stream "  var x/eax: (addr int) <- index arr, 2\n")
 6227     (write _test-input-stream "}\n")
 6228     # convert
 6229     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6230     (flush _test-output-buffered-file)
 6231 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6237     # check output
 6238     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-on-stack-with-literal/0")
 6239     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-on-stack-with-literal/1")
 6240     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-on-stack-with-literal/2")
 6241     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-on-stack-with-literal/3")
 6242     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-on-stack-with-literal/4")
 6243     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-on-stack-with-literal/5")
 6244     # var arr
 6245     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"          "F - test-convert-index-into-array-on-stack-with-literal/6")
 6246     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"                "F - test-convert-index-into-array-on-stack-with-literal/7")
 6247     # var x
 6248     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-on-stack-with-literal/8")
 6249     # x is at (ebp-0x10) + 4 + 2*4 = ebp-4
 6250     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp + 0xfffffffc) 0x00000000/r32"  "F - test-convert-index-into-array-on-stack-with-literal/9")
 6251     # reclaim x
 6252     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-on-stack-with-literal/10")
 6253     # reclaim arr
 6254     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"    "F - test-convert-index-into-array-on-stack-with-literal/11")
 6255     #
 6256     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-on-stack-with-literal/12")
 6257     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-on-stack-with-literal/13")
 6258     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-on-stack-with-literal/14")
 6259     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-on-stack-with-literal/15")
 6260     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-on-stack-with-literal/16")
 6261     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-on-stack-with-literal/17")
 6262     # . epilogue
 6263     89/<- %esp 5/r32/ebp
 6264     5d/pop-to-ebp
 6265     c3/return
 6266 
 6267 test-convert-index-into-array-of-bytes-on-stack-with-literal:
 6268     # . prologue
 6269     55/push-ebp
 6270     89/<- %ebp 4/r32/esp
 6271     # setup
 6272     (clear-stream _test-input-stream)
 6273     (clear-stream $_test-input-buffered-file->buffer)
 6274     (clear-stream _test-output-stream)
 6275     (clear-stream $_test-output-buffered-file->buffer)
 6276     #
 6277     (write _test-input-stream "fn foo {\n")
 6278     (write _test-input-stream "  var arr: (array byte 3)\n")
 6279     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, 2\n")
 6280     (write _test-input-stream "}\n")
 6281     # convert
 6282     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6283     (flush _test-output-buffered-file)
 6284 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6290     # check output
 6291     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/0")
 6292     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/1")
 6293     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/2")
 6294     (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")
 6295     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/4")
 6296     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/5")
 6297     # var arr
 6298     (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")
 6299     (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")
 6300     # var x
 6301     (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")
 6302     # x is at (ebp-7) + 4 + 2 = ebp-1
 6303     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp + 0xffffffff) 0x00000000/r32"  "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/9")
 6304     # reclaim x
 6305     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/10")
 6306     # reclaim arr
 6307     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000007/imm32"    "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/11")
 6308     #
 6309     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/12")
 6310     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/13")
 6311     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/14")
 6312     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/15")
 6313     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/16")
 6314     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/17")
 6315     # . epilogue
 6316     89/<- %esp 5/r32/ebp
 6317     5d/pop-to-ebp
 6318     c3/return
 6319 
 6320 test-convert-index-into-array-using-offset:
 6321     # . prologue
 6322     55/push-ebp
 6323     89/<- %ebp 4/r32/esp
 6324     # setup
 6325     (clear-stream _test-input-stream)
 6326     (clear-stream $_test-input-buffered-file->buffer)
 6327     (clear-stream _test-output-stream)
 6328     (clear-stream $_test-output-buffered-file->buffer)
 6329     #
 6330     (write _test-input-stream "fn foo {\n")
 6331     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 6332     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 6333     (write _test-input-stream "  var off/ecx: (offset int) <- compute-offset arr, idx\n")
 6334     (write _test-input-stream "  var x/eax: (addr int) <- index arr, off\n")
 6335     (write _test-input-stream "}\n")
 6336     # convert
 6337     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6338     (flush _test-output-buffered-file)
 6339 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6345     # check output
 6346     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-using-offset/0")
 6347     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-using-offset/1")
 6348     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-using-offset/2")
 6349     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-using-offset/3")
 6350     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-using-offset/4")
 6351     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-using-offset/5")
 6352     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-using-offset/6")
 6353     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-using-offset/7")
 6354     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-using-offset/8")
 6355     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array-using-offset/9")
 6356     (check-next-stream-line-equal _test-output-stream "    69/multiply %ecx 0x00000004/imm32 0x00000001/r32"  "F - test-convert-index-into-array-using-offset/10")
 6357     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx + 4) 0x00000000/r32"  "F - test-convert-index-into-array-using-offset/11")
 6358     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-using-offset/12")
 6359     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-using-offset/13")
 6360     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-using-offset/14")
 6361     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-using-offset/15")
 6362     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-using-offset/16")
 6363     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-using-offset/17")
 6364     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-using-offset/18")
 6365     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-using-offset/19")
 6366     # . epilogue
 6367     89/<- %esp 5/r32/ebp
 6368     5d/pop-to-ebp
 6369     c3/return
 6370 
 6371 test-convert-index-into-array-of-bytes-using-offset:
 6372     # . prologue
 6373     55/push-ebp
 6374     89/<- %ebp 4/r32/esp
 6375     # setup
 6376     (clear-stream _test-input-stream)
 6377     (clear-stream $_test-input-buffered-file->buffer)
 6378     (clear-stream _test-output-stream)
 6379     (clear-stream $_test-output-buffered-file->buffer)
 6380     #
 6381     (write _test-input-stream "fn foo {\n")
 6382     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 6383     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 6384     (write _test-input-stream "  var off/ecx: (offset byte) <- compute-offset arr, idx\n")
 6385     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, off\n")
 6386     (write _test-input-stream "}\n")
 6387     # convert
 6388     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6389     (flush _test-output-buffered-file)
 6390 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6396     # check output
 6397     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-using-offset/0")
 6398     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-using-offset/1")
 6399     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-using-offset/2")
 6400     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes-using-offset/3")
 6401     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-using-offset/4")
 6402     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-using-offset/5")
 6403     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes-using-offset/6")
 6404     (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")
 6405     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-of-bytes-using-offset/8")
 6406     (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")
 6407     (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")
 6408     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx + 4) 0x00000000/r32"  "F - test-convert-index-into-array-of-bytes-using-offset/11")
 6409     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes-using-offset/12")
 6410     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-using-offset/13")
 6411     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-using-offset/14")
 6412     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-using-offset/15")
 6413     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-using-offset/16")
 6414     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-using-offset/17")
 6415     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-using-offset/18")
 6416     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-using-offset/19")
 6417     # . epilogue
 6418     89/<- %esp 5/r32/ebp
 6419     5d/pop-to-ebp
 6420     c3/return
 6421 
 6422 test-convert-index-into-array-using-offset-on-stack:
 6423     # . prologue
 6424     55/push-ebp
 6425     89/<- %ebp 4/r32/esp
 6426     # setup
 6427     (clear-stream _test-input-stream)
 6428     (clear-stream $_test-input-buffered-file->buffer)
 6429     (clear-stream _test-output-stream)
 6430     (clear-stream $_test-output-buffered-file->buffer)
 6431     #
 6432     (write _test-input-stream "fn foo {\n")
 6433     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 6434     (write _test-input-stream "  var idx: int\n")
 6435     (write _test-input-stream "  var off/ecx: (offset int) <- compute-offset arr, idx\n")
 6436     (write _test-input-stream "  var x/eax: (addr int) <- index arr, off\n")
 6437     (write _test-input-stream "}\n")
 6438     # convert
 6439     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6440     (flush _test-output-buffered-file)
 6441 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6447     # check output
 6448     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-using-offset-on-stack/0")
 6449     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-using-offset-on-stack/1")
 6450     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-using-offset-on-stack/2")
 6451     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-using-offset-on-stack/3")
 6452     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-using-offset-on-stack/4")
 6453     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-using-offset-on-stack/5")
 6454     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-using-offset-on-stack/6")
 6455     (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")
 6456     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                         "F - test-convert-index-into-array-using-offset-on-stack/8")
 6457     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-using-offset-on-stack/9")
 6458     (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")
 6459     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx + 4) 0x00000000/r32"  "F - test-convert-index-into-array-using-offset-on-stack/11")
 6460     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-using-offset-on-stack/12")
 6461     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"    "F - test-convert-index-into-array-using-offset-on-stack/13")
 6462     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-using-offset-on-stack/14")
 6463     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-using-offset-on-stack/15")
 6464     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-using-offset-on-stack/16")
 6465     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-using-offset-on-stack/17")
 6466     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-using-offset-on-stack/18")
 6467     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-using-offset-on-stack/19")
 6468     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-using-offset-on-stack/20")
 6469     # . epilogue
 6470     89/<- %esp 5/r32/ebp
 6471     5d/pop-to-ebp
 6472     c3/return
 6473 
 6474 test-convert-index-into-array-of-bytes-using-offset-on-stack:
 6475     # . prologue
 6476     55/push-ebp
 6477     89/<- %ebp 4/r32/esp
 6478     # setup
 6479     (clear-stream _test-input-stream)
 6480     (clear-stream $_test-input-buffered-file->buffer)
 6481     (clear-stream _test-output-stream)
 6482     (clear-stream $_test-output-buffered-file->buffer)
 6483     #
 6484     (write _test-input-stream "fn foo {\n")
 6485     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 6486     (write _test-input-stream "  var idx: int\n")
 6487     (write _test-input-stream "  var off/ecx: (offset byte) <- compute-offset arr, idx\n")
 6488     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, off\n")
 6489     (write _test-input-stream "}\n")
 6490     # convert
 6491     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6492     (flush _test-output-buffered-file)
 6493 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6499     # check output
 6500     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/0")
 6501     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/1")
 6502     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/2")
 6503     (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")
 6504     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/4")
 6505     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/5")
 6506     (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")
 6507     (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")
 6508     (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")
 6509     (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")
 6510     (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")
 6511     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx + 4) 0x00000000/r32"  "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/11")
 6512     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/12")
 6513     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"    "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/13")
 6514     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/14")
 6515     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/15")
 6516     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/16")
 6517     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/17")
 6518     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/18")
 6519     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/19")
 6520     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/20")
 6521     # . epilogue
 6522     89/<- %esp 5/r32/ebp
 6523     5d/pop-to-ebp
 6524     c3/return
 6525 
 6526 test-convert-function-and-type-definition:
 6527     # . prologue
 6528     55/push-ebp
 6529     89/<- %ebp 4/r32/esp
 6530     # setup
 6531     (clear-stream _test-input-stream)
 6532     (clear-stream $_test-input-buffered-file->buffer)
 6533     (clear-stream _test-output-stream)
 6534     (clear-stream $_test-output-buffered-file->buffer)
 6535     #
 6536     (write _test-input-stream "fn foo a: (addr t) {\n")
 6537     (write _test-input-stream "  var _a/eax: (addr t) <- copy a\n")
 6538     (write _test-input-stream "  var b/ecx: (addr int) <- get _a, x\n")
 6539     (write _test-input-stream "  var c/ecx: (addr int) <- get _a, y\n")
 6540     (write _test-input-stream "}\n")
 6541     (write _test-input-stream "type t {\n")
 6542     (write _test-input-stream "  x: int\n")
 6543     (write _test-input-stream "  y: int\n")
 6544     (write _test-input-stream "}\n")
 6545     # convert
 6546     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6547     (flush _test-output-buffered-file)
 6548 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6554     # check output
 6555     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-and-type-definition/0")
 6556     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-and-type-definition/1")
 6557     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-and-type-definition/2")
 6558     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-and-type-definition/3")
 6559     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-and-type-definition/4")
 6560     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-and-type-definition/5")
 6561     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-and-type-definition/6")
 6562     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-and-type-definition/7")
 6563     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-and-type-definition/8")
 6564     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x00000000) 0x00000001/r32"  "F - test-convert-function-and-type-definition/9")
 6565     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x00000004) 0x00000001/r32"  "F - test-convert-function-and-type-definition/11")
 6566     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-and-type-definition/13")
 6567     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-and-type-definition/14")
 6568     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-and-type-definition/15")
 6569     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-and-type-definition/16")
 6570     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-and-type-definition/17")
 6571     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-and-type-definition/18")
 6572     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-and-type-definition/19")
 6573     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-and-type-definition/20")
 6574     # . epilogue
 6575     89/<- %esp 5/r32/ebp
 6576     5d/pop-to-ebp
 6577     c3/return
 6578 
 6579 test-type-definition-with-array:
 6580     # . prologue
 6581     55/push-ebp
 6582     89/<- %ebp 4/r32/esp
 6583     # setup
 6584     (clear-stream _test-input-stream)
 6585     (clear-stream $_test-input-buffered-file->buffer)
 6586     (clear-stream _test-output-stream)
 6587     (clear-stream $_test-output-buffered-file->buffer)
 6588     (clear-stream _test-error-stream)
 6589     (clear-stream $_test-error-buffered-file->buffer)
 6590     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6591     68/push 0/imm32
 6592     68/push 0/imm32
 6593     89/<- %edx 4/r32/esp
 6594     (tailor-exit-descriptor %edx 0x10)
 6595     #
 6596     (write _test-input-stream "type t {\n")
 6597     (write _test-input-stream "  a: (array int 3)\n")
 6598     (write _test-input-stream "}\n")
 6599     # convert
 6600     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6601     # registers except esp clobbered at this point
 6602     # restore ed
 6603     89/<- %edx 4/r32/esp
 6604     (flush _test-output-buffered-file)
 6605     (flush _test-error-buffered-file)
 6606 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6612     # check output
 6613     (check-stream-equal _test-output-stream  ""  "F - test-type-definition-with-array: output should be empty")
 6614     (check-next-stream-line-equal _test-error-stream  "type t: 'array' elements not allowed for now"  "F - test-type-definition-with-array: error message")
 6615     # check that stop(1) was called
 6616     (check-ints-equal *(edx+4) 2 "F - test-type-definition-with-array: exit status")
 6617     # don't restore from ebp
 6618     81 0/subop/add %esp 8/imm32
 6619     # . epilogue
 6620     5d/pop-to-ebp
 6621     c3/return
 6622 
 6623 test-type-definition-with-addr:
 6624     # . prologue
 6625     55/push-ebp
 6626     89/<- %ebp 4/r32/esp
 6627     # setup
 6628     (clear-stream _test-input-stream)
 6629     (clear-stream $_test-input-buffered-file->buffer)
 6630     (clear-stream _test-output-stream)
 6631     (clear-stream $_test-output-buffered-file->buffer)
 6632     (clear-stream _test-error-stream)
 6633     (clear-stream $_test-error-buffered-file->buffer)
 6634     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6635     68/push 0/imm32
 6636     68/push 0/imm32
 6637     89/<- %edx 4/r32/esp
 6638     (tailor-exit-descriptor %edx 0x10)
 6639     #
 6640     (write _test-input-stream "type t {\n")
 6641     (write _test-input-stream "  a: (addr int)\n")
 6642     (write _test-input-stream "}\n")
 6643     # convert
 6644     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6645     # registers except esp clobbered at this point
 6646     # restore ed
 6647     89/<- %edx 4/r32/esp
 6648     (flush _test-output-buffered-file)
 6649     (flush _test-error-buffered-file)
 6650 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6656     # check output
 6657     (check-stream-equal _test-output-stream  ""  "F - test-type-definition-with-addr: output should be empty")
 6658     (check-next-stream-line-equal _test-error-stream  "type t: 'addr' elements not allowed"  "F - test-type-definition-with-addr: error message")
 6659     # check that stop(1) was called
 6660     (check-ints-equal *(edx+4) 2 "F - test-type-definition-with-addr: exit status")
 6661     # don't restore from ebp
 6662     81 0/subop/add %esp 8/imm32
 6663     # . epilogue
 6664     5d/pop-to-ebp
 6665     c3/return
 6666 
 6667 test-convert-function-with-local-var-with-user-defined-type:
 6668     # . prologue
 6669     55/push-ebp
 6670     89/<- %ebp 4/r32/esp
 6671     # setup
 6672     (clear-stream _test-input-stream)
 6673     (clear-stream $_test-input-buffered-file->buffer)
 6674     (clear-stream _test-output-stream)
 6675     (clear-stream $_test-output-buffered-file->buffer)
 6676     #
 6677     (write _test-input-stream "fn foo {\n")
 6678     (write _test-input-stream "  var a: t\n")
 6679     (write _test-input-stream "}\n")
 6680     (write _test-input-stream "type t {\n")
 6681     (write _test-input-stream "  x: int\n")
 6682     (write _test-input-stream "  y: int\n")
 6683     (write _test-input-stream "}\n")
 6684     # convert
 6685     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6686     (flush _test-output-buffered-file)
 6687 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6693     # check output
 6694     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-with-user-defined-type/0")
 6695     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-with-user-defined-type/1")
 6696     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-with-user-defined-type/2")
 6697     (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")
 6698     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-user-defined-type/4")
 6699     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-with-user-defined-type/5")
 6700     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-user-defined-type/6")
 6701     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-user-defined-type/7")
 6702     (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")
 6703     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-user-defined-type/9")
 6704     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-with-user-defined-type/10")
 6705     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-with-user-defined-type/11")
 6706     (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")
 6707     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-with-user-defined-type/13")
 6708     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-with-user-defined-type/14")
 6709     # . epilogue
 6710     89/<- %esp 5/r32/ebp
 6711     5d/pop-to-ebp
 6712     c3/return
 6713 
 6714 test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type:
 6715     # . prologue
 6716     55/push-ebp
 6717     89/<- %ebp 4/r32/esp
 6718     # setup
 6719     (clear-stream _test-input-stream)
 6720     (clear-stream $_test-input-buffered-file->buffer)
 6721     (clear-stream _test-output-stream)
 6722     (clear-stream $_test-output-buffered-file->buffer)
 6723     #
 6724     (write _test-input-stream "fn foo {\n")
 6725     (write _test-input-stream "  var a: t\n")
 6726     (write _test-input-stream "}\n")
 6727     (write _test-input-stream "type t {\n")
 6728     (write _test-input-stream "  x: s\n")
 6729     (write _test-input-stream "}\n")
 6730     (write _test-input-stream "type s {\n")
 6731     (write _test-input-stream "  z: int\n")
 6732     (write _test-input-stream "}\n")
 6733     # convert
 6734     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6735     (flush _test-output-buffered-file)
 6736 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6742     # check output
 6743     (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")
 6744     (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")
 6745     (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")
 6746     (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")
 6747     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/4")
 6748     (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")
 6749     (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")
 6750     (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")
 6751     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/9")
 6752     (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")
 6753     (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")
 6754     (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")
 6755     (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")
 6756     (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")
 6757     # . epilogue
 6758     89/<- %esp 5/r32/ebp
 6759     5d/pop-to-ebp
 6760     c3/return
 6761 
 6762 test-convert-function-call-with-arg-of-user-defined-type:
 6763     # . prologue
 6764     55/push-ebp
 6765     89/<- %ebp 4/r32/esp
 6766     # setup
 6767     (clear-stream _test-input-stream)
 6768     (clear-stream $_test-input-buffered-file->buffer)
 6769     (clear-stream _test-output-stream)
 6770     (clear-stream $_test-output-buffered-file->buffer)
 6771     #
 6772     (write _test-input-stream "fn f {\n")
 6773     (write _test-input-stream "  var a: t\n")
 6774     (write _test-input-stream "  foo a\n")
 6775     (write _test-input-stream "}\n")
 6776     (write _test-input-stream "fn foo x: t {\n")
 6777     (write _test-input-stream "}\n")
 6778     (write _test-input-stream "type t {\n")
 6779     (write _test-input-stream "  x: int\n")
 6780     (write _test-input-stream "  y: int\n")
 6781     (write _test-input-stream "}\n")
 6782     # convert
 6783     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6784     (flush _test-output-buffered-file)
 6785 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6791     # check output
 6792     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type/0")
 6793     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/1")
 6794     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/2")
 6795     (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")
 6796     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type/4")
 6797     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-arg-of-user-defined-type/5")
 6798     # var a: t
 6799     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-arg-of-user-defined-type/6")
 6800     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-arg-of-user-defined-type/7")
 6801     # foo a
 6802     (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")
 6803     #
 6804     (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")
 6805     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type/10")
 6806     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-arg-of-user-defined-type/11")
 6807     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/12")
 6808     (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")
 6809     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/14")
 6810     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/15")
 6811     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type/16")
 6812     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/17")
 6813     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/18")
 6814     (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")
 6815     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/20")
 6816     (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")
 6817     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/22")
 6818     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/23")
 6819     # . epilogue
 6820     89/<- %esp 5/r32/ebp
 6821     5d/pop-to-ebp
 6822     c3/return
 6823 
 6824 test-convert-function-call-with-arg-of-user-defined-type-register-indirect:
 6825     # . prologue
 6826     55/push-ebp
 6827     89/<- %ebp 4/r32/esp
 6828     # setup
 6829     (clear-stream _test-input-stream)
 6830     (clear-stream $_test-input-buffered-file->buffer)
 6831     (clear-stream _test-output-stream)
 6832     (clear-stream $_test-output-buffered-file->buffer)
 6833     #
 6834     (write _test-input-stream "fn f {\n")
 6835     (write _test-input-stream "  var a/eax: (addr t) <- copy 0\n")
 6836     (write _test-input-stream "  foo *a\n")
 6837     (write _test-input-stream "}\n")
 6838     (write _test-input-stream "fn foo x: t {\n")
 6839     (write _test-input-stream "}\n")
 6840     (write _test-input-stream "type t {\n")
 6841     (write _test-input-stream "  x: int\n")
 6842     (write _test-input-stream "  y: int\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 "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type/0")
 6855     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/1")
 6856     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/2")
 6857     (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")
 6858     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type/4")
 6859     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-arg-of-user-defined-type/5")
 6860     # var a
 6861     (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")
 6862     (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")
 6863     # foo a
 6864     (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")
 6865     #
 6866     (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")
 6867     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type/10")
 6868     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-arg-of-user-defined-type/11")
 6869     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/12")
 6870     (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")
 6871     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/14")
 6872     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/15")
 6873     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type/16")
 6874     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/17")
 6875     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/18")
 6876     (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")
 6877     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/20")
 6878     (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")
 6879     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/22")
 6880     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/23")
 6881     # . epilogue
 6882     89/<- %esp 5/r32/ebp
 6883     5d/pop-to-ebp
 6884     c3/return
 6885 
 6886 # we don't have special support for call-by-reference; just explicitly create
 6887 # a new variable with the address of the arg
 6888 test-convert-function-call-with-arg-of-user-defined-type-by-reference:
 6889     # . prologue
 6890     55/push-ebp
 6891     89/<- %ebp 4/r32/esp
 6892     # setup
 6893     (clear-stream _test-input-stream)
 6894     (clear-stream $_test-input-buffered-file->buffer)
 6895     (clear-stream _test-output-stream)
 6896     (clear-stream $_test-output-buffered-file->buffer)
 6897     #
 6898     (write _test-input-stream "fn f {\n")
 6899     (write _test-input-stream "  var a: t\n")
 6900     (write _test-input-stream "  var b/eax: (addr t) <- address a\n")
 6901     (write _test-input-stream "  foo b\n")
 6902     (write _test-input-stream "}\n")
 6903     (write _test-input-stream "fn foo x: (addr t) {\n")
 6904     (write _test-input-stream "  var x/ecx: (addr t) <- copy x\n")
 6905     (write _test-input-stream "}\n")
 6906     (write _test-input-stream "type t {\n")
 6907     (write _test-input-stream "  x: int\n")
 6908     (write _test-input-stream "  y: int\n")
 6909     (write _test-input-stream "}\n")
 6910     # convert
 6911     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6912     (flush _test-output-buffered-file)
 6913 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6919     # check output
 6920     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/0")
 6921     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/1")
 6922     (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")
 6923     (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")
 6924     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/4")
 6925     (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")
 6926     # var a: t
 6927     (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")
 6928     (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")
 6929     # var b/eax: (addr t)
 6930     (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")
 6931     (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")
 6932     # foo a
 6933     (check-next-stream-line-equal _test-output-stream "    (foo %eax)"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/10")
 6934     #
 6935     (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")
 6936     (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")
 6937     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/13")
 6938     (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")
 6939     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/15")
 6940     (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")
 6941     (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")
 6942     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/18")
 6943     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/19")
 6944     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/20")
 6945     (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")
 6946     (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")
 6947     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/23")
 6948     (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")
 6949     (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")
 6950     (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")
 6951     (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")
 6952     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/28")
 6953     (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")
 6954     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/30")
 6955     (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")
 6956     (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")
 6957     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/33")
 6958     # . epilogue
 6959     89/<- %esp 5/r32/ebp
 6960     5d/pop-to-ebp
 6961     c3/return
 6962 
 6963 test-convert-get-on-local-variable:
 6964     # . prologue
 6965     55/push-ebp
 6966     89/<- %ebp 4/r32/esp
 6967     # setup
 6968     (clear-stream _test-input-stream)
 6969     (clear-stream $_test-input-buffered-file->buffer)
 6970     (clear-stream _test-output-stream)
 6971     (clear-stream $_test-output-buffered-file->buffer)
 6972     #
 6973     (write _test-input-stream "fn foo {\n")
 6974     (write _test-input-stream "  var a: t\n")
 6975     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 6976     (write _test-input-stream "}\n")
 6977     (write _test-input-stream "type t {\n")
 6978     (write _test-input-stream "  x: int\n")
 6979     (write _test-input-stream "  y: int\n")
 6980     (write _test-input-stream "}\n")
 6981     # convert
 6982     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6983     (flush _test-output-buffered-file)
 6984 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6990     # check output
 6991     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-local-variable/0")
 6992     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-local-variable/1")
 6993     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-local-variable/2")
 6994     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-local-variable/3")
 6995     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-local-variable/4")
 6996     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-local-variable/5")
 6997     # var a
 6998     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-get-on-local-variable/6")
 6999     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-get-on-local-variable/7")
 7000     # var c
 7001     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-local-variable/8")
 7002     # get
 7003     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0xfffffffc) 0x00000001/r32"  "F - test-convert-get-on-local-variable/9")
 7004     # reclaim c
 7005     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-local-variable/10")
 7006     # reclaim a
 7007     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000008/imm32"  "F - test-convert-get-on-local-variable/11")
 7008     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-local-variable/12")
 7009     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-local-variable/13")
 7010     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-local-variable/14")
 7011     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-local-variable/15")
 7012     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-local-variable/16")
 7013     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-local-variable/17")
 7014     # . epilogue
 7015     89/<- %esp 5/r32/ebp
 7016     5d/pop-to-ebp
 7017     c3/return
 7018 
 7019 test-convert-get-on-function-argument:
 7020     # . prologue
 7021     55/push-ebp
 7022     89/<- %ebp 4/r32/esp
 7023     # setup
 7024     (clear-stream _test-input-stream)
 7025     (clear-stream $_test-input-buffered-file->buffer)
 7026     (clear-stream _test-output-stream)
 7027     (clear-stream $_test-output-buffered-file->buffer)
 7028     #
 7029     (write _test-input-stream "fn foo a: t {\n")
 7030     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 7031     (write _test-input-stream "}\n")
 7032     (write _test-input-stream "type t {\n")
 7033     (write _test-input-stream "  x: int\n")
 7034     (write _test-input-stream "  y: int\n")
 7035     (write _test-input-stream "}\n")
 7036     # convert
 7037     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7038     (flush _test-output-buffered-file)
 7039 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7045     # check output
 7046     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-function-argument/0")
 7047     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-function-argument/1")
 7048     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-function-argument/2")
 7049     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-function-argument/3")
 7050     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-function-argument/4")
 7051     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-function-argument/5")
 7052     # var c
 7053     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-function-argument/6")
 7054     # get
 7055     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0x0000000c) 0x00000001/r32"  "F - test-convert-get-on-function-argument/7")
 7056     # reclaim c
 7057     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-function-argument/8")
 7058     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-function-argument/9")
 7059     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-function-argument/10")
 7060     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-function-argument/11")
 7061     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-function-argument/12")
 7062     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-function-argument/13")
 7063     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-function-argument/14")
 7064     # . epilogue
 7065     89/<- %esp 5/r32/ebp
 7066     5d/pop-to-ebp
 7067     c3/return
 7068 
 7069 test-convert-get-on-function-argument-with-known-type:
 7070     # . prologue
 7071     55/push-ebp
 7072     89/<- %ebp 4/r32/esp
 7073     # setup
 7074     (clear-stream _test-input-stream)
 7075     (clear-stream $_test-input-buffered-file->buffer)
 7076     (clear-stream _test-output-stream)
 7077     (clear-stream $_test-output-buffered-file->buffer)
 7078     #
 7079     (write _test-input-stream "type t {\n")
 7080     (write _test-input-stream "  x: int\n")
 7081     (write _test-input-stream "  y: int\n")
 7082     (write _test-input-stream "}\n")
 7083     (write _test-input-stream "fn foo a: t {\n")
 7084     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 7085     (write _test-input-stream "}\n")
 7086     # convert
 7087     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7088     (flush _test-output-buffered-file)
 7089 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7095     # check output
 7096     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-function-argument-with-known-type/0")
 7097     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-function-argument-with-known-type/1")
 7098     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-function-argument-with-known-type/2")
 7099     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-function-argument-with-known-type/3")
 7100     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-function-argument-with-known-type/4")
 7101     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-function-argument-with-known-type/5")
 7102     # var c
 7103     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-function-argument-with-known-type/6")
 7104     # get
 7105     (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")
 7106     # reclaim c
 7107     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-function-argument-with-known-type/8")
 7108     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-function-argument-with-known-type/9")
 7109     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-function-argument-with-known-type/10")
 7110     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-function-argument-with-known-type/11")
 7111     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-function-argument-with-known-type/12")
 7112     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-function-argument-with-known-type/13")
 7113     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-function-argument-with-known-type/14")
 7114     # . epilogue
 7115     89/<- %esp 5/r32/ebp
 7116     5d/pop-to-ebp
 7117     c3/return
 7118 
 7119 test-add-with-too-many-inouts:
 7120     # . prologue
 7121     55/push-ebp
 7122     89/<- %ebp 4/r32/esp
 7123     # setup
 7124     (clear-stream _test-input-stream)
 7125     (clear-stream $_test-input-buffered-file->buffer)
 7126     (clear-stream _test-output-stream)
 7127     (clear-stream $_test-output-buffered-file->buffer)
 7128     (clear-stream _test-error-stream)
 7129     (clear-stream $_test-error-buffered-file->buffer)
 7130     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7131     68/push 0/imm32
 7132     68/push 0/imm32
 7133     89/<- %edx 4/r32/esp
 7134     (tailor-exit-descriptor %edx 0x10)
 7135     #
 7136     (write _test-input-stream "fn foo {\n")
 7137     (write _test-input-stream "  var a: int\n")
 7138     (write _test-input-stream "  var b/ecx: int <- add a, 0\n")
 7139     (write _test-input-stream "}\n")
 7140     # convert
 7141     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7142     # registers except esp clobbered at this point
 7143     # restore ed
 7144     89/<- %edx 4/r32/esp
 7145     (flush _test-output-buffered-file)
 7146     (flush _test-error-buffered-file)
 7147 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7153     # check output
 7154     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-inouts: output should be empty")
 7155     (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")
 7156     # check that stop(1) was called
 7157     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-inouts: exit status")
 7158     # don't restore from ebp
 7159     81 0/subop/add %esp 8/imm32
 7160     # . epilogue
 7161     5d/pop-to-ebp
 7162     c3/return
 7163 
 7164 test-add-with-too-many-inouts-2:
 7165     # . prologue
 7166     55/push-ebp
 7167     89/<- %ebp 4/r32/esp
 7168     # setup
 7169     (clear-stream _test-input-stream)
 7170     (clear-stream $_test-input-buffered-file->buffer)
 7171     (clear-stream _test-output-stream)
 7172     (clear-stream $_test-output-buffered-file->buffer)
 7173     (clear-stream _test-error-stream)
 7174     (clear-stream $_test-error-buffered-file->buffer)
 7175     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7176     68/push 0/imm32
 7177     68/push 0/imm32
 7178     89/<- %edx 4/r32/esp
 7179     (tailor-exit-descriptor %edx 0x10)
 7180     #
 7181     (write _test-input-stream "fn foo {\n")
 7182     (write _test-input-stream "  var a: int\n")
 7183     (write _test-input-stream "  add-to a, 0, 1\n")
 7184     (write _test-input-stream "}\n")
 7185     # convert
 7186     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7187     # registers except esp clobbered at this point
 7188     # restore ed
 7189     89/<- %edx 4/r32/esp
 7190     (flush _test-output-buffered-file)
 7191     (flush _test-error-buffered-file)
 7192 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7198     # check output
 7199     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-inouts-2: output should be empty")
 7200     (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")
 7201     # check that stop(1) was called
 7202     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-inouts-2: exit status")
 7203     # don't restore from ebp
 7204     81 0/subop/add %esp 8/imm32
 7205     # . epilogue
 7206     5d/pop-to-ebp
 7207     c3/return
 7208 
 7209 test-add-with-too-many-outputs:
 7210     # . prologue
 7211     55/push-ebp
 7212     89/<- %ebp 4/r32/esp
 7213     # setup
 7214     (clear-stream _test-input-stream)
 7215     (clear-stream $_test-input-buffered-file->buffer)
 7216     (clear-stream _test-output-stream)
 7217     (clear-stream $_test-output-buffered-file->buffer)
 7218     (clear-stream _test-error-stream)
 7219     (clear-stream $_test-error-buffered-file->buffer)
 7220     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7221     68/push 0/imm32
 7222     68/push 0/imm32
 7223     89/<- %edx 4/r32/esp
 7224     (tailor-exit-descriptor %edx 0x10)
 7225     #
 7226     (write _test-input-stream "fn foo {\n")
 7227     (write _test-input-stream "  var a/eax: int <- copy 0\n")
 7228     (write _test-input-stream "  var b/ebx: int <- copy 0\n")
 7229     (write _test-input-stream "  var c/ecx: int <- copy 0\n")
 7230     (write _test-input-stream "  c, b <- add a\n")
 7231     (write _test-input-stream "}\n")
 7232     # convert
 7233     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7234     # registers except esp clobbered at this point
 7235     # restore ed
 7236     89/<- %edx 4/r32/esp
 7237     (flush _test-output-buffered-file)
 7238     (flush _test-error-buffered-file)
 7239 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7245     # check output
 7246     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-outputs: output should be empty")
 7247     (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")
 7248     # check that stop(1) was called
 7249     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-outputs: exit status")
 7250     # don't restore from ebp
 7251     81 0/subop/add %esp 8/imm32
 7252     # . epilogue
 7253     5d/pop-to-ebp
 7254     c3/return
 7255 
 7256 test-add-with-non-number:
 7257     # . prologue
 7258     55/push-ebp
 7259     89/<- %ebp 4/r32/esp
 7260     # setup
 7261     (clear-stream _test-input-stream)
 7262     (clear-stream $_test-input-buffered-file->buffer)
 7263     (clear-stream _test-output-stream)
 7264     (clear-stream $_test-output-buffered-file->buffer)
 7265     (clear-stream _test-error-stream)
 7266     (clear-stream $_test-error-buffered-file->buffer)
 7267     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7268     68/push 0/imm32
 7269     68/push 0/imm32
 7270     89/<- %edx 4/r32/esp
 7271     (tailor-exit-descriptor %edx 0x10)
 7272     #
 7273     (write _test-input-stream "fn foo {\n")
 7274     (write _test-input-stream "  var a: int\n")
 7275     (write _test-input-stream "  var b/ecx: (addr int) <- add a\n")
 7276     (write _test-input-stream "}\n")
 7277     # convert
 7278     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7279     # registers except esp clobbered at this point
 7280     # restore ed
 7281     89/<- %edx 4/r32/esp
 7282     (flush _test-output-buffered-file)
 7283     (flush _test-error-buffered-file)
 7284 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7290     # check output
 7291     (check-stream-equal _test-output-stream  ""  "F - test-add-with-non-number: output should be empty")
 7292     (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")
 7293     # check that stop(1) was called
 7294     (check-ints-equal *(edx+4) 2 "F - test-add-with-non-number: exit status")
 7295     # don't restore from ebp
 7296     81 0/subop/add %esp 8/imm32
 7297     # . epilogue
 7298     5d/pop-to-ebp
 7299     c3/return
 7300 
 7301 test-add-with-addr-dereferenced:
 7302     # . prologue
 7303     55/push-ebp
 7304     89/<- %ebp 4/r32/esp
 7305     # setup
 7306     (clear-stream _test-input-stream)
 7307     (clear-stream $_test-input-buffered-file->buffer)
 7308     (clear-stream _test-output-stream)
 7309     (clear-stream $_test-output-buffered-file->buffer)
 7310     #
 7311     (write _test-input-stream "fn foo {\n")
 7312     (write _test-input-stream "  var a/eax: (addr int) <- copy 0\n")
 7313     (write _test-input-stream "  add-to *a, 1\n")
 7314     (write _test-input-stream "}\n")
 7315     # convert
 7316     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7317     (flush _test-output-buffered-file)
 7318     # no error
 7319     # . epilogue
 7320     89/<- %esp 5/r32/ebp
 7321     5d/pop-to-ebp
 7322     c3/return
 7323 
 7324 test-copy-with-no-inout:
 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     (clear-stream _test-error-stream)
 7334     (clear-stream $_test-error-buffered-file->buffer)
 7335     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7336     68/push 0/imm32
 7337     68/push 0/imm32
 7338     89/<- %edx 4/r32/esp
 7339     (tailor-exit-descriptor %edx 0x10)
 7340     #
 7341     (write _test-input-stream "fn foo {\n")
 7342     (write _test-input-stream "  var x/eax: boolean <- copy\n")
 7343     (write _test-input-stream "}\n")
 7344     # convert
 7345     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7346     # registers except esp clobbered at this point
 7347     # restore ed
 7348     89/<- %edx 4/r32/esp
 7349     (flush _test-output-buffered-file)
 7350     (flush _test-error-buffered-file)
 7351 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7357     # check output
 7358     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-no-inout: output should be empty")
 7359     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy' expects an inout"  "F - test-copy-with-no-inout: error message")
 7360     # check that stop(1) was called
 7361     (check-ints-equal *(edx+4) 2 "F - test-copy-with-no-inout: exit status")
 7362     # don't restore from ebp
 7363     81 0/subop/add %esp 8/imm32
 7364     # . epilogue
 7365     5d/pop-to-ebp
 7366     c3/return
 7367 
 7368 test-copy-with-multiple-inouts:
 7369     # . prologue
 7370     55/push-ebp
 7371     89/<- %ebp 4/r32/esp
 7372     # setup
 7373     (clear-stream _test-input-stream)
 7374     (clear-stream $_test-input-buffered-file->buffer)
 7375     (clear-stream _test-output-stream)
 7376     (clear-stream $_test-output-buffered-file->buffer)
 7377     (clear-stream _test-error-stream)
 7378     (clear-stream $_test-error-buffered-file->buffer)
 7379     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7380     68/push 0/imm32
 7381     68/push 0/imm32
 7382     89/<- %edx 4/r32/esp
 7383     (tailor-exit-descriptor %edx 0x10)
 7384     #
 7385     (write _test-input-stream "fn foo {\n")
 7386     (write _test-input-stream "  var x/eax: boolean <- copy 0, 0\n")
 7387     (write _test-input-stream "}\n")
 7388     # convert
 7389     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7390     # registers except esp clobbered at this point
 7391     # restore ed
 7392     89/<- %edx 4/r32/esp
 7393     (flush _test-output-buffered-file)
 7394     (flush _test-error-buffered-file)
 7395 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7401     # check output
 7402     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-multiple-inouts: output should be empty")
 7403     (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")
 7404     # check that stop(1) was called
 7405     (check-ints-equal *(edx+4) 2 "F - test-copy-with-multiple-inouts: exit status")
 7406     # don't restore from ebp
 7407     81 0/subop/add %esp 8/imm32
 7408     # . epilogue
 7409     5d/pop-to-ebp
 7410     c3/return
 7411 
 7412 test-copy-with-no-output:
 7413     # . prologue
 7414     55/push-ebp
 7415     89/<- %ebp 4/r32/esp
 7416     # setup
 7417     (clear-stream _test-input-stream)
 7418     (clear-stream $_test-input-buffered-file->buffer)
 7419     (clear-stream _test-output-stream)
 7420     (clear-stream $_test-output-buffered-file->buffer)
 7421     (clear-stream _test-error-stream)
 7422     (clear-stream $_test-error-buffered-file->buffer)
 7423     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7424     68/push 0/imm32
 7425     68/push 0/imm32
 7426     89/<- %edx 4/r32/esp
 7427     (tailor-exit-descriptor %edx 0x10)
 7428     #
 7429     (write _test-input-stream "fn foo {\n")
 7430     (write _test-input-stream "  copy 0\n")
 7431     (write _test-input-stream "}\n")
 7432     # convert
 7433     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7434     # registers except esp clobbered at this point
 7435     # restore ed
 7436     89/<- %edx 4/r32/esp
 7437     (flush _test-output-buffered-file)
 7438     (flush _test-error-buffered-file)
 7439 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7445     # check output
 7446     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-no-output: output should be empty")
 7447     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy' expects an output"  "F - test-copy-with-no-output: error message")
 7448     # check that stop(1) was called
 7449     (check-ints-equal *(edx+4) 2 "F - test-copy-with-no-output: exit status")
 7450     # don't restore from ebp
 7451     81 0/subop/add %esp 8/imm32
 7452     # . epilogue
 7453     5d/pop-to-ebp
 7454     c3/return
 7455 
 7456 test-copy-with-multiple-outputs:
 7457     # . prologue
 7458     55/push-ebp
 7459     89/<- %ebp 4/r32/esp
 7460     # setup
 7461     (clear-stream _test-input-stream)
 7462     (clear-stream $_test-input-buffered-file->buffer)
 7463     (clear-stream _test-output-stream)
 7464     (clear-stream $_test-output-buffered-file->buffer)
 7465     (clear-stream _test-error-stream)
 7466     (clear-stream $_test-error-buffered-file->buffer)
 7467     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7468     68/push 0/imm32
 7469     68/push 0/imm32
 7470     89/<- %edx 4/r32/esp
 7471     (tailor-exit-descriptor %edx 0x10)
 7472     #
 7473     (write _test-input-stream "fn foo {\n")
 7474     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 7475     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
 7476     (write _test-input-stream "  x, y <- copy 0\n")
 7477     (write _test-input-stream "}\n")
 7478     # convert
 7479     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7480     # registers except esp clobbered at this point
 7481     # restore ed
 7482     89/<- %edx 4/r32/esp
 7483     (flush _test-output-buffered-file)
 7484     (flush _test-error-buffered-file)
 7485 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7491     # check output
 7492     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-multiple-outputs: output should be empty")
 7493     (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")
 7494     # check that stop(1) was called
 7495     (check-ints-equal *(edx+4) 2 "F - test-copy-with-multiple-outputs: exit status")
 7496     # don't restore from ebp
 7497     81 0/subop/add %esp 8/imm32
 7498     # . epilogue
 7499     5d/pop-to-ebp
 7500     c3/return
 7501 
 7502 test-copy-invalid-value-to-address:
 7503     # . prologue
 7504     55/push-ebp
 7505     89/<- %ebp 4/r32/esp
 7506     # setup
 7507     (clear-stream _test-input-stream)
 7508     (clear-stream $_test-input-buffered-file->buffer)
 7509     (clear-stream _test-output-stream)
 7510     (clear-stream $_test-output-buffered-file->buffer)
 7511     (clear-stream _test-error-stream)
 7512     (clear-stream $_test-error-buffered-file->buffer)
 7513     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7514     68/push 0/imm32
 7515     68/push 0/imm32
 7516     89/<- %edx 4/r32/esp
 7517     (tailor-exit-descriptor %edx 0x10)
 7518     #
 7519     (write _test-input-stream "fn foo {\n")
 7520     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 7521     (write _test-input-stream "  var y/ecx: (addr int) <- copy x\n")
 7522     (write _test-input-stream "}\n")
 7523     # convert
 7524     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7525     # registers except esp clobbered at this point
 7526     # restore ed
 7527     89/<- %edx 4/r32/esp
 7528     (flush _test-output-buffered-file)
 7529     (flush _test-error-buffered-file)
 7530 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7536     # check output
 7537     (check-stream-equal _test-output-stream  ""  "F - test-copy-invalid-value-to-address: output should be empty")
 7538     (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")
 7539     # check that stop(1) was called
 7540     (check-ints-equal *(edx+4) 2 "F - test-copy-invalid-value-to-address: exit status")
 7541     # don't restore from ebp
 7542     81 0/subop/add %esp 8/imm32
 7543     # . epilogue
 7544     5d/pop-to-ebp
 7545     c3/return
 7546 
 7547 test-copy-null-value-to-addr:
 7548     # . prologue
 7549     55/push-ebp
 7550     89/<- %ebp 4/r32/esp
 7551     # setup
 7552     (clear-stream _test-input-stream)
 7553     (clear-stream $_test-input-buffered-file->buffer)
 7554     (clear-stream _test-output-stream)
 7555     (clear-stream $_test-output-buffered-file->buffer)
 7556     #
 7557     (write _test-input-stream "fn foo {\n")
 7558     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
 7559     (write _test-input-stream "}\n")
 7560     # convert
 7561     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7562     (flush _test-output-buffered-file)
 7563 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7569     # no errors
 7570     # . epilogue
 7571     89/<- %esp 5/r32/ebp
 7572     5d/pop-to-ebp
 7573     c3/return
 7574 
 7575 test-copy-invalid-value-to-offset:
 7576     # . prologue
 7577     55/push-ebp
 7578     89/<- %ebp 4/r32/esp
 7579     # setup
 7580     (clear-stream _test-input-stream)
 7581     (clear-stream $_test-input-buffered-file->buffer)
 7582     (clear-stream _test-output-stream)
 7583     (clear-stream $_test-output-buffered-file->buffer)
 7584     (clear-stream _test-error-stream)
 7585     (clear-stream $_test-error-buffered-file->buffer)
 7586     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7587     68/push 0/imm32
 7588     68/push 0/imm32
 7589     89/<- %edx 4/r32/esp
 7590     (tailor-exit-descriptor %edx 0x10)
 7591     #
 7592     (write _test-input-stream "fn foo {\n")
 7593     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 7594     (write _test-input-stream "  var y/ecx: (offset int) <- copy x\n")
 7595     (write _test-input-stream "}\n")
 7596     # convert
 7597     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7598     # registers except esp clobbered at this point
 7599     # restore ed
 7600     89/<- %edx 4/r32/esp
 7601     (flush _test-output-buffered-file)
 7602     (flush _test-error-buffered-file)
 7603 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7609     # check output
 7610     (check-stream-equal _test-output-stream  ""  "F - test-copy-invalid-value-to-address: output should be empty")
 7611     (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")
 7612     # check that stop(1) was called
 7613     (check-ints-equal *(edx+4) 2 "F - test-copy-invalid-value-to-offset: exit status")
 7614     # don't restore from ebp
 7615     81 0/subop/add %esp 8/imm32
 7616     # . epilogue
 7617     5d/pop-to-ebp
 7618     c3/return
 7619 
 7620 test-copy-null-value-to-offset:
 7621     # . prologue
 7622     55/push-ebp
 7623     89/<- %ebp 4/r32/esp
 7624     # setup
 7625     (clear-stream _test-input-stream)
 7626     (clear-stream $_test-input-buffered-file->buffer)
 7627     (clear-stream _test-output-stream)
 7628     (clear-stream $_test-output-buffered-file->buffer)
 7629     #
 7630     (write _test-input-stream "fn foo {\n")
 7631     (write _test-input-stream "  var y/ecx: (offset int) <- copy 0\n")
 7632     (write _test-input-stream "}\n")
 7633     # convert
 7634     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7635     (flush _test-output-buffered-file)
 7636 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7642     # no errors
 7643     # . epilogue
 7644     89/<- %esp 5/r32/ebp
 7645     5d/pop-to-ebp
 7646     c3/return
 7647 
 7648 test-copy-deref-address:
 7649     # . prologue
 7650     55/push-ebp
 7651     89/<- %ebp 4/r32/esp
 7652     # setup
 7653     (clear-stream _test-input-stream)
 7654     (clear-stream $_test-input-buffered-file->buffer)
 7655     (clear-stream _test-output-stream)
 7656     (clear-stream $_test-output-buffered-file->buffer)
 7657     #
 7658     (write _test-input-stream "fn foo {\n")
 7659     (write _test-input-stream "  var x/eax: (addr addr int) <- copy 0\n")
 7660     (write _test-input-stream "  var y/ecx: (addr int) <- copy *x\n")
 7661     (write _test-input-stream "}\n")
 7662     # convert
 7663     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7664     (flush _test-output-buffered-file)
 7665 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7671     # not bothering checking output
 7672     (check-next-stream-line-equal _test-error-stream  ""  "F - test-copy-deref-address: error message")
 7673     # . epilogue
 7674     5d/pop-to-ebp
 7675     c3/return
 7676 
 7677 test-copy-to-non-register:
 7678     # . prologue
 7679     55/push-ebp
 7680     89/<- %ebp 4/r32/esp
 7681     # setup
 7682     (clear-stream _test-input-stream)
 7683     (clear-stream $_test-input-buffered-file->buffer)
 7684     (clear-stream _test-output-stream)
 7685     (clear-stream $_test-output-buffered-file->buffer)
 7686     (clear-stream _test-error-stream)
 7687     (clear-stream $_test-error-buffered-file->buffer)
 7688     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7689     68/push 0/imm32
 7690     68/push 0/imm32
 7691     89/<- %edx 4/r32/esp
 7692     (tailor-exit-descriptor %edx 0x10)
 7693     #
 7694     (write _test-input-stream "fn foo {\n")
 7695     (write _test-input-stream "  var x: int\n")
 7696     (write _test-input-stream "  x <- copy 0\n")
 7697     (write _test-input-stream "}\n")
 7698     # convert
 7699     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7700     # registers except esp clobbered at this point
 7701     # restore ed
 7702     89/<- %edx 4/r32/esp
 7703     (flush _test-output-buffered-file)
 7704     (flush _test-error-buffered-file)
 7705 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7711     # check output
 7712     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-non-register: output should be empty")
 7713     (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")
 7714     # check that stop(1) was called
 7715     (check-ints-equal *(edx+4) 2 "F - test-copy-to-non-register: exit status")
 7716     # don't restore from ebp
 7717     81 0/subop/add %esp 8/imm32
 7718     # . epilogue
 7719     5d/pop-to-ebp
 7720     c3/return
 7721 
 7722 test-copy-non-scalar:
 7723     # . prologue
 7724     55/push-ebp
 7725     89/<- %ebp 4/r32/esp
 7726     # setup
 7727     (clear-stream _test-input-stream)
 7728     (clear-stream $_test-input-buffered-file->buffer)
 7729     (clear-stream _test-output-stream)
 7730     (clear-stream $_test-output-buffered-file->buffer)
 7731     (clear-stream _test-error-stream)
 7732     (clear-stream $_test-error-buffered-file->buffer)
 7733     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7734     68/push 0/imm32
 7735     68/push 0/imm32
 7736     89/<- %edx 4/r32/esp
 7737     (tailor-exit-descriptor %edx 0x10)
 7738     #
 7739     (write _test-input-stream "fn foo {\n")
 7740     (write _test-input-stream "  var x: (handle int)\n")
 7741     (write _test-input-stream "  var y/eax: int <- copy x\n")
 7742     (write _test-input-stream "}\n")
 7743     # convert
 7744     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7745     # registers except esp clobbered at this point
 7746     # restore ed
 7747     89/<- %edx 4/r32/esp
 7748     (flush _test-output-buffered-file)
 7749     (flush _test-error-buffered-file)
 7750 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7756     # check output
 7757     (check-stream-equal _test-output-stream  ""  "F - test-copy-non-scalar: output should be empty")
 7758     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy: 'x' is too large to fit in a register"  "F - test-copy-non-scalar: error message")
 7759     # check that stop(1) was called
 7760     (check-ints-equal *(edx+4) 2 "F - test-copy-non-scalar: exit status")
 7761     # don't restore from ebp
 7762     81 0/subop/add %esp 8/imm32
 7763     # . epilogue
 7764     5d/pop-to-ebp
 7765     c3/return
 7766 
 7767 test-copy-to-with-no-inout:
 7768     # . prologue
 7769     55/push-ebp
 7770     89/<- %ebp 4/r32/esp
 7771     # setup
 7772     (clear-stream _test-input-stream)
 7773     (clear-stream $_test-input-buffered-file->buffer)
 7774     (clear-stream _test-output-stream)
 7775     (clear-stream $_test-output-buffered-file->buffer)
 7776     (clear-stream _test-error-stream)
 7777     (clear-stream $_test-error-buffered-file->buffer)
 7778     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7779     68/push 0/imm32
 7780     68/push 0/imm32
 7781     89/<- %edx 4/r32/esp
 7782     (tailor-exit-descriptor %edx 0x10)
 7783     #
 7784     (write _test-input-stream "fn foo {\n")
 7785     (write _test-input-stream "  copy-to\n")
 7786     (write _test-input-stream "}\n")
 7787     # convert
 7788     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7789     # registers except esp clobbered at this point
 7790     # restore ed
 7791     89/<- %edx 4/r32/esp
 7792     (flush _test-output-buffered-file)
 7793     (flush _test-error-buffered-file)
 7794 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7800     # check output
 7801     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-no-inout: output should be empty")
 7802     (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")
 7803     # check that stop(1) was called
 7804     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-inout: exit status")
 7805     # don't restore from ebp
 7806     81 0/subop/add %esp 8/imm32
 7807     # . epilogue
 7808     5d/pop-to-ebp
 7809     c3/return
 7810 
 7811 test-copy-to-with-no-input:
 7812     # . prologue
 7813     55/push-ebp
 7814     89/<- %ebp 4/r32/esp
 7815     # setup
 7816     (clear-stream _test-input-stream)
 7817     (clear-stream $_test-input-buffered-file->buffer)
 7818     (clear-stream _test-output-stream)
 7819     (clear-stream $_test-output-buffered-file->buffer)
 7820     (clear-stream _test-error-stream)
 7821     (clear-stream $_test-error-buffered-file->buffer)
 7822     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7823     68/push 0/imm32
 7824     68/push 0/imm32
 7825     89/<- %edx 4/r32/esp
 7826     (tailor-exit-descriptor %edx 0x10)
 7827     #
 7828     (write _test-input-stream "fn foo {\n")
 7829     (write _test-input-stream "  var x: boolean\n")
 7830     (write _test-input-stream "  copy-to x\n")
 7831     (write _test-input-stream "}\n")
 7832     # convert
 7833     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7834     # registers except esp clobbered at this point
 7835     # restore ed
 7836     89/<- %edx 4/r32/esp
 7837     (flush _test-output-buffered-file)
 7838     (flush _test-error-buffered-file)
 7839 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7845     # check output
 7846     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-no-input: output should be empty")
 7847     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-to' must have two inouts"  "F - test-copy-to-with-no-input: error message")
 7848     # check that stop(1) was called
 7849     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-input: exit status")
 7850     # don't restore from ebp
 7851     81 0/subop/add %esp 8/imm32
 7852     # . epilogue
 7853     5d/pop-to-ebp
 7854     c3/return
 7855 
 7856 test-copy-to-with-no-register:
 7857     # . prologue
 7858     55/push-ebp
 7859     89/<- %ebp 4/r32/esp
 7860     # setup
 7861     (clear-stream _test-input-stream)
 7862     (clear-stream $_test-input-buffered-file->buffer)
 7863     (clear-stream _test-output-stream)
 7864     (clear-stream $_test-output-buffered-file->buffer)
 7865     (clear-stream _test-error-stream)
 7866     (clear-stream $_test-error-buffered-file->buffer)
 7867     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7868     68/push 0/imm32
 7869     68/push 0/imm32
 7870     89/<- %edx 4/r32/esp
 7871     (tailor-exit-descriptor %edx 0x10)
 7872     #
 7873     (write _test-input-stream "fn foo {\n")
 7874     (write _test-input-stream "  var x: boolean\n")
 7875     (write _test-input-stream "  copy-to x, x\n")
 7876     (write _test-input-stream "}\n")
 7877     # convert
 7878     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7879     # registers except esp clobbered at this point
 7880     # restore ed
 7881     89/<- %edx 4/r32/esp
 7882     (flush _test-output-buffered-file)
 7883     (flush _test-error-buffered-file)
 7884 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7890     # check output
 7891     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-no-register: output should be empty")
 7892     (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")
 7893     # check that stop(1) was called
 7894     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-register: exit status")
 7895     # don't restore from ebp
 7896     81 0/subop/add %esp 8/imm32
 7897     # . epilogue
 7898     5d/pop-to-ebp
 7899     c3/return
 7900 
 7901 test-copy-to-with-too-many-inouts:
 7902     # . prologue
 7903     55/push-ebp
 7904     89/<- %ebp 4/r32/esp
 7905     # setup
 7906     (clear-stream _test-input-stream)
 7907     (clear-stream $_test-input-buffered-file->buffer)
 7908     (clear-stream _test-output-stream)
 7909     (clear-stream $_test-output-buffered-file->buffer)
 7910     (clear-stream _test-error-stream)
 7911     (clear-stream $_test-error-buffered-file->buffer)
 7912     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7913     68/push 0/imm32
 7914     68/push 0/imm32
 7915     89/<- %edx 4/r32/esp
 7916     (tailor-exit-descriptor %edx 0x10)
 7917     #
 7918     (write _test-input-stream "fn foo {\n")
 7919     (write _test-input-stream "  var x: boolean\n")
 7920     (write _test-input-stream "  copy-to x, 0, 0\n")
 7921     (write _test-input-stream "}\n")
 7922     # convert
 7923     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7924     # registers except esp clobbered at this point
 7925     # restore ed
 7926     89/<- %edx 4/r32/esp
 7927     (flush _test-output-buffered-file)
 7928     (flush _test-error-buffered-file)
 7929 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7935     # check output
 7936     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-too-many-inouts: output should be empty")
 7937     (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")
 7938     # check that stop(1) was called
 7939     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-too-many-inouts: exit status")
 7940     # don't restore from ebp
 7941     81 0/subop/add %esp 8/imm32
 7942     # . epilogue
 7943     5d/pop-to-ebp
 7944     c3/return
 7945 
 7946 test-copy-to-with-output:
 7947     # . prologue
 7948     55/push-ebp
 7949     89/<- %ebp 4/r32/esp
 7950     # setup
 7951     (clear-stream _test-input-stream)
 7952     (clear-stream $_test-input-buffered-file->buffer)
 7953     (clear-stream _test-output-stream)
 7954     (clear-stream $_test-output-buffered-file->buffer)
 7955     (clear-stream _test-error-stream)
 7956     (clear-stream $_test-error-buffered-file->buffer)
 7957     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7958     68/push 0/imm32
 7959     68/push 0/imm32
 7960     89/<- %edx 4/r32/esp
 7961     (tailor-exit-descriptor %edx 0x10)
 7962     #
 7963     (write _test-input-stream "fn foo {\n")
 7964     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 7965     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
 7966     (write _test-input-stream "  x <- copy-to y, 0\n")
 7967     (write _test-input-stream "}\n")
 7968     # convert
 7969     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7970     # registers except esp clobbered at this point
 7971     # restore ed
 7972     89/<- %edx 4/r32/esp
 7973     (flush _test-output-buffered-file)
 7974     (flush _test-error-buffered-file)
 7975 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7981     # check output
 7982     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-output: output should be empty")
 7983     (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")
 7984     # check that stop(1) was called
 7985     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-output: exit status")
 7986     # don't restore from ebp
 7987     81 0/subop/add %esp 8/imm32
 7988     # . epilogue
 7989     5d/pop-to-ebp
 7990     c3/return
 7991 
 7992 test-copy-to-invalid-value-to-address:
 7993     # . prologue
 7994     55/push-ebp
 7995     89/<- %ebp 4/r32/esp
 7996     # setup
 7997     (clear-stream _test-input-stream)
 7998     (clear-stream $_test-input-buffered-file->buffer)
 7999     (clear-stream _test-output-stream)
 8000     (clear-stream $_test-output-buffered-file->buffer)
 8001     (clear-stream _test-error-stream)
 8002     (clear-stream $_test-error-buffered-file->buffer)
 8003     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8004     68/push 0/imm32
 8005     68/push 0/imm32
 8006     89/<- %edx 4/r32/esp
 8007     (tailor-exit-descriptor %edx 0x10)
 8008     #
 8009     (write _test-input-stream "fn foo {\n")
 8010     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 8011     (write _test-input-stream "  var y: (addr int)\n")
 8012     (write _test-input-stream "  copy-to y, x\n")
 8013     (write _test-input-stream "}\n")
 8014     # convert
 8015     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8016     # registers except esp clobbered at this point
 8017     # restore ed
 8018     89/<- %edx 4/r32/esp
 8019     (flush _test-output-buffered-file)
 8020     (flush _test-error-buffered-file)
 8021 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8027     # check output
 8028     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-invalid-value-to-address: output should be empty")
 8029     (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")
 8030     # check that stop(1) was called
 8031     (check-ints-equal *(edx+4) 2 "F - test-copy-to-invalid-value-to-address: exit status")
 8032     # don't restore from ebp
 8033     81 0/subop/add %esp 8/imm32
 8034     # . epilogue
 8035     5d/pop-to-ebp
 8036     c3/return
 8037 
 8038 test-copy-to-deref-address:
 8039     # . prologue
 8040     55/push-ebp
 8041     89/<- %ebp 4/r32/esp
 8042     # setup
 8043     (clear-stream _test-input-stream)
 8044     (clear-stream $_test-input-buffered-file->buffer)
 8045     (clear-stream _test-output-stream)
 8046     (clear-stream $_test-output-buffered-file->buffer)
 8047     #
 8048     (write _test-input-stream "fn foo {\n")
 8049     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
 8050     (write _test-input-stream "  var y/ecx: (addr addr int) <- copy 0\n")
 8051     (write _test-input-stream "  copy-to *y, x\n")
 8052     (write _test-input-stream "}\n")
 8053     # convert
 8054     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8055     (flush _test-output-buffered-file)
 8056 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8062     # not bothering checking output
 8063     (check-next-stream-line-equal _test-error-stream  ""  "F - test-copy-to-deref-address: error message")
 8064     # . epilogue
 8065     5d/pop-to-ebp
 8066     c3/return
 8067 
 8068 test-copy-to-non-scalar:
 8069     # . prologue
 8070     55/push-ebp
 8071     89/<- %ebp 4/r32/esp
 8072     # setup
 8073     (clear-stream _test-input-stream)
 8074     (clear-stream $_test-input-buffered-file->buffer)
 8075     (clear-stream _test-output-stream)
 8076     (clear-stream $_test-output-buffered-file->buffer)
 8077     (clear-stream _test-error-stream)
 8078     (clear-stream $_test-error-buffered-file->buffer)
 8079     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8080     68/push 0/imm32
 8081     68/push 0/imm32
 8082     89/<- %edx 4/r32/esp
 8083     (tailor-exit-descriptor %edx 0x10)
 8084     #
 8085     (write _test-input-stream "fn foo {\n")
 8086     (write _test-input-stream "  var x: (handle int)\n")
 8087     (write _test-input-stream "  var y: int\n")
 8088     (write _test-input-stream "  copy-to y, x\n")
 8089     (write _test-input-stream "}\n")
 8090     # convert
 8091     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8092     # registers except esp clobbered at this point
 8093     # restore ed
 8094     89/<- %edx 4/r32/esp
 8095     (flush _test-output-buffered-file)
 8096     (flush _test-error-buffered-file)
 8097 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8103     # check output
 8104     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-non-scalar: output should be empty")
 8105 #?     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-to: 'x' is too large to copy"  "F - test-copy-to-non-scalar: error message")
 8106     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-to: source (second inout) is in memory"  "F - test-copy-to-non-scalar: error message")
 8107     # check that stop(1) was called
 8108     (check-ints-equal *(edx+4) 2 "F - test-copy-to-non-scalar: 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-compare-with-no-inout:
 8116     # . prologue
 8117     55/push-ebp
 8118     89/<- %ebp 4/r32/esp
 8119     # setup
 8120     (clear-stream _test-input-stream)
 8121     (clear-stream $_test-input-buffered-file->buffer)
 8122     (clear-stream _test-output-stream)
 8123     (clear-stream $_test-output-buffered-file->buffer)
 8124     (clear-stream _test-error-stream)
 8125     (clear-stream $_test-error-buffered-file->buffer)
 8126     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8127     68/push 0/imm32
 8128     68/push 0/imm32
 8129     89/<- %edx 4/r32/esp
 8130     (tailor-exit-descriptor %edx 0x10)
 8131     #
 8132     (write _test-input-stream "fn foo {\n")
 8133     (write _test-input-stream "  var x: boolean\n")
 8134     (write _test-input-stream "  compare\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-compare-with-no-inout: output should be empty")
 8151     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must have two inouts"  "F - test-compare-with-no-inout: error message")
 8152     # check that stop(1) was called
 8153     (check-ints-equal *(edx+4) 2 "F - test-compare-with-no-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-compare-with-no-input:
 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 "  var x: boolean\n")
 8179     (write _test-input-stream "  compare x\n")
 8180     (write _test-input-stream "}\n")
 8181     # convert
 8182     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8183     # registers except esp clobbered at this point
 8184     # restore ed
 8185     89/<- %edx 4/r32/esp
 8186     (flush _test-output-buffered-file)
 8187     (flush _test-error-buffered-file)
 8188 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8194     # check output
 8195     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-no-input: output should be empty")
 8196     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must have two inouts"  "F - test-compare-with-no-input: error message")
 8197     # check that stop(1) was called
 8198     (check-ints-equal *(edx+4) 2 "F - test-compare-with-no-input: exit status")
 8199     # don't restore from ebp
 8200     81 0/subop/add %esp 8/imm32
 8201     # . epilogue
 8202     5d/pop-to-ebp
 8203     c3/return
 8204 
 8205 test-compare-with-too-many-inouts:
 8206     # . prologue
 8207     55/push-ebp
 8208     89/<- %ebp 4/r32/esp
 8209     # setup
 8210     (clear-stream _test-input-stream)
 8211     (clear-stream $_test-input-buffered-file->buffer)
 8212     (clear-stream _test-output-stream)
 8213     (clear-stream $_test-output-buffered-file->buffer)
 8214     (clear-stream _test-error-stream)
 8215     (clear-stream $_test-error-buffered-file->buffer)
 8216     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8217     68/push 0/imm32
 8218     68/push 0/imm32
 8219     89/<- %edx 4/r32/esp
 8220     (tailor-exit-descriptor %edx 0x10)
 8221     #
 8222     (write _test-input-stream "fn foo {\n")
 8223     (write _test-input-stream "  var x: boolean\n")
 8224     (write _test-input-stream "  compare x, 0, 0\n")
 8225     (write _test-input-stream "}\n")
 8226     # convert
 8227     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8228     # registers except esp clobbered at this point
 8229     # restore ed
 8230     89/<- %edx 4/r32/esp
 8231     (flush _test-output-buffered-file)
 8232     (flush _test-error-buffered-file)
 8233 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8239     # check output
 8240     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-too-many-inouts: output should be empty")
 8241     (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")
 8242     # check that stop(1) was called
 8243     (check-ints-equal *(edx+4) 2 "F - test-compare-with-too-many-inouts: exit status")
 8244     # don't restore from ebp
 8245     81 0/subop/add %esp 8/imm32
 8246     # . epilogue
 8247     5d/pop-to-ebp
 8248     c3/return
 8249 
 8250 test-compare-with-output:
 8251     # . prologue
 8252     55/push-ebp
 8253     89/<- %ebp 4/r32/esp
 8254     # setup
 8255     (clear-stream _test-input-stream)
 8256     (clear-stream $_test-input-buffered-file->buffer)
 8257     (clear-stream _test-output-stream)
 8258     (clear-stream $_test-output-buffered-file->buffer)
 8259     (clear-stream _test-error-stream)
 8260     (clear-stream $_test-error-buffered-file->buffer)
 8261     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8262     68/push 0/imm32
 8263     68/push 0/imm32
 8264     89/<- %edx 4/r32/esp
 8265     (tailor-exit-descriptor %edx 0x10)
 8266     #
 8267     (write _test-input-stream "fn foo {\n")
 8268     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 8269     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
 8270     (write _test-input-stream "  x <- compare y, 0\n")
 8271     (write _test-input-stream "}\n")
 8272     # convert
 8273     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8274     # registers except esp clobbered at this point
 8275     # restore ed
 8276     89/<- %edx 4/r32/esp
 8277     (flush _test-output-buffered-file)
 8278     (flush _test-error-buffered-file)
 8279 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8285     # check output
 8286     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-output: output should be empty")
 8287     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must not have any outputs"  "F - test-compare-with-output: error message")
 8288     # check that stop(1) was called
 8289     (check-ints-equal *(edx+4) 2 "F - test-compare-with-output: exit status")
 8290     # don't restore from ebp
 8291     81 0/subop/add %esp 8/imm32
 8292     # . epilogue
 8293     5d/pop-to-ebp
 8294     c3/return
 8295 
 8296 test-compare-invalid-value-to-address:
 8297     # . prologue
 8298     55/push-ebp
 8299     89/<- %ebp 4/r32/esp
 8300     # setup
 8301     (clear-stream _test-input-stream)
 8302     (clear-stream $_test-input-buffered-file->buffer)
 8303     (clear-stream _test-output-stream)
 8304     (clear-stream $_test-output-buffered-file->buffer)
 8305     (clear-stream _test-error-stream)
 8306     (clear-stream $_test-error-buffered-file->buffer)
 8307     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8308     68/push 0/imm32
 8309     68/push 0/imm32
 8310     89/<- %edx 4/r32/esp
 8311     (tailor-exit-descriptor %edx 0x10)
 8312     #
 8313     (write _test-input-stream "fn foo {\n")
 8314     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 8315     (write _test-input-stream "  var y: (addr int)\n")
 8316     (write _test-input-stream "  compare y, x\n")
 8317     (write _test-input-stream "}\n")
 8318     # convert
 8319     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8320     # registers except esp clobbered at this point
 8321     # restore ed
 8322     89/<- %edx 4/r32/esp
 8323     (flush _test-output-buffered-file)
 8324     (flush _test-error-buffered-file)
 8325 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8331     # check output
 8332     (check-stream-equal _test-output-stream  ""  "F - test-compare-invalid-value-to-address: output should be empty")
 8333     (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")
 8334     # check that stop(1) was called
 8335     (check-ints-equal *(edx+4) 2 "F - test-compare-invalid-value-to-address: exit status")
 8336     # don't restore from ebp
 8337     81 0/subop/add %esp 8/imm32
 8338     # . epilogue
 8339     5d/pop-to-ebp
 8340     c3/return
 8341 
 8342 test-compare-address:
 8343     # . prologue
 8344     55/push-ebp
 8345     89/<- %ebp 4/r32/esp
 8346     # setup
 8347     (clear-stream _test-input-stream)
 8348     (clear-stream $_test-input-buffered-file->buffer)
 8349     (clear-stream _test-output-stream)
 8350     (clear-stream $_test-output-buffered-file->buffer)
 8351     #
 8352     (write _test-input-stream "fn foo {\n")
 8353     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
 8354     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
 8355     (write _test-input-stream "  compare y, x\n")
 8356     (write _test-input-stream "}\n")
 8357     # convert
 8358     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8359     (flush _test-output-buffered-file)
 8360 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8366     # not bothering checking output
 8367     (check-next-stream-line-equal _test-error-stream  ""  "F - test-compare-address: error message")
 8368     # . epilogue
 8369     5d/pop-to-ebp
 8370     c3/return
 8371 
 8372 test-compare-deref-address:
 8373     # . prologue
 8374     55/push-ebp
 8375     89/<- %ebp 4/r32/esp
 8376     # setup
 8377     (clear-stream _test-input-stream)
 8378     (clear-stream $_test-input-buffered-file->buffer)
 8379     (clear-stream _test-output-stream)
 8380     (clear-stream $_test-output-buffered-file->buffer)
 8381     #
 8382     (write _test-input-stream "fn foo {\n")
 8383     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
 8384     (write _test-input-stream "  var y/ecx: (addr addr int) <- copy 0\n")
 8385     (write _test-input-stream "  compare *y, x\n")
 8386     (write _test-input-stream "}\n")
 8387     # convert
 8388     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8389     (flush _test-output-buffered-file)
 8390 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8396     # not bothering checking output
 8397     (check-next-stream-line-equal _test-error-stream  ""  "F - test-compare-deref-address: error message")
 8398     # . epilogue
 8399     5d/pop-to-ebp
 8400     c3/return
 8401 
 8402 test-compare-two-vars-in-memory:
 8403     # . prologue
 8404     55/push-ebp
 8405     89/<- %ebp 4/r32/esp
 8406     # setup
 8407     (clear-stream _test-input-stream)
 8408     (clear-stream $_test-input-buffered-file->buffer)
 8409     (clear-stream _test-output-stream)
 8410     (clear-stream $_test-output-buffered-file->buffer)
 8411     (clear-stream _test-error-stream)
 8412     (clear-stream $_test-error-buffered-file->buffer)
 8413     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8414     68/push 0/imm32
 8415     68/push 0/imm32
 8416     89/<- %edx 4/r32/esp
 8417     (tailor-exit-descriptor %edx 0x10)
 8418     #
 8419     (write _test-input-stream "fn foo {\n")
 8420     (write _test-input-stream "  var x: boolean\n")
 8421     (write _test-input-stream "  compare x, x\n")
 8422     (write _test-input-stream "}\n")
 8423     # convert
 8424     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8425     # registers except esp clobbered at this point
 8426     # restore ed
 8427     89/<- %edx 4/r32/esp
 8428     (flush _test-output-buffered-file)
 8429     (flush _test-error-buffered-file)
 8430 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8436     # check output
 8437     (check-stream-equal _test-output-stream  ""  "F - test-compare-two-vars-in-memory: output should be empty")
 8438     (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")
 8439     # check that stop(1) was called
 8440     (check-ints-equal *(edx+4) 2 "F - test-compare-two-vars-in-memory: exit status")
 8441     # don't restore from ebp
 8442     81 0/subop/add %esp 8/imm32
 8443     # . epilogue
 8444     5d/pop-to-ebp
 8445     c3/return
 8446 
 8447 test-compare-non-scalar:
 8448     # . prologue
 8449     55/push-ebp
 8450     89/<- %ebp 4/r32/esp
 8451     # setup
 8452     (clear-stream _test-input-stream)
 8453     (clear-stream $_test-input-buffered-file->buffer)
 8454     (clear-stream _test-output-stream)
 8455     (clear-stream $_test-output-buffered-file->buffer)
 8456     (clear-stream _test-error-stream)
 8457     (clear-stream $_test-error-buffered-file->buffer)
 8458     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8459     68/push 0/imm32
 8460     68/push 0/imm32
 8461     89/<- %edx 4/r32/esp
 8462     (tailor-exit-descriptor %edx 0x10)
 8463     #
 8464     (write _test-input-stream "fn foo {\n")
 8465     (write _test-input-stream "  var x: (handle int)\n")
 8466     (write _test-input-stream "  var y: int\n")
 8467     (write _test-input-stream "  compare y, x\n")
 8468     (write _test-input-stream "}\n")
 8469     # convert
 8470     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8471     # registers except esp clobbered at this point
 8472     # restore ed
 8473     89/<- %edx 4/r32/esp
 8474     (flush _test-output-buffered-file)
 8475     (flush _test-error-buffered-file)
 8476 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8482     # check output
 8483     (check-stream-equal _test-output-stream  ""  "F - test-compare-non-scalar: output should be empty")
 8484 #?     (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")
 8485     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compare: both inouts are in memory"  "F - test-compare-non-scalar: error message")
 8486     # check that stop(1) was called
 8487     (check-ints-equal *(edx+4) 2 "F - test-compare-non-scalar: exit status")
 8488     # don't restore from ebp
 8489     81 0/subop/add %esp 8/imm32
 8490     # . epilogue
 8491     5d/pop-to-ebp
 8492     c3/return
 8493 
 8494 test-address-with-no-inout:
 8495     # . prologue
 8496     55/push-ebp
 8497     89/<- %ebp 4/r32/esp
 8498     # setup
 8499     (clear-stream _test-input-stream)
 8500     (clear-stream $_test-input-buffered-file->buffer)
 8501     (clear-stream _test-output-stream)
 8502     (clear-stream $_test-output-buffered-file->buffer)
 8503     (clear-stream _test-error-stream)
 8504     (clear-stream $_test-error-buffered-file->buffer)
 8505     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8506     68/push 0/imm32
 8507     68/push 0/imm32
 8508     89/<- %edx 4/r32/esp
 8509     (tailor-exit-descriptor %edx 0x10)
 8510     #
 8511     (write _test-input-stream "fn foo {\n")
 8512     (write _test-input-stream "  var x/eax: boolean <- address\n")
 8513     (write _test-input-stream "}\n")
 8514     # convert
 8515     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8516     # registers except esp clobbered at this point
 8517     # restore ed
 8518     89/<- %edx 4/r32/esp
 8519     (flush _test-output-buffered-file)
 8520     (flush _test-error-buffered-file)
 8521 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8527     # check output
 8528     (check-stream-equal _test-output-stream  ""  "F - test-address-with-no-inout: output should be empty")
 8529     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'address' expects an inout"  "F - test-address-with-no-inout: error message")
 8530     # check that stop(1) was called
 8531     (check-ints-equal *(edx+4) 2 "F - test-address-with-no-inout: exit status")
 8532     # don't restore from ebp
 8533     81 0/subop/add %esp 8/imm32
 8534     # . epilogue
 8535     5d/pop-to-ebp
 8536     c3/return
 8537 
 8538 test-address-with-multiple-inouts:
 8539     # . prologue
 8540     55/push-ebp
 8541     89/<- %ebp 4/r32/esp
 8542     # setup
 8543     (clear-stream _test-input-stream)
 8544     (clear-stream $_test-input-buffered-file->buffer)
 8545     (clear-stream _test-output-stream)
 8546     (clear-stream $_test-output-buffered-file->buffer)
 8547     (clear-stream _test-error-stream)
 8548     (clear-stream $_test-error-buffered-file->buffer)
 8549     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8550     68/push 0/imm32
 8551     68/push 0/imm32
 8552     89/<- %edx 4/r32/esp
 8553     (tailor-exit-descriptor %edx 0x10)
 8554     #
 8555     (write _test-input-stream "fn foo {\n")
 8556     (write _test-input-stream "  var x/eax: boolean <- address 0, 0\n")
 8557     (write _test-input-stream "}\n")
 8558     # convert
 8559     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8560     # registers except esp clobbered at this point
 8561     # restore ed
 8562     89/<- %edx 4/r32/esp
 8563     (flush _test-output-buffered-file)
 8564     (flush _test-error-buffered-file)
 8565 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8571     # check output
 8572     (check-stream-equal _test-output-stream  ""  "F - test-address-with-multiple-inouts: output should be empty")
 8573     (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")
 8574     # check that stop(1) was called
 8575     (check-ints-equal *(edx+4) 2 "F - test-address-with-multiple-inouts: exit status")
 8576     # don't restore from ebp
 8577     81 0/subop/add %esp 8/imm32
 8578     # . epilogue
 8579     5d/pop-to-ebp
 8580     c3/return
 8581 
 8582 test-address-with-no-output:
 8583     # . prologue
 8584     55/push-ebp
 8585     89/<- %ebp 4/r32/esp
 8586     # setup
 8587     (clear-stream _test-input-stream)
 8588     (clear-stream $_test-input-buffered-file->buffer)
 8589     (clear-stream _test-output-stream)
 8590     (clear-stream $_test-output-buffered-file->buffer)
 8591     (clear-stream _test-error-stream)
 8592     (clear-stream $_test-error-buffered-file->buffer)
 8593     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8594     68/push 0/imm32
 8595     68/push 0/imm32
 8596     89/<- %edx 4/r32/esp
 8597     (tailor-exit-descriptor %edx 0x10)
 8598     #
 8599     (write _test-input-stream "fn foo {\n")
 8600     (write _test-input-stream "  address 0\n")
 8601     (write _test-input-stream "}\n")
 8602     # convert
 8603     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8604     # registers except esp clobbered at this point
 8605     # restore ed
 8606     89/<- %edx 4/r32/esp
 8607     (flush _test-output-buffered-file)
 8608     (flush _test-error-buffered-file)
 8609 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8615     # check output
 8616     (check-stream-equal _test-output-stream  ""  "F - test-address-with-no-output: output should be empty")
 8617     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'address' expects an output"  "F - test-address-with-no-output: error message")
 8618     # check that stop(1) was called
 8619     (check-ints-equal *(edx+4) 2 "F - test-address-with-no-output: exit status")
 8620     # don't restore from ebp
 8621     81 0/subop/add %esp 8/imm32
 8622     # . epilogue
 8623     5d/pop-to-ebp
 8624     c3/return
 8625 
 8626 test-address-with-multiple-outputs:
 8627     # . prologue
 8628     55/push-ebp
 8629     89/<- %ebp 4/r32/esp
 8630     # setup
 8631     (clear-stream _test-input-stream)
 8632     (clear-stream $_test-input-buffered-file->buffer)
 8633     (clear-stream _test-output-stream)
 8634     (clear-stream $_test-output-buffered-file->buffer)
 8635     (clear-stream _test-error-stream)
 8636     (clear-stream $_test-error-buffered-file->buffer)
 8637     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8638     68/push 0/imm32
 8639     68/push 0/imm32
 8640     89/<- %edx 4/r32/esp
 8641     (tailor-exit-descriptor %edx 0x10)
 8642     #
 8643     (write _test-input-stream "fn foo {\n")
 8644     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 8645     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
 8646     (write _test-input-stream "  x, y <- address 0\n")
 8647     (write _test-input-stream "}\n")
 8648     # convert
 8649     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8650     # registers except esp clobbered at this point
 8651     # restore ed
 8652     89/<- %edx 4/r32/esp
 8653     (flush _test-output-buffered-file)
 8654     (flush _test-error-buffered-file)
 8655 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8661     # check output
 8662     (check-stream-equal _test-output-stream  ""  "F - test-address-with-multiple-outputs: output should be empty")
 8663     (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")
 8664     # check that stop(1) was called
 8665     (check-ints-equal *(edx+4) 2 "F - test-address-with-multiple-outputs: exit status")
 8666     # don't restore from ebp
 8667     81 0/subop/add %esp 8/imm32
 8668     # . epilogue
 8669     5d/pop-to-ebp
 8670     c3/return
 8671 
 8672 # silly but it works
 8673 test-address-of-deref:
 8674     # . prologue
 8675     55/push-ebp
 8676     89/<- %ebp 4/r32/esp
 8677     # setup
 8678     (clear-stream _test-input-stream)
 8679     (clear-stream $_test-input-buffered-file->buffer)
 8680     (clear-stream _test-output-stream)
 8681     (clear-stream $_test-output-buffered-file->buffer)
 8682     #
 8683     (write _test-input-stream "fn foo {\n")
 8684     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
 8685     (write _test-input-stream "  var y/ecx: (addr int) <- address *x\n")
 8686     (write _test-input-stream "}\n")
 8687     # convert
 8688     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8689     (flush _test-output-buffered-file)
 8690 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8696     # not bothering checking output
 8697     (check-next-stream-line-equal _test-error-stream  ""  "F - test-address-of-deref: error message")
 8698     # . epilogue
 8699     5d/pop-to-ebp
 8700     c3/return
 8701 
 8702 test-address-to-non-register:
 8703     # . prologue
 8704     55/push-ebp
 8705     89/<- %ebp 4/r32/esp
 8706     # setup
 8707     (clear-stream _test-input-stream)
 8708     (clear-stream $_test-input-buffered-file->buffer)
 8709     (clear-stream _test-output-stream)
 8710     (clear-stream $_test-output-buffered-file->buffer)
 8711     (clear-stream _test-error-stream)
 8712     (clear-stream $_test-error-buffered-file->buffer)
 8713     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8714     68/push 0/imm32
 8715     68/push 0/imm32
 8716     89/<- %edx 4/r32/esp
 8717     (tailor-exit-descriptor %edx 0x10)
 8718     #
 8719     (write _test-input-stream "fn foo {\n")
 8720     (write _test-input-stream "  var x: (addr int)\n")
 8721     (write _test-input-stream "  x <- address 0\n")
 8722     (write _test-input-stream "}\n")
 8723     # convert
 8724     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8725     # registers except esp clobbered at this point
 8726     # restore ed
 8727     89/<- %edx 4/r32/esp
 8728     (flush _test-output-buffered-file)
 8729     (flush _test-error-buffered-file)
 8730 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8736     # check output
 8737     (check-stream-equal _test-output-stream  ""  "F - test-address-to-non-register: output should be empty")
 8738     (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")
 8739     # check that stop(1) was called
 8740     (check-ints-equal *(edx+4) 2 "F - test-address-to-non-register: exit status")
 8741     # don't restore from ebp
 8742     81 0/subop/add %esp 8/imm32
 8743     # . epilogue
 8744     5d/pop-to-ebp
 8745     c3/return
 8746 
 8747 test-address-with-wrong-type:
 8748     # . prologue
 8749     55/push-ebp
 8750     89/<- %ebp 4/r32/esp
 8751     # setup
 8752     (clear-stream _test-input-stream)
 8753     (clear-stream $_test-input-buffered-file->buffer)
 8754     (clear-stream _test-output-stream)
 8755     (clear-stream $_test-output-buffered-file->buffer)
 8756     (clear-stream _test-error-stream)
 8757     (clear-stream $_test-error-buffered-file->buffer)
 8758     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8759     68/push 0/imm32
 8760     68/push 0/imm32
 8761     89/<- %edx 4/r32/esp
 8762     (tailor-exit-descriptor %edx 0x10)
 8763     #
 8764     (write _test-input-stream "fn foo {\n")
 8765     (write _test-input-stream "  var x: int\n")
 8766     (write _test-input-stream "  var y/eax: (addr boolean) <- address x\n")
 8767     (write _test-input-stream "}\n")
 8768     # convert
 8769     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8770     # registers except esp clobbered at this point
 8771     # restore ed
 8772     89/<- %edx 4/r32/esp
 8773     (flush _test-output-buffered-file)
 8774     (flush _test-error-buffered-file)
 8775 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8781     # check output
 8782     (check-stream-equal _test-output-stream  ""  "F - test-address-with-wrong-type: output should be empty")
 8783     (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")
 8784     # check that stop(1) was called
 8785     (check-ints-equal *(edx+4) 2 "F - test-address-with-wrong-type: exit status")
 8786     # don't restore from ebp
 8787     81 0/subop/add %esp 8/imm32
 8788     # . epilogue
 8789     5d/pop-to-ebp
 8790     c3/return
 8791 
 8792 test-address-with-right-type-for-array:
 8793     # . prologue
 8794     55/push-ebp
 8795     89/<- %ebp 4/r32/esp
 8796     # setup
 8797     (clear-stream _test-input-stream)
 8798     (clear-stream $_test-input-buffered-file->buffer)
 8799     (clear-stream _test-output-stream)
 8800     (clear-stream $_test-output-buffered-file->buffer)
 8801     #
 8802     (write _test-input-stream "fn foo {\n")
 8803     (write _test-input-stream "  var x: (array int 3)\n")
 8804     (write _test-input-stream "  var y/eax: (addr array int) <- address x\n")
 8805     (write _test-input-stream "}\n")
 8806     # convert
 8807     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8808     (flush _test-output-buffered-file)
 8809 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8815     # no error
 8816     (check-next-stream-line-equal _test-error-stream  ""  "F - test-address-with-right-type-for-array: error message")
 8817     # don't bother checking output
 8818     # . epilogue
 8819     89/<- %esp 5/r32/ebp
 8820     5d/pop-to-ebp
 8821     c3/return
 8822 
 8823 test-address-with-right-type-for-stream:
 8824     # . prologue
 8825     55/push-ebp
 8826     89/<- %ebp 4/r32/esp
 8827     # setup
 8828     (clear-stream _test-input-stream)
 8829     (clear-stream $_test-input-buffered-file->buffer)
 8830     (clear-stream _test-output-stream)
 8831     (clear-stream $_test-output-buffered-file->buffer)
 8832     #
 8833     (write _test-input-stream "fn foo {\n")
 8834     (write _test-input-stream "  var x: (stream int 3)\n")
 8835     (write _test-input-stream "  var y/eax: (addr stream int) <- address x\n")
 8836     (write _test-input-stream "}\n")
 8837     # convert
 8838     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8839     (flush _test-output-buffered-file)
 8840 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8846     # no error
 8847     (check-next-stream-line-equal _test-error-stream  ""  "F - test-address-with-right-type-for-stream: error message")
 8848     # don't bother checking output
 8849     # . epilogue
 8850     89/<- %esp 5/r32/ebp
 8851     5d/pop-to-ebp
 8852     c3/return
 8853 
 8854 test-get-with-wrong-field:
 8855     # . prologue
 8856     55/push-ebp
 8857     89/<- %ebp 4/r32/esp
 8858     # setup
 8859     (clear-stream _test-input-stream)
 8860     (clear-stream $_test-input-buffered-file->buffer)
 8861     (clear-stream _test-output-stream)
 8862     (clear-stream $_test-output-buffered-file->buffer)
 8863     (clear-stream _test-error-stream)
 8864     (clear-stream $_test-error-buffered-file->buffer)
 8865     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8866     68/push 0/imm32
 8867     68/push 0/imm32
 8868     89/<- %edx 4/r32/esp
 8869     (tailor-exit-descriptor %edx 0x10)
 8870     #
 8871     (write _test-input-stream "fn foo {\n")
 8872     (write _test-input-stream "  var a: t\n")
 8873     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 8874     (write _test-input-stream "}\n")
 8875     (write _test-input-stream "type t {\n")
 8876     (write _test-input-stream "  x: int\n")
 8877     (write _test-input-stream "}\n")
 8878     # convert
 8879     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8880     # registers except esp clobbered at this point
 8881     # restore ed
 8882     89/<- %edx 4/r32/esp
 8883     (flush _test-output-buffered-file)
 8884     (flush _test-error-buffered-file)
 8885 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8891     # check output
 8892     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-field: output should be empty")
 8893     (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")
 8894     # check that stop(1) was called
 8895     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-field: exit status")
 8896     # don't restore from ebp
 8897     81 0/subop/add %esp 8/imm32
 8898     # . epilogue
 8899     5d/pop-to-ebp
 8900     c3/return
 8901 
 8902 test-get-with-wrong-base-type:
 8903     # . prologue
 8904     55/push-ebp
 8905     89/<- %ebp 4/r32/esp
 8906     # setup
 8907     (clear-stream _test-input-stream)
 8908     (clear-stream $_test-input-buffered-file->buffer)
 8909     (clear-stream _test-output-stream)
 8910     (clear-stream $_test-output-buffered-file->buffer)
 8911     (clear-stream _test-error-stream)
 8912     (clear-stream $_test-error-buffered-file->buffer)
 8913     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8914     68/push 0/imm32
 8915     68/push 0/imm32
 8916     89/<- %edx 4/r32/esp
 8917     (tailor-exit-descriptor %edx 0x10)
 8918     #
 8919     (write _test-input-stream "fn foo {\n")
 8920     (write _test-input-stream "  var a: int\n")
 8921     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 8922     (write _test-input-stream "}\n")
 8923     # convert
 8924     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8925     # registers except esp clobbered at this point
 8926     # restore ed
 8927     89/<- %edx 4/r32/esp
 8928     (flush _test-output-buffered-file)
 8929     (flush _test-error-buffered-file)
 8930 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8936     # check output
 8937     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type: output should be empty")
 8938     (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")
 8939     # check that stop(1) was called
 8940     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type: exit status")
 8941     # don't restore from ebp
 8942     81 0/subop/add %esp 8/imm32
 8943     # . epilogue
 8944     5d/pop-to-ebp
 8945     c3/return
 8946 
 8947 test-get-with-wrong-base-type-2:
 8948     # . prologue
 8949     55/push-ebp
 8950     89/<- %ebp 4/r32/esp
 8951     # setup
 8952     (clear-stream _test-input-stream)
 8953     (clear-stream $_test-input-buffered-file->buffer)
 8954     (clear-stream _test-output-stream)
 8955     (clear-stream $_test-output-buffered-file->buffer)
 8956     (clear-stream _test-error-stream)
 8957     (clear-stream $_test-error-buffered-file->buffer)
 8958     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8959     68/push 0/imm32
 8960     68/push 0/imm32
 8961     89/<- %edx 4/r32/esp
 8962     (tailor-exit-descriptor %edx 0x10)
 8963     #
 8964     (write _test-input-stream "fn foo {\n")
 8965     (write _test-input-stream "  var a: (addr t)\n")
 8966     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 8967     (write _test-input-stream "}\n")
 8968     (write _test-input-stream "type t {\n")
 8969     (write _test-input-stream "  x: int\n")
 8970     (write _test-input-stream "}\n")
 8971     # convert
 8972     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8973     # registers except esp clobbered at this point
 8974     # restore ed
 8975     89/<- %edx 4/r32/esp
 8976     (flush _test-output-buffered-file)
 8977     (flush _test-error-buffered-file)
 8978 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8984     # check output
 8985     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type-2: output should be empty")
 8986     (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")
 8987     # check that stop(1) was called
 8988     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type-2: exit status")
 8989     # don't restore from ebp
 8990     81 0/subop/add %esp 8/imm32
 8991     # . epilogue
 8992     5d/pop-to-ebp
 8993     c3/return
 8994 
 8995 test-get-with-wrong-base-type-3:
 8996     # . prologue
 8997     55/push-ebp
 8998     89/<- %ebp 4/r32/esp
 8999     # setup
 9000     (clear-stream _test-input-stream)
 9001     (clear-stream $_test-input-buffered-file->buffer)
 9002     (clear-stream _test-output-stream)
 9003     (clear-stream $_test-output-buffered-file->buffer)
 9004     (clear-stream _test-error-stream)
 9005     (clear-stream $_test-error-buffered-file->buffer)
 9006     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9007     68/push 0/imm32
 9008     68/push 0/imm32
 9009     89/<- %edx 4/r32/esp
 9010     (tailor-exit-descriptor %edx 0x10)
 9011     #
 9012     (write _test-input-stream "fn foo {\n")
 9013     (write _test-input-stream "  var a: (handle int)\n")
 9014     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 9015     (write _test-input-stream "}\n")
 9016     # convert
 9017     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9018     # registers except esp clobbered at this point
 9019     # restore ed
 9020     89/<- %edx 4/r32/esp
 9021     (flush _test-output-buffered-file)
 9022     (flush _test-error-buffered-file)
 9023 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9029     # check output
 9030     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type-3: output should be empty")
 9031     (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")
 9032     # check that stop(1) was called
 9033     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type-3: exit status")
 9034     # don't restore from ebp
 9035     81 0/subop/add %esp 8/imm32
 9036     # . epilogue
 9037     5d/pop-to-ebp
 9038     c3/return
 9039 
 9040 test-get-with-wrong-offset-type:
 9041     # . prologue
 9042     55/push-ebp
 9043     89/<- %ebp 4/r32/esp
 9044     # setup
 9045     (clear-stream _test-input-stream)
 9046     (clear-stream $_test-input-buffered-file->buffer)
 9047     (clear-stream _test-output-stream)
 9048     (clear-stream $_test-output-buffered-file->buffer)
 9049     (clear-stream _test-error-stream)
 9050     (clear-stream $_test-error-buffered-file->buffer)
 9051     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9052     68/push 0/imm32
 9053     68/push 0/imm32
 9054     89/<- %edx 4/r32/esp
 9055     (tailor-exit-descriptor %edx 0x10)
 9056     #
 9057     (write _test-input-stream "fn foo {\n")
 9058     (write _test-input-stream "  var a: t\n")
 9059     (write _test-input-stream "  var b: int\n")
 9060     (write _test-input-stream "  var c/ecx: (addr int) <- get a, b\n")
 9061     (write _test-input-stream "}\n")
 9062     (write _test-input-stream "type t {\n")
 9063     (write _test-input-stream "  x: int\n")
 9064     (write _test-input-stream "}\n")
 9065     # convert
 9066     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9067     # registers except esp clobbered at this point
 9068     # restore ed
 9069     89/<- %edx 4/r32/esp
 9070     (flush _test-output-buffered-file)
 9071     (flush _test-error-buffered-file)
 9072 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9078     # check output
 9079     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-offset-type: output should be empty")
 9080     (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")
 9081     # check that stop(1) was called
 9082     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-offset-type: exit status")
 9083     # don't restore from ebp
 9084     81 0/subop/add %esp 8/imm32
 9085     # . epilogue
 9086     5d/pop-to-ebp
 9087     c3/return
 9088 
 9089 test-get-with-wrong-output-type:
 9090     # . prologue
 9091     55/push-ebp
 9092     89/<- %ebp 4/r32/esp
 9093     # setup
 9094     (clear-stream _test-input-stream)
 9095     (clear-stream $_test-input-buffered-file->buffer)
 9096     (clear-stream _test-output-stream)
 9097     (clear-stream $_test-output-buffered-file->buffer)
 9098     (clear-stream _test-error-stream)
 9099     (clear-stream $_test-error-buffered-file->buffer)
 9100     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9101     68/push 0/imm32
 9102     68/push 0/imm32
 9103     89/<- %edx 4/r32/esp
 9104     (tailor-exit-descriptor %edx 0x10)
 9105     #
 9106     (write _test-input-stream "fn foo {\n")
 9107     (write _test-input-stream "  var a: t\n")
 9108     (write _test-input-stream "  var c: (addr int)\n")
 9109     (write _test-input-stream "  c <- get a, x\n")
 9110     (write _test-input-stream "}\n")
 9111     (write _test-input-stream "type t {\n")
 9112     (write _test-input-stream "  x: int\n")
 9113     (write _test-input-stream "}\n")
 9114     # convert
 9115     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9116     # registers except esp clobbered at this point
 9117     # restore ed
 9118     89/<- %edx 4/r32/esp
 9119     (flush _test-output-buffered-file)
 9120     (flush _test-error-buffered-file)
 9121 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9127     # check output
 9128     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type: output should be empty")
 9129     (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")
 9130     # check that stop(1) was called
 9131     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type: exit status")
 9132     # don't restore from ebp
 9133     81 0/subop/add %esp 8/imm32
 9134     # . epilogue
 9135     5d/pop-to-ebp
 9136     c3/return
 9137 
 9138 test-get-with-wrong-output-type-2:
 9139     # . prologue
 9140     55/push-ebp
 9141     89/<- %ebp 4/r32/esp
 9142     # setup
 9143     (clear-stream _test-input-stream)
 9144     (clear-stream $_test-input-buffered-file->buffer)
 9145     (clear-stream _test-output-stream)
 9146     (clear-stream $_test-output-buffered-file->buffer)
 9147     (clear-stream _test-error-stream)
 9148     (clear-stream $_test-error-buffered-file->buffer)
 9149     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9150     68/push 0/imm32
 9151     68/push 0/imm32
 9152     89/<- %edx 4/r32/esp
 9153     (tailor-exit-descriptor %edx 0x10)
 9154     #
 9155     (write _test-input-stream "fn foo {\n")
 9156     (write _test-input-stream "  var a: t\n")
 9157     (write _test-input-stream "  var c/ecx: int <- get a, x\n")
 9158     (write _test-input-stream "}\n")
 9159     (write _test-input-stream "type t {\n")
 9160     (write _test-input-stream "  x: int\n")
 9161     (write _test-input-stream "}\n")
 9162     # convert
 9163     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9164     # registers except esp clobbered at this point
 9165     # restore ed
 9166     89/<- %edx 4/r32/esp
 9167     (flush _test-output-buffered-file)
 9168     (flush _test-error-buffered-file)
 9169 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9175     # check output
 9176     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-2: output should be empty")
 9177     (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")
 9178     # check that stop(1) was called
 9179     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-2: exit status")
 9180     # don't restore from ebp
 9181     81 0/subop/add %esp 8/imm32
 9182     # . epilogue
 9183     5d/pop-to-ebp
 9184     c3/return
 9185 
 9186 test-get-with-wrong-output-type-3:
 9187     # . prologue
 9188     55/push-ebp
 9189     89/<- %ebp 4/r32/esp
 9190     # setup
 9191     (clear-stream _test-input-stream)
 9192     (clear-stream $_test-input-buffered-file->buffer)
 9193     (clear-stream _test-output-stream)
 9194     (clear-stream $_test-output-buffered-file->buffer)
 9195     (clear-stream _test-error-stream)
 9196     (clear-stream $_test-error-buffered-file->buffer)
 9197     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9198     68/push 0/imm32
 9199     68/push 0/imm32
 9200     89/<- %edx 4/r32/esp
 9201     (tailor-exit-descriptor %edx 0x10)
 9202     #
 9203     (write _test-input-stream "fn foo {\n")
 9204     (write _test-input-stream "  var a: t\n")
 9205     (write _test-input-stream "  var c/ecx: (array int) <- get a, x\n")
 9206     (write _test-input-stream "}\n")
 9207     (write _test-input-stream "type t {\n")
 9208     (write _test-input-stream "  x: int\n")
 9209     (write _test-input-stream "}\n")
 9210     # convert
 9211     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9212     # registers except esp clobbered at this point
 9213     # restore ed
 9214     89/<- %edx 4/r32/esp
 9215     (flush _test-output-buffered-file)
 9216     (flush _test-error-buffered-file)
 9217 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9223     # check output
 9224     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-3: output should be empty")
 9225     (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")
 9226     # check that stop(1) was called
 9227     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-3: exit status")
 9228     # don't restore from ebp
 9229     81 0/subop/add %esp 8/imm32
 9230     # . epilogue
 9231     5d/pop-to-ebp
 9232     c3/return
 9233 
 9234 test-get-with-wrong-output-type-4:
 9235     # . prologue
 9236     55/push-ebp
 9237     89/<- %ebp 4/r32/esp
 9238     # setup
 9239     (clear-stream _test-input-stream)
 9240     (clear-stream $_test-input-buffered-file->buffer)
 9241     (clear-stream _test-output-stream)
 9242     (clear-stream $_test-output-buffered-file->buffer)
 9243     (clear-stream _test-error-stream)
 9244     (clear-stream $_test-error-buffered-file->buffer)
 9245     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9246     68/push 0/imm32
 9247     68/push 0/imm32
 9248     89/<- %edx 4/r32/esp
 9249     (tailor-exit-descriptor %edx 0x10)
 9250     #
 9251     (write _test-input-stream "fn foo {\n")
 9252     (write _test-input-stream "  var a: t\n")
 9253     (write _test-input-stream "  var c/ecx: (addr boolean) <- get a, x\n")
 9254     (write _test-input-stream "}\n")
 9255     (write _test-input-stream "type t {\n")
 9256     (write _test-input-stream "  x: int\n")
 9257     (write _test-input-stream "}\n")
 9258     # convert
 9259     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9260     # registers except esp clobbered at this point
 9261     # restore ed
 9262     89/<- %edx 4/r32/esp
 9263     (flush _test-output-buffered-file)
 9264     (flush _test-error-buffered-file)
 9265 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9271     # check output
 9272     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-4: output should be empty")
 9273     (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")
 9274     # check that stop(1) was called
 9275     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-4: exit status")
 9276     # don't restore from ebp
 9277     81 0/subop/add %esp 8/imm32
 9278     # . epilogue
 9279     5d/pop-to-ebp
 9280     c3/return
 9281 
 9282 test-get-with-wrong-output-type-5:
 9283     # . prologue
 9284     55/push-ebp
 9285     89/<- %ebp 4/r32/esp
 9286     # setup
 9287     (clear-stream _test-input-stream)
 9288     (clear-stream $_test-input-buffered-file->buffer)
 9289     (clear-stream _test-output-stream)
 9290     (clear-stream $_test-output-buffered-file->buffer)
 9291     #
 9292     (write _test-input-stream "fn foo {\n")
 9293     (write _test-input-stream "  var a: t\n")
 9294     (write _test-input-stream "  var c/ecx: (addr handle int) <- get a, x\n")
 9295     (write _test-input-stream "}\n")
 9296     (write _test-input-stream "type t {\n")
 9297     (write _test-input-stream "  x: (handle int)\n")
 9298     (write _test-input-stream "}\n")
 9299     # convert
 9300     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9301     (flush _test-output-buffered-file)
 9302     # no errors
 9303     # . epilogue
 9304     89/<- %esp 5/r32/ebp
 9305     5d/pop-to-ebp
 9306     c3/return
 9307 
 9308 test-get-with-too-few-inouts:
 9309     # . prologue
 9310     55/push-ebp
 9311     89/<- %ebp 4/r32/esp
 9312     # setup
 9313     (clear-stream _test-input-stream)
 9314     (clear-stream $_test-input-buffered-file->buffer)
 9315     (clear-stream _test-output-stream)
 9316     (clear-stream $_test-output-buffered-file->buffer)
 9317     (clear-stream _test-error-stream)
 9318     (clear-stream $_test-error-buffered-file->buffer)
 9319     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9320     68/push 0/imm32
 9321     68/push 0/imm32
 9322     89/<- %edx 4/r32/esp
 9323     (tailor-exit-descriptor %edx 0x10)
 9324     #
 9325     (write _test-input-stream "fn foo {\n")
 9326     (write _test-input-stream "  var a: t\n")
 9327     (write _test-input-stream "  var c/ecx: (addr int) <- get a\n")
 9328     (write _test-input-stream "}\n")
 9329     (write _test-input-stream "type t {\n")
 9330     (write _test-input-stream "  x: int\n")
 9331     (write _test-input-stream "}\n")
 9332     # convert
 9333     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9334     # registers except esp clobbered at this point
 9335     # restore ed
 9336     89/<- %edx 4/r32/esp
 9337     (flush _test-output-buffered-file)
 9338     (flush _test-error-buffered-file)
 9339 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9345     # check output
 9346     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-few-inouts: output should be empty")
 9347     (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")
 9348     # check that stop(1) was called
 9349     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-few-inouts: exit status")
 9350     # don't restore from ebp
 9351     81 0/subop/add %esp 8/imm32
 9352     # . epilogue
 9353     5d/pop-to-ebp
 9354     c3/return
 9355 
 9356 test-get-with-too-many-inouts:
 9357     # . prologue
 9358     55/push-ebp
 9359     89/<- %ebp 4/r32/esp
 9360     # setup
 9361     (clear-stream _test-input-stream)
 9362     (clear-stream $_test-input-buffered-file->buffer)
 9363     (clear-stream _test-output-stream)
 9364     (clear-stream $_test-output-buffered-file->buffer)
 9365     (clear-stream _test-error-stream)
 9366     (clear-stream $_test-error-buffered-file->buffer)
 9367     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9368     68/push 0/imm32
 9369     68/push 0/imm32
 9370     89/<- %edx 4/r32/esp
 9371     (tailor-exit-descriptor %edx 0x10)
 9372     #
 9373     (write _test-input-stream "fn foo {\n")
 9374     (write _test-input-stream "  var a: t\n")
 9375     (write _test-input-stream "  var c/ecx: (addr int) <- get a, x, 0\n")
 9376     (write _test-input-stream "}\n")
 9377     (write _test-input-stream "type t {\n")
 9378     (write _test-input-stream "  x: int\n")
 9379     (write _test-input-stream "}\n")
 9380     # convert
 9381     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9382     # registers except esp clobbered at this point
 9383     # restore ed
 9384     89/<- %edx 4/r32/esp
 9385     (flush _test-output-buffered-file)
 9386     (flush _test-error-buffered-file)
 9387 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9393     # check output
 9394     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-many-inouts: output should be empty")
 9395     (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")
 9396     # check that stop(1) was called
 9397     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-many-inouts: exit status")
 9398     # don't restore from ebp
 9399     81 0/subop/add %esp 8/imm32
 9400     # . epilogue
 9401     5d/pop-to-ebp
 9402     c3/return
 9403 
 9404 test-get-with-no-output:
 9405     # . prologue
 9406     55/push-ebp
 9407     89/<- %ebp 4/r32/esp
 9408     # setup
 9409     (clear-stream _test-input-stream)
 9410     (clear-stream $_test-input-buffered-file->buffer)
 9411     (clear-stream _test-output-stream)
 9412     (clear-stream $_test-output-buffered-file->buffer)
 9413     (clear-stream _test-error-stream)
 9414     (clear-stream $_test-error-buffered-file->buffer)
 9415     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9416     68/push 0/imm32
 9417     68/push 0/imm32
 9418     89/<- %edx 4/r32/esp
 9419     (tailor-exit-descriptor %edx 0x10)
 9420     #
 9421     (write _test-input-stream "fn foo {\n")
 9422     (write _test-input-stream "  var a: t\n")
 9423     (write _test-input-stream "  get a, x\n")
 9424     (write _test-input-stream "}\n")
 9425     (write _test-input-stream "type t {\n")
 9426     (write _test-input-stream "  x: int\n")
 9427     (write _test-input-stream "}\n")
 9428     # convert
 9429     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9430     # registers except esp clobbered at this point
 9431     # restore ed
 9432     89/<- %edx 4/r32/esp
 9433     (flush _test-output-buffered-file)
 9434     (flush _test-error-buffered-file)
 9435 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9441     # check output
 9442     (check-stream-equal _test-output-stream  ""  "F - test-get-with-no-output: output should be empty")
 9443     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: must have an output"  "F - test-get-with-no-output: error message")
 9444     # check that stop(1) was called
 9445     (check-ints-equal *(edx+4) 2 "F - test-get-with-no-output: exit status")
 9446     # don't restore from ebp
 9447     81 0/subop/add %esp 8/imm32
 9448     # . epilogue
 9449     5d/pop-to-ebp
 9450     c3/return
 9451 
 9452 test-get-with-too-many-outputs:
 9453     # . prologue
 9454     55/push-ebp
 9455     89/<- %ebp 4/r32/esp
 9456     # setup
 9457     (clear-stream _test-input-stream)
 9458     (clear-stream $_test-input-buffered-file->buffer)
 9459     (clear-stream _test-output-stream)
 9460     (clear-stream $_test-output-buffered-file->buffer)
 9461     (clear-stream _test-error-stream)
 9462     (clear-stream $_test-error-buffered-file->buffer)
 9463     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9464     68/push 0/imm32
 9465     68/push 0/imm32
 9466     89/<- %edx 4/r32/esp
 9467     (tailor-exit-descriptor %edx 0x10)
 9468     #
 9469     (write _test-input-stream "fn foo {\n")
 9470     (write _test-input-stream "  var a: t\n")
 9471     (write _test-input-stream "  var b: int\n")
 9472     (write _test-input-stream "  var c/eax: (addr int) <- copy 0\n")
 9473     (write _test-input-stream "  c, b <- get a, x\n")
 9474     (write _test-input-stream "}\n")
 9475     (write _test-input-stream "type t {\n")
 9476     (write _test-input-stream "  x: int\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-get-with-too-many-outputs: output should be empty")
 9493     (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")
 9494     # check that stop(1) was called
 9495     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-many-outputs: 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-convert-array-of-user-defined-types:
 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 "type t {\n")  # each t is 8 bytes, which is a power of 2
 9513     (write _test-input-stream "  x: int\n")
 9514     (write _test-input-stream "  y: int\n")
 9515     (write _test-input-stream "}\n")
 9516     (write _test-input-stream "fn foo {\n")
 9517     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
 9518     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 9519     (write _test-input-stream "  var x/eax: (addr t) <- index arr, idx\n")
 9520     (write _test-input-stream "}\n")
 9521     # convert
 9522     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9523     (flush _test-output-buffered-file)
 9524 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9530     # check output
 9531     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-array-of-user-defined-types/0")
 9532     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-array-of-user-defined-types/1")
 9533     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-array-of-user-defined-types/2")
 9534     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-array-of-user-defined-types/3")
 9535     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-array-of-user-defined-types/4")
 9536     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-array-of-user-defined-types/5")
 9537     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-array-of-user-defined-types/6")
 9538     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-array-of-user-defined-types/7")
 9539     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-array-of-user-defined-types/8")
 9540     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-array-of-user-defined-types/9")
 9541     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx<<0x00000003 + 4) 0x00000000/r32"  "F - test-convert-array-of-user-defined-types/11")
 9542     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-array-of-user-defined-types/13")
 9543     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-array-of-user-defined-types/14")
 9544     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-array-of-user-defined-types/15")
 9545     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-array-of-user-defined-types/16")
 9546     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-array-of-user-defined-types/17")
 9547     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-array-of-user-defined-types/18")
 9548     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-array-of-user-defined-types/19")
 9549     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-array-of-user-defined-types/20")
 9550     # . epilogue
 9551     89/<- %esp 5/r32/ebp
 9552     5d/pop-to-ebp
 9553     c3/return
 9554 
 9555 test-convert-length-of-array-of-user-defined-types-to-eax:
 9556     # . prologue
 9557     55/push-ebp
 9558     89/<- %ebp 4/r32/esp
 9559     # setup
 9560     (clear-stream _test-input-stream)
 9561     (clear-stream $_test-input-buffered-file->buffer)
 9562     (clear-stream _test-output-stream)
 9563     (clear-stream $_test-output-buffered-file->buffer)
 9564     #
 9565     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
 9566     (write _test-input-stream "  x: int\n")
 9567     (write _test-input-stream "  y: int\n")
 9568     (write _test-input-stream "  z: int\n")
 9569     (write _test-input-stream "}\n")
 9570     (write _test-input-stream "fn foo {\n")
 9571     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
 9572     (write _test-input-stream "  var x/eax: int <- length arr\n")
 9573     (write _test-input-stream "}\n")
 9574     # convert
 9575     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9576     (flush _test-output-buffered-file)
 9577 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9583     # check output
 9584     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-eax/0")
 9585     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-eax/1")
 9586     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-eax/2")
 9587     (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")
 9588     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-eax/4")
 9589     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-eax/5")
 9590     # var arr
 9591     (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")
 9592     (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")
 9593     # length instruction
 9594     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types-to-eax/8")
 9595     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types-to-eax/9")
 9596     (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")
 9597     (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")
 9598     (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")
 9599     (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")
 9600     (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")
 9601     (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")
 9602     # reclaim arr
 9603     (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")
 9604     #
 9605     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-eax/17")
 9606     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/18")
 9607     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-eax/19")
 9608     (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")
 9609     (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")
 9610     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-eax/22")
 9611     # . epilogue
 9612     89/<- %esp 5/r32/ebp
 9613     5d/pop-to-ebp
 9614     c3/return
 9615 
 9616 test-convert-length-of-array-of-user-defined-types-to-ecx:
 9617     # . prologue
 9618     55/push-ebp
 9619     89/<- %ebp 4/r32/esp
 9620     # setup
 9621     (clear-stream _test-input-stream)
 9622     (clear-stream $_test-input-buffered-file->buffer)
 9623     (clear-stream _test-output-stream)
 9624     (clear-stream $_test-output-buffered-file->buffer)
 9625     #
 9626     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
 9627     (write _test-input-stream "  x: int\n")
 9628     (write _test-input-stream "  y: int\n")
 9629     (write _test-input-stream "  z: int\n")
 9630     (write _test-input-stream "}\n")
 9631     (write _test-input-stream "fn foo {\n")
 9632     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
 9633     (write _test-input-stream "  var x/ecx: int <- length arr\n")
 9634     (write _test-input-stream "}\n")
 9635     # convert
 9636     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9637     (flush _test-output-buffered-file)
 9638 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9644     # check output
 9645     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-ecx/0")
 9646     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-ecx/1")
 9647     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-ecx/2")
 9648     (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")
 9649     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-ecx/4")
 9650     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-ecx/5")
 9651     # var a
 9652     (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")
 9653     (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")
 9654     # var x
 9655     (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")
 9656     # length instruction
 9657     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types-to-ecx/9")
 9658     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types-to-ecx/10")
 9659     (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")
 9660     (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")
 9661     (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")
 9662     (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")
 9663     (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")
 9664     (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")
 9665     (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")
 9666     # reclaim x
 9667     (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")
 9668     # reclaim a
 9669     (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")
 9670     #
 9671     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-ecx/20")
 9672     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/21")
 9673     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-ecx/22")
 9674     (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")
 9675     (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")
 9676     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-ecx/25")
 9677     # . epilogue
 9678     89/<- %esp 5/r32/ebp
 9679     5d/pop-to-ebp
 9680     c3/return
 9681 
 9682 test-convert-length-of-array-of-user-defined-types-to-edx:
 9683     # . prologue
 9684     55/push-ebp
 9685     89/<- %ebp 4/r32/esp
 9686     # setup
 9687     (clear-stream _test-input-stream)
 9688     (clear-stream $_test-input-buffered-file->buffer)
 9689     (clear-stream _test-output-stream)
 9690     (clear-stream $_test-output-buffered-file->buffer)
 9691     #
 9692     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
 9693     (write _test-input-stream "  x: int\n")
 9694     (write _test-input-stream "  y: int\n")
 9695     (write _test-input-stream "  z: int\n")
 9696     (write _test-input-stream "}\n")
 9697     (write _test-input-stream "fn foo {\n")
 9698     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
 9699     (write _test-input-stream "  var x/edx: int <- length arr\n")
 9700     (write _test-input-stream "}\n")
 9701     # convert
 9702     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9703     (flush _test-output-buffered-file)
 9704 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9710     # check output
 9711     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-edx/0")
 9712     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-edx/1")
 9713     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-edx/2")
 9714     (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")
 9715     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-edx/4")
 9716     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-edx/5")
 9717     # var a
 9718     (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")
 9719     (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")
 9720     # var x
 9721     (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")
 9722     # length instruction
 9723     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types-to-edx/9")
 9724     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types-to-edx/10")
 9725     (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")
 9726     (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")
 9727     (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")
 9728     (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")
 9729     (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")
 9730     (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")
 9731     (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")
 9732     # reclaim x
 9733     (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")
 9734     # reclaim a
 9735     (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")
 9736     #
 9737     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-edx/20")
 9738     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/21")
 9739     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-edx/22")
 9740     (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")
 9741     (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")
 9742     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-edx/25")
 9743     # . epilogue
 9744     89/<- %esp 5/r32/ebp
 9745     5d/pop-to-ebp
 9746     c3/return
 9747 
 9748 test-convert-length-of-array-of-user-defined-types:
 9749     # . prologue
 9750     55/push-ebp
 9751     89/<- %ebp 4/r32/esp
 9752     # setup
 9753     (clear-stream _test-input-stream)
 9754     (clear-stream $_test-input-buffered-file->buffer)
 9755     (clear-stream _test-output-stream)
 9756     (clear-stream $_test-output-buffered-file->buffer)
 9757     #
 9758     (write _test-input-stream "type t {\n")  # each t is 8 bytes, which is a power of 2
 9759     (write _test-input-stream "  x: int\n")
 9760     (write _test-input-stream "  y: int\n")
 9761     (write _test-input-stream "  z: int\n")
 9762     (write _test-input-stream "}\n")
 9763     (write _test-input-stream "fn foo {\n")
 9764     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
 9765     (write _test-input-stream "  var x/ebx: int <- length arr\n")
 9766     (write _test-input-stream "}\n")
 9767     # convert
 9768     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9769     (flush _test-output-buffered-file)
 9770 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9776     # check output
 9777     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types/0")
 9778     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types/1")
 9779     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types/2")
 9780     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-user-defined-types/3")
 9781     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types/4")
 9782     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types/5")
 9783     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-of-user-defined-types/6")
 9784     (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")
 9785     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-length-of-array-of-user-defined-types/8")
 9786     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types/9")
 9787     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types/10")
 9788     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types/11")
 9789     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array-of-user-defined-types/12")
 9790     (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")
 9791     (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")
 9792     (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")
 9793     (check-next-stream-line-equal _test-output-stream "    89/<- %ebx 0/r32/eax"  "F - test-convert-length-of-array-of-user-defined-types/16")
 9794     (check-next-stream-line-equal _test-output-stream "    5a/pop-to-edx"       "F - test-convert-length-of-array-of-user-defined-types/17")
 9795     (check-next-stream-line-equal _test-output-stream "    59/pop-to-ecx"       "F - test-convert-length-of-array-of-user-defined-types/18")
 9796     (check-next-stream-line-equal _test-output-stream "    58/pop-to-eax"       "F - test-convert-length-of-array-of-user-defined-types/19")
 9797     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ebx"  "F - test-convert-length-of-array-of-user-defined-types/20")
 9798     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-of-user-defined-types/21")
 9799     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types/22")
 9800     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types/23")
 9801     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types/24")
 9802     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-of-user-defined-types/25")
 9803     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-of-user-defined-types/26")
 9804     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types/27")
 9805     # . epilogue
 9806     89/<- %esp 5/r32/ebp
 9807     5d/pop-to-ebp
 9808     c3/return
 9809 
 9810 test-index-with-non-array-atom-base-type:
 9811     # . prologue
 9812     55/push-ebp
 9813     89/<- %ebp 4/r32/esp
 9814     # setup
 9815     (clear-stream _test-input-stream)
 9816     (clear-stream $_test-input-buffered-file->buffer)
 9817     (clear-stream _test-output-stream)
 9818     (clear-stream $_test-output-buffered-file->buffer)
 9819     (clear-stream _test-error-stream)
 9820     (clear-stream $_test-error-buffered-file->buffer)
 9821     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9822     68/push 0/imm32
 9823     68/push 0/imm32
 9824     89/<- %edx 4/r32/esp
 9825     (tailor-exit-descriptor %edx 0x10)
 9826     #
 9827     (write _test-input-stream "fn foo {\n")
 9828     (write _test-input-stream "  var a: int\n")
 9829     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
 9830     (write _test-input-stream "}\n")
 9831     # convert
 9832     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9833     # registers except esp clobbered at this point
 9834     # restore ed
 9835     89/<- %edx 4/r32/esp
 9836     (flush _test-output-buffered-file)
 9837     (flush _test-error-buffered-file)
 9838 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9844     # check output
 9845     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-atom-base-type: output should be empty")
 9846     (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")
 9847     # check that stop(1) was called
 9848     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-atom-base-type: exit status")
 9849     # don't restore from ebp
 9850     81 0/subop/add %esp 8/imm32
 9851     # . epilogue
 9852     5d/pop-to-ebp
 9853     c3/return
 9854 
 9855 test-index-with-non-array-compound-base-type:
 9856     # . prologue
 9857     55/push-ebp
 9858     89/<- %ebp 4/r32/esp
 9859     # setup
 9860     (clear-stream _test-input-stream)
 9861     (clear-stream $_test-input-buffered-file->buffer)
 9862     (clear-stream _test-output-stream)
 9863     (clear-stream $_test-output-buffered-file->buffer)
 9864     (clear-stream _test-error-stream)
 9865     (clear-stream $_test-error-buffered-file->buffer)
 9866     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9867     68/push 0/imm32
 9868     68/push 0/imm32
 9869     89/<- %edx 4/r32/esp
 9870     (tailor-exit-descriptor %edx 0x10)
 9871     #
 9872     (write _test-input-stream "fn foo {\n")
 9873     (write _test-input-stream "  var a: (handle int)\n")
 9874     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
 9875     (write _test-input-stream "}\n")
 9876     # convert
 9877     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9878     # registers except esp clobbered at this point
 9879     # restore ed
 9880     89/<- %edx 4/r32/esp
 9881     (flush _test-output-buffered-file)
 9882     (flush _test-error-buffered-file)
 9883 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9889     # check output
 9890     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-compound-base-type: output should be empty")
 9891     (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")
 9892     # check that stop(1) was called
 9893     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-compound-base-type: exit status")
 9894     # don't restore from ebp
 9895     81 0/subop/add %esp 8/imm32
 9896     # . epilogue
 9897     5d/pop-to-ebp
 9898     c3/return
 9899 
 9900 test-index-with-non-array-compound-base-type-2:
 9901     # . prologue
 9902     55/push-ebp
 9903     89/<- %ebp 4/r32/esp
 9904     # setup
 9905     (clear-stream _test-input-stream)
 9906     (clear-stream $_test-input-buffered-file->buffer)
 9907     (clear-stream _test-output-stream)
 9908     (clear-stream $_test-output-buffered-file->buffer)
 9909     (clear-stream _test-error-stream)
 9910     (clear-stream $_test-error-buffered-file->buffer)
 9911     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9912     68/push 0/imm32
 9913     68/push 0/imm32
 9914     89/<- %edx 4/r32/esp
 9915     (tailor-exit-descriptor %edx 0x10)
 9916     #
 9917     (write _test-input-stream "fn foo {\n")
 9918     (write _test-input-stream "  var a: (addr int)\n")
 9919     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
 9920     (write _test-input-stream "}\n")
 9921     # convert
 9922     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9923     # registers except esp clobbered at this point
 9924     # restore ed
 9925     89/<- %edx 4/r32/esp
 9926     (flush _test-output-buffered-file)
 9927     (flush _test-error-buffered-file)
 9928 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9934     # check output
 9935     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-compound-base-type-2: output should be empty")
 9936     (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")
 9937     # check that stop(1) was called
 9938     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-compound-base-type-2: exit status")
 9939     # don't restore from ebp
 9940     81 0/subop/add %esp 8/imm32
 9941     # . epilogue
 9942     5d/pop-to-ebp
 9943     c3/return
 9944 
 9945 test-index-with-array-atom-base-type:
 9946     # . prologue
 9947     55/push-ebp
 9948     89/<- %ebp 4/r32/esp
 9949     # setup
 9950     (clear-stream _test-input-stream)
 9951     (clear-stream $_test-input-buffered-file->buffer)
 9952     (clear-stream _test-output-stream)
 9953     (clear-stream $_test-output-buffered-file->buffer)
 9954     (clear-stream _test-error-stream)
 9955     (clear-stream $_test-error-buffered-file->buffer)
 9956     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9957     68/push 0/imm32
 9958     68/push 0/imm32
 9959     89/<- %edx 4/r32/esp
 9960     (tailor-exit-descriptor %edx 0x10)
 9961     #
 9962     (write _test-input-stream "fn foo {\n")
 9963     (write _test-input-stream "  var a: array\n")
 9964     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
 9965     (write _test-input-stream "}\n")
 9966     # convert
 9967     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9968     # registers except esp clobbered at this point
 9969     # restore ed
 9970     89/<- %edx 4/r32/esp
 9971     (flush _test-output-buffered-file)
 9972     (flush _test-error-buffered-file)
 9973 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9979     # check output
 9980     (check-stream-equal _test-output-stream  ""  "F - test-index-with-array-atom-base-type: output should be empty")
 9981     (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")
 9982     # check that stop(1) was called
 9983     (check-ints-equal *(edx+4) 2 "F - test-index-with-array-atom-base-type: exit status")
 9984     # don't restore from ebp
 9985     81 0/subop/add %esp 8/imm32
 9986     # . epilogue
 9987     5d/pop-to-ebp
 9988     c3/return
 9989 
 9990 test-index-with-addr-base-on-stack:
 9991     # . prologue
 9992     55/push-ebp
 9993     89/<- %ebp 4/r32/esp
 9994     # setup
 9995     (clear-stream _test-input-stream)
 9996     (clear-stream $_test-input-buffered-file->buffer)
 9997     (clear-stream _test-output-stream)
 9998     (clear-stream $_test-output-buffered-file->buffer)
 9999     (clear-stream _test-error-stream)
10000     (clear-stream $_test-error-buffered-file->buffer)
10001     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10002     68/push 0/imm32
10003     68/push 0/imm32
10004     89/<- %edx 4/r32/esp
10005     (tailor-exit-descriptor %edx 0x10)
10006     #
10007     (write _test-input-stream "fn foo {\n")
10008     (write _test-input-stream "  var a: (addr array int)\n")
10009     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
10010     (write _test-input-stream "}\n")
10011     # convert
10012     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10013     # registers except esp clobbered at this point
10014     # restore ed
10015     89/<- %edx 4/r32/esp
10016     (flush _test-output-buffered-file)
10017     (flush _test-error-buffered-file)
10018 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10024     # check output
10025     (check-stream-equal _test-output-stream  ""  "F - test-index-with-addr-base-on-stack: output should be empty")
10026     (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")
10027     # check that stop(1) was called
10028     (check-ints-equal *(edx+4) 2 "F - test-index-with-addr-base-on-stack: exit status")
10029     # don't restore from ebp
10030     81 0/subop/add %esp 8/imm32
10031     # . epilogue
10032     5d/pop-to-ebp
10033     c3/return
10034 
10035 test-index-with-wrong-index-type:
10036     # . prologue
10037     55/push-ebp
10038     89/<- %ebp 4/r32/esp
10039     # setup
10040     (clear-stream _test-input-stream)
10041     (clear-stream $_test-input-buffered-file->buffer)
10042     (clear-stream _test-output-stream)
10043     (clear-stream $_test-output-buffered-file->buffer)
10044     (clear-stream _test-error-stream)
10045     (clear-stream $_test-error-buffered-file->buffer)
10046     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10047     68/push 0/imm32
10048     68/push 0/imm32
10049     89/<- %edx 4/r32/esp
10050     (tailor-exit-descriptor %edx 0x10)
10051     #
10052     (write _test-input-stream "fn foo {\n")
10053     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
10054     (write _test-input-stream "  var b: boolean\n")
10055     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
10056     (write _test-input-stream "}\n")
10057     # convert
10058     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10059     # registers except esp clobbered at this point
10060     # restore ed
10061     89/<- %edx 4/r32/esp
10062     (flush _test-output-buffered-file)
10063     (flush _test-error-buffered-file)
10064 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10070     # check output
10071     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-index-type: output should be empty")
10072     (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")
10073     # check that stop(1) was called
10074     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-index-type: exit status")
10075     # don't restore from ebp
10076     81 0/subop/add %esp 8/imm32
10077     # . epilogue
10078     5d/pop-to-ebp
10079     c3/return
10080 
10081 test-index-with-offset-atom-index-type:
10082     # . prologue
10083     55/push-ebp
10084     89/<- %ebp 4/r32/esp
10085     # setup
10086     (clear-stream _test-input-stream)
10087     (clear-stream $_test-input-buffered-file->buffer)
10088     (clear-stream _test-output-stream)
10089     (clear-stream $_test-output-buffered-file->buffer)
10090     (clear-stream _test-error-stream)
10091     (clear-stream $_test-error-buffered-file->buffer)
10092     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10093     68/push 0/imm32
10094     68/push 0/imm32
10095     89/<- %edx 4/r32/esp
10096     (tailor-exit-descriptor %edx 0x10)
10097     #
10098     (write _test-input-stream "fn foo {\n")
10099     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
10100     (write _test-input-stream "  var b: offset\n")
10101     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
10102     (write _test-input-stream "}\n")
10103     # convert
10104     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10105     # registers except esp clobbered at this point
10106     # restore ed
10107     89/<- %edx 4/r32/esp
10108     (flush _test-output-buffered-file)
10109     (flush _test-error-buffered-file)
10110 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10116     # check output
10117     (check-stream-equal _test-output-stream  ""  "F - test-index-with-offset-atom-index-type: output should be empty")
10118     (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")
10119     # check that stop(1) was called
10120     (check-ints-equal *(edx+4) 2 "F - test-index-with-offset-atom-index-type: exit status")
10121     # don't restore from ebp
10122     81 0/subop/add %esp 8/imm32
10123     # . epilogue
10124     5d/pop-to-ebp
10125     c3/return
10126 
10127 test-index-with-offset-on-stack:
10128     # . prologue
10129     55/push-ebp
10130     89/<- %ebp 4/r32/esp
10131     # setup
10132     (clear-stream _test-input-stream)
10133     (clear-stream $_test-input-buffered-file->buffer)
10134     (clear-stream _test-output-stream)
10135     (clear-stream $_test-output-buffered-file->buffer)
10136     (clear-stream _test-error-stream)
10137     (clear-stream $_test-error-buffered-file->buffer)
10138     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10139     68/push 0/imm32
10140     68/push 0/imm32
10141     89/<- %edx 4/r32/esp
10142     (tailor-exit-descriptor %edx 0x10)
10143     #
10144     (write _test-input-stream "fn foo {\n")
10145     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
10146     (write _test-input-stream "  var b: int\n")
10147     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
10148     (write _test-input-stream "}\n")
10149     # convert
10150     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10151     # registers except esp clobbered at this point
10152     # restore ed
10153     89/<- %edx 4/r32/esp
10154     (flush _test-output-buffered-file)
10155     (flush _test-error-buffered-file)
10156 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10162     # check output
10163     (check-stream-equal _test-output-stream  ""  "F - test-index-with-offset-on-stack: output should be empty")
10164     (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")
10165     # check that stop(1) was called
10166     (check-ints-equal *(edx+4) 2 "F - test-index-with-offset-on-stack: exit status")
10167     # don't restore from ebp
10168     81 0/subop/add %esp 8/imm32
10169     # . epilogue
10170     5d/pop-to-ebp
10171     c3/return
10172 
10173 test-index-needs-offset-type:
10174     # . prologue
10175     55/push-ebp
10176     89/<- %ebp 4/r32/esp
10177     # setup
10178     (clear-stream _test-input-stream)
10179     (clear-stream $_test-input-buffered-file->buffer)
10180     (clear-stream _test-output-stream)
10181     (clear-stream $_test-output-buffered-file->buffer)
10182     (clear-stream _test-error-stream)
10183     (clear-stream $_test-error-buffered-file->buffer)
10184     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10185     68/push 0/imm32
10186     68/push 0/imm32
10187     89/<- %edx 4/r32/esp
10188     (tailor-exit-descriptor %edx 0x10)
10189     #
10190     (write _test-input-stream "fn foo {\n")
10191     (write _test-input-stream "  var a/eax: (addr array t) <- copy 0\n")
10192     (write _test-input-stream "  var b/ebx: int <- copy 0\n")
10193     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
10194     (write _test-input-stream "}\n")
10195     (write _test-input-stream "type t {\n")  # size 12 is not a power of two
10196     (write _test-input-stream "  x: int\n")
10197     (write _test-input-stream "  y: int\n")
10198     (write _test-input-stream "  z: int\n")
10199     (write _test-input-stream "}\n")
10200     # convert
10201     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10202     # registers except esp clobbered at this point
10203     # restore ed
10204     89/<- %edx 4/r32/esp
10205     (flush _test-output-buffered-file)
10206     (flush _test-error-buffered-file)
10207 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10213     # check output
10214     (check-stream-equal _test-output-stream  ""  "F - test-index-needs-offset-type: output should be empty")
10215     (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")
10216     # check that stop(1) was called
10217     (check-ints-equal *(edx+4) 2 "F - test-index-needs-offset-type: exit status")
10218     # don't restore from ebp
10219     81 0/subop/add %esp 8/imm32
10220     # . epilogue
10221     5d/pop-to-ebp
10222     c3/return
10223 
10224 test-index-with-output-not-address:
10225     # . prologue
10226     55/push-ebp
10227     89/<- %ebp 4/r32/esp
10228     # setup
10229     (clear-stream _test-input-stream)
10230     (clear-stream $_test-input-buffered-file->buffer)
10231     (clear-stream _test-output-stream)
10232     (clear-stream $_test-output-buffered-file->buffer)
10233     (clear-stream _test-error-stream)
10234     (clear-stream $_test-error-buffered-file->buffer)
10235     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10236     68/push 0/imm32
10237     68/push 0/imm32
10238     89/<- %edx 4/r32/esp
10239     (tailor-exit-descriptor %edx 0x10)
10240     #
10241     (write _test-input-stream "fn foo {\n")
10242     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
10243     (write _test-input-stream "  var o/edi: int <- index a, 0\n")
10244     (write _test-input-stream "}\n")
10245     # convert
10246     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10247     # registers except esp clobbered at this point
10248     # restore ed
10249     89/<- %edx 4/r32/esp
10250     (flush _test-output-buffered-file)
10251     (flush _test-error-buffered-file)
10252 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10258     # check output
10259     (check-stream-equal _test-output-stream  ""  "F - test-index-with-output-not-address: output should be empty")
10260     (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")
10261     # check that stop(1) was called
10262     (check-ints-equal *(edx+4) 2 "F - test-index-with-output-not-address: exit status")
10263     # don't restore from ebp
10264     81 0/subop/add %esp 8/imm32
10265     # . epilogue
10266     5d/pop-to-ebp
10267     c3/return
10268 
10269 test-index-with-output-not-address-2:
10270     # . prologue
10271     55/push-ebp
10272     89/<- %ebp 4/r32/esp
10273     # setup
10274     (clear-stream _test-input-stream)
10275     (clear-stream $_test-input-buffered-file->buffer)
10276     (clear-stream _test-output-stream)
10277     (clear-stream $_test-output-buffered-file->buffer)
10278     (clear-stream _test-error-stream)
10279     (clear-stream $_test-error-buffered-file->buffer)
10280     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10281     68/push 0/imm32
10282     68/push 0/imm32
10283     89/<- %edx 4/r32/esp
10284     (tailor-exit-descriptor %edx 0x10)
10285     #
10286     (write _test-input-stream "fn foo {\n")
10287     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
10288     (write _test-input-stream "  var o/edi: (int) <- index a, 0\n")
10289     (write _test-input-stream "}\n")
10290     # convert
10291     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10292     # registers except esp clobbered at this point
10293     # restore ed
10294     89/<- %edx 4/r32/esp
10295     (flush _test-output-buffered-file)
10296     (flush _test-error-buffered-file)
10297 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10303     # check output
10304     (check-stream-equal _test-output-stream  ""  "F - test-index-with-output-not-address-2: output should be empty")
10305     (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")
10306     # check that stop(1) was called
10307     (check-ints-equal *(edx+4) 2 "F - test-index-with-output-not-address-2: exit status")
10308     # don't restore from ebp
10309     81 0/subop/add %esp 8/imm32
10310     # . epilogue
10311     5d/pop-to-ebp
10312     c3/return
10313 
10314 test-index-with-wrong-output-type:
10315     # . prologue
10316     55/push-ebp
10317     89/<- %ebp 4/r32/esp
10318     # setup
10319     (clear-stream _test-input-stream)
10320     (clear-stream $_test-input-buffered-file->buffer)
10321     (clear-stream _test-output-stream)
10322     (clear-stream $_test-output-buffered-file->buffer)
10323     (clear-stream _test-error-stream)
10324     (clear-stream $_test-error-buffered-file->buffer)
10325     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10326     68/push 0/imm32
10327     68/push 0/imm32
10328     89/<- %edx 4/r32/esp
10329     (tailor-exit-descriptor %edx 0x10)
10330     #
10331     (write _test-input-stream "fn foo {\n")
10332     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
10333     (write _test-input-stream "  var o/edi: (addr int) <- index a, 0\n")
10334     (write _test-input-stream "}\n")
10335     # convert
10336     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10337     # registers except esp clobbered at this point
10338     # restore ed
10339     89/<- %edx 4/r32/esp
10340     (flush _test-output-buffered-file)
10341     (flush _test-error-buffered-file)
10342 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10348     # check output
10349     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-output-type: output should be empty")
10350     (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")
10351     # check that stop(1) was called
10352     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-output-type: exit status")
10353     # don't restore from ebp
10354     81 0/subop/add %esp 8/imm32
10355     # . epilogue
10356     5d/pop-to-ebp
10357     c3/return
10358 
10359 test-index-with-wrong-output-compound-type:
10360     # . prologue
10361     55/push-ebp
10362     89/<- %ebp 4/r32/esp
10363     # setup
10364     (clear-stream _test-input-stream)
10365     (clear-stream $_test-input-buffered-file->buffer)
10366     (clear-stream _test-output-stream)
10367     (clear-stream $_test-output-buffered-file->buffer)
10368     (clear-stream _test-error-stream)
10369     (clear-stream $_test-error-buffered-file->buffer)
10370     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10371     68/push 0/imm32
10372     68/push 0/imm32
10373     89/<- %edx 4/r32/esp
10374     (tailor-exit-descriptor %edx 0x10)
10375     #
10376     (write _test-input-stream "fn foo {\n")
10377     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
10378     (write _test-input-stream "  var o/edi: (addr handle int) <- index a, 0\n")
10379     (write _test-input-stream "}\n")
10380     # convert
10381     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10382     # registers except esp clobbered at this point
10383     # restore ed
10384     89/<- %edx 4/r32/esp
10385     (flush _test-output-buffered-file)
10386     (flush _test-error-buffered-file)
10387 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10393     # check output
10394     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-output-compound-type: output should be empty")
10395     (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")
10396     # check that stop(1) was called
10397     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-output-compound-type: exit status")
10398     # don't restore from ebp
10399     81 0/subop/add %esp 8/imm32
10400     # . epilogue
10401     5d/pop-to-ebp
10402     c3/return
10403 
10404 test-index-with-no-inouts:
10405     # . prologue
10406     55/push-ebp
10407     89/<- %ebp 4/r32/esp
10408     # setup
10409     (clear-stream _test-input-stream)
10410     (clear-stream $_test-input-buffered-file->buffer)
10411     (clear-stream _test-output-stream)
10412     (clear-stream $_test-output-buffered-file->buffer)
10413     (clear-stream _test-error-stream)
10414     (clear-stream $_test-error-buffered-file->buffer)
10415     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10416     68/push 0/imm32
10417     68/push 0/imm32
10418     89/<- %edx 4/r32/esp
10419     (tailor-exit-descriptor %edx 0x10)
10420     #
10421     (write _test-input-stream "fn foo {\n")
10422     (write _test-input-stream "  var c/ecx: (addr int) <- index\n")
10423     (write _test-input-stream "}\n")
10424     # convert
10425     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10426     # registers except esp clobbered at this point
10427     # restore ed
10428     89/<- %edx 4/r32/esp
10429     (flush _test-output-buffered-file)
10430     (flush _test-error-buffered-file)
10431 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10437     # check output
10438     (check-stream-equal _test-output-stream  ""  "F - test-index-with-no-inouts: output should be empty")
10439     (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")
10440     # check that stop(1) was called
10441     (check-ints-equal *(edx+4) 2 "F - test-index-with-no-inouts: exit status")
10442     # don't restore from ebp
10443     81 0/subop/add %esp 8/imm32
10444     # . epilogue
10445     5d/pop-to-ebp
10446     c3/return
10447 
10448 test-index-with-too-few-inouts:
10449     # . prologue
10450     55/push-ebp
10451     89/<- %ebp 4/r32/esp
10452     # setup
10453     (clear-stream _test-input-stream)
10454     (clear-stream $_test-input-buffered-file->buffer)
10455     (clear-stream _test-output-stream)
10456     (clear-stream $_test-output-buffered-file->buffer)
10457     (clear-stream _test-error-stream)
10458     (clear-stream $_test-error-buffered-file->buffer)
10459     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10460     68/push 0/imm32
10461     68/push 0/imm32
10462     89/<- %edx 4/r32/esp
10463     (tailor-exit-descriptor %edx 0x10)
10464     #
10465     (write _test-input-stream "fn foo {\n")
10466     (write _test-input-stream "  var a: (array int 3)\n")
10467     (write _test-input-stream "  var c/ecx: (addr int) <- index a\n")
10468     (write _test-input-stream "}\n")
10469     # convert
10470     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10471     # registers except esp clobbered at this point
10472     # restore ed
10473     89/<- %edx 4/r32/esp
10474     (flush _test-output-buffered-file)
10475     (flush _test-error-buffered-file)
10476 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10482     # check output
10483     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-few-inouts: output should be empty")
10484     (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")
10485     # check that stop(1) was called
10486     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-few-inouts: exit status")
10487     # don't restore from ebp
10488     81 0/subop/add %esp 8/imm32
10489     # . epilogue
10490     5d/pop-to-ebp
10491     c3/return
10492 
10493 test-index-with-too-many-inouts:
10494     # . prologue
10495     55/push-ebp
10496     89/<- %ebp 4/r32/esp
10497     # setup
10498     (clear-stream _test-input-stream)
10499     (clear-stream $_test-input-buffered-file->buffer)
10500     (clear-stream _test-output-stream)
10501     (clear-stream $_test-output-buffered-file->buffer)
10502     (clear-stream _test-error-stream)
10503     (clear-stream $_test-error-buffered-file->buffer)
10504     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10505     68/push 0/imm32
10506     68/push 0/imm32
10507     89/<- %edx 4/r32/esp
10508     (tailor-exit-descriptor %edx 0x10)
10509     #
10510     (write _test-input-stream "fn foo {\n")
10511     (write _test-input-stream "  var a: (array int 3)\n")
10512     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0, 0\n")
10513     (write _test-input-stream "}\n")
10514     # convert
10515     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10516     # registers except esp clobbered at this point
10517     # restore ed
10518     89/<- %edx 4/r32/esp
10519     (flush _test-output-buffered-file)
10520     (flush _test-error-buffered-file)
10521 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10527     # check output
10528     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-many-inouts: output should be empty")
10529     (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")
10530     # check that stop(1) was called
10531     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-many-inouts: exit status")
10532     # don't restore from ebp
10533     81 0/subop/add %esp 8/imm32
10534     # . epilogue
10535     5d/pop-to-ebp
10536     c3/return
10537 
10538 test-index-with-no-output:
10539     # . prologue
10540     55/push-ebp
10541     89/<- %ebp 4/r32/esp
10542     # setup
10543     (clear-stream _test-input-stream)
10544     (clear-stream $_test-input-buffered-file->buffer)
10545     (clear-stream _test-output-stream)
10546     (clear-stream $_test-output-buffered-file->buffer)
10547     (clear-stream _test-error-stream)
10548     (clear-stream $_test-error-buffered-file->buffer)
10549     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10550     68/push 0/imm32
10551     68/push 0/imm32
10552     89/<- %edx 4/r32/esp
10553     (tailor-exit-descriptor %edx 0x10)
10554     #
10555     (write _test-input-stream "fn foo {\n")
10556     (write _test-input-stream "  var a: (array int 3)\n")
10557     (write _test-input-stream "  index a, 0\n")
10558     (write _test-input-stream "}\n")
10559     # convert
10560     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10561     # registers except esp clobbered at this point
10562     # restore ed
10563     89/<- %edx 4/r32/esp
10564     (flush _test-output-buffered-file)
10565     (flush _test-error-buffered-file)
10566 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10572     # check output
10573     (check-stream-equal _test-output-stream  ""  "F - test-index-with-no-output: output should be empty")
10574     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: must have an output"  "F - test-index-with-no-output: error message")
10575     # check that stop(1) was called
10576     (check-ints-equal *(edx+4) 2 "F - test-index-with-no-output: exit status")
10577     # don't restore from ebp
10578     81 0/subop/add %esp 8/imm32
10579     # . epilogue
10580     5d/pop-to-ebp
10581     c3/return
10582 
10583 test-index-with-too-many-outputs:
10584     # . prologue
10585     55/push-ebp
10586     89/<- %ebp 4/r32/esp
10587     # setup
10588     (clear-stream _test-input-stream)
10589     (clear-stream $_test-input-buffered-file->buffer)
10590     (clear-stream _test-output-stream)
10591     (clear-stream $_test-output-buffered-file->buffer)
10592     (clear-stream _test-error-stream)
10593     (clear-stream $_test-error-buffered-file->buffer)
10594     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10595     68/push 0/imm32
10596     68/push 0/imm32
10597     89/<- %edx 4/r32/esp
10598     (tailor-exit-descriptor %edx 0x10)
10599     #
10600     (write _test-input-stream "fn foo {\n")
10601     (write _test-input-stream "  var a: (array int 3)\n")
10602     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
10603     (write _test-input-stream "  var c/ecx: (addr int) <- copy 0\n")
10604     (write _test-input-stream "  b, c <- index a, 0\n")
10605     (write _test-input-stream "}\n")
10606     # convert
10607     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10608     # registers except esp clobbered at this point
10609     # restore ed
10610     89/<- %edx 4/r32/esp
10611     (flush _test-output-buffered-file)
10612     (flush _test-error-buffered-file)
10613 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10619     # check output
10620     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-many-outputs: output should be empty")
10621     (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")
10622     # check that stop(1) was called
10623     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-many-outputs: exit status")
10624     # don't restore from ebp
10625     81 0/subop/add %esp 8/imm32
10626     # . epilogue
10627     5d/pop-to-ebp
10628     c3/return
10629 
10630 test-compute-offset-with-non-array-atom-base-type:
10631     # . prologue
10632     55/push-ebp
10633     89/<- %ebp 4/r32/esp
10634     # setup
10635     (clear-stream _test-input-stream)
10636     (clear-stream $_test-input-buffered-file->buffer)
10637     (clear-stream _test-output-stream)
10638     (clear-stream $_test-output-buffered-file->buffer)
10639     (clear-stream _test-error-stream)
10640     (clear-stream $_test-error-buffered-file->buffer)
10641     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10642     68/push 0/imm32
10643     68/push 0/imm32
10644     89/<- %edx 4/r32/esp
10645     (tailor-exit-descriptor %edx 0x10)
10646     #
10647     (write _test-input-stream "fn foo {\n")
10648     (write _test-input-stream "  var a: int\n")
10649     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
10650     (write _test-input-stream "}\n")
10651     # convert
10652     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10653     # registers except esp clobbered at this point
10654     # restore ed
10655     89/<- %edx 4/r32/esp
10656     (flush _test-output-buffered-file)
10657     (flush _test-error-buffered-file)
10658 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10664     # check output
10665     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-atom-base-type: output should be empty")
10666     (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")
10667     # check that stop(1) was called
10668     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-atom-base-type: exit status")
10669     # don't restore from ebp
10670     81 0/subop/add %esp 8/imm32
10671     # . epilogue
10672     5d/pop-to-ebp
10673     c3/return
10674 
10675 test-compute-offset-with-non-array-compound-base-type:
10676     # . prologue
10677     55/push-ebp
10678     89/<- %ebp 4/r32/esp
10679     # setup
10680     (clear-stream _test-input-stream)
10681     (clear-stream $_test-input-buffered-file->buffer)
10682     (clear-stream _test-output-stream)
10683     (clear-stream $_test-output-buffered-file->buffer)
10684     (clear-stream _test-error-stream)
10685     (clear-stream $_test-error-buffered-file->buffer)
10686     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10687     68/push 0/imm32
10688     68/push 0/imm32
10689     89/<- %edx 4/r32/esp
10690     (tailor-exit-descriptor %edx 0x10)
10691     #
10692     (write _test-input-stream "fn foo {\n")
10693     (write _test-input-stream "  var a: (handle int)\n")
10694     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
10695     (write _test-input-stream "}\n")
10696     # convert
10697     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10698     # registers except esp clobbered at this point
10699     # restore ed
10700     89/<- %edx 4/r32/esp
10701     (flush _test-output-buffered-file)
10702     (flush _test-error-buffered-file)
10703 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10709     # check output
10710     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-compound-base-type: output should be empty")
10711     (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")
10712     # check that stop(1) was called
10713     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-compound-base-type: exit status")
10714     # don't restore from ebp
10715     81 0/subop/add %esp 8/imm32
10716     # . epilogue
10717     5d/pop-to-ebp
10718     c3/return
10719 
10720 test-compute-offset-with-non-array-compound-base-type-2:
10721     # . prologue
10722     55/push-ebp
10723     89/<- %ebp 4/r32/esp
10724     # setup
10725     (clear-stream _test-input-stream)
10726     (clear-stream $_test-input-buffered-file->buffer)
10727     (clear-stream _test-output-stream)
10728     (clear-stream $_test-output-buffered-file->buffer)
10729     (clear-stream _test-error-stream)
10730     (clear-stream $_test-error-buffered-file->buffer)
10731     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10732     68/push 0/imm32
10733     68/push 0/imm32
10734     89/<- %edx 4/r32/esp
10735     (tailor-exit-descriptor %edx 0x10)
10736     #
10737     (write _test-input-stream "fn foo {\n")
10738     (write _test-input-stream "  var a: (addr int)\n")
10739     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
10740     (write _test-input-stream "}\n")
10741     # convert
10742     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10743     # registers except esp clobbered at this point
10744     # restore ed
10745     89/<- %edx 4/r32/esp
10746     (flush _test-output-buffered-file)
10747     (flush _test-error-buffered-file)
10748 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10754     # check output
10755     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-compound-base-type-2: output should be empty")
10756     (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")
10757     # check that stop(1) was called
10758     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-compound-base-type-2: exit status")
10759     # don't restore from ebp
10760     81 0/subop/add %esp 8/imm32
10761     # . epilogue
10762     5d/pop-to-ebp
10763     c3/return
10764 
10765 test-compute-offset-with-array-atom-base-type:
10766     # . prologue
10767     55/push-ebp
10768     89/<- %ebp 4/r32/esp
10769     # setup
10770     (clear-stream _test-input-stream)
10771     (clear-stream $_test-input-buffered-file->buffer)
10772     (clear-stream _test-output-stream)
10773     (clear-stream $_test-output-buffered-file->buffer)
10774     (clear-stream _test-error-stream)
10775     (clear-stream $_test-error-buffered-file->buffer)
10776     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10777     68/push 0/imm32
10778     68/push 0/imm32
10779     89/<- %edx 4/r32/esp
10780     (tailor-exit-descriptor %edx 0x10)
10781     #
10782     (write _test-input-stream "fn foo {\n")
10783     (write _test-input-stream "  var a: array\n")
10784     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
10785     (write _test-input-stream "}\n")
10786     # convert
10787     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10788     # registers except esp clobbered at this point
10789     # restore ed
10790     89/<- %edx 4/r32/esp
10791     (flush _test-output-buffered-file)
10792     (flush _test-error-buffered-file)
10793 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10799     # check output
10800     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-array-atom-base-type: output should be empty")
10801     (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")
10802     # check that stop(1) was called
10803     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-array-atom-base-type: exit status")
10804     # don't restore from ebp
10805     81 0/subop/add %esp 8/imm32
10806     # . epilogue
10807     5d/pop-to-ebp
10808     c3/return
10809 
10810 test-compute-offset-with-wrong-index-type:
10811     # . prologue
10812     55/push-ebp
10813     89/<- %ebp 4/r32/esp
10814     # setup
10815     (clear-stream _test-input-stream)
10816     (clear-stream $_test-input-buffered-file->buffer)
10817     (clear-stream _test-output-stream)
10818     (clear-stream $_test-output-buffered-file->buffer)
10819     (clear-stream _test-error-stream)
10820     (clear-stream $_test-error-buffered-file->buffer)
10821     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10822     68/push 0/imm32
10823     68/push 0/imm32
10824     89/<- %edx 4/r32/esp
10825     (tailor-exit-descriptor %edx 0x10)
10826     #
10827     (write _test-input-stream "fn foo {\n")
10828     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
10829     (write _test-input-stream "  var b: boolean\n")
10830     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, b\n")
10831     (write _test-input-stream "}\n")
10832     # convert
10833     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10834     # registers except esp clobbered at this point
10835     # restore ed
10836     89/<- %edx 4/r32/esp
10837     (flush _test-output-buffered-file)
10838     (flush _test-error-buffered-file)
10839 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10845     # check output
10846     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-index-type: output should be empty")
10847     (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")
10848     # check that stop(1) was called
10849     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-index-type: exit status")
10850     # don't restore from ebp
10851     81 0/subop/add %esp 8/imm32
10852     # . epilogue
10853     5d/pop-to-ebp
10854     c3/return
10855 
10856 test-compute-offset-with-output-not-offset:
10857     # . prologue
10858     55/push-ebp
10859     89/<- %ebp 4/r32/esp
10860     # setup
10861     (clear-stream _test-input-stream)
10862     (clear-stream $_test-input-buffered-file->buffer)
10863     (clear-stream _test-output-stream)
10864     (clear-stream $_test-output-buffered-file->buffer)
10865     (clear-stream _test-error-stream)
10866     (clear-stream $_test-error-buffered-file->buffer)
10867     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10868     68/push 0/imm32
10869     68/push 0/imm32
10870     89/<- %edx 4/r32/esp
10871     (tailor-exit-descriptor %edx 0x10)
10872     #
10873     (write _test-input-stream "fn foo {\n")
10874     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
10875     (write _test-input-stream "  var o/edi: int <- compute-offset a, 0\n")
10876     (write _test-input-stream "}\n")
10877     # convert
10878     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10879     # registers except esp clobbered at this point
10880     # restore ed
10881     89/<- %edx 4/r32/esp
10882     (flush _test-output-buffered-file)
10883     (flush _test-error-buffered-file)
10884 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10890     # check output
10891     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-output-not-offset: output should be empty")
10892     (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")
10893     # check that stop(1) was called
10894     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-output-not-offset: exit status")
10895     # don't restore from ebp
10896     81 0/subop/add %esp 8/imm32
10897     # . epilogue
10898     5d/pop-to-ebp
10899     c3/return
10900 
10901 test-compute-offset-with-output-not-address-2:
10902     # . prologue
10903     55/push-ebp
10904     89/<- %ebp 4/r32/esp
10905     # setup
10906     (clear-stream _test-input-stream)
10907     (clear-stream $_test-input-buffered-file->buffer)
10908     (clear-stream _test-output-stream)
10909     (clear-stream $_test-output-buffered-file->buffer)
10910     (clear-stream _test-error-stream)
10911     (clear-stream $_test-error-buffered-file->buffer)
10912     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10913     68/push 0/imm32
10914     68/push 0/imm32
10915     89/<- %edx 4/r32/esp
10916     (tailor-exit-descriptor %edx 0x10)
10917     #
10918     (write _test-input-stream "fn foo {\n")
10919     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
10920     (write _test-input-stream "  var o/edi: (int) <- compute-offset a, 0\n")
10921     (write _test-input-stream "}\n")
10922     # convert
10923     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10924     # registers except esp clobbered at this point
10925     # restore ed
10926     89/<- %edx 4/r32/esp
10927     (flush _test-output-buffered-file)
10928     (flush _test-error-buffered-file)
10929 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10935     # check output
10936     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-output-not-address-2: output should be empty")
10937     (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")
10938     # check that stop(1) was called
10939     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-output-not-address-2: exit status")
10940     # don't restore from ebp
10941     81 0/subop/add %esp 8/imm32
10942     # . epilogue
10943     5d/pop-to-ebp
10944     c3/return
10945 
10946 test-compute-offset-with-wrong-output-type:
10947     # . prologue
10948     55/push-ebp
10949     89/<- %ebp 4/r32/esp
10950     # setup
10951     (clear-stream _test-input-stream)
10952     (clear-stream $_test-input-buffered-file->buffer)
10953     (clear-stream _test-output-stream)
10954     (clear-stream $_test-output-buffered-file->buffer)
10955     (clear-stream _test-error-stream)
10956     (clear-stream $_test-error-buffered-file->buffer)
10957     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10958     68/push 0/imm32
10959     68/push 0/imm32
10960     89/<- %edx 4/r32/esp
10961     (tailor-exit-descriptor %edx 0x10)
10962     #
10963     (write _test-input-stream "fn foo {\n")
10964     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
10965     (write _test-input-stream "  var o/edi: (offset int) <- compute-offset a, 0\n")
10966     (write _test-input-stream "}\n")
10967     # convert
10968     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10969     # registers except esp clobbered at this point
10970     # restore ed
10971     89/<- %edx 4/r32/esp
10972     (flush _test-output-buffered-file)
10973     (flush _test-error-buffered-file)
10974 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10980     # check output
10981     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-output-type: output should be empty")
10982     (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")
10983     # check that stop(1) was called
10984     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-output-type: exit status")
10985     # don't restore from ebp
10986     81 0/subop/add %esp 8/imm32
10987     # . epilogue
10988     5d/pop-to-ebp
10989     c3/return
10990 
10991 test-compute-offset-with-wrong-output-compound-type:
10992     # . prologue
10993     55/push-ebp
10994     89/<- %ebp 4/r32/esp
10995     # setup
10996     (clear-stream _test-input-stream)
10997     (clear-stream $_test-input-buffered-file->buffer)
10998     (clear-stream _test-output-stream)
10999     (clear-stream $_test-output-buffered-file->buffer)
11000     (clear-stream _test-error-stream)
11001     (clear-stream $_test-error-buffered-file->buffer)
11002     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11003     68/push 0/imm32
11004     68/push 0/imm32
11005     89/<- %edx 4/r32/esp
11006     (tailor-exit-descriptor %edx 0x10)
11007     #
11008     (write _test-input-stream "fn foo {\n")
11009     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
11010     (write _test-input-stream "  var o/edi: (offset handle int) <- compute-offset a, 0\n")
11011     (write _test-input-stream "}\n")
11012     # convert
11013     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11014     # registers except esp clobbered at this point
11015     # restore ed
11016     89/<- %edx 4/r32/esp
11017     (flush _test-output-buffered-file)
11018     (flush _test-error-buffered-file)
11019 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11025     # check output
11026     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-output-compound-type: output should be empty")
11027     (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")
11028     # check that stop(1) was called
11029     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-output-compound-type: exit status")
11030     # don't restore from ebp
11031     81 0/subop/add %esp 8/imm32
11032     # . epilogue
11033     5d/pop-to-ebp
11034     c3/return
11035 
11036 test-compute-offset-with-no-inouts:
11037     # . prologue
11038     55/push-ebp
11039     89/<- %ebp 4/r32/esp
11040     # setup
11041     (clear-stream _test-input-stream)
11042     (clear-stream $_test-input-buffered-file->buffer)
11043     (clear-stream _test-output-stream)
11044     (clear-stream $_test-output-buffered-file->buffer)
11045     (clear-stream _test-error-stream)
11046     (clear-stream $_test-error-buffered-file->buffer)
11047     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11048     68/push 0/imm32
11049     68/push 0/imm32
11050     89/<- %edx 4/r32/esp
11051     (tailor-exit-descriptor %edx 0x10)
11052     #
11053     (write _test-input-stream "fn foo {\n")
11054     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset\n")
11055     (write _test-input-stream "}\n")
11056     # convert
11057     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11058     # registers except esp clobbered at this point
11059     # restore ed
11060     89/<- %edx 4/r32/esp
11061     (flush _test-output-buffered-file)
11062     (flush _test-error-buffered-file)
11063 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11069     # check output
11070     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-no-inouts: output should be empty")
11071     (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")
11072     # check that stop(1) was called
11073     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-no-inouts: exit status")
11074     # don't restore from ebp
11075     81 0/subop/add %esp 8/imm32
11076     # . epilogue
11077     5d/pop-to-ebp
11078     c3/return
11079 
11080 test-compute-offset-with-too-few-inouts:
11081     # . prologue
11082     55/push-ebp
11083     89/<- %ebp 4/r32/esp
11084     # setup
11085     (clear-stream _test-input-stream)
11086     (clear-stream $_test-input-buffered-file->buffer)
11087     (clear-stream _test-output-stream)
11088     (clear-stream $_test-output-buffered-file->buffer)
11089     (clear-stream _test-error-stream)
11090     (clear-stream $_test-error-buffered-file->buffer)
11091     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11092     68/push 0/imm32
11093     68/push 0/imm32
11094     89/<- %edx 4/r32/esp
11095     (tailor-exit-descriptor %edx 0x10)
11096     #
11097     (write _test-input-stream "fn foo {\n")
11098     (write _test-input-stream "  var a: (array int 3)\n")
11099     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a\n")
11100     (write _test-input-stream "}\n")
11101     # convert
11102     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11103     # registers except esp clobbered at this point
11104     # restore ed
11105     89/<- %edx 4/r32/esp
11106     (flush _test-output-buffered-file)
11107     (flush _test-error-buffered-file)
11108 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11114     # check output
11115     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-few-inouts: output should be empty")
11116     (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")
11117     # check that stop(1) was called
11118     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-few-inouts: exit status")
11119     # don't restore from ebp
11120     81 0/subop/add %esp 8/imm32
11121     # . epilogue
11122     5d/pop-to-ebp
11123     c3/return
11124 
11125 test-compute-offset-with-too-many-inouts:
11126     # . prologue
11127     55/push-ebp
11128     89/<- %ebp 4/r32/esp
11129     # setup
11130     (clear-stream _test-input-stream)
11131     (clear-stream $_test-input-buffered-file->buffer)
11132     (clear-stream _test-output-stream)
11133     (clear-stream $_test-output-buffered-file->buffer)
11134     (clear-stream _test-error-stream)
11135     (clear-stream $_test-error-buffered-file->buffer)
11136     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11137     68/push 0/imm32
11138     68/push 0/imm32
11139     89/<- %edx 4/r32/esp
11140     (tailor-exit-descriptor %edx 0x10)
11141     #
11142     (write _test-input-stream "fn foo {\n")
11143     (write _test-input-stream "  var a: (array int 3)\n")
11144     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0, 0\n")
11145     (write _test-input-stream "}\n")
11146     # convert
11147     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11148     # registers except esp clobbered at this point
11149     # restore ed
11150     89/<- %edx 4/r32/esp
11151     (flush _test-output-buffered-file)
11152     (flush _test-error-buffered-file)
11153 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11159     # check output
11160     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-many-inouts: output should be empty")
11161     (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")
11162     # check that stop(1) was called
11163     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-many-inouts: exit status")
11164     # don't restore from ebp
11165     81 0/subop/add %esp 8/imm32
11166     # . epilogue
11167     5d/pop-to-ebp
11168     c3/return
11169 
11170 test-compute-offset-with-no-output:
11171     # . prologue
11172     55/push-ebp
11173     89/<- %ebp 4/r32/esp
11174     # setup
11175     (clear-stream _test-input-stream)
11176     (clear-stream $_test-input-buffered-file->buffer)
11177     (clear-stream _test-output-stream)
11178     (clear-stream $_test-output-buffered-file->buffer)
11179     (clear-stream _test-error-stream)
11180     (clear-stream $_test-error-buffered-file->buffer)
11181     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11182     68/push 0/imm32
11183     68/push 0/imm32
11184     89/<- %edx 4/r32/esp
11185     (tailor-exit-descriptor %edx 0x10)
11186     #
11187     (write _test-input-stream "fn foo {\n")
11188     (write _test-input-stream "  var a: (array int 3)\n")
11189     (write _test-input-stream "  compute-offset a, 0\n")
11190     (write _test-input-stream "}\n")
11191     # convert
11192     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11193     # registers except esp clobbered at this point
11194     # restore ed
11195     89/<- %edx 4/r32/esp
11196     (flush _test-output-buffered-file)
11197     (flush _test-error-buffered-file)
11198 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11204     # check output
11205     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-no-output: output should be empty")
11206     (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")
11207     # check that stop(1) was called
11208     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-no-output: exit status")
11209     # don't restore from ebp
11210     81 0/subop/add %esp 8/imm32
11211     # . epilogue
11212     5d/pop-to-ebp
11213     c3/return
11214 
11215 test-compute-offset-with-too-many-outputs:
11216     # . prologue
11217     55/push-ebp
11218     89/<- %ebp 4/r32/esp
11219     # setup
11220     (clear-stream _test-input-stream)
11221     (clear-stream $_test-input-buffered-file->buffer)
11222     (clear-stream _test-output-stream)
11223     (clear-stream $_test-output-buffered-file->buffer)
11224     (clear-stream _test-error-stream)
11225     (clear-stream $_test-error-buffered-file->buffer)
11226     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11227     68/push 0/imm32
11228     68/push 0/imm32
11229     89/<- %edx 4/r32/esp
11230     (tailor-exit-descriptor %edx 0x10)
11231     #
11232     (write _test-input-stream "fn foo {\n")
11233     (write _test-input-stream "  var a: (array int 3)\n")
11234     (write _test-input-stream "  var b/eax: (offset int) <- compute-offset a, 0\n")
11235     (write _test-input-stream "  var c/ecx: (addr int) <- copy 0\n")
11236     (write _test-input-stream "  b, c <- compute-offset a, 0\n")
11237     (write _test-input-stream "}\n")
11238     # convert
11239     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11240     # registers except esp clobbered at this point
11241     # restore ed
11242     89/<- %edx 4/r32/esp
11243     (flush _test-output-buffered-file)
11244     (flush _test-error-buffered-file)
11245 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11251     # check output
11252     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-many-outputs: output should be empty")
11253     (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")
11254     # check that stop(1) was called
11255     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-many-outputs: exit status")
11256     # don't restore from ebp
11257     81 0/subop/add %esp 8/imm32
11258     # . epilogue
11259     5d/pop-to-ebp
11260     c3/return
11261 
11262 test-convert-read-from-stream:
11263     # . prologue
11264     55/push-ebp
11265     89/<- %ebp 4/r32/esp
11266     # setup
11267     (clear-stream _test-input-stream)
11268     (clear-stream $_test-input-buffered-file->buffer)
11269     (clear-stream _test-output-stream)
11270     (clear-stream $_test-output-buffered-file->buffer)
11271     #
11272     (write _test-input-stream "fn foo {\n")
11273     (write _test-input-stream "  var s/esi: (addr stream int) <- copy 0\n")
11274     (write _test-input-stream "  var o/ecx: (addr int) <- copy 0\n")
11275     (write _test-input-stream "  read-from-stream s, o\n")
11276     (write _test-input-stream "}\n")
11277     # convert
11278     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
11279     # registers except esp clobbered at this point
11280     # restore ed
11281     89/<- %edx 4/r32/esp
11282     (flush _test-output-buffered-file)
11283     (flush _test-error-buffered-file)
11284 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
11290     # check output
11291     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-read-from-stream/0")
11292     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-read-from-stream/1")
11293     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-read-from-stream/2")
11294     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-read-from-stream/3")
11295     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-read-from-stream/4")
11296     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-read-from-stream/5")
11297     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-read-from-stream/6")
11298     (check-next-stream-line-equal _test-output-stream "    be/copy-to-esi 0/imm32"      "F - test-convert-read-from-stream/7")
11299     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-read-from-stream/8")
11300     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"      "F - test-convert-read-from-stream/9")
11301     (check-next-stream-line-equal _test-output-stream "    (read-from-stream %esi %ecx 0x00000004)"  "F - test-convert-read-from-stream/10")
11302     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-read-from-stream/11")
11303     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-read-from-stream/12")
11304     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-read-from-stream/13")
11305     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-read-from-stream/14")
11306     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-read-from-stream/15")
11307     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-read-from-stream/16")
11308     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-read-from-stream/17")
11309     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-read-from-stream/18")
11310     # . epilogue
11311     89/<- %esp 5/r32/ebp
11312     5d/pop-to-ebp
11313     c3/return
11314 
11315 test-convert-read-from-stream-with-correct-payload-size:
11316     # . prologue
11317     55/push-ebp
11318     89/<- %ebp 4/r32/esp
11319     # setup
11320     (clear-stream _test-input-stream)
11321     (clear-stream $_test-input-buffered-file->buffer)
11322     (clear-stream _test-output-stream)
11323     (clear-stream $_test-output-buffered-file->buffer)
11324     #
11325     (write _test-input-stream "fn foo {\n")
11326     (write _test-input-stream "  var s/esi: (addr stream handle int) <- copy 0\n")
11327     (write _test-input-stream "  var o/ecx: (addr handle int) <- copy 0\n")
11328     (write _test-input-stream "  read-from-stream s, o\n")
11329     (write _test-input-stream "}\n")
11330     # convert
11331     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
11332     # registers except esp clobbered at this point
11333     # restore ed
11334     89/<- %edx 4/r32/esp
11335     (flush _test-output-buffered-file)
11336     (flush _test-error-buffered-file)
11337 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
11343     # check output
11344     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-read-from-stream-with-correct-payload-size/0")
11345     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-read-from-stream-with-correct-payload-size/1")
11346     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-read-from-stream-with-correct-payload-size/2")
11347     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-read-from-stream-with-correct-payload-size/3")
11348     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-read-from-stream-with-correct-payload-size/4")
11349     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-read-from-stream-with-correct-payload-size/5")
11350     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-read-from-stream-with-correct-payload-size/6")
11351     (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")
11352     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-read-from-stream-with-correct-payload-size/8")
11353     (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")
11354     (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")
11355     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-read-from-stream-with-correct-payload-size/11")
11356     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-read-from-stream-with-correct-payload-size/12")
11357     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-read-from-stream-with-correct-payload-size/13")
11358     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-read-from-stream-with-correct-payload-size/14")
11359     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-read-from-stream-with-correct-payload-size/15")
11360     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-read-from-stream-with-correct-payload-size/16")
11361     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-read-from-stream-with-correct-payload-size/17")
11362     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-read-from-stream-with-correct-payload-size/18")
11363     # . epilogue
11364     89/<- %esp 5/r32/ebp
11365     5d/pop-to-ebp
11366     c3/return
11367 
11368 test-read-from-stream-with-non-stream-atom-base-type:
11369     # . prologue
11370     55/push-ebp
11371     89/<- %ebp 4/r32/esp
11372     # setup
11373     (clear-stream _test-input-stream)
11374     (clear-stream $_test-input-buffered-file->buffer)
11375     (clear-stream _test-output-stream)
11376     (clear-stream $_test-output-buffered-file->buffer)
11377     (clear-stream _test-error-stream)
11378     (clear-stream $_test-error-buffered-file->buffer)
11379     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11380     68/push 0/imm32
11381     68/push 0/imm32
11382     89/<- %edx 4/r32/esp
11383     (tailor-exit-descriptor %edx 0x10)
11384     #
11385     (write _test-input-stream "fn foo {\n")
11386     (write _test-input-stream "  var a: int\n")
11387     (write _test-input-stream "  read-from-stream a, 0\n")
11388     (write _test-input-stream "}\n")
11389     # convert
11390     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11391     # registers except esp clobbered at this point
11392     # restore ed
11393     89/<- %edx 4/r32/esp
11394     (flush _test-output-buffered-file)
11395     (flush _test-error-buffered-file)
11396 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11402     # check output
11403     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-atom-base-type: output should be empty")
11404     (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")
11405     # check that stop(1) was called
11406     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-atom-base-type: exit status")
11407     # don't restore from ebp
11408     81 0/subop/add %esp 8/imm32
11409     # . epilogue
11410     5d/pop-to-ebp
11411     c3/return
11412 
11413 test-read-from-stream-with-non-stream-compound-base-type:
11414     # . prologue
11415     55/push-ebp
11416     89/<- %ebp 4/r32/esp
11417     # setup
11418     (clear-stream _test-input-stream)
11419     (clear-stream $_test-input-buffered-file->buffer)
11420     (clear-stream _test-output-stream)
11421     (clear-stream $_test-output-buffered-file->buffer)
11422     (clear-stream _test-error-stream)
11423     (clear-stream $_test-error-buffered-file->buffer)
11424     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11425     68/push 0/imm32
11426     68/push 0/imm32
11427     89/<- %edx 4/r32/esp
11428     (tailor-exit-descriptor %edx 0x10)
11429     #
11430     (write _test-input-stream "fn foo {\n")
11431     (write _test-input-stream "  var a: (handle int)\n")
11432     (write _test-input-stream "  read-from-stream a, 0\n")
11433     (write _test-input-stream "}\n")
11434     # convert
11435     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11436     # registers except esp clobbered at this point
11437     # restore ed
11438     89/<- %edx 4/r32/esp
11439     (flush _test-output-buffered-file)
11440     (flush _test-error-buffered-file)
11441 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11447     # check output
11448     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-compound-base-type: output should be empty")
11449     (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")
11450     # check that stop(1) was called
11451     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-compound-base-type: exit status")
11452     # don't restore from ebp
11453     81 0/subop/add %esp 8/imm32
11454     # . epilogue
11455     5d/pop-to-ebp
11456     c3/return
11457 
11458 test-read-from-stream-with-non-stream-compound-base-type-2:
11459     # . prologue
11460     55/push-ebp
11461     89/<- %ebp 4/r32/esp
11462     # setup
11463     (clear-stream _test-input-stream)
11464     (clear-stream $_test-input-buffered-file->buffer)
11465     (clear-stream _test-output-stream)
11466     (clear-stream $_test-output-buffered-file->buffer)
11467     (clear-stream _test-error-stream)
11468     (clear-stream $_test-error-buffered-file->buffer)
11469     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11470     68/push 0/imm32
11471     68/push 0/imm32
11472     89/<- %edx 4/r32/esp
11473     (tailor-exit-descriptor %edx 0x10)
11474     #
11475     (write _test-input-stream "fn foo {\n")
11476     (write _test-input-stream "  var a: (addr int)\n")
11477     (write _test-input-stream "  read-from-stream a, 0\n")
11478     (write _test-input-stream "}\n")
11479     # convert
11480     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11481     # registers except esp clobbered at this point
11482     # restore ed
11483     89/<- %edx 4/r32/esp
11484     (flush _test-output-buffered-file)
11485     (flush _test-error-buffered-file)
11486 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11492     # check output
11493     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-compound-base-type-2: output should be empty")
11494     (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")
11495     # check that stop(1) was called
11496     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-compound-base-type-2: exit status")
11497     # don't restore from ebp
11498     81 0/subop/add %esp 8/imm32
11499     # . epilogue
11500     5d/pop-to-ebp
11501     c3/return
11502 
11503 test-read-from-stream-with-stream-atom-base-type:
11504     # . prologue
11505     55/push-ebp
11506     89/<- %ebp 4/r32/esp
11507     # setup
11508     (clear-stream _test-input-stream)
11509     (clear-stream $_test-input-buffered-file->buffer)
11510     (clear-stream _test-output-stream)
11511     (clear-stream $_test-output-buffered-file->buffer)
11512     (clear-stream _test-error-stream)
11513     (clear-stream $_test-error-buffered-file->buffer)
11514     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11515     68/push 0/imm32
11516     68/push 0/imm32
11517     89/<- %edx 4/r32/esp
11518     (tailor-exit-descriptor %edx 0x10)
11519     #
11520     (write _test-input-stream "fn foo {\n")
11521     (write _test-input-stream "  var a: stream\n")
11522     (write _test-input-stream "  read-from-stream a, 0\n")
11523     (write _test-input-stream "}\n")
11524     # convert
11525     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11526     # registers except esp clobbered at this point
11527     # restore ed
11528     89/<- %edx 4/r32/esp
11529     (flush _test-output-buffered-file)
11530     (flush _test-error-buffered-file)
11531 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11537     # check output
11538     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-stream-atom-base-type: output should be empty")
11539     (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")
11540     # check that stop(1) was called
11541     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-stream-atom-base-type: exit status")
11542     # don't restore from ebp
11543     81 0/subop/add %esp 8/imm32
11544     # . epilogue
11545     5d/pop-to-ebp
11546     c3/return
11547 
11548 test-read-from-stream-with-wrong-index-type:
11549     # . prologue
11550     55/push-ebp
11551     89/<- %ebp 4/r32/esp
11552     # setup
11553     (clear-stream _test-input-stream)
11554     (clear-stream $_test-input-buffered-file->buffer)
11555     (clear-stream _test-output-stream)
11556     (clear-stream $_test-output-buffered-file->buffer)
11557     (clear-stream _test-error-stream)
11558     (clear-stream $_test-error-buffered-file->buffer)
11559     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11560     68/push 0/imm32
11561     68/push 0/imm32
11562     89/<- %edx 4/r32/esp
11563     (tailor-exit-descriptor %edx 0x10)
11564     #
11565     (write _test-input-stream "fn foo {\n")
11566     (write _test-input-stream "  var a/eax: (addr stream int) <- copy 0\n")
11567     (write _test-input-stream "  var b: boolean\n")
11568     (write _test-input-stream "  read-from-stream a, b\n")
11569     (write _test-input-stream "}\n")
11570     # convert
11571     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11572     # registers except esp clobbered at this point
11573     # restore ed
11574     89/<- %edx 4/r32/esp
11575     (flush _test-output-buffered-file)
11576     (flush _test-error-buffered-file)
11577 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11583     # check output
11584     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-wrong-index-type: output should be empty")
11585     (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")
11586     # check that stop(1) was called
11587     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-wrong-index-type: exit status")
11588     # don't restore from ebp
11589     81 0/subop/add %esp 8/imm32
11590     # . epilogue
11591     5d/pop-to-ebp
11592     c3/return
11593 
11594 test-read-from-stream-with-no-inouts:
11595     # . prologue
11596     55/push-ebp
11597     89/<- %ebp 4/r32/esp
11598     # setup
11599     (clear-stream _test-input-stream)
11600     (clear-stream $_test-input-buffered-file->buffer)
11601     (clear-stream _test-output-stream)
11602     (clear-stream $_test-output-buffered-file->buffer)
11603     (clear-stream _test-error-stream)
11604     (clear-stream $_test-error-buffered-file->buffer)
11605     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11606     68/push 0/imm32
11607     68/push 0/imm32
11608     89/<- %edx 4/r32/esp
11609     (tailor-exit-descriptor %edx 0x10)
11610     #
11611     (write _test-input-stream "fn foo {\n")
11612     (write _test-input-stream "  read-from-stream\n")
11613     (write _test-input-stream "}\n")
11614     # convert
11615     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11616     # registers except esp clobbered at this point
11617     # restore ed
11618     89/<- %edx 4/r32/esp
11619     (flush _test-output-buffered-file)
11620     (flush _test-error-buffered-file)
11621 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11627     # check output
11628     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-no-inouts: output should be empty")
11629     (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")
11630     # check that stop(1) was called
11631     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-no-inouts: exit status")
11632     # don't restore from ebp
11633     81 0/subop/add %esp 8/imm32
11634     # . epilogue
11635     5d/pop-to-ebp
11636     c3/return
11637 
11638 test-read-from-stream-with-too-few-inouts:
11639     # . prologue
11640     55/push-ebp
11641     89/<- %ebp 4/r32/esp
11642     # setup
11643     (clear-stream _test-input-stream)
11644     (clear-stream $_test-input-buffered-file->buffer)
11645     (clear-stream _test-output-stream)
11646     (clear-stream $_test-output-buffered-file->buffer)
11647     (clear-stream _test-error-stream)
11648     (clear-stream $_test-error-buffered-file->buffer)
11649     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11650     68/push 0/imm32
11651     68/push 0/imm32
11652     89/<- %edx 4/r32/esp
11653     (tailor-exit-descriptor %edx 0x10)
11654     #
11655     (write _test-input-stream "fn foo {\n")
11656     (write _test-input-stream "  var a: (addr stream int)\n")
11657     (write _test-input-stream "  read-from-stream a\n")
11658     (write _test-input-stream "}\n")
11659     # convert
11660     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11661     # registers except esp clobbered at this point
11662     # restore ed
11663     89/<- %edx 4/r32/esp
11664     (flush _test-output-buffered-file)
11665     (flush _test-error-buffered-file)
11666 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11672     # check output
11673     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-too-few-inouts: output should be empty")
11674     (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")
11675     # check that stop(1) was called
11676     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-too-few-inouts: exit status")
11677     # don't restore from ebp
11678     81 0/subop/add %esp 8/imm32
11679     # . epilogue
11680     5d/pop-to-ebp
11681     c3/return
11682 
11683 test-read-from-stream-with-too-many-inouts:
11684     # . prologue
11685     55/push-ebp
11686     89/<- %ebp 4/r32/esp
11687     # setup
11688     (clear-stream _test-input-stream)
11689     (clear-stream $_test-input-buffered-file->buffer)
11690     (clear-stream _test-output-stream)
11691     (clear-stream $_test-output-buffered-file->buffer)
11692     (clear-stream _test-error-stream)
11693     (clear-stream $_test-error-buffered-file->buffer)
11694     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11695     68/push 0/imm32
11696     68/push 0/imm32
11697     89/<- %edx 4/r32/esp
11698     (tailor-exit-descriptor %edx 0x10)
11699     #
11700     (write _test-input-stream "fn foo {\n")
11701     (write _test-input-stream "  var a: (addr stream int)\n")
11702     (write _test-input-stream "  var b: (addr int)\n")
11703     (write _test-input-stream "  read-from-stream a, b, 0\n")
11704     (write _test-input-stream "}\n")
11705     # convert
11706     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11707     # registers except esp clobbered at this point
11708     # restore ed
11709     89/<- %edx 4/r32/esp
11710     (flush _test-output-buffered-file)
11711     (flush _test-error-buffered-file)
11712 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11718     # check output
11719     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-too-many-inouts: output should be empty")
11720     (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")
11721     # check that stop(1) was called
11722     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-too-many-inouts: exit status")
11723     # don't restore from ebp
11724     81 0/subop/add %esp 8/imm32
11725     # . epilogue
11726     5d/pop-to-ebp
11727     c3/return
11728 
11729 test-read-from-stream-with-output:
11730     # . prologue
11731     55/push-ebp
11732     89/<- %ebp 4/r32/esp
11733     # setup
11734     (clear-stream _test-input-stream)
11735     (clear-stream $_test-input-buffered-file->buffer)
11736     (clear-stream _test-output-stream)
11737     (clear-stream $_test-output-buffered-file->buffer)
11738     (clear-stream _test-error-stream)
11739     (clear-stream $_test-error-buffered-file->buffer)
11740     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11741     68/push 0/imm32
11742     68/push 0/imm32
11743     89/<- %edx 4/r32/esp
11744     (tailor-exit-descriptor %edx 0x10)
11745     #
11746     (write _test-input-stream "fn foo {\n")
11747     (write _test-input-stream "  var a: (addr stream int)\n")
11748     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
11749     (write _test-input-stream "  b <- read-from-stream a, b\n")
11750     (write _test-input-stream "}\n")
11751     # convert
11752     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11753     # registers except esp clobbered at this point
11754     # restore ed
11755     89/<- %edx 4/r32/esp
11756     (flush _test-output-buffered-file)
11757     (flush _test-error-buffered-file)
11758 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11764     # check output
11765     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-output: output should be empty")
11766     (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")
11767     # check that stop(1) was called
11768     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-output: exit status")
11769     # don't restore from ebp
11770     81 0/subop/add %esp 8/imm32
11771     # . epilogue
11772     5d/pop-to-ebp
11773     c3/return
11774 
11775 test-convert-write-to-stream:
11776     # . prologue
11777     55/push-ebp
11778     89/<- %ebp 4/r32/esp
11779     # setup
11780     (clear-stream _test-input-stream)
11781     (clear-stream $_test-input-buffered-file->buffer)
11782     (clear-stream _test-output-stream)
11783     (clear-stream $_test-output-buffered-file->buffer)
11784     #
11785     (write _test-input-stream "fn foo {\n")
11786     (write _test-input-stream "  var s/esi: (addr stream int) <- copy 0\n")
11787     (write _test-input-stream "  var o/ecx: (addr int) <- copy 0\n")
11788     (write _test-input-stream "  write-to-stream s, o\n")
11789     (write _test-input-stream "}\n")
11790     # convert
11791     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
11792     # registers except esp clobbered at this point
11793     # restore ed
11794     89/<- %edx 4/r32/esp
11795     (flush _test-output-buffered-file)
11796     (flush _test-error-buffered-file)
11797 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
11803     # check output
11804     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-write-to-stream/0")
11805     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-write-to-stream/1")
11806     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-write-to-stream/2")
11807     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-write-to-stream/3")
11808     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-write-to-stream/4")
11809     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-write-to-stream/5")
11810     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-write-to-stream/6")
11811     (check-next-stream-line-equal _test-output-stream "    be/copy-to-esi 0/imm32"      "F - test-convert-write-to-stream/7")
11812     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-write-to-stream/8")
11813     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"      "F - test-convert-write-to-stream/9")
11814     (check-next-stream-line-equal _test-output-stream "    (write-to-stream %esi %ecx 0x00000004)"  "F - test-convert-write-to-stream/10")
11815     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-write-to-stream/11")
11816     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-write-to-stream/12")
11817     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-write-to-stream/13")
11818     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-write-to-stream/14")
11819     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-write-to-stream/15")
11820     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-write-to-stream/16")
11821     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-write-to-stream/17")
11822     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-write-to-stream/18")
11823     # . epilogue
11824     89/<- %esp 5/r32/ebp
11825     5d/pop-to-ebp
11826     c3/return
11827 
11828 test-convert-write-to-stream-with-correct-payload-size:
11829     # . prologue
11830     55/push-ebp
11831     89/<- %ebp 4/r32/esp
11832     # setup
11833     (clear-stream _test-input-stream)
11834     (clear-stream $_test-input-buffered-file->buffer)
11835     (clear-stream _test-output-stream)
11836     (clear-stream $_test-output-buffered-file->buffer)
11837     #
11838     (write _test-input-stream "fn foo {\n")
11839     (write _test-input-stream "  var s/esi: (addr stream handle int) <- copy 0\n")
11840     (write _test-input-stream "  var o/ecx: (addr handle int) <- copy 0\n")
11841     (write _test-input-stream "  write-to-stream s, o\n")
11842     (write _test-input-stream "}\n")
11843     # convert
11844     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
11845     # registers except esp clobbered at this point
11846     # restore ed
11847     89/<- %edx 4/r32/esp
11848     (flush _test-output-buffered-file)
11849     (flush _test-error-buffered-file)
11850 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
11856     # check output
11857     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-write-to-stream-with-correct-payload-size/0")
11858     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-write-to-stream-with-correct-payload-size/1")
11859     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-write-to-stream-with-correct-payload-size/2")
11860     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-write-to-stream-with-correct-payload-size/3")
11861     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-write-to-stream-with-correct-payload-size/4")
11862     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-write-to-stream-with-correct-payload-size/5")
11863     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-write-to-stream-with-correct-payload-size/6")
11864     (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")
11865     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-write-to-stream-with-correct-payload-size/8")
11866     (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")
11867     (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")
11868     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-write-to-stream-with-correct-payload-size/11")
11869     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-write-to-stream-with-correct-payload-size/12")
11870     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-write-to-stream-with-correct-payload-size/13")
11871     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-write-to-stream-with-correct-payload-size/14")
11872     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-write-to-stream-with-correct-payload-size/15")
11873     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-write-to-stream-with-correct-payload-size/16")
11874     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-write-to-stream-with-correct-payload-size/17")
11875     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-write-to-stream-with-correct-payload-size/18")
11876     # . epilogue
11877     89/<- %esp 5/r32/ebp
11878     5d/pop-to-ebp
11879     c3/return
11880 
11881 test-write-to-stream-with-non-stream-atom-base-type:
11882     # . prologue
11883     55/push-ebp
11884     89/<- %ebp 4/r32/esp
11885     # setup
11886     (clear-stream _test-input-stream)
11887     (clear-stream $_test-input-buffered-file->buffer)
11888     (clear-stream _test-output-stream)
11889     (clear-stream $_test-output-buffered-file->buffer)
11890     (clear-stream _test-error-stream)
11891     (clear-stream $_test-error-buffered-file->buffer)
11892     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11893     68/push 0/imm32
11894     68/push 0/imm32
11895     89/<- %edx 4/r32/esp
11896     (tailor-exit-descriptor %edx 0x10)
11897     #
11898     (write _test-input-stream "fn foo {\n")
11899     (write _test-input-stream "  var a: int\n")
11900     (write _test-input-stream "  write-to-stream a, 0\n")
11901     (write _test-input-stream "}\n")
11902     # convert
11903     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11904     # registers except esp clobbered at this point
11905     # restore ed
11906     89/<- %edx 4/r32/esp
11907     (flush _test-output-buffered-file)
11908     (flush _test-error-buffered-file)
11909 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11915     # check output
11916     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-atom-base-type: output should be empty")
11917     (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")
11918     # check that stop(1) was called
11919     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-atom-base-type: exit status")
11920     # don't restore from ebp
11921     81 0/subop/add %esp 8/imm32
11922     # . epilogue
11923     5d/pop-to-ebp
11924     c3/return
11925 
11926 test-write-to-stream-with-non-stream-compound-base-type:
11927     # . prologue
11928     55/push-ebp
11929     89/<- %ebp 4/r32/esp
11930     # setup
11931     (clear-stream _test-input-stream)
11932     (clear-stream $_test-input-buffered-file->buffer)
11933     (clear-stream _test-output-stream)
11934     (clear-stream $_test-output-buffered-file->buffer)
11935     (clear-stream _test-error-stream)
11936     (clear-stream $_test-error-buffered-file->buffer)
11937     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11938     68/push 0/imm32
11939     68/push 0/imm32
11940     89/<- %edx 4/r32/esp
11941     (tailor-exit-descriptor %edx 0x10)
11942     #
11943     (write _test-input-stream "fn foo {\n")
11944     (write _test-input-stream "  var a: (handle int)\n")
11945     (write _test-input-stream "  write-to-stream a, 0\n")
11946     (write _test-input-stream "}\n")
11947     # convert
11948     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11949     # registers except esp clobbered at this point
11950     # restore ed
11951     89/<- %edx 4/r32/esp
11952     (flush _test-output-buffered-file)
11953     (flush _test-error-buffered-file)
11954 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11960     # check output
11961     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-compound-base-type: output should be empty")
11962     (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")
11963     # check that stop(1) was called
11964     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-compound-base-type: exit status")
11965     # don't restore from ebp
11966     81 0/subop/add %esp 8/imm32
11967     # . epilogue
11968     5d/pop-to-ebp
11969     c3/return
11970 
11971 test-write-to-stream-with-non-stream-compound-base-type-2:
11972     # . prologue
11973     55/push-ebp
11974     89/<- %ebp 4/r32/esp
11975     # setup
11976     (clear-stream _test-input-stream)
11977     (clear-stream $_test-input-buffered-file->buffer)
11978     (clear-stream _test-output-stream)
11979     (clear-stream $_test-output-buffered-file->buffer)
11980     (clear-stream _test-error-stream)
11981     (clear-stream $_test-error-buffered-file->buffer)
11982     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11983     68/push 0/imm32
11984     68/push 0/imm32
11985     89/<- %edx 4/r32/esp
11986     (tailor-exit-descriptor %edx 0x10)
11987     #
11988     (write _test-input-stream "fn foo {\n")
11989     (write _test-input-stream "  var a: (addr int)\n")
11990     (write _test-input-stream "  write-to-stream a, 0\n")
11991     (write _test-input-stream "}\n")
11992     # convert
11993     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11994     # registers except esp clobbered at this point
11995     # restore ed
11996     89/<- %edx 4/r32/esp
11997     (flush _test-output-buffered-file)
11998     (flush _test-error-buffered-file)
11999 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12005     # check output
12006     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-compound-base-type-2: output should be empty")
12007     (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")
12008     # check that stop(1) was called
12009     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-compound-base-type-2: exit status")
12010     # don't restore from ebp
12011     81 0/subop/add %esp 8/imm32
12012     # . epilogue
12013     5d/pop-to-ebp
12014     c3/return
12015 
12016 test-write-to-stream-with-stream-atom-base-type:
12017     # . prologue
12018     55/push-ebp
12019     89/<- %ebp 4/r32/esp
12020     # setup
12021     (clear-stream _test-input-stream)
12022     (clear-stream $_test-input-buffered-file->buffer)
12023     (clear-stream _test-output-stream)
12024     (clear-stream $_test-output-buffered-file->buffer)
12025     (clear-stream _test-error-stream)
12026     (clear-stream $_test-error-buffered-file->buffer)
12027     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12028     68/push 0/imm32
12029     68/push 0/imm32
12030     89/<- %edx 4/r32/esp
12031     (tailor-exit-descriptor %edx 0x10)
12032     #
12033     (write _test-input-stream "fn foo {\n")
12034     (write _test-input-stream "  var a: stream\n")
12035     (write _test-input-stream "  write-to-stream a, 0\n")
12036     (write _test-input-stream "}\n")
12037     # convert
12038     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12039     # registers except esp clobbered at this point
12040     # restore ed
12041     89/<- %edx 4/r32/esp
12042     (flush _test-output-buffered-file)
12043     (flush _test-error-buffered-file)
12044 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12050     # check output
12051     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-stream-atom-base-type: output should be empty")
12052     (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")
12053     # check that stop(1) was called
12054     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-stream-atom-base-type: exit status")
12055     # don't restore from ebp
12056     81 0/subop/add %esp 8/imm32
12057     # . epilogue
12058     5d/pop-to-ebp
12059     c3/return
12060 
12061 test-write-to-stream-with-wrong-index-type:
12062     # . prologue
12063     55/push-ebp
12064     89/<- %ebp 4/r32/esp
12065     # setup
12066     (clear-stream _test-input-stream)
12067     (clear-stream $_test-input-buffered-file->buffer)
12068     (clear-stream _test-output-stream)
12069     (clear-stream $_test-output-buffered-file->buffer)
12070     (clear-stream _test-error-stream)
12071     (clear-stream $_test-error-buffered-file->buffer)
12072     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12073     68/push 0/imm32
12074     68/push 0/imm32
12075     89/<- %edx 4/r32/esp
12076     (tailor-exit-descriptor %edx 0x10)
12077     #
12078     (write _test-input-stream "fn foo {\n")
12079     (write _test-input-stream "  var a/eax: (addr stream int) <- copy 0\n")
12080     (write _test-input-stream "  var b: boolean\n")
12081     (write _test-input-stream "  write-to-stream a, b\n")
12082     (write _test-input-stream "}\n")
12083     # convert
12084     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12085     # registers except esp clobbered at this point
12086     # restore ed
12087     89/<- %edx 4/r32/esp
12088     (flush _test-output-buffered-file)
12089     (flush _test-error-buffered-file)
12090 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12096     # check output
12097     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-wrong-index-type: output should be empty")
12098     (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")
12099     # check that stop(1) was called
12100     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-wrong-index-type: exit status")
12101     # don't restore from ebp
12102     81 0/subop/add %esp 8/imm32
12103     # . epilogue
12104     5d/pop-to-ebp
12105     c3/return
12106 
12107 test-write-to-stream-with-no-inouts:
12108     # . prologue
12109     55/push-ebp
12110     89/<- %ebp 4/r32/esp
12111     # setup
12112     (clear-stream _test-input-stream)
12113     (clear-stream $_test-input-buffered-file->buffer)
12114     (clear-stream _test-output-stream)
12115     (clear-stream $_test-output-buffered-file->buffer)
12116     (clear-stream _test-error-stream)
12117     (clear-stream $_test-error-buffered-file->buffer)
12118     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12119     68/push 0/imm32
12120     68/push 0/imm32
12121     89/<- %edx 4/r32/esp
12122     (tailor-exit-descriptor %edx 0x10)
12123     #
12124     (write _test-input-stream "fn foo {\n")
12125     (write _test-input-stream "  write-to-stream\n")
12126     (write _test-input-stream "}\n")
12127     # convert
12128     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12129     # registers except esp clobbered at this point
12130     # restore ed
12131     89/<- %edx 4/r32/esp
12132     (flush _test-output-buffered-file)
12133     (flush _test-error-buffered-file)
12134 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12140     # check output
12141     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-no-inouts: output should be empty")
12142     (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")
12143     # check that stop(1) was called
12144     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-no-inouts: exit status")
12145     # don't restore from ebp
12146     81 0/subop/add %esp 8/imm32
12147     # . epilogue
12148     5d/pop-to-ebp
12149     c3/return
12150 
12151 test-write-to-stream-with-too-few-inouts:
12152     # . prologue
12153     55/push-ebp
12154     89/<- %ebp 4/r32/esp
12155     # setup
12156     (clear-stream _test-input-stream)
12157     (clear-stream $_test-input-buffered-file->buffer)
12158     (clear-stream _test-output-stream)
12159     (clear-stream $_test-output-buffered-file->buffer)
12160     (clear-stream _test-error-stream)
12161     (clear-stream $_test-error-buffered-file->buffer)
12162     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12163     68/push 0/imm32
12164     68/push 0/imm32
12165     89/<- %edx 4/r32/esp
12166     (tailor-exit-descriptor %edx 0x10)
12167     #
12168     (write _test-input-stream "fn foo {\n")
12169     (write _test-input-stream "  var a: (addr stream int)\n")
12170     (write _test-input-stream "  write-to-stream a\n")
12171     (write _test-input-stream "}\n")
12172     # convert
12173     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12174     # registers except esp clobbered at this point
12175     # restore ed
12176     89/<- %edx 4/r32/esp
12177     (flush _test-output-buffered-file)
12178     (flush _test-error-buffered-file)
12179 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12185     # check output
12186     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-too-few-inouts: output should be empty")
12187     (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")
12188     # check that stop(1) was called
12189     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-too-few-inouts: exit status")
12190     # don't restore from ebp
12191     81 0/subop/add %esp 8/imm32
12192     # . epilogue
12193     5d/pop-to-ebp
12194     c3/return
12195 
12196 test-write-to-stream-with-too-many-inouts:
12197     # . prologue
12198     55/push-ebp
12199     89/<- %ebp 4/r32/esp
12200     # setup
12201     (clear-stream _test-input-stream)
12202     (clear-stream $_test-input-buffered-file->buffer)
12203     (clear-stream _test-output-stream)
12204     (clear-stream $_test-output-buffered-file->buffer)
12205     (clear-stream _test-error-stream)
12206     (clear-stream $_test-error-buffered-file->buffer)
12207     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12208     68/push 0/imm32
12209     68/push 0/imm32
12210     89/<- %edx 4/r32/esp
12211     (tailor-exit-descriptor %edx 0x10)
12212     #
12213     (write _test-input-stream "fn foo {\n")
12214     (write _test-input-stream "  var a: (addr stream int)\n")
12215     (write _test-input-stream "  var b: (addr int)\n")
12216     (write _test-input-stream "  write-to-stream a, b, 0\n")
12217     (write _test-input-stream "}\n")
12218     # convert
12219     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12220     # registers except esp clobbered at this point
12221     # restore ed
12222     89/<- %edx 4/r32/esp
12223     (flush _test-output-buffered-file)
12224     (flush _test-error-buffered-file)
12225 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12231     # check output
12232     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-too-many-inouts: output should be empty")
12233     (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")
12234     # check that stop(1) was called
12235     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-too-many-inouts: exit status")
12236     # don't restore from ebp
12237     81 0/subop/add %esp 8/imm32
12238     # . epilogue
12239     5d/pop-to-ebp
12240     c3/return
12241 
12242 test-write-to-stream-with-output:
12243     # . prologue
12244     55/push-ebp
12245     89/<- %ebp 4/r32/esp
12246     # setup
12247     (clear-stream _test-input-stream)
12248     (clear-stream $_test-input-buffered-file->buffer)
12249     (clear-stream _test-output-stream)
12250     (clear-stream $_test-output-buffered-file->buffer)
12251     (clear-stream _test-error-stream)
12252     (clear-stream $_test-error-buffered-file->buffer)
12253     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12254     68/push 0/imm32
12255     68/push 0/imm32
12256     89/<- %edx 4/r32/esp
12257     (tailor-exit-descriptor %edx 0x10)
12258     #
12259     (write _test-input-stream "fn foo {\n")
12260     (write _test-input-stream "  var a: (addr stream int)\n")
12261     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
12262     (write _test-input-stream "  b <- write-to-stream a, b\n")
12263     (write _test-input-stream "}\n")
12264     # convert
12265     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12266     # registers except esp clobbered at this point
12267     # restore ed
12268     89/<- %edx 4/r32/esp
12269     (flush _test-output-buffered-file)
12270     (flush _test-error-buffered-file)
12271 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12277     # check output
12278     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-output: output should be empty")
12279     (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")
12280     # check that stop(1) was called
12281     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-output: exit status")
12282     # don't restore from ebp
12283     81 0/subop/add %esp 8/imm32
12284     # . epilogue
12285     5d/pop-to-ebp
12286     c3/return
12287 
12288 test-length-with-non-array-atom-base-type:
12289     # . prologue
12290     55/push-ebp
12291     89/<- %ebp 4/r32/esp
12292     # setup
12293     (clear-stream _test-input-stream)
12294     (clear-stream $_test-input-buffered-file->buffer)
12295     (clear-stream _test-output-stream)
12296     (clear-stream $_test-output-buffered-file->buffer)
12297     (clear-stream _test-error-stream)
12298     (clear-stream $_test-error-buffered-file->buffer)
12299     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12300     68/push 0/imm32
12301     68/push 0/imm32
12302     89/<- %edx 4/r32/esp
12303     (tailor-exit-descriptor %edx 0x10)
12304     #
12305     (write _test-input-stream "fn foo {\n")
12306     (write _test-input-stream "  var a: int\n")
12307     (write _test-input-stream "  var c/ecx: int <- length a\n")
12308     (write _test-input-stream "}\n")
12309     # convert
12310     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12311     # registers except esp clobbered at this point
12312     # restore ed
12313     89/<- %edx 4/r32/esp
12314     (flush _test-output-buffered-file)
12315     (flush _test-error-buffered-file)
12316 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12322     # check output
12323     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-atom-base-type: output should be empty")
12324     (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")
12325     # check that stop(1) was called
12326     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-atom-base-type: exit status")
12327     # don't restore from ebp
12328     81 0/subop/add %esp 8/imm32
12329     # . epilogue
12330     5d/pop-to-ebp
12331     c3/return
12332 
12333 test-length-with-non-array-compound-base-type:
12334     # . prologue
12335     55/push-ebp
12336     89/<- %ebp 4/r32/esp
12337     # setup
12338     (clear-stream _test-input-stream)
12339     (clear-stream $_test-input-buffered-file->buffer)
12340     (clear-stream _test-output-stream)
12341     (clear-stream $_test-output-buffered-file->buffer)
12342     (clear-stream _test-error-stream)
12343     (clear-stream $_test-error-buffered-file->buffer)
12344     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12345     68/push 0/imm32
12346     68/push 0/imm32
12347     89/<- %edx 4/r32/esp
12348     (tailor-exit-descriptor %edx 0x10)
12349     #
12350     (write _test-input-stream "fn foo {\n")
12351     (write _test-input-stream "  var a: (handle int)\n")
12352     (write _test-input-stream "  var c/ecx: (addr int) <- length a, 0\n")
12353     (write _test-input-stream "}\n")
12354     # convert
12355     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12356     # registers except esp clobbered at this point
12357     # restore ed
12358     89/<- %edx 4/r32/esp
12359     (flush _test-output-buffered-file)
12360     (flush _test-error-buffered-file)
12361 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12367     # check output
12368     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-compound-base-type: output should be empty")
12369     (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")
12370     # check that stop(1) was called
12371     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-compound-base-type: exit status")
12372     # don't restore from ebp
12373     81 0/subop/add %esp 8/imm32
12374     # . epilogue
12375     5d/pop-to-ebp
12376     c3/return
12377 
12378 test-length-with-non-array-compound-base-type-2:
12379     # . prologue
12380     55/push-ebp
12381     89/<- %ebp 4/r32/esp
12382     # setup
12383     (clear-stream _test-input-stream)
12384     (clear-stream $_test-input-buffered-file->buffer)
12385     (clear-stream _test-output-stream)
12386     (clear-stream $_test-output-buffered-file->buffer)
12387     (clear-stream _test-error-stream)
12388     (clear-stream $_test-error-buffered-file->buffer)
12389     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12390     68/push 0/imm32
12391     68/push 0/imm32
12392     89/<- %edx 4/r32/esp
12393     (tailor-exit-descriptor %edx 0x10)
12394     #
12395     (write _test-input-stream "fn foo {\n")
12396     (write _test-input-stream "  var a: (addr int)\n")
12397     (write _test-input-stream "  var c/ecx: (addr int) <- length a, 0\n")
12398     (write _test-input-stream "}\n")
12399     # convert
12400     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12401     # registers except esp clobbered at this point
12402     # restore ed
12403     89/<- %edx 4/r32/esp
12404     (flush _test-output-buffered-file)
12405     (flush _test-error-buffered-file)
12406 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12412     # check output
12413     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-compound-base-type-2: output should be empty")
12414     (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")
12415     # check that stop(1) was called
12416     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-compound-base-type-2: exit status")
12417     # don't restore from ebp
12418     81 0/subop/add %esp 8/imm32
12419     # . epilogue
12420     5d/pop-to-ebp
12421     c3/return
12422 
12423 test-length-with-array-atom-base-type:
12424     # . prologue
12425     55/push-ebp
12426     89/<- %ebp 4/r32/esp
12427     # setup
12428     (clear-stream _test-input-stream)
12429     (clear-stream $_test-input-buffered-file->buffer)
12430     (clear-stream _test-output-stream)
12431     (clear-stream $_test-output-buffered-file->buffer)
12432     (clear-stream _test-error-stream)
12433     (clear-stream $_test-error-buffered-file->buffer)
12434     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12435     68/push 0/imm32
12436     68/push 0/imm32
12437     89/<- %edx 4/r32/esp
12438     (tailor-exit-descriptor %edx 0x10)
12439     #
12440     (write _test-input-stream "fn foo {\n")
12441     (write _test-input-stream "  var a: array\n")
12442     (write _test-input-stream "  var c/ecx: (addr int) <- length a\n")
12443     (write _test-input-stream "}\n")
12444     # convert
12445     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12446     # registers except esp clobbered at this point
12447     # restore ed
12448     89/<- %edx 4/r32/esp
12449     (flush _test-output-buffered-file)
12450     (flush _test-error-buffered-file)
12451 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12457     # check output
12458     (check-stream-equal _test-output-stream  ""  "F - test-length-with-array-atom-base-type: output should be empty")
12459     (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")
12460     # check that stop(1) was called
12461     (check-ints-equal *(edx+4) 2 "F - test-length-with-array-atom-base-type: exit status")
12462     # don't restore from ebp
12463     81 0/subop/add %esp 8/imm32
12464     # . epilogue
12465     5d/pop-to-ebp
12466     c3/return
12467 
12468 test-length-with-addr-base-on-stack:
12469     # . prologue
12470     55/push-ebp
12471     89/<- %ebp 4/r32/esp
12472     # setup
12473     (clear-stream _test-input-stream)
12474     (clear-stream $_test-input-buffered-file->buffer)
12475     (clear-stream _test-output-stream)
12476     (clear-stream $_test-output-buffered-file->buffer)
12477     (clear-stream _test-error-stream)
12478     (clear-stream $_test-error-buffered-file->buffer)
12479     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12480     68/push 0/imm32
12481     68/push 0/imm32
12482     89/<- %edx 4/r32/esp
12483     (tailor-exit-descriptor %edx 0x10)
12484     #
12485     (write _test-input-stream "fn foo {\n")
12486     (write _test-input-stream "  var a: (addr array int)\n")
12487     (write _test-input-stream "  var c/ecx: (addr int) <- length a\n")
12488     (write _test-input-stream "}\n")
12489     # convert
12490     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12491     # registers except esp clobbered at this point
12492     # restore ed
12493     89/<- %edx 4/r32/esp
12494     (flush _test-output-buffered-file)
12495     (flush _test-error-buffered-file)
12496 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12502     # check output
12503     (check-stream-equal _test-output-stream  ""  "F - test-length-with-addr-base-on-stack: output should be empty")
12504     (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")
12505     # check that stop(1) was called
12506     (check-ints-equal *(edx+4) 2 "F - test-length-with-addr-base-on-stack: exit status")
12507     # don't restore from ebp
12508     81 0/subop/add %esp 8/imm32
12509     # . epilogue
12510     5d/pop-to-ebp
12511     c3/return
12512 
12513 test-length-with-wrong-output-type:
12514     # . prologue
12515     55/push-ebp
12516     89/<- %ebp 4/r32/esp
12517     # setup
12518     (clear-stream _test-input-stream)
12519     (clear-stream $_test-input-buffered-file->buffer)
12520     (clear-stream _test-output-stream)
12521     (clear-stream $_test-output-buffered-file->buffer)
12522     (clear-stream _test-error-stream)
12523     (clear-stream $_test-error-buffered-file->buffer)
12524     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12525     68/push 0/imm32
12526     68/push 0/imm32
12527     89/<- %edx 4/r32/esp
12528     (tailor-exit-descriptor %edx 0x10)
12529     #
12530     (write _test-input-stream "fn foo {\n")
12531     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
12532     (write _test-input-stream "  var o/edi: (addr int) <- length a\n")
12533     (write _test-input-stream "}\n")
12534     # convert
12535     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12536     # registers except esp clobbered at this point
12537     # restore ed
12538     89/<- %edx 4/r32/esp
12539     (flush _test-output-buffered-file)
12540     (flush _test-error-buffered-file)
12541 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12547     # check output
12548     (check-stream-equal _test-output-stream  ""  "F - test-length-with-wrong-output-type: output should be empty")
12549     (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")
12550     # check that stop(1) was called
12551     (check-ints-equal *(edx+4) 2 "F - test-length-with-wrong-output-type: exit status")
12552     # don't restore from ebp
12553     81 0/subop/add %esp 8/imm32
12554     # . epilogue
12555     5d/pop-to-ebp
12556     c3/return
12557 
12558 test-length-with-wrong-output-compound-type:
12559     # . prologue
12560     55/push-ebp
12561     89/<- %ebp 4/r32/esp
12562     # setup
12563     (clear-stream _test-input-stream)
12564     (clear-stream $_test-input-buffered-file->buffer)
12565     (clear-stream _test-output-stream)
12566     (clear-stream $_test-output-buffered-file->buffer)
12567     (clear-stream _test-error-stream)
12568     (clear-stream $_test-error-buffered-file->buffer)
12569     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12570     68/push 0/imm32
12571     68/push 0/imm32
12572     89/<- %edx 4/r32/esp
12573     (tailor-exit-descriptor %edx 0x10)
12574     #
12575     (write _test-input-stream "fn foo {\n")
12576     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
12577     (write _test-input-stream "  var o/edi: (addr handle int) <- length a\n")
12578     (write _test-input-stream "}\n")
12579     # convert
12580     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12581     # registers except esp clobbered at this point
12582     # restore ed
12583     89/<- %edx 4/r32/esp
12584     (flush _test-output-buffered-file)
12585     (flush _test-error-buffered-file)
12586 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12592     # check output
12593     (check-stream-equal _test-output-stream  ""  "F - test-length-with-wrong-output-compound-type: output should be empty")
12594     (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")
12595     # check that stop(1) was called
12596     (check-ints-equal *(edx+4) 2 "F - test-length-with-wrong-output-compound-type: exit status")
12597     # don't restore from ebp
12598     81 0/subop/add %esp 8/imm32
12599     # . epilogue
12600     5d/pop-to-ebp
12601     c3/return
12602 
12603 test-length-with-no-inouts:
12604     # . prologue
12605     55/push-ebp
12606     89/<- %ebp 4/r32/esp
12607     # setup
12608     (clear-stream _test-input-stream)
12609     (clear-stream $_test-input-buffered-file->buffer)
12610     (clear-stream _test-output-stream)
12611     (clear-stream $_test-output-buffered-file->buffer)
12612     (clear-stream _test-error-stream)
12613     (clear-stream $_test-error-buffered-file->buffer)
12614     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12615     68/push 0/imm32
12616     68/push 0/imm32
12617     89/<- %edx 4/r32/esp
12618     (tailor-exit-descriptor %edx 0x10)
12619     #
12620     (write _test-input-stream "fn foo {\n")
12621     (write _test-input-stream "  var c/ecx: int <- length\n")
12622     (write _test-input-stream "}\n")
12623     # convert
12624     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12625     # registers except esp clobbered at this point
12626     # restore ed
12627     89/<- %edx 4/r32/esp
12628     (flush _test-output-buffered-file)
12629     (flush _test-error-buffered-file)
12630 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12636     # check output
12637     (check-stream-equal _test-output-stream  ""  "F - test-length-with-no-inouts: output should be empty")
12638     (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")
12639     # check that stop(1) was called
12640     (check-ints-equal *(edx+4) 2 "F - test-length-with-no-inouts: exit status")
12641     # don't restore from ebp
12642     81 0/subop/add %esp 8/imm32
12643     # . epilogue
12644     5d/pop-to-ebp
12645     c3/return
12646 
12647 test-length-with-too-many-inouts:
12648     # . prologue
12649     55/push-ebp
12650     89/<- %ebp 4/r32/esp
12651     # setup
12652     (clear-stream _test-input-stream)
12653     (clear-stream $_test-input-buffered-file->buffer)
12654     (clear-stream _test-output-stream)
12655     (clear-stream $_test-output-buffered-file->buffer)
12656     (clear-stream _test-error-stream)
12657     (clear-stream $_test-error-buffered-file->buffer)
12658     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12659     68/push 0/imm32
12660     68/push 0/imm32
12661     89/<- %edx 4/r32/esp
12662     (tailor-exit-descriptor %edx 0x10)
12663     #
12664     (write _test-input-stream "fn foo {\n")
12665     (write _test-input-stream "  var a: (array int 3)\n")
12666     (write _test-input-stream "  var c/ecx: int <- length a, 0, 0\n")
12667     (write _test-input-stream "}\n")
12668     # convert
12669     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12670     # registers except esp clobbered at this point
12671     # restore ed
12672     89/<- %edx 4/r32/esp
12673     (flush _test-output-buffered-file)
12674     (flush _test-error-buffered-file)
12675 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12681     # check output
12682     (check-stream-equal _test-output-stream  ""  "F - test-length-with-too-many-inouts: output should be empty")
12683     (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")
12684     # check that stop(1) was called
12685     (check-ints-equal *(edx+4) 2 "F - test-length-with-too-many-inouts: exit status")
12686     # don't restore from ebp
12687     81 0/subop/add %esp 8/imm32
12688     # . epilogue
12689     5d/pop-to-ebp
12690     c3/return
12691 
12692 test-length-with-no-output:
12693     # . prologue
12694     55/push-ebp
12695     89/<- %ebp 4/r32/esp
12696     # setup
12697     (clear-stream _test-input-stream)
12698     (clear-stream $_test-input-buffered-file->buffer)
12699     (clear-stream _test-output-stream)
12700     (clear-stream $_test-output-buffered-file->buffer)
12701     (clear-stream _test-error-stream)
12702     (clear-stream $_test-error-buffered-file->buffer)
12703     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12704     68/push 0/imm32
12705     68/push 0/imm32
12706     89/<- %edx 4/r32/esp
12707     (tailor-exit-descriptor %edx 0x10)
12708     #
12709     (write _test-input-stream "fn foo {\n")
12710     (write _test-input-stream "  var a: (array int 3)\n")
12711     (write _test-input-stream "  length a\n")
12712     (write _test-input-stream "}\n")
12713     # convert
12714     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12715     # registers except esp clobbered at this point
12716     # restore ed
12717     89/<- %edx 4/r32/esp
12718     (flush _test-output-buffered-file)
12719     (flush _test-error-buffered-file)
12720 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12726     # check output
12727     (check-stream-equal _test-output-stream  ""  "F - test-length-with-no-output: output should be empty")
12728     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: must have an output"  "F - test-length-with-no-output: error message")
12729     # check that stop(1) was called
12730     (check-ints-equal *(edx+4) 2 "F - test-length-with-no-output: exit status")
12731     # don't restore from ebp
12732     81 0/subop/add %esp 8/imm32
12733     # . epilogue
12734     5d/pop-to-ebp
12735     c3/return
12736 
12737 test-length-with-too-many-outputs:
12738     # . prologue
12739     55/push-ebp
12740     89/<- %ebp 4/r32/esp
12741     # setup
12742     (clear-stream _test-input-stream)
12743     (clear-stream $_test-input-buffered-file->buffer)
12744     (clear-stream _test-output-stream)
12745     (clear-stream $_test-output-buffered-file->buffer)
12746     (clear-stream _test-error-stream)
12747     (clear-stream $_test-error-buffered-file->buffer)
12748     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12749     68/push 0/imm32
12750     68/push 0/imm32
12751     89/<- %edx 4/r32/esp
12752     (tailor-exit-descriptor %edx 0x10)
12753     #
12754     (write _test-input-stream "fn foo {\n")
12755     (write _test-input-stream "  var a: (array int 3)\n")
12756     (write _test-input-stream "  var b/eax: int <- copy 0\n")
12757     (write _test-input-stream "  var c/ecx: int <- copy 0\n")
12758     (write _test-input-stream "  b, c <- length a\n")
12759     (write _test-input-stream "}\n")
12760     # convert
12761     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12762     # registers except esp clobbered at this point
12763     # restore ed
12764     89/<- %edx 4/r32/esp
12765     (flush _test-output-buffered-file)
12766     (flush _test-error-buffered-file)
12767 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12773     # check output
12774     (check-stream-equal _test-output-stream  ""  "F - test-length-with-too-many-outputs: output should be empty")
12775     (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")
12776     # check that stop(1) was called
12777     (check-ints-equal *(edx+4) 2 "F - test-length-with-too-many-outputs: exit status")
12778     # don't restore from ebp
12779     81 0/subop/add %esp 8/imm32
12780     # . epilogue
12781     5d/pop-to-ebp
12782     c3/return
12783 
12784 test-convert-function-with-return-register-and-local:
12785     # . prologue
12786     55/push-ebp
12787     89/<- %ebp 4/r32/esp
12788     # setup
12789     (clear-stream _test-input-stream)
12790     (clear-stream $_test-input-buffered-file->buffer)
12791     (clear-stream _test-output-stream)
12792     (clear-stream $_test-output-buffered-file->buffer)
12793     #
12794     (write _test-input-stream "fn foo -> _/eax: int {\n")
12795     (write _test-input-stream "  var y/eax: int <- copy 3\n")
12796     (write _test-input-stream "  var z/ecx: int <- copy 4\n")
12797     (write _test-input-stream "  return y\n")
12798     (write _test-input-stream "}\n")
12799     # convert
12800     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
12801     (flush _test-output-buffered-file)
12802 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
12808     # check output
12809     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register-and-local/0")
12810     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register-and-local/1")
12811     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register-and-local/2")
12812     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register-and-local/3")
12813     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register-and-local/4")
12814     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register-and-local/5")
12815     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register-and-local/6")
12816     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-convert-function-with-return-register-and-local/7")
12817     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-return-register-and-local/8")
12818     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-convert-function-with-return-register-and-local/9")
12819     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-return-register-and-local/10")
12820     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-function-with-return-register-and-local/11")
12821     (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")
12822     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-register-and-local/13")
12823     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register-and-local/14")
12824     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register-and-local/15")
12825     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register-and-local/16")
12826     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register-and-local/17")
12827     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register-and-local/18")
12828     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register-and-local/19")
12829     # . epilogue
12830     89/<- %esp 5/r32/ebp
12831     5d/pop-to-ebp
12832     c3/return
12833 
12834 test-convert-function-with-return-register-and-local-2:
12835     # . prologue
12836     55/push-ebp
12837     89/<- %ebp 4/r32/esp
12838     # setup
12839     (clear-stream _test-input-stream)
12840     (clear-stream $_test-input-buffered-file->buffer)
12841     (clear-stream _test-output-stream)
12842     (clear-stream $_test-output-buffered-file->buffer)
12843     #
12844     (write _test-input-stream "fn foo -> _/eax: int {\n")
12845     (write _test-input-stream "  var y/eax: int <- copy 3\n")
12846     (write _test-input-stream "  var z/ecx: int <- copy 4\n")
12847     (write _test-input-stream "  return z\n")
12848     (write _test-input-stream "}\n")
12849     # convert
12850     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
12851     (flush _test-output-buffered-file)
12852 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
12858     # check output
12859     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register-and-local-2/0")
12860     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register-and-local-2/1")
12861     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register-and-local-2/2")
12862     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register-and-local-2/3")
12863     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register-and-local-2/4")
12864     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register-and-local-2/5")
12865     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register-and-local-2/6")
12866     (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")
12867     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-return-register-and-local-2/8")
12868     (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")
12869     (check-next-stream-line-equal _test-output-stream "    8b/-> %ecx 0x00000000/r32" "F - test-convert-function-with-return-register-and-local-2/10")
12870     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-function-with-return-register-and-local-2/11")
12871     (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")
12872     (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")
12873     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register-and-local-2/14")
12874     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register-and-local-2/15")
12875     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register-and-local-2/16")
12876     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register-and-local-2/17")
12877     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register-and-local-2/18")
12878     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register-and-local-2/19")
12879     # . epilogue
12880     89/<- %esp 5/r32/ebp
12881     5d/pop-to-ebp
12882     c3/return
12883 
12884 test-convert-function-with-return-float-register-and-local:
12885     # . prologue
12886     55/push-ebp
12887     89/<- %ebp 4/r32/esp
12888     # setup
12889     (clear-stream _test-input-stream)
12890     (clear-stream $_test-input-buffered-file->buffer)
12891     (clear-stream _test-output-stream)
12892     (clear-stream $_test-output-buffered-file->buffer)
12893     #
12894     (write _test-input-stream "fn foo -> _/xmm1: float {\n")
12895     (write _test-input-stream "  var y/eax: int <- copy 3\n")
12896     (write _test-input-stream "  var g/xmm0: float <- convert y\n")
12897     (write _test-input-stream "  var h/xmm1: float <- convert y\n")
12898     (write _test-input-stream "  return g\n")
12899     (write _test-input-stream "}\n")
12900     # convert
12901     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
12902     (flush _test-output-buffered-file)
12903 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
12909     # check output
12910     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-float-register-and-local/0")
12911     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-float-register-and-local/1")
12912     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-float-register-and-local/2")
12913     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-float-register-and-local/3")
12914     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-float-register-and-local/4")
12915     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-float-register-and-local/5")
12916     (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
12917     (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")
12918     (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
12919     (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")
12920     (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")
12921     (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
12922     (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")
12923     (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")
12924     (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
12925     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-floating-point-dereferenced/15")  # reclaim h
12926     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 0/x32"  "F - test-convert-floating-point-dereferenced/16")  # reclaim g
12927     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-floating-point-dereferenced/17")
12928     (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
12929     (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")
12930     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-float-register-and-local/20")
12931     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-float-register-and-local/21")
12932     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-float-register-and-local/22")
12933     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-float-register-and-local/23")
12934     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-float-register-and-local/24")
12935     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-float-register-and-local/25")
12936     # . epilogue
12937     89/<- %esp 5/r32/ebp
12938     5d/pop-to-ebp
12939     c3/return
12940 
12941 test-convert-function-with-return-and-local-vars:
12942     # . prologue
12943     55/push-ebp
12944     89/<- %ebp 4/r32/esp
12945     # setup
12946     (clear-stream _test-input-stream)
12947     (clear-stream $_test-input-buffered-file->buffer)
12948     (clear-stream _test-output-stream)
12949     (clear-stream $_test-output-buffered-file->buffer)
12950     #
12951     (write _test-input-stream "fn foo -> _/eax: int {\n")
12952     (write _test-input-stream "  {\n")
12953     (write _test-input-stream "    var x: int\n")
12954     (write _test-input-stream "    {\n")
12955     (write _test-input-stream "      var y: int\n")
12956     (write _test-input-stream "      return y\n")
12957     (write _test-input-stream "      increment x\n")
12958     (write _test-input-stream "    }\n")
12959     (write _test-input-stream "  }\n")
12960     (write _test-input-stream "  return 0\n")
12961     (write _test-input-stream "}\n")
12962     # convert
12963     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
12964     (flush _test-output-buffered-file)
12965 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
12971     # check output
12972     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-and-local-vars/0")
12973     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-and-local-vars/1")
12974     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-and-local-vars/2")
12975     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-and-local-vars/3")
12976     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-and-local-vars/4")
12977     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-and-local-vars/5")
12978     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-return-and-local-vars/6")
12979     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-return-and-local-vars/7")
12980     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-return-and-local-vars/8")  # var x
12981     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-return-and-local-vars/9")
12982     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-return-and-local-vars/10")
12983     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-return-and-local-vars/11")  # var y
12984     (check-next-stream-line-equal _test-output-stream "        8b/-> *(ebp+0xfffffff8) 0x00000000/r32" "F - test-convert-function-with-return-and-local-vars/12")
12985     (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")
12986     (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")
12987     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-and-local-vars/15")
12988     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-return-and-local-vars/16")
12989     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-return-and-local-vars/17")
12990     (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")
12991     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-return-and-local-vars/19")
12992     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-return-and-local-vars/20")
12993     (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")
12994     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-and-local-vars/21")
12995     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-and-local-vars/21")
12996     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-and-local-vars/22")
12997     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-and-local-vars/23")
12998     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-and-local-vars/24")
12999     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-and-local-vars/25")
13000     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-and-local-vars/26")
13001     # . epilogue
13002     89/<- %esp 5/r32/ebp
13003     5d/pop-to-ebp
13004     c3/return
13005 
13006 test-copy-object-with-no-inout:
13007     # . prologue
13008     55/push-ebp
13009     89/<- %ebp 4/r32/esp
13010     # setup
13011     (clear-stream _test-input-stream)
13012     (clear-stream $_test-input-buffered-file->buffer)
13013     (clear-stream _test-output-stream)
13014     (clear-stream $_test-output-buffered-file->buffer)
13015     (clear-stream _test-error-stream)
13016     (clear-stream $_test-error-buffered-file->buffer)
13017     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13018     68/push 0/imm32
13019     68/push 0/imm32
13020     89/<- %edx 4/r32/esp
13021     (tailor-exit-descriptor %edx 0x10)
13022     #
13023     (write _test-input-stream "fn foo {\n")
13024     (write _test-input-stream "  copy-object\n")
13025     (write _test-input-stream "}\n")
13026     # convert
13027     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13028     # registers except esp clobbered at this point
13029     # restore ed
13030     89/<- %edx 4/r32/esp
13031     (flush _test-output-buffered-file)
13032     (flush _test-error-buffered-file)
13033 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13039     # check output
13040     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-no-inout: output should be empty")
13041     (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")
13042     # check that stop(1) was called
13043     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-no-inout: exit status")
13044     # don't restore from ebp
13045     81 0/subop/add %esp 8/imm32
13046     # . epilogue
13047     5d/pop-to-ebp
13048     c3/return
13049 
13050 test-copy-object-with-no-input:
13051     # . prologue
13052     55/push-ebp
13053     89/<- %ebp 4/r32/esp
13054     # setup
13055     (clear-stream _test-input-stream)
13056     (clear-stream $_test-input-buffered-file->buffer)
13057     (clear-stream _test-output-stream)
13058     (clear-stream $_test-output-buffered-file->buffer)
13059     (clear-stream _test-error-stream)
13060     (clear-stream $_test-error-buffered-file->buffer)
13061     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13062     68/push 0/imm32
13063     68/push 0/imm32
13064     89/<- %edx 4/r32/esp
13065     (tailor-exit-descriptor %edx 0x10)
13066     #
13067     (write _test-input-stream "fn foo {\n")
13068     (write _test-input-stream "  var x: (addr int)\n")
13069     (write _test-input-stream "  copy-object x\n")
13070     (write _test-input-stream "}\n")
13071     # convert
13072     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13073     # registers except esp clobbered at this point
13074     # restore ed
13075     89/<- %edx 4/r32/esp
13076     (flush _test-output-buffered-file)
13077     (flush _test-error-buffered-file)
13078 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13084     # check output
13085     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-no-input: output should be empty")
13086     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-object' must have two inouts"  "F - test-copy-object-with-no-input: error message")
13087     # check that stop(1) was called
13088     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-no-input: exit status")
13089     # don't restore from ebp
13090     81 0/subop/add %esp 8/imm32
13091     # . epilogue
13092     5d/pop-to-ebp
13093     c3/return
13094 
13095 test-copy-object-with-too-many-inouts:
13096     # . prologue
13097     55/push-ebp
13098     89/<- %ebp 4/r32/esp
13099     # setup
13100     (clear-stream _test-input-stream)
13101     (clear-stream $_test-input-buffered-file->buffer)
13102     (clear-stream _test-output-stream)
13103     (clear-stream $_test-output-buffered-file->buffer)
13104     (clear-stream _test-error-stream)
13105     (clear-stream $_test-error-buffered-file->buffer)
13106     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13107     68/push 0/imm32
13108     68/push 0/imm32
13109     89/<- %edx 4/r32/esp
13110     (tailor-exit-descriptor %edx 0x10)
13111     #
13112     (write _test-input-stream "fn foo {\n")
13113     (write _test-input-stream "  var x: (addr boolean)\n")
13114     (write _test-input-stream "  copy-object x, x, x\n")
13115     (write _test-input-stream "}\n")
13116     # convert
13117     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13118     # registers except esp clobbered at this point
13119     # restore ed
13120     89/<- %edx 4/r32/esp
13121     (flush _test-output-buffered-file)
13122     (flush _test-error-buffered-file)
13123 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13129     # check output
13130     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-too-many-inouts: output should be empty")
13131     (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")
13132     # check that stop(1) was called
13133     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-too-many-inouts: exit status")
13134     # don't restore from ebp
13135     81 0/subop/add %esp 8/imm32
13136     # . epilogue
13137     5d/pop-to-ebp
13138     c3/return
13139 
13140 test-copy-object-with-output:
13141     # . prologue
13142     55/push-ebp
13143     89/<- %ebp 4/r32/esp
13144     # setup
13145     (clear-stream _test-input-stream)
13146     (clear-stream $_test-input-buffered-file->buffer)
13147     (clear-stream _test-output-stream)
13148     (clear-stream $_test-output-buffered-file->buffer)
13149     (clear-stream _test-error-stream)
13150     (clear-stream $_test-error-buffered-file->buffer)
13151     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13152     68/push 0/imm32
13153     68/push 0/imm32
13154     89/<- %edx 4/r32/esp
13155     (tailor-exit-descriptor %edx 0x10)
13156     #
13157     (write _test-input-stream "fn foo {\n")
13158     (write _test-input-stream "  var x/eax: (addr boolean) <- copy 0\n")
13159     (write _test-input-stream "  var y/ecx: (addr boolean) <- copy 0\n")
13160     (write _test-input-stream "  x <- copy-object x, y\n")
13161     (write _test-input-stream "}\n")
13162     # convert
13163     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13164     # registers except esp clobbered at this point
13165     # restore ed
13166     89/<- %edx 4/r32/esp
13167     (flush _test-output-buffered-file)
13168     (flush _test-error-buffered-file)
13169 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13175     # check output
13176     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-output: output should be empty")
13177     (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")
13178     # check that stop(1) was called
13179     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-output: exit status")
13180     # don't restore from ebp
13181     81 0/subop/add %esp 8/imm32
13182     # . epilogue
13183     5d/pop-to-ebp
13184     c3/return
13185 
13186 test-copy-object-deref-address:
13187     # . prologue
13188     55/push-ebp
13189     89/<- %ebp 4/r32/esp
13190     # setup
13191     (clear-stream _test-input-stream)
13192     (clear-stream $_test-input-buffered-file->buffer)
13193     (clear-stream _test-output-stream)
13194     (clear-stream $_test-output-buffered-file->buffer)
13195     #
13196     (write _test-input-stream "fn foo {\n")
13197     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
13198     (write _test-input-stream "  var y/ecx: (addr addr int) <- copy 0\n")
13199     (write _test-input-stream "  copy-object *y, x\n")
13200     (write _test-input-stream "}\n")
13201     # convert
13202     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
13203     (flush _test-output-buffered-file)
13204 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13210     # not bothering checking output
13211     (check-next-stream-line-equal _test-error-stream  ""  "F - test-copy-object-deref-address: error message")
13212     # . epilogue
13213     5d/pop-to-ebp
13214     c3/return
13215 
13216 test-copy-object-non-addr:
13217     # . prologue
13218     55/push-ebp
13219     89/<- %ebp 4/r32/esp
13220     # setup
13221     (clear-stream _test-input-stream)
13222     (clear-stream $_test-input-buffered-file->buffer)
13223     (clear-stream _test-output-stream)
13224     (clear-stream $_test-output-buffered-file->buffer)
13225     (clear-stream _test-error-stream)
13226     (clear-stream $_test-error-buffered-file->buffer)
13227     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13228     68/push 0/imm32
13229     68/push 0/imm32
13230     89/<- %edx 4/r32/esp
13231     (tailor-exit-descriptor %edx 0x10)
13232     #
13233     (write _test-input-stream "fn foo {\n")
13234     (write _test-input-stream "  var x: int\n")
13235     (write _test-input-stream "  var y: int\n")
13236     (write _test-input-stream "  copy-object y, x\n")
13237     (write _test-input-stream "}\n")
13238     # convert
13239     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13240     # registers except esp clobbered at this point
13241     # restore ed
13242     89/<- %edx 4/r32/esp
13243     (flush _test-output-buffered-file)
13244     (flush _test-error-buffered-file)
13245 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13251     # check output
13252     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-non-addr: output should be empty")
13253     (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")
13254     # check that stop(1) was called
13255     (check-ints-equal *(edx+4) 2 "F - test-copy-object-non-addr: exit status")
13256     # don't restore from ebp
13257     81 0/subop/add %esp 8/imm32
13258     # . epilogue
13259     5d/pop-to-ebp
13260     c3/return
13261 
13262 test-copy-object-non-equal:
13263     # . prologue
13264     55/push-ebp
13265     89/<- %ebp 4/r32/esp
13266     # setup
13267     (clear-stream _test-input-stream)
13268     (clear-stream $_test-input-buffered-file->buffer)
13269     (clear-stream _test-output-stream)
13270     (clear-stream $_test-output-buffered-file->buffer)
13271     (clear-stream _test-error-stream)
13272     (clear-stream $_test-error-buffered-file->buffer)
13273     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13274     68/push 0/imm32
13275     68/push 0/imm32
13276     89/<- %edx 4/r32/esp
13277     (tailor-exit-descriptor %edx 0x10)
13278     #
13279     (write _test-input-stream "fn foo {\n")
13280     (write _test-input-stream "  var x: (addr int)\n")
13281     (write _test-input-stream "  var y: (addr boolean)\n")
13282     (write _test-input-stream "  copy-object y, x\n")
13283     (write _test-input-stream "}\n")
13284     # convert
13285     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13286     # registers except esp clobbered at this point
13287     # restore ed
13288     89/<- %edx 4/r32/esp
13289     (flush _test-output-buffered-file)
13290     (flush _test-error-buffered-file)
13291 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13297     # check output
13298     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-non-equal: output should be empty")
13299     (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")
13300     # check that stop(1) was called
13301     (check-ints-equal *(edx+4) 2 "F - test-copy-object-non-equal: exit status")
13302     # don't restore from ebp
13303     81 0/subop/add %esp 8/imm32
13304     # . epilogue
13305     5d/pop-to-ebp
13306     c3/return
13307 
13308 test-allocate-with-no-inout:
13309     # . prologue
13310     55/push-ebp
13311     89/<- %ebp 4/r32/esp
13312     # setup
13313     (clear-stream _test-input-stream)
13314     (clear-stream $_test-input-buffered-file->buffer)
13315     (clear-stream _test-output-stream)
13316     (clear-stream $_test-output-buffered-file->buffer)
13317     (clear-stream _test-error-stream)
13318     (clear-stream $_test-error-buffered-file->buffer)
13319     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13320     68/push 0/imm32
13321     68/push 0/imm32
13322     89/<- %edx 4/r32/esp
13323     (tailor-exit-descriptor %edx 0x10)
13324     #
13325     (write _test-input-stream "fn foo {\n")
13326     (write _test-input-stream "  allocate\n")
13327     (write _test-input-stream "}\n")
13328     # convert
13329     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13330     # registers except esp clobbered at this point
13331     # restore ed
13332     89/<- %edx 4/r32/esp
13333     (flush _test-output-buffered-file)
13334     (flush _test-error-buffered-file)
13335 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13341     # check output
13342     (check-stream-equal _test-output-stream  ""  "F - test-allocate-with-no-inout: output should be empty")
13343     (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")
13344     # check that stop(1) was called
13345     (check-ints-equal *(edx+4) 2 "F - test-allocate-with-no-inout: exit status")
13346     # don't restore from ebp
13347     81 0/subop/add %esp 8/imm32
13348     # . epilogue
13349     5d/pop-to-ebp
13350     c3/return
13351 
13352 test-allocate-with-too-many-inouts:
13353     # . prologue
13354     55/push-ebp
13355     89/<- %ebp 4/r32/esp
13356     # setup
13357     (clear-stream _test-input-stream)
13358     (clear-stream $_test-input-buffered-file->buffer)
13359     (clear-stream _test-output-stream)
13360     (clear-stream $_test-output-buffered-file->buffer)
13361     (clear-stream _test-error-stream)
13362     (clear-stream $_test-error-buffered-file->buffer)
13363     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13364     68/push 0/imm32
13365     68/push 0/imm32
13366     89/<- %edx 4/r32/esp
13367     (tailor-exit-descriptor %edx 0x10)
13368     #
13369     (write _test-input-stream "fn foo {\n")
13370     (write _test-input-stream "  var x: (addr handle int)\n")
13371     (write _test-input-stream "  allocate x, 0\n")
13372     (write _test-input-stream "}\n")
13373     # convert
13374     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13375     # registers except esp clobbered at this point
13376     # restore ed
13377     89/<- %edx 4/r32/esp
13378     (flush _test-output-buffered-file)
13379     (flush _test-error-buffered-file)
13380 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13386     # check output
13387     (check-stream-equal _test-output-stream  ""  "F - test-allocate-with-too-many-inouts: output should be empty")
13388     (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")
13389     # check that stop(1) was called
13390     (check-ints-equal *(edx+4) 2 "F - test-allocate-with-too-many-inouts: exit status")
13391     # don't restore from ebp
13392     81 0/subop/add %esp 8/imm32
13393     # . epilogue
13394     5d/pop-to-ebp
13395     c3/return
13396 
13397 test-allocate-with-output:
13398     # . prologue
13399     55/push-ebp
13400     89/<- %ebp 4/r32/esp
13401     # setup
13402     (clear-stream _test-input-stream)
13403     (clear-stream $_test-input-buffered-file->buffer)
13404     (clear-stream _test-output-stream)
13405     (clear-stream $_test-output-buffered-file->buffer)
13406     (clear-stream _test-error-stream)
13407     (clear-stream $_test-error-buffered-file->buffer)
13408     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13409     68/push 0/imm32
13410     68/push 0/imm32
13411     89/<- %edx 4/r32/esp
13412     (tailor-exit-descriptor %edx 0x10)
13413     #
13414     (write _test-input-stream "fn foo {\n")
13415     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
13416     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
13417     (write _test-input-stream "  x <- allocate y\n")
13418     (write _test-input-stream "}\n")
13419     # convert
13420     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13421     # registers except esp clobbered at this point
13422     # restore ed
13423     89/<- %edx 4/r32/esp
13424     (flush _test-output-buffered-file)
13425     (flush _test-error-buffered-file)
13426 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13432     # check output
13433     (check-stream-equal _test-output-stream  ""  "F - test-allocate-with-output: output should be empty")
13434     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'allocate' must not have any outputs"  "F - test-allocate-with-output: error message")
13435     # check that stop(1) was called
13436     (check-ints-equal *(edx+4) 2 "F - test-allocate-with-output: exit status")
13437     # don't restore from ebp
13438     81 0/subop/add %esp 8/imm32
13439     # . epilogue
13440     5d/pop-to-ebp
13441     c3/return
13442 
13443 test-allocate-non-addr:
13444     # . prologue
13445     55/push-ebp
13446     89/<- %ebp 4/r32/esp
13447     # setup
13448     (clear-stream _test-input-stream)
13449     (clear-stream $_test-input-buffered-file->buffer)
13450     (clear-stream _test-output-stream)
13451     (clear-stream $_test-output-buffered-file->buffer)
13452     (clear-stream _test-error-stream)
13453     (clear-stream $_test-error-buffered-file->buffer)
13454     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13455     68/push 0/imm32
13456     68/push 0/imm32
13457     89/<- %edx 4/r32/esp
13458     (tailor-exit-descriptor %edx 0x10)
13459     #
13460     (write _test-input-stream "fn foo {\n")
13461     (write _test-input-stream "  var y: (handle int)\n")
13462     (write _test-input-stream "  allocate y\n")
13463     (write _test-input-stream "}\n")
13464     # convert
13465     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13466     # registers except esp clobbered at this point
13467     # restore ed
13468     89/<- %edx 4/r32/esp
13469     (flush _test-output-buffered-file)
13470     (flush _test-error-buffered-file)
13471 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13477     # check output
13478     (check-stream-equal _test-output-stream  ""  "F - test-allocate-non-addr: output must be empty")
13479     (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")
13480     # check that stop(1) was called
13481     (check-ints-equal *(edx+4) 2 "F - test-allocate-non-addr: exit status")
13482     # don't restore from ebp
13483     81 0/subop/add %esp 8/imm32
13484     # . epilogue
13485     5d/pop-to-ebp
13486     c3/return
13487 
13488 test-allocate-non-addr-handle:
13489     # . prologue
13490     55/push-ebp
13491     89/<- %ebp 4/r32/esp
13492     # setup
13493     (clear-stream _test-input-stream)
13494     (clear-stream $_test-input-buffered-file->buffer)
13495     (clear-stream _test-output-stream)
13496     (clear-stream $_test-output-buffered-file->buffer)
13497     (clear-stream _test-error-stream)
13498     (clear-stream $_test-error-buffered-file->buffer)
13499     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13500     68/push 0/imm32
13501     68/push 0/imm32
13502     89/<- %edx 4/r32/esp
13503     (tailor-exit-descriptor %edx 0x10)
13504     #
13505     (write _test-input-stream "fn foo {\n")
13506     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
13507     (write _test-input-stream "  allocate y\n")
13508     (write _test-input-stream "}\n")
13509     # convert
13510     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13511     # registers except esp clobbered at this point
13512     # restore ed
13513     89/<- %edx 4/r32/esp
13514     (flush _test-output-buffered-file)
13515     (flush _test-error-buffered-file)
13516 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13522     # check output
13523     (check-stream-equal _test-output-stream  ""  "F - test-allocate-non-addr-handle: output should be empty")
13524     (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")
13525     # check that stop(1) was called
13526     (check-ints-equal *(edx+4) 2 "F - test-allocate-non-addr-handle: exit status")
13527     # don't restore from ebp
13528     81 0/subop/add %esp 8/imm32
13529     # . epilogue
13530     5d/pop-to-ebp
13531     c3/return
13532 
13533 test-allocate-deref-address:
13534     # . prologue
13535     55/push-ebp
13536     89/<- %ebp 4/r32/esp
13537     # setup
13538     (clear-stream _test-input-stream)
13539     (clear-stream $_test-input-buffered-file->buffer)
13540     (clear-stream _test-output-stream)
13541     (clear-stream $_test-output-buffered-file->buffer)
13542     #
13543     (write _test-input-stream "fn foo {\n")
13544     (write _test-input-stream "  var y/ecx: (addr addr handle int) <- copy 0\n")
13545     (write _test-input-stream "  allocate *y\n")
13546     (write _test-input-stream "}\n")
13547     # convert
13548     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
13549     (flush _test-output-buffered-file)
13550 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13556     # not bothering checking output
13557     (check-next-stream-line-equal _test-error-stream  ""  "F - test-allocate-deref-address: error message")
13558     # . epilogue
13559     5d/pop-to-ebp
13560     c3/return
13561 
13562 test-populate-with-no-inout:
13563     # . prologue
13564     55/push-ebp
13565     89/<- %ebp 4/r32/esp
13566     # setup
13567     (clear-stream _test-input-stream)
13568     (clear-stream $_test-input-buffered-file->buffer)
13569     (clear-stream _test-output-stream)
13570     (clear-stream $_test-output-buffered-file->buffer)
13571     (clear-stream _test-error-stream)
13572     (clear-stream $_test-error-buffered-file->buffer)
13573     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13574     68/push 0/imm32
13575     68/push 0/imm32
13576     89/<- %edx 4/r32/esp
13577     (tailor-exit-descriptor %edx 0x10)
13578     #
13579     (write _test-input-stream "fn foo {\n")
13580     (write _test-input-stream "  populate\n")
13581     (write _test-input-stream "}\n")
13582     # convert
13583     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13584     # registers except esp clobbered at this point
13585     # restore ed
13586     89/<- %edx 4/r32/esp
13587     (flush _test-output-buffered-file)
13588     (flush _test-error-buffered-file)
13589 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13595     # check output
13596     (check-stream-equal _test-output-stream  ""  "F - test-populate-with-no-inout: output should be empty")
13597     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate' must have two inouts"  "F - test-populate-with-no-inout: error message")
13598     # check that stop(1) was called
13599     (check-ints-equal *(edx+4) 2 "F - test-populate-with-no-inout: exit status")
13600     # don't restore from ebp
13601     81 0/subop/add %esp 8/imm32
13602     # . epilogue
13603     5d/pop-to-ebp
13604     c3/return
13605 
13606 test-populate-with-too-many-inouts:
13607     # . prologue
13608     55/push-ebp
13609     89/<- %ebp 4/r32/esp
13610     # setup
13611     (clear-stream _test-input-stream)
13612     (clear-stream $_test-input-buffered-file->buffer)
13613     (clear-stream _test-output-stream)
13614     (clear-stream $_test-output-buffered-file->buffer)
13615     (clear-stream _test-error-stream)
13616     (clear-stream $_test-error-buffered-file->buffer)
13617     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13618     68/push 0/imm32
13619     68/push 0/imm32
13620     89/<- %edx 4/r32/esp
13621     (tailor-exit-descriptor %edx 0x10)
13622     #
13623     (write _test-input-stream "fn foo {\n")
13624     (write _test-input-stream "  var x: (addr handle int)\n")
13625     (write _test-input-stream "  populate x, 3, 0\n")
13626     (write _test-input-stream "}\n")
13627     # convert
13628     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13629     # registers except esp clobbered at this point
13630     # restore ed
13631     89/<- %edx 4/r32/esp
13632     (flush _test-output-buffered-file)
13633     (flush _test-error-buffered-file)
13634 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13640     # check output
13641     (check-stream-equal _test-output-stream  ""  "F - test-populate-with-too-many-inouts: output should be empty")
13642     (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")
13643     # check that stop(1) was called
13644     (check-ints-equal *(edx+4) 2 "F - test-populate-with-too-many-inouts: exit status")
13645     # don't restore from ebp
13646     81 0/subop/add %esp 8/imm32
13647     # . epilogue
13648     5d/pop-to-ebp
13649     c3/return
13650 
13651 test-populate-with-output:
13652     # . prologue
13653     55/push-ebp
13654     89/<- %ebp 4/r32/esp
13655     # setup
13656     (clear-stream _test-input-stream)
13657     (clear-stream $_test-input-buffered-file->buffer)
13658     (clear-stream _test-output-stream)
13659     (clear-stream $_test-output-buffered-file->buffer)
13660     (clear-stream _test-error-stream)
13661     (clear-stream $_test-error-buffered-file->buffer)
13662     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13663     68/push 0/imm32
13664     68/push 0/imm32
13665     89/<- %edx 4/r32/esp
13666     (tailor-exit-descriptor %edx 0x10)
13667     #
13668     (write _test-input-stream "fn foo {\n")
13669     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
13670     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
13671     (write _test-input-stream "  x <- populate y\n")
13672     (write _test-input-stream "}\n")
13673     # convert
13674     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13675     # registers except esp clobbered at this point
13676     # restore ed
13677     89/<- %edx 4/r32/esp
13678     (flush _test-output-buffered-file)
13679     (flush _test-error-buffered-file)
13680 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13686     # check output
13687     (check-stream-equal _test-output-stream  ""  "F - test-populate-with-output: output should be empty")
13688     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate' must not have any outputs"  "F - test-populate-with-output: error message")
13689     # check that stop(1) was called
13690     (check-ints-equal *(edx+4) 2 "F - test-populate-with-output: exit status")
13691     # don't restore from ebp
13692     81 0/subop/add %esp 8/imm32
13693     # . epilogue
13694     5d/pop-to-ebp
13695     c3/return
13696 
13697 test-populate-non-addr:
13698     # . prologue
13699     55/push-ebp
13700     89/<- %ebp 4/r32/esp
13701     # setup
13702     (clear-stream _test-input-stream)
13703     (clear-stream $_test-input-buffered-file->buffer)
13704     (clear-stream _test-output-stream)
13705     (clear-stream $_test-output-buffered-file->buffer)
13706     (clear-stream _test-error-stream)
13707     (clear-stream $_test-error-buffered-file->buffer)
13708     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13709     68/push 0/imm32
13710     68/push 0/imm32
13711     89/<- %edx 4/r32/esp
13712     (tailor-exit-descriptor %edx 0x10)
13713     #
13714     (write _test-input-stream "fn foo {\n")
13715     (write _test-input-stream "  var y: (handle int)\n")
13716     (write _test-input-stream "  populate y, 3\n")
13717     (write _test-input-stream "}\n")
13718     # convert
13719     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13720     # registers except esp clobbered at this point
13721     # restore ed
13722     89/<- %edx 4/r32/esp
13723     (flush _test-output-buffered-file)
13724     (flush _test-error-buffered-file)
13725 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13731     # check output
13732     (check-stream-equal _test-output-stream  ""  "F - test-populate-non-addr: output must be empty")
13733     (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")
13734     # check that stop(1) was called
13735     (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr: exit status")
13736     # don't restore from ebp
13737     81 0/subop/add %esp 8/imm32
13738     # . epilogue
13739     5d/pop-to-ebp
13740     c3/return
13741 
13742 test-populate-non-addr-handle:
13743     # . prologue
13744     55/push-ebp
13745     89/<- %ebp 4/r32/esp
13746     # setup
13747     (clear-stream _test-input-stream)
13748     (clear-stream $_test-input-buffered-file->buffer)
13749     (clear-stream _test-output-stream)
13750     (clear-stream $_test-output-buffered-file->buffer)
13751     (clear-stream _test-error-stream)
13752     (clear-stream $_test-error-buffered-file->buffer)
13753     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13754     68/push 0/imm32
13755     68/push 0/imm32
13756     89/<- %edx 4/r32/esp
13757     (tailor-exit-descriptor %edx 0x10)
13758     #
13759     (write _test-input-stream "fn foo {\n")
13760     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
13761     (write _test-input-stream "  populate y, 3\n")
13762     (write _test-input-stream "}\n")
13763     # convert
13764     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13765     # registers except esp clobbered at this point
13766     # restore ed
13767     89/<- %edx 4/r32/esp
13768     (flush _test-output-buffered-file)
13769     (flush _test-error-buffered-file)
13770 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13776     # check output
13777     (check-stream-equal _test-output-stream  ""  "F - test-populate-non-addr-handle: output should be empty")
13778     (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")
13779     # check that stop(1) was called
13780     (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr-handle: exit status")
13781     # don't restore from ebp
13782     81 0/subop/add %esp 8/imm32
13783     # . epilogue
13784     5d/pop-to-ebp
13785     c3/return
13786 
13787 test-populate-non-addr-handle-array:
13788     # . prologue
13789     55/push-ebp
13790     89/<- %ebp 4/r32/esp
13791     # setup
13792     (clear-stream _test-input-stream)
13793     (clear-stream $_test-input-buffered-file->buffer)
13794     (clear-stream _test-output-stream)
13795     (clear-stream $_test-output-buffered-file->buffer)
13796     (clear-stream _test-error-stream)
13797     (clear-stream $_test-error-buffered-file->buffer)
13798     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13799     68/push 0/imm32
13800     68/push 0/imm32
13801     89/<- %edx 4/r32/esp
13802     (tailor-exit-descriptor %edx 0x10)
13803     #
13804     (write _test-input-stream "fn foo {\n")
13805     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
13806     (write _test-input-stream "  populate y, 3\n")
13807     (write _test-input-stream "}\n")
13808     # convert
13809     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13810     # registers except esp clobbered at this point
13811     # restore ed
13812     89/<- %edx 4/r32/esp
13813     (flush _test-output-buffered-file)
13814     (flush _test-error-buffered-file)
13815 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13821     # check output
13822     (check-stream-equal _test-output-stream  ""  "F - test-populate-non-addr-handle-array: output should be empty")
13823     (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")
13824     # check that stop(1) was called
13825     (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr-handle-array: exit status")
13826     # don't restore from ebp
13827     81 0/subop/add %esp 8/imm32
13828     # . epilogue
13829     5d/pop-to-ebp
13830     c3/return
13831 
13832 test-populate-deref-address:
13833     # . prologue
13834     55/push-ebp
13835     89/<- %ebp 4/r32/esp
13836     # setup
13837     (clear-stream _test-input-stream)
13838     (clear-stream $_test-input-buffered-file->buffer)
13839     (clear-stream _test-output-stream)
13840     (clear-stream $_test-output-buffered-file->buffer)
13841     #
13842     (write _test-input-stream "fn foo {\n")
13843     (write _test-input-stream "  var y/ecx: (addr addr handle array int) <- copy 0\n")
13844     (write _test-input-stream "  populate *y, 3\n")
13845     (write _test-input-stream "}\n")
13846     # convert
13847     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
13848     (flush _test-output-buffered-file)
13849 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13855     # not bothering checking output
13856     (check-next-stream-line-equal _test-error-stream  ""  "F - test-populate-deref-address: error message")
13857     # . epilogue
13858     5d/pop-to-ebp
13859     c3/return
13860 
13861 test-populate-stream-with-no-inout:
13862     # . prologue
13863     55/push-ebp
13864     89/<- %ebp 4/r32/esp
13865     # setup
13866     (clear-stream _test-input-stream)
13867     (clear-stream $_test-input-buffered-file->buffer)
13868     (clear-stream _test-output-stream)
13869     (clear-stream $_test-output-buffered-file->buffer)
13870     (clear-stream _test-error-stream)
13871     (clear-stream $_test-error-buffered-file->buffer)
13872     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13873     68/push 0/imm32
13874     68/push 0/imm32
13875     89/<- %edx 4/r32/esp
13876     (tailor-exit-descriptor %edx 0x10)
13877     #
13878     (write _test-input-stream "fn foo {\n")
13879     (write _test-input-stream "  populate-stream\n")
13880     (write _test-input-stream "}\n")
13881     # convert
13882     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13883     # registers except esp clobbered at this point
13884     # restore ed
13885     89/<- %edx 4/r32/esp
13886     (flush _test-output-buffered-file)
13887     (flush _test-error-buffered-file)
13888 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13894     # check output
13895     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-with-no-inout: output should be empty")
13896     (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")
13897     # check that stop(1) was called
13898     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-no-inout: exit status")
13899     # don't restore from ebp
13900     81 0/subop/add %esp 8/imm32
13901     # . epilogue
13902     5d/pop-to-ebp
13903     c3/return
13904 
13905 test-populate-stream-with-too-many-inouts:
13906     # . prologue
13907     55/push-ebp
13908     89/<- %ebp 4/r32/esp
13909     # setup
13910     (clear-stream _test-input-stream)
13911     (clear-stream $_test-input-buffered-file->buffer)
13912     (clear-stream _test-output-stream)
13913     (clear-stream $_test-output-buffered-file->buffer)
13914     (clear-stream _test-error-stream)
13915     (clear-stream $_test-error-buffered-file->buffer)
13916     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13917     68/push 0/imm32
13918     68/push 0/imm32
13919     89/<- %edx 4/r32/esp
13920     (tailor-exit-descriptor %edx 0x10)
13921     #
13922     (write _test-input-stream "fn foo {\n")
13923     (write _test-input-stream "  var x: (addr handle int)\n")
13924     (write _test-input-stream "  populate-stream x, 3, 0\n")
13925     (write _test-input-stream "}\n")
13926     # convert
13927     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13928     # registers except esp clobbered at this point
13929     # restore ed
13930     89/<- %edx 4/r32/esp
13931     (flush _test-output-buffered-file)
13932     (flush _test-error-buffered-file)
13933 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13939     # check output
13940     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-with-too-many-inouts: output should be empty")
13941     (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")
13942     # check that stop(1) was called
13943     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-too-many-inouts: exit status")
13944     # don't restore from ebp
13945     81 0/subop/add %esp 8/imm32
13946     # . epilogue
13947     5d/pop-to-ebp
13948     c3/return
13949 
13950 test-populate-stream-with-output:
13951     # . prologue
13952     55/push-ebp
13953     89/<- %ebp 4/r32/esp
13954     # setup
13955     (clear-stream _test-input-stream)
13956     (clear-stream $_test-input-buffered-file->buffer)
13957     (clear-stream _test-output-stream)
13958     (clear-stream $_test-output-buffered-file->buffer)
13959     (clear-stream _test-error-stream)
13960     (clear-stream $_test-error-buffered-file->buffer)
13961     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13962     68/push 0/imm32
13963     68/push 0/imm32
13964     89/<- %edx 4/r32/esp
13965     (tailor-exit-descriptor %edx 0x10)
13966     #
13967     (write _test-input-stream "fn foo {\n")
13968     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
13969     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
13970     (write _test-input-stream "  x <- populate-stream y\n")
13971     (write _test-input-stream "}\n")
13972     # convert
13973     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13974     # registers except esp clobbered at this point
13975     # restore ed
13976     89/<- %edx 4/r32/esp
13977     (flush _test-output-buffered-file)
13978     (flush _test-error-buffered-file)
13979 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13985     # check output
13986     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-with-output: output should be empty")
13987     (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")
13988     # check that stop(1) was called
13989     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-output: exit status")
13990     # don't restore from ebp
13991     81 0/subop/add %esp 8/imm32
13992     # . epilogue
13993     5d/pop-to-ebp
13994     c3/return
13995 
13996 test-populate-stream-non-addr:
13997     # . prologue
13998     55/push-ebp
13999     89/<- %ebp 4/r32/esp
14000     # setup
14001     (clear-stream _test-input-stream)
14002     (clear-stream $_test-input-buffered-file->buffer)
14003     (clear-stream _test-output-stream)
14004     (clear-stream $_test-output-buffered-file->buffer)
14005     (clear-stream _test-error-stream)
14006     (clear-stream $_test-error-buffered-file->buffer)
14007     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14008     68/push 0/imm32
14009     68/push 0/imm32
14010     89/<- %edx 4/r32/esp
14011     (tailor-exit-descriptor %edx 0x10)
14012     #
14013     (write _test-input-stream "fn foo {\n")
14014     (write _test-input-stream "  var y: (handle int)\n")
14015     (write _test-input-stream "  populate-stream y, 3\n")
14016     (write _test-input-stream "}\n")
14017     # convert
14018     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14019     # registers except esp clobbered at this point
14020     # restore ed
14021     89/<- %edx 4/r32/esp
14022     (flush _test-output-buffered-file)
14023     (flush _test-error-buffered-file)
14024 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
14030     # check output
14031     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-non-addr: output must be empty")
14032     (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")
14033     # check that stop(1) was called
14034     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr: exit status")
14035     # don't restore from ebp
14036     81 0/subop/add %esp 8/imm32
14037     # . epilogue
14038     5d/pop-to-ebp
14039     c3/return
14040 
14041 test-populate-stream-non-addr-handle:
14042     # . prologue
14043     55/push-ebp
14044     89/<- %ebp 4/r32/esp
14045     # setup
14046     (clear-stream _test-input-stream)
14047     (clear-stream $_test-input-buffered-file->buffer)
14048     (clear-stream _test-output-stream)
14049     (clear-stream $_test-output-buffered-file->buffer)
14050     (clear-stream _test-error-stream)
14051     (clear-stream $_test-error-buffered-file->buffer)
14052     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14053     68/push 0/imm32
14054     68/push 0/imm32
14055     89/<- %edx 4/r32/esp
14056     (tailor-exit-descriptor %edx 0x10)
14057     #
14058     (write _test-input-stream "fn foo {\n")
14059     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
14060     (write _test-input-stream "  populate-stream y, 3\n")
14061     (write _test-input-stream "}\n")
14062     # convert
14063     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14064     # registers except esp clobbered at this point
14065     # restore ed
14066     89/<- %edx 4/r32/esp
14067     (flush _test-output-buffered-file)
14068     (flush _test-error-buffered-file)
14069 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
14075     # check output
14076     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-non-addr-handle: output should be empty")
14077     (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")
14078     # check that stop(1) was called
14079     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr-handle: exit status")
14080     # don't restore from ebp
14081     81 0/subop/add %esp 8/imm32
14082     # . epilogue
14083     5d/pop-to-ebp
14084     c3/return
14085 
14086 test-populate-stream-non-addr-handle-stream:
14087     # . prologue
14088     55/push-ebp
14089     89/<- %ebp 4/r32/esp
14090     # setup
14091     (clear-stream _test-input-stream)
14092     (clear-stream $_test-input-buffered-file->buffer)
14093     (clear-stream _test-output-stream)
14094     (clear-stream $_test-output-buffered-file->buffer)
14095     (clear-stream _test-error-stream)
14096     (clear-stream $_test-error-buffered-file->buffer)
14097     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14098     68/push 0/imm32
14099     68/push 0/imm32
14100     89/<- %edx 4/r32/esp
14101     (tailor-exit-descriptor %edx 0x10)
14102     #
14103     (write _test-input-stream "fn foo {\n")
14104     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
14105     (write _test-input-stream "  populate-stream y, 3\n")
14106     (write _test-input-stream "}\n")
14107     # convert
14108     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14109     # registers except esp clobbered at this point
14110     # restore ed
14111     89/<- %edx 4/r32/esp
14112     (flush _test-output-buffered-file)
14113     (flush _test-error-buffered-file)
14114 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
14120     # check output
14121     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-non-addr-handle-stream: output should be empty")
14122     (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")
14123     # check that stop(1) was called
14124     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr-handle-stream: exit status")
14125     # don't restore from ebp
14126     81 0/subop/add %esp 8/imm32
14127     # . epilogue
14128     5d/pop-to-ebp
14129     c3/return
14130 
14131 test-populate-stream-deref-address:
14132     # . prologue
14133     55/push-ebp
14134     89/<- %ebp 4/r32/esp
14135     # setup
14136     (clear-stream _test-input-stream)
14137     (clear-stream $_test-input-buffered-file->buffer)
14138     (clear-stream _test-output-stream)
14139     (clear-stream $_test-output-buffered-file->buffer)
14140     #
14141     (write _test-input-stream "fn foo {\n")
14142     (write _test-input-stream "  var y/ecx: (addr addr handle stream int) <- copy 0\n")
14143     (write _test-input-stream "  populate-stream *y, 3\n")
14144     (write _test-input-stream "}\n")
14145     # convert
14146     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
14147     (flush _test-output-buffered-file)
14148 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
14154     # not bothering checking output
14155     (check-next-stream-line-equal _test-error-stream  ""  "F - test-populate-stream-deref-address: error message")
14156     # . epilogue
14157     5d/pop-to-ebp
14158     c3/return
14159 
14160 #######################################################
14161 # Parsing
14162 #######################################################
14163 
14164 == data
14165 
14166 # Global state added to each var record when parsing a function
14167 Next-block-index:  # (addr int)
14168     1/imm32
14169 
14170 Curr-block-depth:  # (addr int)
14171     1/imm32
14172 
14173 == code
14174 
14175 parse-mu:  # in: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
14176     # pseudocode
14177     #   var curr-function: (addr handle function) = Program->functions
14178     #   var curr-signature: (addr handle function) = Program->signatures
14179     #   var curr-type: (addr handle typeinfo) = Program->types
14180     #   var line: (stream byte 512)
14181     #   var word-slice: slice
14182     #   while true                                  # line loop
14183     #     clear-stream(line)
14184     #     read-line-buffered(in, line)
14185     #     if (line->write == 0) break               # end of file
14186     #     word-slice = next-mu-token(line)
14187     #     if slice-empty?(word-slice)               # end of line
14188     #       continue
14189     #     else if slice-starts-with?(word-slice, "#")  # comment
14190     #       continue                                # end of line
14191     #     else if slice-equal?(word-slice, "fn")
14192     #       var new-function: (handle function) = allocate(function)
14193     #       var vars: (stack live-var 256)
14194     #       populate-mu-function-header(line, new-function, vars)
14195     #       populate-mu-function-body(in, new-function, vars)
14196     #       assert(vars->top == 0)
14197     #       *curr-function = new-function
14198     #       curr-function = &new-function->next
14199     #     else if slice-equal?(word-slice, "sig")
14200     #       var new-function: (handle function) = allocate(function)
14201     #       populate-mu-function-signature(line, new-function)
14202     #       *curr-signature = new-function
14203     #       curr-signature = &new-function->next
14204     #     else if slice-equal?(word-slice, "type")
14205     #       word-slice = next-mu-token(line)
14206     #       type-id = pos-or-insert-slice(Type-id, word-slice)
14207     #       var new-type: (handle typeinfo) = find-or-create-typeinfo(type-id)
14208     #       assert(next-word(line) == "{")
14209     #       populate-mu-type(in, new-type)
14210     #     else
14211     #       abort()
14212     #
14213     # . prologue
14214     55/push-ebp
14215     89/<- %ebp 4/r32/esp
14216     # var curr-signature: (addr handle function) at *(ebp-4)
14217     68/push _Program-signatures/imm32
14218     # . save registers
14219     50/push-eax
14220     51/push-ecx
14221     52/push-edx
14222     53/push-ebx
14223     56/push-esi
14224     57/push-edi
14225     # var line/ecx: (stream byte 512)
14226     81 5/subop/subtract %esp 0x200/imm32
14227     68/push 0x200/imm32/size
14228     68/push 0/imm32/read
14229     68/push 0/imm32/write
14230     89/<- %ecx 4/r32/esp
14231     # var word-slice/edx: slice
14232     68/push 0/imm32/end
14233     68/push 0/imm32/start
14234     89/<- %edx 4/r32/esp
14235     # var curr-function/edi: (addr handle function)
14236     bf/copy-to-edi _Program-functions/imm32
14237     # var vars/ebx: (stack live-var 256)
14238     81 5/subop/subtract %esp 0xc00/imm32
14239     68/push 0xc00/imm32/size
14240     68/push 0/imm32/top
14241     89/<- %ebx 4/r32/esp
14242     {
14243 $parse-mu:line-loop:
14244       (clear-stream %ecx)
14245       (read-line-buffered *(ebp+8) %ecx)
14246       # if (line->write == 0) break
14247       81 7/subop/compare *ecx 0/imm32
14248       0f 84/jump-if-= break/disp32
14249 +--  6 lines: #?       # dump line ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
14255       (next-mu-token %ecx %edx)
14256       # if slice-empty?(word-slice) continue
14257       (slice-empty? %edx)  # => eax
14258       3d/compare-eax-and 0/imm32/false
14259       0f 85/jump-if-!= loop/disp32
14260       # if (*word-slice->start == "#") continue
14261       # . eax = *word-slice->start
14262       8b/-> *edx 0/r32/eax
14263       8a/copy-byte *eax 0/r32/AL
14264       81 4/subop/and %eax 0xff/imm32
14265       # . if (eax == '#') continue
14266       3d/compare-eax-and 0x23/imm32/hash
14267       0f 84/jump-if-= loop/disp32
14268       # if (slice-equal?(word-slice, "fn")) parse a function
14269       {
14270 $parse-mu:fn:
14271         (slice-equal? %edx "fn")  # => eax
14272         3d/compare-eax-and 0/imm32/false
14273         0f 84/jump-if-= break/disp32
14274         # var new-function/esi: (handle function)
14275         68/push 0/imm32
14276         68/push 0/imm32
14277         89/<- %esi 4/r32/esp
14278         # populate-mu-function(line, in, vars, new-function)
14279         (allocate Heap *Function-size %esi)
14280         # var new-function-addr/eax: (addr function)
14281         (lookup *esi *(esi+4))  # => eax
14282         # initialize vars
14283         (clear-stack %ebx)
14284         #
14285         (populate-mu-function-header %ecx %eax %ebx *(ebp+0xc) *(ebp+0x10))
14286         (populate-mu-function-body *(ebp+8) %eax %ebx *(ebp+0xc) *(ebp+0x10))
14287         # *curr-function = new-function
14288         8b/-> *esi 0/r32/eax
14289         89/<- *edi 0/r32/eax
14290         8b/-> *(esi+4) 0/r32/eax
14291         89/<- *(edi+4) 0/r32/eax
14292         # curr-function = &new-function->next
14293         # . var tmp/eax: (addr function) = lookup(new-function)
14294         (lookup *esi *(esi+4))  # => eax
14295         # . curr-function = &tmp->next
14296         8d/copy-address *(eax+0x20) 7/r32/edi  # Function-next
14297         # reclaim new-function
14298         81 0/subop/add %esp 8/imm32
14299         #
14300         e9/jump $parse-mu:line-loop/disp32
14301       }
14302       # if (slice-equal?(word-slice, "sig")) parse a function signature
14303       # Function signatures are for providing types to SubX functions.
14304       {
14305 $parse-mu:sig:
14306         (slice-equal? %edx "sig")  # => eax
14307         3d/compare-eax-and 0/imm32/false
14308         0f 84/jump-if-= break/disp32
14309         # edi = curr-function
14310         57/push-edi
14311         8b/-> *(ebp-4) 7/r32/edi
14312         # var new-function/esi: (handle function)
14313         68/push 0/imm32
14314         68/push 0/imm32
14315         89/<- %esi 4/r32/esp
14316         # populate-mu-function(line, in, vars, new-function)
14317         (allocate Heap *Function-size %esi)
14318         # var new-function-addr/eax: (addr function)
14319         (lookup *esi *(esi+4))  # => eax
14320         #
14321         (populate-mu-function-signature %ecx %eax *(ebp+0xc) *(ebp+0x10))
14322         # *curr-signature = new-function
14323         8b/-> *esi 0/r32/eax
14324         89/<- *edi 0/r32/eax
14325         8b/-> *(esi+4) 0/r32/eax
14326         89/<- *(edi+4) 0/r32/eax
14327         # curr-signature = &new-function->next
14328         # . var tmp/eax: (addr function) = lookup(new-function)
14329         (lookup *esi *(esi+4))  # => eax
14330         # . curr-function = &tmp->next
14331         8d/copy-address *(eax+0x20) 7/r32/edi  # Function-next
14332         # reclaim new-function
14333         81 0/subop/add %esp 8/imm32
14334         # save curr-function
14335         89/<- *(ebp-4) 7/r32/edi
14336         # restore edi
14337         5f/pop-to-edi
14338         #
14339         e9/jump $parse-mu:line-loop/disp32
14340       }
14341       # if (slice-equal?(word-slice, "type")) parse a type (struct/record) definition
14342       {
14343 $parse-mu:type:
14344         (slice-equal? %edx "type")  # => eax
14345         3d/compare-eax-and 0/imm32
14346         0f 84/jump-if-= break/disp32
14347         (next-mu-token %ecx %edx)
14348         # var type-id/eax: int
14349         (pos-or-insert-slice Type-id %edx)  # => eax
14350         # spill
14351         51/push-ecx
14352         # var new-type/ecx: (handle typeinfo)
14353         68/push 0/imm32
14354         68/push 0/imm32
14355         89/<- %ecx 4/r32/esp
14356         (find-or-create-typeinfo %eax %ecx)
14357         #
14358         (lookup *ecx *(ecx+4))  # => eax
14359         # TODO: ensure that 'line' has nothing else but '{'
14360 #? (dump-typeinfos "=== aaa\n")
14361         (populate-mu-type *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10))  # => eax
14362 #? (dump-typeinfos "=== zzz\n")
14363         # reclaim new-type
14364         81 0/subop/add %esp 8/imm32
14365         # restore
14366         59/pop-to-ecx
14367         e9/jump $parse-mu:line-loop/disp32
14368       }
14369       # otherwise abort
14370       e9/jump $parse-mu:error1/disp32
14371     } # end line loop
14372 $parse-mu:end:
14373     # . reclaim locals
14374     81 0/subop/add %esp 0x20c/imm32  # line
14375     81 0/subop/add %esp 0xc08/imm32  # vars
14376     81 0/subop/add %esp 8/imm32
14377     # . restore registers
14378     5f/pop-to-edi
14379     5e/pop-to-esi
14380     5b/pop-to-ebx
14381     5a/pop-to-edx
14382     59/pop-to-ecx
14383     58/pop-to-eax
14384     # . reclaim local
14385     81 0/subop/add %esp 4/imm32
14386     # . epilogue
14387     89/<- %esp 5/r32/ebp
14388     5d/pop-to-ebp
14389     c3/return
14390 
14391 $parse-mu:error1:
14392     # error("unexpected top-level command: " word-slice "\n")
14393     (write-buffered *(ebp+0xc) "unexpected top-level command: ")
14394     (write-slice-buffered *(ebp+0xc) %edx)
14395     (write-buffered *(ebp+0xc) "\n")
14396     (flush *(ebp+0xc))
14397     (stop *(ebp+0x10) 1)
14398     # never gets here
14399 
14400 $parse-mu:error2:
14401     # error(vars->top " vars not reclaimed after fn '" new-function->name "'\n")
14402     (write-int32-hex-buffered *(ebp+0xc) *ebx)
14403     (write-buffered *(ebp+0xc) " vars not reclaimed after fn '")
14404     (write-slice-buffered *(ebp+0xc) *eax)  # Function-name
14405     (write-buffered *(ebp+0xc) "'\n")
14406     (flush *(ebp+0xc))
14407     (stop *(ebp+0x10) 1)
14408     # never gets here
14409 
14410 # scenarios considered:
14411 # ✗ fn foo  # no block
14412 # ✓ fn foo {
14413 # ✗ fn foo { {
14414 # ✗ fn foo { }
14415 # ✗ fn foo { } {
14416 # ✗ fn foo x {
14417 # ✗ fn foo x: {
14418 # ✓ fn foo x: int {
14419 # ✓ fn foo x: int {
14420 # ✓ fn foo x: int -> _/eax: int {
14421 # TODO:
14422 #   disallow outputs of type `(... addr ...)`
14423 #   disallow inputs of type `(... addr ... addr ...)`
14424 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)
14425     # pseudocode:
14426     #   var word-slice: slice
14427     #   next-mu-token(first-line, word-slice)
14428     #   if slice-empty?(word-slice) abort
14429     #   assert(word-slice not in '{' '}' '->')
14430     #   out->name = slice-to-string(word-slice)
14431     #   ## inouts
14432     #   while true
14433     #     word-slice = next-mu-token(first-line)
14434     #     if slice-empty?(word-slice) abort
14435     #     if (word-slice == '{') goto done
14436     #     if (word-slice == '->') break
14437     #     assert(word-slice != '}')
14438     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
14439     #     assert(v->register == null)
14440     #     # v->block-depth is implicitly 0
14441     #     out->inouts = append(v, out->inouts)
14442     #     push(vars, {v, false})
14443     #   ## outputs
14444     #   while true
14445     #     word-slice = next-mu-token(first-line)
14446     #     if slice-empty?(word-slice) abort
14447     #     if (word-slice == '{') break
14448     #     assert(word-slice not in '}' '->')
14449     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
14450     #     assert(v->register != null)
14451     #     assert(v->name == "_")
14452     #     out->outputs = append(v, out->outputs)
14453     #   done:
14454     #
14455     # . prologue
14456     55/push-ebp
14457     89/<- %ebp 4/r32/esp
14458     # . save registers
14459     50/push-eax
14460     51/push-ecx
14461     52/push-edx
14462     53/push-ebx
14463     57/push-edi
14464     # edi = out
14465     8b/-> *(ebp+0xc) 7/r32/edi
14466     # var word-slice/ecx: slice
14467     68/push 0/imm32/end
14468     68/push 0/imm32/start
14469     89/<- %ecx 4/r32/esp
14470     # var v/ebx: (handle var)
14471     68/push 0/imm32
14472     68/push 0/imm32
14473     89/<- %ebx 4/r32/esp
14474     # read function name
14475     (next-mu-token *(ebp+8) %ecx)
14476     # error checking
14477     # if slice-empty?(word-slice) abort
14478     (slice-empty? %ecx)  # => eax
14479     3d/compare-eax-and 0/imm32/false
14480     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
14481     # if (word-slice == '{') abort
14482     (slice-equal? %ecx "{")   # => eax
14483     3d/compare-eax-and 0/imm32/false
14484     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
14485     # if (word-slice == '->') abort
14486     (slice-equal? %ecx "->")   # => eax
14487     3d/compare-eax-and 0/imm32/false
14488     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
14489     # if (word-slice == '}') abort
14490     (slice-equal? %ecx "}")   # => eax
14491     3d/compare-eax-and 0/imm32/false
14492     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
14493     # if word-slice already defined, abort
14494     (function-exists? %ecx)  # => eax
14495     3d/compare-eax-and 0/imm32/false
14496     0f 85/jump-if-!= $populate-mu-function-header:error-duplicate/disp32
14497     #
14498     (slice-starts-with? %ecx "break")  # => eax
14499     3d/compare-eax-and 0/imm32/false
14500     0f 85/jump-if-!= $populate-mu-function-header:error-break/disp32
14501     (slice-starts-with? %ecx "loop")  # => eax
14502     3d/compare-eax-and 0/imm32/false
14503     0f 85/jump-if-!= $populate-mu-function-header:error-loop/disp32
14504     (slice-equal? %ecx "lookup")  # => eax
14505     3d/compare-eax-and 0/imm32/false
14506     0f 85/jump-if-!= $populate-mu-function-header:error-lookup/disp32
14507     # save function name
14508     (slice-to-string Heap %ecx %edi)  # Function-name
14509     # save function inouts
14510     {
14511 $populate-mu-function-header:check-for-inout:
14512       (next-mu-token *(ebp+8) %ecx)
14513       # if slice-empty?(word-slice) abort
14514       (slice-empty? %ecx)  # => eax
14515       3d/compare-eax-and 0/imm32/false
14516       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
14517       # if (word-slice == '{') goto done
14518       (slice-equal? %ecx "{")   # => eax
14519       3d/compare-eax-and 0/imm32/false
14520       0f 85/jump-if-!= $populate-mu-function-header:done/disp32
14521       # if (word-slice == '->') break
14522       (slice-equal? %ecx "->")   # => eax
14523       3d/compare-eax-and 0/imm32/false
14524       0f 85/jump-if-!= break/disp32
14525       # if (word-slice == '}') abort
14526       (slice-equal? %ecx "}")   # => eax
14527       3d/compare-eax-and 0/imm32/false
14528       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
14529       # v = parse-var-with-type(word-slice, first-line)
14530       (lookup *edi *(edi+4))  # Function-name Function-name => eax
14531       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x14) *(ebp+0x18))
14532       # if (v->register != null) abort
14533       # . eax: (addr var) = lookup(v)
14534       (lookup *ebx *(ebx+4))  # => eax
14535       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
14536       0f 85/jump-if-!= $populate-mu-function-header:error2/disp32
14537       # if function name is not "main"
14538       #    and v->type contains an 'addr' anywhere except the start, abort
14539       {
14540         (lookup *edi *(edi+4))  # Function-name Function-name => eax
14541         (string-equal? %eax "main")  # => eax
14542         3d/compare-eax-and 0/imm32/false
14543         75/jump-if-!= break/disp8
14544         (lookup *ebx *(ebx+4))  # => eax
14545         (addr-payload-contains-addr? %eax)  # => eax
14546         3d/compare-eax-and 0/imm32/false
14547         0f 85/jump-if-!= $populate-mu-function-header:error-nested-addr-inout/disp32
14548       }
14549       # v->block-depth is implicitly 0
14550       #
14551       # out->inouts = append(v, out->inouts)
14552       8d/copy-address *(edi+8) 0/r32/eax  # Function-inouts
14553       (append-list Heap  *ebx *(ebx+4)  *(edi+8) *(edi+0xc)  %eax)  # Function-inouts, Function-inouts
14554       # push(vars, {v, false})
14555       (push *(ebp+0x10) *ebx)
14556       (push *(ebp+0x10) *(ebx+4))
14557       (push *(ebp+0x10) 0)  # false
14558       #
14559       e9/jump loop/disp32
14560     }
14561     # save function outputs
14562     {
14563 $populate-mu-function-header:check-for-out:
14564       (next-mu-token *(ebp+8) %ecx)
14565       # if slice-empty?(word-slice) abort
14566       (slice-empty? %ecx)  # => eax
14567       3d/compare-eax-and 0/imm32/false
14568       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
14569       # if (word-slice == '{') break
14570       (slice-equal? %ecx "{")   # => eax
14571       3d/compare-eax-and 0/imm32/false
14572       0f 85/jump-if-!= break/disp32
14573       # if (word-slice == '->') abort
14574       (slice-equal? %ecx "->")   # => eax
14575       3d/compare-eax-and 0/imm32/false
14576       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
14577       # if (word-slice == '}') abort
14578       (slice-equal? %ecx "}")   # => eax
14579       3d/compare-eax-and 0/imm32/false
14580       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
14581       # v = parse-var-with-type(word-slice, first-line)
14582       (lookup *edi *(edi+4))  # Function-name Function-name => eax
14583       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x14) *(ebp+0x18))
14584       # assert(var->register != null)
14585       # . eax: (addr var) = lookup(v)
14586       (lookup *ebx *(ebx+4))  # => eax
14587       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
14588       0f 84/jump-if-= $populate-mu-function-header:error3/disp32
14589       # if (var->name != "_") abort
14590       (lookup *eax *(eax+4))  # Var-name Var-name => eax
14591       (string-equal? %eax "_")  # => eax
14592       3d/compare-eax-and 0/imm32/false
14593       0f 84/jump-if-= $populate-mu-function-header:error4/disp32
14594       # if v->type is an addr, abort
14595       (lookup *ebx *(ebx+4))  # => eax
14596       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
14597       (is-mu-addr-type? %eax)  # => eax
14598       3d/compare-eax-and 0/imm32/false
14599       0f 85/jump-if-!= $populate-mu-function-header:error-addr-output/disp32
14600       # out->outputs = append(v, out->outputs)
14601       8d/copy-address *(edi+0x10) 0/r32/eax  # Function-outputs
14602       (append-list Heap  *ebx *(ebx+4)  *(edi+0x10) *(edi+0x14)  %eax)  # Function-outputs, Function-outputs
14603       #
14604       e9/jump loop/disp32
14605     }
14606 $populate-mu-function-header:done:
14607     (check-no-tokens-left *(ebp+8))
14608 $populate-mu-function-header:end:
14609     # . reclaim locals
14610     81 0/subop/add %esp 0x10/imm32
14611     # . restore registers
14612     5f/pop-to-edi
14613     5b/pop-to-ebx
14614     5a/pop-to-edx
14615     59/pop-to-ecx
14616     58/pop-to-eax
14617     # . epilogue
14618     89/<- %esp 5/r32/ebp
14619     5d/pop-to-ebp
14620     c3/return
14621 
14622 $populate-mu-function-header:error1:
14623     # error("function header not in form 'fn <name> {'")
14624     (write-buffered *(ebp+0x14) "function header not in form 'fn <name> [inouts] [-> outputs] {' -- '")
14625     (flush *(ebp+0x14))
14626     (rewind-stream *(ebp+8))
14627     (write-stream-data *(ebp+0x14) *(ebp+8))
14628     (write-buffered *(ebp+0x14) "'\n")
14629     (flush *(ebp+0x14))
14630     (stop *(ebp+0x18) 1)
14631     # never gets here
14632 
14633 $populate-mu-function-header:error2:
14634     # error("fn " fn ": function inout '" var "' cannot be in a register")
14635     (write-buffered *(ebp+0x14) "fn ")
14636     50/push-eax
14637     (lookup *edi *(edi+4))  # Function-name Function-name => eax
14638     (write-buffered *(ebp+0x14) %eax)
14639     58/pop-to-eax
14640     (write-buffered *(ebp+0x14) ": function inout '")
14641     (lookup *eax *(eax+4))  # Var-name Var-name => eax
14642     (write-buffered *(ebp+0x14) %eax)
14643     (write-buffered *(ebp+0x14) "' cannot be in a register")
14644     (flush *(ebp+0x14))
14645     (stop *(ebp+0x18) 1)
14646     # never gets here
14647 
14648 $populate-mu-function-header:error3:
14649     # error("fn " fn ": function output '" var "' must be in a register")
14650     (write-buffered *(ebp+0x14) "fn ")
14651     50/push-eax
14652     (lookup *edi *(edi+4))  # Function-name Function-name => eax
14653     (write-buffered *(ebp+0x14) %eax)
14654     58/pop-to-eax
14655     (write-buffered *(ebp+0x14) ": function output '")
14656     (lookup *ebx *(ebx+4))  # => eax
14657     (lookup *eax *(eax+4))  # Var-name Var-name => eax
14658     (write-buffered *(ebp+0x14) %eax)
14659     (write-buffered *(ebp+0x14) "' must be in a register, in instruction '")
14660     (rewind-stream *(ebp+8))
14661     (write-stream-data *(ebp+0x14) *(ebp+8))
14662     (write-buffered *(ebp+0x14) "'\n")
14663     (flush *(ebp+0x14))
14664     (stop *(ebp+0x18) 1)
14665     # never gets here
14666 
14667 $populate-mu-function-header:error4:
14668     # error("fn " fn ": function outputs cannot be named; rename '" var "' in the header to '_'")
14669     (write-buffered *(ebp+0x14) "fn ")
14670     50/push-eax
14671     (lookup *edi *(edi+4))  # Function-name Function-name => eax
14672     (write-buffered *(ebp+0x14) %eax)
14673     58/pop-to-eax
14674     (write-buffered *(ebp+0x14) ": function outputs cannot be named; rename '")
14675     (lookup *ebx *(ebx+4))  # => eax
14676     (lookup *eax *(eax+4))  # Var-name Var-name => eax
14677     (write-buffered *(ebp+0x14) %eax)
14678     (write-buffered *(ebp+0x14) "' in the header to '_'\n")
14679     (flush *(ebp+0x14))
14680     (stop *(ebp+0x18) 1)
14681     # never gets here
14682 
14683 $populate-mu-function-header:error-duplicate:
14684     (write-buffered *(ebp+0x14) "fn ")
14685     (write-slice-buffered *(ebp+0x14) %ecx)
14686     (write-buffered *(ebp+0x14) " defined more than once\n")
14687     (flush *(ebp+0x14))
14688     (stop *(ebp+0x18) 1)
14689     # never gets here
14690 
14691 $populate-mu-function-header:error-break:
14692     (write-buffered *(ebp+0x14) "Sorry, I've reserved all function names starting with 'break' for now. Please contact mu@akkartik.com.\n")
14693     (flush *(ebp+0x14))
14694     (stop *(ebp+0x18) 1)
14695     # never gets here
14696 
14697 $populate-mu-function-header:error-loop:
14698     (write-buffered *(ebp+0x14) "Sorry, I've reserved all function names starting with 'loop' for now. Please contact mu@akkartik.com.\n")
14699     (flush *(ebp+0x14))
14700     (stop *(ebp+0x18) 1)
14701     # never gets here
14702 
14703 $populate-mu-function-header:error-lookup:
14704     (write-buffered *(ebp+0x14) "cannot define a function called 'lookup'\n")
14705     (flush *(ebp+0x14))
14706     (stop *(ebp+0x18) 1)
14707     # never gets here
14708 
14709 $populate-mu-function-header:error-addr-output:
14710     # error("fn " fn ": output cannot have an addr type; that could allow unsafe addresses to escape the function")
14711     (write-buffered *(ebp+0x14) "fn ")
14712     50/push-eax
14713     (lookup *edi *(edi+4))  # Function-name Function-name => eax
14714     (write-buffered *(ebp+0x14) %eax)
14715     58/pop-to-eax
14716     (write-buffered *(ebp+0x14) ": output cannot have an addr type; that could allow unsafe addresses to escape the function\n")
14717     (flush *(ebp+0x14))
14718     (stop *(ebp+0x18) 1)
14719     # never gets here
14720 
14721 $populate-mu-function-header:error-nested-addr-inout:
14722     # 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")
14723     (write-buffered *(ebp+0x14) "fn ")
14724     (lookup *edi *(edi+4))  # Function-name Function-name => eax
14725     (write-buffered *(ebp+0x14) %eax)
14726     (write-buffered *(ebp+0x14) ": inout '")
14727     (lookup *ebx *(ebx+4))  # => eax
14728     (lookup *eax *(eax+4))  # Var-name Var-name => eax
14729     (write-buffered *(ebp+0x14) %eax)
14730     (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")
14731     (flush *(ebp+0x14))
14732     (stop *(ebp+0x18) 1)
14733     # never gets here
14734 
14735 # scenarios considered:
14736 # ✓ fn foo
14737 # ✗ fn foo {
14738 # ✓ fn foo x
14739 # ✓ fn foo x: int
14740 # ✓ fn foo x: int -> _/eax: int
14741 # TODO:
14742 #   disallow outputs of type `(... addr ...)`
14743 #   disallow inputs of type `(... addr ... addr ...)`
14744 populate-mu-function-signature:  # first-line: (addr stream byte), out: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
14745     # pseudocode:
14746     #   var word-slice: slice
14747     #   next-mu-token(first-line, word-slice)
14748     #   assert(word-slice not in '{' '}' '->')
14749     #   out->name = slice-to-string(word-slice)
14750     #   ## inouts
14751     #   while true
14752     #     word-slice = next-mu-token(first-line)
14753     #     if slice-empty?(word-slice) break
14754     #     if (word-slice == '->') break
14755     #     assert(word-slice not in '{' '}')
14756     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
14757     #     assert(v->register == null)
14758     #     # v->block-depth is implicitly 0
14759     #     out->inouts = append(v, out->inouts)
14760     #   ## outputs
14761     #   while true
14762     #     word-slice = next-mu-token(first-line)
14763     #     if slice-empty?(word-slice) break
14764     #     assert(word-slice not in '{' '}' '->')
14765     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
14766     #     assert(v->register != null)
14767     #     out->outputs = append(v, out->outputs)
14768     #
14769     # . prologue
14770     55/push-ebp
14771     89/<- %ebp 4/r32/esp
14772     # . save registers
14773     50/push-eax
14774     51/push-ecx
14775     52/push-edx
14776     53/push-ebx
14777     57/push-edi
14778     # edi = out
14779     8b/-> *(ebp+0xc) 7/r32/edi
14780     # var word-slice/ecx: slice
14781     68/push 0/imm32/end
14782     68/push 0/imm32/start
14783     89/<- %ecx 4/r32/esp
14784     # var v/ebx: (handle var)
14785     68/push 0/imm32
14786     68/push 0/imm32
14787     89/<- %ebx 4/r32/esp
14788     # read function name
14789     (next-mu-token *(ebp+8) %ecx)
14790     # error checking
14791     # if (word-slice == '{') abort
14792     (slice-equal? %ecx "{")   # => eax
14793     3d/compare-eax-and 0/imm32/false
14794     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
14795     # if (word-slice == '->') abort
14796     (slice-equal? %ecx "->")   # => eax
14797     3d/compare-eax-and 0/imm32/false
14798     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
14799     # if (word-slice == '}') abort
14800     (slice-equal? %ecx "}")   # => eax
14801     3d/compare-eax-and 0/imm32/false
14802     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
14803     # if word-slice already defined, abort
14804     (function-exists? %ecx)  # => eax
14805     3d/compare-eax-and 0/imm32/false
14806     0f 85/jump-if-!= $populate-mu-function-signature:error-duplicate/disp32
14807     #
14808     (slice-starts-with? %ecx "break")  # => eax
14809     3d/compare-eax-and 0/imm32/false
14810     0f 85/jump-if-!= $populate-mu-function-signature:error-break/disp32
14811     (slice-starts-with? %ecx "loop")  # => eax
14812     3d/compare-eax-and 0/imm32/false
14813     0f 85/jump-if-!= $populate-mu-function-signature:error-loop/disp32
14814     # save function name
14815     (slice-to-string Heap %ecx %edi)  # Function-name
14816     # save function inouts
14817     {
14818 $populate-mu-function-signature:check-for-inout:
14819       (next-mu-token *(ebp+8) %ecx)
14820       (slice-empty? %ecx)  # => eax
14821       3d/compare-eax-and 0/imm32/false
14822       0f 85/jump-if-!= break/disp32
14823       # if (word-slice == '->') break
14824       (slice-equal? %ecx "->")   # => eax
14825       3d/compare-eax-and 0/imm32/false
14826       0f 85/jump-if-!= break/disp32
14827       # if (word-slice == '{') abort
14828       (slice-equal? %ecx "{")   # => eax
14829       3d/compare-eax-and 0/imm32/false
14830       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
14831       # if (word-slice == '}') abort
14832       (slice-equal? %ecx "}")   # => eax
14833       3d/compare-eax-and 0/imm32/false
14834       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
14835       # v = parse-var-with-type(word-slice, first-line)
14836       (lookup *edi *(edi+4))  # Function-name Function-name => eax
14837       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x10) *(ebp+0x14))
14838       # if (v->register != null) abort
14839       # . eax: (addr var) = lookup(v)
14840       (lookup *ebx *(ebx+4))  # => eax
14841       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
14842       0f 85/jump-if-!= $populate-mu-function-signature:error2/disp32
14843       # if function name is not "main"
14844       #    and v->type contains an 'addr' anywhere except the start, abort
14845       {
14846         (lookup *edi *(edi+4))  # Function-name Function-name => eax
14847         (string-equal? %eax "main")  # => eax
14848         3d/compare-eax-and 0/imm32/false
14849         75/jump-if-!= break/disp8
14850         (lookup *ebx *(ebx+4))  # => eax
14851         (addr-payload-contains-addr? %eax)  # => eax
14852         3d/compare-eax-and 0/imm32/false
14853         0f 85/jump-if-!= $populate-mu-function-signature:error-nested-addr-inout/disp32
14854       }
14855       # assert(v->register == null)
14856       # . eax: (addr var) = lookup(v)
14857       (lookup *ebx *(ebx+4))  # => eax
14858       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
14859       0f 85/jump-if-!= $populate-mu-function-signature:error2/disp32
14860       # v->block-depth is implicitly 0
14861       #
14862       # out->inouts = append(v, out->inouts)
14863       8d/copy-address *(edi+8) 0/r32/eax  # Function-inouts
14864       (append-list Heap  *ebx *(ebx+4)  *(edi+8) *(edi+0xc)  %eax)  # Function-inouts, Function-inouts
14865       #
14866       e9/jump loop/disp32
14867     }
14868     # save function outputs
14869     {
14870 $populate-mu-function-signature:check-for-out:
14871       (next-mu-token *(ebp+8) %ecx)
14872       (slice-empty? %ecx)  # => eax
14873       3d/compare-eax-and 0/imm32/false
14874       0f 85/jump-if-!= break/disp32
14875       # if (word-slice == '{') abort
14876       (slice-equal? %ecx "{")   # => eax
14877       3d/compare-eax-and 0/imm32/false
14878       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
14879       # if (word-slice == '->') abort
14880       (slice-equal? %ecx "->")   # => eax
14881       3d/compare-eax-and 0/imm32/false
14882       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
14883       # if (word-slice == '}') abort
14884       (slice-equal? %ecx "}")   # => eax
14885       3d/compare-eax-and 0/imm32/false
14886       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
14887       # v = parse-var-with-type(word-slice, first-line)
14888       (lookup *edi *(edi+4))  # Function-name Function-name => eax
14889       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x10) *(ebp+0x14))
14890       # assert(var->register != null)
14891       # . eax: (addr var) = lookup(v)
14892       (lookup *ebx *(ebx+4))  # => eax
14893       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
14894       0f 84/jump-if-= $populate-mu-function-signature:error3/disp32
14895       # if (var->name != "_") abort
14896       (lookup *eax *(eax+4))  # Var-name Var-name => eax
14897       (string-equal? %eax "_")  # => eax
14898       3d/compare-eax-and 0/imm32/false
14899       0f 84/jump-if-= $populate-mu-function-signature:error4/disp32
14900       # if function name is not "lookup"
14901       #    and v->type is an addr, abort
14902       {
14903         (lookup *edi *(edi+4))  # Function-name Function-name => eax
14904         (string-equal? %eax "lookup")  # => eax
14905         3d/compare-eax-and 0/imm32/false
14906         75/jump-if-!= break/disp8
14907         (lookup *ebx *(ebx+4))  # => eax
14908         (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
14909         (is-mu-addr-type? %eax)  # => eax
14910         3d/compare-eax-and 0/imm32/false
14911         0f 85/jump-if-!= $populate-mu-function-signature:error-addr-output/disp32
14912       }
14913       # out->outputs = append(v, out->outputs)
14914       8d/copy-address *(edi+0x10) 0/r32/eax  # Function-outputs
14915       (append-list Heap  *ebx *(ebx+4)  *(edi+0x10) *(edi+0x14)  %eax)  # Function-outputs, Function-outputs
14916       #
14917       e9/jump loop/disp32
14918     }
14919 $populate-mu-function-signature:done:
14920     (check-no-tokens-left *(ebp+8))
14921 $populate-mu-function-signature:end:
14922     # . reclaim locals
14923     81 0/subop/add %esp 0x10/imm32
14924     # . restore registers
14925     5f/pop-to-edi
14926     5b/pop-to-ebx
14927     5a/pop-to-edx
14928     59/pop-to-ecx
14929     58/pop-to-eax
14930     # . epilogue
14931     89/<- %esp 5/r32/ebp
14932     5d/pop-to-ebp
14933     c3/return
14934 
14935 $populate-mu-function-signature:error1:
14936     # error("function signature not in form 'fn <name> {'")
14937     (write-buffered *(ebp+0x10) "function signature not in form 'fn <name> [inouts] [-> outputs] {' -- '")
14938     (flush *(ebp+0x10))
14939     (rewind-stream *(ebp+8))
14940     (write-stream-data *(ebp+0x10) *(ebp+8))
14941     (write-buffered *(ebp+0x10) "'\n")
14942     (flush *(ebp+0x10))
14943     (stop *(ebp+0x14) 1)
14944     # never gets here
14945 
14946 $populate-mu-function-signature:error2:
14947     # error("fn " fn ": function inout '" var "' cannot be in a register")
14948     (write-buffered *(ebp+0x10) "fn ")
14949     50/push-eax
14950     (lookup *edi *(edi+4))  # Function-name Function-name => eax
14951     (write-buffered *(ebp+0x10) %eax)
14952     58/pop-to-eax
14953     (write-buffered *(ebp+0x10) ": function inout '")
14954     (lookup *eax *(eax+4))  # Var-name Var-name => eax
14955     (write-buffered *(ebp+0x10) %eax)
14956     (write-buffered *(ebp+0x10) "' cannot be in a register")
14957     (flush *(ebp+0x10))
14958     (stop *(ebp+0x14) 1)
14959     # never gets here
14960 
14961 $populate-mu-function-signature:error3:
14962     # error("fn " fn ": function output '" var "' must be in a register")
14963     (write-buffered *(ebp+0x10) "fn ")
14964     50/push-eax
14965     (lookup *edi *(edi+4))  # Function-name Function-name => eax
14966     (write-buffered *(ebp+0x10) %eax)
14967     58/pop-to-eax
14968     (write-buffered *(ebp+0x10) ": function output '")
14969     (lookup *ebx *(ebx+4))  # => eax
14970     (lookup *eax *(eax+4))  # Var-name Var-name => eax
14971     (write-buffered *(ebp+0x10) %eax)
14972     (write-buffered *(ebp+0x10) "' must be in a register, in instruction '")
14973     (rewind-stream *(ebp+8))
14974     (write-stream-data *(ebp+0x10) *(ebp+8))
14975     (write-buffered *(ebp+0x10) "'\n")
14976     (flush *(ebp+0x10))
14977     (stop *(ebp+0x14) 1)
14978     # never gets here
14979 
14980 $populate-mu-function-signature:error4:
14981     # error("fn " fn ": function outputs cannot be named; rename '" var "' in the header to '_'")
14982     (write-buffered *(ebp+0x10) "fn ")
14983     50/push-eax
14984     (lookup *edi *(edi+4))  # Function-name Function-name => eax
14985     (write-buffered *(ebp+0x10) %eax)
14986     58/pop-to-eax
14987     (write-buffered *(ebp+0x10) ": function outputs cannot be named; rename '")
14988     (lookup *ebx *(ebx+4))  # => eax
14989     (lookup *eax *(eax+4))  # Var-name Var-name => eax
14990     (write-buffered *(ebp+0x10) %eax)
14991     (write-buffered *(ebp+0x10) "' in the header to '_'\n")
14992     (flush *(ebp+0x10))
14993     (stop *(ebp+0x14) 1)
14994     # never gets here
14995 
14996 $populate-mu-function-signature:error-duplicate:
14997     (write-buffered *(ebp+0x10) "fn ")
14998     (write-slice-buffered *(ebp+0x10) %ecx)
14999     (write-buffered *(ebp+0x10) " defined more than once\n")
15000     (flush *(ebp+0x10))
15001     (stop *(ebp+0x14) 1)
15002     # never gets here
15003 
15004 $populate-mu-function-signature:error-break:
15005     (write-buffered *(ebp+0x10) "Sorry, I've reserved all function names starting with 'break' for now. Please contact mu@akkartik.com.\n")
15006     (flush *(ebp+0x10))
15007     (stop *(ebp+0x14) 1)
15008     # never gets here
15009 
15010 $populate-mu-function-signature:error-loop:
15011     (write-buffered *(ebp+0x10) "Sorry, I've reserved all function names starting with 'loop' for now. Please contact mu@akkartik.com.\n")
15012     (flush *(ebp+0x10))
15013     (stop *(ebp+0x14) 1)
15014     # never gets here
15015 
15016 $populate-mu-function-signature:error-addr-output:
15017     # error("fn " fn ": output cannot have an addr type; that could allow unsafe addresses to escape the function")
15018     (write-buffered *(ebp+0x10) "fn ")
15019     50/push-eax
15020     (lookup *edi *(edi+4))  # Function-name Function-name => eax
15021     (write-buffered *(ebp+0x10) %eax)
15022     58/pop-to-eax
15023     (write-buffered *(ebp+0x10) ": output cannot have an addr type; that could allow unsafe addresses to escape the function\n")
15024     (flush *(ebp+0x10))
15025     (stop *(ebp+0x14) 1)
15026     # never gets here
15027 
15028 $populate-mu-function-signature:error-nested-addr-inout:
15029     # 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")
15030     (write-buffered *(ebp+0x10) "fn ")
15031     (lookup *edi *(edi+4))  # Function-name Function-name => eax
15032     (write-buffered *(ebp+0x10) %eax)
15033     (write-buffered *(ebp+0x10) ": inout '")
15034     (lookup *ebx *(ebx+4))  # => eax
15035     (lookup *eax *(eax+4))  # Var-name Var-name => eax
15036     (write-buffered *(ebp+0x10) %eax)
15037     (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")
15038     (flush *(ebp+0x10))
15039     (stop *(ebp+0x14) 1)
15040     # never gets here
15041 
15042 addr-payload-contains-addr?:  # v: (addr var) -> result/eax: boolean
15043     # . prologue
15044     55/push-ebp
15045     89/<- %ebp 4/r32/esp
15046     # var t/eax: (addr type-tree) = v->type
15047     8b/-> *(ebp+8) 0/r32/eax
15048     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
15049     # if t->right contains addr, return true
15050     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
15051     (type-tree-contains? %eax 2)  # addr => eax
15052     # we don't have to look at t->left as long as it's guaranteed to be an atom
15053 $addr-payload-contains-addr?:end:
15054     # . epilogue
15055     89/<- %esp 5/r32/ebp
15056     5d/pop-to-ebp
15057     c3/return
15058 
15059 type-tree-contains?:  # t: (addr type-tree), n: type-id -> result/eax: boolean
15060     # . prologue
15061     55/push-ebp
15062     89/<- %ebp 4/r32/esp
15063     # . save registers
15064     51/push-ecx
15065     # if t is null, return false
15066     8b/-> *(ebp+8) 0/r32/eax
15067     3d/compare-eax-and 0/imm32
15068     0f 84/jump-if-= $type-tree-contains?:end/disp32  # eax changes type
15069     # if t is an atom, return (t->value == n)
15070     81 7/subop/compare *eax 0/imm32/false
15071     {
15072       74/jump-if-= break/disp8
15073       8b/-> *(ebp+0xc) 1/r32/ecx
15074       39/compare *(eax+4) 1/r32/ecx  # Type-tree-value
15075       0f 94/set-if-= %al
15076       81 4/subop/and %eax 0xff/imm32
15077       eb/jump $type-tree-contains?:end/disp8
15078     }
15079     # if t->left contains n, return true
15080     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
15081     (type-tree-contains? %eax *(ebp+0xc))  # => eax
15082     3d/compare-eax-and 0/imm32/false
15083     75/jump-if-!= $type-tree-contains?:end/disp8
15084     # otherwise return whether t->right contains n
15085     8b/-> *(ebp+8) 0/r32/eax
15086     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
15087     (type-tree-contains? %eax *(ebp+0xc))  # => eax
15088 $type-tree-contains?:end:
15089     # . restore registers
15090     59/pop-to-ecx
15091     # . epilogue
15092     89/<- %esp 5/r32/ebp
15093     5d/pop-to-ebp
15094     c3/return
15095 
15096 function-exists?:  # s: (addr slice) -> result/eax: boolean
15097     # . prologue
15098     55/push-ebp
15099     89/<- %ebp 4/r32/esp
15100     # . save registers
15101     51/push-ecx
15102     # var curr/ecx: (addr function) = functions
15103     (lookup *_Program-functions *_Program-functions->payload)  # => eax
15104     89/<- %ecx 0/r32/eax
15105     {
15106       # if (curr == null) break
15107       81 7/subop/compare %ecx 0/imm32
15108       74/jump-if-= break/disp8
15109       # if (curr->name == s) return true
15110       {
15111         (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
15112         (slice-equal? *(ebp+8) %eax)  # => eax
15113         3d/compare-eax-and 0/imm32/false
15114         74/jump-if-= break/disp8
15115         b8/copy-to-eax 1/imm32/true
15116         e9/jump $function-exists?:end/disp32
15117       }
15118       # curr = curr->next
15119       (lookup *(ecx+0x20) *(ecx+0x24))  # Function-next Function-next => eax
15120       89/<- %ecx 0/r32/eax
15121       #
15122       eb/jump loop/disp8
15123     }
15124     # var curr/ecx: (addr function) = signatures
15125     (lookup *_Program-signatures *_Program-signatures->payload)  # => eax
15126     89/<- %ecx 0/r32/eax
15127     {
15128       # if (curr == null) break
15129       81 7/subop/compare %ecx 0/imm32
15130       74/jump-if-= break/disp8
15131       # if (curr->name == s) return true
15132       {
15133         (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
15134         (slice-equal? *(ebp+8) %eax)  # => eax
15135         3d/compare-eax-and 0/imm32/false
15136         74/jump-if-= break/disp8
15137         b8/copy-to-eax 1/imm32/true
15138         eb/jump $function-exists?:end/disp8
15139       }
15140       # curr = curr->next
15141       (lookup *(ecx+0x20) *(ecx+0x24))  # Function-next Function-next => eax
15142       89/<- %ecx 0/r32/eax
15143       #
15144       eb/jump loop/disp8
15145     }
15146     # return false
15147     b8/copy-to-eax 0/imm32/false
15148 $function-exists?:end:
15149     # . restore registers
15150     59/pop-to-ecx
15151     # . epilogue
15152     89/<- %esp 5/r32/ebp
15153     5d/pop-to-ebp
15154     c3/return
15155 
15156 test-function-header-with-arg:
15157     # . prologue
15158     55/push-ebp
15159     89/<- %ebp 4/r32/esp
15160     # setup
15161     8b/-> *Primitive-type-ids 0/r32/eax
15162     89/<- *Type-id 0/r32/eax  # stream-write
15163     c7 0/subop/copy *_Program-functions 0/imm32
15164     c7 0/subop/copy *_Program-functions->payload 0/imm32
15165     c7 0/subop/copy *_Program-types 0/imm32
15166     c7 0/subop/copy *_Program-types->payload 0/imm32
15167     c7 0/subop/copy *_Program-signatures 0/imm32
15168     c7 0/subop/copy *_Program-signatures->payload 0/imm32
15169     (clear-stream _test-input-stream)
15170     (write _test-input-stream "foo n: int {\n")
15171     # var result/ecx: function
15172     2b/subtract *Function-size 4/r32/esp
15173     89/<- %ecx 4/r32/esp
15174     (zero-out %ecx *Function-size)
15175     # var vars/ebx: (stack live-var 16)
15176     81 5/subop/subtract %esp 0xc0/imm32
15177     68/push 0xc0/imm32/size
15178     68/push 0/imm32/top
15179     89/<- %ebx 4/r32/esp
15180     # convert
15181     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
15182     # check result->name
15183     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
15184     (check-strings-equal %eax "foo" "F - test-function-header-with-arg/name")
15185     # var v/edx: (addr var) = result->inouts->value
15186     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
15187     (lookup *eax *(eax+4))  # List-value List-value => eax
15188     89/<- %edx 0/r32/eax
15189     # check v->name
15190     (lookup *edx *(edx+4))  # Var-name Var-name => eax
15191     (check-strings-equal %eax "n" "F - test-function-header-with-arg/inout:0")
15192     # check v->type
15193     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
15194     (check-ints-equal *eax 1 "F - test-function-header-with-arg/inout:0/type:0")  # Type-tree-is-atom
15195     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-arg/inout:0/type:1")  # Type-tree-value
15196     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-arg/inout:0/type:2")  # Type-tree-right
15197     # . epilogue
15198     89/<- %esp 5/r32/ebp
15199     5d/pop-to-ebp
15200     c3/return
15201 
15202 test-function-header-with-multiple-args:
15203     # . prologue
15204     55/push-ebp
15205     89/<- %ebp 4/r32/esp
15206     # setup
15207     8b/-> *Primitive-type-ids 0/r32/eax
15208     89/<- *Type-id 0/r32/eax  # stream-write
15209     c7 0/subop/copy *_Program-functions 0/imm32
15210     c7 0/subop/copy *_Program-functions->payload 0/imm32
15211     c7 0/subop/copy *_Program-types 0/imm32
15212     c7 0/subop/copy *_Program-types->payload 0/imm32
15213     c7 0/subop/copy *_Program-signatures 0/imm32
15214     c7 0/subop/copy *_Program-signatures->payload 0/imm32
15215     (clear-stream _test-input-stream)
15216     (write _test-input-stream "foo a: int, b: int c: int {\n")
15217     # result/ecx: function
15218     2b/subtract *Function-size 4/r32/esp
15219     89/<- %ecx 4/r32/esp
15220     (zero-out %ecx *Function-size)
15221     # var vars/ebx: (stack live-var 16)
15222     81 5/subop/subtract %esp 0xc0/imm32
15223     68/push 0xc0/imm32/size
15224     68/push 0/imm32/top
15225     89/<- %ebx 4/r32/esp
15226     # convert
15227     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
15228     # check result->name
15229     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
15230     (check-strings-equal %eax "foo" "F - test-function-header-with-multiple-args/name")
15231     # var inouts/edx: (addr list var) = lookup(result->inouts)
15232     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
15233     89/<- %edx 0/r32/eax
15234 $test-function-header-with-multiple-args:inout0:
15235     # var v/ebx: (addr var) = lookup(inouts->value)
15236     (lookup *edx *(edx+4))  # List-value List-value => eax
15237     89/<- %ebx 0/r32/eax
15238     # check v->name
15239     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
15240     (check-strings-equal %eax "a" "F - test-function-header-with-multiple-args/inout:0")  # Var-name
15241     # check v->type
15242     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
15243     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:0/type:0")  # Type-tree-is-atom
15244     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:0/type:1")  # Type-tree-value
15245     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:0/type:2")  # Type-tree-right
15246 $test-function-header-with-multiple-args:inout1:
15247     # inouts = lookup(inouts->next)
15248     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
15249     89/<- %edx 0/r32/eax
15250     # v = lookup(inouts->value)
15251     (lookup *edx *(edx+4))  # List-value List-value => eax
15252     89/<- %ebx 0/r32/eax
15253     # check v->name
15254     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
15255     (check-strings-equal %eax "b" "F - test-function-header-with-multiple-args/inout:1")  # Var-name
15256     # check v->type
15257     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
15258     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:1/type:0")  # Type-tree-is-atom
15259     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:1/type:1")  # Type-tree-value
15260     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:1/type:2")  # Type-tree-right
15261 $test-function-header-with-multiple-args:inout2:
15262     # inouts = lookup(inouts->next)
15263     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
15264     89/<- %edx 0/r32/eax
15265     # v = lookup(inouts->value)
15266     (lookup *edx *(edx+4))  # List-value List-value => eax
15267     89/<- %ebx 0/r32/eax
15268     # check v->name
15269     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
15270     (check-strings-equal %eax "c" "F - test-function-header-with-multiple-args/inout:2")  # Var-name
15271     # check v->type
15272     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
15273     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:2/type:0")  # Type-tree-is-atom
15274     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:2/type:1")  # Type-tree-value
15275     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:2/type:2")  # Type-tree-right
15276     # . epilogue
15277     89/<- %esp 5/r32/ebp
15278     5d/pop-to-ebp
15279     c3/return
15280 
15281 test-function-header-with-multiple-args-and-outputs:
15282     # . prologue
15283     55/push-ebp
15284     89/<- %ebp 4/r32/esp
15285     # setup
15286     8b/-> *Primitive-type-ids 0/r32/eax
15287     89/<- *Type-id 0/r32/eax  # stream-write
15288     c7 0/subop/copy *_Program-functions 0/imm32
15289     c7 0/subop/copy *_Program-functions->payload 0/imm32
15290     c7 0/subop/copy *_Program-types 0/imm32
15291     c7 0/subop/copy *_Program-types->payload 0/imm32
15292     c7 0/subop/copy *_Program-signatures 0/imm32
15293     c7 0/subop/copy *_Program-signatures->payload 0/imm32
15294     (clear-stream _test-input-stream)
15295     (write _test-input-stream "foo a: int, b: int, c: int -> _/ecx: int _/edx: int {\n")
15296     # result/ecx: function
15297     2b/subtract *Function-size 4/r32/esp
15298     89/<- %ecx 4/r32/esp
15299     (zero-out %ecx *Function-size)
15300     # var vars/ebx: (stack live-var 16)
15301     81 5/subop/subtract %esp 0xc0/imm32
15302     68/push 0xc0/imm32/size
15303     68/push 0/imm32/top
15304     89/<- %ebx 4/r32/esp
15305     # convert
15306     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
15307     # check result->name
15308     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
15309     (check-strings-equal %eax "foo" "F - test-function-header-with-multiple-args-and-outputs/name")
15310     # var inouts/edx: (addr list var) = lookup(result->inouts)
15311     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
15312     89/<- %edx 0/r32/eax
15313 $test-function-header-with-multiple-args-and-outputs:inout0:
15314     # var v/ebx: (addr var) = lookup(inouts->value)
15315     (lookup *edx *(edx+4))  # List-value List-value => eax
15316     89/<- %ebx 0/r32/eax
15317     # check v->name
15318     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
15319     (check-strings-equal %eax "a" "F - test-function-header-with-multiple-args-and-outputs/inout:0")
15320     # check v->type
15321     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
15322     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:0")  # Type-tree-is-atom
15323     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:1")  # Type-tree-value
15324     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:2")  # Type-tree-right
15325 $test-function-header-with-multiple-args-and-outputs:inout1:
15326     # inouts = lookup(inouts->next)
15327     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
15328     89/<- %edx 0/r32/eax
15329     # v = lookup(inouts->value)
15330     (lookup *edx *(edx+4))  # List-value List-value => eax
15331     89/<- %ebx 0/r32/eax
15332     # check v->name
15333     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
15334     (check-strings-equal %eax "b" "F - test-function-header-with-multiple-args-and-outputs/inout:1")
15335     # check v->type
15336     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
15337     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:0")  # Type-tree-is-atom
15338     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:1")  # Type-tree-value
15339     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:2")  # Type-tree-right
15340 $test-function-header-with-multiple-args-and-outputs:inout2:
15341     # inouts = lookup(inouts->next)
15342     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
15343     89/<- %edx 0/r32/eax
15344     # v = lookup(inouts->value)
15345     (lookup *edx *(edx+4))  # List-value List-value => eax
15346     89/<- %ebx 0/r32/eax
15347     # check v->name
15348     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
15349     (check-strings-equal %eax "c" "F - test-function-header-with-multiple-args-and-outputs/inout:2")
15350     # check v->type
15351     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
15352     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:0")  # Type-tree-is-atom
15353     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:1")  # Type-tree-value
15354     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:2")  # Type-tree-right
15355 $test-function-header-with-multiple-args-and-outputs:out0:
15356     # var outputs/edx: (addr list var) = lookup(result->outputs)
15357     (lookup *(ecx+0x10) *(ecx+0x14))  # Function-outputs Function-outputs => eax
15358     89/<- %edx 0/r32/eax
15359     # v = lookup(outputs->value)
15360     (lookup *edx *(edx+4))  # List-value List-value => eax
15361     89/<- %ebx 0/r32/eax
15362     # check v->name
15363     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
15364     (check-strings-equal %eax "_" "F - test-function-header-with-multiple-args-and-outputs/output:0")
15365     # check v->register
15366     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
15367     (check-strings-equal %eax "ecx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register")
15368     # check v->type
15369     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
15370     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:0")  # Type-tree-is-atom
15371     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1")  # Type-tree-value
15372     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:2")  # Type-tree-right
15373 $test-function-header-with-multiple-args-and-outputs:out1:
15374     # outputs = lookup(outputs->next)
15375     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
15376     89/<- %edx 0/r32/eax
15377     # v = lookup(inouts->value)
15378     (lookup *edx *(edx+4))  # List-value List-value => eax
15379     89/<- %ebx 0/r32/eax
15380     # check v->name
15381     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
15382     (check-strings-equal %eax "_" "F - test-function-header-with-multiple-args-and-outputs/output:1")
15383     # check v->register
15384     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
15385     (check-strings-equal %eax "edx" "F - test-function-header-with-multiple-args-and-outputs/output:1/register")
15386     # check v->type
15387     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
15388     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:0")  # Type-tree-is-atom
15389     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1")  # Type-tree-value
15390     (check-ints-equal *(eax+0c) 0 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:2")  # Type-tree-right
15391     # . epilogue
15392     89/<- %esp 5/r32/ebp
15393     5d/pop-to-ebp
15394     c3/return
15395 
15396 # format for variables with types
15397 #   x: int
15398 #   x: int,
15399 #   x/eax: int
15400 #   x/eax: int,
15401 # ignores at most one trailing comma
15402 # WARNING: modifies name
15403 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)
15404     # pseudocode:
15405     #   var s: slice
15406     #   if (!slice-ends-with(name, ":"))
15407     #     abort
15408     #   --name->end to skip ':'
15409     #   next-token-from-slice(name->start, name->end, '/', s)
15410     #   new-var-from-slice(s, out)
15411     #   ## register
15412     #   next-token-from-slice(s->end, name->end, '/', s)
15413     #   if (!slice-empty?(s))
15414     #     out->register = slice-to-string(s)
15415     #   ## type
15416     #   var type: (handle type-tree) = parse-type(first-line)
15417     #   out->type = type
15418     #
15419     # . prologue
15420     55/push-ebp
15421     89/<- %ebp 4/r32/esp
15422     # . save registers
15423     50/push-eax
15424     51/push-ecx
15425     52/push-edx
15426     53/push-ebx
15427     56/push-esi
15428     57/push-edi
15429     # esi = name
15430     8b/-> *(ebp+8) 6/r32/esi
15431     # if (!slice-ends-with?(name, ":")) abort
15432     8b/-> *(esi+4) 1/r32/ecx  # Slice-end
15433     49/decrement-ecx
15434     8a/copy-byte *ecx 1/r32/CL
15435     81 4/subop/and %ecx 0xff/imm32
15436     81 7/subop/compare %ecx 0x3a/imm32/colon
15437     0f 85/jump-if-!= $parse-var-with-type:abort/disp32
15438     # --name->end to skip ':'
15439     ff 1/subop/decrement *(esi+4)
15440     # var s/ecx: slice
15441     68/push 0/imm32/end
15442     68/push 0/imm32/start
15443     89/<- %ecx 4/r32/esp
15444 $parse-var-with-type:parse-name:
15445     (next-token-from-slice *esi *(esi+4) 0x2f %ecx)  # Slice-start, Slice-end, '/'
15446 $parse-var-with-type:create-var:
15447     # new-var-from-slice(s, out)
15448     (new-var-from-slice Heap %ecx *(ebp+0x10))
15449     # save out->register
15450 $parse-var-with-type:save-register:
15451     # . var out-addr/edi: (addr var) = lookup(*out)
15452     8b/-> *(ebp+0x10) 7/r32/edi
15453     (lookup *edi *(edi+4))  # => eax
15454     89/<- %edi 0/r32/eax
15455     # . s = next-token(...)
15456     (next-token-from-slice *(ecx+4) *(esi+4) 0x2f %ecx)  # s->end, name->end, '/'
15457     # . if (!slice-empty?(s)) out->register = slice-to-string(s)
15458     {
15459 $parse-var-with-type:write-register:
15460       (slice-empty? %ecx)  # => eax
15461       3d/compare-eax-and 0/imm32/false
15462       75/jump-if-!= break/disp8
15463       # out->register = slice-to-string(s)
15464       8d/copy-address *(edi+0x18) 0/r32/eax  # Var-register
15465       (slice-to-string Heap %ecx %eax)
15466     }
15467 $parse-var-with-type:save-type:
15468     8d/copy-address *(edi+8) 0/r32/eax  # Var-type
15469     (parse-type Heap *(ebp+0xc) %eax *(ebp+0x18) *(ebp+0x1c))
15470 $parse-var-with-type:check-register:
15471     (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
15472     3d/compare-eax-and 0/imm32
15473     74/jump-if-= $parse-var-with-type:end/disp8
15474     (is-float-register? %eax)  # => eax
15475     {
15476       3d/compare-eax-and 0/imm32/false
15477       74/jump-if-= break/disp8
15478       # var is in a float register; ensure type is float
15479       (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
15480       (is-simple-mu-type? %eax 0xf)  # float => eax
15481       3d/compare-eax-and 0/imm32/false
15482       0f 84/jump-if-= $parse-var-with-type:error-non-float-in-floating-point-register/disp32
15483       eb/jump $parse-var-with-type:end/disp8
15484     }
15485     # var is not in a float register; ensure type is not float
15486     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
15487     (is-simple-mu-type? %eax 0xf)  # float => eax
15488     3d/compare-eax-and 0/imm32/false
15489     0f 85/jump-if-!= $parse-var-with-type:error-float-in-integer-register/disp32
15490 $parse-var-with-type:end:
15491     # . reclaim locals
15492     81 0/subop/add %esp 8/imm32
15493     # . restore registers
15494     5f/pop-to-edi
15495     5e/pop-to-esi
15496     5b/pop-to-ebx
15497     5a/pop-to-edx
15498     59/pop-to-ecx
15499     58/pop-to-eax
15500     # . epilogue
15501     89/<- %esp 5/r32/ebp
15502     5d/pop-to-ebp
15503     c3/return
15504 
15505 $parse-var-with-type:abort:
15506     # error("fn " fn ": var should have form 'name: type' in '" line "'\n")
15507     (write-buffered *(ebp+0x18) "fn ")
15508     (write-buffered *(ebp+0x18) *(ebp+0x14))
15509     (write-buffered *(ebp+0x18) ": var should have form 'name: type' in '")
15510     (flush *(ebp+0x18))
15511     (rewind-stream *(ebp+0xc))
15512     (write-stream-data *(ebp+0x18) *(ebp+0xc))
15513     (write-buffered *(ebp+0x18) "'\n")
15514     (flush *(ebp+0x18))
15515     (stop *(ebp+0x1c) 1)
15516     # never gets here
15517 
15518 $parse-var-with-type:error-float-in-integer-register:
15519     # error("fn " fn ": float var '" var "' should be in a floating-point register\n")
15520     (write-buffered *(ebp+0x18) "fn ")
15521     (write-buffered *(ebp+0x18) *(ebp+0x14))
15522     (write-buffered *(ebp+0x18) ": float var '")
15523     (lookup *edi *(edi+4))  # Var-name Var-name => eax
15524     (write-buffered *(ebp+0x18) %eax)
15525     (write-buffered *(ebp+0x18) "' should be in a floating-point register\n")
15526     (flush *(ebp+0x18))
15527     (stop *(ebp+0x1c) 1)
15528     # never gets here
15529 
15530 $parse-var-with-type:error-non-float-in-floating-point-register:
15531     # error("fn " fn ": non-float var '" var "' should be in an integer register\n")
15532     (write-buffered *(ebp+0x18) "fn ")
15533     (write-buffered *(ebp+0x18) *(ebp+0x14))
15534     (write-buffered *(ebp+0x18) ": non-float var '")
15535     (lookup *edi *(edi+4))  # Var-name Var-name => eax
15536     (write-buffered *(ebp+0x18) %eax)
15537     (write-buffered *(ebp+0x18) "' should be in an integer register\n")
15538     (flush *(ebp+0x18))
15539     (stop *(ebp+0x1c) 1)
15540     # never gets here
15541 
15542 is-float-register?:  # r: (addr array byte) -> result/eax: boolean
15543     # . prologue
15544     55/push-ebp
15545     89/<- %ebp 4/r32/esp
15546     #
15547     (get Mu-registers-unique *(ebp+8) 0xc "Mu-registers-unique")  # => eax
15548     81 7/subop/compare *eax 8/imm32/start-of-floating-point-registers
15549     0f 9d/set-if->= %al
15550     81 4/subop/and %eax 0xff/imm32
15551 $is-float-register?:end:
15552     # . epilogue
15553     89/<- %esp 5/r32/ebp
15554     5d/pop-to-ebp
15555     c3/return
15556 
15557 parse-type:  # ad: (addr allocation-descriptor), in: (addr stream byte), out: (addr handle type-tree), err: (addr buffered-file), ed: (addr exit-descriptor)
15558     # pseudocode:
15559     #   var s: slice = next-mu-token(in)
15560     #   assert s != ""
15561     #   assert s != "->"
15562     #   assert s != "{"
15563     #   assert s != "}"
15564     #   if s == ")"
15565     #     return
15566     #   out = allocate(Type-tree)
15567     #   if s != "("
15568     #     HACK: if s is an int, parse and return it
15569     #     out->is-atom? = true
15570     #     if (s[0] == "_")
15571     #       out->value = type-parameter
15572     #       out->parameter-name = slice-to-string(ad, s)
15573     #     else
15574     #       out->value = pos-or-insert-slice(Type-id, s)
15575     #     return
15576     #   out->left = parse-type(ad, in)
15577     #   out->right = parse-type-tree(ad, in)
15578     #
15579     # . prologue
15580     55/push-ebp
15581     89/<- %ebp 4/r32/esp
15582     # . save registers
15583     50/push-eax
15584     51/push-ecx
15585     52/push-edx
15586     # clear out
15587     (zero-out *(ebp+0x10) *Handle-size)
15588     # var s/ecx: slice
15589     68/push 0/imm32
15590     68/push 0/imm32
15591     89/<- %ecx 4/r32/esp
15592     # s = next-mu-token(in)
15593     (next-mu-token *(ebp+0xc) %ecx)
15594 #?     (write-buffered Stderr "tok: ")
15595 #?     (write-slice-buffered Stderr %ecx)
15596 #?     (write-buffered Stderr "$\n")
15597 #?     (flush Stderr)
15598     # assert s != ""
15599     (slice-equal? %ecx "")  # => eax
15600     3d/compare-eax-and 0/imm32/false
15601     0f 85/jump-if-!= $parse-type:abort/disp32
15602     # assert s != "{"
15603     (slice-equal? %ecx "{")  # => eax
15604     3d/compare-eax-and 0/imm32/false
15605     0f 85/jump-if-!= $parse-type:abort/disp32
15606     # assert s != "}"
15607     (slice-equal? %ecx "}")  # => eax
15608     3d/compare-eax-and 0/imm32/false
15609     0f 85/jump-if-!= $parse-type:abort/disp32
15610     # assert s != "->"
15611     (slice-equal? %ecx "->")  # => eax
15612     3d/compare-eax-and 0/imm32/false
15613     0f 85/jump-if-!= $parse-type:abort/disp32
15614     # if (s == ")") return
15615     (slice-equal? %ecx ")")  # => eax
15616     3d/compare-eax-and 0/imm32/false
15617     0f 85/jump-if-!= $parse-type:end/disp32
15618     # out = new tree
15619     (allocate *(ebp+8) *Type-tree-size *(ebp+0x10))
15620     # var out-addr/edx: (addr type-tree) = lookup(*out)
15621     8b/-> *(ebp+0x10) 2/r32/edx
15622     (lookup *edx *(edx+4))  # => eax
15623     89/<- %edx 0/r32/eax
15624     {
15625       # if (s != "(") break
15626       (slice-equal? %ecx "(")  # => eax
15627       3d/compare-eax-and 0/imm32/false
15628       0f 85/jump-if-!= break/disp32
15629       # if s is a number, store it in the type's size field
15630       {
15631 $parse-type:check-for-int:
15632         # var tmp/eax: byte = *s->slice
15633         8b/-> *ecx 0/r32/eax
15634         8a/copy-byte *eax 0/r32/AL
15635         81 4/subop/and %eax 0xff/imm32
15636         # TODO: raise an error on `var x: (array int a)`
15637         (is-decimal-digit? %eax)  # => eax
15638         3d/compare-eax-and 0/imm32/false
15639         74/jump-if-= break/disp8
15640         #
15641         (is-hex-int? %ecx)  # => eax
15642         3d/compare-eax-and 0/imm32/false
15643         74/jump-if-= break/disp8
15644 $parse-type:int:
15645         (check-mu-hex-int %ecx *(ebp+0x14) *(ebp+0x18))
15646         (parse-hex-int-from-slice %ecx)  # => eax
15647         c7 0/subop/copy *(edx+4) 9/imm32/type-id-array-capacity  # Type-tree-value
15648         89/<- *(edx+8) 0/r32/eax  # Type-tree-value-size
15649         e9/jump $parse-type:end/disp32
15650       }
15651 $parse-type:atom:
15652       # out->is-atom? = true
15653       c7 0/subop/copy *edx 1/imm32/true  # Type-tree-is-atom
15654       {
15655 $parse-type:check-for-type-parameter:
15656         # var tmp/eax: byte = *s->slice
15657         8b/-> *ecx 0/r32/eax
15658         8a/copy-byte *eax 0/r32/AL
15659         81 4/subop/and %eax 0xff/imm32
15660         # if (tmp != '_') break
15661         3d/compare-eax-and 0x5f/imm32/_
15662         75/jump-if-!= break/disp8
15663 $parse-type:type-parameter:
15664         # out->value = type-parameter
15665         c7 0/subop/copy *(edx+4) 0xa/imm32/type-parameter  # Type-tree-value
15666         # out->parameter-name = slice-to-string(ad, s)
15667         8d/copy-address *(edx+8) 0/r32/eax  # Type-tree-parameter-name
15668         (slice-to-string *(ebp+8) %ecx %eax)
15669         e9/jump $parse-type:end/disp32
15670       }
15671 $parse-type:non-type-parameter:
15672       # out->value = pos-or-insert-slice(Type-id, s)
15673       (pos-or-insert-slice Type-id %ecx)  # => eax
15674       89/<- *(edx+4) 0/r32/eax  # Type-tree-value
15675       e9/jump $parse-type:end/disp32
15676     }
15677 $parse-type:non-atom:
15678     # otherwise s == "("
15679     # out->left = parse-type(ad, in)
15680     8d/copy-address *(edx+4) 0/r32/eax  # Type-tree-left
15681     (parse-type *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
15682     # out->right = parse-type-tree(ad, in)
15683     8d/copy-address *(edx+0xc) 0/r32/eax  # Type-tree-right
15684     (parse-type-tree *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
15685 $parse-type:end:
15686     # . reclaim locals
15687     81 0/subop/add %esp 8/imm32
15688     # . restore registers
15689     5a/pop-to-edx
15690     59/pop-to-ecx
15691     58/pop-to-eax
15692     # . epilogue
15693     89/<- %esp 5/r32/ebp
15694     5d/pop-to-ebp
15695     c3/return
15696 
15697 $parse-type:abort:
15698     # error("unexpected token when parsing type: '" s "'\n")
15699     (write-buffered *(ebp+0x14) "unexpected token when parsing type: '")
15700     (write-slice-buffered *(ebp+0x14) %ecx)
15701     (write-buffered *(ebp+0x14) "'\n")
15702     (flush *(ebp+0x14))
15703     (stop *(ebp+0x18) 1)
15704     # never gets here
15705 
15706 parse-type-tree:  # ad: (addr allocation-descriptor), in: (addr stream byte), out: (addr handle type-tree), err: (addr buffered-file), ed: (addr exit-descriptor)
15707     # pseudocode:
15708     #   var tmp: (handle type-tree) = parse-type(ad, in)
15709     #   if tmp == 0
15710     #     return 0
15711     #   out = allocate(Type-tree)
15712     #   out->left = tmp
15713     #   out->right = parse-type-tree(ad, in)
15714     #
15715     # . prologue
15716     55/push-ebp
15717     89/<- %ebp 4/r32/esp
15718     # . save registers
15719     50/push-eax
15720     51/push-ecx
15721     52/push-edx
15722     #
15723     (zero-out *(ebp+0x10) *Handle-size)
15724     # var tmp/ecx: (handle type-tree)
15725     68/push 0/imm32
15726     68/push 0/imm32
15727     89/<- %ecx 4/r32/esp
15728     # tmp = parse-type(ad, in)
15729     (parse-type *(ebp+8) *(ebp+0xc) %ecx *(ebp+0x14) *(ebp+0x18))
15730     # if (tmp == 0) return
15731     81 7/subop/compare *ecx 0/imm32
15732     74/jump-if-= $parse-type-tree:end/disp8
15733     # out = new tree
15734     (allocate *(ebp+8) *Type-tree-size *(ebp+0x10))
15735     # var out-addr/edx: (addr tree) = lookup(*out)
15736     8b/-> *(ebp+0x10) 2/r32/edx
15737     (lookup *edx *(edx+4))  # => eax
15738     89/<- %edx 0/r32/eax
15739     # out->left = tmp
15740     8b/-> *ecx 0/r32/eax
15741     89/<- *(edx+4) 0/r32/eax  # Type-tree-left
15742     8b/-> *(ecx+4) 0/r32/eax
15743     89/<- *(edx+8) 0/r32/eax  # Type-tree-left
15744     # out->right = parse-type-tree(ad, in)
15745     8d/copy-address *(edx+0xc) 0/r32/eax  # Type-tree-right
15746     (parse-type-tree *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
15747 $parse-type-tree:end:
15748     # . reclaim locals
15749     81 0/subop/add %esp 8/imm32
15750     # . restore registers
15751     5a/pop-to-edx
15752     59/pop-to-ecx
15753     58/pop-to-eax
15754     # . epilogue
15755     89/<- %esp 5/r32/ebp
15756     5d/pop-to-ebp
15757     c3/return
15758 
15759 next-mu-token:  # in: (addr stream byte), out: (addr slice)
15760     # pseudocode:
15761     # start:
15762     #   skip-chars-matching-whitespace(in)
15763     #   if in->read >= in->write              # end of in
15764     #     out = {0, 0}
15765     #     return
15766     #   out->start = &in->data[in->read]
15767     #   var curr-byte/eax: byte = in->data[in->read]
15768     #   if curr->byte == ','                  # comment token
15769     #     ++in->read
15770     #     goto start
15771     #   if curr-byte == '#'                   # comment
15772     #     goto done                             # treat as eof
15773     #   if curr-byte == '"'                   # string literal
15774     #     skip-string(in)
15775     #     goto done                           # no metadata
15776     #   if curr-byte == '('
15777     #     ++in->read
15778     #     goto done
15779     #   if curr-byte == ')'
15780     #     ++in->read
15781     #     goto done
15782     #   # read a word
15783     #   while true
15784     #     if in->read >= in->write
15785     #       break
15786     #     curr-byte = in->data[in->read]
15787     #     if curr-byte == ' '
15788     #       break
15789     #     if curr-byte == '\r'
15790     #       break
15791     #     if curr-byte == '\n'
15792     #       break
15793     #     if curr-byte == '('
15794     #       break
15795     #     if curr-byte == ')'
15796     #       break
15797     #     if curr-byte == ','
15798     #       break
15799     #     ++in->read
15800     # done:
15801     #   out->end = &in->data[in->read]
15802     #
15803     # . prologue
15804     55/push-ebp
15805     89/<- %ebp 4/r32/esp
15806     # . save registers
15807     50/push-eax
15808     51/push-ecx
15809     56/push-esi
15810     57/push-edi
15811     # esi = in
15812     8b/-> *(ebp+8) 6/r32/esi
15813     # edi = out
15814     8b/-> *(ebp+0xc) 7/r32/edi
15815 $next-mu-token:start:
15816     (skip-chars-matching-whitespace %esi)
15817 $next-mu-token:check0:
15818     # if (in->read >= in->write) return out = {0, 0}
15819     # . ecx = in->read
15820     8b/-> *(esi+4) 1/r32/ecx
15821     # . if (ecx >= in->write) return out = {0, 0}
15822     3b/compare<- *esi 1/r32/ecx
15823     c7 0/subop/copy *edi 0/imm32
15824     c7 0/subop/copy *(edi+4) 0/imm32
15825     0f 8d/jump-if->= $next-mu-token:end/disp32
15826     # out->start = &in->data[in->read]
15827     8d/copy-address *(esi+ecx+0xc) 0/r32/eax
15828     89/<- *edi 0/r32/eax
15829     # var curr-byte/eax: byte = in->data[in->read]
15830     31/xor-with %eax 0/r32/eax
15831     8a/copy-byte *(esi+ecx+0xc) 0/r32/AL
15832     {
15833 $next-mu-token:check-for-comma:
15834       # if (curr-byte != ',') break
15835       3d/compare-eax-and 0x2c/imm32/comma
15836       75/jump-if-!= break/disp8
15837       # ++in->read
15838       ff 0/subop/increment *(esi+4)
15839       # restart
15840       e9/jump $next-mu-token:start/disp32
15841     }
15842     {
15843 $next-mu-token:check-for-comment:
15844       # if (curr-byte != '#') break
15845       3d/compare-eax-and 0x23/imm32/pound
15846       75/jump-if-!= break/disp8
15847       # return eof
15848       e9/jump $next-mu-token:done/disp32
15849     }
15850     {
15851 $next-mu-token:check-for-string-literal:
15852       # if (curr-byte != '"') break
15853       3d/compare-eax-and 0x22/imm32/dquote
15854       75/jump-if-!= break/disp8
15855       (skip-string %esi)
15856       # return
15857       e9/jump $next-mu-token:done/disp32
15858     }
15859     {
15860 $next-mu-token:check-for-open-paren:
15861       # if (curr-byte != '(') break
15862       3d/compare-eax-and 0x28/imm32/open-paren
15863       75/jump-if-!= break/disp8
15864       # ++in->read
15865       ff 0/subop/increment *(esi+4)
15866       # return
15867       e9/jump $next-mu-token:done/disp32
15868     }
15869     {
15870 $next-mu-token:check-for-close-paren:
15871       # if (curr-byte != ')') break
15872       3d/compare-eax-and 0x29/imm32/close-paren
15873       75/jump-if-!= break/disp8
15874       # ++in->read
15875       ff 0/subop/increment *(esi+4)
15876       # return
15877       e9/jump $next-mu-token:done/disp32
15878     }
15879     {
15880 $next-mu-token:regular-word-without-metadata:
15881       # if (in->read >= in->write) break
15882       # . ecx = in->read
15883       8b/-> *(esi+4) 1/r32/ecx
15884       # . if (ecx >= in->write) break
15885       3b/compare<- *esi 1/r32/ecx
15886       7d/jump-if->= break/disp8
15887       # var c/eax: byte = in->data[in->read]
15888       31/xor-with %eax 0/r32/eax
15889       8a/copy-byte *(esi+ecx+0xc) 0/r32/AL
15890       # if (c == ' ') break
15891       3d/compare-eax-and 0x20/imm32/space
15892       74/jump-if-= break/disp8
15893       # if (c == '\r') break
15894       3d/compare-eax-and 0xd/imm32/carriage-return
15895       74/jump-if-= break/disp8
15896       # if (c == '\n') break
15897       3d/compare-eax-and 0xa/imm32/newline
15898       74/jump-if-= break/disp8
15899       # if (c == '(') break
15900       3d/compare-eax-and 0x28/imm32/open-paren
15901       0f 84/jump-if-= break/disp32
15902       # if (c == ')') break
15903       3d/compare-eax-and 0x29/imm32/close-paren
15904       0f 84/jump-if-= break/disp32
15905       # if (c == ',') break
15906       3d/compare-eax-and 0x2c/imm32/comma
15907       0f 84/jump-if-= break/disp32
15908       # ++in->read
15909       ff 0/subop/increment *(esi+4)
15910       #
15911       e9/jump loop/disp32
15912     }
15913 $next-mu-token:done:
15914     # out->end = &in->data[in->read]
15915     8b/-> *(esi+4) 1/r32/ecx
15916     8d/copy-address *(esi+ecx+0xc) 0/r32/eax
15917     89/<- *(edi+4) 0/r32/eax
15918 $next-mu-token:end:
15919     # . restore registers
15920     5f/pop-to-edi
15921     5e/pop-to-esi
15922     59/pop-to-ecx
15923     58/pop-to-eax
15924     # . epilogue
15925     89/<- %esp 5/r32/ebp
15926     5d/pop-to-ebp
15927     c3/return
15928 
15929 pos-or-insert-slice:  # arr: (addr stream (addr array byte)), s: (addr slice) -> index/eax: int
15930     # . prologue
15931     55/push-ebp
15932     89/<- %ebp 4/r32/esp
15933     # if (pos-slice(arr, s) != -1) return it
15934     (pos-slice *(ebp+8) *(ebp+0xc))  # => eax
15935     3d/compare-eax-and -1/imm32
15936     75/jump-if-!= $pos-or-insert-slice:end/disp8
15937 $pos-or-insert-slice:insert:
15938     # var s2/eax: (handle array byte)
15939     68/push 0/imm32
15940     68/push 0/imm32
15941     89/<- %eax 4/r32/esp
15942     (slice-to-string Heap *(ebp+0xc) %eax)
15943     # throw away alloc-id
15944     (lookup *eax *(eax+4))  # => eax
15945     (write-int *(ebp+8) %eax)
15946     (pos-slice *(ebp+8) *(ebp+0xc))  # => eax
15947 $pos-or-insert-slice:end:
15948     # . reclaim locals
15949     81 0/subop/add %esp 8/imm32
15950     # . epilogue
15951     89/<- %esp 5/r32/ebp
15952     5d/pop-to-ebp
15953     c3/return
15954 
15955 # return the index in an array of strings matching 's', -1 if not found
15956 # index is denominated in elements, not bytes
15957 pos-slice:  # arr: (addr stream (addr array byte)), s: (addr slice) -> index/eax: int
15958     # . prologue
15959     55/push-ebp
15960     89/<- %ebp 4/r32/esp
15961     # . save registers
15962     51/push-ecx
15963     52/push-edx
15964     53/push-ebx
15965     56/push-esi
15966 #?     (write-buffered Stderr "pos-slice: ")
15967 #?     (write-slice-buffered Stderr *(ebp+0xc))
15968 #?     (write-buffered Stderr "\n")
15969 #?     (flush Stderr)
15970     # esi = arr
15971     8b/-> *(ebp+8) 6/r32/esi
15972     # var index/ecx: int = 0
15973     b9/copy-to-ecx 0/imm32
15974     # var curr/edx: (addr (addr array byte)) = arr->data
15975     8d/copy-address *(esi+0xc) 2/r32/edx
15976     # var max/ebx: (addr (addr array byte)) = &arr->data[arr->write]
15977     8b/-> *esi 3/r32/ebx
15978     8d/copy-address *(esi+ebx+0xc) 3/r32/ebx
15979     {
15980 #?       (write-buffered Stderr "  ")
15981 #?       (write-int32-hex-buffered Stderr %ecx)
15982 #?       (write-buffered Stderr "\n")
15983 #?       (flush Stderr)
15984       # if (curr >= max) return -1
15985       39/compare %edx 3/r32/ebx
15986       b8/copy-to-eax -1/imm32
15987       73/jump-if-addr>= $pos-slice:end/disp8
15988       # if (slice-equal?(s, *curr)) break
15989       (slice-equal? *(ebp+0xc) *edx)  # => eax
15990       3d/compare-eax-and 0/imm32/false
15991       75/jump-if-!= break/disp8
15992       # ++index
15993       41/increment-ecx
15994       # curr += 4
15995       81 0/subop/add %edx 4/imm32
15996       #
15997       eb/jump loop/disp8
15998     }
15999     # return index
16000     89/<- %eax 1/r32/ecx
16001 $pos-slice:end:
16002 #?     (write-buffered Stderr "=> ")
16003 #?     (write-int32-hex-buffered Stderr %eax)
16004 #?     (write-buffered Stderr "\n")
16005     # . restore registers
16006     5e/pop-to-esi
16007     5b/pop-to-ebx
16008     5a/pop-to-edx
16009     59/pop-to-ecx
16010     # . epilogue
16011     89/<- %esp 5/r32/ebp
16012     5d/pop-to-ebp
16013     c3/return
16014 
16015 test-parse-var-with-type:
16016     # . prologue
16017     55/push-ebp
16018     89/<- %ebp 4/r32/esp
16019     # setup
16020     8b/-> *Primitive-type-ids 0/r32/eax
16021     89/<- *Type-id 0/r32/eax  # stream-write
16022     # (eax..ecx) = "x:"
16023     b8/copy-to-eax "x:"/imm32
16024     8b/-> *eax 1/r32/ecx
16025     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16026     05/add-to-eax 4/imm32
16027     # var slice/ecx: slice = {eax, ecx}
16028     51/push-ecx
16029     50/push-eax
16030     89/<- %ecx 4/r32/esp
16031     # _test-input-stream contains "int"
16032     (clear-stream _test-input-stream)
16033     (write _test-input-stream "int")
16034     # var v/edx: (handle var)
16035     68/push 0/imm32
16036     68/push 0/imm32
16037     89/<- %edx 4/r32/esp
16038     #
16039     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
16040     # var v-addr/edx: (addr var) = lookup(v)
16041     (lookup *edx *(edx+4))  # => eax
16042     89/<- %edx 0/r32/eax
16043     # check v-addr->name
16044     (lookup *edx *(edx+4))  # Var-name Var-name => eax
16045     (check-strings-equal %eax "x" "F - test-parse-var-with-type/name")
16046     # check v-addr->type
16047     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
16048     (check-ints-equal *eax 1 "F - test-parse-var-with-type/type:0")  # Type-tree-is-atom
16049     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-type/type:1")  # Type-tree-value
16050     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-type/type:2")  # Type-tree-right
16051     # . epilogue
16052     89/<- %esp 5/r32/ebp
16053     5d/pop-to-ebp
16054     c3/return
16055 
16056 test-parse-var-with-type-and-register:
16057     # . prologue
16058     55/push-ebp
16059     89/<- %ebp 4/r32/esp
16060     # setup
16061     8b/-> *Primitive-type-ids 0/r32/eax
16062     89/<- *Type-id 0/r32/eax  # stream-write
16063     # (eax..ecx) = "x/eax:"
16064     b8/copy-to-eax "x/eax:"/imm32
16065     8b/-> *eax 1/r32/ecx
16066     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16067     05/add-to-eax 4/imm32
16068     # var slice/ecx: slice = {eax, ecx}
16069     51/push-ecx
16070     50/push-eax
16071     89/<- %ecx 4/r32/esp
16072     # _test-input-stream contains "int"
16073     (clear-stream _test-input-stream)
16074     (write _test-input-stream "int")
16075     # var v/edx: (handle var)
16076     68/push 0/imm32
16077     68/push 0/imm32
16078     89/<- %edx 4/r32/esp
16079     #
16080     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
16081     # var v-addr/edx: (addr var) = lookup(v)
16082     (lookup *edx *(edx+4))  # => eax
16083     89/<- %edx 0/r32/eax
16084     # check v-addr->name
16085     (lookup *edx *(edx+4))  # Var-name Var-name => eax
16086     (check-strings-equal %eax "x" "F - test-parse-var-with-type-and-register/name")
16087     # check v-addr->register
16088     (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
16089     (check-strings-equal %eax "eax" "F - test-parse-var-with-type-and-register/register")
16090     # check v-addr->type
16091     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
16092     (check-ints-equal *eax 1 "F - test-parse-var-with-type-and-register/type:0")  # Type-tree-is-atom
16093     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-type-and-register/type:1")  # Type-tree-left
16094     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-type-and-register/type:2")  # Type-tree-right
16095     # . epilogue
16096     89/<- %esp 5/r32/ebp
16097     5d/pop-to-ebp
16098     c3/return
16099 
16100 test-parse-var-with-trailing-characters:
16101     # . prologue
16102     55/push-ebp
16103     89/<- %ebp 4/r32/esp
16104     # setup
16105     8b/-> *Primitive-type-ids 0/r32/eax
16106     89/<- *Type-id 0/r32/eax  # stream-write
16107     # (eax..ecx) = "x:"
16108     b8/copy-to-eax "x:"/imm32
16109     8b/-> *eax 1/r32/ecx
16110     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16111     05/add-to-eax 4/imm32
16112     # var slice/ecx: slice = {eax, ecx}
16113     51/push-ecx
16114     50/push-eax
16115     89/<- %ecx 4/r32/esp
16116     # _test-input-stream contains "int,"
16117     (clear-stream _test-input-stream)
16118     (write _test-input-stream "int,")
16119     # var v/edx: (handle var)
16120     68/push 0/imm32
16121     68/push 0/imm32
16122     89/<- %edx 4/r32/esp
16123     #
16124     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
16125     # var v-addr/edx: (addr var) = lookup(v)
16126     (lookup *edx *(edx+4))  # => eax
16127     89/<- %edx 0/r32/eax
16128     # check v-addr->name
16129     (lookup *edx *(edx+4))  # Var-name Var-name => eax
16130     (check-strings-equal %eax "x" "F - test-parse-var-with-trailing-characters/name")
16131     # check v-addr->register
16132     (check-ints-equal *(edx+0x18) 0 "F - test-parse-var-with-trailing-characters/register")  # Var-register
16133     # check v-addr->type
16134     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
16135     (check-ints-equal *eax 1 "F - test-parse-var-with-trailing-characters/type:0")  # Type-tree-is-atom
16136     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-trailing-characters/type:1")  # Type-tree-left
16137     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-trailing-characters/type:1")  # Type-tree-right
16138     # . epilogue
16139     89/<- %esp 5/r32/ebp
16140     5d/pop-to-ebp
16141     c3/return
16142 
16143 test-parse-var-with-register-and-trailing-characters:
16144     # . prologue
16145     55/push-ebp
16146     89/<- %ebp 4/r32/esp
16147     # setup
16148     8b/-> *Primitive-type-ids 0/r32/eax
16149     89/<- *Type-id 0/r32/eax  # stream-write
16150     # (eax..ecx) = "x/eax:"
16151     b8/copy-to-eax "x/eax:"/imm32
16152     8b/-> *eax 1/r32/ecx
16153     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16154     05/add-to-eax 4/imm32
16155     # var slice/ecx: slice = {eax, ecx}
16156     51/push-ecx
16157     50/push-eax
16158     89/<- %ecx 4/r32/esp
16159     # _test-input-stream contains "int,"
16160     (clear-stream _test-input-stream)
16161     (write _test-input-stream "int,")
16162     # var v/edx: (handle var)
16163     68/push 0/imm32
16164     68/push 0/imm32
16165     89/<- %edx 4/r32/esp
16166     #
16167     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
16168     # var v-addr/edx: (addr var) = lookup(v)
16169     (lookup *edx *(edx+4))  # => eax
16170     89/<- %edx 0/r32/eax
16171     # check v-addr->name
16172     (lookup *edx *(edx+4))  # Var-name Var-name => eax
16173     (check-strings-equal %eax "x" "F - test-parse-var-with-register-and-trailing-characters/name")
16174     # check v-addr->register
16175     (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
16176     (check-strings-equal %eax "eax" "F - test-parse-var-with-register-and-trailing-characters/register")
16177     # check v-addr->type
16178     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
16179     (check-ints-equal *eax 1 "F - test-parse-var-with-register-and-trailing-characters/type:0")  # Type-tree-is-atom
16180     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-register-and-trailing-characters/type:1")  # Type-tree-left
16181     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-register-and-trailing-characters/type:2")  # Type-tree-right
16182     # . epilogue
16183     89/<- %esp 5/r32/ebp
16184     5d/pop-to-ebp
16185     c3/return
16186 
16187 test-parse-var-with-compound-type:
16188     # . prologue
16189     55/push-ebp
16190     89/<- %ebp 4/r32/esp
16191     # setup
16192     8b/-> *Primitive-type-ids 0/r32/eax
16193     89/<- *Type-id 0/r32/eax  # stream-write
16194     # (eax..ecx) = "x:"
16195     b8/copy-to-eax "x:"/imm32
16196     8b/-> *eax 1/r32/ecx
16197     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16198     05/add-to-eax 4/imm32
16199     # var slice/ecx: slice = {eax, ecx}
16200     51/push-ecx
16201     50/push-eax
16202     89/<- %ecx 4/r32/esp
16203     # _test-input-stream contains "(addr int)"
16204     (clear-stream _test-input-stream)
16205     (write _test-input-stream "(addr int)")
16206     # var v/edx: (handle var)
16207     68/push 0/imm32
16208     68/push 0/imm32
16209     89/<- %edx 4/r32/esp
16210     #
16211     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
16212     # var v-addr/edx: (addr var) = lookup(v)
16213     (lookup *edx *(edx+4))  # => eax
16214     89/<- %edx 0/r32/eax
16215     # check v-addr->name
16216     (lookup *edx *(edx+4))  # Var-name Var-name => eax
16217     (check-strings-equal %eax "x" "F - test-parse-var-with-compound-type/name")
16218     # check v-addr->register
16219     (check-ints-equal *(edx+0x18) 0 "F - test-parse-var-with-compound-type/register")  # Var-register
16220     # - check v-addr->type
16221     # var type/edx: (addr type-tree) = var->type
16222     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
16223     89/<- %edx 0/r32/eax
16224     # type is a non-atom
16225     (check-ints-equal *edx 0 "F - test-parse-var-with-compound-type/type:0")  # Type-tree-is-atom
16226     # type->left == atom(addr)
16227     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
16228     (check-ints-equal *eax 1 "F - test-parse-var-with-compound-type/type:1")  # Type-tree-is-atom
16229     (check-ints-equal *(eax+4) 2 "F - test-parse-var-with-compound-type/type:2")  # Type-tree-value
16230     # type->right->left == atom(int)
16231     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
16232     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
16233     (check-ints-equal *eax 1 "F - test-parse-var-with-compound-type/type:3")  # Type-tree-is-atom
16234     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-compound-type/type:4")  # Type-tree-value
16235     # type->right->right == null
16236     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-compound-type/type:5")  # Type-tree-right
16237     # . epilogue
16238     89/<- %esp 5/r32/ebp
16239     5d/pop-to-ebp
16240     c3/return
16241 
16242 # identifier starts with a letter or '$' or '_'
16243 # no constraints at the moment on later letters
16244 # all we really want to do so far is exclude '{', '}' and '->'
16245 is-identifier?:  # in: (addr slice) -> result/eax: boolean
16246     # . prologue
16247     55/push-ebp
16248     89/<- %ebp 4/r32/esp
16249     # if (slice-empty?(in)) return false
16250     (slice-empty? *(ebp+8))  # => eax
16251     3d/compare-eax-and 0/imm32/false
16252     75/jump-if-!= $is-identifier?:false/disp8
16253     # var c/eax: byte = *in->start
16254     8b/-> *(ebp+8) 0/r32/eax
16255     8b/-> *eax 0/r32/eax
16256     8a/copy-byte *eax 0/r32/AL
16257     81 4/subop/and %eax 0xff/imm32
16258     # if (c == '$') return true
16259     3d/compare-eax-and 0x24/imm32/$
16260     74/jump-if-= $is-identifier?:true/disp8
16261     # if (c == '_') return true
16262     3d/compare-eax-and 0x5f/imm32/_
16263     74/jump-if-= $is-identifier?:true/disp8
16264     # drop case
16265     25/and-eax-with 0x5f/imm32
16266     # if (c < 'A') return false
16267     3d/compare-eax-and 0x41/imm32/A
16268     7c/jump-if-< $is-identifier?:false/disp8
16269     # if (c > 'Z') return false
16270     3d/compare-eax-and 0x5a/imm32/Z
16271     7f/jump-if-> $is-identifier?:false/disp8
16272     # otherwise return true
16273 $is-identifier?:true:
16274     b8/copy-to-eax 1/imm32/true
16275     eb/jump $is-identifier?:end/disp8
16276 $is-identifier?:false:
16277     b8/copy-to-eax 0/imm32/false
16278 $is-identifier?:end:
16279     # . epilogue
16280     89/<- %esp 5/r32/ebp
16281     5d/pop-to-ebp
16282     c3/return
16283 
16284 test-is-identifier-dollar:
16285     # . prologue
16286     55/push-ebp
16287     89/<- %ebp 4/r32/esp
16288     # (eax..ecx) = "$a"
16289     b8/copy-to-eax "$a"/imm32
16290     8b/-> *eax 1/r32/ecx
16291     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16292     05/add-to-eax 4/imm32
16293     # var slice/ecx: slice = {eax, ecx}
16294     51/push-ecx
16295     50/push-eax
16296     89/<- %ecx 4/r32/esp
16297     #
16298     (is-identifier? %ecx)
16299     (check-ints-equal %eax 1 "F - test-is-identifier-dollar")
16300     # . epilogue
16301     89/<- %esp 5/r32/ebp
16302     5d/pop-to-ebp
16303     c3/return
16304 
16305 test-is-identifier-underscore:
16306     # . prologue
16307     55/push-ebp
16308     89/<- %ebp 4/r32/esp
16309     # (eax..ecx) = "_a"
16310     b8/copy-to-eax "_a"/imm32
16311     8b/-> *eax 1/r32/ecx
16312     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16313     05/add-to-eax 4/imm32
16314     # var slice/ecx: slice = {eax, ecx}
16315     51/push-ecx
16316     50/push-eax
16317     89/<- %ecx 4/r32/esp
16318     #
16319     (is-identifier? %ecx)
16320     (check-ints-equal %eax 1 "F - test-is-identifier-underscore")
16321     # . epilogue
16322     89/<- %esp 5/r32/ebp
16323     5d/pop-to-ebp
16324     c3/return
16325 
16326 test-is-identifier-a:
16327     # . prologue
16328     55/push-ebp
16329     89/<- %ebp 4/r32/esp
16330     # (eax..ecx) = "a$"
16331     b8/copy-to-eax "a$"/imm32
16332     8b/-> *eax 1/r32/ecx
16333     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16334     05/add-to-eax 4/imm32
16335     # var slice/ecx: slice = {eax, ecx}
16336     51/push-ecx
16337     50/push-eax
16338     89/<- %ecx 4/r32/esp
16339     #
16340     (is-identifier? %ecx)
16341     (check-ints-equal %eax 1 "F - test-is-identifier-a")
16342     # . epilogue
16343     89/<- %esp 5/r32/ebp
16344     5d/pop-to-ebp
16345     c3/return
16346 
16347 test-is-identifier-z:
16348     # . prologue
16349     55/push-ebp
16350     89/<- %ebp 4/r32/esp
16351     # (eax..ecx) = "z$"
16352     b8/copy-to-eax "z$"/imm32
16353     8b/-> *eax 1/r32/ecx
16354     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16355     05/add-to-eax 4/imm32
16356     # var slice/ecx: slice = {eax, ecx}
16357     51/push-ecx
16358     50/push-eax
16359     89/<- %ecx 4/r32/esp
16360     #
16361     (is-identifier? %ecx)
16362     (check-ints-equal %eax 1 "F - test-is-identifier-z")
16363     # . epilogue
16364     89/<- %esp 5/r32/ebp
16365     5d/pop-to-ebp
16366     c3/return
16367 
16368 test-is-identifier-A:
16369     # . prologue
16370     55/push-ebp
16371     89/<- %ebp 4/r32/esp
16372     # (eax..ecx) = "A$"
16373     b8/copy-to-eax "A$"/imm32
16374     8b/-> *eax 1/r32/ecx
16375     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16376     05/add-to-eax 4/imm32
16377     # var slice/ecx: slice = {eax, ecx}
16378     51/push-ecx
16379     50/push-eax
16380     89/<- %ecx 4/r32/esp
16381     #
16382     (is-identifier? %ecx)
16383     (check-ints-equal %eax 1 "F - test-is-identifier-A")
16384     # . epilogue
16385     89/<- %esp 5/r32/ebp
16386     5d/pop-to-ebp
16387     c3/return
16388 
16389 test-is-identifier-Z:
16390     # . prologue
16391     55/push-ebp
16392     89/<- %ebp 4/r32/esp
16393     # (eax..ecx) = "Z$"
16394     b8/copy-to-eax "Z$"/imm32
16395     8b/-> *eax 1/r32/ecx
16396     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16397     05/add-to-eax 4/imm32
16398     # var slice/ecx: slice = {eax, ecx}
16399     51/push-ecx
16400     50/push-eax
16401     89/<- %ecx 4/r32/esp
16402     #
16403     (is-identifier? %ecx)
16404     (check-ints-equal %eax 1 "F - test-is-identifier-Z")
16405     # . epilogue
16406     89/<- %esp 5/r32/ebp
16407     5d/pop-to-ebp
16408     c3/return
16409 
16410 test-is-identifier-at:
16411     # character before 'A' is invalid
16412     # . prologue
16413     55/push-ebp
16414     89/<- %ebp 4/r32/esp
16415     # (eax..ecx) = "@a"
16416     b8/copy-to-eax "@a"/imm32
16417     8b/-> *eax 1/r32/ecx
16418     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16419     05/add-to-eax 4/imm32
16420     # var slice/ecx: slice = {eax, ecx}
16421     51/push-ecx
16422     50/push-eax
16423     89/<- %ecx 4/r32/esp
16424     #
16425     (is-identifier? %ecx)
16426     (check-ints-equal %eax 0 "F - test-is-identifier-@")
16427     # . epilogue
16428     89/<- %esp 5/r32/ebp
16429     5d/pop-to-ebp
16430     c3/return
16431 
16432 test-is-identifier-square-bracket:
16433     # character after 'Z' is invalid
16434     # . prologue
16435     55/push-ebp
16436     89/<- %ebp 4/r32/esp
16437     # (eax..ecx) = "[a"
16438     b8/copy-to-eax "[a"/imm32
16439     8b/-> *eax 1/r32/ecx
16440     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16441     05/add-to-eax 4/imm32
16442     # var slice/ecx: slice = {eax, ecx}
16443     51/push-ecx
16444     50/push-eax
16445     89/<- %ecx 4/r32/esp
16446     #
16447     (is-identifier? %ecx)
16448     (check-ints-equal %eax 0 "F - test-is-identifier-@")
16449     # . epilogue
16450     89/<- %esp 5/r32/ebp
16451     5d/pop-to-ebp
16452     c3/return
16453 
16454 test-is-identifier-backtick:
16455     # character before 'a' is invalid
16456     # . prologue
16457     55/push-ebp
16458     89/<- %ebp 4/r32/esp
16459     # (eax..ecx) = "`a"
16460     b8/copy-to-eax "`a"/imm32
16461     8b/-> *eax 1/r32/ecx
16462     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16463     05/add-to-eax 4/imm32
16464     # var slice/ecx: slice = {eax, ecx}
16465     51/push-ecx
16466     50/push-eax
16467     89/<- %ecx 4/r32/esp
16468     #
16469     (is-identifier? %ecx)
16470     (check-ints-equal %eax 0 "F - test-is-identifier-backtick")
16471     # . epilogue
16472     89/<- %esp 5/r32/ebp
16473     5d/pop-to-ebp
16474     c3/return
16475 
16476 test-is-identifier-curly-brace-open:
16477     # character after 'z' is invalid; also used for blocks
16478     # . prologue
16479     55/push-ebp
16480     89/<- %ebp 4/r32/esp
16481     # (eax..ecx) = "{a"
16482     b8/copy-to-eax "{a"/imm32
16483     8b/-> *eax 1/r32/ecx
16484     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16485     05/add-to-eax 4/imm32
16486     # var slice/ecx: slice = {eax, ecx}
16487     51/push-ecx
16488     50/push-eax
16489     89/<- %ecx 4/r32/esp
16490     #
16491     (is-identifier? %ecx)
16492     (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-open")
16493     # . epilogue
16494     89/<- %esp 5/r32/ebp
16495     5d/pop-to-ebp
16496     c3/return
16497 
16498 test-is-identifier-curly-brace-close:
16499     # . prologue
16500     55/push-ebp
16501     89/<- %ebp 4/r32/esp
16502     # (eax..ecx) = "}a"
16503     b8/copy-to-eax "}a"/imm32
16504     8b/-> *eax 1/r32/ecx
16505     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16506     05/add-to-eax 4/imm32
16507     # var slice/ecx: slice = {eax, ecx}
16508     51/push-ecx
16509     50/push-eax
16510     89/<- %ecx 4/r32/esp
16511     #
16512     (is-identifier? %ecx)
16513     (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-close")
16514     # . epilogue
16515     89/<- %esp 5/r32/ebp
16516     5d/pop-to-ebp
16517     c3/return
16518 
16519 test-is-identifier-hyphen:
16520     # disallow leading '-' since '->' has special meaning
16521     # . prologue
16522     55/push-ebp
16523     89/<- %ebp 4/r32/esp
16524     # (eax..ecx) = "-a"
16525     b8/copy-to-eax "-a"/imm32
16526     8b/-> *eax 1/r32/ecx
16527     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16528     05/add-to-eax 4/imm32
16529     # var slice/ecx: slice = {eax, ecx}
16530     51/push-ecx
16531     50/push-eax
16532     89/<- %ecx 4/r32/esp
16533     #
16534     (is-identifier? %ecx)
16535     (check-ints-equal %eax 0 "F - test-is-identifier-hyphen")
16536     # . epilogue
16537     89/<- %esp 5/r32/ebp
16538     5d/pop-to-ebp
16539     c3/return
16540 
16541 populate-mu-function-body:  # in: (addr buffered-file), out: (addr function), vars: (addr stack live-var), err: (addr buffered-file), ed: (addr exit-descriptor)
16542     # . prologue
16543     55/push-ebp
16544     89/<- %ebp 4/r32/esp
16545     # . save registers
16546     50/push-eax
16547     56/push-esi
16548     57/push-edi
16549     # esi = in
16550     8b/-> *(ebp+8) 6/r32/esi
16551     # edi = out
16552     8b/-> *(ebp+0xc) 7/r32/edi
16553     # initialize some global state
16554     c7 0/subop/copy *Curr-block-depth 1/imm32
16555     # parse-mu-block(in, vars, out, out->body)
16556     8d/copy-address *(edi+0x18) 0/r32/eax  # Function-body
16557     (parse-mu-block %esi *(ebp+0x10) %edi %eax *(ebp+0x14) *(ebp+0x18))
16558 $populate-mu-function-body:end:
16559     # . restore registers
16560     5f/pop-to-edi
16561     5e/pop-to-esi
16562     58/pop-to-eax
16563     # . epilogue
16564     89/<- %esp 5/r32/ebp
16565     5d/pop-to-ebp
16566     c3/return
16567 
16568 # parses a block, assuming that the leading '{' has already been read by the caller
16569 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)
16570     # pseudocode:
16571     #   var line: (stream byte 512)
16572     #   var word-slice: slice
16573     #   allocate(Heap, Stmt-size, out)
16574     #   var out-addr: (addr block) = lookup(*out)
16575     #   out-addr->tag = 0/block
16576     #   out-addr->var = some unique name
16577     #   push(vars, {out-addr->var, false})
16578     #   while true                                  # line loop
16579     #     clear-stream(line)
16580     #     read-line-buffered(in, line)
16581     #     if (line->write == 0) break               # end of file
16582     #     word-slice = next-mu-token(line)
16583     #     if slice-empty?(word-slice)               # end of line
16584     #       continue
16585     #     else if slice-starts-with?(word-slice, "#")
16586     #       continue
16587     #     else if slice-equal?(word-slice, "{")
16588     #       assert(no-tokens-in(line))
16589     #       block = parse-mu-block(in, vars, fn)
16590     #       append-to-block(out-addr, block)
16591     #     else if slice-equal?(word-slice, "}")
16592     #       break
16593     #     else if slice-ends-with?(word-slice, ":")
16594     #       # TODO: error-check the rest of 'line'
16595     #       --word-slice->end to skip ':'
16596     #       named-block = parse-mu-named-block(word-slice, in, vars, fn)
16597     #       append-to-block(out-addr, named-block)
16598     #     else if slice-equal?(word-slice, "var")
16599     #       var-def = parse-mu-var-def(line, vars, fn)
16600     #       append-to-block(out-addr, var-def)
16601     #     else
16602     #       stmt = parse-mu-stmt(line, vars, fn)
16603     #       append-to-block(out-addr, stmt)
16604     #   pop(vars)
16605     #
16606     # . prologue
16607     55/push-ebp
16608     89/<- %ebp 4/r32/esp
16609     # . save registers
16610     50/push-eax
16611     51/push-ecx
16612     52/push-edx
16613     53/push-ebx
16614     57/push-edi
16615     # var line/ecx: (stream byte 512)
16616     81 5/subop/subtract %esp 0x200/imm32
16617     68/push 0x200/imm32/size
16618     68/push 0/imm32/read
16619     68/push 0/imm32/write
16620     89/<- %ecx 4/r32/esp
16621     # var word-slice/edx: slice
16622     68/push 0/imm32/end
16623     68/push 0/imm32/start
16624     89/<- %edx 4/r32/esp
16625     # allocate into out
16626     (allocate Heap *Stmt-size *(ebp+0x14))
16627     # var out-addr/edi: (addr block) = lookup(*out)
16628     8b/-> *(ebp+0x14) 7/r32/edi
16629     (lookup *edi *(edi+4))  # => eax
16630     89/<- %edi 0/r32/eax
16631     # out-addr->tag is 0 (block) by default
16632     # set out-addr->var
16633     8d/copy-address *(edi+0xc) 0/r32/eax  # Block-var
16634     (new-block-name *(ebp+0x10) %eax)
16635     # push(vars, out-addr->var)
16636     (push *(ebp+0xc) *(edi+0xc))  # Block-var
16637     (push *(ebp+0xc) *(edi+0x10))  # Block-var
16638     (push *(ebp+0xc) 0)  # false
16639     # increment *Curr-block-depth
16640     ff 0/subop/increment *Curr-block-depth
16641     {
16642 $parse-mu-block:line-loop:
16643       # line = read-line-buffered(in)
16644       (clear-stream %ecx)
16645       (read-line-buffered *(ebp+8) %ecx)
16646 #?       (write-buffered Stderr "line: ")
16647 #?       (write-stream-data Stderr %ecx)
16648 #? #?       (write-buffered Stderr Newline)  # line has its own newline
16649 #?       (flush Stderr)
16650 #?       (rewind-stream %ecx)
16651       # if (line->write == 0) break
16652       81 7/subop/compare *ecx 0/imm32
16653       0f 84/jump-if-= break/disp32
16654 #?       (write-buffered Stderr "vars:\n")
16655 #?       (dump-vars *(ebp+0xc))
16656       # word-slice = next-mu-token(line)
16657       (next-mu-token %ecx %edx)
16658 #?       (write-buffered Stderr "word: ")
16659 #?       (write-slice-buffered Stderr %edx)
16660 #?       (write-buffered Stderr Newline)
16661 #?       (flush Stderr)
16662       # if slice-empty?(word-slice) continue
16663       (slice-empty? %edx)
16664       3d/compare-eax-and 0/imm32/false
16665       0f 85/jump-if-!= loop/disp32
16666       # if (slice-starts-with?(word-slice, '#') continue
16667       # . eax = *word-slice->start
16668       8b/-> *edx 0/r32/eax
16669       8a/copy-byte *eax 0/r32/AL
16670       81 4/subop/and %eax 0xff/imm32
16671       # . if (eax == '#') continue
16672       3d/compare-eax-and 0x23/imm32/hash
16673       0f 84/jump-if-= loop/disp32
16674       # if slice-equal?(word-slice, "{")
16675       {
16676 $parse-mu-block:check-for-block:
16677         (slice-equal? %edx "{")
16678         3d/compare-eax-and 0/imm32/false
16679         74/jump-if-= break/disp8
16680         (check-no-tokens-left %ecx)
16681         # parse new block and append
16682         # . var tmp/eax: (handle block)
16683         68/push 0/imm32
16684         68/push 0/imm32
16685         89/<- %eax 4/r32/esp
16686         # .
16687         (parse-mu-block *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
16688         (append-to-block Heap %edi  *eax *(eax+4))
16689         # . reclaim tmp
16690         81 0/subop/add %esp 8/imm32
16691         # .
16692         e9/jump $parse-mu-block:line-loop/disp32
16693       }
16694       # if slice-equal?(word-slice, "}") break
16695 $parse-mu-block:check-for-end:
16696       (slice-equal? %edx "}")
16697       3d/compare-eax-and 0/imm32/false
16698       0f 85/jump-if-!= break/disp32
16699       # if slice-ends-with?(word-slice, ":") parse named block and append
16700       {
16701 $parse-mu-block:check-for-named-block:
16702         # . eax = *(word-slice->end-1)
16703         8b/-> *(edx+4) 0/r32/eax
16704         48/decrement-eax
16705         8a/copy-byte *eax 0/r32/AL
16706         81 4/subop/and %eax 0xff/imm32
16707         # . if (eax != ':') break
16708         3d/compare-eax-and 0x3a/imm32/colon
16709         0f 85/jump-if-!= break/disp32
16710         # TODO: error-check the rest of 'line'
16711         #
16712         # skip ':'
16713         ff 1/subop/decrement *(edx+4)  # Slice-end
16714         # var tmp/eax: (handle block)
16715         68/push 0/imm32
16716         68/push 0/imm32
16717         89/<- %eax 4/r32/esp
16718         #
16719         (parse-mu-named-block %edx *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
16720         (append-to-block Heap %edi  *eax *(eax+4))
16721         # reclaim tmp
16722         81 0/subop/add %esp 8/imm32
16723         #
16724         e9/jump $parse-mu-block:line-loop/disp32
16725       }
16726       # if slice-equal?(word-slice, "var")
16727       {
16728 $parse-mu-block:check-for-var:
16729         (slice-equal? %edx "var")
16730         3d/compare-eax-and 0/imm32/false
16731         74/jump-if-= break/disp8
16732         # var tmp/eax: (handle block)
16733         68/push 0/imm32
16734         68/push 0/imm32
16735         89/<- %eax 4/r32/esp
16736         #
16737         (parse-mu-var-def %ecx *(ebp+0xc) %eax *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
16738         (append-to-block Heap %edi  *eax *(eax+4))
16739         # reclaim tmp
16740         81 0/subop/add %esp 8/imm32
16741         #
16742         e9/jump $parse-mu-block:line-loop/disp32
16743       }
16744 $parse-mu-block:regular-stmt:
16745       # otherwise
16746       # var tmp/eax: (handle block)
16747       68/push 0/imm32
16748       68/push 0/imm32
16749       89/<- %eax 4/r32/esp
16750       #
16751       (parse-mu-stmt %ecx *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
16752       (append-to-block Heap %edi  *eax *(eax+4))
16753       # reclaim tmp
16754       81 0/subop/add %esp 8/imm32
16755       #
16756       e9/jump loop/disp32
16757     } # end line loop
16758     (clean-up-blocks *(ebp+0xc) *Curr-block-depth *(ebp+0x10))
16759     # decrement *Curr-block-depth
16760     ff 1/subop/decrement *Curr-block-depth
16761     # pop(vars)
16762     (pop *(ebp+0xc))  # => eax
16763     (pop *(ebp+0xc))  # => eax
16764     (pop *(ebp+0xc))  # => eax
16765 $parse-mu-block:end:
16766     # . reclaim locals
16767     81 0/subop/add %esp 0x214/imm32
16768     # . restore registers
16769     5f/pop-to-edi
16770     5b/pop-to-ebx
16771     5a/pop-to-edx
16772     59/pop-to-ecx
16773     58/pop-to-eax
16774     # . epilogue
16775     89/<- %esp 5/r32/ebp
16776     5d/pop-to-ebp
16777     c3/return
16778 
16779 $parse-mu-block:abort:
16780     # error("'{' or '}' should be on its own line, but got '")
16781     (write-buffered *(ebp+0x18) "'{' or '}' should be on its own line, but got '")
16782     (rewind-stream %ecx)
16783     (write-stream-data *(ebp+0x18) %ecx)
16784     (write-buffered *(ebp+0x18) "'\n")
16785     (flush *(ebp+0x18))
16786     (stop *(ebp+0x1c) 1)
16787     # never gets here
16788 
16789 new-block-name:  # fn: (addr function), out: (addr handle var)
16790     # . prologue
16791     55/push-ebp
16792     89/<- %ebp 4/r32/esp
16793     # . save registers
16794     50/push-eax
16795     51/push-ecx
16796     52/push-edx
16797     # var n/ecx: int = len(fn->name) + 10 for an int + 2 for '$:'
16798     8b/-> *(ebp+8) 0/r32/eax
16799     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16800     8b/-> *eax 0/r32/eax  # String-size
16801     05/add-to-eax 0xd/imm32  # 10 + 2 for '$:'
16802     89/<- %ecx 0/r32/eax
16803     # var name/edx: (stream byte n)
16804     29/subtract-from %esp 1/r32/ecx
16805     ff 6/subop/push %ecx
16806     68/push 0/imm32/read
16807     68/push 0/imm32/write
16808     89/<- %edx 4/r32/esp
16809     (clear-stream %edx)
16810     # eax = fn->name
16811     8b/-> *(ebp+8) 0/r32/eax
16812     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16813     # construct result using Next-block-index (and increment it)
16814     (write %edx "$")
16815     (write %edx %eax)
16816     (write %edx ":")
16817     (write-int32-hex %edx *Next-block-index)
16818     ff 0/subop/increment *Next-block-index
16819     # var s/eax: slice = {name->data, name->data + name->write}  (clobbering edx)
16820     # . eax = name->write
16821     8b/-> *edx 0/r32/eax
16822     # . edx = name->data
16823     8d/copy-address *(edx+0xc) 2/r32/edx
16824     # . eax = name->write + name->data
16825     01/add-to %eax 2/r32/edx
16826     # . push {edx, eax}
16827     ff 6/subop/push %eax
16828     ff 6/subop/push %edx
16829     89/<- %eax 4/r32/esp
16830     # out = new literal(s)
16831     (new-literal Heap %eax *(ebp+0xc))
16832 #?     8b/-> *(ebp+0xc) 0/r32/eax
16833 #?     (write-buffered Stderr "type allocid in caller after new-literal: ")
16834 #?     (write-int32-hex-buffered Stderr *(eax+8))
16835 #?     (write-buffered Stderr " for var ")
16836 #?     (write-int32-hex-buffered Stderr %eax)
16837 #?     (write-buffered Stderr Newline)
16838 #?     (flush Stderr)
16839 $new-block-name:end:
16840     # . reclaim locals
16841     81 0/subop/add %ecx 0xc/imm32  # name.{read/write/len}
16842     81 0/subop/add %ecx 8/imm32  # slice
16843     01/add-to %esp 1/r32/ecx
16844     # . restore registers
16845     5a/pop-to-edx
16846     59/pop-to-ecx
16847     58/pop-to-eax
16848     # . epilogue
16849     89/<- %esp 5/r32/ebp
16850     5d/pop-to-ebp
16851     c3/return
16852 
16853 check-no-tokens-left:  # line: (addr stream byte)
16854     # . prologue
16855     55/push-ebp
16856     89/<- %ebp 4/r32/esp
16857     # . save registers
16858     50/push-eax
16859     51/push-ecx
16860     # var s/ecx: slice
16861     68/push 0/imm32/end
16862     68/push 0/imm32/start
16863     89/<- %ecx 4/r32/esp
16864     #
16865     (next-mu-token *(ebp+8) %ecx)
16866     # if slice-empty?(s) return
16867     (slice-empty? %ecx)
16868     3d/compare-eax-and 0/imm32/false
16869     75/jump-if-!= $check-no-tokens-left:end/disp8
16870     # if (slice-starts-with?(s, '#') return
16871     # . eax = *s->start
16872     8b/-> *edx 0/r32/eax
16873     8a/copy-byte *eax 0/r32/AL
16874     81 4/subop/and %eax 0xff/imm32
16875     # . if (eax == '#') continue
16876     3d/compare-eax-and 0x23/imm32/hash
16877     74/jump-if-= $check-no-tokens-left:end/disp8
16878     # abort
16879     (write-buffered Stderr "'{' or '}' should be on its own line, but got '")
16880     (rewind-stream %ecx)
16881     (write-stream 2 %ecx)
16882     (write-buffered Stderr "'\n")
16883     (flush Stderr)
16884     # . syscall(exit, 1)
16885     bb/copy-to-ebx  1/imm32
16886     e8/call syscall_exit/disp32
16887     # never gets here
16888 $check-no-tokens-left:end:
16889     # . reclaim locals
16890     81 0/subop/add %esp 8/imm32
16891     # . restore registers
16892     59/pop-to-ecx
16893     58/pop-to-eax
16894     # . epilogue
16895     89/<- %esp 5/r32/ebp
16896     5d/pop-to-ebp
16897     c3/return
16898 
16899 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)
16900     # pseudocode:
16901     #   var v: (handle var)
16902     #   new-literal(name, v)
16903     #   push(vars, {v, false})
16904     #   parse-mu-block(in, vars, fn, out)
16905     #   pop(vars)
16906     #   out->tag = block
16907     #   out->var = v
16908     #
16909     # . prologue
16910     55/push-ebp
16911     89/<- %ebp 4/r32/esp
16912     # . save registers
16913     50/push-eax
16914     51/push-ecx
16915     57/push-edi
16916     # var v/ecx: (handle var)
16917     68/push 0/imm32
16918     68/push 0/imm32
16919     89/<- %ecx 4/r32/esp
16920     #
16921     (new-literal Heap *(ebp+8) %ecx)
16922     # push(vars, v)
16923     (push *(ebp+0x10) *ecx)
16924     (push *(ebp+0x10) *(ecx+4))
16925     (push *(ebp+0x10) 0)  # false
16926     #
16927     (parse-mu-block *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c) *(ebp+0x20))
16928     # pop v off vars
16929     (pop *(ebp+0x10))  # => eax
16930     (pop *(ebp+0x10))  # => eax
16931     (pop *(ebp+0x10))  # => eax
16932     # var out-addr/edi: (addr stmt) = lookup(*out)
16933     8b/-> *(ebp+0x18) 7/r32/edi
16934     (lookup *edi *(edi+4))  # => eax
16935     89/<- %edi 0/r32/eax
16936     # out-addr->tag = named-block
16937     c7 0/subop/copy *edi 0/imm32/block  # Stmt-tag
16938     # out-addr->var = v
16939     8b/-> *ecx 0/r32/eax
16940     89/<- *(edi+0xc) 0/r32/eax  # Block-var
16941     8b/-> *(ecx+4) 0/r32/eax
16942     89/<- *(edi+0x10) 0/r32/eax  # Block-var
16943 $parse-mu-named-block:end:
16944     # . reclaim locals
16945     81 0/subop/add %esp 8/imm32
16946     # . restore registers
16947     5f/pop-to-edi
16948     59/pop-to-ecx
16949     58/pop-to-eax
16950     # . epilogue
16951     89/<- %esp 5/r32/ebp
16952     5d/pop-to-ebp
16953     c3/return
16954 
16955 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)
16956     # . prologue
16957     55/push-ebp
16958     89/<- %ebp 4/r32/esp
16959     # . save registers
16960     50/push-eax
16961     51/push-ecx
16962     52/push-edx
16963     56/push-esi
16964     57/push-edi
16965     # edi = out
16966     8b/-> *(ebp+0x10) 7/r32/edi
16967     # var word-slice/ecx: slice
16968     68/push 0/imm32/end
16969     68/push 0/imm32/start
16970     89/<- %ecx 4/r32/esp
16971     # var v/edx: (handle var)
16972     68/push 0/imm32
16973     68/push 0/imm32
16974     89/<- %edx 4/r32/esp
16975     # v = parse-var-with-type(next-mu-token(line))
16976     (next-mu-token *(ebp+8) %ecx)
16977     {
16978       # just for tests, support null fn
16979       8b/-> *(ebp+0x14) 0/r32/eax
16980       3d/compare-eax-and 0/imm32
16981       74/jump-if-= break/disp8
16982       (lookup *eax *(eax+4))  # Var-name Var-name => eax
16983     }
16984     (parse-var-with-type %ecx *(ebp+8) %edx %eax *(ebp+0x18) *(ebp+0x1c))
16985     # var v-addr/esi: (addr var)
16986     (lookup *edx *(edx+4))  # => eax
16987     89/<- %esi 0/r32/eax
16988     # v->block-depth = *Curr-block-depth
16989     8b/-> *Curr-block-depth 0/r32/eax
16990     89/<- *(esi+0x10) 0/r32/eax  # Var-block-depth
16991     # either v has no register and there's no more to this line
16992     81 7/subop/compare *(esi+0x18) 0/imm32
16993     {
16994       75/jump-if-!= break/disp8
16995       # if v-addr->type == byte, abort
16996       (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
16997       (is-simple-mu-type? %eax 8)  # byte => eax
16998       3d/compare-eax-and 0/imm32/false
16999       0f 85/jump-if-!= $parse-mu-var-def:error-byte-on-stack/disp32
17000       # ensure that there's nothing else on this line
17001       (next-mu-token *(ebp+8) %ecx)
17002       (slice-empty? %ecx)  # => eax
17003       3d/compare-eax-and 0/imm32/false
17004       0f 84/jump-if-= $parse-mu-var-def:error2/disp32
17005       #
17006       (new-var-def Heap  *edx *(edx+4)  %edi)
17007       e9/jump $parse-mu-var-def:update-vars/disp32
17008     }
17009     # or v has a register and there's more to this line
17010     {
17011       0f 84/jump-if-= break/disp32
17012       # if v-addr->type == byte, check for unsupported registers
17013       {
17014         (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
17015         (is-simple-mu-type? %eax 8)  # byte => eax
17016         3d/compare-eax-and 0/imm32/false
17017         74/jump-if-= break/disp8
17018         (lookup *(esi+0x18) *(esi+0x1c))  # => eax
17019         (string-equal? %eax "esi")  # => eax
17020         3d/compare-eax-and 0/imm32/false
17021         0f 85/jump-if-!= $parse-mu-var-def:error-byte-registers/disp32
17022         (lookup *(esi+0x18) *(esi+0x1c))  # => eax
17023         (string-equal? %eax "edi")  # => eax
17024         3d/compare-eax-and 0/imm32/false
17025         0f 85/jump-if-!= $parse-mu-var-def:error-byte-registers/disp32
17026       }
17027       # TODO: vars of type 'byte' should only be initialized by clearing to 0
17028       # ensure that the next word is '<-'
17029       (next-mu-token *(ebp+8) %ecx)
17030       (slice-equal? %ecx "<-")  # => eax
17031       3d/compare-eax-and 0/imm32/false
17032       0f 84/jump-if-= $parse-mu-var-def:error1/disp32
17033       #
17034       (new-reg-var-def Heap  *edx *(edx+4)  %edi)
17035       (lookup *edi *(edi+4))  # => eax
17036       (add-operation-and-inputs-to-stmt %eax *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
17037     }
17038 $parse-mu-var-def:update-vars:
17039     # push 'v' at end of function
17040     (push *(ebp+0xc) *edx)
17041     (push *(ebp+0xc) *(edx+4))
17042     (push *(ebp+0xc) 0)  # Live-var-register-spilled is unused during parsing
17043 $parse-mu-var-def:end:
17044     # . reclaim locals
17045     81 0/subop/add %esp 0x10/imm32
17046     # . restore registers
17047     5f/pop-to-edi
17048     5e/pop-to-esi
17049     5a/pop-to-edx
17050     59/pop-to-ecx
17051     58/pop-to-eax
17052     # . epilogue
17053     89/<- %esp 5/r32/ebp
17054     5d/pop-to-ebp
17055     c3/return
17056 
17057 $parse-mu-var-def:error1:
17058     (rewind-stream *(ebp+8))
17059     # error("register variable requires a valid instruction to initialize but got '" line "'\n")
17060     (write-buffered *(ebp+0x18) "register variable requires a valid instruction to initialize but got '")
17061     (flush *(ebp+0x18))
17062     (write-stream-data *(ebp+0x18) *(ebp+8))
17063     (write-buffered *(ebp+0x18) "'\n")
17064     (flush *(ebp+0x18))
17065     (stop *(ebp+0x1c) 1)
17066     # never gets here
17067 
17068 $parse-mu-var-def:error2:
17069     # error("fn " fn ": var " var ": variables on the stack can't take an initializer\n")
17070     (write-buffered *(ebp+0x18) "fn ")
17071     8b/-> *(ebp+0x14) 0/r32/eax
17072     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17073     (write-buffered *(ebp+0x18) %eax)
17074     (write-buffered *(ebp+0x18) ": var ")
17075     # var v-addr/eax: (addr var) = lookup(v)
17076     (lookup *edx *(edx+4))  # => eax
17077     (lookup *eax *(eax+4))  # Var-name Var-name => eax
17078     (write-buffered *(ebp+0x18) %eax)
17079     (write-buffered *(ebp+0x18) ": variables on the stack can't take an initializer\n")
17080     (flush *(ebp+0x18))
17081     (stop *(ebp+0x1c) 1)
17082     # never gets here
17083 
17084 $parse-mu-var-def:error-byte-on-stack:
17085     # error("fn " fn ": var '" var "' of type 'byte' cannot be on the stack\n")
17086     (write-buffered *(ebp+0x18) "fn ")
17087     8b/-> *(ebp+0x14) 0/r32/eax
17088     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17089     (write-buffered *(ebp+0x18) %eax)
17090     (write-buffered *(ebp+0x18) ": var '")
17091     # var v-addr/eax: (addr var) = lookup(v)
17092     (lookup *edx *(edx+4))  # => eax
17093     (lookup *eax *(eax+4))  # Var-name Var-name => eax
17094     (write-buffered *(ebp+0x18) %eax)
17095     (write-buffered *(ebp+0x18) "' of type 'byte' cannot be on the stack\n")
17096     (flush *(ebp+0x18))
17097     (stop *(ebp+0x1c) 1)
17098     # never gets here
17099 
17100 $parse-mu-var-def:error-byte-registers:
17101     # error("fn " fn ": var '" var "' of type 'byte' cannot be in esi or edi\n")
17102     (write-buffered *(ebp+0x18) "fn ")
17103     8b/-> *(ebp+0x14) 0/r32/eax
17104     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17105     (write-buffered *(ebp+0x18) %eax)
17106     (write-buffered *(ebp+0x18) ": var '")
17107     # var v-addr/eax: (addr var) = lookup(v)
17108     (lookup *edx *(edx+4))  # => eax
17109     (lookup *eax *(eax+4))  # Var-name Var-name => eax
17110     (write-buffered *(ebp+0x18) %eax)
17111     (write-buffered *(ebp+0x18) "' of type 'byte' cannot be in esi or edi\n")
17112     (flush *(ebp+0x18))
17113     (stop *(ebp+0x1c) 1)
17114     # never gets here
17115 
17116 test-parse-mu-var-def:
17117     # 'var n: int'
17118     # . prologue
17119     55/push-ebp
17120     89/<- %ebp 4/r32/esp
17121     # setup
17122     8b/-> *Primitive-type-ids 0/r32/eax
17123     89/<- *Type-id 0/r32/eax  # stream-write
17124     (clear-stream _test-input-stream)
17125     (write _test-input-stream "n: int\n")  # caller has consumed the 'var'
17126     c7 0/subop/copy *Curr-block-depth 1/imm32
17127     # var out/esi: (handle stmt)
17128     68/push 0/imm32
17129     68/push 0/imm32
17130     89/<- %esi 4/r32/esp
17131     # var vars/ecx: (stack (addr var) 16)
17132     81 5/subop/subtract %esp 0xc0/imm32
17133     68/push 0xc0/imm32/size
17134     68/push 0/imm32/top
17135     89/<- %ecx 4/r32/esp
17136     (clear-stack %ecx)
17137     # convert
17138     (parse-mu-var-def _test-input-stream %ecx %esi 0 Stderr 0)
17139     # var out-addr/esi: (addr stmt)
17140     (lookup *esi *(esi+4))  # => eax
17141     89/<- %esi 0/r32/eax
17142     #
17143     (check-ints-equal *esi 2 "F - test-parse-mu-var-def/tag")  # Stmt-tag is var-def
17144     # var v/ecx: (addr var) = lookup(out->var)
17145     (lookup *(esi+4) *(esi+8))  # Vardef-var Vardef-var => eax
17146     89/<- %ecx 0/r32/eax
17147     # v->name
17148     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
17149     (check-strings-equal %eax "n" "F - test-parse-mu-var-def/var-name")
17150     # v->register
17151     (check-ints-equal *(ecx+0x18) 0 "F - test-parse-mu-var-def/var-register")  # Var-register
17152     # v->block-depth
17153     (check-ints-equal *(ecx+0x10) 1 "F - test-parse-mu-var-def/output-block-depth")  # Var-block-depth
17154     # v->type == int
17155     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
17156     (check-ints-equal *eax 1 "F - test-parse-mu-var-def/var-type:0")  # Type-tree-is-atom
17157     (check-ints-equal *(eax+4) 1 "F - test-parse-mu-var-def/var-type:1")  # Type-tree-value
17158     (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-var-def/var-type:2")  # Type-tree-right
17159     # . epilogue
17160     89/<- %esp 5/r32/ebp
17161     5d/pop-to-ebp
17162     c3/return
17163 
17164 test-parse-mu-reg-var-def:
17165     # 'var n/eax: int <- copy 0'
17166     # . prologue
17167     55/push-ebp
17168     89/<- %ebp 4/r32/esp
17169     # setup
17170     8b/-> *Primitive-type-ids 0/r32/eax
17171     89/<- *Type-id 0/r32/eax  # stream-write
17172     (clear-stream _test-input-stream)
17173     (write _test-input-stream "n/eax: int <- copy 0\n")  # caller has consumed the 'var'
17174     c7 0/subop/copy *Curr-block-depth 1/imm32
17175     # var out/esi: (handle stmt)
17176     68/push 0/imm32
17177     68/push 0/imm32
17178     89/<- %esi 4/r32/esp
17179     # var vars/ecx: (stack (addr var) 16)
17180     81 5/subop/subtract %esp 0xc0/imm32
17181     68/push 0xc0/imm32/size
17182     68/push 0/imm32/top
17183     89/<- %ecx 4/r32/esp
17184     (clear-stack %ecx)
17185     # convert
17186     (parse-mu-var-def _test-input-stream %ecx %esi 0 Stderr 0)
17187     # var out-addr/esi: (addr stmt)
17188     (lookup *esi *(esi+4))  # => eax
17189     89/<- %esi 0/r32/eax
17190     #
17191     (check-ints-equal *esi 3 "F - test-parse-mu-reg-var-def/tag")  # Stmt-tag is reg-var-def
17192     # var v/ecx: (addr var) = lookup(out->outputs->value)
17193     # . eax: (addr stmt-var) = lookup(out->outputs)
17194     (lookup *(esi+0x14) *(esi+0x18))  # Regvardef-outputs Regvardef-outputs => eax
17195     # .
17196     (check-ints-equal *(eax+8) 0 "F - test-parse-mu-reg-var-def/single-output")  # Stmt-var-next
17197     # . eax: (addr var) = lookup(eax->value)
17198     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
17199     # . ecx = eax
17200     89/<- %ecx 0/r32/eax
17201     # v->name
17202     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
17203     (check-strings-equal %eax "n" "F - test-parse-mu-reg-var-def/output-name")  # Var-name
17204     # v->register
17205     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
17206     (check-strings-equal %eax "eax" "F - test-parse-mu-reg-var-def/output-register")
17207     # v->block-depth
17208     (check-ints-equal *(ecx+0x10) 1 "F - test-parse-mu-reg-var-def/output-block-depth")  # Var-block-depth
17209     # v->type == int
17210     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
17211     (check-ints-equal *eax 1 "F - test-parse-mu-reg-var-def/output-type:0")  # Type-tree-is-atom
17212     (check-ints-equal *(eax+4) 1 "F - test-parse-mu-reg-var-def/output-type:1")  # Type-tree-value
17213     (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-reg-var-def/output-type:2")  # Type-tree-right
17214     # . epilogue
17215     89/<- %esp 5/r32/ebp
17216     5d/pop-to-ebp
17217     c3/return
17218 
17219 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)
17220     # pseudocode:
17221     #   var name: slice
17222     #   allocate(Heap, Stmt-size, out)
17223     #   var out-addr: (addr stmt) = lookup(*out)
17224     #   out-addr->tag = stmt
17225     #   if stmt-has-outputs?(line)
17226     #     while true
17227     #       name = next-mu-token(line)
17228     #       if (name == '<-') break
17229     #       assert(is-identifier?(name))
17230     #       var v: (handle var) = lookup-var(name, vars)
17231     #       out-addr->outputs = append(v, out-addr->outputs)
17232     #   add-operation-and-inputs-to-stmt(out-addr, line, vars)
17233     #
17234     # . prologue
17235     55/push-ebp
17236     89/<- %ebp 4/r32/esp
17237     # . save registers
17238     50/push-eax
17239     51/push-ecx
17240     52/push-edx
17241     53/push-ebx
17242     57/push-edi
17243     # var name/ecx: slice
17244     68/push 0/imm32/end
17245     68/push 0/imm32/start
17246     89/<- %ecx 4/r32/esp
17247     # var is-deref?/edx: boolean = false
17248     ba/copy-to-edx 0/imm32/false
17249     # var v: (handle var)
17250     68/push 0/imm32
17251     68/push 0/imm32
17252     89/<- %ebx 4/r32/esp
17253     #
17254     (allocate Heap *Stmt-size *(ebp+0x14))
17255     # var out-addr/edi: (addr stmt) = lookup(*out)
17256     8b/-> *(ebp+0x14) 7/r32/edi
17257     (lookup *edi *(edi+4))  # => eax
17258     89/<- %edi 0/r32/eax
17259     # out-addr->tag = 1/stmt
17260     c7 0/subop/copy *edi 1/imm32/stmt1  # Stmt-tag
17261     {
17262       (stmt-has-outputs? *(ebp+8))
17263       3d/compare-eax-and 0/imm32/false
17264       0f 84/jump-if-= break/disp32
17265       {
17266 $parse-mu-stmt:read-outputs:
17267         # name = next-mu-token(line)
17268         (next-mu-token *(ebp+8) %ecx)
17269         # if slice-empty?(word-slice) break
17270         (slice-empty? %ecx)  # => eax
17271         3d/compare-eax-and 0/imm32/false
17272         0f 85/jump-if-!= break/disp32
17273         # if (name == "<-") break
17274         (slice-equal? %ecx "<-")  # => eax
17275         3d/compare-eax-and 0/imm32/false
17276         0f 85/jump-if-!= break/disp32
17277         # if slice-starts-with?(name, "*") abort
17278         8b/-> *ecx 0/r32/eax  # Slice-start
17279         8a/copy-byte *eax 0/r32/AL
17280         81 4/subop/and %eax 0xff/imm32
17281         3d/compare-eax-and 0x2a/imm32/asterisk
17282         0f 84/jump-if-= $parse-mu-stmt:error-output-dereferenced/disp32
17283         # assert(is-identifier?(name))
17284         (is-identifier? %ecx)  # => eax
17285         3d/compare-eax-and 0/imm32/false
17286         0f 84/jump-if-= $parse-mu-stmt:abort/disp32
17287         #
17288         (lookup-var %ecx *(ebp+0xc) %ebx *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
17289         8d/copy-address *(edi+0x14) 0/r32/eax  # Stmt1-outputs
17290         (append-stmt-var Heap  *ebx *(ebx+4)  *(edi+0x14) *(edi+0x18)  0  %eax)  # Stmt1-outputs
17291         #
17292         e9/jump loop/disp32
17293       }
17294     }
17295     (add-operation-and-inputs-to-stmt %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
17296 $parse-mu-stmt:end:
17297     # . reclaim locals
17298     81 0/subop/add %esp 0x10/imm32
17299     # . restore registers
17300     5f/pop-to-edi
17301     5b/pop-to-ebx
17302     5a/pop-to-edx
17303     59/pop-to-ecx
17304     58/pop-to-eax
17305     # . epilogue
17306     89/<- %esp 5/r32/ebp
17307     5d/pop-to-ebp
17308     c3/return
17309 
17310 $parse-mu-stmt:abort:
17311     # error("invalid identifier '" name "'\n")
17312     (write-buffered *(ebp+0x18) "fn ")
17313     8b/-> *(ebp+0x10) 0/r32/eax
17314     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17315     (write-buffered *(ebp+0x18) %eax)
17316     (write-buffered *(ebp+0x18) ": invalid identifier '")
17317     (write-slice-buffered *(ebp+0x18) %ecx)
17318     (write-buffered *(ebp+0x18) "'\n")
17319     (flush *(ebp+0x18))
17320     (stop *(ebp+0x1c) 1)
17321     # never gets here
17322 
17323 $parse-mu-stmt:error-output-dereferenced:
17324     # error("invalid identifier '" name "'\n")
17325     (write-buffered *(ebp+0x18) "fn ")
17326     8b/-> *(ebp+0x10) 0/r32/eax
17327     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17328     (write-buffered *(ebp+0x18) %eax)
17329     (write-buffered *(ebp+0x18) ": output '")
17330     (write-slice-buffered *(ebp+0x18) %ecx)
17331     (write-buffered *(ebp+0x18) "' should write to a register, and therefore cannot be dereferenced\n")
17332     (flush *(ebp+0x18))
17333     (stop *(ebp+0x1c) 1)
17334     # never gets here
17335 
17336 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)
17337     # pseudocode:
17338     #   stmt->name = slice-to-string(next-mu-token(line))
17339     #   while true
17340     #     name = next-mu-token(line)
17341     #     v = lookup-var-or-literal(name)
17342     #     stmt->inouts = append(v, stmt->inouts)
17343     #
17344     # . prologue
17345     55/push-ebp
17346     89/<- %ebp 4/r32/esp
17347     # . save registers
17348     50/push-eax
17349     51/push-ecx
17350     52/push-edx
17351     53/push-ebx
17352     56/push-esi
17353     57/push-edi
17354     # edi = stmt
17355     8b/-> *(ebp+8) 7/r32/edi
17356     # var name/ecx: slice
17357     68/push 0/imm32/end
17358     68/push 0/imm32/start
17359     89/<- %ecx 4/r32/esp
17360     # var is-deref?/edx: boolean = false
17361     ba/copy-to-edx 0/imm32/false
17362     # var v/esi: (handle var)
17363     68/push 0/imm32
17364     68/push 0/imm32
17365     89/<- %esi 4/r32/esp
17366 $add-operation-and-inputs-to-stmt:read-operation:
17367     (next-mu-token *(ebp+0xc) %ecx)
17368     8d/copy-address *(edi+4) 0/r32/eax  # Stmt1-operation or Regvardef-operationStmt1-operation or Regvardef-operation
17369     (slice-to-string Heap %ecx %eax)
17370     # var is-get?/ebx: boolean = (name == "get")
17371     (slice-equal? %ecx "get")  # => eax
17372     89/<- %ebx 0/r32/eax
17373     {
17374 $add-operation-and-inputs-to-stmt:read-inouts:
17375       # name = next-mu-token(line)
17376       (next-mu-token *(ebp+0xc) %ecx)
17377       # if slice-empty?(word-slice) break
17378       (slice-empty? %ecx)  # => eax
17379       3d/compare-eax-and 0/imm32/false
17380       0f 85/jump-if-!= break/disp32
17381       # if (name == "<-") abort
17382       (slice-equal? %ecx "<-")
17383       3d/compare-eax-and 0/imm32/false
17384       0f 85/jump-if-!= $add-operation-and-inputs-to-stmt:abort/disp32
17385       # if (is-get? && second operand) lookup or create offset
17386       {
17387         81 7/subop/compare %ebx 0/imm32/false
17388         74/jump-if-= break/disp8
17389         (lookup *(edi+0xc) *(edi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
17390         3d/compare-eax-and 0/imm32
17391         74/jump-if-= break/disp8
17392         (lookup-or-create-constant %eax %ecx %esi)
17393 #?         (lookup *esi *(esi+4))
17394 #?         (write-buffered Stderr "creating new output var ")
17395 #?         (write-int32-hex-buffered Stderr %eax)
17396 #?         (write-buffered Stderr " for field called ")
17397 #?         (write-slice-buffered Stderr %ecx)
17398 #?         (write-buffered Stderr "; var name ")
17399 #?         (lookup *eax *(eax+4))  # Var-name
17400 #?         (write-buffered Stderr %eax)
17401 #?         (write-buffered Stderr Newline)
17402 #?         (flush Stderr)
17403         e9/jump $add-operation-and-inputs-to-stmt:save-var/disp32
17404       }
17405       # is-deref? = false
17406       ba/copy-to-edx 0/imm32/false
17407       # if (slice-starts-with?(name, '*')) ++name->start and set is-deref?
17408       8b/-> *ecx 0/r32/eax  # Slice-start
17409       8a/copy-byte *eax 0/r32/AL
17410       81 4/subop/and %eax 0xff/imm32
17411       3d/compare-eax-and 0x2a/imm32/asterisk
17412       {
17413         75/jump-if-!= break/disp8
17414 $add-operation-and-inputs-to-stmt:inout-is-deref:
17415         ff 0/subop/increment *ecx
17416         ba/copy-to-edx 1/imm32/true
17417       }
17418       (lookup-var-or-literal %ecx *(ebp+0x10) %esi *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
17419       # if (is-deref?) some additional checks
17420       81 7/subop/compare %edx 0/imm32/false
17421       {
17422         74/jump-if-= break/disp8
17423         # if var is not in register, abort
17424         (lookup *esi *(esi+4))  # => eax
17425         81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
17426         0f 84/jump-if-= $add-operation-and-inputs-to-stmt:error-deref-on-stack/disp32
17427         # if var is not an address, abort
17428         (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
17429         (is-mu-addr-type? %eax)  # => eax
17430         3d/compare-eax-and 0/imm32/false
17431         0f 84/jump-if-= $add-operation-and-inputs-to-stmt:error-deref-non-addr/disp32
17432       }
17433 $add-operation-and-inputs-to-stmt:save-var:
17434       8d/copy-address *(edi+0xc) 0/r32/eax
17435       (append-stmt-var Heap  *esi *(esi+4)  *(edi+0xc) *(edi+0x10)  %edx  %eax)  # Stmt1-inouts or Regvardef-inouts
17436       #
17437       e9/jump loop/disp32
17438     }
17439 $add-operation-and-inputs-to-stmt:end:
17440     # . reclaim locals
17441     81 0/subop/add %esp 0x10/imm32
17442     # . restore registers
17443     5f/pop-to-edi
17444     5e/pop-to-esi
17445     5b/pop-to-ebx
17446     5a/pop-to-edx
17447     59/pop-to-ecx
17448     58/pop-to-eax
17449     # . epilogue
17450     89/<- %esp 5/r32/ebp
17451     5d/pop-to-ebp
17452     c3/return
17453 
17454 $add-operation-and-inputs-to-stmt:abort:
17455     # error("fn ___: invalid identifier in '" line "'\n")
17456     (write-buffered *(ebp+0x18) "fn ")
17457     8b/-> *(ebp+0x14) 0/r32/eax
17458     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17459     (write-buffered *(ebp+0x18) %eax)
17460     (rewind-stream *(ebp+0xc))
17461     (write-buffered *(ebp+0x18) ": invalid identifier in '")
17462     (write-stream-data *(ebp+0x18) *(ebp+0xc))
17463     (write-buffered *(ebp+0x18) "'\n")
17464     (flush *(ebp+0x18))
17465     (stop *(ebp+0x1c) 1)
17466     # never gets here
17467 
17468 $add-operation-and-inputs-to-stmt:error-deref-on-stack:
17469     # error("fn ___: cannot dereference var ___ on stack\n")
17470     (write-buffered *(ebp+0x18) "fn ")
17471     8b/-> *(ebp+0x14) 0/r32/eax
17472     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17473     (write-buffered *(ebp+0x18) %eax)
17474     (rewind-stream *(ebp+0xc))
17475     (write-buffered *(ebp+0x18) ": cannot dereference var '")
17476     (lookup *esi *(esi+4))  # => eax
17477     (lookup *eax *(eax+4))  # Var-name Var-name => eax
17478     (write-buffered *(ebp+0x18) %eax)
17479     (write-buffered *(ebp+0x18) "' on stack\n")
17480     (flush *(ebp+0x18))
17481     (stop *(ebp+0x1c) 1)
17482     # never gets here
17483 
17484 $add-operation-and-inputs-to-stmt:error-deref-non-addr:
17485     # error("fn ___: cannot dereference non-addr var ___\n")
17486     (write-buffered *(ebp+0x18) "fn ")
17487     8b/-> *(ebp+0x14) 0/r32/eax
17488     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17489     (write-buffered *(ebp+0x18) %eax)
17490     (rewind-stream *(ebp+0xc))
17491     (write-buffered *(ebp+0x18) ": cannot dereference non-addr var '")
17492     (lookup *esi *(esi+4))  # => eax
17493     (lookup *eax *(eax+4))  # Var-name Var-name => eax
17494     (write-buffered *(ebp+0x18) %eax)
17495     (write-buffered *(ebp+0x18) "'\n")
17496     (flush *(ebp+0x18))
17497     (stop *(ebp+0x1c) 1)
17498     # never gets here
17499 
17500 stmt-has-outputs?:  # line: (addr stream byte) -> result/eax: boolean
17501     # . prologue
17502     55/push-ebp
17503     89/<- %ebp 4/r32/esp
17504     # . save registers
17505     51/push-ecx
17506     # var word-slice/ecx: slice
17507     68/push 0/imm32/end
17508     68/push 0/imm32/start
17509     89/<- %ecx 4/r32/esp
17510     # result = false
17511     b8/copy-to-eax 0/imm32/false
17512     (rewind-stream *(ebp+8))
17513     {
17514       (next-mu-token *(ebp+8) %ecx)
17515       # if slice-empty?(word-slice) break
17516       (slice-empty? %ecx)
17517       3d/compare-eax-and 0/imm32/false
17518       b8/copy-to-eax 0/imm32/false/result  # restore result (if we're here it's still false)
17519       0f 85/jump-if-!= break/disp32
17520       # if slice-starts-with?(word-slice, '#') break
17521       # . eax = *word-slice->start
17522       8b/-> *ecx 0/r32/eax
17523       8a/copy-byte *eax 0/r32/AL
17524       81 4/subop/and %eax 0xff/imm32
17525       # . if (eax == '#') break
17526       3d/compare-eax-and 0x23/imm32/hash
17527       b8/copy-to-eax 0/imm32/false/result  # restore result (if we're here it's still false)
17528       0f 84/jump-if-= break/disp32
17529       # if slice-equal?(word-slice, '<-') return true
17530       (slice-equal? %ecx "<-")
17531       3d/compare-eax-and 0/imm32/false
17532       74/jump-if-= loop/disp8
17533       b8/copy-to-eax 1/imm32/true
17534     }
17535 $stmt-has-outputs:end:
17536     (rewind-stream *(ebp+8))
17537     # . reclaim locals
17538     81 0/subop/add %esp 8/imm32
17539     # . restore registers
17540     59/pop-to-ecx
17541     # . epilogue
17542     89/<- %esp 5/r32/ebp
17543     5d/pop-to-ebp
17544     c3/return
17545 
17546 # if 'name' starts with a digit, create a new literal var for it
17547 # otherwise return first 'name' from the top (back) of 'vars' and abort if not found
17548 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)
17549     # . prologue
17550     55/push-ebp
17551     89/<- %ebp 4/r32/esp
17552     # . save registers
17553     50/push-eax
17554     51/push-ecx
17555     56/push-esi
17556     # esi = name
17557     8b/-> *(ebp+8) 6/r32/esi
17558     # if slice-empty?(name) abort
17559     (slice-empty? %esi)  # => eax
17560     3d/compare-eax-and 0/imm32/false
17561     0f 85/jump-if-!= $lookup-var-or-literal:abort/disp32
17562     # var c/ecx: byte = *name->start
17563     8b/-> *esi 1/r32/ecx
17564     8a/copy-byte *ecx 1/r32/CL
17565     81 4/subop/and %ecx 0xff/imm32
17566     # if (is-decimal-digit?(c) || c == '-') return new var(name)
17567     {
17568       81 7/subop/compare %ecx 0x2d/imm32/dash
17569       74/jump-if-= $lookup-var-or-literal:literal/disp8
17570       (is-decimal-digit? %ecx)  # => eax
17571       3d/compare-eax-and 0/imm32/false
17572       74/jump-if-= break/disp8
17573 $lookup-var-or-literal:literal:
17574       (new-literal-integer Heap %esi *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
17575       eb/jump $lookup-var-or-literal:end/disp8
17576     }
17577     # else if (c == '"') return new var(name)
17578     {
17579       81 7/subop/compare %ecx 0x22/imm32/dquote
17580       75/jump-if-!= break/disp8
17581 $lookup-var-or-literal:literal-string:
17582       (new-literal-string Heap %esi *(ebp+0x10))
17583       eb/jump $lookup-var-or-literal:end/disp8
17584     }
17585     # otherwise return lookup-var(name, vars)
17586     {
17587 $lookup-var-or-literal:var:
17588       (lookup-var %esi *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
17589     }
17590 $lookup-var-or-literal:end:
17591     # . restore registers
17592     5e/pop-to-esi
17593     59/pop-to-ecx
17594     58/pop-to-eax
17595     # . epilogue
17596     89/<- %esp 5/r32/ebp
17597     5d/pop-to-ebp
17598     c3/return
17599 
17600 $lookup-var-or-literal:abort:
17601     (write-buffered *(ebp+0x18) "fn ")
17602     8b/-> *(ebp+0x14) 0/r32/eax
17603     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17604     (write-buffered *(ebp+0x18) %eax)
17605     (write-buffered *(ebp+0x18) ": empty variable!")
17606     (flush *(ebp+0x18))
17607     (stop *(ebp+0x1c) 1)
17608     # never gets here
17609 
17610 # return first 'name' from the top (back) of 'vars' and abort if not found
17611 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)
17612     # . prologue
17613     55/push-ebp
17614     89/<- %ebp 4/r32/esp
17615     # . save registers
17616     50/push-eax
17617     #
17618     (lookup-var-helper *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
17619     # if (*out == 0) abort
17620     8b/-> *(ebp+0x10) 0/r32/eax
17621     81 7/subop/compare *eax 0/imm32
17622     74/jump-if-= $lookup-var:abort/disp8
17623 $lookup-var:end:
17624     # . restore registers
17625     58/pop-to-eax
17626     # . epilogue
17627     89/<- %esp 5/r32/ebp
17628     5d/pop-to-ebp
17629     c3/return
17630 
17631 $lookup-var:abort:
17632     (write-buffered *(ebp+0x18) "fn ")
17633     8b/-> *(ebp+0x14) 0/r32/eax
17634     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17635     (write-buffered *(ebp+0x18) %eax)
17636     (write-buffered *(ebp+0x18) ": unknown variable '")
17637     (write-slice-buffered *(ebp+0x18) *(ebp+8))
17638     (write-buffered *(ebp+0x18) "'\n")
17639     (flush *(ebp+0x18))
17640     (stop *(ebp+0x1c) 1)
17641     # never gets here
17642 
17643 # return first 'name' from the top (back) of 'vars', and 0/null if not found
17644 # ensure that 'name' if in a register is the topmost variable in that register
17645 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)
17646     # pseudocode:
17647     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
17648     #   var min = vars->data
17649     #   while curr >= min
17650     #     var v: (handle var) = *curr
17651     #     if v->name == name
17652     #       return
17653     #     curr -= 12
17654     #
17655     # . prologue
17656     55/push-ebp
17657     89/<- %ebp 4/r32/esp
17658     # . save registers
17659     50/push-eax
17660     51/push-ecx
17661     52/push-edx
17662     53/push-ebx
17663     56/push-esi
17664     57/push-edi
17665     # clear out
17666     (zero-out *(ebp+0x10) *Handle-size)
17667     # esi = vars
17668     8b/-> *(ebp+0xc) 6/r32/esi
17669     # ebx = vars->top
17670     8b/-> *esi 3/r32/ebx
17671     # if (vars->top > vars->size) abort
17672     3b/compare<- *(esi+4) 0/r32/eax
17673     0f 8f/jump-if-> $lookup-var-helper:error1/disp32
17674     # var min/edx: (addr handle var) = vars->data
17675     8d/copy-address *(esi+8) 2/r32/edx
17676     # var curr/ebx: (addr handle var) = &vars->data[vars->top - 12]
17677     8d/copy-address *(esi+ebx-4) 3/r32/ebx  # vars + 8 + vars->type - 12
17678     # var var-in-reg/edi: 16 addrs
17679     68/push 0/imm32
17680     68/push 0/imm32
17681     68/push 0/imm32
17682     68/push 0/imm32
17683     68/push 0/imm32
17684     68/push 0/imm32
17685     68/push 0/imm32
17686     68/push 0/imm32
17687     68/push 0/imm32
17688     68/push 0/imm32
17689     68/push 0/imm32
17690     68/push 0/imm32
17691     68/push 0/imm32
17692     68/push 0/imm32
17693     68/push 0/imm32
17694     68/push 0/imm32
17695     89/<- %edi 4/r32/esp
17696     {
17697 $lookup-var-helper:loop:
17698       # if (curr < min) return
17699       39/compare %ebx 2/r32/edx
17700       0f 82/jump-if-addr< break/disp32
17701       # var v/ecx: (addr var) = lookup(*curr)
17702       (lookup *ebx *(ebx+4))  # => eax
17703       89/<- %ecx 0/r32/eax
17704       # var vn/eax: (addr array byte) = lookup(v->name)
17705       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
17706       # if (vn == name) return curr
17707       (slice-equal? *(ebp+8) %eax)  # => eax
17708       3d/compare-eax-and 0/imm32/false
17709       {
17710         74/jump-if-= break/disp8
17711 $lookup-var-helper:found:
17712         # var vr/eax: (addr array byte) = lookup(v->register)
17713         (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
17714         3d/compare-eax-and 0/imm32
17715         {
17716           74/jump-if-= break/disp8
17717 $lookup-var-helper:found-register:
17718           # var reg/eax: int = get(Registers, vr)
17719           (get Mu-registers-unique %eax 0xc "Mu-registers-unique")  # => eax
17720           8b/-> *eax 0/r32/eax
17721           # if (var-in-reg[reg]) error
17722           8b/-> *(edi+eax<<2) 0/r32/eax
17723           3d/compare-eax-and 0/imm32
17724           0f 85/jump-if-!= $lookup-var-helper:error2/disp32
17725         }
17726 $lookup-var-helper:return:
17727         # esi = out
17728         8b/-> *(ebp+0x10) 6/r32/esi
17729         # *out = *curr
17730         8b/-> *ebx 0/r32/eax
17731         89/<- *esi 0/r32/eax
17732         8b/-> *(ebx+4) 0/r32/eax
17733         89/<- *(esi+4) 0/r32/eax
17734         # return
17735         eb/jump $lookup-var-helper:end/disp8
17736       }
17737       # 'name' not yet found; update var-in-reg if v in register
17738       # . var vr/eax: (addr array byte) = lookup(v->register)
17739       (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
17740       # . if (vr == 0) continue
17741       3d/compare-eax-and 0/imm32
17742       74/jump-if-= $lookup-var-helper:continue/disp8
17743       # . var reg/eax: int = get(Registers, vr)
17744       (get Mu-registers-unique %eax 0xc "Mu-registers-unique")  # => eax
17745       8b/-> *eax 0/r32/eax
17746       # . var-in-reg[reg] = v
17747       89/<- *(edi+eax<<2) 1/r32/ecx
17748 $lookup-var-helper:continue:
17749       # curr -= 12
17750       81 5/subop/subtract %ebx 0xc/imm32
17751       e9/jump loop/disp32
17752     }
17753 $lookup-var-helper:end:
17754     # . reclaim locals
17755     81 0/subop/add %esp 0x40/imm32
17756     # . restore registers
17757     5f/pop-to-edi
17758     5e/pop-to-esi
17759     5b/pop-to-ebx
17760     5a/pop-to-edx
17761     59/pop-to-ecx
17762     58/pop-to-eax
17763     # . epilogue
17764     89/<- %esp 5/r32/ebp
17765     5d/pop-to-ebp
17766     c3/return
17767 
17768 $lookup-var-helper:error1:
17769     (write-buffered *(ebp+0x18) "fn ")
17770     8b/-> *(ebp+0x14) 0/r32/eax
17771     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17772     (write-buffered *(ebp+0x18) %eax)
17773     (write-buffered *(ebp+0x18) ": malformed stack when looking up '")
17774     (write-slice-buffered *(ebp+0x18) *(ebp+8))
17775     (write-buffered *(ebp+0x18) "'\n")
17776     (flush *(ebp+0x18))
17777     (stop *(ebp+0x1c) 1)
17778     # never gets here
17779 
17780 $lookup-var-helper:error2:
17781     # eax contains the conflicting var at this point
17782     (write-buffered *(ebp+0x18) "fn ")
17783     50/push-eax
17784     8b/-> *(ebp+0x14) 0/r32/eax
17785     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17786     (write-buffered *(ebp+0x18) %eax)
17787     58/pop-eax
17788     (write-buffered *(ebp+0x18) ": register ")
17789     50/push-eax
17790     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
17791     (write-buffered *(ebp+0x18) %eax)
17792     58/pop-to-eax
17793     (write-buffered *(ebp+0x18) " reads var '")
17794     (write-slice-buffered *(ebp+0x18) *(ebp+8))
17795     (write-buffered *(ebp+0x18) "' after writing var '")
17796     (lookup *eax *(eax+4))  # Var-name Var-name => eax
17797     (write-buffered *(ebp+0x18) %eax)
17798     (write-buffered *(ebp+0x18) "'\n")
17799     (flush *(ebp+0x18))
17800     (stop *(ebp+0x1c) 1)
17801     # never gets here
17802 
17803 dump-vars:  # vars: (addr stack live-var)
17804     # pseudocode:
17805     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
17806     #   var min = vars->data
17807     #   while curr >= min
17808     #     var v: (handle var) = *curr
17809     #     print v
17810     #     curr -= 12
17811     #
17812     # . prologue
17813     55/push-ebp
17814     89/<- %ebp 4/r32/esp
17815     # . save registers
17816     52/push-edx
17817     53/push-ebx
17818     56/push-esi
17819     # esi = vars
17820     8b/-> *(ebp+8) 6/r32/esi
17821     # ebx = vars->top
17822     8b/-> *esi 3/r32/ebx
17823     # var min/edx: (addr handle var) = vars->data
17824     8d/copy-address *(esi+8) 2/r32/edx
17825     # var curr/ebx: (addr handle var) = &vars->data[vars->top - 12]
17826     8d/copy-address *(esi+ebx-4) 3/r32/ebx  # vars + 8 + vars->type - 12
17827     {
17828 $dump-vars:loop:
17829       # if (curr < min) return
17830       39/compare %ebx 2/r32/edx
17831       0f 82/jump-if-addr< break/disp32
17832       #
17833       (write-buffered Stderr "  var@")
17834       (dump-var 2 %ebx)
17835       # curr -= 12
17836       81 5/subop/subtract %ebx 0xc/imm32
17837       e9/jump loop/disp32
17838     }
17839 $dump-vars:end:
17840     # . restore registers
17841     5e/pop-to-esi
17842     5b/pop-to-ebx
17843     5a/pop-to-edx
17844     # . epilogue
17845     89/<- %esp 5/r32/ebp
17846     5d/pop-to-ebp
17847     c3/return
17848 
17849 == data
17850 # Like Registers, but no esp or ebp
17851 Mu-registers:  # (addr stream {(handle array byte), int})
17852   # a table is a stream
17853   0xa8/imm32/write
17854   0/imm32/read
17855   0xa8/imm32/length
17856   # data
17857   # general-purpose registers
17858   # it is perfectly ok to use fake alloc-ids -- as long as you never try to reclaim them
17859   0x11/imm32/alloc-id $Mu-register-eax/imm32 0/imm32
17860   0x11/imm32/alloc-id $Mu-register-ecx/imm32 1/imm32
17861   0x11/imm32/alloc-id $Mu-register-edx/imm32 2/imm32
17862   0x11/imm32/alloc-id $Mu-register-ebx/imm32 3/imm32
17863   0x11/imm32/alloc-id $Mu-register-esi/imm32 6/imm32
17864   0x11/imm32/alloc-id $Mu-register-edi/imm32 7/imm32
17865   # floating-point registers
17866   0x11/imm32/alloc-id $Mu-register-xmm0/imm32 0/imm32
17867   0x11/imm32/alloc-id $Mu-register-xmm1/imm32 1/imm32
17868   0x11/imm32/alloc-id $Mu-register-xmm2/imm32 2/imm32
17869   0x11/imm32/alloc-id $Mu-register-xmm3/imm32 3/imm32
17870   0x11/imm32/alloc-id $Mu-register-xmm4/imm32 4/imm32
17871   0x11/imm32/alloc-id $Mu-register-xmm5/imm32 5/imm32
17872   0x11/imm32/alloc-id $Mu-register-xmm6/imm32 6/imm32
17873   0x11/imm32/alloc-id $Mu-register-xmm7/imm32 7/imm32
17874 
17875 # Like Mu-registers, but with unique codes for integer and floating-point
17876 # registers.
17877 # Don't use this for code-generation, only for checking.
17878 Mu-registers-unique:  # (addr stream {(handle array byte), int})
17879   # a table is a stream
17880   0xa8/imm32/write
17881   0/imm32/read
17882   0xa8/imm32/length
17883   # data
17884   # general-purpose registers
17885   0x11/imm32/alloc-id $Mu-register-eax/imm32 0/imm32
17886   0x11/imm32/alloc-id $Mu-register-ecx/imm32 1/imm32
17887   0x11/imm32/alloc-id $Mu-register-edx/imm32 2/imm32
17888   0x11/imm32/alloc-id $Mu-register-ebx/imm32 3/imm32
17889   0x11/imm32/alloc-id $Mu-register-esi/imm32 6/imm32
17890   0x11/imm32/alloc-id $Mu-register-edi/imm32 7/imm32
17891   # floating-point registers
17892   0x11/imm32/alloc-id $Mu-register-xmm0/imm32 8/imm32
17893   0x11/imm32/alloc-id $Mu-register-xmm1/imm32 9/imm32
17894   0x11/imm32/alloc-id $Mu-register-xmm2/imm32 0xa/imm32
17895   0x11/imm32/alloc-id $Mu-register-xmm3/imm32 0xb/imm32
17896   0x11/imm32/alloc-id $Mu-register-xmm4/imm32 0xc/imm32
17897   0x11/imm32/alloc-id $Mu-register-xmm5/imm32 0xd/imm32
17898   0x11/imm32/alloc-id $Mu-register-xmm6/imm32 0xe/imm32
17899   0x11/imm32/alloc-id $Mu-register-xmm7/imm32 0xf/imm32
17900 
17901 $Mu-register-eax:
17902   0x11/imm32/alloc-id
17903   3/imm32/size
17904   0x65/e 0x61/a 0x78/x
17905 
17906 $Mu-register-ecx:
17907   0x11/imm32/alloc-id
17908   3/imm32/size
17909   0x65/e 0x63/c 0x78/x
17910 
17911 $Mu-register-edx:
17912   0x11/imm32/alloc-id
17913   3/imm32/size
17914   0x65/e 0x64/d 0x78/x
17915 
17916 $Mu-register-ebx:
17917   0x11/imm32/alloc-id
17918   3/imm32/size
17919   0x65/e 0x62/b 0x78/x
17920 
17921 $Mu-register-esi:
17922   0x11/imm32/alloc-id
17923   3/imm32/size
17924   0x65/e 0x73/s 0x69/i
17925 
17926 $Mu-register-edi:
17927   0x11/imm32/alloc-id
17928   3/imm32/size
17929   0x65/e 0x64/d 0x69/i
17930 
17931 $Mu-register-xmm0:
17932   0x11/imm32/alloc-id:fake:payload
17933   # "xmm0"
17934   0x4/imm32/size
17935   0x78/x 0x6d/m 0x6d/m 0x30/0
17936 
17937 $Mu-register-xmm1:
17938   0x11/imm32/alloc-id:fake:payload
17939   # "xmm1"
17940   0x4/imm32/size
17941   0x78/x 0x6d/m 0x6d/m 0x31/1
17942 
17943 $Mu-register-xmm2:
17944   0x11/imm32/alloc-id:fake:payload
17945   # "xmm2"
17946   0x4/imm32/size
17947   0x78/x 0x6d/m 0x6d/m 0x32/2
17948 
17949 $Mu-register-xmm3:
17950   0x11/imm32/alloc-id:fake:payload
17951   # "xmm3"
17952   0x4/imm32/size
17953   0x78/x 0x6d/m 0x6d/m 0x33/3
17954 
17955 $Mu-register-xmm4:
17956   0x11/imm32/alloc-id:fake:payload
17957   # "xmm4"
17958   0x4/imm32/size
17959   0x78/x 0x6d/m 0x6d/m 0x34/4
17960 
17961 $Mu-register-xmm5:
17962   0x11/imm32/alloc-id:fake:payload
17963   # "xmm5"
17964   0x4/imm32/size
17965   0x78/x 0x6d/m 0x6d/m 0x35/5
17966 
17967 $Mu-register-xmm6:
17968   0x11/imm32/alloc-id:fake:payload
17969   # "xmm6"
17970   0x4/imm32/size
17971   0x78/x 0x6d/m 0x6d/m 0x36/6
17972 
17973 $Mu-register-xmm7:
17974   0x11/imm32/alloc-id:fake:payload
17975   # "xmm7"
17976   0x4/imm32/size
17977   0x78/x 0x6d/m 0x6d/m 0x37/7
17978 
17979 == code
17980 
17981 # push 'out' to 'vars' if not already there; it's assumed to be a fn output
17982 maybe-define-var:  # out: (handle var), vars: (addr stack live-var)
17983     # . prologue
17984     55/push-ebp
17985     89/<- %ebp 4/r32/esp
17986     # . save registers
17987     50/push-eax
17988     # var out-addr/eax: (addr var)
17989     (lookup *(ebp+8) *(ebp+0xc))  # => eax
17990     #
17991     (binding-exists? %eax *(ebp+0x10))  # => eax
17992     3d/compare-eax-and 0/imm32/false
17993     75/jump-if-!= $maybe-define-var:end/disp8
17994     # otherwise update vars
17995     (push *(ebp+0x10) *(ebp+8))
17996     (push *(ebp+0x10) *(ebp+0xc))
17997     (push *(ebp+0x10) 0)  # 'out' is always a fn output; never spill it
17998 $maybe-define-var:end:
17999     # . restore registers
18000     58/pop-to-eax
18001     # . epilogue
18002     89/<- %esp 5/r32/ebp
18003     5d/pop-to-ebp
18004     c3/return
18005 
18006 # simpler version of lookup-var-helper
18007 binding-exists?:  # target: (addr var), vars: (addr stack live-var) -> result/eax: boolean
18008     # pseudocode:
18009     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
18010     #   var min = vars->data
18011     #   while curr >= min
18012     #     var v: (handle var) = *curr
18013     #     if v->name == target->name
18014     #       return true
18015     #     curr -= 12
18016     #   return false
18017     #
18018     # . prologue
18019     55/push-ebp
18020     89/<- %ebp 4/r32/esp
18021     # . save registers
18022     51/push-ecx
18023     52/push-edx
18024     56/push-esi
18025     # var target-name/ecx: (addr array byte) = lookup(target->name)
18026     8b/-> *(ebp+8) 0/r32/eax
18027     (lookup *eax *(eax+4))  # Var-name Var-name => eax
18028     89/<- %ecx 0/r32/eax
18029     # esi = vars
18030     8b/-> *(ebp+0xc) 6/r32/esi
18031     # eax = vars->top
18032     8b/-> *esi 0/r32/eax
18033     # var min/edx: (addr handle var) = vars->data
18034     8d/copy-address *(esi+8) 2/r32/edx
18035     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
18036     8d/copy-address *(esi+eax-4) 6/r32/esi  # vars + 8 + vars->type - 12
18037     {
18038 $binding-exists?:loop:
18039       # if (curr < min) return
18040       39/compare %esi 2/r32/edx
18041       0f 82/jump-if-addr< break/disp32
18042       # var v/eax: (addr var) = lookup(*curr)
18043       (lookup *esi *(esi+4))  # => eax
18044       # var vn/eax: (addr array byte) = lookup(v->name)
18045       (lookup *eax *(eax+4))  # Var-name Var-name => eax
18046       # if (vn == target-name) return true
18047       (string-equal? %ecx %eax)  # => eax
18048       3d/compare-eax-and 0/imm32/false
18049       75/jump-if-!= $binding-exists?:end/disp8  # eax already contains true
18050       # curr -= 12
18051       81 5/subop/subtract %esi 0xc/imm32
18052       e9/jump loop/disp32
18053     }
18054     b8/copy-to-eax 0/imm32/false
18055 $binding-exists?:end:
18056     # . restore registers
18057     5e/pop-to-esi
18058     5a/pop-to-edx
18059     59/pop-to-ecx
18060     # . epilogue
18061     89/<- %esp 5/r32/ebp
18062     5d/pop-to-ebp
18063     c3/return
18064 
18065 test-parse-mu-stmt:
18066     # . prologue
18067     55/push-ebp
18068     89/<- %ebp 4/r32/esp
18069     # setup
18070     8b/-> *Primitive-type-ids 0/r32/eax
18071     89/<- *Type-id 0/r32/eax  # stream-write
18072     (clear-stream _test-input-stream)
18073     (write _test-input-stream "increment n\n")
18074     # var vars/ecx: (stack (addr var) 16)
18075     81 5/subop/subtract %esp 0xc0/imm32
18076     68/push 0xc0/imm32/size
18077     68/push 0/imm32/top
18078     89/<- %ecx 4/r32/esp
18079     (clear-stack %ecx)
18080     # var v/edx: (handle var)
18081     68/push 0/imm32
18082     68/push 0/imm32
18083     89/<- %edx 4/r32/esp
18084     # var s/eax: (handle array byte)
18085     68/push 0/imm32
18086     68/push 0/imm32
18087     89/<- %eax 4/r32/esp
18088     # v = new var("n")
18089     (copy-array Heap "n" %eax)
18090     (new-var Heap *eax *(eax+4) %edx)
18091     #
18092     (push %ecx *edx)
18093     (push %ecx *(edx+4))
18094     (push %ecx 0)
18095     # var out/eax: (handle stmt)
18096     68/push 0/imm32
18097     68/push 0/imm32
18098     89/<- %eax 4/r32/esp
18099     # convert
18100     (parse-mu-stmt _test-input-stream %ecx 0 %eax Stderr 0)
18101     # var out-addr/edx: (addr stmt) = lookup(*out)
18102     (lookup *eax *(eax+4))  # => eax
18103     89/<- %edx 0/r32/eax
18104     # out->tag
18105     (check-ints-equal *edx 1 "F - test-parse-mu-stmt/tag")  # Stmt-tag is Stmt1
18106     # out->operation
18107     (lookup *(edx+4) *(edx+8))  # Stmt1-operation Stmt1-operation => eax
18108     (check-strings-equal %eax "increment" "F - test-parse-mu-stmt/name")  # Stmt1-operation
18109     # out->inouts->value->name
18110     # . eax = out->inouts
18111     (lookup *(edx+0xc) *(edx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
18112     # . eax = out->inouts->value
18113     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
18114     # . eax = out->inouts->value->name
18115     (lookup *eax *(eax+4))  # Var-name Var-name => eax
18116     # .
18117     (check-strings-equal %eax "n" "F - test-parse-mu-stmt/inout:0")
18118     # . epilogue
18119     89/<- %esp 5/r32/ebp
18120     5d/pop-to-ebp
18121     c3/return
18122 
18123 test-parse-mu-stmt-with-comma:
18124     # . prologue
18125     55/push-ebp
18126     89/<- %ebp 4/r32/esp
18127     # setup
18128     8b/-> *Primitive-type-ids 0/r32/eax
18129     89/<- *Type-id 0/r32/eax  # stream-write
18130     (clear-stream _test-input-stream)
18131     (write _test-input-stream "copy-to n, 3\n")
18132     # var vars/ecx: (stack (addr var) 16)
18133     81 5/subop/subtract %esp 0xc0/imm32
18134     68/push 0xc0/imm32/size
18135     68/push 0/imm32/top
18136     89/<- %ecx 4/r32/esp
18137     (clear-stack %ecx)
18138     # var v/edx: (handle var)
18139     68/push 0/imm32
18140     68/push 0/imm32
18141     89/<- %edx 4/r32/esp
18142     # var s/eax: (handle array byte)
18143     68/push 0/imm32
18144     68/push 0/imm32
18145     89/<- %eax 4/r32/esp
18146     # v = new var("n")
18147     (copy-array Heap "n" %eax)
18148     (new-var Heap *eax *(eax+4) %edx)
18149     #
18150     (push %ecx *edx)
18151     (push %ecx *(edx+4))
18152     (push %ecx 0)
18153     # var out/eax: (handle stmt)
18154     68/push 0/imm32
18155     68/push 0/imm32
18156     89/<- %eax 4/r32/esp
18157     # convert
18158     (parse-mu-stmt _test-input-stream %ecx 0 %eax Stderr 0)
18159     # var out-addr/edx: (addr stmt) = lookup(*out)
18160     (lookup *eax *(eax+4))  # => eax
18161     89/<- %edx 0/r32/eax
18162     # out->tag
18163     (check-ints-equal *edx 1 "F - test-parse-mu-stmt-with-comma/tag")  # Stmt-tag is Stmt1
18164     # out->operation
18165     (lookup *(edx+4) *(edx+8))  # Stmt1-operation Stmt1-operation => eax
18166     (check-strings-equal %eax "copy-to" "F - test-parse-mu-stmt-with-comma/name")  # Stmt1-operation
18167     # out->inouts->value->name
18168     # . eax = out->inouts
18169     (lookup *(edx+0xc) *(edx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
18170     # . eax = out->inouts->value
18171     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
18172     # . eax = out->inouts->value->name
18173     (lookup *eax *(eax+4))  # Var-name Var-name => eax
18174     # .
18175     (check-strings-equal %eax "n" "F - test-parse-mu-stmt-with-comma/inout:0")
18176     # . epilogue
18177     89/<- %esp 5/r32/ebp
18178     5d/pop-to-ebp
18179     c3/return
18180 
18181 new-var:  # ad: (addr allocation-descriptor), name: (handle array byte), out: (addr handle var)
18182     # . prologue
18183     55/push-ebp
18184     89/<- %ebp 4/r32/esp
18185     # . save registers
18186     50/push-eax
18187     51/push-ecx
18188     # ecx = out
18189     8b/-> *(ebp+0x14) 1/r32/ecx
18190     #
18191     (allocate *(ebp+8) *Var-size %ecx)
18192     # var out-addr/eax: (addr var)
18193     (lookup *ecx *(ecx+4))  # => eax
18194     # out-addr->name = name
18195     8b/-> *(ebp+0xc) 1/r32/ecx
18196     89/<- *eax 1/r32/ecx  # Var-name
18197     8b/-> *(ebp+0x10) 1/r32/ecx
18198     89/<- *(eax+4) 1/r32/ecx  # Var-name
18199 #?     (write-buffered Stderr "var ")
18200 #?     (lookup *(ebp+0xc) *(ebp+0x10))
18201 #?     (write-buffered Stderr %eax)
18202 #?     (write-buffered Stderr " at ")
18203 #?     8b/-> *(ebp+0x14) 1/r32/ecx
18204 #?     (lookup *ecx *(ecx+4))  # => eax
18205 #?     (write-int32-hex-buffered Stderr %eax)
18206 #?     (write-buffered Stderr Newline)
18207 #?     (flush Stderr)
18208 $new-var:end:
18209     # . restore registers
18210     59/pop-to-ecx
18211     58/pop-to-eax
18212     # . epilogue
18213     89/<- %esp 5/r32/ebp
18214     5d/pop-to-ebp
18215     c3/return
18216 
18217 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)
18218     # . prologue
18219     55/push-ebp
18220     89/<- %ebp 4/r32/esp
18221     # . save registers
18222     50/push-eax
18223     51/push-ecx
18224     # if (!is-hex-int?(name)) abort
18225     (is-hex-int? *(ebp+0xc))  # => eax
18226     3d/compare-eax-and 0/imm32/false
18227     0f 84/jump-if-= $new-literal-integer:abort/disp32
18228     # a little more error-checking
18229     (check-mu-hex-int *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
18230     # out = new var(s)
18231     (new-var-from-slice *(ebp+8) *(ebp+0xc) *(ebp+0x10))
18232     # var out-addr/ecx: (addr var) = lookup(*out)
18233     8b/-> *(ebp+0x10) 0/r32/eax
18234     (lookup *eax *(eax+4))  # => eax
18235     89/<- %ecx 0/r32/eax
18236     # out-addr->block-depth = *Curr-block-depth
18237     8b/-> *Curr-block-depth 0/r32/eax
18238     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
18239     # out-addr->type = new tree()
18240     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
18241     (allocate *(ebp+8) *Type-tree-size %eax)
18242     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
18243     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
18244     # nothing else to do; default type is 'literal'
18245 $new-literal-integer:end:
18246     # . reclaim locals
18247     81 0/subop/add %esp 8/imm32
18248     # . restore registers
18249     59/pop-to-ecx
18250     58/pop-to-eax
18251     # . epilogue
18252     89/<- %esp 5/r32/ebp
18253     5d/pop-to-ebp
18254     c3/return
18255 
18256 $new-literal-integer:abort:
18257     (write-buffered *(ebp+0x18) "fn ")
18258     8b/-> *(ebp+0x14) 0/r32/eax
18259     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18260     (write-buffered *(ebp+0x18) %eax)
18261     (write-buffered *(ebp+0x18) ": variable '")
18262     (write-slice-buffered *(ebp+0x18) *(ebp+0xc))
18263     (write-buffered *(ebp+0x18) "' cannot begin with a digit (or do you have a typo in a number?)\n")
18264     (flush *(ebp+0x18))
18265     (stop *(ebp+0x1c) 1)
18266     # never gets here
18267 
18268 # precondition: name is a valid hex integer; require a '0x' prefix
18269 check-mu-hex-int:  # name: (addr slice), err: (addr buffered-file), ed: (addr exit-descriptor)
18270     # . prologue
18271     55/push-ebp
18272     89/<- %ebp 4/r32/esp
18273     # . save registers
18274     50/push-eax
18275     51/push-ecx
18276     52/push-edx
18277     # ecx = name
18278     8b/-> *(ebp+8) 1/r32/ecx
18279     # var start/edx: (addr byte) = name->start
18280     8b/-> *ecx 2/r32/edx
18281     # if (*start == '-') ++start
18282     b8/copy-to-eax 0/imm32
18283     8a/copy-byte *edx 0/r32/AL
18284     3d/compare-eax-and 0x2d/imm32/dash
18285     {
18286       75/jump-if-!= break/disp8
18287       42/increment-edx
18288     }
18289     # var end/ecx: (addr byte) = name->end
18290     8b/-> *(ecx+4) 1/r32/ecx
18291     # var len/eax: int = name->end - name->start
18292     89/<- %eax 1/r32/ecx
18293     29/subtract-from %eax 2/r32/edx
18294     # if (len <= 1) return
18295     3d/compare-eax-with 1/imm32
18296     0f 8e/jump-if-<= $check-mu-hex-int:end/disp32
18297 $check-mu-hex-int:length->-1:
18298     # if slice-starts-with?({start, end}, "0x") return
18299     # . var tmp = {start, end}
18300     51/push-ecx
18301     52/push-edx
18302     89/<- %eax 4/r32/esp
18303     # .
18304     (slice-starts-with? %eax "0x")  # => eax
18305     # . reclaim tmp
18306     81 0/subop/add %esp 8/imm32
18307     # .
18308     3d/compare-eax-with 0/imm32/false
18309     75/jump-if-!= $check-mu-hex-int:end/disp8
18310 $check-mu-hex-int:abort:
18311     # otherwise abort
18312     (write-buffered *(ebp+0xc) "literal integers are always hex in Mu; start '")
18313     (write-slice-buffered *(ebp+0xc) *(ebp+8))
18314     (write-buffered *(ebp+0xc) "' with a '0x' to be unambiguous, converting it to hexadecimal as necessary.\n")
18315     (flush *(ebp+0xc))
18316     (stop *(ebp+0x10) 1)
18317 $check-mu-hex-int:end:
18318     # . restore registers
18319     5a/pop-to-edx
18320     59/pop-to-ecx
18321     58/pop-to-eax
18322     # . epilogue
18323     89/<- %esp 5/r32/ebp
18324     5d/pop-to-ebp
18325     c3/return
18326 
18327 new-literal:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
18328     # . prologue
18329     55/push-ebp
18330     89/<- %ebp 4/r32/esp
18331     # . save registers
18332     50/push-eax
18333     51/push-ecx
18334     # var s/ecx: (handle array byte)
18335     68/push 0/imm32
18336     68/push 0/imm32
18337     89/<- %ecx 4/r32/esp
18338     # s = slice-to-string(name)
18339     (slice-to-string Heap *(ebp+0xc) %ecx)
18340     # allocate to out
18341     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
18342     # var out-addr/ecx: (addr var) = lookup(*out)
18343     8b/-> *(ebp+0x10) 1/r32/ecx
18344     (lookup *ecx *(ecx+4))  # => eax
18345     89/<- %ecx 0/r32/eax
18346     # out-addr->block-depth = *Curr-block-depth
18347     8b/-> *Curr-block-depth 0/r32/eax
18348     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
18349     # out-addr->type/eax = new type
18350     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
18351     (allocate *(ebp+8) *Type-tree-size %eax)
18352     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
18353     # nothing else to do; default type is 'literal'
18354     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
18355 $new-literal:end:
18356     # . reclaim locals
18357     81 0/subop/add %esp 8/imm32
18358     # . restore registers
18359     59/pop-to-ecx
18360     58/pop-to-eax
18361     # . epilogue
18362     89/<- %esp 5/r32/ebp
18363     5d/pop-to-ebp
18364     c3/return
18365 
18366 new-literal-string:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
18367     # . prologue
18368     55/push-ebp
18369     89/<- %ebp 4/r32/esp
18370     # . save registers
18371     50/push-eax
18372     51/push-ecx
18373     # var s/ecx: (handle array byte)
18374     68/push 0/imm32
18375     68/push 0/imm32
18376     89/<- %ecx 4/r32/esp
18377     # s = slice-to-string(name)
18378     (slice-to-string Heap *(ebp+0xc) %ecx)
18379     # allocate to out
18380     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
18381     # var out-addr/ecx: (addr var) = lookup(*out)
18382     8b/-> *(ebp+0x10) 1/r32/ecx
18383     (lookup *ecx *(ecx+4))  # => eax
18384     89/<- %ecx 0/r32/eax
18385     # out-addr->block-depth = *Curr-block-depth
18386     8b/-> *Curr-block-depth 0/r32/eax
18387     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
18388     # out-addr->type/eax = new type
18389     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
18390     (allocate *(ebp+8) *Type-tree-size %eax)
18391     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
18392     # out-addr->type->value = literal-string
18393     c7 0/subop/copy *(eax+4) 0x10/imm32/type-id-string-literal  # Type-tree-value
18394     # out-addr->type->is-atom? = true
18395     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
18396 $new-literal-string:end:
18397     # . reclaim locals
18398     81 0/subop/add %esp 8/imm32
18399     # . restore registers
18400     59/pop-to-ecx
18401     58/pop-to-eax
18402     # . epilogue
18403     89/<- %esp 5/r32/ebp
18404     5d/pop-to-ebp
18405     c3/return
18406 
18407 new-var-from-slice:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
18408     # . prologue
18409     55/push-ebp
18410     89/<- %ebp 4/r32/esp
18411     # . save registers
18412     51/push-ecx
18413     # var tmp/ecx: (handle array byte)
18414     68/push 0/imm32
18415     68/push 0/imm32
18416     89/<- %ecx 4/r32/esp
18417     # tmp = slice-to-string(name)
18418     (slice-to-string Heap *(ebp+0xc) %ecx)
18419     # out = new-var(tmp)
18420     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
18421 $new-var-from-slice:end:
18422     # . reclaim locals
18423     81 0/subop/add %esp 8/imm32
18424     # . restore registers
18425     59/pop-to-ecx
18426     # . epilogue
18427     89/<- %esp 5/r32/ebp
18428     5d/pop-to-ebp
18429     c3/return
18430 
18431 new-var-def:  # ad: (addr allocation-descriptor), var: (handle var), out: (addr handle stmt)
18432     # . prologue
18433     55/push-ebp
18434     89/<- %ebp 4/r32/esp
18435     # . save registers
18436     50/push-eax
18437     51/push-ecx
18438     #
18439     (allocate *(ebp+8) *Stmt-size *(ebp+0x14))
18440     # var out-addr/eax: (addr stmt) = lookup(*out)
18441     8b/-> *(ebp+0x14) 0/r32/eax
18442     (lookup *eax *(eax+4))  # => eax
18443     # out-addr->tag = stmt
18444     c7 0/subop/copy *eax 2/imm32/tag/var-on-stack  # Stmt-tag
18445     # result->var = var
18446     8b/-> *(ebp+0xc) 1/r32/ecx
18447     89/<- *(eax+4) 1/r32/ecx  # Vardef-var
18448     8b/-> *(ebp+0x10) 1/r32/ecx
18449     89/<- *(eax+8) 1/r32/ecx  # Vardef-var
18450 $new-var-def:end:
18451     # . restore registers
18452     59/pop-to-ecx
18453     58/pop-to-eax
18454     # . epilogue
18455     89/<- %esp 5/r32/ebp
18456     5d/pop-to-ebp
18457     c3/return
18458 
18459 new-reg-var-def:  # ad: (addr allocation-descriptor), var: (handle var), out: (addr handle stmt)
18460     # . prologue
18461     55/push-ebp
18462     89/<- %ebp 4/r32/esp
18463     # . save registers
18464     50/push-eax
18465     # eax = out
18466     8b/-> *(ebp+0x14) 0/r32/eax
18467     #
18468     (allocate *(ebp+8) *Stmt-size %eax)
18469     # var out-addr/eax: (addr stmt) = lookup(*out)
18470     (lookup *eax *(eax+4))  # => eax
18471     # set tag
18472     c7 0/subop/copy *eax 3/imm32/tag/var-in-register  # Stmt-tag
18473     # set output
18474     8d/copy-address *(eax+0x14) 0/r32/eax  # Regvardef-outputs
18475     (append-stmt-var Heap  *(ebp+0xc) *(ebp+0x10)  0 0  0  %eax)
18476 $new-reg-var-def:end:
18477     # . restore registers
18478     58/pop-to-eax
18479     # . epilogue
18480     89/<- %esp 5/r32/ebp
18481     5d/pop-to-ebp
18482     c3/return
18483 
18484 append-list:  # ad: (addr allocation-descriptor), value: (handle _type), list: (handle list _type), out: (addr handle list _type)
18485     # . prologue
18486     55/push-ebp
18487     89/<- %ebp 4/r32/esp
18488     # . save registers
18489     50/push-eax
18490     51/push-ecx
18491     57/push-edi
18492     # edi = out
18493     8b/-> *(ebp+0x1c) 7/r32/edi
18494     # *out = new list
18495     (allocate *(ebp+8) *List-size %edi)
18496     # var out-addr/edi: (addr list _type) = lookup(*out)
18497     (lookup *edi *(edi+4))  # => eax
18498     89/<- %edi 0/r32/eax
18499     # out-addr->value = value
18500     8b/-> *(ebp+0xc) 0/r32/eax
18501     89/<- *edi 0/r32/eax  # List-value
18502     8b/-> *(ebp+0x10) 0/r32/eax
18503     89/<- *(edi+4) 0/r32/eax  # List-value
18504     # if (list == null) return
18505     81 7/subop/compare *(ebp+0x14) 0/imm32
18506     74/jump-if-= $append-list:end/disp8
18507     # otherwise append
18508 $append-list:non-empty-list:
18509     # var curr/eax: (addr list _type) = lookup(list)
18510     (lookup *(ebp+0x14) *(ebp+0x18))  # => eax
18511     # while (curr->next != null) curr = curr->next
18512     {
18513       81 7/subop/compare *(eax+8) 0/imm32  # List-next
18514       74/jump-if-= break/disp8
18515       # curr = lookup(curr->next)
18516       (lookup *(eax+8) *(eax+0xc))  # List-next, List-next => eax
18517       #
18518       eb/jump loop/disp8
18519     }
18520     # edi = out
18521     8b/-> *(ebp+0x1c) 7/r32/edi
18522     # curr->next = out
18523     8b/-> *edi 1/r32/ecx
18524     89/<- *(eax+8) 1/r32/ecx  # List-next
18525     8b/-> *(edi+4) 1/r32/ecx
18526     89/<- *(eax+0xc) 1/r32/ecx  # List-next
18527     # out = list
18528     8b/-> *(ebp+0x14) 1/r32/ecx
18529     89/<- *edi 1/r32/ecx
18530     8b/-> *(ebp+0x18) 1/r32/ecx
18531     89/<- *(edi+4) 1/r32/ecx
18532 $append-list:end:
18533     # . restore registers
18534     5f/pop-to-edi
18535     59/pop-to-ecx
18536     58/pop-to-eax
18537     # . epilogue
18538     89/<- %esp 5/r32/ebp
18539     5d/pop-to-ebp
18540     c3/return
18541 
18542 append-stmt-var:  # ad: (addr allocation-descriptor), v: (handle var), vars: (handle stmt-var), is-deref?: boolean, out: (addr handle stmt-var)
18543     # . prologue
18544     55/push-ebp
18545     89/<- %ebp 4/r32/esp
18546     # . save registers
18547     50/push-eax
18548     51/push-ecx
18549     57/push-edi
18550     # edi = out
18551     8b/-> *(ebp+0x20) 7/r32/edi
18552     # out = new stmt-var
18553     (allocate *(ebp+8) *Stmt-var-size %edi)
18554     # var out-addr/ecx: (addr stmt-var) = lookup(*out)
18555     (lookup *edi *(edi+4))  # => eax
18556     89/<- %ecx 0/r32/eax
18557     # out-addr->value = v
18558     8b/-> *(ebp+0xc) 0/r32/eax
18559     89/<- *ecx 0/r32/eax  # Stmt-var-value
18560     8b/-> *(ebp+0x10) 0/r32/eax
18561     89/<- *(ecx+4) 0/r32/eax  # Stmt-var-value
18562     # out-addr->is-deref? = is-deref?
18563     8b/-> *(ebp+0x1c) 0/r32/eax
18564     89/<- *(ecx+0x10) 0/r32/eax  # Stmt-var-is-deref
18565     # if (vars == null) return result
18566     81 7/subop/compare *(ebp+0x14) 0/imm32/null
18567     74/jump-if-= $append-stmt-var:end/disp8
18568     # otherwise append
18569     # var curr/eax: (addr stmt-var) = lookup(vars)
18570     (lookup *(ebp+0x14) *(ebp+0x18))  # => eax
18571     # while (curr->next != null) curr = curr->next
18572     {
18573       81 7/subop/compare *(eax+8) 0/imm32  # Stmt-var-next
18574       74/jump-if-= break/disp8
18575       # curr = lookup(curr->next)
18576       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next, Stmt-var-next => eax
18577       #
18578       eb/jump loop/disp8
18579     }
18580     # curr->next = out
18581     8b/-> *edi 1/r32/ecx
18582     89/<- *(eax+8) 1/r32/ecx  # Stmt-var-next
18583     8b/-> *(edi+4) 1/r32/ecx
18584     89/<- *(eax+0xc) 1/r32/ecx  # Stmt-var-next
18585     # out = vars
18586     8b/-> *(ebp+0x14) 1/r32/ecx
18587     89/<- *edi 1/r32/ecx
18588     8b/-> *(ebp+0x18) 1/r32/ecx
18589     89/<- *(edi+4) 1/r32/ecx
18590 $append-stmt-var:end:
18591     # . restore registers
18592     5f/pop-to-edi
18593     59/pop-to-ecx
18594     58/pop-to-eax
18595     # . epilogue
18596     89/<- %esp 5/r32/ebp
18597     5d/pop-to-ebp
18598     c3/return
18599 
18600 append-to-block:  # ad: (addr allocation-descriptor), block: (addr block), x: (handle stmt)
18601     # . prologue
18602     55/push-ebp
18603     89/<- %ebp 4/r32/esp
18604     # . save registers
18605     50/push-eax
18606     56/push-esi
18607     # esi = block
18608     8b/-> *(ebp+0xc) 6/r32/esi
18609     # block->stmts = append(x, block->stmts)
18610     8d/copy-address *(esi+4) 0/r32/eax  # Block-stmts
18611     (append-list *(ebp+8)  *(ebp+0x10) *(ebp+0x14)  *(esi+4) *(esi+8)  %eax)  # ad, x, x, Block-stmts, Block-stmts
18612 $append-to-block:end:
18613     # . restore registers
18614     5e/pop-to-esi
18615     58/pop-to-eax
18616     # . epilogue
18617     89/<- %esp 5/r32/ebp
18618     5d/pop-to-ebp
18619     c3/return
18620 
18621 ## Parsing types
18622 # We need to create metadata on user-defined types, and we need to use this
18623 # metadata as we parse instructions.
18624 # However, we also want to allow types to be used before their definitions.
18625 # This means we can't ever assume any type data structures exist.
18626 
18627 lookup-or-create-constant:  # container: (addr stmt-var), field-name: (addr slice), out: (addr handle var)
18628     # . prologue
18629     55/push-ebp
18630     89/<- %ebp 4/r32/esp
18631     # . save registers
18632     50/push-eax
18633     56/push-esi
18634     # var container-type/esi: type-id
18635     (container-type *(ebp+8))  # => eax
18636     89/<- %esi 0/r32/eax
18637     # var tmp/eax: (handle typeinfo) = find-or-create-typeinfo(container-type)
18638     68/push 0/imm32
18639     68/push 0/imm32
18640     89/<- %eax 4/r32/esp
18641     (find-or-create-typeinfo %esi %eax)
18642     # var tmp-addr/eax: (addr typeinfo) = lookup(tmp)
18643     (lookup *eax *(eax+4))  # => eax
18644     # result = find-or-create-typeinfo-output-var(typeinfo, field-name)
18645 #?     (write-buffered Stderr "constant: ")
18646 #?     (write-slice-buffered Stderr *(ebp+0xc))
18647 #?     (write-buffered Stderr Newline)
18648 #?     (flush Stderr)
18649     (find-or-create-typeinfo-output-var %eax *(ebp+0xc) *(ebp+0x10))
18650 #?     8b/-> *(ebp+0x10) 0/r32/eax
18651 #?     (write-buffered Stderr "@")
18652 #?     (lookup *eax *(eax+4))
18653 #?     (write-int32-hex-buffered Stderr %eax)
18654 #?     (lookup *eax *(eax+4))
18655 #?     (write-buffered Stderr %eax)
18656 #?     (write-buffered Stderr Newline)
18657 #?     (flush Stderr)
18658 #?     (write-buffered Stderr "offset: ")
18659 #?     8b/-> *(eax+0x14) 0/r32/eax
18660 #?     (write-int32-hex-buffered Stderr %eax)
18661 #?     (write-buffered Stderr Newline)
18662 #?     (flush Stderr)
18663 $lookup-or-create-constant:end:
18664     # . reclaim locals
18665     81 0/subop/add %esp 8/imm32
18666     # . restore registers
18667     5e/pop-to-esi
18668     58/pop-to-eax
18669     # . epilogue
18670     89/<- %esp 5/r32/ebp
18671     5d/pop-to-ebp
18672     c3/return
18673 
18674 # if addr var:
18675 #   container->var->type->right->left->value
18676 # otherwise
18677 #   container->var->type->value
18678 container-type:  # container: (addr stmt-var) -> result/eax: type-id
18679     # . prologue
18680     55/push-ebp
18681     89/<- %ebp 4/r32/esp
18682     #
18683     8b/-> *(ebp+8) 0/r32/eax
18684     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
18685     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
18686     {
18687       81 7/subop/compare *(eax+8) 0/imm32  # Type-tree-right
18688       74/jump-if-= break/disp8
18689       (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
18690       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
18691     }
18692     8b/-> *(eax+4) 0/r32/eax  # Type-tree-value
18693 $container-type:end:
18694     # . epilogue
18695     89/<- %esp 5/r32/ebp
18696     5d/pop-to-ebp
18697     c3/return
18698 
18699 is-container?:  # t: type-id -> result/eax: boolean
18700     # . prologue
18701     55/push-ebp
18702     89/<- %ebp 4/r32/esp
18703     #
18704     8b/-> *(ebp+8) 0/r32/eax
18705     c1/shift 4/subop/left %eax 2/imm8
18706     3b/compare 0/r32/eax *Primitive-type-ids
18707     0f 9d/set-if->= %al
18708     81 4/subop/and %eax 0xff/imm32
18709 $is-container?:end:
18710     # . epilogue
18711     89/<- %esp 5/r32/ebp
18712     5d/pop-to-ebp
18713     c3/return
18714 
18715 find-or-create-typeinfo:  # t: type-id, out: (addr handle typeinfo)
18716     # . prologue
18717     55/push-ebp
18718     89/<- %ebp 4/r32/esp
18719     # . save registers
18720     50/push-eax
18721     51/push-ecx
18722     52/push-edx
18723     57/push-edi
18724     # edi = out
18725     8b/-> *(ebp+0xc) 7/r32/edi
18726     # var fields/ecx: (handle table (handle array byte) (handle typeinfo-entry))
18727     68/push 0/imm32
18728     68/push 0/imm32
18729     89/<- %ecx 4/r32/esp
18730     # find-typeinfo(t, out)
18731     (find-typeinfo *(ebp+8) %edi)
18732     {
18733       # if (*out != 0) break
18734       81 7/subop/compare *edi 0/imm32
18735       0f 85/jump-if-!= break/disp32
18736 $find-or-create-typeinfo:create:
18737       # *out = allocate
18738       (allocate Heap *Typeinfo-size %edi)
18739       # var tmp/eax: (addr typeinfo) = lookup(*out)
18740       (lookup *edi *(edi+4))  # => eax
18741 #?     (write-buffered Stderr "created typeinfo at ")
18742 #?     (write-int32-hex-buffered Stderr %eax)
18743 #?     (write-buffered Stderr " for type-id ")
18744 #?     (write-int32-hex-buffered Stderr *(ebp+8))
18745 #?     (write-buffered Stderr Newline)
18746 #?     (flush Stderr)
18747       # tmp->id = t
18748       8b/-> *(ebp+8) 2/r32/edx
18749       89/<- *eax 2/r32/edx  # Typeinfo-id
18750       # tmp->fields = new table
18751       # . fields = new table
18752       (new-stream Heap 0x40 *Typeinfo-fields-row-size %ecx)
18753       # . tmp->fields = fields
18754       8b/-> *ecx 2/r32/edx
18755       89/<- *(eax+4) 2/r32/edx  # Typeinfo-fields
18756       8b/-> *(ecx+4) 2/r32/edx
18757       89/<- *(eax+8) 2/r32/edx  # Typeinfo-fields
18758       # tmp->next = Program->types
18759       8b/-> *_Program-types 1/r32/ecx
18760       89/<- *(eax+0x10) 1/r32/ecx  # Typeinfo-next
18761       8b/-> *_Program-types->payload 1/r32/ecx
18762       89/<- *(eax+0x14) 1/r32/ecx  # Typeinfo-next
18763       # Program->types = out
18764       8b/-> *edi 1/r32/ecx
18765       89/<- *_Program-types 1/r32/ecx
18766       8b/-> *(edi+4) 1/r32/ecx
18767       89/<- *_Program-types->payload 1/r32/ecx
18768     }
18769 $find-or-create-typeinfo:end:
18770     # . reclaim locals
18771     81 0/subop/add %esp 8/imm32
18772     # . restore registers
18773     5f/pop-to-edi
18774     5a/pop-to-edx
18775     59/pop-to-ecx
18776     58/pop-to-eax
18777     # . epilogue
18778     89/<- %esp 5/r32/ebp
18779     5d/pop-to-ebp
18780     c3/return
18781 
18782 find-typeinfo:  # t: type-id, out: (addr handle typeinfo)
18783     # . prologue
18784     55/push-ebp
18785     89/<- %ebp 4/r32/esp
18786     # . save registers
18787     50/push-eax
18788     51/push-ecx
18789     52/push-edx
18790     57/push-edi
18791     # ecx = t
18792     8b/-> *(ebp+8) 1/r32/ecx
18793     # edi = out
18794     8b/-> *(ebp+0xc) 7/r32/edi
18795     # *out = Program->types
18796     8b/-> *_Program-types 0/r32/eax
18797     89/<- *edi 0/r32/eax
18798     8b/-> *_Program-types->payload 0/r32/eax
18799     89/<- *(edi+4) 0/r32/eax
18800     {
18801 $find-typeinfo:loop:
18802       # if (*out == 0) break
18803       81 7/subop/compare *edi 0/imm32
18804       74/jump-if-= break/disp8
18805 $find-typeinfo:check:
18806       # var tmp/eax: (addr typeinfo) = lookup(*out)
18807       (lookup *edi *(edi+4))  # => eax
18808       # if (tmp->id == t) break
18809       39/compare *eax 1/r32/ecx  # Typeinfo-id
18810       74/jump-if-= break/disp8
18811 $find-typeinfo:continue:
18812       # *out = tmp->next
18813       8b/-> *(eax+0x10) 2/r32/edx  # Typeinfo-next
18814       89/<- *edi 2/r32/edx
18815       8b/-> *(eax+0x14) 2/r32/edx  # Typeinfo-next
18816       89/<- *(edi+4) 2/r32/edx
18817       #
18818       eb/jump loop/disp8
18819     }
18820 $find-typeinfo:end:
18821     # . restore registers
18822     5f/pop-to-edi
18823     5a/pop-to-edx
18824     59/pop-to-ecx
18825     58/pop-to-eax
18826     # . epilogue
18827     89/<- %esp 5/r32/ebp
18828     5d/pop-to-ebp
18829     c3/return
18830 
18831 find-or-create-typeinfo-output-var:  # T: (addr typeinfo), f: (addr slice), out: (addr handle var)
18832     # . prologue
18833     55/push-ebp
18834     89/<- %ebp 4/r32/esp
18835     # . save registers
18836     50/push-eax
18837     52/push-edx
18838     57/push-edi
18839     # var dest/edi: (handle typeinfo-entry)
18840     68/push 0/imm32
18841     68/push 0/imm32
18842     89/<- %edi 4/r32/esp
18843     # find-or-create-typeinfo-fields(T, f, dest)
18844     (find-or-create-typeinfo-fields *(ebp+8) *(ebp+0xc) %edi)
18845     # var dest-addr/edi: (addr typeinfo-entry) = lookup(dest)
18846     (lookup *edi *(edi+4))  # => eax
18847     89/<- %edi 0/r32/eax
18848     # if dest-addr->output-var doesn't exist, create it
18849     {
18850       81 7/subop/compare *(edi+0xc) 0/imm32  # Typeinfo-entry-output-var
18851       0f 85/jump-if-!= break/disp32
18852       # dest-addr->output-var = new var(dummy name, type, -1 offset)
18853       # . var name/eax: (handle array byte) = "field"
18854       68/push 0/imm32
18855       68/push 0/imm32
18856       89/<- %eax 4/r32/esp
18857       (slice-to-string Heap *(ebp+0xc) %eax)
18858       # . new var
18859       8d/copy-address *(edi+0xc) 2/r32/edx
18860       (new-var Heap  *eax *(eax+4)  %edx)
18861       # . reclaim name
18862       81 0/subop/add %esp 8/imm32
18863       # var result/edx: (addr var) = lookup(dest-addr->output-var)
18864       (lookup *(edi+0xc) *(edi+0x10))  # => eax
18865       89/<- %edx 0/r32/eax
18866       # result->type = new constant type
18867       8d/copy-address *(edx+8) 0/r32/eax  # Var-type
18868       (allocate Heap *Type-tree-size %eax)
18869       (lookup *(edx+8) *(edx+0xc))  # => eax
18870       c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
18871       c7 0/subop/copy *(eax+4) 6/imm32/constant  # Type-tree-value
18872       c7 0/subop/copy *(eax+8) 0/imm32  # Type-tree-left
18873       c7 0/subop/copy *(eax+0xc) 0/imm32  # Type-tree-right
18874       c7 0/subop/copy *(eax+0x10) 0/imm32  # Type-tree-right
18875       # result->offset isn't filled out yet
18876       c7 0/subop/copy *(edx+0x14) -1/imm32/uninitialized  # Var-offset
18877     }
18878     # out = dest-addr->output-var
18879     8b/-> *(ebp+0x10) 2/r32/edx
18880     8b/-> *(edi+0xc) 0/r32/eax  # Typeinfo-entry-output-var
18881     89/<- *edx 0/r32/eax
18882     8b/-> *(edi+0x10) 0/r32/eax  # Typeinfo-entry-output-var
18883     89/<- *(edx+4) 0/r32/eax
18884 $find-or-create-typeinfo-output-var:end:
18885     # . reclaim locals
18886     81 0/subop/add %esp 8/imm32
18887     # . restore registers
18888     5f/pop-to-edi
18889     5a/pop-to-edx
18890     58/pop-to-eax
18891     # . epilogue
18892     89/<- %esp 5/r32/ebp
18893     5d/pop-to-ebp
18894     c3/return
18895 
18896 find-or-create-typeinfo-fields:  # T: (addr typeinfo), f: (addr slice), out: (addr handle typeinfo-entry)
18897     # . prologue
18898     55/push-ebp
18899     89/<- %ebp 4/r32/esp
18900     # . save registers
18901     50/push-eax
18902     56/push-esi
18903     57/push-edi
18904     # eax = lookup(T->fields)
18905     8b/-> *(ebp+8) 0/r32/eax
18906     (lookup *(eax+4) *(eax+8))  # Typeinfo-fields Typeinfo-fields => eax
18907     # edi = out
18908     8b/-> *(ebp+0x10) 7/r32/edi
18909     # var src/esi: (addr handle typeinfo-entry) = get-or-insert-slice(T->fields, f)
18910     (get-or-insert-slice %eax *(ebp+0xc) *Typeinfo-fields-row-size Heap)  # => eax
18911     89/<- %esi 0/r32/eax
18912     # if src doesn't exist, allocate it
18913     {
18914       81 7/subop/compare *esi 0/imm32
18915       75/jump-if-!= break/disp8
18916       (allocate Heap *Typeinfo-entry-size %esi)
18917 #?       (write-buffered Stderr "handle at ")
18918 #?       (write-int32-hex-buffered Stderr %esi)
18919 #?       (write-buffered Stderr ": ")
18920 #?       (write-int32-hex-buffered Stderr *esi)
18921 #?       (write-buffered Stderr " ")
18922 #?       (write-int32-hex-buffered Stderr *(esi+4))
18923 #?       (write-buffered Stderr Newline)
18924 #?       (flush Stderr)
18925 #?       (lookup *esi *(esi+4))
18926 #?       (write-buffered Stderr "created typeinfo fields at ")
18927 #?       (write-int32-hex-buffered Stderr %esi)
18928 #?       (write-buffered Stderr " for ")
18929 #?       (write-int32-hex-buffered Stderr *(ebp+8))
18930 #?       (write-buffered Stderr Newline)
18931 #?       (flush Stderr)
18932     }
18933     # *out = src
18934     # . *edi = *src
18935     8b/-> *esi 0/r32/eax
18936     89/<- *edi 0/r32/eax
18937     8b/-> *(esi+4) 0/r32/eax
18938     89/<- *(edi+4) 0/r32/eax
18939 $find-or-create-typeinfo-fields:end:
18940     # . restore registers
18941     5f/pop-to-edi
18942     5e/pop-to-esi
18943     58/pop-to-eax
18944     # . epilogue
18945     89/<- %esp 5/r32/ebp
18946     5d/pop-to-ebp
18947     c3/return
18948 
18949 populate-mu-type:  # in: (addr stream byte), t: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
18950     # pseudocode:
18951     #   var line: (stream byte 512)
18952     #   curr-index = 0
18953     #   while true
18954     #     clear-stream(line)
18955     #     read-line-buffered(in, line)
18956     #     if line->write == 0
18957     #       abort
18958     #     word-slice = next-mu-token(line)
18959     #     if slice-empty?(word-slice)               # end of line
18960     #       continue
18961     #     if slice-equal?(word-slice, "}")
18962     #       break
18963     #     var v: (handle var) = parse-var-with-type(word-slice, line)
18964     #     var r: (handle typeinfo-fields) = find-or-create-typeinfo-fields(t, word-slice/v->name)
18965     #     TODO: ensure that r->first is null
18966     #     r->index = curr-index
18967     #     curr-index++
18968     #     r->input-var = v
18969     #     if r->output-var == 0
18970     #       r->output-var = new literal
18971     #     TODO: ensure nothing else in line
18972     # t->total-size-in-bytes = -2 (not yet initialized)
18973     #
18974     # . prologue
18975     55/push-ebp
18976     89/<- %ebp 4/r32/esp
18977     # var curr-index: int at *(ebp-4)
18978     68/push 0/imm32
18979     # . save registers
18980     50/push-eax
18981     51/push-ecx
18982     52/push-edx
18983     53/push-ebx
18984     56/push-esi
18985     57/push-edi
18986     # edi = t
18987     8b/-> *(ebp+0xc) 7/r32/edi
18988     # var line/ecx: (stream byte 512)
18989     81 5/subop/subtract %esp 0x200/imm32
18990     68/push 0x200/imm32/size
18991     68/push 0/imm32/read
18992     68/push 0/imm32/write
18993     89/<- %ecx 4/r32/esp
18994     # var word-slice/edx: slice
18995     68/push 0/imm32/end
18996     68/push 0/imm32/start
18997     89/<- %edx 4/r32/esp
18998     # var v/esi: (handle var)
18999     68/push 0/imm32
19000     68/push 0/imm32
19001     89/<- %esi 4/r32/esp
19002     # var r/ebx: (handle typeinfo-entry)
19003     68/push 0/imm32
19004     68/push 0/imm32
19005     89/<- %ebx 4/r32/esp
19006     {
19007 $populate-mu-type:line-loop:
19008       (clear-stream %ecx)
19009       (read-line-buffered *(ebp+8) %ecx)
19010       # if (line->write == 0) abort
19011       81 7/subop/compare *ecx 0/imm32
19012       0f 84/jump-if-= $populate-mu-type:error1/disp32
19013 +--  6 lines: #?       # dump line ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
19019       (next-mu-token %ecx %edx)
19020       # if slice-empty?(word-slice) continue
19021       (slice-empty? %edx)  # => eax
19022       3d/compare-eax-and 0/imm32
19023       0f 85/jump-if-!= loop/disp32
19024       # if slice-equal?(word-slice, "}") break
19025       (slice-equal? %edx "}")
19026       3d/compare-eax-and 0/imm32
19027       0f 85/jump-if-!= break/disp32
19028 $populate-mu-type:parse-element:
19029       # v = parse-var-with-type(word-slice, first-line)
19030       # must do this first to strip the trailing ':' from word-slice before
19031       # using it in find-or-create-typeinfo-fields below
19032       # TODO: clean up that mutation in parse-var-with-type
19033       (type-name *edi)  # Typeinfo-id => eax
19034       (parse-var-with-type %edx %ecx %esi %eax *(ebp+0x10) *(ebp+0x14))
19035       # if v is an addr, abort
19036       (lookup *esi *(esi+4))  # => eax
19037       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
19038       (is-mu-addr-type? %eax)  # => eax
19039       3d/compare-eax-and 0/imm32/false
19040       0f 85/jump-if-!= $populate-mu-type:error2/disp32
19041       # if v is an array, abort  (we could support it, but initialization gets complex)
19042       (lookup *esi *(esi+4))  # => eax
19043       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
19044       (is-mu-array-type? %eax)  # => eax
19045       3d/compare-eax-and 0/imm32/false
19046       0f 85/jump-if-!= $populate-mu-type:error3/disp32
19047       # if v is a byte, abort
19048       (lookup *esi *(esi+4))  # => eax
19049       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
19050       (is-simple-mu-type? %eax 8)  # byte => eax
19051       3d/compare-eax-and 0/imm32/false
19052       0f 85/jump-if-!= $populate-mu-type:error4/disp32
19053       # if v is a slice, abort
19054       (lookup *esi *(esi+4))  # => eax
19055       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
19056       (is-simple-mu-type? %eax 0xc)  # slice => eax
19057       3d/compare-eax-and 0/imm32/false
19058       0f 85/jump-if-!= $populate-mu-type:error5/disp32
19059       # if v is a stream, abort  (we could support it, but initialization gets even more complex)
19060       (lookup *esi *(esi+4))  # => eax
19061       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
19062       (is-mu-stream-type? %eax)  # => eax
19063       3d/compare-eax-and 0/imm32/false
19064       0f 85/jump-if-!= $populate-mu-type:error6/disp32
19065       # var tmp/ecx
19066       51/push-ecx
19067 $populate-mu-type:create-typeinfo-fields:
19068       # var r/ebx: (handle typeinfo-entry)
19069       (find-or-create-typeinfo-fields %edi %edx %ebx)
19070       # r->index = curr-index
19071       (lookup *ebx *(ebx+4))  # => eax
19072       8b/-> *(ebp-4) 1/r32/ecx
19073 #?       (write-buffered Stderr "saving index ")
19074 #?       (write-int32-hex-buffered Stderr %ecx)
19075 #?       (write-buffered Stderr " at ")
19076 #?       (write-int32-hex-buffered Stderr %edi)
19077 #?       (write-buffered Stderr Newline)
19078 #?       (flush Stderr)
19079       89/<- *(eax+8) 1/r32/ecx  # Typeinfo-entry-index
19080       # ++curr-index
19081       ff 0/subop/increment *(ebp-4)
19082 $populate-mu-type:set-input-type:
19083       # r->input-var = v
19084       8b/-> *esi 1/r32/ecx
19085       89/<- *eax 1/r32/ecx  # Typeinfo-entry-input-var
19086       8b/-> *(esi+4) 1/r32/ecx
19087       89/<- *(eax+4) 1/r32/ecx  # Typeinfo-entry-input-var
19088       # restore line
19089       59/pop-to-ecx
19090       {
19091 $populate-mu-type:create-output-type:
19092         # if (r->output-var == 0) create a new var with some placeholder data
19093         81 7/subop/compare *(eax+0xc) 0/imm32  # Typeinfo-entry-output-var
19094         75/jump-if-!= break/disp8
19095         8d/copy-address *(eax+0xc) 0/r32/eax  # Typeinfo-entry-output-var
19096         (new-literal Heap %edx %eax)
19097       }
19098       e9/jump loop/disp32
19099     }
19100 $populate-mu-type:invalidate-total-size-in-bytes:
19101     # Offsets and total size may not be accurate here since we may not yet
19102     # have encountered the element types.
19103     # We'll recompute them separately after parsing the entire program.
19104     c7 0/subop/copy *(edi+0xc) -2/imm32/uninitialized  # Typeinfo-total-size-in-bytes
19105 $populate-mu-type:end:
19106     # . reclaim locals
19107     81 0/subop/add %esp 0x224/imm32
19108     # . restore registers
19109     5f/pop-to-edi
19110     5e/pop-to-esi
19111     5b/pop-to-ebx
19112     5a/pop-to-edx
19113     59/pop-to-ecx
19114     58/pop-to-eax
19115     # reclaim curr-index
19116     81 0/subop/add %esp 4/imm32
19117     # . epilogue
19118     89/<- %esp 5/r32/ebp
19119     5d/pop-to-ebp
19120     c3/return
19121 
19122 $populate-mu-type:error1:
19123     # error("incomplete type definition '" t->name "'\n")
19124     (write-buffered *(ebp+0x10) "incomplete type definition '")
19125     (type-name *edi)  # Typeinfo-id => eax
19126     (write-buffered *(ebp+0x10) %eax)
19127     (write-buffered *(ebp+0x10) "\n")
19128     (flush *(ebp+0x10))
19129     (stop *(ebp+0x14) 1)
19130     # never gets here
19131 
19132 $populate-mu-type:error2:
19133     (write-buffered *(ebp+0x10) "type ")
19134     (type-name *edi)  # Typeinfo-id => eax
19135     (write-buffered *(ebp+0x10) %eax)
19136     (write-buffered *(ebp+0x10) ": 'addr' elements not allowed\n")
19137     (flush *(ebp+0x10))
19138     (stop *(ebp+0x14) 1)
19139     # never gets here
19140 
19141 $populate-mu-type:error3:
19142     (write-buffered *(ebp+0x10) "type ")
19143     (type-name *edi)  # Typeinfo-id => eax
19144     (write-buffered *(ebp+0x10) %eax)
19145     (write-buffered *(ebp+0x10) ": 'array' elements not allowed for now\n")
19146     (flush *(ebp+0x10))
19147     (stop *(ebp+0x14) 1)
19148     # never gets here
19149 
19150 $populate-mu-type:error4:
19151     (write-buffered *(ebp+0x10) "type ")
19152     (type-name *edi)  # Typeinfo-id => eax
19153     (write-buffered *(ebp+0x10) %eax)
19154     (write-buffered *(ebp+0x10) ": 'byte' elements not allowed\n")
19155     (flush *(ebp+0x10))
19156     (stop *(ebp+0x14) 1)
19157     # never gets here
19158 
19159 $populate-mu-type:error5:
19160     (write-buffered *(ebp+0x10) "type ")
19161     (type-name *edi)  # Typeinfo-id => eax
19162     (write-buffered *(ebp+0x10) %eax)
19163     (write-buffered *(ebp+0x10) ": 'slice' elements not allowed\n")
19164     (flush *(ebp+0x10))
19165     (stop *(ebp+0x14) 1)
19166     # never gets here
19167 
19168 $populate-mu-type:error6:
19169     (write-buffered *(ebp+0x10) "type ")
19170     (type-name *edi)  # Typeinfo-id => eax
19171     (write-buffered *(ebp+0x10) %eax)
19172     (write-buffered *(ebp+0x10) ": 'stream' elements not allowed for now\n")
19173     (flush *(ebp+0x10))
19174     (stop *(ebp+0x14) 1)
19175     # never gets here
19176 
19177 type-name:  # index: int -> result/eax: (addr array byte)
19178     # . prologue
19179     55/push-ebp
19180     89/<- %ebp 4/r32/esp
19181     #
19182     (index Type-id *(ebp+8))
19183 $type-name:end:
19184     # . epilogue
19185     89/<- %esp 5/r32/ebp
19186     5d/pop-to-ebp
19187     c3/return
19188 
19189 index:  # arr: (addr stream (handle array byte)), index: int -> result/eax: (addr array byte)
19190     # . prologue
19191     55/push-ebp
19192     89/<- %ebp 4/r32/esp
19193     # . save registers
19194     56/push-esi
19195     # TODO: bounds-check index
19196     # esi = arr
19197     8b/-> *(ebp+8) 6/r32/esi
19198     # eax = index
19199     8b/-> *(ebp+0xc) 0/r32/eax
19200     # eax = *(arr + 12 + index)
19201     8b/-> *(esi+eax<<2+0xc) 0/r32/eax
19202 $index:end:
19203     # . restore registers
19204     5e/pop-to-esi
19205     # . epilogue
19206     89/<- %esp 5/r32/ebp
19207     5d/pop-to-ebp
19208     c3/return
19209 
19210 #######################################################
19211 # Compute type sizes
19212 #######################################################
19213 
19214 # Compute the sizes of all user-defined types.
19215 # We'll need the sizes of their elements, which may be other user-defined
19216 # types, which we will compute as needed.
19217 
19218 # Initially, all user-defined types have their sizes set to -2 (invalid)
19219 populate-mu-type-sizes:  # err: (addr buffered-file), ed: (addr exit-descriptor)
19220     # . prologue
19221     55/push-ebp
19222     89/<- %ebp 4/r32/esp
19223 $populate-mu-type-sizes:total-sizes:
19224     # var curr/eax: (addr typeinfo) = lookup(Program->types)
19225     (lookup *_Program-types *_Program-types->payload)  # => eax
19226     {
19227       # if (curr == null) break
19228       3d/compare-eax-and 0/imm32/null
19229       74/jump-if-= break/disp8
19230       (populate-mu-type-sizes-in-type %eax *(ebp+8) *(ebp+0xc))
19231       # curr = lookup(curr->next)
19232       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
19233       eb/jump loop/disp8
19234     }
19235 $populate-mu-type-sizes:offsets:
19236     # curr = *Program->types
19237     (lookup *_Program-types *_Program-types->payload)  # => eax
19238     {
19239       # if (curr == null) break
19240       3d/compare-eax-and 0/imm32/null
19241       74/jump-if-= break/disp8
19242       (populate-mu-type-offsets %eax *(ebp+8) *(ebp+0xc))
19243       # curr = curr->next
19244       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
19245       eb/jump loop/disp8
19246     }
19247 $populate-mu-type-sizes:end:
19248     # . epilogue
19249     89/<- %esp 5/r32/ebp
19250     5d/pop-to-ebp
19251     c3/return
19252 
19253 # compute sizes of all fields, recursing as necessary
19254 # sum up all their sizes to arrive at total size
19255 # fields may be out of order, but that doesn't affect the answer
19256 populate-mu-type-sizes-in-type:  # T: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
19257     # . prologue
19258     55/push-ebp
19259     89/<- %ebp 4/r32/esp
19260     # . save registers
19261     50/push-eax
19262     51/push-ecx
19263     52/push-edx
19264     56/push-esi
19265     57/push-edi
19266     # esi = T
19267     8b/-> *(ebp+8) 6/r32/esi
19268     # if T is already computed, return
19269     81 7/subop/compare *(esi+0xc) 0/imm32  # Typeinfo-total-size-in-bytes
19270     0f 8d/jump-if->= $populate-mu-type-sizes-in-type:end/disp32
19271     # if T is being computed, abort
19272     81 7/subop/compare *(esi+0xc) -1/imm32/being-computed  # Typeinfo-total-size-in-bytes
19273     0f 84/jump-if-= $populate-mu-type-sizes-in-type:abort/disp32
19274     # tag T (-2 to -1) to avoid infinite recursion
19275     c7 0/subop/copy *(esi+0xc) -1/imm32/being-computed  # Typeinfo-total-size-in-bytes
19276     # var total-size/edi: int = 0
19277     bf/copy-to-edi 0/imm32
19278     # - for every field, if it's a user-defined type, compute its size
19279     # var table/ecx: (addr table (handle array byte) (handle typeinfo-entry)) = lookup(T->fields)
19280     (lookup *(esi+4) *(esi+8))  # Typeinfo-fields Typeinfo-fields => eax
19281     89/<- %ecx 0/r32/eax
19282     # var table-size/edx: int = table->write
19283     8b/-> *ecx 2/r32/edx  # stream-write
19284     # var curr/ecx: (addr table_row) = table->data
19285     8d/copy-address *(ecx+0xc) 1/r32/ecx
19286     # var max/edx: (addr table_row) = table->data + table->write
19287     8d/copy-address *(ecx+edx) 2/r32/edx
19288     {
19289 $populate-mu-type-sizes-in-type:loop:
19290       # if (curr >= max) break
19291       39/compare %ecx 2/r32/edx
19292       73/jump-if-addr>= break/disp8
19293       # var t/eax: (addr typeinfo-entry) = lookup(curr->value)
19294       (lookup *(ecx+8) *(ecx+0xc))  # => eax
19295       # if (t->input-var == 0) silently ignore it; we'll emit a nice error message while type-checking
19296       81 7/subop/compare *eax 0/imm32  # Typeinfo-entry-input-var
19297       74/jump-if-= $populate-mu-type-sizes-in-type:end/disp8
19298       # compute size of t->input-var
19299       (lookup *eax *(eax+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
19300       (compute-size-of-var %eax *(ebp+0xc) *(ebp+0x10))  # => eax
19301       # result += eax
19302       01/add-to %edi 0/r32/eax
19303       # curr += row-size
19304       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-fields-row-size
19305       #
19306       eb/jump loop/disp8
19307     }
19308     # - save result
19309     89/<- *(esi+0xc) 7/r32/edi  # Typeinfo-total-size-in-bytes
19310 $populate-mu-type-sizes-in-type:end:
19311     # . restore registers
19312     5f/pop-to-edi
19313     5e/pop-to-esi
19314     5a/pop-to-edx
19315     59/pop-to-ecx
19316     58/pop-to-eax
19317     # . epilogue
19318     89/<- %esp 5/r32/ebp
19319     5d/pop-to-ebp
19320     c3/return
19321 
19322 $populate-mu-type-sizes-in-type:abort:
19323     (write-buffered *(ebp+0xc) "cycle in type definitions\n")
19324     (flush *(ebp+0xc))
19325     (stop *(ebp+0x10) 1)
19326     # never gets here
19327 
19328 # Analogous to size-of, except we need to compute what size-of can just read
19329 # off the right data structures.
19330 compute-size-of-var:  # in: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
19331     # . prologue
19332     55/push-ebp
19333     89/<- %ebp 4/r32/esp
19334     # . push registers
19335     51/push-ecx
19336     # var t/ecx: (addr type-tree) = lookup(v->type)
19337     8b/-> *(ebp+8) 1/r32/ecx
19338     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
19339     89/<- %ecx 0/r32/eax
19340     # if (t->is-atom == false) t = lookup(t->left)
19341     {
19342       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
19343       75/jump-if-!= break/disp8
19344       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
19345       89/<- %ecx 0/r32/eax
19346     }
19347     # TODO: ensure t is an atom
19348     (compute-size-of-type-id *(ecx+4) *(ebp+0xc) *(ebp+0x10))  # Type-tree-value => eax
19349 $compute-size-of-var:end:
19350     # . restore registers
19351     59/pop-to-ecx
19352     # . epilogue
19353     89/<- %esp 5/r32/ebp
19354     5d/pop-to-ebp
19355     c3/return
19356 
19357 compute-size-of-type-id:  # t: type-id, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
19358     # . prologue
19359     55/push-ebp
19360     89/<- %ebp 4/r32/esp
19361     # . save registers
19362     51/push-ecx
19363     # var out/ecx: (handle typeinfo)
19364     68/push 0/imm32
19365     68/push 0/imm32
19366     89/<- %ecx 4/r32/esp
19367     # eax = t
19368     8b/-> *(ebp+8) 0/r32/eax
19369     # if t is a literal, return 0
19370     3d/compare-eax-and 0/imm32/literal
19371     0f 84/jump-if-= $compute-size-of-type-id:end/disp32  # eax changes type from type-id to int
19372     # if t is a byte, return 4 (because we don't really support non-multiples of 4)
19373     3d/compare-eax-and 8/imm32/byte
19374     {
19375       75/jump-if-!= break/disp8
19376       b8/copy-to-eax 4/imm32
19377       eb/jump $compute-size-of-type-id:end/disp8
19378     }
19379     # if t is a handle, return 8
19380     3d/compare-eax-and 4/imm32/handle
19381     {
19382       75/jump-if-!= break/disp8
19383       b8/copy-to-eax 8/imm32
19384       eb/jump $compute-size-of-type-id:end/disp8  # eax changes type from type-id to int
19385     }
19386     # if t is a slice, return 8
19387     3d/compare-eax-and 0xc/imm32/slice
19388     {
19389       75/jump-if-!= break/disp8
19390       b8/copy-to-eax 8/imm32
19391       eb/jump $compute-size-of-type-id:end/disp8  # eax changes type from type-id to int
19392     }
19393     # if t is a user-defined type, compute its size
19394     # TODO: support non-atom type
19395     (find-typeinfo %eax %ecx)
19396     {
19397       81 7/subop/compare *ecx 0/imm32
19398       74/jump-if-= break/disp8
19399 $compute-size-of-type-id:user-defined:
19400       (lookup *ecx *(ecx+4))  # => eax
19401       (populate-mu-type-sizes-in-type %eax *(ebp+0xc) *(ebp+0x10))
19402       8b/-> *(eax+0xc) 0/r32/eax  # Typeinfo-total-size-in-bytes
19403       eb/jump $compute-size-of-type-id:end/disp8
19404     }
19405     # otherwise return the word size
19406     b8/copy-to-eax 4/imm32
19407 $compute-size-of-type-id:end:
19408     # . reclaim locals
19409     81 0/subop/add %esp 8/imm32
19410     # . restore registers
19411     59/pop-to-ecx
19412     # . epilogue
19413     89/<- %esp 5/r32/ebp
19414     5d/pop-to-ebp
19415     c3/return
19416 
19417 # at this point we have total sizes for all user-defined types
19418 # compute offsets for each element
19419 # complication: fields may be out of order
19420 populate-mu-type-offsets:  # in: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
19421     # . prologue
19422     55/push-ebp
19423     89/<- %ebp 4/r32/esp
19424     # . save registers
19425     50/push-eax
19426     51/push-ecx
19427     52/push-edx
19428     53/push-ebx
19429     56/push-esi
19430     57/push-edi
19431 #?     (dump-typeinfos "aaa\n")
19432     # var curr-offset/edi: int = 0
19433     bf/copy-to-edi 0/imm32
19434     # var table/ecx: (addr table string_key (handle typeinfo-entry)) = lookup(in->fields)
19435     8b/-> *(ebp+8) 1/r32/ecx
19436     (lookup *(ecx+4) *(ecx+8))  # Typeinfo-fields Typeinfo-fields => eax
19437     89/<- %ecx 0/r32/eax
19438     # var num-elems/edx: int = table->write / Typeinfo-fields-row-size
19439     8b/-> *ecx 2/r32/edx  # stream-write
19440     c1 5/subop/shift-right-logical  %edx 4/imm8
19441     # var i/ebx: int = 0
19442     bb/copy-to-ebx 0/imm32
19443     {
19444 $populate-mu-type-offsets:loop:
19445       39/compare %ebx 2/r32/edx
19446       0f 8d/jump-if->= break/disp32
19447 #?       (write-buffered Stderr "looking up index ")
19448 #?       (write-int32-hex-buffered Stderr %ebx)
19449 #?       (write-buffered Stderr " in ")
19450 #?       (write-int32-hex-buffered Stderr *(ebp+8))
19451 #?       (write-buffered Stderr Newline)
19452 #?       (flush Stderr)
19453       # var v/esi: (addr typeinfo-entry)
19454       (locate-typeinfo-entry-with-index %ecx %ebx *(ebp+0xc) *(ebp+0x10))  # => eax
19455       89/<- %esi 0/r32/eax
19456       # if v is null, silently move on; we'll emit a nice error message while type-checking
19457       81 7/subop/compare %esi 0/imm32  # Typeinfo-entry-input-var
19458       74/jump-if-= $populate-mu-type-offsets:end/disp8
19459       # if (v->input-var == 0) silently ignore v; we'll emit a nice error message while type-checking
19460       81 7/subop/compare *esi 0/imm32  # Typeinfo-entry-input-var
19461       74/jump-if-= $populate-mu-type-offsets:end/disp8
19462       # v->output-var->offset = curr-offset
19463       # . eax: (addr var)
19464       (lookup *(esi+0xc) *(esi+0x10))  # Typeinfo-entry-output-var Typeinfo-entry-output-var => eax
19465       89/<- *(eax+0x14) 7/r32/edi  # Var-offset
19466       # curr-offset += size-of(v->input-var)
19467       (lookup *esi *(esi+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
19468       (size-of %eax)  # => eax
19469       01/add-to %edi 0/r32/eax
19470       # ++i
19471       43/increment-ebx
19472       e9/jump loop/disp32
19473     }
19474 $populate-mu-type-offsets:end:
19475     # . restore registers
19476     5f/pop-to-edi
19477     5e/pop-to-esi
19478     5b/pop-to-ebx
19479     5a/pop-to-edx
19480     59/pop-to-ecx
19481     58/pop-to-eax
19482     # . epilogue
19483     89/<- %esp 5/r32/ebp
19484     5d/pop-to-ebp
19485     c3/return
19486 
19487 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)
19488     # . prologue
19489     55/push-ebp
19490     89/<- %ebp 4/r32/esp
19491     # . save registers
19492     51/push-ecx
19493     52/push-edx
19494     53/push-ebx
19495     56/push-esi
19496     57/push-edi
19497     # esi = table
19498     8b/-> *(ebp+8) 6/r32/esi
19499     # var curr/ecx: (addr row (handle array byte) (handle typeinfo-entry)) = table->data
19500     8d/copy-address *(esi+0xc) 1/r32/ecx
19501     # var max/edx: (addr byte) = &table->data[table->write]
19502     8b/-> *esi 2/r32/edx
19503     8d/copy-address *(ecx+edx) 2/r32/edx
19504     {
19505 $locate-typeinfo-entry-with-index:loop:
19506       39/compare %ecx 2/r32/edx
19507       73/jump-if-addr>= break/disp8
19508       # var v/eax: (addr typeinfo-entry)
19509       (lookup *(ecx+8) *(ecx+0xc))  # => eax
19510       # if (v->index == idx) return v
19511       8b/-> *(eax+8) 3/r32/ebx  # Typeinfo-entry-index
19512 #?       (write-buffered Stderr "comparing ")
19513 #?       (write-int32-hex-buffered Stderr %ebx)
19514 #?       (write-buffered Stderr " and ")
19515 #?       (write-int32-hex-buffered Stderr *(ebp+0xc))
19516 #?       (write-buffered Stderr Newline)
19517 #?       (flush Stderr)
19518       39/compare *(ebp+0xc) 3/r32/ebx
19519       74/jump-if-= $locate-typeinfo-entry-with-index:end/disp8
19520       # curr += Typeinfo-entry-size
19521       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-entry-size
19522       #
19523       eb/jump loop/disp8
19524     }
19525     # return 0
19526     b8/copy-to-eax 0/imm32
19527 $locate-typeinfo-entry-with-index:end:
19528 #?     (write-buffered Stderr "returning ")
19529 #?     (write-int32-hex-buffered Stderr %eax)
19530 #?     (write-buffered Stderr Newline)
19531 #?     (flush Stderr)
19532     # . restore registers
19533     5f/pop-to-edi
19534     5e/pop-to-esi
19535     5b/pop-to-ebx
19536     5a/pop-to-edx
19537     59/pop-to-ecx
19538     # . epilogue
19539     89/<- %esp 5/r32/ebp
19540     5d/pop-to-ebp
19541     c3/return
19542 
19543 dump-typeinfos:  # hdr: (addr array byte)
19544     # . prologue
19545     55/push-ebp
19546     89/<- %ebp 4/r32/esp
19547     # . save registers
19548     50/push-eax
19549     #
19550     (write-buffered Stderr *(ebp+8))
19551     (flush Stderr)
19552     # var curr/eax: (addr typeinfo) = lookup(Program->types)
19553     (lookup *_Program-types *_Program-types->payload)  # => eax
19554     {
19555       # if (curr == null) break
19556       3d/compare-eax-and 0/imm32
19557       74/jump-if-= break/disp8
19558       (write-buffered Stderr "---\n")
19559       (flush Stderr)
19560       (dump-typeinfo %eax)
19561       # curr = lookup(curr->next)
19562       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
19563       eb/jump loop/disp8
19564     }
19565 $dump-typeinfos:end:
19566     # . restore registers
19567     58/pop-to-eax
19568     # . epilogue
19569     89/<- %esp 5/r32/ebp
19570     5d/pop-to-ebp
19571     c3/return
19572 
19573 dump-typeinfo:  # in: (addr typeinfo)
19574     # . prologue
19575     55/push-ebp
19576     89/<- %ebp 4/r32/esp
19577     # . save registers
19578     50/push-eax
19579     51/push-ecx
19580     52/push-edx
19581     53/push-ebx
19582     56/push-esi
19583     57/push-edi
19584     # esi = in
19585     8b/-> *(ebp+8) 6/r32/esi
19586     # var table/ecx: (addr table (handle array byte) (handle typeinfo-entry)) = lookup(T->fields)
19587     (lookup *(esi+4) *(esi+8))  # Typeinfo-fields Typeinfo-fields => eax
19588     89/<- %ecx 0/r32/eax
19589     (write-buffered Stderr "id:")
19590     (write-int32-hex-buffered Stderr *esi)
19591     (write-buffered Stderr "\n")
19592     (write-buffered Stderr "fields @ ")
19593     (write-int32-hex-buffered Stderr %ecx)
19594     (write-buffered Stderr Newline)
19595     (flush Stderr)
19596     (write-buffered Stderr "  write: ")
19597     (write-int32-hex-buffered Stderr *ecx)
19598     (write-buffered Stderr Newline)
19599     (flush Stderr)
19600     (write-buffered Stderr "  read: ")
19601     (write-int32-hex-buffered Stderr *(ecx+4))
19602     (write-buffered Stderr Newline)
19603     (flush Stderr)
19604     (write-buffered Stderr "  size: ")
19605     (write-int32-hex-buffered Stderr *(ecx+8))
19606     (write-buffered Stderr Newline)
19607     (flush Stderr)
19608     # var table-size/edx: int = table->write
19609     8b/-> *ecx 2/r32/edx  # stream-write
19610     # var curr/ecx: (addr table_row) = table->data
19611     8d/copy-address *(ecx+0xc) 1/r32/ecx
19612     # var max/edx: (addr table_row) = table->data + table->write
19613     8d/copy-address *(ecx+edx) 2/r32/edx
19614     {
19615 $dump-typeinfo:loop:
19616       # if (curr >= max) break
19617       39/compare %ecx 2/r32/edx
19618       0f 83/jump-if-addr>= break/disp32
19619       (write-buffered Stderr "  row:\n")
19620       (write-buffered Stderr "    key: ")
19621       (write-int32-hex-buffered Stderr *ecx)
19622       (write-buffered Stderr ",")
19623       (write-int32-hex-buffered Stderr *(ecx+4))
19624       (write-buffered Stderr " = '")
19625       (lookup *ecx *(ecx+4))
19626       (write-buffered Stderr %eax)
19627       (write-buffered Stderr "' @ ")
19628       (write-int32-hex-buffered Stderr %eax)
19629       (write-buffered Stderr Newline)
19630       (flush Stderr)
19631       (write-buffered Stderr "    value: ")
19632       (write-int32-hex-buffered Stderr *(ecx+8))
19633       (write-buffered Stderr ",")
19634       (write-int32-hex-buffered Stderr *(ecx+0xc))
19635       (write-buffered Stderr " = typeinfo-entry@")
19636       (lookup *(ecx+8) *(ecx+0xc))
19637       (write-int32-hex-buffered Stderr %eax)
19638       (write-buffered Stderr Newline)
19639       (flush Stderr)
19640       (write-buffered Stderr "        input var@")
19641       (dump-var 5 %eax)
19642       (lookup *(ecx+8) *(ecx+0xc))
19643       (write-buffered Stderr "        index: ")
19644       (write-int32-hex-buffered Stderr *(eax+8))
19645       (write-buffered Stderr Newline)
19646       (flush Stderr)
19647       (write-buffered Stderr "        output var@")
19648       8d/copy-address *(eax+0xc) 0/r32/eax  # Typeinfo-entry-output-var
19649       (dump-var 5 %eax)
19650       (flush Stderr)
19651       # curr += row-size
19652       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-fields-row-size
19653       #
19654       e9/jump loop/disp32
19655     }
19656 $dump-typeinfo:end:
19657     # . restore registers
19658     5f/pop-to-edi
19659     5e/pop-to-esi
19660     5b/pop-to-ebx
19661     5a/pop-to-edx
19662     59/pop-to-ecx
19663     58/pop-to-eax
19664     # . epilogue
19665     89/<- %esp 5/r32/ebp
19666     5d/pop-to-ebp
19667     c3/return
19668 
19669 dump-var:  # indent: int, v: (addr handle var)
19670     # . prologue
19671     55/push-ebp
19672     89/<- %ebp 4/r32/esp
19673     # . save registers
19674     50/push-eax
19675     53/push-ebx
19676     # eax = v
19677     8b/-> *(ebp+0xc) 0/r32/eax
19678     #
19679     (write-int32-hex-buffered Stderr *eax)
19680     (write-buffered Stderr ",")
19681     (write-int32-hex-buffered Stderr *(eax+4))
19682     (write-buffered Stderr "->")
19683     (lookup *eax *(eax+4))
19684     (write-int32-hex-buffered Stderr %eax)
19685     (write-buffered Stderr Newline)
19686     (flush Stderr)
19687     {
19688       3d/compare-eax-and 0/imm32
19689       0f 84/jump-if-= break/disp32
19690       (emit-indent Stderr *(ebp+8))
19691       (write-buffered Stderr "name: ")
19692       89/<- %ebx 0/r32/eax
19693       (write-int32-hex-buffered Stderr *ebx)  # Var-name
19694       (write-buffered Stderr ",")
19695       (write-int32-hex-buffered Stderr *(ebx+4))  # Var-name
19696       (write-buffered Stderr "->")
19697       (lookup *ebx *(ebx+4))  # Var-name
19698       (write-int32-hex-buffered Stderr %eax)
19699       {
19700         3d/compare-eax-and 0/imm32
19701         74/jump-if-= break/disp8
19702         (write-buffered Stderr Space)
19703         (write-buffered Stderr %eax)
19704       }
19705       (write-buffered Stderr Newline)
19706       (flush Stderr)
19707       (emit-indent Stderr *(ebp+8))
19708       (write-buffered Stderr "block depth: ")
19709       (write-int32-hex-buffered Stderr *(ebx+0x10))  # Var-block-depth
19710       (write-buffered Stderr Newline)
19711       (flush Stderr)
19712       (emit-indent Stderr *(ebp+8))
19713       (write-buffered Stderr "stack offset: ")
19714       (write-int32-hex-buffered Stderr *(ebx+0x14))  # Var-offset
19715       (write-buffered Stderr Newline)
19716       (flush Stderr)
19717       (emit-indent Stderr *(ebp+8))
19718       (write-buffered Stderr "reg: ")
19719       (write-int32-hex-buffered Stderr *(ebx+0x18))  # Var-register
19720       (write-buffered Stderr ",")
19721       (write-int32-hex-buffered Stderr *(ebx+0x1c))  # Var-register
19722       (write-buffered Stderr "->")
19723       (flush Stderr)
19724       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register
19725       (write-int32-hex-buffered Stderr %eax)
19726       {
19727         3d/compare-eax-and 0/imm32
19728         74/jump-if-= break/disp8
19729         (write-buffered Stderr Space)
19730         (write-buffered Stderr %eax)
19731       }
19732       (write-buffered Stderr Newline)
19733       (flush Stderr)
19734     }
19735 $dump-var:end:
19736     # . restore registers
19737     5b/pop-to-ebx
19738     58/pop-to-eax
19739     # . epilogue
19740     89/<- %esp 5/r32/ebp
19741     5d/pop-to-ebp
19742     c3/return
19743 
19744 #######################################################
19745 # Type-checking
19746 #######################################################
19747 
19748 check-mu-types:  # err: (addr buffered-file), ed: (addr exit-descriptor)
19749     # . prologue
19750     55/push-ebp
19751     89/<- %ebp 4/r32/esp
19752     # . save registers
19753     50/push-eax
19754     # var curr/eax: (addr function) = lookup(Program->functions)
19755     (lookup *_Program-functions *_Program-functions->payload)  # => eax
19756     {
19757 $check-mu-types:loop:
19758       # if (curr == null) break
19759       3d/compare-eax-and 0/imm32
19760       0f 84/jump-if-= break/disp32
19761 +--  8 lines: #?       # dump curr->name ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
19769       (check-mu-function %eax *(ebp+8) *(ebp+0xc))
19770       # curr = lookup(curr->next)
19771       (lookup *(eax+0x20) *(eax+0x24))  # Function-next Function-next => eax
19772       e9/jump loop/disp32
19773     }
19774 $check-mu-types:end:
19775     # . restore registers
19776     58/pop-to-eax
19777     # . epilogue
19778     89/<- %esp 5/r32/ebp
19779     5d/pop-to-ebp
19780     c3/return
19781 
19782 check-mu-function:  # fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
19783     # . prologue
19784     55/push-ebp
19785     89/<- %ebp 4/r32/esp
19786     # . save registers
19787     50/push-eax
19788     56/push-esi
19789     # esi = f
19790     8b/-> *(ebp+8) 6/r32/esi
19791     # outputs
19792     (lookup *(esi+0x10) *(esi+0x14))  # Function-outputs Function-outputs => eax
19793     (check-all-unique-registers %eax %esi *(ebp+0xc) *(ebp+0x10))
19794     # body
19795     (lookup *(esi+0x18) *(esi+0x1c))  # Function-body Function-body => eax
19796     (check-mu-block %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10))
19797     # if function has no outputs, we're done
19798     81 7/subop/compare *(esi+0x10) 0/imm32
19799     74/jump-if-= $check-mu-function:end/disp8
19800     # some final checks on body
19801     (check-final-stmt-is-return %eax %esi *(ebp+0xc) *(ebp+0x10))
19802     (check-no-breaks %eax %esi *(ebp+0xc) *(ebp+0x10))
19803 $check-mu-function:end:
19804     # . restore registers
19805     5e/pop-to-esi
19806     58/pop-to-eax
19807     # . epilogue
19808     89/<- %esp 5/r32/ebp
19809     5d/pop-to-ebp
19810     c3/return
19811 
19812 check-mu-block:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
19813     # . prologue
19814     55/push-ebp
19815     89/<- %ebp 4/r32/esp
19816     # . save registers
19817     50/push-eax
19818     # eax = block
19819     8b/-> *(ebp+8) 0/r32/eax
19820     # var stmts/eax: (addr list stmt) = lookup(block->statements)
19821     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
19822     #
19823     {
19824 $check-mu-block:check-empty:
19825       3d/compare-eax-and 0/imm32
19826       0f 84/jump-if-= break/disp32
19827       # emit block->statements
19828       (check-mu-stmt-list %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19829     }
19830 $check-mu-block:end:
19831     # . restore registers
19832     58/pop-to-eax
19833     # . epilogue
19834     89/<- %esp 5/r32/ebp
19835     5d/pop-to-ebp
19836     c3/return
19837 
19838 check-mu-stmt-list:  # stmts: (addr list stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
19839     # . prologue
19840     55/push-ebp
19841     89/<- %ebp 4/r32/esp
19842     # . save registers
19843     50/push-eax
19844     56/push-esi
19845     # esi = stmts
19846     8b/-> *(ebp+8) 6/r32/esi
19847     {
19848 $check-mu-stmt-list:loop:
19849       81 7/subop/compare %esi 0/imm32
19850       0f 84/jump-if-= break/disp32
19851       # var curr-stmt/eax: (addr stmt) = lookup(stmts->value)
19852       (lookup *esi *(esi+4))  # List-value List-value => eax
19853       {
19854 $check-mu-stmt-list:check-for-block:
19855         81 7/subop/compare *eax 0/imm32/block  # Stmt-tag
19856         75/jump-if-!= break/disp8
19857 $check-mu-stmt-list:block:
19858         (check-mu-block %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19859         eb/jump $check-mu-stmt-list:continue/disp8
19860       }
19861       {
19862 $check-mu-stmt-list:check-for-stmt1:
19863         81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
19864         0f 85/jump-if-!= break/disp32
19865 $check-mu-stmt-list:stmt1:
19866         (check-mu-stmt %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19867         eb/jump $check-mu-stmt-list:continue/disp8
19868       }
19869       {
19870 $check-mu-stmt-list:check-for-reg-var-def:
19871         81 7/subop/compare *eax 3/imm32/reg-var-def  # Stmt-tag
19872         0f 85/jump-if-!= break/disp32
19873 $check-mu-stmt-list:reg-var-def:
19874         (check-mu-stmt %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19875         eb/jump $check-mu-stmt-list:continue/disp8
19876       }
19877 $check-mu-stmt-list:continue:
19878       # TODO: raise an error on unrecognized Stmt-tag
19879       (lookup *(esi+8) *(esi+0xc))  # List-next List-next => eax
19880       89/<- %esi 0/r32/eax
19881       e9/jump loop/disp32
19882     }
19883 $check-mu-stmt-list:end:
19884     # . restore registers
19885     5e/pop-to-esi
19886     58/pop-to-eax
19887     # . epilogue
19888     89/<- %esp 5/r32/ebp
19889     5d/pop-to-ebp
19890     c3/return
19891 
19892 check-mu-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
19893     # . prologue
19894     55/push-ebp
19895     89/<- %ebp 4/r32/esp
19896     # . save registers
19897     50/push-eax
19898     # - if stmt's operation matches a primitive, check against it
19899     (has-primitive-name? *(ebp+8))  # => eax
19900     3d/compare-eax-and 0/imm32/false
19901     {
19902       74/jump-if-= break/disp8
19903       (check-mu-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19904       e9/jump $check-mu-stmt:end/disp32
19905     }
19906     # - otherwise find a function to check against
19907     # var f/eax: (addr function) = lookup(*Program->functions)
19908     (lookup *_Program-functions *_Program-functions->payload)  # => eax
19909     (find-matching-function %eax *(ebp+8))  # => eax
19910     3d/compare-eax-and 0/imm32
19911     {
19912       74/jump-if-= break/disp8
19913       (check-mu-call *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19914       eb/jump $check-mu-stmt:end/disp8
19915     }
19916     # var f/eax: (addr function) = lookup(*Program->signatures)
19917     (lookup *_Program-signatures *_Program-signatures->payload)  # => eax
19918     (find-matching-function %eax *(ebp+8))  # => eax
19919     3d/compare-eax-and 0/imm32
19920     {
19921       74/jump-if-= break/disp8
19922       (check-mu-call *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19923       eb/jump $check-mu-stmt:end/disp8
19924     }
19925     # - otherwise abort
19926     e9/jump $check-mu-stmt:unknown-call/disp32
19927 $check-mu-stmt:end:
19928     # . restore registers
19929     58/pop-to-eax
19930     # . epilogue
19931     89/<- %esp 5/r32/ebp
19932     5d/pop-to-ebp
19933     c3/return
19934 
19935 $check-mu-stmt:unknown-call:
19936     (write-buffered *(ebp+0x10) "unknown function '")
19937     8b/-> *(ebp+8) 0/r32/eax
19938     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
19939     (write-buffered *(ebp+0x10) %eax)
19940     (write-buffered *(ebp+0x10) "'\n")
19941     (flush *(ebp+0x10))
19942     (stop *(ebp+0x14) 1)
19943     # never gets here
19944 
19945 has-primitive-name?:  # stmt: (addr stmt) -> result/eax: boolean
19946     # . prologue
19947     55/push-ebp
19948     89/<- %ebp 4/r32/esp
19949     # . save registers
19950     51/push-ecx
19951     56/push-esi
19952     # var name/esi: (addr array byte) = lookup(stmt->operation)
19953     8b/-> *(ebp+8) 6/r32/esi
19954     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
19955     89/<- %esi 0/r32/eax
19956     # if (name == "return") return true
19957     (string-equal? %esi "return")  # => eax
19958     3d/compare-eax-and 0/imm32/false
19959     0f 85/jump-if-!= $has-primitive-name?:end/disp32
19960     # if (name == "get") return true
19961     (string-equal? %esi "get")  # => eax
19962     3d/compare-eax-and 0/imm32/false
19963     0f 85/jump-if-!= $has-primitive-name?:end/disp32
19964     # if (name == "index") return true
19965     (string-equal? %esi "index")  # => eax
19966     3d/compare-eax-and 0/imm32/false
19967     0f 85/jump-if-!= $has-primitive-name?:end/disp32
19968     # if (name == "length") return true
19969     (string-equal? %esi "length")  # => eax
19970     3d/compare-eax-and 0/imm32/false
19971     0f 85/jump-if-!= $has-primitive-name?:end/disp32
19972     # if (name == "compute-offset") return true
19973     (string-equal? %esi "compute-offset")  # => eax
19974     3d/compare-eax-and 0/imm32/false
19975     0f 85/jump-if-!= $has-primitive-name?:end/disp32
19976     # if (name == "copy-object") return true
19977     (string-equal? %esi "copy-object")  # => eax
19978     3d/compare-eax-and 0/imm32/false
19979     0f 85/jump-if-!= $has-primitive-name?:end/disp32
19980     # if (name == "clear-object") return true
19981     (string-equal? %esi "clear-object")  # => eax
19982     3d/compare-eax-and 0/imm32/false
19983     0f 85/jump-if-!= $has-primitive-name?:end/disp32
19984     # if (name == "allocate") return true
19985     (string-equal? %esi "allocate")  # => eax
19986     3d/compare-eax-and 0/imm32/false
19987     0f 85/jump-if-!= $has-primitive-name?:end/disp32
19988     # if (name == "populate") return true
19989     (string-equal? %esi "populate")  # => eax
19990     3d/compare-eax-and 0/imm32/false
19991     0f 85/jump-if-!= $has-primitive-name?:end/disp32
19992     # if (name == "populate-stream") return true
19993     (string-equal? %esi "populate-stream")  # => eax
19994     3d/compare-eax-and 0/imm32/false
19995     0f 85/jump-if-!= $has-primitive-name?:end/disp32
19996     # if (name == "read-from-stream") return true
19997     (string-equal? %esi "read-from-stream")  # => eax
19998     3d/compare-eax-and 0/imm32/false
19999     0f 85/jump-if-!= $has-primitive-name?:end/disp32
20000     # if (name == "write-to-stream") return true
20001     (string-equal? %esi "write-to-stream")  # => eax
20002     3d/compare-eax-and 0/imm32/false
20003     0f 85/jump-if-!= $has-primitive-name?:end/disp32
20004     # var curr/ecx: (addr primitive) = Primitives
20005     b9/copy-to-ecx Primitives/imm32
20006     {
20007 $has-primitive-name?:loop:
20008       # if (curr == null) break
20009       81 7/subop/compare %ecx 0/imm32
20010       74/jump-if-= break/disp8
20011       # if (primitive->name == name) return true
20012       (lookup *ecx *(ecx+4))  # Primitive-name Primitive-name => eax
20013 #?       (write-buffered Stderr %eax)
20014 #?       (write-buffered Stderr Newline)
20015 #?       (flush Stderr)
20016       (string-equal? %esi %eax)  # => eax
20017       3d/compare-eax-and 0/imm32/false
20018       75/jump-if-!= $has-primitive-name?:end/disp8
20019 $has-primitive-name?:next-primitive:
20020       # curr = curr->next
20021       (lookup *(ecx+0x3c) *(ecx+0x40))  # Primitive-next Primitive-next => eax
20022       89/<- %ecx 0/r32/eax
20023       #
20024       e9/jump loop/disp32
20025     }
20026     # return null
20027     b8/copy-to-eax 0/imm32
20028 $has-primitive-name?:end:
20029     # . restore registers
20030     5e/pop-to-esi
20031     59/pop-to-ecx
20032     # . epilogue
20033     89/<- %esp 5/r32/ebp
20034     5d/pop-to-ebp
20035     c3/return
20036 
20037 check-mu-primitive:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
20038     # . prologue
20039     55/push-ebp
20040     89/<- %ebp 4/r32/esp
20041     # . save registers
20042     50/push-eax
20043     51/push-ecx
20044     # var op/ecx: (addr array byte) = lookup(stmt->operation)
20045     8b/-> *(ebp+8) 0/r32/eax
20046     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
20047     89/<- %ecx 0/r32/eax
20048     # if (op == "copy") check-mu-copy-stmt
20049     {
20050       (string-equal? %ecx "copy")  # => eax
20051       3d/compare-eax-and 0/imm32/false
20052       74/jump-if-= break/disp8
20053       (check-mu-copy-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20054       e9/jump $check-mu-primitive:end/disp32
20055     }
20056     # if (op == "copy-to") check-mu-copy-to-stmt
20057     {
20058       (string-equal? %ecx "copy-to")  # => eax
20059       3d/compare-eax-and 0/imm32/false
20060       74/jump-if-= break/disp8
20061       (check-mu-copy-to-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20062       e9/jump $check-mu-primitive:end/disp32
20063     }
20064     # if (op == "compare") check-mu-compare-stmt
20065     {
20066       (string-equal? %ecx "compare")  # => eax
20067       3d/compare-eax-and 0/imm32/false
20068       74/jump-if-= break/disp8
20069       (check-mu-compare-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20070       e9/jump $check-mu-primitive:end/disp32
20071     }
20072     # if (op == "address") check-mu-address-stmt
20073     {
20074       (string-equal? %ecx "address")  # => eax
20075       3d/compare-eax-and 0/imm32/false
20076       74/jump-if-= break/disp8
20077       (check-mu-address-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20078       e9/jump $check-mu-primitive:end/disp32
20079     }
20080     # if (op == "return") check-mu-return-stmt
20081     {
20082       (string-equal? %ecx "return")  # => eax
20083       3d/compare-eax-and 0/imm32/false
20084       74/jump-if-= break/disp8
20085       (check-mu-return-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20086       e9/jump $check-mu-primitive:end/disp32
20087     }
20088     # if (op == "get") check-mu-get-stmt
20089     {
20090       (string-equal? %ecx "get")  # => eax
20091       3d/compare-eax-and 0/imm32/false
20092       74/jump-if-= break/disp8
20093       (check-mu-get-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20094       e9/jump $check-mu-primitive:end/disp32
20095     }
20096     # if (op == "index") check-mu-index-stmt
20097     {
20098       (string-equal? %ecx "index")  # => eax
20099       3d/compare-eax-and 0/imm32/false
20100       74/jump-if-= break/disp8
20101       (check-mu-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20102       e9/jump $check-mu-primitive:end/disp32
20103     }
20104     # if (op == "length") check-mu-length-stmt
20105     {
20106       (string-equal? %ecx "length")  # => eax
20107       3d/compare-eax-and 0/imm32/false
20108       74/jump-if-= break/disp8
20109       (check-mu-length-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20110       e9/jump $check-mu-primitive:end/disp32
20111     }
20112     # if (op == "compute-offset") check-mu-compute-offset-stmt
20113     {
20114       (string-equal? %ecx "compute-offset")  # => eax
20115       3d/compare-eax-and 0/imm32/false
20116       74/jump-if-= break/disp8
20117       (check-mu-compute-offset-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20118       e9/jump $check-mu-primitive:end/disp32
20119     }
20120     # if (op == "copy-object") check-mu-copy-object-stmt
20121     {
20122       (string-equal? %ecx "copy-object")  # => eax
20123       3d/compare-eax-and 0/imm32/false
20124       74/jump-if-= break/disp8
20125       (check-mu-copy-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20126       e9/jump $check-mu-primitive:end/disp32
20127     }
20128     # if (op == "clear-object") check-mu-clear-object-stmt
20129     {
20130       (string-equal? %ecx "clear-object")  # => eax
20131       3d/compare-eax-and 0/imm32/false
20132       74/jump-if-= break/disp8
20133       (check-mu-clear-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20134       e9/jump $check-mu-primitive:end/disp32
20135     }
20136     # if (op == "allocate") check-mu-allocate-stmt
20137     {
20138       (string-equal? %ecx "allocate")  # => eax
20139       3d/compare-eax-and 0/imm32/false
20140       74/jump-if-= break/disp8
20141       (check-mu-allocate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20142       e9/jump $check-mu-primitive:end/disp32
20143     }
20144     # if (op == "populate") check-mu-populate-stmt
20145     {
20146       (string-equal? %ecx "populate")  # => eax
20147       3d/compare-eax-and 0/imm32/false
20148       74/jump-if-= break/disp8
20149       (check-mu-populate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20150       e9/jump $check-mu-primitive:end/disp32
20151     }
20152     # if (op == "populate-stream") check-mu-populate-stream-stmt
20153     {
20154       (string-equal? %ecx "populate-stream")  # => eax
20155       3d/compare-eax-and 0/imm32/false
20156       74/jump-if-= break/disp8
20157       (check-mu-populate-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20158       e9/jump $check-mu-primitive:end/disp32
20159     }
20160     # if (op == "read-from-stream") check-mu-read-from-stream-stmt
20161     {
20162       (string-equal? %ecx "read-from-stream")  # => eax
20163       3d/compare-eax-and 0/imm32/false
20164       74/jump-if-= break/disp8
20165       (check-mu-read-from-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20166       e9/jump $check-mu-primitive:end/disp32
20167     }
20168     # if (op == "write-to-stream") check-mu-write-to-stream-stmt
20169     {
20170       (string-equal? %ecx "write-to-stream")  # => eax
20171       3d/compare-eax-and 0/imm32/false
20172       74/jump-if-= break/disp8
20173       (check-mu-write-to-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20174       e9/jump $check-mu-primitive:end/disp32
20175     }
20176     # if (op == "convert") check-mu-convert-stmt
20177     {
20178       (string-equal? %ecx "convert")  # => eax
20179       3d/compare-eax-and 0/imm32/false
20180       74/jump-if-= break/disp8
20181       (check-mu-convert-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20182       e9/jump $check-mu-primitive:end/disp32
20183     }
20184     # otherwise check-numberlike-stmt
20185     (check-mu-numberlike-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20186 $check-mu-primitive:end:
20187     # . restore registers
20188     59/pop-to-ecx
20189     58/pop-to-eax
20190     # . epilogue
20191     89/<- %esp 5/r32/ebp
20192     5d/pop-to-ebp
20193     c3/return
20194 
20195 # by default, Mu primitives should only operate on 'number-like' types
20196 check-mu-numberlike-primitive:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
20197     # . prologue
20198     55/push-ebp
20199     89/<- %ebp 4/r32/esp
20200     # . save registers
20201     50/push-eax
20202     51/push-ecx
20203     56/push-esi
20204     # esi = stmt
20205     8b/-> *(ebp+8) 6/r32/esi
20206     # var gas/ecx: int = 2
20207     b9/copy-to-ecx 2/imm32
20208     # - check at most 1 output
20209     # var output/eax: (addr stmt-var) = stmt->outputs
20210     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
20211     {
20212       3d/compare-eax-and 0/imm32
20213       74/jump-if-= break/disp8
20214 $check-mu-numberlike-primitive:output:
20215       (check-mu-numberlike-output %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20216       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
20217       3d/compare-eax-and 0/imm32
20218       0f 85/jump-if-!= $check-mu-numberlike-primitive:error-too-many-outputs/disp32
20219       # check output is in a register
20220       # --gas
20221       49/decrement-ecx
20222     }
20223     # - check first inout
20224     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
20225     {
20226       3d/compare-eax-and 0/imm32
20227       0f 84/jump-if-= $check-mu-numberlike-primitive:end/disp32
20228 $check-mu-numberlike-primitive:first-inout:
20229       (check-mu-numberlike-arg %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20230       # --gas
20231       49/decrement-ecx
20232     }
20233     # - check second inout
20234     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
20235     {
20236       3d/compare-eax-and 0/imm32
20237       74/jump-if-= $check-mu-numberlike-primitive:end/disp8
20238 $check-mu-numberlike-primitive:second-inout:
20239       # is a second inout allowed?
20240       81 7/subop/compare %ecx 0/imm32
20241       0f 84/jump-if-= $check-mu-numberlike-primitive:error-too-many-inouts/disp32
20242 $check-mu-numberlike-primitive:second-inout-permitted:
20243       (check-mu-numberlike-arg %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20244     }
20245 $check-mu-numberlike-primitive:third-inout:
20246     # if there's a third arg, raise an error
20247     81 7/subop/compare *(eax+8) 0/imm32  # Stmt-var-next
20248     0f 85/jump-if-!= $check-mu-numberlike-primitive:error-too-many-inouts/disp32
20249 $check-mu-numberlike-primitive:end:
20250     # . restore registers
20251     5e/pop-to-esi
20252     59/pop-to-ecx
20253     58/pop-to-eax
20254     # . epilogue
20255     89/<- %esp 5/r32/ebp
20256     5d/pop-to-ebp
20257     c3/return
20258 
20259 $check-mu-numberlike-primitive:error-too-many-inouts:
20260     (write-buffered *(ebp+0x10) "fn ")
20261     8b/-> *(ebp+0xc) 0/r32/eax
20262     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20263     (write-buffered *(ebp+0x10) %eax)
20264     (write-buffered *(ebp+0x10) ": stmt ")
20265     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
20266     (write-buffered *(ebp+0x10) %eax)
20267     (write-buffered *(ebp+0x10) ": too many inouts; most primitives support at most two arguments, across inouts and outputs\n")
20268     (flush *(ebp+0x10))
20269     (stop *(ebp+0x14) 1)
20270     # never gets here
20271 
20272 $check-mu-numberlike-primitive:error-too-many-outputs:
20273     (write-buffered *(ebp+0x10) "fn ")
20274     8b/-> *(ebp+0xc) 0/r32/eax
20275     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20276     (write-buffered *(ebp+0x10) %eax)
20277     (write-buffered *(ebp+0x10) ": stmt ")
20278     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
20279     (write-buffered *(ebp+0x10) %eax)
20280     (write-buffered *(ebp+0x10) ": too many outputs; most primitives support at most one output\n")
20281     (flush *(ebp+0x10))
20282     (stop *(ebp+0x14) 1)
20283     # never gets here
20284 
20285 check-mu-numberlike-arg:  # v: (addr stmt-var), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
20286     # . prologue
20287     55/push-ebp
20288     89/<- %ebp 4/r32/esp
20289     # . save registers
20290     50/push-eax
20291     56/push-esi
20292     # var t/esi: (addr type-tree) = lookup(v->value->type)
20293     8b/-> *(ebp+8) 0/r32/eax
20294     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
20295     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20296     89/<- %esi 0/r32/eax
20297 $check-mu-numberlike-arg:check-literal:
20298     # if t is an int, return
20299     (is-simple-mu-type? %esi 0)  # literal => eax
20300     3d/compare-eax-and 0/imm32/false
20301     0f 85/jump-if-!= $check-mu-numberlike-arg:end/disp32
20302 $check-mu-numberlike-arg:check-addr:
20303     # if t is an addr and v is dereferenced, return whether t->payload is an addr
20304     {
20305       (is-mu-addr-type? %esi)  # => eax
20306       3d/compare-eax-and 0/imm32/false
20307       74/jump-if-= break/disp8
20308       8b/-> *(ebp+8) 0/r32/eax
20309       8b/-> *(eax+0x10) 0/r32/eax  # Stmt-var-is-deref
20310       3d/compare-eax-and 0/imm32/false
20311       {
20312         74/jump-if-= break/disp8
20313         (lookup *(esi+0xc) *(esi+0x10))  # Type-tree-right Type-tree-right => eax
20314         # if t->right is null, t = t->left
20315         81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
20316         {
20317           75/jump-if-!= break/disp8
20318           (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20319         }
20320         (is-mu-addr-type? %eax)  # => eax
20321         3d/compare-eax-and 0/imm32/false
20322         74/jump-if-= $check-mu-numberlike-arg:end/disp8
20323       }
20324     }
20325 $check-mu-numberlike-arg:output-checks:
20326     (check-mu-numberlike-output *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18))
20327 $check-mu-numberlike-arg:end:
20328     # . restore registers
20329     5e/pop-to-esi
20330     58/pop-to-eax
20331     # . epilogue
20332     89/<- %esp 5/r32/ebp
20333     5d/pop-to-ebp
20334     c3/return
20335 
20336 check-mu-numberlike-output:  # v: (addr stmt-var), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
20337     # . prologue
20338     55/push-ebp
20339     89/<- %ebp 4/r32/esp
20340     # . save registers
20341     50/push-eax
20342     #
20343     (is-mu-numberlike-output-var? *(ebp+8))  # => eax
20344     3d/compare-eax-and 0/imm32/false
20345     0f 84/jump-if-= $check-mu-numberlike-output:fail/disp32
20346 $check-mu-numberlike-output:end:
20347     # . restore registers
20348     58/pop-to-eax
20349     # . epilogue
20350     89/<- %esp 5/r32/ebp
20351     5d/pop-to-ebp
20352     c3/return
20353 
20354 $check-mu-numberlike-output:fail:
20355     # otherwise raise an error
20356     (write-buffered *(ebp+0x14) "fn ")
20357     8b/-> *(ebp+0x10) 0/r32/eax
20358     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20359     (write-buffered *(ebp+0x14) %eax)
20360     (write-buffered *(ebp+0x14) ": stmt ")
20361     8b/-> *(ebp+0xc) 0/r32/eax
20362     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
20363     (write-buffered *(ebp+0x14) %eax)
20364     (write-buffered *(ebp+0x14) ": '")
20365     8b/-> *(ebp+8) 0/r32/eax
20366     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
20367     (lookup *eax *(eax+4))  # Var-name Var-name => eax
20368     (write-buffered *(ebp+0x14) %eax)
20369     (write-buffered *(ebp+0x14) "' must be a non-addr non-offset scalar\n")
20370     (flush *(ebp+0x14))
20371     (stop *(ebp+0x18) 1)
20372     # never gets here
20373 
20374 is-mu-numberlike-output-var?:  # v: (addr stmt-var) -> result/eax: boolean
20375     # . prologue
20376     55/push-ebp
20377     89/<- %ebp 4/r32/esp
20378     #
20379     8b/-> *(ebp+8) 0/r32/eax
20380     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
20381     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20382     (is-mu-numberlike-output? %eax)  # => eax
20383 $is-mu-numberlike-output-var?:end:
20384     # . epilogue
20385     89/<- %esp 5/r32/ebp
20386     5d/pop-to-ebp
20387     c3/return
20388 
20389 is-mu-numberlike-output?:  # v: (addr type-tree) -> result/eax: boolean
20390     # . prologue
20391     55/push-ebp
20392     89/<- %ebp 4/r32/esp
20393     # . save registers
20394     56/push-esi
20395     # var t/esi: (addr type-tree) = lookup(v->value->type)
20396     8b/-> *(ebp+8) 6/r32/esi
20397 $is-mu-numberlike-output?:check-int:
20398     # if t is an int, return
20399     (is-simple-mu-type? %esi 1)  # int => eax
20400     3d/compare-eax-and 0/imm32/false
20401     0f 85/jump-if-!= $is-mu-numberlike-output?:return-true/disp32
20402 $is-mu-numberlike-output?:check-float:
20403     # if t is a float, return
20404     (is-simple-mu-type? %esi 0xf)  # float => eax
20405     3d/compare-eax-and 0/imm32/false
20406     75/jump-if-!= $is-mu-numberlike-output?:return-true/disp8
20407 $is-mu-numberlike-output?:check-boolean:
20408     # if t is a boolean, return
20409     (is-simple-mu-type? %esi 5)  # boolean => eax
20410     3d/compare-eax-and 0/imm32/false
20411     75/jump-if-!= $is-mu-numberlike-output?:return-true/disp8
20412 $is-mu-numberlike-output?:check-byte:
20413     # if t is a byte, return
20414     (is-simple-mu-type? %esi 8)  # byte => eax
20415     3d/compare-eax-and 0/imm32/false
20416     75/jump-if-!= $is-mu-numberlike-output?:return-true/disp8
20417 $is-mu-numberlike-output?:check-code-point:
20418     # if t is a code-point, return
20419     (is-simple-mu-type? %esi 0xd)  # code-point => eax
20420     3d/compare-eax-and 0/imm32/false
20421     75/jump-if-!= $is-mu-numberlike-output?:return-true/disp8
20422 $is-mu-numberlike-output?:check-grapheme:
20423     # if t is a grapheme, return
20424     (is-simple-mu-type? %esi 0xe)  # grapheme => eax
20425     3d/compare-eax-and 0/imm32/false
20426     75/jump-if-!= $is-mu-numberlike-output?:return-true/disp8
20427 $is-mu-numberlike-output?:return-false:
20428     b8/copy-to-eax 0/imm32/false
20429     eb/jump $is-mu-numberlike-output?:end/disp8
20430 $is-mu-numberlike-output?:return-true:
20431     b8/copy-to-eax 1/imm32/true
20432 $is-mu-numberlike-output?:end:
20433     # . restore registers
20434     5e/pop-to-esi
20435     # . epilogue
20436     89/<- %esp 5/r32/ebp
20437     5d/pop-to-ebp
20438     c3/return
20439 
20440 check-mu-copy-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
20441     # . prologue
20442     55/push-ebp
20443     89/<- %ebp 4/r32/esp
20444     # . save registers
20445     50/push-eax
20446     51/push-ecx
20447     52/push-edx
20448     56/push-esi
20449     57/push-edi
20450     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
20451     81 5/subop/subtract %esp 0x60/imm32
20452     68/push 0x60/imm32/size
20453     68/push 0/imm32/read
20454     68/push 0/imm32/write
20455     89/<- %edx 4/r32/esp
20456 $check-mu-copy-stmt:get-output:
20457     # esi = stmt
20458     8b/-> *(ebp+8) 6/r32/esi
20459     # var output/edi: (addr stmt-var) = stmt->outputs
20460     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
20461     89/<- %edi 0/r32/eax
20462     # zero outputs
20463     3d/compare-eax-and 0/imm32
20464     0f 84/jump-if-= $check-mu-copy-stmt:error-no-output/disp32
20465     # > 1 output
20466     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
20467     3d/compare-eax-and 0/imm32
20468     0f 85/jump-if-!= $check-mu-copy-stmt:error-too-many-outputs/disp32
20469 $check-mu-copy-stmt:get-inout:
20470     # var inout/esi: (addr stmt-var) = stmt->inouts
20471     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
20472     89/<- %esi 0/r32/eax
20473     # zero inouts
20474     3d/compare-eax-and 0/imm32
20475     0f 84/jump-if-= $check-mu-copy-stmt:error-no-inout/disp32
20476     # > 1 inout
20477     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
20478     3d/compare-eax-and 0/imm32
20479     0f 85/jump-if-!= $check-mu-copy-stmt:error-too-many-inouts/disp32
20480 $check-mu-copy-stmt:types:
20481     # var inout-type/ecx: (addr type-tree) = inout->value->type
20482     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
20483     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20484     89/<- %ecx 0/r32/eax
20485     # if (inout->is-deref?) inout-type = inout-type->payload
20486     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
20487     3d/compare-eax-and 0/imm32/false
20488     {
20489       74/jump-if-= break/disp8
20490       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
20491       # if inout-type->right is null, t = inout-type->left
20492       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
20493       {
20494         75/jump-if-!= break/disp8
20495         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20496       }
20497       89/<- %ecx 0/r32/eax
20498     }
20499     # if output not in register, abort
20500     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
20501     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
20502     3d/compare-eax-and 0/imm32
20503     0f 84/jump-if-= $check-mu-copy-stmt:error-output-not-in-register/disp32
20504     # if inout is not a scalar, abort
20505     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
20506     (size-of %eax)  # => eax
20507     3d/compare-eax-and 4/imm32
20508     0f 8f/jump-if-> $check-mu-copy-stmt:error-inout-too-large/disp32
20509     # var output-type/eax: (addr type-tree) = output->value->type
20510     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
20511     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20512     # if (inout-type == output-type) return
20513     (type-match? %eax %ecx %edx)  # => eax
20514     3d/compare-eax-and 0/imm32
20515     0f 85/jump-if-!= $check-mu-copy-stmt:end/disp32
20516     # if output is an addr and inout is 0, return
20517     {
20518       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
20519       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20520       (is-mu-addr-type? %eax)  # => eax
20521       3d/compare-eax-and 0/imm32/false
20522       74/jump-if-= break/disp8
20523       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
20524       (lookup *eax *(eax+4))  # Var-name Var-name => eax
20525       (string-equal? %eax "0")  # => eax
20526       3d/compare-eax-and 0/imm32/false
20527       74/jump-if-= break/disp8
20528       e9/jump $check-mu-copy-stmt:end/disp32
20529     }
20530     # if output is an offset and inout is 0, return
20531     {
20532       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
20533       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20534       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
20535       75/jump-if-!= break/disp8
20536       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20537       (is-simple-mu-type? %eax 7)  # offset => eax
20538       3d/compare-eax-and 0/imm32/false
20539       74/jump-if-= break/disp8
20540       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
20541       (lookup *eax *(eax+4))  # Var-name Var-name => eax
20542       (string-equal? %eax "0")  # => eax
20543       3d/compare-eax-and 0/imm32/false
20544       74/jump-if-= break/disp8
20545       eb/jump $check-mu-copy-stmt:end/disp8
20546     }
20547     # if output is not number-like, abort
20548     (check-mu-numberlike-output %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20549 $check-mu-copy-stmt:end:
20550     # . reclaim locals
20551     81 0/subop/add %esp 0x6c/imm32
20552     # . restore registers
20553     5f/pop-to-edi
20554     5e/pop-to-esi
20555     5a/pop-to-edx
20556     59/pop-to-ecx
20557     58/pop-to-eax
20558     # . epilogue
20559     89/<- %esp 5/r32/ebp
20560     5d/pop-to-ebp
20561     c3/return
20562 
20563 $check-mu-copy-stmt:error-no-inout:
20564     (write-buffered *(ebp+0x10) "fn ")
20565     8b/-> *(ebp+0xc) 0/r32/eax
20566     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20567     (write-buffered *(ebp+0x10) %eax)
20568     (write-buffered *(ebp+0x10) ": stmt 'copy' expects an inout\n")
20569     (flush *(ebp+0x10))
20570     (stop *(ebp+0x14) 1)
20571     # never gets here
20572 
20573 $check-mu-copy-stmt:error-too-many-inouts:
20574     (write-buffered *(ebp+0x10) "fn ")
20575     8b/-> *(ebp+0xc) 0/r32/eax
20576     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20577     (write-buffered *(ebp+0x10) %eax)
20578     (write-buffered *(ebp+0x10) ": stmt 'copy' must have just one inout\n")
20579     (flush *(ebp+0x10))
20580     (stop *(ebp+0x14) 1)
20581     # never gets here
20582 
20583 $check-mu-copy-stmt:error-no-output:
20584     (write-buffered *(ebp+0x10) "fn ")
20585     8b/-> *(ebp+0xc) 0/r32/eax
20586     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20587     (write-buffered *(ebp+0x10) %eax)
20588     (write-buffered *(ebp+0x10) ": stmt 'copy' expects an output\n")
20589     (flush *(ebp+0x10))
20590     (stop *(ebp+0x14) 1)
20591     # never gets here
20592 
20593 $check-mu-copy-stmt:error-output-not-in-register:
20594     (write-buffered *(ebp+0x10) "fn ")
20595     8b/-> *(ebp+0xc) 0/r32/eax
20596     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20597     (write-buffered *(ebp+0x10) %eax)
20598     (write-buffered *(ebp+0x10) ": stmt copy: output '")
20599     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
20600     (lookup *eax *(eax+4))  # Var-name Var-name => eax
20601     (write-buffered *(ebp+0x10) %eax)
20602     (write-buffered *(ebp+0x10) "' not in a register\n")
20603     (flush *(ebp+0x10))
20604     (stop *(ebp+0x14) 1)
20605     # never gets here
20606 
20607 $check-mu-copy-stmt:error-too-many-outputs:
20608     (write-buffered *(ebp+0x10) "fn ")
20609     8b/-> *(ebp+0xc) 0/r32/eax
20610     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20611     (write-buffered *(ebp+0x10) %eax)
20612     (write-buffered *(ebp+0x10) ": stmt 'copy' must have just one output\n")
20613     (flush *(ebp+0x10))
20614     (stop *(ebp+0x14) 1)
20615     # never gets here
20616 
20617 $check-mu-copy-stmt:error-inout-too-large:
20618     (write-buffered *(ebp+0x10) "fn ")
20619     8b/-> *(ebp+0xc) 0/r32/eax
20620     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20621     (write-buffered *(ebp+0x10) %eax)
20622     (write-buffered *(ebp+0x10) ": stmt copy: '")
20623     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
20624     (lookup *eax *(eax+4))  # Var-name Var-name => eax
20625     (write-buffered *(ebp+0x10) %eax)
20626     (write-buffered *(ebp+0x10) "' is too large to fit in a register\n")
20627     (flush *(ebp+0x10))
20628     (stop *(ebp+0x14) 1)
20629     # never gets here
20630 
20631 check-mu-copy-to-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
20632     # . prologue
20633     55/push-ebp
20634     89/<- %ebp 4/r32/esp
20635     # . save registers
20636     50/push-eax
20637     51/push-ecx
20638     52/push-edx
20639     53/push-ebx
20640     56/push-esi
20641     57/push-edi
20642     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
20643     81 5/subop/subtract %esp 0x60/imm32
20644     68/push 0x60/imm32/size
20645     68/push 0/imm32/read
20646     68/push 0/imm32/write
20647     89/<- %edx 4/r32/esp
20648     # esi = stmt
20649     8b/-> *(ebp+8) 6/r32/esi
20650 $check-mu-copy-to-stmt:check-for-output:
20651     # if stmt->outputs abort
20652     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
20653     3d/compare-eax-and 0/imm32
20654     0f 85/jump-if-!= $check-mu-copy-to-stmt:error-too-many-outputs/disp32
20655 $check-mu-copy-to-stmt:get-dest:
20656     # var dest/edi: (addr stmt-var) = stmt->inouts
20657     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
20658     89/<- %edi 0/r32/eax
20659     # zero inouts
20660     3d/compare-eax-and 0/imm32
20661     0f 84/jump-if-= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32
20662 $check-mu-copy-to-stmt:get-src:
20663     # var src/esi: (addr stmt-var) = dest->next
20664     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
20665     89/<- %esi 0/r32/eax
20666     # 1 inout
20667     3d/compare-eax-and 0/imm32
20668     0f 84/jump-if-= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32
20669     # > 2 inouts
20670     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
20671     3d/compare-eax-and 0/imm32
20672     0f 85/jump-if-!= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32
20673 $check-mu-copy-to-stmt:types:
20674     # var src-type/ecx: (addr type-tree) = src->value->type
20675     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
20676     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20677     89/<- %ecx 0/r32/eax
20678     # if src not in register or literal, abort
20679     # (we can't use stack-offset because it hasn't been computed yet)
20680     {
20681       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
20682       (lookup *(eax+0x8) *(eax+0xc))  # Var-type Var-type => eax
20683       (is-simple-mu-type? %eax 0)  # => eax
20684       3d/compare-eax-and 0/imm32
20685       75/jump-if-!= break/disp8
20686       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
20687       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
20688       3d/compare-eax-and 0/imm32
20689       75/jump-if-!= break/disp8
20690       e9/jump $check-mu-copy-to-stmt:error-src-not-literal-or-in-register/disp32
20691     }
20692     # if src is not a scalar, abort
20693     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
20694     (size-of %eax)  # => eax
20695     3d/compare-eax-and 4/imm32
20696     0f 8f/jump-if-> $check-mu-copy-to-stmt:error-src-too-large/disp32
20697     # var dest-type/ebx: (addr type-tree) = dest->value->type
20698     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
20699     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20700     89/<- %ebx 0/r32/eax
20701     # if (dest->is-deref?) dest-type = dest-type->payload
20702     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
20703     3d/compare-eax-and 0/imm32/false
20704     {
20705       74/jump-if-= break/disp8
20706       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
20707       # if dest-type->right is null, dest-type = dest-type->left
20708       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
20709       {
20710         75/jump-if-!= break/disp8
20711         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20712       }
20713       89/<- %ebx 0/r32/eax
20714     }
20715     # if (src-type == dest-type) return
20716     (type-match? %ebx %ecx %edx)  # => eax
20717     3d/compare-eax-and 0/imm32
20718     0f 85/jump-if-!= $check-mu-copy-to-stmt:end/disp32
20719     # if dest is an addr and src is 0, return
20720     {
20721       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
20722       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20723       (is-mu-addr-type? %eax)  # => eax
20724       3d/compare-eax-and 0/imm32/false
20725       74/jump-if-= break/disp8
20726       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
20727       (lookup *eax *(eax+4))  # Var-name Var-name => eax
20728       (string-equal? %eax "0")  # => eax
20729       3d/compare-eax-and 0/imm32/false
20730       74/jump-if-= break/disp8
20731       eb/jump $check-mu-copy-to-stmt:end/disp8
20732     }
20733     # if dest is not number-like, abort
20734     (check-mu-numberlike-arg %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20735 $check-mu-copy-to-stmt:end:
20736     # . reclaim locals
20737     81 0/subop/add %esp 0x6c/imm32
20738     # . restore registers
20739     5f/pop-to-edi
20740     5e/pop-to-esi
20741     5b/pop-to-ebx
20742     5a/pop-to-edx
20743     59/pop-to-ecx
20744     58/pop-to-eax
20745     # . epilogue
20746     89/<- %esp 5/r32/ebp
20747     5d/pop-to-ebp
20748     c3/return
20749 
20750 $check-mu-copy-to-stmt:error-incorrect-inouts:
20751     (write-buffered *(ebp+0x10) "fn ")
20752     8b/-> *(ebp+0xc) 0/r32/eax
20753     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20754     (write-buffered *(ebp+0x10) %eax)
20755     (write-buffered *(ebp+0x10) ": stmt 'copy-to' must have two inouts\n")
20756     (flush *(ebp+0x10))
20757     (stop *(ebp+0x14) 1)
20758     # never gets here
20759 
20760 $check-mu-copy-to-stmt:error-too-many-outputs:
20761     (write-buffered *(ebp+0x10) "fn ")
20762     8b/-> *(ebp+0xc) 0/r32/eax
20763     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20764     (write-buffered *(ebp+0x10) %eax)
20765     (write-buffered *(ebp+0x10) ": stmt 'copy-to' must not have any outputs\n")
20766     (flush *(ebp+0x10))
20767     (stop *(ebp+0x14) 1)
20768     # never gets here
20769 
20770 $check-mu-copy-to-stmt:error-src-not-literal-or-in-register:
20771     (write-buffered *(ebp+0x10) "fn ")
20772     8b/-> *(ebp+0xc) 0/r32/eax
20773     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20774     (write-buffered *(ebp+0x10) %eax)
20775     (write-buffered *(ebp+0x10) ": stmt copy-to: source (second inout) is in memory\n")
20776     (flush *(ebp+0x10))
20777     (stop *(ebp+0x14) 1)
20778     # never gets here
20779 
20780 $check-mu-copy-to-stmt:error-src-too-large:
20781     (write-buffered *(ebp+0x10) "fn ")
20782     8b/-> *(ebp+0xc) 0/r32/eax
20783     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20784     (write-buffered *(ebp+0x10) %eax)
20785     (write-buffered *(ebp+0x10) ": stmt copy-to: '")
20786     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
20787     (lookup *eax *(eax+4))  # Var-name Var-name => eax
20788     (write-buffered *(ebp+0x10) %eax)
20789     (write-buffered *(ebp+0x10) "' is too large to copy\n")
20790     (flush *(ebp+0x10))
20791     (stop *(ebp+0x14) 1)
20792     # never gets here
20793 
20794 check-mu-compare-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
20795     # . prologue
20796     55/push-ebp
20797     89/<- %ebp 4/r32/esp
20798     # . save registers
20799     50/push-eax
20800     51/push-ecx
20801     52/push-edx
20802     53/push-ebx
20803     56/push-esi
20804     57/push-edi
20805     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
20806     81 5/subop/subtract %esp 0x60/imm32
20807     68/push 0x60/imm32/size
20808     68/push 0/imm32/read
20809     68/push 0/imm32/write
20810     89/<- %edx 4/r32/esp
20811     # esi = stmt
20812     8b/-> *(ebp+8) 6/r32/esi
20813 $check-mu-compare-stmt:check-for-output:
20814     # if stmt->outputs abort
20815     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
20816     3d/compare-eax-and 0/imm32
20817     0f 85/jump-if-!= $check-mu-compare-stmt:error-too-many-outputs/disp32
20818 $check-mu-compare-stmt:get-left:
20819     # var left/edi: (addr stmt-var) = stmt->inouts
20820     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
20821     89/<- %edi 0/r32/eax
20822     # zero inouts
20823     3d/compare-eax-and 0/imm32
20824     0f 84/jump-if-= $check-mu-compare-stmt:error-incorrect-inouts/disp32
20825 $check-mu-compare-stmt:get-right:
20826     # var right/esi: (addr stmt-var) = left->next
20827     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
20828     89/<- %esi 0/r32/eax
20829     # 1 inout
20830     3d/compare-eax-and 0/imm32
20831     0f 84/jump-if-= $check-mu-compare-stmt:error-incorrect-inouts/disp32
20832     # > 2 inouts
20833     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
20834     3d/compare-eax-and 0/imm32
20835     0f 85/jump-if-!= $check-mu-compare-stmt:error-incorrect-inouts/disp32
20836     # if both inouts are in memory, abort
20837     {
20838 $check-mu-compare-stmt:both-in-mem:
20839       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
20840       (lookup *(eax+0x8) *(eax+0xc))  # Var-type Var-type => eax
20841       (is-simple-mu-type? %eax 0)  # => eax
20842       3d/compare-eax-and 0/imm32
20843       0f 85/jump-if-!= break/disp32
20844       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
20845       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
20846       3d/compare-eax-and 0/imm32
20847       75/jump-if-!= break/disp8
20848       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
20849       (lookup *(eax+0x8) *(eax+0xc))  # Var-type Var-type => eax
20850       (is-simple-mu-type? %eax 0)  # => eax
20851       3d/compare-eax-and 0/imm32
20852       75/jump-if-!= break/disp8
20853       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
20854       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
20855       3d/compare-eax-and 0/imm32
20856       75/jump-if-!= break/disp8
20857       e9/jump $check-mu-compare-stmt:error-both-in-memory/disp32
20858     }
20859 $check-mu-compare-stmt:types:
20860     # var right-type/ecx: (addr type-tree) = right->value->type
20861     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
20862     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20863     89/<- %ecx 0/r32/eax
20864     # if (right->is-deref?) right-type = right-type->payload
20865     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
20866     3d/compare-eax-and 0/imm32/false
20867     {
20868       74/jump-if-= break/disp8
20869       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
20870       # if right-type->right is null, right-type = right-type->left
20871       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
20872       {
20873         75/jump-if-!= break/disp8
20874         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20875       }
20876       89/<- %ecx 0/r32/eax
20877     }
20878     # if right is not a scalar, abort
20879     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
20880     (size-of %eax)  # => eax
20881     3d/compare-eax-and 4/imm32
20882     0f 8f/jump-if-> $check-mu-compare-stmt:error-right-too-large/disp32
20883     # if left is not a scalar, abort
20884     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
20885     (size-of %eax)  # => eax
20886     3d/compare-eax-and 4/imm32
20887     0f 8f/jump-if-> $check-mu-compare-stmt:error-left-too-large/disp32
20888     # var left-type/ebx: (addr type-tree) = left->value->type
20889     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
20890     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20891     89/<- %ebx 0/r32/eax
20892     # if (left->is-deref?) left-type = left-type->payload
20893     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
20894     3d/compare-eax-and 0/imm32/false
20895     {
20896       74/jump-if-= break/disp8
20897       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
20898       # if left-type->right is null, left-type = left-type->left
20899       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
20900       {
20901         75/jump-if-!= break/disp8
20902         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20903       }
20904       89/<- %ebx 0/r32/eax
20905     }
20906     # if (left-type == right-type) return
20907     (type-match? %ebx %ecx %edx)  # => eax
20908     3d/compare-eax-and 0/imm32
20909     0f 85/jump-if-!= $check-mu-compare-stmt:end/disp32
20910     # if left is an addr and right is 0, return
20911     {
20912       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
20913       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20914       (is-mu-addr-type? %eax)  # => eax
20915       3d/compare-eax-and 0/imm32/false
20916       74/jump-if-= break/disp8
20917       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
20918       (lookup *eax *(eax+4))  # Var-name Var-name => eax
20919       (string-equal? %eax "0")  # => eax
20920       3d/compare-eax-and 0/imm32/false
20921       74/jump-if-= break/disp8
20922       eb/jump $check-mu-compare-stmt:end/disp8
20923     }
20924     # if left is not number-like, abort
20925     (check-mu-numberlike-arg %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20926 $check-mu-compare-stmt:end:
20927     # . reclaim locals
20928     81 0/subop/add %esp 0x6c/imm32
20929     # . restore registers
20930     5f/pop-to-edi
20931     5e/pop-to-esi
20932     5b/pop-to-ebx
20933     5a/pop-to-edx
20934     59/pop-to-ecx
20935     58/pop-to-eax
20936     # . epilogue
20937     89/<- %esp 5/r32/ebp
20938     5d/pop-to-ebp
20939     c3/return
20940 
20941 $check-mu-compare-stmt:error-incorrect-inouts:
20942     (write-buffered *(ebp+0x10) "fn ")
20943     8b/-> *(ebp+0xc) 0/r32/eax
20944     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20945     (write-buffered *(ebp+0x10) %eax)
20946     (write-buffered *(ebp+0x10) ": stmt 'compare' must have two inouts\n")
20947     (flush *(ebp+0x10))
20948     (stop *(ebp+0x14) 1)
20949     # never gets here
20950 
20951 $check-mu-compare-stmt:error-too-many-outputs:
20952     (write-buffered *(ebp+0x10) "fn ")
20953     8b/-> *(ebp+0xc) 0/r32/eax
20954     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20955     (write-buffered *(ebp+0x10) %eax)
20956     (write-buffered *(ebp+0x10) ": stmt 'compare' must not have any outputs\n")
20957     (flush *(ebp+0x10))
20958     (stop *(ebp+0x14) 1)
20959     # never gets here
20960 
20961 $check-mu-compare-stmt:error-both-in-memory:
20962     (write-buffered *(ebp+0x10) "fn ")
20963     8b/-> *(ebp+0xc) 0/r32/eax
20964     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20965     (write-buffered *(ebp+0x10) %eax)
20966     (write-buffered *(ebp+0x10) ": stmt compare: both inouts are in memory\n")
20967     (flush *(ebp+0x10))
20968     (stop *(ebp+0x14) 1)
20969     # never gets here
20970 
20971 $check-mu-compare-stmt:error-left-too-large:
20972     (write-buffered *(ebp+0x10) "fn ")
20973     8b/-> *(ebp+0xc) 0/r32/eax
20974     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20975     (write-buffered *(ebp+0x10) %eax)
20976     (write-buffered *(ebp+0x10) ": stmt compare: '")
20977     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
20978     (lookup *eax *(eax+4))  # Var-name Var-name => eax
20979     (write-buffered *(ebp+0x10) %eax)
20980     (write-buffered *(ebp+0x10) "' is too large to compare\n")
20981     (flush *(ebp+0x10))
20982     (stop *(ebp+0x14) 1)
20983     # never gets here
20984 
20985 $check-mu-compare-stmt:error-right-too-large:
20986     (write-buffered *(ebp+0x10) "fn ")
20987     8b/-> *(ebp+0xc) 0/r32/eax
20988     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20989     (write-buffered *(ebp+0x10) %eax)
20990     (write-buffered *(ebp+0x10) ": stmt compare: '")
20991     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
20992     (lookup *eax *(eax+4))  # Var-name Var-name => eax
20993     (write-buffered *(ebp+0x10) %eax)
20994     (write-buffered *(ebp+0x10) "' is too large to compare\n")
20995     (flush *(ebp+0x10))
20996     (stop *(ebp+0x14) 1)
20997     # never gets here
20998 
20999 check-mu-address-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21000     # . prologue
21001     55/push-ebp
21002     89/<- %ebp 4/r32/esp
21003     # . save registers
21004     50/push-eax
21005     51/push-ecx
21006     52/push-edx
21007     56/push-esi
21008     57/push-edi
21009 $check-mu-address-stmt:get-output:
21010     # esi = stmt
21011     8b/-> *(ebp+8) 6/r32/esi
21012     # var output/edi: (addr stmt-var) = stmt->outputs
21013     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
21014     89/<- %edi 0/r32/eax
21015     # zero outputs
21016     3d/compare-eax-and 0/imm32
21017     0f 84/jump-if-= $check-mu-address-stmt:error-no-output/disp32
21018     # > 1 output
21019     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
21020     3d/compare-eax-and 0/imm32
21021     0f 85/jump-if-!= $check-mu-address-stmt:error-too-many-outputs/disp32
21022 $check-mu-address-stmt:get-inout:
21023     # var inout/esi: (addr stmt-var) = stmt->inouts
21024     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21025     89/<- %esi 0/r32/eax
21026     # zero inouts
21027     3d/compare-eax-and 0/imm32
21028     0f 84/jump-if-= $check-mu-address-stmt:error-no-inout/disp32
21029     # > 1 inout
21030     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
21031     3d/compare-eax-and 0/imm32
21032     0f 85/jump-if-!= $check-mu-address-stmt:error-too-many-inouts/disp32
21033 $check-mu-address-stmt:types:
21034     # if output not in register, abort
21035     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21036     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
21037     3d/compare-eax-and 0/imm32
21038     0f 84/jump-if-= $check-mu-address-stmt:error-output-not-in-register/disp32
21039     # var output-type/edx: (addr type-tree) = output->value->type
21040     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21041     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21042     89/<- %edx 0/r32/eax
21043     # if output-type not an addr, abort
21044     (is-mu-addr-type? %edx)  # => eax
21045     3d/compare-eax-and 0/imm32/false
21046     0f 84/jump-if-= $check-mu-address-stmt:error-output-not-address/disp32
21047     # output-type = output-type->right
21048     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
21049     # if output-type->right is null, output-type = output-type->left
21050     81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
21051     {
21052       75/jump-if-!= break/disp8
21053       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21054     }
21055     89/<- %edx 0/r32/eax
21056     # var inout-type/ecx: (addr type-tree) = inout->value->type
21057     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
21058     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21059     89/<- %ecx 0/r32/eax
21060     # if (inout->is-deref?) inout-type = inout-type->payload
21061     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
21062     3d/compare-eax-and 0/imm32/false
21063     {
21064       74/jump-if-= break/disp8
21065       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
21066       # if inout-type->right is null, t = inout-type->left
21067       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
21068       {
21069         75/jump-if-!= break/disp8
21070         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21071       }
21072       89/<- %ecx 0/r32/eax
21073     }
21074     # if (inout-type != output-type) abort
21075     (type-equal-ignoring-capacity? %edx %ecx)  # => eax
21076     3d/compare-eax-and 0/imm32
21077     0f 84/jump-if-= $check-mu-address-stmt:error-type-mismatch/disp32
21078 $check-mu-address-stmt:end:
21079     # . restore registers
21080     5f/pop-to-edi
21081     5e/pop-to-esi
21082     5a/pop-to-edx
21083     59/pop-to-ecx
21084     58/pop-to-eax
21085     # . epilogue
21086     89/<- %esp 5/r32/ebp
21087     5d/pop-to-ebp
21088     c3/return
21089 
21090 $check-mu-address-stmt:error-no-inout:
21091     (write-buffered *(ebp+0x10) "fn ")
21092     8b/-> *(ebp+0xc) 0/r32/eax
21093     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21094     (write-buffered *(ebp+0x10) %eax)
21095     (write-buffered *(ebp+0x10) ": stmt 'address' expects an inout\n")
21096     (flush *(ebp+0x10))
21097     (stop *(ebp+0x14) 1)
21098     # never gets here
21099 
21100 $check-mu-address-stmt:error-too-many-inouts:
21101     (write-buffered *(ebp+0x10) "fn ")
21102     8b/-> *(ebp+0xc) 0/r32/eax
21103     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21104     (write-buffered *(ebp+0x10) %eax)
21105     (write-buffered *(ebp+0x10) ": stmt 'address' must have just one inout\n")
21106     (flush *(ebp+0x10))
21107     (stop *(ebp+0x14) 1)
21108     # never gets here
21109 
21110 $check-mu-address-stmt:error-no-output:
21111     (write-buffered *(ebp+0x10) "fn ")
21112     8b/-> *(ebp+0xc) 0/r32/eax
21113     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21114     (write-buffered *(ebp+0x10) %eax)
21115     (write-buffered *(ebp+0x10) ": stmt 'address' expects an output\n")
21116     (flush *(ebp+0x10))
21117     (stop *(ebp+0x14) 1)
21118     # never gets here
21119 
21120 $check-mu-address-stmt:error-output-not-in-register:
21121     (write-buffered *(ebp+0x10) "fn ")
21122     8b/-> *(ebp+0xc) 0/r32/eax
21123     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21124     (write-buffered *(ebp+0x10) %eax)
21125     (write-buffered *(ebp+0x10) ": stmt address: output '")
21126     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21127     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21128     (write-buffered *(ebp+0x10) %eax)
21129     (write-buffered *(ebp+0x10) "' not in a register\n")
21130     (flush *(ebp+0x10))
21131     (stop *(ebp+0x14) 1)
21132     # never gets here
21133 
21134 $check-mu-address-stmt:error-too-many-outputs:
21135     (write-buffered *(ebp+0x10) "fn ")
21136     8b/-> *(ebp+0xc) 0/r32/eax
21137     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21138     (write-buffered *(ebp+0x10) %eax)
21139     (write-buffered *(ebp+0x10) ": stmt 'address' must have just one output\n")
21140     (flush *(ebp+0x10))
21141     (stop *(ebp+0x14) 1)
21142     # never gets here
21143 
21144 $check-mu-address-stmt:error-output-not-address:
21145     (write-buffered *(ebp+0x10) "fn ")
21146     8b/-> *(ebp+0xc) 0/r32/eax
21147     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21148     (write-buffered *(ebp+0x10) %eax)
21149     (write-buffered *(ebp+0x10) ": stmt address: output '")
21150     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21151     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21152     (write-buffered *(ebp+0x10) %eax)
21153     (write-buffered *(ebp+0x10) "' is not an addr\n")
21154     (flush *(ebp+0x10))
21155     (stop *(ebp+0x14) 1)
21156     # never gets here
21157 
21158 $check-mu-address-stmt:error-type-mismatch:
21159     (write-buffered *(ebp+0x10) "fn ")
21160     8b/-> *(ebp+0xc) 0/r32/eax
21161     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21162     (write-buffered *(ebp+0x10) %eax)
21163     (write-buffered *(ebp+0x10) ": stmt address: output '")
21164     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21165     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21166     (write-buffered *(ebp+0x10) %eax)
21167     (write-buffered *(ebp+0x10) "' cannot hold address of '")
21168     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
21169     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21170     (write-buffered *(ebp+0x10) %eax)
21171     (write-buffered *(ebp+0x10) "'\n")
21172     (flush *(ebp+0x10))
21173     (stop *(ebp+0x14) 1)
21174     # never gets here
21175 
21176 type-equal-ignoring-capacity?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
21177     # . prologue
21178     55/push-ebp
21179     89/<- %ebp 4/r32/esp
21180     # . save registers
21181     51/push-ecx
21182     52/push-edx
21183     53/push-ebx
21184     # var curr-a/ecx: (addr type-tree) = a
21185     8b/-> *(ebp+8) 1/r32/ecx
21186     # var curr-b/ebx: (addr type-tree) = b
21187     8b/-> *(ebp+0xc) 3/r32/ebx
21188     # if (curr-a->is-atom?) fall back to regular equality
21189     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
21190     0f 85/jump-if-!= $type-equal-ignoring-capacity?:base-case/disp32
21191     # if (curr-a->left != curr-b->left) return false
21192     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
21193     89/<- %edx 0/r32/eax
21194     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
21195     (type-equal? %edx %eax)  # => eax
21196     3d/compare-eax-and 0/imm32/false
21197     0f 84/jump-if-= $type-equal-ignoring-capacity?:end/disp32  # eax switches meaning
21198     # if (curr-a->left == "array") curr-a = curr-a->element-type
21199     {
21200       (is-mu-array? %edx)  # => eax
21201       3d/compare-eax-and 0/imm32/false
21202       75/jump-if-!= break/disp8
21203 $type-equal-ignoring-capacity?:array:
21204       # curr-a = curr-a->right->left
21205       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
21206       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21207       89/<- %ecx 0/r32/eax
21208       # curr-b = curr-b->right->left
21209       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
21210       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21211       89/<- %ebx 0/r32/eax
21212       eb/jump $type-equal-ignoring-capacity?:base-case/disp8
21213     }
21214     # if (curr-a->left == "stream") curr-a = curr-a->element-type
21215     {
21216       (is-mu-stream? %edx)  # => eax
21217       3d/compare-eax-and 0/imm32/false
21218       75/jump-if-!= break/disp8
21219 $type-equal-ignoring-capacity?:stream:
21220       # curr-a = curr-a->right->left
21221       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
21222       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21223       89/<- %ecx 0/r32/eax
21224       # curr-b = curr-b->right->left
21225       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
21226       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21227       89/<- %ebx 0/r32/eax
21228       eb/jump $type-equal-ignoring-capacity?:base-case/disp8
21229     }
21230 $type-equal-ignoring-capacity?:base-case:
21231     # return type-equal?(curr-a, curr-b)
21232     (type-equal? %ecx %ebx)  # => eax
21233 $type-equal-ignoring-capacity?:end:
21234     # . restore registers
21235     5b/pop-to-ebx
21236     5a/pop-to-edx
21237     59/pop-to-ecx
21238     # . epilogue
21239     89/<- %esp 5/r32/ebp
21240     5d/pop-to-ebp
21241     c3/return
21242 
21243 check-mu-return-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21244     # . prologue
21245     55/push-ebp
21246     89/<- %ebp 4/r32/esp
21247     # . save registers
21248     50/push-eax
21249     51/push-ecx
21250     52/push-edx
21251     53/push-ebx
21252     56/push-esi
21253     57/push-edi
21254     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
21255     81 5/subop/subtract %esp 0x60/imm32
21256     68/push 0x60/imm32/size
21257     68/push 0/imm32/read
21258     68/push 0/imm32/write
21259     89/<- %edx 4/r32/esp
21260     # var template/esi: (addr list var) = fn->outputs
21261     8b/-> *(ebp+0xc) 0/r32/eax
21262     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
21263     89/<- %esi 0/r32/eax
21264     # var curr-template/ebx: (addr list var) = fn->outputs
21265     89/<- %ebx 0/r32/eax
21266     # var curr/edi: (addr stmt-var) = stmt->inouts
21267     8b/-> *(ebp+8) 0/r32/eax
21268     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21269     89/<- %edi 0/r32/eax
21270     {
21271       # if template is null, break
21272       81 7/subop/compare %ebx 0/imm32
21273       0f 84/jump-if-= break/disp32
21274       # if curr is null, abort
21275       81 7/subop/compare %edi 0/imm32
21276       0f 84/jump-if-= $check-mu-return-stmt:error-too-few-inouts/disp32
21277       # var template-type/ecx: (addr type-tree) = template->value->type
21278       (lookup *ebx *(ebx+4))  # List-value List-value => eax
21279       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21280       89/<- %ecx 0/r32/eax
21281       # var curr-type/eax: (addr type-tree) = curr->value->type
21282       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21283       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21284       # if (curr->is-deref?) curr-type = payload of curr-type
21285       81 7/subop/compare *(edi+0x10) 0/imm32/false  # Stmt-var-is-deref
21286       {
21287         74/jump-if-= break/disp8
21288         (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
21289         # if t->right is null, t = t->left
21290         81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
21291         75/jump-if-!= break/disp8
21292         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21293       }
21294       # if (curr-type != template-type) abort
21295       (type-match? %ecx %eax %edx)  # => eax
21296       3d/compare-eax-and 0/imm32/false
21297       0f 84/jump-if-= $check-mu-return-stmt:error1/disp32
21298       # if register-within-list-with-conflict?(curr, original template, curr-template, stmt) abort
21299       (register-within-list-with-conflict? %edi %esi %ebx *(ebp+8))  # => eax
21300       3d/compare-eax-and 0/imm32/false
21301       0f 85/jump-if-!= $check-mu-return-stmt:error2/disp32
21302       # template = template->next
21303       (lookup *(ebx+8) *(ebx+0xc))  # List-next List-next => eax
21304       89/<- %ebx 0/r32/eax
21305       # curr = curr->next
21306       (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
21307       89/<- %edi 0/r32/eax
21308       #
21309       e9/jump loop/disp32
21310     }
21311     # if curr is not null, abort
21312     81 7/subop/compare %edi 0/imm32
21313     0f 85/jump-if-!= $check-mu-return-stmt:error-too-many-inouts/disp32
21314 $check-mu-return-stmt:end:
21315     # . reclaim locals
21316     81 0/subop/add %esp 0x6c/imm32
21317     # . restore registers
21318     5f/pop-to-edi
21319     5e/pop-to-esi
21320     5b/pop-to-ebx
21321     5a/pop-to-edx
21322     59/pop-to-ecx
21323     58/pop-to-eax
21324     # . epilogue
21325     89/<- %esp 5/r32/ebp
21326     5d/pop-to-ebp
21327     c3/return
21328 
21329 $check-mu-return-stmt:error1:
21330     (write-buffered *(ebp+0x10) "fn ")
21331     8b/-> *(ebp+0xc) 0/r32/eax
21332     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21333     (write-buffered *(ebp+0x10) %eax)
21334     (write-buffered *(ebp+0x10) ": return: '")
21335     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21336     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21337     (write-buffered *(ebp+0x10) %eax)
21338     (write-buffered *(ebp+0x10) "' has the wrong type\n")
21339     (flush *(ebp+0x10))
21340     (stop *(ebp+0x14) 1)
21341     # never gets here
21342 
21343 $check-mu-return-stmt:error2:
21344     (write-buffered *(ebp+0x10) "fn ")
21345     8b/-> *(ebp+0xc) 0/r32/eax
21346     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21347     (write-buffered *(ebp+0x10) %eax)
21348     (write-buffered *(ebp+0x10) ": return: '")
21349     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21350     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21351     (write-buffered *(ebp+0x10) %eax)
21352     (write-buffered *(ebp+0x10) "' is no longer available\n")
21353     (flush *(ebp+0x10))
21354     (stop *(ebp+0x14) 1)
21355     # never gets here
21356 
21357 $check-mu-return-stmt:error-too-few-inouts:
21358     (write-buffered *(ebp+0x10) "fn ")
21359     8b/-> *(ebp+0xc) 0/r32/eax
21360     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21361     (write-buffered *(ebp+0x10) %eax)
21362     (write-buffered *(ebp+0x10) ": return: too few inouts\n")
21363     (flush *(ebp+0x10))
21364     (stop *(ebp+0x14) 1)
21365     # never gets here
21366 
21367 $check-mu-return-stmt:error-too-many-inouts:
21368     (write-buffered *(ebp+0x10) "fn ")
21369     8b/-> *(ebp+0xc) 0/r32/eax
21370     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21371     (write-buffered *(ebp+0x10) %eax)
21372     (write-buffered *(ebp+0x10) ": return: too many inouts\n")
21373     (flush *(ebp+0x10))
21374     (stop *(ebp+0x14) 1)
21375     # never gets here
21376 
21377 check-all-unique-registers:  # outputs: (addr list var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21378     # . prologue
21379     55/push-ebp
21380     89/<- %ebp 4/r32/esp
21381     # . save registers
21382     50/push-eax
21383     51/push-ecx
21384     56/push-esi
21385     # var table/esi: (addr table (handle array byte) int 8)
21386     81 5/subop/subtract %esp 0x60/imm32
21387     68/push 0x60/imm32/size
21388     68/push 0/imm32/read
21389     68/push 0/imm32/write
21390     89/<- %esi 4/r32/esp
21391     # var curr/ecx: (addr list var) = outputs
21392     8b/-> *(ebp+8) 1/r32/ecx
21393     {
21394       # if (curr == 0) break
21395       81 7/subop/compare %ecx 0/imm32
21396       0f 84/jump-if-= break/disp32
21397       # var reg/eax: (addr array byte) = curr->value->register  # guaranteed to exist
21398       (lookup *ecx *(ecx+4))  # List-value List-value => eax
21399       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
21400       # if reg exists in table, abort
21401       (maybe-get %esi %eax 0xc)  # => eax
21402       3d/compare-eax-and 0/imm32
21403       0f 85/jump-if-!= $check-all-unique-registers:abort/disp32
21404       # insert reg in table
21405       (lookup *ecx *(ecx+4))  # List-value List-value => eax
21406       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
21407       (get-or-insert %esi %eax 0xc Heap)
21408       # curr = curr->next
21409       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
21410       89/<- %ecx 0/r32/eax
21411       e9/jump loop/disp32
21412     }
21413 $check-all-unique-registers:end:
21414     # . reclaim locals
21415     81 0/subop/add %esp 0x6c/imm32
21416     # . restore registers
21417     5e/pop-to-esi
21418     59/pop-to-ecx
21419     58/pop-to-eax
21420     # . epilogue
21421     89/<- %esp 5/r32/ebp
21422     5d/pop-to-ebp
21423     c3/return
21424 
21425 $check-all-unique-registers:abort:
21426     (write-buffered *(ebp+0x10) "fn ")
21427     8b/-> *(ebp+0xc) 0/r32/eax
21428     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21429     (write-buffered *(ebp+0x10) %eax)
21430     (write-buffered *(ebp+0x10) ": outputs must be in unique registers\n")
21431     (flush *(ebp+0x10))
21432     (stop *(ebp+0x14) 1)
21433     # never gets here
21434 
21435 # return false if s's register is not between start (inclusive) and end (exclusive)
21436 # return false if the positionally corresponding register in stmt->inouts (where s comes from) is also s's register
21437 # otherwise return true
21438 register-within-list-with-conflict?:  # s: (addr stmt-var), start: (addr list var), end: (addr list var), stmt: (addr stmt) -> result/eax: boolean
21439     # . prologue
21440     55/push-ebp
21441     89/<- %ebp 4/r32/esp
21442     # . save registers
21443     51/push-ecx
21444     52/push-edx
21445     53/push-ebx
21446     56/push-esi
21447     57/push-edi
21448     # var target/ebx: (addr array byte) = s->value->register
21449     8b/-> *(ebp+8) 0/r32/eax
21450     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21451     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
21452 #?     (write-buffered Stderr "AA: ")
21453 #?     (write-buffered Stderr %eax)
21454 #?     (write-buffered Stderr Newline)
21455 #?     (flush Stderr)
21456     # if (var->register == 0) return false
21457     3d/compare-eax-and 0/imm32
21458     0f 84/jump-if-= $register-within-list-with-conflict?:end/disp32  # eax turns into result
21459     89/<- %ebx 0/r32/eax
21460     # var curr/ecx: (addr list var) = start
21461     8b/-> *(ebp+0xc) 1/r32/ecx
21462     # edx = end
21463     8b/-> *(ebp+0x10) 2/r32/edx
21464     {
21465       # if (curr == 0) break
21466       81 7/subop/compare %edi 0/imm32
21467       0f 84/jump-if-= break/disp32
21468       # if (curr == end) break
21469       39/compare %ecx 2/r32/edx
21470       0f 84/jump-if-= break/disp32
21471       # var curr-reg/eax: (addr array byte) = curr->value->register
21472       (lookup *ecx *(ecx+4))  # List-value List-value => eax
21473       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
21474       # if (curr-reg == 0) continue
21475       3d/compare-eax-and 0/imm32
21476       74/jump-if-= $register-within-list-with-conflict?:continue/disp8
21477       # if (curr-reg == target) check for conflict
21478       (string-equal? %eax %ebx)  # => eax
21479       3d/compare-eax-and 0/imm32/false
21480       {
21481         74/jump-if-= break/disp8
21482 #?         (write-buffered Stderr "conflict?\n")
21483 #?         (flush Stderr)
21484         # var return-inouts/eax: (addr stmt-var) = stmt->inouts
21485         8b/-> *(ebp+0x14) 0/r32/eax
21486         (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21487         (register-conflict? %ebx %eax *(ebp+0xc))  # => eax
21488         eb/jump $register-within-list-with-conflict?:end/disp8
21489       }
21490 $register-within-list-with-conflict?:continue:
21491       # curr = curr->next
21492       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
21493       89/<- %ecx 0/r32/eax
21494       e9/jump loop/disp32
21495     }
21496     # return false
21497     b8/copy-to-eax 0/imm32/false
21498 $register-within-list-with-conflict?:end:
21499     # . restore registers
21500     5f/pop-to-edi
21501     5e/pop-to-esi
21502     5b/pop-to-ebx
21503     5a/pop-to-edx
21504     59/pop-to-ecx
21505     # . epilogue
21506     89/<- %esp 5/r32/ebp
21507     5d/pop-to-ebp
21508     c3/return
21509 
21510 # At the first occurrence of register 'reg' in fn-outputs,
21511 # check if the corresponding element of return-inouts has a different register.
21512 # This hacky helper is intended to be called in one specific place. Don't
21513 # reuse it as is.
21514 register-conflict?:  # reg: (addr array byte), return-inouts: (addr stmt-var), fn-outputs: (addr list var) => result/eax: boolean
21515     # . prologue
21516     55/push-ebp
21517     89/<- %ebp 4/r32/esp
21518     # . save registers
21519     51/push-ecx
21520     52/push-edx
21521     53/push-ebx
21522     56/push-esi
21523     57/push-edi
21524 #?     (write-buffered Stderr "BB: ")
21525 #?     (write-buffered Stderr *(ebp+8))
21526 #?     (write-buffered Stderr Newline)
21527 #?     (flush Stderr)
21528     # var curr-output/edi: (addr list var) = fn-outputs
21529     8b/-> *(ebp+0x10) 7/r32/edi
21530     # var curr-inout/esi: (addr stmt-var) = return-inouts
21531     8b/-> *(ebp+0xc) 6/r32/esi
21532     {
21533       # if (curr-output == 0) abort
21534       81 7/subop/compare %edi 0/imm32
21535       0f 84/jump-if-= break/disp32
21536       # if (curr-output->value->register != reg) continue
21537       (lookup *edi *(edi+4))  # List-value List-value => eax
21538       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
21539       (string-equal? %eax *(ebp+8))  # => eax
21540       3d/compare-eax-and 0/imm32/false
21541       0f 84/jump-if= $register-conflict?:continue/disp32
21542 #?       (write-buffered Stderr "rescan\n")
21543 #?       (flush Stderr)
21544       # var curr-reg/eax: (addr array byte) = curr-inout->value->register
21545       (lookup *esi *(esi+4))  # List-value List-value => eax
21546       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
21547       # if (curr-reg == 0) return true
21548       3d/compare-eax-and 0/imm32
21549       {
21550         75/jump-if-!= break/disp8
21551 #?         (write-buffered Stderr "no register\n")
21552 #?         (flush Stderr)
21553         b8/copy-to-eax 1/imm32/true
21554         e9/jump $register-conflict?:end/disp32
21555       }
21556       # return (curr-reg != reg)
21557       (string-equal? %eax *(ebp+8))  # => eax
21558       3d/compare-eax-and 0/imm32/false
21559       0f 94/set-if-= %al
21560 #?       (write-buffered Stderr "final: ")
21561 #?       (write-int32-hex-buffered Stderr %eax)
21562 #?       (write-buffered Stderr Newline)
21563 #?       (flush Stderr)
21564       eb/jump $register-conflict?:end/disp8
21565 $register-conflict?:continue:
21566       # curr-output = curr-output->next
21567       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
21568       89/<- %edi 0/r32/eax
21569       # curr-inout = curr-inout->next
21570       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
21571       89/<- %esi 0/r32/eax
21572       e9/jump loop/disp32
21573     }
21574     # should never get here
21575     (write-buffered Stderr "register-conflict? misused\n")
21576     (flush Stderr)
21577     e8/call syscall_exit/disp32
21578 $register-conflict?:end:
21579     # . restore registers
21580     5f/pop-to-edi
21581     5e/pop-to-esi
21582     5b/pop-to-ebx
21583     5a/pop-to-edx
21584     59/pop-to-ecx
21585     # . epilogue
21586     89/<- %esp 5/r32/ebp
21587     5d/pop-to-ebp
21588     c3/return
21589 
21590 check-final-stmt-is-return:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21591     # . prologue
21592     55/push-ebp
21593     89/<- %ebp 4/r32/esp
21594     # . save registers
21595     50/push-eax
21596     51/push-ecx
21597     # var curr/ecx: (addr list stmt) = block->stmts
21598     8b/-> *(ebp+8) 0/r32/eax
21599     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
21600     3d/compare-eax-and 0/imm32
21601     74/jump-if-= $check-final-stmt-is-return:end/disp8
21602     89/<- %ecx 0/r32/eax
21603     {
21604       # if curr->next == 0, break
21605       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
21606       3d/compare-eax-and 0/imm32
21607       74/jump-if-= break/disp8
21608       # curr = curr->next
21609       89/<- %ecx 0/r32/eax
21610       e9/jump loop/disp32
21611     }
21612 $check-final-stmt-is-return:check-tag:
21613     # if curr->value->tag != Stmt1, abort
21614     (lookup *ecx *(ecx+4))  # List-value List-value => eax
21615     81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
21616     75/jump-if-!= $check-final-stmt-is-return:error/disp8
21617 $check-final-stmt-is-return:check-operation:
21618     # if curr->operation != "return", abort
21619     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
21620     (string-equal? %eax "return")
21621     3d/compare-eax-and 0/imm32/false
21622     74/jump-if-= $check-final-stmt-is-return:error/disp8
21623 $check-final-stmt-is-return:end:
21624     # . restore registers
21625     59/pop-to-ecx
21626     58/pop-to-eax
21627     # . epilogue
21628     89/<- %esp 5/r32/ebp
21629     5d/pop-to-ebp
21630     c3/return
21631 
21632 $check-final-stmt-is-return:error:
21633     (write-buffered *(ebp+0x10) "fn ")
21634     8b/-> *(ebp+0xc) 0/r32/eax
21635     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21636     (write-buffered *(ebp+0x10) %eax)
21637     (write-buffered *(ebp+0x10) ": final statement should be a 'return'\n")
21638     (flush *(ebp+0x10))
21639     (stop *(ebp+0x14) 1)
21640     # never gets here
21641 
21642 check-no-breaks:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21643     # . prologue
21644     55/push-ebp
21645     89/<- %ebp 4/r32/esp
21646     # . save registers
21647     50/push-eax
21648     51/push-ecx
21649     # var curr/ecx: (addr list stmt) = block->stmts
21650     8b/-> *(ebp+8) 0/r32/eax
21651     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
21652     3d/compare-eax-and 0/imm32
21653     0f 84/jump-if-= $check-no-breaks:end/disp32
21654     89/<- %ecx 0/r32/eax
21655     {
21656       # if curr->next == 0, break
21657       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
21658       3d/compare-eax-and 0/imm32
21659       74/jump-if-= break/disp8
21660       # if curr->value->tag != Stmt1, continue
21661       (lookup *ecx *(ecx+4))  # List-value List-value => eax
21662       81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
21663       75/jump-if-!= $check-no-breaks:continue/disp8
21664       # if curr->value->operation starts with "break", abort
21665       (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
21666       (string-starts-with? %eax "break")  # => eax
21667       3d/compare-eax-and 0/imm32/false
21668       75/jump-if-!= $check-no-breaks:error/disp8
21669 $check-no-breaks:continue:
21670       # curr = curr->next
21671       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
21672       89/<- %ecx 0/r32/eax
21673       e9/jump loop/disp32
21674     }
21675 $check-no-breaks:end:
21676     # . restore registers
21677     59/pop-to-ecx
21678     58/pop-to-eax
21679     # . epilogue
21680     89/<- %esp 5/r32/ebp
21681     5d/pop-to-ebp
21682     c3/return
21683 
21684 $check-no-breaks:error:
21685     (write-buffered *(ebp+0x10) "fn ")
21686     8b/-> *(ebp+0xc) 0/r32/eax
21687     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21688     (write-buffered *(ebp+0x10) %eax)
21689     (write-buffered *(ebp+0x10) " has outputs, so you cannot 'break' out of the outermost block. Use 'return'.\n")
21690     (flush *(ebp+0x10))
21691     (stop *(ebp+0x14) 1)
21692     # never gets here
21693 
21694 check-mu-get-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21695     # . prologue
21696     55/push-ebp
21697     89/<- %ebp 4/r32/esp
21698     # . save registers
21699     50/push-eax
21700     51/push-ecx
21701     52/push-edx
21702     53/push-ebx
21703     56/push-esi
21704     57/push-edi
21705     # esi = stmt
21706     8b/-> *(ebp+8) 6/r32/esi
21707     # - check for 0 inouts
21708     # var base/ecx: (addr var) = stmt->inouts->value
21709     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21710     3d/compare-eax-and 0/imm32/false
21711     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-inouts/disp32
21712     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21713     89/<- %ecx 0/r32/eax
21714 $check-mu-get-stmt:check-base:
21715     # - check base type
21716     # if it's an 'addr', check that it's in a register
21717     # var base-type/ebx: (addr type-tree) = lookup(base->type)
21718     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
21719     89/<- %ebx 0/r32/eax
21720     {
21721       81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
21722       0f 85/jump-if-!= break/disp32
21723 $check-mu-get-stmt:base-is-compound:
21724       # if (type->left != addr) break
21725       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
21726       (is-simple-mu-type? %eax 2)  # addr => eax
21727       3d/compare-eax-and 0/imm32/false
21728       74/jump-if-= break/disp8
21729 $check-mu-get-stmt:base-is-addr:
21730       # now check for register
21731       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
21732       0f 84/jump-if-= $check-mu-get-stmt:error-base-type-addr-but-not-register/disp32
21733 $check-mu-get-stmt:base-is-addr-in-register:
21734       # type->left is now an addr; skip it
21735       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
21736       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
21737       0f 85/jump-if-!= $check-mu-get-stmt:error-bad-base/disp32
21738 $check-mu-get-stmt:base-is-addr-to-atom-in-register:
21739       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21740       89/<- %ebx 0/r32/eax
21741     }
21742 $check-mu-get-stmt:check-base-typeinfo:
21743     # ensure type is a container
21744     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
21745     {
21746       75/jump-if-!= break/disp8
21747       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
21748       89/<- %ebx 0/r32/eax
21749     }
21750     # var base-type-id/ebx: type-id = base-type->value
21751     8b/-> *(ebx+4) 3/r32/ebx  # Type-tree-value
21752     (is-container? %ebx)  # => eax
21753     3d/compare-eax-and 0/imm32/false
21754     0f 84/jump-if-= $check-mu-get-stmt:error-bad-base/disp32
21755     # var base-typeinfo/edx: (addr typeinfo) = find-typeinfo(base-type-id)
21756     # . var container/ecx: (handle typeinfo)
21757     68/push 0/imm32
21758     68/push 0/imm32
21759     89/<- %ecx 4/r32/esp
21760     # .
21761     (find-typeinfo %ebx %ecx)
21762     (lookup *ecx *(ecx+4))  # => eax
21763     # . reclaim container
21764     81 0/subop/add %esp 8/imm32
21765     # .
21766     89/<- %edx 0/r32/eax
21767     # var offset/ecx: (addr stmt-var) = stmt->inouts->next
21768     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21769     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
21770     89/<- %ecx 0/r32/eax
21771     # - check for 1 inout
21772     3d/compare-eax-and 0/imm32/false
21773     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-inouts/disp32
21774     # var offset/ecx: (addr var) = lookup(offset->value)
21775     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
21776     89/<- %ecx 0/r32/eax
21777     # - check for valid field
21778     81 7/subop/compare *(ecx+0x14) -1/imm32/uninitialized  # Var-offset
21779     0f 84/jump-if-= $check-mu-get-stmt:error-bad-field/disp32
21780     # - check for too many inouts
21781     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21782     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
21783     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
21784     3d/compare-eax-and 0/imm32/false
21785     0f 85/jump-if-!= $check-mu-get-stmt:error-too-many-inouts/disp32
21786     # var output/edi: (addr var) = stmt->outputs->value
21787     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
21788     # - check for 0 outputs
21789     3d/compare-eax-and 0/imm32/false
21790     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-outputs/disp32
21791     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21792     89/<- %edi 0/r32/eax
21793 $check-mu-get-stmt:check-output-type:
21794     # - check output type
21795     # must be in register
21796     (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
21797     3d/compare-eax-and 0/imm32
21798     0f 84/jump-if-= $check-mu-get-stmt:error-output-not-in-register/disp32
21799     # must have a non-atomic type
21800     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
21801     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
21802     0f 85/jump-if-!= $check-mu-get-stmt:error-output-type-not-address/disp32
21803     # type must start with (addr ...)
21804     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21805     (is-simple-mu-type? %eax 2)  # => eax
21806     3d/compare-eax-and 0/imm32/false
21807     0f 84/jump-if-= $check-mu-get-stmt:error-output-type-not-address/disp32
21808 $check-mu-get-stmt:check-output-type-match:
21809     # payload of addr type must match 'type' definition
21810     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
21811     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
21812     # if (payload->right == null) payload = payload->left
21813     81 7/subop/compare *(eax+0xc) 0/imm32/null  # Type-tree-right
21814     {
21815       75/jump-if-!= break/disp8
21816       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21817     }
21818     89/<- %edi 0/r32/eax
21819     # . var output-name/ecx: (addr array byte)
21820     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
21821     89/<- %ecx 0/r32/eax
21822     # . var base-typeinfo-entry/eax: (addr handle typeinfo-entry)
21823     (lookup *(edx+4) *(edx+8))  # Typeinfo-fields Typeinfo-fields => eax
21824     (get %eax %ecx 0x10)  # => eax
21825     # .
21826     (lookup *eax *(eax+4))  # => eax
21827     (lookup *eax *(eax+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
21828     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21829     # .
21830     (type-equal? %edi %eax)  # => eax
21831     3d/compare-eax-and 0/imm32/false
21832     0f 84/jump-if-= $check-mu-get-stmt:error-bad-output-type/disp32
21833     # - check for too many outputs
21834     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
21835     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
21836     3d/compare-eax-and 0/imm32/false
21837     0f 85/jump-if-!= $check-mu-get-stmt:error-too-many-outputs/disp32
21838 $check-mu-get-stmt:end:
21839     # . restore registers
21840     5f/pop-to-edi
21841     5e/pop-to-esi
21842     5b/pop-to-ebx
21843     5a/pop-to-edx
21844     59/pop-to-ecx
21845     58/pop-to-eax
21846     # . epilogue
21847     89/<- %esp 5/r32/ebp
21848     5d/pop-to-ebp
21849     c3/return
21850 
21851 $check-mu-get-stmt:error-too-few-inouts:
21852     (write-buffered *(ebp+0x10) "fn ")
21853     8b/-> *(ebp+0xc) 0/r32/eax
21854     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21855     (write-buffered *(ebp+0x10) %eax)
21856     (write-buffered *(ebp+0x10) ": stmt get: too few inouts (2 required)\n")
21857     (flush *(ebp+0x10))
21858     (stop *(ebp+0x14) 1)
21859     # never gets here
21860 
21861 $check-mu-get-stmt:error-too-many-inouts:
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 get: too many inouts (2 required)\n")
21867     (flush *(ebp+0x10))
21868     (stop *(ebp+0x14) 1)
21869     # never gets here
21870 
21871 $check-mu-get-stmt:error-too-few-outputs:
21872     (write-buffered *(ebp+0x10) "fn ")
21873     8b/-> *(ebp+0xc) 0/r32/eax
21874     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21875     (write-buffered *(ebp+0x10) %eax)
21876     (write-buffered *(ebp+0x10) ": stmt get: must have an output\n")
21877     (flush *(ebp+0x10))
21878     (stop *(ebp+0x14) 1)
21879     # never gets here
21880 
21881 $check-mu-get-stmt:error-too-many-outputs:
21882     (write-buffered *(ebp+0x10) "fn ")
21883     8b/-> *(ebp+0xc) 0/r32/eax
21884     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21885     (write-buffered *(ebp+0x10) %eax)
21886     (write-buffered *(ebp+0x10) ": stmt get: too many outputs (1 required)\n")
21887     (flush *(ebp+0x10))
21888     (stop *(ebp+0x14) 1)
21889     # never gets here
21890 
21891 $check-mu-get-stmt:error-bad-base:
21892     # error("fn " fn ": stmt get: var '" base->name "' must have a 'type' definition\n")
21893     (write-buffered *(ebp+0x10) "fn ")
21894     8b/-> *(ebp+0xc) 0/r32/eax
21895     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21896     (write-buffered *(ebp+0x10) %eax)
21897     (write-buffered *(ebp+0x10) ": stmt get: var '")
21898     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21899     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21900     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21901     (write-buffered *(ebp+0x10) %eax)
21902     (write-buffered *(ebp+0x10) "' must have a 'type' definition\n")
21903     (flush *(ebp+0x10))
21904     (stop *(ebp+0x14) 1)
21905     # never gets here
21906 
21907 $check-mu-get-stmt:error-base-type-addr-but-not-register:
21908     (write-buffered *(ebp+0x10) "fn ")
21909     8b/-> *(ebp+0xc) 0/r32/eax
21910     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21911     (write-buffered *(ebp+0x10) %eax)
21912     (write-buffered *(ebp+0x10) ": stmt get: var '")
21913     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21914     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21915     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21916     (write-buffered *(ebp+0x10) %eax)
21917     (write-buffered *(ebp+0x10) "' is an 'addr' type, and so must live in a register\n")
21918     (flush *(ebp+0x10))
21919     (stop *(ebp+0x14) 1)
21920     # never gets here
21921 
21922 $check-mu-get-stmt:error-bad-field:
21923     # error("fn " fn ": stmt get: type " type " has no member called '" curr->name "'\n")
21924     (write-buffered *(ebp+0x10) "fn ")
21925     8b/-> *(ebp+0xc) 0/r32/eax
21926     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21927     (write-buffered *(ebp+0x10) %eax)
21928     (write-buffered *(ebp+0x10) ": stmt get: type '")
21929     # . write(Type-id->data[tmp])
21930     bf/copy-to-edi Type-id/imm32
21931     8b/-> *(edi+ebx<<2+0xc) 6/r32/esi
21932     {
21933       81 7/subop/compare %esi 0/imm32
21934       74/jump-if-= break/disp8
21935       (write-buffered *(ebp+0x10) %esi)
21936     }
21937     # .
21938     (write-buffered *(ebp+0x10) "' has no member called '")
21939     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
21940     (write-buffered *(ebp+0x10) %eax)
21941     (write-buffered *(ebp+0x10) "'\n")
21942     (flush *(ebp+0x10))
21943     (stop *(ebp+0x14) 1)
21944     # never gets here
21945 
21946 $check-mu-get-stmt:error-output-not-in-register:
21947     (write-buffered *(ebp+0x10) "fn ")
21948     8b/-> *(ebp+0xc) 0/r32/eax
21949     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21950     (write-buffered *(ebp+0x10) %eax)
21951     (write-buffered *(ebp+0x10) ": stmt get: output '")
21952     (lookup *edi *(edi+4))  # Var-name Var-name => eax
21953     (write-buffered *(ebp+0x10) %eax)
21954     (write-buffered *(ebp+0x10) "' is not in a register\n")
21955     (flush *(ebp+0x10))
21956     (stop *(ebp+0x14) 1)
21957     # never gets here
21958 
21959 $check-mu-get-stmt:error-output-type-not-address:
21960     (write-buffered *(ebp+0x10) "fn ")
21961     8b/-> *(ebp+0xc) 0/r32/eax
21962     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21963     (write-buffered *(ebp+0x10) %eax)
21964     (write-buffered *(ebp+0x10) ": stmt get: output must be an addr\n")
21965     (flush *(ebp+0x10))
21966     (stop *(ebp+0x14) 1)
21967     # never gets here
21968 
21969 $check-mu-get-stmt:error-bad-output-type:
21970     (write-buffered *(ebp+0x10) "fn ")
21971     8b/-> *(ebp+0xc) 0/r32/eax
21972     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21973     (write-buffered *(ebp+0x10) %eax)
21974     (write-buffered *(ebp+0x10) ": stmt get: wrong output type for member '")
21975     (write-buffered *(ebp+0x10) %ecx)
21976     (write-buffered *(ebp+0x10) "' of type '")
21977     bf/copy-to-edi Type-id/imm32
21978     8b/-> *(edi+ebx<<2+0xc) 6/r32/esi
21979     {
21980       81 7/subop/compare %esi 0/imm32
21981       74/jump-if-= break/disp8
21982       (write-buffered *(ebp+0x10) %esi)
21983     }
21984     (write-buffered *(ebp+0x10) "'\n")
21985     (flush *(ebp+0x10))
21986     (stop *(ebp+0x14) 1)
21987     # never gets here
21988 
21989 check-mu-index-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21990     # . prologue
21991     55/push-ebp
21992     89/<- %ebp 4/r32/esp
21993     # . save registers
21994     50/push-eax
21995     51/push-ecx
21996     52/push-edx
21997     53/push-ebx
21998     56/push-esi
21999     57/push-edi
22000     # esi = stmt
22001     8b/-> *(ebp+8) 6/r32/esi
22002     # - check for 0 inouts
22003     # var base/ecx: (addr var) = stmt->inouts->value
22004     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22005 $check-mu-index-stmt:check-no-inouts:
22006     3d/compare-eax-and 0/imm32
22007     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-inouts/disp32
22008     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22009     89/<- %ecx 0/r32/eax
22010     # - check base type is either (addr array ...) in register or (array ...) on stack
22011     # var base-type/ebx: (addr type-tree) = lookup(base->type)
22012     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
22013     89/<- %ebx 0/r32/eax
22014     # if base-type is an atom, abort with a precise error
22015     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
22016     {
22017       74/jump-if-= break/disp8
22018       (is-simple-mu-type? %ebx 3)  # array => eax
22019       3d/compare-eax-and 0/imm32/false
22020       0f 85/jump-if-!= $check-mu-index-stmt:error-base-array-atom-type/disp32
22021       0f 84/jump-if-= $check-mu-index-stmt:error-base-non-array-type/disp32
22022     }
22023 $check-mu-index-stmt:base-is-compound:
22024     # if type->left not addr or array, abort
22025     {
22026       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22027       (is-simple-mu-type? %eax 2)  # addr => eax
22028       3d/compare-eax-and 0/imm32/false
22029       75/jump-if-!= break/disp8
22030       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22031       (is-simple-mu-type? %eax 3)  # array => eax
22032       3d/compare-eax-and 0/imm32/false
22033       75/jump-if-!= break/disp8
22034       e9/jump $check-mu-index-stmt:error-base-non-array-type/disp32
22035     }
22036     # if (type->left == addr) ensure type->right->left == array and type->register exists
22037     {
22038       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22039       (is-simple-mu-type? %eax 2)  # addr => eax
22040       3d/compare-eax-and 0/imm32/false
22041       74/jump-if-= break/disp8
22042 $check-mu-index-stmt:base-is-addr:
22043       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22044       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22045       (is-simple-mu-type? %eax 3)  # array => eax
22046       3d/compare-eax-and 0/imm32/false
22047       0f 84/jump-if-= $check-mu-index-stmt:error-base-non-array-type/disp32
22048 $check-mu-index-stmt:check-base-addr-is-register:
22049       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
22050       0f 84/jump-if-= $check-mu-index-stmt:error-base-address-array-type-on-stack/disp32
22051     }
22052     # if (type->left == array) ensure type->register doesn't exist
22053     {
22054       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22055       (is-simple-mu-type? %eax 3)  # array => eax
22056       3d/compare-eax-and 0/imm32/false
22057       74/jump-if-= break/disp8
22058 $check-mu-index-stmt:base-is-array:
22059       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
22060       0f 85/jump-if-!= $check-mu-index-stmt:error-base-array-type-in-register/disp32
22061     }
22062     # if (base-type->left == addr) base-type = base-type->right
22063     {
22064       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22065       (is-simple-mu-type? %eax 2)  # addr => eax
22066       3d/compare-eax-and 0/imm32/false
22067       74/jump-if-= break/disp8
22068       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22069       89/<- %ebx 0/r32/eax
22070     }
22071     # - check for 1 inout
22072     # var index/ecx: (addr stmt-var) = stmt->inouts->next->value
22073     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22074     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
22075 $check-mu-index-stmt:check-single-inout:
22076     3d/compare-eax-and 0/imm32
22077     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-inouts/disp32
22078     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22079     89/<- %ecx 0/r32/eax
22080     # - check index is either a literal or register
22081     # var index-type/edx: (addr type-tree)
22082     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
22083     89/<- %edx 0/r32/eax
22084     # if index type is an atom, it must be a literal or int
22085     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
22086     {
22087       74/jump-if-= break/disp8
22088 $check-mu-index-stmt:index-type-is-atom:
22089       (is-simple-mu-type? %edx 0)  # literal => eax
22090       3d/compare-eax-and 0/imm32/false
22091       75/jump-if-!= $check-mu-index-stmt:index-type-done/disp8
22092       (is-simple-mu-type? %edx 1)  # int => eax
22093       3d/compare-eax-and 0/imm32/false
22094       75/jump-if-!= $check-mu-index-stmt:index-type-done/disp8
22095       (is-simple-mu-type? %edx 7)  # offset => eax
22096       3d/compare-eax-and 0/imm32/false
22097       0f 85/jump-if-!= $check-mu-index-stmt:error-index-offset-atom-type/disp32
22098       e9/jump $check-mu-index-stmt:error-invalid-index-type/disp32
22099     }
22100     # if index type is a non-atom: it must be an offset
22101     {
22102       75/jump-if-!= break/disp8
22103 $check-mu-index-stmt:index-type-is-non-atom:
22104       (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
22105       (is-simple-mu-type? %eax 7)  # offset => eax
22106       3d/compare-eax-and 0/imm32/false
22107       0f 84/jump-if-= $check-mu-index-stmt:error-invalid-index-type/disp32
22108     }
22109 $check-mu-index-stmt:index-type-done:
22110     # check index is either a literal or in a register
22111     {
22112       (is-simple-mu-type? %edx 0)  # literal => eax
22113       3d/compare-eax-and 0/imm32/false
22114       75/jump-if-!= break/disp8
22115 $check-mu-index-stmt:check-index-in-register:
22116       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
22117       0f 84/jump-if-= $check-mu-index-stmt:error-index-on-stack/disp32
22118     }
22119     # - if index is an 'int', check that element type of base has size 1, 2, 4 or 8 bytes.
22120     {
22121       (is-simple-mu-type? %edx 1)  # int => eax
22122       3d/compare-eax-and 0/imm32/false
22123       74/jump-if-= break/disp8
22124 $check-mu-index-stmt:check-index-can-be-int:
22125       (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22126       (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22127       (array-element-size %eax)  # => eax
22128       3d/compare-eax-and 1/imm32
22129       74/jump-if-= break/disp8
22130       3d/compare-eax-and 2/imm32
22131       74/jump-if-= break/disp8
22132       3d/compare-eax-and 4/imm32
22133       74/jump-if-= break/disp8
22134       3d/compare-eax-and 8/imm32
22135       74/jump-if-= break/disp8
22136       e9/jump $check-mu-index-stmt:error-index-needs-offset/disp32
22137     }
22138     # - check for too many inouts
22139     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22140     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
22141     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
22142     3d/compare-eax-and 0/imm32/false
22143     0f 85/jump-if-!= $check-mu-index-stmt:error-too-many-inouts/disp32
22144     # - check for 0 outputs
22145     # var output/edi: (addr var) = stmt->outputs->value
22146     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22147     3d/compare-eax-and 0/imm32/false
22148     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-outputs/disp32
22149     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22150     89/<- %edi 0/r32/eax
22151     # - check output type
22152     # must have a non-atomic type
22153     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
22154     89/<- %edx 0/r32/eax
22155     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
22156     0f 85/jump-if-!= $check-mu-index-stmt:error-output-type-not-address/disp32
22157     # type must start with (addr ...)
22158     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
22159     (is-simple-mu-type? %eax 2)  # addr => eax
22160     3d/compare-eax-and 0/imm32/false
22161     0f 84/jump-if-= $check-mu-index-stmt:error-output-type-not-address/disp32
22162     # if tail(base-type) != tail(output-type) abort
22163     (type-tail %ebx)  # => eax
22164     89/<- %ebx 0/r32/eax
22165     (type-tail %edx)  # => eax
22166     (type-equal? %ebx %eax)  # => eax
22167     3d/compare-eax-and 0/imm32/false
22168     0f 84/jump-if-= $check-mu-index-stmt:error-bad-output-type/disp32
22169     # - check for too many outputs
22170     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22171     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
22172     3d/compare-eax-and 0/imm32/false
22173     0f 85/jump-if-!= $check-mu-index-stmt:error-too-many-outputs/disp32
22174 $check-mu-index-stmt:end:
22175     # . restore registers
22176     5f/pop-to-edi
22177     5e/pop-to-esi
22178     5b/pop-to-ebx
22179     5a/pop-to-edx
22180     59/pop-to-ecx
22181     58/pop-to-eax
22182     # . epilogue
22183     89/<- %esp 5/r32/ebp
22184     5d/pop-to-ebp
22185     c3/return
22186 
22187 $check-mu-index-stmt:error-base-non-array-type:
22188     (write-buffered *(ebp+0x10) "fn ")
22189     8b/-> *(ebp+0xc) 0/r32/eax
22190     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22191     (write-buffered *(ebp+0x10) %eax)
22192     (write-buffered *(ebp+0x10) ": stmt index: var '")
22193     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22194     (write-buffered *(ebp+0x10) %eax)
22195     (write-buffered *(ebp+0x10) "' is not an array\n")
22196     (flush *(ebp+0x10))
22197     (stop *(ebp+0x14) 1)
22198     # never gets here
22199 
22200 $check-mu-index-stmt:error-base-array-atom-type:
22201     (write-buffered *(ebp+0x10) "fn ")
22202     8b/-> *(ebp+0xc) 0/r32/eax
22203     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22204     (write-buffered *(ebp+0x10) %eax)
22205     (write-buffered *(ebp+0x10) ": stmt index: array '")
22206     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22207     (write-buffered *(ebp+0x10) %eax)
22208     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
22209     (flush *(ebp+0x10))
22210     (stop *(ebp+0x14) 1)
22211     # never gets here
22212 
22213 $check-mu-index-stmt:error-base-address-array-type-on-stack:
22214     (write-buffered *(ebp+0x10) "fn ")
22215     8b/-> *(ebp+0xc) 0/r32/eax
22216     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22217     (write-buffered *(ebp+0x10) %eax)
22218     (write-buffered *(ebp+0x10) ": stmt index: var '")
22219     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22220     (write-buffered *(ebp+0x10) %eax)
22221     (write-buffered *(ebp+0x10) "' is an addr to an array, and so must live in a register\n")
22222     (flush *(ebp+0x10))
22223     (stop *(ebp+0x14) 1)
22224     # never gets here
22225 
22226 $check-mu-index-stmt:error-base-array-type-in-register:
22227     (write-buffered *(ebp+0x10) "fn ")
22228     8b/-> *(ebp+0xc) 0/r32/eax
22229     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22230     (write-buffered *(ebp+0x10) %eax)
22231     (write-buffered *(ebp+0x10) ": stmt index: var '")
22232     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22233     (write-buffered *(ebp+0x10) %eax)
22234     (write-buffered *(ebp+0x10) "' is an array, and so must live on the stack\n")
22235     (flush *(ebp+0x10))
22236     (stop *(ebp+0x14) 1)
22237     # never gets here
22238 
22239 $check-mu-index-stmt:error-too-few-inouts:
22240     (write-buffered *(ebp+0x10) "fn ")
22241     8b/-> *(ebp+0xc) 0/r32/eax
22242     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22243     (write-buffered *(ebp+0x10) %eax)
22244     (write-buffered *(ebp+0x10) ": stmt index: too few inouts (2 required)\n")
22245     (flush *(ebp+0x10))
22246     (stop *(ebp+0x14) 1)
22247     # never gets here
22248 
22249 $check-mu-index-stmt:error-invalid-index-type:
22250     (write-buffered *(ebp+0x10) "fn ")
22251     8b/-> *(ebp+0xc) 0/r32/eax
22252     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22253     (write-buffered *(ebp+0x10) %eax)
22254     (write-buffered *(ebp+0x10) ": stmt index: second argument '")
22255     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22256     (write-buffered *(ebp+0x10) %eax)
22257     (write-buffered *(ebp+0x10) "' must be an int or offset\n")
22258     (flush *(ebp+0x10))
22259     (stop *(ebp+0x14) 1)
22260     # never gets here
22261 
22262 $check-mu-index-stmt:error-index-offset-atom-type:
22263     (write-buffered *(ebp+0x10) "fn ")
22264     8b/-> *(ebp+0xc) 0/r32/eax
22265     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22266     (write-buffered *(ebp+0x10) %eax)
22267     (write-buffered *(ebp+0x10) ": stmt index: offset '")
22268     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22269     (write-buffered *(ebp+0x10) %eax)
22270     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
22271     (flush *(ebp+0x10))
22272     (stop *(ebp+0x14) 1)
22273     # never gets here
22274 
22275 $check-mu-index-stmt:error-index-on-stack:
22276     (write-buffered *(ebp+0x10) "fn ")
22277     8b/-> *(ebp+0xc) 0/r32/eax
22278     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22279     (write-buffered *(ebp+0x10) %eax)
22280     (write-buffered *(ebp+0x10) ": stmt index: second argument '")
22281     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22282     (write-buffered *(ebp+0x10) %eax)
22283     (write-buffered *(ebp+0x10) "' must be in a register\n")
22284     (flush *(ebp+0x10))
22285     (stop *(ebp+0x14) 1)
22286     # never gets here
22287 
22288 $check-mu-index-stmt:error-index-needs-offset:
22289     (write-buffered *(ebp+0x10) "fn ")
22290     8b/-> *(ebp+0xc) 0/r32/eax
22291     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22292     (write-buffered *(ebp+0x10) %eax)
22293     (write-buffered *(ebp+0x10) ": stmt index: cannot take an int for array '")
22294     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22295     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22296     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22297     (write-buffered *(ebp+0x10) %eax)
22298     (write-buffered *(ebp+0x10) "'; create an offset instead. See mu.md for details.\n")
22299     (flush *(ebp+0x10))
22300     (stop *(ebp+0x14) 1)
22301     # never gets here
22302 
22303 $check-mu-index-stmt:error-too-many-inouts:
22304     (write-buffered *(ebp+0x10) "fn ")
22305     8b/-> *(ebp+0xc) 0/r32/eax
22306     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22307     (write-buffered *(ebp+0x10) %eax)
22308     (write-buffered *(ebp+0x10) ": stmt index: too many inouts (2 required)\n")
22309     (flush *(ebp+0x10))
22310     (stop *(ebp+0x14) 1)
22311     # never gets here
22312 
22313 $check-mu-index-stmt:error-too-few-outputs:
22314     (write-buffered *(ebp+0x10) "fn ")
22315     8b/-> *(ebp+0xc) 0/r32/eax
22316     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22317     (write-buffered *(ebp+0x10) %eax)
22318     (write-buffered *(ebp+0x10) ": stmt index: must have an output\n")
22319     (flush *(ebp+0x10))
22320     (stop *(ebp+0x14) 1)
22321     # never gets here
22322 
22323 $check-mu-index-stmt:error-too-many-outputs:
22324     (write-buffered *(ebp+0x10) "fn ")
22325     8b/-> *(ebp+0xc) 0/r32/eax
22326     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22327     (write-buffered *(ebp+0x10) %eax)
22328     (write-buffered *(ebp+0x10) ": stmt index: too many outputs (1 required)\n")
22329     (flush *(ebp+0x10))
22330     (stop *(ebp+0x14) 1)
22331     # never gets here
22332 
22333 $check-mu-index-stmt:error-output-not-in-register:
22334     (write-buffered *(ebp+0x10) "fn ")
22335     8b/-> *(ebp+0xc) 0/r32/eax
22336     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22337     (write-buffered *(ebp+0x10) %eax)
22338     (write-buffered *(ebp+0x10) ": stmt index: output '")
22339     (lookup *edi *(edi+4))  # Var-name Var-name => eax
22340     (write-buffered *(ebp+0x10) %eax)
22341     (write-buffered *(ebp+0x10) "' is not in a register\n")
22342     (flush *(ebp+0x10))
22343     (stop *(ebp+0x14) 1)
22344     # never gets here
22345 
22346 $check-mu-index-stmt:error-output-type-not-address:
22347     (write-buffered *(ebp+0x10) "fn ")
22348     8b/-> *(ebp+0xc) 0/r32/eax
22349     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22350     (write-buffered *(ebp+0x10) %eax)
22351     (write-buffered *(ebp+0x10) ": stmt index: output '")
22352     (lookup *edi *(edi+4))  # Var-name Var-name => eax
22353     (write-buffered *(ebp+0x10) %eax)
22354     (write-buffered *(ebp+0x10) "' must be an addr\n")
22355     (flush *(ebp+0x10))
22356     (stop *(ebp+0x14) 1)
22357     # never gets here
22358 
22359 $check-mu-index-stmt:error-bad-output-type:
22360     (write-buffered *(ebp+0x10) "fn ")
22361     8b/-> *(ebp+0xc) 0/r32/eax
22362     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22363     (write-buffered *(ebp+0x10) %eax)
22364     (write-buffered *(ebp+0x10) ": stmt index: output '")
22365     (lookup *edi *(edi+4))  # Var-name Var-name => eax
22366     (write-buffered *(ebp+0x10) %eax)
22367     (write-buffered *(ebp+0x10) "' does not have the right type\n")
22368     (flush *(ebp+0x10))
22369     (stop *(ebp+0x14) 1)
22370     # never gets here
22371 
22372 check-mu-length-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22373     # . prologue
22374     55/push-ebp
22375     89/<- %ebp 4/r32/esp
22376     # . save registers
22377     50/push-eax
22378     51/push-ecx
22379     52/push-edx
22380     53/push-ebx
22381     56/push-esi
22382     57/push-edi
22383     # esi = stmt
22384     8b/-> *(ebp+8) 6/r32/esi
22385     # - check for 0 inouts
22386     # var base/ecx: (addr var) = stmt->inouts->value
22387     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22388 $check-mu-length-stmt:check-no-inouts:
22389     3d/compare-eax-and 0/imm32
22390     0f 84/jump-if-= $check-mu-length-stmt:error-too-few-inouts/disp32
22391     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22392     89/<- %ecx 0/r32/eax
22393     # - check base type is either (addr array ...) in register or (array ...) on stack
22394     # var base-type/ebx: (addr type-tree) = lookup(base->type)
22395     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
22396     89/<- %ebx 0/r32/eax
22397     # if base-type is an atom, abort with a precise error
22398     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
22399     {
22400       74/jump-if-= break/disp8
22401       (is-simple-mu-type? %ebx 3)  # array => eax
22402       3d/compare-eax-and 0/imm32/false
22403       0f 85/jump-if-!= $check-mu-length-stmt:error-base-array-atom-type/disp32
22404       0f 84/jump-if-= $check-mu-length-stmt:error-base-non-array-type/disp32
22405     }
22406 $check-mu-length-stmt:base-is-compound:
22407     # if type->left not addr or array, abort
22408     {
22409       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22410       (is-simple-mu-type? %eax 2)  # addr => eax
22411       3d/compare-eax-and 0/imm32/false
22412       75/jump-if-!= break/disp8
22413       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22414       (is-simple-mu-type? %eax 3)  # array => eax
22415       3d/compare-eax-and 0/imm32/false
22416       75/jump-if-!= break/disp8
22417       e9/jump $check-mu-length-stmt:error-base-non-array-type/disp32
22418     }
22419     # if (type->left == addr) ensure type->right->left == array and type->register exists
22420     {
22421       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22422       (is-simple-mu-type? %eax 2)  # addr => eax
22423       3d/compare-eax-and 0/imm32/false
22424       74/jump-if-= break/disp8
22425 $check-mu-length-stmt:base-is-addr:
22426       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22427       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22428       (is-simple-mu-type? %eax 3)  # array => eax
22429       3d/compare-eax-and 0/imm32/false
22430       0f 84/jump-if-= $check-mu-length-stmt:error-base-non-array-type/disp32
22431 $check-mu-length-stmt:check-base-addr-is-register:
22432       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
22433       0f 84/jump-if-= $check-mu-length-stmt:error-base-address-array-type-on-stack/disp32
22434     }
22435     # if (type->left == array) ensure type->register doesn't exist
22436     {
22437       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22438       (is-simple-mu-type? %eax 3)  # array => eax
22439       3d/compare-eax-and 0/imm32/false
22440       74/jump-if-= break/disp8
22441 $check-mu-length-stmt:base-is-array:
22442       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
22443       0f 85/jump-if-!= $check-mu-length-stmt:error-base-array-type-in-register/disp32
22444     }
22445     # if (base-type->left == addr) base-type = base-type->right
22446     {
22447       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22448       (is-simple-mu-type? %eax 2)  # addr => eax
22449       3d/compare-eax-and 0/imm32/false
22450       74/jump-if-= break/disp8
22451       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22452       89/<- %ebx 0/r32/eax
22453     }
22454     # - check for too many inouts
22455     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22456     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
22457     3d/compare-eax-and 0/imm32/false
22458     0f 85/jump-if-!= $check-mu-length-stmt:error-too-many-inouts/disp32
22459     # - check for 0 outputs
22460     # var output/edi: (addr var) = stmt->outputs->value
22461     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22462     3d/compare-eax-and 0/imm32/false
22463     0f 84/jump-if-= $check-mu-length-stmt:error-too-few-outputs/disp32
22464     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22465     89/<- %edi 0/r32/eax
22466     # - check output type
22467     # must have a non-atomic type
22468     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
22469     (is-simple-mu-type? %eax 1)  # int => eax
22470     3d/compare-eax-and 0/imm32/false
22471     0f 84/jump-if-= $check-mu-length-stmt:error-invalid-output-type/disp32
22472     # - check for too many outputs
22473     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22474     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
22475     3d/compare-eax-and 0/imm32/false
22476     0f 85/jump-if-!= $check-mu-length-stmt:error-too-many-outputs/disp32
22477 $check-mu-length-stmt:end:
22478     # . restore registers
22479     5f/pop-to-edi
22480     5e/pop-to-esi
22481     5b/pop-to-ebx
22482     5a/pop-to-edx
22483     59/pop-to-ecx
22484     58/pop-to-eax
22485     # . epilogue
22486     89/<- %esp 5/r32/ebp
22487     5d/pop-to-ebp
22488     c3/return
22489 
22490 $check-mu-length-stmt:error-base-non-array-type:
22491     (write-buffered *(ebp+0x10) "fn ")
22492     8b/-> *(ebp+0xc) 0/r32/eax
22493     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22494     (write-buffered *(ebp+0x10) %eax)
22495     (write-buffered *(ebp+0x10) ": stmt length: var '")
22496     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22497     (write-buffered *(ebp+0x10) %eax)
22498     (write-buffered *(ebp+0x10) "' is not an array\n")
22499     (flush *(ebp+0x10))
22500     (stop *(ebp+0x14) 1)
22501     # never gets here
22502 
22503 $check-mu-length-stmt:error-base-array-atom-type:
22504     (write-buffered *(ebp+0x10) "fn ")
22505     8b/-> *(ebp+0xc) 0/r32/eax
22506     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22507     (write-buffered *(ebp+0x10) %eax)
22508     (write-buffered *(ebp+0x10) ": stmt length: array '")
22509     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22510     (write-buffered *(ebp+0x10) %eax)
22511     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
22512     (flush *(ebp+0x10))
22513     (stop *(ebp+0x14) 1)
22514     # never gets here
22515 
22516 $check-mu-length-stmt:error-base-address-array-type-on-stack:
22517     (write-buffered *(ebp+0x10) "fn ")
22518     8b/-> *(ebp+0xc) 0/r32/eax
22519     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22520     (write-buffered *(ebp+0x10) %eax)
22521     (write-buffered *(ebp+0x10) ": stmt length: var '")
22522     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22523     (write-buffered *(ebp+0x10) %eax)
22524     (write-buffered *(ebp+0x10) "' is an addr to an array, and so must live in a register\n")
22525     (flush *(ebp+0x10))
22526     (stop *(ebp+0x14) 1)
22527     # never gets here
22528 
22529 $check-mu-length-stmt:error-base-array-type-in-register:
22530     (write-buffered *(ebp+0x10) "fn ")
22531     8b/-> *(ebp+0xc) 0/r32/eax
22532     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22533     (write-buffered *(ebp+0x10) %eax)
22534     (write-buffered *(ebp+0x10) ": stmt length: var '")
22535     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22536     (write-buffered *(ebp+0x10) %eax)
22537     (write-buffered *(ebp+0x10) "' is an array, and so must live on the stack\n")
22538     (flush *(ebp+0x10))
22539     (stop *(ebp+0x14) 1)
22540     # never gets here
22541 
22542 $check-mu-length-stmt:error-too-few-inouts:
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 length: too few inouts (1 required)\n")
22548     (flush *(ebp+0x10))
22549     (stop *(ebp+0x14) 1)
22550     # never gets here
22551 
22552 $check-mu-length-stmt:error-invalid-index-type:
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 length: second argument '")
22558     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22559     (write-buffered *(ebp+0x10) %eax)
22560     (write-buffered *(ebp+0x10) "' must be an int or offset\n")
22561     (flush *(ebp+0x10))
22562     (stop *(ebp+0x14) 1)
22563     # never gets here
22564 
22565 $check-mu-length-stmt:error-index-offset-atom-type:
22566     (write-buffered *(ebp+0x10) "fn ")
22567     8b/-> *(ebp+0xc) 0/r32/eax
22568     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22569     (write-buffered *(ebp+0x10) %eax)
22570     (write-buffered *(ebp+0x10) ": stmt length: offset '")
22571     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22572     (write-buffered *(ebp+0x10) %eax)
22573     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
22574     (flush *(ebp+0x10))
22575     (stop *(ebp+0x14) 1)
22576     # never gets here
22577 
22578 $check-mu-length-stmt:error-index-on-stack:
22579     (write-buffered *(ebp+0x10) "fn ")
22580     8b/-> *(ebp+0xc) 0/r32/eax
22581     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22582     (write-buffered *(ebp+0x10) %eax)
22583     (write-buffered *(ebp+0x10) ": stmt length: second argument '")
22584     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22585     (write-buffered *(ebp+0x10) %eax)
22586     (write-buffered *(ebp+0x10) "' must be in a register\n")
22587     (flush *(ebp+0x10))
22588     (stop *(ebp+0x14) 1)
22589     # never gets here
22590 
22591 $check-mu-length-stmt:error-index-needs-offset:
22592     (write-buffered *(ebp+0x10) "fn ")
22593     8b/-> *(ebp+0xc) 0/r32/eax
22594     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22595     (write-buffered *(ebp+0x10) %eax)
22596     (write-buffered *(ebp+0x10) ": stmt length: cannot take an int for array '")
22597     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22598     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22599     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22600     (write-buffered *(ebp+0x10) %eax)
22601     (write-buffered *(ebp+0x10) "'; create an offset instead. See mu.md for details.\n")
22602     (flush *(ebp+0x10))
22603     (stop *(ebp+0x14) 1)
22604     # never gets here
22605 
22606 $check-mu-length-stmt:error-too-many-inouts:
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 length: too many inouts (1 required)\n")
22612     (flush *(ebp+0x10))
22613     (stop *(ebp+0x14) 1)
22614     # never gets here
22615 
22616 $check-mu-length-stmt:error-too-few-outputs:
22617     (write-buffered *(ebp+0x10) "fn ")
22618     8b/-> *(ebp+0xc) 0/r32/eax
22619     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22620     (write-buffered *(ebp+0x10) %eax)
22621     (write-buffered *(ebp+0x10) ": stmt length: must have an output\n")
22622     (flush *(ebp+0x10))
22623     (stop *(ebp+0x14) 1)
22624     # never gets here
22625 
22626 $check-mu-length-stmt:error-too-many-outputs:
22627     (write-buffered *(ebp+0x10) "fn ")
22628     8b/-> *(ebp+0xc) 0/r32/eax
22629     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22630     (write-buffered *(ebp+0x10) %eax)
22631     (write-buffered *(ebp+0x10) ": stmt length: too many outputs (1 required)\n")
22632     (flush *(ebp+0x10))
22633     (stop *(ebp+0x14) 1)
22634     # never gets here
22635 
22636 $check-mu-length-stmt:error-output-not-in-register:
22637     (write-buffered *(ebp+0x10) "fn ")
22638     8b/-> *(ebp+0xc) 0/r32/eax
22639     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22640     (write-buffered *(ebp+0x10) %eax)
22641     (write-buffered *(ebp+0x10) ": stmt length: output '")
22642     (lookup *edi *(edi+4))  # Var-name Var-name => eax
22643     (write-buffered *(ebp+0x10) %eax)
22644     (write-buffered *(ebp+0x10) "' is not in a register\n")
22645     (flush *(ebp+0x10))
22646     (stop *(ebp+0x14) 1)
22647     # never gets here
22648 
22649 $check-mu-length-stmt:error-invalid-output-type:
22650     (write-buffered *(ebp+0x10) "fn ")
22651     8b/-> *(ebp+0xc) 0/r32/eax
22652     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22653     (write-buffered *(ebp+0x10) %eax)
22654     (write-buffered *(ebp+0x10) ": stmt length: output '")
22655     (lookup *edi *(edi+4))  # Var-name Var-name => eax
22656     (write-buffered *(ebp+0x10) %eax)
22657     (write-buffered *(ebp+0x10) "' does not have the right type\n")
22658     (flush *(ebp+0x10))
22659     (stop *(ebp+0x14) 1)
22660     # never gets here
22661 
22662 check-mu-compute-offset-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22663     # . prologue
22664     55/push-ebp
22665     89/<- %ebp 4/r32/esp
22666     # . save registers
22667     50/push-eax
22668     51/push-ecx
22669     52/push-edx
22670     53/push-ebx
22671     56/push-esi
22672     57/push-edi
22673     # esi = stmt
22674     8b/-> *(ebp+8) 6/r32/esi
22675     # - check for 0 inouts
22676     # var base/ecx: (addr var) = stmt->inouts->value
22677     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22678 $check-mu-compute-offset-stmt:check-no-inouts:
22679     3d/compare-eax-and 0/imm32
22680     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-inouts/disp32
22681     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22682     89/<- %ecx 0/r32/eax
22683     # - check base type is either (addr array ...) in register or (array ...) on stack
22684     # var base-type/ebx: (addr type-tree) = lookup(base->type)
22685     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
22686     89/<- %ebx 0/r32/eax
22687     # if base-type is an atom, abort with a precise error
22688     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
22689     {
22690       74/jump-if-= break/disp8
22691       (is-simple-mu-type? %ebx 3)  # array => eax
22692       3d/compare-eax-and 0/imm32/false
22693       0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-base-array-atom-type/disp32
22694       0f 84/jump-if-= $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
22695     }
22696 $check-mu-compute-offset-stmt:base-is-compound:
22697     # if type->left not addr or array, abort
22698     {
22699       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22700       (is-simple-mu-type? %eax 2)  # addr => eax
22701       3d/compare-eax-and 0/imm32/false
22702       75/jump-if-!= break/disp8
22703       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22704       (is-simple-mu-type? %eax 3)  # array => eax
22705       3d/compare-eax-and 0/imm32/false
22706       75/jump-if-!= break/disp8
22707       e9/jump $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
22708     }
22709     # if (type->left == addr) ensure type->right->left == array and type->register exists
22710     {
22711       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22712       (is-simple-mu-type? %eax 2)  # addr => eax
22713       3d/compare-eax-and 0/imm32/false
22714       74/jump-if-= break/disp8
22715 $check-mu-compute-offset-stmt:base-is-addr:
22716       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22717       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22718       (is-simple-mu-type? %eax 3)  # array => eax
22719       3d/compare-eax-and 0/imm32/false
22720       0f 84/jump-if-= $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
22721     }
22722     # if (base-type->left == addr) base-type = base-type->right
22723     {
22724       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22725       (is-simple-mu-type? %eax 2)  # addr => eax
22726       3d/compare-eax-and 0/imm32/false
22727       74/jump-if-= break/disp8
22728       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22729       89/<- %ebx 0/r32/eax
22730     }
22731     # - check for 1 inout
22732     # var index/ecx: (addr stmt-var) = stmt->inouts->next->value
22733     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22734     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
22735 $check-mu-compute-offset-stmt:check-single-inout:
22736     3d/compare-eax-and 0/imm32
22737     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-inouts/disp32
22738     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22739     89/<- %ecx 0/r32/eax
22740     # - check index is either a literal or register
22741     # var index-type/edx: (addr type-tree)
22742     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
22743     89/<- %edx 0/r32/eax
22744     # index type must be a literal or int
22745     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
22746     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-invalid-index-type/disp32
22747     {
22748 $check-mu-compute-offset-stmt:index-type-is-atom:
22749       (is-simple-mu-type? %edx 0)  # literal => eax
22750       3d/compare-eax-and 0/imm32/false
22751       75/jump-if-!= break/disp8
22752       (is-simple-mu-type? %edx 1)  # int => eax
22753       3d/compare-eax-and 0/imm32/false
22754       75/jump-if-!= break/disp8
22755       e9/jump $check-mu-compute-offset-stmt:error-invalid-index-type/disp32
22756     }
22757     # - check for too many inouts
22758     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22759     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
22760     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
22761     3d/compare-eax-and 0/imm32/false
22762     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-too-many-inouts/disp32
22763     # - check for 0 outputs
22764     # var output/edi: (addr var) = stmt->outputs->value
22765     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22766     3d/compare-eax-and 0/imm32/false
22767     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-outputs/disp32
22768     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22769     89/<- %edi 0/r32/eax
22770     # - check output type
22771     # must have a non-atomic type
22772     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
22773     89/<- %edx 0/r32/eax
22774     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
22775     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-output-type-not-offset/disp32
22776     # type must start with (offset ...)
22777     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
22778     (is-simple-mu-type? %eax 7)  # offset => eax
22779     3d/compare-eax-and 0/imm32/false
22780     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-output-type-not-offset/disp32
22781     # if tail(base-type) != tail(output-type) abort
22782     (type-tail %ebx)  # => eax
22783     89/<- %ebx 0/r32/eax
22784     (type-tail %edx)  # => eax
22785     (type-equal? %ebx %eax)  # => eax
22786     3d/compare-eax-and 0/imm32/false
22787     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-bad-output-type/disp32
22788     # - check for too many outputs
22789     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22790     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
22791     3d/compare-eax-and 0/imm32/false
22792     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-too-many-outputs/disp32
22793 $check-mu-compute-offset-stmt:end:
22794     # . restore registers
22795     5f/pop-to-edi
22796     5e/pop-to-esi
22797     5b/pop-to-ebx
22798     5a/pop-to-edx
22799     59/pop-to-ecx
22800     58/pop-to-eax
22801     # . epilogue
22802     89/<- %esp 5/r32/ebp
22803     5d/pop-to-ebp
22804     c3/return
22805 
22806 $check-mu-compute-offset-stmt:error-base-non-array-type:
22807     (write-buffered *(ebp+0x10) "fn ")
22808     8b/-> *(ebp+0xc) 0/r32/eax
22809     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22810     (write-buffered *(ebp+0x10) %eax)
22811     (write-buffered *(ebp+0x10) ": stmt compute-offset: var '")
22812     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22813     (write-buffered *(ebp+0x10) %eax)
22814     (write-buffered *(ebp+0x10) "' is not an array\n")
22815     (flush *(ebp+0x10))
22816     (stop *(ebp+0x14) 1)
22817     # never gets here
22818 
22819 $check-mu-compute-offset-stmt:error-base-array-atom-type:
22820     (write-buffered *(ebp+0x10) "fn ")
22821     8b/-> *(ebp+0xc) 0/r32/eax
22822     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22823     (write-buffered *(ebp+0x10) %eax)
22824     (write-buffered *(ebp+0x10) ": stmt compute-offset: array '")
22825     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22826     (write-buffered *(ebp+0x10) %eax)
22827     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
22828     (flush *(ebp+0x10))
22829     (stop *(ebp+0x14) 1)
22830     # never gets here
22831 
22832 $check-mu-compute-offset-stmt:error-too-few-inouts:
22833     (write-buffered *(ebp+0x10) "fn ")
22834     8b/-> *(ebp+0xc) 0/r32/eax
22835     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22836     (write-buffered *(ebp+0x10) %eax)
22837     (write-buffered *(ebp+0x10) ": stmt compute-offset: too few inouts (2 required)\n")
22838     (flush *(ebp+0x10))
22839     (stop *(ebp+0x14) 1)
22840     # never gets here
22841 
22842 $check-mu-compute-offset-stmt:error-invalid-index-type:
22843     (write-buffered *(ebp+0x10) "fn ")
22844     8b/-> *(ebp+0xc) 0/r32/eax
22845     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22846     (write-buffered *(ebp+0x10) %eax)
22847     (write-buffered *(ebp+0x10) ": stmt compute-offset: second argument '")
22848     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22849     (write-buffered *(ebp+0x10) %eax)
22850     (write-buffered *(ebp+0x10) "' must be an int\n")
22851     (flush *(ebp+0x10))
22852     (stop *(ebp+0x14) 1)
22853     # never gets here
22854 
22855 $check-mu-compute-offset-stmt:error-index-offset-atom-type:
22856     (write-buffered *(ebp+0x10) "fn ")
22857     8b/-> *(ebp+0xc) 0/r32/eax
22858     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22859     (write-buffered *(ebp+0x10) %eax)
22860     (write-buffered *(ebp+0x10) ": stmt compute-offset: offset '")
22861     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22862     (write-buffered *(ebp+0x10) %eax)
22863     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
22864     (flush *(ebp+0x10))
22865     (stop *(ebp+0x14) 1)
22866     # never gets here
22867 
22868 $check-mu-compute-offset-stmt:error-index-on-stack:
22869     (write-buffered *(ebp+0x10) "fn ")
22870     8b/-> *(ebp+0xc) 0/r32/eax
22871     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22872     (write-buffered *(ebp+0x10) %eax)
22873     (write-buffered *(ebp+0x10) ": stmt compute-offset: second argument '")
22874     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22875     (write-buffered *(ebp+0x10) %eax)
22876     (write-buffered *(ebp+0x10) "' must be in a register\n")
22877     (flush *(ebp+0x10))
22878     (stop *(ebp+0x14) 1)
22879     # never gets here
22880 
22881 $check-mu-compute-offset-stmt:error-too-many-inouts:
22882     (write-buffered *(ebp+0x10) "fn ")
22883     8b/-> *(ebp+0xc) 0/r32/eax
22884     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22885     (write-buffered *(ebp+0x10) %eax)
22886     (write-buffered *(ebp+0x10) ": stmt compute-offset: too many inouts (2 required)\n")
22887     (flush *(ebp+0x10))
22888     (stop *(ebp+0x14) 1)
22889     # never gets here
22890 
22891 $check-mu-compute-offset-stmt:error-too-few-outputs:
22892     (write-buffered *(ebp+0x10) "fn ")
22893     8b/-> *(ebp+0xc) 0/r32/eax
22894     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22895     (write-buffered *(ebp+0x10) %eax)
22896     (write-buffered *(ebp+0x10) ": stmt compute-offset: must have an output\n")
22897     (flush *(ebp+0x10))
22898     (stop *(ebp+0x14) 1)
22899     # never gets here
22900 
22901 $check-mu-compute-offset-stmt:error-too-many-outputs:
22902     (write-buffered *(ebp+0x10) "fn ")
22903     8b/-> *(ebp+0xc) 0/r32/eax
22904     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22905     (write-buffered *(ebp+0x10) %eax)
22906     (write-buffered *(ebp+0x10) ": stmt compute-offset: too many outputs (1 required)\n")
22907     (flush *(ebp+0x10))
22908     (stop *(ebp+0x14) 1)
22909     # never gets here
22910 
22911 $check-mu-compute-offset-stmt:error-output-not-in-register:
22912     (write-buffered *(ebp+0x10) "fn ")
22913     8b/-> *(ebp+0xc) 0/r32/eax
22914     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22915     (write-buffered *(ebp+0x10) %eax)
22916     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
22917     (lookup *edi *(edi+4))  # Var-name Var-name => eax
22918     (write-buffered *(ebp+0x10) %eax)
22919     (write-buffered *(ebp+0x10) "' is not in a register\n")
22920     (flush *(ebp+0x10))
22921     (stop *(ebp+0x14) 1)
22922     # never gets here
22923 
22924 $check-mu-compute-offset-stmt:error-output-type-not-offset:
22925     (write-buffered *(ebp+0x10) "fn ")
22926     8b/-> *(ebp+0xc) 0/r32/eax
22927     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22928     (write-buffered *(ebp+0x10) %eax)
22929     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
22930     (lookup *edi *(edi+4))  # Var-name Var-name => eax
22931     (write-buffered *(ebp+0x10) %eax)
22932     (write-buffered *(ebp+0x10) "' must be an offset\n")
22933     (flush *(ebp+0x10))
22934     (stop *(ebp+0x14) 1)
22935     # never gets here
22936 
22937 $check-mu-compute-offset-stmt:error-bad-output-type:
22938     (write-buffered *(ebp+0x10) "fn ")
22939     8b/-> *(ebp+0xc) 0/r32/eax
22940     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22941     (write-buffered *(ebp+0x10) %eax)
22942     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
22943     (lookup *edi *(edi+4))  # Var-name Var-name => eax
22944     (write-buffered *(ebp+0x10) %eax)
22945     (write-buffered *(ebp+0x10) "' does not have the right type\n")
22946     (flush *(ebp+0x10))
22947     (stop *(ebp+0x14) 1)
22948     # never gets here
22949 
22950 check-mu-copy-object-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22951     # . prologue
22952     55/push-ebp
22953     89/<- %ebp 4/r32/esp
22954     # . save registers
22955     50/push-eax
22956     51/push-ecx
22957     53/push-ebx
22958     56/push-esi
22959     57/push-edi
22960     # esi = stmt
22961     8b/-> *(ebp+8) 6/r32/esi
22962 $check-mu-copy-object-stmt:check-for-output:
22963     # if stmt->outputs abort
22964     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22965     3d/compare-eax-and 0/imm32
22966     0f 85/jump-if-!= $check-mu-copy-object-stmt:error-too-many-outputs/disp32
22967 $check-mu-copy-object-stmt:get-left:
22968     # var dest/edi: (addr stmt-var) = stmt->inouts
22969     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22970     89/<- %edi 0/r32/eax
22971     # zero inouts
22972     3d/compare-eax-and 0/imm32
22973     0f 84/jump-if-= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
22974 $check-mu-copy-object-stmt:get-src:
22975     # var src/esi: (addr stmt-var) = dest->next
22976     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
22977     89/<- %esi 0/r32/eax
22978     # 1 inout
22979     3d/compare-eax-and 0/imm32
22980     0f 84/jump-if-= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
22981     # > 2 inouts
22982     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
22983     3d/compare-eax-and 0/imm32
22984     0f 85/jump-if-!= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
22985 $check-mu-copy-object-stmt:types:
22986     # var src-type/ecx: (addr type-tree) = src->value->type
22987     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22988     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22989     89/<- %ecx 0/r32/eax
22990     # if (src->is-deref?) src-type = src-type->payload
22991     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
22992     3d/compare-eax-and 0/imm32/false
22993     {
22994       74/jump-if-= break/disp8
22995       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
22996       # if src-type->right is null, src-type = src-type->left
22997       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
22998       {
22999         75/jump-if-!= break/disp8
23000         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23001       }
23002       89/<- %ecx 0/r32/eax
23003     }
23004     # if src-type is not addr, abort
23005     (is-mu-addr-type? %ecx)  # => eax
23006     3d/compare-eax-and 0/imm32/false
23007     0f 84/jump-if-= $check-mu-copy-object-stmt:error-invalid-types/disp32
23008     # var dest-type/ebx: (addr type-tree) = dest->value->type
23009     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23010     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23011     89/<- %ebx 0/r32/eax
23012     # if (dest->is-deref?) dest-type = dest-type->payload
23013     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
23014     3d/compare-eax-and 0/imm32/false
23015     {
23016       74/jump-if-= break/disp8
23017       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23018       # if dest-type->right is null, dest-type = dest-type->left
23019       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
23020       {
23021         75/jump-if-!= break/disp8
23022         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23023       }
23024       89/<- %ebx 0/r32/eax
23025     }
23026     # if (dest-type != src-type) abort
23027     (type-equal? %ecx %ebx)  # => eax
23028     3d/compare-eax-and 0/imm32
23029     0f 84/jump-if-= $check-mu-copy-object-stmt:error-invalid-types/disp32
23030 $check-mu-copy-object-stmt:end:
23031     # . restore registers
23032     5f/pop-to-edi
23033     5e/pop-to-esi
23034     5b/pop-to-ebx
23035     59/pop-to-ecx
23036     58/pop-to-eax
23037     # . epilogue
23038     89/<- %esp 5/r32/ebp
23039     5d/pop-to-ebp
23040     c3/return
23041 
23042 $check-mu-copy-object-stmt:error-incorrect-inouts:
23043     (write-buffered *(ebp+0x10) "fn ")
23044     8b/-> *(ebp+0xc) 0/r32/eax
23045     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23046     (write-buffered *(ebp+0x10) %eax)
23047     (write-buffered *(ebp+0x10) ": stmt 'copy-object' must have two inouts\n")
23048     (flush *(ebp+0x10))
23049     (stop *(ebp+0x14) 1)
23050     # never gets here
23051 
23052 $check-mu-copy-object-stmt:error-too-many-outputs:
23053     (write-buffered *(ebp+0x10) "fn ")
23054     8b/-> *(ebp+0xc) 0/r32/eax
23055     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23056     (write-buffered *(ebp+0x10) %eax)
23057     (write-buffered *(ebp+0x10) ": stmt 'copy-object' must not have any outputs\n")
23058     (flush *(ebp+0x10))
23059     (stop *(ebp+0x14) 1)
23060     # never gets here
23061 
23062 $check-mu-copy-object-stmt:error-invalid-types:
23063     (write-buffered *(ebp+0x10) "fn ")
23064     8b/-> *(ebp+0xc) 0/r32/eax
23065     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23066     (write-buffered *(ebp+0x10) %eax)
23067     (write-buffered *(ebp+0x10) ": stmt copy-object: two inouts with identical addr types expected\n")
23068     (flush *(ebp+0x10))
23069     (stop *(ebp+0x14) 1)
23070     # never gets here
23071 
23072 check-mu-clear-object-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23073     # . prologue
23074     55/push-ebp
23075     89/<- %ebp 4/r32/esp
23076     # . save registers
23077     50/push-eax
23078     51/push-ecx
23079     53/push-ebx
23080     56/push-esi
23081     57/push-edi
23082     # esi = stmt
23083     8b/-> *(ebp+8) 6/r32/esi
23084 $check-mu-clear-object-stmt:check-for-output:
23085     # if stmt->outputs abort
23086     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
23087     3d/compare-eax-and 0/imm32
23088     0f 85/jump-if-!= $check-mu-clear-object-stmt:error-too-many-outputs/disp32
23089 $check-mu-clear-object-stmt:get-left:
23090     # var dest/edi: (addr stmt-var) = stmt->inouts
23091     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23092     89/<- %edi 0/r32/eax
23093     # zero inouts
23094     3d/compare-eax-and 0/imm32
23095     0f 84/jump-if-= $check-mu-clear-object-stmt:error-incorrect-inouts/disp32
23096 $check-mu-clear-object-stmt:get-src:
23097     # > 1 inout
23098     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
23099     3d/compare-eax-and 0/imm32
23100     0f 85/jump-if-!= $check-mu-clear-object-stmt:error-incorrect-inouts/disp32
23101 $check-mu-clear-object-stmt:types:
23102     # var src-type/ecx: (addr type-tree) = src->value->type
23103     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23104     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23105     89/<- %ecx 0/r32/eax
23106     # if (src->is-deref?) src-type = src-type->payload
23107     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
23108     3d/compare-eax-and 0/imm32/false
23109     {
23110       74/jump-if-= break/disp8
23111       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
23112       # if src-type->right is null, src-type = src-type->left
23113       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
23114       {
23115         75/jump-if-!= break/disp8
23116         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23117       }
23118       89/<- %ecx 0/r32/eax
23119     }
23120     # if src-type is not addr, abort
23121     (is-mu-addr-type? %ecx)  # => eax
23122     3d/compare-eax-and 0/imm32/false
23123     0f 84/jump-if-= $check-mu-clear-object-stmt:error-invalid-type/disp32
23124 $check-mu-clear-object-stmt:end:
23125     # . restore registers
23126     5f/pop-to-edi
23127     5e/pop-to-esi
23128     5b/pop-to-ebx
23129     59/pop-to-ecx
23130     58/pop-to-eax
23131     # . epilogue
23132     89/<- %esp 5/r32/ebp
23133     5d/pop-to-ebp
23134     c3/return
23135 
23136 $check-mu-clear-object-stmt:error-incorrect-inouts:
23137     (write-buffered *(ebp+0x10) "fn ")
23138     8b/-> *(ebp+0xc) 0/r32/eax
23139     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23140     (write-buffered *(ebp+0x10) %eax)
23141     (write-buffered *(ebp+0x10) ": stmt 'clear-object' must have a single inout\n")
23142     (flush *(ebp+0x10))
23143     (stop *(ebp+0x14) 1)
23144     # never gets here
23145 
23146 $check-mu-clear-object-stmt:error-too-many-outputs:
23147     (write-buffered *(ebp+0x10) "fn ")
23148     8b/-> *(ebp+0xc) 0/r32/eax
23149     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23150     (write-buffered *(ebp+0x10) %eax)
23151     (write-buffered *(ebp+0x10) ": stmt 'clear-object' must not have any outputs\n")
23152     (flush *(ebp+0x10))
23153     (stop *(ebp+0x14) 1)
23154     # never gets here
23155 
23156 $check-mu-clear-object-stmt:error-invalid-type:
23157     (write-buffered *(ebp+0x10) "fn ")
23158     8b/-> *(ebp+0xc) 0/r32/eax
23159     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23160     (write-buffered *(ebp+0x10) %eax)
23161     (write-buffered *(ebp+0x10) ": stmt clear-object: inout must have an addr type\n")
23162     (flush *(ebp+0x10))
23163     (stop *(ebp+0x14) 1)
23164     # never gets here
23165 
23166 check-mu-allocate-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23167     # . prologue
23168     55/push-ebp
23169     89/<- %ebp 4/r32/esp
23170     # . save registers
23171     50/push-eax
23172     53/push-ebx
23173     56/push-esi
23174     57/push-edi
23175     # esi = stmt
23176     8b/-> *(ebp+8) 6/r32/esi
23177 $check-mu-allocate-stmt:check-for-output:
23178     # if stmt->outputs abort
23179     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
23180     3d/compare-eax-and 0/imm32
23181     0f 85/jump-if-!= $check-mu-allocate-stmt:error-too-many-outputs/disp32
23182 $check-mu-allocate-stmt:get-target:
23183     # var target/edi: (addr stmt-var) = stmt->inouts
23184     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23185     89/<- %edi 0/r32/eax
23186     # zero inouts
23187     3d/compare-eax-and 0/imm32
23188     0f 84/jump-if-= $check-mu-allocate-stmt:error-incorrect-inouts/disp32
23189     # > 1 inouts
23190     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
23191     3d/compare-eax-and 0/imm32
23192     0f 85/jump-if-!= $check-mu-allocate-stmt:error-incorrect-inouts/disp32
23193 $check-mu-allocate-stmt:check-type:
23194     # var target-type/ebx: (addr type-tree) = target->value->type
23195     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23196     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23197     89/<- %ebx 0/r32/eax
23198     # if (target->is-deref?) target-type = target-type->payload
23199     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
23200     3d/compare-eax-and 0/imm32/false
23201     {
23202       74/jump-if-= break/disp8
23203       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23204       # if target-type->right is null, target-type = target-type->left
23205       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
23206       {
23207         75/jump-if-!= break/disp8
23208         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23209       }
23210       89/<- %ebx 0/r32/eax
23211     }
23212     # if target-type is not addr, abort
23213     (is-mu-addr-type? %ebx)  # => eax
23214     3d/compare-eax-and 0/imm32/false
23215     0f 84/jump-if-= $check-mu-allocate-stmt:error-invalid-type/disp32
23216     # if target-type->right is an atom, abort
23217     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23218     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
23219     0f 85/jump-if-!= $check-mu-allocate-stmt:error-invalid-type/disp32
23220     # if target-type->right->left is not handle, abort
23221     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23222     (is-simple-mu-type? %eax 4)  # handle => eax
23223     3d/compare-eax-and 0/imm32/false
23224     0f 84/jump-if-= $check-mu-allocate-stmt:error-invalid-type/disp32
23225 $check-mu-allocate-stmt:end:
23226     # . restore registers
23227     5f/pop-to-edi
23228     5e/pop-to-esi
23229     5b/pop-to-ebx
23230     58/pop-to-eax
23231     # . epilogue
23232     89/<- %esp 5/r32/ebp
23233     5d/pop-to-ebp
23234     c3/return
23235 
23236 $check-mu-allocate-stmt:error-incorrect-inouts:
23237     (write-buffered *(ebp+0x10) "fn ")
23238     8b/-> *(ebp+0xc) 0/r32/eax
23239     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23240     (write-buffered *(ebp+0x10) %eax)
23241     (write-buffered *(ebp+0x10) ": stmt 'allocate' must have a single inout\n")
23242     (flush *(ebp+0x10))
23243     (stop *(ebp+0x14) 1)
23244     # never gets here
23245 
23246 $check-mu-allocate-stmt:error-too-many-outputs:
23247     (write-buffered *(ebp+0x10) "fn ")
23248     8b/-> *(ebp+0xc) 0/r32/eax
23249     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23250     (write-buffered *(ebp+0x10) %eax)
23251     (write-buffered *(ebp+0x10) ": stmt 'allocate' must not have any outputs\n")
23252     (flush *(ebp+0x10))
23253     (stop *(ebp+0x14) 1)
23254     # never gets here
23255 
23256 $check-mu-allocate-stmt:error-invalid-type:
23257     (write-buffered *(ebp+0x10) "fn ")
23258     8b/-> *(ebp+0xc) 0/r32/eax
23259     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23260     (write-buffered *(ebp+0x10) %eax)
23261     (write-buffered *(ebp+0x10) ": stmt allocate: inout '")
23262     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23263     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23264     (write-buffered *(ebp+0x10) %eax)
23265     (write-buffered *(ebp+0x10) "' must have type (addr handle ...)\n")
23266     (flush *(ebp+0x10))
23267     (stop *(ebp+0x14) 1)
23268     # never gets here
23269 
23270 check-mu-populate-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23271     # . prologue
23272     55/push-ebp
23273     89/<- %ebp 4/r32/esp
23274     # . save registers
23275     50/push-eax
23276     53/push-ebx
23277     56/push-esi
23278     57/push-edi
23279     # esi = stmt
23280     8b/-> *(ebp+8) 6/r32/esi
23281 $check-mu-populate-stmt:check-for-output:
23282     # if stmt->outputs abort
23283     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
23284     3d/compare-eax-and 0/imm32
23285     0f 85/jump-if-!= $check-mu-populate-stmt:error-too-many-outputs/disp32
23286 $check-mu-populate-stmt:get-target:
23287     # var target/edi: (addr stmt-var) = stmt->inouts
23288     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23289     89/<- %edi 0/r32/eax
23290     # zero inouts
23291     3d/compare-eax-and 0/imm32
23292     0f 84/jump-if-= $check-mu-populate-stmt:error-incorrect-inouts/disp32
23293 $check-mu-populate-stmt:get-length:
23294     # var length/esi: (addr stmt-var) = dest->next
23295     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
23296     89/<- %esi 0/r32/eax
23297     # 1 inout
23298     3d/compare-eax-and 0/imm32
23299     0f 84/jump-if-= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
23300     # > 2 inouts
23301     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
23302     3d/compare-eax-and 0/imm32
23303     0f 85/jump-if-!= $check-mu-populate-stmt:error-incorrect-inouts/disp32
23304 $check-mu-populate-stmt:check-target-type:
23305     # var target-type/ebx: (addr type-tree) = target->value->type
23306     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23307     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23308     89/<- %ebx 0/r32/eax
23309 $check-mu-populate-stmt:check-target-type-deref:
23310     # if (target->is-deref?) target-type = target-type->payload
23311     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
23312     3d/compare-eax-and 0/imm32/false
23313     {
23314       74/jump-if-= break/disp8
23315       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23316       # if target-type->right is null, target-type = target-type->left
23317       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
23318       {
23319         75/jump-if-!= break/disp8
23320         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23321       }
23322       89/<- %ebx 0/r32/eax
23323     }
23324 $check-mu-populate-stmt:check-target-type-addr:
23325     # if target-type is not addr, abort
23326     (is-mu-addr-type? %ebx)  # => eax
23327     3d/compare-eax-and 0/imm32/false
23328     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32
23329     # if target-type->right is an atom, abort
23330     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23331     89/<- %ebx 0/r32/eax
23332     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
23333     0f 85/jump-if-!= $check-mu-populate-stmt:error-invalid-target-type/disp32
23334 $check-mu-populate-stmt:check-target-type-handle:
23335     # if target-type->right->left is not handle, abort
23336     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
23337     (is-simple-mu-type? %eax 4)  # handle => eax
23338     3d/compare-eax-and 0/imm32/false
23339     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32
23340     # if target-type->right->right is an atom, abort
23341     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23342     89/<- %ebx 0/r32/eax
23343     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
23344     0f 85/jump-if-!= $check-mu-populate-stmt:error-invalid-target-type/disp32
23345 $check-mu-populate-stmt:check-target-type-array:
23346     # if target-type->right->right->left is not array, abort
23347     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
23348     (is-simple-mu-type? %eax 3)  # array => eax
23349     3d/compare-eax-and 0/imm32/false
23350     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32
23351 $check-mu-populate-stmt:check-length-type:
23352     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
23353     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23354     89/<- %ebx 0/r32/eax
23355     (is-simple-mu-type? %ebx 0)  # literal => eax
23356     3d/compare-eax-and 0/imm32/false
23357     75/jump-if-!= $check-mu-populate-stmt:end/disp8
23358     (is-simple-mu-type? %ebx 1)  # int => eax
23359     3d/compare-eax-and 0/imm32/false
23360     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-length-type/disp32
23361 $check-mu-populate-stmt:end:
23362     # . restore registers
23363     5f/pop-to-edi
23364     5e/pop-to-esi
23365     5b/pop-to-ebx
23366     58/pop-to-eax
23367     # . epilogue
23368     89/<- %esp 5/r32/ebp
23369     5d/pop-to-ebp
23370     c3/return
23371 
23372 $check-mu-populate-stmt:error-incorrect-inouts:
23373     (write-buffered *(ebp+0x10) "fn ")
23374     8b/-> *(ebp+0xc) 0/r32/eax
23375     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23376     (write-buffered *(ebp+0x10) %eax)
23377     (write-buffered *(ebp+0x10) ": stmt 'populate' must have two inouts\n")
23378     (flush *(ebp+0x10))
23379     (stop *(ebp+0x14) 1)
23380     # never gets here
23381 
23382 $check-mu-populate-stmt:error-too-many-outputs:
23383     (write-buffered *(ebp+0x10) "fn ")
23384     8b/-> *(ebp+0xc) 0/r32/eax
23385     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23386     (write-buffered *(ebp+0x10) %eax)
23387     (write-buffered *(ebp+0x10) ": stmt 'populate' must not have any outputs\n")
23388     (flush *(ebp+0x10))
23389     (stop *(ebp+0x14) 1)
23390     # never gets here
23391 
23392 $check-mu-populate-stmt:error-invalid-target-type:
23393     (write-buffered *(ebp+0x10) "fn ")
23394     8b/-> *(ebp+0xc) 0/r32/eax
23395     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23396     (write-buffered *(ebp+0x10) %eax)
23397     (write-buffered *(ebp+0x10) ": stmt populate: first inout '")
23398     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23399     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23400     (write-buffered *(ebp+0x10) %eax)
23401     (write-buffered *(ebp+0x10) "' must have type (addr handle array ...)\n")
23402     (flush *(ebp+0x10))
23403     (stop *(ebp+0x14) 1)
23404     # never gets here
23405 
23406 $check-mu-populate-stmt:error-invalid-length-type:
23407     (write-buffered *(ebp+0x10) "fn ")
23408     8b/-> *(ebp+0xc) 0/r32/eax
23409     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23410     (write-buffered *(ebp+0x10) %eax)
23411     (write-buffered *(ebp+0x10) ": stmt populate: second inout '")
23412     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
23413     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23414     (write-buffered *(ebp+0x10) %eax)
23415     (write-buffered *(ebp+0x10) "' must be an int\n")
23416     (flush *(ebp+0x10))
23417     (stop *(ebp+0x14) 1)
23418     # never gets here
23419 
23420 check-mu-populate-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23421     # . prologue
23422     55/push-ebp
23423     89/<- %ebp 4/r32/esp
23424     # . save registers
23425     50/push-eax
23426     53/push-ebx
23427     56/push-esi
23428     57/push-edi
23429     # esi = stmt
23430     8b/-> *(ebp+8) 6/r32/esi
23431 $check-mu-populate-stream-stmt:check-for-output:
23432     # if stmt->outputs abort
23433     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
23434     3d/compare-eax-and 0/imm32
23435     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-too-many-outputs/disp32
23436 $check-mu-populate-stream-stmt:get-target:
23437     # var target/edi: (addr stmt-var) = stmt->inouts
23438     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23439     89/<- %edi 0/r32/eax
23440     # zero inouts
23441     3d/compare-eax-and 0/imm32
23442     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32
23443 $check-mu-populate-stream-stmt:get-length:
23444     # var length/esi: (addr stmt-var) = dest->next
23445     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
23446     89/<- %esi 0/r32/eax
23447     # 1 inout
23448     3d/compare-eax-and 0/imm32
23449     0f 84/jump-if-= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
23450     # > 2 inouts
23451     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
23452     3d/compare-eax-and 0/imm32
23453     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32
23454 $check-mu-populate-stream-stmt:check-target-type:
23455     # var target-type/ebx: (addr type-tree) = target->value->type
23456     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23457     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23458     89/<- %ebx 0/r32/eax
23459 $check-mu-populate-stream-stmt:check-target-type-deref:
23460     # if (target->is-deref?) target-type = target-type->payload
23461     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
23462     3d/compare-eax-and 0/imm32/false
23463     {
23464       74/jump-if-= break/disp8
23465       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23466       # if target-type->right is null, target-type = target-type->left
23467       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
23468       {
23469         75/jump-if-!= break/disp8
23470         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23471       }
23472       89/<- %ebx 0/r32/eax
23473     }
23474 $check-mu-populate-stream-stmt:check-target-type-addr:
23475     # if target-type is not addr, abort
23476     (is-mu-addr-type? %ebx)  # => eax
23477     3d/compare-eax-and 0/imm32/false
23478     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
23479     # if target-type->right is an atom, abort
23480     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23481     89/<- %ebx 0/r32/eax
23482     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
23483     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
23484 $check-mu-populate-stream-stmt:check-target-type-handle:
23485     # if target-type->right->left is not handle, abort
23486     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
23487     (is-simple-mu-type? %eax 4)  # handle => eax
23488     3d/compare-eax-and 0/imm32/false
23489     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
23490     # if target-type->right->right is an atom, abort
23491     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23492     89/<- %ebx 0/r32/eax
23493     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
23494     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
23495 $check-mu-populate-stream-stmt:check-target-type-stream:
23496     # if target-type->right->right->left is not stream, abort
23497     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
23498     (is-simple-mu-type? %eax 0xb)  # stream => eax
23499     3d/compare-eax-and 0/imm32/false
23500     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
23501 $check-mu-populate-stream-stmt:check-length-type:
23502     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
23503     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23504     89/<- %ebx 0/r32/eax
23505     (is-simple-mu-type? %ebx 0)  # literal => eax
23506     3d/compare-eax-and 0/imm32/false
23507     75/jump-if-!= $check-mu-populate-stream-stmt:end/disp8
23508     (is-simple-mu-type? %ebx 1)  # int => eax
23509     3d/compare-eax-and 0/imm32/false
23510     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-length-type/disp32
23511 $check-mu-populate-stream-stmt:end:
23512     # . restore registers
23513     5f/pop-to-edi
23514     5e/pop-to-esi
23515     5b/pop-to-ebx
23516     58/pop-to-eax
23517     # . epilogue
23518     89/<- %esp 5/r32/ebp
23519     5d/pop-to-ebp
23520     c3/return
23521 
23522 $check-mu-populate-stream-stmt:error-incorrect-inouts:
23523     (write-buffered *(ebp+0x10) "fn ")
23524     8b/-> *(ebp+0xc) 0/r32/eax
23525     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23526     (write-buffered *(ebp+0x10) %eax)
23527     (write-buffered *(ebp+0x10) ": stmt 'populate-stream' must have two inouts\n")
23528     (flush *(ebp+0x10))
23529     (stop *(ebp+0x14) 1)
23530     # never gets here
23531 
23532 $check-mu-populate-stream-stmt:error-too-many-outputs:
23533     (write-buffered *(ebp+0x10) "fn ")
23534     8b/-> *(ebp+0xc) 0/r32/eax
23535     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23536     (write-buffered *(ebp+0x10) %eax)
23537     (write-buffered *(ebp+0x10) ": stmt 'populate-stream' must not have any outputs\n")
23538     (flush *(ebp+0x10))
23539     (stop *(ebp+0x14) 1)
23540     # never gets here
23541 
23542 $check-mu-populate-stream-stmt:error-invalid-target-type:
23543     (write-buffered *(ebp+0x10) "fn ")
23544     8b/-> *(ebp+0xc) 0/r32/eax
23545     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23546     (write-buffered *(ebp+0x10) %eax)
23547     (write-buffered *(ebp+0x10) ": stmt populate-stream: first inout '")
23548     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23549     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23550     (write-buffered *(ebp+0x10) %eax)
23551     (write-buffered *(ebp+0x10) "' must have type (addr handle stream ...)\n")
23552     (flush *(ebp+0x10))
23553     (stop *(ebp+0x14) 1)
23554     # never gets here
23555 
23556 $check-mu-populate-stream-stmt:error-invalid-length-type:
23557     (write-buffered *(ebp+0x10) "fn ")
23558     8b/-> *(ebp+0xc) 0/r32/eax
23559     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23560     (write-buffered *(ebp+0x10) %eax)
23561     (write-buffered *(ebp+0x10) ": stmt populate-stream: second inout '")
23562     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
23563     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23564     (write-buffered *(ebp+0x10) %eax)
23565     (write-buffered *(ebp+0x10) "' must be an int\n")
23566     (flush *(ebp+0x10))
23567     (stop *(ebp+0x14) 1)
23568     # never gets here
23569 
23570 check-mu-read-from-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23571     # . prologue
23572     55/push-ebp
23573     89/<- %ebp 4/r32/esp
23574     # . save registers
23575     50/push-eax
23576     51/push-ecx
23577     52/push-edx
23578     53/push-ebx
23579     56/push-esi
23580     57/push-edi
23581     # esi = stmt
23582     8b/-> *(ebp+8) 6/r32/esi
23583     # - check for 0 inouts
23584     # var base/ecx: (addr var) = stmt->inouts->value
23585     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23586 $check-mu-read-from-stream-stmt:check-no-inouts:
23587     3d/compare-eax-and 0/imm32
23588     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-too-few-inouts/disp32
23589     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23590     89/<- %ecx 0/r32/eax
23591     # - check base type is (addr stream T)
23592     # var base-type/ebx: (addr type-tree) = lookup(base->type)
23593     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
23594     89/<- %ebx 0/r32/eax
23595 $check-mu-read-from-stream-stmt:check-base-is-compound:
23596     # if base-type is an atom, abort
23597     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
23598     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
23599 $check-mu-read-from-stream-stmt:check-base-is-addr:
23600     # if type->left not addr, abort
23601     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
23602     (is-simple-mu-type? %eax 2)  # addr => eax
23603     3d/compare-eax-and 0/imm32/false
23604     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
23605 $check-mu-read-from-stream-stmt:check-base-is-addr-to-stream:
23606     # base-type = base-type->right
23607     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23608     89/<- %ebx 0/r32/eax
23609     # ensure base-type->left == stream
23610     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23611     (is-simple-mu-type? %eax 0xb)  # stream => eax
23612     3d/compare-eax-and 0/imm32/false
23613     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
23614     # - check target type is (addr T)
23615     # var target/ecx: (addr stmt-var) = stmt->inouts->next->value
23616     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23617     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
23618 $check-mu-read-from-stream-stmt:check-single-inout:
23619     3d/compare-eax-and 0/imm32
23620     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-too-few-inouts/disp32
23621     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23622     89/<- %ecx 0/r32/eax
23623     # var target-type/edx: (addr type-tree)
23624     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
23625     89/<- %edx 0/r32/eax
23626     # if target-type is an atom, it must be a literal or int
23627 $check-mu-read-from-stream-stmt:check-target-is-compound:
23628     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
23629     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-target-type-not-address/disp32
23630 $check-mu-read-from-stream-stmt:check-target-type:
23631     # target type must start with (addr ...)
23632     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
23633     (is-simple-mu-type? %eax 2)  # addr => eax
23634     3d/compare-eax-and 0/imm32/false
23635     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-target-type-not-address/disp32
23636     # if tail(base-type) != tail(target-type) abort
23637     (type-tail %ebx)  # => eax
23638     89/<- %ebx 0/r32/eax
23639     (type-tail %edx)  # => eax
23640     (type-equal? %ebx %eax)  # => eax
23641     3d/compare-eax-and 0/imm32/false
23642     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-target-type/disp32
23643 $check-mu-read-from-stream-stmt:check-too-many-inouts:
23644     # - check for too many inouts
23645     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23646     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
23647     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
23648     3d/compare-eax-and 0/imm32/false
23649     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-too-many-inouts/disp32
23650 $check-mu-read-from-stream-stmt:check-unexpected-output:
23651     # - check for any output
23652     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
23653     3d/compare-eax-and 0/imm32/false
23654     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-unexpected-output/disp32
23655 $check-mu-read-from-stream-stmt:end:
23656     # . restore registers
23657     5f/pop-to-edi
23658     5e/pop-to-esi
23659     5b/pop-to-ebx
23660     5a/pop-to-edx
23661     59/pop-to-ecx
23662     58/pop-to-eax
23663     # . epilogue
23664     89/<- %esp 5/r32/ebp
23665     5d/pop-to-ebp
23666     c3/return
23667 
23668 $check-mu-read-from-stream-stmt:error-invalid-base-type:
23669     (write-buffered *(ebp+0x10) "fn ")
23670     8b/-> *(ebp+0xc) 0/r32/eax
23671     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23672     (write-buffered *(ebp+0x10) %eax)
23673     (write-buffered *(ebp+0x10) ": stmt read-from-stream: var '")
23674     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
23675     (write-buffered *(ebp+0x10) %eax)
23676     (write-buffered *(ebp+0x10) "' must be an addr to a stream\n")
23677     (flush *(ebp+0x10))
23678     (stop *(ebp+0x14) 1)
23679     # never gets here
23680 
23681 $check-mu-read-from-stream-stmt:error-too-few-inouts:
23682     (write-buffered *(ebp+0x10) "fn ")
23683     8b/-> *(ebp+0xc) 0/r32/eax
23684     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23685     (write-buffered *(ebp+0x10) %eax)
23686     (write-buffered *(ebp+0x10) ": stmt read-from-stream: too few inouts (2 required)\n")
23687     (flush *(ebp+0x10))
23688     (stop *(ebp+0x14) 1)
23689     # never gets here
23690 
23691 $check-mu-read-from-stream-stmt:error-target-type-not-address:
23692     (write-buffered *(ebp+0x10) "fn ")
23693     8b/-> *(ebp+0xc) 0/r32/eax
23694     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23695     (write-buffered *(ebp+0x10) %eax)
23696     (write-buffered *(ebp+0x10) ": stmt read-from-stream: target '")
23697     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
23698     (write-buffered *(ebp+0x10) %eax)
23699     (write-buffered *(ebp+0x10) "' must be an addr\n")
23700     (flush *(ebp+0x10))
23701     (stop *(ebp+0x14) 1)
23702     # never gets here
23703 
23704 $check-mu-read-from-stream-stmt:error-invalid-target-type:
23705     (write-buffered *(ebp+0x10) "fn ")
23706     8b/-> *(ebp+0xc) 0/r32/eax
23707     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23708     (write-buffered *(ebp+0x10) %eax)
23709     (write-buffered *(ebp+0x10) ": stmt read-from-stream: second inout '")
23710     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
23711     (write-buffered *(ebp+0x10) %eax)
23712     (write-buffered *(ebp+0x10) "' does not have the right type\n")
23713     (flush *(ebp+0x10))
23714     (stop *(ebp+0x14) 1)
23715     # never gets here
23716 
23717 $check-mu-read-from-stream-stmt:error-too-many-inouts:
23718     (write-buffered *(ebp+0x10) "fn ")
23719     8b/-> *(ebp+0xc) 0/r32/eax
23720     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23721     (write-buffered *(ebp+0x10) %eax)
23722     (write-buffered *(ebp+0x10) ": stmt read-from-stream: too many inouts (2 required)\n")
23723     (flush *(ebp+0x10))
23724     (stop *(ebp+0x14) 1)
23725     # never gets here
23726 
23727 $check-mu-read-from-stream-stmt:error-unexpected-output:
23728     (write-buffered *(ebp+0x10) "fn ")
23729     8b/-> *(ebp+0xc) 0/r32/eax
23730     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23731     (write-buffered *(ebp+0x10) %eax)
23732     (write-buffered *(ebp+0x10) ": stmt read-from-stream: unexpected output\n")
23733     (flush *(ebp+0x10))
23734     (stop *(ebp+0x14) 1)
23735     # never gets here
23736 
23737 check-mu-write-to-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23738     # . prologue
23739     55/push-ebp
23740     89/<- %ebp 4/r32/esp
23741     # . save registers
23742     50/push-eax
23743     51/push-ecx
23744     52/push-edx
23745     53/push-ebx
23746     56/push-esi
23747     57/push-edi
23748     # esi = stmt
23749     8b/-> *(ebp+8) 6/r32/esi
23750     # - check for 0 inouts
23751     # var base/ecx: (addr var) = stmt->inouts->value
23752     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23753 $check-mu-write-to-stream-stmt:check-no-inouts:
23754     3d/compare-eax-and 0/imm32
23755     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-too-few-inouts/disp32
23756     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23757     89/<- %ecx 0/r32/eax
23758     # - check base type is (addr stream T)
23759     # var base-type/ebx: (addr type-tree) = lookup(base->type)
23760     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
23761     89/<- %ebx 0/r32/eax
23762 $check-mu-write-to-stream-stmt:check-base-is-compound:
23763     # if base-type is an atom, abort
23764     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
23765     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
23766 $check-mu-write-to-stream-stmt:check-base-is-addr:
23767     # if type->left not addr, abort
23768     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
23769     (is-simple-mu-type? %eax 2)  # addr => eax
23770     3d/compare-eax-and 0/imm32/false
23771     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
23772 $check-mu-write-to-stream-stmt:check-base-is-addr-to-stream:
23773     # base-type = base-type->right
23774     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23775     89/<- %ebx 0/r32/eax
23776     # ensure base-type->left == stream
23777     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23778     (is-simple-mu-type? %eax 0xb)  # stream => eax
23779     3d/compare-eax-and 0/imm32/false
23780     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
23781     # - check target type is (addr T)
23782     # var target/ecx: (addr stmt-var) = stmt->inouts->next->value
23783     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23784     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
23785 $check-mu-write-to-stream-stmt:check-single-inout:
23786     3d/compare-eax-and 0/imm32
23787     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-too-few-inouts/disp32
23788     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23789     89/<- %ecx 0/r32/eax
23790     # var target-type/edx: (addr type-tree)
23791     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
23792     89/<- %edx 0/r32/eax
23793     # if target-type is an atom, it must be a literal or int
23794 $check-mu-write-to-stream-stmt:check-target-is-compound:
23795     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
23796     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-target-type-not-address/disp32
23797 $check-mu-write-to-stream-stmt:check-target-type:
23798     # target type must start with (addr ...)
23799     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
23800     (is-simple-mu-type? %eax 2)  # addr => eax
23801     3d/compare-eax-and 0/imm32/false
23802     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-target-type-not-address/disp32
23803     # if tail(base-type) != tail(target-type) abort
23804     (type-tail %ebx)  # => eax
23805     89/<- %ebx 0/r32/eax
23806     (type-tail %edx)  # => eax
23807     (type-equal? %ebx %eax)  # => eax
23808     3d/compare-eax-and 0/imm32/false
23809     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-target-type/disp32
23810 $check-mu-write-to-stream-stmt:check-too-many-inouts:
23811     # - check for too many inouts
23812     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23813     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
23814     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
23815     3d/compare-eax-and 0/imm32/false
23816     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-too-many-inouts/disp32
23817 $check-mu-write-to-stream-stmt:check-unexpected-output:
23818     # - check for any output
23819     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
23820     3d/compare-eax-and 0/imm32/false
23821     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-unexpected-output/disp32
23822 $check-mu-write-to-stream-stmt:end:
23823     # . restore registers
23824     5f/pop-to-edi
23825     5e/pop-to-esi
23826     5b/pop-to-ebx
23827     5a/pop-to-edx
23828     59/pop-to-ecx
23829     58/pop-to-eax
23830     # . epilogue
23831     89/<- %esp 5/r32/ebp
23832     5d/pop-to-ebp
23833     c3/return
23834 
23835 $check-mu-write-to-stream-stmt:error-invalid-base-type:
23836     (write-buffered *(ebp+0x10) "fn ")
23837     8b/-> *(ebp+0xc) 0/r32/eax
23838     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23839     (write-buffered *(ebp+0x10) %eax)
23840     (write-buffered *(ebp+0x10) ": stmt write-to-stream: var '")
23841     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
23842     (write-buffered *(ebp+0x10) %eax)
23843     (write-buffered *(ebp+0x10) "' must be an addr to a stream\n")
23844     (flush *(ebp+0x10))
23845     (stop *(ebp+0x14) 1)
23846     # never gets here
23847 
23848 $check-mu-write-to-stream-stmt:error-too-few-inouts:
23849     (write-buffered *(ebp+0x10) "fn ")
23850     8b/-> *(ebp+0xc) 0/r32/eax
23851     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23852     (write-buffered *(ebp+0x10) %eax)
23853     (write-buffered *(ebp+0x10) ": stmt write-to-stream: too few inouts (2 required)\n")
23854     (flush *(ebp+0x10))
23855     (stop *(ebp+0x14) 1)
23856     # never gets here
23857 
23858 $check-mu-write-to-stream-stmt:error-target-type-not-address:
23859     (write-buffered *(ebp+0x10) "fn ")
23860     8b/-> *(ebp+0xc) 0/r32/eax
23861     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23862     (write-buffered *(ebp+0x10) %eax)
23863     (write-buffered *(ebp+0x10) ": stmt write-to-stream: target '")
23864     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
23865     (write-buffered *(ebp+0x10) %eax)
23866     (write-buffered *(ebp+0x10) "' must be an addr\n")
23867     (flush *(ebp+0x10))
23868     (stop *(ebp+0x14) 1)
23869     # never gets here
23870 
23871 $check-mu-write-to-stream-stmt:error-invalid-target-type:
23872     (write-buffered *(ebp+0x10) "fn ")
23873     8b/-> *(ebp+0xc) 0/r32/eax
23874     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23875     (write-buffered *(ebp+0x10) %eax)
23876     (write-buffered *(ebp+0x10) ": stmt write-to-stream: second inout '")
23877     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
23878     (write-buffered *(ebp+0x10) %eax)
23879     (write-buffered *(ebp+0x10) "' does not have the right type\n")
23880     (flush *(ebp+0x10))
23881     (stop *(ebp+0x14) 1)
23882     # never gets here
23883 
23884 $check-mu-write-to-stream-stmt:error-too-many-inouts:
23885     (write-buffered *(ebp+0x10) "fn ")
23886     8b/-> *(ebp+0xc) 0/r32/eax
23887     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23888     (write-buffered *(ebp+0x10) %eax)
23889     (write-buffered *(ebp+0x10) ": stmt write-to-stream: too many inouts (2 required)\n")
23890     (flush *(ebp+0x10))
23891     (stop *(ebp+0x14) 1)
23892     # never gets here
23893 
23894 $check-mu-write-to-stream-stmt:error-unexpected-output:
23895     (write-buffered *(ebp+0x10) "fn ")
23896     8b/-> *(ebp+0xc) 0/r32/eax
23897     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23898     (write-buffered *(ebp+0x10) %eax)
23899     (write-buffered *(ebp+0x10) ": stmt write-to-stream: unexpected output\n")
23900     (flush *(ebp+0x10))
23901     (stop *(ebp+0x14) 1)
23902     # never gets here
23903 
23904 check-mu-convert-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23905     # . prologue
23906     55/push-ebp
23907     89/<- %ebp 4/r32/esp
23908     # . save registers
23909 $check-mu-convert-stmt:end:
23910     # . restore registers
23911     # . epilogue
23912     89/<- %esp 5/r32/ebp
23913     5d/pop-to-ebp
23914     c3/return
23915 
23916 check-mu-call:  # stmt: (addr stmt), callee: (addr function), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23917     # . prologue
23918     55/push-ebp
23919     89/<- %ebp 4/r32/esp
23920     # var type-parameters: (addr table (handle array byte) (addr type-tree) 8)
23921     68/push 0/imm32
23922     # var type-parameters-storage: (table (handle array byte) (addr type-tree) 8)
23923     81 5/subop/subtract %esp 0x60/imm32
23924     68/push 0x60/imm32/size
23925     68/push 0/imm32/read
23926     68/push 0/imm32/write
23927     # save a pointer to type-parameters-storage at type-parameters
23928     89/<- *(ebp-4) 4/r32/esp
23929     (clear-stream *(ebp-4))
23930     # . save registers
23931     50/push-eax
23932     51/push-ecx
23933     52/push-edx
23934     53/push-ebx
23935     56/push-esi
23936     57/push-edi
23937     # esi = stmt
23938     8b/-> *(ebp+8) 6/r32/esi
23939     # edi = callee
23940     8b/-> *(ebp+0xc) 7/r32/edi
23941     # var inouts/ecx: (addr stmt-var) = lookup(stmt->inouts)
23942     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23943     89/<- %ecx 0/r32/eax
23944     # var expected/edx: (addr list var) = lookup(f->inouts)
23945     (lookup *(edi+8) *(edi+0xc))  # Function-inouts Function-inouts => eax
23946     89/<- %edx 0/r32/eax
23947     {
23948 $check-mu-call:check-for-inouts:
23949       # if (inouts == 0) break
23950       81 7/subop/compare %ecx 0/imm32
23951       0f 84/jump-if-= break/disp32
23952       # if (expected == 0) error
23953       81 7/subop/compare %edx 0/imm32
23954       0f 84/jump-if-= break/disp32
23955 $check-mu-call:check-null-addr:
23956       # if (inouts->value->name == "0") continue
23957       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
23958       (lookup *eax *(eax+4))  # Var-name Var-name => eax
23959       (string-equal? %eax "0")  # => eax
23960       3d/compare-eax-and 0/imm32/false
23961       0f 85/jump-if-!= $check-mu-call:continue-to-next-inout/disp32
23962 $check-mu-call:check-inout-type:
23963       # var t/ebx: (addr type-tree) = inouts->value->type
23964       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
23965       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23966       89/<- %ebx 0/r32/eax
23967       # if (inouts->is-deref?) t = t->right
23968       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
23969       {
23970         74/jump-if-= break/disp8
23971         (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23972         89/<- %ebx 0/r32/eax
23973         # if t->right is null, t = t->left
23974         81 7/subop/compare *(ebx+0xc) 0/imm32  # Type-tree-right
23975         75/jump-if-!= break/disp8
23976         (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
23977         89/<- %ebx 0/r32/eax
23978       }
23979       # var v2/eax: (addr v) = lookup(expected->value)
23980       (lookup *edx *(edx+4))  # List-value List-value => eax
23981       # var t2/eax: (addr type-tree) = lookup(v2->type)
23982       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23983       # if (t != t2) error
23984       (type-match? %eax %ebx *(ebp-4))  # => eax
23985       3d/compare-eax-and 0/imm32/false
23986       {
23987         0f 85/jump-if-!= break/disp32
23988         (write-buffered *(ebp+0x14) "fn ")
23989         8b/-> *(ebp+0x10) 0/r32/eax
23990         (lookup *eax *(eax+4))  # Function-name Function-name => eax
23991         (write-buffered *(ebp+0x14) %eax)
23992         (write-buffered *(ebp+0x14) ": call ")
23993         (lookup *edi *(edi+4))  # Function-name Function-name => eax
23994         (write-buffered *(ebp+0x14) %eax)
23995         (write-buffered *(ebp+0x14) ": type for inout '")
23996         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
23997         (lookup *eax *(eax+4))  # Var-name Var-name => eax
23998         (write-buffered *(ebp+0x14) %eax)
23999         (write-buffered *(ebp+0x14) "' is not right\n")
24000         (flush *(ebp+0x14))
24001         (stop *(ebp+0x18) 1)
24002       }
24003 $check-mu-call:continue-to-next-inout:
24004       # inouts = lookup(inouts->next)
24005       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
24006       89/<- %ecx 0/r32/eax
24007       # expected = lookup(expected->next)
24008       (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
24009       89/<- %edx 0/r32/eax
24010       #
24011       e9/jump loop/disp32
24012     }
24013 $check-mu-call:check-inout-count:
24014     # if (inouts == expected) proceed
24015     39/compare %ecx 2/r32/edx
24016     {
24017       0f 84/jump-if-= break/disp32
24018       # exactly one of the two is null
24019       # if (inouts == 0) error("too many inouts")
24020       {
24021         81 7/subop/compare %ecx 0/imm32
24022         0f 84/jump-if-= break/disp32
24023         (write-buffered *(ebp+0x14) "fn ")
24024         8b/-> *(ebp+0x10) 0/r32/eax
24025         (lookup *eax *(eax+4))  # Function-name Function-name => eax
24026         (write-buffered *(ebp+0x14) %eax)
24027         (write-buffered *(ebp+0x14) ": call ")
24028         (lookup *edi *(edi+4))  # Function-name Function-name => eax
24029         (write-buffered *(ebp+0x14) %eax)
24030         (write-buffered *(ebp+0x14) ": too many inouts\n")
24031         (flush *(ebp+0x14))
24032         (stop *(ebp+0x18) 1)
24033       }
24034       # if (expected == 0) error("too few inouts")
24035       {
24036         81 7/subop/compare %edx 0/imm32
24037         0f 84/jump-if-= break/disp32
24038         (write-buffered *(ebp+0x14) "fn ")
24039         8b/-> *(ebp+0x10) 0/r32/eax
24040         (lookup *eax *(eax+4))  # Function-name Function-name => eax
24041         (write-buffered *(ebp+0x14) %eax)
24042         (write-buffered *(ebp+0x14) ": call ")
24043         (lookup *edi *(edi+4))  # Function-name Function-name => eax
24044         (write-buffered *(ebp+0x14) %eax)
24045         (write-buffered *(ebp+0x14) ": too few inouts\n")
24046         (flush *(ebp+0x14))
24047         (stop *(ebp+0x18) 1)
24048       }
24049     }
24050 $check-mu-call:check-outputs:
24051     # var outputs/ecx: (addr stmt-var) = lookup(stmt->outputs)
24052     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24053     89/<- %ecx 0/r32/eax
24054     # var expected/edx: (addr list var) = lookup(f->outputs)
24055     (lookup *(edi+0x10) *(edi+0x14))  # Function-outputs Function-outputs => eax
24056     89/<- %edx 0/r32/eax
24057     {
24058 $check-mu-call:check-for-outputs:
24059       # if (outputs == 0) break
24060       81 7/subop/compare %ecx 0/imm32
24061       0f 84/jump-if-= break/disp32
24062       # if (expected == 0) error
24063       81 7/subop/compare %edx 0/imm32
24064       0f 84/jump-if-= break/disp32
24065 $check-mu-call:check-output-type:
24066       # var v/eax: (addr v) = lookup(outputs->value)
24067       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
24068       # var t/ebx: (addr type-tree) = lookup(v->type)
24069       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
24070       89/<- %ebx 0/r32/eax
24071       # if (outputs->is-deref?) t = t->right  # TODO: check that t->left is an addr
24072       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
24073       {
24074         74/jump-if-= break/disp8
24075         (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
24076         89/<- %ebx 0/r32/eax
24077       }
24078       # var v2/eax: (addr v) = lookup(expected->value)
24079       (lookup *edx *(edx+4))  # List-value List-value => eax
24080       # var t2/eax: (addr type-tree) = lookup(v2->type)
24081       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
24082       # if (t != t2) error
24083       (type-match? %eax %ebx *(ebp-4))  # => eax
24084       3d/compare-eax-and 0/imm32/false
24085       {
24086         0f 85/jump-if-!= break/disp32
24087         (write-buffered *(ebp+0x14) "fn ")
24088         8b/-> *(ebp+0x10) 0/r32/eax
24089         (lookup *eax *(eax+4))  # Function-name Function-name => eax
24090         (write-buffered *(ebp+0x14) %eax)
24091         (write-buffered *(ebp+0x14) ": call ")
24092         (lookup *edi *(edi+4))  # Function-name Function-name => eax
24093         (write-buffered *(ebp+0x14) %eax)
24094         (write-buffered *(ebp+0x14) ": type for output '")
24095         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
24096         (lookup *eax *(eax+4))  # Var-name Var-name => eax
24097         (write-buffered *(ebp+0x14) %eax)
24098         (write-buffered *(ebp+0x14) "' is not right\n")
24099         (flush *(ebp+0x14))
24100         (stop *(ebp+0x18) 1)
24101       }
24102 $check-mu-call:check-output-register:
24103       # var v/eax: (addr v) = lookup(outputs->value)
24104       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
24105       # var r/ebx: (addr array byte) = lookup(v->register)
24106       (lookup *(eax+18) *(eax+0x1c))  # Var-register Var-register => eax
24107       89/<- %ebx 0/r32/eax
24108       # if (r == 0) error
24109       3d/compare-eax-and 0/imm32
24110       {
24111         0f 85/jump-if-!= break/disp32
24112         (write-buffered *(ebp+0x14) "fn ")
24113         8b/-> *(ebp+0x10) 0/r32/eax
24114         (lookup *eax *(eax+4))  # Function-name Function-name => eax
24115         (write-buffered *(ebp+0x14) %eax)
24116         (write-buffered *(ebp+0x14) ": call ")
24117         (lookup *edi *(edi+4))  # Function-name Function-name => eax
24118         (write-buffered *(ebp+0x14) %eax)
24119         (write-buffered *(ebp+0x14) ": output '")
24120         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
24121         (lookup *eax *(eax+4))  # Var-name Var-name => eax
24122         (write-buffered *(ebp+0x14) %eax)
24123         (write-buffered *(ebp+0x14) "' is not in a register\n")
24124         (flush *(ebp+0x14))
24125         (stop *(ebp+0x18) 1)
24126       }
24127       # var v2/eax: (addr v) = lookup(expected->value)
24128       (lookup *edx *(edx+4))  # Stmt-var-value Stmt-var-value => eax
24129       # var r2/eax: (addr array byte) = lookup(v2->register)
24130       (lookup *(eax+18) *(eax+0x1c))  # Var-register Var-register => eax
24131       # if (r != r2) error
24132       (string-equal? %eax %ebx)  # => eax
24133       3d/compare-eax-and 0/imm32/false
24134       {
24135         0f 85/jump-if-!= break/disp32
24136         (write-buffered *(ebp+0x14) "fn ")
24137         8b/-> *(ebp+0x10) 0/r32/eax
24138         (lookup *eax *(eax+4))  # Function-name Function-name => eax
24139         (write-buffered *(ebp+0x14) %eax)
24140         (write-buffered *(ebp+0x14) ": call ")
24141         (lookup *edi *(edi+4))  # Function-name Function-name => eax
24142         (write-buffered *(ebp+0x14) %eax)
24143         (write-buffered *(ebp+0x14) ": register for output '")
24144         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
24145         (lookup *eax *(eax+4))  # Var-name Var-name => eax
24146         (write-buffered *(ebp+0x14) %eax)
24147         (write-buffered *(ebp+0x14) "' is not right\n")
24148         (flush *(ebp+0x14))
24149         (stop *(ebp+0x18) 1)
24150       }
24151 $check-mu-call:continue-to-next-output:
24152       # outputs = lookup(outputs->next)
24153       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
24154       89/<- %ecx 0/r32/eax
24155       # expected = lookup(expected->next)
24156       (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
24157       89/<- %edx 0/r32/eax
24158       #
24159       e9/jump loop/disp32
24160     }
24161 $check-mu-call:check-output-count:
24162     # if (outputs == expected) proceed
24163     39/compare %ecx 2/r32/edx
24164     {
24165       0f 84/jump-if-= break/disp32
24166       # exactly one of the two is null
24167       # if (outputs == 0) error("too many outputs")
24168       {
24169         81 7/subop/compare %ecx 0/imm32
24170         0f 84/jump-if-= break/disp32
24171         (write-buffered *(ebp+0x14) "fn ")
24172         8b/-> *(ebp+0x10) 0/r32/eax
24173         (lookup *eax *(eax+4))  # Function-name Function-name => eax
24174         (write-buffered *(ebp+0x14) %eax)
24175         (write-buffered *(ebp+0x14) ": call ")
24176         (lookup *edi *(edi+4))  # Function-name Function-name => eax
24177         (write-buffered *(ebp+0x14) %eax)
24178         (write-buffered *(ebp+0x14) ": too many outputs\n")
24179         (flush *(ebp+0x14))
24180         (stop *(ebp+0x18) 1)
24181       }
24182       # if (expected == 0) error("too few outputs")
24183       {
24184         81 7/subop/compare %edx 0/imm32
24185         0f 84/jump-if-= break/disp32
24186         (write-buffered *(ebp+0x14) "fn ")
24187         8b/-> *(ebp+0x10) 0/r32/eax
24188         (lookup *eax *(eax+4))  # Function-name Function-name => eax
24189         (write-buffered *(ebp+0x14) %eax)
24190         (write-buffered *(ebp+0x14) ": call ")
24191         (lookup *edi *(edi+4))  # Function-name Function-name => eax
24192         (write-buffered *(ebp+0x14) %eax)
24193         (write-buffered *(ebp+0x14) ": too few outputs\n")
24194         (flush *(ebp+0x14))
24195         (stop *(ebp+0x18) 1)
24196       }
24197     }
24198 $check-mu-call:end:
24199     # . restore registers
24200     5f/pop-to-edi
24201     5e/pop-to-esi
24202     5b/pop-to-ebx
24203     5a/pop-to-edx
24204     59/pop-to-ecx
24205     58/pop-to-eax
24206     # . reclaim locals exclusively on the stack
24207     81 0/subop/add %esp 0x70/imm32
24208     # . epilogue
24209     89/<- %esp 5/r32/ebp
24210     5d/pop-to-ebp
24211     c3/return
24212 
24213 # like type-equal? but takes literals type parameters into account
24214 type-match?:  # def: (addr type-tree), call: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean
24215     # . prologue
24216     55/push-ebp
24217     89/<- %ebp 4/r32/esp
24218     # if (call is literal and def is numberlike) return true
24219     {
24220 $type-match?:check-literal-int:
24221       (is-simple-mu-type? *(ebp+0xc) 0)  # literal => eax
24222       3d/compare-eax-and 0/imm32/false
24223       74/jump-if-= break/disp8
24224       (is-mu-numberlike-output? *(ebp+8))  # => eax
24225       3d/compare-eax-and 0/imm32/false
24226       74/jump-if-= break/disp8
24227       b8/copy-to-eax 1/imm32/true
24228       e9/jump $type-match?:end/disp32
24229     }
24230     # if (call is literal-string and def is string) return true
24231     {
24232 $type-match?:check-literal-string:
24233       (is-simple-mu-type? *(ebp+0xc) 0x10)  # literal-string => eax
24234       3d/compare-eax-and 0/imm32/false
24235       74/jump-if-= break/disp8
24236       (is-mu-string-type? *(ebp+8))  # => eax
24237       3d/compare-eax-and 0/imm32/false
24238       74/jump-if-= break/disp8
24239       b8/copy-to-eax 1/imm32/true
24240       e9/jump $type-match?:end/disp32
24241     }
24242 $type-match?:baseline:
24243     # otherwise fall back
24244     (type-component-match? *(ebp+8) *(ebp+0xc) *(ebp+0x10))  # => eax
24245 $type-match?:end:
24246     # . epilogue
24247     89/<- %esp 5/r32/ebp
24248     5d/pop-to-ebp
24249     c3/return
24250 
24251 type-component-match?:  # def: (addr type-tree), call: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean
24252     # . prologue
24253     55/push-ebp
24254     89/<- %ebp 4/r32/esp
24255     # . save registers
24256     51/push-ecx
24257     52/push-edx
24258     53/push-ebx
24259     # ecx = def
24260     8b/-> *(ebp+8) 1/r32/ecx
24261     # edx = call
24262     8b/-> *(ebp+0xc) 2/r32/edx
24263 $type-component-match?:compare-addr:
24264     # if (def == call) return true
24265     8b/-> %ecx 0/r32/eax  # Var-type
24266     39/compare %edx 0/r32/eax  # Var-type
24267     b8/copy-to-eax 1/imm32/true
24268     0f 84/jump-if-= $type-component-match?:end/disp32
24269     # if (def == 0) return false
24270     b8/copy-to-eax 0/imm32/false
24271     81 7/subop/compare %ecx 0/imm32  # Type-tree-is-atom
24272     0f 84/jump-if-= $type-component-match?:end/disp32
24273     # if (call == 0) return false
24274     81 7/subop/compare %edx 0/imm32  # Type-tree-is-atom
24275     0f 84/jump-if-= $type-component-match?:end/disp32
24276     # if def is a type parameter, just check in type-parameters
24277     {
24278 $type-component-match?:check-type-parameter:
24279       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
24280       74/jump-if-= break/disp8
24281       81 7/subop/compare *(ecx+4) 0xa/imm32/type-parameter  # Type-tree-value
24282       75/jump-if-!= break/disp8
24283 $type-component-match?:type-parameter:
24284       (type-parameter-match? *(ecx+8) *(ecx+0xc)  %edx  *(ebp+0x10))  # => eax
24285       e9/jump $type-component-match?:end/disp32
24286     }
24287     # if def is a list containing just a type parameter, just check in type-parameters
24288     {
24289 $type-component-match?:check-list-type-parameter:
24290       # if def is a list..
24291       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
24292       75/jump-if-!= break/disp8
24293       #   ..that's a singleton
24294       81 7/subop/compare *(ecx+0xc) 0/imm32  # Type-tree-left
24295       75/jump-if-!= break/disp8
24296       #   ..and whose head is a type parameter
24297       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
24298       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
24299       74/jump-if-= break/disp8
24300       81 7/subop/compare *(eax+4) 0xa/imm32/type-parameter  # Type-tree-value
24301       75/jump-if-!= break/disp8
24302 $type-component-match?:list-type-parameter:
24303       (type-parameter-match? *(eax+8) *(eax+0xc)  %edx  *(ebp+0x10))  # => eax
24304       e9/jump $type-component-match?:end/disp32
24305     }
24306 $type-component-match?:compare-atom-state:
24307     # if (def->is-atom? != call->is-atom?) return false
24308     8b/-> *ecx 3/r32/ebx  # Type-tree-is-atom
24309     39/compare *edx 3/r32/ebx  # Type-tree-is-atom
24310     b8/copy-to-eax 0/imm32/false
24311     0f 85/jump-if-!= $type-component-match?:end/disp32
24312     # if def->is-atom? return (def->value == call->value)
24313     {
24314 $type-component-match?:check-atom:
24315       81 7/subop/compare %ebx 0/imm32/false
24316       74/jump-if-= break/disp8
24317 $type-component-match?:is-atom:
24318       8b/-> *(ecx+4) 0/r32/eax  # Type-tree-value
24319       39/compare *(edx+4) 0/r32/eax  # Type-tree-value
24320       0f 94/set-if-= %al
24321       81 4/subop/and %eax 0xff/imm32
24322       e9/jump $type-component-match?:end/disp32
24323     }
24324 $type-component-match?:check-left:
24325     # if (!type-component-match?(def->left, call->left)) return false
24326     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
24327     89/<- %ebx 0/r32/eax
24328     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
24329     (type-component-match? %ebx %eax *(ebp+0x10))  # => eax
24330     3d/compare-eax-and 0/imm32/false
24331     74/jump-if-= $type-component-match?:end/disp8
24332 $type-component-match?:check-right:
24333     # return type-component-match?(def->right, call->right)
24334     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
24335     89/<- %ebx 0/r32/eax
24336     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
24337     (type-component-match? %ebx %eax *(ebp+0x10))  # => eax
24338 $type-component-match?:end:
24339     # . restore registers
24340     5b/pop-to-ebx
24341     5a/pop-to-edx
24342     59/pop-to-ecx
24343     # . epilogue
24344     89/<- %esp 5/r32/ebp
24345     5d/pop-to-ebp
24346     c3/return
24347 
24348 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
24349     # . prologue
24350     55/push-ebp
24351     89/<- %ebp 4/r32/esp
24352     # . save registers
24353     51/push-ecx
24354     #
24355     (get-or-insert-handle *(ebp+0x14)  *(ebp+8) *(ebp+0xc)  0xc)  # => eax
24356     # if parameter wasn't saved, save it
24357     {
24358       81 7/subop/compare *eax 0/imm32
24359       75/jump-if-!= break/disp8
24360       8b/-> *(ebp+0x10) 1/r32/ecx
24361       89/<- *eax 1/r32/ecx
24362     }
24363     #
24364     (type-equal? *(ebp+0x10) *eax)  # => eax
24365 $type-parameter-match?:end:
24366     # . restore registers
24367     59/pop-to-ecx
24368     # . epilogue
24369     89/<- %esp 5/r32/ebp
24370     5d/pop-to-ebp
24371     c3/return
24372 
24373 size-of:  # v: (addr var) -> result/eax: int
24374     # . prologue
24375     55/push-ebp
24376     89/<- %ebp 4/r32/esp
24377     # . save registers
24378     51/push-ecx
24379     # var t/ecx: (addr type-tree) = lookup(v->type)
24380     8b/-> *(ebp+8) 1/r32/ecx
24381 #?     (write-buffered Stderr "size-of ")
24382 #?     (write-int32-hex-buffered Stderr %ecx)
24383 #?     (write-buffered Stderr Newline)
24384 #?     (write-buffered Stderr "type allocid: ")
24385 #?     (write-int32-hex-buffered Stderr *(ecx+8))
24386 #?     (write-buffered Stderr Newline)
24387 #?     (flush Stderr)
24388     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
24389     89/<- %ecx 0/r32/eax
24390     # if is-mu-array?(t) return size-of-array(t)
24391     {
24392       (is-mu-array? %ecx)  # => eax
24393       3d/compare-eax-and 0/imm32/false
24394       74/jump-if-= break/disp8
24395       (size-of-array %ecx)  # => eax
24396       eb/jump $size-of:end/disp8
24397     }
24398     # if is-mu-stream?(t) return size-of-stream(t)
24399     {
24400       (is-mu-stream? %ecx)  # => eax
24401       3d/compare-eax-and 0/imm32/false
24402       74/jump-if-= break/disp8
24403       (size-of-stream %ecx)  # => eax
24404       eb/jump $size-of:end/disp8
24405     }
24406     # if (!t->is-atom?) t = lookup(t->left)
24407     {
24408       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
24409       75/jump-if-!= break/disp8
24410       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
24411       89/<- %ecx 0/r32/eax
24412     }
24413     # TODO: assert t->is-atom?
24414     (size-of-type-id *(ecx+4))  # Type-tree-value => eax
24415 $size-of:end:
24416     # . restore registers
24417     59/pop-to-ecx
24418     # . epilogue
24419     89/<- %esp 5/r32/ebp
24420     5d/pop-to-ebp
24421     c3/return
24422 
24423 size-of-deref:  # v: (addr var) -> result/eax: int
24424     # . prologue
24425     55/push-ebp
24426     89/<- %ebp 4/r32/esp
24427     # . save registers
24428     51/push-ecx
24429     # var t/ecx: (addr type-tree) = lookup(v->type)
24430     8b/-> *(ebp+8) 1/r32/ecx
24431     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
24432     89/<- %ecx 0/r32/eax
24433     # TODO: assert(t is an addr)
24434     # t = lookup(t->right)
24435     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
24436     89/<- %ecx 0/r32/eax
24437     # if is-mu-array?(t) return size-of-array(t)
24438     {
24439       (is-mu-array? %ecx)  # => eax
24440       3d/compare-eax-and 0/imm32/false
24441       74/jump-if-= break/disp8
24442       (size-of-array %ecx)  # => eax
24443       eb/jump $size-of-deref:end/disp8
24444     }
24445     # if is-mu-stream?(t) return size-of-stream(t)
24446     {
24447       (is-mu-stream? %ecx)  # => eax
24448       3d/compare-eax-and 0/imm32/false
24449       74/jump-if-= break/disp8
24450       (size-of-stream %ecx)  # => eax
24451       eb/jump $size-of-deref:end/disp8
24452     }
24453     # if (!t->is-atom?) t = lookup(t->left)
24454     {
24455       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
24456       75/jump-if-!= break/disp8
24457       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
24458       89/<- %ecx 0/r32/eax
24459     }
24460     # TODO: assert t->is-atom?
24461     (size-of-type-id *(ecx+4))  # Type-tree-value => eax
24462 $size-of-deref:end:
24463     # . restore registers
24464     59/pop-to-ecx
24465     # . epilogue
24466     89/<- %esp 5/r32/ebp
24467     5d/pop-to-ebp
24468     c3/return
24469 
24470 is-mu-array?:  # t: (addr type-tree) -> result/eax: boolean
24471     # . prologue
24472     55/push-ebp
24473     89/<- %ebp 4/r32/esp
24474     # . save registers
24475     51/push-ecx
24476     # ecx = t
24477     8b/-> *(ebp+8) 1/r32/ecx
24478     # if t->is-atom?, return false
24479     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
24480     75/jump-if-!= $is-mu-array?:return-false/disp8
24481     # if !t->left->is-atom?, return false
24482     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
24483     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
24484     74/jump-if-= $is-mu-array?:return-false/disp8
24485     # return t->left->value == array
24486     81 7/subop/compare *(eax+4) 3/imm32/array-type-id  # Type-tree-value
24487     0f 94/set-if-= %al
24488     81 4/subop/and %eax 0xff/imm32
24489     eb/jump $is-mu-array?:end/disp8
24490 $is-mu-array?:return-false:
24491     b8/copy-to-eax 0/imm32/false
24492 $is-mu-array?:end:
24493     # . restore registers
24494     59/pop-to-ecx
24495     # . epilogue
24496     89/<- %esp 5/r32/ebp
24497     5d/pop-to-ebp
24498     c3/return
24499 
24500 # size of a statically allocated array where the size is part of the type expression
24501 size-of-array:  # a: (addr type-tree) -> result/eax: int
24502     # . prologue
24503     55/push-ebp
24504     89/<- %ebp 4/r32/esp
24505     # . save registers
24506     51/push-ecx
24507     52/push-edx
24508     #
24509     8b/-> *(ebp+8) 1/r32/ecx
24510     # TODO: assert that a->left is 'array'
24511     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
24512     89/<- %ecx 0/r32/eax
24513     # var elem-type/edx: type-id = a->right->left->value
24514     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
24515     8b/-> *(eax+4) 2/r32/edx  # Type-tree-value
24516     # TODO: assert that a->right->right->left->value == size
24517     # var array-size/ecx: int = a->right->right->left->value-size
24518     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
24519     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
24520     8b/-> *(eax+8) 1/r32/ecx  # Type-tree-value-size
24521     # return 4 + array-size * size-of(elem-type)
24522     (size-of-type-id-as-array-element %edx)  # => eax
24523     f7 4/subop/multiply-into-edx-eax %ecx
24524     05/add-to-eax 4/imm32  # for array size
24525     # TODO: check edx for overflow
24526 $size-of-array:end:
24527     # . restore registers
24528     5a/pop-to-edx
24529     59/pop-to-ecx
24530     # . epilogue
24531     89/<- %esp 5/r32/ebp
24532     5d/pop-to-ebp
24533     c3/return
24534 
24535 is-mu-stream?:  # t: (addr type-tree) -> result/eax: boolean
24536     # . prologue
24537     55/push-ebp
24538     89/<- %ebp 4/r32/esp
24539     # . save registers
24540     51/push-ecx
24541     # ecx = t
24542     8b/-> *(ebp+8) 1/r32/ecx
24543     # if t->is-atom?, return false
24544     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
24545     75/jump-if-!= $is-mu-stream?:return-false/disp8
24546     # if !t->left->is-atom?, return false
24547     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
24548     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
24549     74/jump-if-= $is-mu-stream?:return-false/disp8
24550     # return t->left->value == stream
24551     81 7/subop/compare *(eax+4) 0xb/imm32/stream-type-id  # Type-tree-value
24552     0f 94/set-if-= %al
24553     81 4/subop/and %eax 0xff/imm32
24554     eb/jump $is-mu-stream?:end/disp8
24555 $is-mu-stream?:return-false:
24556     b8/copy-to-eax 0/imm32/false
24557 $is-mu-stream?:end:
24558     # . restore registers
24559     59/pop-to-ecx
24560     # . epilogue
24561     89/<- %esp 5/r32/ebp
24562     5d/pop-to-ebp
24563     c3/return
24564 
24565 # size of a statically allocated stream where the size is part of the type expression
24566 size-of-stream:  # a: (addr type-tree) -> result/eax: int
24567     # . prologue
24568     55/push-ebp
24569     89/<- %ebp 4/r32/esp
24570     #
24571     (size-of-array *(ebp+8))  # assumes we ignore the actual type name 'array' in the type
24572     05/add-to-eax 8/imm32  # for read/write pointers
24573 $size-of-stream:end:
24574     # . epilogue
24575     89/<- %esp 5/r32/ebp
24576     5d/pop-to-ebp
24577     c3/return
24578 
24579 size-of-type-id:  # t: type-id -> result/eax: int
24580     # . prologue
24581     55/push-ebp
24582     89/<- %ebp 4/r32/esp
24583     # . save registers
24584     51/push-ecx
24585     # var out/ecx: (handle typeinfo)
24586     68/push 0/imm32
24587     68/push 0/imm32
24588     89/<- %ecx 4/r32/esp
24589     # eax = t
24590     8b/-> *(ebp+8) 0/r32/eax
24591     # if t is a literal, return 0
24592     3d/compare-eax-and 0/imm32
24593     0f 84/jump-if-= $size-of-type-id:end/disp32  # eax changes type from type-id to int
24594     # if t is a byte, return 4 (because we don't really support non-multiples of 4)
24595     3d/compare-eax-and 8/imm32/byte
24596     {
24597       75/jump-if-!= break/disp8
24598       b8/copy-to-eax 4/imm32
24599       eb/jump $size-of-type-id:end/disp8
24600     }
24601     # if t is a handle, return 8
24602     3d/compare-eax-and 4/imm32/handle
24603     {
24604       75/jump-if-!= break/disp8
24605       b8/copy-to-eax 8/imm32
24606       eb/jump $size-of-type-id:end/disp8  # eax changes type from type-id to int
24607     }
24608     # if t is a slice, return 8
24609     3d/compare-eax-and 0xc/imm32/slice
24610     {
24611       75/jump-if-!= break/disp8
24612       b8/copy-to-eax 8/imm32
24613       eb/jump $size-of-type-id:end/disp8  # eax changes type from type-id to int
24614     }
24615     # if t is a user-defined type, return its size
24616     # TODO: support non-atom type
24617     (find-typeinfo %eax %ecx)
24618     {
24619       81 7/subop/compare *ecx 0/imm32
24620       74/jump-if-= break/disp8
24621 $size-of-type-id:user-defined:
24622       (lookup *ecx *(ecx+4))  # => eax
24623       8b/-> *(eax+0xc) 0/r32/eax  # Typeinfo-total-size-in-bytes
24624       eb/jump $size-of-type-id:end/disp8
24625     }
24626     # otherwise return the word size
24627     b8/copy-to-eax 4/imm32
24628 $size-of-type-id:end:
24629     # . reclaim locals
24630     81 0/subop/add %esp 8/imm32
24631     # . restore registers
24632     59/pop-to-ecx
24633     # . epilogue
24634     89/<- %esp 5/r32/ebp
24635     5d/pop-to-ebp
24636     c3/return
24637 
24638 # Minor violation of our type system since it returns an addr. But we could
24639 # replace it with a handle some time.
24640 # Returns null if t is an atom.
24641 type-tail:  # t: (addr type-tree) -> out/eax: (addr type-tree)
24642     # . prologue
24643     55/push-ebp
24644     89/<- %ebp 4/r32/esp
24645     # . save registers
24646     51/push-ecx
24647     # eax = 0
24648     b8/copy-to-eax 0/imm32
24649     # ecx = t
24650     8b/-> *(ebp+8) 1/r32/ecx
24651 $type-tail:check-atom:
24652     # if t->is-atom? return 0
24653     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
24654     0f 85/jump-if-!= $type-tail:end/disp32
24655     # var tail = t->right
24656     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
24657     89/<- %ecx 0/r32/eax
24658 $type-tail:check-singleton:
24659     # if (tail->right == 0) return tail->left
24660     {
24661       81 7/subop/compare *(ecx+0xc) 0/imm32  # Type-tree-right
24662       75/jump-if-!= break/disp8
24663       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
24664       e9/jump $type-tail:end/disp32
24665     }
24666     # if tail->right->left is an array-capacity, return tail->left
24667     {
24668 $type-tail:check-array-capacity:
24669       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
24670       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
24671       75/jump-if-!= break/disp8
24672 $type-tail:check-array-capacity-1:
24673       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
24674       3d/compare-eax-and 0/imm32
24675       74/jump-if-= break/disp8
24676 $type-tail:check-array-capacity-2:
24677       (is-simple-mu-type? %eax 9)  # array-capacity => eax
24678       3d/compare-eax-and 0/imm32/false
24679       74/jump-if-= break/disp8
24680 $type-tail:array-capacity:
24681       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
24682       eb/jump $type-tail:end/disp8
24683     }
24684 $type-tail:check-compound-left:
24685     # if !tail->left->is-atom? return tail->left
24686     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
24687     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
24688     74/jump-if-= $type-tail:end/disp8
24689 $type-tail:return-tail:
24690     # return tail
24691     89/<- %eax 1/r32/ecx
24692 $type-tail:end:
24693     # . restore registers
24694     59/pop-to-ecx
24695     # . epilogue
24696     89/<- %esp 5/r32/ebp
24697     5d/pop-to-ebp
24698     c3/return
24699 
24700 type-equal?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
24701     # . prologue
24702     55/push-ebp
24703     89/<- %ebp 4/r32/esp
24704     # . save registers
24705     51/push-ecx
24706     52/push-edx
24707     53/push-ebx
24708     # ecx = a
24709     8b/-> *(ebp+8) 1/r32/ecx
24710     # edx = b
24711     8b/-> *(ebp+0xc) 2/r32/edx
24712 $type-equal?:compare-addr:
24713     # if (a == b) return true
24714     8b/-> %ecx 0/r32/eax  # Var-type
24715     39/compare %edx 0/r32/eax  # Var-type
24716     b8/copy-to-eax 1/imm32/true
24717     0f 84/jump-if-= $type-equal?:end/disp32
24718 $type-equal?:compare-null-a:
24719     # if (a == 0) return false
24720     b8/copy-to-eax 0/imm32/false
24721     81 7/subop/compare %ecx 0/imm32
24722     0f 84/jump-if-= $type-equal?:end/disp32
24723 $type-equal?:compare-null-b:
24724     # if (b == 0) return false
24725     81 7/subop/compare %edx 0/imm32
24726     0f 84/jump-if-= $type-equal?:end/disp32
24727 $type-equal?:compare-atom-state:
24728     # if (a->is-atom? != b->is-atom?) return false
24729     8b/-> *ecx 3/r32/ebx  # Type-tree-is-atom
24730     39/compare *edx 3/r32/ebx  # Type-tree-is-atom
24731     b8/copy-to-eax 0/imm32/false
24732     0f 85/jump-if-!= $type-equal?:end/disp32
24733     # if a->is-atom? return (a->value == b->value)
24734     {
24735 $type-equal?:check-atom:
24736       81 7/subop/compare %ebx 0/imm32/false
24737       74/jump-if-= break/disp8
24738 $type-equal?:is-atom:
24739       8b/-> *(ecx+4) 0/r32/eax  # Type-tree-value
24740       39/compare *(edx+4) 0/r32/eax  # Type-tree-value
24741       0f 94/set-if-= %al
24742       81 4/subop/and %eax 0xff/imm32
24743       e9/jump $type-equal?:end/disp32
24744     }
24745 $type-equal?:check-left:
24746     # if (!type-equal?(a->left, b->left)) return false
24747     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
24748     89/<- %ebx 0/r32/eax
24749     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
24750     (type-equal? %eax %ebx)  # => eax
24751     3d/compare-eax-and 0/imm32/false
24752     74/jump-if-= $type-equal?:end/disp8
24753 $type-equal?:check-right:
24754     # return type-equal?(a->right, b->right)
24755     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
24756     89/<- %ebx 0/r32/eax
24757     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
24758     (type-equal? %eax %ebx)  # => eax
24759 $type-equal?:end:
24760     # . restore registers
24761     5b/pop-to-ebx
24762     5a/pop-to-edx
24763     59/pop-to-ecx
24764     # . epilogue
24765     89/<- %esp 5/r32/ebp
24766     5d/pop-to-ebp
24767     c3/return
24768 
24769 #######################################################
24770 # Code-generation
24771 #######################################################
24772 
24773 == data
24774 
24775 # Global state added to each var record when performing code-generation.
24776 Curr-local-stack-offset:  # (addr int)
24777     0/imm32
24778 
24779 == code
24780 
24781 emit-subx:  # out: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
24782     # . prologue
24783     55/push-ebp
24784     89/<- %ebp 4/r32/esp
24785     # . save registers
24786     50/push-eax
24787     # var curr/eax: (addr function) = *Program->functions
24788     (lookup *_Program-functions *_Program-functions->payload)  # => eax
24789     {
24790       # if (curr == null) break
24791       3d/compare-eax-and 0/imm32
24792       0f 84/jump-if-= break/disp32
24793       (emit-subx-function *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10))
24794       # curr = lookup(curr->next)
24795       (lookup *(eax+0x20) *(eax+0x24))  # Function-next Function-next => eax
24796       e9/jump loop/disp32
24797     }
24798 $emit-subx:end:
24799     # . restore registers
24800     58/pop-to-eax
24801     # . epilogue
24802     89/<- %esp 5/r32/ebp
24803     5d/pop-to-ebp
24804     c3/return
24805 
24806 emit-subx-function:  # out: (addr buffered-file), f: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
24807     # . prologue
24808     55/push-ebp
24809     89/<- %ebp 4/r32/esp
24810     # some preprocessing
24811     (populate-mu-type-offsets-in-inouts *(ebp+0xc))
24812     # . save registers
24813     50/push-eax
24814     51/push-ecx
24815     52/push-edx
24816     # initialize some global state
24817     c7 0/subop/copy *Curr-block-depth 1/imm32  # Important: keep this in sync with the parse phase
24818     c7 0/subop/copy *Curr-local-stack-offset 0/imm32
24819     # ecx = f
24820     8b/-> *(ebp+0xc) 1/r32/ecx
24821     # var vars/edx: (stack (addr var) 256)
24822     81 5/subop/subtract %esp 0xc00/imm32
24823     68/push 0xc00/imm32/size
24824     68/push 0/imm32/top
24825     89/<- %edx 4/r32/esp
24826     # var name/eax: (addr array byte) = lookup(f->name)
24827     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
24828     #
24829     (write-buffered *(ebp+8) %eax)
24830     (write-buffered *(ebp+8) ":\n")
24831     (emit-subx-prologue *(ebp+8))
24832     # var body/eax: (addr block) = lookup(f->body)
24833     (lookup *(ecx+0x18) *(ecx+0x1c))  # Function-body Function-body => eax
24834     #
24835     (emit-subx-block *(ebp+8) %eax %edx *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
24836     (emit-subx-epilogue *(ebp+8))
24837     # TODO: validate that *Curr-block-depth and *Curr-local-stack-offset have
24838     # been cleaned up
24839 $emit-subx-function:end:
24840     # . reclaim locals
24841     81 0/subop/add %esp 0xc08/imm32
24842     # . restore registers
24843     5a/pop-to-edx
24844     59/pop-to-ecx
24845     58/pop-to-eax
24846     # . epilogue
24847     89/<- %esp 5/r32/ebp
24848     5d/pop-to-ebp
24849     c3/return
24850 
24851 populate-mu-type-offsets-in-inouts:  # f: (addr function)
24852     # . prologue
24853     55/push-ebp
24854     89/<- %ebp 4/r32/esp
24855     # . save registers
24856     50/push-eax
24857     51/push-ecx
24858     52/push-edx
24859     53/push-ebx
24860     57/push-edi
24861     # var next-offset/edx: int = 8
24862     ba/copy-to-edx 8/imm32
24863     # var curr/ecx: (addr list var) = lookup(f->inouts)
24864     8b/-> *(ebp+8) 1/r32/ecx
24865     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
24866     89/<- %ecx 0/r32/eax
24867     {
24868 $populate-mu-type-offsets-in-inouts:loop:
24869       81 7/subop/compare %ecx 0/imm32
24870       74/jump-if-= break/disp8
24871       # var v/ebx: (addr var) = lookup(curr->value)
24872       (lookup *ecx *(ecx+4))  # List-value List-value => eax
24873       89/<- %ebx 0/r32/eax
24874 #?       (lookup *ebx *(ebx+4))
24875 #?       (write-buffered Stderr "setting offset of fn inout ")
24876 #?       (write-buffered Stderr %eax)
24877 #?       (write-buffered Stderr "@")
24878 #?       (write-int32-hex-buffered Stderr %ebx)
24879 #?       (write-buffered Stderr " to ")
24880 #?       (write-int32-hex-buffered Stderr %edx)
24881 #?       (write-buffered Stderr Newline)
24882 #?       (flush Stderr)
24883       # v->offset = next-offset
24884       89/<- *(ebx+0x14) 2/r32/edx  # Var-offset
24885       # next-offset += size-of(v)
24886       (size-of %ebx)  # => eax
24887       01/add-to %edx 0/r32/eax
24888       # curr = lookup(curr->next)
24889       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
24890       89/<- %ecx 0/r32/eax
24891       #
24892       eb/jump loop/disp8
24893     }
24894 $populate-mu-type-offsets-in-inouts:end:
24895     # . restore registers
24896     5f/pop-to-edi
24897     5b/pop-to-ebx
24898     5a/pop-to-edx
24899     59/pop-to-ecx
24900     58/pop-to-eax
24901     # . epilogue
24902     89/<- %esp 5/r32/ebp
24903     5d/pop-to-ebp
24904     c3/return
24905 
24906 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)
24907     # . prologue
24908     55/push-ebp
24909     89/<- %ebp 4/r32/esp
24910     # . save registers
24911     50/push-eax
24912     51/push-ecx
24913     53/push-ebx
24914     56/push-esi
24915     # esi = stmts
24916     8b/-> *(ebp+0xc) 6/r32/esi
24917     #
24918     {
24919 $emit-subx-stmt-list:loop:
24920       81 7/subop/compare %esi 0/imm32
24921       0f 84/jump-if-= break/disp32
24922       # var curr-stmt/ecx: (addr stmt) = lookup(stmts->value)
24923       (lookup *esi *(esi+4))  # List-value List-value => eax
24924       89/<- %ecx 0/r32/eax
24925       {
24926 $emit-subx-stmt-list:check-for-block:
24927         81 7/subop/compare *ecx 0/imm32/block  # Stmt-tag
24928         75/jump-if-!= break/disp8
24929 $emit-subx-stmt-list:block:
24930         (emit-subx-block *(ebp+8) %ecx *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
24931       }
24932       {
24933 $emit-subx-stmt-list:check-for-stmt:
24934         81 7/subop/compare *ecx 1/imm32/stmt1  # Stmt-tag
24935         0f 85/jump-if-!= break/disp32
24936 $emit-subx-stmt-list:stmt1:
24937         {
24938           (is-mu-branch? %ecx)  # => eax
24939           3d/compare-eax-and 0/imm32/false
24940           0f 84/jump-if-= break/disp32
24941 $emit-subx-stmt-list:branch-stmt:
24942 +-- 25 lines: # unconditional return -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
24967 +-- 27 lines: # unconditional loops --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
24994 +-- 16 lines: # unconditional breaks -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
25010 +-- 38 lines: # simple conditional branches without a target -------------------------------------------------------------------------------------------------------------------------------------------------------
25048 +-- 19 lines: # conditional branches with an explicit target -------------------------------------------------------------------------------------------------------------------------------------------------------
25067         }
25068 $emit-subx-stmt-list:1-to-1:
25069         (emit-subx-stmt *(ebp+8) %ecx Primitives *(ebp+0x18) *(ebp+0x1c))
25070         e9/jump $emit-subx-stmt-list:continue/disp32
25071       }
25072       {
25073 $emit-subx-stmt-list:check-for-var-def:
25074         81 7/subop/compare *ecx 2/imm32/var-def  # Stmt-tag
25075         75/jump-if-!= break/disp8
25076 $emit-subx-stmt-list:var-def:
25077         (emit-subx-var-def *(ebp+8) %ecx)
25078         (push *(ebp+0x10) *(ecx+4))  # Vardef-var
25079         (push *(ebp+0x10) *(ecx+8))  # Vardef-var
25080         (push *(ebp+0x10) 0)  # Live-var-register-spilled = 0 for vars on the stack
25081         #
25082         eb/jump $emit-subx-stmt-list:continue/disp8
25083       }
25084       {
25085 $emit-subx-stmt-list:check-for-reg-var-def:
25086         81 7/subop/compare *ecx 3/imm32/reg-var-def  # Stmt-tag
25087         0f 85/jump-if-!= break/disp32
25088 $emit-subx-stmt-list:reg-var-def:
25089         # TODO: ensure that there's exactly one output
25090         (push-output-and-maybe-emit-spill *(ebp+8) %ecx *(ebp+0x10) %esi *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
25091         # emit the instruction as usual
25092         (emit-subx-stmt *(ebp+8) %ecx Primitives *(ebp+0x18) *(ebp+0x1c))
25093         #
25094         eb/jump $emit-subx-stmt-list:continue/disp8
25095       }
25096 $emit-subx-stmt-list:continue:
25097       # TODO: raise an error on unrecognized Stmt-tag
25098       (lookup *(esi+8) *(esi+0xc))  # List-next List-next => eax
25099       89/<- %esi 0/r32/eax
25100       e9/jump loop/disp32
25101     }
25102 $emit-subx-stmt-list:emit-cleanup:
25103     (emit-cleanup-code-until-depth *(ebp+8) *(ebp+0x10) *Curr-block-depth)
25104 $emit-subx-stmt-list:clean-up:
25105     (clean-up-stack-offset-state *(ebp+0x10) *Curr-block-depth)
25106     (clean-up-blocks *(ebp+0x10) *Curr-block-depth *(ebp+0x14))
25107 $emit-subx-stmt-list:end:
25108     # . restore registers
25109     5e/pop-to-esi
25110     5b/pop-to-ebx
25111     59/pop-to-ecx
25112     58/pop-to-eax
25113     # . epilogue
25114     89/<- %esp 5/r32/ebp
25115     5d/pop-to-ebp
25116     c3/return
25117 
25118 # 'later-stmts' includes 'stmt', but will behave the same even without it; reg-var-def stmts are guaranteed not to write to function outputs.
25119 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)
25120     # . prologue
25121     55/push-ebp
25122     89/<- %ebp 4/r32/esp
25123     # . save registers
25124     50/push-eax
25125     51/push-ecx
25126     52/push-edx
25127     # ecx = stmt
25128     8b/-> *(ebp+0xc) 1/r32/ecx
25129     # var sv/eax: (addr stmt-var) = lookup(curr-stmt->outputs)
25130     (lookup *(ecx+0x14) *(ecx+0x18))  # Regvardef-outputs Regvardef-outputs => eax
25131     # TODO: assert !sv->is-deref?
25132     # var v/ecx: (addr var) = lookup(sv->value)
25133     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25134     89/<- %ecx 0/r32/eax
25135     # v->block-depth = *Curr-block-depth
25136     8b/-> *Curr-block-depth 0/r32/eax
25137     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
25138 #?     (write-buffered Stderr "var ")
25139 #?     (lookup *ecx *(ecx+4))
25140 #?     (write-buffered Stderr %eax)
25141 #?     (write-buffered Stderr " at depth ")
25142 #?     (write-int32-hex-buffered Stderr *(ecx+0x10))
25143 #?     (write-buffered Stderr Newline)
25144 #?     (flush Stderr)
25145     # ensure that v is in a register
25146     81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
25147     0f 84/jump-if-= $push-output-and-maybe-emit-spill:abort/disp32
25148     # var emit-spill?/edx: boolean = not-yet-spilled-this-block? && will-not-write-some-register?(fn)
25149     (not-yet-spilled-this-block? %ecx *(ebp+0x10))  # => eax
25150     89/<- %edx 0/r32/eax
25151     3d/compare-eax-and 0/imm32/false
25152     0f 84/jump-if-= $push-output-and-maybe-emit-spill:push/disp32
25153     (will-not-write-some-register? %ecx *(ebp+0x14) *(ebp+0x18))  # => eax
25154     89/<- %edx 0/r32/eax
25155     # check emit-spill?
25156     3d/compare-eax-and 0/imm32/false
25157     0f 84/jump-if-= $push-output-and-maybe-emit-spill:push/disp32
25158     # TODO: assert(size-of(output) == 4)
25159     # *Curr-local-stack-offset -= 4
25160     81 5/subop/subtract *Curr-local-stack-offset 4/imm32
25161     # emit spill
25162     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
25163     (emit-push-register *(ebp+8) %eax)
25164 $push-output-and-maybe-emit-spill:push:
25165     8b/-> *(ebp+0xc) 1/r32/ecx
25166     (lookup *(ecx+0x14) *(ecx+0x18))  # Regvardef-outputs Regvardef-outputs => eax
25167     # push(vars, {sv->value, emit-spill?})
25168     (push *(ebp+0x10) *eax)  # Stmt-var-value
25169     (push *(ebp+0x10) *(eax+4))  # Stmt-var-value
25170     (push *(ebp+0x10) %edx)
25171 $push-output-and-maybe-emit-spill:end:
25172     # . restore registers
25173     5a/pop-to-edx
25174     59/pop-to-ecx
25175     58/pop-to-eax
25176     # . epilogue
25177     89/<- %esp 5/r32/ebp
25178     5d/pop-to-ebp
25179     c3/return
25180 
25181 $push-output-and-maybe-emit-spill:abort:
25182     # error("var '" var->name "' initialized from an instruction must live in a register\n")
25183     (write-buffered *(ebp+0x1c) "var '")
25184     (write-buffered *(ebp+0x1c) *eax)  # Var-name
25185     (write-buffered *(ebp+0x1c) "' initialized from an instruction must live in a register\n")
25186     (flush *(ebp+0x1c))
25187     (stop *(ebp+0x20) 1)
25188     # never gets here
25189 
25190 emit-subx-cleanup-and-unconditional-nonlocal-branch:  # out: (addr buffered-file), stmt: (addr stmt1), vars: (addr stack live-var)
25191     # . prologue
25192     55/push-ebp
25193     89/<- %ebp 4/r32/esp
25194     # . save registers
25195     50/push-eax
25196     51/push-ecx
25197     # ecx = stmt
25198     8b/-> *(ebp+0xc) 1/r32/ecx
25199     # var target/eax: (addr array byte) = curr-stmt->inouts->value->name
25200     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25201     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25202     (lookup *eax *(eax+4))  # Var-name Var-name => eax
25203     # clean up until target block
25204     (emit-cleanup-code-until-target *(ebp+8) *(ebp+0x10) %eax)
25205     # emit jump to target block
25206     (emit-indent *(ebp+8) *Curr-block-depth)
25207     (write-buffered *(ebp+8) "e9/jump ")
25208     (write-buffered *(ebp+8) %eax)
25209     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
25210     (string-starts-with? %eax "break")
25211     3d/compare-eax-and 0/imm32/false
25212     {
25213       74/jump-if-= break/disp8
25214       (write-buffered *(ebp+8) ":break/disp32\n")
25215       eb/jump $emit-subx-cleanup-and-unconditional-nonlocal-branch:end/disp8
25216     }
25217     (write-buffered *(ebp+8) ":loop/disp32\n")
25218 $emit-subx-cleanup-and-unconditional-nonlocal-branch:end:
25219     # . restore registers
25220     59/pop-to-ecx
25221     58/pop-to-eax
25222     # . epilogue
25223     89/<- %esp 5/r32/ebp
25224     5d/pop-to-ebp
25225     c3/return
25226 
25227 emit-outputs:  # out: (addr buffered-file), return-stmt: (addr stmt1), fn: (addr function)
25228     # pseudocode:
25229     #   for every inout, output in return-stmt, fn->outputs
25230     #     if inout is a literal
25231     #       c7 0/subop/copy %output inout/imm32
25232     #     otherwise
25233     #       8b/-> inout %output
25234     #
25235     # . prologue
25236     55/push-ebp
25237     89/<- %ebp 4/r32/esp
25238     # . save registers
25239     50/push-eax
25240     51/push-ecx
25241     56/push-esi
25242     57/push-edi
25243     # var curr-inout/esi: (addr stmt-var) = return-stmt->inouts
25244     8b/-> *(ebp+0xc) 0/r32/eax
25245     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25246     89/<- %esi 0/r32/eax
25247     # var curr-output/edi: (addr list var) = fn->outputs
25248     8b/-> *(ebp+0x10) 0/r32/eax
25249     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
25250     89/<- %edi 0/r32/eax
25251     {
25252 $emit-outputs:loop:
25253       81 7/subop/compare %esi 0/imm32
25254       0f 84/jump-if-= break/disp32
25255       # emit copy to output register
25256       # var curr-var/ecx = lookup(curr-inout->value)
25257       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
25258       89/<- %ecx 0/r32/eax
25259       # if curr-var is a literal, emit copy of a literal to the output
25260       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
25261       (is-simple-mu-type? %eax 0)  # literal => eax
25262       {
25263         3d/compare-eax-and 0/imm32/false
25264         0f 84/jump-if-= break/disp32
25265         (emit-indent *(ebp+8) *Curr-block-depth)
25266         (write-buffered *(ebp+8) "c7 0/subop/copy %")
25267         (lookup *edi *(edi+4))  # List-value List-value => eax
25268         (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
25269         (write-buffered *(ebp+8) %eax)
25270         (write-buffered *(ebp+8) " ")
25271         (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
25272         (write-buffered *(ebp+8) %eax)
25273         (write-buffered *(ebp+8) "/imm32\n")
25274         e9/jump $emit-outputs:continue/disp32
25275       }
25276       # if the non-literal is a register starting with "x", emit a floating-point copy
25277       (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
25278       {
25279         3d/compare-eax-and 0/imm32
25280         0f 84/jump-if-= break/disp32
25281         8a/copy-byte *(eax+4) 0/r32/AL
25282         81 4/subop/and %eax 0xff/imm32
25283         3d/compare-eax-and 0x78/imm32/x
25284         0f 85/jump-if-!= break/disp32
25285         (emit-indent *(ebp+8) *Curr-block-depth)
25286         (write-buffered *(ebp+8) "f3 0f 10/->")
25287         (emit-subx-var-as-rm32 *(ebp+8) %esi)
25288         (write-buffered *(ebp+8) " ")
25289         (lookup *edi *(edi+4))  # List-value List-value => eax
25290         (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
25291         (get Mu-registers %eax 0xc "Mu-registers")  # => eax
25292         (write-int32-hex-buffered *(ebp+8) *eax)
25293         (write-buffered *(ebp+8) "/x32\n")
25294         e9/jump $emit-outputs:continue/disp32
25295       }
25296       # otherwise emit an integer copy
25297       (emit-indent *(ebp+8) *Curr-block-depth)
25298       (write-buffered *(ebp+8) "8b/->")
25299       (emit-subx-var-as-rm32 *(ebp+8) %esi)
25300       (write-buffered *(ebp+8) " ")
25301       (lookup *edi *(edi+4))  # List-value List-value => eax
25302       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
25303       (get Mu-registers %eax 0xc "Mu-registers")  # => eax
25304       (write-int32-hex-buffered *(ebp+8) *eax)
25305       (write-buffered *(ebp+8) "/r32\n")
25306 $emit-outputs:continue:
25307       # curr-inout = curr-inout->next
25308       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
25309       89/<- %esi 0/r32/eax
25310       # curr-output = curr-output->next
25311       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
25312       89/<- %edi 0/r32/eax
25313       #
25314       e9/jump loop/disp32
25315     }
25316 $emit-outputs:end:
25317     # . restore registers
25318     5f/pop-to-edi
25319     5e/pop-to-esi
25320     59/pop-to-ecx
25321     58/pop-to-eax
25322     # . epilogue
25323     89/<- %esp 5/r32/ebp
25324     5d/pop-to-ebp
25325     c3/return
25326 
25327 is-mu-branch?:  # stmt: (addr stmt1) -> result/eax: boolean
25328     # . prologue
25329     55/push-ebp
25330     89/<- %ebp 4/r32/esp
25331     # . save registers
25332     51/push-ecx
25333     # ecx = lookup(stmt->operation)
25334     8b/-> *(ebp+8) 1/r32/ecx
25335     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
25336     89/<- %ecx 0/r32/eax
25337     # if (stmt->operation starts with "loop") return true
25338     (string-starts-with? %ecx "loop")  # => eax
25339     3d/compare-eax-and 0/imm32/false
25340     75/jump-if-not-equal $is-mu-branch?:end/disp8
25341     # if (stmt->operation starts with "break") return true
25342     (string-starts-with? %ecx "break")  # => eax
25343     3d/compare-eax-and 0/imm32/false
25344     75/jump-if-not-equal $is-mu-branch?:end/disp8
25345     # otherwise return (stmt->operation starts with "return")
25346     (string-starts-with? %ecx "return")  # => eax
25347 $is-mu-branch?:end:
25348     # . restore registers
25349     59/pop-to-ecx
25350     # . epilogue
25351     89/<- %esp 5/r32/ebp
25352     5d/pop-to-ebp
25353     c3/return
25354 
25355 emit-reverse-break:  # out: (addr buffered-file), stmt: (addr stmt1)
25356     # . prologue
25357     55/push-ebp
25358     89/<- %ebp 4/r32/esp
25359     # . save registers
25360     50/push-eax
25361     # eax = stmt
25362     8b/-> *(ebp+0xc) 0/r32/eax
25363     #
25364     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
25365     (get Reverse-branch %eax 0x10 "reverse-branch: ")  # => eax: (addr handle array byte)
25366     (emit-indent *(ebp+8) *Curr-block-depth)
25367     (lookup *eax *(eax+4))  # => eax
25368     (write-buffered *(ebp+8) %eax)
25369     (write-buffered *(ebp+8) " break/disp32\n")
25370 $emit-reverse-break:end:
25371     # . restore registers
25372     58/pop-to-eax
25373     # . epilogue
25374     89/<- %esp 5/r32/ebp
25375     5d/pop-to-ebp
25376     c3/return
25377 
25378 == data
25379 
25380 # Table from Mu branch instructions to the reverse SubX opcodes for them.
25381 Reverse-branch:  # (table (handle array byte) (handle array byte))
25382   # a table is a stream
25383   0x1c0/imm32/write
25384   0/imm32/read
25385   0x1c0/imm32/size
25386   # data
25387   0x11/imm32/alloc-id   _string-break-if-=/imm32                0x11/imm32/alloc-id   _string_0f_85_jump_label/imm32
25388   0x11/imm32/alloc-id   _string-loop-if-=/imm32                 0x11/imm32/alloc-id   _string_0f_85_jump_label/imm32
25389   0x11/imm32/alloc-id   _string-break-if-!=/imm32               0x11/imm32/alloc-id   _string_0f_84_jump_label/imm32
25390   0x11/imm32/alloc-id   _string-loop-if-!=/imm32                0x11/imm32/alloc-id   _string_0f_84_jump_label/imm32
25391   0x11/imm32/alloc-id   _string-break-if-</imm32                0x11/imm32/alloc-id   _string_0f_8d_jump_label/imm32
25392   0x11/imm32/alloc-id   _string-loop-if-</imm32                 0x11/imm32/alloc-id   _string_0f_8d_jump_label/imm32
25393   0x11/imm32/alloc-id   _string-break-if->/imm32                0x11/imm32/alloc-id   _string_0f_8e_jump_label/imm32
25394   0x11/imm32/alloc-id   _string-loop-if->/imm32                 0x11/imm32/alloc-id   _string_0f_8e_jump_label/imm32
25395   0x11/imm32/alloc-id   _string-break-if-<=/imm32               0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
25396   0x11/imm32/alloc-id   _string-loop-if-<=/imm32                0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
25397   0x11/imm32/alloc-id   _string-break-if->=/imm32               0x11/imm32/alloc-id   _string_0f_8c_jump_label/imm32
25398   0x11/imm32/alloc-id   _string-loop-if->=/imm32                0x11/imm32/alloc-id   _string_0f_8c_jump_label/imm32
25399   0x11/imm32/alloc-id   _string-break-if-addr</imm32            0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
25400   0x11/imm32/alloc-id   _string-loop-if-addr</imm32             0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
25401   0x11/imm32/alloc-id   _string-break-if-addr>/imm32            0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
25402   0x11/imm32/alloc-id   _string-loop-if-addr>/imm32             0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
25403   0x11/imm32/alloc-id   _string-break-if-addr<=/imm32           0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
25404   0x11/imm32/alloc-id   _string-loop-if-addr<=/imm32            0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
25405   0x11/imm32/alloc-id   _string-break-if-addr>=/imm32           0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
25406   0x11/imm32/alloc-id   _string-loop-if-addr>=/imm32            0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
25407   0x11/imm32/alloc-id   _string-break-if-float</imm32           0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
25408   0x11/imm32/alloc-id   _string-loop-if-float</imm32            0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
25409   0x11/imm32/alloc-id   _string-break-if-float>/imm32           0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
25410   0x11/imm32/alloc-id   _string-loop-if-float>/imm32            0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
25411   0x11/imm32/alloc-id   _string-break-if-float<=/imm32          0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
25412   0x11/imm32/alloc-id   _string-loop-if-float<=/imm32           0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
25413   0x11/imm32/alloc-id   _string-break-if-float>=/imm32          0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
25414   0x11/imm32/alloc-id   _string-loop-if-float>=/imm32           0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
25415 
25416 == code
25417 
25418 emit-unconditional-jump-to-depth:  # out: (addr buffered-file), vars: (addr stack live-var), depth: int, label-suffix: (addr array byte)
25419     # . prologue
25420     55/push-ebp
25421     89/<- %ebp 4/r32/esp
25422     # . save registers
25423     50/push-eax
25424     51/push-ecx
25425     52/push-edx
25426     53/push-ebx
25427     56/push-esi
25428     # ecx = vars
25429     8b/-> *(ebp+0xc) 1/r32/ecx
25430     # var eax: int = vars->top
25431     8b/-> *ecx 0/r32/eax
25432     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
25433     8d/copy-address *(ecx+eax-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
25434     # var min/ecx: (addr handle var) = vars->data
25435     8d/copy-address *(ecx+8) 1/r32/ecx
25436     # edx = depth
25437     8b/-> *(ebp+0x10) 2/r32/edx
25438     {
25439 $emit-unconditional-jump-to-depth:loop:
25440       # if (curr < min) break
25441       39/compare %esi 1/r32/ecx
25442       0f 82/jump-if-addr< break/disp32
25443       # var v/ebx: (addr var) = lookup(*curr)
25444       (lookup *esi *(esi+4))  # => eax
25445       89/<- %ebx 0/r32/eax
25446       # if (v->block-depth < until-block-depth) break
25447       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
25448       0f 8c/jump-if-< break/disp32
25449       {
25450 $emit-unconditional-jump-to-depth:check:
25451         # if v->block-depth != until-block-depth, continue
25452         39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
25453         0f 85/jump-if-!= break/disp32
25454 $emit-unconditional-jump-to-depth:depth-found:
25455         # if v is not a literal, continue
25456         (size-of %ebx)  # => eax
25457         3d/compare-eax-and 0/imm32
25458         0f 85/jump-if-!= break/disp32
25459 $emit-unconditional-jump-to-depth:label-found:
25460         # emit unconditional jump, then return
25461         (emit-indent *(ebp+8) *Curr-block-depth)
25462         (write-buffered *(ebp+8) "e9/jump ")
25463         (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
25464         (write-buffered *(ebp+8) %eax)
25465         (write-buffered *(ebp+8) ":")
25466         (write-buffered *(ebp+8) *(ebp+0x14))
25467         (write-buffered *(ebp+8) "/disp32\n")
25468         eb/jump $emit-unconditional-jump-to-depth:end/disp8
25469       }
25470       # curr -= 12
25471       81 5/subop/subtract %esi 0xc/imm32
25472       e9/jump loop/disp32
25473     }
25474     # TODO: error if no label at 'depth' was found
25475 $emit-unconditional-jump-to-depth:end:
25476     # . restore registers
25477     5e/pop-to-esi
25478     5b/pop-to-ebx
25479     5a/pop-to-edx
25480     59/pop-to-ecx
25481     58/pop-to-eax
25482     # . epilogue
25483     89/<- %esp 5/r32/ebp
25484     5d/pop-to-ebp
25485     c3/return
25486 
25487 # emit clean-up code for 'vars' until some block depth
25488 # doesn't actually modify 'vars' so we need traverse manually inside the stack
25489 emit-cleanup-code-until-depth:  # out: (addr buffered-file), vars: (addr stack live-var), until-block-depth: int
25490     # . prologue
25491     55/push-ebp
25492     89/<- %ebp 4/r32/esp
25493     # . save registers
25494     50/push-eax
25495     51/push-ecx
25496     52/push-edx
25497     53/push-ebx
25498     56/push-esi
25499 #?     (write-buffered Stderr "--- cleanup\n")
25500 #?     (flush Stderr)
25501     # ecx = vars
25502     8b/-> *(ebp+0xc) 1/r32/ecx
25503     # var esi: int = vars->top
25504     8b/-> *ecx 6/r32/esi
25505     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
25506     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
25507     # var min/ecx: (addr handle var) = vars->data
25508     81 0/subop/add %ecx 8/imm32
25509     # edx = until-block-depth
25510     8b/-> *(ebp+0x10) 2/r32/edx
25511     {
25512 $emit-cleanup-code-until-depth:loop:
25513       # if (curr < min) break
25514       39/compare %esi 1/r32/ecx
25515       0f 82/jump-if-addr< break/disp32
25516       # var v/ebx: (addr var) = lookup(*curr)
25517       (lookup *esi *(esi+4))  # => eax
25518       89/<- %ebx 0/r32/eax
25519 #?       (lookup *ebx *(ebx+4))  # Var-name
25520 #?       (write-buffered Stderr "var ")
25521 #?       (write-buffered Stderr %eax)
25522 #?       (write-buffered Stderr Newline)
25523 #?       (flush Stderr)
25524       # if (v->block-depth < until-block-depth) break
25525       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
25526       0f 8c/jump-if-< break/disp32
25527       # if v is in a register
25528       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
25529       {
25530         0f 84/jump-if-= break/disp32
25531         {
25532 $emit-cleanup-code-until-depth:check-for-previous-spill:
25533           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
25534           3d/compare-eax-and 0/imm32/false
25535           74/jump-if-= break/disp8
25536 $emit-cleanup-code-until-depth:reclaim-var-in-register:
25537           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
25538           (emit-pop-register *(ebp+8) %eax)
25539         }
25540         eb/jump $emit-cleanup-code-until-depth:continue/disp8
25541       }
25542       # otherwise v is on the stack
25543       {
25544         75/jump-if-!= break/disp8
25545 $emit-cleanup-code-until-depth:var-on-stack:
25546         (size-of %ebx)  # => eax
25547         # don't emit code for labels
25548         3d/compare-eax-and 0/imm32
25549         74/jump-if-= break/disp8
25550 $emit-cleanup-code-until-depth:reclaim-var-on-stack:
25551         (emit-indent *(ebp+8) *Curr-block-depth)
25552         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
25553         (write-int32-hex-buffered *(ebp+8) %eax)
25554         (write-buffered *(ebp+8) "/imm32\n")
25555       }
25556 $emit-cleanup-code-until-depth:continue:
25557       # curr -= 12
25558       81 5/subop/subtract %esi 0xc/imm32
25559       e9/jump loop/disp32
25560     }
25561 $emit-cleanup-code-until-depth:end:
25562     # . restore registers
25563     5e/pop-to-esi
25564     5b/pop-to-ebx
25565     5a/pop-to-edx
25566     59/pop-to-ecx
25567     58/pop-to-eax
25568     # . epilogue
25569     89/<- %esp 5/r32/ebp
25570     5d/pop-to-ebp
25571     c3/return
25572 
25573 # emit clean-up code for 'vars' that don't conflict with output registers
25574 # doesn't actually modify 'vars' so we need traverse manually inside the stack
25575 emit-cleanup-code-for-non-outputs:  # out: (addr buffered-file), vars: (addr stack live-var), fn: (addr function)
25576     # . prologue
25577     55/push-ebp
25578     89/<- %ebp 4/r32/esp
25579     # . save registers
25580     50/push-eax
25581     51/push-ecx
25582     52/push-edx
25583     53/push-ebx
25584     56/push-esi
25585     57/push-edi
25586     # ecx = vars
25587     8b/-> *(ebp+0xc) 1/r32/ecx
25588     # var esi: int = vars->top
25589     8b/-> *ecx 6/r32/esi
25590     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
25591     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
25592     # var min/ecx: (addr handle var) = vars->data
25593     81 0/subop/add %ecx 8/imm32
25594     {
25595 $emit-cleanup-code-for-non-outputs:loop:
25596       # if (curr < min) break
25597       39/compare %esi 1/r32/ecx
25598       0f 82/jump-if-addr< break/disp32
25599       # var v/ebx: (addr var) = lookup(*curr)
25600       (lookup *esi *(esi+4))  # => eax
25601       89/<- %ebx 0/r32/eax
25602       # if v is in a register
25603       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
25604       {
25605         0f 84/jump-if-= break/disp32
25606         {
25607 $emit-cleanup-code-for-non-outputs:check-for-previous-spill:
25608           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
25609           3d/compare-eax-and 0/imm32/false
25610           0f 84/jump-if-= break/disp32
25611 $emit-cleanup-code-for-non-outputs:reclaim-var-in-register:
25612           # var reg/edi: (addr array name) = v->register
25613           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
25614           89/<- %edi 0/r32/eax
25615           # if reg is not in function outputs, emit a pop
25616           (reg-in-function-outputs? *(ebp+0x10) %edi)  # => eax
25617           3d/compare-eax-and 0/imm32/false
25618           {
25619             75/jump-if-!= break/disp8
25620             (emit-pop-register *(ebp+8) %edi)
25621             eb/jump $emit-cleanup-code-for-non-outputs:reclaim-var-in-register-done/disp8
25622           }
25623           # otherwise just drop it from the stack
25624           (emit-indent *(ebp+8) *Curr-block-depth)
25625           (write-buffered *(ebp+8) "81 0/subop/add %esp 4/imm32\n")
25626         }
25627 $emit-cleanup-code-for-non-outputs:reclaim-var-in-register-done:
25628         eb/jump $emit-cleanup-code-for-non-outputs:continue/disp8
25629       }
25630       # otherwise v is on the stack
25631       {
25632         75/jump-if-!= break/disp8
25633 $emit-cleanup-code-for-non-outputs:var-on-stack:
25634         (size-of %ebx)  # => eax
25635         # don't emit code for labels
25636         3d/compare-eax-and 0/imm32
25637         74/jump-if-= break/disp8
25638 $emit-cleanup-code-for-non-outputs:reclaim-var-on-stack:
25639         (emit-indent *(ebp+8) *Curr-block-depth)
25640         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
25641         (write-int32-hex-buffered *(ebp+8) %eax)
25642         (write-buffered *(ebp+8) "/imm32\n")
25643       }
25644 $emit-cleanup-code-for-non-outputs:continue:
25645       # curr -= 12
25646       81 5/subop/subtract %esi 0xc/imm32
25647       e9/jump loop/disp32
25648     }
25649 $emit-cleanup-code-for-non-outputs:end:
25650     # . restore registers
25651     5f/pop-to-edi
25652     5e/pop-to-esi
25653     5b/pop-to-ebx
25654     5a/pop-to-edx
25655     59/pop-to-ecx
25656     58/pop-to-eax
25657     # . epilogue
25658     89/<- %esp 5/r32/ebp
25659     5d/pop-to-ebp
25660     c3/return
25661 
25662 emit-push-register:  # out: (addr buffered-file), reg: (addr array byte)
25663     # . prologue
25664     55/push-ebp
25665     89/<- %ebp 4/r32/esp
25666     # eax = reg
25667     8b/-> *(ebp+0xc) 0/r32/eax
25668     # var prefix/eax: byte = reg->data[0]
25669     8a/copy-byte *(eax+4) 0/r32/AL
25670     81 4/subop/and %eax 0xff/imm32
25671     # if (prefix == 'x') push xmm register
25672     {
25673       3d/compare-eax-and 0x78/imm32/x
25674       0f 85/jump-if-!= break/disp32
25675       # TODO validate register
25676       (emit-indent *(ebp+8) *Curr-block-depth)
25677       (write-buffered *(ebp+8) "81 5/subop/subtract %esp 4/imm32\n")
25678       (emit-indent *(ebp+8) *Curr-block-depth)
25679       (write-buffered *(ebp+8) "f3 0f 11/<- *esp ")
25680       # var prefix/eax: byte = reg->data[3]
25681       8b/-> *(ebp+0xc) 0/r32/eax
25682       8a/copy-byte *(eax+7) 0/r32/AL
25683       81 4/subop/and %eax 0xff/imm32
25684       (write-byte-buffered *(ebp+8) %eax)
25685       (write-buffered *(ebp+8) "/x32\n")
25686       e9/jump $emit-push-register:end/disp32
25687     }
25688     # otherwise push gp register
25689     (emit-indent *(ebp+8) *Curr-block-depth)
25690     (write-buffered *(ebp+8) "ff 6/subop/push %")
25691     (write-buffered *(ebp+8) *(ebp+0xc))
25692     (write-buffered *(ebp+8) Newline)
25693 $emit-push-register:end:
25694     # . epilogue
25695     89/<- %esp 5/r32/ebp
25696     5d/pop-to-ebp
25697     c3/return
25698 
25699 emit-pop-register:  # out: (addr buffered-file), reg: (addr array byte)
25700     # . prologue
25701     55/push-ebp
25702     89/<- %ebp 4/r32/esp
25703     # . save registers
25704     50/push-eax
25705     # eax = reg
25706     8b/-> *(ebp+0xc) 0/r32/eax
25707     # var prefix/eax: byte = reg->data[0]
25708     8a/copy-byte *(eax+4) 0/r32/AL
25709     81 4/subop/and %eax 0xff/imm32
25710     # if (prefix == 'x') pop to xmm register
25711     {
25712       3d/compare-eax-and 0x78/imm32/x
25713       0f 85/jump-if-!= break/disp32
25714       # TODO validate register
25715       (emit-indent *(ebp+8) *Curr-block-depth)
25716       (write-buffered *(ebp+8) "f3 0f 10/-> *esp ")
25717       # var prefix/eax: byte = reg->data[3]
25718       8b/-> *(ebp+0xc) 0/r32/eax
25719       8a/copy-byte *(eax+7) 0/r32/AL
25720       81 4/subop/and %eax 0xff/imm32
25721       (write-byte-buffered *(ebp+8) %eax)
25722       (write-buffered *(ebp+8) "/x32\n")
25723       (emit-indent *(ebp+8) *Curr-block-depth)
25724       (write-buffered *(ebp+8) "81 0/subop/add %esp 4/imm32\n")
25725       e9/jump $emit-pop-register:end/disp32
25726     }
25727     # otherwise pop to gp register
25728     (emit-indent *(ebp+8) *Curr-block-depth)
25729     (write-buffered *(ebp+8) "8f 0/subop/pop %")
25730     (write-buffered *(ebp+8) *(ebp+0xc))
25731     (write-buffered *(ebp+8) Newline)
25732 $emit-pop-register:end:
25733     # . restore registers
25734     58/pop-to-eax
25735     # . epilogue
25736     89/<- %esp 5/r32/ebp
25737     5d/pop-to-ebp
25738     c3/return
25739 
25740 # emit clean-up code for 'vars' until a given label is encountered
25741 # doesn't actually modify 'vars' so we need traverse manually inside the stack
25742 emit-cleanup-code-until-target:  # out: (addr buffered-file), vars: (addr stack live-var), until-block-label: (addr array byte)
25743     # . prologue
25744     55/push-ebp
25745     89/<- %ebp 4/r32/esp
25746     # . save registers
25747     50/push-eax
25748     51/push-ecx
25749     52/push-edx
25750     53/push-ebx
25751     # ecx = vars
25752     8b/-> *(ebp+0xc) 1/r32/ecx
25753     # var eax: int = vars->top
25754     8b/-> *ecx 0/r32/eax
25755     # var curr/edx: (addr handle var) = &vars->data[vars->top - 12]
25756     8d/copy-address *(ecx+eax-4) 2/r32/edx  # vars + 8 + vars->top - 12/Live-var-size
25757     # var min/ecx: (addr handle var) = vars->data
25758     81 0/subop/add %ecx 8/imm32
25759     {
25760 $emit-cleanup-code-until-target:loop:
25761       # if (curr < min) break
25762       39/compare %edx 1/r32/ecx
25763       0f 82/jump-if-addr< break/disp32
25764       # var v/ebx: (handle var) = lookup(*curr)
25765       (lookup *edx *(edx+4))  # => eax
25766       89/<- %ebx 0/r32/eax
25767       # if (v->name == until-block-label) break
25768       (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
25769       (string-equal? %eax *(ebp+0x10))  # => eax
25770       3d/compare-eax-and 0/imm32/false
25771       0f 85/jump-if-!= break/disp32
25772       # if v is in a register
25773       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
25774       {
25775         0f 84/jump-if-= break/disp32
25776         {
25777 $emit-cleanup-code-until-target:check-for-previous-spill:
25778           8b/-> *(edx+8) 0/r32/eax  # Live-var-register-spilled
25779           3d/compare-eax-and 0/imm32/false
25780           74/jump-if-= break/disp8
25781 $emit-cleanup-code-until-target:reclaim-var-in-register:
25782           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
25783           (emit-pop-register *(ebp+8) %eax)
25784         }
25785         eb/jump $emit-cleanup-code-until-target:continue/disp8
25786       }
25787       # otherwise v is on the stack
25788       {
25789         75/jump-if-!= break/disp8
25790 $emit-cleanup-code-until-target:reclaim-var-on-stack:
25791         (size-of %ebx)  # => eax
25792         # don't emit code for labels
25793         3d/compare-eax-and 0/imm32
25794         74/jump-if-= break/disp8
25795         #
25796         (emit-indent *(ebp+8) *Curr-block-depth)
25797         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
25798         (write-int32-hex-buffered *(ebp+8) %eax)
25799         (write-buffered *(ebp+8) "/imm32\n")
25800       }
25801 $emit-cleanup-code-until-target:continue:
25802       # curr -= 12
25803       81 5/subop/subtract %edx 0xc/imm32
25804       e9/jump loop/disp32
25805     }
25806 $emit-cleanup-code-until-target:end:
25807     # . restore registers
25808     5b/pop-to-ebx
25809     5a/pop-to-edx
25810     59/pop-to-ecx
25811     58/pop-to-eax
25812     # . epilogue
25813     89/<- %esp 5/r32/ebp
25814     5d/pop-to-ebp
25815     c3/return
25816 
25817 # update Curr-local-stack-offset assuming vars until some block depth are popped
25818 # doesn't actually modify 'vars', so we need traverse manually inside the stack
25819 clean-up-stack-offset-state:  # vars: (addr stack live-var), until-block-depth: int
25820     # . prologue
25821     55/push-ebp
25822     89/<- %ebp 4/r32/esp
25823     # . save registers
25824     50/push-eax
25825     51/push-ecx
25826     52/push-edx
25827     53/push-ebx
25828     56/push-esi
25829     # ecx = vars
25830     8b/-> *(ebp+8) 1/r32/ecx
25831     # var esi: int = vars->top
25832     8b/-> *ecx 6/r32/esi
25833     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
25834     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
25835     # var min/ecx: (addr handle var) = vars->data
25836     81 0/subop/add %ecx 8/imm32
25837     # edx = until-block-depth
25838     8b/-> *(ebp+0xc) 2/r32/edx
25839     {
25840 $clean-up-stack-offset-state:loop:
25841       # if (curr < min) break
25842       39/compare %esi 1/r32/ecx
25843       0f 82/jump-if-addr< break/disp32
25844       # var v/ebx: (addr var) = lookup(*curr)
25845       (lookup *esi *(esi+4))  # => eax
25846       89/<- %ebx 0/r32/eax
25847       # if (v->block-depth < until-block-depth) break
25848       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
25849       0f 8c/jump-if-< break/disp32
25850       # if v is in a register
25851       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
25852       {
25853         0f 84/jump-if-= break/disp32
25854         {
25855 $clean-up-stack-offset-state:check-for-previous-spill:
25856           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
25857           3d/compare-eax-and 0/imm32/false
25858           74/jump-if-= break/disp8
25859 $clean-up-stack-offset-state:reclaim-var-in-register:
25860           81 0/subop/add *Curr-local-stack-offset 4/imm32
25861         }
25862         eb/jump $clean-up-stack-offset-state:continue/disp8
25863       }
25864       # otherwise v is on the stack
25865       {
25866         75/jump-if-!= break/disp8
25867 $clean-up-stack-offset-state:var-on-stack:
25868         (size-of %ebx)  # => eax
25869         01/add-to *Curr-local-stack-offset 0/r32/eax
25870       }
25871 $clean-up-stack-offset-state:continue:
25872       # curr -= 12
25873       81 5/subop/subtract %esi 0xc/imm32
25874       e9/jump loop/disp32
25875     }
25876 $clean-up-stack-offset-state:end:
25877     # . restore registers
25878     5e/pop-to-esi
25879     5b/pop-to-ebx
25880     5a/pop-to-edx
25881     59/pop-to-ecx
25882     58/pop-to-eax
25883     # . epilogue
25884     89/<- %esp 5/r32/ebp
25885     5d/pop-to-ebp
25886     c3/return
25887 
25888 # Return true if there isn't a variable in 'vars' with the same block-depth
25889 # and register as 'v'.
25890 # 'v' is guaranteed not to be within 'vars'.
25891 not-yet-spilled-this-block?:  # v: (addr var), vars: (addr stack live-var) -> result/eax: boolean
25892     # . prologue
25893     55/push-ebp
25894     89/<- %ebp 4/r32/esp
25895     # . save registers
25896     51/push-ecx
25897     52/push-edx
25898     53/push-ebx
25899     56/push-esi
25900     57/push-edi
25901     # ecx = vars
25902     8b/-> *(ebp+0xc) 1/r32/ecx
25903     # var eax: int = vars->top
25904     8b/-> *ecx 0/r32/eax
25905     # var curr/edx: (addr handle var) = &vars->data[vars->top - 12]
25906     8d/copy-address *(ecx+eax-4) 2/r32/edx  # vars + 8 + vars->top - 12/Live-var-size
25907     # var min/ecx: (addr handle var) = vars->data
25908     8d/copy-address *(ecx+8) 1/r32/ecx
25909     # var depth/ebx: int = v->block-depth
25910     8b/-> *(ebp+8) 3/r32/ebx
25911     8b/-> *(ebx+0x10) 3/r32/ebx  # Var-block-depth
25912     # var needle/esi: (addr array byte) = v->register
25913     8b/-> *(ebp+8) 6/r32/esi
25914     (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
25915     89/<- %esi 0/r32/eax
25916     {
25917 $not-yet-spilled-this-block?:loop:
25918       # if (curr < min) break
25919       39/compare %edx 1/r32/ecx
25920       0f 82/jump-if-addr< break/disp32
25921       # var cand/edi: (addr var) = lookup(*curr)
25922       (lookup *edx *(edx+4))  # => eax
25923       89/<- %edi 0/r32/eax
25924       # if (cand->block-depth < depth) break
25925       39/compare *(edi+0x10) 3/r32/ebx  # Var-block-depth
25926       0f 8c/jump-if-< break/disp32
25927       # var cand-reg/edi: (array array byte) = cand->reg
25928       (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
25929       89/<- %edi 0/r32/eax
25930       # if (cand-reg == null) continue
25931       {
25932 $not-yet-spilled-this-block?:check-reg:
25933         81 7/subop/compare %edi 0/imm32
25934         0f 84/jump-if-= break/disp32
25935         # if (cand-reg == needle) return true
25936         (string-equal? %esi %edi)  # => eax
25937         3d/compare-eax-and 0/imm32/false
25938         74/jump-if-= break/disp8
25939 $not-yet-spilled-this-block?:return-false:
25940         b8/copy-to-eax 0/imm32/false
25941         eb/jump $not-yet-spilled-this-block?:end/disp8
25942       }
25943 $not-yet-spilled-this-block?:continue:
25944       # curr -= 12
25945       81 5/subop/subtract %edx 0xc/imm32
25946       e9/jump loop/disp32
25947     }
25948 $not-yet-spilled-this-block?:return-true:
25949     # return true
25950     b8/copy-to-eax 1/imm32/true
25951 $not-yet-spilled-this-block?:end:
25952     # . restore registers
25953     5f/pop-to-edi
25954     5e/pop-to-esi
25955     5b/pop-to-ebx
25956     5a/pop-to-edx
25957     59/pop-to-ecx
25958     # . epilogue
25959     89/<- %esp 5/r32/ebp
25960     5d/pop-to-ebp
25961     c3/return
25962 
25963 # could the register of 'v' ever be written to by one of the vars in fn-outputs?
25964 will-not-write-some-register?:  # v: (addr var), stmts: (addr list stmt), fn: (addr function) -> result/eax: boolean
25965     # . prologue
25966     55/push-ebp
25967     89/<- %ebp 4/r32/esp
25968     # eax = v
25969     8b/-> *(ebp+8) 0/r32/eax
25970     # var reg/eax: (addr array byte) = lookup(v->register)
25971     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
25972     # var target/eax: (addr var) = find-register(fn-outputs, reg)
25973     (find-register *(ebp+0x10) %eax)  # => eax
25974     # if (target == 0) return true
25975     {
25976       3d/compare-eax-and 0/imm32
25977       75/jump-if-!= break/disp8
25978       b8/copy-to-eax 1/imm32/true
25979       eb/jump $will-not-write-some-register?:end/disp8
25980     }
25981     # return !assigns-in-stmts?(stmts, target)
25982     (assigns-in-stmts? *(ebp+0xc) %eax)  # => eax
25983     3d/compare-eax-and 0/imm32/false
25984     # assume: true = 1, so no need to mask with 0x000000ff
25985     0f 94/set-if-= %al
25986 $will-not-write-some-register?:end:
25987     # . epilogue
25988     89/<- %esp 5/r32/ebp
25989     5d/pop-to-ebp
25990     c3/return
25991 
25992 # return fn output with matching register
25993 # always returns false if 'reg' is null
25994 find-register:  # fn: (addr function), reg: (addr array byte) -> result/eax: (addr var)
25995     # . prologue
25996     55/push-ebp
25997     89/<- %ebp 4/r32/esp
25998     # . save registers
25999     51/push-ecx
26000     # var curr/ecx: (addr list var) = lookup(fn->outputs)
26001     8b/-> *(ebp+8) 1/r32/ecx
26002     (lookup *(ecx+0x10) *(ecx+0x14))  # Function-outputs Function-outputs => eax
26003     89/<- %ecx 0/r32/eax
26004     {
26005 $find-register:loop:
26006       # if (curr == 0) break
26007       81 7/subop/compare %ecx 0/imm32
26008       74/jump-if-= break/disp8
26009       # eax = curr->value->register
26010       (lookup *ecx *(ecx+4))  # List-value List-value => eax
26011       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
26012       # if (eax == reg) return curr->value
26013 $find-register:compare:
26014       (string-equal? *(ebp+0xc) %eax)  # => eax
26015       {
26016         3d/compare-eax-and 0/imm32/false
26017         74/jump-if-= break/disp8
26018 $find-register:found:
26019         (lookup *ecx *(ecx+4))  # List-value List-value => eax
26020         eb/jump $find-register:end/disp8
26021       }
26022       # curr = lookup(curr->next)
26023       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
26024       89/<- %ecx 0/r32/eax
26025       #
26026       eb/jump loop/disp8
26027     }
26028 $find-register:end:
26029     # . restore registers
26030     59/pop-to-ecx
26031     # . epilogue
26032     89/<- %esp 5/r32/ebp
26033     5d/pop-to-ebp
26034     c3/return
26035 
26036 assigns-in-stmts?:  # stmts: (addr list stmt), v: (addr var) -> result/eax: boolean
26037     # . prologue
26038     55/push-ebp
26039     89/<- %ebp 4/r32/esp
26040     # . save registers
26041     51/push-ecx
26042     # var curr/ecx: (addr list stmt) = stmts
26043     8b/-> *(ebp+8) 1/r32/ecx
26044     {
26045       # if (curr == 0) break
26046       81 7/subop/compare %ecx 0/imm32
26047       74/jump-if-= break/disp8
26048       # if assigns-in-stmt?(curr->value, v) return true
26049       (lookup *ecx *(ecx+4))  # List-value List-value => eax
26050       (assigns-in-stmt? %eax *(ebp+0xc))  # => eax
26051       3d/compare-eax-and 0/imm32/false
26052       75/jump-if-!= break/disp8
26053       # curr = lookup(curr->next)
26054       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
26055       89/<- %ecx 0/r32/eax
26056       #
26057       eb/jump loop/disp8
26058     }
26059 $assigns-in-stmts?:end:
26060     # . restore registers
26061     59/pop-to-ecx
26062     # . epilogue
26063     89/<- %esp 5/r32/ebp
26064     5d/pop-to-ebp
26065     c3/return
26066 
26067 assigns-in-stmt?:  # stmt: (addr stmt), v: (addr var) -> result/eax: boolean
26068     # . prologue
26069     55/push-ebp
26070     89/<- %ebp 4/r32/esp
26071     # . save registers
26072     51/push-ecx
26073     # ecx = stmt
26074     8b/-> *(ebp+8) 1/r32/ecx
26075     # if stmt is a stmt1, return assigns-in-stmt-vars?(stmt->outputs, v)
26076     {
26077       81 7/subop/compare *ecx 1/imm32/stmt1  # Stmt-tag
26078       75/jump-if-!= break/disp8
26079       (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
26080       (assigns-in-stmt-vars? %eax *(ebp+0xc))  # => eax
26081       eb/jump $assigns-in-stmt?:end/disp8
26082     }
26083     # if stmt is a block, return assigns-in-stmts?(stmt->stmts, v)
26084     {
26085       81 7/subop/compare *ecx 0/imm32/block  # Stmt-tag
26086       75/jump-if-!= break/disp8
26087       (lookup *(ecx+4) *(ecx+8))  # Block-stmts Block-stmts => eax
26088       (assigns-in-stmts? %eax *(ebp+0xc))  # => eax
26089       eb/jump $assigns-in-stmt?:end/disp8
26090     }
26091     # otherwise return false
26092     b8/copy 0/imm32/false
26093 $assigns-in-stmt?:end:
26094     # . restore registers
26095     59/pop-to-ecx
26096     # . epilogue
26097     89/<- %esp 5/r32/ebp
26098     5d/pop-to-ebp
26099     c3/return
26100 
26101 assigns-in-stmt-vars?:  # stmt-var: (addr stmt-var), v: (addr var) -> result/eax: boolean
26102     # . prologue
26103     55/push-ebp
26104     89/<- %ebp 4/r32/esp
26105     # . save registers
26106     51/push-ecx
26107     # var curr/ecx: (addr stmt-var) = stmt-var
26108     8b/-> *(ebp+8) 1/r32/ecx
26109     {
26110       # if (curr == 0) break
26111       81 7/subop/compare %ecx 0/imm32
26112       74/jump-if-= break/disp8
26113       # eax = lookup(curr->value)
26114       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26115       # if (eax == v  &&  curr->is-deref? == false) return true
26116       {
26117         39/compare *(ebp+0xc) 0/r32/eax
26118         75/jump-if-!= break/disp8
26119         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
26120         75/jump-if-!= break/disp8
26121         b8/copy-to-eax 1/imm32/true
26122         eb/jump $assigns-in-stmt-vars?:end/disp8
26123       }
26124       # curr = lookup(curr->next)
26125       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
26126       89/<- %ecx 0/r32/eax
26127       #
26128       eb/jump loop/disp8
26129     }
26130 $assigns-in-stmt-vars?:end:
26131     # . restore registers
26132     59/pop-to-ecx
26133     # . epilogue
26134     89/<- %esp 5/r32/ebp
26135     5d/pop-to-ebp
26136     c3/return
26137 
26138 # is there a var before 'v' with the same block-depth and register on the 'vars' stack?
26139 # v is guaranteed to be within vars
26140 # 'start' is provided as an optimization, a pointer within vars
26141 # *start == v
26142 same-register-spilled-before?:  # v: (addr var), vars: (addr stack (handle var)), start: (addr var) -> result/eax: boolean
26143     # . prologue
26144     55/push-ebp
26145     89/<- %ebp 4/r32/esp
26146     # . save registers
26147     51/push-ecx
26148     52/push-edx
26149     53/push-ebx
26150     56/push-esi
26151     57/push-edi
26152     # ecx = v
26153     8b/-> *(ebp+8) 1/r32/ecx
26154     # var reg/edx: (addr array byte) = lookup(v->register)
26155     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
26156     89/<- %edx 0/r32/eax
26157     # var depth/ebx: int = v->block-depth
26158     8b/-> *(ecx+0x10) 3/r32/ebx  # Var-block-depth
26159     # var min/ecx: (addr handle var) = vars->data
26160     8b/-> *(ebp+0xc) 1/r32/ecx
26161     81 0/subop/add %ecx 8/imm32
26162     # TODO: check that start >= min and start < &vars->data[top]
26163     # TODO: check that *start == v
26164     # var curr/esi: (addr handle var) = start
26165     8b/-> *(ebp+0x10) 6/r32/esi
26166     # curr -= 8
26167     81 5/subop/subtract %esi 8/imm32
26168     {
26169 $same-register-spilled-before?:loop:
26170       # if (curr < min) break
26171       39/compare %esi 1/r32/ecx
26172       0f 82/jump-if-addr< break/disp32
26173       # var x/eax: (addr var) = lookup(*curr)
26174       (lookup *esi *(esi+4))  # => eax
26175       # if (x->block-depth < depth) break
26176       39/compare *(eax+0x10) 3/r32/ebx  # Var-block-depth
26177       0f 8c/jump-if-< break/disp32
26178       # if (x->register == 0) continue
26179       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
26180       74/jump-if-= $same-register-spilled-before?:continue/disp8
26181       # if (x->register == reg) return true
26182       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
26183       (string-equal? %eax %edx)  # => eax
26184       3d/compare-eax-and 0/imm32/false
26185       b8/copy-to-eax 1/imm32/true
26186       75/jump-if-!= $same-register-spilled-before?:end/disp8
26187 $same-register-spilled-before?:continue:
26188       # curr -= 8
26189       81 5/subop/subtract %esi 8/imm32
26190       e9/jump loop/disp32
26191     }
26192 $same-register-spilled-before?:false:
26193     b8/copy-to-eax 0/imm32/false
26194 $same-register-spilled-before?:end:
26195     # . restore registers
26196     5f/pop-to-edi
26197     5e/pop-to-esi
26198     5b/pop-to-ebx
26199     5a/pop-to-edx
26200     59/pop-to-ecx
26201     # . epilogue
26202     89/<- %esp 5/r32/ebp
26203     5d/pop-to-ebp
26204     c3/return
26205 
26206 # clean up global state for 'vars' until some block depth (inclusive)
26207 clean-up-blocks:  # vars: (addr stack live-var), until-block-depth: int, fn: (addr function)
26208     # . prologue
26209     55/push-ebp
26210     89/<- %ebp 4/r32/esp
26211     # . save registers
26212     50/push-eax
26213     51/push-ecx
26214     56/push-esi
26215     # esi = vars
26216     8b/-> *(ebp+8) 6/r32/esi
26217     # ecx = until-block-depth
26218     8b/-> *(ebp+0xc) 1/r32/ecx
26219     {
26220 $clean-up-blocks:reclaim-loop:
26221       # if (vars->top <= 0) break
26222       8b/-> *esi 0/r32/eax  # Stack-top
26223       3d/compare-eax-and 0/imm32
26224       0f 8e/jump-if-<= break/disp32
26225       # var v/eax: (addr var) = lookup(vars[vars->top-12])
26226       (lookup *(esi+eax-4) *(esi+eax))  # vars + 8 + vars->top - 12 => eax
26227       # if (v->block-depth < until-block-depth) break
26228       39/compare *(eax+0x10) 1/r32/ecx  # Var-block-depth
26229       0f 8c/jump-if-< break/disp32
26230       (pop %esi)  # => eax
26231       (pop %esi)  # => eax
26232       (pop %esi)  # => eax
26233       e9/jump loop/disp32
26234     }
26235 $clean-up-blocks:end:
26236     # . restore registers
26237     5e/pop-to-esi
26238     59/pop-to-ecx
26239     58/pop-to-eax
26240     # . epilogue
26241     89/<- %esp 5/r32/ebp
26242     5d/pop-to-ebp
26243     c3/return
26244 
26245 reg-in-function-outputs?:  # fn: (addr function), target: (addr array byte) -> result/eax: boolean
26246     # . prologue
26247     55/push-ebp
26248     89/<- %ebp 4/r32/esp
26249     # . save registers
26250     51/push-ecx
26251     # var curr/ecx: (addr list var) = lookup(fn->outputs)
26252     8b/-> *(ebp+8) 0/r32/eax
26253     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
26254     89/<- %ecx 0/r32/eax
26255     # while curr != null
26256     {
26257       81 7/subop/compare %ecx 0/imm32
26258       74/jump-if-= break/disp8
26259       # var v/eax: (addr var) = lookup(curr->value)
26260       (lookup *ecx *(ecx+4))  # List-value List-value => eax
26261       # var reg/eax: (addr array byte) = lookup(v->register)
26262       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
26263       # if (reg == target) return true
26264       (string-equal? %eax *(ebp+0xc))  # => eax
26265       3d/compare-eax-and 0/imm32/false
26266       75/jump-if-!= $reg-in-function-outputs?:end/disp8
26267       # curr = curr->next
26268       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
26269       89/<- %ecx 0/r32/eax
26270       #
26271       eb/jump loop/disp8
26272     }
26273     # return false
26274     b8/copy-to-eax 0/imm32
26275 $reg-in-function-outputs?:end:
26276     # . restore registers
26277     59/pop-to-ecx
26278     # . epilogue
26279     89/<- %esp 5/r32/ebp
26280     5d/pop-to-ebp
26281     c3/return
26282 
26283 emit-subx-var-def:  # out: (addr buffered-file), stmt: (addr stmt)
26284     # . prologue
26285     55/push-ebp
26286     89/<- %ebp 4/r32/esp
26287     # . save registers
26288     50/push-eax
26289     51/push-ecx
26290     52/push-edx
26291     # eax = stmt
26292     8b/-> *(ebp+0xc) 0/r32/eax
26293     # var v/ecx: (addr var)
26294     (lookup *(eax+4) *(eax+8))  # Vardef-var Vardef-var => eax
26295     89/<- %ecx 0/r32/eax
26296     # v->block-depth = *Curr-block-depth
26297     8b/-> *Curr-block-depth 0/r32/eax
26298     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
26299     # var n/edx: int = size-of(stmt->var)
26300     (size-of %ecx)  # => eax
26301     89/<- %edx 0/r32/eax
26302     # *Curr-local-stack-offset -= n
26303     29/subtract-from *Curr-local-stack-offset 2/r32/edx
26304     # v->offset = *Curr-local-stack-offset
26305     8b/-> *Curr-local-stack-offset 0/r32/eax
26306     89/<- *(ecx+0x14) 0/r32/eax  # Var-offset
26307     # if v is an array, do something special to initialize it
26308     {
26309       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
26310       (is-mu-array? %eax)  # => eax
26311       3d/compare-eax-and 0/imm32/false
26312       0f 84/jump-if-= break/disp32
26313       # var array-size-without-size/edx: int = n-4
26314       81 5/subop/subtract %edx 4/imm32
26315       #
26316       (emit-array-data-initialization *(ebp+8) %edx)
26317       e9/jump $emit-subx-var-def:end/disp32
26318     }
26319     # another special-case for initializing streams
26320     # a stream is an array with 2 extra pointers
26321     {
26322       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
26323       (is-mu-stream? %eax)  # => eax
26324       3d/compare-eax-and 0/imm32/false
26325       0f 84/jump-if-= break/disp32
26326       # var array-size-without-size/edx: int = n-12
26327       81 5/subop/subtract %edx 0xc/imm32
26328       (emit-array-data-initialization *(ebp+8) %edx)
26329       # emit read and write pointers
26330       (emit-indent *(ebp+8) *Curr-block-depth)
26331       (write-buffered *(ebp+8) "68/push 0/imm32\n")
26332       (emit-indent *(ebp+8) *Curr-block-depth)
26333       (write-buffered *(ebp+8) "68/push 0/imm32\n")
26334       #
26335       eb/jump $emit-subx-var-def:end/disp8
26336     }
26337     # while n > 0
26338     {
26339       81 7/subop/compare %edx 0/imm32
26340       7e/jump-if-<= break/disp8
26341       (emit-indent *(ebp+8) *Curr-block-depth)
26342       (write-buffered *(ebp+8) "68/push 0/imm32\n")
26343       # n -= 4
26344       81 5/subop/subtract %edx 4/imm32
26345       #
26346       eb/jump loop/disp8
26347     }
26348 $emit-subx-var-def:end:
26349     # . restore registers
26350     5a/pop-to-edx
26351     59/pop-to-ecx
26352     58/pop-to-eax
26353     # . epilogue
26354     89/<- %esp 5/r32/ebp
26355     5d/pop-to-ebp
26356     c3/return
26357 
26358 emit-array-data-initialization:  # out: (addr buffered-file), n: int
26359     # . prologue
26360     55/push-ebp
26361     89/<- %ebp 4/r32/esp
26362     #
26363     (emit-indent *(ebp+8) *Curr-block-depth)
26364     (write-buffered *(ebp+8) "(push-n-zero-bytes ")
26365     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
26366     (write-buffered *(ebp+8) ")\n")
26367     (emit-indent *(ebp+8) *Curr-block-depth)
26368     (write-buffered *(ebp+8) "68/push ")
26369     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
26370     (write-buffered *(ebp+8) "/imm32\n")
26371 $emit-array-data-initialization:end:
26372     # . epilogue
26373     89/<- %esp 5/r32/ebp
26374     5d/pop-to-ebp
26375     c3/return
26376 
26377 emit-subx-stmt:  # out: (addr buffered-file), stmt: (addr stmt), primitives: (addr primitive), err: (addr buffered-file), ed: (addr exit-descriptor)
26378     # . prologue
26379     55/push-ebp
26380     89/<- %ebp 4/r32/esp
26381     # . save registers
26382     50/push-eax
26383     51/push-ecx
26384     # - some special-case primitives that don't actually use the 'primitives' data structure
26385     # var op/ecx: (addr array byte) = lookup(stmt->operation)
26386     8b/-> *(ebp+0xc) 1/r32/ecx
26387     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
26388     89/<- %ecx 0/r32/eax
26389     # array size
26390     {
26391       # if (!string-equal?(stmt->operation, "length")) break
26392       (string-equal? %ecx "length")  # => eax
26393       3d/compare-eax-and 0/imm32
26394       0f 84/jump-if-= break/disp32
26395       (translate-mu-length-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
26396       e9/jump $emit-subx-stmt:end/disp32
26397     }
26398     # index into array
26399     {
26400       # if (!string-equal?(stmt->operation, "index")) break
26401       (string-equal? %ecx "index")  # => eax
26402       3d/compare-eax-and 0/imm32
26403       0f 84/jump-if-= break/disp32
26404       (translate-mu-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
26405       e9/jump $emit-subx-stmt:end/disp32
26406     }
26407     # compute-offset for index into array
26408     {
26409       # if (!string-equal?(stmt->operation, "compute-offset")) break
26410       (string-equal? %ecx "compute-offset")  # => eax
26411       3d/compare-eax-and 0/imm32
26412       0f 84/jump-if-= break/disp32
26413       (translate-mu-compute-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
26414       e9/jump $emit-subx-stmt:end/disp32
26415     }
26416     # get field from record
26417     {
26418       # if (!string-equal?(stmt->operation, "get")) break
26419       (string-equal? %ecx "get")  # => eax
26420       3d/compare-eax-and 0/imm32
26421       0f 84/jump-if-= break/disp32
26422       (translate-mu-get-stmt *(ebp+8) *(ebp+0xc))
26423       e9/jump $emit-subx-stmt:end/disp32
26424     }
26425     # allocate scalar
26426     {
26427       # if (!string-equal?(stmt->operation, "allocate")) break
26428       (string-equal? %ecx "allocate")  # => eax
26429       3d/compare-eax-and 0/imm32
26430       0f 84/jump-if-= break/disp32
26431       (translate-mu-allocate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
26432       e9/jump $emit-subx-stmt:end/disp32
26433     }
26434     # copy-object
26435     {
26436       # if (!string-equal?(stmt->operation, "copy-object")) break
26437       (string-equal? %ecx "copy-object")  # => eax
26438       3d/compare-eax-and 0/imm32
26439       0f 84/jump-if-= break/disp32
26440       (translate-mu-copy-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
26441       e9/jump $emit-subx-stmt:end/disp32
26442     }
26443     # clear-object
26444     {
26445       # if (!string-equal?(stmt->operation, "clear-object")) break
26446       (string-equal? %ecx "clear-object")  # => eax
26447       3d/compare-eax-and 0/imm32
26448       0f 84/jump-if-= break/disp32
26449       (translate-mu-clear-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
26450       e9/jump $emit-subx-stmt:end/disp32
26451     }
26452     # allocate array
26453     {
26454       # if (!string-equal?(stmt->operation, "populate")) break
26455       (string-equal? %ecx "populate")  # => eax
26456       3d/compare-eax-and 0/imm32
26457       0f 84/jump-if-= break/disp32
26458       (translate-mu-populate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
26459       e9/jump $emit-subx-stmt:end/disp32
26460     }
26461     # allocate stream
26462     {
26463       # if (!string-equal?(stmt->operation, "populate-stream")) break
26464       (string-equal? %ecx "populate-stream")  # => eax
26465       3d/compare-eax-and 0/imm32
26466       0f 84/jump-if-= break/disp32
26467       (translate-mu-populate-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
26468       e9/jump $emit-subx-stmt:end/disp32
26469     }
26470     # read from stream
26471     {
26472       # if (!string-equal?(stmt->operation, "read-from-stream")) break
26473       (string-equal? %ecx "read-from-stream")  # => eax
26474       3d/compare-eax-and 0/imm32
26475       0f 84/jump-if-= break/disp32
26476       (translate-mu-read-from-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
26477       e9/jump $emit-subx-stmt:end/disp32
26478     }
26479     # write to stream
26480     {
26481       # if (!string-equal?(stmt->operation, "write-to-stream")) break
26482       (string-equal? %ecx "write-to-stream")  # => eax
26483       3d/compare-eax-and 0/imm32
26484       0f 84/jump-if-= break/disp32
26485       (translate-mu-write-to-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
26486       e9/jump $emit-subx-stmt:end/disp32
26487     }
26488     # - if stmt matches a primitive, emit it
26489     {
26490 $emit-subx-stmt:check-for-primitive:
26491       # var curr/eax: (addr primitive)
26492       (find-matching-primitive *(ebp+0x10) *(ebp+0xc))  # primitives, stmt => eax
26493       3d/compare-eax-and 0/imm32
26494       74/jump-if-= break/disp8
26495 $emit-subx-stmt:primitive:
26496       (emit-subx-primitive *(ebp+8) *(ebp+0xc) %eax)  # out, stmt, curr
26497       e9/jump $emit-subx-stmt:end/disp32
26498     }
26499     # - otherwise emit a call
26500     # TODO: type-checking
26501 $emit-subx-stmt:call:
26502     (emit-call *(ebp+8) *(ebp+0xc))
26503 $emit-subx-stmt:end:
26504     # . restore registers
26505     59/pop-to-ecx
26506     58/pop-to-eax
26507     # . epilogue
26508     89/<- %esp 5/r32/ebp
26509     5d/pop-to-ebp
26510     c3/return
26511 
26512 translate-mu-length-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
26513     # . prologue
26514     55/push-ebp
26515     89/<- %ebp 4/r32/esp
26516     # . save registers
26517     50/push-eax
26518     51/push-ecx
26519     52/push-edx
26520     53/push-ebx
26521     56/push-esi
26522     # esi = stmt
26523     8b/-> *(ebp+0xc) 6/r32/esi
26524     # var base/ebx: (addr var) = stmt->inouts[0]->value
26525     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
26526     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
26527     89/<- %ebx 0/r32/eax
26528     # var elemsize/ecx: int = array-element-size(base)
26529     (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
26530     89/<- %ecx 0/r32/eax
26531     # var outreg/edx: (addr array byte) = stmt->outputs[0]->value->register
26532     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
26533     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
26534     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
26535     89/<- %edx 0/r32/eax
26536     # if elemsize == 1
26537     {
26538       81 7/subop/compare %ecx 1/imm32
26539       75/jump-if-!= break/disp8
26540 $translate-mu-length-stmt:size-1:
26541       (emit-save-size-to *(ebp+8) %ebx %edx)
26542       e9/jump $translate-mu-length-stmt:end/disp32
26543     }
26544     # if elemsize is a power of 2 less than 256
26545     {
26546       (power-of-2? %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
26547       3d/compare-eax-and 0/imm32/false
26548       74/jump-if-= break/disp8
26549       81 7/subop/compare %ecx 0xff/imm32
26550       7f/jump-if-> break/disp8
26551 $translate-mu-length-stmt:size-power-of-2:
26552       (emit-save-size-to *(ebp+8) %ebx %edx)
26553       (emit-divide-by-shift-right *(ebp+8) %edx %ecx)
26554       e9/jump $translate-mu-length-stmt:end/disp32
26555     }
26556     # otherwise, the complex case
26557     # . emit register spills
26558     {
26559 $translate-mu-length-stmt:complex:
26560       (string-equal? %edx "eax")  # => eax
26561       3d/compare-eax-and 0/imm32/false
26562       75/break-if-!= break/disp8
26563       (emit-indent *(ebp+8) *Curr-block-depth)
26564       (write-buffered *(ebp+8) "50/push-eax\n")
26565     }
26566     {
26567       (string-equal? %edx "ecx")  # => eax
26568       3d/compare-eax-and 0/imm32/false
26569       75/break-if-!= break/disp8
26570       (emit-indent *(ebp+8) *Curr-block-depth)
26571       (write-buffered *(ebp+8) "51/push-ecx\n")
26572     }
26573     {
26574       (string-equal? %edx "edx")  # => eax
26575       3d/compare-eax-and 0/imm32/false
26576       75/break-if-!= break/disp8
26577       (emit-indent *(ebp+8) *Curr-block-depth)
26578       (write-buffered *(ebp+8) "52/push-edx\n")
26579     }
26580     # .
26581     (emit-save-size-to *(ebp+8) %ebx "eax")
26582     (emit-indent *(ebp+8) *Curr-block-depth)
26583     (write-buffered *(ebp+8) "31/xor %edx 2/r32/edx\n")
26584     (emit-indent *(ebp+8) *Curr-block-depth)
26585     (write-buffered *(ebp+8) "b9/copy-to-ecx ")
26586     (write-int32-hex-buffered *(ebp+8) %ecx)
26587     (write-buffered *(ebp+8) "/imm32\n")
26588     (emit-indent *(ebp+8) *Curr-block-depth)
26589     (write-buffered *(ebp+8) "f7 7/subop/idiv-eax-edx-by %ecx\n")
26590     {
26591       (string-equal? %edx "eax")  # => eax
26592       3d/compare-eax-and 0/imm32/false
26593       75/break-if-!= break/disp8
26594       (emit-indent *(ebp+8) *Curr-block-depth)
26595       (write-buffered *(ebp+8) "89/<- %")
26596       (write-buffered *(ebp+8) %edx)
26597       (write-buffered *(ebp+8) " 0/r32/eax\n")
26598     }
26599     # . emit register restores
26600     {
26601       (string-equal? %edx "edx")  # => eax
26602       3d/compare-eax-and 0/imm32/false
26603       75/break-if-!= break/disp8
26604       (emit-indent *(ebp+8) *Curr-block-depth)
26605       (write-buffered *(ebp+8) "5a/pop-to-edx\n")
26606     }
26607     {
26608       (string-equal? %edx "ecx")  # => eax
26609       3d/compare-eax-and 0/imm32/false
26610       75/break-if-!= break/disp8
26611       (emit-indent *(ebp+8) *Curr-block-depth)
26612       (write-buffered *(ebp+8) "59/pop-to-ecx\n")
26613     }
26614     {
26615       (string-equal? %edx "eax")  # => eax
26616       3d/compare-eax-and 0/imm32/false
26617       75/break-if-!= break/disp8
26618       (emit-indent *(ebp+8) *Curr-block-depth)
26619       (write-buffered *(ebp+8) "58/pop-to-eax\n")
26620     }
26621 $translate-mu-length-stmt:end:
26622     # . restore registers
26623     5e/pop-to-esi
26624     5b/pop-to-ebx
26625     5a/pop-to-edx
26626     59/pop-to-ecx
26627     58/pop-to-eax
26628     # . epilogue
26629     89/<- %esp 5/r32/ebp
26630     5d/pop-to-ebp
26631     c3/return
26632 
26633 array-element-size:  # arr: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
26634     # . prologue
26635     55/push-ebp
26636     89/<- %ebp 4/r32/esp
26637     #
26638     (array-element-type-id *(ebp+8) *(ebp+0xc) *(ebp+0x10))  # => eax
26639     (size-of-type-id-as-array-element %eax)  # => eax
26640 $array-element-size:end:
26641     # . epilogue
26642     89/<- %esp 5/r32/ebp
26643     5d/pop-to-ebp
26644     c3/return
26645 
26646 array-element-type-id:  # v: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: type-id
26647     # precondition: n is positive
26648     # . prologue
26649     55/push-ebp
26650     89/<- %ebp 4/r32/esp
26651     #
26652     8b/-> *(ebp+8) 0/r32/eax
26653     # var t/eax: (addr type-tree)
26654     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
26655     # if t == 0 abort
26656     3d/compare-eax-with 0/imm32
26657     0f 84/jump-if-== $array-element-type-id:error0/disp32
26658     # if t->is-atom? abort
26659     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
26660     0f 85/jump-if-!= $array-element-type-id:error1/disp32
26661     # if (t->left == addr) t = t->right
26662     {
26663       50/push-eax
26664       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
26665       (is-simple-mu-type? %eax 2)  # addr => eax
26666       3d/compare-eax-with 0/imm32/false
26667       58/pop-to-eax
26668       74/jump-if-= break/disp8
26669 $array-element-type-id:skip-addr:
26670       (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
26671     }
26672     # if t == 0 abort
26673     3d/compare-eax-with 0/imm32
26674     0f 84/jump-if-= $array-element-type-id:error2/disp32
26675     # if t->is-atom? abort
26676     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
26677     0f 85/jump-if-!= $array-element-type-id:error2/disp32
26678     # if t->left != array abort
26679     {
26680       50/push-eax
26681       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
26682       (is-simple-mu-type? %eax 3)  # array => eax
26683       3d/compare-eax-with 0/imm32/false
26684       58/pop-to-eax
26685 $array-element-type-id:no-array:
26686       0f 84/jump-if-= $array-element-type-id:error2/disp32
26687     }
26688 $array-element-type-id:skip-array:
26689     # t = t->right
26690     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
26691     # if t == 0 abort
26692     3d/compare-eax-with 0/imm32
26693     0f 84/jump-if-= $array-element-type-id:error2/disp32
26694     # if t->is-atom? abort
26695     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
26696     0f 85/jump-if-!= $array-element-type-id:error2/disp32
26697     # t = t->left
26698     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
26699     # if (!t->is-atom?) t = t->left     # TODO: assumes array element size can be determined from just first word of array element type
26700     # if (t->is-atom == false) t = lookup(t->left)
26701     {
26702       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
26703       75/jump-if-!= break/disp8
26704       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
26705     }
26706     # return t->value
26707     8b/-> *(eax+4) 0/r32/eax  # Type-tree-value
26708 $array-element-type-id:end:
26709     # . epilogue
26710     89/<- %esp 5/r32/ebp
26711     5d/pop-to-ebp
26712     c3/return
26713 
26714 $array-element-type-id:error0:
26715     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
26716     50/push-eax
26717     8b/-> *(ebp+8) 0/r32/eax
26718     (lookup *eax *(eax+4))  # Var-name Var-name => eax
26719     (write-buffered *(ebp+0xc) %eax)
26720     58/pop-to-eax
26721     (write-buffered *(ebp+0xc) "' has no type\n")
26722     (flush *(ebp+0xc))
26723     (stop *(ebp+0x10) 1)
26724     # never gets here
26725 
26726 $array-element-type-id:error1:
26727     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
26728     50/push-eax
26729     8b/-> *(ebp+8) 0/r32/eax
26730     (lookup *eax *(eax+4))  # Var-name Var-name => eax
26731     (write-buffered *(ebp+0xc) %eax)
26732     58/pop-to-eax
26733     (write-buffered *(ebp+0xc) "' has atomic type ")
26734     (write-int32-hex-buffered *(ebp+0xc) *(eax+4))  # Type-tree-value
26735     (write-buffered *(ebp+0xc) Newline)
26736     (flush *(ebp+0xc))
26737     (stop *(ebp+0x10) 1)
26738     # never gets here
26739 
26740 $array-element-type-id:error2:
26741     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
26742     50/push-eax
26743     8b/-> *(ebp+8) 0/r32/eax
26744     (lookup *eax *(eax+4))  # Var-name Var-name => eax
26745     (write-buffered *(ebp+0xc) %eax)
26746     58/pop-to-eax
26747     (write-buffered *(ebp+0xc) "' has non-array type\n")
26748     (flush *(ebp+0xc))
26749     (stop *(ebp+0x10) 1)
26750     # never gets here
26751 
26752 size-of-type-id-as-array-element:  # t: type-id -> result/eax: int
26753     # . prologue
26754     55/push-ebp
26755     89/<- %ebp 4/r32/esp
26756     # eax = t
26757     8b/-> *(ebp+8) 0/r32/eax
26758     # if t is 'byte', size is 1
26759     3d/compare-eax-and 8/imm32/byte
26760     {
26761       75/jump-if-!= break/disp8
26762       b8/copy-to-eax 1/imm32
26763       eb/jump $size-of-type-id-as-array-element:end/disp8
26764     }
26765     # otherwise proceed as usual
26766     (size-of-type-id %eax)  # => eax
26767 $size-of-type-id-as-array-element:end:
26768     # . epilogue
26769     89/<- %esp 5/r32/ebp
26770     5d/pop-to-ebp
26771     c3/return
26772 
26773 emit-save-size-to:  # out: (addr buffered-file), base: (addr var), outreg: (addr array byte)
26774     # . prologue
26775     55/push-ebp
26776     89/<- %ebp 4/r32/esp
26777     # . save registers
26778     50/push-eax
26779     53/push-ebx
26780     # ebx = base
26781     8b/-> *(ebp+0xc) 3/r32/ebx
26782     (emit-indent *(ebp+8) *Curr-block-depth)
26783     (write-buffered *(ebp+8) "8b/-> *")
26784     # if base is an (addr array ...) in a register
26785     {
26786       81 7/subop/compare *(ebx+0x18)) 0/imm32  # Var-register
26787       74/jump-if-= break/disp8
26788 $emit-save-size-to:emit-base-from-register:
26789       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
26790       (write-buffered *(ebp+8) %eax)
26791       eb/jump $emit-save-size-to:emit-output/disp8
26792     }
26793     # otherwise if base is an (array ...) on the stack
26794     {
26795       81 7/subop/compare *(ebx+0x14)) 0/imm32  # Var-offset
26796       74/jump-if-= break/disp8
26797 $emit-save-size-to:emit-base-from-stack:
26798       (write-buffered *(ebp+8) "(ebp+")
26799       (write-int32-hex-buffered *(ebp+8) *(ebx+0x14))  # Var-offset
26800       (write-buffered *(ebp+8) ")")
26801     }
26802 $emit-save-size-to:emit-output:
26803     (write-buffered *(ebp+8) " ")
26804     (get Mu-registers *(ebp+0x10) 0xc "Mu-registers")  # => eax
26805     (write-int32-hex-buffered *(ebp+8) *eax)
26806     (write-buffered *(ebp+8) "/r32\n")
26807 $emit-save-size-to:end:
26808     # . restore registers
26809     5b/pop-to-ebx
26810     58/pop-to-eax
26811     # . epilogue
26812     89/<- %esp 5/r32/ebp
26813     5d/pop-to-ebp
26814     c3/return
26815 
26816 emit-divide-by-shift-right:  # out: (addr buffered-file), reg: (addr array byte), size: int
26817     # . prologue
26818     55/push-ebp
26819     89/<- %ebp 4/r32/esp
26820     # . save registers
26821     50/push-eax
26822     #
26823     (emit-indent *(ebp+8) *Curr-block-depth)
26824     (write-buffered *(ebp+8) "c1/shift 5/subop/>> %")
26825     (write-buffered *(ebp+8) *(ebp+0xc))
26826     (write-buffered *(ebp+8) Space)
26827     (num-shift-rights *(ebp+0x10))  # => eax
26828     (write-int32-hex-buffered *(ebp+8) %eax)
26829     (write-buffered *(ebp+8) "/imm8\n")
26830 $emit-divide-by-shift-right:end:
26831     # . restore registers
26832     58/pop-to-eax
26833     # . epilogue
26834     89/<- %esp 5/r32/ebp
26835     5d/pop-to-ebp
26836     c3/return
26837 
26838 translate-mu-index-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
26839     # . prologue
26840     55/push-ebp
26841     89/<- %ebp 4/r32/esp
26842     # . save registers
26843     51/push-ecx
26844     # ecx = stmt
26845     8b/-> *(ebp+0xc) 1/r32/ecx
26846     # var base/ecx: (addr var) = stmt->inouts[0]
26847     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
26848     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
26849     89/<- %ecx 0/r32/eax
26850     # if (var->register) do one thing
26851     {
26852       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
26853       74/jump-if-= break/disp8
26854       # TODO: ensure there's no dereference
26855       (translate-mu-index-stmt-with-array-in-register *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
26856       eb/jump $translate-mu-index-stmt:end/disp8
26857     }
26858     # if (var->offset) do a different thing
26859     {
26860       81 7/subop/compare *(ecx+0x14) 0/imm32  # Var-offset
26861       74/jump-if-= break/disp8
26862       # TODO: ensure there's no dereference
26863       (translate-mu-index-stmt-with-array-on-stack *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
26864       eb/jump $translate-mu-index-stmt:end/disp8
26865     }
26866 $translate-mu-index-stmt:end:
26867     # . restore registers
26868     59/pop-to-ecx
26869     # . epilogue
26870     89/<- %esp 5/r32/ebp
26871     5d/pop-to-ebp
26872     c3/return
26873 
26874 $translate-mu-index-stmt-with-array:error1:
26875     (write-buffered *(ebp+0x10) "couldn't translate an index instruction. second (index) input must either lie in a register or be a literal\n")
26876     (flush *(ebp+0x10))
26877     (stop *(ebp+0x14) 1)
26878     # never gets here
26879 
26880 $translate-mu-index-stmt-with-array:error2:
26881     (write-buffered *(ebp+0x10) "couldn't translate an index instruction. second (index) input when in a register must be an int or offset\n")
26882     (flush *(ebp+0x10))
26883     (stop *(ebp+0x14) 1)
26884     # never gets here
26885 
26886 translate-mu-index-stmt-with-array-in-register:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
26887     # . prologue
26888     55/push-ebp
26889     89/<- %ebp 4/r32/esp
26890     # . save registers
26891     50/push-eax
26892     51/push-ecx
26893     52/push-edx
26894     53/push-ebx
26895     #
26896     (emit-indent *(ebp+8) *Curr-block-depth)
26897     (write-buffered *(ebp+8) "8d/copy-address *(")
26898     # TODO: ensure inouts[0] is in a register and not dereferenced
26899 $translate-mu-index-stmt-with-array-in-register:emit-base:
26900     # ecx = stmt
26901     8b/-> *(ebp+0xc) 1/r32/ecx
26902     # var base/ebx: (addr var) = inouts[0]
26903     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
26904     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
26905     89/<- %ebx 0/r32/eax
26906     # print base->register " + "
26907     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
26908     (write-buffered *(ebp+8) %eax)
26909     (write-buffered *(ebp+8) " + ")
26910     # var index/edx: (addr var) = inouts[1]
26911     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
26912     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
26913     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
26914     89/<- %edx 0/r32/eax
26915     # if index->register
26916     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
26917     {
26918       0f 84/jump-if-= break/disp32
26919 $translate-mu-index-stmt-with-array-in-register:emit-register-index:
26920       # if index is an int
26921       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
26922       (is-simple-mu-type? %eax 1)  # int => eax
26923       3d/compare-eax-and 0/imm32/false
26924       {
26925         0f 84/jump-if-= break/disp32
26926 $translate-mu-index-stmt-with-array-in-register:emit-int-register-index:
26927         # print index->register "<<" log2(array-element-size(base)) " + 4) "
26928         # . index->register "<<"
26929         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
26930         (write-buffered *(ebp+8) %eax)
26931         (write-buffered *(ebp+8) "<<")
26932         # . log2(array-element-size(base->type))
26933         # TODO: ensure size is a power of 2
26934         (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
26935         (num-shift-rights %eax)  # => eax
26936         (write-int32-hex-buffered *(ebp+8) %eax)
26937         e9/jump $translate-mu-index-stmt-with-array-in-register:emit-register-index-done/disp32
26938       }
26939       # if index->type is any other atom, abort
26940       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
26941       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
26942       0f 85/jump-if-!= $translate-mu-index-stmt-with-array:error2/disp32
26943       # if index has type (offset ...)
26944       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
26945       (is-simple-mu-type? %eax 7)  # => eax
26946       3d/compare-eax-and 0/imm32/false
26947       {
26948         0f 84/jump-if-= break/disp32
26949         # print index->register
26950 $translate-mu-index-stmt-with-array-in-register:emit-offset-register-index:
26951         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
26952         (write-buffered *(ebp+8) %eax)
26953       }
26954 $translate-mu-index-stmt-with-array-in-register:emit-register-index-done:
26955       (write-buffered *(ebp+8) " + 4) ")
26956       e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32
26957     }
26958     # otherwise if index is a literal
26959     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
26960     (is-simple-mu-type? %eax 0)  # => eax
26961     3d/compare-eax-and 0/imm32/false
26962     {
26963       0f 84/jump-if-= break/disp32
26964 $translate-mu-index-stmt-with-array-in-register:emit-literal-index:
26965       # var index-value/edx: int = parse-hex-int(index->name)
26966       (lookup *edx *(edx+4))  # Var-name Var-name => eax
26967       (parse-hex-int %eax)  # => eax
26968       89/<- %edx 0/r32/eax
26969       # offset = idx-value * array-element-size(base->type)
26970       (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
26971       f7 4/subop/multiply-into-edx-eax %edx  # clobbers edx
26972       # offset += 4 for array size
26973       05/add-to-eax 4/imm32
26974       # TODO: check edx for overflow
26975       # print offset
26976       (write-int32-hex-buffered *(ebp+8) %eax)
26977       (write-buffered *(ebp+8) ") ")
26978       e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32
26979     }
26980     # otherwise abort
26981     e9/jump $translate-mu-index-stmt-with-array:error1/disp32
26982 $translate-mu-index-stmt-with-array-in-register:emit-output:
26983     # outputs[0] "/r32"
26984     8b/-> *(ebp+0xc) 1/r32/ecx
26985     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
26986     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
26987     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
26988     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
26989     (write-int32-hex-buffered *(ebp+8) *eax)
26990     (write-buffered *(ebp+8) "/r32\n")
26991 $translate-mu-index-stmt-with-array-in-register:end:
26992     # . restore registers
26993     5b/pop-to-ebx
26994     5a/pop-to-edx
26995     59/pop-to-ecx
26996     58/pop-to-eax
26997     # . epilogue
26998     89/<- %esp 5/r32/ebp
26999     5d/pop-to-ebp
27000     c3/return
27001 
27002 translate-mu-index-stmt-with-array-on-stack:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
27003     # . prologue
27004     55/push-ebp
27005     89/<- %ebp 4/r32/esp
27006     # . save registers
27007     50/push-eax
27008     51/push-ecx
27009     52/push-edx
27010     53/push-ebx
27011     #
27012     (emit-indent *(ebp+8) *Curr-block-depth)
27013     (write-buffered *(ebp+8) "8d/copy-address *(ebp + ")
27014     # var curr/edx: (addr stmt-var) = lookup(stmt->inouts)
27015     8b/-> *(ebp+0xc) 0/r32/eax
27016     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27017     89/<- %edx 0/r32/eax
27018     # var base/ecx: (addr var) = lookup(curr->value)
27019     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27020     89/<- %ecx 0/r32/eax
27021     # var curr2/eax: (addr stmt-var) = lookup(curr->next)
27022     (lookup *(edx+8) *(edx+0xc))  # Stmt-var-next Stmt-var-next => eax
27023     # var index/edx: (handle var) = curr2->value
27024     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27025     89/<- %edx 0/r32/eax
27026     # if index->register
27027     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
27028     {
27029       0f 84/jump-if-= break/disp32
27030 $translate-mu-index-stmt-with-array-on-stack:emit-register-index:
27031       # if index is an int
27032       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
27033       (is-simple-mu-type? %eax 1)  # int => eax
27034       3d/compare-eax-and 0/imm32/false
27035       {
27036         0f 84/jump-if-= break/disp32
27037 $translate-mu-index-stmt-with-array-on-stack:emit-int-register-index:
27038         # print index->register "<<" log2(array-element-size(base)) " + " base->offset+4
27039         # . inouts[1]->register "<<"
27040         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
27041         (write-buffered *(ebp+8) %eax)
27042         (write-buffered *(ebp+8) "<<")
27043         # . log2(array-element-size(base))
27044         # TODO: ensure size is a power of 2
27045         (array-element-size %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
27046         (num-shift-rights %eax)  # => eax
27047         (write-int32-hex-buffered *(ebp+8) %eax)
27048         #
27049         (write-buffered *(ebp+8) " + ")
27050         #
27051         8b/-> *(ecx+0x14) 0/r32/eax  # Var-offset
27052         05/add-to-eax 4/imm32  # for array length
27053         (write-int32-hex-buffered *(ebp+8) %eax)
27054         e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done/disp32
27055       }
27056       # if index->type is any other atom, abort
27057       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
27058       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
27059       0f 85/jump-if-!= $translate-mu-index-stmt-with-array:error2/disp32
27060       # if index has type (offset ...)
27061       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
27062       (is-simple-mu-type? %eax 7)  # => eax
27063       3d/compare-eax-and 0/imm32/false
27064       {
27065         0f 84/jump-if-= break/disp32
27066         # print index->register
27067 $translate-mu-index-stmt-with-array-on-stack:emit-offset-register-index:
27068         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
27069         (write-buffered *(ebp+8) %eax)
27070       }
27071 $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done:
27072       (write-buffered *(ebp+8) ") ")
27073       e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32
27074     }
27075     # otherwise if index is a literal
27076     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
27077     (is-simple-mu-type? %eax 0)  # => eax
27078     3d/compare-eax-and 0/imm32/false
27079     {
27080       0f 84/jump-if-= break/disp32
27081 $translate-mu-index-stmt-with-array-on-stack:emit-literal-index:
27082       # var idx-value/edx: int = parse-hex-int(index->name)
27083       (lookup *edx *(edx+4))  # Var-name Var-name => eax
27084       (parse-hex-int %eax)  # Var-name => eax
27085       89/<- %edx 0/r32/eax
27086       # offset = idx-value * array-element-size(base)
27087       (array-element-size %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
27088       f7 4/subop/multiply-into-edx-eax %edx  # clobbers edx
27089       # offset += base->offset
27090       03/add *(ecx+0x14) 0/r32/eax  # Var-offset
27091       # offset += 4 for array size
27092       05/add-to-eax 4/imm32
27093       # TODO: check edx for overflow
27094       # print offset
27095       (write-int32-hex-buffered *(ebp+8) %eax)
27096       (write-buffered *(ebp+8) ") ")
27097       e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32
27098     }
27099     # otherwise abort
27100     e9/jump $translate-mu-index-stmt-with-array:error1/disp32
27101 $translate-mu-index-stmt-with-array-on-stack:emit-output:
27102     # outputs[0] "/r32"
27103     8b/-> *(ebp+0xc) 0/r32/eax
27104     (lookup *(eax+0x14) *(eax+0x18))  # Stmt1-outputs Stmt1-outputs => eax
27105     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27106     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
27107     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
27108     (write-int32-hex-buffered *(ebp+8) *eax)
27109     (write-buffered *(ebp+8) "/r32\n")
27110 $translate-mu-index-stmt-with-array-on-stack:end:
27111     # . restore registers
27112     5b/pop-to-ebx
27113     5a/pop-to-edx
27114     59/pop-to-ecx
27115     58/pop-to-eax
27116     # . epilogue
27117     89/<- %esp 5/r32/ebp
27118     5d/pop-to-ebp
27119     c3/return
27120 
27121 translate-mu-compute-index-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
27122     # . prologue
27123     55/push-ebp
27124     89/<- %ebp 4/r32/esp
27125     # . save registers
27126     50/push-eax
27127     51/push-ecx
27128     52/push-edx
27129     53/push-ebx
27130     #
27131     (emit-indent *(ebp+8) *Curr-block-depth)
27132     (write-buffered *(ebp+8) "69/multiply")
27133     # ecx = stmt
27134     8b/-> *(ebp+0xc) 1/r32/ecx
27135     # var first-inout/ebx: (addr stmt-var) = stmt->inouts[0]
27136     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27137     89/<- %ebx 0/r32/eax
27138 $translate-mu-compute-index-stmt:emit-index:
27139     (lookup *(ebx+8) *(ebx+0xc))  # Stmt-var-next Stmt-var-next => eax
27140     (emit-subx-var-as-rm32 *(ebp+8) %eax)
27141     (write-buffered *(ebp+8) Space)
27142 $translate-mu-compute-index-stmt:emit-elem-size:
27143     # var base/ebx: (addr var)
27144     (lookup *ebx *(ebx+4))  # Stmt-var-value Stmt-var-value => eax
27145     89/<- %ebx 0/r32/eax
27146     # print array-element-size(base)
27147     (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
27148     (write-int32-hex-buffered *(ebp+8) %eax)
27149     (write-buffered *(ebp+8) "/imm32 ")
27150 $translate-mu-compute-index-stmt:emit-output:
27151     # outputs[0] "/r32"
27152     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
27153     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27154     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
27155     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
27156     (write-int32-hex-buffered *(ebp+8) *eax)
27157     (write-buffered *(ebp+8) "/r32\n")
27158 $translate-mu-compute-index-stmt:end:
27159     # . restore registers
27160     5b/pop-to-ebx
27161     5a/pop-to-edx
27162     59/pop-to-ecx
27163     58/pop-to-eax
27164     # . epilogue
27165     89/<- %esp 5/r32/ebp
27166     5d/pop-to-ebp
27167     c3/return
27168 
27169 translate-mu-get-stmt:  # out: (addr buffered-file), stmt: (addr stmt)
27170     # . prologue
27171     55/push-ebp
27172     89/<- %ebp 4/r32/esp
27173     # . save registers
27174     50/push-eax
27175     51/push-ecx
27176     52/push-edx
27177     #
27178     (emit-indent *(ebp+8) *Curr-block-depth)
27179     (write-buffered *(ebp+8) "8d/copy-address ")
27180     # ecx = stmt
27181     8b/-> *(ebp+0xc) 1/r32/ecx
27182     # var offset/edx: int = get offset of stmt
27183     (mu-get-offset %ecx)  # => eax
27184     89/<- %edx 0/r32/eax
27185     # var base/eax: (addr var) = stmt->inouts->value
27186     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27187     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27188     # if base is in a register
27189     81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
27190     {
27191       0f 84/jump-if-= break/disp32
27192 $translate-mu-get-stmt:emit-register-input:
27193       # emit "*(" base->register " + " offset ") "
27194       (write-buffered *(ebp+8) "*(")
27195       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
27196       (write-buffered *(ebp+8) %eax)
27197       (write-buffered *(ebp+8) " + ")
27198       (write-int32-hex-buffered *(ebp+8) %edx)
27199       (write-buffered *(ebp+8) ") ")
27200       e9/jump $translate-mu-get-stmt:emit-output/disp32
27201     }
27202     # otherwise base is on the stack
27203     {
27204 $translate-mu-get-stmt:emit-stack-input:
27205       # emit "*(ebp + " inouts[0]->stack-offset + offset ") "
27206       (write-buffered *(ebp+8) "*(ebp+")
27207       03/add *(eax+0x14) 2/r32/edx  # Var-offset
27208       (write-int32-hex-buffered *(ebp+8) %edx)
27209       (write-buffered *(ebp+8) ") ")
27210       eb/jump $translate-mu-get-stmt:emit-output/disp8
27211     }
27212 $translate-mu-get-stmt:emit-output:
27213     # var output/eax: (addr var) = stmt->outputs->value
27214     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
27215     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27216     # emit offset->register "/r32"
27217     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
27218     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
27219     (write-int32-hex-buffered *(ebp+8) *eax)
27220     (write-buffered *(ebp+8) "/r32\n")
27221 $translate-mu-get-stmt:end:
27222     # . restore registers
27223     5a/pop-to-edx
27224     59/pop-to-ecx
27225     58/pop-to-eax
27226     # . epilogue
27227     89/<- %esp 5/r32/ebp
27228     5d/pop-to-ebp
27229     c3/return
27230 
27231 translate-mu-copy-object-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
27232     # . prologue
27233     55/push-ebp
27234     89/<- %ebp 4/r32/esp
27235     # . save registers
27236     50/push-eax
27237     #
27238     (emit-indent *(ebp+8) *Curr-block-depth)
27239     (write-buffered *(ebp+8) "(copy-bytes")
27240     # eax = stmt
27241     8b/-> *(ebp+0xc) 0/r32/eax
27242     # var first-inout/eax: (addr stmt-var) = stmt->inouts[0]
27243     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27244     (emit-subx-call-operand *(ebp+8) %eax)
27245     # var second-inout/eax: (addr stmt-var) = stmt->inouts[1]
27246     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
27247     (emit-subx-call-operand *(ebp+8) %eax)
27248     # emit size of inouts
27249     (write-buffered *(ebp+8) Space)
27250     (addr-payload-size %eax *(ebp+0x10) *(ebp+0x14))  # => eax
27251     (write-int32-hex-buffered *(ebp+8) %eax)
27252     (write-buffered *(ebp+8) ")\n")
27253 $translate-mu-copy-object-stmt:end:
27254     # . restore registers
27255     58/pop-to-eax
27256     # . epilogue
27257     89/<- %esp 5/r32/ebp
27258     5d/pop-to-ebp
27259     c3/return
27260 
27261 translate-mu-clear-object-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
27262     # . prologue
27263     55/push-ebp
27264     89/<- %ebp 4/r32/esp
27265     # . save registers
27266     50/push-eax
27267     #
27268     (emit-indent *(ebp+8) *Curr-block-depth)
27269     (write-buffered *(ebp+8) "(zero-out")
27270     # eax = stmt
27271     8b/-> *(ebp+0xc) 0/r32/eax
27272     # var dest/eax: (addr stmt-var) = stmt->inouts[0]
27273     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27274     #
27275     (emit-subx-call-operand *(ebp+8) %eax)
27276     (write-buffered *(ebp+8) Space)
27277     (addr-payload-size %eax *(ebp+0x10) *(ebp+0x14))  # => eax
27278     (write-int32-hex-buffered *(ebp+8) %eax)
27279     (write-buffered *(ebp+8) ")\n")
27280 $translate-mu-clear-object-stmt:end:
27281     # . restore registers
27282     58/pop-to-eax
27283     # . epilogue
27284     89/<- %esp 5/r32/ebp
27285     5d/pop-to-ebp
27286     c3/return
27287 
27288 translate-mu-allocate-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
27289     # . prologue
27290     55/push-ebp
27291     89/<- %ebp 4/r32/esp
27292     # . save registers
27293     50/push-eax
27294     56/push-esi
27295     57/push-edi
27296     # esi = stmt
27297     8b/-> *(ebp+0xc) 6/r32/esi
27298     # var target/edi: (addr stmt-var) = stmt->inouts[0]
27299     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27300     89/<- %edi 0/r32/eax
27301     #
27302     (emit-indent *(ebp+8) *Curr-block-depth)
27303     (write-buffered *(ebp+8) "(allocate Heap ")
27304     (addr-handle-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
27305     (write-int32-hex-buffered *(ebp+8) %eax)
27306     (emit-subx-call-operand *(ebp+8) %edi)
27307     (write-buffered *(ebp+8) ")\n")
27308 $translate-mu-allocate-stmt:end:
27309     # . restore registers
27310     5f/pop-to-edi
27311     5e/pop-to-esi
27312     58/pop-to-eax
27313     # . epilogue
27314     89/<- %esp 5/r32/ebp
27315     5d/pop-to-ebp
27316     c3/return
27317 
27318 addr-handle-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
27319     # . prologue
27320     55/push-ebp
27321     89/<- %ebp 4/r32/esp
27322     # var t/eax: (addr type-tree) = s->value->type
27323     8b/-> *(ebp+8) 0/r32/eax
27324     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27325     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
27326     # TODO: check eax != 0
27327     # TODO: check !t->is-atom?
27328     # TODO: check t->left == addr
27329     # t = t->right
27330 $addr-handle-payload-size:skip-addr:
27331     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
27332     # TODO: check eax != 0
27333     # TODO: check !t->is-atom?
27334     # TODO: check t->left == handle
27335     # t = t->right
27336 $addr-handle-payload-size:skip-handle:
27337     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
27338     # TODO: check eax != 0
27339     # if !t->is-atom? t = t->left
27340     81 7/subop/compare *eax 0/imm32/false
27341     {
27342       75/jump-if-!= break/disp8
27343       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
27344     }
27345     # TODO: check t->is-atom?
27346     # return size(t->value)
27347     (size-of-type-id *(eax+4))  # Type-tree-value => eax
27348 $addr-handle-payload-size:end:
27349     # . epilogue
27350     89/<- %esp 5/r32/ebp
27351     5d/pop-to-ebp
27352     c3/return
27353 
27354 addr-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
27355     # . prologue
27356     55/push-ebp
27357     89/<- %ebp 4/r32/esp
27358     # var t/eax: (addr type-tree) = s->value->type
27359     8b/-> *(ebp+8) 0/r32/eax
27360     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27361     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
27362     # TODO: check eax != 0
27363     # TODO: check !t->is-atom?
27364     # TODO: check t->left == addr
27365     # t = t->right
27366 $addr-payload-size:skip-addr:
27367     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
27368     # TODO: check eax != 0
27369     # if !t->is-atom? t = t->left
27370     81 7/subop/compare *eax 0/imm32/false
27371     {
27372       75/jump-if-!= break/disp8
27373       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
27374     }
27375     # TODO: check t->is-atom?
27376     # return size(t->value)
27377     (size-of-type-id *(eax+4))  # Type-tree-value => eax
27378 $addr-payload-size:end:
27379     # . epilogue
27380     89/<- %esp 5/r32/ebp
27381     5d/pop-to-ebp
27382     c3/return
27383 
27384 translate-mu-populate-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
27385     # . prologue
27386     55/push-ebp
27387     89/<- %ebp 4/r32/esp
27388     # . save registers
27389     50/push-eax
27390     51/push-ecx
27391     56/push-esi
27392     57/push-edi
27393     # esi = stmt
27394     8b/-> *(ebp+0xc) 6/r32/esi
27395     # var target/edi: (addr stmt-var) = stmt->inouts[0]
27396     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27397     89/<- %edi 0/r32/eax
27398     # var len/ecx: (addr stmt-var) = stmt->inouts[1]
27399     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
27400     89/<- %ecx 0/r32/eax
27401     #
27402     (emit-indent *(ebp+8) *Curr-block-depth)
27403     (write-buffered *(ebp+8) "(allocate-array2 Heap ")
27404     (addr-handle-array-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
27405     (write-int32-hex-buffered *(ebp+8) %eax)
27406     (emit-subx-call-operand *(ebp+8) %ecx)
27407     (emit-subx-call-operand *(ebp+8) %edi)
27408     (write-buffered *(ebp+8) ")\n")
27409 $translate-mu-populate-stmt:end:
27410     # . restore registers
27411     5f/pop-to-edi
27412     5e/pop-to-esi
27413     59/pop-to-ecx
27414     58/pop-to-eax
27415     # . epilogue
27416     89/<- %esp 5/r32/ebp
27417     5d/pop-to-ebp
27418     c3/return
27419 
27420 translate-mu-populate-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
27421     # . prologue
27422     55/push-ebp
27423     89/<- %ebp 4/r32/esp
27424     # . save registers
27425     50/push-eax
27426     51/push-ecx
27427     56/push-esi
27428     57/push-edi
27429     # esi = stmt
27430     8b/-> *(ebp+0xc) 6/r32/esi
27431     # var target/edi: (addr stmt-var) = stmt->inouts[0]
27432     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27433     89/<- %edi 0/r32/eax
27434     # var len/ecx: (addr stmt-var) = stmt->inouts[1]
27435     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
27436     89/<- %ecx 0/r32/eax
27437     #
27438     (emit-indent *(ebp+8) *Curr-block-depth)
27439     (write-buffered *(ebp+8) "(new-stream Heap ")
27440     (addr-handle-stream-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
27441     (write-int32-hex-buffered *(ebp+8) %eax)
27442     (emit-subx-call-operand *(ebp+8) %ecx)
27443     (emit-subx-call-operand *(ebp+8) %edi)
27444     (write-buffered *(ebp+8) ")\n")
27445 $translate-mu-populate-stream-stmt:end:
27446     # . restore registers
27447     5f/pop-to-edi
27448     5e/pop-to-esi
27449     59/pop-to-ecx
27450     58/pop-to-eax
27451     # . epilogue
27452     89/<- %esp 5/r32/ebp
27453     5d/pop-to-ebp
27454     c3/return
27455 
27456 translate-mu-read-from-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
27457     # . prologue
27458     55/push-ebp
27459     89/<- %ebp 4/r32/esp
27460     # . save registers
27461     50/push-eax
27462     51/push-ecx
27463     56/push-esi
27464     57/push-edi
27465     # esi = stmt
27466     8b/-> *(ebp+0xc) 6/r32/esi
27467     # var stream/ecx: (addr stmt-var) = stmt->inouts[0]
27468     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27469     89/<- %ecx 0/r32/eax
27470     # var target/edi: (addr stmt-var) = stmt->inouts[1]
27471     (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
27472     89/<- %edi 0/r32/eax
27473     #
27474     (emit-indent *(ebp+8) *Curr-block-depth)
27475     (write-buffered *(ebp+8) "(read-from-stream")
27476     (emit-subx-call-operand *(ebp+8) %ecx)
27477     (emit-subx-call-operand *(ebp+8) %edi)
27478     (write-buffered *(ebp+8) Space)
27479     (addr-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
27480     (write-int32-hex-buffered *(ebp+8) %eax)
27481     (write-buffered *(ebp+8) ")\n")
27482 $translate-mu-read-from-stream-stmt:end:
27483     # . restore registers
27484     5f/pop-to-edi
27485     5e/pop-to-esi
27486     59/pop-to-ecx
27487     58/pop-to-eax
27488     # . epilogue
27489     89/<- %esp 5/r32/ebp
27490     5d/pop-to-ebp
27491     c3/return
27492 
27493 translate-mu-write-to-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
27494     # . prologue
27495     55/push-ebp
27496     89/<- %ebp 4/r32/esp
27497     # . save registers
27498     50/push-eax
27499     51/push-ecx
27500     56/push-esi
27501     57/push-edi
27502     # esi = stmt
27503     8b/-> *(ebp+0xc) 6/r32/esi
27504     # var stream/ecx: (addr stmt-var) = stmt->inouts[0]
27505     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27506     89/<- %ecx 0/r32/eax
27507     # var target/edi: (addr stmt-var) = stmt->inouts[1]
27508     (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
27509     89/<- %edi 0/r32/eax
27510     #
27511     (emit-indent *(ebp+8) *Curr-block-depth)
27512     (write-buffered *(ebp+8) "(write-to-stream")
27513     (emit-subx-call-operand *(ebp+8) %ecx)
27514     (flush *(ebp+8))
27515     (emit-subx-call-operand *(ebp+8) %edi)
27516     (flush *(ebp+8))
27517     (write-buffered *(ebp+8) Space)
27518     (flush *(ebp+8))
27519     (addr-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
27520     (write-int32-hex-buffered *(ebp+8) %eax)
27521     (write-buffered *(ebp+8) ")\n")
27522 $translate-mu-write-to-stream-stmt:end:
27523     # . restore registers
27524     5f/pop-to-edi
27525     5e/pop-to-esi
27526     59/pop-to-ecx
27527     58/pop-to-eax
27528     # . epilogue
27529     89/<- %esp 5/r32/ebp
27530     5d/pop-to-ebp
27531     c3/return
27532 
27533 addr-handle-array-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
27534     # . prologue
27535     55/push-ebp
27536     89/<- %ebp 4/r32/esp
27537     # var t/eax: (addr type-tree) = s->value->type
27538     8b/-> *(ebp+8) 0/r32/eax
27539     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27540     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
27541     # TODO: check eax != 0
27542     # TODO: check !t->is-atom?
27543     # TODO: check t->left == addr
27544     # t = t->right
27545 $addr-handle-array-payload-size:skip-addr:
27546     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
27547     # TODO: check eax != 0
27548     # TODO: check !t->is-atom?
27549     # TODO: check t->left == handle
27550     # t = t->right
27551 $addr-handle-array-payload-size:skip-handle:
27552     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
27553     # TODO: check eax != 0
27554     # TODO: check !t->is-atom?
27555     # TODO: check t->left == array
27556     # t = t->right
27557 $addr-handle-array-payload-size:skip-array:
27558     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
27559     # TODO: check eax != 0
27560     # if !t->is-atom? t = t->left
27561     81 7/subop/compare *eax 0/imm32/false
27562     {
27563       75/jump-if-!= break/disp8
27564       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
27565     }
27566 $addr-handle-array-payload-size:compute-size:
27567     # TODO: check t->is-atom?
27568     # return size(t->value)
27569     (size-of-type-id-as-array-element *(eax+4))  # Type-tree-value => eax
27570 $addr-handle-array-payload-size:end:
27571     # . epilogue
27572     89/<- %esp 5/r32/ebp
27573     5d/pop-to-ebp
27574     c3/return
27575 
27576 addr-handle-stream-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
27577     # . prologue
27578     55/push-ebp
27579     89/<- %ebp 4/r32/esp
27580     # var t/eax: (addr type-tree) = s->value->type
27581     8b/-> *(ebp+8) 0/r32/eax
27582     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27583     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
27584     # TODO: check eax != 0
27585     # TODO: check !t->is-atom?
27586     # TODO: check t->left == addr
27587     # t = t->right
27588 $addr-handle-stream-payload-size:skip-addr:
27589     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
27590     # TODO: check eax != 0
27591     # TODO: check !t->is-atom?
27592     # TODO: check t->left == handle
27593     # t = t->right
27594 $addr-handle-stream-payload-size:skip-handle:
27595     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
27596     # TODO: check eax != 0
27597     # TODO: check !t->is-atom?
27598     # TODO: check t->left == stream
27599     # t = t->right
27600 $addr-handle-stream-payload-size:skip-stream:
27601     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
27602     # TODO: check eax != 0
27603     # if !t->is-atom? t = t->left
27604     81 7/subop/compare *eax 0/imm32/false
27605     {
27606       75/jump-if-!= break/disp8
27607       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
27608     }
27609 $addr-handle-stream-payload-size:compute-size:
27610     # TODO: check t->is-atom?
27611     # return size(t->value)
27612     (size-of-type-id-as-array-element *(eax+4))  # Type-tree-value => eax
27613 $addr-handle-stream-payload-size:end:
27614     # . epilogue
27615     89/<- %esp 5/r32/ebp
27616     5d/pop-to-ebp
27617     c3/return
27618 
27619 power-of-2?:  # n: int, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: boolean
27620     # precondition: n is positive
27621     # . prologue
27622     55/push-ebp
27623     89/<- %ebp 4/r32/esp
27624     # eax = n
27625     8b/-> *(ebp+8) 0/r32/eax
27626     # if (n < 0) abort
27627     3d/compare-eax-with 0/imm32
27628     0f 8c/jump-if-< $power-of-2?:abort/disp32
27629     # var tmp/eax: int = n-1
27630     48/decrement-eax
27631     # var tmp2/eax: int = n & tmp
27632     23/and-> *(ebp+8) 0/r32/eax
27633     # return (tmp2 == 0)
27634     3d/compare-eax-and 0/imm32
27635     0f 94/set-byte-if-= %al
27636     81 4/subop/and %eax 0xff/imm32
27637 $power-of-2?:end:
27638     # . epilogue
27639     89/<- %esp 5/r32/ebp
27640     5d/pop-to-ebp
27641     c3/return
27642 
27643 $power-of-2?:abort:
27644     (write-buffered *(ebp+0xc) "power-of-2?: negative number\n")
27645     (flush *(ebp+0xc))
27646     (stop *(ebp+0x10) 1)
27647     # never gets here
27648 
27649 num-shift-rights:  # n: int -> result/eax: int
27650     # precondition: n is a positive power of 2
27651     # . prologue
27652     55/push-ebp
27653     89/<- %ebp 4/r32/esp
27654     # . save registers
27655     51/push-ecx
27656     # var curr/ecx: int = n
27657     8b/-> *(ebp+8) 1/r32/ecx
27658     # result = 0
27659     b8/copy-to-eax 0/imm32
27660     {
27661       # if (curr <= 1) break
27662       81 7/subop/compare %ecx 1/imm32
27663       7e/jump-if-<= break/disp8
27664       40/increment-eax
27665       c1/shift 5/subop/arithmetic-right %ecx 1/imm8
27666       eb/jump loop/disp8
27667     }
27668 $num-shift-rights:end:
27669     # . restore registers
27670     59/pop-to-ecx
27671     # . epilogue
27672     89/<- %esp 5/r32/ebp
27673     5d/pop-to-ebp
27674     c3/return
27675 
27676 mu-get-offset:  # stmt: (addr stmt) -> result/eax: int
27677     # . prologue
27678     55/push-ebp
27679     89/<- %ebp 4/r32/esp
27680     # var second-inout/eax: (addr stmt-var) = stmt->inouts->next
27681     8b/-> *(ebp+8) 0/r32/eax
27682     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27683     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
27684     # var output-var/eax: (addr var) = second-inout->value
27685     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27686 #?     (write-buffered Stderr "mu-get-offset: ")
27687 #?     (write-int32-hex-buffered Stderr %eax)
27688 #?     (write-buffered Stderr " name: ")
27689 #?     50/push-eax
27690 #?     (lookup *eax *(eax+4))  # Var-name
27691 #?     (write-buffered Stderr %eax)
27692 #?     58/pop-to-eax
27693 #?     (write-buffered Stderr Newline)
27694 #?     (flush Stderr)
27695     # return output-var->stack-offset
27696     8b/-> *(eax+0x14) 0/r32/eax  # Var-offset
27697 #?     (write-buffered Stderr "=> ")
27698 #?     (write-int32-hex-buffered Stderr %eax)
27699 #?     (write-buffered Stderr Newline)
27700 #?     (flush Stderr)
27701 $emit-get-offset:end:
27702     # . epilogue
27703     89/<- %esp 5/r32/ebp
27704     5d/pop-to-ebp
27705     c3/return
27706 
27707 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)
27708     # . prologue
27709     55/push-ebp
27710     89/<- %ebp 4/r32/esp
27711     # . save registers
27712     50/push-eax
27713     51/push-ecx
27714     56/push-esi
27715     # esi = block
27716     8b/-> *(ebp+0xc) 6/r32/esi
27717     # block->var->block-depth = *Curr-block-depth
27718     (lookup *(esi+0xc) *(esi+0x10))  # Block-var Block-var => eax
27719     8b/-> *Curr-block-depth 1/r32/ecx
27720     89/<- *(eax+0x10) 1/r32/ecx  # Var-block-depth
27721     # var stmts/eax: (addr list stmt) = lookup(block->statements)
27722     (lookup *(esi+4) *(esi+8))  # Block-stmts Block-stmts => eax
27723     #
27724     {
27725 $emit-subx-block:check-empty:
27726       3d/compare-eax-and 0/imm32
27727       0f 84/jump-if-= break/disp32
27728       (emit-indent *(ebp+8) *Curr-block-depth)
27729       (write-buffered *(ebp+8) "{\n")
27730       # var v/ecx: (addr var) = lookup(block->var)
27731       (lookup *(esi+0xc) *(esi+0x10))  # Block-var Block-var => eax
27732       89/<- %ecx 0/r32/eax
27733       #
27734       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
27735       (write-buffered *(ebp+8) %eax)
27736       (write-buffered *(ebp+8) ":loop:\n")
27737       ff 0/subop/increment *Curr-block-depth
27738       (push *(ebp+0x10) *(esi+0xc))  # Block-var
27739       (push *(ebp+0x10) *(esi+0x10))  # Block-var
27740       (push *(ebp+0x10) 0)  # false
27741       # emit block->statements
27742       (lookup *(esi+4) *(esi+8))  # Block-stmts Block-stmts => eax
27743       (emit-subx-stmt-list *(ebp+8) %eax *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
27744       (pop *(ebp+0x10))  # => eax
27745       (pop *(ebp+0x10))  # => eax
27746       (pop *(ebp+0x10))  # => eax
27747       ff 1/subop/decrement *Curr-block-depth
27748       (emit-indent *(ebp+8) *Curr-block-depth)
27749       (write-buffered *(ebp+8) "}\n")
27750       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
27751       (write-buffered *(ebp+8) %eax)
27752       (write-buffered *(ebp+8) ":break:\n")
27753     }
27754 $emit-subx-block:end:
27755     # . restore registers
27756     5e/pop-to-esi
27757     59/pop-to-ecx
27758     58/pop-to-eax
27759     # . epilogue
27760     89/<- %esp 5/r32/ebp
27761     5d/pop-to-ebp
27762     c3/return
27763 
27764 # Primitives supported
27765 # See mu_instructions for a summary of this linked-list data structure.
27766 #
27767 # For each operation, put variants with hard-coded registers before flexible ones.
27768 #
27769 # Unfortunately, our restrictions on addresses require that various fields in
27770 # primitives be handles, which complicates these definitions.
27771 #   - we need to insert dummy fields all over the place for fake alloc-ids
27772 #   - we can't use our syntax sugar of quoted literals for string fields
27773 #
27774 # Fake alloc-ids are needed because our type definitions up top require
27775 # handles but it's clearer to statically allocate these long-lived objects.
27776 # Fake alloc-ids are perfectly safe, but they can't be reclaimed.
27777 #
27778 # Every 'object' below starts with a fake alloc-id. It may also contain other
27779 # fake alloc-ids for various handle fields.
27780 #
27781 # I think of objects starting with a fake alloc-id as having type 'payload'.
27782 # It's not really intended to be created dynamically; for that use `allocate`
27783 # as usual.
27784 #
27785 # Idea for a notation to simplify such definitions:
27786 #   _Primitive-increment-eax:  # (payload primitive)
27787 #     0x11/alloc-id:fake:payload
27788 #     0x11 @(0x11 "increment")  # name
27789 #     0 0                       # inouts
27790 #     0x11 @(0x11/payload
27791 #            0x11 @(0x11/payload  # List-value
27792 #                   0 0             # Var-name
27793 #                   0x11 @(0x11     # Var-type
27794 #                          1/is-atom
27795 #                          1/value 0/unused   # Type-tree-left
27796 #                          0 0                # Type-tree-right
27797 #                         )
27798 #                   1               # block-depth
27799 #                   0               # stack-offset
27800 #                   0x11 @(0x11 "eax")  # Var-register
27801 #                  )
27802 #            0 0)                 # List-next
27803 #     ...
27804 #     _Primitive-increment-ecx/imm32/next
27805 #   ...
27806 # Awfully complex and non-obvious. But also clearly signals there's something
27807 # to learn here, so may be worth trying.
27808 #
27809 # '@' is just an initial thought. Punctuation used so far in Mu: () * % # / "
27810 #
27811 # For now we'll continue to just use comments and manually ensure they stay up
27812 # to date.
27813 == data
27814 Primitives:  # (addr primitive)
27815 # - increment/decrement
27816 _Primitive-increment-eax:  # (addr primitive)
27817     # var/eax <- increment => 40/increment-eax
27818     0x11/imm32/alloc-id:fake
27819     _string-increment/imm32/name
27820     0/imm32/no-inouts
27821     0/imm32/no-inouts
27822     0x11/imm32/alloc-id:fake
27823     Single-int-var-in-eax/imm32/outputs
27824     0x11/imm32/alloc-id:fake
27825     _string_40_increment_eax/imm32/subx-name
27826     0/imm32/no-rm32
27827     0/imm32/no-r32
27828     0/imm32/no-imm32
27829     0/imm32/no-imm8
27830     0/imm32/no-disp32
27831     0/imm32/no-xm32
27832     0/imm32/no-x32
27833     0x11/imm32/alloc-id:fake
27834     _Primitive-increment-ecx/imm32/next
27835 _Primitive-increment-ecx:  # (payload primitive)
27836     0x11/imm32/alloc-id:fake:payload
27837     # var/ecx <- increment => 41/increment-ecx
27838     0x11/imm32/alloc-id:fake
27839     _string-increment/imm32/name
27840     0/imm32/no-inouts
27841     0/imm32/no-inouts
27842     0x11/imm32/alloc-id:fake
27843     Single-int-var-in-ecx/imm32/outputs
27844     0x11/imm32/alloc-id:fake
27845     _string_41_increment_ecx/imm32/subx-name
27846     0/imm32/no-rm32
27847     0/imm32/no-r32
27848     0/imm32/no-imm32
27849     0/imm32/no-imm8
27850     0/imm32/no-disp32
27851     0/imm32/no-xm32
27852     0/imm32/no-x32
27853     0x11/imm32/alloc-id:fake
27854     _Primitive-increment-edx/imm32/next
27855 _Primitive-increment-edx:  # (payload primitive)
27856     0x11/imm32/alloc-id:fake:payload
27857     # var/edx <- increment => 42/increment-edx
27858     0x11/imm32/alloc-id:fake
27859     _string-increment/imm32/name
27860     0/imm32/no-inouts
27861     0/imm32/no-inouts
27862     0x11/imm32/alloc-id:fake
27863     Single-int-var-in-edx/imm32/outputs
27864     0x11/imm32/alloc-id:fake
27865     _string_42_increment_edx/imm32/subx-name
27866     0/imm32/no-rm32
27867     0/imm32/no-r32
27868     0/imm32/no-imm32
27869     0/imm32/no-imm8
27870     0/imm32/no-disp32
27871     0/imm32/no-xm32
27872     0/imm32/no-x32
27873     0x11/imm32/alloc-id:fake
27874     _Primitive-increment-ebx/imm32/next
27875 _Primitive-increment-ebx:  # (payload primitive)
27876     0x11/imm32/alloc-id:fake:payload
27877     # var/ebx <- increment => 43/increment-ebx
27878     0x11/imm32/alloc-id:fake
27879     _string-increment/imm32/name
27880     0/imm32/no-inouts
27881     0/imm32/no-inouts
27882     0x11/imm32/alloc-id:fake
27883     Single-int-var-in-ebx/imm32/outputs
27884     0x11/imm32/alloc-id:fake
27885     _string_43_increment_ebx/imm32/subx-name
27886     0/imm32/no-rm32
27887     0/imm32/no-r32
27888     0/imm32/no-imm32
27889     0/imm32/no-imm8
27890     0/imm32/no-disp32
27891     0/imm32/no-xm32
27892     0/imm32/no-x32
27893     0x11/imm32/alloc-id:fake
27894     _Primitive-increment-esi/imm32/next
27895 _Primitive-increment-esi:  # (payload primitive)
27896     0x11/imm32/alloc-id:fake:payload
27897     # var/esi <- increment => 46/increment-esi
27898     0x11/imm32/alloc-id:fake
27899     _string-increment/imm32/name
27900     0/imm32/no-inouts
27901     0/imm32/no-inouts
27902     0x11/imm32/alloc-id:fake
27903     Single-int-var-in-esi/imm32/outputs
27904     0x11/imm32/alloc-id:fake
27905     _string_46_increment_esi/imm32/subx-name
27906     0/imm32/no-rm32
27907     0/imm32/no-r32
27908     0/imm32/no-imm32
27909     0/imm32/no-imm8
27910     0/imm32/no-disp32
27911     0/imm32/no-xm32
27912     0/imm32/no-x32
27913     0x11/imm32/alloc-id:fake
27914     _Primitive-increment-edi/imm32/next
27915 _Primitive-increment-edi:  # (payload primitive)
27916     0x11/imm32/alloc-id:fake:payload
27917     # var/edi <- increment => 47/increment-edi
27918     0x11/imm32/alloc-id:fake
27919     _string-increment/imm32/name
27920     0/imm32/no-inouts
27921     0/imm32/no-inouts
27922     0x11/imm32/alloc-id:fake
27923     Single-int-var-in-edi/imm32/outputs
27924     0x11/imm32/alloc-id:fake
27925     _string_47_increment_edi/imm32/subx-name
27926     0/imm32/no-rm32
27927     0/imm32/no-r32
27928     0/imm32/no-imm32
27929     0/imm32/no-imm8
27930     0/imm32/no-disp32
27931     0/imm32/no-xm32
27932     0/imm32/no-x32
27933     0x11/imm32/alloc-id:fake
27934     _Primitive-decrement-eax/imm32/next
27935 _Primitive-decrement-eax:  # (payload primitive)
27936     0x11/imm32/alloc-id:fake:payload
27937     # var/eax <- decrement => 48/decrement-eax
27938     0x11/imm32/alloc-id:fake
27939     _string-decrement/imm32/name
27940     0/imm32/no-inouts
27941     0/imm32/no-inouts
27942     0x11/imm32/alloc-id:fake
27943     Single-int-var-in-eax/imm32/outputs
27944     0x11/imm32/alloc-id:fake
27945     _string_48_decrement_eax/imm32/subx-name
27946     0/imm32/no-rm32
27947     0/imm32/no-r32
27948     0/imm32/no-imm32
27949     0/imm32/no-imm8
27950     0/imm32/no-disp32
27951     0/imm32/no-xm32
27952     0/imm32/no-x32
27953     0x11/imm32/alloc-id:fake
27954     _Primitive-decrement-ecx/imm32/next
27955 _Primitive-decrement-ecx:  # (payload primitive)
27956     0x11/imm32/alloc-id:fake:payload
27957     # var/ecx <- decrement => 49/decrement-ecx
27958     0x11/imm32/alloc-id:fake
27959     _string-decrement/imm32/name
27960     0/imm32/no-inouts
27961     0/imm32/no-inouts
27962     0x11/imm32/alloc-id:fake
27963     Single-int-var-in-ecx/imm32/outputs
27964     0x11/imm32/alloc-id:fake
27965     _string_49_decrement_ecx/imm32/subx-name
27966     0/imm32/no-rm32
27967     0/imm32/no-r32
27968     0/imm32/no-imm32
27969     0/imm32/no-imm8
27970     0/imm32/no-disp32
27971     0/imm32/no-xm32
27972     0/imm32/no-x32
27973     0x11/imm32/alloc-id:fake
27974     _Primitive-decrement-edx/imm32/next
27975 _Primitive-decrement-edx:  # (payload primitive)
27976     0x11/imm32/alloc-id:fake:payload
27977     # var/edx <- decrement => 4a/decrement-edx
27978     0x11/imm32/alloc-id:fake
27979     _string-decrement/imm32/name
27980     0/imm32/no-inouts
27981     0/imm32/no-inouts
27982     0x11/imm32/alloc-id:fake
27983     Single-int-var-in-edx/imm32/outputs
27984     0x11/imm32/alloc-id:fake
27985     _string_4a_decrement_edx/imm32/subx-name
27986     0/imm32/no-rm32
27987     0/imm32/no-r32
27988     0/imm32/no-imm32
27989     0/imm32/no-imm8
27990     0/imm32/no-disp32
27991     0/imm32/no-xm32
27992     0/imm32/no-x32
27993     0x11/imm32/alloc-id:fake
27994     _Primitive-decrement-ebx/imm32/next
27995 _Primitive-decrement-ebx:  # (payload primitive)
27996     0x11/imm32/alloc-id:fake:payload
27997     # var/ebx <- decrement => 4b/decrement-ebx
27998     0x11/imm32/alloc-id:fake
27999     _string-decrement/imm32/name
28000     0/imm32/no-inouts
28001     0/imm32/no-inouts
28002     0x11/imm32/alloc-id:fake
28003     Single-int-var-in-ebx/imm32/outputs
28004     0x11/imm32/alloc-id:fake
28005     _string_4b_decrement_ebx/imm32/subx-name
28006     0/imm32/no-rm32
28007     0/imm32/no-r32
28008     0/imm32/no-imm32
28009     0/imm32/no-imm8
28010     0/imm32/no-disp32
28011     0/imm32/no-xm32
28012     0/imm32/no-x32
28013     0x11/imm32/alloc-id:fake
28014     _Primitive-decrement-esi/imm32/next
28015 _Primitive-decrement-esi:  # (payload primitive)
28016     0x11/imm32/alloc-id:fake:payload
28017     # var/esi <- decrement => 4e/decrement-esi
28018     0x11/imm32/alloc-id:fake
28019     _string-decrement/imm32/name
28020     0/imm32/no-inouts
28021     0/imm32/no-inouts
28022     0x11/imm32/alloc-id:fake
28023     Single-int-var-in-esi/imm32/outputs
28024     0x11/imm32/alloc-id:fake
28025     _string_4e_decrement_esi/imm32/subx-name
28026     0/imm32/no-rm32
28027     0/imm32/no-r32
28028     0/imm32/no-imm32
28029     0/imm32/no-imm8
28030     0/imm32/no-disp32
28031     0/imm32/no-xm32
28032     0/imm32/no-x32
28033     0x11/imm32/alloc-id:fake
28034     _Primitive-decrement-edi/imm32/next
28035 _Primitive-decrement-edi:  # (payload primitive)
28036     0x11/imm32/alloc-id:fake:payload
28037     # var/edi <- decrement => 4f/decrement-edi
28038     0x11/imm32/alloc-id:fake
28039     _string-decrement/imm32/name
28040     0/imm32/no-inouts
28041     0/imm32/no-inouts
28042     0x11/imm32/alloc-id:fake
28043     Single-int-var-in-edi/imm32/outputs
28044     0x11/imm32/alloc-id:fake
28045     _string_4f_decrement_edi/imm32/subx-name
28046     0/imm32/no-rm32
28047     0/imm32/no-r32
28048     0/imm32/no-imm32
28049     0/imm32/no-imm8
28050     0/imm32/no-disp32
28051     0/imm32/no-xm32
28052     0/imm32/no-x32
28053     0x11/imm32/alloc-id:fake
28054     _Primitive-increment-mem/imm32/next
28055 _Primitive-increment-mem:  # (payload primitive)
28056     0x11/imm32/alloc-id:fake:payload
28057     # increment var => ff 0/subop/increment *(ebp+__)
28058     0x11/imm32/alloc-id:fake
28059     _string-increment/imm32/name
28060     0x11/imm32/alloc-id:fake
28061     Single-int-var-in-mem/imm32/inouts
28062     0/imm32/no-outputs
28063     0/imm32/no-outputs
28064     0x11/imm32/alloc-id:fake
28065     _string_ff_subop_increment/imm32/subx-name
28066     1/imm32/rm32-is-first-inout
28067     0/imm32/no-r32
28068     0/imm32/no-imm32
28069     0/imm32/no-imm8
28070     0/imm32/no-disp32
28071     0/imm32/no-xm32
28072     0/imm32/no-x32
28073     0x11/imm32/alloc-id:fake
28074     _Primitive-increment-reg/imm32/next
28075 _Primitive-increment-reg:  # (payload primitive)
28076     0x11/imm32/alloc-id:fake:payload
28077     # var/reg <- increment => ff 0/subop/increment %__
28078     0x11/imm32/alloc-id:fake
28079     _string-increment/imm32/name
28080     0/imm32/no-inouts
28081     0/imm32/no-inouts
28082     0x11/imm32/alloc-id:fake
28083     Single-int-var-in-some-register/imm32/outputs
28084     0x11/imm32/alloc-id:fake
28085     _string_ff_subop_increment/imm32/subx-name
28086     3/imm32/rm32-is-first-output
28087     0/imm32/no-r32
28088     0/imm32/no-imm32
28089     0/imm32/no-imm8
28090     0/imm32/no-disp32
28091     0/imm32/no-xm32
28092     0/imm32/no-x32
28093     0x11/imm32/alloc-id:fake
28094     _Primitive-decrement-mem/imm32/next
28095 _Primitive-decrement-mem:  # (payload primitive)
28096     0x11/imm32/alloc-id:fake:payload
28097     # decrement var => ff 1/subop/decrement *(ebp+__)
28098     0x11/imm32/alloc-id:fake
28099     _string-decrement/imm32/name
28100     0x11/imm32/alloc-id:fake
28101     Single-int-var-in-mem/imm32/inouts
28102     0/imm32/no-outputs
28103     0/imm32/no-outputs
28104     0x11/imm32/alloc-id:fake
28105     _string_ff_subop_decrement/imm32/subx-name
28106     1/imm32/rm32-is-first-inout
28107     0/imm32/no-r32
28108     0/imm32/no-imm32
28109     0/imm32/no-imm8
28110     0/imm32/no-disp32
28111     0/imm32/no-xm32
28112     0/imm32/no-x32
28113     0x11/imm32/alloc-id:fake
28114     _Primitive-decrement-reg/imm32/next
28115 _Primitive-decrement-reg:  # (payload primitive)
28116     0x11/imm32/alloc-id:fake:payload
28117     # var/reg <- decrement => ff 1/subop/decrement %__
28118     0x11/imm32/alloc-id:fake
28119     _string-decrement/imm32/name
28120     0/imm32/no-inouts
28121     0/imm32/no-inouts
28122     0x11/imm32/alloc-id:fake
28123     Single-int-var-in-some-register/imm32/outputs
28124     0x11/imm32/alloc-id:fake
28125     _string_ff_subop_decrement/imm32/subx-name
28126     3/imm32/rm32-is-first-output
28127     0/imm32/no-r32
28128     0/imm32/no-imm32
28129     0/imm32/no-imm8
28130     0/imm32/no-disp32
28131     0/imm32/no-xm32
28132     0/imm32/no-x32
28133     0x11/imm32/alloc-id:fake
28134     _Primitive-add-to-eax/imm32/next
28135 # - add
28136 _Primitive-add-to-eax:  # (payload primitive)
28137     0x11/imm32/alloc-id:fake:payload
28138     # var/eax <- add lit => 05/add-to-eax lit/imm32
28139     0x11/imm32/alloc-id:fake
28140     _string-add/imm32/name
28141     0x11/imm32/alloc-id:fake
28142     Single-lit-var/imm32/inouts
28143     0x11/imm32/alloc-id:fake
28144     Single-int-var-in-eax/imm32/outputs
28145     0x11/imm32/alloc-id:fake
28146     _string_05_add_to_eax/imm32/subx-name
28147     0/imm32/no-rm32
28148     0/imm32/no-r32
28149     1/imm32/imm32-is-first-inout
28150     0/imm32/no-imm8
28151     0/imm32/no-disp32
28152     0/imm32/no-xm32
28153     0/imm32/no-x32
28154     0x11/imm32/alloc-id:fake
28155     _Primitive-add-reg-to-reg/imm32/next
28156 _Primitive-add-reg-to-reg:  # (payload primitive)
28157     0x11/imm32/alloc-id:fake:payload
28158     # var1/reg <- add var2/reg => 01/add-to var1/rm32 var2/r32
28159     0x11/imm32/alloc-id:fake
28160     _string-add/imm32/name
28161     0x11/imm32/alloc-id:fake
28162     Single-int-var-in-some-register/imm32/inouts
28163     0x11/imm32/alloc-id:fake
28164     Single-int-var-in-some-register/imm32/outputs
28165     0x11/imm32/alloc-id:fake
28166     _string_01_add_to/imm32/subx-name
28167     3/imm32/rm32-is-first-output
28168     1/imm32/r32-is-first-inout
28169     0/imm32/no-imm32
28170     0/imm32/no-imm8
28171     0/imm32/no-disp32
28172     0/imm32/no-xm32
28173     0/imm32/no-x32
28174     0x11/imm32/alloc-id:fake
28175     _Primitive-add-reg-to-mem/imm32/next
28176 _Primitive-add-reg-to-mem:  # (payload primitive)
28177     0x11/imm32/alloc-id:fake:payload
28178     # add-to var1 var2/reg => 01/add-to var1 var2/r32
28179     0x11/imm32/alloc-id:fake
28180     _string-add-to/imm32/name
28181     0x11/imm32/alloc-id:fake
28182     Two-args-int-stack-int-reg/imm32/inouts
28183     0/imm32/no-outputs
28184     0/imm32/no-outputs
28185     0x11/imm32/alloc-id:fake
28186     _string_01_add_to/imm32/subx-name
28187     1/imm32/rm32-is-first-inout
28188     2/imm32/r32-is-second-inout
28189     0/imm32/no-imm32
28190     0/imm32/no-imm8
28191     0/imm32/no-disp32
28192     0/imm32/no-xm32
28193     0/imm32/no-x32
28194     0x11/imm32/alloc-id:fake
28195     _Primitive-add-mem-to-reg/imm32/next
28196 _Primitive-add-mem-to-reg:  # (payload primitive)
28197     0x11/imm32/alloc-id:fake:payload
28198     # var1/reg <- add var2 => 03/add var2/rm32 var1/r32
28199     0x11/imm32/alloc-id:fake
28200     _string-add/imm32/name
28201     0x11/imm32/alloc-id:fake
28202     Single-int-var-in-mem/imm32/inouts
28203     0x11/imm32/alloc-id:fake
28204     Single-int-var-in-some-register/imm32/outputs
28205     0x11/imm32/alloc-id:fake
28206     _string_03_add/imm32/subx-name
28207     1/imm32/rm32-is-first-inout
28208     3/imm32/r32-is-first-output
28209     0/imm32/no-imm32
28210     0/imm32/no-imm8
28211     0/imm32/no-disp32
28212     0/imm32/no-xm32
28213     0/imm32/no-x32
28214     0x11/imm32/alloc-id:fake
28215     _Primitive-add-lit-to-reg/imm32/next
28216 _Primitive-add-lit-to-reg:  # (payload primitive)
28217     0x11/imm32/alloc-id:fake:payload
28218     # var1/reg <- add lit => 81 0/subop/add var1/rm32 lit/imm32
28219     0x11/imm32/alloc-id:fake
28220     _string-add/imm32/name
28221     0x11/imm32/alloc-id:fake
28222     Single-lit-var/imm32/inouts
28223     0x11/imm32/alloc-id:fake
28224     Single-int-var-in-some-register/imm32/outputs
28225     0x11/imm32/alloc-id:fake
28226     _string_81_subop_add/imm32/subx-name
28227     3/imm32/rm32-is-first-output
28228     0/imm32/no-r32
28229     1/imm32/imm32-is-first-inout
28230     0/imm32/no-imm8
28231     0/imm32/no-disp32
28232     0/imm32/no-xm32
28233     0/imm32/no-x32
28234     0x11/imm32/alloc-id:fake
28235     _Primitive-add-lit-to-mem/imm32/next
28236 _Primitive-add-lit-to-mem:  # (payload primitive)
28237     0x11/imm32/alloc-id:fake:payload
28238     # add-to var1, lit => 81 0/subop/add var1/rm32 lit/imm32
28239     0x11/imm32/alloc-id:fake
28240     _string-add-to/imm32/name
28241     0x11/imm32/alloc-id:fake
28242     Int-var-and-literal/imm32/inouts
28243     0/imm32/no-outputs
28244     0/imm32/no-outputs
28245     0x11/imm32/alloc-id:fake
28246     _string_81_subop_add/imm32/subx-name
28247     1/imm32/rm32-is-first-inout
28248     0/imm32/no-r32
28249     2/imm32/imm32-is-second-inout
28250     0/imm32/no-imm8
28251     0/imm32/no-disp32
28252     0/imm32/no-xm32
28253     0/imm32/no-x32
28254     0x11/imm32/alloc-id:fake
28255     _Primitive-subtract-from-eax/imm32/next
28256 # - subtract
28257 _Primitive-subtract-from-eax:  # (payload primitive)
28258     0x11/imm32/alloc-id:fake:payload
28259     # var/eax <- subtract lit => 2d/subtract-from-eax lit/imm32
28260     0x11/imm32/alloc-id:fake
28261     _string-subtract/imm32/name
28262     0x11/imm32/alloc-id:fake
28263     Single-lit-var/imm32/inouts
28264     0x11/imm32/alloc-id:fake
28265     Single-int-var-in-eax/imm32/outputs
28266     0x11/imm32/alloc-id:fake
28267     _string_2d_subtract_from_eax/imm32/subx-name
28268     0/imm32/no-rm32
28269     0/imm32/no-r32
28270     1/imm32/imm32-is-first-inout
28271     0/imm32/no-imm8
28272     0/imm32/no-disp32
28273     0/imm32/no-xm32
28274     0/imm32/no-x32
28275     0x11/imm32/alloc-id:fake
28276     _Primitive-subtract-reg-from-reg/imm32/next
28277 _Primitive-subtract-reg-from-reg:  # (payload primitive)
28278     0x11/imm32/alloc-id:fake:payload
28279     # var1/reg <- subtract var2/reg => 29/subtract-from var1/rm32 var2/r32
28280     0x11/imm32/alloc-id:fake
28281     _string-subtract/imm32/name
28282     0x11/imm32/alloc-id:fake
28283     Single-int-var-in-some-register/imm32/inouts
28284     0x11/imm32/alloc-id:fake
28285     Single-int-var-in-some-register/imm32/outputs
28286     0x11/imm32/alloc-id:fake
28287     _string_29_subtract_from/imm32/subx-name
28288     3/imm32/rm32-is-first-output
28289     1/imm32/r32-is-first-inout
28290     0/imm32/no-imm32
28291     0/imm32/no-imm8
28292     0/imm32/no-disp32
28293     0/imm32/no-xm32
28294     0/imm32/no-x32
28295     0x11/imm32/alloc-id:fake
28296     _Primitive-subtract-reg-from-mem/imm32/next
28297 _Primitive-subtract-reg-from-mem:  # (payload primitive)
28298     0x11/imm32/alloc-id:fake:payload
28299     # subtract-from var1 var2/reg => 29/subtract-from var1 var2/r32
28300     0x11/imm32/alloc-id:fake
28301     _string-subtract-from/imm32/name
28302     0x11/imm32/alloc-id:fake
28303     Two-args-int-stack-int-reg/imm32/inouts
28304     0/imm32/no-outputs
28305     0/imm32/no-outputs
28306     0x11/imm32/alloc-id:fake
28307     _string_29_subtract_from/imm32/subx-name
28308     1/imm32/rm32-is-first-inout
28309     2/imm32/r32-is-second-inout
28310     0/imm32/no-imm32
28311     0/imm32/no-imm8
28312     0/imm32/no-disp32
28313     0/imm32/no-xm32
28314     0/imm32/no-x32
28315     0x11/imm32/alloc-id:fake
28316     _Primitive-subtract-mem-from-reg/imm32/next
28317 _Primitive-subtract-mem-from-reg:  # (payload primitive)
28318     0x11/imm32/alloc-id:fake:payload
28319     # var1/reg <- subtract var2 => 2b/subtract var2/rm32 var1/r32
28320     0x11/imm32/alloc-id:fake
28321     _string-subtract/imm32/name
28322     0x11/imm32/alloc-id:fake
28323     Single-int-var-in-mem/imm32/inouts
28324     0x11/imm32/alloc-id:fake
28325     Single-int-var-in-some-register/imm32/outputs
28326     0x11/imm32/alloc-id:fake
28327     _string_2b_subtract/imm32/subx-name
28328     1/imm32/rm32-is-first-inout
28329     3/imm32/r32-is-first-output
28330     0/imm32/no-imm32
28331     0/imm32/no-imm8
28332     0/imm32/no-disp32
28333     0/imm32/no-xm32
28334     0/imm32/no-x32
28335     0x11/imm32/alloc-id:fake
28336     _Primitive-subtract-lit-from-reg/imm32/next
28337 _Primitive-subtract-lit-from-reg:  # (payload primitive)
28338     0x11/imm32/alloc-id:fake:payload
28339     # var1/reg <- subtract lit => 81 5/subop/subtract var1/rm32 lit/imm32
28340     0x11/imm32/alloc-id:fake
28341     _string-subtract/imm32/name
28342     0x11/imm32/alloc-id:fake
28343     Single-lit-var/imm32/inouts
28344     0x11/imm32/alloc-id:fake
28345     Single-int-var-in-some-register/imm32/outputs
28346     0x11/imm32/alloc-id:fake
28347     _string_81_subop_subtract/imm32/subx-name
28348     3/imm32/rm32-is-first-output
28349     0/imm32/no-r32
28350     1/imm32/imm32-is-first-inout
28351     0/imm32/no-imm8
28352     0/imm32/no-disp32
28353     0/imm32/no-xm32
28354     0/imm32/no-x32
28355     0x11/imm32/alloc-id:fake
28356     _Primitive-subtract-lit-from-mem/imm32/next
28357 _Primitive-subtract-lit-from-mem:  # (payload primitive)
28358     0x11/imm32/alloc-id:fake:payload
28359     # subtract-from var1, lit => 81 5/subop/subtract var1/rm32 lit/imm32
28360     0x11/imm32/alloc-id:fake
28361     _string-subtract-from/imm32/name
28362     0x11/imm32/alloc-id:fake
28363     Int-var-and-literal/imm32/inouts
28364     0/imm32/no-outputs
28365     0/imm32/no-outputs
28366     0x11/imm32/alloc-id:fake
28367     _string_81_subop_subtract/imm32/subx-name
28368     1/imm32/rm32-is-first-inout
28369     0/imm32/no-r32
28370     2/imm32/imm32-is-second-inout
28371     0/imm32/no-imm8
28372     0/imm32/no-disp32
28373     0/imm32/no-xm32
28374     0/imm32/no-x32
28375     0x11/imm32/alloc-id:fake
28376     _Primitive-and-with-eax/imm32/next
28377 # - and
28378 _Primitive-and-with-eax:  # (payload primitive)
28379     0x11/imm32/alloc-id:fake:payload
28380     # var/eax <- and lit => 25/and-with-eax lit/imm32
28381     0x11/imm32/alloc-id:fake
28382     _string-and/imm32/name
28383     0x11/imm32/alloc-id:fake
28384     Single-lit-var/imm32/inouts
28385     0x11/imm32/alloc-id:fake
28386     Single-int-var-in-eax/imm32/outputs
28387     0x11/imm32/alloc-id:fake
28388     _string_25_and_with_eax/imm32/subx-name
28389     0/imm32/no-rm32
28390     0/imm32/no-r32
28391     1/imm32/imm32-is-first-inout
28392     0/imm32/no-imm8
28393     0/imm32/no-disp32
28394     0/imm32/no-xm32
28395     0/imm32/no-x32
28396     0x11/imm32/alloc-id:fake
28397     _Primitive-and-reg-with-reg/imm32/next
28398 _Primitive-and-reg-with-reg:  # (payload primitive)
28399     0x11/imm32/alloc-id:fake:payload
28400     # var1/reg <- and var2/reg => 21/and-with var1/rm32 var2/r32
28401     0x11/imm32/alloc-id:fake
28402     _string-and/imm32/name
28403     0x11/imm32/alloc-id:fake
28404     Single-int-var-in-some-register/imm32/inouts
28405     0x11/imm32/alloc-id:fake
28406     Single-int-var-in-some-register/imm32/outputs
28407     0x11/imm32/alloc-id:fake
28408     _string_21_and_with/imm32/subx-name
28409     3/imm32/rm32-is-first-output
28410     1/imm32/r32-is-first-inout
28411     0/imm32/no-imm32
28412     0/imm32/no-imm8
28413     0/imm32/no-disp32
28414     0/imm32/no-xm32
28415     0/imm32/no-x32
28416     0x11/imm32/alloc-id:fake
28417     _Primitive-and-reg-with-mem/imm32/next
28418 _Primitive-and-reg-with-mem:  # (payload primitive)
28419     0x11/imm32/alloc-id:fake:payload
28420     # and-with var1 var2/reg => 21/and-with var1 var2/r32
28421     0x11/imm32/alloc-id:fake
28422     _string-and-with/imm32/name
28423     0x11/imm32/alloc-id:fake
28424     Two-args-int-stack-int-reg/imm32/inouts
28425     0/imm32/no-outputs
28426     0/imm32/no-outputs
28427     0x11/imm32/alloc-id:fake
28428     _string_21_and_with/imm32/subx-name
28429     1/imm32/rm32-is-first-inout
28430     2/imm32/r32-is-second-inout
28431     0/imm32/no-imm32
28432     0/imm32/no-imm8
28433     0/imm32/no-disp32
28434     0/imm32/no-xm32
28435     0/imm32/no-x32
28436     0x11/imm32/alloc-id:fake
28437     _Primitive-and-mem-with-reg/imm32/next
28438 _Primitive-and-mem-with-reg:  # (payload primitive)
28439     0x11/imm32/alloc-id:fake:payload
28440     # var1/reg <- and var2 => 23/and var2/rm32 var1/r32
28441     0x11/imm32/alloc-id:fake
28442     _string-and/imm32/name
28443     0x11/imm32/alloc-id:fake
28444     Single-int-var-in-mem/imm32/inouts
28445     0x11/imm32/alloc-id:fake
28446     Single-int-var-in-some-register/imm32/outputs
28447     0x11/imm32/alloc-id:fake
28448     _string_23_and/imm32/subx-name
28449     1/imm32/rm32-is-first-inout
28450     3/imm32/r32-is-first-output
28451     0/imm32/no-imm32
28452     0/imm32/no-imm8
28453     0/imm32/no-disp32
28454     0/imm32/no-xm32
28455     0/imm32/no-x32
28456     0x11/imm32/alloc-id:fake
28457     _Primitive-and-lit-with-reg/imm32/next
28458 _Primitive-and-lit-with-reg:  # (payload primitive)
28459     0x11/imm32/alloc-id:fake:payload
28460     # var1/reg <- and lit => 81 4/subop/and var1/rm32 lit/imm32
28461     0x11/imm32/alloc-id:fake
28462     _string-and/imm32/name
28463     0x11/imm32/alloc-id:fake
28464     Single-lit-var/imm32/inouts
28465     0x11/imm32/alloc-id:fake
28466     Single-int-var-in-some-register/imm32/outputs
28467     0x11/imm32/alloc-id:fake
28468     _string_81_subop_and/imm32/subx-name
28469     3/imm32/rm32-is-first-output
28470     0/imm32/no-r32
28471     1/imm32/imm32-is-first-inout
28472     0/imm32/no-imm8
28473     0/imm32/no-disp32
28474     0/imm32/no-xm32
28475     0/imm32/no-x32
28476     0x11/imm32/alloc-id:fake
28477     _Primitive-and-lit-with-mem/imm32/next
28478 _Primitive-and-lit-with-mem:  # (payload primitive)
28479     0x11/imm32/alloc-id:fake:payload
28480     # and-with var1, lit => 81 4/subop/and var1/rm32 lit/imm32
28481     0x11/imm32/alloc-id:fake
28482     _string-and-with/imm32/name
28483     0x11/imm32/alloc-id:fake
28484     Int-var-and-literal/imm32/inouts
28485     0/imm32/no-outputs
28486     0/imm32/no-outputs
28487     0x11/imm32/alloc-id:fake
28488     _string_81_subop_and/imm32/subx-name
28489     1/imm32/rm32-is-first-inout
28490     0/imm32/no-r32
28491     2/imm32/imm32-is-second-inout
28492     0/imm32/no-imm8
28493     0/imm32/no-disp32
28494     0/imm32/no-xm32
28495     0/imm32/no-x32
28496     0x11/imm32/alloc-id:fake
28497     _Primitive-or-with-eax/imm32/next
28498 # - or
28499 _Primitive-or-with-eax:  # (payload primitive)
28500     0x11/imm32/alloc-id:fake:payload
28501     # var/eax <- or lit => 0d/or-with-eax lit/imm32
28502     0x11/imm32/alloc-id:fake
28503     _string-or/imm32/name
28504     0x11/imm32/alloc-id:fake
28505     Single-lit-var/imm32/inouts
28506     0x11/imm32/alloc-id:fake
28507     Single-int-var-in-eax/imm32/outputs
28508     0x11/imm32/alloc-id:fake
28509     _string_0d_or_with_eax/imm32/subx-name
28510     0/imm32/no-rm32
28511     0/imm32/no-r32
28512     1/imm32/imm32-is-first-inout
28513     0/imm32/no-imm8
28514     0/imm32/no-disp32
28515     0/imm32/no-xm32
28516     0/imm32/no-x32
28517     0x11/imm32/alloc-id:fake
28518     _Primitive-or-reg-with-reg/imm32/next
28519 _Primitive-or-reg-with-reg:  # (payload primitive)
28520     0x11/imm32/alloc-id:fake:payload
28521     # var1/reg <- or var2/reg => 09/or-with var1/rm32 var2/r32
28522     0x11/imm32/alloc-id:fake
28523     _string-or/imm32/name
28524     0x11/imm32/alloc-id:fake
28525     Single-int-var-in-some-register/imm32/inouts
28526     0x11/imm32/alloc-id:fake
28527     Single-int-var-in-some-register/imm32/outputs
28528     0x11/imm32/alloc-id:fake
28529     _string_09_or_with/imm32/subx-name
28530     3/imm32/rm32-is-first-output
28531     1/imm32/r32-is-first-inout
28532     0/imm32/no-imm32
28533     0/imm32/no-imm8
28534     0/imm32/no-disp32
28535     0/imm32/no-xm32
28536     0/imm32/no-x32
28537     0x11/imm32/alloc-id:fake
28538     _Primitive-or-reg-with-mem/imm32/next
28539 _Primitive-or-reg-with-mem:  # (payload primitive)
28540     0x11/imm32/alloc-id:fake:payload
28541     # or-with var1 var2/reg => 09/or-with var1 var2/r32
28542     0x11/imm32/alloc-id:fake
28543     _string-or-with/imm32/name
28544     0x11/imm32/alloc-id:fake
28545     Two-args-int-stack-int-reg/imm32/inouts
28546     0/imm32/no-outputs
28547     0/imm32/no-outputs
28548     0x11/imm32/alloc-id:fake
28549     _string_09_or_with/imm32/subx-name
28550     1/imm32/rm32-is-first-inout
28551     2/imm32/r32-is-second-inout
28552     0/imm32/no-imm32
28553     0/imm32/no-imm8
28554     0/imm32/no-disp32
28555     0/imm32/no-xm32
28556     0/imm32/no-x32
28557     0x11/imm32/alloc-id:fake
28558     _Primitive-or-mem-with-reg/imm32/next
28559 _Primitive-or-mem-with-reg:  # (payload primitive)
28560     0x11/imm32/alloc-id:fake:payload
28561     # var1/reg <- or var2 => 0b/or var2/rm32 var1/r32
28562     0x11/imm32/alloc-id:fake
28563     _string-or/imm32/name
28564     0x11/imm32/alloc-id:fake
28565     Single-int-var-in-mem/imm32/inouts
28566     0x11/imm32/alloc-id:fake
28567     Single-int-var-in-some-register/imm32/outputs
28568     0x11/imm32/alloc-id:fake
28569     _string_0b_or/imm32/subx-name
28570     1/imm32/rm32-is-first-inout
28571     3/imm32/r32-is-first-output
28572     0/imm32/no-imm32
28573     0/imm32/no-imm8
28574     0/imm32/no-disp32
28575     0/imm32/no-xm32
28576     0/imm32/no-x32
28577     0x11/imm32/alloc-id:fake
28578     _Primitive-or-lit-with-reg/imm32/next
28579 _Primitive-or-lit-with-reg:  # (payload primitive)
28580     0x11/imm32/alloc-id:fake:payload
28581     # var1/reg <- or lit => 81 1/subop/or var1/rm32 lit/imm32
28582     0x11/imm32/alloc-id:fake
28583     _string-or/imm32/name
28584     0x11/imm32/alloc-id:fake
28585     Single-lit-var/imm32/inouts
28586     0x11/imm32/alloc-id:fake
28587     Single-int-var-in-some-register/imm32/outputs
28588     0x11/imm32/alloc-id:fake
28589     _string_81_subop_or/imm32/subx-name
28590     3/imm32/rm32-is-first-output
28591     0/imm32/no-r32
28592     1/imm32/imm32-is-first-inout
28593     0/imm32/no-imm8
28594     0/imm32/no-disp32
28595     0/imm32/no-xm32
28596     0/imm32/no-x32
28597     0x11/imm32/alloc-id:fake
28598     _Primitive-or-lit-with-mem/imm32/next
28599 _Primitive-or-lit-with-mem:  # (payload primitive)
28600     0x11/imm32/alloc-id:fake:payload
28601     # or-with var1, lit => 81 1/subop/or var1/rm32 lit/imm32
28602     0x11/imm32/alloc-id:fake
28603     _string-or-with/imm32/name
28604     0x11/imm32/alloc-id:fake
28605     Int-var-and-literal/imm32/inouts
28606     0/imm32/no-outputs
28607     0/imm32/no-outputs
28608     0x11/imm32/alloc-id:fake
28609     _string_81_subop_or/imm32/subx-name
28610     1/imm32/rm32-is-first-inout
28611     0/imm32/no-r32
28612     2/imm32/imm32-is-second-inout
28613     0/imm32/no-imm8
28614     0/imm32/no-disp32
28615     0/imm32/no-xm32
28616     0/imm32/no-x32
28617     0x11/imm32/alloc-id:fake
28618     _Primitive-xor-with-eax/imm32/next
28619 # - xor
28620 _Primitive-xor-with-eax:  # (payload primitive)
28621     0x11/imm32/alloc-id:fake:payload
28622     # var/eax <- xor lit => 35/xor-with-eax lit/imm32
28623     0x11/imm32/alloc-id:fake
28624     _string-xor/imm32/name
28625     0x11/imm32/alloc-id:fake
28626     Single-lit-var/imm32/inouts
28627     0x11/imm32/alloc-id:fake
28628     Single-int-var-in-eax/imm32/outputs
28629     0x11/imm32/alloc-id:fake
28630     _string_35_xor_with_eax/imm32/subx-name
28631     0/imm32/no-rm32
28632     0/imm32/no-r32
28633     1/imm32/imm32-is-first-inout
28634     0/imm32/no-imm8
28635     0/imm32/no-disp32
28636     0/imm32/no-xm32
28637     0/imm32/no-x32
28638     0x11/imm32/alloc-id:fake
28639     _Primitive-xor-reg-with-reg/imm32/next
28640 _Primitive-xor-reg-with-reg:  # (payload primitive)
28641     0x11/imm32/alloc-id:fake:payload
28642     # var1/reg <- xor var2/reg => 31/xor-with var1/rm32 var2/r32
28643     0x11/imm32/alloc-id:fake
28644     _string-xor/imm32/name
28645     0x11/imm32/alloc-id:fake
28646     Single-int-var-in-some-register/imm32/inouts
28647     0x11/imm32/alloc-id:fake
28648     Single-int-var-in-some-register/imm32/outputs
28649     0x11/imm32/alloc-id:fake
28650     _string_31_xor_with/imm32/subx-name
28651     3/imm32/rm32-is-first-output
28652     1/imm32/r32-is-first-inout
28653     0/imm32/no-imm32
28654     0/imm32/no-imm8
28655     0/imm32/no-disp32
28656     0/imm32/no-xm32
28657     0/imm32/no-x32
28658     0x11/imm32/alloc-id:fake
28659     _Primitive-xor-reg-with-mem/imm32/next
28660 _Primitive-xor-reg-with-mem:  # (payload primitive)
28661     0x11/imm32/alloc-id:fake:payload
28662     # xor-with var1 var2/reg => 31/xor-with var1 var2/r32
28663     0x11/imm32/alloc-id:fake
28664     _string-xor-with/imm32/name
28665     0x11/imm32/alloc-id:fake
28666     Two-args-int-stack-int-reg/imm32/inouts
28667     0/imm32/no-outputs
28668     0/imm32/no-outputs
28669     0x11/imm32/alloc-id:fake
28670     _string_31_xor_with/imm32/subx-name
28671     1/imm32/rm32-is-first-inout
28672     2/imm32/r32-is-second-inout
28673     0/imm32/no-imm32
28674     0/imm32/no-imm8
28675     0/imm32/no-disp32
28676     0/imm32/no-xm32
28677     0/imm32/no-x32
28678     0x11/imm32/alloc-id:fake
28679     _Primitive-xor-mem-with-reg/imm32/next
28680 _Primitive-xor-mem-with-reg:  # (payload primitive)
28681     0x11/imm32/alloc-id:fake:payload
28682     # var1/reg <- xor var2 => 33/xor var2/rm32 var1/r32
28683     0x11/imm32/alloc-id:fake
28684     _string-xor/imm32/name
28685     0x11/imm32/alloc-id:fake
28686     Single-int-var-in-mem/imm32/inouts
28687     0x11/imm32/alloc-id:fake
28688     Single-int-var-in-some-register/imm32/outputs
28689     0x11/imm32/alloc-id:fake
28690     _string_33_xor/imm32/subx-name
28691     1/imm32/rm32-is-first-inout
28692     3/imm32/r32-is-first-output
28693     0/imm32/no-imm32
28694     0/imm32/no-imm8
28695     0/imm32/no-disp32
28696     0/imm32/no-xm32
28697     0/imm32/no-x32
28698     0x11/imm32/alloc-id:fake
28699     _Primitive-xor-lit-with-reg/imm32/next
28700 _Primitive-xor-lit-with-reg:  # (payload primitive)
28701     0x11/imm32/alloc-id:fake:payload
28702     # var1/reg <- xor lit => 81 6/subop/xor var1/rm32 lit/imm32
28703     0x11/imm32/alloc-id:fake
28704     _string-xor/imm32/name
28705     0x11/imm32/alloc-id:fake
28706     Single-lit-var/imm32/inouts
28707     0x11/imm32/alloc-id:fake
28708     Single-int-var-in-some-register/imm32/outputs
28709     0x11/imm32/alloc-id:fake
28710     _string_81_subop_xor/imm32/subx-name
28711     3/imm32/rm32-is-first-output
28712     0/imm32/no-r32
28713     1/imm32/imm32-is-first-inout
28714     0/imm32/no-imm8
28715     0/imm32/no-disp32
28716     0/imm32/no-xm32
28717     0/imm32/no-x32
28718     0x11/imm32/alloc-id:fake
28719     _Primitive-xor-lit-with-mem/imm32/next
28720 _Primitive-xor-lit-with-mem:  # (payload primitive)
28721     0x11/imm32/alloc-id:fake:payload
28722     # xor-with var1, lit => 81 6/subop/xor var1/rm32 lit/imm32
28723     0x11/imm32/alloc-id:fake
28724     _string-xor-with/imm32/name
28725     0x11/imm32/alloc-id:fake
28726     Int-var-and-literal/imm32/inouts
28727     0/imm32/no-outputs
28728     0/imm32/no-outputs
28729     0x11/imm32/alloc-id:fake
28730     _string_81_subop_xor/imm32/subx-name
28731     1/imm32/rm32-is-first-inout
28732     0/imm32/no-r32
28733     2/imm32/imm32-is-second-inout
28734     0/imm32/no-imm8
28735     0/imm32/no-disp32
28736     0/imm32/no-xm32
28737     0/imm32/no-x32
28738     0x11/imm32/alloc-id:fake
28739     _Primitive-shift-reg-left-by-lit/imm32/next
28740 _Primitive-shift-reg-left-by-lit:  # (payload primitive)
28741     0x11/imm32/alloc-id:fake:payload
28742     # var1/reg <- shift-left lit => c1/shift 4/subop/left var1/rm32 lit/imm32
28743     0x11/imm32/alloc-id:fake
28744     _string-shift-left/imm32/name
28745     0x11/imm32/alloc-id:fake
28746     Single-lit-var/imm32/inouts
28747     0x11/imm32/alloc-id:fake
28748     Single-int-var-in-some-register/imm32/outputs
28749     0x11/imm32/alloc-id:fake
28750     _string_c1_subop_shift_left/imm32/subx-name
28751     3/imm32/rm32-is-first-output
28752     0/imm32/no-r32
28753     0/imm32/no-imm32
28754     1/imm32/imm8-is-first-inout
28755     0/imm32/no-disp32
28756     0/imm32/no-xm32
28757     0/imm32/no-x32
28758     0x11/imm32/alloc-id:fake
28759     _Primitive-shift-reg-right-by-lit/imm32/next
28760 _Primitive-shift-reg-right-by-lit:  # (payload primitive)
28761     0x11/imm32/alloc-id:fake:payload
28762     # var1/reg <- shift-right lit => c1/shift 5/subop/right var1/rm32 lit/imm32
28763     0x11/imm32/alloc-id:fake
28764     _string-shift-right/imm32/name
28765     0x11/imm32/alloc-id:fake
28766     Single-lit-var/imm32/inouts
28767     0x11/imm32/alloc-id:fake
28768     Single-int-var-in-some-register/imm32/outputs
28769     0x11/imm32/alloc-id:fake
28770     _string_c1_subop_shift_right_padding_zeroes/imm32/subx-name
28771     3/imm32/rm32-is-first-output
28772     0/imm32/no-r32
28773     0/imm32/no-imm32
28774     1/imm32/imm8-is-first-inout
28775     0/imm32/no-disp32
28776     0/imm32/no-xm32
28777     0/imm32/no-x32
28778     0x11/imm32/alloc-id:fake
28779     _Primitive-shift-reg-right-signed-by-lit/imm32/next
28780 _Primitive-shift-reg-right-signed-by-lit:  # (payload primitive)
28781     0x11/imm32/alloc-id:fake:payload
28782     # var1/reg <- shift-right-signed lit => c1/shift 7/subop/right-preserving-sign var1/rm32 lit/imm32
28783     0x11/imm32/alloc-id:fake
28784     _string-shift-right-signed/imm32/name
28785     0x11/imm32/alloc-id:fake
28786     Single-lit-var/imm32/inouts
28787     0x11/imm32/alloc-id:fake
28788     Single-int-var-in-some-register/imm32/outputs
28789     0x11/imm32/alloc-id:fake
28790     _string_c1_subop_shift_right_preserving_sign/imm32/subx-name
28791     3/imm32/rm32-is-first-output
28792     0/imm32/no-r32
28793     0/imm32/no-imm32
28794     1/imm32/imm8-is-first-inout
28795     0/imm32/no-disp32
28796     0/imm32/no-xm32
28797     0/imm32/no-x32
28798     0x11/imm32/alloc-id:fake
28799     _Primitive-shift-mem-left-by-lit/imm32/next
28800 _Primitive-shift-mem-left-by-lit:  # (payload primitive)
28801     0x11/imm32/alloc-id:fake:payload
28802     # shift-left var1, lit => c1/shift 4/subop/left var1/rm32 lit/imm32
28803     0x11/imm32/alloc-id:fake
28804     _string-shift-left/imm32/name
28805     0x11/imm32/alloc-id:fake
28806     Int-var-and-literal/imm32/inouts
28807     0/imm32/no-outputs
28808     0/imm32/no-outputs
28809     0x11/imm32/alloc-id:fake
28810     _string_c1_subop_shift_left/imm32/subx-name
28811     1/imm32/rm32-is-first-inout
28812     0/imm32/no-r32
28813     0/imm32/no-imm32
28814     2/imm32/imm8-is-second-inout
28815     0/imm32/no-disp32
28816     0/imm32/no-xm32
28817     0/imm32/no-x32
28818     0x11/imm32/alloc-id:fake
28819     _Primitive-shift-mem-right-by-lit/imm32/next
28820 _Primitive-shift-mem-right-by-lit:  # (payload primitive)
28821     0x11/imm32/alloc-id:fake:payload
28822     # shift-right var1, lit => c1/shift 5/subop/right var1/rm32 lit/imm32
28823     0x11/imm32/alloc-id:fake
28824     _string-shift-right/imm32/name
28825     0x11/imm32/alloc-id:fake
28826     Int-var-and-literal/imm32/inouts
28827     0/imm32/no-outputs
28828     0/imm32/no-outputs
28829     0x11/imm32/alloc-id:fake
28830     _string_c1_subop_shift_right_padding_zeroes/imm32/subx-name
28831     1/imm32/rm32-is-first-inout
28832     0/imm32/no-r32
28833     0/imm32/no-imm32
28834     2/imm32/imm8-is-second-inout
28835     0/imm32/no-disp32
28836     0/imm32/no-xm32
28837     0/imm32/no-x32
28838     0x11/imm32/alloc-id:fake
28839     _Primitive-shift-mem-right-signed-by-lit/imm32/next
28840 _Primitive-shift-mem-right-signed-by-lit:  # (payload primitive)
28841     0x11/imm32/alloc-id:fake:payload
28842     # shift-right-signed var1, lit => c1/shift 7/subop/right-preserving-sign var1/rm32 lit/imm32
28843     0x11/imm32/alloc-id:fake
28844     _string-shift-right-signed/imm32/name
28845     0x11/imm32/alloc-id:fake
28846     Int-var-and-literal/imm32/inouts
28847     0/imm32/no-outputs
28848     0/imm32/no-outputs
28849     0x11/imm32/alloc-id:fake
28850     _string_c1_subop_shift_right_preserving_sign/imm32/subx-name
28851     1/imm32/rm32-is-first-inout
28852     0/imm32/no-r32
28853     0/imm32/no-imm32
28854     2/imm32/imm8-is-second-inout
28855     0/imm32/no-disp32
28856     0/imm32/no-xm32
28857     0/imm32/no-x32
28858     0x11/imm32/alloc-id:fake
28859     _Primitive-copy-to-eax/imm32/next
28860 # - copy
28861 _Primitive-copy-to-eax:  # (payload primitive)
28862     0x11/imm32/alloc-id:fake:payload
28863     # var/eax <- copy lit => b8/copy-to-eax lit/imm32
28864     0x11/imm32/alloc-id:fake
28865     _string-copy/imm32/name
28866     0x11/imm32/alloc-id:fake
28867     Single-lit-var/imm32/inouts
28868     0x11/imm32/alloc-id:fake
28869     Single-int-var-in-eax/imm32/outputs
28870     0x11/imm32/alloc-id:fake
28871     _string_b8_copy_to_eax/imm32/subx-name
28872     0/imm32/no-rm32
28873     0/imm32/no-r32
28874     1/imm32/imm32-is-first-inout
28875     0/imm32/no-imm8
28876     0/imm32/no-disp32
28877     0/imm32/no-xm32
28878     0/imm32/no-x32
28879     0x11/imm32/alloc-id:fake
28880     _Primitive-copy-to-ecx/imm32/next
28881 _Primitive-copy-to-ecx:  # (payload primitive)
28882     0x11/imm32/alloc-id:fake:payload
28883     # var/ecx <- copy lit => b9/copy-to-ecx lit/imm32
28884     0x11/imm32/alloc-id:fake
28885     _string-copy/imm32/name
28886     0x11/imm32/alloc-id:fake
28887     Single-lit-var/imm32/inouts
28888     0x11/imm32/alloc-id:fake
28889     Single-int-var-in-ecx/imm32/outputs
28890     0x11/imm32/alloc-id:fake
28891     _string_b9_copy_to_ecx/imm32/subx-name
28892     0/imm32/no-rm32
28893     0/imm32/no-r32
28894     1/imm32/imm32-is-first-inout
28895     0/imm32/no-imm8
28896     0/imm32/no-disp32
28897     0/imm32/no-xm32
28898     0/imm32/no-x32
28899     0x11/imm32/alloc-id:fake
28900     _Primitive-copy-to-edx/imm32/next
28901 _Primitive-copy-to-edx:  # (payload primitive)
28902     0x11/imm32/alloc-id:fake:payload
28903     # var/edx <- copy lit => ba/copy-to-edx lit/imm32
28904     0x11/imm32/alloc-id:fake
28905     _string-copy/imm32/name
28906     0x11/imm32/alloc-id:fake
28907     Single-lit-var/imm32/inouts
28908     0x11/imm32/alloc-id:fake
28909     Single-int-var-in-edx/imm32/outputs
28910     0x11/imm32/alloc-id:fake
28911     _string_ba_copy_to_edx/imm32/subx-name
28912     0/imm32/no-rm32
28913     0/imm32/no-r32
28914     1/imm32/imm32-is-first-inout
28915     0/imm32/no-imm8
28916     0/imm32/no-disp32
28917     0/imm32/no-xm32
28918     0/imm32/no-x32
28919     0x11/imm32/alloc-id:fake
28920     _Primitive-copy-to-ebx/imm32/next
28921 _Primitive-copy-to-ebx:  # (payload primitive)
28922     0x11/imm32/alloc-id:fake:payload
28923     # var/ebx <- copy lit => bb/copy-to-ebx lit/imm32
28924     0x11/imm32/alloc-id:fake
28925     _string-copy/imm32/name
28926     0x11/imm32/alloc-id:fake
28927     Single-lit-var/imm32/inouts
28928     0x11/imm32/alloc-id:fake
28929     Single-int-var-in-ebx/imm32/outputs
28930     0x11/imm32/alloc-id:fake
28931     _string_bb_copy_to_ebx/imm32/subx-name
28932     0/imm32/no-rm32
28933     0/imm32/no-r32
28934     1/imm32/imm32-is-first-inout
28935     0/imm32/no-imm8
28936     0/imm32/no-disp32
28937     0/imm32/no-xm32
28938     0/imm32/no-x32
28939     0x11/imm32/alloc-id:fake
28940     _Primitive-copy-to-esi/imm32/next
28941 _Primitive-copy-to-esi:  # (payload primitive)
28942     0x11/imm32/alloc-id:fake:payload
28943     # var/esi <- copy lit => be/copy-to-esi lit/imm32
28944     0x11/imm32/alloc-id:fake
28945     _string-copy/imm32/name
28946     0x11/imm32/alloc-id:fake
28947     Single-lit-var/imm32/inouts
28948     0x11/imm32/alloc-id:fake
28949     Single-int-var-in-esi/imm32/outputs
28950     0x11/imm32/alloc-id:fake
28951     _string_be_copy_to_esi/imm32/subx-name
28952     0/imm32/no-rm32
28953     0/imm32/no-r32
28954     1/imm32/imm32-is-first-inout
28955     0/imm32/no-imm8
28956     0/imm32/no-disp32
28957     0/imm32/no-xm32
28958     0/imm32/no-x32
28959     0x11/imm32/alloc-id:fake
28960     _Primitive-copy-to-edi/imm32/next
28961 _Primitive-copy-to-edi:  # (payload primitive)
28962     0x11/imm32/alloc-id:fake:payload
28963     # var/edi <- copy lit => bf/copy-to-edi lit/imm32
28964     0x11/imm32/alloc-id:fake
28965     _string-copy/imm32/name
28966     0x11/imm32/alloc-id:fake
28967     Single-lit-var/imm32/inouts
28968     0x11/imm32/alloc-id:fake
28969     Single-int-var-in-edi/imm32/outputs
28970     0x11/imm32/alloc-id:fake
28971     _string_bf_copy_to_edi/imm32/subx-name
28972     0/imm32/no-rm32
28973     0/imm32/no-r32
28974     1/imm32/imm32-is-first-inout
28975     0/imm32/no-imm8
28976     0/imm32/no-disp32
28977     0/imm32/no-xm32
28978     0/imm32/no-x32
28979     0x11/imm32/alloc-id:fake
28980     _Primitive-copy-reg-to-reg/imm32/next
28981 _Primitive-copy-reg-to-reg:  # (payload primitive)
28982     0x11/imm32/alloc-id:fake:payload
28983     # var1/reg <- copy var2/reg => 89/<- var1/rm32 var2/r32
28984     0x11/imm32/alloc-id:fake
28985     _string-copy/imm32/name
28986     0x11/imm32/alloc-id:fake
28987     Single-int-var-in-some-register/imm32/inouts
28988     0x11/imm32/alloc-id:fake
28989     Single-int-var-in-some-register/imm32/outputs
28990     0x11/imm32/alloc-id:fake
28991     _string_89_<-/imm32/subx-name
28992     3/imm32/rm32-is-first-output
28993     1/imm32/r32-is-first-inout
28994     0/imm32/no-imm32
28995     0/imm32/no-imm8
28996     0/imm32/no-disp32
28997     0/imm32/no-xm32
28998     0/imm32/no-x32
28999     0x11/imm32/alloc-id:fake
29000     _Primitive-copy-reg-to-mem/imm32/next
29001 _Primitive-copy-reg-to-mem:  # (payload primitive)
29002     0x11/imm32/alloc-id:fake:payload
29003     # copy-to var1 var2/reg => 89/<- var1 var2/r32
29004     0x11/imm32/alloc-id:fake
29005     _string-copy-to/imm32/name
29006     0x11/imm32/alloc-id:fake
29007     Two-args-int-stack-int-reg/imm32/inouts
29008     0/imm32/no-outputs
29009     0/imm32/no-outputs
29010     0x11/imm32/alloc-id:fake
29011     _string_89_<-/imm32/subx-name
29012     1/imm32/rm32-is-first-inout
29013     2/imm32/r32-is-second-inout
29014     0/imm32/no-imm32
29015     0/imm32/no-imm8
29016     0/imm32/no-disp32
29017     0/imm32/no-xm32
29018     0/imm32/no-x32
29019     0x11/imm32/alloc-id:fake
29020     _Primitive-copy-mem-to-reg/imm32/next
29021 _Primitive-copy-mem-to-reg:  # (payload primitive)
29022     0x11/imm32/alloc-id:fake:payload
29023     # var1/reg <- copy var2 => 8b/-> var2/rm32 var1/r32
29024     0x11/imm32/alloc-id:fake
29025     _string-copy/imm32/name
29026     0x11/imm32/alloc-id:fake
29027     Single-int-var-in-mem/imm32/inouts
29028     0x11/imm32/alloc-id:fake
29029     Single-int-var-in-some-register/imm32/outputs
29030     0x11/imm32/alloc-id:fake
29031     _string_8b_->/imm32/subx-name
29032     1/imm32/rm32-is-first-inout
29033     3/imm32/r32-is-first-output
29034     0/imm32/no-imm32
29035     0/imm32/no-imm8
29036     0/imm32/no-disp32
29037     0/imm32/no-xm32
29038     0/imm32/no-x32
29039     0x11/imm32/alloc-id:fake
29040     _Primitive-copy-lit-to-reg/imm32/next
29041 _Primitive-copy-lit-to-reg:  # (payload primitive)
29042     0x11/imm32/alloc-id:fake:payload
29043     # var1/reg <- copy lit => c7 0/subop/copy var1/rm32 lit/imm32
29044     0x11/imm32/alloc-id:fake
29045     _string-copy/imm32/name
29046     0x11/imm32/alloc-id:fake
29047     Single-lit-var/imm32/inouts
29048     0x11/imm32/alloc-id:fake
29049     Single-int-var-in-some-register/imm32/outputs
29050     0x11/imm32/alloc-id:fake
29051     _string_c7_subop_copy/imm32/subx-name
29052     3/imm32/rm32-is-first-output
29053     0/imm32/no-r32
29054     1/imm32/imm32-is-first-inout
29055     0/imm32/no-imm8
29056     0/imm32/no-disp32
29057     0/imm32/no-xm32
29058     0/imm32/no-x32
29059     0x11/imm32/alloc-id:fake
29060     _Primitive-copy-lit-to-mem/imm32/next
29061 _Primitive-copy-lit-to-mem:  # (payload primitive)
29062     0x11/imm32/alloc-id:fake:payload
29063     # copy-to var1, lit => c7 0/subop/copy var1/rm32 lit/imm32
29064     0x11/imm32/alloc-id:fake
29065     _string-copy-to/imm32/name
29066     0x11/imm32/alloc-id:fake
29067     Int-var-and-literal/imm32/inouts
29068     0/imm32/no-outputs
29069     0/imm32/no-outputs
29070     0x11/imm32/alloc-id:fake
29071     _string_c7_subop_copy/imm32/subx-name
29072     1/imm32/rm32-is-first-inout
29073     0/imm32/no-r32
29074     2/imm32/imm32-is-second-inout
29075     0/imm32/no-imm8
29076     0/imm32/no-disp32
29077     0/imm32/no-xm32
29078     0/imm32/no-x32
29079     0x11/imm32/alloc-id:fake
29080     _Primitive-copy-byte-from-reg/imm32/next
29081 # - copy byte
29082 _Primitive-copy-byte-from-reg:
29083     0x11/imm32/alloc-id:fake:payload
29084     # var/reg <- copy-byte var2/reg2 => 8a/byte-> %var2 var/r32
29085     0x11/imm32/alloc-id:fake
29086     _string-copy-byte/imm32/name
29087     0x11/imm32/alloc-id:fake
29088     Single-byte-var-in-some-register/imm32/inouts
29089     0x11/imm32/alloc-id:fake
29090     Single-byte-var-in-some-register/imm32/outputs
29091     0x11/imm32/alloc-id:fake
29092     _string_8a_copy_byte/imm32/subx-name
29093     1/imm32/rm32-is-first-inout
29094     3/imm32/r32-is-first-output
29095     0/imm32/no-imm32
29096     0/imm32/no-imm8
29097     0/imm32/no-disp32
29098     0/imm32/no-xm32
29099     0/imm32/no-x32
29100     0x11/imm32/alloc-id:fake
29101     _Primitive-copy-byte-from-mem/imm32/next
29102 _Primitive-copy-byte-from-mem:
29103     0x11/imm32/alloc-id:fake:payload
29104     # var/reg <- copy-byte *var2/reg2 => 8a/byte-> *var2 var/r32
29105     0x11/imm32/alloc-id:fake
29106     _string-copy-byte/imm32/name
29107     0x11/imm32/alloc-id:fake
29108     Single-byte-var-in-mem/imm32/inouts
29109     0x11/imm32/alloc-id:fake
29110     Single-byte-var-in-some-register/imm32/outputs
29111     0x11/imm32/alloc-id:fake
29112     _string_8a_copy_byte/imm32/subx-name
29113     1/imm32/rm32-is-first-inout
29114     3/imm32/r32-is-first-output
29115     0/imm32/no-imm32
29116     0/imm32/no-imm8
29117     0/imm32/no-disp32
29118     0/imm32/no-xm32
29119     0/imm32/no-x32
29120     0x11/imm32/alloc-id:fake
29121     _Primitive-copy-byte-to-mem/imm32/next
29122 _Primitive-copy-byte-to-mem:
29123     0x11/imm32/alloc-id:fake:payload
29124     # copy-byte-to *var1/reg1, var2/reg2 => 88/byte<- *reg1 reg2/r32
29125     0x11/imm32/alloc-id:fake
29126     _string-copy-byte-to/imm32/name
29127     0x11/imm32/alloc-id:fake
29128     Two-args-byte-stack-byte-reg/imm32/inouts
29129     0/imm32/no-outputs
29130     0/imm32/no-outputs
29131     0x11/imm32/alloc-id:fake
29132     _string_88_copy_byte/imm32/subx-name
29133     1/imm32/rm32-is-first-inout
29134     2/imm32/r32-is-second-inout
29135     0/imm32/no-imm32
29136     0/imm32/no-imm8
29137     0/imm32/no-disp32
29138     0/imm32/no-xm32
29139     0/imm32/no-x32
29140     0x11/imm32/alloc-id:fake
29141     _Primitive-address/imm32/next
29142 # - address
29143 _Primitive-address:  # (payload primitive)
29144     0x11/imm32/alloc-id:fake:payload
29145     # var1/reg <- address var2 => 8d/copy-address var2/rm32 var1/r32
29146     0x11/imm32/alloc-id:fake
29147     _string-address/imm32/name
29148     0x11/imm32/alloc-id:fake
29149     Single-int-var-in-mem/imm32/inouts
29150     0x11/imm32/alloc-id:fake
29151     Single-addr-var-in-some-register/imm32/outputs
29152     0x11/imm32/alloc-id:fake
29153     _string_8d_copy_address/imm32/subx-name
29154     1/imm32/rm32-is-first-inout
29155     3/imm32/r32-is-first-output
29156     0/imm32/no-imm32
29157     0/imm32/no-imm8
29158     0/imm32/no-disp32
29159     0/imm32/no-xm32
29160     0/imm32/no-x32
29161     0x11/imm32/alloc-id:fake
29162     _Primitive-compare-reg-with-reg/imm32/next
29163 # - compare
29164 _Primitive-compare-reg-with-reg:  # (payload primitive)
29165     0x11/imm32/alloc-id:fake:payload
29166     # compare var1/reg1 var2/reg2 => 39/compare var1/rm32 var2/r32
29167     0x11/imm32/alloc-id:fake
29168     _string-compare/imm32/name
29169     0x11/imm32/alloc-id:fake
29170     Two-int-args-in-regs/imm32/inouts
29171     0/imm32/no-outputs
29172     0/imm32/no-outputs
29173     0x11/imm32/alloc-id:fake
29174     _string_39_compare->/imm32/subx-name
29175     1/imm32/rm32-is-first-inout
29176     2/imm32/r32-is-second-inout
29177     0/imm32/no-imm32
29178     0/imm32/no-imm8
29179     0/imm32/no-disp32
29180     0/imm32/no-xm32
29181     0/imm32/no-x32
29182     0x11/imm32/alloc-id:fake
29183     _Primitive-compare-mem-with-reg/imm32/next
29184 _Primitive-compare-mem-with-reg:  # (payload primitive)
29185     0x11/imm32/alloc-id:fake:payload
29186     # compare var1 var2/reg => 39/compare var1/rm32 var2/r32
29187     0x11/imm32/alloc-id:fake
29188     _string-compare/imm32/name
29189     0x11/imm32/alloc-id:fake
29190     Two-args-int-stack-int-reg/imm32/inouts
29191     0/imm32/no-outputs
29192     0/imm32/no-outputs
29193     0x11/imm32/alloc-id:fake
29194     _string_39_compare->/imm32/subx-name
29195     1/imm32/rm32-is-first-inout
29196     2/imm32/r32-is-second-inout
29197     0/imm32/no-imm32
29198     0/imm32/no-imm8
29199     0/imm32/no-disp32
29200     0/imm32/no-xm32
29201     0/imm32/no-x32
29202     0x11/imm32/alloc-id:fake
29203     _Primitive-compare-reg-with-mem/imm32/next
29204 _Primitive-compare-reg-with-mem:  # (payload primitive)
29205     0x11/imm32/alloc-id:fake:payload
29206     # compare var1/reg var2 => 3b/compare<- var2/rm32 var1/r32
29207     0x11/imm32/alloc-id:fake
29208     _string-compare/imm32/name
29209     0x11/imm32/alloc-id:fake
29210     Two-args-int-reg-int-stack/imm32/inouts
29211     0/imm32/no-outputs
29212     0/imm32/no-outputs
29213     0x11/imm32/alloc-id:fake
29214     _string_3b_compare<-/imm32/subx-name
29215     2/imm32/rm32-is-second-inout
29216     1/imm32/r32-is-first-inout
29217     0/imm32/no-imm32
29218     0/imm32/no-imm8
29219     0/imm32/no-disp32
29220     0/imm32/no-xm32
29221     0/imm32/no-x32
29222     0x11/imm32/alloc-id:fake
29223     _Primitive-compare-eax-with-literal/imm32/next
29224 _Primitive-compare-eax-with-literal:  # (payload primitive)
29225     0x11/imm32/alloc-id:fake:payload
29226     # compare var1/eax n => 3d/compare-eax-with n/imm32
29227     0x11/imm32/alloc-id:fake
29228     _string-compare/imm32/name
29229     0x11/imm32/alloc-id:fake
29230     Two-args-int-eax-int-literal/imm32/inouts
29231     0/imm32/no-outputs
29232     0/imm32/no-outputs
29233     0x11/imm32/alloc-id:fake
29234     _string_3d_compare_eax_with/imm32/subx-name
29235     0/imm32/no-rm32
29236     0/imm32/no-r32
29237     2/imm32/imm32-is-second-inout
29238     0/imm32/no-imm8
29239     0/imm32/no-disp32
29240     0/imm32/no-xm32
29241     0/imm32/no-x32
29242     0x11/imm32/alloc-id:fake
29243     _Primitive-compare-reg-with-literal/imm32/next
29244 _Primitive-compare-reg-with-literal:  # (payload primitive)
29245     0x11/imm32/alloc-id:fake:payload
29246     # compare var1/reg n => 81 7/subop/compare %reg n/imm32
29247     0x11/imm32/alloc-id:fake
29248     _string-compare/imm32/name
29249     0x11/imm32/alloc-id:fake
29250     Int-var-in-register-and-literal/imm32/inouts
29251     0/imm32/no-outputs
29252     0/imm32/no-outputs
29253     0x11/imm32/alloc-id:fake
29254     _string_81_subop_compare/imm32/subx-name
29255     1/imm32/rm32-is-first-inout
29256     0/imm32/no-r32
29257     2/imm32/imm32-is-second-inout
29258     0/imm32/no-imm8
29259     0/imm32/no-disp32
29260     0/imm32/no-xm32
29261     0/imm32/no-x32
29262     0x11/imm32/alloc-id:fake
29263     _Primitive-compare-mem-with-literal/imm32/next
29264 _Primitive-compare-mem-with-literal:  # (payload primitive)
29265     0x11/imm32/alloc-id:fake:payload
29266     # compare var1 n => 81 7/subop/compare *(ebp+___) n/imm32
29267     0x11/imm32/alloc-id:fake
29268     _string-compare/imm32/name
29269     0x11/imm32/alloc-id:fake
29270     Int-var-and-literal/imm32/inouts
29271     0/imm32/no-outputs
29272     0/imm32/no-outputs
29273     0x11/imm32/alloc-id:fake
29274     _string_81_subop_compare/imm32/subx-name
29275     1/imm32/rm32-is-first-inout
29276     0/imm32/no-r32
29277     2/imm32/imm32-is-second-inout
29278     0/imm32/no-imm8
29279     0/imm32/no-disp32
29280     0/imm32/no-xm32
29281     0/imm32/no-x32
29282     0x11/imm32/alloc-id:fake
29283     _Primitive-negate-reg/imm32/next
29284 # - negate
29285 _Primitive-negate-reg:  # (payload primitive)
29286     0x11/imm32/alloc-id:fake:payload
29287     # var1/reg <- negate => f7 3/subop/negate var1/rm32
29288     0x11/imm32/alloc-id:fake
29289     _string-negate/imm32/name
29290     0/imm32/no-inouts
29291     0/imm32/no-inouts
29292     0x11/imm32/alloc-id:fake
29293     Single-int-var-in-some-register/imm32/outputs
29294     0x11/imm32/alloc-id:fake
29295     _string_f7_subop_negate/imm32/subx-name
29296     3/imm32/rm32-is-first-output
29297     0/imm32/no-r32
29298     0/imm32/no-imm32
29299     0/imm32/no-imm8
29300     0/imm32/no-disp32
29301     0/imm32/no-xm32
29302     0/imm32/no-x32
29303     0x11/imm32/alloc-id:fake
29304     _Primitive-negate-mem/imm32/next
29305 _Primitive-negate-mem:  # (payload primitive)
29306     0x11/imm32/alloc-id:fake:payload
29307     # negate var1 => f7 3/subop/negate var1/rm32
29308     0x11/imm32/alloc-id:fake
29309     _string-negate/imm32/name
29310     0x11/imm32/alloc-id:fake
29311     Single-int-var-in-mem/imm32/inouts
29312     0/imm32/no-outputs
29313     0/imm32/no-outputs
29314     0x11/imm32/alloc-id:fake
29315     _string_f7_subop_negate/imm32/subx-name
29316     1/imm32/rm32-is-first-inout
29317     0/imm32/no-r32
29318     0/imm32/no-imm32
29319     0/imm32/no-imm8
29320     0/imm32/no-disp32
29321     0/imm32/no-xm32
29322     0/imm32/no-x32
29323     0x11/imm32/alloc-id:fake
29324     _Primitive-multiply-reg-by-reg/imm32/next
29325 # - multiply
29326 _Primitive-multiply-reg-by-reg:  # (payload primitive)
29327     0x11/imm32/alloc-id:fake:payload
29328     # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32
29329     0x11/imm32/alloc-id:fake
29330     _string-multiply/imm32/name
29331     0x11/imm32/alloc-id:fake
29332     Single-int-var-in-some-register/imm32/inouts
29333     0x11/imm32/alloc-id:fake
29334     Single-int-var-in-some-register/imm32/outputs
29335     0x11/imm32/alloc-id:fake
29336     _string_0f_af_multiply/imm32/subx-name
29337     1/imm32/rm32-is-first-inout
29338     3/imm32/r32-is-first-output
29339     0/imm32/no-imm32
29340     0/imm32/no-imm8
29341     0/imm32/no-disp32
29342     0/imm32/no-xm32
29343     0/imm32/no-x32
29344     0x11/imm32/alloc-id:fake
29345     _Primitive-multiply-reg-by-mem/imm32/next
29346 _Primitive-multiply-reg-by-mem:  # (payload primitive)
29347     0x11/imm32/alloc-id:fake:payload
29348     # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32
29349     0x11/imm32/alloc-id:fake
29350     _string-multiply/imm32/name
29351     0x11/imm32/alloc-id:fake
29352     Single-int-var-in-mem/imm32/inouts
29353     0x11/imm32/alloc-id:fake
29354     Single-int-var-in-some-register/imm32/outputs
29355     0x11/imm32/alloc-id:fake
29356     _string_0f_af_multiply/imm32/subx-name
29357     1/imm32/rm32-is-first-inout
29358     3/imm32/r32-is-first-output
29359     0/imm32/no-imm32
29360     0/imm32/no-imm8
29361     0/imm32/no-disp32
29362     0/imm32/no-xm32
29363     0/imm32/no-x32
29364     0x11/imm32/alloc-id:fake
29365     _Primitive-convert-mem-to-xreg/imm32/next
29366 # - convert int to floating point
29367 _Primitive-convert-mem-to-xreg:  # (payload primitive)
29368     0x11/imm32/alloc-id:fake:payload
29369     # var1/xreg <- convert var2 => f3 0f 2a/convert-to-float var2/rm32 var1/x32
29370     0x11/imm32/alloc-id:fake
29371     _string-convert/imm32/name
29372     0x11/imm32/alloc-id:fake
29373     Single-int-var-in-mem/imm32/inouts
29374     0x11/imm32/alloc-id:fake
29375     Single-float-var-in-some-register/imm32/outputs
29376     0x11/imm32/alloc-id:fake
29377     _string_f3_0f_2a_convert_to_float/imm32/subx-name
29378     1/imm32/rm32-is-first-inout
29379     0/imm32/no-r32
29380     0/imm32/no-imm32
29381     0/imm32/no-imm8
29382     0/imm32/no-disp32
29383     0/imm32/no-xm32
29384     3/imm32/x32-is-first-output
29385     0x11/imm32/alloc-id:fake
29386     _Primitive-convert-reg-to-xreg/imm32/next
29387 _Primitive-convert-reg-to-xreg:  # (payload primitive)
29388     0x11/imm32/alloc-id:fake:payload
29389     # var1/xreg <- convert var2/reg => f3 0f 2a/convert-to-float var2/rm32 var1/x32
29390     0x11/imm32/alloc-id:fake
29391     _string-convert/imm32/name
29392     0x11/imm32/alloc-id:fake
29393     Single-int-var-in-some-register/imm32/inouts
29394     0x11/imm32/alloc-id:fake
29395     Single-float-var-in-some-register/imm32/outputs
29396     0x11/imm32/alloc-id:fake
29397     _string_f3_0f_2a_convert_to_float/imm32/subx-name
29398     1/imm32/rm32-is-first-inout
29399     0/imm32/no-r32
29400     0/imm32/no-imm32
29401     0/imm32/no-imm8
29402     0/imm32/no-disp32
29403     0/imm32/no-xm32
29404     3/imm32/x32-is-first-output
29405     0x11/imm32/alloc-id:fake
29406     _Primitive-convert-xmem-to-reg/imm32/next
29407 # - convert floating point to int
29408 _Primitive-convert-xmem-to-reg:  # (payload primitive)
29409     0x11/imm32/alloc-id:fake:payload
29410     # var1/reg <- convert var2 => f3 0f 2d/convert-to-int var2/xm32 var1/r32
29411     0x11/imm32/alloc-id:fake
29412     _string-convert/imm32/name
29413     0x11/imm32/alloc-id:fake
29414     Single-float-var-in-mem/imm32/inouts
29415     0x11/imm32/alloc-id:fake
29416     Single-int-var-in-some-register/imm32/outputs
29417     0x11/imm32/alloc-id:fake
29418     _string_f3_0f_2d_convert_to_int/imm32/subx-name
29419     0/imm32/no-rm32
29420     3/imm32/r32-is-first-output
29421     0/imm32/no-imm32
29422     0/imm32/no-imm8
29423     0/imm32/no-disp32
29424     1/imm32/xm32-is-first-inout
29425     0/imm32/no-x32
29426     0x11/imm32/alloc-id:fake
29427     _Primitive-convert-xreg-to-reg/imm32/next
29428 _Primitive-convert-xreg-to-reg:  # (payload primitive)
29429     0x11/imm32/alloc-id:fake:payload
29430     # var1/reg <- convert var2/xreg => f3 0f 2d/convert-to-int var2/xm32 var1/r32
29431     0x11/imm32/alloc-id:fake
29432     _string-convert/imm32/name
29433     0x11/imm32/alloc-id:fake
29434     Single-float-var-in-some-register/imm32/inouts
29435     0x11/imm32/alloc-id:fake
29436     Single-int-var-in-some-register/imm32/outputs
29437     0x11/imm32/alloc-id:fake
29438     _string_f3_0f_2d_convert_to_int/imm32/subx-name
29439     0/imm32/no-rm32
29440     3/imm32/r32-is-first-output
29441     0/imm32/no-imm32
29442     0/imm32/no-imm8
29443     0/imm32/no-disp32
29444     1/imm32/xm32-is-first-inout
29445     0/imm32/no-x32
29446     0x11/imm32/alloc-id:fake
29447     _Primitive-truncate-xmem-to-reg/imm32/next
29448 _Primitive-truncate-xmem-to-reg:  # (payload primitive)
29449     0x11/imm32/alloc-id:fake:payload
29450     # var1/reg <- truncate var2 => f3 0f 2c/truncate-to-int var2/xm32 var1/r32
29451     0x11/imm32/alloc-id:fake
29452     _string-truncate/imm32/name
29453     0x11/imm32/alloc-id:fake
29454     Single-float-var-in-mem/imm32/inouts
29455     0x11/imm32/alloc-id:fake
29456     Single-int-var-in-some-register/imm32/outputs
29457     0x11/imm32/alloc-id:fake
29458     _string_f3_0f_2c_truncate_to_int/imm32/subx-name
29459     0/imm32/no-rm32
29460     3/imm32/r32-is-first-output
29461     0/imm32/no-imm32
29462     0/imm32/no-imm8
29463     0/imm32/no-disp32
29464     1/imm32/xm32-is-first-inout
29465     0/imm32/no-x32
29466     0x11/imm32/alloc-id:fake
29467     _Primitive-truncate-xreg-to-reg/imm32/next
29468 _Primitive-truncate-xreg-to-reg:  # (payload primitive)
29469     0x11/imm32/alloc-id:fake:payload
29470     # var1/reg <- truncate var2/xreg => f3 0f 2c/truncate-to-int var2/xm32 var1/r32
29471     0x11/imm32/alloc-id:fake
29472     _string-truncate/imm32/name
29473     0x11/imm32/alloc-id:fake
29474     Single-float-var-in-some-register/imm32/inouts
29475     0x11/imm32/alloc-id:fake
29476     Single-int-var-in-some-register/imm32/outputs
29477     0x11/imm32/alloc-id:fake
29478     _string_f3_0f_2c_truncate_to_int/imm32/subx-name
29479     0/imm32/no-rm32
29480     3/imm32/r32-is-first-output
29481     0/imm32/no-imm32
29482     0/imm32/no-imm8
29483     0/imm32/no-disp32
29484     1/imm32/xm32-is-first-inout
29485     0/imm32/no-x32
29486     0x11/imm32/alloc-id:fake
29487     _Primitive-reinterpret-xmem-as-reg/imm32/next
29488 # - reinterpret bytes (just for debugging)
29489 _Primitive-reinterpret-xmem-as-reg:  # (payload primitive)
29490     0x11/imm32/alloc-id:fake:payload
29491     # var1/reg <- reinterpret var2 => 8b/-> var2/xm32 var1/r32
29492     0x11/imm32/alloc-id:fake
29493     _string-reinterpret/imm32/name
29494     0x11/imm32/alloc-id:fake
29495     Single-float-var-in-mem/imm32/inouts
29496     0x11/imm32/alloc-id:fake
29497     Single-int-var-in-some-register/imm32/outputs
29498     0x11/imm32/alloc-id:fake
29499     _string_8b_->/imm32/subx-name
29500     0/imm32/no-rm32
29501     3/imm32/r32-is-first-output
29502     0/imm32/no-imm32
29503     0/imm32/no-imm8
29504     0/imm32/no-disp32
29505     1/imm32/xm32-is-first-inout
29506     0/imm32/no-x32
29507     0x11/imm32/alloc-id:fake
29508     _Primitive-reinterpret-mem-as-xreg/imm32/next
29509 _Primitive-reinterpret-mem-as-xreg:  # (payload primitive)
29510     0x11/imm32/alloc-id:fake:payload
29511     # var1/xreg <- reinterpret var2 => f3 0f 10/-> var2/rm32 var1/x32
29512     0x11/imm32/alloc-id:fake
29513     _string-reinterpret/imm32/name
29514     0x11/imm32/alloc-id:fake
29515     Single-int-var-in-mem/imm32/inouts
29516     0x11/imm32/alloc-id:fake
29517     Single-float-var-in-some-register/imm32/outputs
29518     0x11/imm32/alloc-id:fake
29519     _string_f3_0f_10_copy/imm32/subx-name
29520     1/imm32/rm32-is-first-inout
29521     0/imm32/no-r32
29522     0/imm32/no-imm32
29523     0/imm32/no-imm8
29524     0/imm32/no-disp32
29525     0/imm32/no-xm32
29526     3/imm32/x32-is-first-output
29527     0x11/imm32/alloc-id:fake
29528     _Primitive-copy-xreg-to-xreg/imm32/next
29529 # - floating-point copy
29530 _Primitive-copy-xreg-to-xreg:  # (payload primitive)
29531     0x11/imm32/alloc-id:fake:payload
29532     # var1/xreg <- copy var2/xreg => f3 0f 11/<- var1/xm32 var2/x32
29533     0x11/imm32/alloc-id:fake
29534     _string-copy/imm32/name
29535     0x11/imm32/alloc-id:fake
29536     Single-float-var-in-some-register/imm32/inouts
29537     0x11/imm32/alloc-id:fake
29538     Single-float-var-in-some-register/imm32/outputs
29539     0x11/imm32/alloc-id:fake
29540     _string_f3_0f_11_copy/imm32/subx-name
29541     0/imm32/no-rm32
29542     0/imm32/no-r32
29543     0/imm32/no-imm32
29544     0/imm32/no-imm8
29545     0/imm32/no-disp32
29546     3/imm32/xm32-is-first-output
29547     1/imm32/x32-is-first-inout
29548     0x11/imm32/alloc-id:fake
29549     _Primitive-copy-xreg-to-mem/imm32/next
29550 _Primitive-copy-xreg-to-mem:  # (payload primitive)
29551     0x11/imm32/alloc-id:fake:payload
29552     # copy-to var1 var2/xreg => f3 0f 11/<- var1 var2/x32
29553     0x11/imm32/alloc-id:fake
29554     _string-copy-to/imm32/name
29555     0x11/imm32/alloc-id:fake
29556     Two-args-float-stack-float-reg/imm32/inouts
29557     0/imm32/no-outputs
29558     0/imm32/no-outputs
29559     0x11/imm32/alloc-id:fake
29560     _string_f3_0f_11_copy/imm32/subx-name
29561     0/imm32/no-rm32
29562     0/imm32/no-r32
29563     0/imm32/no-imm32
29564     0/imm32/no-imm8
29565     0/imm32/no-disp32
29566     1/imm32/xm32-is-first-inout
29567     2/imm32/x32-is-second-inout
29568     0x11/imm32/alloc-id:fake
29569     _Primitive-copy-mem-to-xreg/imm32/next
29570 _Primitive-copy-mem-to-xreg:  # (payload primitive)
29571     0x11/imm32/alloc-id:fake:payload
29572     # var1/xreg <- copy var2 => f3 0f 10/-> var2/rm32 var1/x32
29573     0x11/imm32/alloc-id:fake
29574     _string-copy/imm32/name
29575     0x11/imm32/alloc-id:fake
29576     Single-float-var-in-mem/imm32/inouts
29577     0x11/imm32/alloc-id:fake
29578     Single-float-var-in-some-register/imm32/outputs
29579     0x11/imm32/alloc-id:fake
29580     _string_f3_0f_10_copy/imm32/subx-name
29581     0/imm32/no-rm32
29582     0/imm32/no-r32
29583     0/imm32/no-imm32
29584     0/imm32/no-imm8
29585     0/imm32/no-disp32
29586     1/imm32/xm32-is-first-inout
29587     3/imm32/x32-is-first-output
29588     0x11/imm32/alloc-id:fake
29589     _Primitive-address-of-xmem/imm32/next
29590 # - floating-point-address
29591 _Primitive-address-of-xmem:  # (payload primitive)
29592     0x11/imm32/alloc-id:fake:payload
29593     # var1/reg <- address var2 => 8d/copy-address var2/rm32 var1/r32
29594     0x11/imm32/alloc-id:fake
29595     _string-address/imm32/name
29596     0x11/imm32/alloc-id:fake
29597     Single-float-var-in-mem/imm32/inouts
29598     0x11/imm32/alloc-id:fake
29599     Single-addr-var-in-some-register/imm32/outputs
29600     0x11/imm32/alloc-id:fake
29601     _string_8d_copy_address/imm32/subx-name
29602     1/imm32/rm32-is-first-inout
29603     3/imm32/r32-is-first-output
29604     0/imm32/no-imm32
29605     0/imm32/no-imm8
29606     0/imm32/no-disp32
29607     0/imm32/no-xm32
29608     0/imm32/no-x32
29609     0x11/imm32/alloc-id:fake
29610     _Primitive-add-xreg-to-xreg/imm32/next
29611 # - floating-point add
29612 _Primitive-add-xreg-to-xreg:  # (payload primitive)
29613     0x11/imm32/alloc-id:fake:payload
29614     # var1/xreg <- add var2/xreg => f3 0f 58/add var1/xm32 var2/x32
29615     0x11/imm32/alloc-id:fake
29616     _string-add/imm32/name
29617     0x11/imm32/alloc-id:fake
29618     Single-float-var-in-some-register/imm32/inouts
29619     0x11/imm32/alloc-id:fake
29620     Single-float-var-in-some-register/imm32/outputs
29621     0x11/imm32/alloc-id:fake
29622     _string_f3_0f_58_add/imm32/subx-name
29623     0/imm32/no-rm32
29624     0/imm32/no-r32
29625     0/imm32/no-imm32
29626     0/imm32/no-imm8
29627     0/imm32/no-disp32
29628     1/imm32/xm32-is-first-inout
29629     3/imm32/x32-is-first-output
29630     0x11/imm32/alloc-id:fake
29631     _Primitive-add-mem-to-xreg/imm32/next
29632 _Primitive-add-mem-to-xreg:  # (payload primitive)
29633     0x11/imm32/alloc-id:fake:payload
29634     # var1/xreg <- add var2 => f3 0f 58/add var2/xm32 var1/x32
29635     0x11/imm32/alloc-id:fake
29636     _string-add/imm32/name
29637     0x11/imm32/alloc-id:fake
29638     Single-float-var-in-mem/imm32/inouts
29639     0x11/imm32/alloc-id:fake
29640     Single-float-var-in-some-register/imm32/outputs
29641     0x11/imm32/alloc-id:fake
29642     _string_f3_0f_58_add/imm32/subx-name
29643     0/imm32/no-rm32
29644     0/imm32/no-r32
29645     0/imm32/no-imm32
29646     0/imm32/no-imm8
29647     0/imm32/no-disp32
29648     1/imm32/xm32-is-first-inout
29649     3/imm32/x32-is-first-output
29650     0x11/imm32/alloc-id:fake
29651     _Primitive-subtract-xreg-from-xreg/imm32/next
29652 # - floating-point subtract
29653 _Primitive-subtract-xreg-from-xreg:  # (payload primitive)
29654     0x11/imm32/alloc-id:fake:payload
29655     # var1/xreg <- subtract var2/xreg => f3 0f 5c/subtract var1/xm32 var2/x32
29656     0x11/imm32/alloc-id:fake
29657     _string-subtract/imm32/name
29658     0x11/imm32/alloc-id:fake
29659     Single-float-var-in-some-register/imm32/inouts
29660     0x11/imm32/alloc-id:fake
29661     Single-float-var-in-some-register/imm32/outputs
29662     0x11/imm32/alloc-id:fake
29663     _string_f3_0f_5c_subtract/imm32/subx-name
29664     0/imm32/no-rm32
29665     0/imm32/no-r32
29666     0/imm32/no-imm32
29667     0/imm32/no-imm8
29668     0/imm32/no-disp32
29669     1/imm32/xm32-is-first-inout
29670     3/imm32/x32-is-first-output
29671     0x11/imm32/alloc-id:fake
29672     _Primitive-subtract-mem-from-xreg/imm32/next
29673 _Primitive-subtract-mem-from-xreg:  # (payload primitive)
29674     0x11/imm32/alloc-id:fake:payload
29675     # var1/xreg <- subtract var2 => f3 0f 5c/subtract var2/xm32 var1/x32
29676     0x11/imm32/alloc-id:fake
29677     _string-subtract/imm32/name
29678     0x11/imm32/alloc-id:fake
29679     Single-float-var-in-mem/imm32/inouts
29680     0x11/imm32/alloc-id:fake
29681     Single-float-var-in-some-register/imm32/outputs
29682     0x11/imm32/alloc-id:fake
29683     _string_f3_0f_5c_subtract/imm32/subx-name
29684     0/imm32/no-rm32
29685     0/imm32/no-r32
29686     0/imm32/no-imm32
29687     0/imm32/no-imm8
29688     0/imm32/no-disp32
29689     1/imm32/xm32-is-first-inout
29690     3/imm32/x32-is-first-output
29691     0x11/imm32/alloc-id:fake
29692     _Primitive-multiply-xreg-by-xreg/imm32/next
29693 # - floating-point multiply
29694 _Primitive-multiply-xreg-by-xreg:  # (payload primitive)
29695     0x11/imm32/alloc-id:fake:payload
29696     # var1/xreg <- multiply var2 => f3 0f 59/multiply var2/xm32 var1/x32
29697     0x11/imm32/alloc-id:fake
29698     _string-multiply/imm32/name
29699     0x11/imm32/alloc-id:fake
29700     Single-float-var-in-some-register/imm32/inouts
29701     0x11/imm32/alloc-id:fake
29702     Single-float-var-in-some-register/imm32/outputs
29703     0x11/imm32/alloc-id:fake
29704     _string_f3_0f_59_multiply/imm32/subx-name
29705     0/imm32/no-rm32
29706     0/imm32/no-r32
29707     0/imm32/no-imm32
29708     0/imm32/no-imm8
29709     0/imm32/no-disp32
29710     1/imm32/xm32-is-first-inout
29711     3/imm32/x32-is-first-output
29712     0x11/imm32/alloc-id:fake
29713     _Primitive-multiply-xreg-by-mem/imm32/next
29714 _Primitive-multiply-xreg-by-mem:  # (payload primitive)
29715     0x11/imm32/alloc-id:fake:payload
29716     # var1/xreg <- multiply var2 => 53 0f 59/multiply var2/xm32 var1/x32
29717     0x11/imm32/alloc-id:fake
29718     _string-multiply/imm32/name
29719     0x11/imm32/alloc-id:fake
29720     Single-float-var-in-mem/imm32/inouts
29721     0x11/imm32/alloc-id:fake
29722     Single-float-var-in-some-register/imm32/outputs
29723     0x11/imm32/alloc-id:fake
29724     _string_f3_0f_59_multiply/imm32/subx-name
29725     0/imm32/no-rm32
29726     0/imm32/no-r32
29727     0/imm32/no-imm32
29728     0/imm32/no-imm8
29729     0/imm32/no-disp32
29730     1/imm32/xm32-is-first-inout
29731     3/imm32/x32-is-first-output
29732     0x11/imm32/alloc-id:fake
29733     _Primitive-divide-xreg-by-xreg/imm32/next
29734 # - floating-point divide
29735 _Primitive-divide-xreg-by-xreg:  # (payload primitive)
29736     0x11/imm32/alloc-id:fake:payload
29737     # var1/xreg <- divide var2 => f3 0f 5e/divide var2/xm32 var1/x32
29738     0x11/imm32/alloc-id:fake
29739     _string-divide/imm32/name
29740     0x11/imm32/alloc-id:fake
29741     Single-float-var-in-some-register/imm32/inouts
29742     0x11/imm32/alloc-id:fake
29743     Single-float-var-in-some-register/imm32/outputs
29744     0x11/imm32/alloc-id:fake
29745     _string_f3_0f_5e_divide/imm32/subx-name
29746     0/imm32/no-rm32
29747     0/imm32/no-r32
29748     0/imm32/no-imm32
29749     0/imm32/no-imm8
29750     0/imm32/no-disp32
29751     1/imm32/xm32-is-first-inout
29752     3/imm32/x32-is-first-output
29753     0x11/imm32/alloc-id:fake
29754     _Primitive-divide-xreg-by-mem/imm32/next
29755 _Primitive-divide-xreg-by-mem:  # (payload primitive)
29756     0x11/imm32/alloc-id:fake:payload
29757     # var1/xreg <- divide var2 => f3 0f 5e/divide var2/xm32 var1/x32
29758     0x11/imm32/alloc-id:fake
29759     _string-divide/imm32/name
29760     0x11/imm32/alloc-id:fake
29761     Single-float-var-in-mem/imm32/inouts
29762     0x11/imm32/alloc-id:fake
29763     Single-float-var-in-some-register/imm32/outputs
29764     0x11/imm32/alloc-id:fake
29765     _string_f3_0f_5e_divide/imm32/subx-name
29766     0/imm32/no-rm32
29767     0/imm32/no-r32
29768     0/imm32/no-imm32
29769     0/imm32/no-imm8
29770     0/imm32/no-disp32
29771     1/imm32/xm32-is-first-inout
29772     3/imm32/x32-is-first-output
29773     0x11/imm32/alloc-id:fake
29774     _Primitive-max-xreg-with-xreg/imm32/next
29775 # - floating-point maximum
29776 _Primitive-max-xreg-with-xreg:  # (payload primitive)
29777     0x11/imm32/alloc-id:fake:payload
29778     # var1/xreg <- max var2 => f3 0f 5f/max var2/xm32 var1/x32
29779     0x11/imm32/alloc-id:fake
29780     _string-max/imm32/name
29781     0x11/imm32/alloc-id:fake
29782     Single-float-var-in-some-register/imm32/inouts
29783     0x11/imm32/alloc-id:fake
29784     Single-float-var-in-some-register/imm32/outputs
29785     0x11/imm32/alloc-id:fake
29786     _string_f3_0f_5f_max/imm32/subx-name
29787     0/imm32/no-rm32
29788     0/imm32/no-r32
29789     0/imm32/no-imm32
29790     0/imm32/no-imm8
29791     0/imm32/no-disp32
29792     1/imm32/xm32-is-first-inout
29793     3/imm32/x32-is-first-output
29794     0x11/imm32/alloc-id:fake
29795     _Primitive-max-xreg-with-mem/imm32/next
29796 _Primitive-max-xreg-with-mem:  # (payload primitive)
29797     0x11/imm32/alloc-id:fake:payload
29798     # var1/xreg <- divide var2 => f3 0f 5f/max var2/xm32 var1/x32
29799     0x11/imm32/alloc-id:fake
29800     _string-max/imm32/name
29801     0x11/imm32/alloc-id:fake
29802     Single-float-var-in-mem/imm32/inouts
29803     0x11/imm32/alloc-id:fake
29804     Single-float-var-in-some-register/imm32/outputs
29805     0x11/imm32/alloc-id:fake
29806     _string_f3_0f_5f_max/imm32/subx-name
29807     0/imm32/no-rm32
29808     0/imm32/no-r32
29809     0/imm32/no-imm32
29810     0/imm32/no-imm8
29811     0/imm32/no-disp32
29812     1/imm32/xm32-is-first-inout
29813     3/imm32/x32-is-first-output
29814     0x11/imm32/alloc-id:fake
29815     _Primitive-min-xreg-with-xreg/imm32/next
29816 # - floating-point minimum
29817 _Primitive-min-xreg-with-xreg:  # (payload primitive)
29818     0x11/imm32/alloc-id:fake:payload
29819     # var1/xreg <- divide var2 => f3 0f 5d/min var2/xm32 var1/x32
29820     0x11/imm32/alloc-id:fake
29821     _string-min/imm32/name
29822     0x11/imm32/alloc-id:fake
29823     Single-float-var-in-some-register/imm32/inouts
29824     0x11/imm32/alloc-id:fake
29825     Single-float-var-in-some-register/imm32/outputs
29826     0x11/imm32/alloc-id:fake
29827     _string_f3_0f_5d_min/imm32/subx-name
29828     0/imm32/no-rm32
29829     0/imm32/no-r32
29830     0/imm32/no-imm32
29831     0/imm32/no-imm8
29832     0/imm32/no-disp32
29833     1/imm32/xm32-is-first-inout
29834     3/imm32/x32-is-first-output
29835     0x11/imm32/alloc-id:fake
29836     _Primitive-min-xreg-with-mem/imm32/next
29837 _Primitive-min-xreg-with-mem:  # (payload primitive)
29838     0x11/imm32/alloc-id:fake:payload
29839     # var1/xreg <- divide var2 => f3 0f 5d/min var2/xm32 var1/x32
29840     0x11/imm32/alloc-id:fake
29841     _string-min/imm32/name
29842     0x11/imm32/alloc-id:fake
29843     Single-float-var-in-mem/imm32/inouts
29844     0x11/imm32/alloc-id:fake
29845     Single-float-var-in-some-register/imm32/outputs
29846     0x11/imm32/alloc-id:fake
29847     _string_f3_0f_5d_min/imm32/subx-name
29848     0/imm32/no-rm32
29849     0/imm32/no-r32
29850     0/imm32/no-imm32
29851     0/imm32/no-imm8
29852     0/imm32/no-disp32
29853     1/imm32/xm32-is-first-inout
29854     3/imm32/x32-is-first-output
29855     0x11/imm32/alloc-id:fake
29856     _Primitive-reciprocal-xreg-to-xreg/imm32/next
29857 # - floating-point reciprocal
29858 _Primitive-reciprocal-xreg-to-xreg:  # (payload primitive)
29859     0x11/imm32/alloc-id:fake:payload
29860     # var1/xreg <- reciprocal var2 => f3 0f 53/reciprocal var2/xm32 var1/x32
29861     0x11/imm32/alloc-id:fake
29862     _string-reciprocal/imm32/name
29863     0x11/imm32/alloc-id:fake
29864     Single-float-var-in-some-register/imm32/inouts
29865     0x11/imm32/alloc-id:fake
29866     Single-float-var-in-some-register/imm32/outputs
29867     0x11/imm32/alloc-id:fake
29868     _string_f3_0f_53_reciprocal/imm32/subx-name
29869     0/imm32/no-rm32
29870     0/imm32/no-r32
29871     0/imm32/no-imm32
29872     0/imm32/no-imm8
29873     0/imm32/no-disp32
29874     1/imm32/xm32-is-first-inout
29875     3/imm32/x32-is-first-output
29876     0x11/imm32/alloc-id:fake
29877     _Primitive-reciprocal-mem-to-xreg/imm32/next
29878 _Primitive-reciprocal-mem-to-xreg:  # (payload primitive)
29879     0x11/imm32/alloc-id:fake:payload
29880     # var1/xreg <- divide var2 => f3 0f 53/reciprocal var2/xm32 var1/x32
29881     0x11/imm32/alloc-id:fake
29882     _string-reciprocal/imm32/name
29883     0x11/imm32/alloc-id:fake
29884     Single-float-var-in-mem/imm32/inouts
29885     0x11/imm32/alloc-id:fake
29886     Single-float-var-in-some-register/imm32/outputs
29887     0x11/imm32/alloc-id:fake
29888     _string_f3_0f_53_reciprocal/imm32/subx-name
29889     0/imm32/no-rm32
29890     0/imm32/no-r32
29891     0/imm32/no-imm32
29892     0/imm32/no-imm8
29893     0/imm32/no-disp32
29894     1/imm32/xm32-is-first-inout
29895     3/imm32/x32-is-first-output
29896     0x11/imm32/alloc-id:fake
29897     _Primitive-square-root-xreg-to-xreg/imm32/next
29898 # - floating-point square root
29899 _Primitive-square-root-xreg-to-xreg:  # (payload primitive)
29900     0x11/imm32/alloc-id:fake:payload
29901     # var1/xreg <- square-root var2 => f3 0f 51/square-root var2/xm32 var1/x32
29902     0x11/imm32/alloc-id:fake
29903     _string-square-root/imm32/name
29904     0x11/imm32/alloc-id:fake
29905     Single-float-var-in-some-register/imm32/inouts
29906     0x11/imm32/alloc-id:fake
29907     Single-float-var-in-some-register/imm32/outputs
29908     0x11/imm32/alloc-id:fake
29909     _string_f3_0f_51_square_root/imm32/subx-name
29910     0/imm32/no-rm32
29911     0/imm32/no-r32
29912     0/imm32/no-imm32
29913     0/imm32/no-imm8
29914     0/imm32/no-disp32
29915     1/imm32/xm32-is-first-inout
29916     3/imm32/x32-is-first-output
29917     0x11/imm32/alloc-id:fake
29918     _Primitive-square-root-mem-to-xreg/imm32/next
29919 _Primitive-square-root-mem-to-xreg:  # (payload primitive)
29920     0x11/imm32/alloc-id:fake:payload
29921     # var1/xreg <- divide var2 => f3 0f 51/square-root var2/xm32 var1/x32
29922     0x11/imm32/alloc-id:fake
29923     _string-square-root/imm32/name
29924     0x11/imm32/alloc-id:fake
29925     Single-float-var-in-mem/imm32/inouts
29926     0x11/imm32/alloc-id:fake
29927     Single-float-var-in-some-register/imm32/outputs
29928     0x11/imm32/alloc-id:fake
29929     _string_f3_0f_51_square_root/imm32/subx-name
29930     0/imm32/no-rm32
29931     0/imm32/no-r32
29932     0/imm32/no-imm32
29933     0/imm32/no-imm8
29934     0/imm32/no-disp32
29935     1/imm32/xm32-is-first-inout
29936     3/imm32/x32-is-first-output
29937     0x11/imm32/alloc-id:fake
29938     _Primitive-inverse-square-root-xreg-to-xreg/imm32/next
29939 # - floating-point inverse square root 1/sqrt(x)
29940 _Primitive-inverse-square-root-xreg-to-xreg:  # (payload primitive)
29941     0x11/imm32/alloc-id:fake:payload
29942     # var1/xreg <- reciprocal var2 => f3 0f 52/inverse-square-root var2/xm32 var1/x32
29943     0x11/imm32/alloc-id:fake
29944     _string-inverse-square-root/imm32/name
29945     0x11/imm32/alloc-id:fake
29946     Single-float-var-in-some-register/imm32/inouts
29947     0x11/imm32/alloc-id:fake
29948     Single-float-var-in-some-register/imm32/outputs
29949     0x11/imm32/alloc-id:fake
29950     _string_f3_0f_52_inverse_square_root/imm32/subx-name
29951     0/imm32/no-rm32
29952     0/imm32/no-r32
29953     0/imm32/no-imm32
29954     0/imm32/no-imm8
29955     0/imm32/no-disp32
29956     1/imm32/xm32-is-first-inout
29957     3/imm32/x32-is-first-output
29958     0x11/imm32/alloc-id:fake
29959     _Primitive-inverse-square-root-mem-to-xreg/imm32/next
29960 _Primitive-inverse-square-root-mem-to-xreg:  # (payload primitive)
29961     0x11/imm32/alloc-id:fake:payload
29962     # var1/xreg <- divide var2 => f3 0f 52/inverse-square-root var2/xm32 var1/x32
29963     0x11/imm32/alloc-id:fake
29964     _string-inverse-square-root/imm32/name
29965     0x11/imm32/alloc-id:fake
29966     Single-float-var-in-mem/imm32/inouts
29967     0x11/imm32/alloc-id:fake
29968     Single-float-var-in-some-register/imm32/outputs
29969     0x11/imm32/alloc-id:fake
29970     _string_f3_0f_52_inverse_square_root/imm32/subx-name
29971     0/imm32/no-rm32
29972     0/imm32/no-r32
29973     0/imm32/no-imm32
29974     0/imm32/no-imm8
29975     0/imm32/no-disp32
29976     1/imm32/xm32-is-first-inout
29977     3/imm32/x32-is-first-output
29978     0x11/imm32/alloc-id:fake
29979     _Primitive-compare-xreg-with-xreg/imm32/next
29980 # - floating-point compare
29981 _Primitive-compare-xreg-with-xreg:  # (payload primitive)
29982     0x11/imm32/alloc-id:fake:payload
29983     # compare var1/reg1 var2/reg2 => 0f 2f/compare var2/x32 var1/xm32
29984     0x11/imm32/alloc-id:fake
29985     _string-compare/imm32/name
29986     0x11/imm32/alloc-id:fake
29987     Two-float-args-in-regs/imm32/inouts
29988     0/imm32/no-outputs
29989     0/imm32/no-outputs
29990     0x11/imm32/alloc-id:fake
29991     _string_0f_2f_compare/imm32/subx-name
29992     0/imm32/no-rm32
29993     0/imm32/no-r32
29994     0/imm32/no-imm32
29995     0/imm32/no-imm8
29996     0/imm32/no-disp32
29997     1/imm32/xm32-is-first-inout
29998     2/imm32/x32-is-second-inout
29999     0x11/imm32/alloc-id:fake
30000     _Primitive-compare-xreg-with-mem/imm32/next
30001 _Primitive-compare-xreg-with-mem:  # (payload primitive)
30002     0x11/imm32/alloc-id:fake:payload
30003     # compare var1/xreg var2 => 0f 2f/compare var1/x32 var2/xm32
30004     0x11/imm32/alloc-id:fake
30005     _string-compare/imm32/name
30006     0x11/imm32/alloc-id:fake
30007     Two-args-float-reg-float-stack/imm32/inouts
30008     0/imm32/no-outputs
30009     0/imm32/no-outputs
30010     0x11/imm32/alloc-id:fake
30011     _string_0f_2f_compare/imm32/subx-name
30012     0/imm32/no-rm32
30013     0/imm32/no-r32
30014     0/imm32/no-imm32
30015     0/imm32/no-imm8
30016     0/imm32/no-disp32
30017     2/imm32/xm32-is-second-inout
30018     1/imm32/x32-is-first-inout
30019     0x11/imm32/alloc-id:fake
30020     _Primitive-break-if-addr</imm32/next
30021 # - branches
30022 _Primitive-break-if-addr<:  # (payload primitive)
30023     0x11/imm32/alloc-id:fake:payload
30024     0x11/imm32/alloc-id:fake
30025     _string-break-if-addr</imm32/name
30026     0/imm32/no-inouts
30027     0/imm32/no-inouts
30028     0/imm32/no-outputs
30029     0/imm32/no-outputs
30030     0x11/imm32/alloc-id:fake
30031     _string_0f_82_jump_break/imm32/subx-name
30032     0/imm32/no-rm32
30033     0/imm32/no-r32
30034     0/imm32/no-imm32
30035     0/imm32/no-imm8
30036     0/imm32/no-disp32
30037     0/imm32/no-xm32
30038     0/imm32/no-x32
30039     0x11/imm32/alloc-id:fake
30040     _Primitive-break-if-addr>=/imm32/next
30041 _Primitive-break-if-addr>=:  # (payload primitive)
30042     0x11/imm32/alloc-id:fake:payload
30043     0x11/imm32/alloc-id:fake
30044     _string-break-if-addr>=/imm32/name
30045     0/imm32/no-inouts
30046     0/imm32/no-inouts
30047     0/imm32/no-outputs
30048     0/imm32/no-outputs
30049     0x11/imm32/alloc-id:fake
30050     _string_0f_83_jump_break/imm32/subx-name
30051     0/imm32/no-rm32
30052     0/imm32/no-r32
30053     0/imm32/no-imm32
30054     0/imm32/no-imm8
30055     0/imm32/no-disp32
30056     0/imm32/no-xm32
30057     0/imm32/no-x32
30058     0x11/imm32/alloc-id:fake
30059     _Primitive-break-if-=/imm32/next
30060 _Primitive-break-if-=:  # (payload primitive)
30061     0x11/imm32/alloc-id:fake:payload
30062     0x11/imm32/alloc-id:fake
30063     _string-break-if-=/imm32/name
30064     0/imm32/no-inouts
30065     0/imm32/no-inouts
30066     0/imm32/no-outputs
30067     0/imm32/no-outputs
30068     0x11/imm32/alloc-id:fake
30069     _string_0f_84_jump_break/imm32/subx-name
30070     0/imm32/no-rm32
30071     0/imm32/no-r32
30072     0/imm32/no-imm32
30073     0/imm32/no-imm8
30074     0/imm32/no-disp32
30075     0/imm32/no-xm32
30076     0/imm32/no-x32
30077     0x11/imm32/alloc-id:fake
30078     _Primitive-break-if-!=/imm32/next
30079 _Primitive-break-if-!=:  # (payload primitive)
30080     0x11/imm32/alloc-id:fake:payload
30081     0x11/imm32/alloc-id:fake
30082     _string-break-if-!=/imm32/name
30083     0/imm32/no-inouts
30084     0/imm32/no-inouts
30085     0/imm32/no-outputs
30086     0/imm32/no-outputs
30087     0x11/imm32/alloc-id:fake
30088     _string_0f_85_jump_break/imm32/subx-name
30089     0/imm32/no-rm32
30090     0/imm32/no-r32
30091     0/imm32/no-imm32
30092     0/imm32/no-imm8
30093     0/imm32/no-disp32
30094     0/imm32/no-xm32
30095     0/imm32/no-x32
30096     0x11/imm32/alloc-id:fake
30097     _Primitive-break-if-addr<=/imm32/next
30098 _Primitive-break-if-addr<=:  # (payload primitive)
30099     0x11/imm32/alloc-id:fake:payload
30100     0x11/imm32/alloc-id:fake
30101     _string-break-if-addr<=/imm32/name
30102     0/imm32/no-inouts
30103     0/imm32/no-inouts
30104     0/imm32/no-outputs
30105     0/imm32/no-outputs
30106     0x11/imm32/alloc-id:fake
30107     _string_0f_86_jump_break/imm32/subx-name
30108     0/imm32/no-rm32
30109     0/imm32/no-r32
30110     0/imm32/no-imm32
30111     0/imm32/no-imm8
30112     0/imm32/no-disp32
30113     0/imm32/no-xm32
30114     0/imm32/no-x32
30115     0x11/imm32/alloc-id:fake
30116     _Primitive-break-if-addr>/imm32/next
30117 _Primitive-break-if-addr>:  # (payload primitive)
30118     0x11/imm32/alloc-id:fake:payload
30119     0x11/imm32/alloc-id:fake
30120     _string-break-if-addr>/imm32/name
30121     0/imm32/no-inouts
30122     0/imm32/no-inouts
30123     0/imm32/no-outputs
30124     0/imm32/no-outputs
30125     0x11/imm32/alloc-id:fake
30126     _string_0f_87_jump_break/imm32/subx-name
30127     0/imm32/no-rm32
30128     0/imm32/no-r32
30129     0/imm32/no-imm32
30130     0/imm32/no-imm8
30131     0/imm32/no-disp32
30132     0/imm32/no-xm32
30133     0/imm32/no-x32
30134     0x11/imm32/alloc-id:fake
30135     _Primitive-break-if-</imm32/next
30136 _Primitive-break-if-<:  # (payload primitive)
30137     0x11/imm32/alloc-id:fake:payload
30138     0x11/imm32/alloc-id:fake
30139     _string-break-if-</imm32/name
30140     0/imm32/no-inouts
30141     0/imm32/no-inouts
30142     0/imm32/no-outputs
30143     0/imm32/no-outputs
30144     0x11/imm32/alloc-id:fake
30145     _string_0f_8c_jump_break/imm32/subx-name
30146     0/imm32/no-rm32
30147     0/imm32/no-r32
30148     0/imm32/no-imm32
30149     0/imm32/no-imm8
30150     0/imm32/no-disp32
30151     0/imm32/no-xm32
30152     0/imm32/no-x32
30153     0x11/imm32/alloc-id:fake
30154     _Primitive-break-if->=/imm32/next
30155 _Primitive-break-if->=:  # (payload primitive)
30156     0x11/imm32/alloc-id:fake:payload
30157     0x11/imm32/alloc-id:fake
30158     _string-break-if->=/imm32/name
30159     0/imm32/no-inouts
30160     0/imm32/no-inouts
30161     0/imm32/no-outputs
30162     0/imm32/no-outputs
30163     0x11/imm32/alloc-id:fake
30164     _string_0f_8d_jump_break/imm32/subx-name
30165     0/imm32/no-rm32
30166     0/imm32/no-r32
30167     0/imm32/no-imm32
30168     0/imm32/no-imm8
30169     0/imm32/no-disp32
30170     0/imm32/no-xm32
30171     0/imm32/no-x32
30172     0x11/imm32/alloc-id:fake
30173     _Primitive-break-if-<=/imm32/next
30174 _Primitive-break-if-<=:  # (payload primitive)
30175     0x11/imm32/alloc-id:fake:payload
30176     0x11/imm32/alloc-id:fake
30177     _string-break-if-<=/imm32/name
30178     0/imm32/no-inouts
30179     0/imm32/no-inouts
30180     0/imm32/no-outputs
30181     0/imm32/no-outputs
30182     0x11/imm32/alloc-id:fake
30183     _string_0f_8e_jump_break/imm32/subx-name
30184     0/imm32/no-rm32
30185     0/imm32/no-r32
30186     0/imm32/no-imm32
30187     0/imm32/no-imm8
30188     0/imm32/no-disp32
30189     0/imm32/no-xm32
30190     0/imm32/no-x32
30191     0x11/imm32/alloc-id:fake
30192     _Primitive-break-if->/imm32/next
30193 _Primitive-break-if->:  # (payload primitive)
30194     0x11/imm32/alloc-id:fake:payload
30195     0x11/imm32/alloc-id:fake
30196     _string-break-if->/imm32/name
30197     0/imm32/no-inouts
30198     0/imm32/no-inouts
30199     0/imm32/no-outputs
30200     0/imm32/no-outputs
30201     0x11/imm32/alloc-id:fake
30202     _string_0f_8f_jump_break/imm32/subx-name
30203     0/imm32/no-rm32
30204     0/imm32/no-r32
30205     0/imm32/no-imm32
30206     0/imm32/no-imm8
30207     0/imm32/no-disp32
30208     0/imm32/no-xm32
30209     0/imm32/no-x32
30210     0x11/imm32/alloc-id:fake
30211     _Primitive-break/imm32/next
30212 _Primitive-break:  # (payload primitive)
30213     0x11/imm32/alloc-id:fake:payload
30214     0x11/imm32/alloc-id:fake
30215     _string-break/imm32/name
30216     0/imm32/no-inouts
30217     0/imm32/no-inouts
30218     0/imm32/no-outputs
30219     0/imm32/no-outputs
30220     0x11/imm32/alloc-id:fake
30221     _string_e9_jump_break/imm32/subx-name
30222     0/imm32/no-rm32
30223     0/imm32/no-r32
30224     0/imm32/no-imm32
30225     0/imm32/no-imm8
30226     0/imm32/no-disp32
30227     0/imm32/no-xm32
30228     0/imm32/no-x32
30229     0x11/imm32/alloc-id:fake
30230     _Primitive-loop-if-addr</imm32/next
30231 _Primitive-loop-if-addr<:  # (payload primitive)
30232     0x11/imm32/alloc-id:fake:payload
30233     0x11/imm32/alloc-id:fake
30234     _string-loop-if-addr</imm32/name
30235     0/imm32/no-inouts
30236     0/imm32/no-inouts
30237     0/imm32/no-outputs
30238     0/imm32/no-outputs
30239     0x11/imm32/alloc-id:fake
30240     _string_0f_82_jump_loop/imm32/subx-name
30241     0/imm32/no-rm32
30242     0/imm32/no-r32
30243     0/imm32/no-imm32
30244     0/imm32/no-imm8
30245     0/imm32/no-disp32
30246     0/imm32/no-xm32
30247     0/imm32/no-x32
30248     0x11/imm32/alloc-id:fake
30249     _Primitive-loop-if-addr>=/imm32/next
30250 _Primitive-loop-if-addr>=:  # (payload primitive)
30251     0x11/imm32/alloc-id:fake:payload
30252     0x11/imm32/alloc-id:fake
30253     _string-loop-if-addr>=/imm32/name
30254     0/imm32/no-inouts
30255     0/imm32/no-inouts
30256     0/imm32/no-outputs
30257     0/imm32/no-outputs
30258     0x11/imm32/alloc-id:fake
30259     _string_0f_83_jump_loop/imm32/subx-name
30260     0/imm32/no-rm32
30261     0/imm32/no-r32
30262     0/imm32/no-imm32
30263     0/imm32/no-imm8
30264     0/imm32/no-disp32
30265     0/imm32/no-xm32
30266     0/imm32/no-x32
30267     0x11/imm32/alloc-id:fake
30268     _Primitive-loop-if-=/imm32/next
30269 _Primitive-loop-if-=:  # (payload primitive)
30270     0x11/imm32/alloc-id:fake:payload
30271     0x11/imm32/alloc-id:fake
30272     _string-loop-if-=/imm32/name
30273     0/imm32/no-inouts
30274     0/imm32/no-inouts
30275     0/imm32/no-outputs
30276     0/imm32/no-outputs
30277     0x11/imm32/alloc-id:fake
30278     _string_0f_84_jump_loop/imm32/subx-name
30279     0/imm32/no-rm32
30280     0/imm32/no-r32
30281     0/imm32/no-imm32
30282     0/imm32/no-imm8
30283     0/imm32/no-disp32
30284     0/imm32/no-xm32
30285     0/imm32/no-x32
30286     0x11/imm32/alloc-id:fake
30287     _Primitive-loop-if-!=/imm32/next
30288 _Primitive-loop-if-!=:  # (payload primitive)
30289     0x11/imm32/alloc-id:fake:payload
30290     0x11/imm32/alloc-id:fake
30291     _string-loop-if-!=/imm32/name
30292     0/imm32/no-inouts
30293     0/imm32/no-inouts
30294     0/imm32/no-outputs
30295     0/imm32/no-outputs
30296     0x11/imm32/alloc-id:fake
30297     _string_0f_85_jump_loop/imm32/subx-name
30298     0/imm32/no-rm32
30299     0/imm32/no-r32
30300     0/imm32/no-imm32
30301     0/imm32/no-imm8
30302     0/imm32/no-disp32
30303     0/imm32/no-xm32
30304     0/imm32/no-x32
30305     0x11/imm32/alloc-id:fake
30306     _Primitive-loop-if-addr<=/imm32/next
30307 _Primitive-loop-if-addr<=:  # (payload primitive)
30308     0x11/imm32/alloc-id:fake:payload
30309     0x11/imm32/alloc-id:fake
30310     _string-loop-if-addr<=/imm32/name
30311     0/imm32/no-inouts
30312     0/imm32/no-inouts
30313     0/imm32/no-outputs
30314     0/imm32/no-outputs
30315     0x11/imm32/alloc-id:fake
30316     _string_0f_86_jump_loop/imm32/subx-name
30317     0/imm32/no-rm32
30318     0/imm32/no-r32
30319     0/imm32/no-imm32
30320     0/imm32/no-imm8
30321     0/imm32/no-disp32
30322     0/imm32/no-xm32
30323     0/imm32/no-x32
30324     0x11/imm32/alloc-id:fake
30325     _Primitive-loop-if-addr>/imm32/next
30326 _Primitive-loop-if-addr>:  # (payload primitive)
30327     0x11/imm32/alloc-id:fake:payload
30328     0x11/imm32/alloc-id:fake
30329     _string-loop-if-addr>/imm32/name
30330     0/imm32/no-inouts
30331     0/imm32/no-inouts
30332     0/imm32/no-outputs
30333     0/imm32/no-outputs
30334     0x11/imm32/alloc-id:fake
30335     _string_0f_87_jump_loop/imm32/subx-name
30336     0/imm32/no-rm32
30337     0/imm32/no-r32
30338     0/imm32/no-imm32
30339     0/imm32/no-imm8
30340     0/imm32/no-disp32
30341     0/imm32/no-xm32
30342     0/imm32/no-x32
30343     0x11/imm32/alloc-id:fake
30344     _Primitive-loop-if-</imm32/next
30345 _Primitive-loop-if-<:  # (payload primitive)
30346     0x11/imm32/alloc-id:fake:payload
30347     0x11/imm32/alloc-id:fake
30348     _string-loop-if-</imm32/name
30349     0/imm32/no-inouts
30350     0/imm32/no-inouts
30351     0/imm32/no-outputs
30352     0/imm32/no-outputs
30353     0x11/imm32/alloc-id:fake
30354     _string_0f_8c_jump_loop/imm32/subx-name
30355     0/imm32/no-rm32
30356     0/imm32/no-r32
30357     0/imm32/no-imm32
30358     0/imm32/no-imm8
30359     0/imm32/no-disp32
30360     0/imm32/no-xm32
30361     0/imm32/no-x32
30362     0x11/imm32/alloc-id:fake
30363     _Primitive-loop-if->=/imm32/next
30364 _Primitive-loop-if->=:  # (payload primitive)
30365     0x11/imm32/alloc-id:fake:payload
30366     0x11/imm32/alloc-id:fake
30367     _string-loop-if->=/imm32/name
30368     0/imm32/no-inouts
30369     0/imm32/no-inouts
30370     0/imm32/no-outputs
30371     0/imm32/no-outputs
30372     0x11/imm32/alloc-id:fake
30373     _string_0f_8d_jump_loop/imm32/subx-name
30374     0/imm32/no-rm32
30375     0/imm32/no-r32
30376     0/imm32/no-imm32
30377     0/imm32/no-imm8
30378     0/imm32/no-disp32
30379     0/imm32/no-xm32
30380     0/imm32/no-x32
30381     0x11/imm32/alloc-id:fake
30382     _Primitive-loop-if-<=/imm32/next
30383 _Primitive-loop-if-<=:  # (payload primitive)
30384     0x11/imm32/alloc-id:fake:payload
30385     0x11/imm32/alloc-id:fake
30386     _string-loop-if-<=/imm32/name
30387     0/imm32/no-inouts
30388     0/imm32/no-inouts
30389     0/imm32/no-outputs
30390     0/imm32/no-outputs
30391     0x11/imm32/alloc-id:fake
30392     _string_0f_8e_jump_loop/imm32/subx-name
30393     0/imm32/no-rm32
30394     0/imm32/no-r32
30395     0/imm32/no-imm32
30396     0/imm32/no-imm8
30397     0/imm32/no-disp32
30398     0/imm32/no-xm32
30399     0/imm32/no-x32
30400     0x11/imm32/alloc-id:fake
30401     _Primitive-loop-if->/imm32/next
30402 _Primitive-loop-if->:  # (payload primitive)
30403     0x11/imm32/alloc-id:fake:payload
30404     0x11/imm32/alloc-id:fake
30405     _string-loop-if->/imm32/name
30406     0/imm32/no-inouts
30407     0/imm32/no-inouts
30408     0/imm32/no-outputs
30409     0/imm32/no-outputs
30410     0x11/imm32/alloc-id:fake
30411     _string_0f_8f_jump_loop/imm32/subx-name
30412     0/imm32/no-rm32
30413     0/imm32/no-r32
30414     0/imm32/no-imm32
30415     0/imm32/no-imm8
30416     0/imm32/no-disp32
30417     0/imm32/no-xm32
30418     0/imm32/no-x32
30419     0x11/imm32/alloc-id:fake
30420     _Primitive-loop/imm32/next  # we probably don't need an unconditional break
30421 _Primitive-loop:  # (payload primitive)
30422     0x11/imm32/alloc-id:fake:payload
30423     0x11/imm32/alloc-id:fake
30424     _string-loop/imm32/name
30425     0/imm32/no-inouts
30426     0/imm32/no-inouts
30427     0/imm32/no-outputs
30428     0/imm32/no-outputs
30429     0x11/imm32/alloc-id:fake
30430     _string_e9_jump_loop/imm32/subx-name
30431     0/imm32/no-rm32
30432     0/imm32/no-r32
30433     0/imm32/no-imm32
30434     0/imm32/no-imm8
30435     0/imm32/no-disp32
30436     0/imm32/no-xm32
30437     0/imm32/no-x32
30438     0x11/imm32/alloc-id:fake
30439     _Primitive-break-if-addr<-named/imm32/next
30440 # - branches to named blocks
30441 _Primitive-break-if-addr<-named:  # (payload primitive)
30442     0x11/imm32/alloc-id:fake:payload
30443     0x11/imm32/alloc-id:fake
30444     _string-break-if-addr</imm32/name
30445     0x11/imm32/alloc-id:fake
30446     Single-lit-var/imm32/inouts
30447     0/imm32/no-outputs
30448     0/imm32/no-outputs
30449     0x11/imm32/alloc-id:fake
30450     _string_0f_82_jump_label/imm32/subx-name
30451     0/imm32/no-rm32
30452     0/imm32/no-r32
30453     0/imm32/no-imm32
30454     0/imm32/no-imm8
30455     1/imm32/disp32-is-first-inout
30456     0/imm32/no-xm32
30457     0/imm32/no-x32
30458     0x11/imm32/alloc-id:fake
30459     _Primitive-break-if-addr>=-named/imm32/next
30460 _Primitive-break-if-addr>=-named:  # (payload primitive)
30461     0x11/imm32/alloc-id:fake:payload
30462     0x11/imm32/alloc-id:fake
30463     _string-break-if-addr>=/imm32/name
30464     0x11/imm32/alloc-id:fake
30465     Single-lit-var/imm32/inouts
30466     0/imm32/no-outputs
30467     0/imm32/no-outputs
30468     0x11/imm32/alloc-id:fake
30469     _string_0f_83_jump_label/imm32/subx-name
30470     0/imm32/no-rm32
30471     0/imm32/no-r32
30472     0/imm32/no-imm32
30473     0/imm32/no-imm8
30474     1/imm32/disp32-is-first-inout
30475     0/imm32/no-xm32
30476     0/imm32/no-x32
30477     0x11/imm32/alloc-id:fake
30478     _Primitive-break-if-=-named/imm32/next
30479 _Primitive-break-if-=-named:  # (payload primitive)
30480     0x11/imm32/alloc-id:fake:payload
30481     0x11/imm32/alloc-id:fake
30482     _string-break-if-=/imm32/name
30483     0x11/imm32/alloc-id:fake
30484     Single-lit-var/imm32/inouts
30485     0/imm32/no-outputs
30486     0/imm32/no-outputs
30487     0x11/imm32/alloc-id:fake
30488     _string_0f_84_jump_label/imm32/subx-name
30489     0/imm32/no-rm32
30490     0/imm32/no-r32
30491     0/imm32/no-imm32
30492     0/imm32/no-imm8
30493     1/imm32/disp32-is-first-inout
30494     0/imm32/no-xm32
30495     0/imm32/no-x32
30496     0x11/imm32/alloc-id:fake
30497     _Primitive-break-if-!=-named/imm32/next
30498 _Primitive-break-if-!=-named:  # (payload primitive)
30499     0x11/imm32/alloc-id:fake:payload
30500     0x11/imm32/alloc-id:fake
30501     _string-break-if-!=/imm32/name
30502     0x11/imm32/alloc-id:fake
30503     Single-lit-var/imm32/inouts
30504     0/imm32/no-outputs
30505     0/imm32/no-outputs
30506     0x11/imm32/alloc-id:fake
30507     _string_0f_85_jump_label/imm32/subx-name
30508     0/imm32/no-rm32
30509     0/imm32/no-r32
30510     0/imm32/no-imm32
30511     0/imm32/no-imm8
30512     1/imm32/disp32-is-first-inout
30513     0/imm32/no-xm32
30514     0/imm32/no-x32
30515     0x11/imm32/alloc-id:fake
30516     _Primitive-break-if-addr<=-named/imm32/next
30517 _Primitive-break-if-addr<=-named:  # (payload primitive)
30518     0x11/imm32/alloc-id:fake:payload
30519     0x11/imm32/alloc-id:fake
30520     _string-break-if-addr<=/imm32/name
30521     0x11/imm32/alloc-id:fake
30522     Single-lit-var/imm32/inouts
30523     0/imm32/no-outputs
30524     0/imm32/no-outputs
30525     0x11/imm32/alloc-id:fake
30526     _string_0f_86_jump_label/imm32/subx-name
30527     0/imm32/no-rm32
30528     0/imm32/no-r32
30529     0/imm32/no-imm32
30530     0/imm32/no-imm8
30531     1/imm32/disp32-is-first-inout
30532     0/imm32/no-xm32
30533     0/imm32/no-x32
30534     0x11/imm32/alloc-id:fake
30535     _Primitive-break-if-addr>-named/imm32/next
30536 _Primitive-break-if-addr>-named:  # (payload primitive)
30537     0x11/imm32/alloc-id:fake:payload
30538     0x11/imm32/alloc-id:fake
30539     _string-break-if-addr>/imm32/name
30540     0x11/imm32/alloc-id:fake
30541     Single-lit-var/imm32/inouts
30542     0/imm32/no-outputs
30543     0/imm32/no-outputs
30544     0x11/imm32/alloc-id:fake
30545     _string_0f_87_jump_label/imm32/subx-name
30546     0/imm32/no-rm32
30547     0/imm32/no-r32
30548     0/imm32/no-imm32
30549     0/imm32/no-imm8
30550     1/imm32/disp32-is-first-inout
30551     0/imm32/no-xm32
30552     0/imm32/no-x32
30553     0x11/imm32/alloc-id:fake
30554     _Primitive-break-if-<-named/imm32/next
30555 _Primitive-break-if-<-named:  # (payload primitive)
30556     0x11/imm32/alloc-id:fake:payload
30557     0x11/imm32/alloc-id:fake
30558     _string-break-if-</imm32/name
30559     0x11/imm32/alloc-id:fake
30560     Single-lit-var/imm32/inouts
30561     0/imm32/no-outputs
30562     0/imm32/no-outputs
30563     0x11/imm32/alloc-id:fake
30564     _string_0f_8c_jump_label/imm32/subx-name
30565     0/imm32/no-rm32
30566     0/imm32/no-r32
30567     0/imm32/no-imm32
30568     0/imm32/no-imm8
30569     1/imm32/disp32-is-first-inout
30570     0/imm32/no-xm32
30571     0/imm32/no-x32
30572     0x11/imm32/alloc-id:fake
30573     _Primitive-break-if->=-named/imm32/next
30574 _Primitive-break-if->=-named:  # (payload primitive)
30575     0x11/imm32/alloc-id:fake:payload
30576     0x11/imm32/alloc-id:fake
30577     _string-break-if->=/imm32/name
30578     0x11/imm32/alloc-id:fake
30579     Single-lit-var/imm32/inouts
30580     0/imm32/no-outputs
30581     0/imm32/no-outputs
30582     0x11/imm32/alloc-id:fake
30583     _string_0f_8d_jump_label/imm32/subx-name
30584     0/imm32/no-rm32
30585     0/imm32/no-r32
30586     0/imm32/no-imm32
30587     0/imm32/no-imm8
30588     1/imm32/disp32-is-first-inout
30589     0/imm32/no-xm32
30590     0/imm32/no-x32
30591     0x11/imm32/alloc-id:fake
30592     _Primitive-break-if-<=-named/imm32/next
30593 _Primitive-break-if-<=-named:  # (payload primitive)
30594     0x11/imm32/alloc-id:fake:payload
30595     0x11/imm32/alloc-id:fake
30596     _string-break-if-<=/imm32/name
30597     0x11/imm32/alloc-id:fake
30598     Single-lit-var/imm32/inouts
30599     0/imm32/no-outputs
30600     0/imm32/no-outputs
30601     0x11/imm32/alloc-id:fake
30602     _string_0f_8e_jump_label/imm32/subx-name
30603     0/imm32/no-rm32
30604     0/imm32/no-r32
30605     0/imm32/no-imm32
30606     0/imm32/no-imm8
30607     1/imm32/disp32-is-first-inout
30608     0/imm32/no-xm32
30609     0/imm32/no-x32
30610     0x11/imm32/alloc-id:fake
30611     _Primitive-break-if->-named/imm32/next
30612 _Primitive-break-if->-named:  # (payload primitive)
30613     0x11/imm32/alloc-id:fake:payload
30614     0x11/imm32/alloc-id:fake
30615     _string-break-if->/imm32/name
30616     0x11/imm32/alloc-id:fake
30617     Single-lit-var/imm32/inouts
30618     0/imm32/no-outputs
30619     0/imm32/no-outputs
30620     0x11/imm32/alloc-id:fake
30621     _string_0f_8f_jump_label/imm32/subx-name
30622     0/imm32/no-rm32
30623     0/imm32/no-r32
30624     0/imm32/no-imm32
30625     0/imm32/no-imm8
30626     1/imm32/disp32-is-first-inout
30627     0/imm32/no-xm32
30628     0/imm32/no-x32
30629     0x11/imm32/alloc-id:fake
30630     _Primitive-break-named/imm32/next
30631 _Primitive-break-named:  # (payload primitive)
30632     0x11/imm32/alloc-id:fake:payload
30633     0x11/imm32/alloc-id:fake
30634     _string-break/imm32/name
30635     0x11/imm32/alloc-id:fake
30636     Single-lit-var/imm32/inouts
30637     0/imm32/no-outputs
30638     0/imm32/no-outputs
30639     0x11/imm32/alloc-id:fake
30640     _string_e9_jump_label/imm32/subx-name
30641     0/imm32/no-rm32
30642     0/imm32/no-r32
30643     0/imm32/no-imm32
30644     0/imm32/no-imm8
30645     1/imm32/disp32-is-first-inout
30646     0/imm32/no-xm32
30647     0/imm32/no-x32
30648     0x11/imm32/alloc-id:fake
30649     _Primitive-loop-if-addr<-named/imm32/next
30650 _Primitive-loop-if-addr<-named:  # (payload primitive)
30651     0x11/imm32/alloc-id:fake:payload
30652     0x11/imm32/alloc-id:fake
30653     _string-loop-if-addr</imm32/name
30654     0x11/imm32/alloc-id:fake
30655     Single-lit-var/imm32/inouts
30656     0/imm32/no-outputs
30657     0/imm32/no-outputs
30658     0x11/imm32/alloc-id:fake
30659     _string_0f_82_jump_label/imm32/subx-name
30660     0/imm32/no-rm32
30661     0/imm32/no-r32
30662     0/imm32/no-imm32
30663     0/imm32/no-imm8
30664     1/imm32/disp32-is-first-inout
30665     0/imm32/no-xm32
30666     0/imm32/no-x32
30667     0x11/imm32/alloc-id:fake
30668     _Primitive-loop-if-addr>=-named/imm32/next
30669 _Primitive-loop-if-addr>=-named:  # (payload primitive)
30670     0x11/imm32/alloc-id:fake:payload
30671     0x11/imm32/alloc-id:fake
30672     _string-loop-if-addr>=/imm32/name
30673     0x11/imm32/alloc-id:fake
30674     Single-lit-var/imm32/inouts
30675     0/imm32/no-outputs
30676     0/imm32/no-outputs
30677     0x11/imm32/alloc-id:fake
30678     _string_0f_83_jump_label/imm32/subx-name
30679     0/imm32/no-rm32
30680     0/imm32/no-r32
30681     0/imm32/no-imm32
30682     0/imm32/no-imm8
30683     1/imm32/disp32-is-first-inout
30684     0/imm32/no-xm32
30685     0/imm32/no-x32
30686     0x11/imm32/alloc-id:fake
30687     _Primitive-loop-if-=-named/imm32/next
30688 _Primitive-loop-if-=-named:  # (payload primitive)
30689     0x11/imm32/alloc-id:fake:payload
30690     0x11/imm32/alloc-id:fake
30691     _string-loop-if-=/imm32/name
30692     0x11/imm32/alloc-id:fake
30693     Single-lit-var/imm32/inouts
30694     0/imm32/no-outputs
30695     0/imm32/no-outputs
30696     0x11/imm32/alloc-id:fake
30697     _string_0f_84_jump_label/imm32/subx-name
30698     0/imm32/no-rm32
30699     0/imm32/no-r32
30700     0/imm32/no-imm32
30701     0/imm32/no-imm8
30702     1/imm32/disp32-is-first-inout
30703     0/imm32/no-xm32
30704     0/imm32/no-x32
30705     0x11/imm32/alloc-id:fake
30706     _Primitive-loop-if-!=-named/imm32/next
30707 _Primitive-loop-if-!=-named:  # (payload primitive)
30708     0x11/imm32/alloc-id:fake:payload
30709     0x11/imm32/alloc-id:fake
30710     _string-loop-if-!=/imm32/name
30711     0x11/imm32/alloc-id:fake
30712     Single-lit-var/imm32/inouts
30713     0/imm32/no-outputs
30714     0/imm32/no-outputs
30715     0x11/imm32/alloc-id:fake
30716     _string_0f_85_jump_label/imm32/subx-name
30717     0/imm32/no-rm32
30718     0/imm32/no-r32
30719     0/imm32/no-imm32
30720     0/imm32/no-imm8
30721     1/imm32/disp32-is-first-inout
30722     0/imm32/no-xm32
30723     0/imm32/no-x32
30724     0x11/imm32/alloc-id:fake
30725     _Primitive-loop-if-addr<=-named/imm32/next
30726 _Primitive-loop-if-addr<=-named:  # (payload primitive)
30727     0x11/imm32/alloc-id:fake:payload
30728     0x11/imm32/alloc-id:fake
30729     _string-loop-if-addr<=/imm32/name
30730     0x11/imm32/alloc-id:fake
30731     Single-lit-var/imm32/inouts
30732     0/imm32/no-outputs
30733     0/imm32/no-outputs
30734     0x11/imm32/alloc-id:fake
30735     _string_0f_86_jump_label/imm32/subx-name
30736     0/imm32/no-rm32
30737     0/imm32/no-r32
30738     0/imm32/no-imm32
30739     0/imm32/no-imm8
30740     1/imm32/disp32-is-first-inout
30741     0/imm32/no-xm32
30742     0/imm32/no-x32
30743     0x11/imm32/alloc-id:fake
30744     _Primitive-loop-if-addr>-named/imm32/next
30745 _Primitive-loop-if-addr>-named:  # (payload primitive)
30746     0x11/imm32/alloc-id:fake:payload
30747     0x11/imm32/alloc-id:fake
30748     _string-loop-if-addr>/imm32/name
30749     0x11/imm32/alloc-id:fake
30750     Single-lit-var/imm32/inouts
30751     0/imm32/no-outputs
30752     0/imm32/no-outputs
30753     0x11/imm32/alloc-id:fake
30754     _string_0f_87_jump_label/imm32/subx-name
30755     0/imm32/no-rm32
30756     0/imm32/no-r32
30757     0/imm32/no-imm32
30758     0/imm32/no-imm8
30759     1/imm32/disp32-is-first-inout
30760     0/imm32/no-xm32
30761     0/imm32/no-x32
30762     0x11/imm32/alloc-id:fake
30763     _Primitive-loop-if-<-named/imm32/next
30764 _Primitive-loop-if-<-named:  # (payload primitive)
30765     0x11/imm32/alloc-id:fake:payload
30766     0x11/imm32/alloc-id:fake
30767     _string-loop-if-</imm32/name
30768     0x11/imm32/alloc-id:fake
30769     Single-lit-var/imm32/inouts
30770     0/imm32/no-outputs
30771     0/imm32/no-outputs
30772     0x11/imm32/alloc-id:fake
30773     _string_0f_8c_jump_label/imm32/subx-name
30774     0/imm32/no-rm32
30775     0/imm32/no-r32
30776     0/imm32/no-imm32
30777     0/imm32/no-imm8
30778     1/imm32/disp32-is-first-inout
30779     0/imm32/no-xm32
30780     0/imm32/no-x32
30781     0x11/imm32/alloc-id:fake
30782     _Primitive-loop-if->=-named/imm32/next
30783 _Primitive-loop-if->=-named:  # (payload primitive)
30784     0x11/imm32/alloc-id:fake:payload
30785     0x11/imm32/alloc-id:fake
30786     _string-loop-if->=/imm32/name
30787     0x11/imm32/alloc-id:fake
30788     Single-lit-var/imm32/inouts
30789     0/imm32/no-outputs
30790     0/imm32/no-outputs
30791     0x11/imm32/alloc-id:fake
30792     _string_0f_8d_jump_label/imm32/subx-name
30793     0/imm32/no-rm32
30794     0/imm32/no-r32
30795     0/imm32/no-imm32
30796     0/imm32/no-imm8
30797     1/imm32/disp32-is-first-inout
30798     0/imm32/no-xm32
30799     0/imm32/no-x32
30800     0x11/imm32/alloc-id:fake
30801     _Primitive-loop-if-<=-named/imm32/next
30802 _Primitive-loop-if-<=-named:  # (payload primitive)
30803     0x11/imm32/alloc-id:fake:payload
30804     0x11/imm32/alloc-id:fake
30805     _string-loop-if-<=/imm32/name
30806     0x11/imm32/alloc-id:fake
30807     Single-lit-var/imm32/inouts
30808     0/imm32/no-outputs
30809     0/imm32/no-outputs
30810     0x11/imm32/alloc-id:fake
30811     _string_0f_8e_jump_label/imm32/subx-name
30812     0/imm32/no-rm32
30813     0/imm32/no-r32
30814     0/imm32/no-imm32
30815     0/imm32/no-imm8
30816     1/imm32/disp32-is-first-inout
30817     0/imm32/no-xm32
30818     0/imm32/no-x32
30819     0x11/imm32/alloc-id:fake
30820     _Primitive-loop-if->-named/imm32/next
30821 _Primitive-loop-if->-named:  # (payload primitive)
30822     0x11/imm32/alloc-id:fake:payload
30823     0x11/imm32/alloc-id:fake
30824     _string-loop-if->/imm32/name
30825     0x11/imm32/alloc-id:fake
30826     Single-lit-var/imm32/inouts
30827     0/imm32/no-outputs
30828     0/imm32/no-outputs
30829     0x11/imm32/alloc-id:fake
30830     _string_0f_8f_jump_label/imm32/subx-name
30831     0/imm32/no-rm32
30832     0/imm32/no-r32
30833     0/imm32/no-imm32
30834     0/imm32/no-imm8
30835     1/imm32/disp32-is-first-inout
30836     0/imm32/no-xm32
30837     0/imm32/no-x32
30838     0x11/imm32/alloc-id:fake
30839     _Primitive-loop-named/imm32/next  # we probably don't need an unconditional break
30840 _Primitive-loop-named:  # (payload primitive)
30841     0x11/imm32/alloc-id:fake:payload
30842     0x11/imm32/alloc-id:fake
30843     _string-loop/imm32/name
30844     0x11/imm32/alloc-id:fake
30845     Single-lit-var/imm32/inouts
30846     0/imm32/no-outputs
30847     0/imm32/no-outputs
30848     0x11/imm32/alloc-id:fake
30849     _string_e9_jump_label/imm32/subx-name
30850     0/imm32/no-rm32
30851     0/imm32/no-r32
30852     0/imm32/no-imm32
30853     0/imm32/no-imm8
30854     1/imm32/disp32-is-first-inout
30855     0/imm32/no-xm32
30856     0/imm32/no-x32
30857     0x11/imm32/alloc-id:fake
30858     _Primitive-break-if-float</imm32/next
30859 # - branches based on floating-point comparisons
30860 _Primitive-break-if-float<:  # (payload primitive)
30861     0x11/imm32/alloc-id:fake:payload
30862     0x11/imm32/alloc-id:fake
30863     _string-break-if-float</imm32/name
30864     0/imm32/no-inouts
30865     0/imm32/no-inouts
30866     0/imm32/no-outputs
30867     0/imm32/no-outputs
30868     0x11/imm32/alloc-id:fake
30869     _string_0f_82_jump_break/imm32/subx-name
30870     0/imm32/no-rm32
30871     0/imm32/no-r32
30872     0/imm32/no-imm32
30873     0/imm32/no-imm8
30874     0/imm32/no-disp32
30875     0/imm32/no-xm32
30876     0/imm32/no-x32
30877     0x11/imm32/alloc-id:fake
30878     _Primitive-break-if-float>=/imm32/next
30879 _Primitive-break-if-float>=:  # (payload primitive)
30880     0x11/imm32/alloc-id:fake:payload
30881     0x11/imm32/alloc-id:fake
30882     _string-break-if-float>=/imm32/name
30883     0/imm32/no-inouts
30884     0/imm32/no-inouts
30885     0/imm32/no-outputs
30886     0/imm32/no-outputs
30887     0x11/imm32/alloc-id:fake
30888     _string_0f_83_jump_break/imm32/subx-name
30889     0/imm32/no-rm32
30890     0/imm32/no-r32
30891     0/imm32/no-imm32
30892     0/imm32/no-imm8
30893     0/imm32/no-disp32
30894     0/imm32/no-xm32
30895     0/imm32/no-x32
30896     0x11/imm32/alloc-id:fake
30897     _Primitive-break-if-float<=/imm32/next
30898 _Primitive-break-if-float<=:  # (payload primitive)
30899     0x11/imm32/alloc-id:fake:payload
30900     0x11/imm32/alloc-id:fake
30901     _string-break-if-float<=/imm32/name
30902     0/imm32/no-inouts
30903     0/imm32/no-inouts
30904     0/imm32/no-outputs
30905     0/imm32/no-outputs
30906     0x11/imm32/alloc-id:fake
30907     _string_0f_86_jump_break/imm32/subx-name
30908     0/imm32/no-rm32
30909     0/imm32/no-r32
30910     0/imm32/no-imm32
30911     0/imm32/no-imm8
30912     0/imm32/no-disp32
30913     0/imm32/no-xm32
30914     0/imm32/no-x32
30915     0x11/imm32/alloc-id:fake
30916     _Primitive-break-if-float>/imm32/next
30917 _Primitive-break-if-float>:  # (payload primitive)
30918     0x11/imm32/alloc-id:fake:payload
30919     0x11/imm32/alloc-id:fake
30920     _string-break-if-float>/imm32/name
30921     0/imm32/no-inouts
30922     0/imm32/no-inouts
30923     0/imm32/no-outputs
30924     0/imm32/no-outputs
30925     0x11/imm32/alloc-id:fake
30926     _string_0f_87_jump_break/imm32/subx-name
30927     0/imm32/no-rm32
30928     0/imm32/no-r32
30929     0/imm32/no-imm32
30930     0/imm32/no-imm8
30931     0/imm32/no-disp32
30932     0/imm32/no-xm32
30933     0/imm32/no-x32
30934     0x11/imm32/alloc-id:fake
30935     _Primitive-loop-if-float</imm32/next
30936 _Primitive-loop-if-float<:  # (payload primitive)
30937     0x11/imm32/alloc-id:fake:payload
30938     0x11/imm32/alloc-id:fake
30939     _string-loop-if-float</imm32/name
30940     0/imm32/no-inouts
30941     0/imm32/no-inouts
30942     0/imm32/no-outputs
30943     0/imm32/no-outputs
30944     0x11/imm32/alloc-id:fake
30945     _string_0f_82_jump_loop/imm32/subx-name
30946     0/imm32/no-rm32
30947     0/imm32/no-r32
30948     0/imm32/no-imm32
30949     0/imm32/no-imm8
30950     0/imm32/no-disp32
30951     0/imm32/no-xm32
30952     0/imm32/no-x32
30953     0x11/imm32/alloc-id:fake
30954     _Primitive-loop-if-float>=/imm32/next
30955 _Primitive-loop-if-float>=:  # (payload primitive)
30956     0x11/imm32/alloc-id:fake:payload
30957     0x11/imm32/alloc-id:fake
30958     _string-loop-if-float>=/imm32/name
30959     0/imm32/no-inouts
30960     0/imm32/no-inouts
30961     0/imm32/no-outputs
30962     0/imm32/no-outputs
30963     0x11/imm32/alloc-id:fake
30964     _string_0f_83_jump_loop/imm32/subx-name
30965     0/imm32/no-rm32
30966     0/imm32/no-r32
30967     0/imm32/no-imm32
30968     0/imm32/no-imm8
30969     0/imm32/no-disp32
30970     0/imm32/no-xm32
30971     0/imm32/no-x32
30972     0x11/imm32/alloc-id:fake
30973     _Primitive-loop-if-float<=/imm32/next
30974 _Primitive-loop-if-float<=:  # (payload primitive)
30975     0x11/imm32/alloc-id:fake:payload
30976     0x11/imm32/alloc-id:fake
30977     _string-loop-if-float<=/imm32/name
30978     0/imm32/no-inouts
30979     0/imm32/no-inouts
30980     0/imm32/no-outputs
30981     0/imm32/no-outputs
30982     0x11/imm32/alloc-id:fake
30983     _string_0f_86_jump_loop/imm32/subx-name
30984     0/imm32/no-rm32
30985     0/imm32/no-r32
30986     0/imm32/no-imm32
30987     0/imm32/no-imm8
30988     0/imm32/no-disp32
30989     0/imm32/no-xm32
30990     0/imm32/no-x32
30991     0x11/imm32/alloc-id:fake
30992     _Primitive-loop-if-float>/imm32/next
30993 _Primitive-loop-if-float>:  # (payload primitive)
30994     0x11/imm32/alloc-id:fake:payload
30995     0x11/imm32/alloc-id:fake
30996     _string-loop-if-float>/imm32/name
30997     0/imm32/no-inouts
30998     0/imm32/no-inouts
30999     0/imm32/no-outputs
31000     0/imm32/no-outputs
31001     0x11/imm32/alloc-id:fake
31002     _string_0f_87_jump_loop/imm32/subx-name
31003     0/imm32/no-rm32
31004     0/imm32/no-r32
31005     0/imm32/no-imm32
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-break-if-float<-named/imm32/next
31012 _Primitive-break-if-float<-named:  # (payload primitive)
31013     0x11/imm32/alloc-id:fake:payload
31014     0x11/imm32/alloc-id:fake
31015     _string-break-if-float</imm32/name
31016     0x11/imm32/alloc-id:fake
31017     Single-lit-var/imm32/inouts
31018     0/imm32/no-outputs
31019     0/imm32/no-outputs
31020     0x11/imm32/alloc-id:fake
31021     _string_0f_82_jump_label/imm32/subx-name
31022     0/imm32/no-rm32
31023     0/imm32/no-r32
31024     0/imm32/no-imm32
31025     0/imm32/no-imm8
31026     1/imm32/disp32-is-first-inout
31027     0/imm32/no-xm32
31028     0/imm32/no-x32
31029     0x11/imm32/alloc-id:fake
31030     _Primitive-break-if-float>=-named/imm32/next
31031 _Primitive-break-if-float>=-named:  # (payload primitive)
31032     0x11/imm32/alloc-id:fake:payload
31033     0x11/imm32/alloc-id:fake
31034     _string-break-if-float>=/imm32/name
31035     0x11/imm32/alloc-id:fake
31036     Single-lit-var/imm32/inouts
31037     0/imm32/no-outputs
31038     0/imm32/no-outputs
31039     0x11/imm32/alloc-id:fake
31040     _string_0f_83_jump_label/imm32/subx-name
31041     0/imm32/no-rm32
31042     0/imm32/no-r32
31043     0/imm32/no-imm32
31044     0/imm32/no-imm8
31045     1/imm32/disp32-is-first-inout
31046     0/imm32/no-xm32
31047     0/imm32/no-x32
31048     0x11/imm32/alloc-id:fake
31049     _Primitive-break-if-float<=-named/imm32/next
31050 _Primitive-break-if-float<=-named:  # (payload primitive)
31051     0x11/imm32/alloc-id:fake:payload
31052     0x11/imm32/alloc-id:fake
31053     _string-break-if-float<=/imm32/name
31054     0x11/imm32/alloc-id:fake
31055     Single-lit-var/imm32/inouts
31056     0/imm32/no-outputs
31057     0/imm32/no-outputs
31058     0x11/imm32/alloc-id:fake
31059     _string_0f_86_jump_label/imm32/subx-name
31060     0/imm32/no-rm32
31061     0/imm32/no-r32
31062     0/imm32/no-imm32
31063     0/imm32/no-imm8
31064     1/imm32/disp32-is-first-inout
31065     0/imm32/no-xm32
31066     0/imm32/no-x32
31067     0x11/imm32/alloc-id:fake
31068     _Primitive-break-if-float>-named/imm32/next
31069 _Primitive-break-if-float>-named:  # (payload primitive)
31070     0x11/imm32/alloc-id:fake:payload
31071     0x11/imm32/alloc-id:fake
31072     _string-break-if-float>/imm32/name
31073     0x11/imm32/alloc-id:fake
31074     Single-lit-var/imm32/inouts
31075     0/imm32/no-outputs
31076     0/imm32/no-outputs
31077     0x11/imm32/alloc-id:fake
31078     _string_0f_87_jump_label/imm32/subx-name
31079     0/imm32/no-rm32
31080     0/imm32/no-r32
31081     0/imm32/no-imm32
31082     0/imm32/no-imm8
31083     1/imm32/disp32-is-first-inout
31084     0/imm32/no-xm32
31085     0/imm32/no-x32
31086     0x11/imm32/alloc-id:fake
31087     _Primitive-loop-if-float<-named/imm32/next
31088 _Primitive-loop-if-float<-named:  # (payload primitive)
31089     0x11/imm32/alloc-id:fake:payload
31090     0x11/imm32/alloc-id:fake
31091     _string-loop-if-float</imm32/name
31092     0x11/imm32/alloc-id:fake
31093     Single-lit-var/imm32/inouts
31094     0/imm32/no-outputs
31095     0/imm32/no-outputs
31096     0x11/imm32/alloc-id:fake
31097     _string_0f_82_jump_label/imm32/subx-name
31098     0/imm32/no-rm32
31099     0/imm32/no-r32
31100     0/imm32/no-imm32
31101     0/imm32/no-imm8
31102     1/imm32/disp32-is-first-inout
31103     0/imm32/no-xm32
31104     0/imm32/no-x32
31105     0x11/imm32/alloc-id:fake
31106     _Primitive-loop-if-float>=-named/imm32/next
31107 _Primitive-loop-if-float>=-named:  # (payload primitive)
31108     0x11/imm32/alloc-id:fake:payload
31109     0x11/imm32/alloc-id:fake
31110     _string-loop-if-float>=/imm32/name
31111     0x11/imm32/alloc-id:fake
31112     Single-lit-var/imm32/inouts
31113     0/imm32/no-outputs
31114     0/imm32/no-outputs
31115     0x11/imm32/alloc-id:fake
31116     _string_0f_83_jump_label/imm32/subx-name
31117     0/imm32/no-rm32
31118     0/imm32/no-r32
31119     0/imm32/no-imm32
31120     0/imm32/no-imm8
31121     1/imm32/disp32-is-first-inout
31122     0/imm32/no-xm32
31123     0/imm32/no-x32
31124     0x11/imm32/alloc-id:fake
31125     _Primitive-loop-if-float<=-named/imm32/next
31126 _Primitive-loop-if-float<=-named:  # (payload primitive)
31127     0x11/imm32/alloc-id:fake:payload
31128     0x11/imm32/alloc-id:fake
31129     _string-loop-if-float<=/imm32/name
31130     0x11/imm32/alloc-id:fake
31131     Single-lit-var/imm32/inouts
31132     0/imm32/no-outputs
31133     0/imm32/no-outputs
31134     0x11/imm32/alloc-id:fake
31135     _string_0f_86_jump_label/imm32/subx-name
31136     0/imm32/no-rm32
31137     0/imm32/no-r32
31138     0/imm32/no-imm32
31139     0/imm32/no-imm8
31140     1/imm32/disp32-is-first-inout
31141     0/imm32/no-xm32
31142     0/imm32/no-x32
31143     0x11/imm32/alloc-id:fake
31144     _Primitive-loop-if-float>-named/imm32/next
31145 _Primitive-loop-if-float>-named:  # (payload primitive)
31146     0x11/imm32/alloc-id:fake:payload
31147     0x11/imm32/alloc-id:fake
31148     _string-loop-if-float>/imm32/name
31149     0x11/imm32/alloc-id:fake
31150     Single-lit-var/imm32/inouts
31151     0/imm32/no-outputs
31152     0/imm32/no-outputs
31153     0x11/imm32/alloc-id:fake
31154     _string_0f_87_jump_label/imm32/subx-name
31155     0/imm32/no-rm32
31156     0/imm32/no-r32
31157     0/imm32/no-imm32
31158     0/imm32/no-imm8
31159     1/imm32/disp32-is-first-inout
31160     0/imm32/no-xm32
31161     0/imm32/no-x32
31162     0/imm32/next
31163     0/imm32/next
31164 
31165 # string literals for Mu instructions
31166 _string-add:  # (payload array byte)
31167     0x11/imm32/alloc-id:fake:payload
31168     # "add"
31169     0x3/imm32/size
31170     0x61/a 0x64/d 0x64/d
31171 _string-address:  # (payload array byte)
31172     0x11/imm32/alloc-id:fake:payload
31173     # "address"
31174     0x7/imm32/size
31175     0x61/a 0x64/d 0x64/d 0x72/r 0x65/e 0x73/s 0x73/s
31176 _string-add-to:  # (payload array byte)
31177     0x11/imm32/alloc-id:fake:payload
31178     # "add-to"
31179     0x6/imm32/size
31180     0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o
31181 _string-and:  # (payload array byte)
31182     0x11/imm32/alloc-id:fake:payload
31183     # "and"
31184     0x3/imm32/size
31185     0x61/a 0x6e/n 0x64/d
31186 _string-and-with:  # (payload array byte)
31187     0x11/imm32/alloc-id:fake:payload
31188     # "and-with"
31189     0x8/imm32/size
31190     0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
31191 _string-break:  # (payload array byte)
31192     0x11/imm32/alloc-id:fake:payload
31193     # "break"
31194     0x5/imm32/size
31195     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k
31196 _string-break-if-<:  # (payload array byte)
31197     0x11/imm32/alloc-id:fake:payload
31198     # "break-if-<"
31199     0xa/imm32/size
31200     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/<
31201 _string-break-if-<=:  # (payload array byte)
31202     0x11/imm32/alloc-id:fake:payload
31203     # "break-if-<="
31204     0xb/imm32/size
31205     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/=
31206 _string-break-if-=:  # (payload array byte)
31207     0x11/imm32/alloc-id:fake:payload
31208     # "break-if-="
31209     0xa/imm32/size
31210     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/=
31211 _string-break-if->:  # (payload array byte)
31212     0x11/imm32/alloc-id:fake:payload
31213     # "break-if->"
31214     0xa/imm32/size
31215     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/>
31216 _string-break-if->=:  # (payload array byte)
31217     0x11/imm32/alloc-id:fake:payload
31218     # "break-if->="
31219     0xb/imm32/size
31220     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/=
31221 _string-break-if-!=:  # (payload array byte)
31222     0x11/imm32/alloc-id:fake:payload
31223     # "break-if-!="
31224     0xb/imm32/size
31225     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/=
31226 _string-break-if-addr<:  # (payload array byte)
31227     0x11/imm32/alloc-id:fake:payload
31228     # "break-if-addr<"
31229     0xe/imm32/size
31230     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/<
31231 _string-break-if-addr<=:  # (payload array byte)
31232     0x11/imm32/alloc-id:fake:payload
31233     # "break-if-addr<="
31234     0xf/imm32/size
31235     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/=
31236 _string-break-if-addr>:  # (payload array byte)
31237     0x11/imm32/alloc-id:fake:payload
31238     # "break-if-addr>"
31239     0xe/imm32/size
31240     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/>
31241 _string-break-if-addr>=:  # (payload array byte)
31242     0x11/imm32/alloc-id:fake:payload
31243     # "break-if-addr>="
31244     0xf/imm32/size
31245     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/=
31246 _string-break-if-float<:  # (payload array byte)
31247     0x11/imm32/alloc-id:fake:payload
31248     # "break-if-float<"
31249     0xf/imm32/size
31250     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/<
31251 _string-break-if-float<=:  # (payload array byte)
31252     0x11/imm32/alloc-id:fake:payload
31253     # "break-if-float<="
31254     0x10/imm32/size
31255     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/=
31256 _string-break-if-float>:  # (payload array byte)
31257     0x11/imm32/alloc-id:fake:payload
31258     # "break-if-float>"
31259     0xf/imm32/size
31260     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/>
31261 _string-break-if-float>=:  # (payload array byte)
31262     0x11/imm32/alloc-id:fake:payload
31263     # "break-if-float>="
31264     0x10/imm32/size
31265     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/=
31266 _string-compare:  # (payload array byte)
31267     0x11/imm32/alloc-id:fake:payload
31268     # "compare"
31269     0x7/imm32/size
31270     0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e
31271 _string-copy:  # (payload array byte)
31272     0x11/imm32/alloc-id:fake:payload
31273     # "copy"
31274     0x4/imm32/size
31275     0x63/c 0x6f/o 0x70/p 0x79/y
31276 _string-copy-to:  # (payload array byte)
31277     0x11/imm32/alloc-id:fake:payload
31278     # "copy-to"
31279     0x7/imm32/size
31280     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o
31281 _string-copy-byte:
31282     0x11/imm32/alloc-id:fake:payload
31283     # "copy-byte"
31284     0x9/imm32/size
31285     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/- 0x62/b 0x79/y 0x74/t 0x65/e
31286 _string-copy-byte-to:
31287     0x11/imm32/alloc-id:fake:payload
31288     # "copy-byte-to"
31289     0xc/imm32/size
31290     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/- 0x62/b 0x79/y 0x74/t 0x65/e 0x2d/- 0x74/t 0x6f/o
31291 _string-decrement:  # (payload array byte)
31292     0x11/imm32/alloc-id:fake:payload
31293     # "decrement"
31294     0x9/imm32/size
31295     0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t
31296 _string-increment:  # (payload array byte)
31297     0x11/imm32/alloc-id:fake:payload
31298     # "increment"
31299     0x9/imm32/size
31300     0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t
31301 _string-loop:  # (payload array byte)
31302     0x11/imm32/alloc-id:fake:payload
31303     # "loop"
31304     0x4/imm32/size
31305     0x6c/l 0x6f/o 0x6f/o 0x70/p
31306 _string-loop-if-<:  # (payload array byte)
31307     0x11/imm32/alloc-id:fake:payload
31308     # "loop-if-<"
31309     0x9/imm32/size
31310     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/<
31311 _string-loop-if-<=:  # (payload array byte)
31312     0x11/imm32/alloc-id:fake:payload
31313     # "loop-if-<="
31314     0xa/imm32/size
31315     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/=
31316 _string-loop-if-=:  # (payload array byte)
31317     0x11/imm32/alloc-id:fake:payload
31318     # "loop-if-="
31319     0x9/imm32/size
31320     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/=
31321 _string-loop-if->:  # (payload array byte)
31322     0x11/imm32/alloc-id:fake:payload
31323     # "loop-if->"
31324     0x9/imm32/size
31325     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/>
31326 _string-loop-if->=:  # (payload array byte)
31327     0x11/imm32/alloc-id:fake:payload
31328     # "loop-if->="
31329     0xa/imm32/size
31330     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/=
31331 _string-loop-if-!=:  # (payload array byte)
31332     0x11/imm32/alloc-id:fake:payload
31333     # "loop-if-!="
31334     0xa/imm32/size
31335     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/=
31336 _string-loop-if-addr<:  # (payload array byte)
31337     0x11/imm32/alloc-id:fake:payload
31338     # "loop-if-addr<"
31339     0xd/imm32/size
31340     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/<
31341 _string-loop-if-addr<=:  # (payload array byte)
31342     0x11/imm32/alloc-id:fake:payload
31343     # "loop-if-addr<="
31344     0xe/imm32/size
31345     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/=
31346 _string-loop-if-addr>:  # (payload array byte)
31347     0x11/imm32/alloc-id:fake:payload
31348     # "loop-if-addr>"
31349     0xd/imm32/size
31350     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/>
31351 _string-loop-if-addr>=:  # (payload array byte)
31352     0x11/imm32/alloc-id:fake:payload
31353     # "loop-if-addr>="
31354     0xe/imm32/size
31355     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/=
31356 _string-loop-if-float<:  # (payload array byte)
31357     0x11/imm32/alloc-id:fake:payload
31358     # "loop-if-float<"
31359     0xe/imm32/size
31360     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/<
31361 _string-loop-if-float<=:  # (payload array byte)
31362     0x11/imm32/alloc-id:fake:payload
31363     # "loop-if-float<="
31364     0xf/imm32/size
31365     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/=
31366 _string-loop-if-float>:  # (payload array byte)
31367     0x11/imm32/alloc-id:fake:payload
31368     # "loop-if-float>"
31369     0xe/imm32/size
31370     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/>
31371 _string-loop-if-float>=:  # (payload array byte)
31372     0x11/imm32/alloc-id:fake:payload
31373     # "loop-if-float>="
31374     0xf/imm32/size
31375     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/=
31376 _string-multiply:  # (payload array byte)
31377     0x11/imm32/alloc-id:fake:payload
31378     # "multiply"
31379     0x8/imm32/size
31380     0x6d/m 0x75/u 0x6c/l 0x74/t 0x69/i 0x70/p 0x6c/l 0x79/y
31381 _string-convert:  # (payload array byte)
31382     0x11/imm32/alloc-id:fake:payload
31383     # "convert"
31384     0x7/imm32/size
31385     0x63/c 0x6f/o 0x6e/n 0x76/v 0x65/e 0x72/r 0x74/t
31386 _string-truncate:  # (payload array byte)
31387     0x11/imm32/alloc-id:fake:payload
31388     # "truncate"
31389     0x8/imm32/size
31390     0x74/t 0x72/r 0x75/u 0x6e/n 0x63/c 0x61/a 0x74/t 0x65/e
31391 _string-reinterpret:  # (payload array byte)
31392     0x11/imm32/alloc-id:fake:payload
31393     # "reinterpret"
31394     0xb/imm32/size
31395     0x72/r 0x65/e 0x69/i 0x6e/n 0x74/t 0x65/e 0x72/r 0x70/p 0x72/r 0x65/e 0x74/t
31396 _string-divide:
31397     0x11/imm32/alloc-id:fake:payload
31398     # "divide"
31399     0x6/imm32/size
31400     0x64/d 0x69/i 0x76/v 0x69/i 0x64/d 0x65/e
31401 _string-max:
31402     0x11/imm32/alloc-id:fake:payload
31403     # "max"
31404     0x3/imm32/size
31405     0x6d/m 0x61/a 0x78/x
31406 _string-min:
31407     0x11/imm32/alloc-id:fake:payload
31408     # "min"
31409     0x3/imm32/size
31410     0x6d/m 0x69/i 0x6e/n
31411 _string-reciprocal:
31412     0x11/imm32/alloc-id:fake:payload
31413     # "reciprocal"
31414     0xa/imm32/size
31415     0x72/r 0x65/e 0x63/c 0x69/i 0x70/p 0x72/r 0x6f/o 0x63/c 0x61/a 0x6c/l
31416 _string-square-root:
31417     0x11/imm32/alloc-id:fake:payload
31418     # "square-root"
31419     0xb/imm32/size
31420     0x73/s 0x71/q 0x75/u 0x61/a 0x72/r 0x65/e 0x2d/- 0x72/r 0x6f/o 0x6f/o 0x74/t
31421 _string-inverse-square-root:
31422     0x11/imm32/alloc-id:fake:payload
31423     # "inverse-square-root"
31424     0x13/imm32/size
31425     0x69/i 0x6e/n 0x76/v 0x65/e 0x72/r 0x73/s 0x65/e 0x2d/- 0x73/s 0x71/q 0x75/u 0x61/a 0x72/r 0x65/e 0x2d/- 0x72/r 0x6f/o 0x6f/o 0x74/t
31426 _string-negate:  # (payload array byte)
31427     0x11/imm32/alloc-id:fake:payload
31428     # "negate"
31429     0x6/imm32/size
31430     0x6e/n 0x65/e 0x67/g 0x61/a 0x74/t 0x65/e
31431 _string-or:  # (payload array byte)
31432     0x11/imm32/alloc-id:fake:payload
31433     # "or"
31434     0x2/imm32/size
31435     0x6f/o 0x72/r
31436 _string-or-with:  # (payload array byte)
31437     0x11/imm32/alloc-id:fake:payload
31438     # "or-with"
31439     0x7/imm32/size
31440     0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
31441 _string-subtract:  # (payload array byte)
31442     0x11/imm32/alloc-id:fake:payload
31443     # "subtract"
31444     0x8/imm32/size
31445     0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t
31446 _string-subtract-from:  # (payload array byte)
31447     0x11/imm32/alloc-id:fake:payload
31448     # "subtract-from"
31449     0xd/imm32/size
31450     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
31451 _string-xor:  # (payload array byte)
31452     0x11/imm32/alloc-id:fake:payload
31453     # "xor"
31454     0x3/imm32/size
31455     0x78/x 0x6f/o 0x72/r
31456 _string-xor-with:  # (payload array byte)
31457     0x11/imm32/alloc-id:fake:payload
31458     # "xor-with"
31459     0x8/imm32/size
31460     0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
31461 _string-shift-left:  # (payload array byte)
31462     0x11/imm32/alloc-id:fake:payload
31463     # "shift-left"
31464     0xa/imm32/size
31465     0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x6c/l 0x65/e 0x66/f 0x74/t
31466 _string-shift-right:  # (payload array byte)
31467     0x11/imm32/alloc-id:fake:payload
31468     # "shift-right"
31469     0xb/imm32/size
31470     0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x72/r 0x69/i 0x67/g 0x68/h 0x74/t
31471 _string-shift-right-signed:  # (payload array byte)
31472     0x11/imm32/alloc-id:fake:payload
31473     # "shift-right-signed"
31474     0x12/imm32/size
31475     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
31476 
31477 # string literals for SubX instructions
31478 _string_01_add_to:  # (payload array byte)
31479     0x11/imm32/alloc-id:fake:payload
31480     # "01/add-to"
31481     0x9/imm32/size
31482     0x30/0 0x31/1 0x2f/slash 0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o
31483 _string_03_add:  # (payload array byte)
31484     0x11/imm32/alloc-id:fake:payload
31485     # "03/add"
31486     0x6/imm32/size
31487     0x30/0 0x33/3 0x2f/slash 0x61/a 0x64/d 0x64/d
31488 _string_05_add_to_eax:  # (payload array byte)
31489     0x11/imm32/alloc-id:fake:payload
31490     # "05/add-to-eax"
31491     0xd/imm32/size
31492     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
31493 _string_09_or_with:  # (payload array byte)
31494     0x11/imm32/alloc-id:fake:payload
31495     # "09/or-with"
31496     0xa/imm32/size
31497     0x30/0 0x39/9 0x2f/slash 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
31498 _string_0b_or:  # (payload array byte)
31499     0x11/imm32/alloc-id:fake:payload
31500     # "0b/or"
31501     0x5/imm32/size
31502     0x30/0 0x62/b 0x2f/slash 0x6f/o 0x72/r
31503 _string_0d_or_with_eax:  # (payload array byte)
31504     0x11/imm32/alloc-id:fake:payload
31505     # "0d/or-with-eax"
31506     0xe/imm32/size
31507     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
31508 _string_0f_82_jump_label:  # (payload array byte)
31509     0x11/imm32/alloc-id:fake:payload
31510     # "0f 82/jump-if-addr<"
31511     0x13/imm32/size
31512     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/<
31513 _string_0f_82_jump_break:  # (payload array byte)
31514     0x11/imm32/alloc-id:fake:payload
31515     # "0f 82/jump-if-addr< break/disp32"
31516     0x20/imm32/size
31517     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
31518 _string_0f_82_jump_loop:  # (payload array byte)
31519     0x11/imm32/alloc-id:fake:payload
31520     # "0f 82/jump-if-addr< loop/disp32"
31521     0x1f/imm32/size
31522     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
31523 _string_0f_83_jump_label:  # (payload array byte)
31524     0x11/imm32/alloc-id:fake:payload
31525     # "0f 83/jump-if-addr>="
31526     0x14/imm32/size
31527     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/=
31528 _string_0f_83_jump_break:  # (payload array byte)
31529     0x11/imm32/alloc-id:fake:payload
31530     # "0f 83/jump-if-addr>= break/disp32"
31531     0x21/imm32/size
31532     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
31533 _string_0f_83_jump_loop:  # (payload array byte)
31534     0x11/imm32/alloc-id:fake:payload
31535     # "0f 83/jump-if-addr>= loop/disp32"
31536     0x20/imm32/size
31537     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
31538 _string_0f_84_jump_label:  # (payload array byte)
31539     0x11/imm32/alloc-id:fake:payload
31540     # "0f 84/jump-if-="
31541     0xf/imm32/size
31542     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/=
31543 _string_0f_84_jump_break:  # (payload array byte)
31544     0x11/imm32/alloc-id:fake:payload
31545     # "0f 84/jump-if-= break/disp32"
31546     0x1c/imm32/size
31547     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
31548 _string_0f_84_jump_loop:  # (payload array byte)
31549     0x11/imm32/alloc-id:fake:payload
31550     # "0f 84/jump-if-= loop/disp32"
31551     0x1b/imm32/size
31552     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
31553 _string_0f_85_jump_label:  # (payload array byte)
31554     0x11/imm32/alloc-id:fake:payload
31555     # "0f 85/jump-if-!="
31556     0x10/imm32/size
31557     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/=
31558 _string_0f_85_jump_break:  # (payload array byte)
31559     0x11/imm32/alloc-id:fake:payload
31560     # "0f 85/jump-if-!= break/disp32"
31561     0x1d/imm32/size
31562     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
31563 _string_0f_85_jump_loop:  # (payload array byte)
31564     0x11/imm32/alloc-id:fake:payload
31565     # "0f 85/jump-if-!= loop/disp32"
31566     0x1c/imm32/size
31567     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
31568 _string_0f_86_jump_label:  # (payload array byte)
31569     0x11/imm32/alloc-id:fake:payload
31570     # "0f 86/jump-if-addr<="
31571     0x14/imm32/size
31572     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/=
31573 _string_0f_86_jump_break:  # (payload array byte)
31574     0x11/imm32/alloc-id:fake:payload
31575     # "0f 86/jump-if-addr<= break/disp32"
31576     0x21/imm32/size
31577     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
31578 _string_0f_86_jump_loop:  # (payload array byte)
31579     0x11/imm32/alloc-id:fake:payload
31580     # "0f 86/jump-if-addr<= loop/disp32"
31581     0x20/imm32/size
31582     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
31583 _string_0f_87_jump_label:  # (payload array byte)
31584     0x11/imm32/alloc-id:fake:payload
31585     # "0f 87/jump-if-addr>"
31586     0x13/imm32/size
31587     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/>
31588 _string_0f_87_jump_break:  # (payload array byte)
31589     0x11/imm32/alloc-id:fake:payload
31590     # "0f 87/jump-if-addr> break/disp32"
31591     0x20/imm32/size
31592     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
31593 _string_0f_87_jump_loop:  # (payload array byte)
31594     0x11/imm32/alloc-id:fake:payload
31595     # "0f 87/jump-if-addr> loop/disp32"
31596     0x1f/imm32/size
31597     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
31598 _string_0f_8c_jump_label:  # (payload array byte)
31599     0x11/imm32/alloc-id:fake:payload
31600     # "0f 8c/jump-if-<"
31601     0xf/imm32/size
31602     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/<
31603 _string_0f_8c_jump_break:  # (payload array byte)
31604     0x11/imm32/alloc-id:fake:payload
31605     # "0f 8c/jump-if-< break/disp32"
31606     0x1c/imm32/size
31607     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
31608 _string_0f_8c_jump_loop:  # (payload array byte)
31609     0x11/imm32/alloc-id:fake:payload
31610     # "0f 8c/jump-if-< loop/disp32"
31611     0x1b/imm32/size
31612     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
31613 _string_0f_8d_jump_label:  # (payload array byte)
31614     0x11/imm32/alloc-id:fake:payload
31615     # "0f 8d/jump-if->="
31616     0x10/imm32/size
31617     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/=
31618 _string_0f_8d_jump_break:  # (payload array byte)
31619     0x11/imm32/alloc-id:fake:payload
31620     # "0f 8d/jump-if->= break/disp32"
31621     0x1d/imm32/size
31622     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
31623 _string_0f_8d_jump_loop:  # (payload array byte)
31624     0x11/imm32/alloc-id:fake:payload
31625     # "0f 8d/jump-if->= loop/disp32"
31626     0x1c/imm32/size
31627     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
31628 _string_0f_8e_jump_label:  # (payload array byte)
31629     0x11/imm32/alloc-id:fake:payload
31630     # "0f 8e/jump-if-<="
31631     0x10/imm32/size
31632     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/=
31633 _string_0f_8e_jump_break:  # (payload array byte)
31634     0x11/imm32/alloc-id:fake:payload
31635     # "0f 8e/jump-if-<= break/disp32"
31636     0x1d/imm32/size
31637     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
31638 _string_0f_8e_jump_loop:  # (payload array byte)
31639     0x11/imm32/alloc-id:fake:payload
31640     # "0f 8e/jump-if-<= loop/disp32"
31641     0x1c/imm32/size
31642     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
31643 _string_0f_8f_jump_label:  # (payload array byte)
31644     0x11/imm32/alloc-id:fake:payload
31645     # "0f 8f/jump-if->"
31646     0xf/imm32/size
31647     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/>
31648 _string_0f_8f_jump_break:  # (payload array byte)
31649     0x11/imm32/alloc-id:fake:payload
31650     # "0f 8f/jump-if-> break/disp32"
31651     0x1c/imm32/size
31652     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
31653 _string_0f_8f_jump_loop:  # (payload array byte)
31654     0x11/imm32/alloc-id:fake:payload
31655     # "0f 8f/jump-if-> loop/disp32"
31656     0x1b/imm32/size
31657     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
31658 _string_0f_af_multiply:  # (payload array byte)
31659     0x11/imm32/alloc-id:fake:payload
31660     # "0f af/multiply"
31661     0xe/imm32/size
31662     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
31663 _string_f3_0f_2a_convert_to_float:
31664     0x11/imm32/alloc-id:fake:payload
31665     # "f3 0f 2a/convert-to-float"
31666     0x19/imm32/size
31667     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
31668 _string_f3_0f_2d_convert_to_int:
31669     0x11/imm32/alloc-id:fake:payload
31670     # "f3 0f 2d/convert-to-int"
31671     0x17/imm32/size
31672     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
31673 _string_f3_0f_2c_truncate_to_int:
31674     0x11/imm32/alloc-id:fake:payload
31675     # "f3 0f 2c/truncate-to-int"
31676     0x18/imm32/size
31677     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
31678 _string_f3_0f_58_add:
31679     0x11/imm32/alloc-id:fake:payload
31680     # "f3 0f 58/add"
31681     0xc/imm32/size
31682     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x38/8 0x2f/slash 0x61/a 0x64/d 0x64/d
31683 _string_f3_0f_5c_subtract:
31684     0x11/imm32/alloc-id:fake:payload
31685     # "f3 0f 5c/subtract"
31686     0x11/imm32/size
31687     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
31688 _string_f3_0f_59_multiply:
31689     0x11/imm32/alloc-id:fake:payload
31690     # "f3 0f 59/multiply"
31691     0x11/imm32/size
31692     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
31693 _string_f3_0f_5e_divide:
31694     0x11/imm32/alloc-id:fake:payload
31695     # "f3 0f 5e/divide"
31696     0xf/imm32/size
31697     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
31698 _string_f3_0f_53_reciprocal:
31699     0x11/imm32/alloc-id:fake:payload
31700     # "f3 0f 53/reciprocal"
31701     0x13/imm32/size
31702     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
31703 _string_f3_0f_51_square_root:
31704     0x11/imm32/alloc-id:fake:payload
31705     # "f3 0f 51/square-root"
31706     0x14/imm32/size
31707     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
31708 _string_f3_0f_52_inverse_square_root:
31709     0x11/imm32/alloc-id:fake:payload
31710     # "f3 0f 52/inverse-square-root"
31711     0x1c/imm32/size
31712     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
31713 _string_f3_0f_5d_min:
31714     0x11/imm32/alloc-id:fake:payload
31715     # "f3 0f 5d/min"
31716     0xc/imm32/size
31717     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x64/d 0x2f/slash 0x6d/m 0x69/i 0x6e/n
31718 _string_f3_0f_5f_max:
31719     0x11/imm32/alloc-id:fake:payload
31720     # "f3 0f 5f/max"
31721     0xc/imm32/size
31722     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x66/f 0x2f/slash 0x6d/m 0x61/a 0x78/x
31723 _string_f3_0f_10_copy:
31724     0x11/imm32/alloc-id:fake:payload
31725     # "f3 0f 10/copy"
31726     0xd/imm32/size
31727     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
31728 _string_f3_0f_11_copy:
31729     0x11/imm32/alloc-id:fake:payload
31730     # "f3 0f 11/copy"
31731     0xd/imm32/size
31732     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
31733 _string_0f_2f_compare:
31734     0x11/imm32/alloc-id:fake:payload
31735     # "0f 2f/compare"
31736     0xd/imm32/size
31737     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
31738 _string_21_and_with:  # (payload array byte)
31739     0x11/imm32/alloc-id:fake:payload
31740     # "21/and-with"
31741     0xb/imm32/size
31742     0x32/2 0x31/1 0x2f/slash 0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
31743 _string_23_and:  # (payload array byte)
31744     0x11/imm32/alloc-id:fake:payload
31745     # "23/and"
31746     0x6/imm32/size
31747     0x32/2 0x33/3 0x2f/slash 0x61/a 0x6e/n 0x64/d
31748 _string_25_and_with_eax:  # (payload array byte)
31749     0x11/imm32/alloc-id:fake:payload
31750     # "25/and-with-eax"
31751     0xf/imm32/size
31752     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
31753 _string_29_subtract_from:  # (payload array byte)
31754     0x11/imm32/alloc-id:fake:payload
31755     # "29/subtract-from"
31756     0x10/imm32/size
31757     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
31758 _string_2b_subtract:  # (payload array byte)
31759     0x11/imm32/alloc-id:fake:payload
31760     # "2b/subtract"
31761     0xb/imm32/size
31762     0x32/2 0x62/b 0x2f/slash 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t
31763 _string_2d_subtract_from_eax:  # (payload array byte)
31764     0x11/imm32/alloc-id:fake:payload
31765     # "2d/subtract-from-eax"
31766     0x14/imm32/size
31767     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
31768 _string_31_xor_with:  # (payload array byte)
31769     0x11/imm32/alloc-id:fake:payload
31770     # "31/xor-with"
31771     0xb/imm32/size
31772     0x33/3 0x31/1 0x2f/slash 0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
31773 _string_33_xor:  # (payload array byte)
31774     0x11/imm32/alloc-id:fake:payload
31775     # "33/xor"
31776     0x6/imm32/size
31777     0x33/3 0x33/3 0x2f/slash 0x78/x 0x6f/o 0x72/r
31778 _string_35_xor_with_eax:  # (payload array byte)
31779     0x11/imm32/alloc-id:fake:payload
31780     # "35/xor-with-eax"
31781     0xf/imm32/size
31782     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
31783 _string_39_compare->:  # (payload array byte)
31784     0x11/imm32/alloc-id:fake:payload
31785     # "39/compare->"
31786     0xc/imm32/size
31787     0x33/3 0x39/9 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x2d/dash 0x3e/>
31788 _string_3b_compare<-:  # (payload array byte)
31789     0x11/imm32/alloc-id:fake:payload
31790     # "3b/compare<-"
31791     0xc/imm32/size
31792     0x33/3 0x62/b 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x3c/< 0x2d/dash
31793 _string_3d_compare_eax_with:  # (payload array byte)
31794     0x11/imm32/alloc-id:fake:payload
31795     # "3d/compare-eax-with"
31796     0x13/imm32/size
31797     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
31798 _string_40_increment_eax:  # (payload array byte)
31799     0x11/imm32/alloc-id:fake:payload
31800     # "40/increment-eax"
31801     0x10/imm32/size
31802     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
31803 _string_41_increment_ecx:  # (payload array byte)
31804     0x11/imm32/alloc-id:fake:payload
31805     # "41/increment-ecx"
31806     0x10/imm32/size
31807     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
31808 _string_42_increment_edx:  # (payload array byte)
31809     0x11/imm32/alloc-id:fake:payload
31810     # "42/increment-edx"
31811     0x10/imm32/size
31812     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
31813 _string_43_increment_ebx:  # (payload array byte)
31814     0x11/imm32/alloc-id:fake:payload
31815     # "43/increment-ebx"
31816     0x10/imm32/size
31817     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
31818 _string_46_increment_esi:  # (payload array byte)
31819     0x11/imm32/alloc-id:fake:payload
31820     # "46/increment-esi"
31821     0x10/imm32/size
31822     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
31823 _string_47_increment_edi:  # (payload array byte)
31824     0x11/imm32/alloc-id:fake:payload
31825     # "47/increment-edi"
31826     0x10/imm32/size
31827     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
31828 _string_48_decrement_eax:  # (payload array byte)
31829     0x11/imm32/alloc-id:fake:payload
31830     # "48/decrement-eax"
31831     0x10/imm32/size
31832     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
31833 _string_49_decrement_ecx:  # (payload array byte)
31834     0x11/imm32/alloc-id:fake:payload
31835     # "49/decrement-ecx"
31836     0x10/imm32/size
31837     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
31838 _string_4a_decrement_edx:  # (payload array byte)
31839     0x11/imm32/alloc-id:fake:payload
31840     # "4a/decrement-edx"
31841     0x10/imm32/size
31842     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
31843 _string_4b_decrement_ebx:  # (payload array byte)
31844     0x11/imm32/alloc-id:fake:payload
31845     # "4b/decrement-ebx"
31846     0x10/imm32/size
31847     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
31848 _string_4e_decrement_esi:  # (payload array byte)
31849     0x11/imm32/alloc-id:fake:payload
31850     # "4e/decrement-esi"
31851     0x10/imm32/size
31852     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
31853 _string_4f_decrement_edi:  # (payload array byte)
31854     0x11/imm32/alloc-id:fake:payload
31855     # "4f/decrement-edi"
31856     0x10/imm32/size
31857     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
31858 _string_81_subop_add:  # (payload array byte)
31859     0x11/imm32/alloc-id:fake:payload
31860     # "81 0/subop/add"
31861     0xe/imm32/size
31862     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
31863 _string_81_subop_or:  # (payload array byte)
31864     0x11/imm32/alloc-id:fake:payload
31865     # "81 1/subop/or"
31866     0xd/imm32/size
31867     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
31868 _string_81_subop_and:  # (payload array byte)
31869     0x11/imm32/alloc-id:fake:payload
31870     # "81 4/subop/and"
31871     0xe/imm32/size
31872     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
31873 _string_81_subop_subtract:  # (payload array byte)
31874     0x11/imm32/alloc-id:fake:payload
31875     # "81 5/subop/subtract"
31876     0x13/imm32/size
31877     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
31878 _string_81_subop_xor:  # (payload array byte)
31879     0x11/imm32/alloc-id:fake:payload
31880     # "81 6/subop/xor"
31881     0xe/imm32/size
31882     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
31883 _string_81_subop_compare:  # (payload array byte)
31884     0x11/imm32/alloc-id:fake:payload
31885     # "81 7/subop/compare"
31886     0x12/imm32/size
31887     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
31888 _string_89_<-:  # (payload array byte)
31889     0x11/imm32/alloc-id:fake:payload
31890     # "89/<-"
31891     0x5/imm32/size
31892     0x38/8 0x39/9 0x2f/slash 0x3c/< 0x2d/dash
31893 _string_8b_->:  # (payload array byte)
31894     0x11/imm32/alloc-id:fake:payload
31895     # "8b/->"
31896     0x5/imm32/size
31897     0x38/8 0x62/b 0x2f/slash 0x2d/dash 0x3e/>
31898 _string_8a_copy_byte:
31899     0x11/imm32/alloc-id:fake:payload
31900     # "8a/byte->"
31901     0x9/imm32/size
31902     0x38/8 0x61/a 0x2f// 0x62/b 0x79/y 0x74/t 0x65/e 0x2d/- 0x3e/>
31903 _string_88_copy_byte:
31904     0x11/imm32/alloc-id:fake:payload
31905     # "88/byte<-"
31906     0x9/imm32/size
31907     0x38/8 0x38/8 0x2f// 0x62/b 0x79/y 0x74/t 0x65/e 0x3c/< 0x2d/-
31908 _string_8d_copy_address:  # (payload array byte)
31909     0x11/imm32/alloc-id:fake:payload
31910     # "8d/copy-address"
31911     0xf/imm32/size
31912     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
31913 _string_b8_copy_to_eax:  # (payload array byte)
31914     0x11/imm32/alloc-id:fake:payload
31915     # "b8/copy-to-eax"
31916     0xe/imm32/size
31917     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
31918 _string_b9_copy_to_ecx:  # (payload array byte)
31919     0x11/imm32/alloc-id:fake:payload
31920     # "b9/copy-to-ecx"
31921     0xe/imm32/size
31922     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
31923 _string_ba_copy_to_edx:  # (payload array byte)
31924     0x11/imm32/alloc-id:fake:payload
31925     # "ba/copy-to-edx"
31926     0xe/imm32/size
31927     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
31928 _string_bb_copy_to_ebx:  # (payload array byte)
31929     0x11/imm32/alloc-id:fake:payload
31930     # "bb/copy-to-ebx"
31931     0xe/imm32/size
31932     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
31933 _string_be_copy_to_esi:  # (payload array byte)
31934     0x11/imm32/alloc-id:fake:payload
31935     # "be/copy-to-esi"
31936     0xe/imm32/size
31937     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
31938 _string_bf_copy_to_edi:  # (payload array byte)
31939     0x11/imm32/alloc-id:fake:payload
31940     # "bf/copy-to-edi"
31941     0xe/imm32/size
31942     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
31943 _string_c7_subop_copy:  # (payload array byte)
31944     0x11/imm32/alloc-id:fake:payload
31945     # "c7 0/subop/copy"
31946     0xf/imm32/size
31947     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
31948 _string_e9_jump_label:  # (payload array byte)
31949     0x11/imm32/alloc-id:fake:payload
31950     # "e9/jump"
31951     0x7/imm32/size
31952     0x65/e 0x39/9 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p
31953 _string_e9_jump_break:  # (payload array byte)
31954     0x11/imm32/alloc-id:fake:payload
31955     # "e9/jump break/disp32"
31956     0x14/imm32/size
31957     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
31958 _string_e9_jump_loop:  # (payload array byte)
31959     0x11/imm32/alloc-id:fake:payload
31960     # "e9/jump loop/disp32"
31961     0x13/imm32/size
31962     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
31963 _string_f7_subop_negate:
31964     0x11/imm32/alloc-id:fake:payload
31965     # "f7 3/subop/negate"
31966     0x11/imm32/size
31967     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
31968 _string_ff_subop_increment:  # (payload array byte)
31969     0x11/imm32/alloc-id:fake:payload
31970     # "ff 0/subop/increment"
31971     0x14/imm32/size
31972     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
31973 _string_ff_subop_decrement:  # (payload array byte)
31974     0x11/imm32/alloc-id:fake:payload
31975     # "ff 1/subop/decrement"
31976     0x14/imm32/size
31977     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
31978 _string_c1_subop_shift_left:  # (payload array byte)
31979     0x11/imm32/alloc-id:fake:payload
31980     # "c1/shift 4/subop/left"
31981     0x15/imm32/size
31982     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
31983 _string_c1_subop_shift_right_padding_zeroes:  # (payload array byte)
31984     0x11/imm32/alloc-id:fake:payload
31985     # "c1/shift 5/subop/right-padding-zeroes"
31986     0x25/imm32/size
31987     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
31988 _string_c1_subop_shift_right_preserving_sign:  # (payload array byte)
31989     0x11/imm32/alloc-id:fake:payload
31990     # "c1/shift 7/subop/right-preserving-sign"
31991     0x26/imm32/size
31992     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
31993 
31994 Single-int-var-in-mem:  # (payload list var)
31995     0x11/imm32/alloc-id:fake:payload
31996     0x11/imm32/alloc-id:fake
31997     Int-var-in-mem/imm32
31998     0/imm32/next
31999     0/imm32/next
32000 
32001 Int-var-in-mem:  # (payload var)
32002     0x11/imm32/alloc-id:fake:payload
32003     0/imm32/name
32004     0/imm32/name
32005     0x11/imm32/alloc-id:fake
32006     Type-int/imm32
32007     1/imm32/some-block-depth
32008     1/imm32/some-stack-offset
32009     0/imm32/no-register
32010     0/imm32/no-register
32011 
32012 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
32013 Single-byte-var-in-mem:  # (payload list var)
32014     0x11/imm32/alloc-id:fake:payload
32015     0x11/imm32/alloc-id:fake
32016     Byte-var-in-mem/imm32
32017     0/imm32/next
32018     0/imm32/next
32019 
32020 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
32021 Byte-var-in-mem:  # (payload var)
32022     0x11/imm32/alloc-id:fake:payload
32023     0/imm32/name
32024     0/imm32/name
32025     0x11/imm32/alloc-id:fake
32026     Type-byte/imm32
32027     1/imm32/some-block-depth
32028     1/imm32/some-stack-offset
32029     0/imm32/no-register
32030     0/imm32/no-register
32031 
32032 Two-args-int-stack-int-reg:  # (payload list var)
32033     0x11/imm32/alloc-id:fake:payload
32034     0x11/imm32/alloc-id:fake
32035     Int-var-in-mem/imm32
32036     0x11/imm32/alloc-id:fake
32037     Single-int-var-in-some-register/imm32/next
32038 
32039 Two-int-args-in-regs:  # (payload list var)
32040     0x11/imm32/alloc-id:fake:payload
32041     0x11/imm32/alloc-id:fake
32042     Int-var-in-some-register/imm32
32043     0x11/imm32/alloc-id:fake
32044     Single-int-var-in-some-register/imm32/next
32045 
32046 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
32047 Two-args-byte-stack-byte-reg:  # (payload list var)
32048     0x11/imm32/alloc-id:fake:payload
32049     0x11/imm32/alloc-id:fake
32050     Byte-var-in-mem/imm32
32051     0x11/imm32/alloc-id:fake
32052     Single-byte-var-in-some-register/imm32/next
32053 
32054 Two-args-int-reg-int-stack:  # (payload list var)
32055     0x11/imm32/alloc-id:fake:payload
32056     0x11/imm32/alloc-id:fake
32057     Int-var-in-some-register/imm32
32058     0x11/imm32/alloc-id:fake
32059     Single-int-var-in-mem/imm32/next
32060 
32061 Two-args-int-eax-int-literal:  # (payload list var)
32062     0x11/imm32/alloc-id:fake:payload
32063     0x11/imm32/alloc-id:fake
32064     Int-var-in-eax/imm32
32065     0x11/imm32/alloc-id:fake
32066     Single-lit-var/imm32/next
32067 
32068 Int-var-and-literal:  # (payload list var)
32069     0x11/imm32/alloc-id:fake:payload
32070     0x11/imm32/alloc-id:fake
32071     Int-var-in-mem/imm32
32072     0x11/imm32/alloc-id:fake
32073     Single-lit-var/imm32/next
32074 
32075 Int-var-in-register-and-literal:  # (payload list var)
32076     0x11/imm32/alloc-id:fake:payload
32077     0x11/imm32/alloc-id:fake
32078     Int-var-in-some-register/imm32
32079     0x11/imm32/alloc-id:fake
32080     Single-lit-var/imm32/next
32081 
32082 Two-float-args-in-regs:  # (payload list var)
32083     0x11/imm32/alloc-id:fake:payload
32084     0x11/imm32/alloc-id:fake
32085     Float-var-in-some-register/imm32
32086     0x11/imm32/alloc-id:fake
32087     Single-float-var-in-some-register/imm32/next
32088 
32089 Two-args-float-reg-float-stack:  # (payload list var)
32090     0x11/imm32/alloc-id:fake:payload
32091     0x11/imm32/alloc-id:fake
32092     Float-var-in-some-register/imm32
32093     0x11/imm32/alloc-id:fake
32094     Single-float-var-in-mem/imm32/next
32095 
32096 Two-args-float-stack-float-reg:  # (payload list var)
32097     0x11/imm32/alloc-id:fake:payload
32098     0x11/imm32/alloc-id:fake
32099     Float-var-in-mem/imm32
32100     0x11/imm32/alloc-id:fake
32101     Single-float-var-in-some-register/imm32/next
32102 
32103 Single-int-var-in-some-register:  # (payload list var)
32104     0x11/imm32/alloc-id:fake:payload
32105     0x11/imm32/alloc-id:fake
32106     Int-var-in-some-register/imm32
32107     0/imm32/next
32108     0/imm32/next
32109 
32110 Single-addr-var-in-some-register:  # (payload list var)
32111     0x11/imm32/alloc-id:fake:payload
32112     0x11/imm32/alloc-id:fake
32113     Addr-var-in-some-register/imm32
32114     0/imm32/next
32115     0/imm32/next
32116 
32117 Single-byte-var-in-some-register:  # (payload list var)
32118     0x11/imm32/alloc-id:fake:payload
32119     0x11/imm32/alloc-id:fake
32120     Byte-var-in-some-register/imm32
32121     0/imm32/next
32122     0/imm32/next
32123 
32124 Int-var-in-some-register:  # (payload var)
32125     0x11/imm32/alloc-id:fake:payload
32126     0/imm32/name
32127     0/imm32/name
32128     0x11/imm32/alloc-id:fake
32129     Type-int/imm32
32130     1/imm32/some-block-depth
32131     0/imm32/no-stack-offset
32132     0x11/imm32/alloc-id:fake
32133     Any-register/imm32
32134 
32135 Any-register:  # (payload array byte)
32136     0x11/imm32/alloc-id:fake:payload
32137     1/imm32/size
32138     # data
32139     2a/asterisk
32140 
32141 Addr-var-in-some-register:  # (payload var)
32142     0x11/imm32/alloc-id:fake:payload
32143     0/imm32/name
32144     0/imm32/name
32145     0x11/imm32/alloc-id:fake
32146     Type-addr/imm32
32147     1/imm32/some-block-depth
32148     0/imm32/no-stack-offset
32149     0x11/imm32/alloc-id:fake
32150     Any-register/imm32
32151 
32152 Byte-var-in-some-register:  # (payload var)
32153     0x11/imm32/alloc-id:fake:payload
32154     0/imm32/name
32155     0/imm32/name
32156     0x11/imm32/alloc-id:fake
32157     Type-byte/imm32
32158     1/imm32/some-block-depth
32159     0/imm32/no-stack-offset
32160     0x11/imm32/alloc-id:fake
32161     Any-register/imm32
32162 
32163 Single-int-var-in-eax:  # (payload list var)
32164     0x11/imm32/alloc-id:fake:payload
32165     0x11/imm32/alloc-id:fake
32166     Int-var-in-eax/imm32
32167     0/imm32/next
32168     0/imm32/next
32169 
32170 Int-var-in-eax:
32171     0x11/imm32/alloc-id:fake:payload
32172     0/imm32/name
32173     0/imm32/name
32174     0x11/imm32/alloc-id:fake
32175     Type-int/imm32
32176     1/imm32/some-block-depth
32177     0/imm32/no-stack-offset
32178     0x11/imm32/alloc-id:fake
32179     $Mu-register-eax/imm32  # can't use Register-eax only to keep our buggy tools/treeshake.cc happy (TODO)
32180 
32181 Single-int-var-in-ecx:  # (payload list var)
32182     0x11/imm32/alloc-id:fake:payload
32183     0x11/imm32/alloc-id:fake
32184     Int-var-in-ecx/imm32
32185     0/imm32/next
32186     0/imm32/next
32187 
32188 Int-var-in-ecx:
32189     0x11/imm32/alloc-id:fake:payload
32190     0/imm32/name
32191     0/imm32/name
32192     0x11/imm32/alloc-id:fake
32193     Type-int/imm32
32194     1/imm32/some-block-depth
32195     0/imm32/no-stack-offset
32196     0x11/imm32/alloc-id:fake
32197     $Register-ecx/imm32/register
32198 
32199 Single-int-var-in-edx:  # (payload list var)
32200     0x11/imm32/alloc-id:fake:payload
32201     0x11/imm32/alloc-id:fake
32202     Int-var-in-edx/imm32
32203     0/imm32/next
32204     0/imm32/next
32205 
32206 Int-var-in-edx:  # (payload list var)
32207     0x11/imm32/alloc-id:fake:payload
32208     0/imm32/name
32209     0/imm32/name
32210     0x11/imm32/alloc-id:fake
32211     Type-int/imm32
32212     1/imm32/some-block-depth
32213     0/imm32/no-stack-offset
32214     0x11/imm32/alloc-id:fake
32215     $Register-edx/imm32/register
32216 
32217 Single-int-var-in-ebx:  # (payload list var)
32218     0x11/imm32/alloc-id:fake:payload
32219     0x11/imm32/alloc-id:fake
32220     Int-var-in-ebx/imm32
32221     0/imm32/next
32222     0/imm32/next
32223 
32224 Int-var-in-ebx:  # (payload list var)
32225     0x11/imm32/alloc-id:fake:payload
32226     0/imm32/name
32227     0/imm32/name
32228     0x11/imm32/alloc-id:fake
32229     Type-int/imm32
32230     1/imm32/some-block-depth
32231     0/imm32/no-stack-offset
32232     0x11/imm32/alloc-id:fake
32233     $Register-ebx/imm32/register
32234 
32235 Single-int-var-in-esi:  # (payload list var)
32236     0x11/imm32/alloc-id:fake:payload
32237     0x11/imm32/alloc-id:fake
32238     Int-var-in-esi/imm32
32239     0/imm32/next
32240     0/imm32/next
32241 
32242 Int-var-in-esi:  # (payload list var)
32243     0x11/imm32/alloc-id:fake:payload
32244     0/imm32/name
32245     0/imm32/name
32246     0x11/imm32/alloc-id:fake
32247     Type-int/imm32
32248     1/imm32/some-block-depth
32249     0/imm32/no-stack-offset
32250     0x11/imm32/alloc-id:fake
32251     $Register-esi/imm32/register
32252 
32253 Single-int-var-in-edi:  # (payload list var)
32254     0x11/imm32/alloc-id:fake:payload
32255     0x11/imm32/alloc-id:fake
32256     Int-var-in-edi/imm32
32257     0/imm32/next
32258     0/imm32/next
32259 
32260 Int-var-in-edi:  # (payload list var)
32261     0x11/imm32/alloc-id:fake:payload
32262     0/imm32/name
32263     0/imm32/name
32264     0x11/imm32/alloc-id:fake
32265     Type-int/imm32
32266     1/imm32/some-block-depth
32267     0/imm32/no-stack-offset
32268     0x11/imm32/alloc-id:fake
32269     $Register-edi/imm32/register
32270 
32271 Single-lit-var:  # (payload list var)
32272     0x11/imm32/alloc-id:fake:payload
32273     0x11/imm32/alloc-id:fake
32274     Lit-var/imm32
32275     0/imm32/next
32276     0/imm32/next
32277 
32278 Lit-var:  # (payload var)
32279     0x11/imm32/alloc-id:fake:payload
32280     0/imm32/name
32281     0/imm32/name
32282     0x11/imm32/alloc-id:fake
32283     Type-literal/imm32
32284     1/imm32/some-block-depth
32285     0/imm32/no-stack-offset
32286     0/imm32/no-register
32287     0/imm32/no-register
32288 
32289 Single-float-var-in-mem:  # (payload list var)
32290     0x11/imm32/alloc-id:fake:payload
32291     0x11/imm32/alloc-id:fake
32292     Float-var-in-mem/imm32
32293     0/imm32/next
32294     0/imm32/next
32295 
32296 Float-var-in-mem:  # (payload var)
32297     0x11/imm32/alloc-id:fake:payload
32298     0/imm32/name
32299     0/imm32/name
32300     0x11/imm32/alloc-id:fake
32301     Type-float/imm32
32302     1/imm32/some-block-depth
32303     1/imm32/some-stack-offset
32304     0/imm32/no-register
32305     0/imm32/no-register
32306 
32307 Single-float-var-in-some-register:  # (payload list var)
32308     0x11/imm32/alloc-id:fake:payload
32309     0x11/imm32/alloc-id:fake
32310     Float-var-in-some-register/imm32
32311     0/imm32/next
32312     0/imm32/next
32313 
32314 Float-var-in-some-register:  # (payload var)
32315     0x11/imm32/alloc-id:fake:payload
32316     0/imm32/name
32317     0/imm32/name
32318     0x11/imm32/alloc-id:fake
32319     Type-float/imm32
32320     1/imm32/some-block-depth
32321     0/imm32/no-stack-offset
32322     0x11/imm32/alloc-id:fake
32323     Any-register/imm32
32324 
32325 Type-int:  # (payload type-tree)
32326     0x11/imm32/alloc-id:fake:payload
32327     1/imm32/is-atom
32328     1/imm32/value:int
32329     0/imm32/left:unused
32330     0/imm32/right:null
32331     0/imm32/right:null
32332 
32333 Type-literal:  # (payload type-tree)
32334     0x11/imm32/alloc-id:fake:payload
32335     1/imm32/is-atom
32336     0/imm32/value:literal
32337     0/imm32/left:unused
32338     0/imm32/right:null
32339     0/imm32/right:null
32340 
32341 Type-addr:  # (payload type-tree)
32342     0x11/imm32/alloc-id:fake:payload
32343     1/imm32/is-atom
32344     2/imm32/value:addr
32345     0/imm32/left:unused
32346     0/imm32/right:null
32347     0/imm32/right:null
32348 
32349 Type-byte:  # (payload type-tree)
32350     0x11/imm32/alloc-id:fake:payload
32351     1/imm32/is-atom
32352     8/imm32/value:byte
32353     0/imm32/left:unused
32354     0/imm32/right:null
32355     0/imm32/right:null
32356 
32357 Type-float:  # (payload type-tree)
32358     0x11/imm32/alloc-id:fake:payload
32359     1/imm32/is-atom
32360     0xf/imm32/value:float
32361     0/imm32/left:unused
32362     0/imm32/right:null
32363     0/imm32/right:null
32364 
32365 == code
32366 emit-subx-primitive:  # out: (addr buffered-file), stmt: (addr stmt), primitive: (addr primitive), err: (addr buffered-file), ed: (addr exit-descriptor)
32367     # . prologue
32368     55/push-ebp
32369     89/<- %ebp 4/r32/esp
32370     # . save registers
32371     50/push-eax
32372     51/push-ecx
32373     # ecx = primitive
32374     8b/-> *(ebp+0x10) 1/r32/ecx
32375     # emit primitive name
32376     (emit-indent *(ebp+8) *Curr-block-depth)
32377     (lookup *(ecx+0x18) *(ecx+0x1c))  # Primitive-subx-name Primitive-subx-name => eax
32378     (write-buffered *(ebp+8) %eax)
32379     # emit rm32 if necessary
32380     (emit-subx-rm32 *(ebp+8) *(ecx+0x20) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-rm32
32381     # emit xm32 if necessary
32382     (emit-subx-rm32 *(ebp+8) *(ecx+0x34) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-xm32
32383     # emit r32 if necessary
32384     (emit-subx-r32 *(ebp+8) *(ecx+0x24) *(ebp+0xc))  # Primitive-subx-r32
32385     # emit x32 if necessary
32386     (emit-subx-x32 *(ebp+8) *(ecx+0x38) *(ebp+0xc))  # Primitive-subx-x32
32387     # emit imm32 if necessary
32388     (emit-subx-imm32 *(ebp+8) *(ecx+0x28) *(ebp+0xc))  # Primitive-subx-imm32
32389     # emit imm8 if necessary
32390     (emit-subx-imm8 *(ebp+8) *(ecx+0x2c) *(ebp+0xc))  # Primitive-subx-imm8
32391     # emit disp32 if necessary
32392     (emit-subx-disp32 *(ebp+8) *(ecx+0x30) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-disp32
32393     (write-buffered *(ebp+8) Newline)
32394 $emit-subx-primitive:end:
32395     # . restore registers
32396     59/pop-to-ecx
32397     58/pop-to-eax
32398     # . epilogue
32399     89/<- %esp 5/r32/ebp
32400     5d/pop-to-ebp
32401     c3/return
32402 
32403 emit-subx-rm32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
32404     # . prologue
32405     55/push-ebp
32406     89/<- %ebp 4/r32/esp
32407     # . save registers
32408     50/push-eax
32409     # if (l == 0) return
32410     81 7/subop/compare *(ebp+0xc) 0/imm32
32411     74/jump-if-= $emit-subx-rm32:end/disp8
32412     # var v/eax: (addr stmt-var)
32413     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # => eax
32414     (emit-subx-var-as-rm32 *(ebp+8) %eax)
32415 $emit-subx-rm32:end:
32416     # . restore registers
32417     58/pop-to-eax
32418     # . epilogue
32419     89/<- %esp 5/r32/ebp
32420     5d/pop-to-ebp
32421     c3/return
32422 
32423 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)
32424     # . prologue
32425     55/push-ebp
32426     89/<- %ebp 4/r32/esp
32427     # . save registers
32428     51/push-ecx
32429     # eax = l
32430     8b/-> *(ebp+0xc) 0/r32/eax
32431     # ecx = stmt
32432     8b/-> *(ebp+8) 1/r32/ecx
32433     # if (l == 1) return stmt->inouts
32434     {
32435       3d/compare-eax-and 1/imm32
32436       75/jump-if-!= break/disp8
32437 $get-stmt-operand-from-arg-location:1:
32438       (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
32439       eb/jump $get-stmt-operand-from-arg-location:end/disp8
32440     }
32441     # if (l == 2) return stmt->inouts->next
32442     {
32443       3d/compare-eax-and 2/imm32
32444       75/jump-if-!= break/disp8
32445 $get-stmt-operand-from-arg-location:2:
32446       (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
32447       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
32448       eb/jump $get-stmt-operand-from-arg-location:end/disp8
32449     }
32450     # if (l == 3) return stmt->outputs
32451     {
32452       3d/compare-eax-and 3/imm32
32453       75/jump-if-!= break/disp8
32454 $get-stmt-operand-from-arg-location:3:
32455       (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
32456       eb/jump $get-stmt-operand-from-arg-location:end/disp8
32457     }
32458     # abort
32459     e9/jump $get-stmt-operand-from-arg-location:abort/disp32
32460 $get-stmt-operand-from-arg-location:end:
32461     # . restore registers
32462     59/pop-to-ecx
32463     # . epilogue
32464     89/<- %esp 5/r32/ebp
32465     5d/pop-to-ebp
32466     c3/return
32467 
32468 $get-stmt-operand-from-arg-location:abort:
32469     # error("invalid arg-location " eax)
32470     (write-buffered *(ebp+0x10) "invalid arg-location ")
32471     (write-int32-hex-buffered *(ebp+0x10) %eax)
32472     (write-buffered *(ebp+0x10) Newline)
32473     (flush *(ebp+0x10))
32474     (stop *(ebp+0x14) 1)
32475     # never gets here
32476 
32477 emit-subx-r32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
32478     # . prologue
32479     55/push-ebp
32480     89/<- %ebp 4/r32/esp
32481     # . save registers
32482     50/push-eax
32483     51/push-ecx
32484     # if (l == 0) return
32485     81 7/subop/compare *(ebp+0xc) 0/imm32
32486     0f 84/jump-if-= $emit-subx-r32:end/disp32
32487     # var v/eax: (addr stmt-var)
32488     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
32489     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
32490     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
32491 #?     (write-buffered Stderr "looking up ")
32492 #?     (write-buffered Stderr %eax)
32493 #?     (write-buffered Stderr Newline)
32494 #?     (flush Stderr)
32495     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
32496     (write-buffered *(ebp+8) Space)
32497     (write-int32-hex-buffered *(ebp+8) *eax)
32498     (write-buffered *(ebp+8) "/r32")
32499 $emit-subx-r32:end:
32500     # . restore registers
32501     59/pop-to-ecx
32502     58/pop-to-eax
32503     # . epilogue
32504     89/<- %esp 5/r32/ebp
32505     5d/pop-to-ebp
32506     c3/return
32507 
32508 emit-subx-x32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
32509     # . prologue
32510     55/push-ebp
32511     89/<- %ebp 4/r32/esp
32512     # . save registers
32513     50/push-eax
32514     51/push-ecx
32515     # if (l == 0) return
32516     81 7/subop/compare *(ebp+0xc) 0/imm32
32517     0f 84/jump-if-= $emit-subx-x32:end/disp32
32518     # var v/eax: (addr stmt-var)
32519     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
32520     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
32521     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
32522 #?     (write-buffered Stderr "looking up ")
32523 #?     (write-buffered Stderr %eax)
32524 #?     (write-buffered Stderr Newline)
32525 #?     (flush Stderr)
32526     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
32527     (write-buffered *(ebp+8) Space)
32528     (write-int32-hex-buffered *(ebp+8) *eax)
32529     (write-buffered *(ebp+8) "/x32")
32530 $emit-subx-x32:end:
32531     # . restore registers
32532     59/pop-to-ecx
32533     58/pop-to-eax
32534     # . epilogue
32535     89/<- %esp 5/r32/ebp
32536     5d/pop-to-ebp
32537     c3/return
32538 
32539 emit-subx-imm32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
32540     # . prologue
32541     55/push-ebp
32542     89/<- %ebp 4/r32/esp
32543     # . save registers
32544     50/push-eax
32545     51/push-ecx
32546     # if (l == 0) return
32547     81 7/subop/compare *(ebp+0xc) 0/imm32
32548     0f 84/jump-if-= $emit-subx-imm32:end/disp32
32549     # var v/eax: (handle var)
32550     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
32551     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
32552     (lookup *eax *(eax+4))  # Var-name Var-name => eax
32553     (write-buffered *(ebp+8) Space)
32554     (write-buffered *(ebp+8) %eax)
32555     (write-buffered *(ebp+8) "/imm32")
32556 $emit-subx-imm32:end:
32557     # . restore registers
32558     59/pop-to-ecx
32559     58/pop-to-eax
32560     # . epilogue
32561     89/<- %esp 5/r32/ebp
32562     5d/pop-to-ebp
32563     c3/return
32564 
32565 emit-subx-imm8:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
32566     # . prologue
32567     55/push-ebp
32568     89/<- %ebp 4/r32/esp
32569     # . save registers
32570     50/push-eax
32571     51/push-ecx
32572     # if (l == 0) return
32573     81 7/subop/compare *(ebp+0xc) 0/imm32
32574     0f 84/jump-if-= $emit-subx-imm32:end/disp32
32575     # var v/eax: (handle var)
32576     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
32577     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
32578     (lookup *eax *(eax+4))  # Var-name Var-name => eax
32579     (write-buffered *(ebp+8) Space)
32580     (write-buffered *(ebp+8) %eax)
32581     (write-buffered *(ebp+8) "/imm8")
32582 $emit-subx-imm8:end:
32583     # . restore registers
32584     59/pop-to-ecx
32585     58/pop-to-eax
32586     # . epilogue
32587     89/<- %esp 5/r32/ebp
32588     5d/pop-to-ebp
32589     c3/return
32590 
32591 emit-subx-disp32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
32592     # . prologue
32593     55/push-ebp
32594     89/<- %ebp 4/r32/esp
32595     # . save registers
32596     50/push-eax
32597     51/push-ecx
32598     # if (location == 0) return
32599     81 7/subop/compare *(ebp+0xc) 0/imm32
32600     0f 84/jump-if-= $emit-subx-disp32:end/disp32
32601     # var v/eax: (addr stmt-var)
32602     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # => eax
32603     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
32604     (lookup *eax *(eax+4))  # Var-name Var-name => eax
32605     (write-buffered *(ebp+8) Space)
32606     (write-buffered *(ebp+8) %eax)
32607     # hack: if instruction operation starts with "break", emit ":break"
32608     # var name/ecx: (addr array byte) = lookup(stmt->operation)
32609     8b/-> *(ebp+0x10) 0/r32/eax
32610     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
32611     89/<- %ecx 0/r32/eax
32612     {
32613       (string-starts-with? %ecx "break")  # => eax
32614       3d/compare-eax-and 0/imm32/false
32615       74/jump-if-= break/disp8
32616       (write-buffered *(ebp+8) ":break")
32617     }
32618     # hack: if instruction operation starts with "loop", emit ":loop"
32619     {
32620       (string-starts-with? %ecx "loop")  # => eax
32621       3d/compare-eax-and 0/imm32/false
32622       74/jump-if-= break/disp8
32623       (write-buffered *(ebp+8) ":loop")
32624     }
32625     (write-buffered *(ebp+8) "/disp32")
32626 $emit-subx-disp32:end:
32627     # . restore registers
32628     59/pop-to-ecx
32629     58/pop-to-eax
32630     # . epilogue
32631     89/<- %esp 5/r32/ebp
32632     5d/pop-to-ebp
32633     c3/return
32634 
32635 emit-call:  # out: (addr buffered-file), stmt: (addr stmt)
32636     # . prologue
32637     55/push-ebp
32638     89/<- %ebp 4/r32/esp
32639     # . save registers
32640     50/push-eax
32641     51/push-ecx
32642     #
32643     (emit-indent *(ebp+8) *Curr-block-depth)
32644     (write-buffered *(ebp+8) "(")
32645     # ecx = stmt
32646     8b/-> *(ebp+0xc) 1/r32/ecx
32647     # - emit function name
32648     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
32649     (write-buffered *(ebp+8) %eax)
32650     # - emit arguments
32651     # var curr/eax: (addr stmt-var) = lookup(stmt->inouts)
32652     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
32653     {
32654       # if (curr == null) break
32655       3d/compare-eax-and 0/imm32
32656       74/jump-if-= break/disp8
32657       #
32658       (emit-subx-call-operand *(ebp+8) %eax)
32659       # curr = lookup(curr->next)
32660       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
32661       eb/jump loop/disp8
32662     }
32663     #
32664     (write-buffered *(ebp+8) ")\n")
32665 $emit-call:end:
32666     # . restore registers
32667     59/pop-to-ecx
32668     58/pop-to-eax
32669     # . epilogue
32670     89/<- %esp 5/r32/ebp
32671     5d/pop-to-ebp
32672     c3/return
32673 
32674 emit-subx-call-operand:  # out: (addr buffered-file), s: (addr stmt-var)
32675     # shares code with emit-subx-var-as-rm32
32676     # . prologue
32677     55/push-ebp
32678     89/<- %ebp 4/r32/esp
32679     # . save registers
32680     50/push-eax
32681     51/push-ecx
32682     56/push-esi
32683     # ecx = s
32684     8b/-> *(ebp+0xc) 1/r32/ecx
32685     # var operand/esi: (addr var) = lookup(s->value)
32686     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
32687     89/<- %esi 0/r32/eax
32688     # if (operand->register && !s->is-deref?) emit "%__"
32689     {
32690 $emit-subx-call-operand:check-for-register-direct:
32691       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
32692       74/jump-if-= break/disp8
32693       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
32694       75/jump-if-!= break/disp8
32695 $emit-subx-call-operand:register-direct:
32696       (write-buffered *(ebp+8) " %")
32697       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
32698       (write-buffered *(ebp+8) %eax)
32699       e9/jump $emit-subx-call-operand:end/disp32
32700     }
32701     # else if (operand->register && s->is-deref?) emit "*__"
32702     {
32703 $emit-subx-call-operand:check-for-register-indirect:
32704       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
32705       74/jump-if-= break/disp8
32706       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
32707       74/jump-if-= break/disp8
32708 $emit-subx-call-operand:register-indirect:
32709       (emit-subx-call-operand-register-indirect *(ebp+8) %esi)
32710       e9/jump $emit-subx-call-operand:end/disp32
32711     }
32712     # else if (operand->stack-offset) emit "*(ebp+__)"
32713     {
32714       81 7/subop/compare *(esi+0x14) 0/imm32  # Var-offset
32715       74/jump-if-= break/disp8
32716 $emit-subx-call-operand:stack:
32717       (emit-subx-call-operand-stack *(ebp+8) %esi)
32718       e9/jump $emit-subx-call-operand:end/disp32
32719     }
32720     # else if (operand->type == literal) emit "__"
32721     {
32722       (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
32723       81 7/subop/compare *(eax+4) 0/imm32  # Type-tree-value
32724       75/jump-if-!= break/disp8
32725 $emit-subx-call-operand:literal:
32726       (write-buffered *(ebp+8) Space)
32727       (lookup *esi *(esi+4))  # Var-name Var-name => eax
32728       (write-buffered *(ebp+8) %eax)
32729       e9/jump $emit-subx-call-operand:end/disp32
32730     }
32731     # else if (operand->type == literal-string) emit "__"
32732     {
32733       (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
32734       81 7/subop/compare *(eax+4) 0x10/imm32  # Type-tree-value
32735       75/jump-if-!= break/disp8
32736 $emit-subx-call-operand:literal-string:
32737       (write-buffered *(ebp+8) Space)
32738       (lookup *esi *(esi+4))  # Var-name Var-name => eax
32739       (write-buffered *(ebp+8) %eax)
32740     }
32741 $emit-subx-call-operand:end:
32742     # . restore registers
32743     5e/pop-to-esi
32744     59/pop-to-ecx
32745     58/pop-to-eax
32746     # . epilogue
32747     89/<- %esp 5/r32/ebp
32748     5d/pop-to-ebp
32749     c3/return
32750 
32751 emit-subx-call-operand-register-indirect:  # out: (addr buffered-file), v: (addr var)
32752     # . prologue
32753     55/push-ebp
32754     89/<- %ebp 4/r32/esp
32755     # . save registers
32756     50/push-eax
32757     51/push-ecx
32758     56/push-esi
32759     # esi = v
32760     8b/-> *(ebp+0xc) 6/r32/esi
32761     # var size/ecx: int = size-of-deref(v)
32762     (size-of-deref %esi)  # => eax
32763     89/<- %ecx 0/r32/eax
32764     # var reg-name/esi: (addr array byte) = lookup(v->register)
32765     (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
32766     89/<- %esi 0/r32/eax
32767     # TODO: assert size is a multiple of 4
32768     # var i/eax: int = 0
32769     b8/copy-to-eax 0/imm32
32770     {
32771 $emit-subx-call-operand-register-indirect:loop:
32772       # if (i >= size) break
32773       39/compare %eax 1/r32/ecx
32774       7d/jump-if->= break/disp8
32775       # emit " *(" v->register "+" i ")"
32776       (write-buffered *(ebp+8) " *(")
32777       (write-buffered *(ebp+8) %esi)
32778       (write-buffered *(ebp+8) "+")
32779       (write-int32-hex-buffered *(ebp+8) %eax)
32780       (write-buffered *(ebp+8) ")")
32781       # i += 4
32782       05/add-to-eax 4/imm32
32783       #
32784       eb/jump loop/disp8
32785     }
32786 $emit-subx-call-operand-register-indirect:end:
32787     # . restore registers
32788     5e/pop-to-esi
32789     59/pop-to-ecx
32790     58/pop-to-eax
32791     # . epilogue
32792     89/<- %esp 5/r32/ebp
32793     5d/pop-to-ebp
32794     c3/return
32795 
32796 emit-subx-call-operand-stack:  # out: (addr buffered-file), v: (addr var)
32797     # . prologue
32798     55/push-ebp
32799     89/<- %ebp 4/r32/esp
32800     # . save registers
32801     50/push-eax
32802     51/push-ecx
32803     56/push-esi
32804     # esi = v
32805     8b/-> *(ebp+0xc) 6/r32/esi
32806     # var curr/ecx: int = v->offset
32807     8b/-> *(esi+0x14) 1/r32/ecx  # Var-offset
32808     # var max/eax: int = v->offset + size-of(v)
32809     (size-of %esi)  # => eax
32810     # TODO: assert size is a multiple of 4
32811     01/add-to %eax 1/r32/ecx
32812     {
32813 $emit-subx-call-operand-stack:loop:
32814       # if (curr >= max) break
32815       39/compare %ecx 0/r32/eax
32816       7d/jump-if->= break/disp8
32817       # emit " *(ebp+" curr ")"
32818       (write-buffered *(ebp+8) " *(ebp+")
32819       (write-int32-hex-buffered *(ebp+8) %ecx)
32820       (write-buffered *(ebp+8) ")")
32821       # i += 4
32822       81 0/subop/add %ecx 4/imm32
32823       #
32824       eb/jump loop/disp8
32825     }
32826 $emit-subx-call-operand-stack:end:
32827     # . restore registers
32828     5e/pop-to-esi
32829     59/pop-to-ecx
32830     58/pop-to-eax
32831     # . epilogue
32832     89/<- %esp 5/r32/ebp
32833     5d/pop-to-ebp
32834     c3/return
32835 
32836 emit-subx-var-as-rm32:  # out: (addr buffered-file), s: (addr stmt-var)
32837     # . prologue
32838     55/push-ebp
32839     89/<- %ebp 4/r32/esp
32840     # . save registers
32841     50/push-eax
32842     51/push-ecx
32843     56/push-esi
32844     # ecx = s
32845     8b/-> *(ebp+0xc) 1/r32/ecx
32846     # var operand/esi: (addr var) = lookup(s->value)
32847     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
32848     89/<- %esi 0/r32/eax
32849     # if (operand->register && s->is-deref?) emit "*__"
32850     {
32851 $emit-subx-var-as-rm32:check-for-register-indirect:
32852       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
32853       74/jump-if-= break/disp8
32854       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
32855       74/jump-if-= break/disp8
32856 $emit-subx-var-as-rm32:register-indirect:
32857       (write-buffered *(ebp+8) " *")
32858       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
32859       (write-buffered *(ebp+8) %eax)
32860       e9/jump $emit-subx-var-as-rm32:end/disp32
32861     }
32862     # if (operand->register && !s->is-deref?) emit "%__"
32863     {
32864 $emit-subx-var-as-rm32:check-for-register-direct:
32865       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
32866       74/jump-if-= break/disp8
32867       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
32868       75/jump-if-!= break/disp8
32869 $emit-subx-var-as-rm32:register-direct:
32870       (write-buffered *(ebp+8) " %")
32871       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
32872       (write-buffered *(ebp+8) %eax)
32873       e9/jump $emit-subx-var-as-rm32:end/disp32
32874     }
32875     # else if (operand->stack-offset) emit "*(ebp+__)"
32876     {
32877       81 7/subop/compare *(esi+0x14) 0/imm32  # Var-offset
32878       74/jump-if-= break/disp8
32879 $emit-subx-var-as-rm32:stack:
32880       (write-buffered *(ebp+8) Space)
32881       (write-buffered *(ebp+8) "*(ebp+")
32882       (write-int32-hex-buffered *(ebp+8) *(esi+0x14))  # Var-offset
32883       (write-buffered *(ebp+8) ")")
32884     }
32885 $emit-subx-var-as-rm32:end:
32886     # . restore registers
32887     5e/pop-to-esi
32888     59/pop-to-ecx
32889     58/pop-to-eax
32890     # . epilogue
32891     89/<- %esp 5/r32/ebp
32892     5d/pop-to-ebp
32893     c3/return
32894 
32895 find-matching-primitive:  # primitives: (addr primitive), stmt: (addr stmt) -> result/eax: (addr primitive)
32896     # . prologue
32897     55/push-ebp
32898     89/<- %ebp 4/r32/esp
32899     # . save registers
32900     51/push-ecx
32901     # var curr/ecx: (addr primitive) = primitives
32902     8b/-> *(ebp+8) 1/r32/ecx
32903     {
32904 $find-matching-primitive:loop:
32905       # if (curr == null) break
32906       81 7/subop/compare %ecx 0/imm32
32907       74/jump-if-= break/disp8
32908       # if match(curr, stmt) return curr
32909       {
32910         (mu-stmt-matches-primitive? *(ebp+0xc) %ecx)  # => eax
32911         3d/compare-eax-and 0/imm32/false
32912         74/jump-if-= break/disp8
32913         89/<- %eax 1/r32/ecx
32914         eb/jump $find-matching-primitive:end/disp8
32915       }
32916 $find-matching-primitive:next-primitive:
32917       # curr = curr->next
32918       (lookup *(ecx+0x3c) *(ecx+0x40))  # Primitive-next Primitive-next => eax
32919       89/<- %ecx 0/r32/eax
32920       #
32921       e9/jump loop/disp32
32922     }
32923     # return null
32924     b8/copy-to-eax 0/imm32
32925 $find-matching-primitive:end:
32926     # . restore registers
32927     59/pop-to-ecx
32928     # . epilogue
32929     89/<- %esp 5/r32/ebp
32930     5d/pop-to-ebp
32931     c3/return
32932 
32933 mu-stmt-matches-primitive?:  # stmt: (addr stmt), primitive: (addr primitive) -> result/eax: boolean
32934     # A mu stmt matches a primitive if the name matches, all the inout vars
32935     # match, and all the output vars match.
32936     # Vars match if types match and registers match.
32937     # In addition, a stmt output matches a primitive's output if types match
32938     # and the primitive has a wildcard register.
32939     # . prologue
32940     55/push-ebp
32941     89/<- %ebp 4/r32/esp
32942     # . save registers
32943     51/push-ecx
32944     52/push-edx
32945     53/push-ebx
32946     56/push-esi
32947     57/push-edi
32948     # ecx = stmt
32949     8b/-> *(ebp+8) 1/r32/ecx
32950     # edx = primitive
32951     8b/-> *(ebp+0xc) 2/r32/edx
32952     {
32953 $mu-stmt-matches-primitive?:check-name:
32954       # if (primitive->name != stmt->operation) return false
32955       # . var esi: (addr array byte) = lookup(stmt->operation)
32956       (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
32957       89/<- %esi 0/r32/eax
32958       # . var edi: (addr array byte) = lookup(primitive->name)
32959       (lookup *edx *(edx+4))  # Primitive-name Primitive-name => eax
32960 #?       (write-buffered Stderr %eax)
32961 #?       (write-buffered Stderr Newline)
32962 #?       (flush Stderr)
32963       89/<- %edi 0/r32/eax
32964       (string-equal? %esi %edi)  # => eax
32965       3d/compare-eax-and 0/imm32/false
32966       75/jump-if-!= break/disp8
32967       b8/copy-to-eax 0/imm32
32968       e9/jump $mu-stmt-matches-primitive?:end/disp32
32969     }
32970     # var curr/esi: (addr stmt-var) = lookup(stmt->inouts)
32971     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
32972     89/<- %esi 0/r32/eax
32973     # var curr2/edi: (addr list var) = lookup(primitive->inouts)
32974     (lookup *(edx+8) *(edx+0xc))  # Primitive-inouts Primitive-inouts => eax
32975     89/<- %edi 0/r32/eax
32976     {
32977 $mu-stmt-matches-primitive?:inouts-loop:
32978       # if (curr == 0 && curr2 == 0) move on to check outputs
32979       {
32980 $mu-stmt-matches-primitive?:check-both-inouts-null:
32981         81 7/subop/compare %esi 0/imm32
32982         75/jump-if-!= break/disp8
32983 $mu-stmt-matches-primitive?:stmt-inout-null:
32984         81 7/subop/compare %edi 0/imm32
32985         0f 84/jump-if-= $mu-stmt-matches-primitive?:check-outputs/disp32
32986 $mu-stmt-matches-primitive?:stmt-inout-null-and-prim-inout-not-null:
32987         # return false
32988         b8/copy-to-eax 0/imm32/false
32989         e9/jump $mu-stmt-matches-primitive?:end/disp32
32990       }
32991       # if (curr2 == 0) return false
32992       {
32993 $mu-stmt-matches-primitive?:check-prim-inout-null:
32994         81 7/subop/compare %edi 0/imm32
32995         75/jump-if-!= break/disp8
32996 $mu-stmt-matches-primitive?:prim-inout-null:
32997         b8/copy-to-eax 0/imm32/false
32998         e9/jump $mu-stmt-matches-primitive?:end/disp32
32999       }
33000       # if (curr != curr2) return false
33001       {
33002 $mu-stmt-matches-primitive?:check-inouts-match:
33003         (lookup *edi *(edi+4))  # List-value List-value => eax
33004         (operand-matches-primitive? %esi %eax)  # => eax
33005         3d/compare-eax-and 0/imm32/false
33006         75/jump-if-!= break/disp8
33007 $mu-stmt-matches-primitive?:inouts-match:
33008         b8/copy-to-eax 0/imm32/false
33009         e9/jump $mu-stmt-matches-primitive?:end/disp32
33010       }
33011 $mu-stmt-matches-primitive?:next-inout:
33012       # curr = lookup(curr->next)
33013       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
33014       89/<- %esi 0/r32/eax
33015       # curr2 = lookup(curr2->next)
33016       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
33017       89/<- %edi 0/r32/eax
33018       #
33019       e9/jump loop/disp32
33020     }
33021 $mu-stmt-matches-primitive?:check-outputs:
33022     # var curr/esi: (addr stmt-var) = lookup(stmt->outputs)
33023     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
33024     89/<- %esi 0/r32/eax
33025     # var curr2/edi: (addr list var) = lookup(primitive->outputs)
33026     (lookup *(edx+0x10) *(edx+0x14))  # Primitive-outputs Primitive-outputs => eax
33027     89/<- %edi 0/r32/eax
33028     {
33029 $mu-stmt-matches-primitive?:outputs-loop:
33030       # if (curr == 0) return (curr2 == 0)
33031       {
33032 $mu-stmt-matches-primitive?:check-both-outputs-null:
33033         81 7/subop/compare %esi 0/imm32
33034         75/jump-if-!= break/disp8
33035         {
33036 $mu-stmt-matches-primitive?:stmt-output-null:
33037           81 7/subop/compare %edi 0/imm32
33038           75/jump-if-!= break/disp8
33039 $mu-stmt-matches-primitive?:both-outputs-null:
33040           # return true
33041           b8/copy-to-eax 1/imm32
33042           e9/jump $mu-stmt-matches-primitive?:end/disp32
33043         }
33044 $mu-stmt-matches-primitive?:stmt-output-null-and-prim-output-not-null:
33045         # return false
33046         b8/copy-to-eax 0/imm32
33047         e9/jump $mu-stmt-matches-primitive?:end/disp32
33048       }
33049       # if (curr2 == 0) return false
33050       {
33051 $mu-stmt-matches-primitive?:check-prim-output-null:
33052         81 7/subop/compare %edi 0/imm32
33053         75/jump-if-!= break/disp8
33054 $mu-stmt-matches-primitive?:prim-output-is-null:
33055         b8/copy-to-eax 0/imm32
33056         e9/jump $mu-stmt-matches-primitive?:end/disp32
33057       }
33058       # if (curr != curr2) return false
33059       {
33060 $mu-stmt-matches-primitive?:check-outputs-match:
33061         (lookup *edi *(edi+4))  # List-value List-value => eax
33062         (operand-matches-primitive? %esi %eax)  # => eax
33063         3d/compare-eax-and 0/imm32/false
33064         75/jump-if-!= break/disp8
33065 $mu-stmt-matches-primitive?:outputs-match:
33066         b8/copy-to-eax 0/imm32
33067         e9/jump $mu-stmt-matches-primitive?:end/disp32
33068       }
33069 $mu-stmt-matches-primitive?:next-output:
33070       # curr = lookup(curr->next)
33071       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
33072       89/<- %esi 0/r32/eax
33073       # curr2 = lookup(curr2->next)
33074       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
33075       89/<- %edi 0/r32/eax
33076       #
33077       e9/jump loop/disp32
33078     }
33079 $mu-stmt-matches-primitive?:return-true:
33080     b8/copy-to-eax 1/imm32
33081 $mu-stmt-matches-primitive?:end:
33082     # . restore registers
33083     5f/pop-to-edi
33084     5e/pop-to-esi
33085     5b/pop-to-ebx
33086     5a/pop-to-edx
33087     59/pop-to-ecx
33088     # . epilogue
33089     89/<- %esp 5/r32/ebp
33090     5d/pop-to-ebp
33091     c3/return
33092 
33093 operand-matches-primitive?:  # s: (addr stmt-var), prim-var: (addr var) -> result/eax: boolean
33094     # . prologue
33095     55/push-ebp
33096     89/<- %ebp 4/r32/esp
33097     # . save registers
33098     51/push-ecx
33099     52/push-edx
33100     53/push-ebx
33101     56/push-esi
33102     57/push-edi
33103     # ecx = s
33104     8b/-> *(ebp+8) 1/r32/ecx
33105     # var var/esi: (addr var) = lookup(s->value)
33106     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
33107     89/<- %esi 0/r32/eax
33108     # edi = prim-var
33109     8b/-> *(ebp+0xc) 7/r32/edi
33110 $operand-matches-primitive?:check-type:
33111     # if !category-match?(var->type, prim-var->type) return false
33112     # . var vtype/ebx: (addr type-tree) = lookup(var->type)
33113     (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
33114     89/<- %ebx 0/r32/eax
33115     # . if s is deref, vtype = vtype->right
33116     {
33117       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
33118       74/jump-if-= break/disp8
33119 $operand-matches-primitive?:is-deref:
33120       # . var t/eax: (addr type)
33121       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
33122       # . if !t->is-atom? t = t->left
33123       81 7/subop/compare *eax 0/imm32/false
33124       {
33125         75/jump-if-!= break/disp8
33126         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
33127       }
33128       # .
33129       89/<- %ebx 0/r32/eax
33130     }
33131     # . var ptype/eax: (addr type-tree) = lookup(prim-var->type)
33132     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
33133     (subx-type-category-match? %ebx %eax)  # => eax
33134     3d/compare-eax-and 0/imm32/false
33135     0f 84/jump-if-= $operand-matches-primitive?:return-false/disp32
33136     {
33137 $operand-matches-primitive?:check-register:
33138       # if prim-var is in memory and var is in register but dereference, match
33139       {
33140         81 7/subop/compare *(edi+0x18) 0/imm32  # Var-register
33141         0f 85/jump-if-!= break/disp32
33142         81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
33143         74/jump-if-= break/disp8
33144         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
33145         74/jump-if-= break/disp8
33146 $operand-matches-primitive?:var-deref-match:
33147         e9/jump $operand-matches-primitive?:return-true/disp32
33148       }
33149       # if prim-var is in register and var is in register but dereference, no match
33150       {
33151         81 7/subop/compare *(edi+0x18) 0/imm32  # Var-register
33152         0f 84/jump-if-= break/disp32
33153         81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
33154         0f 84/jump-if-= break/disp32
33155         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
33156         74/jump-if-= break/disp8
33157 $operand-matches-primitive?:var-deref-no-match:
33158         e9/jump $operand-matches-primitive?:return-false/disp32
33159       }
33160       # return false if var->register doesn't match prim-var->register
33161       {
33162         # if register addresses are equal, it's a match
33163         # var vreg/ebx: (addr array byte) = lookup(var->register)
33164         (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
33165         89/<- %ebx 0/r32/eax
33166         # var preg/ecx: (addr array byte) = lookup(prim-var->register)
33167         (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
33168         89/<- %ecx 0/r32/eax
33169         # if (vreg == preg) break
33170         39/compare %ecx 3/r32/ebx
33171         74/jump-if-= break/disp8
33172 $operand-matches-primitive?:var-register-no-match:
33173         # if either address is 0, return false
33174         81 7/subop/compare %ebx 0/imm32
33175         74/jump-if-=  $operand-matches-primitive?:return-false/disp8
33176         81 7/subop/compare %ecx 0/imm32
33177         74/jump-if-=  $operand-matches-primitive?:return-false/disp8
33178         # if prim-var->register is wildcard, it's a match
33179         (string-equal? %ecx "*")  # Any-register => eax
33180         3d/compare-eax-and 0/imm32/false
33181         75/jump-if-!= break/disp8
33182 $operand-matches-primitive?:wildcard-no-match:
33183         # if string contents aren't equal, return false
33184         (string-equal? %ecx %ebx)  # => eax
33185         3d/compare-eax-and 0/imm32/false
33186         74/jump-if-= $operand-matches-primitive?:return-false/disp8
33187       }
33188     }
33189 $operand-matches-primitive?:return-true:
33190     b8/copy-to-eax 1/imm32/true
33191     eb/jump $operand-matches-primitive?:end/disp8
33192 $operand-matches-primitive?:return-false:
33193     b8/copy-to-eax 0/imm32/false
33194 $operand-matches-primitive?:end:
33195     # . restore registers
33196     5f/pop-to-edi
33197     5e/pop-to-esi
33198     5b/pop-to-ebx
33199     5a/pop-to-edx
33200     59/pop-to-ecx
33201     # . epilogue
33202     89/<- %esp 5/r32/ebp
33203     5d/pop-to-ebp
33204     c3/return
33205 
33206 find-matching-function:  # functions: (addr function), stmt: (addr stmt) -> result/eax: (addr function)
33207     # . prologue
33208     55/push-ebp
33209     89/<- %ebp 4/r32/esp
33210     # . save registers
33211     51/push-ecx
33212     # var curr/ecx: (handle function) = functions
33213     8b/-> *(ebp+8) 1/r32/ecx
33214     {
33215       # if (curr == null) break
33216       81 7/subop/compare %ecx 0/imm32
33217       74/jump-if-= break/disp8
33218 #?       (write-buffered Stderr "iter\n")
33219 #?       (flush Stderr)
33220       # if match(stmt, curr) return curr
33221       {
33222         (mu-stmt-matches-function? *(ebp+0xc) %ecx)  # => eax
33223         3d/compare-eax-and 0/imm32/false
33224         74/jump-if-= break/disp8
33225         89/<- %eax 1/r32/ecx
33226         eb/jump $find-matching-function:end/disp8
33227       }
33228       # curr = curr->next
33229       (lookup *(ecx+0x20) *(ecx+0x24))  # Function-next Function-next => eax
33230       89/<- %ecx 0/r32/eax
33231       #
33232       eb/jump loop/disp8
33233     }
33234     # return null
33235     b8/copy-to-eax 0/imm32
33236 $find-matching-function:end:
33237     # . restore registers
33238     59/pop-to-ecx
33239     # . epilogue
33240     89/<- %esp 5/r32/ebp
33241     5d/pop-to-ebp
33242     c3/return
33243 
33244 # Just compare names; user-defined functions don't support overloading yet.
33245 mu-stmt-matches-function?:  # stmt: (addr stmt1), function: (addr function) -> result/eax: boolean
33246     # . prologue
33247     55/push-ebp
33248     89/<- %ebp 4/r32/esp
33249     # . save registers
33250     51/push-ecx
33251     # return function->name == stmt->operation
33252     # ecx = lookup(stmt->operation)
33253     8b/-> *(ebp+8) 0/r32/eax
33254     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
33255     89/<- %ecx 0/r32/eax
33256     # eax = lookup(function->name)
33257     8b/-> *(ebp+0xc) 0/r32/eax
33258     (lookup *eax *(eax+4))  # Function-name Function-name => eax
33259     (string-equal? %eax %ecx)  # => eax
33260 $mu-stmt-matches-function?:end:
33261     # . restore registers
33262     59/pop-to-ecx
33263     # . epilogue
33264     89/<- %esp 5/r32/ebp
33265     5d/pop-to-ebp
33266     c3/return
33267 
33268 # Type-checking happens elsewhere. This method is for selecting between
33269 # primitives.
33270 subx-type-category-match?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
33271     # . prologue
33272     55/push-ebp
33273     89/<- %ebp 4/r32/esp
33274     # . save registers
33275     51/push-ecx
33276     # var cata/ecx: int = type-category(a)
33277     (type-category *(ebp+8))  # => eax
33278     89/<- %ecx 0/r32/eax
33279     # var catb/eax: int = type-category(b)
33280     (type-category *(ebp+0xc))  # => eax
33281     # return cata == catb
33282     39/compare %eax 1/r32/ecx
33283     0f 94/set-byte-if-= %al
33284     81 4/subop/and %eax 0xff/imm32
33285 $subx-type-category-match?:end:
33286     # . restore registers
33287     59/pop-to-ecx
33288     # . epilogue
33289     89/<- %esp 5/r32/ebp
33290     5d/pop-to-ebp
33291     c3/return
33292 
33293 type-category:  # a: (addr type-tree) -> result/eax: int
33294     # . prologue
33295     55/push-ebp
33296     89/<- %ebp 4/r32/esp
33297     # . save registers
33298     51/push-ecx
33299     # var lit?/ecx: boolean = is-literal-type?(a)
33300     (is-simple-mu-type? *(ebp+8) 0)  # literal => eax
33301     89/<- %ecx 0/r32/eax
33302     # var float?/eax: int = is-float?(a)
33303     (is-simple-mu-type? *(ebp+8) 0xf)  # => eax
33304     # set bits for lit? and float?
33305     c1/shift 4/subop/left %ecx 1/imm8
33306     09/or %eax 1/r32/ecx
33307 $type-category:end:
33308     # . restore registers
33309     59/pop-to-ecx
33310     # . epilogue
33311     89/<- %esp 5/r32/ebp
33312     5d/pop-to-ebp
33313     c3/return
33314 
33315 is-simple-mu-type?:  # a: (addr type-tree), n: type-id -> result/eax: boolean
33316     # . prologue
33317     55/push-ebp
33318     89/<- %ebp 4/r32/esp
33319     # . save registers
33320     51/push-ecx
33321     # ecx = n
33322     8b/-> *(ebp+0xc) 1/r32/ecx
33323     # return (a->value == n)
33324     8b/-> *(ebp+8) 0/r32/eax
33325     39/compare *(eax+4) 1/r32/ecx  # Type-tree-value
33326     0f 94/set-byte-if-= %al
33327     81 4/subop/and %eax 0xff/imm32
33328 $is-simple-mu-type?:end:
33329     # . restore registers
33330     59/pop-to-ecx
33331     # . epilogue
33332     89/<- %esp 5/r32/ebp
33333     5d/pop-to-ebp
33334     c3/return
33335 
33336 is-mu-addr-type?:  # a: (addr type-tree) -> result/eax: boolean
33337     # . prologue
33338     55/push-ebp
33339     89/<- %ebp 4/r32/esp
33340     # eax = a
33341     8b/-> *(ebp+8) 0/r32/eax
33342     # if (!a->is-atom?) a = a->left
33343     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
33344     {
33345       75/jump-if-!= break/disp8
33346       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
33347     }
33348     # return (a->value == addr)
33349     81 7/subop/compare *(eax+4) 2/imm32/addr  # Type-tree-value
33350     0f 94/set-byte-if-= %al
33351     81 4/subop/and %eax 0xff/imm32
33352 $is-mu-addr-type?:end:
33353     # . epilogue
33354     89/<- %esp 5/r32/ebp
33355     5d/pop-to-ebp
33356     c3/return
33357 
33358 is-mu-array-type?:  # a: (addr type-tree) -> result/eax: boolean
33359     # . prologue
33360     55/push-ebp
33361     89/<- %ebp 4/r32/esp
33362     # eax = a
33363     8b/-> *(ebp+8) 0/r32/eax
33364     # if (!a->is-atom?) a = a->left
33365     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
33366     {
33367       75/jump-if-!= break/disp8
33368       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
33369     }
33370     # return (a->value == array)
33371     81 7/subop/compare *(eax+4) 3/imm32/array  # Type-tree-value
33372     0f 94/set-byte-if-= %al
33373     81 4/subop/and %eax 0xff/imm32
33374 $is-mu-array-type?:end:
33375     # . epilogue
33376     89/<- %esp 5/r32/ebp
33377     5d/pop-to-ebp
33378     c3/return
33379 
33380 is-mu-string-type?:  # a: (addr type-tree) -> result/eax: boolean
33381     # . prologue
33382     55/push-ebp
33383     89/<- %ebp 4/r32/esp
33384     # . save registers
33385     56/push-esi
33386     # esi = a
33387     8b/-> *(ebp+8) 6/r32/esi
33388     # if (a->is-atom?) return false
33389     81 7/subop/compare *esi 0/imm32/false  # Type-tree-is-atom
33390     0f 85/jump-if-!= $is-mu-string-type?:return-false/disp32
33391     # if a is not an addr, return false
33392     (is-mu-addr-type? %esi)  # => eax
33393     3d/compare-eax-with 0/imm32/false
33394     0f 84/jump-if-= $is-mu-string-type?:end/disp32  # eax changes var
33395     # if a is not an array, return false
33396     (lookup *(esi+0xc) *(esi+0x10))  # Type-tree-right Type-tree-right => eax
33397     (is-mu-array-type? %eax)  # => eax
33398     3d/compare-eax-with 0/imm32/false
33399     74/jump-if-= $is-mu-string-type?:end/disp8  # eax changes var
33400     # var p/eax: (addr type-tree) = payload of a
33401     (lookup *(esi+0xc) *(esi+0x10))  # Type-tree-right Type-tree-right => eax
33402     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
33403     # if p is an atom, return false
33404     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
33405     75/jump-if-!= $is-mu-string-type?:return-false/disp8
33406     # return (p == byte)
33407     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
33408     (is-simple-mu-type? %eax 8)  # byte => eax
33409     eb/jump $is-mu-string-type?:end/disp8
33410 $is-mu-string-type?:return-false:
33411     b8/copy-to-eax 0/imm32/false
33412 $is-mu-string-type?:end:
33413     # . restore registers
33414     5e/pop-to-esi
33415     # . epilogue
33416     89/<- %esp 5/r32/ebp
33417     5d/pop-to-ebp
33418     c3/return
33419 
33420 is-mu-stream-type?:  # a: (addr type-tree) -> result/eax: boolean
33421     # . prologue
33422     55/push-ebp
33423     89/<- %ebp 4/r32/esp
33424     # eax = a
33425     8b/-> *(ebp+8) 0/r32/eax
33426     # if (!a->is-atom?) a = a->left
33427     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
33428     {
33429       75/jump-if-!= break/disp8
33430       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
33431     }
33432     # return (a->value == stream)
33433     81 7/subop/compare *(eax+4) 0xb/imm32/stream  # Type-tree-value
33434     0f 94/set-byte-if-= %al
33435     81 4/subop/and %eax 0xff/imm32
33436 $is-mu-stream-type?:end:
33437     # . epilogue
33438     89/<- %esp 5/r32/ebp
33439     5d/pop-to-ebp
33440     c3/return
33441 
33442 test-emit-subx-stmt-primitive:
33443     # Primitive operation on a variable on the stack.
33444     #   increment foo
33445     # =>
33446     #   ff 0/subop/increment *(ebp-8)
33447     #
33448     # There's a variable on the var stack as follows:
33449     #   name: 'foo'
33450     #   type: int
33451     #   stack-offset: -8
33452     #
33453     # There's a primitive with this info:
33454     #   name: 'increment'
33455     #   inouts: int/mem
33456     #   value: 'ff 0/subop/increment'
33457     #
33458     # . prologue
33459     55/push-ebp
33460     89/<- %ebp 4/r32/esp
33461     # setup
33462     (clear-stream _test-output-stream)
33463     (clear-stream $_test-output-buffered-file->buffer)
33464     # simulate allocated payloads starting with an initial fake alloc-id (0x11)
33465 $test-emit-subx-stmt-primitive:initialize-type:
33466     # var type/ecx: (payload type-tree) = int
33467     68/push 0/imm32/right:null
33468     68/push 0/imm32/right:null
33469     68/push 0/imm32/left:unused
33470     68/push 1/imm32/value:int
33471     68/push 1/imm32/is-atom?:true
33472     68/push 0x11/imm32/alloc-id:fake:payload
33473     89/<- %ecx 4/r32/esp
33474 $test-emit-subx-stmt-primitive:initialize-var:
33475     # var var-foo/ecx: (payload var) = var(type)
33476     68/push 0/imm32/no-register
33477     68/push 0/imm32/no-register
33478     68/push -8/imm32/stack-offset
33479     68/push 1/imm32/block-depth
33480     51/push-ecx/type
33481     68/push 0x11/imm32/alloc-id:fake
33482     68/push 0/imm32/name
33483     68/push 0/imm32/name
33484     68/push 0x11/imm32/alloc-id:fake:payload
33485     89/<- %ecx 4/r32/esp
33486 $test-emit-subx-stmt-primitive:initialize-var-name:
33487     # var-foo->name = "foo"
33488     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
33489     (copy-array Heap "foo" %eax)
33490 $test-emit-subx-stmt-primitive:initialize-stmt-var:
33491     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
33492     68/push 0/imm32/is-deref:false
33493     68/push 0/imm32/next
33494     68/push 0/imm32/next
33495     51/push-ecx/var-foo
33496     68/push 0x11/imm32/alloc-id:fake
33497     68/push 0x11/imm32/alloc-id:fake:payload
33498     89/<- %ebx 4/r32/esp
33499 $test-emit-subx-stmt-primitive:initialize-stmt:
33500     # var stmt/esi: (addr statement)
33501     68/push 0/imm32/no-outputs
33502     68/push 0/imm32/no-outputs
33503     53/push-ebx/inouts
33504     68/push 0x11/imm32/alloc-id:fake
33505     68/push 0/imm32/operation
33506     68/push 0/imm32/operation
33507     68/push 1/imm32/tag
33508     89/<- %esi 4/r32/esp
33509 $test-emit-subx-stmt-primitive:initialize-stmt-operation:
33510     # stmt->operation = "increment"
33511     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
33512     (copy-array Heap "increment" %eax)
33513 $test-emit-subx-stmt-primitive:initialize-primitive:
33514     # var primitives/ebx: (addr primitive)
33515     68/push 0/imm32/next
33516     68/push 0/imm32/next
33517     68/push 0/imm32/no-x32
33518     68/push 0/imm32/no-xm32
33519     68/push 0/imm32/no-disp32
33520     68/push 0/imm32/no-imm8
33521     68/push 0/imm32/no-imm32
33522     68/push 0/imm32/no-r32
33523     68/push 1/imm32/rm32-is-first-inout
33524     68/push 0/imm32/subx-name
33525     68/push 0/imm32/subx-name
33526     68/push 0/imm32/no-outputs
33527     68/push 0/imm32/no-outputs
33528     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
33529     68/push 0x11/imm32/alloc-id:fake
33530     68/push 0/imm32/name
33531     68/push 0/imm32/name
33532     89/<- %ebx 4/r32/esp
33533 $test-emit-subx-stmt-primitive:initialize-primitive-name:
33534     # primitives->name = "increment"
33535     (copy-array Heap "increment" %ebx)  # Primitive-name
33536 $test-emit-subx-stmt-primitive:initialize-primitive-subx-name:
33537     # primitives->subx-name = "ff 0/subop/increment"
33538     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
33539     (copy-array Heap "ff 0/subop/increment" %eax)
33540     # convert
33541     c7 0/subop/copy *Curr-block-depth 0/imm32
33542     (emit-subx-stmt _test-output-buffered-file %esi %ebx Stderr 0)
33543     (flush _test-output-buffered-file)
33544 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
33550     # check output
33551     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-stmt-primitive")
33552     # . epilogue
33553     89/<- %esp 5/r32/ebp
33554     5d/pop-to-ebp
33555     c3/return
33556 
33557 test-emit-subx-stmt-primitive-register:
33558     # Primitive operation on a variable in a register.
33559     #   foo <- increment
33560     # =>
33561     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
33562     #
33563     # There's a variable on the var stack as follows:
33564     #   name: 'foo'
33565     #   type: int
33566     #   register: 'eax'
33567     #
33568     # There's a primitive with this info:
33569     #   name: 'increment'
33570     #   out: int/reg
33571     #   value: 'ff 0/subop/increment'
33572     #
33573     # . prologue
33574     55/push-ebp
33575     89/<- %ebp 4/r32/esp
33576     # setup
33577     (clear-stream _test-output-stream)
33578     (clear-stream $_test-output-buffered-file->buffer)
33579 $test-emit-subx-stmt-primitive-register:initialize-type:
33580     # var type/ecx: (payload type-tree) = int
33581     68/push 0/imm32/right:null
33582     68/push 0/imm32/right:null
33583     68/push 0/imm32/left:unused
33584     68/push 1/imm32/value:int
33585     68/push 1/imm32/is-atom?:true
33586     68/push 0x11/imm32/alloc-id:fake:payload
33587     89/<- %ecx 4/r32/esp
33588 $test-emit-subx-stmt-primitive-register:initialize-var:
33589     # var var-foo/ecx: (payload var)
33590     68/push 0/imm32/register
33591     68/push 0/imm32/register
33592     68/push 0/imm32/no-stack-offset
33593     68/push 1/imm32/block-depth
33594     51/push-ecx
33595     68/push 0x11/imm32/alloc-id:fake
33596     68/push 0/imm32/name
33597     68/push 0/imm32/name
33598     68/push 0x11/imm32/alloc-id:fake:payload
33599     89/<- %ecx 4/r32/esp
33600 $test-emit-subx-stmt-primitive-register:initialize-var-name:
33601     # var-foo->name = "foo"
33602     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
33603     (copy-array Heap "foo" %eax)
33604 $test-emit-subx-stmt-primitive-register:initialize-var-register:
33605     # var-foo->register = "eax"
33606     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
33607     (copy-array Heap "eax" %eax)
33608 $test-emit-subx-stmt-primitive-register:initialize-stmt-var:
33609     # var operand/ebx: (payload stmt-var)
33610     68/push 0/imm32/is-deref:false
33611     68/push 0/imm32/next
33612     68/push 0/imm32/next
33613     51/push-ecx/var-foo
33614     68/push 0x11/imm32/alloc-id:fake
33615     68/push 0x11/imm32/alloc-id:fake:payload
33616     89/<- %ebx 4/r32/esp
33617 $test-emit-subx-stmt-primitive-register:initialize-stmt:
33618     # var stmt/esi: (addr statement)
33619     53/push-ebx/outputs
33620     68/push 0x11/imm32/alloc-id:fake
33621     68/push 0/imm32/no-inouts
33622     68/push 0/imm32/no-inouts
33623     68/push 0/imm32/operation
33624     68/push 0/imm32/operation
33625     68/push 1/imm32
33626     89/<- %esi 4/r32/esp
33627 $test-emit-subx-stmt-primitive-register:initialize-stmt-operation:
33628     # stmt->operation = "increment"
33629     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
33630     (copy-array Heap "increment" %eax)
33631 $test-emit-subx-stmt-primitive-register:initialize-formal-var:
33632     # var formal-var/ebx: (payload var)
33633     68/push 0/imm32/register
33634     68/push 0/imm32/register
33635     68/push 0/imm32/no-stack-offset
33636     68/push 1/imm32/block-depth
33637     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
33638     68/push 0x11/imm32/alloc-id:fake
33639     68/push 0/imm32/name
33640     68/push 0/imm32/name
33641     68/push 0x11/imm32/alloc-id:fake:payload
33642     89/<- %ebx 4/r32/esp
33643 $test-emit-subx-stmt-primitive-register:initialize-formal-var-name:
33644     # formal-var->name = "dummy"
33645     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
33646     (copy-array Heap "dummy" %eax)
33647 $test-emit-subx-stmt-primitive-register:initialize-formal-register:
33648     # formal-var->register = "*"
33649     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
33650     (copy-array Heap "*" %eax)  # Any-register
33651 $test-emit-subx-stmt-primitive-register:initialize-var-list:
33652     # var formal-outputs/ebx: (payload list var)
33653     68/push 0/imm32/next
33654     68/push 0/imm32/next
33655     53/push-ebx/formal-var
33656     68/push 0x11/imm32/alloc-id:fake
33657     68/push 0x11/imm32/alloc-id:fake:payload
33658     89/<- %ebx 4/r32/esp
33659 $test-emit-subx-stmt-primitive-register:initialize-primitive:
33660     # var primitives/ebx: (addr primitive)
33661     68/push 0/imm32/next
33662     68/push 0/imm32/next
33663     68/push 0/imm32/no-x32
33664     68/push 0/imm32/no-xm32
33665     68/push 0/imm32/no-disp32
33666     68/push 0/imm32/no-imm8
33667     68/push 0/imm32/no-imm32
33668     68/push 0/imm32/no-r32
33669     68/push 3/imm32/rm32-is-first-output
33670     68/push 0/imm32/subx-name
33671     68/push 0/imm32/subx-name
33672     53/push-ebx/outputs
33673     68/push 0x11/imm32/alloc-id:fake
33674     68/push 0/imm32/no-inouts
33675     68/push 0/imm32/no-inouts
33676     68/push 0/imm32/name
33677     68/push 0/imm32/name
33678     89/<- %ebx 4/r32/esp
33679 $test-emit-subx-stmt-primitive-register:initialize-primitive-name:
33680     # primitives->name = "increment"
33681     (copy-array Heap "increment" %ebx)  # Primitive-name
33682 $test-emit-subx-stmt-primitive-register:initialize-primitive-subx-name:
33683     # primitives->subx-name = "ff 0/subop/increment"
33684     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
33685     (copy-array Heap "ff 0/subop/increment" %eax)
33686     # convert
33687     c7 0/subop/copy *Curr-block-depth 0/imm32
33688     (emit-subx-stmt _test-output-buffered-file %esi %ebx Stderr 0)
33689     (flush _test-output-buffered-file)
33690 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
33696     # check output
33697     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-primitive-register")
33698     # . epilogue
33699     89/<- %esp 5/r32/ebp
33700     5d/pop-to-ebp
33701     c3/return
33702 
33703 test-emit-subx-stmt-select-primitive:
33704     # Select the right primitive between overloads.
33705     #   foo <- increment
33706     # =>
33707     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
33708     #
33709     # There's a variable on the var stack as follows:
33710     #   name: 'foo'
33711     #   type: int
33712     #   register: 'eax'
33713     #
33714     # There's two primitives, as follows:
33715     #   - name: 'increment'
33716     #     out: int/reg
33717     #     value: 'ff 0/subop/increment'
33718     #   - name: 'increment'
33719     #     inout: int/mem
33720     #     value: 'ff 0/subop/increment'
33721     #
33722     # . prologue
33723     55/push-ebp
33724     89/<- %ebp 4/r32/esp
33725     # setup
33726     (clear-stream _test-output-stream)
33727     (clear-stream $_test-output-buffered-file->buffer)
33728 $test-emit-subx-stmt-select-primitive:initialize-type:
33729     # var type/ecx: (payload type-tree) = int
33730     68/push 0/imm32/right:null
33731     68/push 0/imm32/right:null
33732     68/push 0/imm32/left:unused
33733     68/push 1/imm32/value:int
33734     68/push 1/imm32/is-atom?:true
33735     68/push 0x11/imm32/alloc-id:fake:payload
33736     89/<- %ecx 4/r32/esp
33737 $test-emit-subx-stmt-select-primitive:initialize-var:
33738     # var var-foo/ecx: (payload var)
33739     68/push 0/imm32/register
33740     68/push 0/imm32/register
33741     68/push 0/imm32/no-stack-offset
33742     68/push 1/imm32/block-depth
33743     51/push-ecx
33744     68/push 0x11/imm32/alloc-id:fake
33745     68/push 0/imm32/name
33746     68/push 0/imm32/name
33747     68/push 0x11/imm32/alloc-id:fake:payload
33748     89/<- %ecx 4/r32/esp
33749 $test-emit-subx-stmt-select-primitive:initialize-var-name:
33750     # var-foo->name = "foo"
33751     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
33752     (copy-array Heap "foo" %eax)
33753 $test-emit-subx-stmt-select-primitive:initialize-var-register:
33754     # var-foo->register = "eax"
33755     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
33756     (copy-array Heap "eax" %eax)
33757 $test-emit-subx-stmt-select-primitive:initialize-stmt-var:
33758     # var operand/ebx: (payload stmt-var)
33759     68/push 0/imm32/is-deref:false
33760     68/push 0/imm32/next
33761     68/push 0/imm32/next
33762     51/push-ecx/var-foo
33763     68/push 0x11/imm32/alloc-id:fake
33764     68/push 0x11/imm32/alloc-id:fake:payload
33765     89/<- %ebx 4/r32/esp
33766 $test-emit-subx-stmt-select-primitive:initialize-stmt:
33767     # var stmt/esi: (addr statement)
33768     53/push-ebx/outputs
33769     68/push 0x11/imm32/alloc-id:fake
33770     68/push 0/imm32/no-inouts
33771     68/push 0/imm32/no-inouts
33772     68/push 0/imm32/operation
33773     68/push 0/imm32/operation
33774     68/push 1/imm32
33775     89/<- %esi 4/r32/esp
33776 $test-emit-subx-stmt-select-primitive:initialize-stmt-operation:
33777     # stmt->operation = "increment"
33778     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
33779     (copy-array Heap "increment" %eax)
33780 $test-emit-subx-stmt-select-primitive:initialize-formal-var:
33781     # var formal-var/ebx: (payload var)
33782     68/push 0/imm32/register
33783     68/push 0/imm32/register
33784     68/push 0/imm32/no-stack-offset
33785     68/push 1/imm32/block-depth
33786     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
33787     68/push 0x11/imm32/alloc-id:fake
33788     68/push 0/imm32/name
33789     68/push 0/imm32/name
33790     68/push 0x11/imm32/alloc-id:fake:payload
33791     89/<- %ebx 4/r32/esp
33792 $test-emit-subx-stmt-select-primitive:initialize-formal-var-name:
33793     # formal-var->name = "dummy"
33794     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
33795     (copy-array Heap "dummy" %eax)
33796 $test-emit-subx-stmt-select-primitive:initialize-formal-register:
33797     # formal-var->register = "*"
33798     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
33799     (copy-array Heap "*" %eax)  # Any-register
33800 $test-emit-subx-stmt-select-primitive:initialize-var-list:
33801     # var formal-outputs/ebx: (payload list var)
33802     68/push 0/imm32/next
33803     68/push 0/imm32/next
33804     53/push-ebx/formal-var
33805     68/push 0x11/imm32/alloc-id:fake
33806     68/push 0x11/imm32/alloc-id:fake:payload
33807     89/<- %ebx 4/r32/esp
33808 $test-emit-subx-stmt-select-primitive:initialize-primitive2:
33809     # var primitive2/edi: (payload primitive)
33810     68/push 0/imm32/next
33811     68/push 0/imm32/next
33812     68/push 0/imm32/no-x32
33813     68/push 0/imm32/no-xm32
33814     68/push 0/imm32/no-disp32
33815     68/push 0/imm32/no-imm8
33816     68/push 0/imm32/no-imm32
33817     68/push 0/imm32/no-r32
33818     68/push 3/imm32/rm32-is-first-output
33819     68/push 0/imm32/subx-name
33820     68/push 0/imm32/subx-name
33821     53/push-ebx/outputs
33822     68/push 0x11/imm32/alloc-id:fake
33823     68/push 0/imm32/no-inouts
33824     68/push 0/imm32/no-inouts
33825     68/push 0/imm32/name
33826     68/push 0/imm32/name
33827     68/push 0x11/imm32/alloc-id:fake:payload
33828     89/<- %edi 4/r32/esp
33829 $test-emit-subx-stmt-select-primitive:initialize-primitive2-name:
33830     # primitives->name = "increment"
33831     8d/copy-address *(edi+4) 0/r32/eax  # Primitive-name + 4
33832     (copy-array Heap "increment" %eax)
33833 $test-emit-subx-stmt-select-primitive:initialize-primitive2-subx-name:
33834     # primitives->subx-name = "ff 0/subop/increment"
33835     8d/copy-address *(edi+0x1c) 0/r32/eax  # Primitive-subx-name + 4
33836     (copy-array Heap "ff 0/subop/increment" %eax)
33837 $test-emit-subx-stmt-select-primitive:initialize-primitive:
33838     # var primitives/ebx: (addr primitive)
33839     57/push-edi
33840     68/push 0x11/imm32/alloc-id:fake
33841     68/push 0/imm32/no-x32
33842     68/push 0/imm32/no-xm32
33843     68/push 0/imm32/no-disp32
33844     68/push 0/imm32/no-imm8
33845     68/push 0/imm32/no-imm32
33846     68/push 0/imm32/no-r32
33847     68/push 1/imm32/rm32-is-first-inout
33848     68/push 0/imm32/subx-name
33849     68/push 0/imm32/subx-name
33850     68/push 0/imm32/no-outputs
33851     68/push 0/imm32/no-outputs
33852     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
33853     68/push 0x11/imm32/alloc-id:fake
33854     68/push 0/imm32/name
33855     68/push 0/imm32/name
33856     89/<- %ebx 4/r32/esp
33857 $test-emit-subx-stmt-select-primitive:initialize-primitive-name:
33858     # primitives->name = "increment"
33859     (copy-array Heap "increment" %ebx)  # Primitive-name
33860 $test-emit-subx-stmt-select-primitive:initialize-primitive-subx-name:
33861     # primitives->subx-name = "ff 0/subop/increment"
33862     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
33863     (copy-array Heap "ff 0/subop/increment" %eax)
33864     # convert
33865     c7 0/subop/copy *Curr-block-depth 0/imm32
33866     (emit-subx-stmt _test-output-buffered-file %esi %ebx Stderr 0)
33867     (flush _test-output-buffered-file)
33868 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
33874     # check output
33875     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive")
33876     # . epilogue
33877     89/<- %esp 5/r32/ebp
33878     5d/pop-to-ebp
33879     c3/return
33880 
33881 test-emit-subx-stmt-select-primitive-2:
33882     # Select the right primitive between overloads.
33883     #   increment foo
33884     # =>
33885     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
33886     #
33887     # There's a variable on the var stack as follows:
33888     #   name: 'foo'
33889     #   type: int
33890     #   register: 'eax'
33891     #
33892     # There's two primitives, as follows:
33893     #   - name: 'increment'
33894     #     out: int/reg
33895     #     value: 'ff 0/subop/increment'
33896     #   - name: 'increment'
33897     #     inout: int/mem
33898     #     value: 'ff 0/subop/increment'
33899     #
33900     # . prologue
33901     55/push-ebp
33902     89/<- %ebp 4/r32/esp
33903     # setup
33904     (clear-stream _test-output-stream)
33905     (clear-stream $_test-output-buffered-file->buffer)
33906 $test-emit-subx-stmt-select-primitive-2:initialize-type:
33907     # var type/ecx: (payload type-tree) = int
33908     68/push 0/imm32/right:null
33909     68/push 0/imm32/right:null
33910     68/push 0/imm32/left:unused
33911     68/push 1/imm32/value:int
33912     68/push 1/imm32/is-atom?:true
33913     68/push 0x11/imm32/alloc-id:fake:payload
33914     89/<- %ecx 4/r32/esp
33915 $test-emit-subx-stmt-select-primitive-2:initialize-var:
33916     # var var-foo/ecx: (payload var)
33917     68/push 0/imm32/register
33918     68/push 0/imm32/register
33919     68/push 0/imm32/no-stack-offset
33920     68/push 1/imm32/block-depth
33921     51/push-ecx
33922     68/push 0x11/imm32/alloc-id:fake
33923     68/push 0/imm32/name
33924     68/push 0/imm32/name
33925     68/push 0x11/imm32/alloc-id:fake:payload
33926     89/<- %ecx 4/r32/esp
33927 $test-emit-subx-stmt-select-primitive-2:initialize-var-name:
33928     # var-foo->name = "foo"
33929     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
33930     (copy-array Heap "foo" %eax)
33931 $test-emit-subx-stmt-select-primitive-2:initialize-var-register:
33932     # var-foo->register = "eax"
33933     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
33934     (copy-array Heap "eax" %eax)
33935 $test-emit-subx-stmt-select-primitive-2:initialize-stmt-var:
33936     # var operand/ebx: (payload stmt-var)
33937     68/push 0/imm32/is-deref:false
33938     68/push 0/imm32/next
33939     68/push 0/imm32/next
33940     51/push-ecx/var-foo
33941     68/push 0x11/imm32/alloc-id:fake
33942     68/push 0x11/imm32/alloc-id:fake:payload
33943     89/<- %ebx 4/r32/esp
33944 $test-emit-subx-stmt-select-primitive-2:initialize-stmt:
33945     # var stmt/esi: (addr statement)
33946     68/push 0/imm32/no-outputs
33947     68/push 0/imm32/no-outputs
33948     53/push-ebx/inouts
33949     68/push 0x11/imm32/alloc-id:fake
33950     68/push 0/imm32/operation
33951     68/push 0/imm32/operation
33952     68/push 1/imm32
33953     89/<- %esi 4/r32/esp
33954 $test-emit-subx-stmt-select-primitive-2:initialize-stmt-operation:
33955     # stmt->operation = "increment"
33956     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
33957     (copy-array Heap "increment" %eax)
33958 $test-emit-subx-stmt-select-primitive-2:initialize-formal-var:
33959     # var formal-var/ebx: (payload var)
33960     68/push 0/imm32/register
33961     68/push 0/imm32/register
33962     68/push 0/imm32/no-stack-offset
33963     68/push 1/imm32/block-depth
33964     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
33965     68/push 0x11/imm32/alloc-id:fake
33966     68/push 0/imm32/name
33967     68/push 0/imm32/name
33968     68/push 0x11/imm32/alloc-id:fake:payload
33969     89/<- %ebx 4/r32/esp
33970 $test-emit-subx-stmt-select-primitive-2:initialize-formal-var-name:
33971     # formal-var->name = "dummy"
33972     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
33973     (copy-array Heap "dummy" %eax)
33974 $test-emit-subx-stmt-select-primitive-2:initialize-formal-register:
33975     # formal-var->register = "*"
33976     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
33977     (copy-array Heap "*" %eax)  # Any-register
33978 $test-emit-subx-stmt-select-primitive-2:initialize-var-list:
33979     # var formal-outputs/ebx: (payload list stmt-var)
33980     68/push 0/imm32/next
33981     68/push 0/imm32/next
33982     53/push-ebx/formal-var
33983     68/push 0x11/imm32/alloc-id:fake
33984     68/push 0x11/imm32/alloc-id:fake:payload
33985     89/<- %ebx 4/r32/esp
33986 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2:
33987     # var primitive2/edi: (payload primitive)
33988     68/push 0/imm32/next
33989     68/push 0/imm32/next
33990     68/push 0/imm32/no-x32
33991     68/push 0/imm32/no-xm32
33992     68/push 0/imm32/no-disp32
33993     68/push 0/imm32/no-imm8
33994     68/push 0/imm32/no-imm32
33995     68/push 0/imm32/no-r32
33996     68/push 3/imm32/rm32-is-first-output
33997     68/push 0/imm32/subx-name
33998     68/push 0/imm32/subx-name
33999     53/push-ebx/outputs
34000     68/push 0x11/imm32/alloc-id:fake
34001     68/push 0/imm32/no-inouts
34002     68/push 0/imm32/no-inouts
34003     68/push 0/imm32/name
34004     68/push 0/imm32/name
34005     68/push 0x11/imm32/alloc-id:fake:payload
34006     89/<- %edi 4/r32/esp
34007 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2-name:
34008     # primitives->name = "increment"
34009     8d/copy-address *(edi+4) 0/r32/eax  # Primitive-name + 4
34010     (copy-array Heap "increment" %eax)
34011 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2-subx-name:
34012     # primitives->subx-name = "ff 0/subop/increment"
34013     8d/copy-address *(edi+0x1c) 0/r32/eax  # Primitive-subx-name + 4
34014     (copy-array Heap "ff 0/subop/increment" %eax)
34015 $test-emit-subx-stmt-select-primitive-2:initialize-primitive:
34016     # var primitives/ebx: (addr primitive)
34017     57/push-edi
34018     68/push 0x11/imm32/alloc-id:fake
34019     68/push 0/imm32/no-x32
34020     68/push 0/imm32/no-xm32
34021     68/push 0/imm32/no-disp32
34022     68/push 0/imm32/no-imm8
34023     68/push 0/imm32/no-imm32
34024     68/push 0/imm32/no-r32
34025     68/push 1/imm32/rm32-is-first-inout
34026     68/push 0/imm32/subx-name
34027     68/push 0/imm32/subx-name
34028     68/push 0/imm32/no-outputs
34029     68/push 0/imm32/no-outputs
34030     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
34031     68/push 0x11/imm32/alloc-id:fake
34032     68/push 0/imm32/name
34033     68/push 0/imm32/name
34034     89/<- %ebx 4/r32/esp
34035 $test-emit-subx-stmt-select-primitive-2:initialize-primitive-name:
34036     # primitives->name = "increment"
34037     (copy-array Heap "increment" %ebx)  # Primitive-name
34038 $test-emit-subx-stmt-select-primitive-2:initialize-primitive-subx-name:
34039     # primitives->subx-name = "ff 0/subop/increment"
34040     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
34041     (copy-array Heap "ff 0/subop/increment" %eax)
34042     # convert
34043     c7 0/subop/copy *Curr-block-depth 0/imm32
34044     (emit-subx-stmt _test-output-buffered-file %esi %ebx Stderr 0)
34045     (flush _test-output-buffered-file)
34046 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
34052     # check output
34053     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive-2")
34054     # . epilogue
34055     89/<- %esp 5/r32/ebp
34056     5d/pop-to-ebp
34057     c3/return
34058 
34059 test-increment-register:
34060     # Select the right register between overloads.
34061     #   foo <- increment
34062     # =>
34063     #   50/increment-eax
34064     #
34065     # There's a variable on the var stack as follows:
34066     #   name: 'foo'
34067     #   type: int
34068     #   register: 'eax'
34069     #
34070     # Primitives are the global definitions.
34071     #
34072     # . prologue
34073     55/push-ebp
34074     89/<- %ebp 4/r32/esp
34075     # setup
34076     (clear-stream _test-output-stream)
34077     (clear-stream $_test-output-buffered-file->buffer)
34078 $test-increment-register:initialize-type:
34079     # var type/ecx: (payload type-tree) = int
34080     68/push 0/imm32/right:null
34081     68/push 0/imm32/right:null
34082     68/push 0/imm32/left:unused
34083     68/push 1/imm32/value:int
34084     68/push 1/imm32/is-atom?:true
34085     68/push 0x11/imm32/alloc-id:fake:payload
34086     89/<- %ecx 4/r32/esp
34087 $test-increment-register:initialize-var:
34088     # var var-foo/ecx: (payload var)
34089     68/push 0/imm32/register
34090     68/push 0/imm32/register
34091     68/push 0/imm32/no-stack-offset
34092     68/push 1/imm32/block-depth
34093     51/push-ecx
34094     68/push 0x11/imm32/alloc-id:fake
34095     68/push 0/imm32/name
34096     68/push 0/imm32/name
34097     68/push 0x11/imm32/alloc-id:fake:payload
34098     89/<- %ecx 4/r32/esp
34099 $test-increment-register:initialize-var-name:
34100     # var-foo->name = "foo"
34101     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
34102     (copy-array Heap "foo" %eax)
34103 $test-increment-register:initialize-var-register:
34104     # var-foo->register = "eax"
34105     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
34106     (copy-array Heap "eax" %eax)
34107 $test-increment-register:initialize-stmt-var:
34108     # var operand/ebx: (payload stmt-var)
34109     68/push 0/imm32/is-deref:false
34110     68/push 0/imm32/next
34111     68/push 0/imm32/next
34112     51/push-ecx/var-foo
34113     68/push 0x11/imm32/alloc-id:fake
34114     68/push 0x11/imm32/alloc-id:fake:payload
34115     89/<- %ebx 4/r32/esp
34116 $test-increment-register:initialize-stmt:
34117     # var stmt/esi: (addr statement)
34118     53/push-ebx/outputs
34119     68/push 0x11/imm32/alloc-id:fake
34120     68/push 0/imm32/no-inouts
34121     68/push 0/imm32/no-inouts
34122     68/push 0/imm32/operation
34123     68/push 0/imm32/operation
34124     68/push 1/imm32
34125     89/<- %esi 4/r32/esp
34126 $test-increment-register:initialize-stmt-operation:
34127     # stmt->operation = "increment"
34128     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
34129     (copy-array Heap "increment" %eax)
34130     # convert
34131     c7 0/subop/copy *Curr-block-depth 0/imm32
34132     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
34133     (flush _test-output-buffered-file)
34134 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
34140     # check output
34141     (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-register")
34142     # . epilogue
34143     89/<- %esp 5/r32/ebp
34144     5d/pop-to-ebp
34145     c3/return
34146 
34147 test-add-reg-to-reg:
34148     #   var1/reg <- add var2/reg
34149     # =>
34150     #   01/add-to %var1 var2
34151     #
34152     # . prologue
34153     55/push-ebp
34154     89/<- %ebp 4/r32/esp
34155     # setup
34156     (clear-stream _test-output-stream)
34157     (clear-stream $_test-output-buffered-file->buffer)
34158 $test-add-reg-to-reg:initialize-type:
34159     # var type/ecx: (payload type-tree) = int
34160     68/push 0/imm32/right:null
34161     68/push 0/imm32/right:null
34162     68/push 0/imm32/left:unused
34163     68/push 1/imm32/value:int
34164     68/push 1/imm32/is-atom?:true
34165     68/push 0x11/imm32/alloc-id:fake:payload
34166     89/<- %ecx 4/r32/esp
34167 $test-add-reg-to-reg:initialize-var1:
34168     # var var1/ecx: (payload var)
34169     68/push 0/imm32/register
34170     68/push 0/imm32/register
34171     68/push 0/imm32/no-stack-offset
34172     68/push 1/imm32/block-depth
34173     51/push-ecx
34174     68/push 0x11/imm32/alloc-id:fake
34175     68/push 0/imm32/name
34176     68/push 0/imm32/name
34177     68/push 0x11/imm32/alloc-id:fake:payload
34178     89/<- %ecx 4/r32/esp
34179 $test-add-reg-to-reg:initialize-var1-name:
34180     # var1->name = "var1"
34181     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
34182     (copy-array Heap "var1" %eax)
34183 $test-add-reg-to-reg:initialize-var1-register:
34184     # var1->register = "eax"
34185     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
34186     (copy-array Heap "eax" %eax)
34187 $test-add-reg-to-reg:initialize-var2:
34188     # var var2/edx: (payload var)
34189     68/push 0/imm32/register
34190     68/push 0/imm32/register
34191     68/push 0/imm32/no-stack-offset
34192     68/push 1/imm32/block-depth
34193     ff 6/subop/push *(ecx+0x10)
34194     68/push 0x11/imm32/alloc-id:fake
34195     68/push 0/imm32/name
34196     68/push 0/imm32/name
34197     68/push 0x11/imm32/alloc-id:fake:payload
34198     89/<- %edx 4/r32/esp
34199 $test-add-reg-to-reg:initialize-var2-name:
34200     # var2->name = "var2"
34201     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
34202     (copy-array Heap "var2" %eax)
34203 $test-add-reg-to-reg:initialize-var2-register:
34204     # var2->register = "ecx"
34205     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
34206     (copy-array Heap "ecx" %eax)
34207 $test-add-reg-to-reg:initialize-inouts:
34208     # var inouts/esi: (payload stmt-var) = [var2]
34209     68/push 0/imm32/is-deref:false
34210     68/push 0/imm32/next
34211     68/push 0/imm32/next
34212     52/push-edx/var2
34213     68/push 0x11/imm32/alloc-id:fake
34214     68/push 0x11/imm32/alloc-id:fake:payload
34215     89/<- %esi 4/r32/esp
34216 $test-add-reg-to-reg:initialize-outputs:
34217     # var outputs/edi: (payload stmt-var) = [var1]
34218     68/push 0/imm32/is-deref:false
34219     68/push 0/imm32/next
34220     68/push 0/imm32/next
34221     51/push-ecx/var1
34222     68/push 0x11/imm32/alloc-id:fake
34223     68/push 0x11/imm32/alloc-id:fake:payload
34224     89/<- %edi 4/r32/esp
34225 $test-add-reg-to-reg:initialize-stmt:
34226     # var stmt/esi: (addr statement)
34227     68/push 0/imm32/next
34228     68/push 0/imm32/next
34229     57/push-edi/outputs
34230     68/push 0x11/imm32/alloc-id:fake
34231     56/push-esi/inouts
34232     68/push 0x11/imm32/alloc-id:fake
34233     68/push 0/imm32/operation
34234     68/push 0/imm32/operation
34235     68/push 1/imm32/tag:stmt1
34236     89/<- %esi 4/r32/esp
34237 $test-add-reg-to-reg:initialize-stmt-operation:
34238     # stmt->operation = "add"
34239     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
34240     (copy-array Heap "add" %eax)
34241     # convert
34242     c7 0/subop/copy *Curr-block-depth 0/imm32
34243     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
34244     (flush _test-output-buffered-file)
34245 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
34251     # check output
34252     (check-next-stream-line-equal _test-output-stream "01/add-to %eax 0x00000001/r32" "F - test-add-reg-to-reg")
34253     # . epilogue
34254     89/<- %esp 5/r32/ebp
34255     5d/pop-to-ebp
34256     c3/return
34257 
34258 test-add-reg-to-mem:
34259     #   add-to var1 var2/reg
34260     # =>
34261     #   01/add-to *(ebp+__) var2
34262     #
34263     # . prologue
34264     55/push-ebp
34265     89/<- %ebp 4/r32/esp
34266     # setup
34267     (clear-stream _test-output-stream)
34268     (clear-stream $_test-output-buffered-file->buffer)
34269 $test-add-reg-to-mem:initialize-type:
34270     # var type/ecx: (payload type-tree) = int
34271     68/push 0/imm32/right:null
34272     68/push 0/imm32/right:null
34273     68/push 0/imm32/left:unused
34274     68/push 1/imm32/value:int
34275     68/push 1/imm32/is-atom?:true
34276     68/push 0x11/imm32/alloc-id:fake:payload
34277     89/<- %ecx 4/r32/esp
34278 $test-add-reg-to-mem:initialize-var1:
34279     # var var1/ecx: (payload var)
34280     68/push 0/imm32/register
34281     68/push 0/imm32/register
34282     68/push 8/imm32/stack-offset
34283     68/push 1/imm32/block-depth
34284     51/push-ecx
34285     68/push 0x11/imm32/alloc-id:fake
34286     68/push 0/imm32/name
34287     68/push 0/imm32/name
34288     68/push 0x11/imm32/alloc-id:fake:payload
34289     89/<- %ecx 4/r32/esp
34290 $test-add-reg-to-mem:initialize-var1-name:
34291     # var1->name = "var1"
34292     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
34293     (copy-array Heap "var1" %eax)
34294 $test-add-reg-to-mem:initialize-var2:
34295     # var var2/edx: (payload var)
34296     68/push 0/imm32/register
34297     68/push 0/imm32/register
34298     68/push 0/imm32/no-stack-offset
34299     68/push 1/imm32/block-depth
34300     ff 6/subop/push *(ecx+0x10)
34301     68/push 0x11/imm32/alloc-id:fake
34302     68/push 0/imm32/name
34303     68/push 0/imm32/name
34304     68/push 0x11/imm32/alloc-id:fake:payload
34305     89/<- %edx 4/r32/esp
34306 $test-add-reg-to-mem:initialize-var2-name:
34307     # var2->name = "var2"
34308     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
34309     (copy-array Heap "var2" %eax)
34310 $test-add-reg-to-mem:initialize-var2-register:
34311     # var2->register = "ecx"
34312     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
34313     (copy-array Heap "ecx" %eax)
34314 $test-add-reg-to-mem:initialize-inouts:
34315     # var inouts/esi: (payload stmt-var) = [var2]
34316     68/push 0/imm32/is-deref:false
34317     68/push 0/imm32/next
34318     68/push 0/imm32/next
34319     52/push-edx/var2
34320     68/push 0x11/imm32/alloc-id:fake
34321     68/push 0x11/imm32/alloc-id:fake:payload
34322     89/<- %esi 4/r32/esp
34323     # inouts = [var1, var2]
34324     68/push 0/imm32/is-deref:false
34325     56/push-esi/next
34326     68/push 0x11/imm32/alloc-id:fake
34327     51/push-ecx/var1
34328     68/push 0x11/imm32/alloc-id:fake
34329     68/push 0x11/imm32/alloc-id:fake:payload
34330     89/<- %esi 4/r32/esp
34331 $test-add-reg-to-mem:initialize-stmt:
34332     # var stmt/esi: (addr statement)
34333     68/push 0/imm32/next
34334     68/push 0/imm32/next
34335     68/push 0/imm32/outputs
34336     68/push 0/imm32/outputs
34337     56/push-esi/inouts
34338     68/push 0x11/imm32/alloc-id:fake
34339     68/push 0/imm32/operation
34340     68/push 0/imm32/operation
34341     68/push 1/imm32/tag:stmt1
34342     89/<- %esi 4/r32/esp
34343 $test-add-reg-to-mem:initialize-stmt-operation:
34344     # stmt->operation = "add-to"
34345     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
34346     (copy-array Heap "add-to" %eax)
34347     # convert
34348     c7 0/subop/copy *Curr-block-depth 0/imm32
34349     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
34350     (flush _test-output-buffered-file)
34351 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
34357     # check output
34358     (check-next-stream-line-equal _test-output-stream "01/add-to *(ebp+0x00000008) 0x00000001/r32" "F - test-add-reg-to-mem")
34359     # . epilogue
34360     89/<- %esp 5/r32/ebp
34361     5d/pop-to-ebp
34362     c3/return
34363 
34364 test-add-mem-to-reg:
34365     #   var1/reg <- add var2
34366     # =>
34367     #   03/add *(ebp+__) var1
34368     #
34369     # . prologue
34370     55/push-ebp
34371     89/<- %ebp 4/r32/esp
34372     # setup
34373     (clear-stream _test-output-stream)
34374     (clear-stream $_test-output-buffered-file->buffer)
34375 $test-add-mem-to-reg:initialize-type:
34376     # var type/ecx: (payload type-tree) = int
34377     68/push 0/imm32/right:null
34378     68/push 0/imm32/right:null
34379     68/push 0/imm32/left:unused
34380     68/push 1/imm32/value:int
34381     68/push 1/imm32/is-atom?:true
34382     68/push 0x11/imm32/alloc-id:fake:payload
34383     89/<- %ecx 4/r32/esp
34384 $test-add-mem-to-reg:initialize-var:
34385     # var var1/ecx: (payload var)
34386     68/push 0/imm32/register
34387     68/push 0/imm32/register
34388     68/push 0/imm32/no-stack-offset
34389     68/push 1/imm32/block-depth
34390     51/push-ecx
34391     68/push 0x11/imm32/alloc-id:fake
34392     68/push 0/imm32/name
34393     68/push 0/imm32/name
34394     68/push 0x11/imm32/alloc-id:fake:payload
34395     89/<- %ecx 4/r32/esp
34396 $test-add-mem-to-reg:initialize-var-name:
34397     # var1->name = "foo"
34398     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
34399     (copy-array Heap "var1" %eax)
34400 $test-add-mem-to-reg:initialize-var-register:
34401     # var1->register = "eax"
34402     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
34403     (copy-array Heap "eax" %eax)
34404 $test-add-mem-to-reg:initialize-var2:
34405     # var var2/edx: (payload var)
34406     68/push 0/imm32/register
34407     68/push 0/imm32/register
34408     68/push 8/imm32/stack-offset
34409     68/push 1/imm32/block-depth
34410     ff 6/subop/push *(ecx+0x10)
34411     68/push 0x11/imm32/alloc-id:fake
34412     68/push 0/imm32/name
34413     68/push 0/imm32/name
34414     68/push 0x11/imm32/alloc-id:fake:payload
34415     89/<- %edx 4/r32/esp
34416 $test-add-mem-to-reg:initialize-var2-name:
34417     # var2->name = "var2"
34418     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
34419     (copy-array Heap "var2" %eax)
34420 $test-add-mem-to-reg:initialize-inouts:
34421     # var inouts/esi: (payload stmt-var) = [var2]
34422     68/push 0/imm32/is-deref:false
34423     68/push 0/imm32/next
34424     68/push 0/imm32/next
34425     52/push-edx/var2
34426     68/push 0x11/imm32/alloc-id:fake
34427     68/push 0x11/imm32/alloc-id:fake:payload
34428     89/<- %esi 4/r32/esp
34429 $test-add-mem-to-reg:initialize-outputs:
34430     # var outputs/edi: (payload stmt-var) = [var1]
34431     68/push 0/imm32/is-deref:false
34432     68/push 0/imm32/next
34433     68/push 0/imm32/next
34434     51/push-ecx/var1
34435     68/push 0x11/imm32/alloc-id:fake
34436     68/push 0x11/imm32/alloc-id:fake:payload
34437     89/<- %edi 4/r32/esp
34438 $test-add-mem-to-reg:initialize-stmt:
34439     # var stmt/esi: (addr statement)
34440     68/push 0/imm32/next
34441     68/push 0/imm32/next
34442     57/push-edi/outputs
34443     68/push 0x11/imm32/alloc-id:fake
34444     56/push-esi/inouts
34445     68/push 0x11/imm32/alloc-id:fake
34446     68/push 0/imm32/operation
34447     68/push 0/imm32/operation
34448     68/push 1/imm32/tag:stmt1
34449     89/<- %esi 4/r32/esp
34450 $test-add-mem-to-reg:initialize-stmt-operation:
34451     # stmt->operation = "add"
34452     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
34453     (copy-array Heap "add" %eax)
34454     # convert
34455     c7 0/subop/copy *Curr-block-depth 0/imm32
34456     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
34457     (flush _test-output-buffered-file)
34458 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
34464     # check output
34465     (check-next-stream-line-equal _test-output-stream "03/add *(ebp+0x00000008) 0x00000000/r32" "F - test-add-mem-to-reg")
34466     # . epilogue
34467     89/<- %esp 5/r32/ebp
34468     5d/pop-to-ebp
34469     c3/return
34470 
34471 test-add-literal-to-eax:
34472     #   var1/eax <- add 0x34
34473     # =>
34474     #   05/add-to-eax 0x34/imm32
34475     #
34476     # . prologue
34477     55/push-ebp
34478     89/<- %ebp 4/r32/esp
34479     # setup
34480     (clear-stream _test-output-stream)
34481     (clear-stream $_test-output-buffered-file->buffer)
34482 $test-add-literal-to-eax:initialize-var-type:
34483     # var type/ecx: (payload type-tree) = int
34484     68/push 0/imm32/right:null
34485     68/push 0/imm32/right:null
34486     68/push 0/imm32/left:unused
34487     68/push 1/imm32/value:int
34488     68/push 1/imm32/is-atom?:true
34489     68/push 0x11/imm32/alloc-id:fake:payload
34490     89/<- %ecx 4/r32/esp
34491 $test-add-literal-to-eax:initialize-var:
34492     # var v/ecx: (payload var)
34493     68/push 0/imm32/register
34494     68/push 0/imm32/register
34495     68/push 0/imm32/no-stack-offset
34496     68/push 1/imm32/block-depth
34497     51/push-ecx
34498     68/push 0x11/imm32/alloc-id:fake
34499     68/push 0/imm32/name
34500     68/push 0/imm32/name
34501     68/push 0x11/imm32/alloc-id:fake:payload
34502     89/<- %ecx 4/r32/esp
34503 $test-add-literal-to-eax:initialize-var-name:
34504     # v->name = "v"
34505     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
34506     (copy-array Heap "v" %eax)
34507 $test-add-literal-to-eax:initialize-var-register:
34508     # v->register = "eax"
34509     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
34510     (copy-array Heap "eax" %eax)
34511 $test-add-literal-to-eax:initialize-literal-type:
34512     # var type/edx: (payload type-tree) = literal
34513     68/push 0/imm32/right:null
34514     68/push 0/imm32/right:null
34515     68/push 0/imm32/left:unused
34516     68/push 0/imm32/value:literal
34517     68/push 1/imm32/is-atom?:true
34518     68/push 0x11/imm32/alloc-id:fake:payload
34519     89/<- %edx 4/r32/esp
34520 $test-add-literal-to-eax:initialize-literal:
34521     # var l/edx: (payload var)
34522     68/push 0/imm32/register
34523     68/push 0/imm32/register
34524     68/push 0/imm32/no-stack-offset
34525     68/push 1/imm32/block-depth
34526     52/push-edx
34527     68/push 0x11/imm32/alloc-id:fake
34528     68/push 0/imm32/name
34529     68/push 0/imm32/name
34530     68/push 0x11/imm32/alloc-id:fake:payload
34531     89/<- %edx 4/r32/esp
34532 $test-add-literal-to-eax:initialize-literal-value:
34533     # l->name = "0x34"
34534     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
34535     (copy-array Heap "0x34" %eax)
34536 $test-add-literal-to-eax:initialize-inouts:
34537     # var inouts/esi: (payload stmt-var) = [l]
34538     68/push 0/imm32/is-deref:false
34539     68/push 0/imm32/next
34540     68/push 0/imm32/next
34541     52/push-edx/l
34542     68/push 0x11/imm32/alloc-id:fake
34543     68/push 0x11/imm32/alloc-id:fake:payload
34544     89/<- %esi 4/r32/esp
34545 $test-add-literal-to-eax:initialize-outputs:
34546     # var outputs/edi: (payload stmt-var) = [v]
34547     68/push 0/imm32/is-deref:false
34548     68/push 0/imm32/next
34549     68/push 0/imm32/next
34550     51/push-ecx/v
34551     68/push 0x11/imm32/alloc-id:fake
34552     68/push 0x11/imm32/alloc-id:fake:payload
34553     89/<- %edi 4/r32/esp
34554 $test-add-literal-to-eax:initialize-stmt:
34555     # var stmt/esi: (addr statement)
34556     68/push 0/imm32/next
34557     68/push 0/imm32/next
34558     57/push-edi/outputs
34559     68/push 0x11/imm32/alloc-id:fake
34560     56/push-esi/inouts
34561     68/push 0x11/imm32/alloc-id:fake
34562     68/push 0/imm32/operation
34563     68/push 0/imm32/operation
34564     68/push 1/imm32/tag:stmt1
34565     89/<- %esi 4/r32/esp
34566 $test-add-literal-to-eax:initialize-stmt-operation:
34567     # stmt->operation = "add"
34568     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
34569     (copy-array Heap "add" %eax)
34570     # convert
34571     c7 0/subop/copy *Curr-block-depth 0/imm32
34572     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
34573     (flush _test-output-buffered-file)
34574 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
34580     # check output
34581     (check-next-stream-line-equal _test-output-stream "05/add-to-eax 0x34/imm32" "F - test-add-literal-to-eax")
34582     # . epilogue
34583     89/<- %esp 5/r32/ebp
34584     5d/pop-to-ebp
34585     c3/return
34586 
34587 test-add-literal-to-reg:
34588     #   var1/ecx <- add 0x34
34589     # =>
34590     #   81 0/subop/add %ecx 0x34/imm32
34591     #
34592     # . prologue
34593     55/push-ebp
34594     89/<- %ebp 4/r32/esp
34595     # setup
34596     (clear-stream _test-output-stream)
34597     (clear-stream $_test-output-buffered-file->buffer)
34598 $test-add-literal-to-reg:initialize-var-type:
34599     # var type/ecx: (payload type-tree) = int
34600     68/push 0/imm32/right:null
34601     68/push 0/imm32/right:null
34602     68/push 0/imm32/left:unused
34603     68/push 1/imm32/value:int
34604     68/push 1/imm32/is-atom?:true
34605     68/push 0x11/imm32/alloc-id:fake:payload
34606     89/<- %ecx 4/r32/esp
34607 $test-add-literal-to-reg:initialize-var:
34608     # var v/ecx: (payload var)
34609     68/push 0/imm32/register
34610     68/push 0/imm32/register
34611     68/push 0/imm32/no-stack-offset
34612     68/push 1/imm32/block-depth
34613     51/push-ecx
34614     68/push 0x11/imm32/alloc-id:fake
34615     68/push 0/imm32/name
34616     68/push 0/imm32/name
34617     68/push 0x11/imm32/alloc-id:fake:payload
34618     89/<- %ecx 4/r32/esp
34619 $test-add-literal-to-reg:initialize-var-name:
34620     # v->name = "v"
34621     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
34622     (copy-array Heap "v" %eax)
34623 $test-add-literal-to-reg:initialize-var-register:
34624     # v->register = "ecx"
34625     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
34626     (copy-array Heap "ecx" %eax)
34627 $test-add-literal-to-reg:initialize-literal-type:
34628     # var type/edx: (payload type-tree) = literal
34629     68/push 0/imm32/right:null
34630     68/push 0/imm32/right:null
34631     68/push 0/imm32/left:unused
34632     68/push 0/imm32/value:literal
34633     68/push 1/imm32/is-atom?:true
34634     68/push 0x11/imm32/alloc-id:fake:payload
34635     89/<- %edx 4/r32/esp
34636 $test-add-literal-to-reg:initialize-literal:
34637     # var l/edx: (payload var)
34638     68/push 0/imm32/register
34639     68/push 0/imm32/register
34640     68/push 0/imm32/no-stack-offset
34641     68/push 1/imm32/block-depth
34642     52/push-edx
34643     68/push 0x11/imm32/alloc-id:fake
34644     68/push 0/imm32/name
34645     68/push 0/imm32/name
34646     68/push 0x11/imm32/alloc-id:fake:payload
34647     89/<- %edx 4/r32/esp
34648 $test-add-literal-to-reg:initialize-literal-value:
34649     # l->name = "0x34"
34650     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
34651     (copy-array Heap "0x34" %eax)
34652 $test-add-literal-to-reg:initialize-inouts:
34653     # var inouts/esi: (payload stmt-var) = [l]
34654     68/push 0/imm32/is-deref:false
34655     68/push 0/imm32/next
34656     68/push 0/imm32/next
34657     52/push-edx/l
34658     68/push 0x11/imm32/alloc-id:fake
34659     68/push 0x11/imm32/alloc-id:fake:payload
34660     89/<- %esi 4/r32/esp
34661 $test-add-literal-to-reg:initialize-outputs:
34662     # var outputs/edi: (payload stmt-var) = [v]
34663     68/push 0/imm32/is-deref:false
34664     68/push 0/imm32/next
34665     68/push 0/imm32/next
34666     51/push-ecx/v
34667     68/push 0x11/imm32/alloc-id:fake
34668     68/push 0x11/imm32/alloc-id:fake:payload
34669     89/<- %edi 4/r32/esp
34670 $test-add-literal-to-reg:initialize-stmt:
34671     # var stmt/esi: (addr statement)
34672     68/push 0/imm32/next
34673     68/push 0/imm32/next
34674     57/push-edi/outputs
34675     68/push 0x11/imm32/alloc-id:fake
34676     56/push-esi/inouts
34677     68/push 0x11/imm32/alloc-id:fake
34678     68/push 0/imm32/operation
34679     68/push 0/imm32/operation
34680     68/push 1/imm32/tag:stmt1
34681     89/<- %esi 4/r32/esp
34682 $test-add-literal-to-reg:initialize-stmt-operation:
34683     # stmt->operation = "add"
34684     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
34685     (copy-array Heap "add" %eax)
34686     # convert
34687     c7 0/subop/copy *Curr-block-depth 0/imm32
34688     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
34689     (flush _test-output-buffered-file)
34690 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
34696     # check output
34697     (check-next-stream-line-equal _test-output-stream "81 0/subop/add %ecx 0x34/imm32" "F - test-add-literal-to-reg")
34698     # . epilogue
34699     89/<- %esp 5/r32/ebp
34700     5d/pop-to-ebp
34701     c3/return
34702 
34703 test-add-literal-to-mem:
34704     #   add-to var1, 0x34
34705     # =>
34706     #   81 0/subop/add %eax 0x34/imm32
34707     #
34708     # . prologue
34709     55/push-ebp
34710     89/<- %ebp 4/r32/esp
34711     # setup
34712     (clear-stream _test-output-stream)
34713     (clear-stream $_test-output-buffered-file->buffer)
34714 $test-add-literal-to-mem:initialize-type:
34715     # var type/ecx: (payload type-tree) = int
34716     68/push 0/imm32/right:null
34717     68/push 0/imm32/right:null
34718     68/push 0/imm32/left:unused
34719     68/push 1/imm32/value:int
34720     68/push 1/imm32/is-atom?:true
34721     68/push 0x11/imm32/alloc-id:fake:payload
34722     89/<- %ecx 4/r32/esp
34723 $test-add-literal-to-mem:initialize-var1:
34724     # var var1/ecx: (payload var)
34725     68/push 0/imm32/register
34726     68/push 0/imm32/register
34727     68/push 8/imm32/stack-offset
34728     68/push 1/imm32/block-depth
34729     51/push-ecx
34730     68/push 0x11/imm32/alloc-id:fake
34731     68/push 0/imm32/name
34732     68/push 0/imm32/name
34733     68/push 0x11/imm32/alloc-id:fake:payload
34734     89/<- %ecx 4/r32/esp
34735 $test-add-literal-to-mem:initialize-var1-name:
34736     # var1->name = "var1"
34737     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
34738     (copy-array Heap "var1" %eax)
34739 $test-add-literal-to-mem:initialize-literal-type:
34740     # var type/edx: (payload type-tree) = literal
34741     68/push 0/imm32/right:null
34742     68/push 0/imm32/right:null
34743     68/push 0/imm32/left:unused
34744     68/push 0/imm32/value:literal
34745     68/push 1/imm32/is-atom?:true
34746     68/push 0x11/imm32/alloc-id:fake:payload
34747     89/<- %edx 4/r32/esp
34748 $test-add-literal-to-mem:initialize-literal:
34749     # var l/edx: (payload var)
34750     68/push 0/imm32/register
34751     68/push 0/imm32/register
34752     68/push 0/imm32/no-stack-offset
34753     68/push 1/imm32/block-depth
34754     52/push-edx
34755     68/push 0x11/imm32/alloc-id:fake
34756     68/push 0/imm32/name
34757     68/push 0/imm32/name
34758     68/push 0x11/imm32/alloc-id:fake:payload
34759     89/<- %edx 4/r32/esp
34760 $test-add-literal-to-mem:initialize-literal-value:
34761     # l->name = "0x34"
34762     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
34763     (copy-array Heap "0x34" %eax)
34764 $test-add-literal-to-mem:initialize-inouts:
34765     # var inouts/esi: (payload stmt-var) = [l]
34766     68/push 0/imm32/is-deref:false
34767     68/push 0/imm32/next
34768     68/push 0/imm32/next
34769     52/push-edx/l
34770     68/push 0x11/imm32/alloc-id:fake
34771     68/push 0x11/imm32/alloc-id:fake:payload
34772     89/<- %esi 4/r32/esp
34773     # var inouts = (handle stmt-var) = [var1, var2]
34774     68/push 0/imm32/is-deref:false
34775     56/push-esi/next
34776     68/push 0x11/imm32/alloc-id:fake
34777     51/push-ecx/var1
34778     68/push 0x11/imm32/alloc-id:fake
34779     68/push 0x11/imm32/alloc-id:fake:payload
34780     89/<- %esi 4/r32/esp
34781 $test-add-literal-to-mem:initialize-stmt:
34782     # var stmt/esi: (addr statement)
34783     68/push 0/imm32/next
34784     68/push 0/imm32/next
34785     68/push 0/imm32/outputs
34786     68/push 0/imm32/outputs
34787     56/push-esi/inouts
34788     68/push 0x11/imm32/alloc-id:fake
34789     68/push 0/imm32/operation
34790     68/push 0/imm32/operation
34791     68/push 1/imm32/tag:stmt1
34792     89/<- %esi 4/r32/esp
34793 $test-add-literal-to-mem:initialize-stmt-operation:
34794     # stmt->operation = "add-to"
34795     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
34796     (copy-array Heap "add-to" %eax)
34797     # convert
34798     c7 0/subop/copy *Curr-block-depth 0/imm32
34799     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
34800     (flush _test-output-buffered-file)
34801 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
34807     # check output
34808     (check-next-stream-line-equal _test-output-stream "81 0/subop/add *(ebp+0x00000008) 0x34/imm32" "F - test-add-literal-to-mem")
34809     # . epilogue
34810     89/<- %esp 5/r32/ebp
34811     5d/pop-to-ebp
34812     c3/return
34813 
34814 test-shift-reg-by-literal:
34815     #   var1/ecx <- shift-left 2
34816     # =>
34817     #   c1/shift 4/subop/left %ecx 2/imm8
34818     #
34819     # . prologue
34820     55/push-ebp
34821     89/<- %ebp 4/r32/esp
34822     # setup
34823     (clear-stream _test-output-stream)
34824     (clear-stream $_test-output-buffered-file->buffer)
34825 $test-shift-reg-by-literal:initialize-var-type:
34826     # var type/ecx: (payload type-tree) = int
34827     68/push 0/imm32/right:null
34828     68/push 0/imm32/right:null
34829     68/push 0/imm32/left:unused
34830     68/push 1/imm32/value:int
34831     68/push 1/imm32/is-atom?:true
34832     68/push 0x11/imm32/alloc-id:fake:payload
34833     89/<- %ecx 4/r32/esp
34834 $test-shift-reg-by-literal:initialize-var:
34835     # var v/ecx: (payload var)
34836     68/push 0/imm32/register
34837     68/push 0/imm32/register
34838     68/push 0/imm32/no-stack-offset
34839     68/push 1/imm32/block-depth
34840     51/push-ecx
34841     68/push 0x11/imm32/alloc-id:fake
34842     68/push 0/imm32/name
34843     68/push 0/imm32/name
34844     68/push 0x11/imm32/alloc-id:fake:payload
34845     89/<- %ecx 4/r32/esp
34846 $test-shift-reg-by-literal:initialize-var-name:
34847     # v->name = "v"
34848     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
34849     (copy-array Heap "v" %eax)
34850 $test-shift-reg-by-literal:initialize-var-register:
34851     # v->register = "ecx"
34852     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
34853     (copy-array Heap "ecx" %eax)
34854 $test-shift-reg-by-literal:initialize-literal-type:
34855     # var type/edx: (payload type-tree) = literal
34856     68/push 0/imm32/right:null
34857     68/push 0/imm32/right:null
34858     68/push 0/imm32/left:unused
34859     68/push 0/imm32/value:literal
34860     68/push 1/imm32/is-atom?:true
34861     68/push 0x11/imm32/alloc-id:fake:payload
34862     89/<- %edx 4/r32/esp
34863 $test-shift-reg-by-literal:initialize-literal:
34864     # var l/edx: (payload var)
34865     68/push 0/imm32/register
34866     68/push 0/imm32/register
34867     68/push 0/imm32/no-stack-offset
34868     68/push 1/imm32/block-depth
34869     52/push-edx
34870     68/push 0x11/imm32/alloc-id:fake
34871     68/push 0/imm32/name
34872     68/push 0/imm32/name
34873     68/push 0x11/imm32/alloc-id:fake:payload
34874     89/<- %edx 4/r32/esp
34875 $test-shift-reg-by-literal:initialize-literal-value:
34876     # l->name = "2"
34877     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
34878     (copy-array Heap "2" %eax)
34879 $test-shift-reg-by-literal:initialize-inouts:
34880     # var inouts/esi: (payload stmt-var) = [l]
34881     68/push 0/imm32/is-deref:false
34882     68/push 0/imm32/next
34883     68/push 0/imm32/next
34884     52/push-edx/l
34885     68/push 0x11/imm32/alloc-id:fake
34886     68/push 0x11/imm32/alloc-id:fake:payload
34887     89/<- %esi 4/r32/esp
34888 $test-shift-reg-by-literal:initialize-outputs:
34889     # var outputs/edi: (payload stmt-var) = [v]
34890     68/push 0/imm32/is-deref:false
34891     68/push 0/imm32/next
34892     68/push 0/imm32/next
34893     51/push-ecx/v
34894     68/push 0x11/imm32/alloc-id:fake
34895     68/push 0x11/imm32/alloc-id:fake:payload
34896     89/<- %edi 4/r32/esp
34897 $test-shift-reg-by-literal:initialize-stmt:
34898     # var stmt/esi: (addr statement)
34899     68/push 0/imm32/next
34900     68/push 0/imm32/next
34901     57/push-edi/outputs
34902     68/push 0x11/imm32/alloc-id:fake
34903     56/push-esi/inouts
34904     68/push 0x11/imm32/alloc-id:fake
34905     68/push 0/imm32/operation
34906     68/push 0/imm32/operation
34907     68/push 1/imm32/tag:stmt1
34908     89/<- %esi 4/r32/esp
34909 $test-shift-reg-by-literal:initialize-stmt-operation:
34910     # stmt->operation = "shift-left"
34911     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
34912     (copy-array Heap "shift-left" %eax)
34913     # convert
34914     c7 0/subop/copy *Curr-block-depth 0/imm32
34915     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
34916     (flush _test-output-buffered-file)
34917 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
34923     # check output
34924     (check-next-stream-line-equal _test-output-stream "c1/shift 4/subop/left %ecx 2/imm8" "F - test-shift-reg-by-literal")
34925     # . epilogue
34926     89/<- %esp 5/r32/ebp
34927     5d/pop-to-ebp
34928     c3/return
34929 
34930 test-shift-mem-by-literal:
34931     #   shift-left var 3
34932     # =>
34933     #   c1/shift 4/subop/left *(ebp+8) 3/imm8
34934     #
34935     # . prologue
34936     55/push-ebp
34937     89/<- %ebp 4/r32/esp
34938     # setup
34939     (clear-stream _test-output-stream)
34940     (clear-stream $_test-output-buffered-file->buffer)
34941 $test-shift-mem-by-literal:initialize-type:
34942     # var type/ecx: (payload type-tree) = int
34943     68/push 0/imm32/right:null
34944     68/push 0/imm32/right:null
34945     68/push 0/imm32/left:unused
34946     68/push 1/imm32/value:int
34947     68/push 1/imm32/is-atom?:true
34948     68/push 0x11/imm32/alloc-id:fake:payload
34949     89/<- %ecx 4/r32/esp
34950 $test-shift-mem-by-literal:initialize-var1:
34951     # var var1/ecx: (payload var)
34952     68/push 0/imm32/register
34953     68/push 0/imm32/register
34954     68/push 8/imm32/stack-offset
34955     68/push 1/imm32/block-depth
34956     51/push-ecx
34957     68/push 0x11/imm32/alloc-id:fake
34958     68/push 0/imm32/name
34959     68/push 0/imm32/name
34960     68/push 0x11/imm32/alloc-id:fake:payload
34961     89/<- %ecx 4/r32/esp
34962 $test-shift-mem-by-literal:initialize-var1-name:
34963     # var1->name = "var1"
34964     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
34965     (copy-array Heap "var1" %eax)
34966 $test-shift-mem-by-literal:initialize-literal-type:
34967     # var type/edx: (payload type-tree) = literal
34968     68/push 0/imm32/right:null
34969     68/push 0/imm32/right:null
34970     68/push 0/imm32/left:unused
34971     68/push 0/imm32/value:literal
34972     68/push 1/imm32/is-atom?:true
34973     68/push 0x11/imm32/alloc-id:fake:payload
34974     89/<- %edx 4/r32/esp
34975 $test-shift-mem-by-literal:initialize-literal:
34976     # var l/edx: (payload var)
34977     68/push 0/imm32/register
34978     68/push 0/imm32/register
34979     68/push 0/imm32/no-stack-offset
34980     68/push 1/imm32/block-depth
34981     52/push-edx
34982     68/push 0x11/imm32/alloc-id:fake
34983     68/push 0/imm32/name
34984     68/push 0/imm32/name
34985     68/push 0x11/imm32/alloc-id:fake:payload
34986     89/<- %edx 4/r32/esp
34987 $test-shift-mem-by-literal:initialize-literal-value:
34988     # l->name = "3"
34989     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
34990     (copy-array Heap "3" %eax)
34991 $test-shift-mem-by-literal:initialize-inouts:
34992     # var inouts/esi: (payload stmt-var) = [l]
34993     68/push 0/imm32/is-deref:false
34994     68/push 0/imm32/next
34995     68/push 0/imm32/next
34996     52/push-edx/l
34997     68/push 0x11/imm32/alloc-id:fake
34998     68/push 0x11/imm32/alloc-id:fake:payload
34999     89/<- %esi 4/r32/esp
35000     # var inouts = (handle stmt-var) = [var1, var2]
35001     68/push 0/imm32/is-deref:false
35002     56/push-esi/next
35003     68/push 0x11/imm32/alloc-id:fake
35004     51/push-ecx/var1
35005     68/push 0x11/imm32/alloc-id:fake
35006     68/push 0x11/imm32/alloc-id:fake:payload
35007     89/<- %esi 4/r32/esp
35008 $test-shift-mem-by-literal:initialize-stmt:
35009     # var stmt/esi: (addr statement)
35010     68/push 0/imm32/next
35011     68/push 0/imm32/next
35012     68/push 0/imm32/outputs
35013     68/push 0/imm32/outputs
35014     56/push-esi/inouts
35015     68/push 0x11/imm32/alloc-id:fake
35016     68/push 0/imm32/operation
35017     68/push 0/imm32/operation
35018     68/push 1/imm32/tag:stmt1
35019     89/<- %esi 4/r32/esp
35020 $test-shift-mem-by-literal:initialize-stmt-operation:
35021     # stmt->operation = "shift-left"
35022     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
35023     (copy-array Heap "shift-left" %eax)
35024     # convert
35025     c7 0/subop/copy *Curr-block-depth 0/imm32
35026     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
35027     (flush _test-output-buffered-file)
35028 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
35034     # check output
35035     (check-next-stream-line-equal _test-output-stream "c1/shift 4/subop/left *(ebp+0x00000008) 3/imm8" "F - test-shift-mem-by-literal")
35036     # . epilogue
35037     89/<- %esp 5/r32/ebp
35038     5d/pop-to-ebp
35039     c3/return
35040 
35041 test-compare-reg-with-reg:
35042     #   compare var1/ecx, var2/eax
35043     # =>
35044     #   39/compare %ecx 0/r32/eax
35045     #
35046     # . prologue
35047     55/push-ebp
35048     89/<- %ebp 4/r32/esp
35049     # setup
35050     (clear-stream _test-output-stream)
35051     (clear-stream $_test-output-buffered-file->buffer)
35052 $test-compare-reg-with-reg:initialize-type:
35053     # var type/ecx: (payload type-tree) = int
35054     68/push 0/imm32/right:null
35055     68/push 0/imm32/right:null
35056     68/push 0/imm32/left:unused
35057     68/push 1/imm32/value:int
35058     68/push 1/imm32/is-atom?:true
35059     68/push 0x11/imm32/alloc-id:fake:payload
35060     89/<- %ecx 4/r32/esp
35061 $test-compare-reg-with-reg:initialize-var1:
35062     # var var1/ecx: (payload var)
35063     68/push 0/imm32/register
35064     68/push 0/imm32/register
35065     68/push 0/imm32/no-stack-offset
35066     68/push 1/imm32/block-depth
35067     51/push-ecx
35068     68/push 0x11/imm32/alloc-id:fake
35069     68/push 0/imm32/name
35070     68/push 0/imm32/name
35071     68/push 0x11/imm32/alloc-id:fake:payload
35072     89/<- %ecx 4/r32/esp
35073 $test-compare-reg-with-reg:initialize-var1-name:
35074     # var1->name = "var1"
35075     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
35076     (copy-array Heap "var1" %eax)
35077 $test-compare-reg-with-reg:initialize-var1-register:
35078     # var1->register = "ecx"
35079     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
35080     (copy-array Heap "ecx" %eax)
35081 $test-compare-reg-with-reg:initialize-var2:
35082     # var var2/edx: (payload var)
35083     68/push 0/imm32/register
35084     68/push 0/imm32/register
35085     68/push 0/imm32/no-stack-offset
35086     68/push 1/imm32/block-depth
35087     ff 6/subop/push *(ecx+0x10)
35088     68/push 0x11/imm32/alloc-id:fake
35089     68/push 0/imm32/name
35090     68/push 0/imm32/name
35091     68/push 0x11/imm32/alloc-id:fake:payload
35092     89/<- %edx 4/r32/esp
35093 $test-compare-reg-with-reg:initialize-var2-name:
35094     # var2->name = "var2"
35095     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
35096     (copy-array Heap "var2" %eax)
35097 $test-compare-reg-with-reg:initialize-var2-register:
35098     # var2->register = "eax"
35099     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
35100     (copy-array Heap "eax" %eax)
35101 $test-compare-reg-with-reg:initialize-inouts:
35102     # var inouts/esi: (payload stmt-var) = [var2]
35103     68/push 0/imm32/is-deref:false
35104     68/push 0/imm32/next
35105     68/push 0/imm32/next
35106     52/push-edx/var2
35107     68/push 0x11/imm32/alloc-id:fake
35108     68/push 0x11/imm32/alloc-id:fake:payload
35109     89/<- %esi 4/r32/esp
35110     # inouts = [var1, var2]
35111     68/push 0/imm32/is-deref:false
35112     56/push-esi/next
35113     68/push 0x11/imm32/alloc-id:fake
35114     51/push-ecx/var1
35115     68/push 0x11/imm32/alloc-id:fake
35116     68/push 0x11/imm32/alloc-id:fake:payload
35117     89/<- %esi 4/r32/esp
35118 $test-compare-reg-with-reg:initialize-stmt:
35119     # var stmt/esi: (addr statement)
35120     68/push 0/imm32/next
35121     68/push 0/imm32/next
35122     68/push 0/imm32/outputs
35123     68/push 0/imm32/outputs
35124     56/push-esi/inouts
35125     68/push 0x11/imm32/alloc-id:fake
35126     68/push 0/imm32/operation
35127     68/push 0/imm32/operation
35128     68/push 1/imm32/tag:stmt1
35129     89/<- %esi 4/r32/esp
35130 $test-compare-reg-with-reg:initialize-stmt-operation:
35131     # stmt->operation = "compare"
35132     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
35133     (copy-array Heap "compare" %eax)
35134     # convert
35135     c7 0/subop/copy *Curr-block-depth 0/imm32
35136     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
35137     (flush _test-output-buffered-file)
35138 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
35144     # check output
35145     (check-next-stream-line-equal _test-output-stream "39/compare-> %ecx 0x00000000/r32" "F - test-compare-reg-with-reg")
35146     # . epilogue
35147     89/<- %esp 5/r32/ebp
35148     5d/pop-to-ebp
35149     c3/return
35150 
35151 test-compare-mem-with-reg:
35152     #   compare var1, var2/eax
35153     # =>
35154     #   39/compare *(ebp+___) 0/r32/eax
35155     #
35156     # . prologue
35157     55/push-ebp
35158     89/<- %ebp 4/r32/esp
35159     # setup
35160     (clear-stream _test-output-stream)
35161     (clear-stream $_test-output-buffered-file->buffer)
35162 $test-compare-mem-with-reg:initialize-type:
35163     # var type/ecx: (payload type-tree) = int
35164     68/push 0/imm32/right:null
35165     68/push 0/imm32/right:null
35166     68/push 0/imm32/left:unused
35167     68/push 1/imm32/value:int
35168     68/push 1/imm32/is-atom?:true
35169     68/push 0x11/imm32/alloc-id:fake:payload
35170     89/<- %ecx 4/r32/esp
35171 $test-compare-mem-with-reg:initialize-var1:
35172     # var var1/ecx: (payload var)
35173     68/push 0/imm32/register
35174     68/push 0/imm32/register
35175     68/push 8/imm32/stack-offset
35176     68/push 1/imm32/block-depth
35177     51/push-ecx
35178     68/push 0x11/imm32/alloc-id:fake
35179     68/push 0/imm32/name
35180     68/push 0/imm32/name
35181     68/push 0x11/imm32/alloc-id:fake:payload
35182     89/<- %ecx 4/r32/esp
35183 $test-compare-mem-with-reg:initialize-var1-name:
35184     # var1->name = "var1"
35185     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
35186     (copy-array Heap "var1" %eax)
35187 $test-compare-mem-with-reg:initialize-var2:
35188     # var var2/edx: (payload var)
35189     68/push 0/imm32/register
35190     68/push 0/imm32/register
35191     68/push 0/imm32/no-stack-offset
35192     68/push 1/imm32/block-depth
35193     ff 6/subop/push *(ecx+0x10)
35194     68/push 0x11/imm32/alloc-id:fake
35195     68/push 0/imm32/name
35196     68/push 0/imm32/name
35197     68/push 0x11/imm32/alloc-id:fake:payload
35198     89/<- %edx 4/r32/esp
35199 $test-compare-mem-with-reg:initialize-var2-name:
35200     # var2->name = "var2"
35201     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
35202     (copy-array Heap "var2" %eax)
35203 $test-compare-mem-with-reg:initialize-var2-register:
35204     # var2->register = "eax"
35205     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
35206     (copy-array Heap "eax" %eax)
35207 $test-compare-mem-with-reg:initialize-inouts:
35208     # var inouts/esi: (payload stmt-var) = [var2]
35209     68/push 0/imm32/is-deref:false
35210     68/push 0/imm32/next
35211     68/push 0/imm32/next
35212     52/push-edx/var2
35213     68/push 0x11/imm32/alloc-id:fake
35214     68/push 0x11/imm32/alloc-id:fake:payload
35215     89/<- %esi 4/r32/esp
35216     # inouts = [var1, var2]
35217     68/push 0/imm32/is-deref:false
35218     56/push-esi/next
35219     68/push 0x11/imm32/alloc-id:fake
35220     51/push-ecx/var1
35221     68/push 0x11/imm32/alloc-id:fake
35222     68/push 0x11/imm32/alloc-id:fake:payload
35223     89/<- %esi 4/r32/esp
35224 $test-compare-mem-with-reg:initialize-stmt:
35225     # var stmt/esi: (addr statement)
35226     68/push 0/imm32/next
35227     68/push 0/imm32/next
35228     68/push 0/imm32/outputs
35229     68/push 0/imm32/outputs
35230     56/push-esi/inouts
35231     68/push 0x11/imm32/alloc-id:fake
35232     68/push 0/imm32/operation
35233     68/push 0/imm32/operation
35234     68/push 1/imm32/tag:stmt1
35235     89/<- %esi 4/r32/esp
35236 $test-compare-mem-with-reg:initialize-stmt-operation:
35237     # stmt->operation = "compare"
35238     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
35239     (copy-array Heap "compare" %eax)
35240     # convert
35241     c7 0/subop/copy *Curr-block-depth 0/imm32
35242     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
35243     (flush _test-output-buffered-file)
35244 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
35250     # check output
35251     (check-next-stream-line-equal _test-output-stream "39/compare-> *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-mem-with-reg")
35252     # . epilogue
35253     89/<- %esp 5/r32/ebp
35254     5d/pop-to-ebp
35255     c3/return
35256 
35257 test-compare-reg-with-mem:
35258     #   compare var1/eax, var2
35259     # =>
35260     #   3b/compare<- *(ebp+___) 0/r32/eax
35261     #
35262     # . prologue
35263     55/push-ebp
35264     89/<- %ebp 4/r32/esp
35265     # setup
35266     (clear-stream _test-output-stream)
35267     (clear-stream $_test-output-buffered-file->buffer)
35268 $test-compare-reg-with-mem:initialize-type:
35269     # var type/ecx: (payload type-tree) = int
35270     68/push 0/imm32/right:null
35271     68/push 0/imm32/right:null
35272     68/push 0/imm32/left:unused
35273     68/push 1/imm32/value:int
35274     68/push 1/imm32/is-atom?:true
35275     68/push 0x11/imm32/alloc-id:fake:payload
35276     89/<- %ecx 4/r32/esp
35277 $test-compare-reg-with-mem:initialize-var1:
35278     # var var1/ecx: (payload var)
35279     68/push 0/imm32/register
35280     68/push 0/imm32/register
35281     68/push 0/imm32/no-stack-offset
35282     68/push 1/imm32/block-depth
35283     51/push-ecx
35284     68/push 0x11/imm32/alloc-id:fake
35285     68/push 0/imm32/name
35286     68/push 0/imm32/name
35287     68/push 0x11/imm32/alloc-id:fake:payload
35288     89/<- %ecx 4/r32/esp
35289 $test-compare-reg-with-mem:initialize-var1-name:
35290     # var1->name = "var1"
35291     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
35292     (copy-array Heap "var1" %eax)
35293 $test-compare-reg-with-mem:initialize-var1-register:
35294     # var1->register = "eax"
35295     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
35296     (copy-array Heap "eax" %eax)
35297 $test-compare-reg-with-mem:initialize-var2:
35298     # var var2/edx: (payload var)
35299     68/push 0/imm32/register
35300     68/push 0/imm32/register
35301     68/push 8/imm32/stack-offset
35302     68/push 1/imm32/block-depth
35303     ff 6/subop/push *(ecx+0x10)
35304     68/push 0x11/imm32/alloc-id:fake
35305     68/push 0/imm32/name
35306     68/push 0/imm32/name
35307     68/push 0x11/imm32/alloc-id:fake:payload
35308     89/<- %edx 4/r32/esp
35309 $test-compare-reg-with-mem:initialize-var2-name:
35310     # var2->name = "var2"
35311     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
35312     (copy-array Heap "var2" %eax)
35313 $test-compare-reg-with-mem:initialize-inouts:
35314     # var inouts/esi: (payload stmt-var) = [var2]
35315     68/push 0/imm32/is-deref:false
35316     68/push 0/imm32/next
35317     68/push 0/imm32/next
35318     52/push-edx/var2
35319     68/push 0x11/imm32/alloc-id:fake
35320     68/push 0x11/imm32/alloc-id:fake:payload
35321     89/<- %esi 4/r32/esp
35322     # inouts = [var1, var2]
35323     68/push 0/imm32/is-deref:false
35324     56/push-esi/next
35325     68/push 0x11/imm32/alloc-id:fake
35326     51/push-ecx/var1
35327     68/push 0x11/imm32/alloc-id:fake
35328     68/push 0x11/imm32/alloc-id:fake:payload
35329     89/<- %esi 4/r32/esp
35330 $test-compare-reg-with-mem:initialize-stmt:
35331     # var stmt/esi: (addr statement)
35332     68/push 0/imm32/next
35333     68/push 0/imm32/next
35334     68/push 0/imm32/outputs
35335     68/push 0/imm32/outputs
35336     56/push-esi/inouts
35337     68/push 0x11/imm32/alloc-id:fake
35338     68/push 0/imm32/operation
35339     68/push 0/imm32/operation
35340     68/push 1/imm32/tag:stmt1
35341     89/<- %esi 4/r32/esp
35342 $test-compare-reg-with-mem:initialize-stmt-operation:
35343     # stmt->operation = "compare"
35344     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
35345     (copy-array Heap "compare" %eax)
35346     # convert
35347     c7 0/subop/copy *Curr-block-depth 0/imm32
35348     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
35349     (flush _test-output-buffered-file)
35350 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
35356     # check output
35357     (check-next-stream-line-equal _test-output-stream "3b/compare<- *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-reg-with-mem")
35358     # . epilogue
35359     89/<- %esp 5/r32/ebp
35360     5d/pop-to-ebp
35361     c3/return
35362 
35363 test-compare-mem-with-literal:
35364     #   compare var1, 0x34
35365     # =>
35366     #   81 7/subop/compare *(ebp+___) 0x34/imm32
35367     #
35368     # . prologue
35369     55/push-ebp
35370     89/<- %ebp 4/r32/esp
35371     # setup
35372     (clear-stream _test-output-stream)
35373     (clear-stream $_test-output-buffered-file->buffer)
35374 $test-compare-mem-with-literal:initialize-type:
35375     # var type/ecx: (payload type-tree) = int
35376     68/push 0/imm32/right:null
35377     68/push 0/imm32/right:null
35378     68/push 0/imm32/left:unused
35379     68/push 1/imm32/value:int
35380     68/push 1/imm32/is-atom?:true
35381     68/push 0x11/imm32/alloc-id:fake:payload
35382     89/<- %ecx 4/r32/esp
35383 $test-compare-mem-with-literal:initialize-var1:
35384     # var var1/ecx: (payload var)
35385     68/push 0/imm32/register
35386     68/push 0/imm32/register
35387     68/push 8/imm32/stack-offset
35388     68/push 1/imm32/block-depth
35389     51/push-ecx
35390     68/push 0x11/imm32/alloc-id:fake
35391     68/push 0/imm32/name
35392     68/push 0/imm32/name
35393     68/push 0x11/imm32/alloc-id:fake:payload
35394     89/<- %ecx 4/r32/esp
35395 $test-compare-mem-with-literal:initialize-var1-name:
35396     # var1->name = "var1"
35397     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
35398     (copy-array Heap "var1" %eax)
35399 $test-compare-mem-with-literal:initialize-literal-type:
35400     # var type/edx: (payload type-tree) = literal
35401     68/push 0/imm32/right:null
35402     68/push 0/imm32/right:null
35403     68/push 0/imm32/left:unused
35404     68/push 0/imm32/value:literal
35405     68/push 1/imm32/is-atom?:true
35406     68/push 0x11/imm32/alloc-id:fake:payload
35407     89/<- %edx 4/r32/esp
35408 $test-compare-mem-with-literal:initialize-literal:
35409     # var l/edx: (payload var)
35410     68/push 0/imm32/register
35411     68/push 0/imm32/register
35412     68/push 0/imm32/no-stack-offset
35413     68/push 1/imm32/block-depth
35414     52/push-edx
35415     68/push 0x11/imm32/alloc-id:fake
35416     68/push 0/imm32/name
35417     68/push 0/imm32/name
35418     68/push 0x11/imm32/alloc-id:fake:payload
35419     89/<- %edx 4/r32/esp
35420 $test-compare-mem-with-literal:initialize-literal-value:
35421     # l->name = "0x34"
35422     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
35423     (copy-array Heap "0x34" %eax)
35424 $test-compare-mem-with-literal:initialize-inouts:
35425     # var inouts/esi: (payload stmt-var) = [l]
35426     68/push 0/imm32/is-deref:false
35427     68/push 0/imm32/next
35428     68/push 0/imm32/next
35429     52/push-edx/l
35430     68/push 0x11/imm32/alloc-id:fake
35431     68/push 0x11/imm32/alloc-id:fake:payload
35432     89/<- %esi 4/r32/esp
35433     # var inouts = (handle stmt-var) = [var1, var2]
35434     68/push 0/imm32/is-deref:false
35435     56/push-esi/next
35436     68/push 0x11/imm32/alloc-id:fake
35437     51/push-ecx/var1
35438     68/push 0x11/imm32/alloc-id:fake
35439     68/push 0x11/imm32/alloc-id:fake:payload
35440     89/<- %esi 4/r32/esp
35441 $test-compare-mem-with-literal:initialize-stmt:
35442     # var stmt/esi: (addr statement)
35443     68/push 0/imm32/next
35444     68/push 0/imm32/next
35445     68/push 0/imm32/outputs
35446     68/push 0/imm32/outputs
35447     56/push-esi/inouts
35448     68/push 0x11/imm32/alloc-id:fake
35449     68/push 0/imm32/operation
35450     68/push 0/imm32/operation
35451     68/push 1/imm32/tag:stmt1
35452     89/<- %esi 4/r32/esp
35453 $test-compare-mem-with-literal:initialize-stmt-operation:
35454     # stmt->operation = "compare"
35455     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
35456     (copy-array Heap "compare" %eax)
35457     # convert
35458     c7 0/subop/copy *Curr-block-depth 0/imm32
35459     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
35460     (flush _test-output-buffered-file)
35461 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
35467     # check output
35468     (check-next-stream-line-equal _test-output-stream "81 7/subop/compare *(ebp+0x00000008) 0x34/imm32" "F - test-compare-mem-with-literal")
35469     # . epilogue
35470     89/<- %esp 5/r32/ebp
35471     5d/pop-to-ebp
35472     c3/return
35473 
35474 test-compare-eax-with-literal:
35475     #   compare var1/eax 0x34
35476     # =>
35477     #   3d/compare-eax-with 0x34/imm32
35478     #
35479     # . prologue
35480     55/push-ebp
35481     89/<- %ebp 4/r32/esp
35482     # setup
35483     (clear-stream _test-output-stream)
35484     (clear-stream $_test-output-buffered-file->buffer)
35485 $test-compare-eax-with-literal:initialize-type:
35486     # var type/ecx: (payload type-tree) = int
35487     68/push 0/imm32/right:null
35488     68/push 0/imm32/right:null
35489     68/push 0/imm32/left:unused
35490     68/push 1/imm32/value:int
35491     68/push 1/imm32/is-atom?:true
35492     68/push 0x11/imm32/alloc-id:fake:payload
35493     89/<- %ecx 4/r32/esp
35494 $test-compare-eax-with-literal:initialize-var1:
35495     # var var1/ecx: (payload var)
35496     68/push 0/imm32/register
35497     68/push 0/imm32/register
35498     68/push 0/imm32/no-stack-offset
35499     68/push 1/imm32/block-depth
35500     51/push-ecx
35501     68/push 0x11/imm32/alloc-id:fake
35502     68/push 0/imm32/name
35503     68/push 0/imm32/name
35504     68/push 0x11/imm32/alloc-id:fake:payload
35505     89/<- %ecx 4/r32/esp
35506 $test-compare-eax-with-literal:initialize-var1-name:
35507     # var1->name = "var1"
35508     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
35509     (copy-array Heap "var1" %eax)
35510 $test-compare-eax-with-literal:initialize-var1-register:
35511     # v->register = "eax"
35512     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
35513     (copy-array Heap "eax" %eax)
35514 $test-compare-eax-with-literal:initialize-literal-type:
35515     # var type/edx: (payload type-tree) = literal
35516     68/push 0/imm32/right:null
35517     68/push 0/imm32/right:null
35518     68/push 0/imm32/left:unused
35519     68/push 0/imm32/value:literal
35520     68/push 1/imm32/is-atom?:true
35521     68/push 0x11/imm32/alloc-id:fake:payload
35522     89/<- %edx 4/r32/esp
35523 $test-compare-eax-with-literal:initialize-literal:
35524     # var l/edx: (payload var)
35525     68/push 0/imm32/register
35526     68/push 0/imm32/register
35527     68/push 0/imm32/no-stack-offset
35528     68/push 1/imm32/block-depth
35529     52/push-edx
35530     68/push 0x11/imm32/alloc-id:fake
35531     68/push 0/imm32/name
35532     68/push 0/imm32/name
35533     68/push 0x11/imm32/alloc-id:fake:payload
35534     89/<- %edx 4/r32/esp
35535 $test-compare-eax-with-literal:initialize-literal-value:
35536     # l->name = "0x34"
35537     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
35538     (copy-array Heap "0x34" %eax)
35539 $test-compare-eax-with-literal:initialize-inouts:
35540     # var inouts/esi: (payload stmt-var) = [l]
35541     68/push 0/imm32/is-deref:false
35542     68/push 0/imm32/next
35543     68/push 0/imm32/next
35544     52/push-edx/l
35545     68/push 0x11/imm32/alloc-id:fake
35546     68/push 0x11/imm32/alloc-id:fake:payload
35547     89/<- %esi 4/r32/esp
35548     # var inouts = (handle stmt-var) = [var1, var2]
35549     68/push 0/imm32/is-deref:false
35550     56/push-esi/next
35551     68/push 0x11/imm32/alloc-id:fake
35552     51/push-ecx/var1
35553     68/push 0x11/imm32/alloc-id:fake
35554     68/push 0x11/imm32/alloc-id:fake:payload
35555     89/<- %esi 4/r32/esp
35556 $test-compare-eax-with-literal:initialize-stmt:
35557     # var stmt/esi: (addr statement)
35558     68/push 0/imm32/next
35559     68/push 0/imm32/next
35560     68/push 0/imm32/outputs
35561     68/push 0/imm32/outputs
35562     56/push-esi/inouts
35563     68/push 0x11/imm32/alloc-id:fake
35564     68/push 0/imm32/operation
35565     68/push 0/imm32/operation
35566     68/push 1/imm32/tag:stmt1
35567     89/<- %esi 4/r32/esp
35568 $test-compare-eax-with-literal:initialize-stmt-operation:
35569     # stmt->operation = "compare"
35570     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
35571     (copy-array Heap "compare" %eax)
35572     # convert
35573     c7 0/subop/copy *Curr-block-depth 0/imm32
35574     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
35575     (flush _test-output-buffered-file)
35576 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
35582     # check output
35583     (check-next-stream-line-equal _test-output-stream "3d/compare-eax-with 0x34/imm32" "F - test-compare-eax-with-literal")
35584     # . epilogue
35585     89/<- %esp 5/r32/ebp
35586     5d/pop-to-ebp
35587     c3/return
35588 
35589 test-compare-reg-with-literal:
35590     #   compare var1/ecx 0x34
35591     # =>
35592     #   81 7/subop/compare %ecx 0x34/imm32
35593     #
35594     # . prologue
35595     55/push-ebp
35596     89/<- %ebp 4/r32/esp
35597     # setup
35598     (clear-stream _test-output-stream)
35599     (clear-stream $_test-output-buffered-file->buffer)
35600 $test-compare-reg-with-literal:initialize-type:
35601     # var type/ecx: (payload type-tree) = int
35602     68/push 0/imm32/right:null
35603     68/push 0/imm32/right:null
35604     68/push 0/imm32/left:unused
35605     68/push 1/imm32/value:int
35606     68/push 1/imm32/is-atom?:true
35607     68/push 0x11/imm32/alloc-id:fake:payload
35608     89/<- %ecx 4/r32/esp
35609 $test-compare-reg-with-literal:initialize-var1:
35610     # var var1/ecx: (payload var)
35611     68/push 0/imm32/register
35612     68/push 0/imm32/register
35613     68/push 0/imm32/no-stack-offset
35614     68/push 1/imm32/block-depth
35615     51/push-ecx
35616     68/push 0x11/imm32/alloc-id:fake
35617     68/push 0/imm32/name
35618     68/push 0/imm32/name
35619     68/push 0x11/imm32/alloc-id:fake:payload
35620     89/<- %ecx 4/r32/esp
35621 $test-compare-reg-with-literal:initialize-var1-name:
35622     # var1->name = "var1"
35623     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
35624     (copy-array Heap "var1" %eax)
35625 $test-compare-reg-with-literal:initialize-var1-register:
35626     # v->register = "ecx"
35627     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
35628     (copy-array Heap "ecx" %eax)
35629 $test-compare-reg-with-literal:initialize-literal-type:
35630     # var type/edx: (payload type-tree) = literal
35631     68/push 0/imm32/right:null
35632     68/push 0/imm32/right:null
35633     68/push 0/imm32/left:unused
35634     68/push 0/imm32/value:literal
35635     68/push 1/imm32/is-atom?:true
35636     68/push 0x11/imm32/alloc-id:fake:payload
35637     89/<- %edx 4/r32/esp
35638 $test-compare-reg-with-literal:initialize-literal:
35639     # var l/edx: (payload var)
35640     68/push 0/imm32/register
35641     68/push 0/imm32/register
35642     68/push 0/imm32/no-stack-offset
35643     68/push 1/imm32/block-depth
35644     52/push-edx
35645     68/push 0x11/imm32/alloc-id:fake
35646     68/push 0/imm32/name
35647     68/push 0/imm32/name
35648     68/push 0x11/imm32/alloc-id:fake:payload
35649     89/<- %edx 4/r32/esp
35650 $test-compare-reg-with-literal:initialize-literal-value:
35651     # l->name = "0x34"
35652     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
35653     (copy-array Heap "0x34" %eax)
35654 $test-compare-reg-with-literal:initialize-inouts:
35655     # var inouts/esi: (payload stmt-var) = [l]
35656     68/push 0/imm32/is-deref:false
35657     68/push 0/imm32/next
35658     68/push 0/imm32/next
35659     52/push-edx/l
35660     68/push 0x11/imm32/alloc-id:fake
35661     68/push 0x11/imm32/alloc-id:fake:payload
35662     89/<- %esi 4/r32/esp
35663     # var inouts = (handle stmt-var) = [var1, var2]
35664     68/push 0/imm32/is-deref:false
35665     56/push-esi/next
35666     68/push 0x11/imm32/alloc-id:fake
35667     51/push-ecx/var1
35668     68/push 0x11/imm32/alloc-id:fake
35669     68/push 0x11/imm32/alloc-id:fake:payload
35670     89/<- %esi 4/r32/esp
35671 $test-compare-reg-with-literal:initialize-stmt:
35672     # var stmt/esi: (addr statement)
35673     68/push 0/imm32/next
35674     68/push 0/imm32/next
35675     68/push 0/imm32/outputs
35676     68/push 0/imm32/outputs
35677     56/push-esi/inouts
35678     68/push 0x11/imm32/alloc-id:fake
35679     68/push 0/imm32/operation
35680     68/push 0/imm32/operation
35681     68/push 1/imm32/tag:stmt1
35682     89/<- %esi 4/r32/esp
35683 $test-compare-reg-with-literal:initialize-stmt-operation:
35684     # stmt->operation = "compare"
35685     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
35686     (copy-array Heap "compare" %eax)
35687     # convert
35688     c7 0/subop/copy *Curr-block-depth 0/imm32
35689     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
35690     (flush _test-output-buffered-file)
35691 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
35697     # check output
35698     (check-next-stream-line-equal _test-output-stream "81 7/subop/compare %ecx 0x34/imm32" "F - test-compare-reg-with-literal")
35699     # . epilogue
35700     89/<- %esp 5/r32/ebp
35701     5d/pop-to-ebp
35702     c3/return
35703 
35704 test-emit-subx-stmt-function-call:
35705     # Call a function on a variable on the stack.
35706     #   f foo
35707     # =>
35708     #   (f *(ebp-8))
35709     # (Changing the function name supports overloading in general, but here it
35710     # just serves to help disambiguate things.)
35711     #
35712     # There's a variable on the var stack as follows:
35713     #   name: 'foo'
35714     #   type: int
35715     #   stack-offset: -8
35716     #
35717     # There's nothing in primitives.
35718     #
35719     # We don't perform any checking here on the type of 'f'.
35720     #
35721     # . prologue
35722     55/push-ebp
35723     89/<- %ebp 4/r32/esp
35724     # setup
35725     (clear-stream _test-output-stream)
35726     (clear-stream $_test-output-buffered-file->buffer)
35727 $test-emit-subx-function-call:initialize-type:
35728     # var type/ecx: (payload type-tree) = int
35729     68/push 0/imm32/right:null
35730     68/push 0/imm32/right:null
35731     68/push 0/imm32/left:unused
35732     68/push 1/imm32/value:int
35733     68/push 1/imm32/is-atom?:true
35734     68/push 0x11/imm32/alloc-id:fake:payload
35735     89/<- %ecx 4/r32/esp
35736 $test-emit-subx-function-call:initialize-var:
35737     # var var-foo/ecx: (payload var) = var(type)
35738     68/push 0/imm32/no-register
35739     68/push 0/imm32/no-register
35740     68/push -8/imm32/stack-offset
35741     68/push 1/imm32/block-depth
35742     51/push-ecx/type
35743     68/push 0x11/imm32/alloc-id:fake
35744     68/push 0/imm32/name
35745     68/push 0/imm32/name
35746     68/push 0x11/imm32/alloc-id:fake:payload
35747     89/<- %ecx 4/r32/esp
35748 $test-emit-subx-function-call:initialize-var-name:
35749     # var-foo->name = "foo"
35750     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
35751     (copy-array Heap "foo" %eax)
35752 $test-emit-subx-function-call:initialize-stmt-var:
35753     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
35754     68/push 0/imm32/is-deref:false
35755     68/push 0/imm32/next
35756     68/push 0/imm32/next
35757     51/push-ecx/var-foo
35758     68/push 0x11/imm32/alloc-id:fake
35759     68/push 0x11/imm32/alloc-id:fake:payload
35760     89/<- %ebx 4/r32/esp
35761 $test-emit-subx-function-call:initialize-stmt:
35762     # var stmt/esi: (addr statement)
35763     68/push 0/imm32/no-outputs
35764     68/push 0/imm32/no-outputs
35765     53/push-ebx/inouts
35766     68/push 0x11/imm32/alloc-id:fake
35767     68/push 0/imm32/operation
35768     68/push 0/imm32/operation
35769     68/push 1/imm32/tag
35770     89/<- %esi 4/r32/esp
35771 $test-emit-subx-function-call:initialize-stmt-operation:
35772     # stmt->operation = "f"
35773     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
35774     (copy-array Heap "f" %eax)
35775     # convert
35776     c7 0/subop/copy *Curr-block-depth 0/imm32
35777     (emit-subx-stmt _test-output-buffered-file %esi 0 Stderr 0)
35778     (flush _test-output-buffered-file)
35779 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
35785     # check output
35786     (check-next-stream-line-equal _test-output-stream "(f *(ebp+0xfffffff8))" "F - test-emit-subx-stmt-function-call")
35787     # . epilogue
35788     89/<- %esp 5/r32/ebp
35789     5d/pop-to-ebp
35790     c3/return
35791 
35792 test-emit-subx-stmt-function-call-with-literal-arg:
35793     # Call a function on a literal.
35794     #   f 0x34
35795     # =>
35796     #   (f2 0x34)
35797     #
35798     # . prologue
35799     55/push-ebp
35800     89/<- %ebp 4/r32/esp
35801     # setup
35802     (clear-stream _test-output-stream)
35803     (clear-stream $_test-output-buffered-file->buffer)
35804 $test-emit-subx-function-call-with-literal-arg:initialize-type:
35805     # var type/ecx: (payload type-tree) = int
35806     68/push 0/imm32/right:null
35807     68/push 0/imm32/right:null
35808     68/push 0/imm32/left:unused
35809     68/push 0/imm32/value:literal
35810     68/push 1/imm32/is-atom?:true
35811     68/push 0x11/imm32/alloc-id:fake:payload
35812     89/<- %ecx 4/r32/esp
35813 $test-emit-subx-function-call-with-literal-arg:initialize-var:
35814     # var var-foo/ecx: (payload var) = var(lit)
35815     68/push 0/imm32/no-register
35816     68/push 0/imm32/no-register
35817     68/push 0/imm32/no-stack-offset
35818     68/push 1/imm32/block-depth
35819     51/push-ecx/type
35820     68/push 0x11/imm32/alloc-id:fake
35821     68/push 0/imm32/name
35822     68/push 0/imm32/name
35823     68/push 0x11/imm32/alloc-id:fake:payload
35824     89/<- %ecx 4/r32/esp
35825 $test-emit-subx-function-call-with-literal-arg:initialize-var-name:
35826     # var-foo->name = "0x34"
35827     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
35828     (copy-array Heap "0x34" %eax)
35829 $test-emit-subx-function-call-with-literal-arg:initialize-stmt-var:
35830     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
35831     68/push 0/imm32/is-deref:false
35832     68/push 0/imm32/next
35833     68/push 0/imm32/next
35834     51/push-ecx/var-foo
35835     68/push 0x11/imm32/alloc-id:fake
35836     68/push 0x11/imm32/alloc-id:fake:payload
35837     89/<- %ebx 4/r32/esp
35838 $test-emit-subx-function-call-with-literal-arg:initialize-stmt:
35839     # var stmt/esi: (addr statement)
35840     68/push 0/imm32/no-outputs
35841     68/push 0/imm32/no-outputs
35842     53/push-ebx/inouts
35843     68/push 0x11/imm32/alloc-id:fake
35844     68/push 0/imm32/operation
35845     68/push 0/imm32/operation
35846     68/push 1/imm32/tag
35847     89/<- %esi 4/r32/esp
35848 $test-emit-subx-function-call-with-literal-arg:initialize-stmt-operation:
35849     # stmt->operation = "f"
35850     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
35851     (copy-array Heap "f" %eax)
35852     # convert
35853     c7 0/subop/copy *Curr-block-depth 0/imm32
35854     (emit-subx-stmt _test-output-buffered-file %esi 0 %ebx Stderr 0)
35855     (flush _test-output-buffered-file)
35856 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
35862     # check output
35863     (check-next-stream-line-equal _test-output-stream "(f 0x34)" "F - test-emit-subx-stmt-function-call-with-literal-arg")
35864     # . epilogue
35865     89/<- %esp 5/r32/ebp
35866     5d/pop-to-ebp
35867     c3/return
35868 
35869 emit-indent:  # out: (addr buffered-file), n: int
35870     # . prologue
35871     55/push-ebp
35872     89/<- %ebp 4/r32/esp
35873     # . save registers
35874     50/push-eax
35875     # var i/eax: int = n
35876     8b/-> *(ebp+0xc) 0/r32/eax
35877     {
35878       # if (i <= 0) break
35879       3d/compare-eax-with 0/imm32
35880       7e/jump-if-<= break/disp8
35881       (write-buffered *(ebp+8) "  ")
35882       48/decrement-eax
35883       eb/jump loop/disp8
35884     }
35885 $emit-indent:end:
35886     # . restore registers
35887     58/pop-to-eax
35888     # . epilogue
35889     89/<- %esp 5/r32/ebp
35890     5d/pop-to-ebp
35891     c3/return
35892 
35893 emit-subx-prologue:  # out: (addr buffered-file)
35894     # . prologue
35895     55/push-ebp
35896     89/<- %ebp 4/r32/esp
35897     #
35898     (write-buffered *(ebp+8) "  # . prologue\n")
35899     (write-buffered *(ebp+8) "  55/push-ebp\n")
35900     (write-buffered *(ebp+8) "  89/<- %ebp 4/r32/esp\n")
35901 $emit-subx-prologue:end:
35902     # . epilogue
35903     89/<- %esp 5/r32/ebp
35904     5d/pop-to-ebp
35905     c3/return
35906 
35907 emit-subx-epilogue:  # out: (addr buffered-file)
35908     # . prologue
35909     55/push-ebp
35910     89/<- %ebp 4/r32/esp
35911     #
35912     (write-buffered *(ebp+8) "  # . epilogue\n")
35913     (write-buffered *(ebp+8) "  89/<- %esp 5/r32/ebp\n")
35914     (write-buffered *(ebp+8) "  5d/pop-to-ebp\n")
35915     (write-buffered *(ebp+8) "  c3/return\n")
35916 $emit-subx-epilogue:end:
35917     # . epilogue
35918     89/<- %esp 5/r32/ebp
35919     5d/pop-to-ebp
35920     c3/return