Due: Thursday, December 5 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 double
, floating-point
constants, output, assignment, and basic arithmetic operations.
You do not need
to implement conversions between int
s
and double
s; the double
s essentially live in a
parallel numeric universe similar to that occupied
by int
s, but not interacting with them.
As with the rest of MiniJava, the resulting language should 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 javac
/java
.
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.
double
" as a new production.
"double
" is a new reserved word.double
, and use of double
values in
assignment statements and as arguments and return values in method
calls.+
", "-
",
"*
" and "<
" to
support double
values.System.out.println
so it can
print double
values 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 double
to strings
in the proper format (see the implementation section below).double
s and integers, including implicit
conversions in assignments or method calls, or implicit
conversions needed to support mixed-mode arithmetic such as
1 + 2.0.double
values
like NaN and IEEE floating-point infinities.double
s 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 double
s and look at the assembly code generated
by gcc -S
.boot.c
to do some or all of the work and generate compiled code to call this
function as needed.double
-precision floating point values
in their argument lists. Again, see the Bryant/O’Halloron SSE
floating-point discussion for details. Note
that double
s have a separate set of registers. You
will need to be careful with parameter lists that have a mixture
of double
s 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.).double
s is somewhat tricky because the formatting
needed to convert a double
to 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 printf
format strings. We have provided two
files, number_converter.h
and number_converter.c
, that contain a
function convert_double
that creates the string
representation of a double
value using the rules
defined by Java. These rules are found
in https://docs.oracle.com/en/java/javase/11/docs/api/java.base/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.boot.c
to
implement System.out.println
for double
s by calling the supplied formatting functions
and then printing the formatted string.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 .double
directive 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
.data
section 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.)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 .double
directive as described above),
then it needs to be loaded into a register from memory. Because of quirks
in the assembler, you may need to explicitly specify the addressing mode
in the movsd
instruction. For example, to load the constant
pi
shown above into the xmm0
register,
you can use the instruction movsd pi(%rip),%xmm0
As with the rest of the compiler project,
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 the required compiler
addition working properly. Extra credit will not be awarded to
projects that do not include a substantially correct implementation of
double
.
Some possibilities:
double
s. (This one should be quite simple, actually.)double
s
and int
s, and widening conversions
from int
to double
in assignment statements and
method argument lists.(int)
and (double)
to convert between numeric types.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.
As with previous parts of the project you should include a brief
file, called additions-notes.txt
this time, in the
Notes/
top-level directory of your project 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
separate assignment.
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
properly,
create a 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
the 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/runtime/boot.c
,
and that the number_converter.h
and
number_converter.c
files
are also copied into this directory.
We will use your versions of these files to compile and
test your compiler.