Programming Assignment 6 (P6)
CS536-S24 Intro to PLs and Compilers

In this page: Due date | Overview | Specifications | Handing in | Grading criteria

Due Friday, May 3 at 11:59 pm

Late policy for P6: Programming Assignment 6 will be accepted up to 48 hours after its due date. There will be no penalty assessed for work submitted within 48 hours of the due date.


Overview

For this assignment you will write a code generator that generates MIPS assembly code (suitable as input to the Spim interpreter) for base programs represented as abstract-syntax trees.

Specifications

General information

Similar to the fourth and fifth assignments, the code generator will be implemented by writing codeGen member functions for the various kinds of AST nodes. See the on-line Code Generation notes (as well as lecture notes from 4/10, 4/15, and 4/17 ) for lots of useful details.

Note that you are not required to implement code generation for tuples or anything tuple-related (like colon-accesses).

Getting started

You can start by downloading p6-init.zip. After unzipping it, you will see all the files required for the project except the final version of ast.java. The version of ast.java that is included in p6-init.zip is the initial version from P5 along with the changes described in Changes to old code (aside from the change to the typecheck method for the WriteStmtNode described in item 6).

After the last late day for P5 has passed (i.e., 12:01 am Friday, April 26), you start by downloading p6.zip (link will be live once the deadline has passed). After unzipping it, you will see all the files required for the project. Alternatively, if you have already downloaded p6-init.zip, you can just download the updated ast.java file (link will be live once the deadline has passed).

Some useful code-generation methods can be found in the file Codegen.java. Note that to use the methods and constants defined in that file you will need to prefix the names with Codegen.; for example, you would write: Codegen.genPop(Codegen.T0) rather than genPop(T0). Also note that a PrintWriter p is declared as a static public field in the Codegen class. The code-generation methods in Codegen.java all write to PrintWriter p, so it is used when the output file is opened in P6.java:

Codegen.p = new PrintWriter(args[1]);

and that PrintWriter is closed at the end of the main program:

Codegen.p.close();

Spim

The best way to test your MIPS code is using the simulator SPIM (written by at-the-time UW-Madison Computer Science Professor Jim Larus). The class supports two versions of spim:

  1. A command line program, called spim
    Accessing spim:
  2. A GUI-driven program, called QtSpim
    Accessing QtSpim:

Both of these tools use the same backend, but I recommend using QtSpim since it is much more of a modern interface. To use spim, it should be enough to be remotely logged in to a CS Linux machine and run

~cs536-1/public/tools/bin/spim -file mips_code.s

(where mips_code.s is the name of your source file, i.e., the one containing your MIPS code)

However, if you want more guidance on using spim, you can check out this (fairly old) Reference Manual (pdf).

To get the Spim simulator to correctly recognize your main function and to exit the program gracefully, there is one thing you need to do (besides what has been discussed in lecture):

When generating the function exit for main, instead of returning using "jr $ra", issue a syscall to exit by doing:

li $v0, 10
syscall

(Note that this means that a program that contains a function which calls main won't work correctly, which will be ok for the purposes of this project.)

Here is a link to an example base program and the corresponding MIPS code.

Changes to old code

The following changes have been made since P5, which we recommend you look at before implementing the assignment:

  1. The main program (P6.java) has been updated so that, if there are no errors, the code generator is called after the type checker. Note that the main program no longer calls the unparser, nor does it report that the program was parsed successfully.

  2. Added to the name analyzer: a check whether the program contains a function named main. If there is no such function, the error message: "No main function" is printed. This is in the nameAnalysis() method of ProgramNode. See also the added isMain() method in IdNode, as it is likely to be useful during code generation.

  3. A new "offset" field has been added to the Sym class. The name analyzer has also been changed to compute offsets for each function's parameters and local variables (i.e., where in the function's Activation Record they will be stored at runtime) and to fill in the new offset field. These changes can be found in the nameAnalysis() methods in VarDeclNode, FctnDeclNode, FormalDeclNode.

  4. The name analyzer has been modified to compute and save the total size of the local variables declared in each function (e.g., in a new field of the function name's symbol-table entry). This will be useful when you do code generation for function entry (to set the SP correctly).

  5. A method has been written to compute the total size of the formal parameters declared in a function. This will also be useful for code generation for function entry.

  6. The definition of class WriteStmtNode has been changed to include a (private) field to hold the type of the expression being written, and the typecheck method for the WriteStmtNode has been updated to fill in this field. This will be useful for code generation for the write statement (since you will need to generate different code depending on the type of the expression being output).

  7. The name analysis has been modified so that the code generator can determine if an Id is local or global. You can use sym.isGlobal() to check if a variable is global or not.

Code generation

Your main focus for this assignment is to implement code generation for each of the following features:

Non-obvious semantic issues

  1. All parameters should be passed by value.

  2. The and and or operators (& and |) are short circuited, just as they are in Java. That means that their right operands are only evaluated if necessary (for all of the other binary operators, both operands are always evaluated). If the left operand of "&" evaluates to False, then the right operand is not evaluated (and the value of the whole expression is False); similarly, if the left operand of "|" evaluates to True, then the right operand is not evaluated (and the value of the whole expression is True).

  3. In base (as in C++ and Java), two string literals are considered equal if they contain the same sequence of characters. So, for example, the first two of the following expressions should evaluate to False and the last two should evaluate to True:

    "a" == "abc"
    "a" == "A"
    "a" == "a"
    "abc" == "abc"
    
  4. Logical values should be output as 1 for True and 0 for False (and that is probably how you should represent them internally as well).

  5. Logical values should also be input using 1 for True and 0 for False.

Suggestions for how to work on this assignment

  1. Locate all the changes made that were mentioned in Changes to old code and think about why they were added and what you will need them for.

  2. Implement the code generation methods in a similar way as you did with the name analysis and type check methods, such as top-down from the root ProgramNode.

  3. Test your implementation after each change. Instead of testing your entire implementation at once, it is helpful to implement one feature at a time and test your work by augmenting your test.base or by writing a base program that includes the new feature you want to test. (Note that you are not submitting any test files for this assignment, but you should write your tests as if you did have to submit one — it will likely make things a lot easier.)

Handing in

Please read the following handing in instructions carefully.

Turn in the following file to the appropriate assignment in Gradescope (note: this should be the only file changed/needed to run with the provided materials):

Please ensure that you do not turn in any sub-directories or put your Java files in any packages.

If you are working in a pair, make sure both partners are indicated when submitting to Gradescope.

Grading criteria

General information on program grading criteria can be found on the Assignments page.

For more advice on Java programming style, see these style and commenting standards (which are essentially identical to the standards used in CS200 / CS300 / CS400).


Last Updated: 4/23/2024     © 2024 Beck Hasti