Q1: Do we need to initialize the fields of new objects?
Do we need to initialize the values of new arrays?
If so, where do we do it?
A1: No. When you call __allocateObject and __allocateArray
they return an chunk of memory in which all bytes are initialized to 0. This exactly fits
the default value defined for every type (false for boolean,
0 for int, and null for reference types).
Q2: Do I have to name all variables and registers differently in different functions
to avoid clashes?
A2: No. microLIR supports activation records internally so x and R1
in the caller are totally different from x and R1 in the callee,
even if it's the same function (in the case of recursion).
Q3: When I do register allocation, do I have to reset the register number in each function
(that is, start naming the registers R0,R1,...)?
A3: Yes. In fact, you should reset the number in each statement, since after a statement
is executed all of the registers it used are no longer needed.
Q4: How do we represent LIR instructions in our project? As strings?
A4: You should have a class for every type of instruction. You shouldn't
use strings because you will need the information in the instructions for PA5.
I suggest you use the classes in the microlir.instructions package as a starting point.
I also suggest that you keep a field in each LIR instruction to remember the AST node
that it was translated from, at least for call instructions, since you will need this
information in PA5.
Q5: I translated logical negation (y=!x) using the LIR instruction
Not (Not R1) but it produces strange results. Why is that?
A5: The logical instructions Not/And/Or/Xor in LIR work on the bit level, same as the assembly
instructions, so the bit-level negation of 1 gives -2. How you should translate logical negation
is by using the Xor operation, like this: Xor 1,x.
Q6: When we allocate an array, should we allocate the number of bytes needed only for
its elements or should we include the extra 4 bytes store to hold its length?
A6: Only for its elements. The library function __allocateArray (both in microLIR
and the one used for PA5) automatically adds 4 bytes to the size you specify.
Q7: How do you suggest translating assignment statements into LIR?
A7: I suggest that in your Java code you have the following code to treat
assignments (in the visit(Assignment) method of the visitor).
First, you recognize the type of location, which can be one of three:
(1) a variable, (2) an array location, an (3) a field location.
Now, you handle each case separately:
x=e1.
First, uou translate the expression e1 (by calling its accept method),
which returns a target register, say R0. Now you translate this into the LIR
instruction Move x,R1.
e2[e3]=e1
You translate each of the expressions, which return the target registers
R1,R2,R3. (Notice, you don't attempt to translate e1[e2] as a whole, but rather
you access its parts --- e1 and e2 --- and call accept on each of them).
Now you translate this into the LIR instruction MoveArray R1,R2[R3].
e2.f=e1
You translate each of the expressions, which return the target registers
R1,R2. You access the offset of the field f and get a number, e.g., 4.
Now you translate this into the LIR instruction MoveField R1,R2.4.
Q8: I think there is no way to define a string that will be printed with a
'new line' character. If I write:
str1 : "dsf
sdf"
it throws an exception, and if I write:
str1: "sdsf \n sdfrsd"
it prints it as I wrote it.
A8: This is a documented limitation of microLIR. However, it is not your problem
and you don't have to worry about this. You should write
str1: "sdsf \n sdfrsd"
and it will work just fine in PA5.