package vaporize; import cs132.vapor.ast.*; import graphviz.*; import cfg.*; import misc.*; import java.io.File; import java.util.*; public class LIRVisitor extends VInstr.VisitorPR { private boolean use_graphviz = false; // if true, generates svg files of the edges in each function private Kettle kettle; private ArrayList lirs; private CFGNode curr; // the current node being processed private int curr_out_num; private String dot_format; // a list of edges to be processed by graphviz public LIRVisitor(VaporProgram vp, ArrayList vapor) { this.kettle = new Kettle(vapor); this.lirs = new ArrayList(); this.curr = null; for (VFunction f : vp.functions) { ControlFlowGraph cfg = new ControlFlowGraph(f); this.dot_format = ""; this.curr_out_num = 0; MinimalLogger.info(String.format("LIRVisitor is collecting nodes for %s", this.kettle.parseFuncName(f))); for (VCodeLabel s : f.labels) { cfg.addNode(new CFGNode(s)); } for (VInstr s : f.body) { cfg.addNode(new CFGNode(s)); } MinimalLogger.info(String.format("LIRVisitor is collecting edges for %s", this.kettle.parseFuncName(f))); // inital setup // first visit may not find edges; cfg.addEdges will handle this.curr = cfg.getNode(f.body[0]); // cascades downwards --- cfg.addEdges for (VVarRef.Local l : f.params) cfg.addDefinition(this.curr, l.ident.toString()); for (VInstr s : f.body) s.accept(cfg, this); int line = this.curr.getInstruction().sourcePos.line; int stop = f.body[0].sourcePos.line; MinimalLogger.info(String.format("Looking for liveness from final node %d to %d", line, stop)); for (int i = line; i >= stop; --i) { this.curr = cfg.getNode(new Integer(i)); for (CFGNode source : this.curr.getSources()) { for (String var : this.curr.getLiveness()) { if (!source.getDefinitions().contains(var)) { // MinimalLogger.info(String.format("%s: %s added to liveness of %s.", // this.curr, // var, // source)); source.liveness.add(var); } else { // MinimalLogger.info(String.format("%s: %s was defined in %s.", // this.curr, // var, // source)); } } } } MinimalLogger.info(String.format("Spitting out reaching/liveness...")); for (CFGNode n : cfg.getNodes()) MinimalLogger.info(String.format("%s ::: %s ::: %s ::: %s", n.toString(), n.getDefinitions(), n.getReaching(), n.getLiveness())); if (this.use_graphviz) this.createDotGraph(this.kettle.parseFuncName(f)); MinimalLogger.info(String.format("Gathering intervals for %s", this.kettle.parseFuncName(f))); LIRDict lir = new LIRDict(f, cfg, this.curr_out_num); this.lirs.add(lir); MinimalLogger.info(String.format("Found intervals: %s", lir.getIntervals().toString())); } } public ArrayList getLIRs() { return this.lirs; } protected void createDotGraph(String file_name) { MinimalLogger.info(String.format("Outputting %s to %s", this.dot_format, file_name)); GraphViz gv = new GraphViz(); gv.addln(gv.start_graph()); gv.add(this.dot_format); gv.addln(gv.end_graph()); String type = "svg"; gv.decreaseDpi(); gv.decreaseDpi(); gv.decreaseDpi(); gv.decreaseDpi(); File out = new File(file_name+"."+ type); gv.writeGraphToFile( gv.getGraph( gv.getDotSource(), type ), out ); } public String visit(ControlFlowGraph cfg, VMemRead n) throws RuntimeException { MinimalLogger.info(String.format("->%s (\"%s\":%s)", n.getClass().getSimpleName(), this.kettle.get(n).trim(), n.sourcePos.toString())); /////////////////////////////////////////////////////////////// CFGNode curr = cfg.getNode(n); cfg.addDefinition(curr, n.dest.toString()); cfg.addReference(curr, ((VMemRef.Global) n.source).base.toString()); this.dot_format += cfg.addEdge(this.curr, curr); this.curr = curr; /////////////////////////////////////////////////////////////// MinimalLogger.info(String.format("<-%s (\"%s\":%s)", n.getClass().getSimpleName(), this.kettle.get(n).trim(), n.sourcePos.toString())); return null; } public String visit(ControlFlowGraph cfg, VMemWrite n) throws RuntimeException { MinimalLogger.info(String.format("->%s (\"%s\":%s)", n.getClass().getSimpleName(), this.kettle.get(n).trim(), n.sourcePos.toString())); /////////////////////////////////////////////////////////////// CFGNode curr = cfg.getNode(n); cfg.addReference(curr, ((VMemRef.Global) n.dest).base.toString()); cfg.addReference(curr, n.source.toString()); this.dot_format += cfg.addEdge(this.curr, curr); this.curr = curr; /////////////////////////////////////////////////////////////// MinimalLogger.info(String.format("<-%s (\"%s\":%s)", n.getClass().getSimpleName(), this.kettle.get(n).trim(), n.sourcePos.toString())); return null; } public String visit(ControlFlowGraph cfg, VAssign n) throws RuntimeException { MinimalLogger.info(String.format("->%s (\"%s\":%s)", n.getClass().getSimpleName(), this.kettle.get(n).trim(), n.sourcePos.toString())); /////////////////////////////////////////////////////////////// CFGNode curr = cfg.getNode(n); cfg.addDefinition(curr, n.dest.toString()); cfg.addReference(curr, n.source.toString()); this.dot_format += cfg.addEdge(this.curr, curr); this.curr = curr; /////////////////////////////////////////////////////////////// MinimalLogger.info(String.format("<-%s (\"%s\":%s)", n.getClass().getSimpleName(), this.kettle.get(n).trim(), n.sourcePos.toString())); return null; } public String visit(ControlFlowGraph cfg, VBranch n) throws RuntimeException { MinimalLogger.info(String.format("->%s (\"%s\":%s)", n.getClass().getSimpleName(), this.kettle.get(n).trim(), n.sourcePos.toString())); /////////////////////////////////////////////////////////////// CFGNode curr = cfg.getNode(n); cfg.addReference(curr, n.value.toString()); this.dot_format += cfg.addEdge(this.curr, curr); this.dot_format += cfg.addEdge(curr, cfg.getNode(new Integer(this.kettle .findLabelIndex(n.target.toString())))); /////////////////////////////////////////////////////////////// MinimalLogger.info(String.format("<-%s (\"%s\":%s)", n.getClass().getSimpleName(), this.kettle.get(n).trim(), n.sourcePos.toString())); return null; } public String visit(ControlFlowGraph cfg, VGoto n) throws RuntimeException { MinimalLogger.info(String.format("->%s (\"%s\":%s)", n.getClass().getSimpleName(), this.kettle.get(n).trim(), n.sourcePos.toString())); /////////////////////////////////////////////////////////////// CFGNode curr = cfg.getNode(n); this.dot_format += cfg.addEdge(this.curr, curr); this.dot_format += cfg.addEdge(curr, cfg.getNode(new Integer(this.kettle .findLabelIndex(n.target.toString())))); this.curr = cfg.getNextNode(curr); /////////////////////////////////////////////////////////////// MinimalLogger.info(String.format("<-%s (\"%s\":%s)", n.getClass().getSimpleName(), this.kettle.get(n).trim(), n.sourcePos.toString())); return null; } public String visit(ControlFlowGraph cfg, VCall n) throws RuntimeException { MinimalLogger.info(String.format("->%s (\"%s\":%s)", n.getClass().getSimpleName(), this.kettle.get(n).trim(), n.sourcePos.toString())); /////////////////////////////////////////////////////////////// CFGNode curr = cfg.getNode(n); this.curr_out_num = Math.max(this.curr_out_num, n.args.length-4); if (n.dest != null) cfg.addDefinition(curr, n.dest.toString()); for (VOperand a : n.args) { cfg.addReference(curr, a.toString()); } cfg.addReference(curr, n.addr.toString()); this.dot_format += cfg.addEdge(this.curr, curr); this.curr = curr; /////////////////////////////////////////////////////////////// MinimalLogger.info(String.format("<-%s (\"%s\":%s)", n.getClass().getSimpleName(), this.kettle.get(n).trim(), n.sourcePos.toString())); return null; } public String visit(ControlFlowGraph cfg, VBuiltIn n) throws RuntimeException { MinimalLogger.info(String.format("->%s (\"%s\":%s)", n.getClass().getSimpleName(), this.kettle.get(n).trim(), n.sourcePos.toString())); /////////////////////////////////////////////////////////////// CFGNode curr = cfg.getNode(n); if (n.dest != null) cfg.addDefinition(curr, n.dest.toString()); for (VOperand a : n.args) { cfg.addReference(curr, a.toString()); } this.dot_format += cfg.addEdge(this.curr, curr); this.curr = curr; /////////////////////////////////////////////////////////////// MinimalLogger.info(String.format("<-%s (\"%s\":%s)", n.getClass().getSimpleName(), this.kettle.get(n).trim(), n.sourcePos.toString())); return null; } public String visit(ControlFlowGraph cfg, VReturn n) throws RuntimeException { MinimalLogger.info(String.format("->%s (\"%s\":%s)", n.getClass().getSimpleName(), this.kettle.get(n).trim(), n.sourcePos.toString())); /////////////////////////////////////////////////////////////// CFGNode curr = cfg.getNode(n); if (n.value != null) cfg.addReference(curr, n.value.toString()); this.dot_format += cfg.addEdge(this.curr, curr); this.curr = curr; /////////////////////////////////////////////////////////////// MinimalLogger.info(String.format("<-%s (\"%s\":%s)", n.getClass().getSimpleName(), this.kettle.get(n).trim(), n.sourcePos.toString())); return null; } }