languages and compiler design ii project 5 hints

23
PSU CS322 HM 1 Languages and Compiler Design II Project 5 Hints Material provided by Prof. Jingke Li Stolen with pride and modified by Herb Mayer PSU Spring 2010 rev.: 4/16/2010

Upload: deon

Post on 11-Jan-2016

35 views

Category:

Documents


3 download

DESCRIPTION

Languages and Compiler Design II Project 5 Hints. Material provided by Prof. Jingke Li Stolen with pride and modified by Herb Mayer PSU Spring 2010 rev.: 4/16/2010. Agenda. SPARC Assembly Code Generation CodeGen Class Register Representation Simple Register Allocation Freeing Registers - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Languages and Compiler Design II Project 5 Hints

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

Page 2: Languages and Compiler Design II Project 5 Hints

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

Page 3: Languages and Compiler Design II Project 5 Hints

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

Page 4: Languages and Compiler Design II Project 5 Hints

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

Page 5: Languages and Compiler Design II Project 5 Hints

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")

};

Page 6: Languages and Compiler Design II Project 5 Hints

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

Page 7: Languages and Compiler Design II Project 5 Hints

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

Page 8: Languages and Compiler Design II Project 5 Hints

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

Page 9: Languages and Compiler Design II Project 5 Hints

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

Page 10: Languages and Compiler Design II Project 5 Hints

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

Page 11: Languages and Compiler Design II Project 5 Hints

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

Page 12: Languages and Compiler Design II Project 5 Hints

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

Page 13: Languages and Compiler Design II Project 5 Hints

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

Page 14: Languages and Compiler Design II Project 5 Hints

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

Page 15: Languages and Compiler Design II Project 5 Hints

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; }

Page 16: Languages and Compiler Design II Project 5 Hints

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.

Page 17: Languages and Compiler Design II Project 5 Hints

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

Page 18: Languages and Compiler Design II Project 5 Hints

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

Page 19: Languages and Compiler Design II Project 5 Hints

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

Page 20: Languages and Compiler Design II Project 5 Hints

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

Page 21: Languages and Compiler Design II Project 5 Hints

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

Page 22: Languages and Compiler Design II Project 5 Hints

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)

Page 23: Languages and Compiler Design II Project 5 Hints

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