1 19 20 package jode.expr; 21 import jode.type.Type; 22 import jode.GlobalOptions; 23 import jode.decompiler.TabbedPrintWriter; 24 25 import java.util.Collection ; 26 import java.util.Set ; 27 28 public abstract class Operator extends Expression { 29 30 public final static int ADD_OP = 1; 31 public final static int SUB_OP = 2; 32 public final static int SHIFT_OP = 6; 33 public final static int AND_OP = 9; 34 public final static int ASSIGN_OP = 12; 35 public final static int OPASSIGN_OP= 12; 36 public final static int INC_OP = 24; 37 public final static int DEC_OP = 25; 38 public final static int COMPARE_OP = 26; 39 public final static int EQUALS_OP = 26; 40 public final static int NOTEQUALS_OP = 27; 41 public final static int LESS_OP = 28; 42 public final static int GREATEREQ_OP = 29; 43 public final static int GREATER_OP = 30; 44 public final static int LESSEQ_OP = 31; 45 public final static int LOG_AND_OP = 32; 46 public final static int LOG_OR_OP = 33; 47 public final static int LOG_NOT_OP = 34; 48 public final static int NEG_OP = 36; 49 static String opString[] = { 50 "", " + ", " - ", " * ", " / ", " % ", 51 " << ", " >> ", " >>> ", " & ", " | ", " ^ ", 52 " = ", " += ", " -= ", " *= ", " /= ", " %= ", 53 " <<= ", " >>= ", " >>>= ", " &= ", " |= ", " ^= ", 54 "++", "--", 55 " == "," != "," < "," >= "," > ", " <= ", " && ", " || ", 56 "!", "~", "-" 57 }; 58 59 protected int operatorIndex; 60 private int operandcount; 61 62 Expression[] subExpressions; 63 64 public Operator(Type type) { 65 this(type,0); 66 } 67 68 public Operator(Type type, int op) { 69 super(type); 70 this.operatorIndex = op; 71 if (type == null) 72 throw new jode.AssertError("type == null"); 73 } 74 75 public void initOperands(int opcount) { 76 operandcount = opcount; 77 subExpressions = new Expression[opcount]; 78 for (int i=0; i < opcount; i++) { 79 subExpressions[i] = new NopOperator(Type.tUnknown); 80 subExpressions[i].parent = this; 81 } 82 updateSubTypes(); 83 } 84 85 public int getFreeOperandCount() { 86 return operandcount; 87 } 88 89 93 public boolean isFreeOperator() { 94 return subExpressions.length == 0 95 || subExpressions[subExpressions.length-1] instanceof NopOperator; 96 } 97 98 102 public boolean isFreeOperator(int opcount) { 103 return subExpressions.length == opcount 104 && (opcount == 0 105 || subExpressions[opcount-1] instanceof NopOperator); 106 } 107 108 public Expression addOperand(Expression op) { 109 for (int i= subExpressions.length; i-- > 0;) { 110 int opcount = subExpressions[i].getFreeOperandCount(); 111 if (opcount > 0) { 112 subExpressions[i] = subExpressions[i].addOperand(op); 113 operandcount 114 += subExpressions[i].getFreeOperandCount() - opcount; 115 updateType(); 116 return this; 117 } 118 } 119 throw new jode.AssertError("addOperand called, but no operand needed"); 120 } 121 122 public Operator getOperator() { 123 return this; 124 } 125 126 public Expression[] getSubExpressions() { 127 return subExpressions; 128 } 129 130 public void setSubExpressions(int i, Expression expr) { 131 int diff = expr.getFreeOperandCount() 132 - subExpressions[i].getFreeOperandCount(); 133 subExpressions[i] = expr; 134 expr.parent = this; 135 for (Operator ce = this; ce != null; ce = (Operator) ce.parent) 136 ce.operandcount += diff; 137 updateType(); 138 } 139 140 public int getOperatorIndex() { 141 return operatorIndex; 142 } 143 public void setOperatorIndex(int op) { 144 operatorIndex = op; 145 } 146 147 public String getOperatorString() { 148 return opString[operatorIndex]; 149 } 150 151 public boolean opEquals(Operator o) { 152 return this == o; 153 } 154 155 public Expression simplify() { 156 for (int i=0; i< subExpressions.length; i++) { 157 subExpressions[i] = subExpressions[i].simplify(); 158 subExpressions[i].parent = this; 159 } 160 return this; 161 } 162 163 public void fillInGenSet(Collection in, Collection gen) { 164 if (this instanceof LocalVarOperator) { 165 LocalVarOperator varOp = (LocalVarOperator) this; 166 if (varOp.isRead() && in != null) 167 in.add(varOp.getLocalInfo()); 168 if (gen != null) 169 gen.add(varOp.getLocalInfo()); 170 } 171 for (int i=0; i< subExpressions.length; i++) 172 subExpressions[i].fillInGenSet(in,gen); 173 } 174 175 public void fillDeclarables(Collection used) { 176 for (int i=0; i< subExpressions.length; i++) 177 subExpressions[i].fillDeclarables(used); 178 } 179 180 public void makeDeclaration(Set done) { 181 for (int i=0; i< subExpressions.length; i++) 182 subExpressions[i].makeDeclaration(done); 183 } 184 185 186 192 public boolean hasSideEffects(Expression expr) { 193 if (expr instanceof MatchableOperator 194 && expr.containsConflictingLoad((MatchableOperator)expr)) 195 return true; 196 for (int i=0; i < subExpressions.length; i++) { 197 if (subExpressions[i].hasSideEffects(expr)) 198 return true; 199 } 200 return false; 201 } 202 203 210 public boolean containsConflictingLoad(MatchableOperator op) { 211 if (op.matches(this)) 212 return true; 213 for (int i=0; i < subExpressions.length; i++) { 214 if (subExpressions[i].containsConflictingLoad(op)) 215 return true; 216 } 217 return false; 218 } 219 220 228 public boolean containsMatchingLoad(CombineableOperator comb) { 229 Operator combOp = (Operator) comb; 230 if (comb.getLValue().matches(this)) { 231 if (subsEquals((Operator) comb.getLValue())) 232 return true; 233 } 234 for (int i=0; i < subExpressions.length; i++) { 235 if (subExpressions[i].containsMatchingLoad(comb)) 236 return true; 237 } 238 return false; 239 } 240 241 250 public int canCombine(CombineableOperator combOp) { 251 if (combOp.getLValue() instanceof LocalStoreOperator 253 && ((Operator)combOp).getFreeOperandCount() == 0) { 254 257 for (int i=0; i < subExpressions.length; i++) { 258 int result = subExpressions[i].canCombine(combOp); 259 if (result != 0) 260 return result; 261 if (subExpressions[i].hasSideEffects((Expression)combOp)) 262 return -1; 263 } 264 } 265 266 if (combOp.lvalueMatches(this)) 267 return subsEquals((Operator)combOp) ? 1 : -1; 268 if (subExpressions.length > 0) 269 return subExpressions[0].canCombine(combOp); 270 return 0; 271 } 272 273 282 public Expression combine(CombineableOperator comb) { 283 Operator combOp = (Operator) comb; 284 if (comb.lvalueMatches(this)) { 285 286 comb.makeNonVoid(); 287 combOp.parent = parent; 288 return combOp; 289 } 290 for (int i=0; i < subExpressions.length; i++) { 291 Expression combined = subExpressions[i].combine(comb); 292 if (combined != null) { 293 subExpressions[i] = combined; 294 updateType(); 295 return this; 296 } 297 } 298 return null; 299 } 300 301 public boolean subsEquals(Operator other) { 302 if (this == other) 303 return true; 304 if (other.subExpressions == null) 305 return (subExpressions == null); 306 307 if (subExpressions.length != other.subExpressions.length) 308 return false; 309 310 for (int i=0; i<subExpressions.length; i++) { 311 if(!subExpressions[i].equals(other.subExpressions[i])) 312 return false; 313 } 314 return true; 315 } 316 317 public boolean equals(Object o) { 318 if (this == o) 319 return true; 320 if (!(o instanceof Operator)) 321 return false; 322 Operator other = (Operator) o; 323 return opEquals(other) && subsEquals(other); 324 } 325 326 public boolean isConstant() { 327 for (int i=0; i< subExpressions.length; i++) 328 if (!subExpressions[i].isConstant()) 329 return false; 330 return true; 331 } 332 333 public abstract void dumpExpression(TabbedPrintWriter writer) 334 throws java.io.IOException ; 335 } 336 337 | Popular Tags |