1 cananian 1.1.2.1 // SCC.java, created Fri Sep 18 17:45:07 1998 by cananian 2 cananian 1.1.2.1 // Copyright (C) 1998 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.Analysis.Quads.SCC; 5 cananian 1.1.2.1 6 cananian 1.1.2.1 import harpoon.Analysis.Maps.ConstMap; 7 cananian 1.1.2.11 import harpoon.Analysis.Maps.ExactTypeMap; 8 cananian 1.1.2.1 import harpoon.Analysis.Maps.ExecMap; 9 cananian 1.1.2.1 import harpoon.Analysis.Maps.TypeMap; 10 cananian 1.1.2.1 import harpoon.Analysis.Maps.UseDefMap; 11 cananian 1.1.2.8 import harpoon.ClassFile.HClass; 12 cananian 1.1.2.8 import harpoon.ClassFile.HCode; 13 cananian 1.1.2.8 import harpoon.ClassFile.HCodeEdge; 14 cananian 1.1.2.8 import harpoon.ClassFile.HCodeElement; 15 cananian 1.1.2.8 import harpoon.ClassFile.HField; 16 cananian 1.1.2.8 import harpoon.ClassFile.HMethod; 17 cananian 1.1.2.8 import harpoon.ClassFile.Linker; 18 cananian 1.1.2.8 import harpoon.IR.Quads.AGET; 19 cananian 1.1.2.8 import harpoon.IR.Quads.ALENGTH; 20 cananian 1.1.2.8 import harpoon.IR.Quads.ANEW; 21 cananian 1.1.2.8 import harpoon.IR.Quads.ASET; 22 cananian 1.1.2.8 import harpoon.IR.Quads.CALL; 23 cananian 1.1.2.8 import harpoon.IR.Quads.CJMP; 24 cananian 1.1.2.8 import harpoon.IR.Quads.COMPONENTOF; 25 cananian 1.1.2.8 import harpoon.IR.Quads.CONST; 26 cananian 1.1.2.8 import harpoon.IR.Quads.Edge; 27 cananian 1.1.2.8 import harpoon.IR.Quads.FOOTER; 28 cananian 1.1.2.8 import harpoon.IR.Quads.GET; 29 cananian 1.1.2.8 import harpoon.IR.Quads.HEADER; 30 cananian 1.1.2.8 import harpoon.IR.Quads.INSTANCEOF; 31 cananian 1.1.2.8 import harpoon.IR.Quads.METHOD; 32 cananian 1.1.2.8 import harpoon.IR.Quads.MONITORENTER; 33 cananian 1.1.2.8 import harpoon.IR.Quads.MONITOREXIT; 34 cananian 1.1.2.8 import harpoon.IR.Quads.MOVE; 35 cananian 1.1.2.8 import harpoon.IR.Quads.NEW; 36 cananian 1.1.2.8 import harpoon.IR.Quads.NOP; 37 cananian 1.1.2.8 import harpoon.IR.Quads.OPER; 38 cananian 1.1.2.8 import harpoon.IR.Quads.OperVisitor; 39 cananian 1.1.2.8 import harpoon.IR.Quads.PHI; 40 cananian 1.1.2.8 import harpoon.IR.Quads.Qop; 41 cananian 1.1.2.8 import harpoon.IR.Quads.Quad; 42 cananian 1.1.2.8 import harpoon.IR.Quads.QuadSSI; 43 cananian 1.1.2.8 import harpoon.IR.Quads.QuadVisitor; 44 cananian 1.1.2.8 import harpoon.IR.Quads.RETURN; 45 cananian 1.1.2.8 import harpoon.IR.Quads.SET; 46 cananian 1.1.2.16 import harpoon.IR.Quads.SIGMA; 47 cananian 1.1.2.8 import harpoon.IR.Quads.SWITCH; 48 cananian 1.1.2.8 import harpoon.IR.Quads.THROW; 49 cananian 1.1.2.10 import harpoon.IR.Quads.TYPESWITCH; 50 cananian 1.1.2.1 import harpoon.Temp.Temp; 51 cananian 1.1.2.16 import harpoon.Temp.TempMap; 52 cananian 1.3.2.2 import harpoon.Util.ArrayIterator; 53 cananian 1.1.2.1 import harpoon.Util.HClassUtil; 54 cananian 1.1.2.1 import harpoon.Util.Worklist; 55 cananian 1.1.2.27 import harpoon.Util.Collections.WorkSet; 56 cananian 1.1.2.1 57 cananian 1.1.2.21 import java.util.Arrays; 58 cananian 1.1.2.1 import java.util.Enumeration; 59 cananian 1.1.2.9 import java.util.HashMap; 60 cananian 1.1.2.9 import java.util.HashSet; 61 cananian 1.3.2.2 import java.util.Iterator; 62 cananian 1.1.2.9 import java.util.Map; 63 cananian 1.1.2.9 import java.util.Set; 64 cananian 1.7 65 cananian 1.7 import net.cscott.jutil.Util; 66 cananian 1.1.2.1 /** 67 cananian 1.1.2.1 * <code>SCCAnalysis</code> implements Sparse Conditional Constant Propagation, 68 cananian 1.1.2.1 * with extensions to allow type and bitwidth analysis. Fun, fun, fun. 69 cananian 1.1.2.6 * <p>Only works with quads in SSI form. 70 cananian 1.1.2.1 * 71 cananian 1.1.2.1 * @author C. Scott Ananian <cananian@alumni.princeton.edu> 72 cananian 1.7 * @version $Id: SCCAnalysis.java,v 1.7 2004/02/08 01:53:44 cananian Exp $ 73 cananian 1.1.2.1 */ 74 cananian 1.1.2.1 75 cananian 1.1.2.11 public class SCCAnalysis implements ExactTypeMap, ConstMap, ExecMap { 76 cananian 1.1.2.21 private final static boolean DEBUG=false; 77 cananian 1.1.2.7 final Linker linker; 78 cananian 1.1.2.1 UseDefMap udm; 79 cananian 1.1.2.1 80 cananian 1.1.2.1 /** Creates a <code>SCC</code>. */ 81 cananian 1.1.2.1 public SCCAnalysis(HCode hc, UseDefMap usedef) { 82 cananian 1.3.2.1 assert hc.getName().equals(QuadSSI.codename); 83 cananian 1.1.2.7 this.linker = hc.getMethod().getDeclaringClass().getLinker(); 84 cananian 1.1.2.1 this.udm = usedef; 85 cananian 1.1.2.1 analyze(hc); 86 cananian 1.1.2.21 // DEBUG: 87 cananian 1.1.2.21 if (DEBUG) hc.print(new java.io.PrintWriter(System.out), 88 cananian 1.1.2.21 new HCode.PrintCallback() { 89 cananian 1.1.2.21 public void printAfter(java.io.PrintWriter pw, HCodeElement hce) { 90 cananian 1.1.2.21 Quad q = (Quad) hce; 91 cananian 1.1.2.21 HashMap hm = new HashMap(V); 92 cananian 1.1.2.21 HashSet temps = new HashSet(Arrays.asList(q.use())); 93 cananian 1.1.2.21 temps.addAll(Arrays.asList(q.def())); 94 cananian 1.1.2.21 hm.keySet().retainAll(temps); 95 cananian 1.1.2.21 pw.println(hm); 96 cananian 1.1.2.21 } 97 cananian 1.1.2.21 }); 98 cananian 1.1.2.1 } 99 cananian 1.1.2.1 /** Creates a <code>SCC</code>, and uses <code>UseDef</code> for the 100 cananian 1.1.2.1 * <code>UseDefMap</code>. */ 101 cananian 1.1.2.1 public SCCAnalysis(HCode hc) { 102 cananian 1.1.2.1 this(hc, new harpoon.Analysis.UseDef()); 103 cananian 1.1.2.1 } 104 cananian 1.1.2.1 105 cananian 1.1.2.1 /*-----------------------------*/ 106 cananian 1.1.2.1 // Class state. 107 cananian 1.1.2.1 /** Set of all executable edges. */ 108 cananian 1.1.2.1 Set Ee = new HashSet(); 109 cananian 1.1.2.1 /** Set of all executable quads. */ 110 cananian 1.1.2.1 Set Eq = new HashSet(); 111 cananian 1.1.2.1 /** Mapping from <code>Temp</code>s to lattice values. */ 112 cananian 1.1.2.9 Map V = new HashMap(); 113 cananian 1.1.2.1 114 cananian 1.1.2.1 /*---------------------------*/ 115 cananian 1.1.2.1 // public information accessor methods. 116 cananian 1.1.2.1 117 cananian 1.1.2.1 /** Determine whether <code>Quad</code> <code>q</code> 118 cananian 1.1.2.1 * is executable. */ 119 cananian 1.1.2.1 public boolean execMap(HCodeElement quad) { 120 cananian 1.1.2.1 // ignore hc 121 cananian 1.1.2.1 return Eq.contains(quad); 122 cananian 1.1.2.1 } 123 cananian 1.1.2.1 /** Determine whether <code>Edge</code> <code>e</code> 124 cananian 1.1.2.1 * is executable. */ 125 cananian 1.1.2.1 public boolean execMap(HCodeEdge edge) { 126 cananian 1.1.2.1 // ignore hc 127 cananian 1.1.2.1 return Ee.contains(edge); 128 cananian 1.1.2.1 } 129 cananian 1.1.2.1 /** Determine the static type of <code>Temp</code> <code>t</code> in 130 cananian 1.1.2.1 * <code>HMethod</code> <code>m</code>. */ 131 cananian 1.1.2.1 public HClass typeMap(HCodeElement hce, Temp t) { 132 cananian 1.1.2.1 // ignore hce 133 cananian 1.1.2.1 LatticeVal v = (LatticeVal) V.get(t); 134 cananian 1.1.2.1 if (v instanceof xClass) return ((xClass)v).type(); 135 cananian 1.1.2.1 return null; 136 cananian 1.1.2.1 } 137 cananian 1.1.2.11 /** Determine whether the static type of <code>Temp</code> <code>t</code> 138 cananian 1.1.2.11 * defined at <code>hce</code> is exact (or whether the runtime type 139 cananian 1.1.2.11 * could be a subclass of the static type). */ 140 cananian 1.1.2.11 public boolean isExactType(HCodeElement hce, Temp t) { 141 cananian 1.1.2.11 // ignore hce 142 cananian 1.1.2.11 return V.get(t) instanceof xClassExact; 143 cananian 1.1.2.11 } 144 cananian 1.1.2.16 /** Determine whether the given <code>Temp</code> can possibly be 145 cananian 1.1.2.16 * <code>null</code>. */ 146 cananian 1.1.2.16 public boolean isPossiblyNull(HCodeElement hce, Temp t) { 147 cananian 1.1.2.16 return !(V.get(t) instanceof xClassNonNull); 148 cananian 1.1.2.16 } 149 cananian 1.1.2.1 /** Determine whether <code>Temp</code> <code>t</code> 150 cananian 1.1.2.1 * has a constant value. */ 151 cananian 1.1.2.1 public boolean isConst(HCodeElement hce, Temp t) { 152 cananian 1.1.2.1 // ignore hce -- this is SSA form 153 cananian 1.1.2.1 return (V.get(t) instanceof xConstant); 154 cananian 1.1.2.1 } 155 cananian 1.1.2.1 /** Determine the constant value of <code>Temp</code> <code>t</code>. 156 cananian 1.1.2.1 * @exception Error if <code>Temp</code> <code>t</code> is not a constant. 157 cananian 1.1.2.1 */ 158 cananian 1.1.2.1 public Object constMap(HCodeElement hce, Temp t) { 159 cananian 1.1.2.1 // ignore hce -- this is SSA form. 160 cananian 1.1.2.1 LatticeVal v = (LatticeVal) V.get(t); 161 cananian 1.1.2.1 if (v instanceof xConstant) return ((xConstant)v).constValue(); 162 cananian 1.1.2.1 throw new Error(t.toString() + " not a constant"); 163 cananian 1.1.2.1 } 164 cananian 1.1.2.1 165 cananian 1.1.2.1 /** Determine the positive bit width of <code>Temp</code> <code>t</code>. 166 cananian 1.1.2.1 */ 167 cananian 1.1.2.1 public int plusWidthMap(HCodeElement hce, Temp t) { 168 cananian 1.1.2.1 // ignore hce -- this is SSA form 169 cananian 1.1.2.1 LatticeVal v = (LatticeVal) V.get(t); 170 cananian 1.1.2.1 if (v==null) throw new Error("Unknown "+t); 171 cananian 1.1.2.1 xBitWidth bw = extractWidth(v); 172 cananian 1.1.2.1 return bw.plusWidth(); 173 cananian 1.1.2.1 } 174 cananian 1.1.2.1 /** Determine the negative bit width of <code>Temp</code> <code>t</code>. 175 cananian 1.1.2.1 */ 176 cananian 1.1.2.1 public int minusWidthMap(HCodeElement hce, Temp t) { 177 cananian 1.1.2.1 // ignore hce -- this is SSA form. 178 cananian 1.1.2.1 LatticeVal v = (LatticeVal) V.get(t); 179 cananian 1.1.2.1 if (v==null) throw new Error("Unknown "+t); 180 cananian 1.1.2.1 xBitWidth bw = extractWidth(v); 181 cananian 1.1.2.1 return bw.minusWidth(); 182 cananian 1.1.2.1 } 183 cananian 1.1.2.1 184 cananian 1.1.2.1 /*---------------------------*/ 185 cananian 1.1.2.1 // Analysis code. 186 cananian 1.1.2.1 187 cananian 1.1.2.1 /** Main analysis method. */ 188 cananian 1.1.2.1 private void analyze(HCode hc) { 189 cananian 1.1.2.1 // Initialize worklists. 190 cananian 1.1.2.9 Worklist Wv = new WorkSet(); // variable worklist. 191 cananian 1.1.2.9 Worklist Wq = new WorkSet(); // block worklist. 192 cananian 1.1.2.1 193 cananian 1.1.2.1 // Make instance of visitor class. 194 cananian 1.1.2.1 SCCVisitor visitor = new SCCVisitor(hc, Wv, Wq); 195 cananian 1.1.2.1 196 cananian 1.1.2.1 // put the root entry on the worklist and mark it executable. 197 cananian 1.1.2.1 HCodeElement root = hc.getRootElement(); 198 cananian 1.3.2.1 assert root instanceof Quad : "SCC analysis works only on QuadSSI form."; 199 cananian 1.1.2.1 Wq.push(root); 200 cananian 1.1.2.9 Eq.add(root); 201 cananian 1.1.2.1 202 cananian 1.1.2.1 // Iterate. 203 cananian 1.1.2.1 while (! (Wq.isEmpty() && Wv.isEmpty()) ) { // until both are empty. 204 cananian 1.1.2.1 205 cananian 1.1.2.1 if (!Wq.isEmpty()) { // grab statement from We if we can. 206 cananian 1.1.2.1 Quad q = (Quad) Wq.pull(); 207 cananian 1.1.2.1 // Rule 2: for any executable block with 208 cananian 1.1.2.1 // only one successor C, set edge leading to C executable. 209 cananian 1.1.2.1 if (q.next().length==1) { 210 cananian 1.1.2.1 raiseE(Ee, Eq, Wq, q.nextEdge(0)); 211 cananian 1.1.2.1 } 212 cananian 1.1.2.1 // check conditions 3-8 for q. 213 cananian 1.1.2.2 q.accept(visitor); 214 cananian 1.1.2.1 } 215 cananian 1.1.2.1 216 cananian 1.1.2.1 if (!Wv.isEmpty()) { // grab temp from Wv is possible. 217 cananian 1.1.2.1 Temp t = (Temp) Wv.pull(); 218 cananian 1.1.2.1 // for every use of t... 219 cananian 1.3.2.2 for (Iterator it=new ArrayIterator(udm.useMap(hc, t)); 220 cananian 1.3.2.2 it.hasNext(); ) 221 cananian 1.1.2.1 // check conditions 3-8 222 cananian 1.3.2.2 ((Quad) it.next()).accept(visitor); 223 cananian 1.1.2.1 } 224 cananian 1.1.2.1 } // end while loop. 225 cananian 1.1.2.1 } // end analysis. 226 cananian 1.1.2.1 227 cananian 1.1.2.1 /*----------------------------------------*/ 228 cananian 1.1.2.1 // raising values in the lattice: 229 cananian 1.1.2.1 230 cananian 1.1.2.1 /** Raise edge e in Ee/Eq, adding target q to Wq if necessary. */ 231 cananian 1.1.2.1 void raiseE(Set Ee, Set Eq, Worklist Wq, Edge e) { 232 cananian 1.1.2.1 Quad q = (Quad) e.to(); 233 cananian 1.1.2.28 if (Ee.add(e)) { 234 cananian 1.1.2.28 // if making this edge executable for the first time, verify 235 cananian 1.1.2.28 // that destination 'q' is marked executable, and add q to the 236 cananian 1.1.2.28 // work list to be looked at (may be a PHI, needs to be re-eval). 237 cananian 1.1.2.28 // NOTE that this works even if: quad's already been added 238 cananian 1.1.2.28 // to Eq (this may happen for PHIs) and even if this edge leads 239 cananian 1.1.2.28 // to itself (infinite loop in the program). 240 cananian 1.1.2.28 Eq.add(q); 241 cananian 1.1.2.28 Wq.push(q); 242 cananian 1.1.2.28 } 243 cananian 1.1.2.1 } 244 cananian 1.1.2.1 /** Raise element t to a in V, adding t to Wv if necessary. */ 245 cananian 1.1.2.9 void raiseV(Map V, Worklist Wv, Temp t, LatticeVal a) { 246 cananian 1.1.2.1 LatticeVal old = (LatticeVal) V.get(t); 247 cananian 1.1.2.1 if (corruptor!=null) a=corruptor.corrupt(a); // support incrementalism 248 cananian 1.1.2.1 // only allow raising value in lattice. 249 cananian 1.1.2.21 if (old != null) { 250 cananian 1.1.2.21 a = a.merge(old); 251 cananian 1.1.2.21 if (old.equals(a) && a.equals(old)) return; // same old same old 252 cananian 1.1.2.21 } 253 cananian 1.1.2.1 V.put(t, a); 254 cananian 1.1.2.1 Wv.push(t); 255 cananian 1.1.2.1 } 256 cananian 1.1.2.1 /*------------------------------------------------------------*/ 257 cananian 1.1.2.1 // VISITOR CLASS (the real guts of the routine) 258 cananian 1.1.2.1 class SCCVisitor extends QuadVisitor { 259 cananian 1.1.2.1 // local reference to HCode. 260 cananian 1.1.2.1 HCode hc; 261 cananian 1.1.2.1 // local references to worklists. 262 cananian 1.1.2.1 Worklist Wv, Wq; 263 cananian 1.1.2.1 // give us an OperVisitor class to go along with this. 264 cananian 1.1.2.1 OperVisitor opVisitor = new SCCOpVisitor(); 265 cananian 1.1.2.1 266 cananian 1.1.2.1 SCCVisitor(HCode hc, Worklist Wv, Worklist Wq) { 267 cananian 1.1.2.1 this.hc = hc; this.Wv = Wv; this.Wq = Wq; 268 cananian 1.1.2.1 } 269 cananian 1.1.2.1 270 cananian 1.1.2.1 // utility functions. 271 cananian 1.1.2.1 LatticeVal get(Temp t) { return (LatticeVal) V.get(t); } 272 cananian 1.1.2.1 273 cananian 1.1.2.22 void handleSigmas(CJMP q, boolean falseTaken, boolean trueTaken) { 274 cananian 1.1.2.22 // for every sigma source: 275 cananian 1.1.2.22 for (int i=0; i < q.numSigmas(); i++) { 276 cananian 1.1.2.22 LatticeVal v = get( q.src(i) ); 277 cananian 1.1.2.22 if (v == null) continue; // skip: insufficient info. 278 cananian 1.1.2.22 // check if this is the CJMP condition. 279 cananian 1.1.2.22 if (useSigmas && q.test() == q.src(i)) { 280 cananian 1.1.2.22 // we know that the conditional is zero on the false leg 281 cananian 1.1.2.22 if (falseTaken) 282 cananian 1.1.2.22 raiseV(V, Wv, q.dst(i,0), 283 cananian 1.1.2.22 new xIntConstant(toInternal(HClass.Boolean),0)); 284 cananian 1.1.2.22 // CJMP test is possibly non-boolean, so we don't in fact 285 cananian 1.1.2.22 // know the value of the true side (except that it is 286 cananian 1.1.2.22 // non-zero) 287 cananian 1.1.2.22 if (trueTaken) raiseV(V, Wv, q.dst(i,1), v.rename(q, 1)); 288 cananian 1.1.2.22 } else { 289 cananian 1.1.2.22 // fall back. 290 cananian 1.1.2.22 if (falseTaken) raiseV(V, Wv, q.dst(i,0), v.rename(q, 0)); 291 cananian 1.1.2.22 if (trueTaken) raiseV(V, Wv, q.dst(i,1), v.rename(q, 1)); 292 cananian 1.1.2.22 } 293 cananian 1.1.2.22 } 294 cananian 1.1.2.22 } 295 cananian 1.1.2.22 void handleSigmas(CJMP q, xInstanceofResult io, 296 cananian 1.1.2.22 boolean falseTaken, boolean trueTaken) { 297 cananian 1.1.2.1 // for every sigma source: 298 cananian 1.1.2.1 for (int i=0; i < q.numSigmas(); i++) { 299 cananian 1.1.2.1 // check if this is the CJMP condition. 300 cananian 1.1.2.1 if (q.test() == q.src(i)) { // known value after branch 301 cananian 1.1.2.22 if (falseTaken) raiseV(V, Wv, q.dst(i,0), 302 cananian 1.1.2.22 io.makeKnown(false).rename(q,0)); 303 cananian 1.1.2.22 if (trueTaken) raiseV(V, Wv, q.dst(i,1), 304 cananian 1.1.2.22 io.makeKnown(true).rename(q,1)); 305 cananian 1.1.2.1 continue; // go on. 306 cananian 1.1.2.1 } 307 cananian 1.1.2.1 308 cananian 1.1.2.1 LatticeVal v = get( q.src(i) ); 309 cananian 1.1.2.1 if (v == null) continue; // skip: insufficient info. 310 cananian 1.1.2.1 311 cananian 1.1.2.1 // check to see if this is the temp tested by INSTANCEOF 312 cananian 1.1.2.16 if (q.src(i) == io.tested()) { 313 cananian 1.1.2.1 // no new info on false branch. 314 cananian 1.1.2.22 if (falseTaken) 315 cananian 1.1.2.22 raiseV(V, Wv, q.dst(i,0), v.rename(q, 0)); 316 cananian 1.1.2.1 // we know q.dst[i][1] is INSTANCEOF def.hclass 317 cananian 1.1.2.1 // secret inside info: INSTANCEOF src is always non-null. 318 cananian 1.1.2.23 HClass hcI = io.def().hclass(); 319 cananian 1.1.2.23 HClass hcV = ((xClass)v).type(); 320 cananian 1.1.2.23 // use more specific type 321 cananian 1.1.2.23 if (!hcI.isInterface() && !hcV.isInterface() && 322 cananian 1.1.2.23 hcI.isSuperclassOf(hcV)) 323 cananian 1.1.2.23 hcI = hcV; 324 cananian 1.1.2.23 LatticeVal nv = new xClassNonNull(hcI); 325 cananian 1.1.2.23 // use more specific of original class, instanceof. 326 cananian 1.1.2.23 if (v.isLowerThan(nv)) nv = v; 327 cananian 1.1.2.22 if (trueTaken) 328 cananian 1.1.2.23 raiseV(V, Wv, q.dst(i,1), nv); 329 cananian 1.1.2.1 } else { 330 cananian 1.1.2.1 // fall back. 331 cananian 1.1.2.22 if (falseTaken) raiseV(V, Wv, q.dst(i,0), v.rename(q, 0)); 332 cananian 1.1.2.22 if (trueTaken) raiseV(V, Wv, q.dst(i,1), v.rename(q, 1)); 333 cananian 1.1.2.1 } 334 cananian 1.1.2.1 } 335 cananian 1.1.2.1 } 336 cananian 1.1.2.22 void handleSigmas(CJMP q, xOperBooleanResult or, 337 cananian 1.1.2.22 boolean falseTaken, boolean trueTaken) { 338 cananian 1.1.2.16 int opc = or.def().opcode(); 339 cananian 1.1.2.16 int opa = or.operands().length; 340 cananian 1.1.2.16 LatticeVal left = opa<1?null:get(or.operands()[0]); 341 cananian 1.1.2.16 LatticeVal right= opa<2?null:get(or.operands()[1]); 342 cananian 1.1.2.1 343 cananian 1.1.2.1 // for every sigma source: 344 cananian 1.1.2.1 for (int i=0; i < q.numSigmas(); i++) { 345 cananian 1.1.2.1 // check if this is the CJMP condition. 346 cananian 1.1.2.1 if (q.test() == q.src(i)) { 347 cananian 1.1.2.22 if (falseTaken) raiseV(V, Wv, q.dst(i,0), 348 cananian 1.1.2.22 or.makeKnown(false).rename(q,0)); 349 cananian 1.1.2.22 if (trueTaken) raiseV(V, Wv, q.dst(i,1), 350 cananian 1.1.2.22 or.makeKnown(true).rename(q,1)); 351 cananian 1.1.2.1 continue; // go on. 352 cananian 1.1.2.1 } 353 cananian 1.1.2.1 354 cananian 1.1.2.1 LatticeVal v = get( q.src(i) ); 355 cananian 1.1.2.1 if (v == null) continue; // skip: insufficient info. 356 cananian 1.1.2.1 357 cananian 1.1.2.1 // check to see if it comes from the OPER defining the boolean. 358 cananian 1.1.2.1 boolean handled = false; 359 cananian 1.1.2.22 boolean leftIsSource = false, swapped = false; 360 cananian 1.1.2.16 if (q.src(i) == or.operands()[0]) { // left is source. 361 cananian 1.1.2.22 leftIsSource = true; 362 cananian 1.1.2.22 } else if (q.src(i) == or.operands()[1]) { // right is source. 363 cananian 1.1.2.22 LatticeVal t = left; left = right; right = t; 364 cananian 1.1.2.22 leftIsSource = true; swapped = true; 365 cananian 1.1.2.22 } 366 cananian 1.1.2.22 if (leftIsSource) { 367 cananian 1.1.2.1 if (opc == Qop.ACMPEQ && 368 cananian 1.1.2.1 left instanceof xClass && // not already xClassNonNull 369 cananian 1.1.2.22 (!(left instanceof xNullConstant)) && 370 cananian 1.1.2.1 right instanceof xNullConstant) { 371 cananian 1.1.2.22 if (falseTaken) 372 cananian 1.1.2.22 raiseV(V, Wv, q.dst(i,0), // false branch: non-null 373 cananian 1.1.2.22 new xClassNonNull( ((xClass)left).type() )); 374 cananian 1.1.2.22 if (trueTaken) 375 cananian 1.1.2.22 raiseV(V, Wv, q.dst(i,1), // true branch: null 376 cananian 1.1.2.22 new xNullConstant() ); 377 cananian 1.1.2.1 handled = true; 378 cananian 1.1.2.1 } else if ((opc == Qop.ICMPEQ || opc == Qop.LCMPEQ || 379 cananian 1.1.2.1 opc == Qop.FCMPEQ || opc == Qop.DCMPEQ) && 380 cananian 1.1.2.1 right instanceof xConstant) { 381 cananian 1.1.2.22 if (falseTaken) 382 cananian 1.1.2.22 raiseV(V, Wv, q.dst(i,0), // false branch: no info 383 cananian 1.1.2.22 left.rename(q, 0)); 384 cananian 1.1.2.22 if (trueTaken) 385 cananian 1.1.2.22 raiseV(V, Wv, q.dst(i,1), // true branch: constant! 386 cananian 1.1.2.22 right.rename(q, 1)); 387 cananian 1.1.2.1 handled = true; 388 cananian 1.1.2.22 } else if ((opc == Qop.ICMPGT || opc == Qop.LCMPGT ) && 389 cananian 1.1.2.1 right instanceof xBitWidth) { 390 cananian 1.1.2.1 xBitWidth bw = (xBitWidth) right; 391 cananian 1.1.2.22 xBitWidth sr = extractWidth(left); 392 cananian 1.1.2.22 xBitWidth lessThan = new xBitWidth 393 cananian 1.1.2.22 (sr.type(), 394 cananian 1.1.2.22 sr.minusWidth(), 395 cananian 1.1.2.22 Math.min(sr.plusWidth(), bw.plusWidth()) ); 396 cananian 1.1.2.22 xBitWidth greaterThan = new xBitWidth 397 cananian 1.1.2.22 (sr.type(), 398 cananian 1.1.2.22 Math.min(sr.minusWidth(),bw.minusWidth()), 399 cananian 1.1.2.22 sr.plusWidth() ); 400 cananian 1.1.2.23 // use more specific of original class, xBitWidth. 401 cananian 1.1.2.23 if (left.isLowerThan(lessThan)) 402 cananian 1.1.2.23 lessThan = (xBitWidth) left; 403 cananian 1.1.2.23 if (left.isLowerThan(greaterThan)) 404 cananian 1.1.2.23 greaterThan = (xBitWidth) left; 405 cananian 1.1.2.1 // false branch: 406 cananian 1.1.2.22 if (falseTaken) 407 cananian 1.1.2.22 raiseV(V, Wv, q.dst(i,0), 408 cananian 1.1.2.22 swapped ? greaterThan : lessThan); 409 cananian 1.1.2.1 // true branch. 410 cananian 1.1.2.22 if (trueTaken) 411 cananian 1.1.2.22 raiseV(V, Wv, q.dst(i,1), 412 cananian 1.1.2.22 swapped ? lessThan : greaterThan); 413 cananian 1.1.2.1 handled = true; 414 cananian 1.1.2.1 } 415 cananian 1.1.2.1 } 416 cananian 1.1.2.1 // fall back. 417 cananian 1.1.2.1 if (!handled) { 418 cananian 1.1.2.22 if (falseTaken) raiseV(V, Wv, q.dst(i,0), v.rename(q, 0)); 419 cananian 1.1.2.22 if (trueTaken) raiseV(V, Wv, q.dst(i,1), v.rename(q, 1)); 420 cananian 1.1.2.1 } 421 cananian 1.1.2.1 } 422 cananian 1.1.2.1 } 423 cananian 1.1.2.1 424 cananian 1.1.2.1 // visitation. 425 cananian 1.1.2.1 public void visit(Quad q) { /* do nothing. */ } 426 cananian 1.1.2.1 public void visit(AGET q) { 427 cananian 1.1.2.1 LatticeVal v = get( q.objectref() ); 428 cananian 1.1.2.22 if (corruptor==null) 429 cananian 1.3.2.1 assert v==null || v instanceof xClassNonNull; 430 cananian 1.1.2.1 if (v instanceof xClass) 431 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), 432 cananian 1.1.2.1 new xClass( toInternal( ((xClass)v).type().getComponentType() ) ) ); 433 cananian 1.1.2.1 } 434 cananian 1.1.2.1 public void visit(ALENGTH q) { 435 cananian 1.1.2.1 LatticeVal v = get( q.objectref() ); 436 cananian 1.1.2.22 if (corruptor==null) 437 cananian 1.3.2.1 assert v==null || v instanceof xClassNonNull; 438 cananian 1.1.2.1 if (v instanceof xClassArray) 439 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), 440 cananian 1.1.2.1 new xIntConstant(HClass.Int, 441 cananian 1.1.2.1 ((xClassArray)v).length() ) ); 442 cananian 1.1.2.1 else if (v instanceof xClass) // length is non-negative. 443 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), new xBitWidth(HClass.Int, 0, 32) ); 444 cananian 1.1.2.1 } 445 cananian 1.1.2.1 public void visit(ANEW q) { // dst of ANEW is non-null. 446 cananian 1.1.2.1 if (q.dimsLength()==1) { 447 cananian 1.1.2.1 LatticeVal v = get( q.dims(0) ); 448 cananian 1.1.2.1 if (v instanceof xIntConstant) { 449 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), 450 cananian 1.1.2.1 new xClassArray(q.hclass(), 451 cananian 1.1.2.1 (int) ((xIntConstant)v).value()) ); 452 cananian 1.1.2.1 return; 453 cananian 1.1.2.1 } else if (v == null) return; // bottom. 454 cananian 1.1.2.1 } 455 cananian 1.1.2.11 raiseV(V, Wv, q.dst(), new xClassExact(q.hclass()) ); 456 cananian 1.1.2.1 } 457 cananian 1.1.2.22 public void visit(ASET q) { 458 cananian 1.1.2.22 LatticeVal v = get( q.objectref() ); 459 cananian 1.1.2.22 if (corruptor==null) 460 cananian 1.3.2.1 assert v==null || v instanceof xClassNonNull; 461 cananian 1.1.2.22 /* do nothing. */ 462 cananian 1.1.2.22 } 463 cananian 1.1.2.1 public void visit(CALL q) { 464 cananian 1.1.2.22 if (corruptor==null) 465 cananian 1.3.2.1 assert (q.isVirtual() ? 466 cananian 1.1.2.22 get( q.params(0) )==null || 467 cananian 1.3.2.1 get( q.params(0) ) instanceof xClassNonNull : true) : q; 468 cananian 1.1.2.1 if (q.retval() != null) { 469 cananian 1.1.2.1 // in the bytecode world, everything's an int. 470 cananian 1.1.2.1 HClass ty = q.method().getReturnType(); 471 cananian 1.1.2.1 LatticeVal v = new xClass(toInternal(ty)); 472 cananian 1.1.2.1 if (ty==HClass.Byte) 473 cananian 1.1.2.1 v = new xBitWidth(toInternal(HClass.Byte), 8, 7); 474 cananian 1.1.2.1 else if (ty==HClass.Short) 475 cananian 1.1.2.1 v = new xBitWidth(toInternal(HClass.Short), 16, 15); 476 cananian 1.1.2.1 else if (ty==HClass.Char) 477 cananian 1.1.2.1 v = new xBitWidth(toInternal(HClass.Char), 0, 16); 478 cananian 1.1.2.1 else if (ty==HClass.Boolean) 479 cananian 1.1.2.1 v = new xBitWidth(toInternal(HClass.Boolean),0, 1); 480 cananian 1.1.2.1 else if (ty.isPrimitive()) 481 cananian 1.1.2.1 v = new xClassNonNull(toInternal(ty)); 482 cananian 1.1.2.1 raiseV(V, Wv, q.retval(), v); 483 cananian 1.1.2.1 } 484 cananian 1.1.2.1 raiseV(V, Wv, q.retex(), 485 cananian 1.1.2.16 new xClassNonNull( linker.forName("java.lang.Throwable") )); 486 cananian 1.1.2.3 // both outgoing edges are potentially executable. 487 cananian 1.1.2.3 raiseE(Ee, Eq, Wq, q.nextEdge(1) ); 488 cananian 1.1.2.3 raiseE(Ee, Eq, Wq, q.nextEdge(0) ); 489 cananian 1.1.2.3 // handle SIGMAs 490 cananian 1.1.2.3 for (int i=0; i < q.numSigmas(); i++) { 491 cananian 1.1.2.3 // no q.src(x) should equal retval or retex... 492 cananian 1.1.2.3 // not that it would particularly break anything if it 493 cananian 1.1.2.3 // did. 494 cananian 1.1.2.3 LatticeVal v2 = get ( q.src(i) ); 495 cananian 1.1.2.3 if (v2 != null) { 496 cananian 1.1.2.16 raiseV(V, Wv, q.dst(i, 0), v2.rename(q, 0)); 497 cananian 1.1.2.16 raiseV(V, Wv, q.dst(i, 1), v2.rename(q, 1)); 498 cananian 1.1.2.3 } 499 cananian 1.1.2.3 } 500 cananian 1.1.2.1 } 501 cananian 1.1.2.1 public void visit(CJMP q) { 502 cananian 1.1.2.1 // is test constant? 503 cananian 1.1.2.1 LatticeVal v = get( q.test() ); 504 cananian 1.1.2.1 if (v instanceof xIntConstant) { 505 cananian 1.1.2.1 boolean test = ((xIntConstant)v).value()!=0; 506 cananian 1.1.2.1 507 cananian 1.1.2.1 if (test) 508 cananian 1.1.2.1 raiseE(Ee, Eq, Wq, q.nextEdge(1) ); // true edge. 509 cananian 1.1.2.1 else 510 cananian 1.1.2.1 raiseE(Ee, Eq, Wq, q.nextEdge(0) ); // false edge. 511 cananian 1.1.2.1 // handle sigmas. 512 cananian 1.1.2.22 if (useSigmas && v instanceof xOperBooleanResult) 513 cananian 1.1.2.22 handleSigmas((CJMP) q, (xOperBooleanResult)v, 514 cananian 1.1.2.22 !test, test); 515 cananian 1.1.2.22 else if (useSigmas && v instanceof xInstanceofResult) 516 cananian 1.1.2.22 handleSigmas((CJMP) q, (xInstanceofResult) v, 517 cananian 1.1.2.22 !test, test); 518 cananian 1.1.2.22 else // fallback. 519 cananian 1.1.2.22 handleSigmas((CJMP) q, !test, test); 520 cananian 1.1.2.1 return; // done. 521 cananian 1.1.2.1 } else if (v instanceof xClass) { // ie, not bottom. 522 cananian 1.1.2.1 // both edges are potentially executable. 523 cananian 1.1.2.1 raiseE(Ee, Eq, Wq, q.nextEdge(1) ); 524 cananian 1.1.2.1 raiseE(Ee, Eq, Wq, q.nextEdge(0) ); 525 cananian 1.1.2.1 526 cananian 1.1.2.1 // look at definition of boolean condition. 527 cananian 1.1.2.16 if (useSigmas && v instanceof xOperBooleanResult) 528 cananian 1.1.2.22 handleSigmas((CJMP) q, (xOperBooleanResult)v, true, true); 529 cananian 1.1.2.16 else if (useSigmas && v instanceof xInstanceofResult) 530 cananian 1.1.2.22 handleSigmas((CJMP) q, (xInstanceofResult) v, true, true); 531 cananian 1.1.2.1 else // fallback. 532 cananian 1.1.2.22 handleSigmas((CJMP) q, true, true); 533 cananian 1.1.2.1 } 534 cananian 1.1.2.1 } 535 cananian 1.1.2.1 public void visit(COMPONENTOF q) { 536 cananian 1.1.2.1 // we're guaranteed that q.arrayref is non-null here. 537 cananian 1.1.2.1 LatticeVal vA = get( q.arrayref() ); 538 cananian 1.1.2.1 LatticeVal vO = get( q.objectref() ); 539 cananian 1.1.2.1 if (vA instanceof xClass && vO instanceof xClass) { 540 cananian 1.1.2.1 HClass hcA = ((xClass) vA).type().getComponentType() ; 541 cananian 1.1.2.1 HClass hcO = ((xClass) vO).type(); 542 cananian 1.1.2.1 if (hcA==null) { // can't prove type is array; usually this 543 cananian 1.1.2.1 // means we've turned useSigmas off. 544 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), new xBitWidth(toInternal(HClass.Boolean),0,1)); 545 cananian 1.1.2.1 return; 546 cananian 1.1.2.1 } 547 cananian 1.1.2.1 hcA = toInternal(hcA); // normalize external types. 548 cananian 1.1.2.1 // special case when q.objectref is null 549 cananian 1.1.2.1 if (hcO == HClass.Void) // always true. 550 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), new xIntConstant(toInternal(HClass.Boolean),1)); 551 cananian 1.1.2.23 else if (vA instanceof xClassExact && 552 cananian 1.1.2.23 hcO.isInstanceOf(hcA)) // always true 553 cananian 1.1.2.23 raiseV(V, Wv, q.dst(), new xIntConstant(toInternal(HClass.Boolean),1)); 554 cananian 1.1.2.23 else if (vO instanceof xClassExact && 555 cananian 1.1.2.23 !hcO.isInstanceOf(hcA)) // always false 556 cananian 1.1.2.23 raiseV(V, Wv, q.dst(), new xIntConstant(toInternal(HClass.Boolean),0)); 557 cananian 1.6 else if (hcA.isInterface() || 558 cananian 1.6 hcO.isInterface() || 559 cananian 1.6 hcO.isInstanceOf(hcA) || 560 cananian 1.1.2.15 hcA.isInstanceOf(hcO)) // unknowable. 561 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), new xBitWidth(toInternal(HClass.Boolean),0,1)); 562 cananian 1.1.2.1 else // always false. 563 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), new xIntConstant(toInternal(HClass.Boolean),0)); 564 cananian 1.1.2.1 } 565 cananian 1.1.2.1 } 566 cananian 1.1.2.1 public void visit(CONST q) { 567 cananian 1.1.2.1 if (q.type() == HClass.Void) // null constant 568 cananian 1.1.2.1 raiseV(V,Wv, q.dst(), new xNullConstant() ); 569 cananian 1.1.2.7 else if (q.type()==linker.forName("java.lang.String"))// string constant 570 cananian 1.1.2.1 raiseV(V,Wv, q.dst(), new xStringConstant(q.type(),q.value())); 571 cananian 1.1.2.1 else if (q.type()==HClass.Float || q.type()==HClass.Double) // f-p 572 cananian 1.1.2.1 raiseV(V,Wv, q.dst(), new xFloatConstant(q.type(),q.value()) ); 573 cananian 1.1.2.1 else if (q.type()==HClass.Int || q.type() == HClass.Long) 574 cananian 1.1.2.1 raiseV(V,Wv, q.dst(), 575 cananian 1.1.2.1 new xIntConstant(q.type(), 576 cananian 1.1.2.1 ((Number)q.value()).longValue())); 577 cananian 1.1.2.13 else if (q.type()==linker.forName("java.lang.Class") || 578 cananian 1.1.2.13 q.type()==linker.forName("java.lang.reflect.Field") || 579 cananian 1.1.2.13 q.type()==linker.forName("java.lang.reflect.Method")) 580 cananian 1.1.2.13 raiseV(V,Wv, q.dst(), new xClassNonNull( q.type() ) ); 581 cananian 1.1.2.1 else throw new Error("Unknown CONST type: "+q.type()); 582 cananian 1.1.2.1 } 583 cananian 1.1.2.1 public void visit(FOOTER q) { /* do nothing. */ } 584 cananian 1.1.2.1 public void visit(GET q) { 585 cananian 1.1.2.22 if (corruptor==null) 586 cananian 1.3.2.1 assert (q.objectref()!=null ? 587 cananian 1.1.2.22 get(q.objectref())==null || 588 cananian 1.3.2.1 get(q.objectref()) instanceof xClassNonNull : true) : q; 589 cananian 1.1.2.1 HClass type = toInternal(q.field().getType()); 590 cananian 1.1.2.1 if (q.field().isConstant()) { 591 cananian 1.1.2.1 Object val = q.field().getConstant(); 592 cananian 1.1.2.7 if (type == linker.forName("java.lang.String")) 593 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), new xStringConstant(type, val) ); 594 cananian 1.1.2.1 else if (type == HClass.Float || type == HClass.Double ) 595 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), new xFloatConstant(type, val) ); 596 cananian 1.1.2.1 else if (type == HClass.Int || type == HClass.Long) 597 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), 598 cananian 1.1.2.1 new xIntConstant(type,((Number)val).longValue() ) ); 599 cananian 1.1.2.1 else throw new Error("Unknown constant field type: "+type); 600 cananian 1.1.2.1 } else raiseV(V, Wv, q.dst(), new xClass( type ) ); 601 cananian 1.1.2.1 } 602 cananian 1.1.2.1 public void visit(HEADER q) { 603 cananian 1.1.2.1 // mark both edges executable. 604 cananian 1.1.2.1 raiseE(Ee, Eq, Wq, q.nextEdge(0)); 605 cananian 1.1.2.1 raiseE(Ee, Eq, Wq, q.nextEdge(1)); 606 cananian 1.1.2.1 } 607 cananian 1.1.2.1 public void visit(INSTANCEOF q) { 608 cananian 1.1.2.1 // no guarantee that src is not null. 609 cananian 1.1.2.1 LatticeVal v = get( q.src() ); 610 cananian 1.1.2.4 if (v instanceof xNullConstant) // always false. 611 cananian 1.1.2.22 raiseV(V, Wv, q.dst(), new xInstanceofResultKnown(q,false)); 612 cananian 1.6 else if (v instanceof xClassExact) { // always known. 613 cananian 1.6 HClass hcO = ((xClassNonNull)v).type(); 614 cananian 1.6 assert !hcO.isInterface();//but can be an array type. 615 cananian 1.6 boolean result = hcO.isInstanceOf(q.hclass()); 616 cananian 1.6 raiseV(V,Wv, q.dst(), new xInstanceofResultKnown(q,result)); 617 cananian 1.6 } 618 cananian 1.1.2.1 else if (v instanceof xClassNonNull) { // analyzable 619 cananian 1.1.2.1 HClass hcO = ((xClassNonNull)v).type(); 620 cananian 1.1.2.1 if (hcO.isInstanceOf(q.hclass())) // always true 621 cananian 1.1.2.22 raiseV(V,Wv, q.dst(), new xInstanceofResultKnown(q,true)); 622 cananian 1.6 else if (q.hclass().isInterface() || hcO.isInterface() || 623 cananian 1.6 q.hclass().isInstanceOf(hcO)) // unknowable. 624 cananian 1.1.2.22 raiseV(V,Wv, q.dst(), new xInstanceofResultUnknown(q)); 625 cananian 1.1.2.1 else // always false. 626 cananian 1.1.2.22 raiseV(V,Wv, q.dst(), new xInstanceofResultKnown(q,false)); 627 cananian 1.1.2.1 } 628 cananian 1.1.2.1 else if (v instanceof xClass) { // could be null. 629 cananian 1.1.2.1 HClass hcO = ((xClass)v).type(); 630 cananian 1.6 if (q.hclass().isInterface() || hcO.isInterface() || 631 cananian 1.6 q.hclass().isInstanceOf(hcO) || 632 cananian 1.1.2.1 hcO.isInstanceOf(q.hclass()) ) // unknowable. 633 cananian 1.1.2.22 raiseV(V,Wv, q.dst(), new xInstanceofResultUnknown(q)); 634 cananian 1.1.2.1 else // always false (even if src==null) 635 cananian 1.1.2.22 raiseV(V,Wv, q.dst(), new xInstanceofResultKnown(q,false)); 636 cananian 1.1.2.1 } 637 cananian 1.1.2.1 } 638 cananian 1.1.2.1 public void visit(METHOD q) { 639 cananian 1.1.2.1 HMethod m = hc.getMethod(); 640 cananian 1.1.2.1 HClass[] pt = m.getParameterTypes(); 641 cananian 1.1.2.1 int j=0; 642 cananian 1.1.2.1 if (!m.isStatic() ) // raise 'this' variable (non-null!) 643 cananian 1.1.2.1 raiseV(V, Wv, q.params(j++), 644 cananian 1.1.2.1 new xClassNonNull( m.getDeclaringClass() ) ); 645 cananian 1.1.2.1 for (int k=0; k < pt.length; j++, k++) 646 cananian 1.1.2.1 if (pt[k].isPrimitive()) 647 cananian 1.1.2.1 raiseV(V, Wv, q.params(j), new xClassNonNull( toInternal(pt[k]) ) ); 648 cananian 1.1.2.1 else 649 cananian 1.1.2.1 raiseV(V, Wv, q.params(j), new xClass( pt[k] ) ); 650 cananian 1.1.2.1 } 651 cananian 1.1.2.22 public void visit(MONITORENTER q) { 652 cananian 1.1.2.22 LatticeVal v = get( q.lock() ); 653 cananian 1.3.2.1 assert v==null || v instanceof xClassNonNull; 654 cananian 1.1.2.22 /* do nothing. */ 655 cananian 1.1.2.22 } 656 cananian 1.1.2.22 public void visit(MONITOREXIT q) { 657 cananian 1.1.2.22 LatticeVal v = get( q.lock() ); 658 cananian 1.3.2.1 assert v==null || v instanceof xClassNonNull; 659 cananian 1.1.2.22 /* do nothing. */ 660 cananian 1.1.2.22 } 661 cananian 1.1.2.1 public void visit(MOVE q) { 662 cananian 1.1.2.1 LatticeVal v = get ( q.src() ); 663 cananian 1.1.2.1 if (v != null) 664 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), v); 665 cananian 1.1.2.1 } 666 cananian 1.1.2.1 public void visit(NEW q) { 667 cananian 1.1.2.11 raiseV(V, Wv, q.dst(), new xClassExact( q.hclass() ) ); 668 cananian 1.1.2.1 } 669 cananian 1.1.2.1 public void visit(NOP q) { /* do nothing. */ } 670 cananian 1.1.2.1 public void visit(OPER q) { 671 cananian 1.1.2.1 int opc = q.opcode(); 672 cananian 1.1.2.1 boolean allConst = true; 673 cananian 1.1.2.1 boolean allWidth = true; 674 cananian 1.1.2.1 675 cananian 1.1.2.1 Object[] op = new Object[q.operandsLength()]; 676 cananian 1.1.2.1 for (int i=0; i < q.operandsLength(); i++) { 677 cananian 1.1.2.1 LatticeVal v = get( q.operands(i) ); 678 cananian 1.1.2.1 if (v==null) return; // can't eval yet. 679 cananian 1.1.2.1 if (v instanceof xConstant) 680 cananian 1.1.2.1 op[i] = ((xConstant)v).constValue(); 681 cananian 1.1.2.1 else if (v instanceof xBitWidth) 682 cananian 1.1.2.1 allConst = false; 683 cananian 1.1.2.1 else 684 cananian 1.1.2.1 allConst = allWidth = false; 685 cananian 1.1.2.1 } 686 cananian 1.1.2.1 if (allConst) { 687 cananian 1.1.2.1 // RULE 3: 688 cananian 1.1.2.1 HClass ty = q.evalType(); 689 cananian 1.1.2.1 Object o = q.evalValue(op); 690 cananian 1.1.2.1 if (ty == HClass.Boolean) 691 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), 692 cananian 1.1.2.22 new xOperBooleanResultKnown 693 cananian 1.1.2.22 (q,((Boolean)o).booleanValue())); 694 cananian 1.1.2.1 else if (ty == HClass.Int || ty == HClass.Long) 695 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), 696 cananian 1.1.2.1 new xIntConstant(ty, ((Number)o).longValue() ) ); 697 cananian 1.1.2.1 else if (ty == HClass.Float || ty == HClass.Double) 698 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), new xFloatConstant(ty, o) ); 699 cananian 1.1.2.1 else throw new Error("Unknown OPER result type: "+ty); 700 cananian 1.1.2.1 } else if ((allWidth) || 701 cananian 1.1.2.1 opc == Qop.I2B || opc == Qop.I2C || opc == Qop.I2L || 702 cananian 1.1.2.1 opc == Qop.I2S || opc == Qop.L2I) { 703 cananian 1.1.2.1 // do something intelligent with the bitwidths. 704 cananian 1.1.2.2 q.accept(opVisitor); 705 cananian 1.1.2.1 } else { // not all constant, not all known widths... 706 cananian 1.1.2.1 // special-case ACMPEQ x, null 707 cananian 1.1.2.1 if (opc == Qop.ACMPEQ && 708 cananian 1.1.2.1 ((get( q.operands(0) ) instanceof xNullConstant && 709 cananian 1.1.2.1 get( q.operands(1) ) instanceof xClassNonNull) || 710 cananian 1.1.2.1 (get( q.operands(0) ) instanceof xClassNonNull && 711 cananian 1.1.2.1 get( q.operands(1) ) instanceof xNullConstant) ) ) 712 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), // always false. 713 cananian 1.1.2.22 new xOperBooleanResultKnown(q, false)); 714 cananian 1.1.2.16 // special case boolean operations. 715 cananian 1.1.2.16 else if (opc == Qop.ACMPEQ || 716 cananian 1.1.2.16 opc == Qop.DCMPEQ || opc == Qop.DCMPGE || 717 cananian 1.1.2.16 opc == Qop.DCMPGT || 718 cananian 1.1.2.16 opc == Qop.FCMPEQ || opc == Qop.FCMPGE || 719 cananian 1.1.2.16 opc == Qop.FCMPGT || 720 cananian 1.1.2.16 opc == Qop.ICMPEQ || opc == Qop.ICMPGT || 721 cananian 1.1.2.16 opc == Qop.LCMPEQ || opc == Qop.LCMPGT) 722 cananian 1.1.2.22 raiseV(V, Wv, q.dst(), new xOperBooleanResultUnknown(q)); 723 cananian 1.1.2.1 else { 724 cananian 1.1.2.1 // RULE 4: 725 cananian 1.1.2.1 HClass ty = q.evalType(); 726 cananian 1.1.2.1 if (ty.isPrimitive()) 727 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), new xClassNonNull( toInternal(ty) ) ); 728 cananian 1.1.2.1 else 729 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), new xClass( ty ) ); 730 cananian 1.1.2.1 } 731 cananian 1.1.2.1 } 732 cananian 1.1.2.1 } 733 cananian 1.1.2.1 public void visit(PHI q) { 734 cananian 1.1.2.1 for (int i=0; i<q.numPhis(); i++) { // for each phi-function. 735 cananian 1.1.2.21 LatticeVal merged = null; 736 cananian 1.1.2.1 for (int j=0; j < q.arity(); j++) { 737 cananian 1.1.2.1 if (!Ee.contains( q.prevEdge(j) )) 738 cananian 1.1.2.1 continue; // skip non-executable edges. 739 cananian 1.1.2.1 LatticeVal v = get ( q.src(i,j) ); 740 cananian 1.1.2.1 if (v == null) 741 cananian 1.1.2.1 continue; // skip this arg function. 742 cananian 1.1.2.21 v = v.rename(q, j); 743 cananian 1.1.2.21 if (merged == null) 744 cananian 1.1.2.21 merged = v; // first valid value 745 cananian 1.1.2.21 else merged = merged.merge(v); 746 cananian 1.1.2.1 } 747 cananian 1.1.2.1 // assess results. 748 cananian 1.1.2.21 if (merged == null) 749 cananian 1.1.2.1 continue; // nothing to go on. 750 cananian 1.1.2.21 else raiseV(V, Wv, q.dst(i), merged); 751 cananian 1.1.2.1 } // for each phi function. 752 cananian 1.1.2.1 } 753 cananian 1.1.2.1 public void visit(RETURN q) { /* do nothing. */ } 754 cananian 1.1.2.22 public void visit(SET q) { 755 cananian 1.1.2.22 if (corruptor==null) 756 cananian 1.3.2.1 assert (q.objectref()!=null ? 757 cananian 1.1.2.22 get(q.objectref())==null || 758 cananian 1.3.2.1 get(q.objectref()) instanceof xClassNonNull : true) : q; 759 cananian 1.1.2.22 /* do nothing. */ 760 cananian 1.1.2.22 } 761 cananian 1.1.2.1 public void visit(SWITCH q) { 762 cananian 1.1.2.1 LatticeVal v = get( q.index() ); 763 cananian 1.1.2.1 if (v instanceof xIntConstant) { 764 cananian 1.1.2.1 int index = (int) ((xIntConstant)v).value(); 765 cananian 1.1.2.1 int i; 766 cananian 1.1.2.1 for (i=0; i<q.keysLength(); i++) 767 cananian 1.1.2.1 if (q.keys(i) == index) 768 cananian 1.1.2.1 break; 769 cananian 1.1.2.1 // now i has the target index, even for the default case. 770 cananian 1.1.2.1 raiseE(Ee, Eq, Wq, q.nextEdge(i) ); // executable edge. 771 cananian 1.1.2.1 // handle sigmas. 772 cananian 1.1.2.1 for (int j=0; j < q.numSigmas(); j++) { 773 cananian 1.1.2.1 LatticeVal v2 = get( q.src(j) ); 774 cananian 1.1.2.1 if (v2 != null) 775 cananian 1.1.2.16 raiseV(V, Wv, q.dst(j,i), v2.rename(q,i)); 776 cananian 1.1.2.1 } 777 cananian 1.1.2.1 } 778 cananian 1.1.2.1 else if (v != null) { 779 cananian 1.1.2.23 xBitWidth bw = extractWidth(v); 780 cananian 1.1.2.23 // mark some edges executable & propagate to all sigmas. 781 cananian 1.1.2.24 int executable=0; 782 cananian 1.1.2.23 for (int j=0; j < q.nextEdge().length; j++) { 783 cananian 1.1.2.24 if (j<q.keysLength()) { // non-default edge. 784 cananian 1.1.2.23 // learn stuff about cases from bitwidth of v. 785 cananian 1.1.2.23 int k = q.keys(j); 786 cananian 1.1.2.23 if (k>0 && Util.fls(k) > bw.plusWidth()) 787 cananian 1.1.2.23 continue; // key too large to be selected. 788 cananian 1.1.2.23 if (k<0 && Util.fls(-k) > bw.minusWidth()) 789 cananian 1.1.2.23 continue; // key too small to be selected. 790 cananian 1.1.2.24 executable++; 791 cananian 1.1.2.24 } else { 792 cananian 1.1.2.24 // pigeon-hole principle: default edge is executable 793 cananian 1.1.2.24 // iff number of executable edges (so far) is less 794 cananian 1.1.2.24 // than possible number of cases constrained by 795 cananian 1.1.2.24 // plusWidth and minusWidth. 796 cananian 1.1.2.24 // --- bail if plusWidth/minusWidth too large; we 797 cananian 1.1.2.24 // know (we hope!) that switch can't have this 798 cananian 1.1.2.24 // many edges. 799 cananian 1.1.2.24 if (bw.plusWidth<30 && bw.minusWidth<30) { 800 cananian 1.1.2.24 // number of cases is (2^pw + 2^mw)-1 801 cananian 1.1.2.24 // (don't count zero twice!) 802 cananian 1.1.2.24 long cases = -1 + 803 cananian 1.1.2.24 (1L<<bw.plusWidth()) + (1L<<bw.minusWidth()); 804 cananian 1.3.2.1 assert executable<=cases; 805 cananian 1.1.2.24 if (executable==cases) 806 cananian 1.1.2.24 continue; // default not executable. 807 cananian 1.1.2.24 } 808 cananian 1.1.2.23 } 809 cananian 1.1.2.23 raiseE(Ee, Eq, Wq, q.nextEdge(j) ); 810 cananian 1.1.2.23 for (int i=0; i < q.numSigmas(); i++) { 811 cananian 1.1.2.23 LatticeVal v2 = get( q.src(i) ); 812 cananian 1.1.2.23 if (v2 != null) 813 cananian 1.1.2.16 raiseV(V, Wv, q.dst(i,j), v2.rename(q,j)); 814 cananian 1.1.2.23 } 815 cananian 1.1.2.1 } 816 cananian 1.1.2.1 } 817 cananian 1.1.2.1 } 818 cananian 1.1.2.22 public void visit(THROW q) { 819 cananian 1.1.2.22 if (corruptor==null) 820 cananian 1.3.2.1 assert get(q.throwable())==null || 821 cananian 1.3.2.1 get(q.throwable()) instanceof xClassNonNull; 822 cananian 1.1.2.22 /* do nothing. */ 823 cananian 1.1.2.22 } 824 cananian 1.1.2.10 public void visit(TYPESWITCH q) { 825 cananian 1.1.2.10 LatticeVal v = get( q.index() ); 826 cananian 1.1.2.10 if (v instanceof xClass) { 827 cananian 1.1.2.10 HClass type = ((xClass)v).type(); 828 cananian 1.1.2.10 boolean catchAll = false; 829 cananian 1.1.2.10 for (int i=0; i<q.keysLength(); i++) { 830 cananian 1.1.2.10 if (type.isInstanceOf(q.keys(i))) {// catches all remaining 831 cananian 1.1.2.14 raiseE(Ee, Eq, Wq, q.nextEdge(i) ); 832 cananian 1.1.2.10 catchAll = true; 833 cananian 1.1.2.10 break; 834 cananian 1.1.2.10 } 835 cananian 1.6 if (q.keys(i).isInterface() || type.isInterface() || 836 cananian 1.6 q.keys(i).isInstanceOf(type)) // executable 837 cananian 1.6 raiseE(Ee, Eq, Wq, q.nextEdge(i) ); 838 cananian 1.1.2.10 } 839 cananian 1.1.2.12 if ((!q.hasDefault()) || 840 cananian 1.1.2.12 (catchAll && v instanceof xClassNonNull)) 841 cananian 1.1.2.10 /* default edge never taken */; 842 cananian 1.1.2.10 else // make the default case executable. 843 cananian 1.1.2.10 raiseE(Ee, Eq, Wq, q.nextEdge(q.keysLength())); 844 cananian 1.1.2.10 845 cananian 1.1.2.10 // handle sigmas. 846 cananian 1.1.2.10 for (int i=0; i < q.arity(); i++) { 847 cananian 1.1.2.10 if (!Ee.contains(q.nextEdge(i))) continue;//only raise exec 848 cananian 1.1.2.10 for (int j=0; j < q.numSigmas(); j++) { 849 cananian 1.1.2.10 if (q.src(j)==q.index() && i<q.keysLength()) 850 cananian 1.1.2.10 raiseV(V, Wv, q.dst(j,i), 851 cananian 1.1.2.10 new xClassNonNull(q.keys(i))); 852 cananian 1.1.2.10 else { 853 cananian 1.1.2.10 LatticeVal v2 = get( q.src(j) ); 854 cananian 1.1.2.10 if (v2 != null) 855 cananian 1.1.2.16 raiseV(V, Wv, q.dst(j,i), v2.rename(q,i)); 856 cananian 1.1.2.10 } 857 cananian 1.1.2.10 } 858 cananian 1.1.2.10 } 859 cananian 1.1.2.10 } 860 cananian 1.1.2.10 else if (v != null) { 861 cananian 1.1.2.10 // mark all edges executable & propagate to all sigmas. 862 cananian 1.1.2.12 for (int i=0; i < q.nextLength(); i++) 863 cananian 1.1.2.10 raiseE(Ee, Eq, Wq, q.nextEdge(i) ); 864 cananian 1.1.2.10 for (int i=0; i < q.numSigmas(); i++) { 865 cananian 1.1.2.10 LatticeVal v2 = get( q.src(i) ); 866 cananian 1.1.2.10 if (v2 != null) 867 cananian 1.1.2.10 for (int j=0; j < q.arity(); j++) 868 cananian 1.1.2.16 raiseV(V, Wv, q.dst(i,j), v2.rename(q,j)); 869 cananian 1.1.2.10 } 870 cananian 1.1.2.10 } 871 cananian 1.1.2.10 } 872 cananian 1.1.2.1 873 cananian 1.1.2.1 /*------------------------------------------------------------*/ 874 cananian 1.1.2.1 // VISITOR CLASS FOR OPER (ugh. lots of cases) 875 cananian 1.1.2.1 class SCCOpVisitor extends OperVisitor { 876 cananian 1.1.2.1 877 cananian 1.1.2.1 public void visit_default(OPER q) { 878 cananian 1.1.2.1 HClass ty = q.evalType(); 879 cananian 1.1.2.1 if (ty.isPrimitive()) 880 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), new xClassNonNull( toInternal(ty) ) ); 881 cananian 1.1.2.1 else 882 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), new xClass( ty ) ); 883 cananian 1.1.2.1 } 884 cananian 1.1.2.17 // comparisons 885 cananian 1.1.2.17 void visit_cmpeq(OPER q) { 886 cananian 1.1.2.17 xBitWidth left = extractWidth( get( q.operands(0) ) ); 887 cananian 1.1.2.17 xBitWidth right= extractWidth( get( q.operands(1) ) ); 888 cananian 1.1.2.17 // comparisons against a constant. 889 cananian 1.1.2.17 if ((left instanceof xIntConstant &&// left a constant and 890 cananian 1.1.2.17 ((left.minusWidth()==0 && // right smaller than left. 891 cananian 1.1.2.17 right.plusWidth() < left.plusWidth()) || 892 cananian 1.1.2.17 (left.plusWidth()==0 && 893 cananian 1.1.2.17 right.minusWidth() < left.minusWidth()))) || // or... 894 cananian 1.1.2.17 (right instanceof xIntConstant &&// right a constant and 895 cananian 1.1.2.17 ((right.minusWidth()==0 && // left smaller than right. 896 cananian 1.1.2.17 left.plusWidth() < right.plusWidth()) || 897 cananian 1.1.2.17 (right.plusWidth()==0 && 898 cananian 1.1.2.17 left.minusWidth() < right.minusWidth()))) ) 899 cananian 1.1.2.17 // okay, comparison can never be true. 900 cananian 1.1.2.17 raiseV(V, Wv, q.dst(), 901 cananian 1.1.2.22 new xOperBooleanResultKnown(q,false)); 902 cananian 1.1.2.17 else // okay, nothing known. 903 cananian 1.1.2.22 raiseV(V, Wv, q.dst(), new xOperBooleanResultUnknown(q)); 904 cananian 1.1.2.17 } 905 cananian 1.1.2.17 public void visit_icmpeq(OPER q) { visit_cmpeq(q); } 906 cananian 1.1.2.17 public void visit_lcmpeq(OPER q) { visit_cmpeq(q); } 907 cananian 1.1.2.17 void visit_cmpgt(OPER q) { 908 cananian 1.1.2.17 xBitWidth left = extractWidth( get( q.operands(0) ) ); 909 cananian 1.1.2.17 xBitWidth right= extractWidth( get( q.operands(1) ) ); 910 cananian 1.1.2.17 // comparisons against a non-zero constant. 911 cananian 1.1.2.17 if ((left instanceof xIntConstant && 912 cananian 1.1.2.17 ((xIntConstant)left).value()!=0 && 913 cananian 1.1.2.17 left.plusWidth() > right.plusWidth()) || 914 cananian 1.1.2.17 (right instanceof xIntConstant && 915 cananian 1.1.2.17 ((xIntConstant)right).value()!=0 && 916 cananian 1.1.2.17 right.minusWidth() > left.minusWidth())) 917 cananian 1.1.2.17 // comparison is always true 918 cananian 1.1.2.22 raiseV(V,Wv, q.dst(), new xOperBooleanResultKnown(q,true)); 919 cananian 1.1.2.17 else if ((left instanceof xIntConstant && 920 cananian 1.1.2.17 ((xIntConstant)left).value()!=0 && 921 cananian 1.1.2.17 left.minusWidth() > right.minusWidth()) || 922 cananian 1.1.2.17 (right instanceof xIntConstant && 923 cananian 1.1.2.17 ((xIntConstant)right).value()!=0 && 924 cananian 1.1.2.17 right.plusWidth() > left.plusWidth())) 925 cananian 1.1.2.17 // comparison is always false 926 cananian 1.1.2.22 raiseV(V,Wv, q.dst(),new xOperBooleanResultKnown(q,false)); 927 cananian 1.1.2.17 // comparisons against zero. 928 cananian 1.1.2.17 else if ((left instanceof xIntConstant && 929 cananian 1.1.2.17 ((xIntConstant)left).value()==0 && 930 cananian 1.1.2.17 right.minusWidth()==0) || 931 cananian 1.1.2.17 (right instanceof xIntConstant && 932 cananian 1.1.2.17 ((xIntConstant)right).value()==0 && 933 cananian 1.1.2.17 left.plusWidth()==0)) 934 cananian 1.1.2.17 // comparison is always false. 0 > 0+ or 0- > 0 935 cananian 1.1.2.22 raiseV(V,Wv, q.dst(),new xOperBooleanResultKnown(q,false)); 936 cananian 1.1.2.17 else // okay, nothing known. 937 cananian 1.1.2.22 raiseV(V, Wv, q.dst(), new xOperBooleanResultUnknown(q)); 938 cananian 1.1.2.17 } 939 cananian 1.1.2.17 public void visit_icmpgt(OPER q) { visit_cmpgt(q); } 940 cananian 1.1.2.17 public void visit_lcmpgt(OPER q) { visit_cmpgt(q); } 941 cananian 1.1.2.17 // conversions 942 cananian 1.1.2.1 public void visit_i2b(OPER q) { 943 cananian 1.1.2.1 xBitWidth bw = extractWidth( get( q.operands(0) ) ); 944 cananian 1.5 int mbw = bw.minusWidth(), pbw = bw.plusWidth(); 945 cananian 1.5 if (bw.plusWidth>=8) 946 cananian 1.5 mbw = 8; // large + val may become large - val. 947 cananian 1.5 if (bw.minusWidth()>=8) 948 cananian 1.5 pbw = 7; // large - val may become large + val. 949 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), 950 cananian 1.1.2.1 new xBitWidth(HClass.Int, 951 cananian 1.5 Math.min(8, mbw), 952 cananian 1.5 Math.min(7, pbw) )); 953 cananian 1.1.2.1 } 954 cananian 1.1.2.1 public void visit_i2c(OPER q) { 955 cananian 1.1.2.1 xBitWidth bw = extractWidth( get( q.operands(0) ) ); 956 cananian 1.5 int mbw = bw.minusWidth(), pbw = bw.plusWidth(); 957 cananian 1.5 if (bw.minusWidth()>0) 958 cananian 1.5 pbw = 16; // - val may become large + val. 959 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), 960 cananian 1.1.2.1 new xBitWidth(HClass.Int, 0, 961 cananian 1.5 Math.min(16, pbw) )); 962 cananian 1.1.2.1 } 963 cananian 1.1.2.1 public void visit_i2l(OPER q) { 964 cananian 1.1.2.1 xBitWidth bw = extractWidth( get( q.operands(0) ) ); 965 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), 966 cananian 1.1.2.1 new xBitWidth(HClass.Long, 967 cananian 1.1.2.1 Math.min(32, bw.minusWidth()), 968 cananian 1.1.2.1 Math.min(31, bw.plusWidth()) )); 969 cananian 1.1.2.1 } 970 cananian 1.1.2.1 public void visit_i2s(OPER q) { 971 cananian 1.1.2.1 xBitWidth bw = extractWidth( get( q.operands(0) ) ); 972 cananian 1.5 int mbw = bw.minusWidth(), pbw = bw.plusWidth(); 973 cananian 1.5 if (bw.plusWidth>=16) 974 cananian 1.5 mbw = 16; // large + val may become large - val. 975 cananian 1.5 if (bw.minusWidth()>=16) 976 cananian 1.5 pbw = 15; // large - val may become large + val. 977 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), 978 cananian 1.1.2.1 new xBitWidth(HClass.Int, 979 cananian 1.5 Math.min(16, mbw), 980 cananian 1.5 Math.min(15, pbw) )); 981 cananian 1.1.2.1 } 982 cananian 1.1.2.1 public void visit_l2i(OPER q) { 983 cananian 1.1.2.1 xBitWidth bw = extractWidth( get( q.operands(0) ) ); 984 cananian 1.5 int mbw = bw.minusWidth(), pbw = bw.plusWidth(); 985 cananian 1.5 if (bw.plusWidth>=32) 986 cananian 1.5 mbw = 32; // large + val may become large - val. 987 cananian 1.5 if (bw.minusWidth()>=32) 988 cananian 1.5 pbw = 31; // large - val may become large + val. 989 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), 990 cananian 1.1.2.1 new xBitWidth(HClass.Int, 991 cananian 1.5 Math.min(32, mbw), 992 cananian 1.5 Math.min(31, pbw) )); 993 cananian 1.1.2.1 } 994 cananian 1.1.2.17 // binops 995 cananian 1.5 void visit_add(OPER q, int maxbits) { 996 cananian 1.1.2.1 xBitWidth left = extractWidth( get( q.operands(0) ) ); 997 cananian 1.1.2.1 xBitWidth right= extractWidth( get( q.operands(1) ) ); 998 cananian 1.1.2.1 int m = Math.max( left.minusWidth(), right.minusWidth() ); 999 cananian 1.1.2.1 int p = Math.max( left.plusWidth(), right.plusWidth() ); 1000 cananian 1.1.2.1 // zero plus zero is always zero, but other numbers grow. 1001 cananian 1.5 // also 0+x: x doesn't grow. 1002 cananian 1.5 if (left.minusWidth()>0 && right.minusWidth()>0) m++; 1003 cananian 1.5 if (left.plusWidth()>0 && right.plusWidth()>0) p++; 1004 cananian 1.5 // handle overflow. 1005 cananian 1.5 if (p >= maxbits) 1006 cananian 1.5 m = maxbits; // large + val becomes large - val. 1007 cananian 1.5 if (m >= maxbits) 1008 cananian 1.5 p = maxbits-1; // large - val becomes large + val. 1009 cananian 1.5 // okay, raise it! 1010 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), new xBitWidth(q.evalType(), m, p) ); 1011 cananian 1.1.2.1 } 1012 cananian 1.5 public void visit_iadd(OPER q) { visit_add(q, 32); } 1013 cananian 1.5 public void visit_ladd(OPER q) { visit_add(q, 64); } 1014 cananian 1.1.2.1 1015 cananian 1.1.2.1 void visit_and(OPER q) { 1016 cananian 1.1.2.1 xBitWidth left = extractWidth( get( q.operands(0) ) ); 1017 cananian 1.1.2.1 xBitWidth right= extractWidth( get( q.operands(1) ) ); 1018 cananian 1.1.2.1 // if there are zero crossings, we have worst-case performance. 1019 cananian 1.1.2.1 int m = Math.max( left.minusWidth(), right.minusWidth() ); 1020 cananian 1.1.2.1 int p = Math.max( left.plusWidth(), right.plusWidth() ); 1021 cananian 1.1.2.1 // check for special positive-number cases. 1022 cananian 1.1.2.1 if (left.minusWidth()==0 && right.minusWidth()==0) 1023 cananian 1.1.2.1 p = Math.min( left.plusWidth(), right.plusWidth() ); 1024 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), new xBitWidth(q.evalType(), m, p) ); 1025 cananian 1.1.2.1 } 1026 cananian 1.1.2.1 public void visit_iand(OPER q) { visit_and(q); } 1027 cananian 1.1.2.1 public void visit_land(OPER q) { visit_and(q); } 1028 cananian 1.1.2.1 1029 cananian 1.1.2.1 void visit_div(OPER q) { 1030 cananian 1.1.2.1 // we can ignore divide-by-zero. 1031 cananian 1.1.2.1 xBitWidth left = extractWidth( get( q.operands(0) ) ); 1032 cananian 1.1.2.1 xBitWidth right= extractWidth( get( q.operands(1) ) ); 1033 cananian 1.1.2.1 // worst case: either number both pos and neg 1034 cananian 1.1.2.1 int m = Math.max(left.minusWidth(), left.plusWidth()); 1035 cananian 1.1.2.1 int p = Math.max(left.minusWidth(), left.plusWidth()); 1036 cananian 1.1.2.1 // check for special one-quadrant cases. 1037 cananian 1.1.2.1 if (left.minusWidth()==0) { 1038 cananian 1.1.2.1 if (right.minusWidth()==0) m=0; // result positive 1039 cananian 1.1.2.1 if (right.plusWidth()==0) p=0; // result negative 1040 cananian 1.1.2.1 } 1041 cananian 1.1.2.1 if (left.plusWidth()==0) { 1042 cananian 1.1.2.1 if (right.minusWidth()==0) m=0; // result negative 1043 cananian 1.1.2.1 if (right.plusWidth()==0) p=0; // result positive 1044 cananian 1.1.2.1 } 1045 cananian 1.1.2.1 // special case if divisor is a constant. 1046 cananian 1.1.2.1 if (right instanceof xIntConstant) { 1047 cananian 1.1.2.1 if (right.minusWidth()==0) { // a positive constant 1048 cananian 1.1.2.1 m = Math.max(0, left.minusWidth() - right.plusWidth()); 1049 cananian 1.1.2.1 p = Math.max(0, left.plusWidth() - right.plusWidth()); 1050 cananian 1.1.2.1 } 1051 cananian 1.1.2.1 if (right.plusWidth()==0) { // a negative constant 1052 cananian 1.1.2.1 m = Math.max(0, left.minusWidth()-right.minusWidth()); 1053 cananian 1.1.2.1 p = Math.max(0, left.plusWidth() -right.minusWidth()); 1054 cananian 1.1.2.1 } 1055 cananian 1.1.2.1 } 1056 cananian 1.5 // XXX overflow? 1057 cananian 1.1.2.1 // done. 1058 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), new xBitWidth(q.evalType(), m, p) ); 1059 cananian 1.1.2.1 } 1060 cananian 1.1.2.1 public void visit_idiv(OPER q) { visit_div(q); } 1061 cananian 1.1.2.1 public void visit_ldiv(OPER q) { visit_div(q); } 1062 cananian 1.1.2.1 1063 cananian 1.5 void visit_mul(OPER q, int maxbits) { 1064 cananian 1.1.2.1 xBitWidth left = extractWidth( get( q.operands(0) ) ); 1065 cananian 1.1.2.1 xBitWidth right= extractWidth( get( q.operands(1) ) ); 1066 cananian 1.1.2.1 // worst case: either number both pos and neg 1067 cananian 1.1.2.1 int m = Math.max(left.minusWidth() + right.plusWidth(), 1068 cananian 1.1.2.1 left.plusWidth() + right.minusWidth()); 1069 cananian 1.1.2.1 int p = Math.max(left.minusWidth() + right.minusWidth(), 1070 cananian 1.1.2.1 left.plusWidth() + right.plusWidth()); 1071 cananian 1.1.2.1 // special case multiplication by zero, one, and two. 1072 cananian 1.1.2.26 if (right instanceof xIntConstant) { // switch r and l 1073 cananian 1.1.2.26 xBitWidth temp=left; left=right; right=temp; 1074 cananian 1.1.2.26 } 1075 cananian 1.1.2.1 if (left instanceof xIntConstant) { 1076 cananian 1.1.2.1 long val = ((xIntConstant)left).value(); 1077 cananian 1.1.2.1 if (val==0) { 1078 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), left); return; 1079 cananian 1.1.2.1 } 1080 cananian 1.1.2.1 if (val==1) { 1081 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), right); return; 1082 cananian 1.1.2.1 } 1083 cananian 1.1.2.1 if (val==2) { 1084 cananian 1.1.2.1 m = right.minusWidth()+1; 1085 cananian 1.1.2.1 p = right.plusWidth() +1; 1086 cananian 1.1.2.1 } 1087 cananian 1.1.2.1 } 1088 cananian 1.1.2.1 // XXX special case multiplication by one-bit quantities? 1089 cananian 1.5 // handle overflow. 1090 cananian 1.5 if (p >= maxbits) 1091 cananian 1.5 m = maxbits; // large + val becomes large - val. 1092 cananian 1.5 if (m >= maxbits) 1093 cananian 1.5 p = maxbits-1; // large - val becomes large + val. 1094 cananian 1.1.2.1 // done. 1095 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), new xBitWidth(q.evalType(), m, p) ); 1096 cananian 1.1.2.1 } 1097 cananian 1.5 public void visit_imul(OPER q) { visit_mul(q,32); } 1098 cananian 1.5 public void visit_lmul(OPER q) { visit_mul(q,64); } 1099 cananian 1.1.2.1 1100 cananian 1.5 void visit_neg(OPER q, int maxbits) { 1101 cananian 1.1.2.1 xBitWidth bw = extractWidth( get( q.operands(0) ) ); 1102 cananian 1.1.2.1 int m = bw.plusWidth(); 1103 cananian 1.1.2.1 int p = bw.minusWidth(); 1104 cananian 1.5 // special case: negating the largest neg num results in neg 1105 cananian 1.5 if (bw.minusWidth() >= maxbits) 1106 cananian 1.5 m = maxbits; // -X = X for largest negative number 1107 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), new xBitWidth(q.evalType(), m, p) ); 1108 cananian 1.1.2.1 } 1109 cananian 1.5 public void visit_ineg(OPER q) { visit_neg(q, 32); } 1110 cananian 1.5 public void visit_lneg(OPER q) { visit_neg(q, 64); } 1111 cananian 1.1.2.5 1112 cananian 1.1.2.5 void visit_or(OPER q) { 1113 cananian 1.1.2.5 xBitWidth left = extractWidth( get( q.operands(0) ) ); 1114 cananian 1.1.2.5 xBitWidth right= extractWidth( get( q.operands(1) ) ); 1115 cananian 1.1.2.5 // if there are zero crossings, we have worst-case performance. 1116 cananian 1.1.2.5 // XXX: check this "worst-case" computation; might be overly 1117 cananian 1.1.2.5 // conservative. If definitely correct for the 1118 cananian 1.1.2.5 // positive-number-only case. 1119 cananian 1.1.2.5 int m = Math.max( left.minusWidth(), right.minusWidth() ); 1120 cananian 1.1.2.5 int p = Math.max( left.plusWidth(), right.plusWidth() ); 1121 cananian 1.1.2.5 raiseV(V, Wv, q.dst(), new xBitWidth(q.evalType(), m, p) ); 1122 cananian 1.1.2.5 } 1123 cananian 1.1.2.5 public void visit_ior(OPER q) { visit_or(q); } 1124 cananian 1.1.2.5 public void visit_lor(OPER q) { visit_or(q); } 1125 cananian 1.1.2.26 1126 cananian 1.1.2.26 void visit_rem(OPER q) { 1127 cananian 1.1.2.26 // we don't have to worry about division by zero. 1128 cananian 1.1.2.26 xBitWidth left = extractWidth( get( q.operands(0) ) ); 1129 cananian 1.1.2.26 xBitWidth right= extractWidth( get( q.operands(1) ) ); 1130 cananian 1.1.2.26 // from JLS 15.17.3: "the result of the remainder 1131 cananian 1.1.2.26 // operation can be negative only if the dividend is 1132 cananian 1.1.2.26 // negative, and can be positive only if the dividend 1133 cananian 1.1.2.26 // is positive; moreover, the magnitude of the result 1134 cananian 1.1.2.26 // is always less than the magnitude of the divisor." 1135 cananian 1.1.2.26 if (right instanceof xIntConstant) { 1136 cananian 1.1.2.26 // use the fact that result is strictly less to narrow 1137 cananian 1.1.2.26 long val = ((xIntConstant)right).value(); 1138 cananian 1.1.2.26 right = new xIntConstant(right.type(), val-1 ); 1139 cananian 1.1.2.26 } 1140 cananian 1.1.2.26 int absmag=Math.max(left.minusWidth(), left.plusWidth()); 1141 cananian 1.1.2.26 // abs value of result will also always be smaller than 1142 cananian 1.1.2.26 // abs value of dividend. 1143 cananian 1.1.2.26 int m = Math.min(right.minusWidth(), absmag); 1144 cananian 1.1.2.26 int p = Math.min(right.plusWidth(), absmag); 1145 cananian 1.5 // XXX overflow? 1146 cananian 1.1.2.26 raiseV(V, Wv, q.dst(), new xBitWidth(q.evalType(), m, p) ); 1147 cananian 1.1.2.26 } 1148 cananian 1.1.2.26 public void visit_irem(OPER q) { visit_rem(q); } 1149 cananian 1.1.2.26 public void visit_lrem(OPER q) { visit_rem(q); } 1150 cananian 1.1.2.26 1151 cananian 1.1.2.26 // SHIFTS. From the JLS, 15.19: "If the promoted type of 1152 cananian 1.1.2.26 // the left-hand operand is int, only the five 1153 cananian 1.1.2.26 // lowest-order bits of the right-hand operand are used as 1154 cananian 1.1.2.26 // the shift distance. It is as if the right-hand operand 1155 cananian 1.1.2.26 // were subjected to a bitwise logical AND operator & 1156 cananian 1.1.2.26 // (15.22.1) with the mask value 0x1f. The shift distance 1157 cananian 1.1.2.26 // actually used is therefore always in the range 0 to 31, 1158 cananian 1.1.2.26 // inclusive. 1159 cananian 1.1.2.26 // 1160 cananian 1.1.2.26 // "If the promoted type of the left-hand operand is long, 1161 cananian 1.1.2.26 // then only the six lowest-order bits of the right-hand 1162 cananian 1.1.2.26 // operand are used as the shift distance. It is as if the 1163 cananian 1.1.2.26 // right-hand operand were subjected to a bitwise logical 1164 cananian 1.1.2.26 // AND operator & (15.22.1) with the mask value 0x3f. The 1165 cananian 1.1.2.26 // shift distance actually used is therefore always in the 1166 cananian 1.1.2.26 // range 0 to 63, inclusive." 1167 cananian 1.1.2.26 1168 cananian 1.1.2.26 void visit_shl(OPER q, boolean isLong) { 1169 cananian 1.1.2.26 xBitWidth left = extractWidth( get( q.operands(0) ) ); 1170 cananian 1.1.2.26 xBitWidth right= extractWidth( get( q.operands(1) ) ); 1171 cananian 1.1.2.26 int shift; 1172 cananian 1.1.2.26 // compute largest possible shift. 1173 cananian 1.1.2.26 if (right instanceof xIntConstant) { 1174 cananian 1.1.2.26 // we know the shift exactly. whoo-hoo! 1175 cananian 1.1.2.26 long val = ((xIntConstant)right).value(); 1176 cananian 1.1.2.26 shift = (int) (val & (isLong ? 0x3F : 0x1F )); 1177 cananian 1.1.2.26 // equivalent to mult by constant 2^shift. 1178 cananian 1.1.2.26 } else if (right.minusWidth()==0 && 1179 cananian 1.1.2.26 right.plusWidth() < (isLong ? 6 : 5)) { 1180 cananian 1.1.2.26 //largest value possible on right is (2^p)-1. 1181 cananian 1.1.2.26 shift = (1<<right.plusWidth())-1; 1182 cananian 1.1.2.26 } else 1183 cananian 1.1.2.26 shift = (isLong) ? 63 : 31; 1184 cananian 1.1.2.26 // okay. nominally widths are width+shift. 1185 cananian 1.1.2.26 int m = left.minusWidth()+shift; 1186 cananian 1.1.2.26 int p = left.plusWidth()+shift; 1187 cananian 1.1.2.26 // zero shifted by anything is still zero, though. 1188 cananian 1.1.2.26 if (left.minusWidth()==0) m=0; 1189 cananian 1.1.2.26 if (left.plusWidth()==0) p=0; 1190 cananian 1.1.2.26 // if we could corrupt the sign bit, all bets are off. 1191 cananian 1.1.2.26 boolean canFrobSign = 1192 cananian 1.1.2.26 /* can leftmost one move into sign bit? */ 1193 cananian 1.1.2.26 ( (left.plusWidth()+shift) >= (isLong?64:32) ) || 1194 cananian 1.1.2.26 /* can leftmost zero move into sign bit? */ 1195 cananian 1.1.2.26 ( (left.minusWidth()+shift) >= (isLong?64:32) ); 1196 cananian 1.1.2.26 if (canFrobSign) { m=1000; p=1000; } 1197 cananian 1.1.2.26 // rely on bitwidth limiting the below. 1198 cananian 1.1.2.26 raiseV(V, Wv, q.dst(), new xBitWidth(q.evalType(), m, p) ); 1199 cananian 1.1.2.26 } 1200 cananian 1.1.2.26 public void visit_ishl(OPER q) { visit_shl(q, false); } 1201 cananian 1.1.2.26 public void visit_lshl(OPER q) { visit_shl(q, true); } 1202 cananian 1.1.2.26 1203 cananian 1.1.2.26 void visit_shr(OPER q, boolean isSigned, boolean isLong) { 1204 cananian 1.1.2.26 xBitWidth left = extractWidth( get( q.operands(0) ) ); 1205 cananian 1.1.2.26 xBitWidth right= extractWidth( get( q.operands(1) ) ); 1206 cananian 1.1.2.26 int shift; boolean exactlyZero=false; 1207 cananian 1.1.2.26 // compute smallest possible shift. 1208 cananian 1.1.2.26 if (right instanceof xIntConstant) { 1209 cananian 1.1.2.26 // we know the shift exactly. whoo-hoo! 1210 cananian 1.1.2.26 long val = ((xIntConstant)right).value(); 1211 cananian 1.1.2.26 shift = (int) (val & (isLong ? 0x3F : 0x1F )); 1212 cananian 1.1.2.26 if (shift==0) exactlyZero=true; 1213 cananian 1.1.2.26 } else 1214 cananian 1.1.2.26 // smallest possible shift is zero. 1215 cananian 1.1.2.26 shift = 0; 1216 cananian 1.1.2.26 // okay. nominally widths are width-shift. 1217 cananian 1.1.2.26 int m = Math.max(0, left.minusWidth()-shift); 1218 cananian 1.1.2.26 int p = Math.max(0, left.plusWidth()-shift); 1219 cananian 1.1.2.26 // zero shifted by anything is still zero, though. 1220 cananian 1.1.2.26 if (left.minusWidth()==0) m=0; 1221 cananian 1.1.2.26 if (left.plusWidth()==0) p=0; 1222 cananian 1.1.2.26 // if we could corrupt the sign bit, negative numbers 1223 cananian 1.1.2.26 // can become large positive numbers. 1224 cananian 1.1.2.26 if (left.minusWidth()>0 && !isSigned && !exactlyZero) 1225 cananian 1.1.2.26 p=Math.max(p, (isLong?64:32)-shift); 1226 cananian 1.1.2.26 // rely on bitwidth limiting the below. 1227 cananian 1.1.2.26 raiseV(V, Wv, q.dst(), new xBitWidth(q.evalType(), m, p) ); 1228 cananian 1.1.2.26 } 1229 cananian 1.1.2.26 public void visit_ishr(OPER q) { visit_shr(q, false, false); } 1230 cananian 1.1.2.26 public void visit_lshr(OPER q) { visit_shr(q, false, true); } 1231 cananian 1.1.2.26 public void visit_iushr(OPER q) { visit_shr(q, true, false); } 1232 cananian 1.1.2.26 public void visit_lushr(OPER q) { visit_shr(q, true, true); } 1233 cananian 1.1.2.26 1234 cananian 1.1.2.26 void visit_xor(OPER q) { 1235 cananian 1.1.2.26 xBitWidth left = extractWidth( get( q.operands(0) ) ); 1236 cananian 1.1.2.26 xBitWidth right= extractWidth( get( q.operands(1) ) ); 1237 cananian 1.1.2.26 int mL=left.minusWidth(), pL=left.plusWidth(); 1238 cananian 1.1.2.26 int mR=right.minusWidth(), pR=right.plusWidth(); 1239 cananian 1.1.2.26 int m=0, p=0; 1240 cananian 1.1.2.26 // note that <0,0>=constant zero is included in plus range 1241 cananian 1.1.2.26 // (i.e. all ranges are said to have '+' components (the 0) ) 1242 cananian 1.1.2.26 // <0,pL> xor <0,pR> = <0,MAX(pL,pR)> 1243 cananian 1.1.2.26 if (pL>=0 && pR>=0) 1244 cananian 1.1.2.26 p = Math.max(p, Math.max(pL, pR)); 1245 cananian 1.1.2.26 // <0,pL> xor <mR,0> = <MAX(pL,mR),0> 1246 cananian 1.1.2.26 if (pL>=0 && mR>0) 1247 cananian 1.1.2.26 m = Math.max(m, Math.max(pL, mR)); 1248 cananian 1.1.2.26 // <mL,0> xor <0,pR> = <MAX(mL,pR),0> 1249 cananian 1.1.2.26 if (mL>0 && pR>=0) 1250 cananian 1.1.2.26 m = Math.max(m, Math.max(mL, pR)); 1251 cananian 1.1.2.26 // <mL,0> xor <mR,0> = <0,MAX(mL,mR)> 1252 cananian 1.1.2.26 if (mL>0 && mR>0) 1253 cananian 1.1.2.26 p = Math.max(p, Math.max(mL, mR)); 1254 cananian 1.1.2.26 // ta-da! 1255 cananian 1.1.2.26 raiseV(V, Wv, q.dst(), new xBitWidth(q.evalType(), m, p) ); 1256 cananian 1.1.2.26 } 1257 cananian 1.1.2.26 public void visit_ixor(OPER q) { visit_xor(q); } 1258 cananian 1.1.2.26 public void visit_lxor(OPER q) { visit_xor(q); } 1259 cananian 1.1.2.1 } 1260 cananian 1.1.2.1 } 1261 cananian 1.1.2.1 /*-------------------------------------------------------------*/ 1262 cananian 1.1.2.1 // Extract bitwidth information from unwilling victims. 1263 cananian 1.1.2.1 xBitWidth extractWidth(LatticeVal v) { 1264 cananian 1.1.2.1 if (v instanceof xBitWidth) 1265 cananian 1.1.2.1 return (xBitWidth) v; 1266 cananian 1.1.2.1 if (! (v instanceof xClass) ) 1267 cananian 1.1.2.1 throw new Error("Something's seriously screwed up."); 1268 cananian 1.1.2.1 xClass xc = (xClass) v; 1269 cananian 1.1.2.1 // trust xBitWidth to properly limit. 1270 cananian 1.1.2.1 return new xBitWidth(xc.type(), 1000, 1000); 1271 cananian 1.1.2.1 } 1272 cananian 1.1.2.1 1273 cananian 1.1.2.1 // Deal with the fact that external Byte/Short/Char/Boolean classes 1274 cananian 1.1.2.1 // are represented internally as ints. 1275 cananian 1.1.2.1 1276 cananian 1.1.2.1 static HClass toInternal(HClass c) { 1277 cananian 1.1.2.1 if (c.equals(HClass.Byte) || c.equals(HClass.Short) || 1278 cananian 1.1.2.1 c.equals(HClass.Char) || c.equals(HClass.Boolean)) 1279 cananian 1.1.2.1 return HClass.Int; 1280 cananian 1.1.2.1 return c; 1281 cananian 1.1.2.1 } 1282 cananian 1.1.2.1 1283 cananian 1.1.2.1 /*-------------------------------------------------------------*/ 1284 cananian 1.1.2.1 // Lattice classes. 1285 cananian 1.1.2.1 1286 cananian 1.1.2.1 /** No information obtainable about a temp. */ 1287 cananian 1.1.2.21 static abstract class LatticeVal { 1288 cananian 1.1.2.1 public String toString() { return "Top"; } 1289 cananian 1.1.2.1 public boolean equals(Object o) { return o instanceof LatticeVal; } 1290 cananian 1.1.2.21 // merge. 1291 cananian 1.1.2.21 public abstract LatticeVal merge(LatticeVal v); 1292 cananian 1.1.2.23 // narrow. 1293 cananian 1.1.2.23 public abstract boolean isLowerThan(LatticeVal v); 1294 cananian 1.1.2.16 // by default, the renaming does nothing. 1295 cananian 1.1.2.16 public LatticeVal rename(PHI p, int i) { return this; } 1296 cananian 1.1.2.16 public LatticeVal rename(SIGMA s, int i) { return this; } 1297 cananian 1.1.2.1 } 1298 cananian 1.1.2.1 /** A typed temp. */ 1299 cananian 1.1.2.1 static class xClass extends LatticeVal { 1300 cananian 1.1.2.1 protected HClass type; 1301 cananian 1.1.2.1 public xClass(HClass type) { 1302 cananian 1.3.2.1 assert type!=HClass.Boolean && type!=HClass.Byte && 1303 cananian 1.3.2.1 type!=HClass.Short && type!=HClass.Char : "Not an internal type ("+type+")"; 1304 cananian 1.1.2.1 this.type = type; 1305 cananian 1.1.2.1 } 1306 cananian 1.1.2.1 public HClass type() { return type; } 1307 cananian 1.1.2.1 public String toString() { 1308 cananian 1.1.2.1 return "xClass: " + type; 1309 cananian 1.1.2.1 } 1310 cananian 1.1.2.21 public boolean equals(Object o) { return _equals(o); } 1311 cananian 1.1.2.21 private boolean _equals(Object o) { 1312 cananian 1.1.2.1 xClass xc; 1313 cananian 1.1.2.1 try { xc=(xClass) o; } 1314 cananian 1.1.2.1 catch (ClassCastException e) { return false;} 1315 cananian 1.1.2.1 return xc!=null && xc.type.equals(type); 1316 cananian 1.1.2.1 } 1317 cananian 1.1.2.21 public LatticeVal merge(LatticeVal v) { 1318 cananian 1.1.2.21 xClass vv = (xClass) v; 1319 cananian 1.1.2.21 return new xClass(mergeTypes(this.type, vv.type)); 1320 cananian 1.1.2.21 } 1321 cananian 1.1.2.23 public boolean isLowerThan(LatticeVal v) { 1322 cananian 1.1.2.23 return !(v instanceof xClass); 1323 cananian 1.1.2.23 } 1324 cananian 1.1.2.21 // Class merge function. 1325 cananian 1.1.2.21 static HClass mergeTypes(HClass a, HClass b) { 1326 cananian 1.3.2.1 assert a!=null && b!=null; 1327 cananian 1.1.2.21 if (a==b) return a; // take care of primitive types. 1328 cananian 1.1.2.21 1329 cananian 1.1.2.21 // Special case 'Void' Hclass, used for null constants. 1330 cananian 1.1.2.21 if (a==HClass.Void) 1331 cananian 1.1.2.21 return b; 1332 cananian 1.1.2.21 if (b==HClass.Void) 1333 cananian 1.1.2.21 return a; 1334 cananian 1.1.2.21 1335 cananian 1.1.2.21 // by this point better be array ref or object, not primitive type. 1336 cananian 1.3.2.1 assert (!a.isPrimitive()) && (!b.isPrimitive()); 1337 cananian 1.1.2.21 return HClassUtil.commonParent(a,b); 1338 cananian 1.1.2.1 } 1339 cananian 1.1.2.1 } 1340 cananian 1.1.2.1 /** A single class type; guaranteed the value is not null. */ 1341 cananian 1.1.2.1 static class xClassNonNull extends xClass { 1342 cananian 1.1.2.1 public xClassNonNull(HClass type) { 1343 cananian 1.1.2.1 super( type ); 1344 cananian 1.3.2.1 assert type!=HClass.Void; 1345 cananian 1.1.2.1 } 1346 cananian 1.1.2.1 public String toString() { 1347 cananian 1.1.2.1 return "xClassNonNull: { " + type + " }"; 1348 cananian 1.1.2.1 } 1349 cananian 1.1.2.21 public boolean equals(Object o) { return _equals(o); } 1350 cananian 1.1.2.21 private boolean _equals(Object o) { 1351 cananian 1.1.2.1 return (o instanceof xClassNonNull && super.equals(o)); 1352 cananian 1.1.2.1 } 1353 cananian 1.1.2.21 public LatticeVal merge(LatticeVal v) { 1354 cananian 1.1.2.21 if (!(v instanceof xClassNonNull)) return super.merge(v); 1355 cananian 1.1.2.21 xClassNonNull vv = (xClassNonNull) v; 1356 cananian 1.1.2.21 return new xClassNonNull(mergeTypes(this.type, vv.type)); 1357 cananian 1.1.2.1 } 1358 cananian 1.1.2.23 public boolean isLowerThan(LatticeVal v) { 1359 cananian 1.1.2.23 return !(v instanceof xClassNonNull); 1360 cananian 1.1.2.23 } 1361 cananian 1.1.2.1 } 1362 cananian 1.1.2.11 /** An object of the specified *exact* type (not a subtype). */ 1363 cananian 1.1.2.11 static class xClassExact extends xClassNonNull { 1364 cananian 1.1.2.11 public xClassExact(HClass type) { 1365 cananian 1.1.2.11 super(type); 1366 cananian 1.6 assert !type.isInterface(); // interface types can't be exact. 1367 cananian 1.1.2.11 } 1368 cananian 1.1.2.11 public String toString() { 1369 cananian 1.1.2.11 return "xClassExact: { " + type + " }"; 1370 cananian 1.1.2.11 } 1371 cananian 1.1.2.21 public boolean equals(Object o) { return _equals(o); } 1372 cananian 1.1.2.21 private boolean _equals(Object o) { 1373 cananian 1.1.2.11 return (o instanceof xClassExact && super.equals(o)); 1374 cananian 1.1.2.11 } 1375 cananian 1.1.2.21 public LatticeVal merge(LatticeVal v) { 1376 cananian 1.1.2.21 if (this._equals(v)) return new xClassExact(type); 1377 cananian 1.1.2.21 return super.merge(v); 1378 cananian 1.1.2.11 } 1379 cananian 1.1.2.23 public boolean isLowerThan(LatticeVal v) { 1380 cananian 1.1.2.23 return !(v instanceof xClassExact); 1381 cananian 1.1.2.23 } 1382 cananian 1.1.2.11 } 1383 cananian 1.1.2.1 /** An array with constant length. The array is not null, of course. */ 1384 cananian 1.1.2.11 static class xClassArray extends xClassExact { 1385 cananian 1.1.2.1 protected int length; 1386 cananian 1.1.2.1 public xClassArray(HClass type, int length) { 1387 cananian 1.1.2.1 super(type); 1388 cananian 1.1.2.1 this.length = length; 1389 cananian 1.1.2.1 } 1390 cananian 1.1.2.1 public int length() { return length; } 1391 cananian 1.1.2.1 public String toString() { 1392 cananian 1.1.2.1 return "xClassArray: " + 1393 cananian 1.1.2.1 type.getComponentType() + "["+length+"]"; 1394 cananian 1.1.2.1 } 1395 cananian 1.1.2.21 public boolean equals(Object o) { return _equals(o); } 1396 cananian 1.1.2.21 private boolean _equals(Object o) { 1397 cananian 1.1.2.1 xClassArray xca; 1398 cananian 1.1.2.1 try { xca = (xClassArray) o; } 1399 cananian 1.1.2.1 catch (ClassCastException e) { return false; } 1400 cananian 1.1.2.1 return xca!=null && super.equals(xca) && xca.length == length; 1401 cananian 1.1.2.1 } 1402 cananian 1.1.2.21 public LatticeVal merge(LatticeVal v) { 1403 cananian 1.1.2.21 if (this._equals(v)) return new xClassArray(type,length); 1404 cananian 1.1.2.21 return super.merge(v); 1405 cananian 1.1.2.1 } 1406 cananian 1.1.2.23 public boolean isLowerThan(LatticeVal v) { 1407 cananian 1.1.2.23 return !(v instanceof xClassArray); 1408 cananian 1.1.2.23 } 1409 cananian 1.1.2.1 } 1410 cananian 1.1.2.1 /** An integer value of the specified bitwidth. */ 1411 cananian 1.1.2.11 static class xBitWidth extends xClassExact { 1412 cananian 1.1.2.1 /** Highest significant bit for positive numbers. */ 1413 cananian 1.1.2.1 protected int plusWidth; 1414 cananian 1.1.2.1 /** Highest significant bit for negative numbers. */ 1415 cananian 1.1.2.1 protected int minusWidth; 1416 cananian 1.1.2.1 /** Constructor. */ 1417 cananian 1.1.2.1 public xBitWidth(HClass type, int minusWidth, int plusWidth) { 1418 cananian 1.1.2.1 super(toInternal(type)); 1419 cananian 1.1.2.1 // limit. 1420 cananian 1.1.2.1 if (type == HClass.Long) { 1421 cananian 1.1.2.1 this.minusWidth = Math.min(64, minusWidth); 1422 cananian 1.1.2.1 this.plusWidth = Math.min(63, plusWidth); 1423 cananian 1.1.2.1 } else if (type == HClass.Int) { 1424 cananian 1.1.2.1 this.minusWidth = Math.min(32, minusWidth); 1425 cananian 1.1.2.1 this.plusWidth = Math.min(31, plusWidth); 1426 cananian 1.1.2.1 } else // NON-CANONICAL TYPES: CAREFUL! (this.type fixed by above) 1427 cananian 1.1.2.1 if (type == HClass.Boolean) { 1428 cananian 1.1.2.1 this.minusWidth = Math.min( 0, minusWidth); 1429 cananian 1.1.2.1 this.plusWidth = Math.min( 1, plusWidth); 1430 cananian 1.1.2.1 } else if (type == HClass.Short) { 1431 cananian 1.1.2.1 this.minusWidth = Math.min(16, minusWidth); 1432 cananian 1.1.2.1 this.plusWidth = Math.min(15, plusWidth); 1433 cananian 1.1.2.1 } else if (type == HClass.Byte) { 1434 cananian 1.1.2.1 this.minusWidth = Math.min( 8, minusWidth); 1435 cananian 1.1.2.1 this.plusWidth = Math.min( 7, plusWidth); 1436 cananian 1.1.2.1 } else if (type == HClass.Char) { 1437 cananian 1.1.2.1 this.minusWidth = Math.min( 0, minusWidth); 1438 cananian 1.1.2.1 this.plusWidth = Math.min(16, plusWidth); 1439 cananian 1.1.2.1 } else throw new Error("Unknown type for xBitWidth: "+type); 1440 cananian 1.1.2.1 } 1441 cananian 1.1.2.1 public int minusWidth() { return minusWidth; } 1442 cananian 1.1.2.1 public int plusWidth () { return plusWidth; } 1443 cananian 1.1.2.1 public String toString() { 1444 cananian 1.1.2.1 return "xBitWidth: " + type + " " + 1445 cananian 1.1.2.1 "-"+minusWidth+"+"+plusWidth+" bits"; 1446 cananian 1.1.2.1 } 1447 cananian 1.1.2.21 public boolean equals(Object o) { return _equals(o); } 1448 cananian 1.1.2.21 private boolean _equals(Object o) { 1449 cananian 1.1.2.1 xBitWidth xbw; 1450 cananian 1.1.2.1 try { xbw = (xBitWidth) o; } 1451 cananian 1.1.2.1 catch (ClassCastException e) { return false; } 1452 cananian 1.1.2.1 return xbw!=null && super.equals(xbw) && 1453 cananian 1.1.2.1 xbw.minusWidth == minusWidth && 1454 cananian 1.1.2.1 xbw.plusWidth == plusWidth; 1455 cananian 1.1.2.1 } 1456 cananian 1.1.2.21 public LatticeVal merge(LatticeVal v) { 1457 cananian 1.1.2.21 if (!(v instanceof xBitWidth)) return super.merge(v); 1458 cananian 1.1.2.21 // bitwidth merge 1459 cananian 1.1.2.21 xBitWidth vv = (xBitWidth) v; 1460 cananian 1.1.2.21 if (!this.type.equals(vv.type)) return super.merge(vv); 1461 cananian 1.1.2.21 return new xBitWidth 1462 cananian 1.1.2.21 (this.type, 1463 cananian 1.1.2.21 Math.max(this.minusWidth, vv.minusWidth), 1464 cananian 1.1.2.21 Math.max(this.plusWidth, vv.plusWidth)); 1465 cananian 1.1.2.16 } 1466 cananian 1.1.2.23 public boolean isLowerThan(LatticeVal v) { 1467 cananian 1.1.2.23 return !(v instanceof xBitWidth); 1468 cananian 1.1.2.23 } 1469 cananian 1.1.2.16 } 1470 cananian 1.1.2.16 /** An integer value which is the result of an INSTANCEOF. */ 1471 cananian 1.1.2.22 static class xInstanceofResultUnknown extends xBitWidth 1472 cananian 1.1.2.22 implements xInstanceofResult { 1473 cananian 1.1.2.16 Temp tested; 1474 cananian 1.1.2.16 INSTANCEOF q; 1475 cananian 1.1.2.22 public xInstanceofResultUnknown(INSTANCEOF q) { this(q, q.src()); } 1476 cananian 1.1.2.22 xInstanceofResultUnknown(INSTANCEOF q, Temp tested) { 1477 cananian 1.1.2.16 super(toInternal(HClass.Boolean),0,1); 1478 cananian 1.1.2.16 this.q = q; 1479 cananian 1.1.2.16 this.tested = tested; 1480 cananian 1.1.2.16 } 1481 cananian 1.1.2.16 public Temp tested() { return tested; } 1482 cananian 1.1.2.16 public INSTANCEOF def() { return q; } 1483 cananian 1.1.2.16 public String toString() { 1484 cananian 1.1.2.22 return "xInstanceofResultUnknown: " + type + " " +q; 1485 cananian 1.1.2.16 } 1486 cananian 1.1.2.21 public boolean equals(Object o) { return _equals(o); } 1487 cananian 1.1.2.21 private boolean _equals(Object o) { 1488 cananian 1.1.2.22 return (o instanceof xInstanceofResultUnknown && super.equals(o) && 1489 cananian 1.1.2.22 ((xInstanceofResultUnknown)o).q == q && 1490 cananian 1.1.2.22 ((xInstanceofResultUnknown)o).tested == tested); 1491 cananian 1.1.2.16 } 1492 cananian 1.1.2.21 public LatticeVal merge(LatticeVal v) { 1493 cananian 1.1.2.22 if (v instanceof xInstanceofResult) 1494 cananian 1.1.2.22 // xInstanceofResultKnown merged with 1495 cananian 1.1.2.22 // xInstanceofResultKnown or xInstanceofResultUnknown 1496 cananian 1.1.2.22 return makeUnknown(); 1497 cananian 1.1.2.22 // all others. 1498 cananian 1.1.2.21 return super.merge(v); 1499 cananian 1.1.2.16 } 1500 cananian 1.1.2.23 public boolean isLowerThan(LatticeVal v) { 1501 cananian 1.1.2.23 return !(v instanceof xBitWidth); 1502 cananian 1.1.2.23 } 1503 cananian 1.1.2.22 public xInstanceofResultKnown makeKnown(boolean nvalue) { 1504 cananian 1.1.2.22 return new xInstanceofResultKnown(q,tested,nvalue?1:0); 1505 cananian 1.1.2.22 } 1506 cananian 1.1.2.22 public xInstanceofResultUnknown makeUnknown() { 1507 cananian 1.1.2.22 return new xInstanceofResultUnknown(q,tested); 1508 cananian 1.1.2.22 } 1509 cananian 1.1.2.16 // override renaming functions. 1510 cananian 1.1.2.16 public LatticeVal rename(PHI q, int j) { 1511 cananian 1.1.2.16 for (int i=0; i<q.numPhis(); i++) 1512 cananian 1.1.2.16 if (q.src(i, j)==this.tested) 1513 cananian 1.1.2.22 return new xInstanceofResultUnknown(def(), q.dst(i)); 1514 cananian 1.1.2.16 return this; 1515 cananian 1.1.2.16 } 1516 cananian 1.1.2.16 public LatticeVal rename(SIGMA q, int j) { 1517 cananian 1.1.2.16 for (int i=0; i<q.numSigmas(); i++) 1518 cananian 1.1.2.16 if (q.src(i)==this.tested) 1519 cananian 1.1.2.22 return new xInstanceofResultUnknown(def(), q.dst(i, j)); 1520 cananian 1.1.2.16 return this; 1521 cananian 1.1.2.16 } 1522 cananian 1.1.2.16 } 1523 cananian 1.1.2.22 /** An unknown boolean value which is the result of an OPER. */ 1524 cananian 1.1.2.22 static class xOperBooleanResultUnknown extends xBitWidth 1525 cananian 1.1.2.22 implements xOperBooleanResult { 1526 cananian 1.1.2.16 OPER q; 1527 cananian 1.1.2.16 Temp[] operands; 1528 cananian 1.1.2.22 public xOperBooleanResultUnknown(OPER q) { this(q, q.operands()); } 1529 cananian 1.1.2.22 xOperBooleanResultUnknown(OPER q, Temp[] operands) { 1530 cananian 1.1.2.16 super(toInternal(HClass.Boolean),0,1); 1531 cananian 1.1.2.16 this.q = q; 1532 cananian 1.1.2.16 this.operands = operands; 1533 cananian 1.1.2.16 } 1534 cananian 1.1.2.16 public Temp[] operands() { return operands; } 1535 cananian 1.1.2.16 public OPER def() { return q; } 1536 cananian 1.1.2.16 public String toString() { 1537 cananian 1.1.2.22 return "xOperBooleanResultUnknown: " + type + " " +q; 1538 cananian 1.1.2.16 } 1539 cananian 1.1.2.21 public boolean equals(Object o) { return _equals(o); } 1540 cananian 1.1.2.21 private boolean _equals(Object o) { 1541 cananian 1.1.2.16 if (o==this) return true; // common case. 1542 cananian 1.1.2.22 if (!(o instanceof xOperBooleanResultUnknown)) return false; 1543 cananian 1.1.2.16 if (!super.equals(o)) return false; 1544 cananian 1.1.2.22 xOperBooleanResultUnknown oo = (xOperBooleanResultUnknown)o; 1545 cananian 1.1.2.16 if (oo.q != q) return false; 1546 cananian 1.1.2.16 if (oo.operands.length != operands.length) return false; 1547 cananian 1.1.2.16 for (int i=0; i<operands.length; i++) 1548 cananian 1.1.2.16 if (oo.operands[i] != operands[i]) return false; 1549 cananian 1.1.2.16 return true; 1550 cananian 1.1.2.16 } 1551 cananian 1.1.2.21 public LatticeVal merge(LatticeVal v) { 1552 cananian 1.1.2.22 if (v instanceof xOperBooleanResult) 1553 cananian 1.1.2.22 // xOperBooleanResultKnown merged with 1554 cananian 1.1.2.22 // xOperBooleanResultKnown or xOperBooleanResultUnknown 1555 cananian 1.1.2.22 return makeUnknown(); 1556 cananian 1.1.2.22 // all others. 1557 cananian 1.1.2.21 return super.merge(v); 1558 cananian 1.1.2.16 } 1559 cananian 1.1.2.23 public boolean isLowerThan(LatticeVal v) { 1560 cananian 1.1.2.23 return !(v instanceof xBitWidth); 1561 cananian 1.1.2.23 } 1562 cananian 1.1.2.22 public xOperBooleanResultKnown makeKnown(boolean nvalue) { 1563 cananian 1.1.2.22 return new xOperBooleanResultKnown(q,operands,nvalue?1:0); 1564 cananian 1.1.2.22 } 1565 cananian 1.1.2.22 public xOperBooleanResultUnknown makeUnknown() { 1566 cananian 1.1.2.22 return new xOperBooleanResultUnknown(q,operands); 1567 cananian 1.1.2.22 } 1568 cananian 1.1.2.16 // override renaming functions. 1569 cananian 1.1.2.16 public LatticeVal rename(PHI q, int j) { 1570 cananian 1.1.2.16 MyTempMap mtm = new MyTempMap(); 1571 cananian 1.1.2.16 for (int i=0; i<q.numPhis(); i++) 1572 cananian 1.1.2.16 mtm.put(q.src(i,j), q.dst(i)); 1573 cananian 1.1.2.22 return new xOperBooleanResultUnknown(def(), mtm.tempMap(operands())); 1574 cananian 1.1.2.16 } 1575 cananian 1.1.2.16 public LatticeVal rename(SIGMA q, int j) { 1576 cananian 1.1.2.16 MyTempMap mtm = new MyTempMap(); 1577 cananian 1.1.2.16 for (int i=0; i<q.numSigmas(); i++) 1578 cananian 1.1.2.16 mtm.put(q.src(i), q.dst(i, j)); 1579 cananian 1.1.2.22 return new xOperBooleanResultUnknown(def(), mtm.tempMap(operands())); 1580 cananian 1.1.2.16 } 1581 cananian 1.1.2.16 private static class MyTempMap extends HashMap implements TempMap { 1582 cananian 1.1.2.16 public Temp tempMap(Temp t) { 1583 cananian 1.1.2.16 return containsKey(t) ? (Temp) get(t) : t; 1584 cananian 1.1.2.16 } 1585 cananian 1.1.2.16 public Temp[] tempMap(Temp[] t) { 1586 cananian 1.1.2.16 Temp[] r = new Temp[t.length]; 1587 cananian 1.1.2.16 for (int i=0; i<r.length; i++) 1588 cananian 1.1.2.16 r[i] = tempMap(t[i]); 1589 cananian 1.1.2.16 return r; 1590 cananian 1.1.2.16 } 1591 cananian 1.1.2.1 } 1592 cananian 1.1.2.1 } 1593 cananian 1.1.2.1 /** An integer or boolean constant. */ 1594 cananian 1.1.2.1 static class xIntConstant extends xBitWidth implements xConstant { 1595 cananian 1.1.2.1 protected long value; 1596 cananian 1.1.2.1 public xIntConstant(HClass type, long value) { 1597 cananian 1.1.2.1 super(type, value<0?Util.fls(-value):0, value>0?Util.fls(value):0); 1598 cananian 1.1.2.1 this.value = value; 1599 cananian 1.1.2.1 } 1600 cananian 1.1.2.1 public long value() { return value; } 1601 cananian 1.1.2.1 public Object constValue() { 1602 cananian 1.1.2.1 if (type==HClass.Int) return new Integer((int)value); 1603 cananian 1.1.2.1 if (type==HClass.Long) return new Long((long)value); 1604 cananian 1.1.2.1 //if (type==HClass.Boolean) return new Integer(value!=0?1:0); 1605 cananian 1.1.2.1 throw new Error("Unknown integer constant type."); 1606 cananian 1.1.2.1 } 1607 cananian 1.1.2.1 public String toString() { 1608 cananian 1.1.2.1 return "xIntConstant: " + type + " " + value; 1609 cananian 1.1.2.1 } 1610 cananian 1.1.2.21 public boolean equals(Object o) { return _equals(o); } 1611 cananian 1.1.2.21 private boolean _equals(Object o) { 1612 cananian 1.1.2.1 return (o instanceof xIntConstant && super.equals(o) && 1613 cananian 1.1.2.1 ((xIntConstant)o).value == value); 1614 cananian 1.1.2.1 } 1615 cananian 1.1.2.21 public LatticeVal merge(LatticeVal v) { 1616 cananian 1.1.2.21 if (this._equals(v)) return new xIntConstant(type,value); 1617 cananian 1.1.2.21 return super.merge(v); 1618 cananian 1.1.2.1 } 1619 cananian 1.1.2.23 public boolean isLowerThan(LatticeVal v) { 1620 cananian 1.1.2.23 return !(v instanceof xIntConstant); 1621 cananian 1.1.2.23 } 1622 cananian 1.1.2.1 } 1623 cananian 1.1.2.22 /** An integer value which is the result of an INSTANCEOF. */ 1624 cananian 1.1.2.22 static class xInstanceofResultKnown extends xIntConstant 1625 cananian 1.1.2.22 implements xInstanceofResult { 1626 cananian 1.1.2.22 Temp tested; 1627 cananian 1.1.2.22 INSTANCEOF q; 1628 cananian 1.1.2.22 public xInstanceofResultKnown(INSTANCEOF q, boolean value) { 1629 cananian 1.1.2.22 this(q, q.src(), value?1:0); 1630 cananian 1.1.2.22 } 1631 cananian 1.1.2.22 private xInstanceofResultKnown(INSTANCEOF q, Temp tested, long value) { 1632 cananian 1.1.2.22 super(toInternal(HClass.Boolean),value); 1633 cananian 1.1.2.22 this.q = q; 1634 cananian 1.1.2.22 this.tested = tested; 1635 cananian 1.3.2.1 assert value==0 || value==1; 1636 cananian 1.1.2.22 } 1637 cananian 1.1.2.22 public Temp tested() { return tested; } 1638 cananian 1.1.2.22 public INSTANCEOF def() { return q; } 1639 cananian 1.1.2.22 public String toString() { 1640 cananian 1.1.2.22 return "xInstanceofResultKnown: " + value + " " +q; 1641 cananian 1.1.2.22 } 1642 cananian 1.1.2.22 public boolean equals(Object o) { return _equals(o); } 1643 cananian 1.1.2.22 private boolean _equals(Object o) { 1644 cananian 1.1.2.22 return (o instanceof xInstanceofResultKnown && super.equals(o) && 1645 cananian 1.1.2.22 ((xInstanceofResultKnown)o).q == q && 1646 cananian 1.1.2.22 ((xInstanceofResultKnown)o).tested == tested); 1647 cananian 1.1.2.22 } 1648 cananian 1.1.2.22 public LatticeVal merge(LatticeVal v) { 1649 cananian 1.1.2.22 if (v instanceof xInstanceofResult) 1650 cananian 1.1.2.22 // xInstanceofResultKnown merged with 1651 cananian 1.1.2.22 // xInstanceofResultKnown or xInstanceofResultUnknown 1652 cananian 1.1.2.22 return this._equals(v) ? (LatticeVal) 1653 cananian 1.1.2.22 makeKnown(value!=0) : makeUnknown(); 1654 cananian 1.1.2.22 // all others. 1655 cananian 1.1.2.22 return super.merge(v); 1656 cananian 1.1.2.22 } 1657 cananian 1.1.2.23 public boolean isLowerThan(LatticeVal v) { 1658 cananian 1.1.2.23 return !(v instanceof xIntConstant); 1659 cananian 1.1.2.23 } 1660 cananian 1.1.2.22 public xInstanceofResultKnown makeKnown(boolean nvalue) { 1661 cananian 1.1.2.22 return new xInstanceofResultKnown(q,tested,nvalue?1:0); 1662 cananian 1.1.2.22 } 1663 cananian 1.1.2.22 public xInstanceofResultUnknown makeUnknown() { 1664 cananian 1.1.2.22 return new xInstanceofResultUnknown(q,tested); 1665 cananian 1.1.2.22 } 1666 cananian 1.1.2.22 // override renaming functions. 1667 cananian 1.1.2.22 public LatticeVal rename(PHI q, int j) { 1668 cananian 1.1.2.22 for (int i=0; i<q.numPhis(); i++) 1669 cananian 1.1.2.22 if (q.src(i, j)==this.tested) 1670 cananian 1.1.2.22 return new xInstanceofResultKnown(def(), q.dst(i), value); 1671 cananian 1.1.2.22 return this; 1672 cananian 1.1.2.22 } 1673 cananian 1.1.2.22 public LatticeVal rename(SIGMA q, int j) { 1674 cananian 1.1.2.22 for (int i=0; i<q.numSigmas(); i++) 1675 cananian 1.1.2.22 if (q.src(i)==this.tested) 1676 cananian 1.1.2.22 return new xInstanceofResultKnown(def(),q.dst(i, j),value); 1677 cananian 1.1.2.22 return this; 1678 cananian 1.1.2.22 } 1679 cananian 1.1.2.22 } 1680 cananian 1.1.2.22 /** A known boolean value which is the result of an OPER. */ 1681 cananian 1.1.2.22 static class xOperBooleanResultKnown extends xIntConstant 1682 cananian 1.1.2.22 implements xOperBooleanResult { 1683 cananian 1.1.2.22 OPER q; 1684 cananian 1.1.2.22 Temp[] operands; 1685 cananian 1.1.2.22 public xOperBooleanResultKnown(OPER q, boolean value) { 1686 cananian 1.1.2.22 this(q, q.operands(), value?1:0); 1687 cananian 1.1.2.22 } 1688 cananian 1.1.2.22 xOperBooleanResultKnown(OPER q, Temp[] operands, long value) 1689 cananian 1.1.2.22 { 1690 cananian 1.1.2.22 super(toInternal(HClass.Boolean),value); 1691 cananian 1.1.2.22 this.q = q; 1692 cananian 1.1.2.22 this.operands = operands; 1693 cananian 1.3.2.1 assert value==0 || value==1; 1694 cananian 1.1.2.22 } 1695 cananian 1.1.2.22 public Temp[] operands() { return operands; } 1696 cananian 1.1.2.22 public OPER def() { return q; } 1697 cananian 1.1.2.22 public String toString() { 1698 cananian 1.1.2.22 return "xOperBooleanResultKnown: " + value + " " +q; 1699 cananian 1.1.2.22 } 1700 cananian 1.1.2.22 public boolean equals(Object o) { return _equals(o); } 1701 cananian 1.1.2.22 private boolean _equals(Object o) { 1702 cananian 1.1.2.22 if (o==this) return true; // common case. 1703 cananian 1.1.2.22 if (!(o instanceof xOperBooleanResultKnown)) return false; 1704 cananian 1.1.2.22 if (!super.equals(o)) return false; 1705 cananian 1.1.2.22 xOperBooleanResultKnown oo = (xOperBooleanResultKnown)o; 1706 cananian 1.1.2.22 if (oo.q != q) return false; 1707 cananian 1.1.2.22 if (oo.operands.length != operands.length) return false; 1708 cananian 1.1.2.22 for (int i=0; i<operands.length; i++) 1709 cananian 1.1.2.22 if (oo.operands[i] != operands[i]) return false; 1710 cananian 1.1.2.22 return true; 1711 cananian 1.1.2.22 } 1712 cananian 1.1.2.22 public LatticeVal merge(LatticeVal v) { 1713 cananian 1.1.2.22 if (v instanceof xOperBooleanResult) 1714 cananian 1.1.2.22 // xOperBooleanResultKnown merged with 1715 cananian 1.1.2.22 // xOperBooleanResultKnown or xOperBooleanResultUnknown 1716 cananian 1.1.2.22 return this._equals(v) ? (LatticeVal) 1717 cananian 1.1.2.22 makeKnown(value!=0) : makeUnknown(); 1718 cananian 1.1.2.22 // all others. 1719 cananian 1.1.2.22 return super.merge(v); 1720 cananian 1.1.2.22 } 1721 cananian 1.1.2.23 public boolean isLowerThan(LatticeVal v) { 1722 cananian 1.1.2.23 return !(v instanceof xIntConstant); 1723 cananian 1.1.2.23 } 1724 cananian 1.1.2.22 public xOperBooleanResultKnown makeKnown(boolean nvalue) { 1725 cananian 1.1.2.22 return new xOperBooleanResultKnown(q,operands,nvalue?1:0); 1726 cananian 1.1.2.22 } 1727 cananian 1.1.2.22 public xOperBooleanResultUnknown makeUnknown() { 1728 cananian 1.1.2.22 return new xOperBooleanResultUnknown(q,operands); 1729 cananian 1.1.2.22 } 1730 cananian 1.1.2.22 // override renaming functions. 1731 cananian 1.1.2.22 public LatticeVal rename(PHI q, int j) { 1732 cananian 1.1.2.22 MyTempMap mtm = new MyTempMap(); 1733 cananian 1.1.2.22 for (int i=0; i<q.numPhis(); i++) 1734 cananian 1.1.2.22 mtm.put(q.src(i,j), q.dst(i)); 1735 cananian 1.1.2.22 return new xOperBooleanResultKnown(def(), mtm.tempMap(operands()), 1736 cananian 1.1.2.22 value); 1737 cananian 1.1.2.22 } 1738 cananian 1.1.2.22 public LatticeVal rename(SIGMA q, int j) { 1739 cananian 1.1.2.22 MyTempMap mtm = new MyTempMap(); 1740 cananian 1.1.2.22 for (int i=0; i<q.numSigmas(); i++) 1741 cananian 1.1.2.22 mtm.put(q.src(i), q.dst(i, j)); 1742 cananian 1.1.2.22 return new xOperBooleanResultKnown(def(), mtm.tempMap(operands()), 1743 cananian 1.1.2.22 value); 1744 cananian 1.1.2.22 } 1745 cananian 1.1.2.22 private static class MyTempMap extends HashMap implements TempMap { 1746 cananian 1.1.2.22 public Temp tempMap(Temp t) { 1747 cananian 1.1.2.22 return containsKey(t) ? (Temp) get(t) : t; 1748 cananian 1.1.2.22 } 1749 cananian 1.1.2.22 public Temp[] tempMap(Temp[] t) { 1750 cananian 1.1.2.22 Temp[] r = new Temp[t.length]; 1751 cananian 1.1.2.22 for (int i=0; i<r.length; i++) 1752 cananian 1.1.2.22 r[i] = tempMap(t[i]); 1753 cananian 1.1.2.22 return r; 1754 cananian 1.1.2.22 } 1755 cananian 1.1.2.22 } 1756 cananian 1.1.2.22 } 1757 cananian 1.1.2.1 static class xNullConstant extends xClass implements xConstant { 1758 cananian 1.1.2.1 public xNullConstant() { 1759 cananian 1.1.2.1 super(HClass.Void); 1760 cananian 1.1.2.1 } 1761 cananian 1.1.2.1 public Object constValue() { return null; } 1762 cananian 1.1.2.1 public String toString() { 1763 cananian 1.1.2.1 return "xNullConstant: null"; 1764 cananian 1.1.2.1 } 1765 cananian 1.1.2.21 public boolean equals(Object o) { return _equals(o); } 1766 cananian 1.1.2.21 private boolean _equals(Object o) { 1767 cananian 1.1.2.1 return (o instanceof xNullConstant); 1768 cananian 1.1.2.1 } 1769 cananian 1.1.2.21 public LatticeVal merge(LatticeVal v) { 1770 cananian 1.1.2.21 if (this._equals(v)) return new xNullConstant(); 1771 cananian 1.1.2.21 return super.merge(v); 1772 cananian 1.1.2.1 } 1773 cananian 1.1.2.23 public boolean isLowerThan(LatticeVal v) { 1774 cananian 1.1.2.23 return !(v instanceof xNullConstant); 1775 cananian 1.1.2.23 } 1776 cananian 1.1.2.1 } 1777 cananian 1.1.2.11 static class xFloatConstant extends xClassExact 1778 cananian 1.1.2.1 implements xConstant { 1779 cananian 1.1.2.1 protected Object value; 1780 cananian 1.1.2.1 public xFloatConstant(HClass type, Object value) { 1781 cananian 1.1.2.1 super(type); this.value = value; 1782 cananian 1.1.2.1 } 1783 cananian 1.1.2.1 public Object constValue() { return value; } 1784 cananian 1.1.2.1 public String toString() { 1785 cananian 1.1.2.1 return "xFloatConstant: " + type + " " + value.toString(); 1786 cananian 1.1.2.1 } 1787 cananian 1.1.2.21 public boolean equals(Object o) { return _equals(o); } 1788 cananian 1.1.2.21 private boolean _equals(Object o) { 1789 cananian 1.1.2.1 return (o instanceof xFloatConstant && super.equals(o) && 1790 cananian 1.1.2.1 ((xFloatConstant)o).value.equals(value)); 1791 cananian 1.1.2.1 } 1792 cananian 1.1.2.21 public LatticeVal merge(LatticeVal v) { 1793 cananian 1.1.2.21 if (this._equals(v)) return new xFloatConstant(type, value); 1794 cananian 1.1.2.21 return super.merge(v); 1795 cananian 1.1.2.1 } 1796 cananian 1.1.2.23 public boolean isLowerThan(LatticeVal v) { 1797 cananian 1.1.2.23 return !(v instanceof xFloatConstant); 1798 cananian 1.1.2.23 } 1799 cananian 1.1.2.1 } 1800 cananian 1.1.2.11 static class xStringConstant extends xClassExact 1801 cananian 1.1.2.1 implements xConstant { 1802 cananian 1.1.2.1 protected Object value; 1803 cananian 1.1.2.1 public xStringConstant(HClass type, Object value) { 1804 cananian 1.1.2.19 super(type); 1805 cananian 1.1.2.19 // note that the string constant objects are intern()ed. 1806 cananian 1.1.2.19 // doing this here ensures that evaluating ACMPEQ with constant 1807 cananian 1.1.2.19 // args works correctly. 1808 cananian 1.1.2.19 this.value = ((String)value).intern(); 1809 cananian 1.1.2.1 } 1810 cananian 1.1.2.1 public Object constValue() { return value; } 1811 cananian 1.1.2.1 public String toString() { 1812 cananian 1.1.2.1 return "xStringConstant: " + 1813 cananian 1.7 "\"" + harpoon.Util.Util.escape(value.toString()) + "\""; 1814 cananian 1.1.2.1 } 1815 cananian 1.1.2.21 public boolean equals(Object o) { return _equals(o); } 1816 cananian 1.1.2.21 private boolean _equals(Object o) { 1817 cananian 1.1.2.1 return (o instanceof xStringConstant && super.equals(o) && 1818 cananian 1.1.2.1 ((xStringConstant)o).value.equals(value)); 1819 cananian 1.1.2.1 } 1820 cananian 1.1.2.21 public LatticeVal merge(LatticeVal v) { 1821 cananian 1.1.2.21 if (this._equals(v)) return new xStringConstant(type, value); 1822 cananian 1.1.2.21 return super.merge(v); 1823 cananian 1.1.2.23 } 1824 cananian 1.1.2.23 public boolean isLowerThan(LatticeVal v) { 1825 cananian 1.1.2.23 return !(v instanceof xStringConstant); 1826 cananian 1.1.2.1 } 1827 cananian 1.1.2.1 } 1828 cananian 1.1.2.1 static interface xConstant { 1829 cananian 1.1.2.1 public Object constValue(); 1830 cananian 1.1.2.1 } 1831 cananian 1.1.2.22 static interface xInstanceofResult { 1832 cananian 1.1.2.22 public Temp tested(); 1833 cananian 1.1.2.22 public INSTANCEOF def(); 1834 cananian 1.1.2.22 public xInstanceofResultKnown makeKnown(boolean value); 1835 cananian 1.1.2.22 public xInstanceofResultUnknown makeUnknown(); 1836 cananian 1.1.2.22 } 1837 cananian 1.1.2.22 static interface xOperBooleanResult { 1838 cananian 1.1.2.22 public Temp[] operands(); 1839 cananian 1.1.2.22 public OPER def(); 1840 cananian 1.1.2.22 public xOperBooleanResultKnown makeKnown(boolean value); 1841 cananian 1.1.2.22 public xOperBooleanResultUnknown makeUnknown(); 1842 cananian 1.1.2.22 } 1843 cananian 1.1.2.1 ///////////////////////////////////////////////////////// 1844 cananian 1.1.2.1 // ways to degrade the analysis to collect statistics. 1845 cananian 1.1.2.1 private final Corruptor corruptor = null; // no corruption. 1846 cananian 1.1.2.1 private final boolean useSigmas = true; 1847 cananian 1.1.2.1 /** A <code>Corruptor</code> lets you 'dumb-down' the analysis 1848 cananian 1.1.2.1 * incrementally, so that we can generate numbers showing that 1849 cananian 1.1.2.1 * every step makes it better and better. */ 1850 cananian 1.1.2.1 static abstract class Corruptor { 1851 cananian 1.1.2.1 /** make this lattice value worse than we know it to be. */ 1852 cananian 1.1.2.1 abstract LatticeVal corrupt(LatticeVal v); 1853 cananian 1.1.2.1 } 1854 cananian 1.1.2.1 static final Corruptor nobitwidth = new Corruptor() { 1855 cananian 1.1.2.1 public LatticeVal corrupt(LatticeVal v) { 1856 cananian 1.1.2.22 if (v!=null && v.toString().startsWith("xBitWidth:")) 1857 cananian 1.1.2.22 return new xClassExact(((xClassExact)v).type); 1858 cananian 1.1.2.1 return v; 1859 cananian 1.1.2.1 } 1860 cananian 1.1.2.1 }; 1861 cananian 1.1.2.1 static final Corruptor nofixedarray = new Corruptor() { 1862 cananian 1.1.2.1 public LatticeVal corrupt(LatticeVal v) { 1863 cananian 1.1.2.1 v = nobitwidth.corrupt(v); 1864 cananian 1.1.2.1 if (v instanceof xClassArray) 1865 cananian 1.1.2.1 return new xClassNonNull(((xClassNonNull)v).type); 1866 cananian 1.1.2.1 return v; 1867 cananian 1.1.2.1 } 1868 cananian 1.1.2.1 }; 1869 cananian 1.1.2.1 static final Corruptor nonullpointer = new Corruptor() { 1870 cananian 1.1.2.1 public LatticeVal corrupt(LatticeVal v) { 1871 cananian 1.1.2.1 if (v instanceof xClassNonNull) 1872 cananian 1.1.2.1 return new xClass(((xClassNonNull)v).type); 1873 cananian 1.1.2.1 return v; 1874 cananian 1.1.2.1 } 1875 cananian 1.1.2.1 }; 1876 cananian 1.1.2.1 static final Corruptor nononint = new Corruptor() { 1877 cananian 1.1.2.1 public LatticeVal corrupt(LatticeVal v) { 1878 cananian 1.1.2.1 v = nonullpointer.corrupt(v); 1879 cananian 1.1.2.1 if (v instanceof xFloatConstant || 1880 cananian 1.1.2.1 v instanceof xStringConstant || 1881 cananian 1.1.2.1 (v instanceof xIntConstant && ((xClass)v).type!=HClass.Int)) 1882 cananian 1.1.2.1 return new xClass(((xClass)v).type); 1883 cananian 1.1.2.1 return v; 1884 cananian 1.1.2.1 } 1885 cananian 1.1.2.1 }; 1886 cananian 1.2 }