Putting It All Together

Over the semester, you have implemented the front end stages of a compiler for Tiger, plus code generation for the variable-free subset of the language.

In this final project, you are to complete your compiler, with support for a nearly-complete specification of Tiger. By "nearly complete", I mean everything except for nested procedure definitions.

Specifically, you must complete implementations in JVMGeneratorV of:

In addition, you must include a "main", which allows the user to specify a Tiger source file. This program should compile the specified source file to a Jasmin JVM assembly file (use the extension ".j" in the generated file name).

Testing Your Work

If you have not already done so, install a local copy of the Jasmin tool, available at http://jasmin.sourceforge.net/. Use of this tool is very straightforward: it takes a .j file and produces the corresponding .class file.

It's probably best not to waste time trying to integrate this with your Eclipse project (though a plugin does exist). Instead, run everything from the command line. Here's an example:

Suppose first that we have generated our standard library in a separate file, TigerStdLib.j:

.class TigerStdLib
.super java/lang/Object
.method public ()V
aload_0
return
.end method
.method public static print(Ljava/lang/String;)V
.limit stack 2
.limit locals 1
getstatic java/lang/System/out Ljava/io/PrintStream;
aload_0
invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V
return
.end method

Now suppose we have the Tiger source file myprog.tig:

print("Hello, world!\n")

You would compile your work with

$ java TigerC myprog.tig
Code written to myprog.j

This should produce a Jasmin file similar to

; opening comments, if any
.class Myprog
.super java/lang/Object
.method public ()V
aload_0
return
.end method
; end initial setup for class Myprog
;
.method public static main([Ljava/lang/String;)V
.limit locals 1
.limit stack 1
ldc "Hello, world!\n"
invokestatic TigerStdLib/print(Ljava/lang/String;)V
return
.end method

You can then use Jasmin to produce JVM byte code:

$ java -jar jasmin.jar TigerStdLib.j
Generated: TigerStdLib.class
$ java -jar jasmin.jar myprog.j
Generated: Myprog.class

This will create the files Myprog.class and TigerStdLib.class. You can now run your program as you would any other compiled Java program:

$ java Myprog
Hello, world!
$ 

Submitting Your Work

Turn in your completed tigerc project to your CPSC 433 class folder. Some time between 7:00 and 10:00 pm on Tuesday evening, you will meet with me to give a demo of your work. Other times on Monday the 12th or earlier on Tuesday may be possible, too. I will have a sign up sheet outside of my office door.

Code Architecture and Ideas

Over the past three weeks, we have discussed various ideas and techniques for implementing JVM generation of ordinary control flow, binary and unary operators, variable declaration and assignment, and procedure definition and calls.

In the labs given during the term, I required you to conform your solutions to specific architectural decisions. The purpose of that was to make the assignments as modular as possible, so that difficulty at one stage did not prevent success in the later stages. For this final effort, you are free to use my suggested design decisions or make your own. If you are unsure of your solution to one of the earlier stages of the compiler, please ask me for a binary of my solution. If you've followed the earlier architectural requirements, you should be able to plug in my .class files and have everything Just Work.

Assorted Advice

The following is a summary of points made in the last week or two of classes:

Nested Procedure Support

The presence of nested procedure definitions in a language gives rise to a problem known as the downward funarg problem. The real challenge arises in nested procedure bodies that access variables or procedures defined in an enclosing scope. In such cases, the procedure's frame must have access to the most recent frame of the statically-enclosing procedure. In the general case, this cannot be done with a frame's control link, but in JVM, it is flatly impossible to access another procedure/method frame at all, so the usual technique of adding a static link will not work.

Nonetheless, it is possible to solve this problem, and many languages that support nested procedure definitions have implementations on the JVM.

Completing this feature of the Tiger compiler is not required of any of you, but if you do so, there is a substantial reward: anyone who completes a Tiger compiler with correct support for nested procedures will earn a minimum grade of an A for the course, regardless of past performance. If you think you've got a correct solution, let me know in advance, and I'll help you set up a few test cases.


John H. E. Lasseter