CSE 401 17wi - Project V - Compiler Additions
Due: Thursday, March 9 at 11 pm. You will "turn in" your project as you did with previous assignments by pushing it to your GitLab repository and providing a suitable tag. The final code and tag must be committed and pushed by the deadline. See the end of this writeup for details.
For the final part of the project, extend your MiniJava compiler by
adding support for IEEE-754 64-bit floating point numbers.
The support should include
the new type
constants, output, assignment, and basic arithmetic operations.
You do not need
to implement conversions between
doubles essentially live in a
parallel numeric universe similar to that occupied
ints, but not interacting with them.
As with the rest of MiniJava, the resulting language will be a
proper subset of standard Java, and programs executed with your
MiniJava compiler should have the same behavior that they
have when executed using
You should make appropriate changes to your compiler to scan, parse, type-check, and generate code for programs that use these new floating-point additions.
You should continue to use your CSE 401 gitlab repository to store the code for this part of the compiler project.
- Add Type ::= "
double" as a new production. "
double" is a new reserved word.
- Add Expression ::= <DOUBLE_LITERAL> as a new production.
- Allow parameters, variables, and object fields of
double, and use of
doublevalues in assignment statements and as arguments and return values in method calls.
- Overload the operators "+", "-", "*" and "<" to
System.out.printlnso it can print
doublevalues as well as integers. Numeric output should be formatted as it is in standard Java. We have provided a set of C routines to convert values of type
doubleto strings in the proper format (see the implementation section below).
Restrictions and simplifying assumptions
- A <DOUBLE_LITERAL> should have the form of a Java decimal floating-point literal containing decimal digits, an optional decimal point, and an optional exponent part consisting of the letter "e" or "E" followed by a signed integer exponent. As in Java, there must be at least one digit and either a decimal point or an exponent (or both). You are not required to implement Java’s "float suffix" ("f", "F", "d", or "D" following the rest of the literal). You may restrict the syntax further if needed so that it can be directly included in an assembly-language program as a floating-point literal (although we don't think additional restrictions should be necessary).
- You do not need to support implicit or explicit conversions
doubles and integers, including implicit conversions in assignments or method calls, or implicit conversions needed to support mixed-mode arithmetic such as 1 + 2.0.
- You do not need to deal with unusual
doublevalues like NaN and IEEE floating-point infinities.
- You should use the x86-64 SSE registers and instructions to
doubles using 64-bit IEEE floating-point arithmetic. The web site for the Bryant/O’Hallaron textbook used in CSE 351 has a good introduction to and description of this part of the x86-64 architecture. See http://csapp.cs.cmu.edu/public/waside/waside-sse.pdf. You also may find it useful to write small C functions using
doubles and look at the assembly code generated by
- Generating code to compare doubles can be somewhat tricky if you
support the full IEEE standard and Java semantics for floating point,
but since you are not required to deal with NaNs and other unusual
values, it should not be
much more difficult than dealing with integers.
However, if you want, you could add a C function to
boot.cto do some or all of the work and generate compiled code to call this function as needed.
- You should use the x86-64 C language calling conventions for
double-precision floating point values in their argument lists. Again, see the Bryant/O’Halloron SSE floating-point discussion for details. Note that
doubles have a separate set of registers. You will need to be careful with parameter lists that have a mixture of
doubles and other values, and you need to be aware of how registers are used when functions are called (i.e., which registers need to be saved and restored across function calls, etc.).
- Output of
doubles is somewhat tricky because the formatting needed to convert a
doubleto a string whose format matches the one used by Java is fairly complex, and not quite the same as that produced by any of the basic C
printfformat strings. We have provided two files,
number_converter.c, that contain a function
convert_doublethat creates the string representation of a
doublevalue using the rules defined by Java. These rules are found in http://docs.oracle.com/javase/8/docs/api/java/lang/Double.html#toString-double-. You do not need to understand how this code works, but it is interesting to see what is needed to do these conversions correctly.
- You will definitely want to add code to
- You will need to figure out how you want to handle
<DOUBLE_LITERAL> constants in your source code, and how
to include those constants in your generated code.
You could use Java library routines in the compiler to convert constants
to binary values of
double, then generate code with hexadecimal or integer values that would assemble to the correct binary data bits. But it's probably (much) simpler to let the assembler handle this by copying the floating-point number into the generated code as a constant data value and let the assembler’s .
doubledirective to do the conversion for you. A line of code that looks like
pi: .double 3.1415926535e0can be used to add a labeled constant in a
.datasection in the generated code. (Note: it is possible that there are edge cases where the assembler and Java might convert the same double literal to binary values that don't agree exactly in the final bit or two. Feel free to ignore those possibilities for this project.)
- To load an integer constant into a register in the x86-64 architecture,
a simple move instruction containing the constant value can be used (e.g.,
movq $17,%rax). The x86-64 SSE architecture doesn't provide an immediate constant mode that works like this for floating-point values. Instead, the constant value needs to be stored in memory (possibly by using a
.doubledirective as described above), then it needs to be loaded into a register from memory. Because of quirks in the assembler, you need to explicitly specify the addressing mode in the
movsdinstruction. For example, to load the constant
pishown above into the
xmm0register, you can use the instruction
A small amount of extra credit will be awarded for extensions that
go beyond these basic requirements. However, do not
attempt extra credit extensions until you have your chosen compiler
addition working properly. Extra credit will not be awarded to
projects that do not include a substantially correct implementation of
- Add arrays of
doubles. (This one should be quite simple, actually.)
- Support mixed-mode arithmetic using
ints, and widening conversions from
doublein assignment statements and method argument lists.
- (harder) Add type casts
(double)to convert between numeric types.
- Add "built-in" functions like
sqrt. The best way to do this probably would be to add additional syntax for
Math.sqrt(...)somewhat like the way
System.out.println(...)is already done.
What to Hand In
As with previous parts of the project you should include a brief
ADDITIONS-NOTES this time, describing
anything unusual about your project, including notes about
extensions, clever code generation strategies, or other
interesting things in this phase of the compiler. You should give
a brief description of how much is working and any major surprises
(either good or bad) you encountered along the way. In particular,
this phase of the project will involve making changes
to previously implemented parts of the compiler. Include a brief description
of what was done and why it was needed, and whether there were
any unanticipated changes required. This file should only
discuss this phase of the project. After finishing the project
code you will be asked to prepare a (short) summary report about
the entire compiler project. Details will be supplied in a
As before you will submit this part of the project by pushing code
to your GitLab repository. Once you are satisfied that everything is working
additions-final tag and push that to the repository.
Then we strongly suggest that you create a fresh clone of your
repository in some completely different temporary directory, checkout
additions-final tag, and verify that everything
works as expect. If necessary, fix any problems back in your regular
working copy of the code, push the changes to
the repository, and update the
additions-final tag to
refer to the correct commit in the repository.
Be sure that your
boot.c runtime code is in
src/boot.c, and the
should also be in this
Computer Science & Engineering University of Washington Box 352350 Seattle, WA 98195-2350 (206) 543-1695 voice, (206) 543-2969 FAX
Comments to adminanchor