https://github.com/akkartik/mu/blob/master/apps/mu.subx
    1 # The Mu computer's level-2 language, also called Mu.
    2 # http://akkartik.name/post/mu-2019-2
    3 #
    4 # To run:
    5 #   $ ./translate_subx init.linux [0-9]*.subx apps/mu.subx
    6 #   $ ./a.elf < prog.mu > prog.elf
    7 
    8 # == Goals
    9 # 1. Be memory safe. It should be impossible to corrupt the heap, or to create
   10 # a bad pointer. (Requires strong type safety.)
   11 # 2. Do as little as possible to achieve goal 1. The translator should be
   12 # implementable in machine code.
   13 #   - minimize impedance mismatch between source language and SubX target
   14 #     (e.g. programmer manages registers manually)
   15 #   - checks over syntax
   16 #     (e.g. programmer's register allocation is checked)
   17 #   - runtime checks to avoid complex static analysis
   18 #     (e.g. array indexing always checks bounds)
   19 
   20 # == Language description
   21 # A program is a sequence of function and type definitions.
   22 #
   23 # Function example:
   24 #   fn foo n: int -> _/eax: int {
   25 #     ...
   26 #   }
   27 #
   28 # Functions consist of a name, optional inputs, optional outputs and a block.
   29 #
   30 # Function inputs and outputs are variables. All variables have a type and
   31 # storage specifier. They can be placed either in memory (on the stack) or in
   32 # one of 6 named registers.
   33 #   eax ecx edx ebx esi edi
   34 # Variables in registers must be primitive 32-bit types.
   35 # Variables not explicitly placed in a register are on the stack.
   36 #
   37 # Function inputs are always passed in memory (on the stack), while outputs
   38 # are always returned in registers. Outputs can't be named; they use the
   39 # dummy value '_'.
   40 #
   41 # Blocks mostly consist of statements.
   42 #
   43 # Statements mostly consist of a name, optional inputs and optional outputs.
   44 #
   45 # Statement inputs are variables or literals. Variables need to specify type
   46 # (and storage) the first time they're mentioned but not later.
   47 #
   48 # Statement outputs, like function outputs, must be variables in registers.
   49 #
   50 # Statement names must be either primitives or user-defined functions.
   51 #
   52 # Primitives can write to any register.
   53 # User-defined functions only write to hard-coded registers. Outputs of each
   54 # call must have the same registers as in the function definition.
   55 #
   56 # There are some other statement types:
   57 #   - blocks. Multiple statements surrounded by '{...}' and optionally
   58 #     prefixed with a label name and ':'
   59 #       - {
   60 #           ...
   61 #         }
   62 #       - foo: {
   63 #           ...
   64 #         }
   65 #
   66 #   - variable definitions on the stack. E.g.:
   67 #       - var foo: int
   68 #       - var bar: (array int 3)
   69 #     There's no initializer; variables are automatically initialized.
   70 #     The type of a local variable is either word-length (4 bytes) or starts with 'ref'.
   71 #
   72 #   - variables definitions in a register. E.g.:
   73 #       - var foo/eax: int <- add bar 1
   74 #     The initializer is mandatory and must be a valid instruction that writes
   75 #     a single output to the right register. In practice registers will
   76 #     usually be either initialized by primitives or copied from eax.
   77 #       - var eax: int <- foo bar quux
   78 #         var floo/ecx: int <- copy eax
   79 #
   80 # Still todo:
   81 #   global variables
   82 #   union types
   83 #
   84 # Formal types:
   85 #   A program is a linked list of functions
   86 #   A function contains:
   87 #     name: (handle array byte)
   88 #     inouts: linked list of vars  <-- 'inouts' is more precise than 'inputs'
   89 #       data: (handle var)
   90 #       next: (handle list)
   91 #     outputs: linked list of vars
   92 #       data: (handle var)
   93 #       next: (handle list)
   94 #     body: (handle block)
   95 #   A var-type contains:
   96 #     name: (handle array byte)
   97 #     type: (handle type-tree)
   98 #
   99 #   A statement can be:
  100 #     tag 0: a block
  101 #     tag 1: a simple statement (stmt1)
  102 #     tag 2: a variable defined on the stack
  103 #     tag 3: a variable defined in a register
  104 #
  105 #   A block contains:
  106 #     tag: 0
  107 #     statements: (handle list stmt)
  108 #     name: (handle array byte) -- starting with '$'
  109 #
  110 #   A regular statement contains:
  111 #     tag: 1
  112 #     operation: (handle array byte)
  113 #     inouts: (handle list operand)
  114 #     outputs: (handle list var)
  115 #
  116 #   A variable defined on the stack contains:
  117 #     tag: 2
  118 #     name: (handle array byte)
  119 #     type: (handle type-tree)
  120 #
  121 #   A variable defined in a register contains:
  122 #     tag: 3
  123 #     name: (handle array byte)
  124 #     type: (handle type-tree)
  125 #     reg: (handle array byte)
  126 
  127 # == Translation: managing the stack
  128 # Now that we know what the language looks like in the large, let's think
  129 # about how translation happens from the bottom up. One crucial piece of the
  130 # puzzle is how Mu will clean up variables defined on the stack for you.
  131 #
  132 # Assume that we maintain a 'functions' list while parsing source code. And a
  133 # 'primitives' list is a global constant. Both these contain enough information
  134 # to perform type-checking on function calls or primitive statements, respectively.
  135 #
  136 # Defining variables pushes them on a stack with the current block depth and
  137 # enough information about their location (stack offset or register).
  138 # Starting a block increments the current block id.
  139 # Each statement now has enough information to emit code for it.
  140 # Ending a block is where the magic happens:
  141 #   pop all variables at the current block depth
  142 #   emit code to restore all register variables introduced at the current depth
  143 #   emit code to clean up all stack variables at the current depth (just increment esp)
  144 #   decrement the current block depth
  145 #
  146 # Formal types:
  147 #   live-vars: stack of vars
  148 #   var:
  149 #     name: (handle array byte)
  150 #     type: (handle type-tree)
  151 #     block: int
  152 #     stack-offset: int  (added to ebp)
  153 #     register: (handle array byte)
  154 #       either usual register names
  155 #       or '*' to indicate any register
  156 #   At most one of stack-offset or register-index must be non-zero.
  157 #   A register of '*' designates a variable _template_. Only legal in formal
  158 #   parameters for primitives.
  159 
  160 # == Translating a single function call
  161 # This one's easy. Assuming we've already checked things, we just drop the
  162 # outputs (which use hard-coded registers) and emit inputs in a standard format.
  163 #
  164 # out1, out2, out3, ... <- name inout1, inout2, inout3, ...
  165 # =>
  166 # (name inout1 inout2 inout3)
  167 #
  168 # Formal types:
  169 #   functions: linked list of info
  170 #     name: (handle array byte)
  171 #     inouts: linked list of vars
  172 #     outputs: linked list of vars
  173 #     body: block (linked list of statements)
  174 
  175 # == Translating a single primitive instruction
  176 # A second crucial piece of the puzzle is how Mu converts fairly regular
  177 # primitives with their uniform syntax to SubX instructions with their gnarly
  178 # x86 details.
  179 #
  180 # Mu instructions have inputs and outputs. Primitives can have up to 2 of
  181 # them.
  182 # SubX instructions have rm32 and r32 operands.
  183 # The translation between them covers almost all the possibilities.
  184 #   Instructions with 1 inout may turn into ones with 1 rm32
  185 #     (e.g. incrementing a var on the stack)
  186 #   Instructions with 1 output may turn into ones with 1 rm32
  187 #     (e.g. incrementing a var in a register)
  188 #   1 inout and 1 output may turn into 1 rm32 and 1 r32
  189 #     (e.g. adding a var to a reg)
  190 #   2 inouts may turn into 1 rm32 and 1 r32
  191 #     (e.g. adding a reg to a var)
  192 #   1 inout and 1 literal may turn into 1 rm32 and 1 imm32
  193 #     (e.g. adding a constant to a var)
  194 #   1 output and 1 literal may turn into 1 rm32 and 1 imm32
  195 #     (e.g. adding a constant to a reg)
  196 #   2 outputs to hardcoded registers and 1 inout may turn into 1 rm32
  197 #     (special-case: divide edx:eax by a var or reg)
  198 # Observations:
  199 #   We always emit rm32. It may be the first inout or the first output.
  200 #   We may emit r32 or imm32 or neither.
  201 #   When we emit r32 it may come from first inout or second inout or first output.
  202 #
  203 # Accordingly, the formal data structure for a primitive looks like this:
  204 #   primitives: linked list of info
  205 #     name: (handle array byte)
  206 #     mu-inouts: linked list of vars to check
  207 #     mu-outputs: linked list of vars to check; at most a singleton
  208 #     subx-name: (handle array byte)
  209 #     subx-rm32: enum arg-location
  210 #     subx-r32: enum arg-location
  211 #     subx-imm32: enum arg-location
  212 #     subx-imm8: enum arg-location
  213 #     subx-disp32: enum arg-location
  214 #     subx-xm32: enum arg-location
  215 #     subx-x32: enum arg-location
  216 #   arg-location: enum
  217 #     0 means none
  218 #     1 means first inout
  219 #     2 means second inout
  220 #     3 means first output
  221 
  222 # == Translating a block
  223 # Emit block name if necessary
  224 # Emit '{'
  225 # When you encounter a statement, emit it as above
  226 # When you encounter a variable declaration
  227 #   emit any code needed for it (bzeros)
  228 #   push it on the var stack
  229 #   update register dict if necessary
  230 # When you encounter '}'
  231 #   While popping variables off the var stack until block id changes
  232 #     Emit code needed to clean up the stack
  233 #       either increment esp
  234 #       or pop into appropriate register
  235 
  236 # The rest is straightforward.
  237 
  238 == data
  239 
  240 Program:
  241 _Program-functions:  # (handle function)
  242   0/imm32
  243 _Program-functions->payload:
  244   0/imm32
  245 _Program-types:  # (handle typeinfo)
  246   0/imm32
  247 _Program-types->payload:
  248   0/imm32
  249 _Program-signatures:  # (handle function)
  250   0/imm32
  251 _Program-signatures->payload:
  252   0/imm32
  253 
  254 # Some constants for simulating the data structures described above.
  255 # Many constants here come with a type in a comment.
  256 #
  257 # Sometimes the type is of the value at that offset for the given type. For
  258 # example, if you start at a function record and move forward Function-inouts
  259 # bytes, you'll find a (handle list var).
  260 #
  261 # At other times, the type is of the constant itself. For example, the type of
  262 # the constant Function-size is (addr int). To get the size of a function,
  263 # look in *Function-size.
  264 
  265 Function-name:  # (handle array byte)
  266   0/imm32
  267 Function-inouts:  # (handle list var)
  268   8/imm32
  269 Function-outputs:  # (handle list var)
  270   0x10/imm32
  271 Function-body:  # (handle block)
  272   0x18/imm32
  273 Function-next:  # (handle function)
  274   0x20/imm32
  275 Function-size:  # (addr int)
  276   0x28/imm32/40
  277 
  278 Primitive-name:  # (handle array byte)
  279   0/imm32
  280 Primitive-inouts:  # (handle list var)
  281   8/imm32
  282 Primitive-outputs:  # (handle list var)
  283   0x10/imm32
  284 Primitive-subx-name:  # (handle array byte)
  285   0x18/imm32
  286 Primitive-subx-rm32:  # enum arg-location
  287   0x20/imm32
  288 Primitive-subx-r32:  # enum arg-location
  289   0x24/imm32
  290 Primitive-subx-imm32:  # enum arg-location
  291   0x28/imm32
  292 Primitive-subx-imm8:  # enum arg-location  -- only for bit shifts
  293   0x2c/imm32
  294 Primitive-subx-disp32:  # enum arg-location  -- only for branches
  295   0x30/imm32
  296 Primitive-subx-xm32:  # enum arg-location
  297   0x34/imm32
  298 Primitive-subx-x32:  # enum arg-location
  299   0x38/imm32
  300 Primitive-next:  # (handle function)
  301   0x3c/imm32
  302 Primitive-size:  # (addr int)
  303   0x44/imm32/68
  304 
  305 Stmt-tag:  # int
  306   0/imm32
  307 
  308 Block-stmts:  # (handle list stmt)
  309   4/imm32
  310 Block-var:  # (handle var)
  311   0xc/imm32
  312 
  313 Stmt1-operation:  # (handle array byte)
  314   4/imm32
  315 Stmt1-inouts:  # (handle stmt-var)
  316   0xc/imm32
  317 Stmt1-outputs:  # (handle stmt-var)
  318   0x14/imm32
  319 
  320 Vardef-var:  # (handle var)
  321   4/imm32
  322 
  323 Regvardef-operation:  # (handle array byte)
  324   4/imm32
  325 Regvardef-inouts:  # (handle stmt-var)
  326   0xc/imm32
  327 Regvardef-outputs:  # (handle stmt-var)  # will have exactly one element
  328   0x14/imm32
  329 
  330 Stmt-size:  # (addr int)
  331   0x1c/imm32
  332 
  333 Var-name:  # (handle array byte)
  334   0/imm32
  335 Var-type:  # (handle type-tree)
  336   8/imm32
  337 Var-block-depth:  # int -- not available until code-generation time
  338   0x10/imm32
  339 Var-offset:  # int -- not available until code-generation time
  340   0x14/imm32
  341 Var-register:  # (handle array byte) -- name of a register
  342   0x18/imm32
  343 Var-size:  # (addr int)
  344   0x20/imm32
  345 
  346 List-value:  # (handle _)
  347   0/imm32
  348 List-next:  # (handle list _)
  349   8/imm32
  350 List-size:  # (addr int)
  351   0x10/imm32
  352 
  353 # A stmt-var is like a list of vars with call-site specific metadata
  354 Stmt-var-value:  # (handle var)
  355   0/imm32
  356 Stmt-var-next:  # (handle stmt-var)
  357   8/imm32
  358 Stmt-var-is-deref:  # boolean
  359   0x10/imm32
  360 Stmt-var-size:  # (addr int)
  361   0x14/imm32
  362 
  363 # A live-var is a var augmented with information needed for tracking live
  364 # variables.
  365 Live-var-value:  # (handle var)
  366   0/imm32
  367 Live-var-register-spilled:  # boolean; only used if value is in a register, and only during code-gen
  368   8/imm32
  369 Live-var-size:  # (addr int)
  370   0xc/imm32
  371 
  372 # Types are expressed as trees (s-expressions) of type-ids (ints).
  373 
  374 Type-tree-is-atom:  # boolean
  375   0/imm32
  376 # if is-atom?
  377 Type-tree-value:  # type-id
  378   4/imm32
  379 Type-tree-value-size:  # int (for static data structure sizes)
  380   8/imm32
  381 Type-tree-parameter-name:  # (handle array byte) for type parameters
  382   8/imm32
  383 # unless is-atom?
  384 Type-tree-left:  # (addr type-tree)
  385   4/imm32
  386 Type-tree-right:  # (addr type-tree)
  387   0xc/imm32
  388 #
  389 Type-tree-size:  # (addr int)
  390   0x14/imm32
  391 
  392 # Types
  393 
  394 # TODO: Turn this data structure into valid Mu, with (fake) handles rather than addrs.
  395 Type-id:  # (stream (addr array byte))
  396   0/imm32/write  # initialized later from Primitive-type-ids
  397   0/imm32/read
  398   0x100/imm32/size
  399   # data
  400   0/imm32  # 0 reserved for literals; value is just the name
  401            # Not to be used directly, so we don't include a name here.
  402   "int"/imm32  # 1
  403   "addr"/imm32  # 2
  404   "array"/imm32  # 3
  405   "handle"/imm32  # 4
  406   "boolean"/imm32  # 5
  407   0/imm32  # 6 reserved for constants; they're like literals, but value is an int in Var-offset
  408            # Not to be used directly, so we don't include a name here.
  409   "offset"/imm32  # 7: (offset T) is guaranteed to be a 32-bit multiple of size-of(T)
  410   # 0x20
  411   "byte"/imm32  # 8
  412   0/imm32  # 9 reserved for array-capacity; value is in Type-tree-size.
  413            # Not to be used directly, so we don't include a name here.
  414   0/imm32  # 10 reserved for type parameters; value is (address array byte) in Type-tree-value2.
  415            # Not to be used directly, so we don't include a name here.
  416   "stream"/imm32  # 11
  417   "slice"/imm32  # 12
  418   "code-point"/imm32  # 13; smallest scannable unit from a text stream
  419   "grapheme"/imm32  # 14; smallest printable unit; will eventually be composed of multiple code-points, but currently corresponds 1:1
  420                     # only 4-byte graphemes in utf-8 are currently supported;
  421                     # unclear how we should deal with larger clusters.
  422   "float"/imm32     # 15
  423   # 0x40
  424   0/imm32  # 16 reserved for literal strings; value is just the name
  425            # Not to be used directly, so we don't include a name here.
  426            # TODO: move this up next to literal ints
  427   # Keep Primitive-type-ids in sync if you add types here.
  428           0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  429   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  430   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  431   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  432   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  433   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  434 
  435 Primitive-type-ids:  # (addr int)
  436   0x44
  437 
  438 # == Type definitions
  439 # Program->types contains some typeinfo for each type definition.
  440 # Types contain vars with types, but can't specify registers.
  441 Typeinfo-id:  # type-id
  442   0/imm32
  443 Typeinfo-fields:  # (handle table (handle array byte) (handle typeinfo-entry))
  444   4/imm32
  445 # Total size must be >= 0
  446 # During parsing it may take on two additional values:
  447 #   -2: not yet initialized
  448 #   -1: in process of being computed
  449 # See populate-mu-type-sizes for details.
  450 Typeinfo-total-size-in-bytes:  # int
  451   0xc/imm32
  452 Typeinfo-next:  # (handle typeinfo)
  453   0x10/imm32
  454 Typeinfo-size:  # (addr int)
  455   0x18/imm32
  456 
  457 # Each entry in the typeinfo->fields table has a pointer to a string and a
  458 # pointer to a typeinfo-entry.
  459 Typeinfo-fields-row-size:  # (addr int)
  460   0x10/imm32
  461 
  462 # typeinfo-entry objects have information about a field in a single record type
  463 #
  464 # each field of a type is represented using two var's:
  465 #   1. the input var: expected type of the field; convenient for creating using parse-var-with-type
  466 #   2. the output var: a constant containing the byte offset; convenient for code-generation
  467 # computing the output happens after parsing; in the meantime we preserve the
  468 # order of fields in the 'index' field.
  469 Typeinfo-entry-input-var:  # (handle var)
  470   0/imm32
  471 Typeinfo-entry-index:  # int
  472   8/imm32
  473 Typeinfo-entry-output-var:  # (handle var)
  474   0xc/imm32
  475 Typeinfo-entry-size:  # (addr int)
  476   0x14/imm32
  477 
  478 == code
  479 
  480 Entry:
  481     # . prologue
  482     89/<- %ebp 4/r32/esp
  483     (new-segment *Heap-size Heap)
  484     # if (argv[1] == "test') run-tests()
  485     {
  486       # if (argc <= 1) break
  487       81 7/subop/compare *ebp 1/imm32
  488       7e/jump-if-<= break/disp8
  489       # if (argv[1] != "test") break
  490       (kernel-string-equal? *(ebp+8) "test")  # => eax
  491       3d/compare-eax-and 0/imm32/false
  492       74/jump-if-= break/disp8
  493       #
  494       (run-tests)
  495       # syscall(exit, *Num-test-failures)
  496       8b/-> *Num-test-failures 3/r32/ebx
  497       eb/jump $mu-main:end/disp8
  498     }
  499     # otherwise convert Stdin
  500     (convert-mu Stdin Stdout Stderr 0)
  501     (flush Stdout)
  502     # syscall(exit, 0)
  503     bb/copy-to-ebx 0/imm32
  504 $mu-main:end:
  505     e8/call syscall_exit/disp32
  506 
  507 convert-mu:  # in: (addr buffered-file), out: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
  508     # . prologue
  509     55/push-ebp
  510     89/<- %ebp 4/r32/esp
  511     # . save registers
  512     50/push-eax
  513     # initialize global data structures
  514     c7 0/subop/copy *Next-block-index 1/imm32
  515     8b/-> *Primitive-type-ids 0/r32/eax
  516     89/<- *Type-id 0/r32/eax  # stream-write
  517     c7 0/subop/copy *_Program-functions 0/imm32
  518     c7 0/subop/copy *_Program-functions->payload 0/imm32
  519     c7 0/subop/copy *_Program-types 0/imm32
  520     c7 0/subop/copy *_Program-types->payload 0/imm32
  521     c7 0/subop/copy *_Program-signatures 0/imm32
  522     c7 0/subop/copy *_Program-signatures->payload 0/imm32
  523     #
  524     (parse-mu *(ebp+8) *(ebp+0x10) *(ebp+0x14))
  525     (populate-mu-type-sizes *(ebp+0x10) *(ebp+0x14))
  526 #?     (dump-typeinfos "=== typeinfos\n")
  527     (check-mu-types *(ebp+0x10) *(ebp+0x14))
  528     (emit-subx *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
  529 $convert-mu:end:
  530     # . restore registers
  531     58/pop-to-eax
  532     # . epilogue
  533     89/<- %esp 5/r32/ebp
  534     5d/pop-to-ebp
  535     c3/return
  536 
  537 test-convert-empty-input:
  538     # empty input => empty output
  539     # . prologue
  540     55/push-ebp
  541     89/<- %ebp 4/r32/esp
  542     # setup
  543     (clear-stream _test-input-stream)
  544     (clear-stream $_test-input-buffered-file->buffer)
  545     (clear-stream _test-output-stream)
  546     (clear-stream $_test-output-buffered-file->buffer)
  547     #
  548     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  549     (flush _test-output-buffered-file)
  550     (check-stream-equal _test-output-stream "" "F - test-convert-empty-input")
  551     # . epilogue
  552     89/<- %esp 5/r32/ebp
  553     5d/pop-to-ebp
  554     c3/return
  555 
  556 test-convert-function-skeleton:
  557     # . prologue
  558     55/push-ebp
  559     89/<- %ebp 4/r32/esp
  560     # setup
  561     (clear-stream _test-input-stream)
  562     (clear-stream $_test-input-buffered-file->buffer)
  563     (clear-stream _test-output-stream)
  564     (clear-stream $_test-output-buffered-file->buffer)
  565     #
  566     (write _test-input-stream "fn foo {\n")
  567     (write _test-input-stream "}\n")
  568     # convert
  569     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  570     (flush _test-output-buffered-file)
  571 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
  577     # check output
  578     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-skeleton/0")
  579     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-skeleton/1")
  580     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-skeleton/2")
  581     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-skeleton/3")
  582     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-skeleton/4")
  583     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-skeleton/5")
  584     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-skeleton/6")
  585     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-skeleton/7")
  586     # . epilogue
  587     89/<- %esp 5/r32/ebp
  588     5d/pop-to-ebp
  589     c3/return
  590 
  591 test-convert-multiple-function-skeletons:
  592     # . prologue
  593     55/push-ebp
  594     89/<- %ebp 4/r32/esp
  595     # setup
  596     (clear-stream _test-input-stream)
  597     (clear-stream $_test-input-buffered-file->buffer)
  598     (clear-stream _test-output-stream)
  599     (clear-stream $_test-output-buffered-file->buffer)
  600     #
  601     (write _test-input-stream "fn foo {\n")
  602     (write _test-input-stream "}\n")
  603     (write _test-input-stream "fn bar {\n")
  604     (write _test-input-stream "}\n")
  605     # convert
  606     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  607     (flush _test-output-buffered-file)
  608 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
  614     # check first function
  615     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-multiple-function-skeletons/0")
  616     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-multiple-function-skeletons/1")
  617     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-multiple-function-skeletons/2")
  618     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-multiple-function-skeletons/3")
  619     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-multiple-function-skeletons/4")
  620     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-multiple-function-skeletons/5")
  621     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-multiple-function-skeletons/6")
  622     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-multiple-function-skeletons/7")
  623     # check second function
  624     (check-next-stream-line-equal _test-output-stream "bar:"                    "F - test-convert-multiple-function-skeletons/10")
  625     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-multiple-function-skeletons/11")
  626     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-multiple-function-skeletons/12")
  627     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-multiple-function-skeletons/13")
  628     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-multiple-function-skeletons/14")
  629     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-multiple-function-skeletons/15")
  630     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-multiple-function-skeletons/16")
  631     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-multiple-function-skeletons/17")
  632     # . epilogue
  633     89/<- %esp 5/r32/ebp
  634     5d/pop-to-ebp
  635     c3/return
  636 
  637 test-convert-function-with-arg:
  638     # . prologue
  639     55/push-ebp
  640     89/<- %ebp 4/r32/esp
  641     # setup
  642     (clear-stream _test-input-stream)
  643     (clear-stream $_test-input-buffered-file->buffer)
  644     (clear-stream _test-output-stream)
  645     (clear-stream $_test-output-buffered-file->buffer)
  646     #
  647     (write _test-input-stream "fn foo n: int {\n")
  648     (write _test-input-stream "}\n")
  649     # convert
  650     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  651     (flush _test-output-buffered-file)
  652 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
  658     # check output
  659     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-arg/0")
  660     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-arg/1")
  661     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-arg/2")
  662     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-arg/3")
  663     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-arg/4")
  664     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-arg/5")
  665     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-arg/6")
  666     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-arg/7")
  667     # . epilogue
  668     89/<- %esp 5/r32/ebp
  669     5d/pop-to-ebp
  670     c3/return
  671 
  672 test-function-with-redefined-name:
  673     # . prologue
  674     55/push-ebp
  675     89/<- %ebp 4/r32/esp
  676     # setup
  677     (clear-stream _test-input-stream)
  678     (clear-stream $_test-input-buffered-file->buffer)
  679     (clear-stream _test-output-stream)
  680     (clear-stream $_test-output-buffered-file->buffer)
  681     (clear-stream _test-error-stream)
  682     (clear-stream $_test-error-buffered-file->buffer)
  683     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  684     68/push 0/imm32
  685     68/push 0/imm32
  686     89/<- %edx 4/r32/esp
  687     (tailor-exit-descriptor %edx 0x10)
  688     #
  689     (write _test-input-stream "fn foo {\n")
  690     (write _test-input-stream "}\n")
  691     (write _test-input-stream "fn foo {\n")
  692     (write _test-input-stream "}\n")
  693     # convert
  694     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  695     # registers except esp clobbered at this point
  696     # restore ed
  697     89/<- %edx 4/r32/esp
  698     (flush _test-output-buffered-file)
  699     (flush _test-error-buffered-file)
  700 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
  706     # check output
  707     (check-stream-equal _test-output-stream  ""  "F - test-function-with-redefined-name: output should be empty")
  708     (check-next-stream-line-equal _test-error-stream  "fn foo defined more than once"  "F - test-function-with-redefined-name: error message")
  709     # check that stop(1) was called
  710     (check-ints-equal *(edx+4) 2 "F - test-function-with-redefined-name: exit status")
  711     # don't restore from ebp
  712     81 0/subop/add %esp 8/imm32
  713     # . epilogue
  714     5d/pop-to-ebp
  715     c3/return
  716 
  717 test-function-with-redefined-name-2:
  718     # . prologue
  719     55/push-ebp
  720     89/<- %ebp 4/r32/esp
  721     # setup
  722     (clear-stream _test-input-stream)
  723     (clear-stream $_test-input-buffered-file->buffer)
  724     (clear-stream _test-output-stream)
  725     (clear-stream $_test-output-buffered-file->buffer)
  726     (clear-stream _test-error-stream)
  727     (clear-stream $_test-error-buffered-file->buffer)
  728     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  729     68/push 0/imm32
  730     68/push 0/imm32
  731     89/<- %edx 4/r32/esp
  732     (tailor-exit-descriptor %edx 0x10)
  733     #
  734     (write _test-input-stream "fn foo {\n")
  735     (write _test-input-stream "}\n")
  736     (write _test-input-stream "sig foo\n")
  737     # convert
  738     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  739     # registers except esp clobbered at this point
  740     # restore ed
  741     89/<- %edx 4/r32/esp
  742     (flush _test-output-buffered-file)
  743     (flush _test-error-buffered-file)
  744 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
  750     # check output
  751     (check-stream-equal _test-output-stream  ""  "F - test-function-with-redefined-name-2: output should be empty")
  752     (check-next-stream-line-equal _test-error-stream  "fn foo defined more than once"  "F - test-function-with-redefined-name-2: error message")
  753     # check that stop(1) was called
  754     (check-ints-equal *(edx+4) 2 "F - test-function-with-redefined-name-2: exit status")
  755     # don't restore from ebp
  756     81 0/subop/add %esp 8/imm32
  757     # . epilogue
  758     5d/pop-to-ebp
  759     c3/return
  760 
  761 test-function-with-redefined-name-3:
  762     # . prologue
  763     55/push-ebp
  764     89/<- %ebp 4/r32/esp
  765     # setup
  766     (clear-stream _test-input-stream)
  767     (clear-stream $_test-input-buffered-file->buffer)
  768     (clear-stream _test-output-stream)
  769     (clear-stream $_test-output-buffered-file->buffer)
  770     (clear-stream _test-error-stream)
  771     (clear-stream $_test-error-buffered-file->buffer)
  772     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  773     68/push 0/imm32
  774     68/push 0/imm32
  775     89/<- %edx 4/r32/esp
  776     (tailor-exit-descriptor %edx 0x10)
  777     #
  778     (write _test-input-stream "sig foo\n")
  779     (write _test-input-stream "fn foo {\n")
  780     (write _test-input-stream "}\n")
  781     # convert
  782     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  783     # registers except esp clobbered at this point
  784     # restore ed
  785     89/<- %edx 4/r32/esp
  786     (flush _test-output-buffered-file)
  787     (flush _test-error-buffered-file)
  788 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
  794     # check output
  795     (check-stream-equal _test-output-stream  ""  "F - test-function-with-redefined-name-3: output should be empty")
  796     (check-next-stream-line-equal _test-error-stream  "fn foo defined more than once"  "F - test-function-with-redefined-name-3: error message")
  797     # check that stop(1) was called
  798     (check-ints-equal *(edx+4) 2 "F - test-function-with-redefined-name-3: exit status")
  799     # don't restore from ebp
  800     81 0/subop/add %esp 8/imm32
  801     # . epilogue
  802     5d/pop-to-ebp
  803     c3/return
  804 
  805 test-function-with-inout-in-register:
  806     # . prologue
  807     55/push-ebp
  808     89/<- %ebp 4/r32/esp
  809     # setup
  810     (clear-stream _test-input-stream)
  811     (clear-stream $_test-input-buffered-file->buffer)
  812     (clear-stream _test-output-stream)
  813     (clear-stream $_test-output-buffered-file->buffer)
  814     (clear-stream _test-error-stream)
  815     (clear-stream $_test-error-buffered-file->buffer)
  816     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  817     68/push 0/imm32
  818     68/push 0/imm32
  819     89/<- %edx 4/r32/esp
  820     (tailor-exit-descriptor %edx 0x10)
  821     #
  822     (write _test-input-stream "fn foo x/eax: int {\n")
  823     (write _test-input-stream "}\n")
  824     # convert
  825     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  826     # registers except esp clobbered at this point
  827     # restore ed
  828     89/<- %edx 4/r32/esp
  829     (flush _test-output-buffered-file)
  830     (flush _test-error-buffered-file)
  831 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
  837     # check output
  838     (check-stream-equal _test-output-stream  ""  "F - test-function-with-inout-in-register: output should be empty")
  839     (check-next-stream-line-equal _test-error-stream  "fn foo: function inout 'x' cannot be in a register"  "F - test-function-with-inout-in-register: error message")
  840     # check that stop(1) was called
  841     (check-ints-equal *(edx+4) 2 "F - test-function-with-inout-in-register: exit status")
  842     # don't restore from ebp
  843     81 0/subop/add %esp 8/imm32
  844     # . epilogue
  845     5d/pop-to-ebp
  846     c3/return
  847 
  848 test-function-with-addr-output:
  849     # . prologue
  850     55/push-ebp
  851     89/<- %ebp 4/r32/esp
  852     # setup
  853     (clear-stream _test-input-stream)
  854     (clear-stream $_test-input-buffered-file->buffer)
  855     (clear-stream _test-output-stream)
  856     (clear-stream $_test-output-buffered-file->buffer)
  857     (clear-stream _test-error-stream)
  858     (clear-stream $_test-error-buffered-file->buffer)
  859     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  860     68/push 0/imm32
  861     68/push 0/imm32
  862     89/<- %edx 4/r32/esp
  863     (tailor-exit-descriptor %edx 0x10)
  864     #
  865     (write _test-input-stream "fn foo -> _/eax: (addr int) {\n")
  866     (write _test-input-stream "}\n")
  867     # convert
  868     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  869     # registers except esp clobbered at this point
  870     # restore ed
  871     89/<- %edx 4/r32/esp
  872     (flush _test-output-buffered-file)
  873     (flush _test-error-buffered-file)
  874 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
  880     # check output
  881     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-output: output should be empty")
  882     (check-next-stream-line-equal _test-error-stream  "fn foo: output cannot have an addr type; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-output: error message")
  883     # check that stop(1) was called
  884     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-output: exit status")
  885     # don't restore from ebp
  886     81 0/subop/add %esp 8/imm32
  887     # . epilogue
  888     5d/pop-to-ebp
  889     c3/return
  890 
  891 test-function-with-addr-inout:
  892     # . prologue
  893     55/push-ebp
  894     89/<- %ebp 4/r32/esp
  895     # setup
  896     (clear-stream _test-input-stream)
  897     (clear-stream $_test-input-buffered-file->buffer)
  898     (clear-stream _test-output-stream)
  899     (clear-stream $_test-output-buffered-file->buffer)
  900     (clear-stream _test-error-stream)
  901     (clear-stream $_test-error-buffered-file->buffer)
  902     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  903     68/push 0/imm32
  904     68/push 0/imm32
  905     89/<- %edx 4/r32/esp
  906     (tailor-exit-descriptor %edx 0x10)
  907     #
  908     (write _test-input-stream "fn foo a: (addr addr int) {\n")
  909     (write _test-input-stream "}\n")
  910     # convert
  911     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  912     # registers except esp clobbered at this point
  913     # restore ed
  914     89/<- %edx 4/r32/esp
  915     (flush _test-output-buffered-file)
  916     (flush _test-error-buffered-file)
  917 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
  923     # check output
  924     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout: output should be empty")
  925     (check-next-stream-line-equal _test-error-stream  "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-inout: error message")
  926     # check that stop(1) was called
  927     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout: exit status")
  928     # don't restore from ebp
  929     81 0/subop/add %esp 8/imm32
  930     # . epilogue
  931     5d/pop-to-ebp
  932     c3/return
  933 
  934 test-function-with-addr-inout-2:
  935     # . prologue
  936     55/push-ebp
  937     89/<- %ebp 4/r32/esp
  938     # setup
  939     (clear-stream _test-input-stream)
  940     (clear-stream $_test-input-buffered-file->buffer)
  941     (clear-stream _test-output-stream)
  942     (clear-stream $_test-output-buffered-file->buffer)
  943     (clear-stream _test-error-stream)
  944     (clear-stream $_test-error-buffered-file->buffer)
  945     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  946     68/push 0/imm32
  947     68/push 0/imm32
  948     89/<- %edx 4/r32/esp
  949     (tailor-exit-descriptor %edx 0x10)
  950     #
  951     (write _test-input-stream "fn foo a: (addr array addr int) {\n")
  952     (write _test-input-stream "}\n")
  953     # convert
  954     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  955     # registers except esp clobbered at this point
  956     # restore ed
  957     89/<- %edx 4/r32/esp
  958     (flush _test-output-buffered-file)
  959     (flush _test-error-buffered-file)
  960 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
  966     # check output
  967     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout-2: output should be empty")
  968     (check-next-stream-line-equal _test-error-stream  "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-inout-2: error message")
  969     # check that stop(1) was called
  970     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout-2: exit status")
  971     # don't restore from ebp
  972     81 0/subop/add %esp 8/imm32
  973     # . epilogue
  974     5d/pop-to-ebp
  975     c3/return
  976 
  977 test-function-with-addr-inout-3:
  978     # . prologue
  979     55/push-ebp
  980     89/<- %ebp 4/r32/esp
  981     # setup
  982     (clear-stream _test-input-stream)
  983     (clear-stream $_test-input-buffered-file->buffer)
  984     (clear-stream _test-output-stream)
  985     (clear-stream $_test-output-buffered-file->buffer)
  986     (clear-stream _test-error-stream)
  987     (clear-stream $_test-error-buffered-file->buffer)
  988     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  989     68/push 0/imm32
  990     68/push 0/imm32
  991     89/<- %edx 4/r32/esp
  992     (tailor-exit-descriptor %edx 0x10)
  993     #
  994     (write _test-input-stream "fn foo a: (addr array (addr int) 3) {\n")
  995     (write _test-input-stream "}\n")
  996     # convert
  997     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  998     # registers except esp clobbered at this point
  999     # restore ed
 1000     89/<- %edx 4/r32/esp
 1001     (flush _test-output-buffered-file)
 1002     (flush _test-error-buffered-file)
 1003 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1009     # check output
 1010     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout-3: output should be empty")
 1011     (check-next-stream-line-equal _test-error-stream  "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-inout-3: error message")
 1012     # check that stop(1) was called
 1013     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout-3: exit status")
 1014     # don't restore from ebp
 1015     81 0/subop/add %esp 8/imm32
 1016     # . epilogue
 1017     5d/pop-to-ebp
 1018     c3/return
 1019 
 1020 test-function-with-addr-inout-4:
 1021     # . prologue
 1022     55/push-ebp
 1023     89/<- %ebp 4/r32/esp
 1024     # setup
 1025     (clear-stream _test-input-stream)
 1026     (clear-stream $_test-input-buffered-file->buffer)
 1027     (clear-stream _test-output-stream)
 1028     (clear-stream $_test-output-buffered-file->buffer)
 1029     (clear-stream _test-error-stream)
 1030     (clear-stream $_test-error-buffered-file->buffer)
 1031     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1032     68/push 0/imm32
 1033     68/push 0/imm32
 1034     89/<- %edx 4/r32/esp
 1035     (tailor-exit-descriptor %edx 0x10)
 1036     #
 1037     (write _test-input-stream "fn foo a: (array (addr int) 3) {\n")
 1038     (write _test-input-stream "}\n")
 1039     # convert
 1040     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1041     # registers except esp clobbered at this point
 1042     # restore ed
 1043     89/<- %edx 4/r32/esp
 1044     (flush _test-output-buffered-file)
 1045     (flush _test-error-buffered-file)
 1046 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1052     # check output
 1053     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout-4: output should be empty")
 1054     (check-next-stream-line-equal _test-error-stream  "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-inout-4: error message")
 1055     # check that stop(1) was called
 1056     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout-4: exit status")
 1057     # don't restore from ebp
 1058     81 0/subop/add %esp 8/imm32
 1059     # . epilogue
 1060     5d/pop-to-ebp
 1061     c3/return
 1062 
 1063 # 'main' is an exception
 1064 test-function-main-with-addr-inout:
 1065     # . prologue
 1066     55/push-ebp
 1067     89/<- %ebp 4/r32/esp
 1068     # setup
 1069     (clear-stream _test-input-stream)
 1070     (clear-stream $_test-input-buffered-file->buffer)
 1071     (clear-stream _test-output-stream)
 1072     (clear-stream $_test-output-buffered-file->buffer)
 1073     #
 1074     (write _test-input-stream "fn main a: (addr addr int) {\n")
 1075     (write _test-input-stream "}\n")
 1076     # convert
 1077     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1078     (flush _test-output-buffered-file)
 1079     # no errors
 1080     # . epilogue
 1081     89/<- %esp 5/r32/ebp
 1082     5d/pop-to-ebp
 1083     c3/return
 1084 
 1085 # 'lookup' is an exception, but only in signatures
 1086 test-signature-lookup-with-addr-inout:
 1087     # . prologue
 1088     55/push-ebp
 1089     89/<- %ebp 4/r32/esp
 1090     # setup
 1091     (clear-stream _test-input-stream)
 1092     (clear-stream $_test-input-buffered-file->buffer)
 1093     (clear-stream _test-output-stream)
 1094     (clear-stream $_test-output-buffered-file->buffer)
 1095     #
 1096     (write _test-input-stream "sig lookup h: (handle _T) -> _/eax: (addr _T)\n")
 1097     # convert
 1098     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1099     (flush _test-output-buffered-file)
 1100     # no errors
 1101     # . epilogue
 1102     89/<- %esp 5/r32/ebp
 1103     5d/pop-to-ebp
 1104     c3/return
 1105 
 1106 test-convert-function-with-arg-and-body:
 1107     # . prologue
 1108     55/push-ebp
 1109     89/<- %ebp 4/r32/esp
 1110     # setup
 1111     (clear-stream _test-input-stream)
 1112     (clear-stream $_test-input-buffered-file->buffer)
 1113     (clear-stream _test-output-stream)
 1114     (clear-stream $_test-output-buffered-file->buffer)
 1115     #
 1116     (write _test-input-stream "fn foo n: int {\n")
 1117     (write _test-input-stream "  increment n\n")
 1118     (write _test-input-stream "}\n")
 1119     # convert
 1120     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1121     (flush _test-output-buffered-file)
 1122 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1128     # check output
 1129     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-arg-and-body/0")
 1130     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-arg-and-body/1")
 1131     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-arg-and-body/2")
 1132     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-arg-and-body/3")
 1133     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-arg-and-body/4")
 1134     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-arg-and-body/5")
 1135     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-arg-and-body/6")
 1136     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-arg-and-body/7")
 1137     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-arg-and-body/8")
 1138     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-arg-and-body/9")
 1139     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-arg-and-body/10")
 1140     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-arg-and-body/11")
 1141     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-arg-and-body/12")
 1142     # . epilogue
 1143     89/<- %esp 5/r32/ebp
 1144     5d/pop-to-ebp
 1145     c3/return
 1146 
 1147 test-convert-function-distinguishes-args:
 1148     # . prologue
 1149     55/push-ebp
 1150     89/<- %ebp 4/r32/esp
 1151     # setup
 1152     (clear-stream _test-input-stream)
 1153     (clear-stream $_test-input-buffered-file->buffer)
 1154     (clear-stream _test-output-stream)
 1155     (clear-stream $_test-output-buffered-file->buffer)
 1156     #
 1157     (write _test-input-stream "fn foo a: int, b: int {\n")
 1158     (write _test-input-stream "  increment b\n")
 1159     (write _test-input-stream "}\n")
 1160     # convert
 1161     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1162     (flush _test-output-buffered-file)
 1163 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1169     # check output
 1170     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-distinguishes-args/0")
 1171     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-distinguishes-args/1")
 1172     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-distinguishes-args/2")
 1173     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-distinguishes-args/3")
 1174     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-distinguishes-args/4")
 1175     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-distinguishes-args/5")
 1176     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0x0000000c)"  "F - test-convert-function-distinguishes-args/6")
 1177     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-distinguishes-args/7")
 1178     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-distinguishes-args/8")
 1179     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-distinguishes-args/9")
 1180     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-distinguishes-args/10")
 1181     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-distinguishes-args/11")
 1182     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-distinguishes-args/12")
 1183     # . epilogue
 1184     89/<- %esp 5/r32/ebp
 1185     5d/pop-to-ebp
 1186     c3/return
 1187 
 1188 test-convert-function-with-return-literal:
 1189     # . prologue
 1190     55/push-ebp
 1191     89/<- %ebp 4/r32/esp
 1192     # setup
 1193     (clear-stream _test-input-stream)
 1194     (clear-stream $_test-input-buffered-file->buffer)
 1195     (clear-stream _test-output-stream)
 1196     (clear-stream $_test-output-buffered-file->buffer)
 1197     #
 1198     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1199     (write _test-input-stream "  return 0\n")
 1200     (write _test-input-stream "}\n")
 1201     # convert
 1202     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1203     (flush _test-output-buffered-file)
 1204 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1210     # check output
 1211     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-literal/0")
 1212     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-literal/1")
 1213     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-literal/2")
 1214     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-literal/3")
 1215     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-literal/4")
 1216     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-literal/5")
 1217     (check-next-stream-line-equal _test-output-stream "    c7 0/subop/copy %eax 0/imm32"  "F - test-convert-function-with-return-literal/6")
 1218     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-literal/7")
 1219     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-literal/8")
 1220     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-literal/9")
 1221     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-literal/10")
 1222     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-literal/11")
 1223     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-literal/12")
 1224     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-literal/13")
 1225     # . epilogue
 1226     89/<- %esp 5/r32/ebp
 1227     5d/pop-to-ebp
 1228     c3/return
 1229 
 1230 test-convert-function-with-return:
 1231     # . prologue
 1232     55/push-ebp
 1233     89/<- %ebp 4/r32/esp
 1234     # setup
 1235     (clear-stream _test-input-stream)
 1236     (clear-stream $_test-input-buffered-file->buffer)
 1237     (clear-stream _test-output-stream)
 1238     (clear-stream $_test-output-buffered-file->buffer)
 1239     #
 1240     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1241     (write _test-input-stream "  var y: int\n")
 1242     (write _test-input-stream "  return y\n")
 1243     (write _test-input-stream "}\n")
 1244     # convert
 1245     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1246     (flush _test-output-buffered-file)
 1247 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1253     # check output
 1254     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return/0")
 1255     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return/1")
 1256     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return/2")
 1257     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return/3")
 1258     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return/4")
 1259     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return/5")
 1260     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-return/6")  # y
 1261     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0xfffffffc) 0x00000000/r32" "F - test-convert-function-with-return/7")
 1262     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-return/8")
 1263     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return/9")
 1264     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return/10")
 1265     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return/11")
 1266     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return/12")
 1267     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return/13")
 1268     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return/14")
 1269     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return/15")
 1270     # . epilogue
 1271     89/<- %esp 5/r32/ebp
 1272     5d/pop-to-ebp
 1273     c3/return
 1274 
 1275 test-convert-function-with-return-float:
 1276     # . prologue
 1277     55/push-ebp
 1278     89/<- %ebp 4/r32/esp
 1279     # setup
 1280     (clear-stream _test-input-stream)
 1281     (clear-stream $_test-input-buffered-file->buffer)
 1282     (clear-stream _test-output-stream)
 1283     (clear-stream $_test-output-buffered-file->buffer)
 1284     #
 1285     (write _test-input-stream "fn foo -> _/xmm0: float {\n")
 1286     (write _test-input-stream "  var y: float\n")
 1287     (write _test-input-stream "  return y\n")
 1288     (write _test-input-stream "}\n")
 1289     # convert
 1290     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1291     (flush _test-output-buffered-file)
 1292 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1298     # check output
 1299     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return/0")
 1300     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return/1")
 1301     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return/2")
 1302     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return/3")
 1303     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return/4")
 1304     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return/5")
 1305     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-return/6")  # y
 1306     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *(ebp+0xfffffffc) 0x00000000/x32" "F - test-convert-function-with-return/7")
 1307     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-return/8")
 1308     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return/9")
 1309     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return/10")
 1310     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return/11")
 1311     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return/12")
 1312     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return/13")
 1313     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return/14")
 1314     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return/15")
 1315     # . epilogue
 1316     89/<- %esp 5/r32/ebp
 1317     5d/pop-to-ebp
 1318     c3/return
 1319 
 1320 test-convert-function-with-return-register:
 1321     # . prologue
 1322     55/push-ebp
 1323     89/<- %ebp 4/r32/esp
 1324     # setup
 1325     (clear-stream _test-input-stream)
 1326     (clear-stream $_test-input-buffered-file->buffer)
 1327     (clear-stream _test-output-stream)
 1328     (clear-stream $_test-output-buffered-file->buffer)
 1329     #
 1330     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1331     (write _test-input-stream "  var y/eax: int <- copy 3\n")
 1332     (write _test-input-stream "  return y\n")
 1333     (write _test-input-stream "}\n")
 1334     # convert
 1335     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1336     (flush _test-output-buffered-file)
 1337 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1343     # check output
 1344     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register/0")
 1345     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register/1")
 1346     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register/2")
 1347     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register/3")
 1348     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register/4")
 1349     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register/5")
 1350     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register/6")
 1351     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-convert-function-with-return-register/7")
 1352     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-return-register/8")
 1353     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-return-register/9")
 1354     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-register/10")
 1355     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register/11")
 1356     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register/12")
 1357     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register/13")
 1358     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register/14")
 1359     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register/15")
 1360     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register/16")
 1361     # . epilogue
 1362     89/<- %esp 5/r32/ebp
 1363     5d/pop-to-ebp
 1364     c3/return
 1365 
 1366 test-function-with-output-without-register:
 1367     # . prologue
 1368     55/push-ebp
 1369     89/<- %ebp 4/r32/esp
 1370     # setup
 1371     (clear-stream _test-input-stream)
 1372     (clear-stream $_test-input-buffered-file->buffer)
 1373     (clear-stream _test-output-stream)
 1374     (clear-stream $_test-output-buffered-file->buffer)
 1375     (clear-stream _test-error-stream)
 1376     (clear-stream $_test-error-buffered-file->buffer)
 1377     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1378     68/push 0/imm32
 1379     68/push 0/imm32
 1380     89/<- %edx 4/r32/esp
 1381     (tailor-exit-descriptor %edx 0x10)
 1382     #
 1383     (write _test-input-stream "fn foo -> _: int {\n")
 1384     (write _test-input-stream "}\n")
 1385     # convert
 1386     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1387     # registers except esp clobbered at this point
 1388     # restore ed
 1389     89/<- %edx 4/r32/esp
 1390     (flush _test-output-buffered-file)
 1391     (flush _test-error-buffered-file)
 1392 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1398     # check output
 1399     (check-stream-equal _test-output-stream  ""  "F - test-function-with-output-without-register: output should be empty")
 1400     (check-next-stream-line-equal _test-error-stream  "fn foo: function output '_' must be in a register, in instruction 'fn foo -> _: int {"  "F - test-function-with-output-without-register: error message")
 1401     # check that stop(1) was called
 1402     (check-ints-equal *(edx+4) 2 "F - test-function-with-output-without-register: exit status")
 1403     # don't restore from ebp
 1404     81 0/subop/add %esp 8/imm32
 1405     # . epilogue
 1406     5d/pop-to-ebp
 1407     c3/return
 1408 
 1409 test-function-with-outputs-in-conflicting-registers:
 1410     # . prologue
 1411     55/push-ebp
 1412     89/<- %ebp 4/r32/esp
 1413     # setup
 1414     (clear-stream _test-input-stream)
 1415     (clear-stream $_test-input-buffered-file->buffer)
 1416     (clear-stream _test-output-stream)
 1417     (clear-stream $_test-output-buffered-file->buffer)
 1418     (clear-stream _test-error-stream)
 1419     (clear-stream $_test-error-buffered-file->buffer)
 1420     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1421     68/push 0/imm32
 1422     68/push 0/imm32
 1423     89/<- %edx 4/r32/esp
 1424     (tailor-exit-descriptor %edx 0x10)
 1425     #
 1426     (write _test-input-stream "fn foo -> _/eax: int, _/eax: int {\n")
 1427     (write _test-input-stream "}\n")
 1428     # convert
 1429     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1430     # registers except esp clobbered at this point
 1431     # restore ed
 1432     89/<- %edx 4/r32/esp
 1433     (flush _test-output-buffered-file)
 1434     (flush _test-error-buffered-file)
 1435 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1441     # check output
 1442     (check-stream-equal _test-output-stream  ""  "F - test-function-with-outputs-in-conflicting-registers: output should be empty")
 1443     (check-next-stream-line-equal _test-error-stream  "fn foo: outputs must be in unique registers"  "F - test-function-with-outputs-in-conflicting-registers: error message")
 1444     # check that stop(1) was called
 1445     (check-ints-equal *(edx+4) 2 "F - test-function-with-outputs-in-conflicting-registers: exit status")
 1446     # don't restore from ebp
 1447     81 0/subop/add %esp 8/imm32
 1448     # . epilogue
 1449     5d/pop-to-ebp
 1450     c3/return
 1451 
 1452 test-function-with-named-output:
 1453     # . prologue
 1454     55/push-ebp
 1455     89/<- %ebp 4/r32/esp
 1456     # setup
 1457     (clear-stream _test-input-stream)
 1458     (clear-stream $_test-input-buffered-file->buffer)
 1459     (clear-stream _test-output-stream)
 1460     (clear-stream $_test-output-buffered-file->buffer)
 1461     (clear-stream _test-error-stream)
 1462     (clear-stream $_test-error-buffered-file->buffer)
 1463     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1464     68/push 0/imm32
 1465     68/push 0/imm32
 1466     89/<- %edx 4/r32/esp
 1467     (tailor-exit-descriptor %edx 0x10)
 1468     #
 1469     (write _test-input-stream "fn foo -> x/eax: int {\n")
 1470     (write _test-input-stream "  return 0\n")
 1471     (write _test-input-stream "}\n")
 1472     # convert
 1473     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1474     # registers except esp clobbered at this point
 1475     # restore ed
 1476     89/<- %edx 4/r32/esp
 1477     (flush _test-output-buffered-file)
 1478     (flush _test-error-buffered-file)
 1479 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1485     # check output
 1486     (check-stream-equal _test-output-stream  ""  "F - test-function-with-named-output: output should be empty")
 1487     (check-next-stream-line-equal _test-error-stream  "fn foo: function outputs cannot be named; rename 'x' in the header to '_'"  "F - test-function-with-named-output: error message")
 1488     # check that stop(1) was called
 1489     (check-ints-equal *(edx+4) 2 "F - test-function-with-named-output: exit status")
 1490     # don't restore from ebp
 1491     81 0/subop/add %esp 8/imm32
 1492     # . epilogue
 1493     5d/pop-to-ebp
 1494     c3/return
 1495 
 1496 test-return-with-wrong-type:
 1497     # . prologue
 1498     55/push-ebp
 1499     89/<- %ebp 4/r32/esp
 1500     # setup
 1501     (clear-stream _test-input-stream)
 1502     (clear-stream $_test-input-buffered-file->buffer)
 1503     (clear-stream _test-output-stream)
 1504     (clear-stream $_test-output-buffered-file->buffer)
 1505     (clear-stream _test-error-stream)
 1506     (clear-stream $_test-error-buffered-file->buffer)
 1507     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1508     68/push 0/imm32
 1509     68/push 0/imm32
 1510     89/<- %edx 4/r32/esp
 1511     (tailor-exit-descriptor %edx 0x10)
 1512     #
 1513     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1514     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 1515     (write _test-input-stream "  return x\n")
 1516     (write _test-input-stream "}\n")
 1517     # convert
 1518     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1519     # registers except esp clobbered at this point
 1520     # restore ed
 1521     89/<- %edx 4/r32/esp
 1522     (flush _test-output-buffered-file)
 1523     (flush _test-error-buffered-file)
 1524 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1530     # check output
 1531     (check-stream-equal _test-output-stream  ""  "F - test-return-with-wrong-type: output should be empty")
 1532     (check-next-stream-line-equal _test-error-stream  "fn foo: return: 'x' has the wrong type"  "F - test-return-with-wrong-type: error message")
 1533     # check that stop(1) was called
 1534     (check-ints-equal *(edx+4) 2 "F - test-return-with-wrong-type: exit status")
 1535     # don't restore from ebp
 1536     81 0/subop/add %esp 8/imm32
 1537     # . epilogue
 1538     5d/pop-to-ebp
 1539     c3/return
 1540 
 1541 test-missing-return:
 1542     # . prologue
 1543     55/push-ebp
 1544     89/<- %ebp 4/r32/esp
 1545     # setup
 1546     (clear-stream _test-input-stream)
 1547     (clear-stream $_test-input-buffered-file->buffer)
 1548     (clear-stream _test-output-stream)
 1549     (clear-stream $_test-output-buffered-file->buffer)
 1550     (clear-stream _test-error-stream)
 1551     (clear-stream $_test-error-buffered-file->buffer)
 1552     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1553     68/push 0/imm32
 1554     68/push 0/imm32
 1555     89/<- %edx 4/r32/esp
 1556     (tailor-exit-descriptor %edx 0x10)
 1557     #
 1558     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1559     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 1560     (write _test-input-stream "}\n")
 1561     # convert
 1562     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1563     # registers except esp clobbered at this point
 1564     # restore ed
 1565     89/<- %edx 4/r32/esp
 1566     (flush _test-output-buffered-file)
 1567     (flush _test-error-buffered-file)
 1568 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1574     # check output
 1575     (check-stream-equal _test-output-stream  ""  "F - test-missing-return: output should be empty")
 1576     (check-next-stream-line-equal _test-error-stream  "fn foo: final statement should be a 'return'"  "F - test-missing-return: error message")
 1577     # check that stop(1) was called
 1578     (check-ints-equal *(edx+4) 2 "F - test-missing-return: exit status")
 1579     # don't restore from ebp
 1580     81 0/subop/add %esp 8/imm32
 1581     # . epilogue
 1582     5d/pop-to-ebp
 1583     c3/return
 1584 
 1585 test-missing-return-2:
 1586     # . prologue
 1587     55/push-ebp
 1588     89/<- %ebp 4/r32/esp
 1589     # setup
 1590     (clear-stream _test-input-stream)
 1591     (clear-stream $_test-input-buffered-file->buffer)
 1592     (clear-stream _test-output-stream)
 1593     (clear-stream $_test-output-buffered-file->buffer)
 1594     (clear-stream _test-error-stream)
 1595     (clear-stream $_test-error-buffered-file->buffer)
 1596     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1597     68/push 0/imm32
 1598     68/push 0/imm32
 1599     89/<- %edx 4/r32/esp
 1600     (tailor-exit-descriptor %edx 0x10)
 1601     #
 1602     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1603     (write _test-input-stream "}\n")
 1604     # convert
 1605     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1606     # registers except esp clobbered at this point
 1607     # restore ed
 1608     89/<- %edx 4/r32/esp
 1609     (flush _test-output-buffered-file)
 1610     (flush _test-error-buffered-file)
 1611 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1617     # check output
 1618     (check-stream-equal _test-output-stream  ""  "F - test-missing-return-2: output should be empty")
 1619     (check-next-stream-line-equal _test-error-stream  "fn foo: final statement should be a 'return'"  "F - test-missing-return-2: error message")
 1620     # check that stop(1) was called
 1621     (check-ints-equal *(edx+4) 2 "F - test-missing-return-2: exit status")
 1622     # don't restore from ebp
 1623     81 0/subop/add %esp 8/imm32
 1624     # . epilogue
 1625     5d/pop-to-ebp
 1626     c3/return
 1627 
 1628 test-early-exit-without-return:
 1629     # . prologue
 1630     55/push-ebp
 1631     89/<- %ebp 4/r32/esp
 1632     # setup
 1633     (clear-stream _test-input-stream)
 1634     (clear-stream $_test-input-buffered-file->buffer)
 1635     (clear-stream _test-output-stream)
 1636     (clear-stream $_test-output-buffered-file->buffer)
 1637     (clear-stream _test-error-stream)
 1638     (clear-stream $_test-error-buffered-file->buffer)
 1639     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1640     68/push 0/imm32
 1641     68/push 0/imm32
 1642     89/<- %edx 4/r32/esp
 1643     (tailor-exit-descriptor %edx 0x10)
 1644     #
 1645     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1646     (write _test-input-stream "  break\n")
 1647     (write _test-input-stream "  return 0\n")
 1648     (write _test-input-stream "}\n")
 1649     # convert
 1650     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1651     # registers except esp clobbered at this point
 1652     # restore ed
 1653     89/<- %edx 4/r32/esp
 1654     (flush _test-output-buffered-file)
 1655     (flush _test-error-buffered-file)
 1656 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1662     # check output
 1663     (check-stream-equal _test-output-stream  ""  "F - test-early-exit-without-return: output should be empty")
 1664     (check-next-stream-line-equal _test-error-stream  "fn foo has outputs, so you cannot 'break' out of the outermost block. Use 'return'."  "F - test-early-exit-without-return: error message")
 1665     # check that stop(1) was called
 1666     (check-ints-equal *(edx+4) 2 "F - test-early-exit-without-return: exit status")
 1667     # don't restore from ebp
 1668     81 0/subop/add %esp 8/imm32
 1669     # . epilogue
 1670     5d/pop-to-ebp
 1671     c3/return
 1672 
 1673 test-return-with-too-few-inouts:
 1674     # . prologue
 1675     55/push-ebp
 1676     89/<- %ebp 4/r32/esp
 1677     # setup
 1678     (clear-stream _test-input-stream)
 1679     (clear-stream $_test-input-buffered-file->buffer)
 1680     (clear-stream _test-output-stream)
 1681     (clear-stream $_test-output-buffered-file->buffer)
 1682     (clear-stream _test-error-stream)
 1683     (clear-stream $_test-error-buffered-file->buffer)
 1684     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1685     68/push 0/imm32
 1686     68/push 0/imm32
 1687     89/<- %edx 4/r32/esp
 1688     (tailor-exit-descriptor %edx 0x10)
 1689     #
 1690     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1691     (write _test-input-stream "  return\n")
 1692     (write _test-input-stream "}\n")
 1693     # convert
 1694     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1695     # registers except esp clobbered at this point
 1696     # restore ed
 1697     89/<- %edx 4/r32/esp
 1698     (flush _test-output-buffered-file)
 1699     (flush _test-error-buffered-file)
 1700 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1706     # check output
 1707     (check-stream-equal _test-output-stream  ""  "F - test-return-with-too-few-inouts: output should be empty")
 1708     (check-next-stream-line-equal _test-error-stream  "fn foo: return: too few inouts"  "F - test-return-with-too-few-inouts: error message")
 1709     # check that stop(1) was called
 1710     (check-ints-equal *(edx+4) 2 "F - test-return-with-too-few-inouts: exit status")
 1711     # don't restore from ebp
 1712     81 0/subop/add %esp 8/imm32
 1713     # . epilogue
 1714     5d/pop-to-ebp
 1715     c3/return
 1716 
 1717 test-return-with-too-many-inouts:
 1718     # . prologue
 1719     55/push-ebp
 1720     89/<- %ebp 4/r32/esp
 1721     # setup
 1722     (clear-stream _test-input-stream)
 1723     (clear-stream $_test-input-buffered-file->buffer)
 1724     (clear-stream _test-output-stream)
 1725     (clear-stream $_test-output-buffered-file->buffer)
 1726     (clear-stream _test-error-stream)
 1727     (clear-stream $_test-error-buffered-file->buffer)
 1728     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1729     68/push 0/imm32
 1730     68/push 0/imm32
 1731     89/<- %edx 4/r32/esp
 1732     (tailor-exit-descriptor %edx 0x10)
 1733     #
 1734     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1735     (write _test-input-stream "  return 0, 0\n")
 1736     (write _test-input-stream "}\n")
 1737     # convert
 1738     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1739     # registers except esp clobbered at this point
 1740     # restore ed
 1741     89/<- %edx 4/r32/esp
 1742     (flush _test-output-buffered-file)
 1743     (flush _test-error-buffered-file)
 1744 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1750     # check output
 1751     (check-stream-equal _test-output-stream  ""  "F - test-return-with-too-many-inouts: output should be empty")
 1752     (check-next-stream-line-equal _test-error-stream  "fn foo: return: too many inouts"  "F - test-return-with-too-many-inouts: error message")
 1753     # check that stop(1) was called
 1754     (check-ints-equal *(edx+4) 2 "F - test-return-with-too-many-inouts: exit status")
 1755     # don't restore from ebp
 1756     81 0/subop/add %esp 8/imm32
 1757     # . epilogue
 1758     5d/pop-to-ebp
 1759     c3/return
 1760 
 1761 test-return-unavailable-value:
 1762     # . prologue
 1763     55/push-ebp
 1764     89/<- %ebp 4/r32/esp
 1765     # setup
 1766     (clear-stream _test-input-stream)
 1767     (clear-stream $_test-input-buffered-file->buffer)
 1768     (clear-stream _test-output-stream)
 1769     (clear-stream $_test-output-buffered-file->buffer)
 1770     (clear-stream _test-error-stream)
 1771     (clear-stream $_test-error-buffered-file->buffer)
 1772     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1773     68/push 0/imm32
 1774     68/push 0/imm32
 1775     89/<- %edx 4/r32/esp
 1776     (tailor-exit-descriptor %edx 0x10)
 1777     #
 1778     (write _test-input-stream "fn foo -> _/eax: int, _/ecx: int {\n")
 1779     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 1780     (write _test-input-stream "  var y/ecx: int <- copy 0\n")
 1781     (write _test-input-stream "  return y, x\n")
 1782     (write _test-input-stream "}\n")
 1783     # convert
 1784     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1785     # registers except esp clobbered at this point
 1786     # restore ed
 1787     89/<- %edx 4/r32/esp
 1788     (flush _test-output-buffered-file)
 1789     (flush _test-error-buffered-file)
 1790 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1796     # check output
 1797     (check-stream-equal _test-output-stream  ""  "F - test-return-unavailable-value: output should be empty")
 1798     (check-next-stream-line-equal _test-error-stream  "fn foo: return: 'x' is no longer available"  "F - test-return-unavailable-value: error message")
 1799     # check that stop(1) was called
 1800     (check-ints-equal *(edx+4) 2 "F - test-return-unavailable-value: exit status")
 1801     # don't restore from ebp
 1802     81 0/subop/add %esp 8/imm32
 1803     # . epilogue
 1804     5d/pop-to-ebp
 1805     c3/return
 1806 
 1807 test-return-literal-to-float:
 1808     # . prologue
 1809     55/push-ebp
 1810     89/<- %ebp 4/r32/esp
 1811     # setup
 1812     (clear-stream _test-input-stream)
 1813     (clear-stream $_test-input-buffered-file->buffer)
 1814     (clear-stream _test-output-stream)
 1815     (clear-stream $_test-output-buffered-file->buffer)
 1816     (clear-stream _test-error-stream)
 1817     (clear-stream $_test-error-buffered-file->buffer)
 1818     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1819     68/push 0/imm32
 1820     68/push 0/imm32
 1821     89/<- %edx 4/r32/esp
 1822     (tailor-exit-descriptor %edx 0x10)
 1823     #
 1824     (write _test-input-stream "fn foo -> _/xmm0: float {\n")
 1825     (write _test-input-stream "  return 0\n")
 1826     (write _test-input-stream "}\n")
 1827     # convert
 1828     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1829     # registers except esp clobbered at this point
 1830     # restore ed
 1831     89/<- %edx 4/r32/esp
 1832     (flush _test-output-buffered-file)
 1833     (flush _test-error-buffered-file)
 1834 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1840     # check output
 1841     (check-stream-equal _test-output-stream  ""  "F - test-return-literal-to-float: output should be empty")
 1842     (check-next-stream-line-equal _test-error-stream  "fn foo: return: cannot copy literal '0' to float"  "F - test-return-literal-to-float: error message")
 1843     # check that stop(1) was called
 1844     (check-ints-equal *(edx+4) 2 "F - test-return-literal-to-float: exit status")
 1845     # don't restore from ebp
 1846     81 0/subop/add %esp 8/imm32
 1847     # . epilogue
 1848     5d/pop-to-ebp
 1849     c3/return
 1850 
 1851 test-convert-return-with-duplicate-values:
 1852     # . prologue
 1853     55/push-ebp
 1854     89/<- %ebp 4/r32/esp
 1855     # setup
 1856     (clear-stream _test-input-stream)
 1857     (clear-stream $_test-input-buffered-file->buffer)
 1858     (clear-stream _test-output-stream)
 1859     (clear-stream $_test-output-buffered-file->buffer)
 1860     #
 1861     (write _test-input-stream "fn foo -> _/eax: int, _/ecx: int {\n")
 1862     (write _test-input-stream "  var x/eax: int <- copy 0x34\n")
 1863     (write _test-input-stream "  return x, x\n")
 1864     (write _test-input-stream "}\n")
 1865     # convert
 1866     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1867     (flush _test-output-buffered-file)
 1868 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1874     # check output
 1875     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-return-with-duplicate-values/0")
 1876     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-return-with-duplicate-values/1")
 1877     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-return-with-duplicate-values/2")
 1878     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-return-with-duplicate-values/3")
 1879     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-return-with-duplicate-values/4")
 1880     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-return-with-duplicate-values/5")
 1881     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-return-with-duplicate-values/6")
 1882     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0x34/imm32"  "F - test-convert-return-with-duplicate-values/7")
 1883     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32"  "F - test-convert-return-with-duplicate-values/8")
 1884     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000001/r32"  "F - test-convert-return-with-duplicate-values/9")
 1885     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-return-with-duplicate-values/10")
 1886     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-return-with-duplicate-values/11")
 1887     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-return-with-duplicate-values/12")
 1888     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-return-with-duplicate-values/13")
 1889     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-return-with-duplicate-values/14")
 1890     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-return-with-duplicate-values/15")
 1891     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-return-with-duplicate-values/16")
 1892     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-return-with-duplicate-values/17")
 1893     # . epilogue
 1894     89/<- %esp 5/r32/ebp
 1895     5d/pop-to-ebp
 1896     c3/return
 1897 
 1898 test-convert-return-with-duplicate-values-2:
 1899     # . prologue
 1900     55/push-ebp
 1901     89/<- %ebp 4/r32/esp
 1902     # setup
 1903     (clear-stream _test-input-stream)
 1904     (clear-stream $_test-input-buffered-file->buffer)
 1905     (clear-stream _test-output-stream)
 1906     (clear-stream $_test-output-buffered-file->buffer)
 1907     #
 1908     (write _test-input-stream "fn foo -> _/eax: int, _/ecx: int {\n")
 1909     (write _test-input-stream "  var x/ecx: int <- copy 0x34\n")
 1910     (write _test-input-stream "  return x, x\n")
 1911     (write _test-input-stream "}\n")
 1912     # convert
 1913     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1914     (flush _test-output-buffered-file)
 1915 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1921     # check output
 1922     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-return-with-duplicate-values-2/0")
 1923     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-return-with-duplicate-values-2/1")
 1924     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-return-with-duplicate-values-2/2")
 1925     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-return-with-duplicate-values-2/3")
 1926     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-return-with-duplicate-values-2/4")
 1927     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-return-with-duplicate-values-2/5")
 1928     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-return-with-duplicate-values-2/6")
 1929     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0x34/imm32"  "F - test-convert-return-with-duplicate-values-2/7")
 1930     (check-next-stream-line-equal _test-output-stream "    8b/-> %ecx 0x00000000/r32"  "F - test-convert-return-with-duplicate-values-2/8")
 1931     (check-next-stream-line-equal _test-output-stream "    8b/-> %ecx 0x00000001/r32"  "F - test-convert-return-with-duplicate-values-2/9")
 1932     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-return-with-duplicate-values-2/10")
 1933     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-return-with-duplicate-values-2/11")
 1934     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-return-with-duplicate-values-2/12")
 1935     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-return-with-duplicate-values-2/13")
 1936     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-return-with-duplicate-values-2/14")
 1937     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-return-with-duplicate-values-2/15")
 1938     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-return-with-duplicate-values-2/16")
 1939     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-return-with-duplicate-values-2/17")
 1940     # . epilogue
 1941     89/<- %esp 5/r32/ebp
 1942     5d/pop-to-ebp
 1943     c3/return
 1944 
 1945 test-stmt-with-unknown-var:
 1946     # . prologue
 1947     55/push-ebp
 1948     89/<- %ebp 4/r32/esp
 1949     # setup
 1950     (clear-stream _test-input-stream)
 1951     (clear-stream $_test-input-buffered-file->buffer)
 1952     (clear-stream _test-output-stream)
 1953     (clear-stream $_test-output-buffered-file->buffer)
 1954     (clear-stream _test-error-stream)
 1955     (clear-stream $_test-error-buffered-file->buffer)
 1956     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1957     68/push 0/imm32
 1958     68/push 0/imm32
 1959     89/<- %edx 4/r32/esp
 1960     (tailor-exit-descriptor %edx 0x10)
 1961     #
 1962     (write _test-input-stream "fn foo {\n")
 1963     (write _test-input-stream "  x <- copy 0x34\n")
 1964     (write _test-input-stream "}\n")
 1965     # convert
 1966     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1967     # registers except esp clobbered at this point
 1968     # restore ed
 1969     89/<- %edx 4/r32/esp
 1970     (flush _test-output-buffered-file)
 1971     (flush _test-error-buffered-file)
 1972 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1978     # check output
 1979     (check-stream-equal _test-output-stream  ""  "F - test-stmt-with-unknown-var: output should be empty")
 1980     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-stmt-with-unknown-var: error message")
 1981     # check that stop(1) was called
 1982     (check-ints-equal *(edx+4) 2 "F - test-stmt-with-unknown-var: exit status")
 1983     # don't restore from ebp
 1984     81 0/subop/add %esp 8/imm32
 1985     # . epilogue
 1986     5d/pop-to-ebp
 1987     c3/return
 1988 
 1989 test-stmt-with-invalid-identifier:
 1990     # . prologue
 1991     55/push-ebp
 1992     89/<- %ebp 4/r32/esp
 1993     # setup
 1994     (clear-stream _test-input-stream)
 1995     (clear-stream $_test-input-buffered-file->buffer)
 1996     (clear-stream _test-output-stream)
 1997     (clear-stream $_test-output-buffered-file->buffer)
 1998     (clear-stream _test-error-stream)
 1999     (clear-stream $_test-error-buffered-file->buffer)
 2000     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2001     68/push 0/imm32
 2002     68/push 0/imm32
 2003     89/<- %edx 4/r32/esp
 2004     (tailor-exit-descriptor %edx 0x10)
 2005     #
 2006     (write _test-input-stream "fn foo {\n")
 2007     (write _test-input-stream "  1 <- copy 0x34\n")
 2008     (write _test-input-stream "}\n")
 2009     # convert
 2010     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2011     # registers except esp clobbered at this point
 2012     # restore ed
 2013     89/<- %edx 4/r32/esp
 2014     (flush _test-output-buffered-file)
 2015     (flush _test-error-buffered-file)
 2016 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2022     # check output
 2023     (check-stream-equal _test-output-stream  ""  "F - test-stmt-with-invalid-identifier: output should be empty")
 2024     (check-next-stream-line-equal _test-error-stream  "fn foo: invalid identifier '1'"  "F - test-stmt-with-invalid-identifier: error message")
 2025     # check that stop(1) was called
 2026     (check-ints-equal *(edx+4) 2 "F - test-stmt-with-invalid-identifier: exit status")
 2027     # don't restore from ebp
 2028     81 0/subop/add %esp 8/imm32
 2029     # . epilogue
 2030     5d/pop-to-ebp
 2031     c3/return
 2032 
 2033 test-stmt-with-deref-var:
 2034     # . prologue
 2035     55/push-ebp
 2036     89/<- %ebp 4/r32/esp
 2037     # setup
 2038     (clear-stream _test-input-stream)
 2039     (clear-stream $_test-input-buffered-file->buffer)
 2040     (clear-stream _test-output-stream)
 2041     (clear-stream $_test-output-buffered-file->buffer)
 2042     (clear-stream _test-error-stream)
 2043     (clear-stream $_test-error-buffered-file->buffer)
 2044     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2045     68/push 0/imm32
 2046     68/push 0/imm32
 2047     89/<- %edx 4/r32/esp
 2048     (tailor-exit-descriptor %edx 0x10)
 2049     #
 2050     (write _test-input-stream "fn foo {\n")
 2051     (write _test-input-stream "  *x <- copy 0x34\n")
 2052     (write _test-input-stream "}\n")
 2053     # convert
 2054     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2055     # registers except esp clobbered at this point
 2056     # restore ed
 2057     89/<- %edx 4/r32/esp
 2058     (flush _test-output-buffered-file)
 2059     (flush _test-error-buffered-file)
 2060 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2066     # check output
 2067     (check-stream-equal _test-output-stream  ""  "F - test-stmt-with-deref-var: output should be empty")
 2068     (check-next-stream-line-equal _test-error-stream  "fn foo: output '*x' should write to a register, and therefore cannot be dereferenced"  "F - test-stmt-with-deref-var: error message")
 2069     # check that stop(1) was called
 2070     (check-ints-equal *(edx+4) 2 "F - test-stmt-with-deref-var: exit status")
 2071     # don't restore from ebp
 2072     81 0/subop/add %esp 8/imm32
 2073     # . epilogue
 2074     5d/pop-to-ebp
 2075     c3/return
 2076 
 2077 test-convert-function-with-literal-arg:
 2078     # . prologue
 2079     55/push-ebp
 2080     89/<- %ebp 4/r32/esp
 2081     # setup
 2082     (clear-stream _test-input-stream)
 2083     (clear-stream $_test-input-buffered-file->buffer)
 2084     (clear-stream _test-output-stream)
 2085     (clear-stream $_test-output-buffered-file->buffer)
 2086     #
 2087     (write _test-input-stream "fn foo a: int, b: int -> _/eax: int {\n")
 2088     (write _test-input-stream "  var result/eax: int <- copy a\n")
 2089     (write _test-input-stream "  result <- add 1\n")
 2090     (write _test-input-stream "  return result\n")
 2091     (write _test-input-stream "}\n")
 2092     # convert
 2093     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2094     (flush _test-output-buffered-file)
 2095 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2101     # check output
 2102     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-literal-arg/0")
 2103     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-literal-arg/1")
 2104     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-literal-arg/2")
 2105     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-literal-arg/3")
 2106     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-literal-arg/4")
 2107     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-literal-arg/5")
 2108     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-literal-arg/6")
 2109     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-with-literal-arg/7")
 2110     (check-next-stream-line-equal _test-output-stream "    05/add-to-eax 1/imm32"  "F - test-convert-function-with-literal-arg/8")
 2111     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-literal-arg/9")
 2112     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-literal-arg/10")
 2113     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-literal-arg/11")
 2114     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-literal-arg/12")
 2115     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-literal-arg/13")
 2116     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-literal-arg/14")
 2117     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-literal-arg/15")
 2118     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-literal-arg/16")
 2119     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-literal-arg/17")
 2120     # . epilogue
 2121     89/<- %esp 5/r32/ebp
 2122     5d/pop-to-ebp
 2123     c3/return
 2124 
 2125 test-convert-function-with-literal-arg-2:
 2126     # . prologue
 2127     55/push-ebp
 2128     89/<- %ebp 4/r32/esp
 2129     # setup
 2130     (clear-stream _test-input-stream)
 2131     (clear-stream $_test-input-buffered-file->buffer)
 2132     (clear-stream _test-output-stream)
 2133     (clear-stream $_test-output-buffered-file->buffer)
 2134     #
 2135     (write _test-input-stream "fn foo a: int, b: int -> _/ebx: int {\n")
 2136     (write _test-input-stream "  var result/ebx: int <- copy a\n")
 2137     (write _test-input-stream "  result <- add 1\n")
 2138     (write _test-input-stream "  return result\n")
 2139     (write _test-input-stream "}\n")
 2140     # convert
 2141     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2142     (flush _test-output-buffered-file)
 2143 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2149     # check output
 2150     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-literal-arg-2/0")
 2151     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-literal-arg-2/1")
 2152     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-literal-arg-2/2")
 2153     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-literal-arg-2/3")
 2154     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-literal-arg-2/4")
 2155     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-literal-arg-2/5")
 2156     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-with-literal-arg-2/6")
 2157     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000003/r32"  "F - test-convert-function-with-literal-arg-2/7")
 2158     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %ebx 1/imm32"  "F - test-convert-function-with-literal-arg-2/8")
 2159     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-with-literal-arg-2/9")
 2160     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-literal-arg-2/10")
 2161     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-literal-arg-2/11")
 2162     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-literal-arg-2/12")
 2163     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-literal-arg-2/13")
 2164     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-literal-arg-2/14")
 2165     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-literal-arg-2/15")
 2166     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-literal-arg-2/16")
 2167     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-literal-arg-2/17")
 2168     # . epilogue
 2169     89/<- %esp 5/r32/ebp
 2170     5d/pop-to-ebp
 2171     c3/return
 2172 
 2173 test-convert-function-call-with-literal-arg:
 2174     # . prologue
 2175     55/push-ebp
 2176     89/<- %ebp 4/r32/esp
 2177     # setup
 2178     (clear-stream _test-input-stream)
 2179     (clear-stream $_test-input-buffered-file->buffer)
 2180     (clear-stream _test-output-stream)
 2181     (clear-stream $_test-output-buffered-file->buffer)
 2182     #
 2183     (write _test-input-stream "fn main -> _/ebx: int {\n")
 2184     (write _test-input-stream "  var result/eax: int <- do-add 3 4\n")
 2185     (write _test-input-stream "  return result\n")
 2186     (write _test-input-stream "}\n")
 2187     (write _test-input-stream "fn do-add a: int, b: int -> _/eax: int {\n")
 2188     (write _test-input-stream "  var result/eax: int <- copy a\n")
 2189     (write _test-input-stream "  result <- add b\n")
 2190     (write _test-input-stream "  return result\n")
 2191     (write _test-input-stream "}\n")
 2192     # convert
 2193     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2194     (flush _test-output-buffered-file)
 2195 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2201     # check output
 2202     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call-with-literal-arg/0")
 2203     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-literal-arg/1")
 2204     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-literal-arg/2")
 2205     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-literal-arg/3")
 2206     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-literal-arg/4")
 2207     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call-with-literal-arg/5")
 2208     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/6")
 2209     (check-next-stream-line-equal _test-output-stream "    (do-add 3 4)"        "F - test-convert-function-call-with-literal-arg/7")
 2210     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 2211     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-with-local-var-in-reg/9")
 2212     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 2213     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-literal-arg/11")
 2214     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call-with-literal-arg/12")
 2215     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-literal-arg/13")
 2216     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-literal-arg/14")
 2217     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-literal-arg/15")
 2218     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-literal-arg/16")
 2219     (check-next-stream-line-equal _test-output-stream "do-add:"                 "F - test-convert-function-call-with-literal-arg/17")
 2220     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-literal-arg/18")
 2221     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-literal-arg/19")
 2222     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-literal-arg/20")
 2223     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-literal-arg/21")
 2224     (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:loop:"  "F - test-convert-function-call-with-literal-arg/22")
 2225     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/23")
 2226     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-call-with-literal-arg/24")
 2227     (check-next-stream-line-equal _test-output-stream "    03/add *(ebp+0x0000000c) 0x00000000/r32"  "F - test-convert-function-call-with-literal-arg/25")
 2228     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-call-with-literal-arg/26")
 2229     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
 2230     (check-next-stream-line-equal _test-output-stream "    e9/jump $do-add:0x00000002:break/disp32"  "F - test-convert-function-call-with-literal-arg/28")
 2231     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-literal-arg/29")
 2232     (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:break:"  "F - test-convert-function-call-with-literal-arg/30")
 2233     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-literal-arg/31")
 2234     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-literal-arg/32")
 2235     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-literal-arg/33")
 2236     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-literal-arg/34")
 2237     # . epilogue
 2238     89/<- %esp 5/r32/ebp
 2239     5d/pop-to-ebp
 2240     c3/return
 2241 
 2242 test-convert-function-call-with-literal-string-arg:
 2243     # . prologue
 2244     55/push-ebp
 2245     89/<- %ebp 4/r32/esp
 2246     # setup
 2247     (clear-stream _test-input-stream)
 2248     (clear-stream $_test-input-buffered-file->buffer)
 2249     (clear-stream _test-output-stream)
 2250     (clear-stream $_test-output-buffered-file->buffer)
 2251     #
 2252     (write _test-input-stream "fn foo {\n")
 2253     (write _test-input-stream "  string-func \"abc\"\n")
 2254     (write _test-input-stream "}\n")
 2255     (write _test-input-stream "sig string-func in: (addr array byte)\n")
 2256     # convert
 2257     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2258     # no errors
 2259     # not bothering checking output
 2260     # . epilogue
 2261     89/<- %esp 5/r32/ebp
 2262     5d/pop-to-ebp
 2263     c3/return
 2264 
 2265 test-convert-function-call-with-null-addr:
 2266     # . prologue
 2267     55/push-ebp
 2268     89/<- %ebp 4/r32/esp
 2269     # setup
 2270     (clear-stream _test-input-stream)
 2271     (clear-stream $_test-input-buffered-file->buffer)
 2272     (clear-stream _test-output-stream)
 2273     (clear-stream $_test-output-buffered-file->buffer)
 2274     #
 2275     (write _test-input-stream "fn foo {\n")
 2276     (write _test-input-stream "  bar 0\n")
 2277     (write _test-input-stream "}\n")
 2278     (write _test-input-stream "sig bar in: (addr int)\n")
 2279     # convert
 2280     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2281     # no errors
 2282     # not bothering checking output
 2283     # . epilogue
 2284     89/<- %esp 5/r32/ebp
 2285     5d/pop-to-ebp
 2286     c3/return
 2287 
 2288 test-convert-function-call-with-signature:
 2289     # . prologue
 2290     55/push-ebp
 2291     89/<- %ebp 4/r32/esp
 2292     # setup
 2293     (clear-stream _test-input-stream)
 2294     (clear-stream $_test-input-buffered-file->buffer)
 2295     (clear-stream _test-output-stream)
 2296     (clear-stream $_test-output-buffered-file->buffer)
 2297     #
 2298     (write _test-input-stream "fn main -> _/ebx: int {\n")
 2299     (write _test-input-stream "  var result/eax: int <- do-add 3 4\n")
 2300     (write _test-input-stream "  return result\n")
 2301     (write _test-input-stream "}\n")
 2302     (write _test-input-stream "sig do-add a: int, b: int -> _/eax: int\n")
 2303     # convert
 2304     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2305     (flush _test-output-buffered-file)
 2306 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2312     # check output
 2313     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call-with-signature/0")
 2314     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-signature/1")
 2315     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-signature/2")
 2316     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-signature/3")
 2317     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-signature/4")
 2318     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call-with-signature/5")
 2319     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/6")
 2320     (check-next-stream-line-equal _test-output-stream "    (do-add 3 4)"        "F - test-convert-function-call-with-signature/6")
 2321     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 2322     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-with-local-var-in-reg/9")
 2323     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 2324     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-signature/7")
 2325     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call-with-signature/8")
 2326     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-signature/9")
 2327     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-signature/10")
 2328     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-signature/11")
 2329     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-signature/12")
 2330     # . epilogue
 2331     89/<- %esp 5/r32/ebp
 2332     5d/pop-to-ebp
 2333     c3/return
 2334 
 2335 test-convert-function-with-local-var-in-mem:
 2336     # . prologue
 2337     55/push-ebp
 2338     89/<- %ebp 4/r32/esp
 2339     # setup
 2340     (clear-stream _test-input-stream)
 2341     (clear-stream $_test-input-buffered-file->buffer)
 2342     (clear-stream _test-output-stream)
 2343     (clear-stream $_test-output-buffered-file->buffer)
 2344     #
 2345     (write _test-input-stream "fn foo {\n")
 2346     (write _test-input-stream "  var x: int\n")
 2347     (write _test-input-stream "  increment x\n")
 2348     (write _test-input-stream "}\n")
 2349     # convert
 2350     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2351     (flush _test-output-buffered-file)
 2352 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2358     # check output
 2359     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-mem/0")
 2360     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-mem/1")
 2361     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-mem/2")
 2362     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-mem/3")
 2363     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-mem/4")
 2364     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-mem/5")
 2365     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-in-mem/6")
 2366     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-local-var-in-mem/7")
 2367     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-local-var-in-mem/8")
 2368     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-mem/9")
 2369     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-mem/10")
 2370     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-mem/11")
 2371     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-mem/12")
 2372     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-mem/13")
 2373     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-mem/14")
 2374     # . epilogue
 2375     89/<- %esp 5/r32/ebp
 2376     5d/pop-to-ebp
 2377     c3/return
 2378 
 2379 test-convert-invalid-literal:
 2380     # . prologue
 2381     55/push-ebp
 2382     89/<- %ebp 4/r32/esp
 2383     # setup
 2384     (clear-stream _test-input-stream)
 2385     (clear-stream $_test-input-buffered-file->buffer)
 2386     (clear-stream _test-output-stream)
 2387     (clear-stream $_test-output-buffered-file->buffer)
 2388     (clear-stream _test-error-stream)
 2389     (clear-stream $_test-error-buffered-file->buffer)
 2390     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2391     68/push 0/imm32
 2392     68/push 0/imm32
 2393     89/<- %edx 4/r32/esp
 2394     (tailor-exit-descriptor %edx 0x10)
 2395     #
 2396     (write _test-input-stream "fn foo {\n")
 2397     (write _test-input-stream "  increment 1n\n")
 2398     (write _test-input-stream "}\n")
 2399     # convert
 2400     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2401     # registers except esp clobbered at this point
 2402     # restore ed
 2403     89/<- %edx 4/r32/esp
 2404     (flush _test-output-buffered-file)
 2405     (flush _test-error-buffered-file)
 2406 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2412     # check output
 2413     (check-stream-equal _test-output-stream  ""  "F - test-convert-invalid-literal: output should be empty")
 2414     (check-next-stream-line-equal _test-error-stream  "fn foo: variable '1n' cannot begin with a digit (or do you have a typo in a number?)"  "F - test-convert-invalid-literal: error message")
 2415     # check that stop(1) was called
 2416     (check-ints-equal *(edx+4) 2 "F - test-convert-invalid-literal: exit status")
 2417     # don't restore from ebp
 2418     81 0/subop/add %esp 8/imm32
 2419     # . epilogue
 2420     5d/pop-to-ebp
 2421     c3/return
 2422 
 2423 test-local-var-in-mem-has-no-initializer:
 2424     # . prologue
 2425     55/push-ebp
 2426     89/<- %ebp 4/r32/esp
 2427     # setup
 2428     (clear-stream _test-input-stream)
 2429     (clear-stream $_test-input-buffered-file->buffer)
 2430     (clear-stream _test-output-stream)
 2431     (clear-stream $_test-output-buffered-file->buffer)
 2432     (clear-stream _test-error-stream)
 2433     (clear-stream $_test-error-buffered-file->buffer)
 2434     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2435     68/push 0/imm32
 2436     68/push 0/imm32
 2437     89/<- %edx 4/r32/esp
 2438     (tailor-exit-descriptor %edx 0x10)
 2439     #
 2440     (write _test-input-stream "fn foo {\n")
 2441     (write _test-input-stream "  var x: int <- copy 0\n")
 2442     (write _test-input-stream "  increment x\n")
 2443     (write _test-input-stream "}\n")
 2444     # convert
 2445     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2446     # registers except esp clobbered at this point
 2447     # restore ed
 2448     89/<- %edx 4/r32/esp
 2449     (flush _test-output-buffered-file)
 2450     (flush _test-error-buffered-file)
 2451 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2457     # check output
 2458     (check-stream-equal _test-output-stream  ""  "F - test-var-in-mem-has-no-initializer: output should be empty")
 2459     (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")
 2460     # check that stop(1) was called
 2461     (check-ints-equal *(edx+4) 2 "F - test-var-in-mem-has-no-initializer: exit status")
 2462     # don't restore from ebp
 2463     81 0/subop/add %esp 8/imm32
 2464     # . epilogue
 2465     5d/pop-to-ebp
 2466     c3/return
 2467 
 2468 test-convert-function-with-local-var-with-compound-type-in-mem:
 2469     # . prologue
 2470     55/push-ebp
 2471     89/<- %ebp 4/r32/esp
 2472     # setup
 2473     (clear-stream _test-input-stream)
 2474     (clear-stream $_test-input-buffered-file->buffer)
 2475     (clear-stream _test-output-stream)
 2476     (clear-stream $_test-output-buffered-file->buffer)
 2477     #
 2478     (write _test-input-stream "fn foo {\n")
 2479     (write _test-input-stream "  var x: (addr int)\n")
 2480     (write _test-input-stream "  copy-to x, 0\n")
 2481     (write _test-input-stream "}\n")
 2482     # convert
 2483     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2484     (flush _test-output-buffered-file)
 2485 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2491     # check output
 2492     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-with-compound-type-in-mem/0")
 2493     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-with-compound-type-in-mem/1")
 2494     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-with-compound-type-in-mem/2")
 2495     (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")
 2496     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-compound-type-in-mem/4")
 2497     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-with-compound-type-in-mem/5")
 2498     (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")
 2499     (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")
 2500     (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")
 2501     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-compound-type-in-mem/9")
 2502     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-with-compound-type-in-mem/10")
 2503     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-with-compound-type-in-mem/11")
 2504     (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")
 2505     (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")
 2506     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-with-compound-type-in-mem/14")
 2507     # . epilogue
 2508     89/<- %esp 5/r32/ebp
 2509     5d/pop-to-ebp
 2510     c3/return
 2511 
 2512 test-convert-function-with-local-var-in-reg:
 2513     # . prologue
 2514     55/push-ebp
 2515     89/<- %ebp 4/r32/esp
 2516     # setup
 2517     (clear-stream _test-input-stream)
 2518     (clear-stream $_test-input-buffered-file->buffer)
 2519     (clear-stream _test-output-stream)
 2520     (clear-stream $_test-output-buffered-file->buffer)
 2521     #
 2522     (write _test-input-stream "fn foo {\n")
 2523     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2524     (write _test-input-stream "  x <- increment\n")
 2525     (write _test-input-stream "}\n")
 2526     # convert
 2527     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2528     (flush _test-output-buffered-file)
 2529 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2535     # check output
 2536     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-reg/0")
 2537     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-reg/1")
 2538     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-reg/2")
 2539     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-reg/3")
 2540     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-reg/4")
 2541     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-reg/5")
 2542     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-in-reg/6")
 2543     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-convert-function-with-local-var-in-reg/7")
 2544     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-convert-function-with-local-var-in-reg/8")
 2545     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-in-reg/9")
 2546     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-reg/10")
 2547     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-reg/11")
 2548     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-reg/12")
 2549     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-reg/13")
 2550     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-reg/14")
 2551     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-reg/15")
 2552     # . epilogue
 2553     89/<- %esp 5/r32/ebp
 2554     5d/pop-to-ebp
 2555     c3/return
 2556 
 2557 test-float-var-in-wrong-register:
 2558     # . prologue
 2559     55/push-ebp
 2560     89/<- %ebp 4/r32/esp
 2561     # setup
 2562     (clear-stream _test-input-stream)
 2563     (clear-stream $_test-input-buffered-file->buffer)
 2564     (clear-stream _test-output-stream)
 2565     (clear-stream $_test-output-buffered-file->buffer)
 2566     (clear-stream _test-error-stream)
 2567     (clear-stream $_test-error-buffered-file->buffer)
 2568     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2569     68/push 0/imm32
 2570     68/push 0/imm32
 2571     89/<- %edx 4/r32/esp
 2572     (tailor-exit-descriptor %edx 0x10)
 2573     #
 2574     (write _test-input-stream "fn foo {\n")
 2575     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 2576     (write _test-input-stream "  var y/eax: float <- convert x\n")
 2577     (write _test-input-stream "}\n")
 2578     # convert
 2579     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2580     # registers except esp clobbered at this point
 2581     # restore ed
 2582     89/<- %edx 4/r32/esp
 2583     (flush _test-output-buffered-file)
 2584     (flush _test-error-buffered-file)
 2585 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2591     # check output
 2592     (check-stream-equal _test-output-stream  ""  "F - test-float-var-in-wrong-register: output should be empty")
 2593     (check-next-stream-line-equal _test-error-stream  "fn foo: float var 'y' should be in a floating-point register"  "F - test-float-var-in-wrong-register: error message")
 2594     # check that stop(1) was called
 2595     (check-ints-equal *(edx+4) 2 "F - test-float-var-in-wrong-register: exit status")
 2596     # don't restore from ebp
 2597     81 0/subop/add %esp 8/imm32
 2598     # . epilogue
 2599     5d/pop-to-ebp
 2600     c3/return
 2601 
 2602 test-non-float-var-in-wrong-register:
 2603     # . prologue
 2604     55/push-ebp
 2605     89/<- %ebp 4/r32/esp
 2606     # setup
 2607     (clear-stream _test-input-stream)
 2608     (clear-stream $_test-input-buffered-file->buffer)
 2609     (clear-stream _test-output-stream)
 2610     (clear-stream $_test-output-buffered-file->buffer)
 2611     (clear-stream _test-error-stream)
 2612     (clear-stream $_test-error-buffered-file->buffer)
 2613     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2614     68/push 0/imm32
 2615     68/push 0/imm32
 2616     89/<- %edx 4/r32/esp
 2617     (tailor-exit-descriptor %edx 0x10)
 2618     #
 2619     (write _test-input-stream "fn foo {\n")
 2620     (write _test-input-stream "  var x/xmm5: int <- copy 0\n")
 2621     (write _test-input-stream "}\n")
 2622     # convert
 2623     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2624     # registers except esp clobbered at this point
 2625     # restore ed
 2626     89/<- %edx 4/r32/esp
 2627     (flush _test-output-buffered-file)
 2628     (flush _test-error-buffered-file)
 2629 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2635     # check output
 2636     (check-stream-equal _test-output-stream  ""  "F - test-non-float-var-in-wrong-register: output should be empty")
 2637     (check-next-stream-line-equal _test-error-stream  "fn foo: non-float var 'x' should be in an integer register"  "F - test-non-float-var-in-wrong-register: error message")
 2638     # check that stop(1) was called
 2639     (check-ints-equal *(edx+4) 2 "F - test-non-float-var-in-wrong-register: exit status")
 2640     # don't restore from ebp
 2641     81 0/subop/add %esp 8/imm32
 2642     # . epilogue
 2643     5d/pop-to-ebp
 2644     c3/return
 2645 
 2646 test-convert-function-with-allocate:
 2647     # . prologue
 2648     55/push-ebp
 2649     89/<- %ebp 4/r32/esp
 2650     # setup
 2651     (clear-stream _test-input-stream)
 2652     (clear-stream $_test-input-buffered-file->buffer)
 2653     (clear-stream _test-output-stream)
 2654     (clear-stream $_test-output-buffered-file->buffer)
 2655     #
 2656     (write _test-input-stream "fn foo {\n")
 2657     (write _test-input-stream "  var x/ecx: (addr handle int) <- copy 0\n")
 2658     (write _test-input-stream "  allocate x\n")
 2659     (write _test-input-stream "}\n")
 2660     # convert
 2661     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2662     (flush _test-output-buffered-file)
 2663 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2669     # check output
 2670     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-allocate/0")
 2671     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-allocate/1")
 2672     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-allocate/2")
 2673     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-allocate/3")
 2674     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-allocate/4")
 2675     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-allocate/5")
 2676     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-allocate/6")
 2677     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-allocate/7")
 2678     (check-next-stream-line-equal _test-output-stream "    (allocate Heap 0x00000004 %ecx)"  "F - test-convert-function-with-allocate/8")  # 4 = size-of(int)
 2679     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-allocate/9")
 2680     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-allocate/10")
 2681     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-allocate/11")
 2682     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-allocate/12")
 2683     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-allocate/13")
 2684     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-allocate/14")
 2685     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-allocate/15")
 2686     # . epilogue
 2687     89/<- %esp 5/r32/ebp
 2688     5d/pop-to-ebp
 2689     c3/return
 2690 
 2691 test-initializer-in-hex:
 2692     # . prologue
 2693     55/push-ebp
 2694     89/<- %ebp 4/r32/esp
 2695     # setup
 2696     (clear-stream _test-input-stream)
 2697     (clear-stream $_test-input-buffered-file->buffer)
 2698     (clear-stream _test-output-stream)
 2699     (clear-stream $_test-output-buffered-file->buffer)
 2700     (clear-stream _test-error-stream)
 2701     (clear-stream $_test-error-buffered-file->buffer)
 2702     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2703     68/push 0/imm32
 2704     68/push 0/imm32
 2705     89/<- %edx 4/r32/esp
 2706     (tailor-exit-descriptor %edx 0x10)
 2707     #
 2708     (write _test-input-stream "fn foo {\n")
 2709     (write _test-input-stream "  var x/ecx: int <- copy 10\n")
 2710     (write _test-input-stream "}\n")
 2711     # convert
 2712     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2713     # registers except esp clobbered at this point
 2714     # restore ed
 2715     89/<- %edx 4/r32/esp
 2716     (flush _test-output-buffered-file)
 2717     (flush _test-error-buffered-file)
 2718 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2724     # check output
 2725     (check-stream-equal _test-output-stream  ""  "F - test-initializer-in-hex: output should be empty")
 2726     (check-next-stream-line-equal _test-error-stream  "literal integers are always hex in Mu; start '10' with a '0x' to be unambiguous, converting it to hexadecimal as necessary."  "F - test-initializer-in-hex: error message")
 2727     # check that stop(1) was called
 2728     (check-ints-equal *(edx+4) 2 "F - test-initializer-in-hex: exit status")
 2729     # don't restore from ebp
 2730     81 0/subop/add %esp 8/imm32
 2731     # . epilogue
 2732     5d/pop-to-ebp
 2733     c3/return
 2734 
 2735 test-convert-function-with-second-local-var-in-same-reg:
 2736     # . prologue
 2737     55/push-ebp
 2738     89/<- %ebp 4/r32/esp
 2739     # setup
 2740     (clear-stream _test-input-stream)
 2741     (clear-stream $_test-input-buffered-file->buffer)
 2742     (clear-stream _test-output-stream)
 2743     (clear-stream $_test-output-buffered-file->buffer)
 2744     #
 2745     (write _test-input-stream "fn foo {\n")
 2746     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2747     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 2748     (write _test-input-stream "  y <- increment\n")
 2749     (write _test-input-stream "}\n")
 2750     # convert
 2751     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2752     (flush _test-output-buffered-file)
 2753 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2759     # check output
 2760     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-second-local-var-in-same-reg/0")
 2761     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-second-local-var-in-same-reg/1")
 2762     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-second-local-var-in-same-reg/2")
 2763     (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")
 2764     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-second-local-var-in-same-reg/4")
 2765     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-second-local-var-in-same-reg/5")
 2766     (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")
 2767     (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")
 2768     (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")
 2769     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-convert-function-with-second-local-var-in-same-reg/9")
 2770     (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")
 2771     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-second-local-var-in-same-reg/11")
 2772     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-second-local-var-in-same-reg/12")
 2773     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-second-local-var-in-same-reg/13")
 2774     (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")
 2775     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-second-local-var-in-same-reg/15")
 2776     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-second-local-var-in-same-reg/16")
 2777     # . epilogue
 2778     89/<- %esp 5/r32/ebp
 2779     5d/pop-to-ebp
 2780     c3/return
 2781 
 2782 test-read-clobbered-reg-var:
 2783     # . prologue
 2784     55/push-ebp
 2785     89/<- %ebp 4/r32/esp
 2786     # setup
 2787     (clear-stream _test-input-stream)
 2788     (clear-stream $_test-input-buffered-file->buffer)
 2789     (clear-stream _test-output-stream)
 2790     (clear-stream $_test-output-buffered-file->buffer)
 2791     (clear-stream _test-error-stream)
 2792     (clear-stream $_test-error-buffered-file->buffer)
 2793     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
 2794     68/push 0/imm32
 2795     68/push 0/imm32
 2796     89/<- %edx 4/r32/esp
 2797     (tailor-exit-descriptor %edx 0x10)
 2798     #
 2799     (write _test-input-stream "fn foo {\n")
 2800     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2801     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 2802     (write _test-input-stream "  x <- increment\n")
 2803     (write _test-input-stream "}\n")
 2804     # convert
 2805     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2806     # registers except esp clobbered at this point
 2807     # restore ed
 2808     89/<- %edx 4/r32/esp
 2809     (flush _test-output-buffered-file)
 2810     (flush _test-error-buffered-file)
 2811 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2817     # check output
 2818     (check-stream-equal _test-output-stream  ""  "F - test-read-clobbered-reg-var: output should be empty")
 2819     (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")
 2820     # check that stop(1) was called
 2821     (check-ints-equal *(edx+4) 2 "F - test-read-clobbered-reg-var: exit status")
 2822     # don't restore from ebp
 2823     81 0/subop/add %esp 8/imm32
 2824     # . epilogue
 2825     5d/pop-to-ebp
 2826     c3/return
 2827 
 2828 test-overlapping-int-fp-registers:
 2829     # . prologue
 2830     55/push-ebp
 2831     89/<- %ebp 4/r32/esp
 2832     # setup
 2833     (clear-stream _test-input-stream)
 2834     (clear-stream $_test-input-buffered-file->buffer)
 2835     (clear-stream _test-output-stream)
 2836     (clear-stream $_test-output-buffered-file->buffer)
 2837     (clear-stream _test-error-stream)
 2838     (clear-stream $_test-error-buffered-file->buffer)
 2839     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
 2840     68/push 0/imm32
 2841     68/push 0/imm32
 2842     89/<- %edx 4/r32/esp
 2843     (tailor-exit-descriptor %edx 0x10)
 2844     #
 2845     (write _test-input-stream "fn foo {\n")
 2846     (write _test-input-stream "  var x/eax: int <- copy 3\n")
 2847     (write _test-input-stream "  var y/xmm0: float <- convert x\n")
 2848     (write _test-input-stream "  x <- increment\n")
 2849     (write _test-input-stream "}\n")
 2850     # convert
 2851     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2852     # registers except esp clobbered at this point
 2853     # restore ed
 2854     89/<- %edx 4/r32/esp
 2855     (flush _test-output-buffered-file)
 2856     (flush _test-error-buffered-file)
 2857 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2863     # no errors
 2864     (check-next-stream-line-equal _test-error-stream  ""  "F - test-overlapping-int-fp-registers: error message")
 2865     # don't bother checking the generated code
 2866     # don't restore from ebp
 2867     81 0/subop/add %esp 8/imm32
 2868     # . epilogue
 2869     5d/pop-to-ebp
 2870     c3/return
 2871 
 2872 test-convert-function-call:
 2873     # . prologue
 2874     55/push-ebp
 2875     89/<- %ebp 4/r32/esp
 2876     # setup
 2877     (clear-stream _test-input-stream)
 2878     (clear-stream $_test-input-buffered-file->buffer)
 2879     (clear-stream _test-output-stream)
 2880     (clear-stream $_test-output-buffered-file->buffer)
 2881     #
 2882     (write _test-input-stream "fn main -> _/ebx: int {\n")
 2883     (write _test-input-stream "  var result/ebx: int <- foo\n")
 2884     (write _test-input-stream "  return result\n")
 2885     (write _test-input-stream "}\n")
 2886     (write _test-input-stream "fn foo -> _/ebx: int {\n")
 2887     (write _test-input-stream "  var result/ebx: int <- copy 3\n")
 2888     (write _test-input-stream "  return result\n")
 2889     (write _test-input-stream "}\n")
 2890     # convert
 2891     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2892     (flush _test-output-buffered-file)
 2893 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2899     # check output
 2900     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call/0")
 2901     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call/1")
 2902     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call/2")
 2903     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call/3")
 2904     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call/4")
 2905     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call/5")
 2906     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-call-with-literal-arg/6")
 2907     (check-next-stream-line-equal _test-output-stream "    (foo)"               "F - test-convert-function-call/6")
 2908     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 2909     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
 2910     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 2911     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call/7")
 2912     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call/8")
 2913     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call/9")
 2914     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call/10")
 2915     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call/11")
 2916     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call/12")
 2917     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call/13")
 2918     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call/14")
 2919     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call/15")
 2920     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call/16")
 2921     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call/17")
 2922     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"  "F - test-convert-function-call/18")
 2923     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-call-with-literal-arg/6")
 2924     (check-next-stream-line-equal _test-output-stream "    bb/copy-to-ebx 3/imm32"  "F - test-convert-function-call/19")
 2925     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 2926     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
 2927     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 2928     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call/20")
 2929     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-call/21")
 2930     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call/22")
 2931     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call/23")
 2932     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call/24")
 2933     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call/25")
 2934     # . epilogue
 2935     89/<- %esp 5/r32/ebp
 2936     5d/pop-to-ebp
 2937     c3/return
 2938 
 2939 test-convert-function-call-with-inout-with-compound-type:
 2940     # . prologue
 2941     55/push-ebp
 2942     89/<- %ebp 4/r32/esp
 2943     # setup
 2944     (clear-stream _test-input-stream)
 2945     (clear-stream $_test-input-buffered-file->buffer)
 2946     (clear-stream _test-output-stream)
 2947     (clear-stream $_test-output-buffered-file->buffer)
 2948     #
 2949     (write _test-input-stream "fn f {\n")
 2950     (write _test-input-stream "  var x: (addr int)\n")
 2951     (write _test-input-stream "  g x\n")
 2952     (write _test-input-stream "}\n")
 2953     (write _test-input-stream "fn g a: (addr int) {\n")
 2954     (write _test-input-stream "}\n")
 2955     # convert
 2956     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2957     (flush _test-output-buffered-file)
 2958 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2964     # check output
 2965     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-inout-with-compound-type/0")
 2966     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-inout-with-compound-type/1")
 2967     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-inout-with-compound-type/2")
 2968     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-inout-with-compound-type/3")
 2969     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-inout-with-compound-type/4")
 2970     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-inout-with-compound-type/5")
 2971     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-inout-with-compound-type/6")
 2972     (check-next-stream-line-equal _test-output-stream "    (g *(ebp+0xfffffffc))"  "F - test-convert-function-call-with-inout-with-compound-type/7")
 2973     (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")
 2974     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-inout-with-compound-type/9")
 2975     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-inout-with-compound-type/10")
 2976     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-inout-with-compound-type/11")
 2977     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-inout-with-compound-type/12")
 2978     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-inout-with-compound-type/13")
 2979     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-inout-with-compound-type/14")
 2980     (check-next-stream-line-equal _test-output-stream "g:"                      "F - test-convert-function-call-with-inout-with-compound-type/15")
 2981     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-inout-with-compound-type/16")
 2982     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-inout-with-compound-type/17")
 2983     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-inout-with-compound-type/18")
 2984     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-inout-with-compound-type/19")
 2985     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-inout-with-compound-type/20")
 2986     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-inout-with-compound-type/21")
 2987     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-inout-with-compound-type/22")
 2988     # . epilogue
 2989     89/<- %esp 5/r32/ebp
 2990     5d/pop-to-ebp
 2991     c3/return
 2992 
 2993 test-convert-function-call-with-inout-with-type-parameter:
 2994     # . prologue
 2995     55/push-ebp
 2996     89/<- %ebp 4/r32/esp
 2997     # setup
 2998     (clear-stream _test-input-stream)
 2999     (clear-stream $_test-input-buffered-file->buffer)
 3000     (clear-stream _test-output-stream)
 3001     (clear-stream $_test-output-buffered-file->buffer)
 3002     (clear-stream _test-error-stream)
 3003     (clear-stream $_test-error-buffered-file->buffer)
 3004     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3005     68/push 0/imm32
 3006     68/push 0/imm32
 3007     89/<- %edx 4/r32/esp
 3008     (tailor-exit-descriptor %edx 0x10)
 3009     #
 3010     (write _test-input-stream "fn f {\n")
 3011     (write _test-input-stream "  var x: (addr int)\n")
 3012     (write _test-input-stream "  g x\n")
 3013     (write _test-input-stream "}\n")
 3014     (write _test-input-stream "fn g a: (addr _) {\n")
 3015     (write _test-input-stream "}\n")
 3016     # convert
 3017     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3018     # registers except esp clobbered at this point
 3019     # restore ed
 3020     89/<- %edx 4/r32/esp
 3021     (flush _test-output-buffered-file)
 3022     (flush _test-error-buffered-file)
 3023 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3029     # no error; types matched
 3030     (check-stream-equal _test-error-stream  ""  "F - test-convert-function-call-with-inout-with-type-parameter: error stream should be empty")
 3031     # don't bother checking the generated code; that's in the test 'test-local-clobbered-by-fn-output' below
 3032     # don't restore from ebp
 3033     81 0/subop/add %esp 8/imm32
 3034     # . epilogue
 3035     5d/pop-to-ebp
 3036     c3/return
 3037 
 3038 test-convert-function-call-with-incorrect-inout-type:
 3039     # . prologue
 3040     55/push-ebp
 3041     89/<- %ebp 4/r32/esp
 3042     # setup
 3043     (clear-stream _test-input-stream)
 3044     (clear-stream $_test-input-buffered-file->buffer)
 3045     (clear-stream _test-output-stream)
 3046     (clear-stream $_test-output-buffered-file->buffer)
 3047     (clear-stream _test-error-stream)
 3048     (clear-stream $_test-error-buffered-file->buffer)
 3049     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3050     68/push 0/imm32
 3051     68/push 0/imm32
 3052     89/<- %edx 4/r32/esp
 3053     (tailor-exit-descriptor %edx 0x10)
 3054     #
 3055     (write _test-input-stream "fn f {\n")
 3056     (write _test-input-stream "  var x: int\n")
 3057     (write _test-input-stream "  g x\n")
 3058     (write _test-input-stream "}\n")
 3059     (write _test-input-stream "fn g a: foo {\n")
 3060     (write _test-input-stream "}\n")
 3061     # convert
 3062     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3063     # registers except esp clobbered at this point
 3064     # restore ed
 3065     89/<- %edx 4/r32/esp
 3066     (flush _test-output-buffered-file)
 3067     (flush _test-error-buffered-file)
 3068 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3074     # check output
 3075     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-inout-type: output should be empty")
 3076     (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")
 3077     # check that stop(1) was called
 3078     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-inout-type: exit status")
 3079     # don't restore from ebp
 3080     81 0/subop/add %esp 8/imm32
 3081     5d/pop-to-ebp
 3082     c3/return
 3083 
 3084 test-convert-function-call-with-inout-with-incorrect-compound-type:
 3085     # . prologue
 3086     55/push-ebp
 3087     89/<- %ebp 4/r32/esp
 3088     # setup
 3089     (clear-stream _test-input-stream)
 3090     (clear-stream $_test-input-buffered-file->buffer)
 3091     (clear-stream _test-output-stream)
 3092     (clear-stream $_test-output-buffered-file->buffer)
 3093     (clear-stream _test-error-stream)
 3094     (clear-stream $_test-error-buffered-file->buffer)
 3095     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3096     68/push 0/imm32
 3097     68/push 0/imm32
 3098     89/<- %edx 4/r32/esp
 3099     (tailor-exit-descriptor %edx 0x10)
 3100     #
 3101     (write _test-input-stream "fn f {\n")
 3102     (write _test-input-stream "  var x: (addr int)\n")
 3103     (write _test-input-stream "  g x\n")
 3104     (write _test-input-stream "}\n")
 3105     (write _test-input-stream "fn g a: (addr bool) {\n")
 3106     (write _test-input-stream "}\n")
 3107     # convert
 3108     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3109     # registers except esp clobbered at this point
 3110     # restore ed
 3111     89/<- %edx 4/r32/esp
 3112     (flush _test-output-buffered-file)
 3113     (flush _test-error-buffered-file)
 3114 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3120     # check output
 3121     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-inout-with-incorrect-compound-type: output should be empty")
 3122     (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")
 3123     # don't restore from ebp
 3124     81 0/subop/add %esp 8/imm32
 3125     # . epilogue
 3126     5d/pop-to-ebp
 3127     c3/return
 3128 
 3129 test-convert-function-call-with-inout-with-multiple-type-parameters:
 3130     # . prologue
 3131     55/push-ebp
 3132     89/<- %ebp 4/r32/esp
 3133     # setup
 3134     (clear-stream _test-input-stream)
 3135     (clear-stream $_test-input-buffered-file->buffer)
 3136     (clear-stream _test-output-stream)
 3137     (clear-stream $_test-output-buffered-file->buffer)
 3138     (clear-stream _test-error-stream)
 3139     (clear-stream $_test-error-buffered-file->buffer)
 3140     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3141     68/push 0/imm32
 3142     68/push 0/imm32
 3143     89/<- %edx 4/r32/esp
 3144     (tailor-exit-descriptor %edx 0x10)
 3145     #
 3146     (write _test-input-stream "fn f {\n")
 3147     (write _test-input-stream "  var x: (addr int)\n")
 3148     (write _test-input-stream "  var y: (addr int)\n")
 3149     (write _test-input-stream "  g x, y\n")
 3150     (write _test-input-stream "}\n")
 3151     (write _test-input-stream "fn g a: (addr _), b: (addr _) {\n")
 3152     (write _test-input-stream "}\n")
 3153     # convert
 3154     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3155     # registers except esp clobbered at this point
 3156     # restore ed
 3157     89/<- %edx 4/r32/esp
 3158     (flush _test-output-buffered-file)
 3159     (flush _test-error-buffered-file)
 3160 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3166     # no errors
 3167     (check-stream-equal _test-error-stream  ""  "F - test-convert-function-call-with-inout-with-multiple-type-parameters: error stream should be empty")
 3168     # don't bother checking the generated code
 3169     # don't restore from ebp
 3170     81 0/subop/add %esp 8/imm32
 3171     # . epilogue
 3172     5d/pop-to-ebp
 3173     c3/return
 3174 
 3175 test-type-parameter-matches-rest-of-type:
 3176     # . prologue
 3177     55/push-ebp
 3178     89/<- %ebp 4/r32/esp
 3179     # setup
 3180     (clear-stream _test-input-stream)
 3181     (clear-stream $_test-input-buffered-file->buffer)
 3182     (clear-stream _test-output-stream)
 3183     (clear-stream $_test-output-buffered-file->buffer)
 3184     (clear-stream _test-error-stream)
 3185     (clear-stream $_test-error-buffered-file->buffer)
 3186     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3187     68/push 0/imm32
 3188     68/push 0/imm32
 3189     89/<- %edx 4/r32/esp
 3190     (tailor-exit-descriptor %edx 0x10)
 3191     #
 3192     (write _test-input-stream "fn f {\n")
 3193     (write _test-input-stream "  var x: (addr array int)\n")
 3194     (write _test-input-stream "  g x\n")
 3195     (write _test-input-stream "}\n")
 3196     (write _test-input-stream "fn g a: (addr _) {\n")
 3197     (write _test-input-stream "}\n")
 3198     # convert
 3199     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3200     # registers except esp clobbered at this point
 3201     # restore ed
 3202     89/<- %edx 4/r32/esp
 3203     (flush _test-output-buffered-file)
 3204     (flush _test-error-buffered-file)
 3205 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3211     # no errors
 3212     (check-stream-equal _test-error-stream  ""  "F - test-type-parameter-matches-rest-of-type: error stream should be empty")
 3213     # don't bother checking the generated code
 3214     # don't restore from ebp
 3215     81 0/subop/add %esp 8/imm32
 3216     # . epilogue
 3217     5d/pop-to-ebp
 3218     c3/return
 3219 
 3220 test-convert-function-call-with-inout-with-incompatible-type-parameters:
 3221     # . prologue
 3222     55/push-ebp
 3223     89/<- %ebp 4/r32/esp
 3224     # setup
 3225     (clear-stream _test-input-stream)
 3226     (clear-stream $_test-input-buffered-file->buffer)
 3227     (clear-stream _test-output-stream)
 3228     (clear-stream $_test-output-buffered-file->buffer)
 3229     (clear-stream _test-error-stream)
 3230     (clear-stream $_test-error-buffered-file->buffer)
 3231     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3232     68/push 0/imm32
 3233     68/push 0/imm32
 3234     89/<- %edx 4/r32/esp
 3235     (tailor-exit-descriptor %edx 0x10)
 3236     #
 3237     (write _test-input-stream "fn f {\n")
 3238     (write _test-input-stream "  var x: (addr int)\n")
 3239     (write _test-input-stream "  var y: (addr boolean)\n")
 3240     (write _test-input-stream "  g x, y\n")
 3241     (write _test-input-stream "}\n")
 3242     (write _test-input-stream "fn g a: (addr _T), b: (addr _T) {\n")
 3243     (write _test-input-stream "}\n")
 3244     # convert
 3245     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3246     # registers except esp clobbered at this point
 3247     # restore ed
 3248     89/<- %edx 4/r32/esp
 3249     (flush _test-output-buffered-file)
 3250     (flush _test-error-buffered-file)
 3251 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3257     # check output
 3258     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-inout-with-incompatible-type-parameters: output should be empty")
 3259     (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")
 3260     # don't restore from ebp
 3261     81 0/subop/add %esp 8/imm32
 3262     # . epilogue
 3263     5d/pop-to-ebp
 3264     c3/return
 3265 
 3266 test-convert-function-call-with-too-few-inouts:
 3267     # . prologue
 3268     55/push-ebp
 3269     89/<- %ebp 4/r32/esp
 3270     # setup
 3271     (clear-stream _test-input-stream)
 3272     (clear-stream $_test-input-buffered-file->buffer)
 3273     (clear-stream _test-output-stream)
 3274     (clear-stream $_test-output-buffered-file->buffer)
 3275     (clear-stream _test-error-stream)
 3276     (clear-stream $_test-error-buffered-file->buffer)
 3277     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3278     68/push 0/imm32
 3279     68/push 0/imm32
 3280     89/<- %edx 4/r32/esp
 3281     (tailor-exit-descriptor %edx 0x10)
 3282     #
 3283     (write _test-input-stream "fn f {\n")
 3284     (write _test-input-stream "  g\n")
 3285     (write _test-input-stream "}\n")
 3286     (write _test-input-stream "fn g a: int {\n")
 3287     (write _test-input-stream "}\n")
 3288     # convert
 3289     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3290     # registers except esp clobbered at this point
 3291     # restore ed
 3292     89/<- %edx 4/r32/esp
 3293     (flush _test-output-buffered-file)
 3294     (flush _test-error-buffered-file)
 3295 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3301     # check output
 3302     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-few-inouts: output should be empty")
 3303     (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")
 3304     # check that stop(1) was called
 3305     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-few-inouts: exit status")
 3306     # don't restore from ebp
 3307     81 0/subop/add %esp 8/imm32
 3308     5d/pop-to-ebp
 3309     c3/return
 3310 
 3311 test-convert-function-call-with-too-many-inouts:
 3312     # . prologue
 3313     55/push-ebp
 3314     89/<- %ebp 4/r32/esp
 3315     # setup
 3316     (clear-stream _test-input-stream)
 3317     (clear-stream $_test-input-buffered-file->buffer)
 3318     (clear-stream _test-output-stream)
 3319     (clear-stream $_test-output-buffered-file->buffer)
 3320     (clear-stream _test-error-stream)
 3321     (clear-stream $_test-error-buffered-file->buffer)
 3322     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3323     68/push 0/imm32
 3324     68/push 0/imm32
 3325     89/<- %edx 4/r32/esp
 3326     (tailor-exit-descriptor %edx 0x10)
 3327     #
 3328     (write _test-input-stream "fn f {\n")
 3329     (write _test-input-stream "  var x: int\n")
 3330     (write _test-input-stream "  g x\n")
 3331     (write _test-input-stream "}\n")
 3332     (write _test-input-stream "fn g {\n")
 3333     (write _test-input-stream "}\n")
 3334     # convert
 3335     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3336     # registers except esp clobbered at this point
 3337     # restore ed
 3338     89/<- %edx 4/r32/esp
 3339     (flush _test-output-buffered-file)
 3340     (flush _test-error-buffered-file)
 3341 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3347     # check output
 3348     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-many-inouts: output should be empty")
 3349     (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")
 3350     # check that stop(1) was called
 3351     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-many-inouts: exit status")
 3352     # don't restore from ebp
 3353     81 0/subop/add %esp 8/imm32
 3354     5d/pop-to-ebp
 3355     c3/return
 3356 
 3357 test-convert-function-call-with-incorrect-output-type:
 3358     # . prologue
 3359     55/push-ebp
 3360     89/<- %ebp 4/r32/esp
 3361     # setup
 3362     (clear-stream _test-input-stream)
 3363     (clear-stream $_test-input-buffered-file->buffer)
 3364     (clear-stream _test-output-stream)
 3365     (clear-stream $_test-output-buffered-file->buffer)
 3366     (clear-stream _test-error-stream)
 3367     (clear-stream $_test-error-buffered-file->buffer)
 3368     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3369     68/push 0/imm32
 3370     68/push 0/imm32
 3371     89/<- %edx 4/r32/esp
 3372     (tailor-exit-descriptor %edx 0x10)
 3373     #
 3374     (write _test-input-stream "fn f {\n")
 3375     (write _test-input-stream "  var x/eax: int <- g\n")
 3376     (write _test-input-stream "}\n")
 3377     (write _test-input-stream "fn g -> _/eax: foo {\n")
 3378     (write _test-input-stream "}\n")
 3379     # convert
 3380     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3381     # registers except esp clobbered at this point
 3382     # restore ed
 3383     89/<- %edx 4/r32/esp
 3384     (flush _test-output-buffered-file)
 3385     (flush _test-error-buffered-file)
 3386 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3392     # check output
 3393     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-output-type: output should be empty")
 3394     (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")
 3395     # check that stop(1) was called
 3396     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-output-type: exit status")
 3397     # don't restore from ebp
 3398     81 0/subop/add %esp 8/imm32
 3399     5d/pop-to-ebp
 3400     c3/return
 3401 
 3402 test-convert-function-call-with-too-few-outputs:
 3403     # . prologue
 3404     55/push-ebp
 3405     89/<- %ebp 4/r32/esp
 3406     # setup
 3407     (clear-stream _test-input-stream)
 3408     (clear-stream $_test-input-buffered-file->buffer)
 3409     (clear-stream _test-output-stream)
 3410     (clear-stream $_test-output-buffered-file->buffer)
 3411     (clear-stream _test-error-stream)
 3412     (clear-stream $_test-error-buffered-file->buffer)
 3413     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3414     68/push 0/imm32
 3415     68/push 0/imm32
 3416     89/<- %edx 4/r32/esp
 3417     (tailor-exit-descriptor %edx 0x10)
 3418     #
 3419     (write _test-input-stream "fn f {\n")
 3420     (write _test-input-stream "  g\n")
 3421     (write _test-input-stream "}\n")
 3422     (write _test-input-stream "fn g -> _/eax: int {\n")
 3423     (write _test-input-stream "}\n")
 3424     # convert
 3425     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3426     # registers except esp clobbered at this point
 3427     # restore ed
 3428     89/<- %edx 4/r32/esp
 3429     (flush _test-output-buffered-file)
 3430     (flush _test-error-buffered-file)
 3431 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3437     # check output
 3438     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-few-outputs: output should be empty")
 3439     (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")
 3440     # check that stop(1) was called
 3441     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-few-outputs: exit status")
 3442     # don't restore from ebp
 3443     81 0/subop/add %esp 8/imm32
 3444     5d/pop-to-ebp
 3445     c3/return
 3446 
 3447 test-convert-function-call-with-too-many-outputs:
 3448     # . prologue
 3449     55/push-ebp
 3450     89/<- %ebp 4/r32/esp
 3451     # setup
 3452     (clear-stream _test-input-stream)
 3453     (clear-stream $_test-input-buffered-file->buffer)
 3454     (clear-stream _test-output-stream)
 3455     (clear-stream $_test-output-buffered-file->buffer)
 3456     (clear-stream _test-error-stream)
 3457     (clear-stream $_test-error-buffered-file->buffer)
 3458     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3459     68/push 0/imm32
 3460     68/push 0/imm32
 3461     89/<- %edx 4/r32/esp
 3462     (tailor-exit-descriptor %edx 0x10)
 3463     #
 3464     (write _test-input-stream "fn f {\n")
 3465     (write _test-input-stream "  var x/eax: int <- g\n")
 3466     (write _test-input-stream "}\n")
 3467     (write _test-input-stream "fn g {\n")
 3468     (write _test-input-stream "}\n")
 3469     # convert
 3470     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3471     # registers except esp clobbered at this point
 3472     # restore ed
 3473     89/<- %edx 4/r32/esp
 3474     (flush _test-output-buffered-file)
 3475     (flush _test-error-buffered-file)
 3476 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3482     # check output
 3483     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-many-outputs: output should be empty")
 3484     (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")
 3485     # check that stop(1) was called
 3486     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-many-outputs: exit status")
 3487     # don't restore from ebp
 3488     81 0/subop/add %esp 8/imm32
 3489     5d/pop-to-ebp
 3490     c3/return
 3491 
 3492 test-convert-function-call-with-missing-output-register:
 3493     # . prologue
 3494     55/push-ebp
 3495     89/<- %ebp 4/r32/esp
 3496     # setup
 3497     (clear-stream _test-input-stream)
 3498     (clear-stream $_test-input-buffered-file->buffer)
 3499     (clear-stream _test-output-stream)
 3500     (clear-stream $_test-output-buffered-file->buffer)
 3501     (clear-stream _test-error-stream)
 3502     (clear-stream $_test-error-buffered-file->buffer)
 3503     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3504     68/push 0/imm32
 3505     68/push 0/imm32
 3506     89/<- %edx 4/r32/esp
 3507     (tailor-exit-descriptor %edx 0x10)
 3508     #
 3509     (write _test-input-stream "fn f {\n")
 3510     (write _test-input-stream "  var x: int\n")
 3511     (write _test-input-stream "  x <- g\n")
 3512     (write _test-input-stream "}\n")
 3513     (write _test-input-stream "fn g -> _/eax: int {\n")
 3514     (write _test-input-stream "}\n")
 3515     # convert
 3516     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3517     # registers except esp clobbered at this point
 3518     # restore ed
 3519     89/<- %edx 4/r32/esp
 3520     (flush _test-output-buffered-file)
 3521     (flush _test-error-buffered-file)
 3522 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3528     # check output
 3529     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-missing-output-register: output should be empty")
 3530     (check-next-stream-line-equal _test-error-stream  "fn f: call g: output 'x' is not in a register"  "F - test-convert-function-call-with-missing-output-register: error message")
 3531     # check that stop(1) was called
 3532     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-missing-output-register: exit status")
 3533     # don't restore from ebp
 3534     81 0/subop/add %esp 8/imm32
 3535     5d/pop-to-ebp
 3536     c3/return
 3537 
 3538 test-convert-function-call-with-incorrect-output-register:
 3539     # . prologue
 3540     55/push-ebp
 3541     89/<- %ebp 4/r32/esp
 3542     # setup
 3543     (clear-stream _test-input-stream)
 3544     (clear-stream $_test-input-buffered-file->buffer)
 3545     (clear-stream _test-output-stream)
 3546     (clear-stream $_test-output-buffered-file->buffer)
 3547     (clear-stream _test-error-stream)
 3548     (clear-stream $_test-error-buffered-file->buffer)
 3549     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3550     68/push 0/imm32
 3551     68/push 0/imm32
 3552     89/<- %edx 4/r32/esp
 3553     (tailor-exit-descriptor %edx 0x10)
 3554     #
 3555     (write _test-input-stream "fn f {\n")
 3556     (write _test-input-stream "  var x/ecx: int <- g\n")
 3557     (write _test-input-stream "}\n")
 3558     (write _test-input-stream "fn g -> _/eax: int {\n")
 3559     (write _test-input-stream "}\n")
 3560     # convert
 3561     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3562     # registers except esp clobbered at this point
 3563     # restore ed
 3564     89/<- %edx 4/r32/esp
 3565     (flush _test-output-buffered-file)
 3566     (flush _test-error-buffered-file)
 3567 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3573     # check output
 3574     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-output-register: output should be empty")
 3575     (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")
 3576     # check that stop(1) was called
 3577     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-output-register: exit status")
 3578     # don't restore from ebp
 3579     81 0/subop/add %esp 8/imm32
 3580     5d/pop-to-ebp
 3581     c3/return
 3582 
 3583 test-convert-function-with-local-var-dereferenced:
 3584     # . prologue
 3585     55/push-ebp
 3586     89/<- %ebp 4/r32/esp
 3587     # setup
 3588     (clear-stream _test-input-stream)
 3589     (clear-stream $_test-input-buffered-file->buffer)
 3590     (clear-stream _test-output-stream)
 3591     (clear-stream $_test-output-buffered-file->buffer)
 3592     #
 3593     (write _test-input-stream "fn foo {\n")
 3594     (write _test-input-stream "  var x/ecx: (addr int) <- copy 0\n")
 3595     (write _test-input-stream "  increment *x\n")
 3596     (write _test-input-stream "}\n")
 3597     # convert
 3598     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3599     (flush _test-output-buffered-file)
 3600 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3606     # check output
 3607     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-dereferenced/0")
 3608     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-dereferenced/1")
 3609     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-dereferenced/2")
 3610     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-dereferenced/3")
 3611     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-dereferenced/4")
 3612     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-dereferenced/5")
 3613     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-dereferenced/6")
 3614     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-local-var-dereferenced/7")
 3615     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *ecx"  "F - test-convert-function-with-local-var-dereferenced/8")
 3616     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-dereferenced/9")
 3617     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-dereferenced/10")
 3618     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-dereferenced/11")
 3619     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-dereferenced/12")
 3620     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-dereferenced/13")
 3621     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-dereferenced/14")
 3622     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-dereferenced/15")
 3623     # . epilogue
 3624     89/<- %esp 5/r32/ebp
 3625     5d/pop-to-ebp
 3626     c3/return
 3627 
 3628 test-dereference-of-var-on-stack:
 3629     # . prologue
 3630     55/push-ebp
 3631     89/<- %ebp 4/r32/esp
 3632     # setup
 3633     (clear-stream _test-input-stream)
 3634     (clear-stream $_test-input-buffered-file->buffer)
 3635     (clear-stream _test-output-stream)
 3636     (clear-stream $_test-output-buffered-file->buffer)
 3637     (clear-stream _test-error-stream)
 3638     (clear-stream $_test-error-buffered-file->buffer)
 3639     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3640     68/push 0/imm32
 3641     68/push 0/imm32
 3642     89/<- %edx 4/r32/esp
 3643     (tailor-exit-descriptor %edx 0x10)
 3644     #
 3645     (write _test-input-stream "fn foo {\n")
 3646     (write _test-input-stream "  var x: (addr int)\n")
 3647     (write _test-input-stream "  increment *x\n")
 3648     (write _test-input-stream "}\n")
 3649     # convert
 3650     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3651     # registers except esp clobbered at this point
 3652     # restore ed
 3653     89/<- %edx 4/r32/esp
 3654     (flush _test-output-buffered-file)
 3655     (flush _test-error-buffered-file)
 3656 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3662     # check output
 3663     (check-stream-equal _test-output-stream  ""  "F - test-dereference-of-var-on-stack: output should be empty")
 3664     (check-next-stream-line-equal _test-error-stream  "fn foo: cannot dereference var 'x' on stack"  "F - test-dereference-of-var-on-stack: error message")
 3665     # check that stop(1) was called
 3666     (check-ints-equal *(edx+4) 2 "F - test-dereference-of-var-on-stack: exit status")
 3667     # don't restore from ebp
 3668     81 0/subop/add %esp 8/imm32
 3669     # . epilogue
 3670     5d/pop-to-ebp
 3671     c3/return
 3672 
 3673 test-convert-function-with-byte-operations:
 3674     # . prologue
 3675     55/push-ebp
 3676     89/<- %ebp 4/r32/esp
 3677     # setup
 3678     (clear-stream _test-input-stream)
 3679     (clear-stream $_test-input-buffered-file->buffer)
 3680     (clear-stream _test-output-stream)
 3681     (clear-stream $_test-output-buffered-file->buffer)
 3682     #
 3683     (write _test-input-stream "fn foo {\n")
 3684     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
 3685     (write _test-input-stream "  var y/ecx: byte <- copy 0\n")
 3686     (write _test-input-stream "  y <- copy-byte x\n")
 3687     (write _test-input-stream "  var z/edx: (addr byte) <- copy 0\n")
 3688     (write _test-input-stream "  y <- copy-byte *z\n")
 3689     (write _test-input-stream "  copy-byte-to *z, x\n")
 3690     (write _test-input-stream "}\n")
 3691     # convert
 3692     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3693     (flush _test-output-buffered-file)
 3694 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3700     # check output
 3701     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-function-with-byte-operations/0")
 3702     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-function-with-byte-operations/1")
 3703     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-function-with-byte-operations/2")
 3704     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-function-with-byte-operations/3")
 3705     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-function-with-byte-operations/4")
 3706     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-function-with-byte-operations/5")
 3707     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-function-with-byte-operations/6")
 3708     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-function-with-byte-operations/7")
 3709     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-function-with-byte-operations/8")
 3710     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"                  "F - test-convert-function-with-byte-operations/9")
 3711     (check-next-stream-line-equal _test-output-stream "    8a/byte-> %eax 0x00000001/r32"           "F - test-convert-function-with-byte-operations/10")
 3712     (check-next-stream-line-equal _test-output-stream "    81 4/subop/and %ecx 0xff/imm32"          "F - test-convert-function-with-byte-operations/11")
 3713     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %edx"                    "F - test-convert-function-with-byte-operations/12")
 3714     (check-next-stream-line-equal _test-output-stream "    ba/copy-to-edx 0/imm32"                  "F - test-convert-function-with-byte-operations/13")
 3715     (check-next-stream-line-equal _test-output-stream "    8a/byte-> *edx 0x00000001/r32"           "F - test-convert-function-with-byte-operations/14")
 3716     (check-next-stream-line-equal _test-output-stream "    81 4/subop/and %ecx 0xff/imm32"          "F - test-convert-function-with-byte-operations/15")
 3717     (check-next-stream-line-equal _test-output-stream "    88/byte<- *edx 0x00000000/r32"           "F - test-convert-function-with-byte-operations/16")
 3718     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %edx"                     "F - test-convert-function-with-byte-operations/17")
 3719     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-function-with-byte-operations/18")
 3720     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-function-with-byte-operations/19")
 3721     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-function-with-byte-operations/20")
 3722     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-function-with-byte-operations/21")
 3723     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-function-with-byte-operations/22")
 3724     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-function-with-byte-operations/23")
 3725     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-function-with-byte-operations/24")
 3726     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-function-with-byte-operations/25")
 3727     # . epilogue
 3728     89/<- %esp 5/r32/ebp
 3729     5d/pop-to-ebp
 3730     c3/return
 3731 
 3732 # variables of type 'byte' are not allowed on the stack
 3733 test-byte-values-on-stack:
 3734     # . prologue
 3735     55/push-ebp
 3736     89/<- %ebp 4/r32/esp
 3737     # setup
 3738     (clear-stream _test-input-stream)
 3739     (clear-stream $_test-input-buffered-file->buffer)
 3740     (clear-stream _test-output-stream)
 3741     (clear-stream $_test-output-buffered-file->buffer)
 3742     (clear-stream _test-error-stream)
 3743     (clear-stream $_test-error-buffered-file->buffer)
 3744     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3745     68/push 0/imm32
 3746     68/push 0/imm32
 3747     89/<- %edx 4/r32/esp
 3748     (tailor-exit-descriptor %edx 0x10)
 3749     #
 3750     (write _test-input-stream "fn foo {\n")
 3751     (write _test-input-stream "  var x: byte\n")
 3752     (write _test-input-stream "}\n")
 3753     # convert
 3754     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3755     # registers except esp clobbered at this point
 3756     # restore ed
 3757     89/<- %edx 4/r32/esp
 3758     (flush _test-output-buffered-file)
 3759     (flush _test-error-buffered-file)
 3760 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3766     # check output
 3767     (check-stream-equal _test-output-stream  ""  "F - test-byte-values-on-stack: output should be empty")
 3768     (check-next-stream-line-equal _test-error-stream  "fn foo: var 'x' of type 'byte' cannot be on the stack"  "F - test-byte-values-on-stack: error message")
 3769     # check that stop(1) was called
 3770     (check-ints-equal *(edx+4) 2 "F - test-byte-values-on-stack: exit status")
 3771     # don't restore from ebp
 3772     81 0/subop/add %esp 8/imm32
 3773     # . epilogue
 3774     5d/pop-to-ebp
 3775     c3/return
 3776 
 3777 # variables of type 'byte' are not allowed in esi or edi
 3778 test-byte-values-in-unsupported-registers:
 3779     # . prologue
 3780     55/push-ebp
 3781     89/<- %ebp 4/r32/esp
 3782     # setup
 3783     (clear-stream _test-input-stream)
 3784     (clear-stream $_test-input-buffered-file->buffer)
 3785     (clear-stream _test-output-stream)
 3786     (clear-stream $_test-output-buffered-file->buffer)
 3787     (clear-stream _test-error-stream)
 3788     (clear-stream $_test-error-buffered-file->buffer)
 3789     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3790     68/push 0/imm32
 3791     68/push 0/imm32
 3792     89/<- %edx 4/r32/esp
 3793     (tailor-exit-descriptor %edx 0x10)
 3794     #
 3795     (write _test-input-stream "fn foo {\n")
 3796     (write _test-input-stream "  var x/esi: byte <- copy 0\n")
 3797     (write _test-input-stream "}\n")
 3798     # convert
 3799     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3800     # registers except esp clobbered at this point
 3801     # restore ed
 3802     89/<- %edx 4/r32/esp
 3803     (flush _test-output-buffered-file)
 3804     (flush _test-error-buffered-file)
 3805 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3811     # check output
 3812     (check-stream-equal _test-output-stream  ""  "F - test-byte-values-in-unsupported-registers: output should be empty")
 3813     (check-next-stream-line-equal _test-error-stream  "fn foo: var 'x' of type 'byte' cannot be in esi or edi"  "F - test-byte-values-in-unsupported-registers: error message")
 3814     # check that stop(1) was called
 3815     (check-ints-equal *(edx+4) 2 "F - test-byte-values-in-unsupported-registers: exit status")
 3816     # don't restore from ebp
 3817     81 0/subop/add %esp 8/imm32
 3818     # . epilogue
 3819     5d/pop-to-ebp
 3820     c3/return
 3821 
 3822 # variables of type 'byte' _can_ be function args. They then occupy 4 bytes.
 3823 test-copy-byte-var-from-fn-arg:
 3824     # . prologue
 3825     55/push-ebp
 3826     89/<- %ebp 4/r32/esp
 3827     # setup
 3828     (clear-stream _test-input-stream)
 3829     (clear-stream $_test-input-buffered-file->buffer)
 3830     (clear-stream _test-output-stream)
 3831     (clear-stream $_test-output-buffered-file->buffer)
 3832     #
 3833     (write _test-input-stream "fn foo x: byte, y: int {\n")
 3834     (write _test-input-stream "  var a/eax: byte <- copy x\n")
 3835     (write _test-input-stream "  var b/eax: int <- copy y\n")
 3836     (write _test-input-stream "}\n")
 3837     # convert
 3838     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3839     (flush _test-output-buffered-file)
 3840 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3846     # check output
 3847     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-copy-byte-from-fn-arg/0")
 3848     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-copy-byte-from-fn-arg/1")
 3849     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-copy-byte-from-fn-arg/2")
 3850     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-copy-byte-from-fn-arg/3")
 3851     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-copy-byte-from-fn-arg/4")
 3852     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-copy-byte-from-fn-arg/5")
 3853     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-copy-byte-from-fn-arg/6")
 3854     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-copy-byte-from-fn-arg/7")
 3855     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x0000000c) 0x00000000/r32"  "F - test-copy-byte-from-fn-arg/8")
 3856     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"   "F - test-copy-byte-from-fn-arg/9")
 3857     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-copy-byte-from-fn-arg/10")
 3858     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-copy-byte-from-fn-arg/11")
 3859     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-copy-byte-from-fn-arg/12")
 3860     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-copy-byte-from-fn-arg/13")
 3861     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-copy-byte-from-fn-arg/14")
 3862     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-copy-byte-from-fn-arg/15")
 3863     # . epilogue
 3864     89/<- %esp 5/r32/ebp
 3865     5d/pop-to-ebp
 3866     c3/return
 3867 
 3868 test-convert-compare-register-with-literal:
 3869     # . prologue
 3870     55/push-ebp
 3871     89/<- %ebp 4/r32/esp
 3872     # setup
 3873     (clear-stream _test-input-stream)
 3874     (clear-stream $_test-input-buffered-file->buffer)
 3875     (clear-stream _test-output-stream)
 3876     (clear-stream $_test-output-buffered-file->buffer)
 3877     #
 3878     (write _test-input-stream "fn foo {\n")
 3879     (write _test-input-stream "  var x/ecx: int <- copy 0\n")
 3880     (write _test-input-stream "  compare x, 0\n")
 3881     (write _test-input-stream "}\n")
 3882     # convert
 3883     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3884     (flush _test-output-buffered-file)
 3885 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3891     # check output
 3892     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-compare-register-with-literal/0")
 3893     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-compare-register-with-literal/1")
 3894     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-compare-register-with-literal/2")
 3895     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-compare-register-with-literal/3")
 3896     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-compare-register-with-literal/4")
 3897     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-compare-register-with-literal/5")
 3898     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-compare-register-with-literal/6")
 3899     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-compare-register-with-literal/7")
 3900     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %ecx 0/imm32"  "F - test-convert-compare-register-with-literal/8")
 3901     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-compare-register-with-literal/9")
 3902     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-compare-register-with-literal/10")
 3903     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-compare-register-with-literal/11")
 3904     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-compare-register-with-literal/12")
 3905     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-compare-register-with-literal/13")
 3906     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-compare-register-with-literal/14")
 3907     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-compare-register-with-literal/15")
 3908     # . epilogue
 3909     89/<- %esp 5/r32/ebp
 3910     5d/pop-to-ebp
 3911     c3/return
 3912 
 3913 test-convert-compare-byte-with-literal:
 3914     # . prologue
 3915     55/push-ebp
 3916     89/<- %ebp 4/r32/esp
 3917     # setup
 3918     (clear-stream _test-input-stream)
 3919     (clear-stream $_test-input-buffered-file->buffer)
 3920     (clear-stream _test-output-stream)
 3921     (clear-stream $_test-output-buffered-file->buffer)
 3922     #
 3923     (write _test-input-stream "fn foo {\n")
 3924     (write _test-input-stream "  var x/ecx: byte <- copy 0\n")
 3925     (write _test-input-stream "  compare x, 0\n")
 3926     (write _test-input-stream "}\n")
 3927     # convert
 3928     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3929     (flush _test-output-buffered-file)
 3930 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3936     # no errors; output is identical to test-convert-compare-register-with-literal
 3937     # . epilogue
 3938     89/<- %esp 5/r32/ebp
 3939     5d/pop-to-ebp
 3940     c3/return
 3941 
 3942 test-unknown-variable:
 3943     # . prologue
 3944     55/push-ebp
 3945     89/<- %ebp 4/r32/esp
 3946     # setup
 3947     (clear-stream _test-input-stream)
 3948     (clear-stream $_test-input-buffered-file->buffer)
 3949     (clear-stream _test-output-stream)
 3950     (clear-stream $_test-output-buffered-file->buffer)
 3951     (clear-stream _test-error-stream)
 3952     (clear-stream $_test-error-buffered-file->buffer)
 3953     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3954     68/push 0/imm32
 3955     68/push 0/imm32
 3956     89/<- %edx 4/r32/esp
 3957     (tailor-exit-descriptor %edx 0x10)
 3958     #
 3959     (write _test-input-stream "fn foo {\n")
 3960     (write _test-input-stream "  compare x, 0\n")
 3961     (write _test-input-stream "}\n")
 3962     # convert
 3963     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3964     # registers except esp clobbered at this point
 3965     # restore ed
 3966     89/<- %edx 4/r32/esp
 3967     (flush _test-output-buffered-file)
 3968     (flush _test-error-buffered-file)
 3969 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3975     # check output
 3976     (check-stream-equal _test-output-stream  ""  "F - test-unknown-variable: output should be empty")
 3977     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-unknown-variable: error message")
 3978     # check that stop(1) was called
 3979     (check-ints-equal *(edx+4) 2 "F - test-unknown-variable: exit status")
 3980     # don't restore from ebp
 3981     81 0/subop/add %esp 8/imm32
 3982     # . epilogue
 3983     5d/pop-to-ebp
 3984     c3/return
 3985 
 3986 test-convert-function-with-local-var-in-block:
 3987     # . prologue
 3988     55/push-ebp
 3989     89/<- %ebp 4/r32/esp
 3990     # setup
 3991     (clear-stream _test-input-stream)
 3992     (clear-stream $_test-input-buffered-file->buffer)
 3993     (clear-stream _test-output-stream)
 3994     (clear-stream $_test-output-buffered-file->buffer)
 3995     #
 3996     (write _test-input-stream "fn foo {\n")
 3997     (write _test-input-stream "  {\n")
 3998     (write _test-input-stream "    var x: int\n")
 3999     (write _test-input-stream "    increment x\n")
 4000     (write _test-input-stream "  }\n")
 4001     (write _test-input-stream "}\n")
 4002     # convert
 4003     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4004     (flush _test-output-buffered-file)
 4005 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4011     # check output
 4012     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-block/0")
 4013     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-block/1")
 4014     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-block/2")
 4015     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-block/3")
 4016     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-block/4")
 4017     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-block/5")
 4018     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-block/6")
 4019     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-local-var-in-block/7")
 4020     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-block/8")
 4021     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-local-var-in-block/9")
 4022     (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")
 4023     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-block/11")
 4024     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-local-var-in-block/12")
 4025     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-block/13")
 4026     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-block/14")
 4027     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-block/15")
 4028     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-block/16")
 4029     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-block/17")
 4030     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-block/18")
 4031     # . epilogue
 4032     89/<- %esp 5/r32/ebp
 4033     5d/pop-to-ebp
 4034     c3/return
 4035 
 4036 test-convert-function-with-local-var-in-mem-after-block:
 4037     # . prologue
 4038     55/push-ebp
 4039     89/<- %ebp 4/r32/esp
 4040     # setup
 4041     (clear-stream _test-input-stream)
 4042     (clear-stream $_test-input-buffered-file->buffer)
 4043     (clear-stream _test-output-stream)
 4044     (clear-stream $_test-output-buffered-file->buffer)
 4045     #
 4046     (write _test-input-stream "fn foo {\n")
 4047     (write _test-input-stream "  {\n")
 4048     (write _test-input-stream "    var y: int\n")
 4049     (write _test-input-stream "  }\n")
 4050     (write _test-input-stream "  var x: int\n")
 4051     (write _test-input-stream "  increment x\n")
 4052     (write _test-input-stream "}\n")
 4053     # convert
 4054     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4055     (flush _test-output-buffered-file)
 4056 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4062     # check output
 4063     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-mem-after-block/0")
 4064     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-mem-after-block/1")
 4065     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-mem-after-block/2")
 4066     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-mem-after-block/3")
 4067     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-mem-after-block/4")
 4068     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-mem-after-block/5")
 4069     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-mem-after-block/6")
 4070     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-local-var-in-mem-after-block/7")
 4071     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-mem-after-block/8")
 4072     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-local-var-in-mem-after-block/9")
 4073     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-mem-after-block/10")
 4074     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-local-var-in-mem-after-block/11")
 4075     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-in-mem-after-block/12")
 4076     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-local-var-in-mem-after-block/13")
 4077     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-local-var-in-mem-after-block/14")
 4078     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-mem-after-block/15")
 4079     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-mem-after-block/16")
 4080     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-mem-after-block/17")
 4081     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-mem-after-block/18")
 4082     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-mem-after-block/19")
 4083     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-mem-after-block/20")
 4084     # . epilogue
 4085     89/<- %esp 5/r32/ebp
 4086     5d/pop-to-ebp
 4087     c3/return
 4088 
 4089 test-convert-function-with-local-var-in-named-block:
 4090     # . prologue
 4091     55/push-ebp
 4092     89/<- %ebp 4/r32/esp
 4093     # setup
 4094     (clear-stream _test-input-stream)
 4095     (clear-stream $_test-input-buffered-file->buffer)
 4096     (clear-stream _test-output-stream)
 4097     (clear-stream $_test-output-buffered-file->buffer)
 4098     #
 4099     (write _test-input-stream "fn foo {\n")
 4100     (write _test-input-stream "  $bar: {\n")
 4101     (write _test-input-stream "    var x: int\n")
 4102     (write _test-input-stream "    increment x\n")
 4103     (write _test-input-stream "  }\n")
 4104     (write _test-input-stream "}\n")
 4105     # convert
 4106     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4107     (flush _test-output-buffered-file)
 4108 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4114     # check output
 4115     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-named-block/0")
 4116     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-named-block/1")
 4117     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-named-block/2")
 4118     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-named-block/3")
 4119     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-named-block/4")
 4120     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-named-block/5")
 4121     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-named-block/6")
 4122     (check-next-stream-line-equal _test-output-stream "$bar:loop:"              "F - test-convert-function-with-local-var-in-named-block/7")
 4123     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-named-block/8")
 4124     (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")
 4125     (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")
 4126     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-named-block/11")
 4127     (check-next-stream-line-equal _test-output-stream "$bar:break:"             "F - test-convert-function-with-local-var-in-named-block/12")
 4128     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-named-block/13")
 4129     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-named-block/14")
 4130     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-named-block/15")
 4131     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-named-block/16")
 4132     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-named-block/17")
 4133     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-named-block/18")
 4134     # . epilogue
 4135     89/<- %esp 5/r32/ebp
 4136     5d/pop-to-ebp
 4137     c3/return
 4138 
 4139 test-unknown-variable-in-named-block:
 4140     # . prologue
 4141     55/push-ebp
 4142     89/<- %ebp 4/r32/esp
 4143     # setup
 4144     (clear-stream _test-input-stream)
 4145     (clear-stream $_test-input-buffered-file->buffer)
 4146     (clear-stream _test-output-stream)
 4147     (clear-stream $_test-output-buffered-file->buffer)
 4148     (clear-stream _test-error-stream)
 4149     (clear-stream $_test-error-buffered-file->buffer)
 4150     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 4151     68/push 0/imm32
 4152     68/push 0/imm32
 4153     89/<- %edx 4/r32/esp
 4154     (tailor-exit-descriptor %edx 0x10)
 4155     #
 4156     (write _test-input-stream "fn foo {\n")
 4157     (write _test-input-stream "  $a: {\n")
 4158     (write _test-input-stream "    compare x, 0\n")
 4159     (write _test-input-stream "  }\n")
 4160     (write _test-input-stream "}\n")
 4161     # convert
 4162     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 4163     # registers except esp clobbered at this point
 4164     # restore ed
 4165     89/<- %edx 4/r32/esp
 4166     (flush _test-output-buffered-file)
 4167     (flush _test-error-buffered-file)
 4168 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 4174     # check output
 4175     (check-stream-equal _test-output-stream  ""  "F - test-unknown-variable-in-named-block: output should be empty")
 4176     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-unknown-variable-in-named-block: error message")
 4177     # check that stop(1) was called
 4178     (check-ints-equal *(edx+4) 2 "F - test-unknown-variable-in-named-block: exit status")
 4179     # don't restore from ebp
 4180     81 0/subop/add %esp 8/imm32
 4181     # . epilogue
 4182     5d/pop-to-ebp
 4183     c3/return
 4184 
 4185 test-always-shadow-outermost-reg-vars-in-function:
 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 {\n")
 4196     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4197     (write _test-input-stream "}\n")
 4198     # convert
 4199     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4200     (flush _test-output-buffered-file)
 4201 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4207     # check output
 4208     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-always-shadow-outermost-reg-vars-in-function/0")
 4209     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-always-shadow-outermost-reg-vars-in-function/1")
 4210     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-always-shadow-outermost-reg-vars-in-function/2")
 4211     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-always-shadow-outermost-reg-vars-in-function/3")
 4212     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-always-shadow-outermost-reg-vars-in-function/4")
 4213     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-always-shadow-outermost-reg-vars-in-function/5")
 4214     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-compare-register-with-literal/6")
 4215     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-always-shadow-outermost-reg-vars-in-function/8")
 4216     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-compare-register-with-literal/9")
 4217     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-always-shadow-outermost-reg-vars-in-function/12")
 4218     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-always-shadow-outermost-reg-vars-in-function/13")
 4219     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-always-shadow-outermost-reg-vars-in-function/14")
 4220     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-always-shadow-outermost-reg-vars-in-function/15")
 4221     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-always-shadow-outermost-reg-vars-in-function/16")
 4222     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-always-shadow-outermost-reg-vars-in-function/17")
 4223     # . epilogue
 4224     89/<- %esp 5/r32/ebp
 4225     5d/pop-to-ebp
 4226     c3/return
 4227 
 4228 test-shadow-local:
 4229     # . prologue
 4230     55/push-ebp
 4231     89/<- %ebp 4/r32/esp
 4232     # setup
 4233     (clear-stream _test-input-stream)
 4234     (clear-stream $_test-input-buffered-file->buffer)
 4235     (clear-stream _test-output-stream)
 4236     (clear-stream $_test-output-buffered-file->buffer)
 4237     #
 4238     (write _test-input-stream "fn foo {\n")
 4239     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4240     (write _test-input-stream "  {\n")
 4241     (write _test-input-stream "    var y/ecx: int <- copy 4\n")
 4242     (write _test-input-stream "  }\n")
 4243     (write _test-input-stream "  x <- increment\n")
 4244     (write _test-input-stream "}\n")
 4245     # convert
 4246     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4247     (flush _test-output-buffered-file)
 4248 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4254     # check output
 4255     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-local/0")
 4256     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-local/1")
 4257     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-local/2")
 4258     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-local/3")
 4259     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-local/4")
 4260     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-local/5")
 4261     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-local/6")
 4262     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-local/7")
 4263     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-local/8")
 4264     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-local/9")
 4265     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %ecx"  "F - test-shadow-local/10")
 4266     (check-next-stream-line-equal _test-output-stream "      b9/copy-to-ecx 4/imm32"  "F - test-shadow-local/11")
 4267     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %ecx" "F - test-shadow-local/12")
 4268     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-local/13")
 4269     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-local/14")
 4270     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-local/15")
 4271     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-local/16")
 4272     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-local/17")
 4273     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-local/18")
 4274     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-local/19")
 4275     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-local/20")
 4276     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-local/21")
 4277     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-local/22")
 4278     # . epilogue
 4279     89/<- %esp 5/r32/ebp
 4280     5d/pop-to-ebp
 4281     c3/return
 4282 
 4283 test-shadow-name:
 4284     # . prologue
 4285     55/push-ebp
 4286     89/<- %ebp 4/r32/esp
 4287     # setup
 4288     (clear-stream _test-input-stream)
 4289     (clear-stream $_test-input-buffered-file->buffer)
 4290     (clear-stream _test-output-stream)
 4291     (clear-stream $_test-output-buffered-file->buffer)
 4292     #
 4293     (write _test-input-stream "fn foo {\n")
 4294     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4295     (write _test-input-stream "  {\n")
 4296     (write _test-input-stream "    var x/edx: int <- copy 4\n")
 4297     (write _test-input-stream "  }\n")
 4298     (write _test-input-stream "  x <- increment\n")
 4299     (write _test-input-stream "}\n")
 4300     # convert
 4301     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4302     (flush _test-output-buffered-file)
 4303 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4309     # check output
 4310     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-name/0")
 4311     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-name/1")
 4312     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-name/2")
 4313     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-name/3")
 4314     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-name/4")
 4315     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-name/5")
 4316     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-name/6")
 4317     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-name/7")
 4318     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-name/8")
 4319     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-name/9")
 4320     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %edx"  "F - test-shadow-name/10")
 4321     (check-next-stream-line-equal _test-output-stream "      ba/copy-to-edx 4/imm32"  "F - test-shadow-name/11")
 4322     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %edx" "F - test-shadow-name/12")
 4323     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-name/13")
 4324     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-name/14")
 4325     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-name/15")
 4326     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-name/16")
 4327     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-name/17")
 4328     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-name/18")
 4329     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-name/19")
 4330     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-name/20")
 4331     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-name/21")
 4332     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-name/22")
 4333     # . epilogue
 4334     89/<- %esp 5/r32/ebp
 4335     5d/pop-to-ebp
 4336     c3/return
 4337 
 4338 test-shadow-name-2:
 4339     # . prologue
 4340     55/push-ebp
 4341     89/<- %ebp 4/r32/esp
 4342     # setup
 4343     (clear-stream _test-input-stream)
 4344     (clear-stream $_test-input-buffered-file->buffer)
 4345     (clear-stream _test-output-stream)
 4346     (clear-stream $_test-output-buffered-file->buffer)
 4347     #
 4348     (write _test-input-stream "fn foo {\n")
 4349     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4350     (write _test-input-stream "  {\n")
 4351     (write _test-input-stream "    var x/edx: int <- copy 4\n")
 4352     (write _test-input-stream "    var y/ecx: int <- copy 5\n")
 4353     (write _test-input-stream "  }\n")
 4354     (write _test-input-stream "  x <- increment\n")
 4355     (write _test-input-stream "}\n")
 4356     # convert
 4357     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4358     (flush _test-output-buffered-file)
 4359 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4365     # check output
 4366     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-name-2/0")
 4367     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-name-2/1")
 4368     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-name-2/2")
 4369     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-name-2/3")
 4370     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-name-2/4")
 4371     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-name-2/5")
 4372     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-name-2/6")
 4373     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-name-2/7")
 4374     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-name-2/8")
 4375     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-name-2/9")
 4376     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %edx"  "F - test-shadow-name-2/10")
 4377     (check-next-stream-line-equal _test-output-stream "      ba/copy-to-edx 4/imm32"  "F - test-shadow-name-2/11")
 4378     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %ecx"  "F - test-shadow-name-2/12")
 4379     (check-next-stream-line-equal _test-output-stream "      b9/copy-to-ecx 5/imm32"  "F - test-shadow-name-2/13")
 4380     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %ecx" "F - test-shadow-name-2/14")
 4381     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %edx" "F - test-shadow-name-2/15")
 4382     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-name-2/16")
 4383     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-name-2/17")
 4384     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-name-2/18")
 4385     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-name-2/19")
 4386     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-name-2/20")
 4387     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-name-2/21")
 4388     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-name-2/22")
 4389     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-name-2/23")
 4390     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-name-2/24")
 4391     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-name-2/25")
 4392     # . epilogue
 4393     89/<- %esp 5/r32/ebp
 4394     5d/pop-to-ebp
 4395     c3/return
 4396 
 4397 test-do-not-spill-same-register-in-block:
 4398     # . prologue
 4399     55/push-ebp
 4400     89/<- %ebp 4/r32/esp
 4401     # setup
 4402     (clear-stream _test-input-stream)
 4403     (clear-stream $_test-input-buffered-file->buffer)
 4404     (clear-stream _test-output-stream)
 4405     (clear-stream $_test-output-buffered-file->buffer)
 4406     #
 4407     (write _test-input-stream "fn foo {\n")
 4408     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4409     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 4410     (write _test-input-stream "  y <- increment\n")
 4411     (write _test-input-stream "}\n")
 4412     # convert
 4413     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4414     (flush _test-output-buffered-file)
 4415 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4421     # check output
 4422     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-do-not-spill-same-register-in-block/0")
 4423     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-do-not-spill-same-register-in-block/1")
 4424     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-do-not-spill-same-register-in-block/2")
 4425     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-do-not-spill-same-register-in-block/3")
 4426     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-do-not-spill-same-register-in-block/4")
 4427     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-do-not-spill-same-register-in-block/5")
 4428     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-do-not-spill-same-register-in-block/6")
 4429     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-do-not-spill-same-register-in-block/7")
 4430     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-do-not-spill-same-register-in-block/8")
 4431     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-do-not-spill-same-register-in-block/9")
 4432     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-do-not-spill-same-register-in-block/10")
 4433     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-do-not-spill-same-register-in-block/11")
 4434     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-do-not-spill-same-register-in-block/12")
 4435     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-do-not-spill-same-register-in-block/13")
 4436     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-do-not-spill-same-register-in-block/14")
 4437     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-do-not-spill-same-register-in-block/15")
 4438     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-do-not-spill-same-register-in-block/16")
 4439     # . epilogue
 4440     89/<- %esp 5/r32/ebp
 4441     5d/pop-to-ebp
 4442     c3/return
 4443 
 4444 test-spill-different-register-in-block:
 4445     # . prologue
 4446     55/push-ebp
 4447     89/<- %ebp 4/r32/esp
 4448     # setup
 4449     (clear-stream _test-input-stream)
 4450     (clear-stream $_test-input-buffered-file->buffer)
 4451     (clear-stream _test-output-stream)
 4452     (clear-stream $_test-output-buffered-file->buffer)
 4453     #
 4454     (write _test-input-stream "fn foo {\n")
 4455     (write _test-input-stream "  var x/eax: int <- copy 3\n")
 4456     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 4457     (write _test-input-stream "  y <- increment\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-spill-different-register-in-block/0")
 4470     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-spill-different-register-in-block/1")
 4471     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-spill-different-register-in-block/2")
 4472     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-spill-different-register-in-block/3")
 4473     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-spill-different-register-in-block/4")
 4474     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-spill-different-register-in-block/5")
 4475     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-spill-different-register-in-block/6")
 4476     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-spill-different-register-in-block/7")
 4477     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-spill-different-register-in-block/8")
 4478     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-spill-different-register-in-block/9")
 4479     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-spill-different-register-in-block/10")
 4480     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-spill-different-register-in-block/11")
 4481     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-spill-different-register-in-block/12")
 4482     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-spill-different-register-in-block/13")
 4483     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-spill-different-register-in-block/14")
 4484     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-spill-different-register-in-block/15")
 4485     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-spill-different-register-in-block/16")
 4486     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-spill-different-register-in-block/17")
 4487     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-spill-different-register-in-block/18")
 4488     # . epilogue
 4489     89/<- %esp 5/r32/ebp
 4490     5d/pop-to-ebp
 4491     c3/return
 4492 
 4493 test-convert-function-with-branches-in-block:
 4494     # . prologue
 4495     55/push-ebp
 4496     89/<- %ebp 4/r32/esp
 4497     # setup
 4498     (clear-stream _test-input-stream)
 4499     (clear-stream $_test-input-buffered-file->buffer)
 4500     (clear-stream _test-output-stream)
 4501     (clear-stream $_test-output-buffered-file->buffer)
 4502     #
 4503     (write _test-input-stream "fn foo x: int {\n")
 4504     (write _test-input-stream "  {\n")
 4505     (write _test-input-stream "    break-if->=\n")
 4506     (write _test-input-stream "    loop-if-addr<\n")
 4507     (write _test-input-stream "    increment x\n")
 4508     (write _test-input-stream "    loop\n")
 4509     (write _test-input-stream "  }\n")
 4510     (write _test-input-stream "}\n")
 4511     # convert
 4512     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4513     (flush _test-output-buffered-file)
 4514 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4520     # check output
 4521     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-block/0")
 4522     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-block/1")
 4523     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-block/2")
 4524     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-block/3")
 4525     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-block/4")
 4526     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-block/5")
 4527     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-block/6")
 4528     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-in-block/7")
 4529     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/8")
 4530     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-block/9")
 4531     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-in-block/10")
 4532     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/11")
 4533     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/12")
 4534     (check-next-stream-line-equal _test-output-stream "        0f 83/jump-if-addr>= break/disp32"  "F - test-convert-function-with-branches-in-block/13")
 4535     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:loop/disp32"  "F - test-convert-function-with-branches-in-block/14")
 4536     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/15")
 4537     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-block/16")
 4538     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-in-block/17")
 4539     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-block/18")
 4540     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-in-block/19")
 4541     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-block/20")
 4542     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-block/21")
 4543     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-block/22")
 4544     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-block/23")
 4545     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-block/24")
 4546     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-block/25")
 4547     # . epilogue
 4548     89/<- %esp 5/r32/ebp
 4549     5d/pop-to-ebp
 4550     c3/return
 4551 
 4552 test-convert-function-with-branches-in-block-2:
 4553     # . prologue
 4554     55/push-ebp
 4555     89/<- %ebp 4/r32/esp
 4556     # setup
 4557     (clear-stream _test-input-stream)
 4558     (clear-stream $_test-input-buffered-file->buffer)
 4559     (clear-stream _test-output-stream)
 4560     (clear-stream $_test-output-buffered-file->buffer)
 4561     #
 4562     (write _test-input-stream "fn foo x: int {\n")
 4563     (write _test-input-stream "  {\n")
 4564     (write _test-input-stream "    break-if->=\n")
 4565     (write _test-input-stream "    loop-if-float<\n")
 4566     (write _test-input-stream "    increment x\n")
 4567     (write _test-input-stream "    loop\n")
 4568     (write _test-input-stream "  }\n")
 4569     (write _test-input-stream "}\n")
 4570     # convert
 4571     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4572     (flush _test-output-buffered-file)
 4573 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4579     # check output
 4580     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-block/0")
 4581     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-block/1")
 4582     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-block/2")
 4583     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-block/3")
 4584     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-block/4")
 4585     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-block/5")
 4586     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-block/6")
 4587     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-in-block/7")
 4588     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/8")
 4589     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-block/9")
 4590     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-in-block/10")
 4591     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/11")
 4592     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/12")
 4593     (check-next-stream-line-equal _test-output-stream "        0f 83/jump-if-addr>= break/disp32"  "F - test-convert-function-with-branches-in-block/13")
 4594     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:loop/disp32"  "F - test-convert-function-with-branches-in-block/14")
 4595     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/15")
 4596     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-block/16")
 4597     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-in-block/17")
 4598     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-block/18")
 4599     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-in-block/19")
 4600     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-block/20")
 4601     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-block/21")
 4602     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-block/22")
 4603     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-block/23")
 4604     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-block/24")
 4605     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-block/25")
 4606     # . epilogue
 4607     89/<- %esp 5/r32/ebp
 4608     5d/pop-to-ebp
 4609     c3/return
 4610 
 4611 test-convert-function-with-branches-in-named-block:
 4612     # . prologue
 4613     55/push-ebp
 4614     89/<- %ebp 4/r32/esp
 4615     # setup
 4616     (clear-stream _test-input-stream)
 4617     (clear-stream $_test-input-buffered-file->buffer)
 4618     (clear-stream _test-output-stream)
 4619     (clear-stream $_test-output-buffered-file->buffer)
 4620     #
 4621     (write _test-input-stream "fn foo x: int {\n")
 4622     (write _test-input-stream "  $bar: {\n")
 4623     (write _test-input-stream "    break-if->= $bar\n")
 4624     (write _test-input-stream "    loop-if-addr< $bar\n")
 4625     (write _test-input-stream "    increment x\n")
 4626     (write _test-input-stream "    loop\n")
 4627     (write _test-input-stream "  }\n")
 4628     (write _test-input-stream "}\n")
 4629     # convert
 4630     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4631     (flush _test-output-buffered-file)
 4632 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4638     # check output
 4639     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-named-block/0")
 4640     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-named-block/1")
 4641     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-named-block/2")
 4642     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-named-block/3")
 4643     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-named-block/4")
 4644     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-named-block/5")
 4645     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-named-block/6")
 4646     (check-next-stream-line-equal _test-output-stream "$bar:loop:"              "F - test-convert-function-with-branches-in-named-block/7")
 4647     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-named-block/8")
 4648     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-named-block/9")
 4649     (check-next-stream-line-equal _test-output-stream "        e9/jump $bar:break/disp32"  "F - test-convert-function-with-branches-in-named-block/10")
 4650     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-named-block/11")
 4651     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-named-block/12")
 4652     (check-next-stream-line-equal _test-output-stream "        0f 83/jump-if-addr>= break/disp32"  "F - test-convert-function-with-branches-in-named-block/13")
 4653     (check-next-stream-line-equal _test-output-stream "        e9/jump $bar:loop/disp32"  "F - test-convert-function-with-branches-in-named-block/14")
 4654     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-named-block/15")
 4655     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-named-block/16")
 4656     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"   "F - test-convert-function-with-branches-in-named-block/17")
 4657     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-named-block/18")
 4658     (check-next-stream-line-equal _test-output-stream "$bar:break:"             "F - test-convert-function-with-branches-in-named-block/19")
 4659     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-named-block/20")
 4660     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-named-block/21")
 4661     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-named-block/22")
 4662     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-named-block/23")
 4663     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-named-block/24")
 4664     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-named-block/25")
 4665     # . epilogue
 4666     89/<- %esp 5/r32/ebp
 4667     5d/pop-to-ebp
 4668     c3/return
 4669 
 4670 test-convert-function-with-var-in-nested-block:
 4671     # . prologue
 4672     55/push-ebp
 4673     89/<- %ebp 4/r32/esp
 4674     # setup
 4675     (clear-stream _test-input-stream)
 4676     (clear-stream $_test-input-buffered-file->buffer)
 4677     (clear-stream _test-output-stream)
 4678     (clear-stream $_test-output-buffered-file->buffer)
 4679     #
 4680     (write _test-input-stream "fn foo x: int {\n")
 4681     (write _test-input-stream "  {\n")
 4682     (write _test-input-stream "    {\n")
 4683     (write _test-input-stream "      var x: int\n")
 4684     (write _test-input-stream "      increment x\n")
 4685     (write _test-input-stream "    }\n")
 4686     (write _test-input-stream "  }\n")
 4687     (write _test-input-stream "}\n")
 4688     # convert
 4689     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4690     (flush _test-output-buffered-file)
 4691 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4697     # check output
 4698     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-var-in-nested-block/0")
 4699     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-var-in-nested-block/1")
 4700     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-var-in-nested-block/2")
 4701     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-var-in-nested-block/3")
 4702     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-var-in-nested-block/4")
 4703     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-var-in-nested-block/5")
 4704     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-var-in-nested-block/6")
 4705     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-var-in-nested-block/7")
 4706     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-var-in-nested-block/8")
 4707     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-var-in-nested-block/9")
 4708     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-var-in-nested-block/10")
 4709     (check-next-stream-line-equal _test-output-stream "        ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-var-in-nested-block/11")
 4710     (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")
 4711     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-var-in-nested-block/13")
 4712     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-var-in-nested-block/14")
 4713     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-var-in-nested-block/15")
 4714     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-var-in-nested-block/16")
 4715     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-var-in-nested-block/17")
 4716     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-var-in-nested-block/18")
 4717     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-var-in-nested-block/19")
 4718     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-var-in-nested-block/20")
 4719     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-var-in-nested-block/21")
 4720     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-var-in-nested-block/22")
 4721     # . epilogue
 4722     89/<- %esp 5/r32/ebp
 4723     5d/pop-to-ebp
 4724     c3/return
 4725 
 4726 test-convert-function-with-multiple-vars-in-nested-blocks:
 4727     # . prologue
 4728     55/push-ebp
 4729     89/<- %ebp 4/r32/esp
 4730     # setup
 4731     (clear-stream _test-input-stream)
 4732     (clear-stream $_test-input-buffered-file->buffer)
 4733     (clear-stream _test-output-stream)
 4734     (clear-stream $_test-output-buffered-file->buffer)
 4735     #
 4736     (write _test-input-stream "fn foo x: int {\n")
 4737     (write _test-input-stream "  {\n")
 4738     (write _test-input-stream "    var x/eax: int <- copy 0\n")
 4739     (write _test-input-stream "    {\n")
 4740     (write _test-input-stream "      var y: int\n")
 4741     (write _test-input-stream "      x <- add y\n")
 4742     (write _test-input-stream "    }\n")
 4743     (write _test-input-stream "  }\n")
 4744     (write _test-input-stream "}\n")
 4745     # convert
 4746     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4747     (flush _test-output-buffered-file)
 4748 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4754     # check output
 4755     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-multiple-vars-in-nested-blocks/0")
 4756     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-multiple-vars-in-nested-blocks/1")
 4757     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-multiple-vars-in-nested-blocks/2")
 4758     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/3")
 4759     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-multiple-vars-in-nested-blocks/4")
 4760     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/5")
 4761     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-multiple-vars-in-nested-blocks/6")
 4762     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/7")
 4763     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %eax"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/8")
 4764     (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")
 4765     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-multiple-vars-in-nested-blocks/10")
 4766     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/11")
 4767     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-multiple-vars-in-nested-blocks/12")
 4768     (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")
 4769     (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")
 4770     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-multiple-vars-in-nested-blocks/15")
 4771     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/16")
 4772     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %eax"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/17")
 4773     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-multiple-vars-in-nested-blocks/18")
 4774     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/19")
 4775     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-multiple-vars-in-nested-blocks/20")
 4776     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/21")
 4777     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-multiple-vars-in-nested-blocks/22")
 4778     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/23")
 4779     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-multiple-vars-in-nested-blocks/24")
 4780     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-multiple-vars-in-nested-blocks/25")
 4781     # . epilogue
 4782     89/<- %esp 5/r32/ebp
 4783     5d/pop-to-ebp
 4784     c3/return
 4785 
 4786 test-convert-function-with-branches-and-local-vars:
 4787     # A conditional 'break' after a 'var' in a block is converted into a
 4788     # nested block that performs all necessary cleanup before jumping. This
 4789     # results in some ugly code duplication.
 4790     # . prologue
 4791     55/push-ebp
 4792     89/<- %ebp 4/r32/esp
 4793     # setup
 4794     (clear-stream _test-input-stream)
 4795     (clear-stream $_test-input-buffered-file->buffer)
 4796     (clear-stream _test-output-stream)
 4797     (clear-stream $_test-output-buffered-file->buffer)
 4798     #
 4799     (write _test-input-stream "fn foo {\n")
 4800     (write _test-input-stream "  {\n")
 4801     (write _test-input-stream "    var x: int\n")
 4802     (write _test-input-stream "    break-if->=\n")
 4803     (write _test-input-stream "    increment x\n")
 4804     (write _test-input-stream "  }\n")
 4805     (write _test-input-stream "}\n")
 4806     # convert
 4807     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4808     (flush _test-output-buffered-file)
 4809 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4815     # check output
 4816     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-and-local-vars/0")
 4817     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-and-local-vars/1")
 4818     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-and-local-vars/2")
 4819     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-and-local-vars/3")
 4820     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-and-local-vars/4")
 4821     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-and-local-vars/5")
 4822     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-and-local-vars/6")
 4823     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-and-local-vars/7")
 4824     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-branches-and-local-vars/8")
 4825     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-and-local-vars/9")
 4826     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-and-local-vars/10")
 4827     (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")
 4828     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-and-local-vars/12")
 4829     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-and-local-vars/13")
 4830     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-branches-and-local-vars/14")
 4831     (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")
 4832     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-and-local-vars/16")
 4833     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-and-local-vars/17")
 4834     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-and-local-vars/18")
 4835     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-and-local-vars/19")
 4836     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-and-local-vars/20")
 4837     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-and-local-vars/21")
 4838     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-and-local-vars/22")
 4839     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-and-local-vars/23")
 4840     # . epilogue
 4841     89/<- %esp 5/r32/ebp
 4842     5d/pop-to-ebp
 4843     c3/return
 4844 
 4845 test-convert-function-with-conditional-loops-and-local-vars:
 4846     # A conditional 'loop' after a 'var' in a block is converted into a nested
 4847     # block that performs all necessary cleanup before jumping. This results
 4848     # in some ugly code duplication.
 4849     # . prologue
 4850     55/push-ebp
 4851     89/<- %ebp 4/r32/esp
 4852     # setup
 4853     (clear-stream _test-input-stream)
 4854     (clear-stream $_test-input-buffered-file->buffer)
 4855     (clear-stream _test-output-stream)
 4856     (clear-stream $_test-output-buffered-file->buffer)
 4857     #
 4858     (write _test-input-stream "fn foo {\n")
 4859     (write _test-input-stream "  {\n")
 4860     (write _test-input-stream "    var x: int\n")
 4861     (write _test-input-stream "    loop-if->=\n")
 4862     (write _test-input-stream "    increment x\n")
 4863     (write _test-input-stream "  }\n")
 4864     (write _test-input-stream "}\n")
 4865     # convert
 4866     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4867     (flush _test-output-buffered-file)
 4868 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4874     # check output
 4875     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-conditional-loops-and-local-vars/0")
 4876     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-conditional-loops-and-local-vars/1")
 4877     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-conditional-loops-and-local-vars/2")
 4878     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-conditional-loops-and-local-vars/3")
 4879     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-conditional-loops-and-local-vars/4")
 4880     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-conditional-loops-and-local-vars/5")
 4881     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-conditional-loops-and-local-vars/6")
 4882     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-conditional-loops-and-local-vars/7")
 4883     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-conditional-loops-and-local-vars/8")
 4884     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-conditional-loops-and-local-vars/9")
 4885     (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")
 4886     (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")
 4887     (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")
 4888     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-conditional-loops-and-local-vars/13")
 4889     (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")
 4890     (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")
 4891     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-conditional-loops-and-local-vars/16")
 4892     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-conditional-loops-and-local-vars/17")
 4893     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-conditional-loops-and-local-vars/18")
 4894     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-conditional-loops-and-local-vars/19")
 4895     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-conditional-loops-and-local-vars/20")
 4896     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-conditional-loops-and-local-vars/21")
 4897     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-conditional-loops-and-local-vars/22")
 4898     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-conditional-loops-and-local-vars/23")
 4899     # . epilogue
 4900     89/<- %esp 5/r32/ebp
 4901     5d/pop-to-ebp
 4902     c3/return
 4903 
 4904 test-convert-function-with-unconditional-loops-and-local-vars:
 4905     # An unconditional 'loop' after a 'var' in a block is emitted _after_ the
 4906     # regular block cleanup. Any instructions after 'loop' are dead and
 4907     # therefore skipped.
 4908     # . prologue
 4909     55/push-ebp
 4910     89/<- %ebp 4/r32/esp
 4911     # setup
 4912     (clear-stream _test-input-stream)
 4913     (clear-stream $_test-input-buffered-file->buffer)
 4914     (clear-stream _test-output-stream)
 4915     (clear-stream $_test-output-buffered-file->buffer)
 4916     #
 4917     (write _test-input-stream "fn foo {\n")
 4918     (write _test-input-stream "  {\n")
 4919     (write _test-input-stream "    var x: int\n")
 4920     (write _test-input-stream "    loop\n")
 4921     (write _test-input-stream "    increment x\n")
 4922     (write _test-input-stream "  }\n")
 4923     (write _test-input-stream "}\n")
 4924     # convert
 4925     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4926     (flush _test-output-buffered-file)
 4927 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4933     # check output
 4934     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-unconditional-loops-and-local-vars/0")
 4935     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-unconditional-loops-and-local-vars/1")
 4936     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-unconditional-loops-and-local-vars/2")
 4937     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-unconditional-loops-and-local-vars/3")
 4938     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-unconditional-loops-and-local-vars/4")
 4939     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-unconditional-loops-and-local-vars/5")
 4940     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-unconditional-loops-and-local-vars/6")
 4941     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-unconditional-loops-and-local-vars/7")
 4942     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-unconditional-loops-and-local-vars/8")
 4943     (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")
 4944     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-unconditional-loops-and-local-vars/10")
 4945     # not emitted:                                           ff 0/subop/increment *(ebp+0xfffffffc)
 4946     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-unconditional-loops-and-local-vars/11")
 4947     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-unconditional-loops-and-local-vars/12")
 4948     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-unconditional-loops-and-local-vars/13")
 4949     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-unconditional-loops-and-local-vars/14")
 4950     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-unconditional-loops-and-local-vars/15")
 4951     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-unconditional-loops-and-local-vars/16")
 4952     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-unconditional-loops-and-local-vars/17")
 4953     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-unconditional-loops-and-local-vars/18")
 4954     # . epilogue
 4955     89/<- %esp 5/r32/ebp
 4956     5d/pop-to-ebp
 4957     c3/return
 4958 
 4959 test-convert-function-with-branches-and-loops-and-local-vars:
 4960     # . prologue
 4961     55/push-ebp
 4962     89/<- %ebp 4/r32/esp
 4963     # setup
 4964     (clear-stream _test-input-stream)
 4965     (clear-stream $_test-input-buffered-file->buffer)
 4966     (clear-stream _test-output-stream)
 4967     (clear-stream $_test-output-buffered-file->buffer)
 4968     #
 4969     (write _test-input-stream "fn foo {\n")
 4970     (write _test-input-stream "  {\n")
 4971     (write _test-input-stream "    var x: int\n")
 4972     (write _test-input-stream "    break-if->=\n")
 4973     (write _test-input-stream "    increment x\n")
 4974     (write _test-input-stream "    loop\n")
 4975     (write _test-input-stream "  }\n")
 4976     (write _test-input-stream "}\n")
 4977     # convert
 4978     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4979     (flush _test-output-buffered-file)
 4980 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4986     # check output
 4987     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-and-loops-and-local-vars/0")
 4988     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-and-loops-and-local-vars/1")
 4989     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-and-loops-and-local-vars/2")
 4990     (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")
 4991     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-and-loops-and-local-vars/4")
 4992     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-and-loops-and-local-vars/5")
 4993     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-and-loops-and-local-vars/6")
 4994     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-and-loops-and-local-vars/7")
 4995     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-branches-and-loops-and-local-vars/8")
 4996     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-and-loops-and-local-vars/9")
 4997     (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")
 4998     (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")
 4999     (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")
 5000     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-and-loops-and-local-vars/13")
 5001     (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")
 5002     (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")
 5003     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-and-loops-and-local-vars/16")
 5004     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-and-loops-and-local-vars/17")
 5005     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-and-loops-and-local-vars/18")
 5006     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-and-loops-and-local-vars/19")
 5007     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-and-loops-and-local-vars/20")
 5008     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-and-loops-and-local-vars/21")
 5009     (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")
 5010     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-and-loops-and-local-vars/23")
 5011     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-and-loops-and-local-vars/24")
 5012     # . epilogue
 5013     89/<- %esp 5/r32/ebp
 5014     5d/pop-to-ebp
 5015     c3/return
 5016 
 5017 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars:
 5018     # . prologue
 5019     55/push-ebp
 5020     89/<- %ebp 4/r32/esp
 5021     # setup
 5022     (clear-stream _test-input-stream)
 5023     (clear-stream $_test-input-buffered-file->buffer)
 5024     (clear-stream _test-output-stream)
 5025     (clear-stream $_test-output-buffered-file->buffer)
 5026     #
 5027     (write _test-input-stream "fn foo {\n")
 5028     (write _test-input-stream "  a: {\n")
 5029     (write _test-input-stream "    var x: int\n")
 5030     (write _test-input-stream "    {\n")
 5031     (write _test-input-stream "      var y: int\n")
 5032     (write _test-input-stream "      break-if->= a\n")
 5033     (write _test-input-stream "      increment x\n")
 5034     (write _test-input-stream "      loop\n")
 5035     (write _test-input-stream "    }\n")
 5036     (write _test-input-stream "  }\n")
 5037     (write _test-input-stream "}\n")
 5038     # convert
 5039     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5040     (flush _test-output-buffered-file)
 5041 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5047     # check output
 5048     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/0")
 5049     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/1")
 5050     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/2")
 5051     (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")
 5052     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/4")
 5053     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/5")
 5054     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/6")
 5055     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/7")
 5056     (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")
 5057     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/9")
 5058     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/10")
 5059     (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")
 5060     (check-next-stream-line-equal _test-output-stream "        {"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/12")
 5061     (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")
 5062     (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")
 5063     (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")
 5064     (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")
 5065     (check-next-stream-line-equal _test-output-stream "        }"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/17")
 5066     (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")
 5067     (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")
 5068     (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")
 5069     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/21")
 5070     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/22")
 5071     (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")
 5072     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/24")
 5073     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/25")
 5074     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/26")
 5075     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/27")
 5076     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/28")
 5077     (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")
 5078     (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")
 5079     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/31")
 5080     # . epilogue
 5081     89/<- %esp 5/r32/ebp
 5082     5d/pop-to-ebp
 5083     c3/return
 5084 
 5085 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2:
 5086     # . prologue
 5087     55/push-ebp
 5088     89/<- %ebp 4/r32/esp
 5089     # setup
 5090     (clear-stream _test-input-stream)
 5091     (clear-stream $_test-input-buffered-file->buffer)
 5092     (clear-stream _test-output-stream)
 5093     (clear-stream $_test-output-buffered-file->buffer)
 5094     # non-local conditional branch from a block without a local variable,
 5095     # unwinding a local on the stack
 5096     (write _test-input-stream "fn foo {\n")
 5097     (write _test-input-stream "  a: {\n")
 5098     (write _test-input-stream "    var x: int\n")
 5099     (write _test-input-stream "    {\n")
 5100     (write _test-input-stream "      break-if->= a\n")
 5101     (write _test-input-stream "    }\n")
 5102     (write _test-input-stream "  }\n")
 5103     (write _test-input-stream "}\n")
 5104     # convert
 5105     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5106     (flush _test-output-buffered-file)
 5107 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5113     # check output
 5114     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/0")
 5115     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/1")
 5116     (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")
 5117     (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")
 5118     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/4")
 5119     (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")
 5120     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/6")
 5121     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/7")
 5122     (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")
 5123     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/9")
 5124     (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")
 5125     (check-next-stream-line-equal _test-output-stream "        {"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/11")
 5126     (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")
 5127     (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")
 5128     (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")
 5129     (check-next-stream-line-equal _test-output-stream "        }"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/15")
 5130     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/16")
 5131     (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")
 5132     (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")
 5133     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/19")
 5134     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/20")
 5135     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/21")
 5136     (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")
 5137     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/23")
 5138     (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")
 5139     (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")
 5140     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/26")
 5141     # . epilogue
 5142     89/<- %esp 5/r32/ebp
 5143     5d/pop-to-ebp
 5144     c3/return
 5145 
 5146 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3:
 5147     # . prologue
 5148     55/push-ebp
 5149     89/<- %ebp 4/r32/esp
 5150     # setup
 5151     (clear-stream _test-input-stream)
 5152     (clear-stream $_test-input-buffered-file->buffer)
 5153     (clear-stream _test-output-stream)
 5154     (clear-stream $_test-output-buffered-file->buffer)
 5155     # non-local unconditional branch from a block without a local variable,
 5156     # unwinding a local on the stack
 5157     (write _test-input-stream "fn foo {\n")
 5158     (write _test-input-stream "  a: {\n")
 5159     (write _test-input-stream "    var x: int\n")
 5160     (write _test-input-stream "    {\n")
 5161     (write _test-input-stream "      break a\n")
 5162     (write _test-input-stream "    }\n")
 5163     (write _test-input-stream "  }\n")
 5164     (write _test-input-stream "}\n")
 5165     # convert
 5166     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5167     (flush _test-output-buffered-file)
 5168 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5174     # check output
 5175     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/0")
 5176     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/1")
 5177     (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")
 5178     (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")
 5179     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/4")
 5180     (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")
 5181     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/6")
 5182     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/7")
 5183     (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")
 5184     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/9")
 5185     (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")
 5186     (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")
 5187     (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")
 5188     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/14")
 5189     (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")
 5190     (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")
 5191     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/17")
 5192     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/18")
 5193     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/19")
 5194     (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")
 5195     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/21")
 5196     (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")
 5197     (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")
 5198     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/24")
 5199     # . epilogue
 5200     89/<- %esp 5/r32/ebp
 5201     5d/pop-to-ebp
 5202     c3/return
 5203 
 5204 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4:
 5205     # . prologue
 5206     55/push-ebp
 5207     89/<- %ebp 4/r32/esp
 5208     # setup
 5209     (clear-stream _test-input-stream)
 5210     (clear-stream $_test-input-buffered-file->buffer)
 5211     (clear-stream _test-output-stream)
 5212     (clear-stream $_test-output-buffered-file->buffer)
 5213     #
 5214     (write _test-input-stream "fn foo {\n")
 5215     (write _test-input-stream "  a: {\n")
 5216     (write _test-input-stream "    var x/esi: int <- copy 0\n")
 5217     (write _test-input-stream "    {\n")
 5218     (write _test-input-stream "      break a\n")
 5219     (write _test-input-stream "    }\n")
 5220     (write _test-input-stream "  }\n")
 5221     (write _test-input-stream "}\n")
 5222     # convert
 5223     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5224     (flush _test-output-buffered-file)
 5225 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5231     # check output
 5232     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/0")
 5233     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/1")
 5234     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/2")
 5235     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/3")
 5236     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/4")
 5237     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/5")
 5238     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/6")
 5239     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/7")
 5240     (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")
 5241     (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")
 5242     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/10")
 5243     (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")
 5244     (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")
 5245     (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")
 5246     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/14")
 5247     (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")
 5248     (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")
 5249     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/17")
 5250     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/18")
 5251     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/19")
 5252     (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")
 5253     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/21")
 5254     (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")
 5255     (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")
 5256     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/24")
 5257     # . epilogue
 5258     89/<- %esp 5/r32/ebp
 5259     5d/pop-to-ebp
 5260     c3/return
 5261 
 5262 test-convert-function-with-nonlocal-unconditional-break-and-local-vars:
 5263     # . prologue
 5264     55/push-ebp
 5265     89/<- %ebp 4/r32/esp
 5266     # setup
 5267     (clear-stream _test-input-stream)
 5268     (clear-stream $_test-input-buffered-file->buffer)
 5269     (clear-stream _test-output-stream)
 5270     (clear-stream $_test-output-buffered-file->buffer)
 5271     #
 5272     (write _test-input-stream "fn foo {\n")
 5273     (write _test-input-stream "  a: {\n")
 5274     (write _test-input-stream "    var x: int\n")
 5275     (write _test-input-stream "    {\n")
 5276     (write _test-input-stream "      var y: int\n")
 5277     (write _test-input-stream "      break a\n")
 5278     (write _test-input-stream "      increment x\n")
 5279     (write _test-input-stream "    }\n")
 5280     (write _test-input-stream "  }\n")
 5281     (write _test-input-stream "}\n")
 5282     # convert
 5283     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5284     (flush _test-output-buffered-file)
 5285 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5291     # check output
 5292     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/0")
 5293     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/1")
 5294     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/2")
 5295     (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")
 5296     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/4")
 5297     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/5")
 5298     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/6")
 5299     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/7")
 5300     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/8")
 5301     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/9")
 5302     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/10")
 5303     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/11")
 5304     (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")
 5305     (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")
 5306     (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")
 5307     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/15")
 5308     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/16")
 5309     (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")
 5310     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/18")
 5311     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/19")
 5312     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/20")
 5313     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/21")
 5314     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/22")
 5315     (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")
 5316     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/24")
 5317     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/25")
 5318     # . epilogue
 5319     89/<- %esp 5/r32/ebp
 5320     5d/pop-to-ebp
 5321     c3/return
 5322 
 5323 test-convert-function-with-unconditional-break-and-local-vars:
 5324     # . prologue
 5325     55/push-ebp
 5326     89/<- %ebp 4/r32/esp
 5327     # setup
 5328     (clear-stream _test-input-stream)
 5329     (clear-stream $_test-input-buffered-file->buffer)
 5330     (clear-stream _test-output-stream)
 5331     (clear-stream $_test-output-buffered-file->buffer)
 5332     #
 5333     (write _test-input-stream "fn foo {\n")
 5334     (write _test-input-stream "  {\n")
 5335     (write _test-input-stream "    var x: int\n")
 5336     (write _test-input-stream "    {\n")
 5337     (write _test-input-stream "      var y: int\n")
 5338     (write _test-input-stream "      break\n")
 5339     (write _test-input-stream "      increment x\n")
 5340     (write _test-input-stream "    }\n")
 5341     (write _test-input-stream "  }\n")
 5342     (write _test-input-stream "}\n")
 5343     # convert
 5344     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5345     (flush _test-output-buffered-file)
 5346 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5352     # check output
 5353     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-unconditional-break-and-local-vars/0")
 5354     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-unconditional-break-and-local-vars/1")
 5355     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-unconditional-break-and-local-vars/2")
 5356     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-unconditional-break-and-local-vars/3")
 5357     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-unconditional-break-and-local-vars/4")
 5358     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/5")
 5359     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-unconditional-break-and-local-vars/6")
 5360     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/7")
 5361     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-unconditional-break-and-local-vars/8")
 5362     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-unconditional-break-and-local-vars/9")
 5363     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/10")
 5364     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-unconditional-break-and-local-vars/11")
 5365     (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")
 5366     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-unconditional-break-and-local-vars/13")
 5367     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/14")
 5368     (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")
 5369     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-unconditional-break-and-local-vars/16")
 5370     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/17")
 5371     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-unconditional-break-and-local-vars/18")
 5372     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/19")
 5373     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-unconditional-break-and-local-vars/20")
 5374     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-unconditional-break-and-local-vars/21")
 5375     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-unconditional-break-and-local-vars/22")
 5376     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-unconditional-break-and-local-vars/23")
 5377     # . epilogue
 5378     89/<- %esp 5/r32/ebp
 5379     5d/pop-to-ebp
 5380     c3/return
 5381 
 5382 test-convert-function-with-nonlocal-unconditional-loop-and-local-vars:
 5383     # . prologue
 5384     55/push-ebp
 5385     89/<- %ebp 4/r32/esp
 5386     # setup
 5387     (clear-stream _test-input-stream)
 5388     (clear-stream $_test-input-buffered-file->buffer)
 5389     (clear-stream _test-output-stream)
 5390     (clear-stream $_test-output-buffered-file->buffer)
 5391     #
 5392     (write _test-input-stream "fn foo {\n")
 5393     (write _test-input-stream "  a: {\n")
 5394     (write _test-input-stream "    var x: int\n")
 5395     (write _test-input-stream "    {\n")
 5396     (write _test-input-stream "      var y: int\n")
 5397     (write _test-input-stream "      loop a\n")
 5398     (write _test-input-stream "      increment x\n")
 5399     (write _test-input-stream "    }\n")
 5400     (write _test-input-stream "  }\n")
 5401     (write _test-input-stream "}\n")
 5402     # convert
 5403     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5404     (flush _test-output-buffered-file)
 5405 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5411     # check output
 5412     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/0")
 5413     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/1")
 5414     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/2")
 5415     (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")
 5416     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/4")
 5417     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/5")
 5418     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/6")
 5419     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/7")
 5420     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/8")
 5421     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/9")
 5422     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/10")
 5423     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/11")
 5424     (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")
 5425     (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")
 5426     (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")
 5427     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/15")
 5428     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/16")
 5429     (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")
 5430     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/18")
 5431     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/19")
 5432     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/20")
 5433     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/21")
 5434     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/22")
 5435     (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")
 5436     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/24")
 5437     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/25")
 5438     # . epilogue
 5439     89/<- %esp 5/r32/ebp
 5440     5d/pop-to-ebp
 5441     c3/return
 5442 
 5443 test-convert-function-with-local-array-var-in-mem:
 5444     # . prologue
 5445     55/push-ebp
 5446     89/<- %ebp 4/r32/esp
 5447     # setup
 5448     (clear-stream _test-input-stream)
 5449     (clear-stream $_test-input-buffered-file->buffer)
 5450     (clear-stream _test-output-stream)
 5451     (clear-stream $_test-output-buffered-file->buffer)
 5452     #
 5453     (write _test-input-stream "fn foo {\n")
 5454     (write _test-input-stream "  var x: (array int 3)\n")
 5455     (write _test-input-stream "}\n")
 5456     # convert
 5457     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5458     (flush _test-output-buffered-file)
 5459 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5465     # check output
 5466     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-array-var-in-mem/0")
 5467     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-array-var-in-mem/1")
 5468     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-array-var-in-mem/2")
 5469     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-array-var-in-mem/3")
 5470     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-array-var-in-mem/4")
 5471     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-array-var-in-mem/5")
 5472     # define x
 5473     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"  "F - test-convert-function-with-local-array-var-in-mem/7")
 5474     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"  "F - test-convert-function-with-local-array-var-in-mem/8")
 5475     # reclaim x
 5476     (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")
 5477     #
 5478     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-array-var-in-mem/10")
 5479     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-array-var-in-mem/11")
 5480     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-array-var-in-mem/12")
 5481     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-array-var-in-mem/13")
 5482     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-array-var-in-mem/14")
 5483     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-array-var-in-mem/15")
 5484     # . epilogue
 5485     89/<- %esp 5/r32/ebp
 5486     5d/pop-to-ebp
 5487     c3/return
 5488 
 5489 test-array-size-in-hex:
 5490     # . prologue
 5491     55/push-ebp
 5492     89/<- %ebp 4/r32/esp
 5493     # setup
 5494     (clear-stream _test-input-stream)
 5495     (clear-stream $_test-input-buffered-file->buffer)
 5496     (clear-stream _test-output-stream)
 5497     (clear-stream $_test-output-buffered-file->buffer)
 5498     (clear-stream _test-error-stream)
 5499     (clear-stream $_test-error-buffered-file->buffer)
 5500     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 5501     68/push 0/imm32
 5502     68/push 0/imm32
 5503     89/<- %edx 4/r32/esp
 5504     (tailor-exit-descriptor %edx 0x10)
 5505     #
 5506     (write _test-input-stream "fn foo {\n")
 5507     (write _test-input-stream "  var x: (array int 10)\n")
 5508     (write _test-input-stream "}\n")
 5509     # convert
 5510     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 5511     # registers except esp clobbered at this point
 5512     # restore ed
 5513     89/<- %edx 4/r32/esp
 5514     (flush _test-output-buffered-file)
 5515     (flush _test-error-buffered-file)
 5516 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 5522     # check output
 5523     (check-stream-equal _test-output-stream  ""  "F - test-array-size-in-hex: output should be empty")
 5524     (check-next-stream-line-equal _test-error-stream  "literal integers are always hex in Mu; start '10' with a '0x' to be unambiguous, converting it to hexadecimal as necessary."  "F - test-array-size-in-hex: error message")
 5525     # check that stop(1) was called
 5526     (check-ints-equal *(edx+4) 2 "F - test-array-size-in-hex: exit status")
 5527     # don't restore from ebp
 5528     81 0/subop/add %esp 8/imm32
 5529     # . epilogue
 5530     5d/pop-to-ebp
 5531     c3/return
 5532 
 5533 test-convert-function-with-populate:
 5534     # . prologue
 5535     55/push-ebp
 5536     89/<- %ebp 4/r32/esp
 5537     # setup
 5538     (clear-stream _test-input-stream)
 5539     (clear-stream $_test-input-buffered-file->buffer)
 5540     (clear-stream _test-output-stream)
 5541     (clear-stream $_test-output-buffered-file->buffer)
 5542     #
 5543     (write _test-input-stream "fn foo {\n")
 5544     (write _test-input-stream "  var x/ecx: (addr handle array int) <- copy 0\n")
 5545     (write _test-input-stream "  populate x, 7\n")
 5546     (write _test-input-stream "}\n")
 5547     # convert
 5548     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5549     (flush _test-output-buffered-file)
 5550 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5556     # check output
 5557     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-populate/0")
 5558     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-populate/1")
 5559     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-populate/2")
 5560     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-populate/3")
 5561     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-populate/4")
 5562     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-populate/5")
 5563     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-populate/6")
 5564     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-populate/7")
 5565     (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)
 5566     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-populate/9")
 5567     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-populate/10")
 5568     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-populate/11")
 5569     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-populate/12")
 5570     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-populate/13")
 5571     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-populate/14")
 5572     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-populate/15")
 5573     # . epilogue
 5574     89/<- %esp 5/r32/ebp
 5575     5d/pop-to-ebp
 5576     c3/return
 5577 
 5578 # special-case for size(byte) when allocating array
 5579 test-convert-function-with-local-array-of-bytes-in-mem:
 5580     # . prologue
 5581     55/push-ebp
 5582     89/<- %ebp 4/r32/esp
 5583     # setup
 5584     (clear-stream _test-input-stream)
 5585     (clear-stream $_test-input-buffered-file->buffer)
 5586     (clear-stream _test-output-stream)
 5587     (clear-stream $_test-output-buffered-file->buffer)
 5588     #
 5589     (write _test-input-stream "fn foo {\n")
 5590     (write _test-input-stream "  var x: (array byte 3)\n")
 5591     (write _test-input-stream "}\n")
 5592     # convert
 5593     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5594     (flush _test-output-buffered-file)
 5595 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5601     # check output
 5602     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-array-of-bytes-in-mem/0")
 5603     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-array-of-bytes-in-mem/1")
 5604     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-array-of-bytes-in-mem/2")
 5605     (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")
 5606     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-array-of-bytes-in-mem/4")
 5607     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-array-of-bytes-in-mem/5")
 5608     # define x
 5609     (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")
 5610     (check-next-stream-line-equal _test-output-stream "    68/push 0x00000003/imm32"  "F - test-convert-function-with-local-array-of-bytes-in-mem/8")
 5611     # reclaim x
 5612     (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")
 5613     #
 5614     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-array-of-bytes-in-mem/10")
 5615     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-array-of-bytes-in-mem/11")
 5616     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-array-of-bytes-in-mem/12")
 5617     (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")
 5618     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-array-of-bytes-in-mem/14")
 5619     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-array-of-bytes-in-mem/15")
 5620     # . epilogue
 5621     89/<- %esp 5/r32/ebp
 5622     5d/pop-to-ebp
 5623     c3/return
 5624 
 5625 test-convert-address:
 5626     # . prologue
 5627     55/push-ebp
 5628     89/<- %ebp 4/r32/esp
 5629     # setup
 5630     (clear-stream _test-input-stream)
 5631     (clear-stream $_test-input-buffered-file->buffer)
 5632     (clear-stream _test-output-stream)
 5633     (clear-stream $_test-output-buffered-file->buffer)
 5634     #
 5635     (write _test-input-stream "fn foo {\n")
 5636     (write _test-input-stream "  var a: int\n")
 5637     (write _test-input-stream "  var b/eax: (addr int) <- address a\n")
 5638     (write _test-input-stream "}\n")
 5639     # convert
 5640     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5641     (flush _test-output-buffered-file)
 5642 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5648     # check output
 5649     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-address/0")
 5650     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-address/1")
 5651     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-address/2")
 5652     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-address/3")
 5653     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-address/4")
 5654     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-address/5")
 5655     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-address/6")
 5656     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-address/7")
 5657     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0xfffffffc) 0x00000000/r32"  "F - test-convert-address/8")
 5658     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-address/9")
 5659     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-address/10")
 5660     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-address/11")
 5661     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-address/12")
 5662     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-address/13")
 5663     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-address/14")
 5664     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-address/15")
 5665     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-address/16")
 5666     # . epilogue
 5667     89/<- %esp 5/r32/ebp
 5668     5d/pop-to-ebp
 5669     c3/return
 5670 
 5671 test-convert-floating-point-convert:
 5672     # . prologue
 5673     55/push-ebp
 5674     89/<- %ebp 4/r32/esp
 5675     # setup
 5676     (clear-stream _test-input-stream)
 5677     (clear-stream $_test-input-buffered-file->buffer)
 5678     (clear-stream _test-output-stream)
 5679     (clear-stream $_test-output-buffered-file->buffer)
 5680     #
 5681     (write _test-input-stream "fn foo {\n")
 5682     (write _test-input-stream "  var a/eax: int <- copy 0\n")
 5683     (write _test-input-stream "  var b/xmm1: float <- convert a\n")
 5684     (write _test-input-stream "}\n")
 5685     # convert
 5686     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5687     (flush _test-output-buffered-file)
 5688 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5694     # check output
 5695     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-floating-point-convert/0")
 5696     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-floating-point-convert/1")
 5697     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-floating-point-convert/2")
 5698     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-floating-point-convert/3")
 5699     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-floating-point-convert/4")
 5700     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-floating-point-convert/5")
 5701     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-floating-point-convert/6")
 5702     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-floating-point-convert/7")
 5703     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"  "F - test-convert-floating-point-convert/8")
 5704     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"  "F - test-convert-floating-point-convert/9")
 5705     (check-next-stream-line-equal _test-output-stream "    f3 0f 2a/convert-to-float %eax 0x00000001/x32"  "F - test-convert-floating-point-convert/10")
 5706     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"  "F - test-convert-floating-point-convert/11")
 5707     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-floating-point-convert/12")
 5708     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-floating-point-convert/13")
 5709     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-floating-point-convert/14")
 5710     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-floating-point-convert/15")
 5711     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-floating-point-convert/16")
 5712     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-floating-point-convert/17")
 5713     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-floating-point-convert/18")
 5714     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-floating-point-convert/19")
 5715     # . epilogue
 5716     89/<- %esp 5/r32/ebp
 5717     5d/pop-to-ebp
 5718     c3/return
 5719 
 5720 test-convert-floating-point-convert-2:
 5721     # . prologue
 5722     55/push-ebp
 5723     89/<- %ebp 4/r32/esp
 5724     # setup
 5725     (clear-stream _test-input-stream)
 5726     (clear-stream $_test-input-buffered-file->buffer)
 5727     (clear-stream _test-output-stream)
 5728     (clear-stream $_test-output-buffered-file->buffer)
 5729     #
 5730     (write _test-input-stream "fn foo {\n")
 5731     (write _test-input-stream "  var a/eax: int <- copy 0\n")
 5732     (write _test-input-stream "  var b/xmm1: float <- convert a\n")
 5733     (write _test-input-stream "  a <- convert b\n")
 5734     (write _test-input-stream "}\n")
 5735     # convert
 5736     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5737     (flush _test-output-buffered-file)
 5738 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5744     # check output
 5745     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-floating-point-convert-2/0")
 5746     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-floating-point-convert-2/1")
 5747     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-floating-point-convert-2/2")
 5748     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-floating-point-convert-2/3")
 5749     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-floating-point-convert-2/4")
 5750     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-floating-point-convert-2/5")
 5751     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-floating-point-convert-2/6")
 5752     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-floating-point-convert-2/7")
 5753     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"  "F - test-convert-floating-point-convert-2/8")
 5754     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"  "F - test-convert-floating-point-convert-2/9")
 5755     (check-next-stream-line-equal _test-output-stream "    f3 0f 2a/convert-to-float %eax 0x00000001/x32"  "F - test-convert-floating-point-convert-2/10")
 5756     (check-next-stream-line-equal _test-output-stream "    f3 0f 2d/convert-to-int %xmm1 0x00000000/r32"  "F - test-convert-floating-point-convert-2/11")
 5757     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"  "F - test-convert-floating-point-convert-2/12")
 5758     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-floating-point-convert-2/13")
 5759     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-floating-point-convert-2/14")
 5760     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-floating-point-convert-2/15")
 5761     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-floating-point-convert-2/16")
 5762     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-floating-point-convert-2/17")
 5763     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-floating-point-convert-2/18")
 5764     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-floating-point-convert-2/19")
 5765     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-floating-point-convert-2/20")
 5766     # . epilogue
 5767     89/<- %esp 5/r32/ebp
 5768     5d/pop-to-ebp
 5769     c3/return
 5770 
 5771 test-convert-floating-point-operation:
 5772     # . prologue
 5773     55/push-ebp
 5774     89/<- %ebp 4/r32/esp
 5775     # setup
 5776     (clear-stream _test-input-stream)
 5777     (clear-stream $_test-input-buffered-file->buffer)
 5778     (clear-stream _test-output-stream)
 5779     (clear-stream $_test-output-buffered-file->buffer)
 5780     #
 5781     (write _test-input-stream "fn f {\n")
 5782     (write _test-input-stream "  var m: float\n")
 5783     (write _test-input-stream "  var x/xmm1: float <- copy m\n")
 5784     (write _test-input-stream "  var y/xmm5: float <- copy m\n")
 5785     (write _test-input-stream "  x <- copy y\n")
 5786     (write _test-input-stream "  copy-to m, y\n")
 5787     (write _test-input-stream "  x <- add y\n")
 5788     (write _test-input-stream "  x <- add m\n")
 5789     (write _test-input-stream "  x <- subtract y\n")
 5790     (write _test-input-stream "  x <- subtract m\n")
 5791     (write _test-input-stream "  x <- multiply y\n")
 5792     (write _test-input-stream "  x <- multiply m\n")
 5793     (write _test-input-stream "  x <- divide y\n")
 5794     (write _test-input-stream "  x <- divide m\n")
 5795     (write _test-input-stream "  x <- reciprocal y\n")
 5796     (write _test-input-stream "  x <- reciprocal m\n")
 5797     (write _test-input-stream "  x <- square-root y\n")
 5798     (write _test-input-stream "  x <- square-root m\n")
 5799     (write _test-input-stream "  x <- inverse-square-root y\n")
 5800     (write _test-input-stream "  x <- inverse-square-root m\n")
 5801     (write _test-input-stream "  x <- max y\n")
 5802     (write _test-input-stream "  x <- max m\n")
 5803     (write _test-input-stream "  x <- min y\n")
 5804     (write _test-input-stream "  x <- min m\n")
 5805     (write _test-input-stream "  compare x, y\n")
 5806     (write _test-input-stream "  compare x, m\n")
 5807     (write _test-input-stream "}\n")
 5808     # convert
 5809     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5810     (flush _test-output-buffered-file)
 5811 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5817     # check output
 5818     (check-next-stream-line-equal _test-output-stream "f:"                                                                     "F - test-convert-floating-point-operation/0")
 5819     (check-next-stream-line-equal _test-output-stream "  # . prologue"                                                         "F - test-convert-floating-point-operation/1")
 5820     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                                                          "F - test-convert-floating-point-operation/2")
 5821     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                                                 "F - test-convert-floating-point-operation/3")
 5822     (check-next-stream-line-equal _test-output-stream "  {"                                                                    "F - test-convert-floating-point-operation/4")
 5823     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"                                                    "F - test-convert-floating-point-operation/5")
 5824     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                                                    "F - test-convert-floating-point-operation/6")
 5825     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-operation/7")
 5826     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"                                             "F - test-convert-floating-point-operation/8")
 5827     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-operation/9")
 5828     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-operation/10")
 5829     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 5/x32"                                             "F - test-convert-floating-point-operation/11")
 5830     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000005/x32"                     "F - test-convert-floating-point-operation/12")
 5831     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/copy %xmm1 0x00000005/x32"                                 "F - test-convert-floating-point-operation/13")
 5832     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/copy *(ebp+0xfffffffc) 0x00000005/x32"                     "F - test-convert-floating-point-operation/14")
 5833     (check-next-stream-line-equal _test-output-stream "    f3 0f 58/add %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/15")
 5834     (check-next-stream-line-equal _test-output-stream "    f3 0f 58/add *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/16")
 5835     (check-next-stream-line-equal _test-output-stream "    f3 0f 5c/subtract %xmm5 0x00000001/x32"                             "F - test-convert-floating-point-operation/17")
 5836     (check-next-stream-line-equal _test-output-stream "    f3 0f 5c/subtract *(ebp+0xfffffffc) 0x00000001/x32"                 "F - test-convert-floating-point-operation/18")
 5837     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply %xmm5 0x00000001/x32"                             "F - test-convert-floating-point-operation/19")
 5838     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply *(ebp+0xfffffffc) 0x00000001/x32"                 "F - test-convert-floating-point-operation/20")
 5839     (check-next-stream-line-equal _test-output-stream "    f3 0f 5e/divide %xmm5 0x00000001/x32"                               "F - test-convert-floating-point-operation/21")
 5840     (check-next-stream-line-equal _test-output-stream "    f3 0f 5e/divide *(ebp+0xfffffffc) 0x00000001/x32"                   "F - test-convert-floating-point-operation/22")
 5841     (check-next-stream-line-equal _test-output-stream "    f3 0f 53/reciprocal %xmm5 0x00000001/x32"                           "F - test-convert-floating-point-operation/23")
 5842     (check-next-stream-line-equal _test-output-stream "    f3 0f 53/reciprocal *(ebp+0xfffffffc) 0x00000001/x32"               "F - test-convert-floating-point-operation/24")
 5843     (check-next-stream-line-equal _test-output-stream "    f3 0f 51/square-root %xmm5 0x00000001/x32"                          "F - test-convert-floating-point-operation/25")
 5844     (check-next-stream-line-equal _test-output-stream "    f3 0f 51/square-root *(ebp+0xfffffffc) 0x00000001/x32"              "F - test-convert-floating-point-operation/26")
 5845     (check-next-stream-line-equal _test-output-stream "    f3 0f 52/inverse-square-root %xmm5 0x00000001/x32"                  "F - test-convert-floating-point-operation/27")
 5846     (check-next-stream-line-equal _test-output-stream "    f3 0f 52/inverse-square-root *(ebp+0xfffffffc) 0x00000001/x32"      "F - test-convert-floating-point-operation/28")
 5847     (check-next-stream-line-equal _test-output-stream "    f3 0f 5f/max %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/29")
 5848     (check-next-stream-line-equal _test-output-stream "    f3 0f 5f/max *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/30")
 5849     (check-next-stream-line-equal _test-output-stream "    f3 0f 5d/min %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/31")
 5850     (check-next-stream-line-equal _test-output-stream "    f3 0f 5d/min *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/32")
 5851     (check-next-stream-line-equal _test-output-stream "    0f 2f/compare %xmm1 0x00000005/x32"                                 "F - test-convert-floating-point-operation/33")
 5852     (check-next-stream-line-equal _test-output-stream "    0f 2f/compare *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-operation/34")
 5853     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 5/x32"                                             "F - test-convert-floating-point-operation/35")
 5854     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-operation/36")
 5855     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"                                             "F - test-convert-floating-point-operation/37")
 5856     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-operation/38")
 5857     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"                               "F - test-convert-floating-point-operation/39")
 5858     (check-next-stream-line-equal _test-output-stream "  }"                                                                    "F - test-convert-floating-point-operation/40")
 5859     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"                                                   "F - test-convert-floating-point-operation/41")
 5860     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                                                         "F - test-convert-floating-point-operation/42")
 5861     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                                                 "F - test-convert-floating-point-operation/43")
 5862     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                                                        "F - test-convert-floating-point-operation/44")
 5863     (check-next-stream-line-equal _test-output-stream "  c3/return"                                                            "F - test-convert-floating-point-operation/45")
 5864     # . epilogue
 5865     89/<- %esp 5/r32/ebp
 5866     5d/pop-to-ebp
 5867     c3/return
 5868 
 5869 test-convert-floating-point-dereferenced:
 5870     # . prologue
 5871     55/push-ebp
 5872     89/<- %ebp 4/r32/esp
 5873     # setup
 5874     (clear-stream _test-input-stream)
 5875     (clear-stream $_test-input-buffered-file->buffer)
 5876     (clear-stream _test-output-stream)
 5877     (clear-stream $_test-output-buffered-file->buffer)
 5878     #
 5879     (write _test-input-stream "fn f {\n")
 5880     (write _test-input-stream "  var m: float\n")
 5881     (write _test-input-stream "  var x/xmm1: float <- copy m\n")
 5882     (write _test-input-stream "  var y/eax: (addr float) <- copy 0\n")
 5883     (write _test-input-stream "  x <- multiply *y\n")
 5884     (write _test-input-stream "}\n")
 5885     # convert
 5886     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5887     (flush _test-output-buffered-file)
 5888 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5894     # check output
 5895     (check-next-stream-line-equal _test-output-stream "f:"                                                                     "F - test-convert-floating-point-dereferenced/0")
 5896     (check-next-stream-line-equal _test-output-stream "  # . prologue"                                                         "F - test-convert-floating-point-dereferenced/1"