due: Monday, Nov 9
Changes:
The goal of this assignment is to generate assembly code from your IR, therefore making your compiler fully functional. The output should be processable by the GNU assembler and linkable with the runtime library we provide in order to produce working executables. Your code will run!
We require the code you produce to be able to interface with the runtime we provide, and to interoperate with other functions we may create for testing. To do this it is sufficient to follow the I9 ABI, and you have likely done most of the required work in the previous assignment. In here, you should finish implementing the details that were not visible in your IR. In particular, you'll need to be aware of the rules on register saving. Please see the updated ABI overview document for more details.
You should download the sources for the library here, as a .tar.gz or a .zip (Version 3, Oct 29th). The archive also includes sample assembly files, and instructions on testing them. Please see README.txt in the file for more details
We do not expect you to implement optimizations or high-quality register allocation for this assignment; the goal here is to produce working programs. However, we do expect you to implement non-trivial instruction selection with tiles that take advantage of the expressive x86 instruction set features like complicated addressing modes and in-memory operands. You are free to implement register allocation if you wish, but it is fully acceptable to stack-allocate all temporaries and use registers only to shuttle data between instructions and the stack.
Your new functionality must be invokable through your driver. Your driver must support at least the following command-line interface:
java -jar YOUR_JAR [-O] [-o OUTPUT_FILE] SOURCE_FILE
-O | Disable optimizations. |
-o OUTPUT_FILE | Specify the file to write the output to. If this option is not specified, and the file name SOURCE_FILE ends with .i9, replace that with .s. If SOURCE_FILE has a different extension, append .s instead. |
As in previous assignments, your driver should accept the file name of an Iota9 source file. If the file is invalid Iota (syntactic or semantic), you should report a helpful error message including the position of the invalid code and a description of the problem. If the program is valid, you should compile it, and output the assembly to a file, with the name determined as given above in the description of the -o option.
For example, java -jar acm22_ahj5_mo85.jar hello.i9
should output the assembly code the compiler produces for the program
hello.i9
into hello.s
.
You may add additional flags and options as long as you support these requirements.
You should complete your implementation as you see fit, but we offer the following suggestions.
First, download and compile the runtime. Take a look at the .s files inside the examples/ directory, and try assembling and linking them by hand. If you can do it for the examples, you'll be able to run programs your compiler produces.
As part of your solution, you'll be specifying many different tiles and their mapping to the IR. You probably want to plan out how you'll be specifying and organizing these tiles.
Since you're now able to produce runnable programs, you can have runnable functionality test cases. Taking advantage of that can help automate testing. However, do not limit yourself to such tests, as it may be hard to get good coverage over instruction-selection cases from .i9 sources alone.
As before, you are building upon your work from PA4. The protocol is the same as in prior assignments: you are required to devise and incorporate tests that expose any issues with your implementation, then fix these issues.
Now that your compilers will generate runnable code, you will be able to include end-to-end tests (often called functional tests) as part of your testing strategies. For fun (and for good karma), groups may participate in a contest of sorts. Each group may (optionally) submit a subset of their most difficult test cases, and the course staff will run these test cases against every group's compilers. The goal will be to craft test cases (that conform to the common language specification) that expose bugs in others' compilers.
Each functional test case will be a valid Iota9 source file. A
compiler c
passes a test t
if and only if:
c
successfully compiles t
into an assembly file
a
.a
against the standard
Iota9 library results in a runnable program o
.o
, when executed, terminates (within an arbitrarily bounded
amount of time) with a return code of 0 (i.e., it terminates normally, and not
as a result of an assertion failing or an array out-of-bounds violation).All test cases must:
io
, conv
, and
assert
interfaces.Each group may submit up to 5 test cases. Submitting test cases that fail to conform to the above requirements may result in disqualification (and thus bad karma). Groups that submit test cases that expose bugs in compilers (i.e., test cases that compilers do not pass) will discover good karma. All test cases submitted for the contest will be released after the assignment's due date.
As in previous assignments, please ensure that all your Java code lives in a package containing the NetId of at least one of your group members. Your code should compile without errors or warnings. Your code should not contain any superfluous print or debug statements.
Submit the following:
*.class
).Main-Class
to be your driver. This
will enable us to run your JAR file directly. See Sun's tutorial for
help with this.*.java
, *.flex
, *.cup
, etc.). Do not forget to
include your source. Failure to do so will result in a 0 for this
assignment..jar
, .zip
, or
.tar.gz
) containing your testing code and test cases..zip
, or .tar.gz
)
containing up to 5 functional test cases your group would like to be considered
for the test case contest.