1 cananian 1.1.2.1 // IdentifyNoHandler.java, created Wed Jul 12 18:26:16 2000 by cananian 2 cananian 1.1.2.1 // Copyright (C) 2000 C. Scott Ananian <cananian@alumni.princeton.edu> 3 cananian 1.1.2.1 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 cananian 1.1.2.1 package harpoon.Backend.PreciseC; 5 cananian 1.1.2.1 6 cananian 1.1.2.1 import harpoon.ClassFile.HCodeEdge; 7 cananian 1.1.2.1 import harpoon.IR.Properties.CFGrapher; 8 cananian 1.1.2.1 import harpoon.IR.Tree.CALL; 9 cananian 1.1.2.1 import harpoon.IR.Tree.JUMP; 10 cananian 1.1.2.1 import harpoon.IR.Tree.LABEL; 11 cananian 1.1.2.1 import harpoon.IR.Tree.MOVE; 12 cananian 1.1.2.1 import harpoon.IR.Tree.NAME; 13 cananian 1.1.2.1 import harpoon.IR.Tree.Stm; 14 cananian 1.1.2.1 import harpoon.IR.Tree.TEMP; 15 cananian 1.1.2.1 import harpoon.IR.Tree.THROW; 16 cananian 1.1.2.1 import harpoon.IR.Tree.Tree; 17 cananian 1.1.2.1 import harpoon.IR.Tree.TreeVisitor; 18 cananian 1.1.2.1 import harpoon.Temp.Temp; 19 cananian 1.5 import net.cscott.jutil.GenericMultiMap; 20 cananian 1.5 import net.cscott.jutil.MultiMap; 21 cananian 1.1.2.1 import harpoon.Util.Util; 22 cananian 1.1.2.1 import java.util.Collection; 23 cananian 1.1.2.1 import java.util.HashSet; 24 cananian 1.1.2.1 import java.util.Iterator; 25 cananian 1.1.2.1 import java.util.Set; 26 cananian 1.1.2.1 /** 27 cananian 1.1.2.1 * <code>IdentifyNoHandler</code> 28 cananian 1.1.2.1 * 29 cananian 1.1.2.1 * @author C. Scott Ananian <cananian@alumni.princeton.edu> 30 cananian 1.5 * @version $Id: IdentifyNoHandler.java,v 1.5 2004/02/08 01:57:40 cananian Exp $ 31 cananian 1.1.2.1 */ 32 cananian 1.1.2.1 public class IdentifyNoHandler { 33 cananian 1.1.2.1 private Set nohandlercalls = new HashSet(); 34 cananian 1.1.2.1 /** Creates a <code>IdentifyNoHandler</code>. */ 35 cananian 1.1.2.1 public IdentifyNoHandler(harpoon.IR.Tree.Code c) { 36 cananian 1.1.2.1 // post-order DFS. 37 cananian 1.1.2.1 CFGrapher gr = c.getGrapher(); 38 cananian 1.1.2.1 dfs((Stm)gr.getFirstElement(c),gr,new HashSet(), new Visitor(gr)); 39 cananian 1.1.2.1 // done with init. 40 cananian 1.1.2.1 } 41 cananian 1.1.2.1 public boolean requiresHandler(CALL call) { 42 cananian 1.1.2.1 return !nohandlercalls.contains(call); 43 cananian 1.1.2.1 } 44 cananian 1.1.2.1 private static void dfs(Stm stm, CFGrapher gr, Set seen, TreeVisitor v) { 45 cananian 1.3.2.1 assert !seen.contains(stm); 46 cananian 1.1.2.1 seen.add(stm); 47 cananian 1.1.2.1 for (Iterator it=gr.succC(stm).iterator(); it.hasNext(); ) { 48 cananian 1.1.2.1 Stm succ = (Stm) ((HCodeEdge)it.next()).to(); 49 cananian 1.1.2.1 if (!seen.contains(succ)) 50 cananian 1.1.2.1 dfs(succ, gr, seen, v); 51 cananian 1.1.2.1 } 52 cananian 1.1.2.1 // post-order visit. 53 cananian 1.1.2.1 stm.accept(v); 54 cananian 1.1.2.1 } 55 cananian 1.1.2.1 56 cananian 1.1.2.1 /* this is like a simple reaching-def analysis, except we want to 57 cananian 1.1.2.1 * make sure that the exception isn't tested-and-branched-on before 58 cananian 1.1.2.1 * it is thrown. */ 59 cananian 1.1.2.1 private class Visitor extends TreeVisitor { 60 cananian 1.1.2.1 final CFGrapher gr; 61 cananian 1.1.2.1 final MultiMap directlyThrows = new GenericMultiMap(); 62 cananian 1.1.2.1 Visitor(CFGrapher gr) { this.gr = gr; } 63 cananian 1.1.2.1 public void visit(Tree t) { 64 cananian 1.3.2.1 assert false : "should only visit stms"; 65 cananian 1.1.2.1 } 66 cananian 1.1.2.1 public void visit(Stm t) { // only propagate if t is a no-op. 67 cananian 1.1.2.1 if (Stm.isNop(t)) propagate(t); 68 cananian 1.1.2.1 } 69 cananian 1.1.2.1 public void visit(THROW t) { 70 cananian 1.1.2.1 if (t.getRetex() instanceof TEMP) 71 cananian 1.1.2.1 directlyThrows.put(t, ((TEMP)t.getRetex()).temp); 72 cananian 1.1.2.1 } 73 cananian 1.1.2.1 public void visit(MOVE t) { 74 cananian 1.1.2.1 propagate(t); 75 cananian 1.1.2.1 if (t.getDst() instanceof TEMP) { 76 cananian 1.1.2.1 Temp dst = ((TEMP)t.getDst()).temp; 77 cananian 1.1.2.1 if (directlyThrows.contains(t, dst)) { // kill 78 cananian 1.1.2.1 directlyThrows.remove(t, dst); 79 cananian 1.1.2.1 if (t.getSrc() instanceof TEMP) // gen 80 cananian 1.1.2.1 directlyThrows.add(t, ((TEMP)t.getSrc()).temp); 81 cananian 1.1.2.1 } 82 cananian 1.1.2.1 } 83 cananian 1.1.2.1 } 84 cananian 1.1.2.1 public void visit(CALL t) { 85 cananian 1.1.2.1 for (Iterator it=gr.succC(t).iterator(); it.hasNext(); ) { 86 cananian 1.1.2.1 Stm stm = (Stm) ((HCodeEdge)it.next()).to(); 87 cananian 1.1.2.1 if (!(stm instanceof LABEL)) continue; 88 cananian 1.1.2.1 if (!t.getHandler().label.equals(((LABEL)stm).label)) continue; 89 cananian 1.1.2.1 // oh boy, this is the exception edge! 90 cananian 1.1.2.1 Set thrown = (Set) directlyThrows.getValues(stm); 91 cananian 1.1.2.1 if (thrown.contains(t.getRetex().temp)) 92 cananian 1.1.2.1 // and we directly throw the retex! 93 cananian 1.1.2.1 nohandlercalls.add(t); // this is a no-handler call! 94 cananian 1.1.2.1 } 95 cananian 1.1.2.1 } 96 cananian 1.1.2.1 // unconditional JUMP has no effect on thrown set 97 cananian 1.1.2.1 public void visit(JUMP t) { 98 cananian 1.1.2.1 if (t.getExp() instanceof NAME) propagate(t); 99 cananian 1.1.2.1 } 100 cananian 1.1.2.1 // LABEL has no effect on thrown set 101 cananian 1.1.2.1 public void visit(LABEL t) { propagate(t); } 102 cananian 1.1.2.1 103 cananian 1.1.2.1 // in set == out set. 104 cananian 1.1.2.1 private void propagate(Tree t) { 105 cananian 1.1.2.1 Collection c = gr.succC(t); 106 cananian 1.3.2.1 assert c.size()==1; 107 cananian 1.1.2.1 Stm next = (Stm) ((HCodeEdge)c.iterator().next()).to(); 108 cananian 1.1.2.1 // note that thrown set is already defined because we're 109 cananian 1.1.2.1 // doing this is dfs post-order. 110 cananian 1.1.2.1 Set thrown = (Set) directlyThrows.getValues(next); 111 cananian 1.1.2.1 directlyThrows.addAll(t, thrown); 112 cananian 1.1.2.1 } 113 cananian 1.1.2.1 } 114 cananian 1.2 }