Code Generation

Translate the Fun abstract syntax into MIPS assembly with virtual registers.
  1. Create a directory as6 for this assignment. Copy all your as4 files into it, as well as mips.sig and mips.sml from as5. Unpack as6.zip, giving you codegen.sml and compile.sml. Update sources.cm by adding mips.sig, mips.sml, codegen.sml.
  2. Read and understand codegen.sml; you'll notice that it is similar to the fibx.sml from Assignment 5.
  3. Implement the function gen_func.
    • Copy the callee-save registers (and the ra register) to new temporaries (can be created by Mips.newReg()).
    • Copy the argument registers to fresh temporaries (in Fun there is only one argument register).
    • Make a new environment by adding the function parameters atop the global function-names environment (in Fun there is only one function parameter).
    • Generate code for the function-body expression in this new environment.
    • Copy the result of the function-body expression to the return-value register.
    • Copy all the callee-save temporaries (and ra) back to the callee-save registers.
    • Emit a label for the epilog.
    • Return.
    Do NOT be worried about all the extra Move instructions you're generating; almost all of these will be removed by a good register allocator.
  4. Implement the function gen_exp.
    • It would be a good thing if the argument passed to gen_exp had been stripped of all its Pos and Constrain constructors, as these get in the way of pattern-matching "maximal munches".
    • For each different kind of expression, generate the code for that expression into a result register.
    • Liberally use Mips.newReg() to create new temporaries to hold intermediate values of expressions.
    • For Ref and Tuple expressions, call "alloc" to allocate the right number of words, then store the field-values into memory.
    • For the <> expression, it's not strictly necessary to call "alloc"; the value 0 represents <> quite adequately.
  5. Test by Compile.compile "test.fun"; This will generate test.fun.noregalloc.s, which will be assembly language that doesn't work because:
    • It contains temporaries of the form $x1, $x2, etc. that are not real Mips registers.
    • Parts of the procedure prologs and epilogs have not yet been inserted (they will be finished after register allocation).
  6. After you have gotten it working, read through the output ".noregalloc.s" files to make sure it looks sane--because that's about the only way to debug this assignment without having a register allocator.
  7. After you're convinced that it's sane, improve the quality of the generated code by adding 3 or 4 "munches" that match larger patterns. Don't go overboard with this, because most optimizations should really be done in later phases of the compiler, and it's not always appropriate to prematurely optimize here.
  8. Submit README and codegen.sml to dropbox here. In the README, explain your extra 3 or 4 munches.

Note: Your code generator should not explicitly save and restore caller-save (or callee-save) registers in memory (by reserving space in the frame stack and loading/storing) --not even the return address! It is not the case that the caller must save all the caller-save registers before calling a function. The caller must save all the caller-save registers that are live after the call. However, the codegen module doesn't know what's live. So it should not save or restore anything. A later module (spilling) will fix this up.

Due date: Monday, 11 April 2016, 9:00 PM