1 / 23

Languages and Compiler Design II Project 5 Hints

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

deon
Download Presentation

Languages and Compiler Design II Project 5 Hints

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


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

  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 CS322

  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 CS322

  4. The CodeGen Class public 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 CS322

  5. Register Representation public 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") }; CS322

  6. Simple Register Allocation Upon 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 for throw 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 if r.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 CS322

  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 CS322

  8. Low-Level Code Emission void 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 CS322

  9. Top-Level Code Emission public 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 for printStrConsts(); 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 CS322

  10. Sample: hello world class 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 4 main: !locals=0, max_args=0 save %sp,-96,%sp ![CALLST( NAME prString ) ( ( STRING "Hello World!“ ))] sethi %hi(L$2),%o0 call printf or %o0, %lo(L$2),%o0 ret restore L$2: .ascii "Hello World!\12\0" !Total regs: 1 !Total insts: 8 CS322

  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 CS322

  12. Statements: Move, Jump MOVE — 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 CS322

  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 CS322

  14. Statements: Call and Print void 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 CS322

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

  16. Expressions Gen 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. CS322

  17. MEM Example class 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 CS322

  18. Handling Expressions, Cont’d BINOP • 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 CS322

  19. MEM Example, Cont’d class 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 4 main: !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,%o1 st %l0,[%fp-4] sethi %hi(L$0),%o0 ! [MOVE (VAR 2) (CONST 3)] call printf mov 3,%l0 or %o0, %lo(L$0),%o0 st %l0,[%fp-8] ret ! [CALLST (NAME prInt) ...] restore ld [%fp-4],%l0 set 4096,%l1 L$0: . ascii "%d\12\0" add %l0,%l1,%l0 ld [%fp-8],%l1 !Total regs: 3 smul %l1,4095,%l1 !Total insts: 21 CS322

  20. CALL Example class 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,%sp ld [%fp+72],%l0 ld [%fp+68],%l0 ld [%fp+76],%l1 st %l0,[%sp+68] add %l0,%l1,%l0 mov 1,%l0 ld [%fp+80],%l1 st %l0,[%sp+72] add %l0,%l1,%l0 mov 2,%l0 ld [%fp+84],%l1 st %l0,[%sp+76] add %l0,%l1,%l0 mov 3,%l0 mov %l0,%i0 st %l0,[%sp+80] ret mov 4,%l0 restore st %l0,[%sp+84] call tt2_f nop mov %o0,%l0 ... !Total regs: 3 !Total insts: 36 CS322

  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 CS322

  22. Other Expressions TEMP: 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) CS322

  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 CS322

More Related