1 marinov 1.1 // Graph.java, created Thu Oct 15 20:22:46 1998 by marinov 2 cananian 1.2.2.6 // Copyright (C) 1998 Darko Marinov <marinov@lcs.mit.edu> 3 cananian 1.2.2.6 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 marinov 1.1 package harpoon.Util; 5 marinov 1.1 6 cananian 1.2.2.9 import harpoon.Analysis.ClassHierarchy; 7 cananian 1.2.2.5 import harpoon.ClassFile.HClass; 8 cananian 1.2.2.3 import harpoon.ClassFile.HCode; 9 cananian 1.2.2.3 import harpoon.ClassFile.HCodeEdge; 10 cananian 1.2.2.3 import harpoon.ClassFile.HCodeElement; 11 salcianu 1.2.2.13 import harpoon.ClassFile.HCodeFactory; 12 cananian 1.2.2.5 import harpoon.ClassFile.HMethod; 13 marinov 1.1 import harpoon.Analysis.DomTree; 14 marinov 1.1 import harpoon.Analysis.DomFrontier; 15 cananian 1.2.2.10 import harpoon.IR.Properties.CFGraphable; 16 salcianu 1.2.2.13 import harpoon.IR.Quads.Quad; 17 salcianu 1.2.2.13 import harpoon.IR.Quads.CALL; 18 salcianu 1.2.2.13 import harpoon.IR.Quads.HANDLER; 19 salcianu 1.2.2.13 import harpoon.IR.Quads.METHOD; 20 salcianu 1.2.2.13 import harpoon.IR.Quads.HEADER; 21 salcianu 1.2.2.13 import harpoon.IR.Quads.FOOTER; 22 salcianu 1.2.2.13 23 salcianu 1.2.2.13 24 salcianu 1.2.2.13 import harpoon.Util.LightBasicBlocks.LightBasicBlock; 25 salcianu 1.2.2.13 import harpoon.Util.LightBasicBlocks.LBBConverter; 26 salcianu 1.2.2.13 import harpoon.Util.BasicBlocks.BBConverter; 27 salcianu 1.2.2.13 28 salcianu 1.2.2.13 import harpoon.Temp.Temp; 29 salcianu 1.2.2.13 30 marinov 1.1 import java.util.Enumeration; 31 cananian 1.2.2.7 import java.util.Iterator; 32 salcianu 1.2.2.13 import java.util.Set; 33 salcianu 1.2.2.13 import java.util.HashSet; 34 salcianu 1.2.2.13 import java.util.Map; 35 salcianu 1.2.2.13 import java.util.HashMap; 36 salcianu 1.2.2.13 37 salcianu 1.2.2.13 import java.io.PrintWriter; 38 salcianu 1.2.2.13 39 salcianu 1.2.2.13 40 marinov 1.1 /** 41 marinov 1.1 * <code>Graph</code> 42 marinov 1.1 * 43 marinov 1.1 * @author Darko Marinov <marinov@lcs.mit.edu> 44 cananian 1.6 * @version $Id: Graph.java,v 1.6 2004/02/08 03:21:41 cananian Exp $ 45 marinov 1.1 */ 46 marinov 1.1 47 marinov 1.2 public abstract class Graph { 48 marinov 1.1 49 marinov 1.2 /** Print (vcg format) control from graph representing code view. Use default style. */ 50 marinov 1.2 public static final void printCFG(HCode hc, java.io.PrintWriter pw, String title) { 51 marinov 1.2 printCFG(hc,pw,title,null); 52 marinov 1.2 } 53 marinov 1.2 54 marinov 1.2 /** Print (vcg format) DomTree of code view. Use default style. */ 55 marinov 1.2 public static final void printDomTree(HCode hc, java.io.PrintWriter pw, String title) { 56 marinov 1.2 printDomTree(false,hc,pw,title,null); 57 marinov 1.2 } 58 marinov 1.2 59 marinov 1.2 /** Print (vcg format) (Post)DomTree of code view. Use default style. */ 60 marinov 1.2 public static final void printDomTree(boolean isPost, HCode hc, java.io.PrintWriter pw, String title) { 61 marinov 1.2 printDomTree(isPost,hc,pw,title,null); 62 marinov 1.2 } 63 marinov 1.2 64 marinov 1.2 /** Print (vcg format) control flow graph representing code view. */ 65 marinov 1.2 public static final void printCFG(HCode hc, java.io.PrintWriter pw, String title, String[] setup) { 66 marinov 1.2 commonHeader(hc, pw, title, setup, "CFG"); 67 cananian 1.2.2.10 // control flow graph. The HCodeElements better implement CFGraphable 68 cananian 1.5 for (Iterator e = hc.getElementsI(); e.hasNext(); ) { 69 cananian 1.5 HCodeElement hce = (HCodeElement) e.next(); 70 cananian 1.2.2.10 HCodeEdge[] next = ((CFGraphable)hce).succ(); 71 marinov 1.2 for (int j=0; j<next.length; j++) { 72 marinov 1.2 String label; 73 marinov 1.2 if (next.length==1) 74 marinov 1.2 label = null; 75 marinov 1.2 else if (next.length==2) 76 marinov 1.2 label = (j==0)?"false":"true"; 77 marinov 1.2 else 78 marinov 1.2 label = Integer.toString(j); 79 cananian 1.2.2.8 // also print which_pred of edge, for QuadSSI. 80 cananian 1.2.2.2 if (next[j] instanceof harpoon.IR.Quads.Edge && 81 cananian 1.2.2.10 ((CFGraphable)next[j].to()).pred().length > 1) 82 cananian 1.2.2.1 label = ((label==null)?"":label) + "[" + 83 cananian 1.2.2.2 ((harpoon.IR.Quads.Edge)next[j]).which_pred() + 84 cananian 1.2.2.1 "]"; 85 marinov 1.2 pw.println(edgeString(next[j].from(), next[j].to(), 86 marinov 1.2 label)); 87 marinov 1.2 } 88 marinov 1.2 } 89 marinov 1.2 commonFooter(pw); 90 marinov 1.2 } 91 marinov 1.2 92 marinov 1.2 /** Print (vcg format) of DomTree. */ 93 marinov 1.2 public static final void printDomTree(HCode hc, java.io.PrintWriter pw, String title, String[] setup) { 94 marinov 1.2 printDomTree(false,hc,pw,title,setup); 95 marinov 1.2 } 96 marinov 1.2 97 marinov 1.2 /** Print (vcg format) of (Post)DomTree. */ 98 marinov 1.2 public static final void printDomTree(boolean isPost, HCode hc, java.io.PrintWriter pw, String title, String[] setup) { 99 marinov 1.2 commonHeader(hc, pw, title, setup, "DomTree"); 100 cananian 1.2.2.12 DomTree dt = new DomTree(hc, isPost); 101 marinov 1.2 DomFrontier df = new DomFrontier(dt); 102 cananian 1.5 for (Iterator e = hc.getElementsI(); e.hasNext(); ) { 103 cananian 1.5 HCodeElement hce = (HCodeElement) e.next(); 104 cananian 1.2.2.12 HCodeElement idom = dt.idom(hce); 105 marinov 1.2 // make dominance frontier label. 106 marinov 1.2 StringBuffer sb = new StringBuffer("DF["); 107 marinov 1.2 sb.append(hce.getID()); sb.append("]={"); 108 cananian 1.2.2.12 for (Iterator it2=df.dfS(hce).iterator(); it2.hasNext(); ) { 109 cananian 1.2.2.12 sb.append(((HCodeElement)it2.next()).getID()); 110 cananian 1.2.2.12 if (it2.hasNext()) 111 marinov 1.2 sb.append(","); 112 marinov 1.2 } 113 marinov 1.2 sb.append("}"); 114 marinov 1.2 if (idom!=null) 115 marinov 1.2 pw.println(edgeString(idom, hce, 116 marinov 1.2 sb.toString())); 117 marinov 1.2 } 118 marinov 1.2 commonFooter(pw); 119 marinov 1.1 } 120 marinov 1.1 121 cananian 1.2.2.5 public static final void printClassHierarchy(java.io.PrintWriter pw, HMethod root, ClassHierarchy ch) { 122 cananian 1.2.2.5 pw.println("graph: {"); 123 cananian 1.2.2.5 pw.println(" title: \"Class Hierarchy: "+root+"\""); 124 cananian 1.2.2.5 pw.println(" x: 30"); 125 cananian 1.2.2.5 pw.println(" y: 30"); 126 cananian 1.2.2.5 pw.println(" height: 800"); 127 cananian 1.2.2.5 pw.println(" width: 500"); 128 cananian 1.2.2.5 pw.println(" stretch: 60"); 129 cananian 1.2.2.5 pw.println(" shrink: 100"); 130 cananian 1.2.2.5 pw.println(" display_edge_labels: no"); 131 cananian 1.2.2.5 pw.println(" dirty_edge_labels: no"); 132 cananian 1.2.2.5 pw.println(" near_edges: no"); 133 cananian 1.2.2.5 pw.println(" orientation: left_to_right"); 134 cananian 1.2.2.5 pw.println(" layoutalgorithm: minbackward"); 135 cananian 1.2.2.5 pw.println(" port_sharing: no"); 136 cananian 1.2.2.5 pw.println(" arrowmode: free"); 137 cananian 1.6 for (Object cO : ch.classes()) { 138 cananian 1.6 HClass c = (HClass) cO; 139 cananian 1.2.2.5 pw.print(" node: { "); 140 cananian 1.2.2.5 pw.print("title:\""+c.getName()+"\" "); 141 cananian 1.2.2.5 pw.print("label:\""+c.getName()+ "\" "); 142 cananian 1.2.2.5 pw.print("shape: box "); 143 cananian 1.2.2.5 pw.println("}"); 144 cananian 1.2.2.5 } 145 cananian 1.6 for (Object cO : ch.classes()) { 146 cananian 1.6 HClass c = (HClass) cO; 147 cananian 1.2.2.5 HClass sc= c.getSuperclass(); 148 cananian 1.2.2.5 if (sc!=null) 149 cananian 1.2.2.5 pw.println(" edge: { " + 150 cananian 1.2.2.5 "sourcename: \""+sc.getName()+"\" " + 151 cananian 1.2.2.5 "targetname: \""+ c.getName()+"\" " + 152 cananian 1.2.2.5 "}"); 153 cananian 1.2.2.5 HClass[] in=c.getInterfaces(); 154 cananian 1.2.2.5 for (int i=0; i<in.length; i++) 155 cananian 1.2.2.5 pw.println(" edge: { " + 156 cananian 1.2.2.5 "sourcename: \""+in[i].getName()+"\" " + 157 cananian 1.2.2.5 "targetname: \""+ c.getName()+"\" " + 158 cananian 1.2.2.5 "}"); 159 cananian 1.2.2.5 } 160 cananian 1.2.2.5 pw.println("}"); 161 marinov 1.1 } 162 marinov 1.1 163 marinov 1.2 /** Print common header of (vcg format) graphs for CFG and (Post)DomTree. */ 164 marinov 1.2 private static void commonHeader(HCode hc, java.io.PrintWriter pw, String title, String[] setup, String type) { 165 marinov 1.1 pw.println("graph: {"); 166 marinov 1.1 pw.println("title: \""+title+"/"+hc.getName()+"\""); 167 marinov 1.1 if (setup==null) { 168 cananian 1.2.2.11 String[] defaultSetup = { "x: 30", "y: 30", "yspace: 15", 169 marinov 1.1 "height: 800", "width: 500", 170 marinov 1.1 "stretch: 60", "shrink: 100", 171 marinov 1.1 "display_edge_labels: yes", 172 marinov 1.1 "dirty_edge_labels: yes", 173 marinov 1.1 "near_edges: no" 174 marinov 1.1 }; 175 marinov 1.1 setup = defaultSetup; 176 marinov 1.1 } 177 marinov 1.1 for (int i=0; i<setup.length; i++) 178 marinov 1.1 pw.println(setup[i]); 179 marinov 1.2 pw.println((type!="CFG") ? "layoutalgorithm: tree" : "priority_phase: yes"); 180 cananian 1.5 for (Iterator e = hc.getElementsI(); e.hasNext(); ) { 181 cananian 1.5 HCodeElement hce = (HCodeElement) e.next(); 182 marinov 1.1 String label = "#" + hce.getID() + ": " + escape(hce.toString()); 183 marinov 1.1 pw.print("node: { "); 184 marinov 1.1 pw.print("title:\""+hce.getID()+"\" "); 185 marinov 1.1 pw.print("label:\"" + label + "\" "); 186 marinov 1.1 pw.print("shape: box "); 187 marinov 1.1 pw.println("}"); 188 marinov 1.1 } 189 marinov 1.2 190 marinov 1.2 } 191 marinov 1.2 192 marinov 1.2 private static void commonFooter (java.io.PrintWriter pw) { 193 marinov 1.1 pw.println("}"); 194 marinov 1.1 } 195 marinov 1.1 196 marinov 1.1 private static String edgeString(HCodeElement from, HCodeElement to, String label) 197 marinov 1.1 { 198 marinov 1.1 return "edge: { " + 199 marinov 1.1 "sourcename: \""+from.getID()+"\" " + 200 marinov 1.1 "targetname: \""+to.getID()+"\" " + 201 marinov 1.1 ( (label==null)?"":("label: \""+label+"\" ") ) + 202 marinov 1.1 "}"; 203 marinov 1.1 } 204 marinov 1.1 205 marinov 1.1 private static String escape(String s) { 206 marinov 1.1 s = Util.escape(s); 207 marinov 1.1 return s.replace('\"', ' '); 208 salcianu 1.2.2.13 } 209 salcianu 1.2.2.13 210 salcianu 1.2.2.13 211 salcianu 1.2.2.13 212 salcianu 1.2.2.13 213 salcianu 1.2.2.13 /** Print the Control Flow Graph of the Basic Blocks composing 214 salcianu 1.2.2.13 the code of method <code>hm</code>, as constructed by the 215 salcianu 1.2.2.13 code factory <code>hcf</code>. The output is written to 216 salcianu 1.2.2.13 <code>out</code> in VCG format. */ 217 salcianu 1.2.2.13 public static void printBBCFG(HMethod hm, HCodeFactory hcf, 218 salcianu 1.2.2.13 PrintWriter out) { 219 salcianu 1.2.2.13 BBConverter bbconv = new BBConverter(hcf); 220 salcianu 1.2.2.13 LBBConverter lbbconv = new LBBConverter(bbconv); 221 salcianu 1.2.2.13 printBBCFG(hm, lbbconv, out); 222 salcianu 1.2.2.13 } 223 salcianu 1.2.2.13 224 salcianu 1.2.2.13 /** Print the Control Flow Graph of the Basic Blocks composing 225 salcianu 1.2.2.13 the code of method <code>hm</code>, as constructed by the 226 salcianu 1.2.2.13 <code>LBBConverter</code> <code>hcf</code>. 227 salcianu 1.2.2.13 The output is written to <code>out</code> in VCG format. */ 228 salcianu 1.2.2.13 public static void printBBCFG(HMethod hm, LBBConverter lbbconv, 229 salcianu 1.2.2.13 PrintWriter out) { 230 salcianu 1.2.2.13 LightBasicBlock.Factory lbbfact = lbbconv.convert2lbb(hm); 231 salcianu 1.2.2.13 232 salcianu 1.2.2.13 print_VCG_header(out, "BB_CFG for " + hm.getName()); 233 salcianu 1.2.2.13 Map map = print_VCG_nodes(out, lbbfact); 234 salcianu 1.2.2.13 print_VCG_edges(out, lbbfact, map); 235 salcianu 1.2.2.13 print_VCG_footer(out); 236 salcianu 1.2.2.13 } 237 salcianu 1.2.2.13 238 salcianu 1.2.2.13 private static void print_VCG_header(PrintWriter out, String graph_name) { 239 salcianu 1.2.2.13 out.println("graph: {"); 240 salcianu 1.2.2.13 out.println("\ttitle: \"" + graph_name + "\""); 241 salcianu 1.2.2.13 out.println("\tlayoutalgorithm: maxdepthslow"); 242 salcianu 1.2.2.13 out.println("\tdisplay_edge_labels: yes"); 243 salcianu 1.2.2.13 } 244 salcianu 1.2.2.13 245 salcianu 1.2.2.13 private static Map print_VCG_nodes 246 salcianu 1.2.2.13 (PrintWriter out, LightBasicBlock.Factory lbbfact) { 247 salcianu 1.2.2.13 out.println("\n/* (light) basic block description */"); 248 salcianu 1.2.2.13 Map map = new HashMap(); 249 salcianu 1.2.2.13 LightBasicBlock lbbs[] = lbbfact.getAllBBs(); 250 salcianu 1.2.2.13 for(int i = 0; i < lbbs.length ; i++) { 251 salcianu 1.2.2.13 String lbb_name = Integer.toString(i); 252 salcianu 1.2.2.13 map.put(lbbs[i], lbb_name); 253 salcianu 1.2.2.13 print_VCG_node(out, lbbs[i], lbb_name); 254 salcianu 1.2.2.13 } 255 salcianu 1.2.2.13 out.println(); 256 salcianu 1.2.2.13 return map; 257 salcianu 1.2.2.13 } 258 salcianu 1.2.2.13 259 salcianu 1.2.2.13 private static void print_VCG_node 260 salcianu 1.2.2.13 (PrintWriter out, LightBasicBlock lbb, String lbb_name) { 261 salcianu 1.2.2.13 out.println("node: {"); 262 salcianu 1.2.2.13 out.println("\ttitle: \"" + lbb_name + "\""); 263 salcianu 1.2.2.13 out.print("\tlabel: \""); 264 salcianu 1.2.2.13 HCodeElement quads[] = lbb.getElements(); 265 salcianu 1.2.2.13 for(int i = 0; i < quads.length; i++) 266 salcianu 1.2.2.13 out.print( ((i == 0) ? "" : "\\n") + 267 salcianu 1.2.2.13 quad2string(quads[i]) ); 268 salcianu 1.2.2.13 out.println("\""); 269 salcianu 1.2.2.13 out.println("}"); 270 salcianu 1.2.2.13 } 271 salcianu 1.2.2.13 272 salcianu 1.2.2.13 private static String quad2string(HCodeElement hce) { 273 salcianu 1.2.2.13 if(!(hce instanceof CALL)) 274 salcianu 1.2.2.14 return Util.adjust_quotes(hce.toString()); 275 salcianu 1.2.2.13 CALL call = (CALL) hce; 276 salcianu 1.2.2.13 StringBuffer buff = new StringBuffer(); 277 salcianu 1.2.2.13 if(call.retval() != null) { 278 salcianu 1.2.2.13 buff.append(call.retval()); 279 salcianu 1.2.2.13 buff.append(" = "); 280 salcianu 1.2.2.13 } 281 salcianu 1.2.2.13 if(call.isStatic()) 282 salcianu 1.2.2.13 buff.append("(static) "); 283 salcianu 1.2.2.13 buff.append("CALL "); 284 salcianu 1.2.2.13 HMethod hm = call.method(); 285 salcianu 1.2.2.13 286 salcianu 1.2.2.13 String classname = hm.getDeclaringClass().getName(); 287 salcianu 1.2.2.13 classname = classname.substring(classname.lastIndexOf(".") + 1); 288 salcianu 1.2.2.13 buff.append(classname); 289 salcianu 1.2.2.13 290 salcianu 1.2.2.13 buff.append("."); 291 salcianu 1.2.2.13 buff.append(hm.getName()); 292 salcianu 1.2.2.13 buff.append("("); 293 salcianu 1.2.2.13 Temp params[] = call.params(); 294 salcianu 1.2.2.13 for(int i = 0; i < params.length; i++) 295 salcianu 1.2.2.13 buff.append(((i == 0) ? "" : ",") + params[i]); 296 salcianu 1.2.2.13 buff.append(")"); 297 salcianu 1.2.2.14 return Util.adjust_quotes(buff.toString()); 298 salcianu 1.2.2.13 } 299 salcianu 1.2.2.13 300 salcianu 1.2.2.13 private static void print_VCG_edges 301 salcianu 1.2.2.13 (PrintWriter out, LightBasicBlock.Factory lbbfact, Map map) { 302 salcianu 1.2.2.13 out.println("\n/* control flow edges */"); 303 salcianu 1.2.2.13 304 salcianu 1.2.2.13 METHOD method = get_METHOD(lbbfact); 305 salcianu 1.2.2.13 306 salcianu 1.2.2.13 LightBasicBlock lbbs[] = lbbfact.getAllBBs(); 307 salcianu 1.2.2.13 for(int i = 0; i < lbbs.length; i++) { 308 salcianu 1.2.2.13 LightBasicBlock lbb = lbbs[i]; 309 salcianu 1.2.2.13 String sourcename = (String) map.get(lbb); 310 salcianu 1.2.2.13 311 salcianu 1.2.2.13 LightBasicBlock next[] = lbb.getNextLBBs(); 312 salcianu 1.2.2.13 for(int j = 0; j < next.length; j++) { 313 salcianu 1.2.2.13 String targetname = (String) map.get(next[j]); 314 salcianu 1.2.2.13 out.println("edge: { " + 315 salcianu 1.2.2.13 "sourcename : \"" + sourcename + "\" " + 316 salcianu 1.2.2.13 "targetname : \"" + targetname + "\" " + 317 salcianu 1.2.2.13 ((j >= lbb.getHandlerStartIndex()) ? 318 salcianu 1.4 "linestyle : dotted " : "" ) + 319 salcianu 1.2.2.13 "}"); 320 salcianu 1.2.2.13 } 321 salcianu 1.2.2.13 } 322 salcianu 1.2.2.13 } 323 salcianu 1.2.2.13 324 salcianu 1.2.2.13 private static METHOD get_METHOD(LightBasicBlock.Factory lbbfact) { 325 salcianu 1.2.2.13 LightBasicBlock root = lbbfact.getRoot(); 326 salcianu 1.2.2.13 HEADER header = (HEADER) root.getFirstElement(); 327 salcianu 1.2.2.13 return (METHOD) header.next(1); 328 salcianu 1.2.2.13 } 329 salcianu 1.2.2.13 330 salcianu 1.2.2.13 private static void print_VCG_footer(PrintWriter out) { 331 salcianu 1.2.2.13 out.println("}"); 332 marinov 1.1 } 333 marinov 1.1 334 marinov 1.1 }