CS 536 - Spring 2008Part IICS 536 — Spring 2008CSX Code Generation RoutinesPart II I/O StatementsAll CSX I/O is done by calling members of the class CSXLib. To read an integer we call readInt(); to read a character we call readChar(). To write an integer we call printInt(int); to write a boolean we call printBool(boolean); to write a character we call printChar(char); to write a string we call printString(String); to write a character array we call printCharArray(char[]).We start with read statements. A read is translated like an assignment, where the source of the assignment is produced by a call to readInt or readChar. void genCall(String methodDescriptor){ // Generate a static method call: // invokestatic methodDescriptor } cg(){ // for readNode // Compute address associated with target variable computeAdr(targetVar); // Call library routine to do the read if (targetVar.varName.idinfo.type.val == Types.Integer) genCall("CSXLib/readInt()I"); else // targetVar.varName.idinfo.type.val==Types.Character genCall("CSXLib/readChar()C"); storeName(targetVar); moreReads.cg(); }For write statements, we’ll first evaluate an operand, placing an integer, character, boolean or string value, or character array reference, on the stack. Then we’ll call the appropriate library routine, based on the type of the operand. We’ll update the code generation routine for nameNodes to include array values.String arrayTypeCode(Types type){ // Return array type code switch(type.val){ case Types.Integer: return "[I"; case Types.Character: return "[C"; case Types.Boolean: return "[Z"; }}2 of 10void loadGlobalReference(String name, String typeCode){ // Generate a load of a reference to the stack from // a static field: // getstatic CLASS/name typeCode } void loadLocalReference(int index){ // Generate a load of a reference to the stack from // a local variable: // aload index } cg(){ // for nameNode (revised) if (subscriptVal.isNull()) { // Simple (unsubscripted) identifier if (varName.idinfo.kind.val == Kinds.Var || varName.idinfo.kind.val == Kinds.Value || varName.idinfo.kind.val == Kinds.ScalarParm) { // id is a scalar variable, parameter or const if (varName.idinfo.adr == global){// id is a global label = varName.idinfo.label; loadGlobalInt(label); } else { // (varName.idinfo.adr == local) varIndex = varName.idinfo.varIndex; loadLocalInt(varIndex); } } else { // varName is an array var or array parm if (varName.idinfo.adr == global){ label = varName.idinfo.label; loadGlobalReference(label, arrayTypeCode(varName.idinfo.type)); } else { // (varName.idinfo.adr == local) varIndex = varName.idinfo.varIndex; loadLocalReference(varIndex); } } adr = stack; } else // Handle subscripted variables later }cg(){ // for strLitNode // generate: // ldc strval }3 of 10cg(){ // for writeNode outputValue.cg(); if (outputValue.kind.val == Kinds.Array || outputValue.kind.val == Kinds.ArrayParm) genCall("CSXLib/printCharArray([C)V"); else switch(outputValue.type.val){ case Types.Integer: genCall("CSXLib/printInt(I)V"); break; case Types.Boolean: genCall("CSXLib/printBool(Z)V"); break; case Types.Character: genCall("CSXLib/printChar(C)V"); break; case Types.String: genCall("CSXLib/printString(Ljava/lang/String;)V"); break; } moreWrites.cg(); }While Loops The JVM code we will generate will be of the form: L1: {Evaluate control expr onto stack} ifeq L2 ; branch to L2 if top of stack == 0 (false) {Code for loop body} goto L1 L2:We will assume that the SymbolInfo node contains two String valued fields, topLabel and bottomLabel. These will be used for identifiers that label while loops. The code needed to translate a whileLoopNode is: static int labelCnt = 1;String genLab(){ return "L"+labelCnt++; }void defineLab(String label){ // Generate: // label: } void branchZ(String label){ // Generate branch to label if stack top contains 0: // ifeq label }4 of 10void branch(String label) { // Generate nconditional branch to label: // goto label } cg(){ // for whileLoopNode String top = genLab(); String bottom = genLab(); if (! label.isNull()){ label.idinfo.topLabel = top; label.idinfo.bottomLabel = bottom;} defineLab(top); condition.cg(); branchZ(bottom); loopBody.cg(); branch(top); defineLab(bottom); }Break and Continue Statements Break and continue statements will use the bottom-of-loop and top-of-loop labels stored in the SymbolInfo nodes associated with labels. The JVM code we will generate is: cg(){ // for breakNode branch(label.idinfo.bottomLabel); } cg(){ // for continueNode branch(label.idinfo.topLabel); } Conditional Statements The JVM code we will generate will be of the form: {Evaluate control expr onto stack top} ifeq L1 {Code for then part} goto L2 L1: {Code for else part} L2: The code to translate an ifThenNode is:5 of 10cg(){ // for ifThenNode condition.cg(); String elseLab = genLab(); branchZ(elseLab); thenPart.cg(); String endLab = genLab(); branch(endLab); defineLab(elseLab); elsePart.cg(); defineLab(endLab); }Type Casts and Relational Operators The JVM does not include operations that directly implement relational operators (==, !=, etc.). Rather they must be synthesized using conditional branches. String relationCode(int tokenCode){ // Determine relation code of an operator based on its tokenCode: switch(tokenCode){ case sym.EQ: return "eq"; case sym.NOTEQ: return "ne"; case sym.LT: return "lt"; case sym.LEQ: return "le"; case sym.GT: return "gt"; case sym.GEQ: return "ge"; default: return ""; } }void branchRelationalCompare(int tokenCode, String label){ // Generate a conditional branch to label based on tokenCode: // Generate: // "if_icmp"+relationCode(tokenCode) label }void genRelationalOp(int operatorCode){ // Generate code to evaluate a relational operator String trueLab = genLab();
View Full Document