CS 496 - Assignment 5

Due: Thursday, May 1st by 11:59 PM

Updated: 4/15 (Code generation hints)

Semantic Analysis and Code Generation

In this assignment, you will extend your compiler to check the abstract syntax tree for an input program for semantic errors, build symbol tables, and generate Java bytecode as the compiled form of the program.  You will be able to execute the emitted Java bytecode from the command lineusing the Java virtual machine.

Getting Started

First: make a copy of your solution to Assignment 4.  Then use your Assignment 4 solution as a starting point.

Copy the following file(s) into the default (nameless) package:


Copy the following file(s) into the edu.ycp.cs496.spl package:

Main.java IO.java

Copy the following file(s) into the edu.ycp.cs496.spl.fe package:

SPLType.java SymbolTable.java SymbolTableEntry.java  SymbolKind.java SemanticAnalysisVisitor.java SemanticAnalysisException.java

Copy the following file(s) into the edu.ycp.cs496.spl.codegen package:

ClassUtil.java TypeUtil.java CodeGeneratingVisitor.java

Extract the following zip file in the tools subdirectory:


(You will need to refresh the project after copying all of the above files.)

Once all of the above files have been copied, right click on the name of the project (spl) in the package explorer, choose Build Path->Configure Build Path..., choose the Libraries tab, click Add JARs..., and choose spl/tools/bcel-5.2/bcel.jar in the resulting dialog.

Semantic Analysis

Implement the SemanticAnalysisVisitor class so that it

1. Builds symbol tables containing entries for each variable, function, temporary value, and constant value in the input program.  For every ASTNode in the AST that could usefully have a symbol table entry, store a reference to the symbol table entry in the ASTNode.  (You should find some commented-out fields and methods in the ASTNode class which allow this.)

2. It diagnoses semantic errors in the input program by throwing a SemanticAnalysisException.  Specifically, it should find references to undeclared variables and functions, and also type check the input program to ensure that in every case where a value is used in the program, the value has a type that is appropriate for the operation being performed.

Some helper methods are provided in this class to simplify your task.

You should download errprogs.zip and extract it into the test directory.  Each of the SPL source files beginning with an "x" contains a semantic error that should be diagnosed by your SemanticAnalysisVisitor.

Code Generation

Download testprogs.zip and extract them into the test subdirectory of your project.

Use the BCEL library to generate Java bytecode for an AST which has been annotated with symbol table information by your SemanticAnalysisVisitor.  You will probably find it helpful to consult the BCEL API Documentation.

You will almost certainly need to refer to Chapter 6 of the JVM Specification to read about the various Java bytecode instructions that are available, and how they work.

You should implement code generation by implementing the methods in the CodeGeneratingVisitor class.  Some helper methods are provided in this class to simplify your task.

For each global variable in the input program, you should generate a static field.

For each function in the input program, you should generate a static method.

Use the emitInstruction methods to emit bytecode instructions for the method currently being compiled.

Note that Java bytecode does not have a boolean data type.  You should represent each SPL boolean value using a Java int value: 0 for false values, 1 for true values.

You can emit calls to static methods in the SPLRuntime class to simplify the task of performing code generation.  (This will make your job MUCH easier.)

Code generation hints

Added 4/15

Typically, generating code for an ASTNode boils down to recursively generating code for the children, and (possibly) generating an instruction to combine the results computed by the children into a single overall result.

Here are some specific hints for code generation for specific constructs:

global variables - add a static field to the generated class

functions - add a static method to the generated class.  The fun part is generating code for the function body.

variable declarations - if the variable is a local variable (not a parameter), make sure the variable is initialized with an appropriate default value.

expressions involving binary operators - Recursively generate code to compute and push the operand (subexpression) values.  Then, for arithmetic, iadd/isub/imul/idiv.  For the relational and logical operators, your best bet is to call one of the functions in the runtime library (SPLRuntime.java) to compute the result of the expression.

expressions involving a unary operator - Recursively generate code to compute the operand (subexpression) value.  Then, ineg for unary minus, or call the not function in SPLRuntime for logical not.

literal values - iconst for integer constants, LDC (load constant) to load constant strings.  You will need to create the string constant in the generated class's constant pool.

variable references - getstatic if it's a global variable, iload/aload if it's a local variable or parameter.

expression statements - generate code for the expression.  Make sure that if the expression computes a value, that it is popped off the operand stack.

assignment statements - generate code for the expression, then use either istore/astore or putstatic to store the result, depending on whether the variable being assigned is local or global.

if and if/else statements - See the hints for Compiling code containing conditional branches.

while statements - See the hints for Compiling code containing conditional branches.

You may find it useful to run the reference implementation (splCompiler.jar) and inspect its output using the javap command (to disassemble the generated class file.)

Grading Scale

This is a complex assignment.  Credit will be awared as follows:

max 40/100: Semantic analysis only

max 70/100: Compiling programs that don't have if, if/else, or while statements, but can have functions and global variables

max 100/100: Compiling programs that have if/else statements

max 120/100: Compiling programs that have while statements.

The last part is not a typo: it is possible to earn more than 100% on this assignment.


Make a zip file of just the src subdirectory of your project and upload it to Marmoset as Project 5: