package condense; import cs132.vapor.ast.*; import misc.*; import java.util.*; import java.util.regex.*; public class CondenseVisitor extends VInstr.Visitor{ ArrayList vaporm; ArrayList mips; StackHelper curr; public CondenseVisitor(VaporProgram vp, ArrayList vaporm) { this.vaporm = vaporm; this.mips = new ArrayList(); // preamble this.mips.add(0, ".data"); this.addMIPS(".text"); this.addMIPS("jal Main"); this.addMIPS("li $v0 10"); this.addMIPS("syscall"); for (int i = 0; i < vp.functions.length; ++i) { this.curr = new StackHelper(vp.functions[i].stack); this.addMIPS(vp.functions[i].ident+":"); // prologue this.addMIPS(" sw $fp -8($sp)"); this.addMIPS(" move $fp $sp"); this.addMIPS(String.format(" subu $sp $sp %d", this.curr.getFrameSize())); this.addMIPS(" sw $ra -4($fp)"); TreeSet f = this.sortFunction(vp.functions[i]); MinimalLogger.info(String.format("Starting loop with function:\n %s", f.toString())); for (Node n : f) { if (n instanceof VInstr) { ((VInstr) n).accept(this); } else this.addMIPS(((VCodeLabel) n).ident + ":"); } // epilogue this.addMIPS(" lw $ra -4($fp)"); this.addMIPS(" lw $fp -8($fp)"); this.addMIPS(String.format(" addu $sp $sp %d", this.curr.getFrameSize())); this.addMIPS(" jr $ra"); } this.addMIPS("_print:"); this.addMIPS(" li $v0 1 # syscall: print integer"); this.addMIPS(" syscall"); this.addMIPS(" la $a0 _newline"); this.addMIPS(" li $v0 4 # syscall: print string"); this.addMIPS(" syscall"); this.addMIPS(" jr $ra"); this.addMIPS("_error:"); this.addMIPS(" li $v0 4 # syscall: print string"); this.addMIPS(" syscall"); this.addMIPS(" li $v0 10 # syscall: exit"); this.addMIPS(" syscall"); this.addMIPS("_heapAlloc:"); this.addMIPS(" li $v0 9 # syscall: sbrk"); this.addMIPS(" syscall"); this.addMIPS(" jr $ra"); this.addMIPS(".data"); this.addMIPS(".align 0"); this.addMIPS("_newline: .asciiz \"\\n\""); this.addMIPS("_str0: .asciiz \"null pointer\\n\""); } public ArrayList getMIPS() { return this.mips; } public void addMIPS(String str) { MinimalLogger.info(String.format("Adding string:\n%s", str)); this.mips.add(str); } public TreeSet sortFunction(VFunction f) { TreeSet sort = new TreeSet((v1, v2) -> { return Integer.compare(v1.sourcePos.line, v2.sourcePos.line); }); for (VInstr s : f.body) { sort.add(s); } for (VCodeLabel l : f.labels) { sort.add(l); } return sort; } public static boolean isNumeric(String strNum) { if (strNum == null) { return false; } try { double d = Double.parseDouble(strNum); } catch (NumberFormatException nfe) { return false; } return true; } public void visit(VAssign n) throws RuntimeException { MinimalLogger.info(String.format("->%s (%s)", n.getClass().getSimpleName(), n.sourcePos.toString())); /////////////////////////////////////////////////////////////// this.addMIPS(String.format(" move $%s %s", ((VVarRef.Register) n.dest).ident, n.source.toString())); /////////////////////////////////////////////////////////////// MinimalLogger.info(String.format("<-%s (%s)", n.getClass().getSimpleName(), n.sourcePos.toString())); } public void visit(VCall n) throws RuntimeException { MinimalLogger.info(String.format("->%s (%s)", n.getClass().getSimpleName(), n.sourcePos.toString())); /////////////////////////////////////////////////////////////// this.addMIPS(String.format(" jal %s", n.addr.toString().substring(1))); /////////////////////////////////////////////////////////////// MinimalLogger.info(String.format("<-%s (%s)", n.getClass().getSimpleName(), n.sourcePos.toString())); } public void visit(VBuiltIn n) throws RuntimeException { MinimalLogger.info(String.format("->%s (%s)", n.getClass().getSimpleName(), n.sourcePos.toString())); /////////////////////////////////////////////////////////////// // treat the arguments (place all in temp registers) String[] ts = new String[] { "$a0", "$t9"}; for (int i = 0; i < n.args.length; ++i) { if (this.isNumeric(n.args[i].toString())) this.addMIPS(String.format(" li %s %s", ts[i], n.args[i].toString())); else this.addMIPS(String.format(" move %s %s", ts[i], n.args[i].toString())); } String ret = ""; String op = ((VBuiltIn.Op) n.op).name; if (op.equals("Add")) ret += " add"; else if (op.equals("Sub")) ret += " sub"; else if (op.equals("MulS")) ret += " mul"; else if (op.equals("Eq")) ret += "NULL"; // fixme else if (op.equals("Lt")) ; else if (op.equals("LtS")) ret += " slti"; else if (op.equals("PrintIntS")) ret += " jal _print"; else if (op.equals("HeapAllocZ")) ret += " jal _heapAlloc"; else if (op.equals("Error")) ret += " la $a0 _str0\n j _error"; if (n.dest != null) ret += String.format(" $%s", ((VVarRef.Register) n.dest).ident); for (int i = 0; i < n.args.length; ++i) ret += String.format(" %s", ts[i]); this.addMIPS(ret); /////////////////////////////////////////////////////////////// MinimalLogger.info(String.format("<-%s (%s)", n.getClass().getSimpleName(), n.sourcePos.toString())); } public void visit(VMemWrite n) throws RuntimeException { MinimalLogger.info(String.format("->%s (%s)", n.getClass().getSimpleName(), n.sourcePos.toString())); /////////////////////////////////////////////////////////////// this.addMIPS(String.format(" sw %s %s", n.source.toString(), this.curr.get(((VMemRef.Stack) n.dest)))); /////////////////////////////////////////////////////////////// MinimalLogger.info(String.format("<-%s (%s)", n.getClass().getSimpleName(), n.sourcePos.toString())); } public void visit(VMemRead n) throws RuntimeException { MinimalLogger.info(String.format("->%s (%s)", n.getClass().getSimpleName(), n.sourcePos.toString())); /////////////////////////////////////////////////////////////// this.addMIPS(String.format(" lw %s %s", n.dest.toString(), this.curr.get(((VMemRef.Stack) n.source)))); /////////////////////////////////////////////////////////////// MinimalLogger.info(String.format("<-%s (%s)", n.getClass().getSimpleName(), n.sourcePos.toString())); } public void visit(VBranch n) throws RuntimeException { MinimalLogger.info(String.format("->%s (%s)", n.getClass().getSimpleName(), n.sourcePos.toString())); /////////////////////////////////////////////////////////////// String ret = " "; if (n.positive) ret += "bnez "; else ret += "beqz "; ret += n.value.toString() + " :"; ret += n.target.ident; this.addMIPS(ret); /////////////////////////////////////////////////////////////// MinimalLogger.info(String.format("<-%s (%s)", n.getClass().getSimpleName(), n.sourcePos.toString())); } public void visit(VGoto n) throws RuntimeException { MinimalLogger.info(String.format("->%s (%s)", n.getClass().getSimpleName(), n.sourcePos.toString())); /////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////// MinimalLogger.info(String.format("<-%s (%s)", n.getClass().getSimpleName(), n.sourcePos.toString())); } public void visit(VReturn n) throws RuntimeException { MinimalLogger.info(String.format("->%s (%s)", n.getClass().getSimpleName(), n.sourcePos.toString())); /////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////// MinimalLogger.info(String.format("<-%s (%s)", n.getClass().getSimpleName(), n.sourcePos.toString())); } }