Classnotes, April 28, Brian Knoch knoch@cs.wisc.edu Read 11.1-11.2,12.1-12.2 Basically, the entire lecture was on the codegen project, finishing up the first handout and starting the second. CSX Constructs Literals Scalar var/const local Name varIndex <-this is the i'th local / \ variable ID (index) To access Globals Label - assignment with field. getstatic class/label I <-always 32 bit integers vars Expressions evaluate operands, generate OPCODE for operator cg() for binaryOpNode is on pg.4 of handout 1 binOp(String op) (pg2) generates the opcode message, selectOpCode(int tokenCode) (pg3) generates the string for binOp Question asked about where to declare functions for the assignment: Answer: Add functions to ASTNode instead of descendant nodes, as it is easier. NOTE: Code is not quite compilable. Variables may need to be added, etc. cg() for asgNode i.e. var = expr; cg() { computeAdr(target); <-figure out address of target, not value source->cg(); storeName(target); <-store at address of target } ex. a = b + 1; assume a= local, varIndex = 0 b = global, label = b$ add $ to b to prevent confusion with jasmin commands asgNode / \ Name + / \ / \ a Name 1 / \ b Q: Led to the idea that you cannot put computeAdr() into storeName() due to future array operations. asgNode computeAdr(a) / \ // a is local, so addr is 0 a + getstatic C/b$ I ldc 1 iadd istore 0 <- addr of a Global declarations (var & const) ex. class C { int I = 1; char C = 'x'; int J = 2*I+1; const K = 17; METHODS } -must separate declaration & initialization into 2 parts: declField() generates field declarations and trivial initializations cg() will do non-trivial initializations The code for declField() is in handout 1, pp 6-7. ex. for varDeclNode varLabel = ID + "$"; // add a $ to end of identifier .field public static varLabel I = INITVALUE (jasmin code) or array: .field public static A$ [C //[C means an array of chars if non-trivial, cg() generates code for initialization ex: class C { int I = 1; int J = I + 1; } declField() generates: .field public static I$ I = 1 .field public static J$ I cg() for varDeclNode(p.7) getstatic C/I$ I // evaluates the binary op I + 1 ldc 1 iadd putstatic C/J$ I // stores it in J Handout #2 Start I/O -call subroutines from CSXLib -int readInt() -char readChar() -printInt(int) -printBool(boolean) -printChar(char) -printString(String) -printCharArray(char[]) readNode cg() calls genCall (handout 2 pg 1) basically puts "invokestatic" before the passed string cg() // for readNode { computeAddr(targetVar); genCall either: "CSXLib/readInt()I" "CSXLib/readChar()C" storeName(targetVar); moreReads->cg(); } As before, arrayTypeCodes(Types type) pg. 1 is used for arrays. Arrays use loadGlobalReference(...) and loadLocalReference(...) p.2 to compute addresses. The new nameNode, on pg 2 handout 2, now handles unsubscripted arrays using the 3 functions just described. printNode Similar to readNode, except nothing is stored. For each printNode, the appropriate CSXLib function is called using genCall while loops p.3 Use labels to branch to labels are L#, where ther # starts at 0 and is incremented at each new label String genLab() p.3 creates a label name void defineLab(String label) p.3 puts a label into the .j file "label:" void branchZ(String label) goes to label if the top of the stack contains 0 while loops look like the following: L1: {Evaluate control expr onto stack} ifeq L2 {Code for loop body} goto L1 L2: void branch(String label) p.4 generates "goto label" cg() { // for whileLoopNode String top = genLab(); //generate labels String bottom = genLab(); if (! label.isNull()) { label.idinfo.topLabel = top; //save top & bottom in label's label.idinfo.bottomLabel = bottom;} // symbol tab entry defineLab(top); //put code down "L1:" condition.cg(); //eval condition branchZ(bottom); //if stack is zero, goto L2 loopBody.cg(); //{body of loop} branch(top); // "goto L1" defineLab(bottom); //put code down "L2:" break and continue Statements p.4 handout 2 // self-explanatory conditional statements p.4-5 handout 2 // Uses labels and evals like a while loop Type Casts and Relational Operators String relationCode(int tokenCode) p.5 gives back the string of the suffix of the relational code NOTE: there are two le, one should be ge, with GEQ in the case part. void branchRelationalCompare(int tokenCode,String label) p.5 uses relationCode to find the right suffic Jasmin uses "if_icmp" + relationCode(tokenCode) label to branch to label void genRelationalOp(int operatorCode) p.5 generates code to evaluate a relational operator cg() for binaryOpNode pg.6/handout 2 was updated, to handle binaryOps and relationalOps For a castNode, we need to generate code for only two cases. If an int or char value is cast into a bool, we must generate code to test if the value is not equal to zero. If an int is cast into a char, we must extract the rightmost 7 bits of the integer value. In all other cases, the value of the operand may be used without modification. p.6