package IRT; import java.io.PrintWriter; /** * Print the various parts of an intermediate representation tree * (with components given by the Tree and Temp packages). *

* History *

*
Version 1.0 (11 December 1998) *
Created in support of the Tiger compiler project *
Version 1.1 (16 December 1998) *
Added support for printing the new RETURN instruction *
* * @author Samuel A. Rebelsky * @version 1.1 of 16 December 1998 */ public class Print { // +---------------------------------+------------------------- // | Printing temporaries and labels | // +---------------------------------+ /** * Print a label. * * @exception Exception * If the label is undefined. */ public static void print(PrintWriter out, Temp.Label label) throws Exception { if (label == null) throw new Exception("Undefined label"); out.print("L(" + label.toString() + ")"); } // print(PrintWriter, Temp.Label) /** * Print a list of labels. * * @exception Exception * If any of the labels is null. */ public static void print(PrintWriter out, Temp.LabelList labels) throws Exception { if (labels == null) return; print(out, labels.head); out.print(" "); print(out, labels.tail); } // print(PrintWriter, Temp.LabelList) /** * Print a temporary. Relies on the modifed Temp.toString method. * * @exception Exception * If the temporary is undefined. */ public static void print(PrintWriter out, Temp.Temp temp) throws Exception { if (temp == null) throw new Exception("Undefined temporary"); out.print(temp.toString()); } // print(PrintWriter, Temp.Temp) /** * Print a list of temporaries. * * @exception Exception * If any of the temporaries is null. */ public static void print(PrintWriter out, Temp.TempList temps) throws Exception { if (temps == null) return; print(out, temps.head); out.print(" "); print(out, temps.tail); } // print(PrintWriter, Temp.TempList) // +----------------------+------------------------------------ // | Printing expressions | // +----------------------+ /** * Print any expression. * * @exception Exception * If the expression is unprintable (see the various kinds of * expressions for more information) or if it's not one of * the standard kinds of expressions. */ public static void print(PrintWriter out, Tree.Exp exp) throws Exception { if (exp instanceof Tree.BINOP) print(out, (Tree.BINOP) exp); else if (exp instanceof Tree.BUILTIN) print(out, (Tree.BUILTIN) exp); else if (exp instanceof Tree.CALL) print(out, (Tree.CALL) exp); else if (exp instanceof Tree.CONST) print(out, (Tree.CONST) exp); else if (exp instanceof Tree.ESEQ) print(out, (Tree.ESEQ) exp); else if (exp instanceof Tree.MEM) print(out, (Tree.MEM) exp); else if (exp instanceof Tree.NAME) print(out, (Tree.NAME) exp); else if (exp instanceof Tree.TEMP) print(out, (Tree.TEMP) exp); else throw new Exception("Unknown type of expression"); } // print(PrintWriter, Tree.Exp) /** * Print a list of expressions. * * @exception Exception * If any of the parts of the list is invalid. */ public static void print(PrintWriter out, Tree.ExpList explist) throws Exception { if (explist == null) return; print(out, explist.head); print(out, explist.tail); } // print(PrintWriter, Tree.ExpList) /** * Print a binary operator. * * @exception Exception * When the operator is incorrect or one of the arguments * is invalid. */ public static void print(PrintWriter out, Tree.BINOP binop) throws Exception { // Sanity check if (binop == null) return; // Print the instruction name out.print("BINOP "); // Print the operator switch (binop.binop) { case Tree.BINOP.PLUS: out.print("PLUS "); break; case Tree.BINOP.MINUS: out.print("MINUS "); break; case Tree.BINOP.MUL: out.print("MUL "); break; case Tree.BINOP.DIV: out.print("DIV "); break; case Tree.BINOP.AND: out.print("AND "); break; case Tree.BINOP.OR: out.print("OR "); break; case Tree.BINOP.LSHIFT: out.print("LSHIFT "); break; case Tree.BINOP.RSHIFT: out.print("RSHIFT "); break; case Tree.BINOP.ARSHIFT: out.print("ARSHIFT "); break; case Tree.BINOP.XOR: out.print("XOR "); break; default: out.print("BOZO "); throw new Exception("Invalid operator"); } // switch // Print the arguments print(out, binop.left); out.print(" "); print(out, binop.right); out.println(); } // print(PrintWriter,Tree.BINOP) /** * Print a call to a builtin operator. * * @exception Exception * When one of the arguments is incorrect. */ public static void print(PrintWriter out, Tree.BUILTIN builtin) throws Exception { // Sanity check if (builtin == null) return; // Print the instruction out.print("BUILTIN "); // Print the function name print(out, builtin.func); // Print the arguments to the function print(out, builtin.args); // Print the carriage return out.println(); } // print(PrintWriter,Tree.BUILTIN) /** * Print a function call. * * @exception Exception * When one of the arguments is incorrect. */ public static void print(PrintWriter out, Tree.CALL call) throws Exception { // Sanity check if (call == null) return; // Print the instruction out.print("CALL "); // Print the function name print(out, call.func); // Print the arguments to the function print(out, call.args); // Print the carriage return out.println(); } // print(PrintWriter,Tree.CALL) /** * Print a constant. Since this should only be used as an * argument to something, it does not include a carriage return. *

* This is one of the few print methods that does * not throw an exception. */ public static void print(PrintWriter out, Tree.CONST c) { // Sanity check if (c == null) out.print(0); // Print the value else out.print(c.value); } // print(PrintWriter,Tree.CONST) /** * Print an ESEQ. Since straight line IRTs should not have * ESEQs, this should never be called. Nonetheless, it is * included for safety. * * @exception Exception * If it's ever called */ public static void print(PrintWriter out, Tree.ESEQ eseq) throws Exception { // Sanity check if (eseq == null) return; // Print the two parts print(out, eseq.stm); print(out, eseq.exp); // Report the error throw new Exception("Attempt to print an ESEQ"); } // print(out,Tree.ESEQ) /** * Print a memory reference. * * @exception Exception * When the subreference is invalid or the whole thing is null. */ public static void print(PrintWriter out, Tree.MEM mem) throws Exception { if (mem == null) { throw new Exception("Undefined MEM"); } out.print("M("); print(out, mem.exp); out.print(")"); } // print(PrintWriter, Tree.MEM) /** * Print a label used as part of an argument. * * @exception Exception * If the label is unspecified. */ public static void print(PrintWriter out, Tree.NAME name) throws Exception { if (name == null) { throw new Exception("Undefined NAME"); } print(out, name.label); } // print(PrintWriter, Tree.NAME) /** * Print a temporary. * * @exception Exception * If the temporary is unspecified. */ public static void print(PrintWriter out, Tree.TEMP temp) throws Exception { if (temp == null) { throw new Exception("Undefined TEMP"); } print(out, temp.temp); } // print(PrintWriter, Tree.TEMP) // +---------------------+------------------------------------- // | Printing statements | // +---------------------+ /** * Print a statement. This method figures out which related * method to call, depending on which type of statement it is. * * @exception Exception * If there's a problem printing the specific type of statement. */ public static void print(PrintWriter out, Tree.Stm stm) throws Exception { if (stm instanceof Tree.CJUMP) print(out, (Tree.CJUMP) stm); else if (stm instanceof Tree.EXP) print(out, (Tree.EXP) stm); else if (stm instanceof Tree.JUMP) print(out, (Tree.JUMP) stm); else if (stm instanceof Tree.LABEL) print(out, (Tree.LABEL) stm); else if (stm instanceof Tree.MOVE) print(out, (Tree.MOVE) stm); else if (stm instanceof Tree.RETURN) print(out, (Tree.RETURN) stm); else if (stm instanceof Tree.SEQ) print(out, (Tree.SEQ) stm); else if (stm instanceof Tree.STRING) print(out, (Tree.STRING) stm); else throw new Exception("Unknown type of statement"); } // print(PrintWriter, Tree.Stm) /** * Print a list of statements. * * @exception Exception * If there are problems with the individual statements. */ public static void print(PrintWriter out, Tree.StmList statements) throws Exception { // End of the list. Print the legendary END statement. if (statements == null) { out.println("END"); } else { print(out, statements.head); print(out, statements.tail); } } // print(PrintWriter, Tree.StmList) /** * Print a conditional jump. Note that the second label * for the conditional jump is not printed. * * @exception Exception * If the operator is invalid or one of the arguments is incorrect. */ public static void print(PrintWriter out, Tree.CJUMP cjump) throws Exception { // Sanity check if (cjump == null) return; // Print the instruction out.print("CJUMP "); // Print the operator switch (cjump.relop) { case Tree.CJUMP.EQ: out.print("EQ "); break; case Tree.CJUMP.NE: out.print("NE "); break; case Tree.CJUMP.LT: out.print("LT "); break; case Tree.CJUMP.GT: out.print("GT "); break; case Tree.CJUMP.LE: out.print("LE "); break; case Tree.CJUMP.GE: out.print("GE "); break; default: out.print("BOZO "); throw new Exception("Invalid operator in CJUMP"); } // switch // Print the arguments print(out, cjump.left); out.print(" "); print(out, cjump.right); out.print(" "); // Print the label and carriage return print(out, cjump.iftrue); out.println(); } // print(PrintWriter,Tree.CJUMP) /** * Print an expression instruction. * * @exception Exception * If it's an invalid type of subexpression or * there's a problem printing the subexpression. */ public static void print(PrintWriter out, Tree.EXP exp) throws Exception { // Sanity check if (exp == null) return; // Verify that it's a valid type of expression to print if ( (exp.exp instanceof Tree.CONST) || (exp.exp instanceof Tree.ESEQ) || (exp.exp instanceof Tree.MEM) || (exp.exp instanceof Tree.NAME) || (exp.exp instanceof Tree.TEMP) ) { throw new Exception("Invalid expression in this context"); } // Print the expression print(out, exp.exp); } // print(PrintWriter, Tree.EXP) /** * Print a JUMP instruction. * * @exception Exception * If one of the parts of the jump is invalid. */ public static void print(PrintWriter out, Tree.JUMP jump) throws Exception { // Sanity check if (jump == null) return; // Print the instruction out.print("JUMP "); // Print the switch part print(out, jump.exp); // Print the targets print(out, jump.targets); // Print the carriage return out.println(); } // print(PrintWriter, Tree.JUMP) /** * Print a label instruction. * * @exception Exception * If the label is unspecified. */ public static void print(PrintWriter out, Tree.LABEL label) throws Exception { if (label == null) return; out.print("LABEL "); print(out, label.label); out.println(); } // print(PrintWriter, Tree.LABEL) /** * Print a move instruction. * * @exception Exception * If there's an error in one of the arguments. */ public static void print(PrintWriter out, Tree.MOVE move) throws Exception { if (move == null) return; out.print("MOVE "); print(out, move.dst); out.print(" "); print(out, move.src); out.println(); } // print(PrintWriter, Tree.MOVE) /** * Print a sequence of instructions. This should never be called, as * all the SEQ nodes in a tree should have been removed. * * @exception Exception * If some element of the sequence is erroneous or if it's called * at all. */ public static void print(PrintWriter out, Tree.SEQ seq) throws Exception { if (seq == null) return; print(out, seq.left); print(out, seq.right); } // print(PrintWriter, Tree.SEQ) /** * Print a return-from-function instruction. *

* No exceptions! */ public static void print(PrintWriter out, Tree.RETURN ret) { out.println("RETURN"); } // print /** * Print a string declaration. *

* Nope. No exceptions. */ public static void print(PrintWriter out, Tree.STRING string) { if (string == null) return; out.println("STRING string.str"); } // print(PrintWriter, Tree.STRING) } // class Print