PSUCS322 HM 1 Languages and Compiler Design II Project 5 Hints Material provided by Prof. Jingke Li...
-
date post
19-Dec-2015 -
Category
Documents
-
view
215 -
download
0
Transcript of PSUCS322 HM 1 Languages and Compiler Design II Project 5 Hints Material provided by Prof. Jingke Li...
PSU CS322 HM 1
Languages and Compiler Design IIProject 5 Hints
Material provided by Prof. Jingke Li
Stolen with pride and modified by Herb Mayer
PSU Spring 2010rev.: 4/16/2010
PSU CS322 HM 2
Agenda• SPARC Assembly Code Generation• CodeGen Class• Register Representation• Simple Register Allocation• Freeing Registers• Low-Level Code Emission• Sample: hello world• Statements• Operands• Expressions• Sample: MEM• Sample: CALL
PSU CS322 HM 3
SPARC Assembly Code Generation
• Input: IR Tree program• Strategy: Traverse IR tree top-down; generate
code bottom-up — for each node, generate code for its children first, then generate code for itself
• Register Management: When needed, allocate the next available register; if mo registers available, issue an error and die with suitable message
PSU CS322 HM 4
The CodeGen Classpublic class Codegen{
static final int wordSize = 4,// word size
minArgSize=24, // minumum arg-build area
reservedSize=68; // space for reg window dump
private PROG program; // input IR program
private Hashtable<Integer, Reg> tempTable; // temp-reg table
private Hashtable<String, String> strTable; // string table
private int tempCnt, strCnt, // sizes of the two tables
regUseCnt, maxRegCnt; // reg-use statistics
public Codegen( PROG p ) {
program = p;
tempTable = new Hashtable<Integer, Reg>();
strTable = new Hashtable<String, String>();
tempCnt = 0;
strCnt = 2; // The first two slots are reserved for ’printf’
regUseCnt = 0;
maxRegCnt = 0;
} //end Codegen
PSU CS322 HM 5
Register Representationpublic class Reg extends Operand {
static final int RESERVED = -1, FREE = 0, USE = 1, TEM P=2;
String name;
int status;
public Reg(String s) { name=s; status=FREE; }
public Reg(String s, int st) { name=s; status=st; }
public void emit() { System.out.print(name); }
} //end Reg
// SPARC special registers
static final Reg regSP = new Reg("%sp", Reg.RESERVED), // stack ptr
regFP = new Reg("%fp", Reg.RESERVED), // frame ptr
regG0 = new Reg("%g0", Reg.RESERVED), // always zero
regY = new Reg("%y", Reg.RESERVED), // for div op
regO0 = new Reg("%o0"), // first arg
regO1 = new Reg("%o1"), // second arg
regRV = new Reg("%i0"); // return value
// general SPARC registers
static final int maxRegs = 26;
static final Reg[] reg = {
new Reg("%l0"), new Reg("%l1"), new Reg("%l2"), new Reg("%l3"),
new Reg("%l4"), new Reg("%l5"), new Reg("%l6"), new Reg("%l7"),
new Reg("%i1"), new Reg("%i2"), new Reg("%i3"), new Reg("%i4"),
new Reg("%i5"), new Reg("%i7"), new Reg("%g1"), new Reg("%g2"),
new Reg("%g3"), new Reg("%g4"), new Reg("%g5"), new Reg("%g6"),
new Reg("%g7"), new Reg("%o2"), new Reg("%o3"), new Reg("%o4"),
new Reg("%o5"), new Reg("%o7")
};
PSU CS322 HM 6
Simple Register AllocationUpon a request, allocate next register numerically. None available? Exception!
private Reg getReg() throws CodegenException {for( int i = 0; i < maxRegs; i++ ) {
if( reg[i].status == Reg.FREE ) {Reg[i].status = Reg.USE;if( ++regUseCnt > maxRegCnt ) maxRegCnt = regUseCnt;
return reg[i];} //end if
} //end forthrow new CodegenException( "Out of registers“ );
} //end getReg
private void useReg( Reg r ) throws CodegenException {if( r.status != Reg.FREE ) {
throw new CodegenException( "Trying to use an occupied reg: " ...); } //end ifr.status = Reg.USE;if( ++regUseCnt > maxRegCnt ) maxRegCnt = regUseCnt;
} //end useReg
When temp is assigned a register, status set to Reg.TEMP, so not to be freed
PSU CS322 HM 7
Freeing Registers// freeing a used reg, skip if it holds a temp
void freeReg( Reg r ) {
if( r.status == Reg.USE ) {
r.status = Reg.FREE;
regUseCnt--;
} //end if
} //end freeReg
// freeing all used regs, including those holding temps
void freeAllRegs() {
for( int i = 0; i < maxRegs; i++ ) {
if( ( reg[i].status == Reg.USE ) ||
( reg[i].status == Reg.TEMP) ) { //Then
reg[i].status = Reg.FREE;
} //end if
regUseCnt = 0;
} //end for
} //end freeAllRegs
PSU CS322 HM 8
Low-Level Code Emissionvoid emit ( String s ) { System.out.print(s); }
void emit0( String op) { emit("\t" + op + "\n"); }
void emit2( String op, Operand rand1, Operand rand2 ) {
emit("\t" + op + " "); rand1.emit();
emit(","); rand2.emit(); emit("\n");
} //end emit2
void emit3( String op, Operand rand1, Operand rand2,
Operand rand3) {
emit( "\t" + op + " "); rand1.emit(); emit(",");
rand2.emit(); emit(","); rand3.emit(); emit("\n");
} //end emit3
void emitStore( Operand rand1, Operand rand2 ) {
emit("\tst "); rand1.emit(); emit(",["); rand2.emit(); emit("]\n");
} //end emitStore
void emitLoad( Operand rand1, Operand rand2 ) {
emit( "\tld [“ ); rand1.emit(); emit("],");
rand2.emit(); emit("\n");
} //end emitLoad
PSU CS322 HM 9
Top-Level Code Emissionpublic void go() throws CodegenException {
for( int i = 0; i < program.funcs.size(); i++ ) {FUNC f = (FUNC) program.funcs.elementAt(i);int framesize = frameSize(f.varCnt * wordSize, f.argCnt *
wordSize);if( f.label.equals("main") ) emit0(".global main");emit0(".align 4"); emit(f.label + ":\n");emit("!locals=" + f.varCnt + ", max_args=" + f.argCnt + "\n");emit0("save %sp,-" + framesize + ",%sp");genStmts(f.stmts);freeAllRegs();emit0("ret"); emit0("restore"); emit("\n");
} //end forprintStrConsts();printRegStatus();
} //end go
private int roundup( int x, int p) { return ((x+p-1)/p) * p; }
private int frameSize( int localSize, int argSize) {if( argSize < minArgSize ) argSize = minArgSize;return roundup( reservedSize + localSize + argSize, 8 );
} //end frameSize
PSU CS322 HM 10
Sample: hello worldclass hello {
public static void main(String[] a) {
System.out.println("Hello World!");
}
}
IR_PROGRAM
main( locals = 0, max_args = 0 ) {
[CALLST (NAME prString) ( (STRING "Hello World!"))]
} //end main
------------------maps into------------------------------------.global main.align 4main:!locals=0, max_args=0
save %sp,-96,%sp![CALLST( NAME prString ) ( ( STRING "Hello World!“ ))]
sethi %hi(L$2),%o0call printfor %o0, %lo(L$2),%o0retrestore
L$2: .ascii "Hello World!\12\0"!Total regs: 1!Total insts: 8
PSU CS322 HM 11
Statements
void genStmts( STMTlist sl ) throws CodegenException{
for( int i = 0; i < sl.size(); i++ ) {
STMT s = (STMT) sl.elementAt(i);
emit("!"); s.dump();
if( s instanceof MOVE) genMove((MOVE) s);
else if( s instanceof JUMP) genJump((JUMP) s );
else if( s instanceof CJUMP) genCjump((CJUMP) s );
else if( s instanceof LABEL) genLabel((LABEL) s );
else if( s instanceof CALLST) genCallSt((CALLST) s);
else if( s instanceof RETURN) genReturn((RETURN) s);
else throw new CodegenException("Illegal STMT: "+s);
} //end for
} //end genStmts
PSU CS322 HM 12
Statements: Move, JumpMOVE — Generate code for src and bring result to a reg; if dst is temp, then gen a mov
instruction, else generate code for dst; then gen a store instruction:
void genMove( MOVE s ) throws CodegenException {
if( s.dst instanceof TEMP ) {
Reg r = toReg(genExp(s.src));
Operand dst = genTemp((TEMP) s.dst);
emit2("mov", r, dst);
freeReg( r );
}else{ ...
} //end if
} //end genMove
JUMP — Gen a ba instruction followed by a nop:
void genJump( JUMP s ) throws CodegenException {
if( s.target instanceof NAME )
emit0("ba " + ((NAME) s.target).id); emit0("nop");
else
throw new CodegenException("JUMP target not a NAME");
} //end genJump
PSU CS322 HM 13
Statements: Return etc.
CJUMP:
First gen a cmp instruction; then gen a conditional jump
LABEL:
Void genLabel(LABEL s) { emit0(s.lab + ":"); }
RETURN:
void genReturn( RETURN s ) throws CodegenException {
if( s.exp != null)
// gen code for s.exp and bring result to RegRV
emit0("ret");
emit0("restore");
} //end genReturn
PSU CS322 HM 14
Statements: Call and Printvoid genCallSt( CALLST s ) throws CodegenException {
String fname = s.func.id;if( fname.equals( "prInt“ )) genPrintInt(s.args);else if( fname.equals( "prString“ ) ) genPrintString( s.args );else if( fname.equals( "error“ ) ) genPrintError();else handleCall( fname, s.args );
} //end genCall
void genPrintInt( EXPlist args ) throws CodegenException {if( args.size() != 1) throw new CodegenException("wrong number of args to prInt");useReg( regO0 );useReg( regO1 );toReg( regO1, genExp((EXP) args.elementAt(0)));emit0( "sethi %hi(L$0),%o0");emit0( "call printf");emit0( "or %o0, %lo(L$0),%o0“ );freeReg( regO0 ); freeReg( regO1 );
} //end genPrint
PSU CS322 HM 15
Operands Intermediate results are stored in different operands: registers, stack
locations, 13-bit and 32-bit immediate values, or globals
abstract class Operand {}
public class Reg extends Operand {
static final int RESERVED=-1, FREE=0, USE=1, TEMP=2;
String name;
int status;
} //end Operand
public class RegOffset extends Operand{ Reg r; int o; }
public class Imm13 extends Operand { int i; }
public class Imm32 extends Operand { int i; }
public class AddrName extends Operand { String s; }
PSU CS322 HM 16
ExpressionsGen code and return Operand that is holding the expression’s value.
Operand genExp( EXP e ) throws CodegenException {
if( e instanceof MEM ) return genMem((MEM) e);
else if( e instanceof CALL ) return genCall((CALL) e);
else if( e instanceof BINOP ) return genBinop((BINOP) e);
else if( e instanceof TEMP ) return genTemp((TEMP) e);
...
} //end genExp
MEM: exp component is translated into Operand node, which should represent an address. If the MEM appears on the left-hand-side of a MOVE statement, it should be translated into a store instruction; otherwise it should be translated into a load instruction. Can default the genMem routine to translate a MEM into a load, and have the genMOVE routine handle the store case directly.
PSU CS322 HM 17
MEM Exampleclass tt3 {
public static void main( String[] a ){
int[] a = new int[4];
int len = a.length();
System.out.println(len);
} } //end main
main:
save %sp,-104,% sp st %l2,[%l1]
mov 5,%l0 sub %l1,4,%l2
smul %l0,4,%l0 mov %l2,%l1
mov %l0,%o0 cmp %l1,%l0
call malloc bg L0
nop nop
mov %o0,%l0 st %l0,[%fp-4]
mov 4,%l1 ld [%fp-4],%l2
st %l1,[%l0] st %l2,[%fp-8]
mov 4,%l1 ld [%fp-8],%o1
smul %l1,4,%l1 sethi %hi(L$0),%o0
add %l0,%l1,%l2 call printf
mov %l2,%l1 or %o0, %lo(L$0),%o0
L0: ret
mov 0,%l2 restore
PSU CS322 HM 18
Handling Expressions, Cont’dBINOP• The first operand must be a register.• Only a 13-bit immediate value can directly participate in an operation
as an operand. A large immediate value must be load to a register (with a set instruction) first.
• DIV operation is implemented with the instruction sdiv, which require the use of a special register %y. The content of %y needs to be cleared before the execution of udiv
CALL• Distinguish system routines (i.e. prInt(), prString(), error(), and
malloc() ) from user-defined routines. For system routines, pass parameters through the registers %o0 and %o1
• For user-defined routines, pass parameters on the stack
PSU CS322 HM 19
MEM Example, Cont’dclass tt1 {
public static void main( String[] a ) {int a = 12; int b = 3;System.out.println(a+4096-b*4095/15);
} //end main } //end tt1
.global main
.align 4main:!locals=2, max_args=0 wr %g0,%g0,%y
save %sp,-104,%sp sdiv %l1,15,%l1! [MOVE (VAR 1) (CONST 12)] sub %l0,%l1,%l0
mov 12,%l0 mov %l0,%o1st %l0,[%fp-4] sethi %hi(L$0),%o0
! [MOVE (VAR 2) (CONST 3)] call printfmov 3,%l0 or %o0, %lo(L$0),%o0st %l0,[%fp-8] ret
! [CALLST (NAME prInt) ...] restoreld [%fp-4],%l0set 4096,%l1 L$0: . ascii "%d\12\0"add %l0,%l1,%l0ld [%fp-8],%l1 !Total regs: 3smul %l1,4095,%l1 !Total insts: 21
PSU CS322 HM 20
CALL Exampleclass tt2 {
public int f( int a, int b, int c, int d ){ return a+b+c+d; }
public static void main( String[] a ){ System.out.println( f( 1,2,3,4 ) ); }
} //end tt2
tt2_f: main:save %sp,-96,%sp save %sp,-96,%spld [%fp+72],%l0 ld [%fp+68],%l0ld [%fp+76],%l1 st %l0,[%sp+68]add %l0,%l1,%l0 mov 1,%l0ld [%fp+80],%l1 st %l0,[%sp+72]add %l0,%l1,%l0 mov 2,%l0ld [%fp+84],%l1 st %l0,[%sp+76]add %l0,%l1,%l0 mov 3,%l0mov %l0,%i0 st %l0,[%sp+80]ret mov 4,%l0restore st %l0,[%sp+84]
call tt2_fnopmov %o0,%l0...
!Total regs: 3!Total insts: 36
PSU CS322 HM 21
genBinop and genMem// A primitive version, both operands are brought into registers
Operand genBinop( BINOP e ) throws CodegenException {
Reg r1 = toReg( genExp( e.left ) );
Reg r2 = toReg( genExp( e.right ) );
Reg r3 = getReg();
if( e.op == BINOP.DIV )
emit3( "wr", regG0, regG0, regY );
emit3( binopCode(e.op), r1, r2, r3 );
freeReg( r1 );
freeReg( r2 );
return r3;
} //end genBinop
// Generate a load instruction
Operand genMem( MEM e ) throws CodegenException {
Operand t = genAddr( e.exp );
if( t instanceof Reg ) { emitLoad(t, t ); return t;
}else if( t instanceof RegOffset ) { ...
}else if( t instanceof AddrName ) { ...
} //end if
throw new CodegenException( "wrong address form: " + t );
} //end genMem
PSU CS322 HM 22
Other ExpressionsTEMP: Check tempTable to see if the temp has been assigned a register
already; if so, return that register; otherwise, get a new register and save
the info in the table:
Operand genTemp(TEMP t) throws CodegenException {
Reg r = (Reg) tempTable.get( t.num );
if( r == null ) { ... }
return r;
} //end genTemp
VAR: Generate a RegOffset operand; using %fp as the base register:
Operand genVar( VAR e ) {
return new RegOffset(regFP, - e.idx * wordSize);
} //end genVar
PARAM: Similar to VAR; but offset needs to be adjusted by the reserved
space (i.e. 68 bytes)
PSU CS322 HM 23
Other Expressions, Cont’d
MEMBER: Bring the base address (i.e. the obj component) into a register and then generate a RegOffset operand
NAME wSZ: Gen a word-size constant:
Operand genName( NAME e ) throws CodegenException {
if( e.id.equals("wSZ") )
return new Imm13( wordSize );
throw new CodegenException( "Illegal NAME node“ );
} //end genName
CONST: Gen either a 13-bit or 32-bit const value:
Operand genConst( CONST e ) throws CodegenException {
if( (e.val >= -4096) && (e.val < 4096) )
return new Imm13( e.val );
return new Imm32( e.val );
} //end genConst