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 -> result/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.
   39 #
   40 # Blocks mostly consist of statements.
   41 #
   42 # Statements mostly consist of a name, optional inputs and optional outputs.
   43 #
   44 # Statement inputs are variables or literals. Variables need to specify type
   45 # (and storage) the first time they're mentioned but not later.
   46 #
   47 # Statement outputs, like function outputs, must be variables in registers.
   48 #
   49 # Statement names must be either primitives or user-defined functions.
   50 #
   51 # Primitives can write to any register.
   52 # User-defined functions only write to hard-coded registers. Outputs of each
   53 # call must have the same registers as in the function definition.
   54 #
   55 # There are some other statement types:
   56 #   - blocks. Multiple statements surrounded by '{...}' and optionally
   57 #     prefixed with a label name and ':'
   58 #       - {
   59 #           ...
   60 #         }
   61 #       - foo: {
   62 #           ...
   63 #         }
   64 #
   65 #   - variable definitions on the stack. E.g.:
   66 #       - var foo: int
   67 #       - var bar: (array int 3)
   68 #     There's no initializer; variables are automatically initialized.
   69 #     The type of a local variable is either word-length (4 bytes) or starts with 'ref'.
   70 #
   71 #   - variables definitions in a register. E.g.:
   72 #       - var foo/eax: int <- add bar 1
   73 #     The initializer is mandatory and must be a valid instruction that writes
   74 #     a single output to the right register. In practice registers will
   75 #     usually be either initialized by primitives or copied from eax.
   76 #       - var eax: int <- foo bar quux
   77 #         var floo/ecx: int <- copy eax
   78 #
   79 # Still todo:
   80 #   global variables
   81 #   union types
   82 #
   83 # Formal types:
   84 #   A program is a linked list of functions
   85 #   A function contains:
   86 #     name: (handle array byte)
   87 #     inouts: linked list of vars  <-- 'inouts' is more precise than 'inputs'
   88 #       data: (handle var)
   89 #       next: (handle list)
   90 #     outputs: linked list of vars
   91 #       data: (handle var)
   92 #       next: (handle list)
   93 #     body: (handle block)
   94 #   A var-type contains:
   95 #     name: (handle array byte)
   96 #     type: (handle type-tree)
   97 #
   98 #   A statement can be:
   99 #     tag 0: a block
  100 #     tag 1: a simple statement (stmt1)
  101 #     tag 2: a variable defined on the stack
  102 #     tag 3: a variable defined in a register
  103 #
  104 #   A block contains:
  105 #     tag: 0
  106 #     statements: (handle list stmt)
  107 #     name: (handle array byte) -- starting with '$'
  108 #
  109 #   A regular statement contains:
  110 #     tag: 1
  111 #     operation: (handle array byte)
  112 #     inouts: (handle list operand)
  113 #     outputs: (handle list var)
  114 #
  115 #   A variable defined on the stack contains:
  116 #     tag: 2
  117 #     name: (handle array byte)
  118 #     type: (handle type-tree)
  119 #
  120 #   A variable defined in a register contains:
  121 #     tag: 3
  122 #     name: (handle array byte)
  123 #     type: (handle type-tree)
  124 #     reg: (handle array byte)
  125 
  126 # == Translation: managing the stack
  127 # Now that we know what the language looks like in the large, let's think
  128 # about how translation happens from the bottom up. One crucial piece of the
  129 # puzzle is how Mu will clean up variables defined on the stack for you.
  130 #
  131 # Assume that we maintain a 'functions' list while parsing source code. And a
  132 # 'primitives' list is a global constant. Both these contain enough information
  133 # to perform type-checking on function calls or primitive statements, respectively.
  134 #
  135 # Defining variables pushes them on a stack with the current block depth and
  136 # enough information about their location (stack offset or register).
  137 # Starting a block increments the current block id.
  138 # Each statement now has enough information to emit code for it.
  139 # Ending a block is where the magic happens:
  140 #   pop all variables at the current block depth
  141 #   emit code to restore all register variables introduced at the current depth
  142 #   emit code to clean up all stack variables at the current depth (just increment esp)
  143 #   decrement the current block depth
  144 #
  145 # Formal types:
  146 #   live-vars: stack of vars
  147 #   var:
  148 #     name: (handle array byte)
  149 #     type: (handle type-tree)
  150 #     block: int
  151 #     stack-offset: int  (added to ebp)
  152 #     register: (handle array byte)
  153 #       either usual register names
  154 #       or '*' to indicate any register
  155 #   At most one of stack-offset or register-index must be non-zero.
  156 #   A register of '*' designates a variable _template_. Only legal in formal
  157 #   parameters for primitives.
  158 
  159 # == Translating a single function call
  160 # This one's easy. Assuming we've already checked things, we just drop the
  161 # outputs (which use hard-coded registers) and emit inputs in a standard format.
  162 #
  163 # out1, out2, out3, ... <- name inout1, inout2, inout3, ...
  164 # =>
  165 # (name inout1 inout2 inout3)
  166 #
  167 # Formal types:
  168 #   functions: linked list of info
  169 #     name: (handle array byte)
  170 #     inouts: linked list of vars
  171 #     outputs: linked list of vars
  172 #     body: block (linked list of statements)
  173 
  174 # == Translating a single primitive instruction
  175 # A second crucial piece of the puzzle is how Mu converts fairly regular
  176 # primitives with their uniform syntax to SubX instructions with their gnarly
  177 # x86 details.
  178 #
  179 # Mu instructions have inputs and outputs. Primitives can have up to 2 of
  180 # them.
  181 # SubX instructions have rm32 and r32 operands.
  182 # The translation between them covers almost all the possibilities.
  183 #   Instructions with 1 inout may turn into ones with 1 rm32
  184 #     (e.g. incrementing a var on the stack)
  185 #   Instructions with 1 output may turn into ones with 1 rm32
  186 #     (e.g. incrementing a var in a register)
  187 #   1 inout and 1 output may turn into 1 rm32 and 1 r32
  188 #     (e.g. adding a var to a reg)
  189 #   2 inouts may turn into 1 rm32 and 1 r32
  190 #     (e.g. adding a reg to a var)
  191 #   1 inout and 1 literal may turn into 1 rm32 and 1 imm32
  192 #     (e.g. adding a constant to a var)
  193 #   1 output and 1 literal may turn into 1 rm32 and 1 imm32
  194 #     (e.g. adding a constant to a reg)
  195 #   2 outputs to hardcoded registers and 1 inout may turn into 1 rm32
  196 #     (special-case: divide edx:eax by a var or reg)
  197 # Observations:
  198 #   We always emit rm32. It may be the first inout or the first output.
  199 #   We may emit r32 or imm32 or neither.
  200 #   When we emit r32 it may come from first inout or second inout or first output.
  201 #
  202 # Accordingly, the formal data structure for a primitive looks like this:
  203 #   primitives: linked list of info
  204 #     name: (handle array byte)
  205 #     mu-inouts: linked list of vars to check
  206 #     mu-outputs: linked list of vars to check; at most a singleton
  207 #     subx-name: (handle array byte)
  208 #     subx-rm32: enum arg-location
  209 #     subx-r32: enum arg-location
  210 #     subx-imm32: enum arg-location
  211 #     subx-imm8: enum arg-location
  212 #     subx-disp32: enum arg-location
  213 #     output-is-write-only: boolean
  214 #   arg-location: enum
  215 #     0 means none
  216 #     1 means first inout
  217 #     2 means second inout
  218 #     3 means first output
  219 
  220 # == Translating a block
  221 # Emit block name if necessary
  222 # Emit '{'
  223 # When you encounter a statement, emit it as above
  224 # When you encounter a variable declaration
  225 #   emit any code needed for it (bzeros)
  226 #   push it on the var stack
  227 #   update register dict if necessary
  228 # When you encounter '}'
  229 #   While popping variables off the var stack until block id changes
  230 #     Emit code needed to clean up the stack
  231 #       either increment esp
  232 #       or pop into appropriate register
  233 
  234 # The rest is straightforward.
  235 
  236 == data
  237 
  238 Program:
  239 _Program-functions:  # (handle function)
  240   0/imm32
  241 _Program-functions->payload:
  242   0/imm32
  243 _Program-types:  # (handle typeinfo)
  244   0/imm32
  245 _Program-types->payload:
  246   0/imm32
  247 _Program-signatures:  # (handle function)
  248   0/imm32
  249 _Program-signatures->payload:
  250   0/imm32
  251 
  252 # Some constants for simulating the data structures described above.
  253 # Many constants here come with a type in a comment.
  254 #
  255 # Sometimes the type is of the value at that offset for the given type. For
  256 # example, if you start at a function record and move forward Function-inouts
  257 # bytes, you'll find a (handle list var).
  258 #
  259 # At other times, the type is of the constant itself. For example, the type of
  260 # the constant Function-size is (addr int). To get the size of a function,
  261 # look in *Function-size.
  262 
  263 Function-name:  # (handle array byte)
  264   0/imm32
  265 Function-inouts:  # (handle list var)
  266   8/imm32
  267 Function-outputs:  # (handle list var)
  268   0x10/imm32
  269 Function-body:  # (handle block)
  270   0x18/imm32
  271 Function-next:  # (handle function)
  272   0x20/imm32
  273 Function-size:  # (addr int)
  274   0x28/imm32/40
  275 
  276 Primitive-name:  # (handle array byte)
  277   0/imm32
  278 Primitive-inouts:  # (handle list var)
  279   8/imm32
  280 Primitive-outputs:  # (handle list var)
  281   0x10/imm32
  282 Primitive-subx-name:  # (handle array byte)
  283   0x18/imm32
  284 Primitive-subx-rm32:  # enum arg-location
  285   0x20/imm32
  286 Primitive-subx-r32:  # enum arg-location
  287   0x24/imm32
  288 Primitive-subx-imm32:  # enum arg-location
  289   0x28/imm32
  290 Primitive-subx-imm8:  # enum arg-location  -- only for bit shifts
  291   0x2c/imm32
  292 Primitive-subx-disp32:  # enum arg-location  -- only for branches
  293   0x30/imm32
  294 Primitive-output-is-write-only:  # boolean
  295   0x34/imm32
  296 Primitive-next:  # (handle function)
  297   0x38/imm32
  298 Primitive-size:  # (addr int)
  299   0x40/imm32/60
  300 
  301 Stmt-tag:  # int
  302   0/imm32
  303 
  304 Block-stmts:  # (handle list stmt)
  305   4/imm32
  306 Block-var:  # (handle var)
  307   0xc/imm32
  308 
  309 Stmt1-operation:  # (handle array byte)
  310   4/imm32
  311 Stmt1-inouts:  # (handle stmt-var)
  312   0xc/imm32
  313 Stmt1-outputs:  # (handle stmt-var)
  314   0x14/imm32
  315 
  316 Vardef-var:  # (handle var)
  317   4/imm32
  318 
  319 Regvardef-operation:  # (handle array byte)
  320   4/imm32
  321 Regvardef-inouts:  # (handle stmt-var)
  322   0xc/imm32
  323 Regvardef-outputs:  # (handle stmt-var)  # will have exactly one element
  324   0x14/imm32
  325 
  326 Stmt-size:  # (addr int)
  327   0x1c/imm32
  328 
  329 Var-name:  # (handle array byte)
  330   0/imm32
  331 Var-type:  # (handle type-tree)
  332   8/imm32
  333 Var-block-depth:  # int -- not available until code-generation time
  334   0x10/imm32
  335 Var-offset:  # int -- not available until code-generation time
  336   0x14/imm32
  337 Var-register:  # (handle array byte) -- name of a register
  338   0x18/imm32
  339 Var-size:  # (addr int)
  340   0x20/imm32
  341 
  342 List-value:  # (handle _)
  343   0/imm32
  344 List-next:  # (handle list _)
  345   8/imm32
  346 List-size:  # (addr int)
  347   0x10/imm32
  348 
  349 # A stmt-var is like a list of vars with call-site specific metadata
  350 Stmt-var-value:  # (handle var)
  351   0/imm32
  352 Stmt-var-next:  # (handle stmt-var)
  353   8/imm32
  354 Stmt-var-is-deref:  # boolean
  355   0x10/imm32
  356 Stmt-var-size:  # (addr int)
  357   0x14/imm32
  358 
  359 # A live-var is a var augmented with information needed for tracking live
  360 # variables.
  361 Live-var-value:  # (handle var)
  362   0/imm32
  363 Live-var-register-spilled:  # boolean; only used if value is in a register, and only during code-gen
  364   8/imm32
  365 Live-var-size:  # (addr int)
  366   0xc/imm32
  367 
  368 # Types are expressed as trees (s-expressions) of type-ids (ints).
  369 
  370 Type-tree-is-atom:  # boolean
  371   0/imm32
  372 # if is-atom?
  373 Type-tree-value:  # type-id
  374   4/imm32
  375 Type-tree-value-size:  # int (for static data structure sizes)
  376   8/imm32
  377 Type-tree-parameter-name:  # (handle array byte) for type parameters
  378   8/imm32
  379 # unless is-atom?
  380 Type-tree-left:  # (addr type-tree)
  381   4/imm32
  382 Type-tree-right:  # (addr type-tree)
  383   0xc/imm32
  384 #
  385 Type-tree-size:  # (addr int)
  386   0x14/imm32
  387 
  388 # Types
  389 
  390 # TODO: Turn this data structure into valid Mu, with (fake) handles rather than addrs.
  391 Type-id:  # (stream (addr array byte))
  392   0/imm32/write  # initialized later from Primitive-type-ids
  393   0/imm32/read
  394   0x100/imm32/size
  395   # data
  396   0/imm32  # 0 reserved for literals; value is just the name
  397            # Not to be used directly, so we don't include a name here.
  398   "int"/imm32  # 1
  399   "addr"/imm32  # 2
  400   "array"/imm32  # 3
  401   "handle"/imm32  # 4
  402   "boolean"/imm32  # 5
  403   0/imm32  # 6 reserved for constants; they're like literals, but value is an int in Var-offset
  404            # Not to be used directly, so we don't include a name here.
  405   "offset"/imm32  # 7: (offset T) is guaranteed to be a 32-bit multiple of size-of(T)
  406   # 0x20
  407   "byte"/imm32  # 8
  408   0/imm32  # 9 reserved for array-capacity; value is in Type-tree-size.
  409            # Not to be used directly, so we don't include a name here.
  410   0/imm32  # 10 reserved for type parameters; value is (address array byte) in Type-tree-value2.
  411            # Not to be used directly, so we don't include a name here.
  412   # some SubX types deliberately left undefined in Mu; they can only be operated on using SubX primitives
  413   "stream"/imm32  # 11
  414   "slice"/imm32  # 12
  415   "code-point"/imm32  # 13; smallest scannable unit from a text stream
  416   "grapheme"/imm32  # 14; smallest printable unit; will eventually be composed of multiple code-points, but currently corresponds 1:1
  417                     # only 4-byte graphemes in utf-8 are currently supported;
  418                     # unclear how we should deal with larger clusters.
  419   # Keep Primitive-type-ids in sync if you add types here.
  420                                                           0/imm32
  421   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  422   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  423   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  424   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  425   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  426   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  427 
  428 Primitive-type-ids:  # (addr int)
  429   0x34
  430 
  431 # == Type definitions
  432 # Program->types contains some typeinfo for each type definition.
  433 # Types contain vars with types, but can't specify registers.
  434 Typeinfo-id:  # type-id
  435   0/imm32
  436 Typeinfo-fields:  # (handle table (handle array byte) (handle typeinfo-entry))
  437   4/imm32
  438 # Total size must be >= 0
  439 # During parsing it may take on two additional values:
  440 #   -2: not yet initialized
  441 #   -1: in process of being computed
  442 # See populate-mu-type-sizes for details.
  443 Typeinfo-total-size-in-bytes:  # int
  444   0xc/imm32
  445 Typeinfo-next:  # (handle typeinfo)
  446   0x10/imm32
  447 Typeinfo-size:  # (addr int)
  448   0x18/imm32
  449 
  450 # Each entry in the typeinfo->fields table has a pointer to a string and a
  451 # pointer to a typeinfo-entry.
  452 Typeinfo-fields-row-size:  # (addr int)
  453   0x10/imm32
  454 
  455 # typeinfo-entry objects have information about a field in a single record type
  456 #
  457 # each field of a type is represented using two var's:
  458 #   1. the input var: expected type of the field; convenient for creating using parse-var-with-type
  459 #   2. the output var: a constant containing the byte offset; convenient for code-generation
  460 # computing the output happens after parsing; in the meantime we preserve the
  461 # order of fields in the 'index' field.
  462 Typeinfo-entry-input-var:  # (handle var)
  463   0/imm32
  464 Typeinfo-entry-index:  # int
  465   8/imm32
  466 Typeinfo-entry-output-var:  # (handle var)
  467   0xc/imm32
  468 Typeinfo-entry-size:  # (addr int)
  469   0x14/imm32
  470 
  471 == code
  472 
  473 Entry:
  474     # . prologue
  475     89/<- %ebp 4/r32/esp
  476     (new-segment *Heap-size Heap)
  477     # if (argv[1] == "test') run-tests()
  478     {
  479       # if (argc <= 1) break
  480       81 7/subop/compare *ebp 1/imm32
  481       7e/jump-if-<= break/disp8
  482       # if (argv[1] != "test") break
  483       (kernel-string-equal? *(ebp+8) "test")  # => eax
  484       3d/compare-eax-and 0/imm32/false
  485       74/jump-if-= break/disp8
  486       #
  487       (run-tests)
  488       # syscall(exit, *Num-test-failures)
  489       8b/-> *Num-test-failures 3/r32/ebx
  490       eb/jump $mu-main:end/disp8
  491     }
  492     # otherwise convert Stdin
  493     (convert-mu Stdin Stdout Stderr 0)
  494     (flush Stdout)
  495     # syscall(exit, 0)
  496     bb/copy-to-ebx 0/imm32
  497 $mu-main:end:
  498     e8/call syscall_exit/disp32
  499 
  500 convert-mu:  # in: (addr buffered-file), out: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
  501     # . prologue
  502     55/push-ebp
  503     89/<- %ebp 4/r32/esp
  504     # . save registers
  505     50/push-eax
  506     # initialize global data structures
  507     c7 0/subop/copy *Next-block-index 1/imm32
  508     8b/-> *Primitive-type-ids 0/r32/eax
  509     89/<- *Type-id 0/r32/eax  # stream-write
  510     c7 0/subop/copy *_Program-functions 0/imm32
  511     c7 0/subop/copy *_Program-functions->payload 0/imm32
  512     c7 0/subop/copy *_Program-types 0/imm32
  513     c7 0/subop/copy *_Program-types->payload 0/imm32
  514     c7 0/subop/copy *_Program-signatures 0/imm32
  515     c7 0/subop/copy *_Program-signatures->payload 0/imm32
  516     #
  517     (parse-mu *(ebp+8) *(ebp+0x10) *(ebp+0x14))
  518     (populate-mu-type-sizes *(ebp+0x10) *(ebp+0x14))
  519 #?     (dump-typeinfos "=== typeinfos\n")
  520     (check-mu-types *(ebp+0x10) *(ebp+0x14))
  521     (emit-subx *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
  522 $convert-mu:end:
  523     # . restore registers
  524     58/pop-to-eax
  525     # . epilogue
  526     89/<- %esp 5/r32/ebp
  527     5d/pop-to-ebp
  528     c3/return
  529 
  530 test-convert-empty-input:
  531     # empty input => empty output
  532     # . prologue
  533     55/push-ebp
  534     89/<- %ebp 4/r32/esp
  535     # setup
  536     (clear-stream _test-input-stream)
  537     (clear-stream $_test-input-buffered-file->buffer)
  538     (clear-stream _test-output-stream)
  539     (clear-stream $_test-output-buffered-file->buffer)
  540     #
  541     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  542     (flush _test-output-buffered-file)
  543     (check-stream-equal _test-output-stream "" "F - test-convert-empty-input")
  544     # . epilogue
  545     89/<- %esp 5/r32/ebp
  546     5d/pop-to-ebp
  547     c3/return
  548 
  549 test-convert-function-skeleton:
  550     # . prologue
  551     55/push-ebp
  552     89/<- %ebp 4/r32/esp
  553     # setup
  554     (clear-stream _test-input-stream)
  555     (clear-stream $_test-input-buffered-file->buffer)
  556     (clear-stream _test-output-stream)
  557     (clear-stream $_test-output-buffered-file->buffer)
  558     #
  559     (write _test-input-stream "fn foo {\n")
  560     (write _test-input-stream "}\n")
  561     # convert
  562     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  563     (flush _test-output-buffered-file)
  564 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
  570     # check output
  571     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-skeleton/0")
  572     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-skeleton/1")
  573     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-skeleton/2")
  574     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-skeleton/3")
  575     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-skeleton/4")
  576     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-skeleton/5")
  577     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-skeleton/6")
  578     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-skeleton/7")
  579     # . epilogue
  580     89/<- %esp 5/r32/ebp
  581     5d/pop-to-ebp
  582     c3/return
  583 
  584 test-convert-multiple-function-skeletons:
  585     # . prologue
  586     55/push-ebp
  587     89/<- %ebp 4/r32/esp
  588     # setup
  589     (clear-stream _test-input-stream)
  590     (clear-stream $_test-input-buffered-file->buffer)
  591     (clear-stream _test-output-stream)
  592     (clear-stream $_test-output-buffered-file->buffer)
  593     #
  594     (write _test-input-stream "fn foo {\n")
  595     (write _test-input-stream "}\n")
  596     (write _test-input-stream "fn bar {\n")
  597     (write _test-input-stream "}\n")
  598     # convert
  599     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  600     (flush _test-output-buffered-file)
  601 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
  607     # check first function
  608     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-multiple-function-skeletons/0")
  609     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-multiple-function-skeletons/1")
  610     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-multiple-function-skeletons/2")
  611     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-multiple-function-skeletons/3")
  612     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-multiple-function-skeletons/4")
  613     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-multiple-function-skeletons/5")
  614     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-multiple-function-skeletons/6")
  615     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-multiple-function-skeletons/7")
  616     # check second function
  617     (check-next-stream-line-equal _test-output-stream "bar:"                    "F - test-convert-multiple-function-skeletons/10")
  618     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-multiple-function-skeletons/11")
  619     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-multiple-function-skeletons/12")
  620     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-multiple-function-skeletons/13")
  621     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-multiple-function-skeletons/14")
  622     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-multiple-function-skeletons/15")
  623     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-multiple-function-skeletons/16")
  624     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-multiple-function-skeletons/17")
  625     # . epilogue
  626     89/<- %esp 5/r32/ebp
  627     5d/pop-to-ebp
  628     c3/return
  629 
  630 test-convert-function-with-arg:
  631     # . prologue
  632     55/push-ebp
  633     89/<- %ebp 4/r32/esp
  634     # setup
  635     (clear-stream _test-input-stream)
  636     (clear-stream $_test-input-buffered-file->buffer)
  637     (clear-stream _test-output-stream)
  638     (clear-stream $_test-output-buffered-file->buffer)
  639     #
  640     (write _test-input-stream "fn foo n: int {\n")
  641     (write _test-input-stream "}\n")
  642     # convert
  643     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  644     (flush _test-output-buffered-file)
  645 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
  651     # check output
  652     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-arg/0")
  653     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-arg/1")
  654     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-arg/2")
  655     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-arg/3")
  656     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-arg/4")
  657     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-arg/5")
  658     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-arg/6")
  659     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-arg/7")
  660     # . epilogue
  661     89/<- %esp 5/r32/ebp
  662     5d/pop-to-ebp
  663     c3/return
  664 
  665 test-convert-function-with-arg-and-body:
  666     # . prologue
  667     55/push-ebp
  668     89/<- %ebp 4/r32/esp
  669     # setup
  670     (clear-stream _test-input-stream)
  671     (clear-stream $_test-input-buffered-file->buffer)
  672     (clear-stream _test-output-stream)
  673     (clear-stream $_test-output-buffered-file->buffer)
  674     #
  675     (write _test-input-stream "fn foo n: int {\n")
  676     (write _test-input-stream "  increment n\n")
  677     (write _test-input-stream "}\n")
  678     # convert
  679     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  680     (flush _test-output-buffered-file)
  681 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
  687     # check output
  688     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-arg-and-body/0")
  689     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-arg-and-body/1")
  690     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-arg-and-body/2")
  691     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-arg-and-body/3")
  692     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-arg-and-body/4")
  693     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-arg-and-body/5")
  694     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-arg-and-body/6")
  695     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-arg-and-body/7")
  696     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-arg-and-body/8")
  697     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-arg-and-body/9")
  698     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-arg-and-body/10")
  699     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-arg-and-body/11")
  700     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-arg-and-body/12")
  701     # . epilogue
  702     89/<- %esp 5/r32/ebp
  703     5d/pop-to-ebp
  704     c3/return
  705 
  706 test-convert-function-distinguishes-args:
  707     # . prologue
  708     55/push-ebp
  709     89/<- %ebp 4/r32/esp
  710     # setup
  711     (clear-stream _test-input-stream)
  712     (clear-stream $_test-input-buffered-file->buffer)
  713     (clear-stream _test-output-stream)
  714     (clear-stream $_test-output-buffered-file->buffer)
  715     #
  716     (write _test-input-stream "fn foo a: int, b: int {\n")
  717     (write _test-input-stream "  increment b\n")
  718     (write _test-input-stream "}\n")
  719     # convert
  720     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  721     (flush _test-output-buffered-file)
  722 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
  728     # check output
  729     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-distinguishes-args/0")
  730     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-distinguishes-args/1")
  731     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-distinguishes-args/2")
  732     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-distinguishes-args/3")
  733     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-distinguishes-args/4")
  734     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-distinguishes-args/5")
  735     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0x0000000c)"  "F - test-convert-function-distinguishes-args/6")
  736     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-distinguishes-args/7")
  737     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-distinguishes-args/8")
  738     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-distinguishes-args/9")
  739     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-distinguishes-args/10")
  740     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-distinguishes-args/11")
  741     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-distinguishes-args/12")
  742     # . epilogue
  743     89/<- %esp 5/r32/ebp
  744     5d/pop-to-ebp
  745     c3/return
  746 
  747 test-convert-function-returns-result:
  748     # . prologue
  749     55/push-ebp
  750     89/<- %ebp 4/r32/esp
  751     # setup
  752     (clear-stream _test-input-stream)
  753     (clear-stream $_test-input-buffered-file->buffer)
  754     (clear-stream _test-output-stream)
  755     (clear-stream $_test-output-buffered-file->buffer)
  756     #
  757     (write _test-input-stream "fn foo a: int, b: int -> result/eax: int {\n")
  758     (write _test-input-stream "  result <- copy a\n")
  759     (write _test-input-stream "  result <- increment\n")
  760     (write _test-input-stream "}\n")
  761     # convert
  762     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  763     (flush _test-output-buffered-file)
  764 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
  770     # check output
  771     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-returns-result/0")
  772     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-returns-result/1")
  773     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-returns-result/2")
  774     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-returns-result/3")
  775     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-returns-result/4")
  776     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-returns-result/5")
  777     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-returns-result/6")
  778     (check-next-stream-line-equal _test-output-stream "    40/increment-eax"    "F - test-convert-function-returns-result/7")
  779     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-returns-result/8")
  780     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-returns-result/9")
  781     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-returns-result/10")
  782     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-returns-result/11")
  783     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-returns-result/12")
  784     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-returns-result/13")
  785     # . epilogue
  786     89/<- %esp 5/r32/ebp
  787     5d/pop-to-ebp
  788     c3/return
  789 
  790 test-convert-function-with-literal-arg:
  791     # . prologue
  792     55/push-ebp
  793     89/<- %ebp 4/r32/esp
  794     # setup
  795     (clear-stream _test-input-stream)
  796     (clear-stream $_test-input-buffered-file->buffer)
  797     (clear-stream _test-output-stream)
  798     (clear-stream $_test-output-buffered-file->buffer)
  799     #
  800     (write _test-input-stream "fn foo a: int, b: int -> result/eax: int {\n")
  801     (write _test-input-stream "  result <- copy a\n")
  802     (write _test-input-stream "  result <- add 1\n")
  803     (write _test-input-stream "}\n")
  804     # convert
  805     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  806     (flush _test-output-buffered-file)
  807 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
  813     # check output
  814     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-literal-arg/0")
  815     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-literal-arg/1")
  816     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-literal-arg/2")
  817     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-literal-arg/3")
  818     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-literal-arg/4")
  819     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-literal-arg/5")
  820     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-with-literal-arg/6")
  821     (check-next-stream-line-equal _test-output-stream "    05/add-to-eax 1/imm32"  "F - test-convert-function-with-literal-arg/7")
  822     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-literal-arg/8")
  823     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-literal-arg/9")
  824     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-literal-arg/10")
  825     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-literal-arg/11")
  826     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-literal-arg/12")
  827     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-literal-arg/13")
  828     # . epilogue
  829     89/<- %esp 5/r32/ebp
  830     5d/pop-to-ebp
  831     c3/return
  832 
  833 test-convert-function-with-literal-arg-2:
  834     # . prologue
  835     55/push-ebp
  836     89/<- %ebp 4/r32/esp
  837     # setup
  838     (clear-stream _test-input-stream)
  839     (clear-stream $_test-input-buffered-file->buffer)
  840     (clear-stream _test-output-stream)
  841     (clear-stream $_test-output-buffered-file->buffer)
  842     #
  843     (write _test-input-stream "fn foo a: int, b: int -> result/ebx: int {\n")
  844     (write _test-input-stream "  result <- copy a\n")
  845     (write _test-input-stream "  result <- add 1\n")
  846     (write _test-input-stream "}\n")
  847     # convert
  848     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  849     (flush _test-output-buffered-file)
  850 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
  856     # check output
  857     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-literal-arg-2/0")
  858     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-literal-arg-2/1")
  859     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-literal-arg-2/2")
  860     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-literal-arg-2/3")
  861     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-literal-arg-2/4")
  862     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-literal-arg-2/5")
  863     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000003/r32"  "F - test-convert-function-with-literal-arg-2/6")
  864     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %ebx 1/imm32"  "F - test-convert-function-with-literal-arg-2/7")
  865     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-literal-arg-2/8")
  866     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-literal-arg-2/9")
  867     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-literal-arg-2/10")
  868     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-literal-arg-2/11")
  869     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-literal-arg-2/12")
  870     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-literal-arg-2/13")
  871     # . epilogue
  872     89/<- %esp 5/r32/ebp
  873     5d/pop-to-ebp
  874     c3/return
  875 
  876 test-convert-function-call-with-literal-arg:
  877     # . prologue
  878     55/push-ebp
  879     89/<- %ebp 4/r32/esp
  880     # setup
  881     (clear-stream _test-input-stream)
  882     (clear-stream $_test-input-buffered-file->buffer)
  883     (clear-stream _test-output-stream)
  884     (clear-stream $_test-output-buffered-file->buffer)
  885     #
  886     (write _test-input-stream "fn main -> result/ebx: int {\n")
  887     (write _test-input-stream "  result <- do-add 3 4\n")
  888     (write _test-input-stream "}\n")
  889     (write _test-input-stream "fn do-add a: int, b: int -> result/ebx: int {\n")
  890     (write _test-input-stream "  result <- copy a\n")
  891     (write _test-input-stream "  result <- add b\n")
  892     (write _test-input-stream "}\n")
  893     # convert
  894     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  895     (flush _test-output-buffered-file)
  896 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
  902     # check output
  903     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call-with-literal-arg/0")
  904     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-literal-arg/1")
  905     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-literal-arg/2")
  906     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-literal-arg/3")
  907     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-literal-arg/4")
  908     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call-with-literal-arg/5")
  909     (check-next-stream-line-equal _test-output-stream "    (do-add 3 4)"        "F - test-convert-function-call-with-literal-arg/6")
  910     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-literal-arg/7")
  911     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call-with-literal-arg/8")
  912     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-literal-arg/9")
  913     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-literal-arg/10")
  914     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-literal-arg/11")
  915     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-literal-arg/12")
  916     (check-next-stream-line-equal _test-output-stream "do-add:"                 "F - test-convert-function-call-with-literal-arg/13")
  917     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-literal-arg/14")
  918     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-literal-arg/15")
  919     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-literal-arg/16")
  920     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-literal-arg/17")
  921     (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:loop:"  "F - test-convert-function-call-with-literal-arg/18")
  922     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000003/r32"  "F - test-convert-function-call-with-literal-arg/19")
  923     (check-next-stream-line-equal _test-output-stream "    03/add *(ebp+0x0000000c) 0x00000003/r32"  "F - test-convert-function-call-with-literal-arg/20")
  924     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-literal-arg/21")
  925     (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:break:"  "F - test-convert-function-call-with-literal-arg/22")
  926     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-literal-arg/23")
  927     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-literal-arg/24")
  928     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-literal-arg/25")
  929     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-literal-arg/26")
  930     # . epilogue
  931     89/<- %esp 5/r32/ebp
  932     5d/pop-to-ebp
  933     c3/return
  934 
  935 test-convert-function-call-with-signature:
  936     # . prologue
  937     55/push-ebp
  938     89/<- %ebp 4/r32/esp
  939     # setup
  940     (clear-stream _test-input-stream)
  941     (clear-stream $_test-input-buffered-file->buffer)
  942     (clear-stream _test-output-stream)
  943     (clear-stream $_test-output-buffered-file->buffer)
  944     #
  945     (write _test-input-stream "fn main -> result/ebx: int {\n")
  946     (write _test-input-stream "  result <- do-add 3 4\n")
  947     (write _test-input-stream "}\n")
  948     (write _test-input-stream "sig do-add a: int, b: int -> result/ebx: int\n")
  949     # convert
  950     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  951     (flush _test-output-buffered-file)
  952 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
  958     # check output
  959     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call-with-signature/0")
  960     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-signature/1")
  961     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-signature/2")
  962     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-signature/3")
  963     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-signature/4")
  964     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call-with-signature/5")
  965     (check-next-stream-line-equal _test-output-stream "    (do-add 3 4)"        "F - test-convert-function-call-with-signature/6")
  966     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-signature/7")
  967     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call-with-signature/8")
  968     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-signature/9")
  969     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-signature/10")
  970     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-signature/11")
  971     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-signature/12")
  972     # . epilogue
  973     89/<- %esp 5/r32/ebp
  974     5d/pop-to-ebp
  975     c3/return
  976 
  977 test-convert-function-with-local-var-in-mem:
  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     #
  987     (write _test-input-stream "fn foo {\n")
  988     (write _test-input-stream "  var x: int\n")
  989     (write _test-input-stream "  increment x\n")
  990     (write _test-input-stream "}\n")
  991     # convert
  992     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  993     (flush _test-output-buffered-file)
  994 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1000     # check output
 1001     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-mem/0")
 1002     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-mem/1")
 1003     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-mem/2")
 1004     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-mem/3")
 1005     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-mem/4")
 1006     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-mem/5")
 1007     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-in-mem/6")
 1008     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-local-var-in-mem/7")
 1009     (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")
 1010     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-mem/9")
 1011     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-mem/10")
 1012     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-mem/11")
 1013     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-mem/12")
 1014     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-mem/13")
 1015     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-mem/14")
 1016     # . epilogue
 1017     89/<- %esp 5/r32/ebp
 1018     5d/pop-to-ebp
 1019     c3/return
 1020 
 1021 test-convert-invalid-literal:
 1022     # . prologue
 1023     55/push-ebp
 1024     89/<- %ebp 4/r32/esp
 1025     # setup
 1026     (clear-stream _test-input-stream)
 1027     (clear-stream $_test-input-buffered-file->buffer)
 1028     (clear-stream _test-output-stream)
 1029     (clear-stream $_test-output-buffered-file->buffer)
 1030     (clear-stream _test-error-stream)
 1031     (clear-stream $_test-error-buffered-file->buffer)
 1032     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1033     68/push 0/imm32
 1034     68/push 0/imm32
 1035     89/<- %edx 4/r32/esp
 1036     (tailor-exit-descriptor %edx 0x10)
 1037     #
 1038     (write _test-input-stream "fn foo {\n")
 1039     (write _test-input-stream "  increment 1n\n")
 1040     (write _test-input-stream "}\n")
 1041     # convert
 1042     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1043     # registers except esp clobbered at this point
 1044     # restore ed
 1045     89/<- %edx 4/r32/esp
 1046     (flush _test-output-buffered-file)
 1047     (flush _test-error-buffered-file)
 1048 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1054     # check output
 1055     (check-stream-equal _test-output-stream  ""  "F - test-convert-invalid-literal: output should be empty")
 1056     (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")
 1057     # check that stop(1) was called
 1058     (check-ints-equal *(edx+4) 2 "F - test-convert-invalid-literal: exit status")
 1059     # don't restore from ebp
 1060     81 0/subop/add %esp 8/imm32
 1061     # . epilogue
 1062     5d/pop-to-ebp
 1063     c3/return
 1064 
 1065 test-local-var-in-mem-has-no-initializer:
 1066     # . prologue
 1067     55/push-ebp
 1068     89/<- %ebp 4/r32/esp
 1069     # setup
 1070     (clear-stream _test-input-stream)
 1071     (clear-stream $_test-input-buffered-file->buffer)
 1072     (clear-stream _test-output-stream)
 1073     (clear-stream $_test-output-buffered-file->buffer)
 1074     (clear-stream _test-error-stream)
 1075     (clear-stream $_test-error-buffered-file->buffer)
 1076     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1077     68/push 0/imm32
 1078     68/push 0/imm32
 1079     89/<- %edx 4/r32/esp
 1080     (tailor-exit-descriptor %edx 0x10)
 1081     #
 1082     (write _test-input-stream "fn foo {\n")
 1083     (write _test-input-stream "  var x: int <- copy 0\n")
 1084     (write _test-input-stream "  increment x\n")
 1085     (write _test-input-stream "}\n")
 1086     # convert
 1087     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1088     # registers except esp clobbered at this point
 1089     # restore ed
 1090     89/<- %edx 4/r32/esp
 1091     (flush _test-output-buffered-file)
 1092     (flush _test-error-buffered-file)
 1093 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1099     # check output
 1100     (check-stream-equal _test-output-stream  ""  "F - test-var-in-mem-has-no-initializer: output should be empty")
 1101     (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")
 1102     # check that stop(1) was called
 1103     (check-ints-equal *(edx+4) 2 "F - test-var-in-mem-has-no-initializer: exit status")
 1104     # don't restore from ebp
 1105     81 0/subop/add %esp 8/imm32
 1106     # . epilogue
 1107     5d/pop-to-ebp
 1108     c3/return
 1109 
 1110 test-convert-function-with-local-var-with-compound-type-in-mem:
 1111     # . prologue
 1112     55/push-ebp
 1113     89/<- %ebp 4/r32/esp
 1114     # setup
 1115     (clear-stream _test-input-stream)
 1116     (clear-stream $_test-input-buffered-file->buffer)
 1117     (clear-stream _test-output-stream)
 1118     (clear-stream $_test-output-buffered-file->buffer)
 1119     #
 1120     (write _test-input-stream "fn foo {\n")
 1121     (write _test-input-stream "  var x: (addr int)\n")
 1122     (write _test-input-stream "  copy-to x, 0\n")
 1123     (write _test-input-stream "}\n")
 1124     # convert
 1125     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1126     (flush _test-output-buffered-file)
 1127 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1133     # check output
 1134     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-with-compound-type-in-mem/0")
 1135     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-with-compound-type-in-mem/1")
 1136     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-with-compound-type-in-mem/2")
 1137     (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")
 1138     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-compound-type-in-mem/4")
 1139     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-with-compound-type-in-mem/5")
 1140     (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")
 1141     (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")
 1142     (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")
 1143     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-compound-type-in-mem/9")
 1144     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-with-compound-type-in-mem/10")
 1145     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-with-compound-type-in-mem/11")
 1146     (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")
 1147     (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")
 1148     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-with-compound-type-in-mem/14")
 1149     # . epilogue
 1150     89/<- %esp 5/r32/ebp
 1151     5d/pop-to-ebp
 1152     c3/return
 1153 
 1154 test-convert-function-with-local-var-in-reg:
 1155     # . prologue
 1156     55/push-ebp
 1157     89/<- %ebp 4/r32/esp
 1158     # setup
 1159     (clear-stream _test-input-stream)
 1160     (clear-stream $_test-input-buffered-file->buffer)
 1161     (clear-stream _test-output-stream)
 1162     (clear-stream $_test-output-buffered-file->buffer)
 1163     #
 1164     (write _test-input-stream "fn foo {\n")
 1165     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 1166     (write _test-input-stream "  x <- increment\n")
 1167     (write _test-input-stream "}\n")
 1168     # convert
 1169     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1170     (flush _test-output-buffered-file)
 1171 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1177     # check output
 1178     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-reg/0")
 1179     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-reg/1")
 1180     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-reg/2")
 1181     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-reg/3")
 1182     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-reg/4")
 1183     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-reg/5")
 1184     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-in-reg/6")
 1185     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-convert-function-with-local-var-in-reg/7")
 1186     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-convert-function-with-local-var-in-reg/8")
 1187     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-in-reg/9")
 1188     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-reg/10")
 1189     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-reg/11")
 1190     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-reg/12")
 1191     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-reg/13")
 1192     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-reg/14")
 1193     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-reg/15")
 1194     # . epilogue
 1195     89/<- %esp 5/r32/ebp
 1196     5d/pop-to-ebp
 1197     c3/return
 1198 
 1199 test-convert-function-with-allocate:
 1200     # . prologue
 1201     55/push-ebp
 1202     89/<- %ebp 4/r32/esp
 1203     # setup
 1204     (clear-stream _test-input-stream)
 1205     (clear-stream $_test-input-buffered-file->buffer)
 1206     (clear-stream _test-output-stream)
 1207     (clear-stream $_test-output-buffered-file->buffer)
 1208     #
 1209     (write _test-input-stream "fn foo {\n")
 1210     (write _test-input-stream "  var x/ecx: (addr handle int) <- copy 0\n")
 1211     (write _test-input-stream "  allocate x\n")
 1212     (write _test-input-stream "}\n")
 1213     # convert
 1214     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1215     (flush _test-output-buffered-file)
 1216 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1222     # check output
 1223     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-allocate/0")
 1224     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-allocate/1")
 1225     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-allocate/2")
 1226     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-allocate/3")
 1227     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-allocate/4")
 1228     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-allocate/5")
 1229     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-allocate/6")
 1230     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-allocate/7")
 1231     (check-next-stream-line-equal _test-output-stream "    (allocate Heap 0x00000004 %ecx)"  "F - test-convert-function-with-allocate/8")  # 4 = size-of(int)
 1232     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-allocate/9")
 1233     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-allocate/10")
 1234     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-allocate/11")
 1235     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-allocate/12")
 1236     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-allocate/13")
 1237     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-allocate/14")
 1238     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-allocate/15")
 1239     # . epilogue
 1240     89/<- %esp 5/r32/ebp
 1241     5d/pop-to-ebp
 1242     c3/return
 1243 
 1244 test-initializer-in-hex:
 1245     # . prologue
 1246     55/push-ebp
 1247     89/<- %ebp 4/r32/esp
 1248     # setup
 1249     (clear-stream _test-input-stream)
 1250     (clear-stream $_test-input-buffered-file->buffer)
 1251     (clear-stream _test-output-stream)
 1252     (clear-stream $_test-output-buffered-file->buffer)
 1253     (clear-stream _test-error-stream)
 1254     (clear-stream $_test-error-buffered-file->buffer)
 1255     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1256     68/push 0/imm32
 1257     68/push 0/imm32
 1258     89/<- %edx 4/r32/esp
 1259     (tailor-exit-descriptor %edx 0x10)
 1260     #
 1261     (write _test-input-stream "fn foo {\n")
 1262     (write _test-input-stream "  var x/ecx: int <- copy 10\n")
 1263     (write _test-input-stream "}\n")
 1264     # convert
 1265     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1266     # registers except esp clobbered at this point
 1267     # restore ed
 1268     89/<- %edx 4/r32/esp
 1269     (flush _test-output-buffered-file)
 1270     (flush _test-error-buffered-file)
 1271 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1277     # check output
 1278     (check-stream-equal _test-output-stream  ""  "F - test-initializer-in-hex: output should be empty")
 1279     (check-next-stream-line-equal _test-error-stream  "literal integers are always hex in Mu; either start '10' with a '0x' to be unambiguous, or convert it to decimal."  "F - test-initializer-in-hex: error message")
 1280     # check that stop(1) was called
 1281     (check-ints-equal *(edx+4) 2 "F - test-initializer-in-hex: exit status")
 1282     # don't restore from ebp
 1283     81 0/subop/add %esp 8/imm32
 1284     # . epilogue
 1285     5d/pop-to-ebp
 1286     c3/return
 1287 
 1288 test-convert-function-with-second-local-var-in-same-reg:
 1289     # . prologue
 1290     55/push-ebp
 1291     89/<- %ebp 4/r32/esp
 1292     # setup
 1293     (clear-stream _test-input-stream)
 1294     (clear-stream $_test-input-buffered-file->buffer)
 1295     (clear-stream _test-output-stream)
 1296     (clear-stream $_test-output-buffered-file->buffer)
 1297     #
 1298     (write _test-input-stream "fn foo {\n")
 1299     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 1300     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 1301     (write _test-input-stream "  y <- increment\n")
 1302     (write _test-input-stream "}\n")
 1303     # convert
 1304     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1305     (flush _test-output-buffered-file)
 1306 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1312     # check output
 1313     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-second-local-var-in-same-reg/0")
 1314     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-second-local-var-in-same-reg/1")
 1315     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-second-local-var-in-same-reg/2")
 1316     (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")
 1317     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-second-local-var-in-same-reg/4")
 1318     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-second-local-var-in-same-reg/5")
 1319     (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")
 1320     (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")
 1321     (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")
 1322     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-convert-function-with-second-local-var-in-same-reg/9")
 1323     (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")
 1324     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-second-local-var-in-same-reg/11")
 1325     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-second-local-var-in-same-reg/12")
 1326     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-second-local-var-in-same-reg/13")
 1327     (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")
 1328     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-second-local-var-in-same-reg/15")
 1329     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-second-local-var-in-same-reg/16")
 1330     # . epilogue
 1331     89/<- %esp 5/r32/ebp
 1332     5d/pop-to-ebp
 1333     c3/return
 1334 
 1335 test-read-clobbered-reg-var:
 1336     # . prologue
 1337     55/push-ebp
 1338     89/<- %ebp 4/r32/esp
 1339     # setup
 1340     (clear-stream _test-input-stream)
 1341     (clear-stream $_test-input-buffered-file->buffer)
 1342     (clear-stream _test-output-stream)
 1343     (clear-stream $_test-output-buffered-file->buffer)
 1344     (clear-stream _test-error-stream)
 1345     (clear-stream $_test-error-buffered-file->buffer)
 1346     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
 1347     68/push 0/imm32
 1348     68/push 0/imm32
 1349     89/<- %edx 4/r32/esp
 1350     (tailor-exit-descriptor %edx 0x10)
 1351     #
 1352     (write _test-input-stream "fn foo {\n")
 1353     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 1354     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 1355     (write _test-input-stream "  x <- increment\n")
 1356     (write _test-input-stream "}\n")
 1357     # convert
 1358     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1359     # registers except esp clobbered at this point
 1360     # restore ed
 1361     89/<- %edx 4/r32/esp
 1362     (flush _test-output-buffered-file)
 1363     (flush _test-error-buffered-file)
 1364 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1370     # check output
 1371     (check-stream-equal _test-output-stream  ""  "F - test-read-clobbered-reg-var: output should be empty")
 1372     (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")
 1373     # check that stop(1) was called
 1374     (check-ints-equal *(edx+4) 2 "F - test-read-clobbered-reg-var: exit status")
 1375     # don't restore from ebp
 1376     81 0/subop/add %esp 8/imm32
 1377     # . epilogue
 1378     5d/pop-to-ebp
 1379     c3/return
 1380 
 1381 test-convert-function-call:
 1382     # . prologue
 1383     55/push-ebp
 1384     89/<- %ebp 4/r32/esp
 1385     # setup
 1386     (clear-stream _test-input-stream)
 1387     (clear-stream $_test-input-buffered-file->buffer)
 1388     (clear-stream _test-output-stream)
 1389     (clear-stream $_test-output-buffered-file->buffer)
 1390     #
 1391     (write _test-input-stream "fn main -> result/ebx: int {\n")
 1392     (write _test-input-stream "  result <- foo\n")
 1393     (write _test-input-stream "}\n")
 1394     (write _test-input-stream "fn foo -> result/ebx: int {\n")
 1395     (write _test-input-stream "  result <- copy 3\n")
 1396     (write _test-input-stream "}\n")
 1397     # convert
 1398     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1399     (flush _test-output-buffered-file)
 1400 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1406     # check output
 1407     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call/0")
 1408     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call/1")
 1409     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call/2")
 1410     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call/3")
 1411     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call/4")
 1412     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call/5")
 1413     (check-next-stream-line-equal _test-output-stream "    (foo)"               "F - test-convert-function-call/6")
 1414     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call/7")
 1415     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call/8")
 1416     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call/9")
 1417     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call/10")
 1418     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call/11")
 1419     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call/12")
 1420     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call/13")
 1421     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call/14")
 1422     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call/15")
 1423     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call/16")
 1424     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call/17")
 1425     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"  "F - test-convert-function-call/18")
 1426     (check-next-stream-line-equal _test-output-stream "    bb/copy-to-ebx 3/imm32"  "F - test-convert-function-call/19")
 1427     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call/20")
 1428     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-call/21")
 1429     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call/22")
 1430     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call/23")
 1431     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call/24")
 1432     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call/25")
 1433     # . epilogue
 1434     89/<- %esp 5/r32/ebp
 1435     5d/pop-to-ebp
 1436     c3/return
 1437 
 1438 test-convert-function-call-with-inout-with-compound-type:
 1439     # . prologue
 1440     55/push-ebp
 1441     89/<- %ebp 4/r32/esp
 1442     # setup
 1443     (clear-stream _test-input-stream)
 1444     (clear-stream $_test-input-buffered-file->buffer)
 1445     (clear-stream _test-output-stream)
 1446     (clear-stream $_test-output-buffered-file->buffer)
 1447     #
 1448     (write _test-input-stream "fn f {\n")
 1449     (write _test-input-stream "  var x: (addr int)\n")
 1450     (write _test-input-stream "  g x\n")
 1451     (write _test-input-stream "}\n")
 1452     (write _test-input-stream "fn g a: (addr int) {\n")
 1453     (write _test-input-stream "}\n")
 1454     # convert
 1455     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1456     (flush _test-output-buffered-file)
 1457 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1463     # check output
 1464     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-inout-with-compound-type/0")
 1465     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-inout-with-compound-type/1")
 1466     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-inout-with-compound-type/2")
 1467     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-inout-with-compound-type/3")
 1468     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-inout-with-compound-type/4")
 1469     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-inout-with-compound-type/5")
 1470     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-inout-with-compound-type/6")
 1471     (check-next-stream-line-equal _test-output-stream "    (g *(ebp+0xfffffffc))"  "F - test-convert-function-call-with-inout-with-compound-type/7")
 1472     (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")
 1473     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-inout-with-compound-type/9")
 1474     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-inout-with-compound-type/10")
 1475     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-inout-with-compound-type/11")
 1476     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-inout-with-compound-type/12")
 1477     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-inout-with-compound-type/13")
 1478     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-inout-with-compound-type/14")
 1479     (check-next-stream-line-equal _test-output-stream "g:"                      "F - test-convert-function-call-with-inout-with-compound-type/15")
 1480     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-inout-with-compound-type/16")
 1481     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-inout-with-compound-type/17")
 1482     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-inout-with-compound-type/18")
 1483     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-inout-with-compound-type/19")
 1484     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-inout-with-compound-type/20")
 1485     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-inout-with-compound-type/21")
 1486     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-inout-with-compound-type/22")
 1487     # . epilogue
 1488     89/<- %esp 5/r32/ebp
 1489     5d/pop-to-ebp
 1490     c3/return
 1491 
 1492 test-convert-function-call-with-inout-with-type-parameter:
 1493     # . prologue
 1494     55/push-ebp
 1495     89/<- %ebp 4/r32/esp
 1496     # setup
 1497     (clear-stream _test-input-stream)
 1498     (clear-stream $_test-input-buffered-file->buffer)
 1499     (clear-stream _test-output-stream)
 1500     (clear-stream $_test-output-buffered-file->buffer)
 1501     (clear-stream _test-error-stream)
 1502     (clear-stream $_test-error-buffered-file->buffer)
 1503     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1504     68/push 0/imm32
 1505     68/push 0/imm32
 1506     89/<- %edx 4/r32/esp
 1507     (tailor-exit-descriptor %edx 0x10)
 1508     #
 1509     (write _test-input-stream "fn f {\n")
 1510     (write _test-input-stream "  var x: (addr int)\n")
 1511     (write _test-input-stream "  g x\n")
 1512     (write _test-input-stream "}\n")
 1513     (write _test-input-stream "fn g a: (addr _) {\n")
 1514     (write _test-input-stream "}\n")
 1515     # convert
 1516     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1517     # registers except esp clobbered at this point
 1518     # restore ed
 1519     89/<- %edx 4/r32/esp
 1520     (flush _test-output-buffered-file)
 1521     (flush _test-error-buffered-file)
 1522 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1528     # no error; types matched
 1529     (check-stream-equal _test-error-stream  ""  "F - test-convert-function-call-with-inout-with-type-parameter: error stream should be empty")
 1530     # don't bother checking the generated code; that's in the test 'test-local-clobbered-by-fn-output' below
 1531     # don't restore from ebp
 1532     81 0/subop/add %esp 8/imm32
 1533     # . epilogue
 1534     5d/pop-to-ebp
 1535     c3/return
 1536 
 1537 test-convert-function-call-with-incorrect-inout-type:
 1538     # . prologue
 1539     55/push-ebp
 1540     89/<- %ebp 4/r32/esp
 1541     # setup
 1542     (clear-stream _test-input-stream)
 1543     (clear-stream $_test-input-buffered-file->buffer)
 1544     (clear-stream _test-output-stream)
 1545     (clear-stream $_test-output-buffered-file->buffer)
 1546     (clear-stream _test-error-stream)
 1547     (clear-stream $_test-error-buffered-file->buffer)
 1548     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1549     68/push 0/imm32
 1550     68/push 0/imm32
 1551     89/<- %edx 4/r32/esp
 1552     (tailor-exit-descriptor %edx 0x10)
 1553     #
 1554     (write _test-input-stream "fn f {\n")
 1555     (write _test-input-stream "  var x: int\n")
 1556     (write _test-input-stream "  g x\n")
 1557     (write _test-input-stream "}\n")
 1558     (write _test-input-stream "fn g a: foo {\n")
 1559     (write _test-input-stream "}\n")
 1560     # convert
 1561     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1562     # registers except esp clobbered at this point
 1563     # restore ed
 1564     89/<- %edx 4/r32/esp
 1565     (flush _test-output-buffered-file)
 1566     (flush _test-error-buffered-file)
 1567 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1573     # check output
 1574     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-inout-type: output should be empty")
 1575     (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")
 1576     # check that stop(1) was called
 1577     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-inout-type: exit status")
 1578     # don't restore from ebp
 1579     81 0/subop/add %esp 8/imm32
 1580     5d/pop-to-ebp
 1581     c3/return
 1582 
 1583 test-convert-function-call-with-inout-with-incorrect-compound-type:
 1584     # . prologue
 1585     55/push-ebp
 1586     89/<- %ebp 4/r32/esp
 1587     # setup
 1588     (clear-stream _test-input-stream)
 1589     (clear-stream $_test-input-buffered-file->buffer)
 1590     (clear-stream _test-output-stream)
 1591     (clear-stream $_test-output-buffered-file->buffer)
 1592     (clear-stream _test-error-stream)
 1593     (clear-stream $_test-error-buffered-file->buffer)
 1594     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1595     68/push 0/imm32
 1596     68/push 0/imm32
 1597     89/<- %edx 4/r32/esp
 1598     (tailor-exit-descriptor %edx 0x10)
 1599     #
 1600     (write _test-input-stream "fn f {\n")
 1601     (write _test-input-stream "  var x: (addr int)\n")
 1602     (write _test-input-stream "  g x\n")
 1603     (write _test-input-stream "}\n")
 1604     (write _test-input-stream "fn g a: (addr bool) {\n")
 1605     (write _test-input-stream "}\n")
 1606     # convert
 1607     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1608     # registers except esp clobbered at this point
 1609     # restore ed
 1610     89/<- %edx 4/r32/esp
 1611     (flush _test-output-buffered-file)
 1612     (flush _test-error-buffered-file)
 1613 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1619     # check output
 1620     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-inout-with-incorrect-compound-type: output should be empty")
 1621     (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")
 1622     # don't restore from ebp
 1623     81 0/subop/add %esp 8/imm32
 1624     # . epilogue
 1625     5d/pop-to-ebp
 1626     c3/return
 1627 
 1628 test-convert-function-call-with-inout-with-multiple-type-parameters:
 1629     # . prologue
 1630     55/push-ebp
 1631     89/<- %ebp 4/r32/esp
 1632     # setup
 1633     (clear-stream _test-input-stream)
 1634     (clear-stream $_test-input-buffered-file->buffer)
 1635     (clear-stream _test-output-stream)
 1636     (clear-stream $_test-output-buffered-file->buffer)
 1637     (clear-stream _test-error-stream)
 1638     (clear-stream $_test-error-buffered-file->buffer)
 1639     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1640     68/push 0/imm32
 1641     68/push 0/imm32
 1642     89/<- %edx 4/r32/esp
 1643     (tailor-exit-descriptor %edx 0x10)
 1644     #
 1645     (write _test-input-stream "fn f {\n")
 1646     (write _test-input-stream "  var x: (addr int)\n")
 1647     (write _test-input-stream "  var y: (addr int)\n")
 1648     (write _test-input-stream "  g x, y\n")
 1649     (write _test-input-stream "}\n")
 1650     (write _test-input-stream "fn g a: (addr _), b: (addr _) {\n")
 1651     (write _test-input-stream "}\n")
 1652     # convert
 1653     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1654     # registers except esp clobbered at this point
 1655     # restore ed
 1656     89/<- %edx 4/r32/esp
 1657     (flush _test-output-buffered-file)
 1658     (flush _test-error-buffered-file)
 1659 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1665     # no errors
 1666     (check-stream-equal _test-error-stream  ""  "F - test-convert-function-call-with-inout-with-multiple-type-parameters: error stream should be empty")
 1667     # don't bother checking the generated code
 1668     # don't restore from ebp
 1669     81 0/subop/add %esp 8/imm32
 1670     # . epilogue
 1671     5d/pop-to-ebp
 1672     c3/return
 1673 
 1674 test-type-parameter-matches-rest-of-type:
 1675     # . prologue
 1676     55/push-ebp
 1677     89/<- %ebp 4/r32/esp
 1678     # setup
 1679     (clear-stream _test-input-stream)
 1680     (clear-stream $_test-input-buffered-file->buffer)
 1681     (clear-stream _test-output-stream)
 1682     (clear-stream $_test-output-buffered-file->buffer)
 1683     (clear-stream _test-error-stream)
 1684     (clear-stream $_test-error-buffered-file->buffer)
 1685     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1686     68/push 0/imm32
 1687     68/push 0/imm32
 1688     89/<- %edx 4/r32/esp
 1689     (tailor-exit-descriptor %edx 0x10)
 1690     #
 1691     (write _test-input-stream "fn f {\n")
 1692     (write _test-input-stream "  var x: (addr array int)\n")
 1693     (write _test-input-stream "  g x\n")
 1694     (write _test-input-stream "}\n")
 1695     (write _test-input-stream "fn g a: (addr _) {\n")
 1696     (write _test-input-stream "}\n")
 1697     # convert
 1698     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1699     # registers except esp clobbered at this point
 1700     # restore ed
 1701     89/<- %edx 4/r32/esp
 1702     (flush _test-output-buffered-file)
 1703     (flush _test-error-buffered-file)
 1704 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1710     # no errors
 1711     (check-stream-equal _test-error-stream  ""  "F - test-type-parameter-matches-rest-of-type: error stream should be empty")
 1712     # don't bother checking the generated code
 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-function-call-with-inout-with-incompatible-type-parameters:
 1720     # . prologue
 1721     55/push-ebp
 1722     89/<- %ebp 4/r32/esp
 1723     # setup
 1724     (clear-stream _test-input-stream)
 1725     (clear-stream $_test-input-buffered-file->buffer)
 1726     (clear-stream _test-output-stream)
 1727     (clear-stream $_test-output-buffered-file->buffer)
 1728     (clear-stream _test-error-stream)
 1729     (clear-stream $_test-error-buffered-file->buffer)
 1730     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1731     68/push 0/imm32
 1732     68/push 0/imm32
 1733     89/<- %edx 4/r32/esp
 1734     (tailor-exit-descriptor %edx 0x10)
 1735     #
 1736     (write _test-input-stream "fn f {\n")
 1737     (write _test-input-stream "  var x: (addr int)\n")
 1738     (write _test-input-stream "  var y: (addr boolean)\n")
 1739     (write _test-input-stream "  g x, y\n")
 1740     (write _test-input-stream "}\n")
 1741     (write _test-input-stream "fn g a: (addr _T), b: (addr _T) {\n")
 1742     (write _test-input-stream "}\n")
 1743     # convert
 1744     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1745     # registers except esp clobbered at this point
 1746     # restore ed
 1747     89/<- %edx 4/r32/esp
 1748     (flush _test-output-buffered-file)
 1749     (flush _test-error-buffered-file)
 1750 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1756     # check output
 1757     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-inout-with-incompatible-type-parameters: output should be empty")
 1758     (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")
 1759     # don't restore from ebp
 1760     81 0/subop/add %esp 8/imm32
 1761     # . epilogue
 1762     5d/pop-to-ebp
 1763     c3/return
 1764 
 1765 test-convert-function-call-with-too-few-inouts:
 1766     # . prologue
 1767     55/push-ebp
 1768     89/<- %ebp 4/r32/esp
 1769     # setup
 1770     (clear-stream _test-input-stream)
 1771     (clear-stream $_test-input-buffered-file->buffer)
 1772     (clear-stream _test-output-stream)
 1773     (clear-stream $_test-output-buffered-file->buffer)
 1774     (clear-stream _test-error-stream)
 1775     (clear-stream $_test-error-buffered-file->buffer)
 1776     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1777     68/push 0/imm32
 1778     68/push 0/imm32
 1779     89/<- %edx 4/r32/esp
 1780     (tailor-exit-descriptor %edx 0x10)
 1781     #
 1782     (write _test-input-stream "fn f {\n")
 1783     (write _test-input-stream "  g\n")
 1784     (write _test-input-stream "}\n")
 1785     (write _test-input-stream "fn g a: int {\n")
 1786     (write _test-input-stream "}\n")
 1787     # convert
 1788     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1789     # registers except esp clobbered at this point
 1790     # restore ed
 1791     89/<- %edx 4/r32/esp
 1792     (flush _test-output-buffered-file)
 1793     (flush _test-error-buffered-file)
 1794 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1800     # check output
 1801     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-few-inouts: output should be empty")
 1802     (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")
 1803     # check that stop(1) was called
 1804     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-few-inouts: exit status")
 1805     # don't restore from ebp
 1806     81 0/subop/add %esp 8/imm32
 1807     5d/pop-to-ebp
 1808     c3/return
 1809 
 1810 test-convert-function-call-with-too-many-inouts:
 1811     # . prologue
 1812     55/push-ebp
 1813     89/<- %ebp 4/r32/esp
 1814     # setup
 1815     (clear-stream _test-input-stream)
 1816     (clear-stream $_test-input-buffered-file->buffer)
 1817     (clear-stream _test-output-stream)
 1818     (clear-stream $_test-output-buffered-file->buffer)
 1819     (clear-stream _test-error-stream)
 1820     (clear-stream $_test-error-buffered-file->buffer)
 1821     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1822     68/push 0/imm32
 1823     68/push 0/imm32
 1824     89/<- %edx 4/r32/esp
 1825     (tailor-exit-descriptor %edx 0x10)
 1826     #
 1827     (write _test-input-stream "fn f {\n")
 1828     (write _test-input-stream "  var x: int\n")
 1829     (write _test-input-stream "  g x\n")
 1830     (write _test-input-stream "}\n")
 1831     (write _test-input-stream "fn g {\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-convert-function-call-with-too-many-inouts: output should be empty")
 1848     (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")
 1849     # check that stop(1) was called
 1850     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-many-inouts: exit status")
 1851     # don't restore from ebp
 1852     81 0/subop/add %esp 8/imm32
 1853     5d/pop-to-ebp
 1854     c3/return
 1855 
 1856 test-convert-function-call-with-incorrect-output-type:
 1857     # . prologue
 1858     55/push-ebp
 1859     89/<- %ebp 4/r32/esp
 1860     # setup
 1861     (clear-stream _test-input-stream)
 1862     (clear-stream $_test-input-buffered-file->buffer)
 1863     (clear-stream _test-output-stream)
 1864     (clear-stream $_test-output-buffered-file->buffer)
 1865     (clear-stream _test-error-stream)
 1866     (clear-stream $_test-error-buffered-file->buffer)
 1867     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1868     68/push 0/imm32
 1869     68/push 0/imm32
 1870     89/<- %edx 4/r32/esp
 1871     (tailor-exit-descriptor %edx 0x10)
 1872     #
 1873     (write _test-input-stream "fn f {\n")
 1874     (write _test-input-stream "  var x/eax: int <- g\n")
 1875     (write _test-input-stream "}\n")
 1876     (write _test-input-stream "fn g -> a/eax: foo {\n")
 1877     (write _test-input-stream "}\n")
 1878     # convert
 1879     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1880     # registers except esp clobbered at this point
 1881     # restore ed
 1882     89/<- %edx 4/r32/esp
 1883     (flush _test-output-buffered-file)
 1884     (flush _test-error-buffered-file)
 1885 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1891     # check output
 1892     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-output-type: output should be empty")
 1893     (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")
 1894     # check that stop(1) was called
 1895     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-output-type: exit status")
 1896     # don't restore from ebp
 1897     81 0/subop/add %esp 8/imm32
 1898     5d/pop-to-ebp
 1899     c3/return
 1900 
 1901 test-convert-function-call-with-too-few-outputs:
 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 f {\n")
 1919     (write _test-input-stream "  g\n")
 1920     (write _test-input-stream "}\n")
 1921     (write _test-input-stream "fn g -> a/eax: int {\n")
 1922     (write _test-input-stream "}\n")
 1923     # convert
 1924     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1925     # registers except esp clobbered at this point
 1926     # restore ed
 1927     89/<- %edx 4/r32/esp
 1928     (flush _test-output-buffered-file)
 1929     (flush _test-error-buffered-file)
 1930 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1936     # check output
 1937     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-few-outputs: output should be empty")
 1938     (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")
 1939     # check that stop(1) was called
 1940     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-few-outputs: exit status")
 1941     # don't restore from ebp
 1942     81 0/subop/add %esp 8/imm32
 1943     5d/pop-to-ebp
 1944     c3/return
 1945 
 1946 test-convert-function-call-with-too-many-outputs:
 1947     # . prologue
 1948     55/push-ebp
 1949     89/<- %ebp 4/r32/esp
 1950     # setup
 1951     (clear-stream _test-input-stream)
 1952     (clear-stream $_test-input-buffered-file->buffer)
 1953     (clear-stream _test-output-stream)
 1954     (clear-stream $_test-output-buffered-file->buffer)
 1955     (clear-stream _test-error-stream)
 1956     (clear-stream $_test-error-buffered-file->buffer)
 1957     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1958     68/push 0/imm32
 1959     68/push 0/imm32
 1960     89/<- %edx 4/r32/esp
 1961     (tailor-exit-descriptor %edx 0x10)
 1962     #
 1963     (write _test-input-stream "fn f {\n")
 1964     (write _test-input-stream "  var x/eax: int <- g\n")
 1965     (write _test-input-stream "}\n")
 1966     (write _test-input-stream "fn g {\n")
 1967     (write _test-input-stream "}\n")
 1968     # convert
 1969     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1970     # registers except esp clobbered at this point
 1971     # restore ed
 1972     89/<- %edx 4/r32/esp
 1973     (flush _test-output-buffered-file)
 1974     (flush _test-error-buffered-file)
 1975 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1981     # check output
 1982     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-many-outputs: output should be empty")
 1983     (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")
 1984     # check that stop(1) was called
 1985     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-many-outputs: exit status")
 1986     # don't restore from ebp
 1987     81 0/subop/add %esp 8/imm32
 1988     5d/pop-to-ebp
 1989     c3/return
 1990 
 1991 test-convert-function-call-with-incorrect-output-register:
 1992     # . prologue
 1993     55/push-ebp
 1994     89/<- %ebp 4/r32/esp
 1995     # setup
 1996     (clear-stream _test-input-stream)
 1997     (clear-stream $_test-input-buffered-file->buffer)
 1998     (clear-stream _test-output-stream)
 1999     (clear-stream $_test-output-buffered-file->buffer)
 2000     (clear-stream _test-error-stream)
 2001     (clear-stream $_test-error-buffered-file->buffer)
 2002     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2003     68/push 0/imm32
 2004     68/push 0/imm32
 2005     89/<- %edx 4/r32/esp
 2006     (tailor-exit-descriptor %edx 0x10)
 2007     #
 2008     (write _test-input-stream "fn f {\n")
 2009     (write _test-input-stream "  var x/ecx: int <- g\n")
 2010     (write _test-input-stream "}\n")
 2011     (write _test-input-stream "fn g -> a/eax: int {\n")
 2012     (write _test-input-stream "}\n")
 2013     # convert
 2014     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2015     # registers except esp clobbered at this point
 2016     # restore ed
 2017     89/<- %edx 4/r32/esp
 2018     (flush _test-output-buffered-file)
 2019     (flush _test-error-buffered-file)
 2020 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2026     # check output
 2027     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-output-register: output should be empty")
 2028     (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")
 2029     # check that stop(1) was called
 2030     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-output-register: exit status")
 2031     # don't restore from ebp
 2032     81 0/subop/add %esp 8/imm32
 2033     5d/pop-to-ebp
 2034     c3/return
 2035 
 2036 test-convert-function-with-local-var-dereferenced:
 2037     # . prologue
 2038     55/push-ebp
 2039     89/<- %ebp 4/r32/esp
 2040     # setup
 2041     (clear-stream _test-input-stream)
 2042     (clear-stream $_test-input-buffered-file->buffer)
 2043     (clear-stream _test-output-stream)
 2044     (clear-stream $_test-output-buffered-file->buffer)
 2045     #
 2046     (write _test-input-stream "fn foo {\n")
 2047     (write _test-input-stream "  var x/ecx: (addr int) <- copy 0\n")
 2048     (write _test-input-stream "  increment *x\n")
 2049     (write _test-input-stream "}\n")
 2050     # convert
 2051     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2052     (flush _test-output-buffered-file)
 2053 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2059     # check output
 2060     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-dereferenced/0")
 2061     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-dereferenced/1")
 2062     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-dereferenced/2")
 2063     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-dereferenced/3")
 2064     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-dereferenced/4")
 2065     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-dereferenced/5")
 2066     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-dereferenced/6")
 2067     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-local-var-dereferenced/7")
 2068     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *ecx"  "F - test-convert-function-with-local-var-dereferenced/8")
 2069     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-dereferenced/9")
 2070     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-dereferenced/10")
 2071     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-dereferenced/11")
 2072     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-dereferenced/12")
 2073     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-dereferenced/13")
 2074     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-dereferenced/14")
 2075     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-dereferenced/15")
 2076     # . epilogue
 2077     89/<- %esp 5/r32/ebp
 2078     5d/pop-to-ebp
 2079     c3/return
 2080 
 2081 # variables of type 'byte' are not allowed on the stack
 2082 test-convert-function-with-byte-operations:
 2083     # . prologue
 2084     55/push-ebp
 2085     89/<- %ebp 4/r32/esp
 2086     # setup
 2087     (clear-stream _test-input-stream)
 2088     (clear-stream $_test-input-buffered-file->buffer)
 2089     (clear-stream _test-output-stream)
 2090     (clear-stream $_test-output-buffered-file->buffer)
 2091     #
 2092     (write _test-input-stream "fn foo {\n")
 2093     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
 2094     (write _test-input-stream "  var y/ecx: byte <- copy 0\n")
 2095     (write _test-input-stream "  y <- copy-byte x\n")
 2096     (write _test-input-stream "  var z/edx: (addr byte) <- copy 0\n")
 2097     (write _test-input-stream "  y <- copy-byte *z\n")
 2098     (write _test-input-stream "  copy-byte-to *z, x\n")
 2099     (write _test-input-stream "}\n")
 2100     # convert
 2101     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2102     (flush _test-output-buffered-file)
 2103 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2109     # check output
 2110     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-function-with-byte-operations/0")
 2111     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-function-with-byte-operations/1")
 2112     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-function-with-byte-operations/2")
 2113     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-function-with-byte-operations/3")
 2114     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-function-with-byte-operations/4")
 2115     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-function-with-byte-operations/5")
 2116     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-function-with-byte-operations/6")
 2117     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-function-with-byte-operations/7")
 2118     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-function-with-byte-operations/8")
 2119     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"                  "F - test-convert-function-with-byte-operations/9")
 2120     (check-next-stream-line-equal _test-output-stream "    8a/byte-> %eax 0x00000001/r32"           "F - test-convert-function-with-byte-operations/10")
 2121     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %edx"                    "F - test-convert-function-with-byte-operations/11")
 2122     (check-next-stream-line-equal _test-output-stream "    ba/copy-to-edx 0/imm32"                  "F - test-convert-function-with-byte-operations/12")
 2123     (check-next-stream-line-equal _test-output-stream "    8a/byte-> *edx 0x00000001/r32"           "F - test-convert-function-with-byte-operations/13")
 2124     (check-next-stream-line-equal _test-output-stream "    88/byte<- *edx 0x00000000/r32"           "F - test-convert-function-with-byte-operations/14")
 2125     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %edx"                     "F - test-convert-function-with-byte-operations/15")
 2126     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-function-with-byte-operations/16")
 2127     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-function-with-byte-operations/17")
 2128     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-function-with-byte-operations/18")
 2129     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-function-with-byte-operations/19")
 2130     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-function-with-byte-operations/20")
 2131     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-function-with-byte-operations/21")
 2132     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-function-with-byte-operations/22")
 2133     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-function-with-byte-operations/23")
 2134     # . epilogue
 2135     89/<- %esp 5/r32/ebp
 2136     5d/pop-to-ebp
 2137     c3/return
 2138 
 2139 # variables of type 'byte' _can_ be function args. They then occupy 4 bytes.
 2140 test-copy-byte-var-from-fn-arg:
 2141     # . prologue
 2142     55/push-ebp
 2143     89/<- %ebp 4/r32/esp
 2144     # setup
 2145     (clear-stream _test-input-stream)
 2146     (clear-stream $_test-input-buffered-file->buffer)
 2147     (clear-stream _test-output-stream)
 2148     (clear-stream $_test-output-buffered-file->buffer)
 2149     #
 2150     (write _test-input-stream "fn foo x: byte, y: int {\n")
 2151     (write _test-input-stream "  var a/eax: byte <- copy x\n")
 2152     (write _test-input-stream "  var b/eax: int <- copy y\n")
 2153     (write _test-input-stream "}\n")
 2154     # convert
 2155     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2156     (flush _test-output-buffered-file)
 2157 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2163     # check output
 2164     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-copy-byte-from-fn-arg/0")
 2165     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-copy-byte-from-fn-arg/1")
 2166     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-copy-byte-from-fn-arg/2")
 2167     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-copy-byte-from-fn-arg/3")
 2168     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-copy-byte-from-fn-arg/4")
 2169     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-copy-byte-from-fn-arg/5")
 2170     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-copy-byte-from-fn-arg/6")
 2171     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-copy-byte-from-fn-arg/7")
 2172     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x0000000c) 0x00000000/r32"  "F - test-copy-byte-from-fn-arg/8")
 2173     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"   "F - test-copy-byte-from-fn-arg/9")
 2174     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-copy-byte-from-fn-arg/10")
 2175     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-copy-byte-from-fn-arg/11")
 2176     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-copy-byte-from-fn-arg/12")
 2177     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-copy-byte-from-fn-arg/13")
 2178     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-copy-byte-from-fn-arg/14")
 2179     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-copy-byte-from-fn-arg/15")
 2180     # . epilogue
 2181     89/<- %esp 5/r32/ebp
 2182     5d/pop-to-ebp
 2183     c3/return
 2184 
 2185 test-convert-compare-register-with-literal:
 2186     # . prologue
 2187     55/push-ebp
 2188     89/<- %ebp 4/r32/esp
 2189     # setup
 2190     (clear-stream _test-input-stream)
 2191     (clear-stream $_test-input-buffered-file->buffer)
 2192     (clear-stream _test-output-stream)
 2193     (clear-stream $_test-output-buffered-file->buffer)
 2194     #
 2195     (write _test-input-stream "fn foo {\n")
 2196     (write _test-input-stream "  var x/ecx: int <- copy 0\n")
 2197     (write _test-input-stream "  compare x, 0\n")
 2198     (write _test-input-stream "}\n")
 2199     # convert
 2200     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2201     (flush _test-output-buffered-file)
 2202 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2208     # check output
 2209     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-compare-register-with-literal/0")
 2210     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-compare-register-with-literal/1")
 2211     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-compare-register-with-literal/2")
 2212     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-compare-register-with-literal/3")
 2213     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-compare-register-with-literal/4")
 2214     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-compare-register-with-literal/5")
 2215     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-compare-register-with-literal/6")
 2216     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-compare-register-with-literal/7")
 2217     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %ecx 0/imm32"  "F - test-convert-compare-register-with-literal/8")
 2218     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-compare-register-with-literal/9")
 2219     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-compare-register-with-literal/10")
 2220     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-compare-register-with-literal/11")
 2221     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-compare-register-with-literal/12")
 2222     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-compare-register-with-literal/13")
 2223     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-compare-register-with-literal/14")
 2224     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-compare-register-with-literal/15")
 2225     # . epilogue
 2226     89/<- %esp 5/r32/ebp
 2227     5d/pop-to-ebp
 2228     c3/return
 2229 
 2230 test-unknown-variable:
 2231     # . prologue
 2232     55/push-ebp
 2233     89/<- %ebp 4/r32/esp
 2234     # setup
 2235     (clear-stream _test-input-stream)
 2236     (clear-stream $_test-input-buffered-file->buffer)
 2237     (clear-stream _test-output-stream)
 2238     (clear-stream $_test-output-buffered-file->buffer)
 2239     (clear-stream _test-error-stream)
 2240     (clear-stream $_test-error-buffered-file->buffer)
 2241     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2242     68/push 0/imm32
 2243     68/push 0/imm32
 2244     89/<- %edx 4/r32/esp
 2245     (tailor-exit-descriptor %edx 0x10)
 2246     #
 2247     (write _test-input-stream "fn foo {\n")
 2248     (write _test-input-stream "  compare x, 0\n")
 2249     (write _test-input-stream "}\n")
 2250     # convert
 2251     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2252     # registers except esp clobbered at this point
 2253     # restore ed
 2254     89/<- %edx 4/r32/esp
 2255     (flush _test-output-buffered-file)
 2256     (flush _test-error-buffered-file)
 2257 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2263     # check output
 2264     (check-stream-equal _test-output-stream  ""  "F - test-unknown-variable: output should be empty")
 2265     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-unknown-variable: error message")
 2266     # check that stop(1) was called
 2267     (check-ints-equal *(edx+4) 2 "F - test-unknown-variable: exit status")
 2268     # don't restore from ebp
 2269     81 0/subop/add %esp 8/imm32
 2270     # . epilogue
 2271     5d/pop-to-ebp
 2272     c3/return
 2273 
 2274 test-convert-function-with-local-var-in-block:
 2275     # . prologue
 2276     55/push-ebp
 2277     89/<- %ebp 4/r32/esp
 2278     # setup
 2279     (clear-stream _test-input-stream)
 2280     (clear-stream $_test-input-buffered-file->buffer)
 2281     (clear-stream _test-output-stream)
 2282     (clear-stream $_test-output-buffered-file->buffer)
 2283     #
 2284     (write _test-input-stream "fn foo {\n")
 2285     (write _test-input-stream "  {\n")
 2286     (write _test-input-stream "    var x: int\n")
 2287     (write _test-input-stream "    increment x\n")
 2288     (write _test-input-stream "  }\n")
 2289     (write _test-input-stream "}\n")
 2290     # convert
 2291     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2292     (flush _test-output-buffered-file)
 2293 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2299     # check output
 2300     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-block/0")
 2301     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-block/1")
 2302     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-block/2")
 2303     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-block/3")
 2304     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-block/4")
 2305     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-block/5")
 2306     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-block/6")
 2307     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-local-var-in-block/7")
 2308     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-block/8")
 2309     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-local-var-in-block/9")
 2310     (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")
 2311     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-block/11")
 2312     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-local-var-in-block/12")
 2313     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-block/13")
 2314     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-block/14")
 2315     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-block/15")
 2316     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-block/16")
 2317     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-block/17")
 2318     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-block/18")
 2319     # . epilogue
 2320     89/<- %esp 5/r32/ebp
 2321     5d/pop-to-ebp
 2322     c3/return
 2323 
 2324 test-convert-function-with-local-var-in-named-block:
 2325     # . prologue
 2326     55/push-ebp
 2327     89/<- %ebp 4/r32/esp
 2328     # setup
 2329     (clear-stream _test-input-stream)
 2330     (clear-stream $_test-input-buffered-file->buffer)
 2331     (clear-stream _test-output-stream)
 2332     (clear-stream $_test-output-buffered-file->buffer)
 2333     #
 2334     (write _test-input-stream "fn foo {\n")
 2335     (write _test-input-stream "  $bar: {\n")
 2336     (write _test-input-stream "    var x: int\n")
 2337     (write _test-input-stream "    increment x\n")
 2338     (write _test-input-stream "  }\n")
 2339     (write _test-input-stream "}\n")
 2340     # convert
 2341     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2342     (flush _test-output-buffered-file)
 2343 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2349     # check output
 2350     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-named-block/0")
 2351     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-named-block/1")
 2352     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-named-block/2")
 2353     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-named-block/3")
 2354     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-named-block/4")
 2355     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-named-block/5")
 2356     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-named-block/6")
 2357     (check-next-stream-line-equal _test-output-stream "$bar:loop:"              "F - test-convert-function-with-local-var-in-named-block/7")
 2358     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-named-block/8")
 2359     (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")
 2360     (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")
 2361     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-named-block/11")
 2362     (check-next-stream-line-equal _test-output-stream "$bar:break:"             "F - test-convert-function-with-local-var-in-named-block/12")
 2363     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-named-block/13")
 2364     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-named-block/14")
 2365     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-named-block/15")
 2366     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-named-block/16")
 2367     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-named-block/17")
 2368     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-named-block/18")
 2369     # . epilogue
 2370     89/<- %esp 5/r32/ebp
 2371     5d/pop-to-ebp
 2372     c3/return
 2373 
 2374 test-unknown-variable-in-named-block:
 2375     # . prologue
 2376     55/push-ebp
 2377     89/<- %ebp 4/r32/esp
 2378     # setup
 2379     (clear-stream _test-input-stream)
 2380     (clear-stream $_test-input-buffered-file->buffer)
 2381     (clear-stream _test-output-stream)
 2382     (clear-stream $_test-output-buffered-file->buffer)
 2383     (clear-stream _test-error-stream)
 2384     (clear-stream $_test-error-buffered-file->buffer)
 2385     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2386     68/push 0/imm32
 2387     68/push 0/imm32
 2388     89/<- %edx 4/r32/esp
 2389     (tailor-exit-descriptor %edx 0x10)
 2390     #
 2391     (write _test-input-stream "fn foo {\n")
 2392     (write _test-input-stream "  $a: {\n")
 2393     (write _test-input-stream "    compare x, 0\n")
 2394     (write _test-input-stream "  }\n")
 2395     (write _test-input-stream "}\n")
 2396     # convert
 2397     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2398     # registers except esp clobbered at this point
 2399     # restore ed
 2400     89/<- %edx 4/r32/esp
 2401     (flush _test-output-buffered-file)
 2402     (flush _test-error-buffered-file)
 2403 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2409     # check output
 2410     (check-stream-equal _test-output-stream  ""  "F - test-unknown-variable-in-named-block: output should be empty")
 2411     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-unknown-variable-in-named-block: error message")
 2412     # check that stop(1) was called
 2413     (check-ints-equal *(edx+4) 2 "F - test-unknown-variable-in-named-block: exit status")
 2414     # don't restore from ebp
 2415     81 0/subop/add %esp 8/imm32
 2416     # . epilogue
 2417     5d/pop-to-ebp
 2418     c3/return
 2419 
 2420 test-always-shadow-outermost-reg-vars-in-function:
 2421     # . prologue
 2422     55/push-ebp
 2423     89/<- %ebp 4/r32/esp
 2424     # setup
 2425     (clear-stream _test-input-stream)
 2426     (clear-stream $_test-input-buffered-file->buffer)
 2427     (clear-stream _test-output-stream)
 2428     (clear-stream $_test-output-buffered-file->buffer)
 2429     #
 2430     (write _test-input-stream "fn foo {\n")
 2431     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2432     (write _test-input-stream "}\n")
 2433     # convert
 2434     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2435     (flush _test-output-buffered-file)
 2436 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2442     # check output
 2443     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-always-shadow-outermost-reg-vars-in-function/0")
 2444     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-always-shadow-outermost-reg-vars-in-function/1")
 2445     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-always-shadow-outermost-reg-vars-in-function/2")
 2446     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-always-shadow-outermost-reg-vars-in-function/3")
 2447     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-always-shadow-outermost-reg-vars-in-function/4")
 2448     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-always-shadow-outermost-reg-vars-in-function/5")
 2449     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-compare-register-with-literal/6")
 2450     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-always-shadow-outermost-reg-vars-in-function/8")
 2451     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-compare-register-with-literal/9")
 2452     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-always-shadow-outermost-reg-vars-in-function/12")
 2453     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-always-shadow-outermost-reg-vars-in-function/13")
 2454     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-always-shadow-outermost-reg-vars-in-function/14")
 2455     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-always-shadow-outermost-reg-vars-in-function/15")
 2456     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-always-shadow-outermost-reg-vars-in-function/16")
 2457     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-always-shadow-outermost-reg-vars-in-function/17")
 2458     # . epilogue
 2459     89/<- %esp 5/r32/ebp
 2460     5d/pop-to-ebp
 2461     c3/return
 2462 
 2463 _pending-test-clobber-dead-local:
 2464     # . prologue
 2465     55/push-ebp
 2466     89/<- %ebp 4/r32/esp
 2467     # setup
 2468     (clear-stream _test-input-stream)
 2469     (clear-stream $_test-input-buffered-file->buffer)
 2470     (clear-stream _test-output-stream)
 2471     (clear-stream $_test-output-buffered-file->buffer)
 2472     #
 2473     (write _test-input-stream "fn foo {\n")
 2474     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2475     (write _test-input-stream "  {\n")
 2476     (write _test-input-stream "    var y/ecx: int <- copy 4\n")
 2477     (write _test-input-stream "  }\n")
 2478     (write _test-input-stream "}\n")
 2479     # convert
 2480     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2481     (flush _test-output-buffered-file)
 2482 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2488     # check output
 2489     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-clobber-dead-local/0")
 2490     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-clobber-dead-local/1")
 2491     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-clobber-dead-local/2")
 2492     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-clobber-dead-local/3")
 2493     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-clobber-dead-local/4")
 2494     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-clobber-dead-local/5")
 2495     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-clobber-dead-local/6")
 2496     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-clobber-dead-local/7")
 2497     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-clobber-dead-local/8")
 2498     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-clobber-dead-local/9")
 2499     (check-next-stream-line-equal _test-output-stream "      b9/copy-to-ecx 4/imm32"  "F - test-clobber-dead-local/10")  # no push/pop here
 2500     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-clobber-dead-local/11")
 2501     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-clobber-dead-local/12")
 2502     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-clobber-dead-local/13")
 2503     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-clobber-dead-local/14")
 2504     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-clobber-dead-local/15")
 2505     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-clobber-dead-local/16")
 2506     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-clobber-dead-local/17")
 2507     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-clobber-dead-local/18")
 2508     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-clobber-dead-local/19")
 2509     # . epilogue
 2510     89/<- %esp 5/r32/ebp
 2511     5d/pop-to-ebp
 2512     c3/return
 2513 
 2514 test-shadow-live-local:
 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: int <- copy 3\n")
 2526     (write _test-input-stream "  {\n")
 2527     (write _test-input-stream "    var y/ecx: int <- copy 4\n")
 2528     (write _test-input-stream "  }\n")
 2529     (write _test-input-stream "  x <- increment\n")
 2530     (write _test-input-stream "}\n")
 2531     # convert
 2532     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2533     (flush _test-output-buffered-file)
 2534 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2540     # check output
 2541     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-live-local/0")
 2542     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-live-local/1")
 2543     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-live-local/2")
 2544     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-live-local/3")
 2545     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-live-local/4")
 2546     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-live-local/5")
 2547     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-live-local/6")
 2548     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-live-local/7")
 2549     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-live-local/8")
 2550     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-live-local/9")
 2551     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %ecx"  "F - test-shadow-live-local/10")
 2552     (check-next-stream-line-equal _test-output-stream "      b9/copy-to-ecx 4/imm32"  "F - test-shadow-live-local/11")
 2553     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %ecx" "F - test-shadow-live-local/12")
 2554     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-live-local/13")
 2555     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-live-local/14")
 2556     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-live-local/15")
 2557     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-live-local/16")
 2558     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-live-local/17")
 2559     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-live-local/18")
 2560     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-live-local/19")
 2561     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-live-local/20")
 2562     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-live-local/21")
 2563     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-live-local/22")
 2564     # . epilogue
 2565     89/<- %esp 5/r32/ebp
 2566     5d/pop-to-ebp
 2567     c3/return
 2568 
 2569 test-shadow-name:
 2570     # . prologue
 2571     55/push-ebp
 2572     89/<- %ebp 4/r32/esp
 2573     # setup
 2574     (clear-stream _test-input-stream)
 2575     (clear-stream $_test-input-buffered-file->buffer)
 2576     (clear-stream _test-output-stream)
 2577     (clear-stream $_test-output-buffered-file->buffer)
 2578     #
 2579     (write _test-input-stream "fn foo {\n")
 2580     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2581     (write _test-input-stream "  {\n")
 2582     (write _test-input-stream "    var x/edx: int <- copy 4\n")
 2583     (write _test-input-stream "  }\n")
 2584     (write _test-input-stream "  x <- increment\n")
 2585     (write _test-input-stream "}\n")
 2586     # convert
 2587     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2588     (flush _test-output-buffered-file)
 2589 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2595     # check output
 2596     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-name/0")
 2597     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-name/1")
 2598     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-name/2")
 2599     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-name/3")
 2600     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-name/4")
 2601     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-name/5")
 2602     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-name/6")
 2603     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-name/7")
 2604     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-name/8")
 2605     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-name/9")
 2606     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %edx"  "F - test-shadow-name/10")
 2607     (check-next-stream-line-equal _test-output-stream "      ba/copy-to-edx 4/imm32"  "F - test-shadow-name/11")
 2608     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %edx" "F - test-shadow-name/12")
 2609     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-name/13")
 2610     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-name/14")
 2611     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-name/15")
 2612     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-name/16")
 2613     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-name/17")
 2614     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-name/18")
 2615     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-name/19")
 2616     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-name/20")
 2617     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-name/21")
 2618     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-name/22")
 2619     # . epilogue
 2620     89/<- %esp 5/r32/ebp
 2621     5d/pop-to-ebp
 2622     c3/return
 2623 
 2624 test-shadow-name-2:
 2625     # . prologue
 2626     55/push-ebp
 2627     89/<- %ebp 4/r32/esp
 2628     # setup
 2629     (clear-stream _test-input-stream)
 2630     (clear-stream $_test-input-buffered-file->buffer)
 2631     (clear-stream _test-output-stream)
 2632     (clear-stream $_test-output-buffered-file->buffer)
 2633     #
 2634     (write _test-input-stream "fn foo {\n")
 2635     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2636     (write _test-input-stream "  {\n")
 2637     (write _test-input-stream "    var x/edx: int <- copy 4\n")
 2638     (write _test-input-stream "    var y/ecx: int <- copy 5\n")
 2639     (write _test-input-stream "  }\n")
 2640     (write _test-input-stream "  x <- increment\n")
 2641     (write _test-input-stream "}\n")
 2642     # convert
 2643     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2644     (flush _test-output-buffered-file)
 2645 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2651     # check output
 2652     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-name-2/0")
 2653     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-name-2/1")
 2654     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-name-2/2")
 2655     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-name-2/3")
 2656     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-name-2/4")
 2657     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-name-2/5")
 2658     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-name-2/6")
 2659     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-name-2/7")
 2660     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-name-2/8")
 2661     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-name-2/9")
 2662     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %edx"  "F - test-shadow-name-2/10")
 2663     (check-next-stream-line-equal _test-output-stream "      ba/copy-to-edx 4/imm32"  "F - test-shadow-name-2/11")
 2664     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %ecx"  "F - test-shadow-name-2/12")
 2665     (check-next-stream-line-equal _test-output-stream "      b9/copy-to-ecx 5/imm32"  "F - test-shadow-name-2/13")
 2666     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %ecx" "F - test-shadow-name-2/14")
 2667     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %edx" "F - test-shadow-name-2/15")
 2668     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-name-2/16")
 2669     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-name-2/17")
 2670     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-name-2/18")
 2671     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-name-2/19")
 2672     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-name-2/20")
 2673     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-name-2/21")
 2674     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-name-2/22")
 2675     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-name-2/23")
 2676     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-name-2/24")
 2677     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-name-2/25")
 2678     # . epilogue
 2679     89/<- %esp 5/r32/ebp
 2680     5d/pop-to-ebp
 2681     c3/return
 2682 
 2683 test-do-not-spill-same-register-in-block:
 2684     # . prologue
 2685     55/push-ebp
 2686     89/<- %ebp 4/r32/esp
 2687     # setup
 2688     (clear-stream _test-input-stream)
 2689     (clear-stream $_test-input-buffered-file->buffer)
 2690     (clear-stream _test-output-stream)
 2691     (clear-stream $_test-output-buffered-file->buffer)
 2692     #
 2693     (write _test-input-stream "fn foo {\n")
 2694     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2695     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 2696     (write _test-input-stream "  y <- increment\n")
 2697     (write _test-input-stream "}\n")
 2698     # convert
 2699     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2700     (flush _test-output-buffered-file)
 2701 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2707     # check output
 2708     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-do-not-spill-same-register-in-block/0")
 2709     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-do-not-spill-same-register-in-block/1")
 2710     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-do-not-spill-same-register-in-block/2")
 2711     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-do-not-spill-same-register-in-block/3")
 2712     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-do-not-spill-same-register-in-block/4")
 2713     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-do-not-spill-same-register-in-block/5")
 2714     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-do-not-spill-same-register-in-block/6")
 2715     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-do-not-spill-same-register-in-block/7")
 2716     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-do-not-spill-same-register-in-block/8")
 2717     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-do-not-spill-same-register-in-block/9")
 2718     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-do-not-spill-same-register-in-block/10")
 2719     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-do-not-spill-same-register-in-block/11")
 2720     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-do-not-spill-same-register-in-block/12")
 2721     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-do-not-spill-same-register-in-block/13")
 2722     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-do-not-spill-same-register-in-block/14")
 2723     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-do-not-spill-same-register-in-block/15")
 2724     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-do-not-spill-same-register-in-block/16")
 2725     # . epilogue
 2726     89/<- %esp 5/r32/ebp
 2727     5d/pop-to-ebp
 2728     c3/return
 2729 
 2730 test-spill-different-register-in-block:
 2731     # . prologue
 2732     55/push-ebp
 2733     89/<- %ebp 4/r32/esp
 2734     # setup
 2735     (clear-stream _test-input-stream)
 2736     (clear-stream $_test-input-buffered-file->buffer)
 2737     (clear-stream _test-output-stream)
 2738     (clear-stream $_test-output-buffered-file->buffer)
 2739     #
 2740     (write _test-input-stream "fn foo {\n")
 2741     (write _test-input-stream "  var x/eax: int <- copy 3\n")
 2742     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 2743     (write _test-input-stream "  y <- increment\n")
 2744     (write _test-input-stream "}\n")
 2745     # convert
 2746     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2747     (flush _test-output-buffered-file)
 2748 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2754     # check output
 2755     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-spill-different-register-in-block/0")
 2756     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-spill-different-register-in-block/1")
 2757     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-spill-different-register-in-block/2")
 2758     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-spill-different-register-in-block/3")
 2759     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-spill-different-register-in-block/4")
 2760     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-spill-different-register-in-block/5")
 2761     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-spill-different-register-in-block/6")
 2762     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-spill-different-register-in-block/7")
 2763     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-spill-different-register-in-block/8")
 2764     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-spill-different-register-in-block/9")
 2765     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-spill-different-register-in-block/10")
 2766     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-spill-different-register-in-block/11")
 2767     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-spill-different-register-in-block/12")
 2768     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-spill-different-register-in-block/13")
 2769     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-spill-different-register-in-block/14")
 2770     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-spill-different-register-in-block/15")
 2771     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-spill-different-register-in-block/16")
 2772     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-spill-different-register-in-block/17")
 2773     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-spill-different-register-in-block/18")
 2774     # . epilogue
 2775     89/<- %esp 5/r32/ebp
 2776     5d/pop-to-ebp
 2777     c3/return
 2778 
 2779 test-shadow-live-output:
 2780     # . prologue
 2781     55/push-ebp
 2782     89/<- %ebp 4/r32/esp
 2783     # setup
 2784     (clear-stream _test-input-stream)
 2785     (clear-stream $_test-input-buffered-file->buffer)
 2786     (clear-stream _test-output-stream)
 2787     (clear-stream $_test-output-buffered-file->buffer)
 2788     #
 2789     (write _test-input-stream "fn foo -> x/ecx: int {\n")
 2790     (write _test-input-stream "  x <- copy 3\n")
 2791     (write _test-input-stream "  {\n")
 2792     (write _test-input-stream "    var y/ecx: int <- copy 4\n")
 2793     (write _test-input-stream "  }\n")
 2794     (write _test-input-stream "  x <- increment\n")
 2795     (write _test-input-stream "}\n")
 2796     # convert
 2797     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2798     (flush _test-output-buffered-file)
 2799 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2805     # check output
 2806     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-live-output/0")
 2807     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-live-output/1")
 2808     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-live-output/2")
 2809     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-live-output/3")
 2810     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-live-output/4")
 2811     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-live-output/5")
 2812     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-live-output/7")  # no push because it's an output reg
 2813     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-live-output/8")
 2814     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-live-output/9")
 2815     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %ecx"  "F - test-shadow-live-output/10")
 2816     (check-next-stream-line-equal _test-output-stream "      b9/copy-to-ecx 4/imm32"  "F - test-shadow-live-output/11")
 2817     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %ecx" "F - test-shadow-live-output/12")
 2818     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-live-output/13")
 2819     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-live-output/14")
 2820     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-live-output/15")
 2821     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-live-output/17")
 2822     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-live-output/18")
 2823     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-live-output/19")
 2824     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-live-output/20")
 2825     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-live-output/21")
 2826     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-live-output/21")
 2827     # . epilogue
 2828     89/<- %esp 5/r32/ebp
 2829     5d/pop-to-ebp
 2830     c3/return
 2831 
 2832 test-stmt-defines-output-in-same-register-as-inout:
 2833     # . prologue
 2834     55/push-ebp
 2835     89/<- %ebp 4/r32/esp
 2836     # setup
 2837     (clear-stream _test-input-stream)
 2838     (clear-stream $_test-input-buffered-file->buffer)
 2839     (clear-stream _test-output-stream)
 2840     (clear-stream $_test-output-buffered-file->buffer)
 2841     (clear-stream _test-error-stream)
 2842     (clear-stream $_test-error-buffered-file->buffer)
 2843     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2844     68/push 0/imm32
 2845     68/push 0/imm32
 2846     89/<- %edx 4/r32/esp
 2847     (tailor-exit-descriptor %edx 0x10)
 2848     #
 2849     (write _test-input-stream "fn foo -> x/ecx: int {\n")
 2850     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 2851     (write _test-input-stream "  x <- copy y\n")  # writing to a fn output is currently the only way for a statement to define a new var
 2852     (write _test-input-stream "}\n")
 2853     # convert
 2854     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2855     # registers except esp clobbered at this point
 2856     # restore ed
 2857     89/<- %edx 4/r32/esp
 2858     (flush _test-output-buffered-file)
 2859     (flush _test-error-buffered-file)
 2860 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2866     # no error; we looked up 'y' correctly before pushing the binding for 'x'
 2867     (check-stream-equal _test-error-stream  ""  "F - test-stmt-defines-output-in-same-register-as-inout: error stream should be empty")
 2868     # don't bother checking the generated code; that's in the test 'test-local-clobbered-by-fn-output' below
 2869     # don't restore from ebp
 2870     81 0/subop/add %esp 8/imm32
 2871     # . epilogue
 2872     5d/pop-to-ebp
 2873     c3/return
 2874 
 2875 test-local-clobbered-by-fn-output:
 2876     # . prologue
 2877     55/push-ebp
 2878     89/<- %ebp 4/r32/esp
 2879     # setup
 2880     (clear-stream _test-input-stream)
 2881     (clear-stream $_test-input-buffered-file->buffer)
 2882     (clear-stream _test-output-stream)
 2883     (clear-stream $_test-output-buffered-file->buffer)
 2884     #
 2885     (write _test-input-stream "fn foo -> x/ecx: int {\n")
 2886     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 2887     (write _test-input-stream "  x <- copy y\n")
 2888     (write _test-input-stream "}\n")
 2889     # convert
 2890     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2891     (flush _test-output-buffered-file)
 2892 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2898     # check output
 2899     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-local-clobbered-by-fn-output/0")
 2900     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-local-clobbered-by-fn-output/1")
 2901     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-local-clobbered-by-fn-output/2")
 2902     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-local-clobbered-by-fn-output/3")
 2903     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-local-clobbered-by-fn-output/4")
 2904     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-local-clobbered-by-fn-output/5")
 2905     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-local-clobbered-by-fn-output/6")  # no push because it's an output reg
 2906     (check-next-stream-line-equal _test-output-stream "    89/<- %ecx 0x00000001/r32"  "F - test-local-clobbered-by-fn-output/7")
 2907     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-local-clobbered-by-fn-output/8")
 2908     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-local-clobbered-by-fn-output/9")
 2909     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-local-clobbered-by-fn-output/10")
 2910     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-local-clobbered-by-fn-output/11")
 2911     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-local-clobbered-by-fn-output/12")
 2912     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-local-clobbered-by-fn-output/13")
 2913     # . epilogue
 2914     89/<- %esp 5/r32/ebp
 2915     5d/pop-to-ebp
 2916     c3/return
 2917 
 2918 test-read-output:
 2919     # . prologue
 2920     55/push-ebp
 2921     89/<- %ebp 4/r32/esp
 2922     # setup
 2923     (clear-stream _test-input-stream)
 2924     (clear-stream $_test-input-buffered-file->buffer)
 2925     (clear-stream _test-output-stream)
 2926     (clear-stream $_test-output-buffered-file->buffer)
 2927     #
 2928     (write _test-input-stream "fn foo -> x/ecx: int {\n")
 2929     (write _test-input-stream "  x <- copy 0x34\n")
 2930     (write _test-input-stream "  compare x, 0x35\n")
 2931     (write _test-input-stream "}\n")
 2932     # convert
 2933     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2934     (flush _test-output-buffered-file)
 2935 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2941     # check output
 2942     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-read-output/0")
 2943     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-read-output/1")
 2944     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-read-output/2")
 2945     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-read-output/3")
 2946     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-read-output/4")
 2947     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-read-output/5")
 2948     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0x34/imm32"  "F - test-read-output/6")
 2949     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %ecx 0x35/imm32"  "F - test-read-output/7")
 2950     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-read-output/8")
 2951     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-read-output/9")
 2952     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-read-output/10")
 2953     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-read-output/11")
 2954     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-read-output/12")
 2955     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-read-output/13")
 2956     # . epilogue
 2957     89/<- %esp 5/r32/ebp
 2958     5d/pop-to-ebp
 2959     c3/return
 2960 
 2961 test-fn-output-written-in-inner-block:
 2962     # . prologue
 2963     55/push-ebp
 2964     89/<- %ebp 4/r32/esp
 2965     # setup
 2966     (clear-stream _test-input-stream)
 2967     (clear-stream $_test-input-buffered-file->buffer)
 2968     (clear-stream _test-output-stream)
 2969     (clear-stream $_test-output-buffered-file->buffer)
 2970     #
 2971     (write _test-input-stream "fn foo -> out/edi: int {\n")
 2972     (write _test-input-stream "  var a/eax: int <- copy 3\n")  # define outer local
 2973     (write _test-input-stream "  {\n")
 2974     (write _test-input-stream "    var a/ecx: int <- copy 4\n")  # shadow outer local
 2975     (write _test-input-stream "    out <- copy a\n")  # write to fn output
 2976     (write _test-input-stream "  }\n")
 2977     (write _test-input-stream "  compare a, 0\n")  # use outer local
 2978     (write _test-input-stream "}\n")
 2979     # convert
 2980     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2981     (flush _test-output-buffered-file)
 2982 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2988     # no error; defining 'out' didn't interfere with the reclamation of 'b'
 2989     # check output
 2990     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-fn-output-written-in-inner-block/0")
 2991     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-fn-output-written-in-inner-block/1")
 2992     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-fn-output-written-in-inner-block/2")
 2993     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-fn-output-written-in-inner-block/3")
 2994     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-fn-output-written-in-inner-block/4")
 2995     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-fn-output-written-in-inner-block/5")
 2996     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-fn-output-written-in-inner-block/6")
 2997     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-fn-output-written-in-inner-block/7")
 2998     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-fn-output-written-in-inner-block/8")
 2999     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-fn-output-written-in-inner-block/9")
 3000     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %ecx"  "F - test-fn-output-written-in-inner-block/10")
 3001     (check-next-stream-line-equal _test-output-stream "      b9/copy-to-ecx 4/imm32"  "F - test-fn-output-written-in-inner-block/10")
 3002     (check-next-stream-line-equal _test-output-stream "      89/<- %edi 0x00000001/r32"  "F - test-fn-output-written-in-inner-block/11")
 3003     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %ecx"  "F - test-fn-output-written-in-inner-block/12")
 3004     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-fn-output-written-in-inner-block/13")
 3005     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-fn-output-written-in-inner-block/14")
 3006     (check-next-stream-line-equal _test-output-stream "    3d/compare-eax-with 0/imm32"  "F - test-fn-output-written-in-inner-block/15")
 3007     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-fn-output-written-in-inner-block/16")
 3008     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-fn-output-written-in-inner-block/17")
 3009     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-fn-output-written-in-inner-block/18")
 3010     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-fn-output-written-in-inner-block/19")
 3011     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-fn-output-written-in-inner-block/20")
 3012     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-fn-output-written-in-inner-block/21")
 3013     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-fn-output-written-in-inner-block/22")
 3014     # . epilogue
 3015     89/<- %esp 5/r32/ebp
 3016     5d/pop-to-ebp
 3017     c3/return
 3018 
 3019 test-convert-function-with-branches-in-block:
 3020     # . prologue
 3021     55/push-ebp
 3022     89/<- %ebp 4/r32/esp
 3023     # setup
 3024     (clear-stream _test-input-stream)
 3025     (clear-stream $_test-input-buffered-file->buffer)
 3026     (clear-stream _test-output-stream)
 3027     (clear-stream $_test-output-buffered-file->buffer)
 3028     #
 3029     (write _test-input-stream "fn foo x: int {\n")
 3030     (write _test-input-stream "  {\n")
 3031     (write _test-input-stream "    break-if->=\n")
 3032     (write _test-input-stream "    loop-if-addr<\n")
 3033     (write _test-input-stream "    increment x\n")
 3034     (write _test-input-stream "    loop\n")
 3035     (write _test-input-stream "  }\n")
 3036     (write _test-input-stream "}\n")
 3037     # convert
 3038     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3039     (flush _test-output-buffered-file)
 3040 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3046     # check output
 3047     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-block/0")
 3048     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-block/1")
 3049     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-block/2")
 3050     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-block/3")
 3051     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-block/4")
 3052     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-block/5")
 3053     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-block/6")
 3054     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-in-block/7")
 3055     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/8")
 3056     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-block/9")
 3057     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-in-block/10")
 3058     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/11")
 3059     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/12")
 3060     (check-next-stream-line-equal _test-output-stream "        0f 83/jump-if-addr>= break/disp32"  "F - test-convert-function-with-branches-in-block/13")
 3061     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:loop/disp32"  "F - test-convert-function-with-branches-in-block/14")
 3062     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/15")
 3063     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-block/16")
 3064     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-in-block/17")
 3065     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-block/18")
 3066     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-in-block/19")
 3067     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-block/20")
 3068     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-block/21")
 3069     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-block/22")
 3070     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-block/23")
 3071     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-block/24")
 3072     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-block/25")
 3073     # . epilogue
 3074     89/<- %esp 5/r32/ebp
 3075     5d/pop-to-ebp
 3076     c3/return
 3077 
 3078 test-convert-function-with-branches-in-named-block:
 3079     # . prologue
 3080     55/push-ebp
 3081     89/<- %ebp 4/r32/esp
 3082     # setup
 3083     (clear-stream _test-input-stream)
 3084     (clear-stream $_test-input-buffered-file->buffer)
 3085     (clear-stream _test-output-stream)
 3086     (clear-stream $_test-output-buffered-file->buffer)
 3087     #
 3088     (write _test-input-stream "fn foo x: int {\n")
 3089     (write _test-input-stream "  $bar: {\n")
 3090     (write _test-input-stream "    break-if->= $bar\n")
 3091     (write _test-input-stream "    loop-if-addr< $bar\n")
 3092     (write _test-input-stream "    increment x\n")
 3093     (write _test-input-stream "    loop\n")
 3094     (write _test-input-stream "  }\n")
 3095     (write _test-input-stream "}\n")
 3096     # convert
 3097     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3098     (flush _test-output-buffered-file)
 3099 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3105     # check output
 3106     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-named-block/0")
 3107     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-named-block/1")
 3108     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-named-block/2")
 3109     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-named-block/3")
 3110     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-named-block/4")
 3111     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-named-block/5")
 3112     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-named-block/6")
 3113     (check-next-stream-line-equal _test-output-stream "$bar:loop:"              "F - test-convert-function-with-branches-in-named-block/7")
 3114     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-named-block/8")
 3115     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-named-block/9")
 3116     (check-next-stream-line-equal _test-output-stream "        e9/jump $bar:break/disp32"  "F - test-convert-function-with-branches-in-named-block/10")
 3117     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-named-block/11")
 3118     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-named-block/12")
 3119     (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")
 3120     (check-next-stream-line-equal _test-output-stream "        e9/jump $bar:loop/disp32"  "F - test-convert-function-with-branches-in-named-block/14")
 3121     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-named-block/15")
 3122     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-named-block/16")
 3123     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"   "F - test-convert-function-with-branches-in-named-block/17")
 3124     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-named-block/18")
 3125     (check-next-stream-line-equal _test-output-stream "$bar:break:"             "F - test-convert-function-with-branches-in-named-block/19")
 3126     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-named-block/20")
 3127     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-named-block/21")
 3128     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-named-block/22")
 3129     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-named-block/23")
 3130     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-named-block/24")
 3131     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-named-block/25")
 3132     # . epilogue
 3133     89/<- %esp 5/r32/ebp
 3134     5d/pop-to-ebp
 3135     c3/return
 3136 
 3137 test-convert-function-with-var-in-nested-block:
 3138     # . prologue
 3139     55/push-ebp
 3140     89/<- %ebp 4/r32/esp
 3141     # setup
 3142     (clear-stream _test-input-stream)
 3143     (clear-stream $_test-input-buffered-file->buffer)
 3144     (clear-stream _test-output-stream)
 3145     (clear-stream $_test-output-buffered-file->buffer)
 3146     #
 3147     (write _test-input-stream "fn foo x: int {\n")
 3148     (write _test-input-stream "  {\n")
 3149     (write _test-input-stream "    {\n")
 3150     (write _test-input-stream "      var x: int\n")
 3151     (write _test-input-stream "      increment x\n")
 3152     (write _test-input-stream "    }\n")
 3153     (write _test-input-stream "  }\n")
 3154     (write _test-input-stream "}\n")
 3155     # convert
 3156     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3157     (flush _test-output-buffered-file)
 3158 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3164     # check output
 3165     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-var-in-nested-block/0")
 3166     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-var-in-nested-block/1")
 3167     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-var-in-nested-block/2")
 3168     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-var-in-nested-block/3")
 3169     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-var-in-nested-block/4")
 3170     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-var-in-nested-block/5")
 3171     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-var-in-nested-block/6")
 3172     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-var-in-nested-block/7")
 3173     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-var-in-nested-block/8")
 3174     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-var-in-nested-block/9")
 3175     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-var-in-nested-block/10")
 3176     (check-next-stream-line-equal _test-output-stream "        ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-var-in-nested-block/11")
 3177     (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")
 3178     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-var-in-nested-block/13")
 3179     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-var-in-nested-block/14")
 3180     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-var-in-nested-block/15")
 3181     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-var-in-nested-block/16")
 3182     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-var-in-nested-block/17")
 3183     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-var-in-nested-block/18")
 3184     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-var-in-nested-block/19")
 3185     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-var-in-nested-block/20")
 3186     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-var-in-nested-block/21")
 3187     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-var-in-nested-block/22")
 3188     # . epilogue
 3189     89/<- %esp 5/r32/ebp
 3190     5d/pop-to-ebp
 3191     c3/return
 3192 
 3193 test-convert-function-with-multiple-vars-in-nested-blocks:
 3194     # . prologue
 3195     55/push-ebp
 3196     89/<- %ebp 4/r32/esp
 3197     # setup
 3198     (clear-stream _test-input-stream)
 3199     (clear-stream $_test-input-buffered-file->buffer)
 3200     (clear-stream _test-output-stream)
 3201     (clear-stream $_test-output-buffered-file->buffer)
 3202     #
 3203     (write _test-input-stream "fn foo x: int {\n")
 3204     (write _test-input-stream "  {\n")
 3205     (write _test-input-stream "    var x/eax: int <- copy 0\n")
 3206     (write _test-input-stream "    {\n")
 3207     (write _test-input-stream "      var y: int\n")
 3208     (write _test-input-stream "      x <- add y\n")
 3209     (write _test-input-stream "    }\n")
 3210     (write _test-input-stream "  }\n")
 3211     (write _test-input-stream "}\n")
 3212     # convert
 3213     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3214     (flush _test-output-buffered-file)
 3215 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3221     # check output
 3222     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-multiple-vars-in-nested-blocks/0")
 3223     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-multiple-vars-in-nested-blocks/1")
 3224     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-multiple-vars-in-nested-blocks/2")
 3225     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/3")
 3226     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-multiple-vars-in-nested-blocks/4")
 3227     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/5")
 3228     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-multiple-vars-in-nested-blocks/6")
 3229     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/7")
 3230     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %eax"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/8")
 3231     (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")
 3232     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-multiple-vars-in-nested-blocks/10")
 3233     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/11")
 3234     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-multiple-vars-in-nested-blocks/12")
 3235     (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")
 3236     (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")
 3237     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-multiple-vars-in-nested-blocks/15")
 3238     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/16")
 3239     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %eax"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/17")
 3240     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-multiple-vars-in-nested-blocks/18")
 3241     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/19")
 3242     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-multiple-vars-in-nested-blocks/20")
 3243     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/21")
 3244     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-multiple-vars-in-nested-blocks/22")
 3245     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/23")
 3246     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-multiple-vars-in-nested-blocks/24")
 3247     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-multiple-vars-in-nested-blocks/25")
 3248     # . epilogue
 3249     89/<- %esp 5/r32/ebp
 3250     5d/pop-to-ebp
 3251     c3/return
 3252 
 3253 test-convert-function-with-branches-and-local-vars:
 3254     # A conditional 'break' after a 'var' in a block is converted into a
 3255     # nested block that performs all necessary cleanup before jumping. This
 3256     # results in some ugly code duplication.
 3257     # . prologue
 3258     55/push-ebp
 3259     89/<- %ebp 4/r32/esp
 3260     # setup
 3261     (clear-stream _test-input-stream)
 3262     (clear-stream $_test-input-buffered-file->buffer)
 3263     (clear-stream _test-output-stream)
 3264     (clear-stream $_test-output-buffered-file->buffer)
 3265     #
 3266     (write _test-input-stream "fn foo {\n")
 3267     (write _test-input-stream "  {\n")
 3268     (write _test-input-stream "    var x: int\n")
 3269     (write _test-input-stream "    break-if->=\n")
 3270     (write _test-input-stream "    increment x\n")
 3271     (write _test-input-stream "  }\n")
 3272     (write _test-input-stream "}\n")
 3273     # convert
 3274     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3275     (flush _test-output-buffered-file)
 3276 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3282     # check output
 3283     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-and-local-vars/0")
 3284     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-and-local-vars/1")
 3285     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-and-local-vars/2")
 3286     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-and-local-vars/3")
 3287     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-and-local-vars/4")
 3288     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-and-local-vars/5")
 3289     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-and-local-vars/6")
 3290     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-and-local-vars/7")
 3291     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-branches-and-local-vars/8")
 3292     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-and-local-vars/9")
 3293     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-and-local-vars/10")
 3294     (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")
 3295     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-and-local-vars/12")
 3296     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-and-local-vars/13")
 3297     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-branches-and-local-vars/14")
 3298     (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")
 3299     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-and-local-vars/16")
 3300     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-and-local-vars/17")
 3301     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-and-local-vars/18")
 3302     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-and-local-vars/19")
 3303     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-and-local-vars/20")
 3304     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-and-local-vars/21")
 3305     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-and-local-vars/22")
 3306     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-and-local-vars/23")
 3307     # . epilogue
 3308     89/<- %esp 5/r32/ebp
 3309     5d/pop-to-ebp
 3310     c3/return
 3311 
 3312 test-convert-function-with-conditional-loops-and-local-vars:
 3313     # A conditional 'loop' after a 'var' in a block is converted into a nested
 3314     # block that performs all necessary cleanup before jumping. This results
 3315     # in some ugly code duplication.
 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     #
 3325     (write _test-input-stream "fn foo {\n")
 3326     (write _test-input-stream "  {\n")
 3327     (write _test-input-stream "    var x: int\n")
 3328     (write _test-input-stream "    loop-if->=\n")
 3329     (write _test-input-stream "    increment x\n")
 3330     (write _test-input-stream "  }\n")
 3331     (write _test-input-stream "}\n")
 3332     # convert
 3333     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3334     (flush _test-output-buffered-file)
 3335 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3341     # check output
 3342     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-conditional-loops-and-local-vars/0")
 3343     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-conditional-loops-and-local-vars/1")
 3344     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-conditional-loops-and-local-vars/2")
 3345     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-conditional-loops-and-local-vars/3")
 3346     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-conditional-loops-and-local-vars/4")
 3347     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-conditional-loops-and-local-vars/5")
 3348     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-conditional-loops-and-local-vars/6")
 3349     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-conditional-loops-and-local-vars/7")
 3350     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-conditional-loops-and-local-vars/8")
 3351     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-conditional-loops-and-local-vars/9")
 3352     (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")
 3353     (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")
 3354     (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")
 3355     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-conditional-loops-and-local-vars/13")
 3356     (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")
 3357     (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")
 3358     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-conditional-loops-and-local-vars/16")
 3359     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-conditional-loops-and-local-vars/17")
 3360     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-conditional-loops-and-local-vars/18")
 3361     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-conditional-loops-and-local-vars/19")
 3362     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-conditional-loops-and-local-vars/20")
 3363     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-conditional-loops-and-local-vars/21")
 3364     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-conditional-loops-and-local-vars/22")
 3365     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-conditional-loops-and-local-vars/23")
 3366     # . epilogue
 3367     89/<- %esp 5/r32/ebp
 3368     5d/pop-to-ebp
 3369     c3/return
 3370 
 3371 test-convert-function-with-unconditional-loops-and-local-vars:
 3372     # An unconditional 'loop' after a 'var' in a block is emitted _after_ the
 3373     # regular block cleanup. Any instructions after 'loop' are dead and
 3374     # therefore skipped.
 3375     # . prologue
 3376     55/push-ebp
 3377     89/<- %ebp 4/r32/esp
 3378     # setup
 3379     (clear-stream _test-input-stream)
 3380     (clear-stream $_test-input-buffered-file->buffer)
 3381     (clear-stream _test-output-stream)
 3382     (clear-stream $_test-output-buffered-file->buffer)
 3383     #
 3384     (write _test-input-stream "fn foo {\n")
 3385     (write _test-input-stream "  {\n")
 3386     (write _test-input-stream "    var x: int\n")
 3387     (write _test-input-stream "    loop\n")
 3388     (write _test-input-stream "    increment x\n")
 3389     (write _test-input-stream "  }\n")
 3390     (write _test-input-stream "}\n")
 3391     # convert
 3392     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3393     (flush _test-output-buffered-file)
 3394 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3400     # check output
 3401     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-unconditional-loops-and-local-vars/0")
 3402     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-unconditional-loops-and-local-vars/1")
 3403     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-unconditional-loops-and-local-vars/2")
 3404     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-unconditional-loops-and-local-vars/3")
 3405     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-unconditional-loops-and-local-vars/4")
 3406     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-unconditional-loops-and-local-vars/5")
 3407     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-unconditional-loops-and-local-vars/6")
 3408     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-unconditional-loops-and-local-vars/7")
 3409     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-unconditional-loops-and-local-vars/8")
 3410     (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")
 3411     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-unconditional-loops-and-local-vars/10")
 3412     # not emitted:                                           ff 0/subop/increment *(ebp+0xfffffffc)
 3413     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-unconditional-loops-and-local-vars/11")
 3414     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-unconditional-loops-and-local-vars/12")
 3415     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-unconditional-loops-and-local-vars/13")
 3416     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-unconditional-loops-and-local-vars/14")
 3417     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-unconditional-loops-and-local-vars/15")
 3418     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-unconditional-loops-and-local-vars/16")
 3419     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-unconditional-loops-and-local-vars/17")
 3420     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-unconditional-loops-and-local-vars/18")
 3421     # . epilogue
 3422     89/<- %esp 5/r32/ebp
 3423     5d/pop-to-ebp
 3424     c3/return
 3425 
 3426 test-convert-function-with-branches-and-loops-and-local-vars:
 3427     # . prologue
 3428     55/push-ebp
 3429     89/<- %ebp 4/r32/esp
 3430     # setup
 3431     (clear-stream _test-input-stream)
 3432     (clear-stream $_test-input-buffered-file->buffer)
 3433     (clear-stream _test-output-stream)
 3434     (clear-stream $_test-output-buffered-file->buffer)
 3435     #
 3436     (write _test-input-stream "fn foo {\n")
 3437     (write _test-input-stream "  {\n")
 3438     (write _test-input-stream "    var x: int\n")
 3439     (write _test-input-stream "    break-if->=\n")
 3440     (write _test-input-stream "    increment x\n")
 3441     (write _test-input-stream "    loop\n")
 3442     (write _test-input-stream "  }\n")
 3443     (write _test-input-stream "}\n")
 3444     # convert
 3445     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3446     (flush _test-output-buffered-file)
 3447 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3453     # check output
 3454     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-and-loops-and-local-vars/0")
 3455     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-and-loops-and-local-vars/1")
 3456     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-and-loops-and-local-vars/2")
 3457     (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")
 3458     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-and-loops-and-local-vars/4")
 3459     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-and-loops-and-local-vars/5")
 3460     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-and-loops-and-local-vars/6")
 3461     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-and-loops-and-local-vars/7")
 3462     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-branches-and-loops-and-local-vars/8")
 3463     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-and-loops-and-local-vars/9")
 3464     (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")
 3465     (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")
 3466     (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")
 3467     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-and-loops-and-local-vars/13")
 3468     (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")
 3469     (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")
 3470     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-and-loops-and-local-vars/16")
 3471     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-and-loops-and-local-vars/17")
 3472     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-and-loops-and-local-vars/18")
 3473     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-and-loops-and-local-vars/19")
 3474     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-and-loops-and-local-vars/20")
 3475     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-and-loops-and-local-vars/21")
 3476     (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")
 3477     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-and-loops-and-local-vars/23")
 3478     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-and-loops-and-local-vars/24")
 3479     # . epilogue
 3480     89/<- %esp 5/r32/ebp
 3481     5d/pop-to-ebp
 3482     c3/return
 3483 
 3484 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars:
 3485     # . prologue
 3486     55/push-ebp
 3487     89/<- %ebp 4/r32/esp
 3488     # setup
 3489     (clear-stream _test-input-stream)
 3490     (clear-stream $_test-input-buffered-file->buffer)
 3491     (clear-stream _test-output-stream)
 3492     (clear-stream $_test-output-buffered-file->buffer)
 3493     #
 3494     (write _test-input-stream "fn foo {\n")
 3495     (write _test-input-stream "  a: {\n")
 3496     (write _test-input-stream "    var x: int\n")
 3497     (write _test-input-stream "    {\n")
 3498     (write _test-input-stream "      var y: int\n")
 3499     (write _test-input-stream "      break-if->= a\n")
 3500     (write _test-input-stream "      increment x\n")
 3501     (write _test-input-stream "      loop\n")
 3502     (write _test-input-stream "    }\n")
 3503     (write _test-input-stream "  }\n")
 3504     (write _test-input-stream "}\n")
 3505     # convert
 3506     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3507     (flush _test-output-buffered-file)
 3508 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3514     # check output
 3515     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/0")
 3516     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/1")
 3517     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/2")
 3518     (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")
 3519     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/4")
 3520     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/5")
 3521     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/6")
 3522     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/7")
 3523     (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")
 3524     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/9")
 3525     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/10")
 3526     (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")
 3527     (check-next-stream-line-equal _test-output-stream "        {"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/12")
 3528     (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")
 3529     (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")
 3530     (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")
 3531     (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")
 3532     (check-next-stream-line-equal _test-output-stream "        }"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/17")
 3533     (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")
 3534     (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")
 3535     (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")
 3536     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/21")
 3537     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/22")
 3538     (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")
 3539     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/24")
 3540     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/25")
 3541     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/26")
 3542     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/27")
 3543     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/28")
 3544     (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")
 3545     (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")
 3546     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/31")
 3547     # . epilogue
 3548     89/<- %esp 5/r32/ebp
 3549     5d/pop-to-ebp
 3550     c3/return
 3551 
 3552 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2:
 3553     # . prologue
 3554     55/push-ebp
 3555     89/<- %ebp 4/r32/esp
 3556     # setup
 3557     (clear-stream _test-input-stream)
 3558     (clear-stream $_test-input-buffered-file->buffer)
 3559     (clear-stream _test-output-stream)
 3560     (clear-stream $_test-output-buffered-file->buffer)
 3561     # non-local conditional branch from a block without a local variable,
 3562     # unwinding a local on the stack
 3563     (write _test-input-stream "fn foo {\n")
 3564     (write _test-input-stream "  a: {\n")
 3565     (write _test-input-stream "    var x: int\n")
 3566     (write _test-input-stream "    {\n")
 3567     (write _test-input-stream "      break-if->= a\n")
 3568     (write _test-input-stream "    }\n")
 3569     (write _test-input-stream "  }\n")
 3570     (write _test-input-stream "}\n")
 3571     # convert
 3572     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3573     (flush _test-output-buffered-file)
 3574 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3580     # check output
 3581     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/0")
 3582     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/1")
 3583     (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")
 3584     (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")
 3585     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/4")
 3586     (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")
 3587     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/6")
 3588     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/7")
 3589     (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")
 3590     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/9")
 3591     (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")
 3592     (check-next-stream-line-equal _test-output-stream "        {"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/11")
 3593     (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")
 3594     (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")
 3595     (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")
 3596     (check-next-stream-line-equal _test-output-stream "        }"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/15")
 3597     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/16")
 3598     (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")
 3599     (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")
 3600     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/19")
 3601     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/20")
 3602     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/21")
 3603     (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")
 3604     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/23")
 3605     (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")
 3606     (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")
 3607     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/26")
 3608     # . epilogue
 3609     89/<- %esp 5/r32/ebp
 3610     5d/pop-to-ebp
 3611     c3/return
 3612 
 3613 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3:
 3614     # . prologue
 3615     55/push-ebp
 3616     89/<- %ebp 4/r32/esp
 3617     # setup
 3618     (clear-stream _test-input-stream)
 3619     (clear-stream $_test-input-buffered-file->buffer)
 3620     (clear-stream _test-output-stream)
 3621     (clear-stream $_test-output-buffered-file->buffer)
 3622     # non-local unconditional branch from a block without a local variable,
 3623     # unwinding a local on the stack
 3624     (write _test-input-stream "fn foo {\n")
 3625     (write _test-input-stream "  a: {\n")
 3626     (write _test-input-stream "    var x: int\n")
 3627     (write _test-input-stream "    {\n")
 3628     (write _test-input-stream "      break a\n")
 3629     (write _test-input-stream "    }\n")
 3630     (write _test-input-stream "  }\n")
 3631     (write _test-input-stream "}\n")
 3632     # convert
 3633     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3634     (flush _test-output-buffered-file)
 3635 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3641     # check output
 3642     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/0")
 3643     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/1")
 3644     (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")
 3645     (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")
 3646     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/4")
 3647     (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")
 3648     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/6")
 3649     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/7")
 3650     (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")
 3651     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/9")
 3652     (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")
 3653     (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")
 3654     (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")
 3655     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/14")
 3656     (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")
 3657     (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")
 3658     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/17")
 3659     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/18")
 3660     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/19")
 3661     (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")
 3662     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/21")
 3663     (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")
 3664     (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")
 3665     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/24")
 3666     # . epilogue
 3667     89/<- %esp 5/r32/ebp
 3668     5d/pop-to-ebp
 3669     c3/return
 3670 
 3671 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4:
 3672     # . prologue
 3673     55/push-ebp
 3674     89/<- %ebp 4/r32/esp
 3675     # setup
 3676     (clear-stream _test-input-stream)
 3677     (clear-stream $_test-input-buffered-file->buffer)
 3678     (clear-stream _test-output-stream)
 3679     (clear-stream $_test-output-buffered-file->buffer)
 3680     #
 3681     (write _test-input-stream "fn foo {\n")
 3682     (write _test-input-stream "  a: {\n")
 3683     (write _test-input-stream "    var x/esi: int <- copy 0\n")
 3684     (write _test-input-stream "    {\n")
 3685     (write _test-input-stream "      break a\n")
 3686     (write _test-input-stream "    }\n")
 3687     (write _test-input-stream "  }\n")
 3688     (write _test-input-stream "}\n")
 3689     # convert
 3690     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3691     (flush _test-output-buffered-file)
 3692 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3698     # check output
 3699     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/0")
 3700     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/1")
 3701     (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")
 3702     (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")
 3703     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/4")
 3704     (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")
 3705     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/6")
 3706     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/7")
 3707     (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")
 3708     (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")
 3709     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/10")
 3710     (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")
 3711     (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")
 3712     (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")
 3713     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/14")
 3714     (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")
 3715     (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")
 3716     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/17")
 3717     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/18")
 3718     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/19")
 3719     (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")
 3720     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/21")
 3721     (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")
 3722     (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")
 3723     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/24")
 3724     # . epilogue
 3725     89/<- %esp 5/r32/ebp
 3726     5d/pop-to-ebp
 3727     c3/return
 3728 
 3729 test-convert-function-with-nonlocal-unconditional-break-and-local-vars:
 3730     # . prologue
 3731     55/push-ebp
 3732     89/<- %ebp 4/r32/esp
 3733     # setup
 3734     (clear-stream _test-input-stream)
 3735     (clear-stream $_test-input-buffered-file->buffer)
 3736     (clear-stream _test-output-stream)
 3737     (clear-stream $_test-output-buffered-file->buffer)
 3738     #
 3739     (write _test-input-stream "fn foo {\n")
 3740     (write _test-input-stream "  a: {\n")
 3741     (write _test-input-stream "    var x: int\n")
 3742     (write _test-input-stream "    {\n")
 3743     (write _test-input-stream "      var y: int\n")
 3744     (write _test-input-stream "      break a\n")
 3745     (write _test-input-stream "      increment x\n")
 3746     (write _test-input-stream "    }\n")
 3747     (write _test-input-stream "  }\n")
 3748     (write _test-input-stream "}\n")
 3749     # convert
 3750     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3751     (flush _test-output-buffered-file)
 3752 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3758     # check output
 3759     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/0")
 3760     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/1")
 3761     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/2")
 3762     (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")
 3763     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/4")
 3764     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/5")
 3765     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/6")
 3766     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/7")
 3767     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/8")
 3768     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/9")
 3769     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/10")
 3770     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/11")
 3771     (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")
 3772     (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")
 3773     (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")
 3774     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/15")
 3775     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/16")
 3776     (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")
 3777     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/18")
 3778     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/19")
 3779     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/20")
 3780     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/21")
 3781     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/22")
 3782     (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")
 3783     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/24")
 3784     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/25")
 3785     # . epilogue
 3786     89/<- %esp 5/r32/ebp
 3787     5d/pop-to-ebp
 3788     c3/return
 3789 
 3790 test-convert-function-with-unconditional-break-and-local-vars:
 3791     # . prologue
 3792     55/push-ebp
 3793     89/<- %ebp 4/r32/esp
 3794     # setup
 3795     (clear-stream _test-input-stream)
 3796     (clear-stream $_test-input-buffered-file->buffer)
 3797     (clear-stream _test-output-stream)
 3798     (clear-stream $_test-output-buffered-file->buffer)
 3799     #
 3800     (write _test-input-stream "fn foo {\n")
 3801     (write _test-input-stream "  {\n")
 3802     (write _test-input-stream "    var x: int\n")
 3803     (write _test-input-stream "    {\n")
 3804     (write _test-input-stream "      var y: int\n")
 3805     (write _test-input-stream "      break\n")
 3806     (write _test-input-stream "      increment x\n")
 3807     (write _test-input-stream "    }\n")
 3808     (write _test-input-stream "  }\n")
 3809     (write _test-input-stream "}\n")
 3810     # convert
 3811     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3812     (flush _test-output-buffered-file)
 3813 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3819     # check output
 3820     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-unconditional-break-and-local-vars/0")
 3821     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-unconditional-break-and-local-vars/1")
 3822     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-unconditional-break-and-local-vars/2")
 3823     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-unconditional-break-and-local-vars/3")
 3824     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-unconditional-break-and-local-vars/4")
 3825     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/5")
 3826     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-unconditional-break-and-local-vars/6")
 3827     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/7")
 3828     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-unconditional-break-and-local-vars/8")
 3829     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-unconditional-break-and-local-vars/9")
 3830     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/10")
 3831     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-unconditional-break-and-local-vars/11")
 3832     (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")
 3833     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-unconditional-break-and-local-vars/13")
 3834     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/14")
 3835     (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")
 3836     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-unconditional-break-and-local-vars/16")
 3837     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/17")
 3838     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-unconditional-break-and-local-vars/18")
 3839     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/19")
 3840     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-unconditional-break-and-local-vars/20")
 3841     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-unconditional-break-and-local-vars/21")
 3842     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-unconditional-break-and-local-vars/22")
 3843     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-unconditional-break-and-local-vars/23")
 3844     # . epilogue
 3845     89/<- %esp 5/r32/ebp
 3846     5d/pop-to-ebp
 3847     c3/return
 3848 
 3849 test-convert-function-with-nonlocal-unconditional-loop-and-local-vars:
 3850     # . prologue
 3851     55/push-ebp
 3852     89/<- %ebp 4/r32/esp
 3853     # setup
 3854     (clear-stream _test-input-stream)
 3855     (clear-stream $_test-input-buffered-file->buffer)
 3856     (clear-stream _test-output-stream)
 3857     (clear-stream $_test-output-buffered-file->buffer)
 3858     #
 3859     (write _test-input-stream "fn foo {\n")
 3860     (write _test-input-stream "  a: {\n")
 3861     (write _test-input-stream "    var x: int\n")
 3862     (write _test-input-stream "    {\n")
 3863     (write _test-input-stream "      var y: int\n")
 3864     (write _test-input-stream "      loop a\n")
 3865     (write _test-input-stream "      increment x\n")
 3866     (write _test-input-stream "    }\n")
 3867     (write _test-input-stream "  }\n")
 3868     (write _test-input-stream "}\n")
 3869     # convert
 3870     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3871     (flush _test-output-buffered-file)
 3872 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3878     # check output
 3879     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/0")
 3880     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/1")
 3881     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/2")
 3882     (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")
 3883     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/4")
 3884     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/5")
 3885     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/6")
 3886     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/7")
 3887     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/8")
 3888     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/9")
 3889     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/10")
 3890     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/11")
 3891     (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")
 3892     (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")
 3893     (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")
 3894     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/15")
 3895     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/16")
 3896     (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")
 3897     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/18")
 3898     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/19")
 3899     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/20")
 3900     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/21")
 3901     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/22")
 3902     (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")
 3903     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/24")
 3904     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/25")
 3905     # . epilogue
 3906     89/<- %esp 5/r32/ebp
 3907     5d/pop-to-ebp
 3908     c3/return
 3909 
 3910 test-convert-function-with-local-array-var-in-mem:
 3911     # . prologue
 3912     55/push-ebp
 3913     89/<- %ebp 4/r32/esp
 3914     # setup
 3915     (clear-stream _test-input-stream)
 3916     (clear-stream $_test-input-buffered-file->buffer)
 3917     (clear-stream _test-output-stream)
 3918     (clear-stream $_test-output-buffered-file->buffer)
 3919     #
 3920     (write _test-input-stream "fn foo {\n")
 3921     (write _test-input-stream "  var x: (array int 3)\n")
 3922     (write _test-input-stream "}\n")
 3923     # convert
 3924     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3925     (flush _test-output-buffered-file)
 3926 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3932     # check output
 3933     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-array-var-in-mem/0")
 3934     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-array-var-in-mem/1")
 3935     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-array-var-in-mem/2")
 3936     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-array-var-in-mem/3")
 3937     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-array-var-in-mem/4")
 3938     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-array-var-in-mem/5")
 3939     # define x
 3940     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"  "F - test-convert-function-with-local-array-var-in-mem/7")
 3941     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"  "F - test-convert-function-with-local-array-var-in-mem/8")
 3942     # reclaim x
 3943     (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")
 3944     #
 3945     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-array-var-in-mem/10")
 3946     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-array-var-in-mem/11")
 3947     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-array-var-in-mem/12")
 3948     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-array-var-in-mem/13")
 3949     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-array-var-in-mem/14")
 3950     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-array-var-in-mem/15")
 3951     # . epilogue
 3952     89/<- %esp 5/r32/ebp
 3953     5d/pop-to-ebp
 3954     c3/return
 3955 
 3956 test-array-size-in-hex:
 3957     # . prologue
 3958     55/push-ebp
 3959     89/<- %ebp 4/r32/esp
 3960     # setup
 3961     (clear-stream _test-input-stream)
 3962     (clear-stream $_test-input-buffered-file->buffer)
 3963     (clear-stream _test-output-stream)
 3964     (clear-stream $_test-output-buffered-file->buffer)
 3965     (clear-stream _test-error-stream)
 3966     (clear-stream $_test-error-buffered-file->buffer)
 3967     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3968     68/push 0/imm32
 3969     68/push 0/imm32
 3970     89/<- %edx 4/r32/esp
 3971     (tailor-exit-descriptor %edx 0x10)
 3972     #
 3973     (write _test-input-stream "fn foo {\n")
 3974     (write _test-input-stream "  var x: (array int 10)\n")
 3975     (write _test-input-stream "}\n")
 3976     # convert
 3977     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3978     # registers except esp clobbered at this point
 3979     # restore ed
 3980     89/<- %edx 4/r32/esp
 3981     (flush _test-output-buffered-file)
 3982     (flush _test-error-buffered-file)
 3983 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3989     # check output
 3990     (check-stream-equal _test-output-stream  ""  "F - test-array-size-in-hex: output should be empty")
 3991     (check-next-stream-line-equal _test-error-stream  "literal integers are always hex in Mu; either start '10' with a '0x' to be unambiguous, or convert it to decimal."  "F - test-array-size-in-hex: error message")
 3992     # check that stop(1) was called
 3993     (check-ints-equal *(edx+4) 2 "F - test-array-size-in-hex: exit status")
 3994     # don't restore from ebp
 3995     81 0/subop/add %esp 8/imm32
 3996     # . epilogue
 3997     5d/pop-to-ebp
 3998     c3/return
 3999 
 4000 test-convert-function-with-populate:
 4001     # . prologue
 4002     55/push-ebp
 4003     89/<- %ebp 4/r32/esp
 4004     # setup
 4005     (clear-stream _test-input-stream)
 4006     (clear-stream $_test-input-buffered-file->buffer)
 4007     (clear-stream _test-output-stream)
 4008     (clear-stream $_test-output-buffered-file->buffer)
 4009     #
 4010     (write _test-input-stream "fn foo {\n")
 4011     (write _test-input-stream "  var x/ecx: (addr handle array int) <- copy 0\n")
 4012     (write _test-input-stream "  populate x, 7\n")
 4013     (write _test-input-stream "}\n")
 4014     # convert
 4015     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4016     (flush _test-output-buffered-file)
 4017 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4023     # check output
 4024     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-populate/0")
 4025     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-populate/1")
 4026     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-populate/2")
 4027     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-populate/3")
 4028     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-populate/4")
 4029     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-populate/5")
 4030     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-populate/6")
 4031     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-populate/7")
 4032     (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)
 4033     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-populate/9")
 4034     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-populate/10")
 4035     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-populate/11")
 4036     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-populate/12")
 4037     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-populate/13")
 4038     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-populate/14")
 4039     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-populate/15")
 4040     # . epilogue
 4041     89/<- %esp 5/r32/ebp
 4042     5d/pop-to-ebp
 4043     c3/return
 4044 
 4045 # special-case for size(byte) when allocating array
 4046 test-convert-function-with-local-array-of-bytes-in-mem:
 4047     # . prologue
 4048     55/push-ebp
 4049     89/<- %ebp 4/r32/esp
 4050     # setup
 4051     (clear-stream _test-input-stream)
 4052     (clear-stream $_test-input-buffered-file->buffer)
 4053     (clear-stream _test-output-stream)
 4054     (clear-stream $_test-output-buffered-file->buffer)
 4055     #
 4056     (write _test-input-stream "fn foo {\n")
 4057     (write _test-input-stream "  var x: (array byte 3)\n")
 4058     (write _test-input-stream "}\n")
 4059     # convert
 4060     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4061     (flush _test-output-buffered-file)
 4062 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4068     # check output
 4069     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-array-of-bytes-in-mem/0")
 4070     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-array-of-bytes-in-mem/1")
 4071     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-array-of-bytes-in-mem/2")
 4072     (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")
 4073     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-array-of-bytes-in-mem/4")
 4074     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-array-of-bytes-in-mem/5")
 4075     # define x
 4076     (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")
 4077     (check-next-stream-line-equal _test-output-stream "    68/push 0x00000003/imm32"  "F - test-convert-function-with-local-array-of-bytes-in-mem/8")
 4078     # reclaim x
 4079     (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")
 4080     #
 4081     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-array-of-bytes-in-mem/10")
 4082     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-array-of-bytes-in-mem/11")
 4083     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-array-of-bytes-in-mem/12")
 4084     (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")
 4085     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-array-of-bytes-in-mem/14")
 4086     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-array-of-bytes-in-mem/15")
 4087     # . epilogue
 4088     89/<- %esp 5/r32/ebp
 4089     5d/pop-to-ebp
 4090     c3/return
 4091 
 4092 test-convert-address:
 4093     # . prologue
 4094     55/push-ebp
 4095     89/<- %ebp 4/r32/esp
 4096     # setup
 4097     (clear-stream _test-input-stream)
 4098     (clear-stream $_test-input-buffered-file->buffer)
 4099     (clear-stream _test-output-stream)
 4100     (clear-stream $_test-output-buffered-file->buffer)
 4101     #
 4102     (write _test-input-stream "fn foo {\n")
 4103     (write _test-input-stream "  var a: int\n")
 4104     (write _test-input-stream "  var b/eax: (addr int) <- address a\n")
 4105     (write _test-input-stream "}\n")
 4106     # convert
 4107     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4108     (flush _test-output-buffered-file)
 4109 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4115     # check output
 4116     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-address/0")
 4117     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-address/1")
 4118     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-address/2")
 4119     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-address/3")
 4120     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-address/4")
 4121     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-address/5")
 4122     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-address/6")
 4123     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-address/7")
 4124     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0xfffffffc) 0x00000000/r32"  "F - test-convert-address/8")
 4125     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-address/9")
 4126     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-address/10")
 4127     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-address/11")
 4128     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-address/12")
 4129     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-address/13")
 4130     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-address/14")
 4131     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-address/15")
 4132     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-address/16")
 4133     # . epilogue
 4134     89/<- %esp 5/r32/ebp
 4135     5d/pop-to-ebp
 4136     c3/return
 4137 
 4138 test-convert-length-of-array:
 4139     # . prologue
 4140     55/push-ebp
 4141     89/<- %ebp 4/r32/esp
 4142     # setup
 4143     (clear-stream _test-input-stream)
 4144     (clear-stream $_test-input-buffered-file->buffer)
 4145     (clear-stream _test-output-stream)
 4146     (clear-stream $_test-output-buffered-file->buffer)
 4147     #
 4148     (write _test-input-stream "fn foo a: (addr array int) {\n")
 4149     (write _test-input-stream "  var b/eax: (addr array int) <- copy a\n")
 4150     (write _test-input-stream "  var c/eax: int <- length b\n")
 4151     (write _test-input-stream "}\n")
 4152     # convert
 4153     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4154     (flush _test-output-buffered-file)
 4155 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4161     # check output
 4162     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array/0")
 4163     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array/1")
 4164     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array/2")
 4165     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array/3")
 4166     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array/4")
 4167     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array/5")
 4168     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array/6")
 4169     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-length-of-array/7")
 4170     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array/8")
 4171     (check-next-stream-line-equal _test-output-stream "    c1/shift 5/subop/>> %eax 0x00000002/imm8"  "F - test-convert-length-of-array/9")
 4172     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array/10")
 4173     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array/11")
 4174     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array/12")
 4175     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array/13")
 4176     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array/14")
 4177     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array/15")
 4178     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array/16")
 4179     # . epilogue
 4180     89/<- %esp 5/r32/ebp
 4181     5d/pop-to-ebp
 4182     c3/return
 4183 
 4184 # special-case for size(byte) when computing array length
 4185 test-convert-length-of-array-of-bytes:
 4186     # . prologue
 4187     55/push-ebp
 4188     89/<- %ebp 4/r32/esp
 4189     # setup
 4190     (clear-stream _test-input-stream)
 4191     (clear-stream $_test-input-buffered-file->buffer)
 4192     (clear-stream _test-output-stream)
 4193     (clear-stream $_test-output-buffered-file->buffer)
 4194     #
 4195     (write _test-input-stream "fn foo a: (addr array byte) {\n")
 4196     (write _test-input-stream "  var b/eax: (addr array byte) <- copy a\n")
 4197     (write _test-input-stream "  var c/eax: int <- length b\n")
 4198     (write _test-input-stream "}\n")
 4199     # convert
 4200     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4201     (flush _test-output-buffered-file)
 4202 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4208     # check output
 4209     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-bytes/0")
 4210     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-bytes/1")
 4211     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-bytes/2")
 4212     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-bytes/3")
 4213     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-bytes/4")
 4214     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-bytes/5")
 4215     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-of-bytes/6")
 4216     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-length-of-array-of-bytes/7")
 4217     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array-of-bytes/8")
 4218     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-of-bytes/9")
 4219     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-bytes/10")
 4220     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-bytes/11")
 4221     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-bytes/12")
 4222     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-of-bytes/13")
 4223     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-of-bytes/14")
 4224     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-bytes/15")
 4225     # . epilogue
 4226     89/<- %esp 5/r32/ebp
 4227     5d/pop-to-ebp
 4228     c3/return
 4229 
 4230 test-convert-length-of-array-on-stack:
 4231     # . prologue
 4232     55/push-ebp
 4233     89/<- %ebp 4/r32/esp
 4234     # setup
 4235     (clear-stream _test-input-stream)
 4236     (clear-stream $_test-input-buffered-file->buffer)
 4237     (clear-stream _test-output-stream)
 4238     (clear-stream $_test-output-buffered-file->buffer)
 4239     #
 4240     (write _test-input-stream "fn foo {\n")
 4241     (write _test-input-stream "  var a: (array int 3)\n")
 4242     (write _test-input-stream "  var b/eax: int <- length a\n")
 4243     (write _test-input-stream "}\n")
 4244     # convert
 4245     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4246     (flush _test-output-buffered-file)
 4247 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4253     # check output
 4254     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-on-stack/0")
 4255     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-on-stack/1")
 4256     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-on-stack/2")
 4257     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-on-stack/3")
 4258     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-on-stack/4")
 4259     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-on-stack/5")
 4260     # define x
 4261     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"  "F - test-convert-length-of-array-on-stack/6")
 4262     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"  "F - test-convert-length-of-array-on-stack/7")
 4263     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-on-stack/8")
 4264     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0xfffffff0) 0x00000000/r32"  "F - test-convert-length-of-array-on-stack/9")
 4265     (check-next-stream-line-equal _test-output-stream "    c1/shift 5/subop/>> %eax 0x00000002/imm8"  "F - test-convert-length-of-array-on-stack/10")
 4266     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-on-stack/11")
 4267     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"  "F - test-convert-length-of-array-on-stack/12")
 4268     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-on-stack/13")
 4269     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-on-stack/14")
 4270     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-on-stack/15")
 4271     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-on-stack/16")
 4272     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-on-stack/17")
 4273     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-on-stack/18")
 4274     # . epilogue
 4275     89/<- %esp 5/r32/ebp
 4276     5d/pop-to-ebp
 4277     c3/return
 4278 
 4279 test-reg-var-def-with-read-of-same-register:
 4280     # . prologue
 4281     55/push-ebp
 4282     89/<- %ebp 4/r32/esp
 4283     # setup
 4284     (clear-stream _test-input-stream)
 4285     (clear-stream $_test-input-buffered-file->buffer)
 4286     (clear-stream _test-output-stream)
 4287     (clear-stream $_test-output-buffered-file->buffer)
 4288     (clear-stream _test-error-stream)
 4289     (clear-stream $_test-error-buffered-file->buffer)
 4290     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
 4291     68/push 0/imm32
 4292     68/push 0/imm32
 4293     89/<- %edx 4/r32/esp
 4294     (tailor-exit-descriptor %edx 0x10)
 4295     #
 4296     (write _test-input-stream "fn foo {\n")
 4297     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 4298     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 4299     (write _test-input-stream "  var x/eax: (addr int) <- index arr, idx\n")
 4300     (write _test-input-stream "}\n")
 4301     # convert
 4302     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 4303     # registers except esp could be clobbered at this point (though they shouldn't be)
 4304     # restore ed
 4305     89/<- %edx 4/r32/esp
 4306     (flush _test-output-buffered-file)
 4307     (flush _test-error-buffered-file)
 4308 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4314 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4320     (check-stream-equal _test-error-stream  ""  "F - test-reg-var-def-with-read-of-same-register: error stream should be empty")
 4321     # check output
 4322     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-reg-var-def-with-read-of-same-register/0")
 4323     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-reg-var-def-with-read-of-same-register/1")
 4324     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-reg-var-def-with-read-of-same-register/2")
 4325     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-reg-var-def-with-read-of-same-register/3")
 4326     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-reg-var-def-with-read-of-same-register/4")
 4327     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-reg-var-def-with-read-of-same-register/5")
 4328     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-reg-var-def-with-read-of-same-register/6")
 4329     (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")
 4330     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-reg-var-def-with-read-of-same-register/8")
 4331     (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")
 4332     (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")
 4333     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-reg-var-def-with-read-of-same-register/13")
 4334     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-reg-var-def-with-read-of-same-register/14")
 4335     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-reg-var-def-with-read-of-same-register/15")
 4336     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-reg-var-def-with-read-of-same-register/16")
 4337     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-reg-var-def-with-read-of-same-register/17")
 4338     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-reg-var-def-with-read-of-same-register/18")
 4339     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-reg-var-def-with-read-of-same-register/19")
 4340     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-reg-var-def-with-read-of-same-register/20")
 4341     # don't restore from ebp
 4342     81 0/subop/add %esp 8/imm32
 4343     # . epilogue
 4344     5d/pop-to-ebp
 4345     c3/return
 4346 
 4347 test-convert-index-into-array:
 4348     # . prologue
 4349     55/push-ebp
 4350     89/<- %ebp 4/r32/esp
 4351     # setup
 4352     (clear-stream _test-input-stream)
 4353     (clear-stream $_test-input-buffered-file->buffer)
 4354     (clear-stream _test-output-stream)
 4355     (clear-stream $_test-output-buffered-file->buffer)
 4356     #
 4357     (write _test-input-stream "fn foo {\n")
 4358     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 4359     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 4360     (write _test-input-stream "  var x/eax: (addr int) <- index arr, idx\n")
 4361     (write _test-input-stream "}\n")
 4362     # convert
 4363     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4364     (flush _test-output-buffered-file)
 4365 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4371     # check output
 4372     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array/0")
 4373     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array/1")
 4374     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array/2")
 4375     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array/3")
 4376     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array/4")
 4377     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array/5")
 4378     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array/6")
 4379     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array/7")
 4380     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array/8")
 4381     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array/9")
 4382     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx<<0x00000002 + 4) 0x00000000/r32"  "F - test-convert-index-into-array/10")
 4383     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array/11")
 4384     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array/12")
 4385     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array/13")
 4386     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array/14")
 4387     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array/15")
 4388     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array/16")
 4389     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array/17")
 4390     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array/18")
 4391     # . epilogue
 4392     89/<- %esp 5/r32/ebp
 4393     5d/pop-to-ebp
 4394     c3/return
 4395 
 4396 test-convert-index-into-array-of-bytes:
 4397     # . prologue
 4398     55/push-ebp
 4399     89/<- %ebp 4/r32/esp
 4400     # setup
 4401     (clear-stream _test-input-stream)
 4402     (clear-stream $_test-input-buffered-file->buffer)
 4403     (clear-stream _test-output-stream)
 4404     (clear-stream $_test-output-buffered-file->buffer)
 4405     #
 4406     (write _test-input-stream "fn foo {\n")
 4407     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 4408     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 4409     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, idx\n")
 4410     (write _test-input-stream "}\n")
 4411     # convert
 4412     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4413     (flush _test-output-buffered-file)
 4414 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4420     # check output
 4421     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes/0")
 4422     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes/1")
 4423     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes/2")
 4424     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes/3")
 4425     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes/4")
 4426     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes/5")
 4427     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes/6")
 4428     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-of-bytes/7")
 4429     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-of-bytes/8")
 4430     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array-of-bytes/9")
 4431     (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")
 4432     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes/13")
 4433     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes/14")
 4434     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes/15")
 4435     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes/16")
 4436     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes/17")
 4437     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes/18")
 4438     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes/19")
 4439     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes/20")
 4440     # . epilogue
 4441     89/<- %esp 5/r32/ebp
 4442     5d/pop-to-ebp
 4443     c3/return
 4444 
 4445 test-convert-index-into-array-with-literal:
 4446     # . prologue
 4447     55/push-ebp
 4448     89/<- %ebp 4/r32/esp
 4449     # setup
 4450     (clear-stream _test-input-stream)
 4451     (clear-stream $_test-input-buffered-file->buffer)
 4452     (clear-stream _test-output-stream)
 4453     (clear-stream $_test-output-buffered-file->buffer)
 4454     #
 4455     (write _test-input-stream "fn foo {\n")
 4456     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 4457     (write _test-input-stream "  var x/eax: (addr int) <- index arr, 2\n")
 4458     (write _test-input-stream "}\n")
 4459     # convert
 4460     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4461     (flush _test-output-buffered-file)
 4462 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4468     # check output
 4469     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-with-literal/0")
 4470     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-with-literal/1")
 4471     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-with-literal/2")
 4472     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-with-literal/3")
 4473     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-with-literal/4")
 4474     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-with-literal/5")
 4475     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-with-literal/6")
 4476     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-with-literal/7")
 4477                                                                                  # 2 * 4 bytes/elem + 4 bytes for size = offset 12
 4478     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x0000000c) 0x00000000/r32"  "F - test-convert-index-into-array-with-literal/8")
 4479     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-with-literal/9")
 4480     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-with-literal/10")
 4481     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-with-literal/11")
 4482     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-with-literal/12")
 4483     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-with-literal/13")
 4484     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-with-literal/14")
 4485     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-with-literal/15")
 4486     # . epilogue
 4487     89/<- %esp 5/r32/ebp
 4488     5d/pop-to-ebp
 4489     c3/return
 4490 
 4491 test-convert-index-into-array-of-bytes-with-literal:
 4492     # . prologue
 4493     55/push-ebp
 4494     89/<- %ebp 4/r32/esp
 4495     # setup
 4496     (clear-stream _test-input-stream)
 4497     (clear-stream $_test-input-buffered-file->buffer)
 4498     (clear-stream _test-output-stream)
 4499     (clear-stream $_test-output-buffered-file->buffer)
 4500     #
 4501     (write _test-input-stream "fn foo {\n")
 4502     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 4503     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, 2\n")
 4504     (write _test-input-stream "}\n")
 4505     # convert
 4506     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4507     (flush _test-output-buffered-file)
 4508 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4514     # check output
 4515     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-with-literal/0")
 4516     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-with-literal/1")
 4517     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-with-literal/2")
 4518     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes-with-literal/3")
 4519     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-with-literal/4")
 4520     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-with-literal/5")
 4521     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes-with-literal/6")
 4522     (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")
 4523                                                                                  # 2 * 1 byte/elem + 4 bytes for size = offset 6
 4524     (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")
 4525     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-with-literal/9")
 4526     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-with-literal/10")
 4527     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-with-literal/11")
 4528     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-with-literal/12")
 4529     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-with-literal/13")
 4530     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-with-literal/14")
 4531     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-with-literal/15")
 4532     # . epilogue
 4533     89/<- %esp 5/r32/ebp
 4534     5d/pop-to-ebp
 4535     c3/return
 4536 
 4537 test-convert-index-into-array-on-stack:
 4538     # . prologue
 4539     55/push-ebp
 4540     89/<- %ebp 4/r32/esp
 4541     # setup
 4542     (clear-stream _test-input-stream)
 4543     (clear-stream $_test-input-buffered-file->buffer)
 4544     (clear-stream _test-output-stream)
 4545     (clear-stream $_test-output-buffered-file->buffer)
 4546     #
 4547     (write _test-input-stream "fn foo {\n")
 4548     (write _test-input-stream "  var arr: (array int 3)\n")
 4549     (write _test-input-stream "  var idx/eax: int <- copy 2\n")
 4550     (write _test-input-stream "  var x/eax: (addr int) <- index arr, idx\n")
 4551     (write _test-input-stream "}\n")
 4552     # convert
 4553     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4554     (flush _test-output-buffered-file)
 4555 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4561     # check output
 4562     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-on-stack/0")
 4563     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-on-stack/1")
 4564     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-on-stack/2")
 4565     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-on-stack/3")
 4566     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-on-stack/4")
 4567     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-on-stack/5")
 4568     # var arr
 4569     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"          "F - test-convert-index-into-array-on-stack/6")
 4570     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"                "F - test-convert-index-into-array-on-stack/7")
 4571     # var idx
 4572     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-on-stack/8")
 4573     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 2/imm32"                  "F - test-convert-index-into-array-on-stack/9")
 4574     # var x is at (ebp-0x10) + idx<<2 + 4 = ebp + idx<<2 - 0xc
 4575     (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")
 4576     # reclaim idx
 4577     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-on-stack/11")
 4578     # reclaim arr
 4579     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"    "F - test-convert-index-into-array-on-stack/12")
 4580     #
 4581     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-on-stack/13")
 4582     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-on-stack/14")
 4583     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-on-stack/15")
 4584     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-on-stack/16")
 4585     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-on-stack/17")
 4586     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-on-stack/18")
 4587     # . epilogue
 4588     89/<- %esp 5/r32/ebp
 4589     5d/pop-to-ebp
 4590     c3/return
 4591 
 4592 test-convert-index-into-array-on-stack-with-literal:
 4593     # . prologue
 4594     55/push-ebp
 4595     89/<- %ebp 4/r32/esp
 4596     # setup
 4597     (clear-stream _test-input-stream)
 4598     (clear-stream $_test-input-buffered-file->buffer)
 4599     (clear-stream _test-output-stream)
 4600     (clear-stream $_test-output-buffered-file->buffer)
 4601     #
 4602     (write _test-input-stream "fn foo {\n")
 4603     (write _test-input-stream "  var arr: (array int 3)\n")
 4604     (write _test-input-stream "  var x/eax: (addr int) <- index arr, 2\n")
 4605     (write _test-input-stream "}\n")
 4606     # convert
 4607     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4608     (flush _test-output-buffered-file)
 4609 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4615     # check output
 4616     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-on-stack-with-literal/0")
 4617     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-on-stack-with-literal/1")
 4618     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-on-stack-with-literal/2")
 4619     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-on-stack-with-literal/3")
 4620     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-on-stack-with-literal/4")
 4621     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-on-stack-with-literal/5")
 4622     # var arr
 4623     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"          "F - test-convert-index-into-array-on-stack-with-literal/6")
 4624     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"                "F - test-convert-index-into-array-on-stack-with-literal/7")
 4625     # var x
 4626     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-on-stack-with-literal/8")
 4627     # x is at (ebp-0x10) + 4 + 2*4 = ebp-4
 4628     (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")
 4629     # reclaim x
 4630     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-on-stack-with-literal/10")
 4631     # reclaim arr
 4632     (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")
 4633     #
 4634     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-on-stack-with-literal/12")
 4635     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-on-stack-with-literal/13")
 4636     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-on-stack-with-literal/14")
 4637     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-on-stack-with-literal/15")
 4638     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-on-stack-with-literal/16")
 4639     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-on-stack-with-literal/17")
 4640     # . epilogue
 4641     89/<- %esp 5/r32/ebp
 4642     5d/pop-to-ebp
 4643     c3/return
 4644 
 4645 test-convert-index-into-array-of-bytes-on-stack-with-literal:
 4646     # . prologue
 4647     55/push-ebp
 4648     89/<- %ebp 4/r32/esp
 4649     # setup
 4650     (clear-stream _test-input-stream)
 4651     (clear-stream $_test-input-buffered-file->buffer)
 4652     (clear-stream _test-output-stream)
 4653     (clear-stream $_test-output-buffered-file->buffer)
 4654     #
 4655     (write _test-input-stream "fn foo {\n")
 4656     (write _test-input-stream "  var arr: (array byte 3)\n")
 4657     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, 2\n")
 4658     (write _test-input-stream "}\n")
 4659     # convert
 4660     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4661     (flush _test-output-buffered-file)
 4662 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4668     # check output
 4669     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/0")
 4670     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/1")
 4671     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/2")
 4672     (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")
 4673     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/4")
 4674     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/5")
 4675     # var arr
 4676     (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")
 4677     (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")
 4678     # var x
 4679     (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")
 4680     # x is at (ebp-7) + 4 + 2 = ebp-1
 4681     (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")
 4682     # reclaim x
 4683     (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")
 4684     # reclaim arr
 4685     (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")
 4686     #
 4687     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/12")
 4688     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/13")
 4689     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/14")
 4690     (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")
 4691     (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")
 4692     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/17")
 4693     # . epilogue
 4694     89/<- %esp 5/r32/ebp
 4695     5d/pop-to-ebp
 4696     c3/return
 4697 
 4698 test-convert-index-into-array-using-offset:
 4699     # . prologue
 4700     55/push-ebp
 4701     89/<- %ebp 4/r32/esp
 4702     # setup
 4703     (clear-stream _test-input-stream)
 4704     (clear-stream $_test-input-buffered-file->buffer)
 4705     (clear-stream _test-output-stream)
 4706     (clear-stream $_test-output-buffered-file->buffer)
 4707     #
 4708     (write _test-input-stream "fn foo {\n")
 4709     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 4710     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 4711     (write _test-input-stream "  var off/ecx: (offset int) <- compute-offset arr, idx\n")
 4712     (write _test-input-stream "  var x/eax: (addr int) <- index arr, off\n")
 4713     (write _test-input-stream "}\n")
 4714     # convert
 4715     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4716     (flush _test-output-buffered-file)
 4717 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4723     # check output
 4724     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-using-offset/0")
 4725     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-using-offset/1")
 4726     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-using-offset/2")
 4727     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-using-offset/3")
 4728     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-using-offset/4")
 4729     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-using-offset/5")
 4730     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-using-offset/6")
 4731     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-using-offset/7")
 4732     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-using-offset/8")
 4733     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array-using-offset/9")
 4734     (check-next-stream-line-equal _test-output-stream "    69/multiply %ecx 0x00000004/imm32 0x00000001/r32"  "F - test-convert-index-into-array-using-offset/10")
 4735     (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")
 4736     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-using-offset/12")
 4737     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-using-offset/13")
 4738     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-using-offset/14")
 4739     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-using-offset/15")
 4740     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-using-offset/16")
 4741     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-using-offset/17")
 4742     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-using-offset/18")
 4743     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-using-offset/19")
 4744     # . epilogue
 4745     89/<- %esp 5/r32/ebp
 4746     5d/pop-to-ebp
 4747     c3/return
 4748 
 4749 test-convert-index-into-array-of-bytes-using-offset:
 4750     # . prologue
 4751     55/push-ebp
 4752     89/<- %ebp 4/r32/esp
 4753     # setup
 4754     (clear-stream _test-input-stream)
 4755     (clear-stream $_test-input-buffered-file->buffer)
 4756     (clear-stream _test-output-stream)
 4757     (clear-stream $_test-output-buffered-file->buffer)
 4758     #
 4759     (write _test-input-stream "fn foo {\n")
 4760     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 4761     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 4762     (write _test-input-stream "  var off/ecx: (offset byte) <- compute-offset arr, idx\n")
 4763     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, off\n")
 4764     (write _test-input-stream "}\n")
 4765     # convert
 4766     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4767     (flush _test-output-buffered-file)
 4768 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4774     # check output
 4775     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-using-offset/0")
 4776     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-using-offset/1")
 4777     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-using-offset/2")
 4778     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes-using-offset/3")
 4779     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-using-offset/4")
 4780     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-using-offset/5")
 4781     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes-using-offset/6")
 4782     (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")
 4783     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-of-bytes-using-offset/8")
 4784     (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")
 4785     (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")
 4786     (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")
 4787     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes-using-offset/12")
 4788     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-using-offset/13")
 4789     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-using-offset/14")
 4790     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-using-offset/15")
 4791     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-using-offset/16")
 4792     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-using-offset/17")
 4793     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-using-offset/18")
 4794     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-using-offset/19")
 4795     # . epilogue
 4796     89/<- %esp 5/r32/ebp
 4797     5d/pop-to-ebp
 4798     c3/return
 4799 
 4800 test-convert-index-into-array-using-offset-on-stack:
 4801     # . prologue
 4802     55/push-ebp
 4803     89/<- %ebp 4/r32/esp
 4804     # setup
 4805     (clear-stream _test-input-stream)
 4806     (clear-stream $_test-input-buffered-file->buffer)
 4807     (clear-stream _test-output-stream)
 4808     (clear-stream $_test-output-buffered-file->buffer)
 4809     #
 4810     (write _test-input-stream "fn foo {\n")
 4811     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 4812     (write _test-input-stream "  var idx: int\n")
 4813     (write _test-input-stream "  var off/ecx: (offset int) <- compute-offset arr, idx\n")
 4814     (write _test-input-stream "  var x/eax: (addr int) <- index arr, off\n")
 4815     (write _test-input-stream "}\n")
 4816     # convert
 4817     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4818     (flush _test-output-buffered-file)
 4819 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4825     # check output
 4826     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-using-offset-on-stack/0")
 4827     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-using-offset-on-stack/1")
 4828     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-using-offset-on-stack/2")
 4829     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-using-offset-on-stack/3")
 4830     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-using-offset-on-stack/4")
 4831     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-using-offset-on-stack/5")
 4832     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-using-offset-on-stack/6")
 4833     (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")
 4834     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                         "F - test-convert-index-into-array-using-offset-on-stack/8")
 4835     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-using-offset-on-stack/9")
 4836     (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")
 4837     (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")
 4838     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-using-offset-on-stack/12")
 4839     (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")
 4840     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-using-offset-on-stack/14")
 4841     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-using-offset-on-stack/15")
 4842     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-using-offset-on-stack/16")
 4843     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-using-offset-on-stack/17")
 4844     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-using-offset-on-stack/18")
 4845     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-using-offset-on-stack/19")
 4846     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-using-offset-on-stack/20")
 4847     # . epilogue
 4848     89/<- %esp 5/r32/ebp
 4849     5d/pop-to-ebp
 4850     c3/return
 4851 
 4852 test-convert-index-into-array-of-bytes-using-offset-on-stack:
 4853     # . prologue
 4854     55/push-ebp
 4855     89/<- %ebp 4/r32/esp
 4856     # setup
 4857     (clear-stream _test-input-stream)
 4858     (clear-stream $_test-input-buffered-file->buffer)
 4859     (clear-stream _test-output-stream)
 4860     (clear-stream $_test-output-buffered-file->buffer)
 4861     #
 4862     (write _test-input-stream "fn foo {\n")
 4863     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 4864     (write _test-input-stream "  var idx: int\n")
 4865     (write _test-input-stream "  var off/ecx: (offset byte) <- compute-offset arr, idx\n")
 4866     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, off\n")
 4867     (write _test-input-stream "}\n")
 4868     # convert
 4869     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4870     (flush _test-output-buffered-file)
 4871 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4877     # check output
 4878     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/0")
 4879     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/1")
 4880     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/2")
 4881     (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")
 4882     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/4")
 4883     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/5")
 4884     (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")
 4885     (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")
 4886     (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")
 4887     (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")
 4888     (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")
 4889     (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")
 4890     (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")
 4891     (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")
 4892     (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")
 4893     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/15")
 4894     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/16")
 4895     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/17")
 4896     (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")
 4897     (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")
 4898     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/20")
 4899     # . epilogue
 4900     89/<- %esp 5/r32/ebp
 4901     5d/pop-to-ebp
 4902     c3/return
 4903 
 4904 test-convert-function-and-type-definition:
 4905     # . prologue
 4906     55/push-ebp
 4907     89/<- %ebp 4/r32/esp
 4908     # setup
 4909     (clear-stream _test-input-stream)
 4910     (clear-stream $_test-input-buffered-file->buffer)
 4911     (clear-stream _test-output-stream)
 4912     (clear-stream $_test-output-buffered-file->buffer)
 4913     #
 4914     (write _test-input-stream "fn foo a: (addr t) {\n")
 4915     (write _test-input-stream "  var _a/eax: (addr t) <- copy a\n")
 4916     (write _test-input-stream "  var b/ecx: (addr int) <- get _a, x\n")
 4917     (write _test-input-stream "  var c/ecx: (addr int) <- get _a, y\n")
 4918     (write _test-input-stream "}\n")
 4919     (write _test-input-stream "type t {\n")
 4920     (write _test-input-stream "  x: int\n")
 4921     (write _test-input-stream "  y: int\n")
 4922     (write _test-input-stream "}\n")
 4923     # convert
 4924     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4925     (flush _test-output-buffered-file)
 4926 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4932     # check output
 4933     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-and-type-definition/0")
 4934     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-and-type-definition/1")
 4935     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-and-type-definition/2")
 4936     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-and-type-definition/3")
 4937     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-and-type-definition/4")
 4938     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-and-type-definition/5")
 4939     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-and-type-definition/6")
 4940     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-and-type-definition/7")
 4941     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-and-type-definition/8")
 4942     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x00000000) 0x00000001/r32"  "F - test-convert-function-and-type-definition/9")
 4943     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x00000004) 0x00000001/r32"  "F - test-convert-function-and-type-definition/11")
 4944     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-and-type-definition/13")
 4945     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-and-type-definition/14")
 4946     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-and-type-definition/15")
 4947     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-and-type-definition/16")
 4948     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-and-type-definition/17")
 4949     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-and-type-definition/18")
 4950     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-and-type-definition/19")
 4951     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-and-type-definition/20")
 4952     # . epilogue
 4953     89/<- %esp 5/r32/ebp
 4954     5d/pop-to-ebp
 4955     c3/return
 4956 
 4957 test-type-definition-with-array:
 4958     # . prologue
 4959     55/push-ebp
 4960     89/<- %ebp 4/r32/esp
 4961     # setup
 4962     (clear-stream _test-input-stream)
 4963     (clear-stream $_test-input-buffered-file->buffer)
 4964     (clear-stream _test-output-stream)
 4965     (clear-stream $_test-output-buffered-file->buffer)
 4966     (clear-stream _test-error-stream)
 4967     (clear-stream $_test-error-buffered-file->buffer)
 4968     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 4969     68/push 0/imm32
 4970     68/push 0/imm32
 4971     89/<- %edx 4/r32/esp
 4972     (tailor-exit-descriptor %edx 0x10)
 4973     #
 4974     (write _test-input-stream "type t {\n")
 4975     (write _test-input-stream "  a: (array int 3)\n")
 4976     (write _test-input-stream "}\n")
 4977     # convert
 4978     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 4979     # registers except esp clobbered at this point
 4980     # restore ed
 4981     89/<- %edx 4/r32/esp
 4982     (flush _test-output-buffered-file)
 4983     (flush _test-error-buffered-file)
 4984 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4990     # check output
 4991     (check-stream-equal _test-output-stream  ""  "F - test-type-definition-with-array: output should be empty")
 4992     (check-next-stream-line-equal _test-error-stream  "type t: 'array' elements not allowed for now"  "F - test-type-definition-with-array: error message")
 4993     # check that stop(1) was called
 4994     (check-ints-equal *(edx+4) 2 "F - test-type-definition-with-array: exit status")
 4995     # don't restore from ebp
 4996     81 0/subop/add %esp 8/imm32
 4997     # . epilogue
 4998     5d/pop-to-ebp
 4999     c3/return
 5000 
 5001 test-type-definition-with-addr:
 5002     # . prologue
 5003     55/push-ebp
 5004     89/<- %ebp 4/r32/esp
 5005     # setup
 5006     (clear-stream _test-input-stream)
 5007     (clear-stream $_test-input-buffered-file->buffer)
 5008     (clear-stream _test-output-stream)
 5009     (clear-stream $_test-output-buffered-file->buffer)
 5010     (clear-stream _test-error-stream)
 5011     (clear-stream $_test-error-buffered-file->buffer)
 5012     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 5013     68/push 0/imm32
 5014     68/push 0/imm32
 5015     89/<- %edx 4/r32/esp
 5016     (tailor-exit-descriptor %edx 0x10)
 5017     #
 5018     (write _test-input-stream "type t {\n")
 5019     (write _test-input-stream "  a: (addr int)\n")
 5020     (write _test-input-stream "}\n")
 5021     # convert
 5022     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 5023     # registers except esp clobbered at this point
 5024     # restore ed
 5025     89/<- %edx 4/r32/esp
 5026     (flush _test-output-buffered-file)
 5027     (flush _test-error-buffered-file)
 5028 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5034     # check output
 5035     (check-stream-equal _test-output-stream  ""  "F - test-type-definition-with-addr: output should be empty")
 5036     (check-next-stream-line-equal _test-error-stream  "type t: 'addr' elements not allowed"  "F - test-type-definition-with-addr: error message")
 5037     # check that stop(1) was called
 5038     (check-ints-equal *(edx+4) 2 "F - test-type-definition-with-addr: exit status")
 5039     # don't restore from ebp
 5040     81 0/subop/add %esp 8/imm32
 5041     # . epilogue
 5042     5d/pop-to-ebp
 5043     c3/return
 5044 
 5045 test-convert-function-with-local-var-with-user-defined-type:
 5046     # . prologue
 5047     55/push-ebp
 5048     89/<- %ebp 4/r32/esp
 5049     # setup
 5050     (clear-stream _test-input-stream)
 5051     (clear-stream $_test-input-buffered-file->buffer)
 5052     (clear-stream _test-output-stream)
 5053     (clear-stream $_test-output-buffered-file->buffer)
 5054     #
 5055     (write _test-input-stream "fn foo {\n")
 5056     (write _test-input-stream "  var a: t\n")
 5057     (write _test-input-stream "}\n")
 5058     (write _test-input-stream "type t {\n")
 5059     (write _test-input-stream "  x: int\n")
 5060     (write _test-input-stream "  y: int\n")
 5061     (write _test-input-stream "}\n")
 5062     # convert
 5063     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5064     (flush _test-output-buffered-file)
 5065 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5071     # check output
 5072     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-with-user-defined-type/0")
 5073     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-with-user-defined-type/1")
 5074     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-with-user-defined-type/2")
 5075     (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")
 5076     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-user-defined-type/4")
 5077     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-with-user-defined-type/5")
 5078     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-user-defined-type/6")
 5079     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-user-defined-type/7")
 5080     (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")
 5081     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-user-defined-type/9")
 5082     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-with-user-defined-type/10")
 5083     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-with-user-defined-type/11")
 5084     (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")
 5085     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-with-user-defined-type/13")
 5086     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-with-user-defined-type/14")
 5087     # . epilogue
 5088     89/<- %esp 5/r32/ebp
 5089     5d/pop-to-ebp
 5090     c3/return
 5091 
 5092 test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type:
 5093     # . prologue
 5094     55/push-ebp
 5095     89/<- %ebp 4/r32/esp
 5096     # setup
 5097     (clear-stream _test-input-stream)
 5098     (clear-stream $_test-input-buffered-file->buffer)
 5099     (clear-stream _test-output-stream)
 5100     (clear-stream $_test-output-buffered-file->buffer)
 5101     #
 5102     (write _test-input-stream "fn foo {\n")
 5103     (write _test-input-stream "  var a: t\n")
 5104     (write _test-input-stream "}\n")
 5105     (write _test-input-stream "type t {\n")
 5106     (write _test-input-stream "  x: s\n")
 5107     (write _test-input-stream "}\n")
 5108     (write _test-input-stream "type s {\n")
 5109     (write _test-input-stream "  z: int\n")
 5110     (write _test-input-stream "}\n")
 5111     # convert
 5112     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5113     (flush _test-output-buffered-file)
 5114 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5120     # check output
 5121     (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")
 5122     (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")
 5123     (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")
 5124     (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")
 5125     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/4")
 5126     (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")
 5127     (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")
 5128     (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")
 5129     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/9")
 5130     (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")
 5131     (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")
 5132     (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")
 5133     (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")
 5134     (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")
 5135     # . epilogue
 5136     89/<- %esp 5/r32/ebp
 5137     5d/pop-to-ebp
 5138     c3/return
 5139 
 5140 test-convert-function-call-with-arg-of-user-defined-type:
 5141     # . prologue
 5142     55/push-ebp
 5143     89/<- %ebp 4/r32/esp
 5144     # setup
 5145     (clear-stream _test-input-stream)
 5146     (clear-stream $_test-input-buffered-file->buffer)
 5147     (clear-stream _test-output-stream)
 5148     (clear-stream $_test-output-buffered-file->buffer)
 5149     #
 5150     (write _test-input-stream "fn f {\n")
 5151     (write _test-input-stream "  var a: t\n")
 5152     (write _test-input-stream "  foo a\n")
 5153     (write _test-input-stream "}\n")
 5154     (write _test-input-stream "fn foo x: t {\n")
 5155     (write _test-input-stream "}\n")
 5156     (write _test-input-stream "type t {\n")
 5157     (write _test-input-stream "  x: int\n")
 5158     (write _test-input-stream "  y: int\n")
 5159     (write _test-input-stream "}\n")
 5160     # convert
 5161     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5162     (flush _test-output-buffered-file)
 5163 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5169     # check output
 5170     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type/0")
 5171     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/1")
 5172     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/2")
 5173     (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")
 5174     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type/4")
 5175     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-arg-of-user-defined-type/5")
 5176     # var a: t
 5177     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-arg-of-user-defined-type/6")
 5178     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-arg-of-user-defined-type/7")
 5179     # foo a
 5180     (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")
 5181     #
 5182     (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")
 5183     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type/10")
 5184     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-arg-of-user-defined-type/11")
 5185     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/12")
 5186     (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")
 5187     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/14")
 5188     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/15")
 5189     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type/16")
 5190     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/17")
 5191     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/18")
 5192     (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")
 5193     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/20")
 5194     (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")
 5195     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/22")
 5196     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/23")
 5197     # . epilogue
 5198     89/<- %esp 5/r32/ebp
 5199     5d/pop-to-ebp
 5200     c3/return
 5201 
 5202 test-convert-function-call-with-arg-of-user-defined-type-register-indirect:
 5203     # . prologue
 5204     55/push-ebp
 5205     89/<- %ebp 4/r32/esp
 5206     # setup
 5207     (clear-stream _test-input-stream)
 5208     (clear-stream $_test-input-buffered-file->buffer)
 5209     (clear-stream _test-output-stream)
 5210     (clear-stream $_test-output-buffered-file->buffer)
 5211     #
 5212     (write _test-input-stream "fn f {\n")
 5213     (write _test-input-stream "  var a/eax: (addr t) <- copy 0\n")
 5214     (write _test-input-stream "  foo *a\n")
 5215     (write _test-input-stream "}\n")
 5216     (write _test-input-stream "fn foo x: t {\n")
 5217     (write _test-input-stream "}\n")
 5218     (write _test-input-stream "type t {\n")
 5219     (write _test-input-stream "  x: int\n")
 5220     (write _test-input-stream "  y: int\n")
 5221     (write _test-input-stream "}\n")
 5222     # convert
 5223     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5224     (flush _test-output-buffered-file)
 5225 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5231     # check output
 5232     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type/0")
 5233     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/1")
 5234     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/2")
 5235     (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")
 5236     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type/4")
 5237     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-arg-of-user-defined-type/5")
 5238     # var a
 5239     (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")
 5240     (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")
 5241     # foo a
 5242     (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")
 5243     #
 5244     (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")
 5245     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type/10")
 5246     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-arg-of-user-defined-type/11")
 5247     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/12")
 5248     (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")
 5249     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/14")
 5250     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/15")
 5251     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type/16")
 5252     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/17")
 5253     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/18")
 5254     (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")
 5255     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/20")
 5256     (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")
 5257     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/22")
 5258     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/23")
 5259     # . epilogue
 5260     89/<- %esp 5/r32/ebp
 5261     5d/pop-to-ebp
 5262     c3/return
 5263 
 5264 # we don't have special support for call-by-reference; just explicitly create
 5265 # a new variable with the address of the arg
 5266 test-convert-function-call-with-arg-of-user-defined-type-by-reference:
 5267     # . prologue
 5268     55/push-ebp
 5269     89/<- %ebp 4/r32/esp
 5270     # setup
 5271     (clear-stream _test-input-stream)
 5272     (clear-stream $_test-input-buffered-file->buffer)
 5273     (clear-stream _test-output-stream)
 5274     (clear-stream $_test-output-buffered-file->buffer)
 5275     #
 5276     (write _test-input-stream "fn f {\n")
 5277     (write _test-input-stream "  var a: t\n")
 5278     (write _test-input-stream "  var b/eax: (addr t) <- address a\n")
 5279     (write _test-input-stream "  foo b\n")
 5280     (write _test-input-stream "}\n")
 5281     (write _test-input-stream "fn foo x: (addr t) {\n")
 5282     (write _test-input-stream "  var x/ecx: (addr int) <- copy x\n")
 5283     (write _test-input-stream "  increment *x\n")
 5284     (write _test-input-stream "}\n")
 5285     (write _test-input-stream "type t {\n")
 5286     (write _test-input-stream "  x: int\n")
 5287     (write _test-input-stream "  y: int\n")
 5288     (write _test-input-stream "}\n")
 5289     # convert
 5290     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5291     (flush _test-output-buffered-file)
 5292 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5298     # check output
 5299     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/0")
 5300     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/1")
 5301     (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")
 5302     (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")
 5303     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/4")
 5304     (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")
 5305     # var a: t
 5306     (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")
 5307     (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")
 5308     # var b/eax: (addr t)
 5309     (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")
 5310     (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")
 5311     # foo a
 5312     (check-next-stream-line-equal _test-output-stream "    (foo %eax)"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/10")
 5313     #
 5314     (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")
 5315     (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")
 5316     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/13")
 5317     (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")
 5318     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/15")
 5319     (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")
 5320     (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")
 5321     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/18")
 5322     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/19")
 5323     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/20")
 5324     (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")
 5325     (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")
 5326     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/23")
 5327     (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")
 5328     (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")
 5329     (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")
 5330     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *ecx"  "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/27")
 5331     (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/28")
 5332     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/29")
 5333     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/30")
 5334     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/31")
 5335     (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/32")
 5336     (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/33")
 5337     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/34")
 5338     # . epilogue
 5339     89/<- %esp 5/r32/ebp
 5340     5d/pop-to-ebp
 5341     c3/return
 5342 
 5343 test-convert-get-on-local-variable:
 5344     # . prologue
 5345     55/push-ebp
 5346     89/<- %ebp 4/r32/esp
 5347     # setup
 5348     (clear-stream _test-input-stream)
 5349     (clear-stream $_test-input-buffered-file->buffer)
 5350     (clear-stream _test-output-stream)
 5351     (clear-stream $_test-output-buffered-file->buffer)
 5352     #
 5353     (write _test-input-stream "fn foo {\n")
 5354     (write _test-input-stream "  var a: t\n")
 5355     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 5356     (write _test-input-stream "}\n")
 5357     (write _test-input-stream "type t {\n")
 5358     (write _test-input-stream "  x: int\n")
 5359     (write _test-input-stream "  y: int\n")
 5360     (write _test-input-stream "}\n")
 5361     # convert
 5362     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5363     (flush _test-output-buffered-file)
 5364 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5370     # check output
 5371     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-local-variable/0")
 5372     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-local-variable/1")
 5373     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-local-variable/2")
 5374     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"