Reading

Setting Up the Project

No new files this week, though you'll probably be making some of your own. In particular,

Your job

This week we'll make further, incremental progress on our code generator. The main task for now is to complete generated code for the Tiger standard library.

In addition, you should complete code generation for procedure calls (i.e., visit(ExpCall)).

The Standard Library

This is a collection of predefined procedures that come with every implementation of Tiger. There are several ways to complete this task, but all of them involve generating ".method" definitions for each procedure. I suggest writing these definitions to a separate class, and defining a library of generation procedures, rather than putting the whole mess in JVMGeneratorV. For example:

package tigerc.codegen.jvm;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;

public class StdLibGenerator {

	public static void makeStdLibrary() {
		if (new File("TigerStdLib.class").exists())
			return;

		PrintWriter stdlibOut = null;
		try {
			stdlibOut = new PrintWriter(new File("TigerStdLib.j"));
		} catch (FileNotFoundException e) {
			System.err.println("fatal error:  cannot create standard library.");
			System.exit(1);
		}

		// Write out the prelude for the TigerStdLib class
		new JVMGeneratorV(stdlibOut).emitPrelude("TigerStdLib",
				"standard library for the Tiger language");
		stdlibPrint(stdlibOut);

		// remaining standard library definitions go here
	}

	// //// Standard library definitions
	private static void stdlibPrint(PrintWriter out) {
		assert out != null;		
		out.println(".method public static print(Ljava/lang/String;)V");
		out.println(".limit stack 2");
		out.println(".limit locals 1");
		out.println("getstatic java/lang/System/out Ljava/io/PrintStream;");
		out.println("aload_0");
		out.println("invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V");
		out.println("return");
		out.println(".end method");
	}
}

Under this scheme, you'd implement the makeStdLib() method in JVMGenerator as

	public void emitStdLibrary() {
		StdLibGenerator.makeStdLibrary();
	}

You are free to use your own creativity for this, however.

Procedure Calls

Complete the implementation of visit(ExpCall). In the JVM, this is quite straightforward, really, since we don't need to worry about a procedure's entry label (and hence don't need to store it in tigerc.semant.Entry.FunEntry). Just push each argument onto the current stack, then invoke the method that's been called. All necessary type information is already in the procedure's FunEntry record, of course.

However, this leads us to ...

Incorporating Type Information

Though semantic analysis has already filtered out ill-typed programs, we're going to need some information about expression types, in order to generate the correct JVM instructions. The task is much simpler here, since you can always assume that everything is correctly typed. Still, you're going to need to modify your JVMGenerator to include a "current expression type" value, and you're going to need a value environment (see tigerc.semant.SemantV.venv and tenv).

Happily, there's no need to check types. You just need to record the type of the last expression encountered. For example, in visit(ExpBreak), we add at the end of the method the statement

    this.currentT = PrimtT.VOID_T;

(assuming that your JVMGeneratorV has a field declared as "Type currentT").

This also implies that you should include, as part of the skeleton of your visit(DeclGroupFunction) and visit(DeclVar) methods, statements sufficient to add the appropriate VarEntry and FunEntry bindings. I'd suggest making this much of the skeletons now (remember, you don't have to check anything, since you can assume everything is well-typed).

John H. E. Lasseter