Implements Static Checking for a subset of Java (MiniJava) and production of Intermediate Representation code fed to LLVM compiler π
Compilation consists of a variety of stages, first one being Semantic Analysis. It is task is to ensure that the declarations and the statements of a target program are semantically correct. Their meaning has to be clear and consistent with the way in which control structures and data types are supposed to be used.
These requirements can be met by applying a throughout Static Checking, which focuses on types and errors that are independent of the specific value that a variable has. We can regard type as a set of values. Static Checking guarantees that a variable will have some value from that set, but we don't know until runtime exactly which value it has.
In order to be able to traverse the contents of the target program, a map is needed, namely MiniJava's grammmar in JavaCC Form.
JTB Tool is used to convert it into a grammar that produces class hierarchies, contained within a
Abstact Syntax Tree. Following the Visitor Pattern,
the First Visitor (MGVisitor
) program is developed that recursively traverses the different noed of the tree, based on the type of entity that is currently read from the target file.
At each step, semantic correctness is examined.
Traversal is used to gather useful data for every class such as the names and the offsets of every field and method this class contains. In this way,
the Second Visitor (TCVisitor
) has all the necessary type level information to infer whether subsequent commands and expressions are valid based on the data type of
the operators that partake in them. This process is known as the population of classes' Virtual Method Table and is crucial for the inheritance aspect
of modern languages.
After we have guaranteed the Semantic Correctness of the target program, we have to translate it into its Intermediate Representation.
This is a low level language, that contains simple memory based commands, the concept of a class is no more relevant. The produced code is subsequently
fed to a LLVM Compiler. Here, the low level representation is translated into binary code, that can run on the computer's
hardware. This phase is achieved by the Third Visitor (LLVMVisitor
), that traverses each expression and command in the target file and for each one,
produces its corresponding IR.
- In order to compile the code, enter the
/Compiler
folder and type:make compile
. - To make the target Java files visible to the compiler, you have to put them into the
/target_java
. - Execute the program by staying in the
/Compiler
folder and typing:java Main <target java file 1> ... <target java file N>
IMPORTANT - Program takes the raw names of the files as they are in the target_java
folder. You DON'T have to include the absolute path!
After the compilation commences, you can find the Intermidiate Representation of each requested target file in the output_ll
folder.
If you want to produce an executable of an IR File, you have to download Clang and run the following command:
clang -o <executable name> <ll file>
Built as part of the course: Compilers , Summer of 2021. University of Athens, DiT.