You will implement a register allocation algorithm in your
compiler. As in prior assigments, your compiler will call csc
compiler on subset C files. Then, your register
allocator will take the 3-address format program as the
input, and perform register allocation for the PowerPC processor.
It will generate an intermediate format called RA3 code (register allocated
3-address format code) as the output. Then, you will translate the code
in RA3 from to PowerPC assembly code by calling a translator that we provide.
You need to test your code on PowerPC machine, and generate
an analysis report based on the results.

The source files of the 3-addr to PowerPC translator are in the
3addr_to_ppc directory. Here is an example call to the translator:cd 3addr_to_ppc; run.sh -backend=ppc
The example files of the RA3 form code
are in the example directory. Among them, s4.c is the original C
source file, s4.3addr is the 3-addresss form code, s4.3addr.ra3 is the
RA3 form code, and s4.s is the translated code for the PowerPC
machine.

Implement your own new register allocation component in the
lab4 directory. As usual, your compiler should accept 3-address code
as input from stdin, and write output to stdout. Your compiler
back end should generate the following output:

RA3 format code with the specified number of registers
registers.

An optimization report

Your compiler will be invoked by the script 'run.sh', and should
accept the following command line arguments.

-opt, a comma separated list of transformations. The
transformations you will support are:

rga,x: perform basic register allocation with x
available registers, where x is a number in the set: (4, 6, 8, 10,
12, 14, 16).

Perform register allocation from the source of your choice. You will
generate the RA3 format code, which is an extension of the 3-address
format.

RA3: Register allocated 3-address format
RA3 formatis very similar to 3-address. We list the differences
below.

A new operand type, register, is defined in the RA3 format.
It ends with "~". For example, "r20~" is a legal
register operand. r20~ specifies that the operand is in register 20.
(See the PPC register table below for valid register names.)
When storing the result of an instruction to a register, generate
the register operand at the beginning of the instruction as follows:

"r23~instr 15: mul r20~ 10."
This instruction has two
operands, the 1st is the register r20, the 2nd is a constant, the
result is stored in register r23.

You
only need to allocate one register for the results of the 2nd
instruction. Please notice the format of the 2nd instruction is
different from the 3-address format.

B: Store global variable:

instr 4: add res_base#32756 GP
instr 5: store 18 res_base#32756

This instruction stores a constant 18 in a global variable with the address 32756.

If a register is stored, the instructions are:

instr 4: add res_base#32756 GP
instr 5: store r18~ res_base#32756

This instruction stores the contents of register r18 in a global variable with the address 32756.

The local variables, such as x#-4, y#-8, are on the stack
after any function is called. Operands in this format will access
memory, rather than using registers.

Only load/store instructions can access local variables
directly.

All other instructions must have register or constant
operands. The only exception is the address for the global variables: the
add instruction, that is computing the address, accesses the GP and offset directly.

The WriteLong() function can print the value of register
operand. It adds a \n at the end. You must not call
WriteLine() any more.

The max number of the parameters for each function is 8.

Array and Structure are not supported.

The example of a 3-address format code and its RA3 format code
are listed below:

Usage Constraints for the PPC registers
The PowerPC architecture provides 32 general purpose registers, each
32 bits wide. Here are general purpose registers and their usage.

Register Name

Usage

r0

Volatile register which may be modified during function
linkage

r1

Stack frame pointer, always valid

r2

System-reserved register

r3-r4

Volatile registers used for parameter passing and return
values

r5-r10

Volatile registers used for parameter passing

r11-r12

Volatile registers which may be modified during function
linkage

r13

Small data area pointer register

r14-r30

Registers used for local variables
Only these numbers are available to your register allocator.

r31

Used for local variables or "environment
pointers"

CR0-CR7

Condition Register Fields, each 4 bits wide

LR

Link Register

Since we provide the translation from RA3 format into PPC, you will
not implement the ABI component (i.e., the calling convention that
saves and restores registers on a procedure call and return). However,
you need to notice:

Only registers r14-r30 are available for local variables that you will allocate.

r1 is the stack frame pointer.

All data is 32 bits.

Report format
You will run your code on a CS linux machine, and generate the ra3
code. when "-backend=rep" is speficied, please generate the report in
the form as below, note, the number of resisters is specified by "-opt
=rga"

C File: testcase1.c

<Graph coloring/Linear scan>
Register number: 4, Number of Spills: 20

Then, You will translate the ra3 code into ppc assembly code by calling
the translator provided on a CS Linux machine. You will test your
assebmly code on a PPC machine (we will send you account information
shortly). You will report the compilation and execution time. Please
report the execution time with variant number of registers as below,
note, you need to generate this report manually, and write it into a
file, named testcase1.ppc.rep.

A single tgz file named lab4.tgz, which, when extracted,
creates the lab4 directory.

The lab4 directory can contain sub-directories.

The lab4 directory should contain the following files:

README - Please include your name(s) and UTEID(s) here.

compile.sh - a script to compile your source code.

run.sh - a script that runs your compiler. This script
should read 3-address code as input from stdin and write output to
stdout. The output is specified by the command line arguments
described in the previous section.

Turn in your assignment by running the following commands on a
UTCS Linux machine.