00001 package edu.ksu.cis.bandera.specification.predicate;
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 import edu.ksu.cis.bandera.annotation.*;
00036 import edu.ksu.cis.bandera.jjjc.*;
00037 import edu.ksu.cis.bandera.jjjc.symboltable.*;
00038 import ca.mcgill.sable.soot.*;
00039 import ca.mcgill.sable.soot.grimp.*;
00040 import ca.mcgill.sable.soot.jimple.*;
00041 import edu.ksu.cis.bandera.jext.*;
00042 import edu.ksu.cis.bandera.jjjc.util.*;
00043 import edu.ksu.cis.bandera.specification.predicate.datastructure.*;
00044 import edu.ksu.cis.bandera.specification.predicate.analysis.*;
00045 import edu.ksu.cis.bandera.specification.predicate.node.*;
00046 import java.util.*;
00047 public class PredicateProcessor extends DepthFirstAdapter {
00048 private static Grimp grimp = Grimp.v();
00049 private static Jimple jimple = Jimple.v();
00050 private static Value ph;
00051 private static Hashtable phParams;
00052 private Value currentValue;
00053 private Vector constraintValues = new Vector();
00054 private static Hashtable variablesUsed;
00055 private static SootMethod sm;
00056
00057
00058
00059
00060 public void caseABinaryExp(ABinaryExp node) {
00061 node.getLeft().apply(this);
00062 Value leftValue = currentValue;
00063 node.getRight().apply(this);
00064
00065 PBinOp op = node.getBinOp();
00066 if (op instanceof AEqualBinOp) {
00067 currentValue = grimp.newEqExpr(leftValue, currentValue);
00068 } else if (op instanceof ANotEqualBinOp) {
00069 currentValue = grimp.newNeExpr(leftValue, currentValue);
00070 } else if (op instanceof ALessBinOp) {
00071 currentValue = grimp.newLtExpr(leftValue, currentValue);
00072 } else if (op instanceof ALessEqualBinOp) {
00073 currentValue = grimp.newLeExpr(leftValue, currentValue);
00074 } else if (op instanceof AGreaterBinOp) {
00075 currentValue = grimp.newGtExpr(leftValue, currentValue);
00076 } else if (op instanceof AGreaterEqualBinOp) {
00077 currentValue = grimp.newGeExpr(leftValue, currentValue);
00078 } else if (op instanceof AAndBinOp) {
00079 currentValue = new LogicalAndExpr(leftValue, currentValue);
00080 } else if (op instanceof AOrBinOp) {
00081 currentValue = new LogicalOrExpr(leftValue, currentValue);
00082 } else if (op instanceof APlusBinOp) {
00083 currentValue = grimp.newAddExpr(leftValue, currentValue);
00084 } else if (op instanceof AMinusBinOp) {
00085 currentValue = grimp.newSubExpr(leftValue, currentValue);
00086 } else if (op instanceof ATimesBinOp) {
00087 currentValue = grimp.newMulExpr(leftValue, currentValue);
00088 } else if (op instanceof AShiftLeftBinOp) {
00089 currentValue = grimp.newShlExpr(leftValue, currentValue);
00090 } else if (op instanceof ASignedShiftRightBinOp) {
00091 currentValue = grimp.newShrExpr(leftValue, currentValue);
00092 } else if (op instanceof AUnsignedShiftRightBinOp) {
00093 currentValue = grimp.newUshrExpr(leftValue, currentValue);
00094 } else if (op instanceof ABitAndBinOp) {
00095 currentValue = grimp.newAndExpr(leftValue, currentValue);
00096 } else if (op instanceof ABitOrBinOp) {
00097 currentValue = grimp.newOrExpr(leftValue, currentValue);
00098 } else if (op instanceof ABitXorBinOp) {
00099 currentValue = grimp.newXorExpr(leftValue, currentValue);
00100 } else if (op instanceof AStrongDivBinOp) {
00101 constraintValues.add(grimp.newNeExpr(currentValue, IntConstant.v(0)));
00102 currentValue = grimp.newDivExpr(leftValue, currentValue);
00103 } else if (op instanceof AStrongModBinOp) {
00104 constraintValues.add(grimp.newNeExpr(currentValue, IntConstant.v(0)));
00105 currentValue = grimp.newRemExpr(leftValue, currentValue);
00106 }
00107 }
00108
00109
00110
00111
00112 public void caseABitComplementExp(ABitComplementExp node) {
00113 node.getExp().apply(this);
00114 if (currentValue.getType() instanceof ca.mcgill.sable.soot.LongType) {
00115 currentValue = grimp.newXorExpr(currentValue, LongConstant.v(-1));
00116 } else {
00117 currentValue = grimp.newXorExpr(currentValue, IntConstant.v(-1));
00118 }
00119 }
00120
00121
00122
00123
00124 public void caseACharLiteral(ACharLiteral node) {
00125 String literal = node.toString().trim();
00126 literal = literal.substring(1, literal.length() - 1);
00127 int value = 0;
00128
00129 if (literal.startsWith("\\")) {
00130 switch (literal.charAt(1)) {
00131 case 'b': value = '\b';
00132 break;
00133 case 't': value = '\t';
00134 break;
00135 case 'n': value = '\n';
00136 break;
00137 case 'f': value = '\f';
00138 break;
00139 case 'r': value = '\r';
00140 break;
00141 case '\"': value = '\"';
00142 break;
00143 case '\'': value = '\'';
00144 break;
00145 case '\\': value = '\\';
00146 break;
00147 default: value = Integer.valueOf(literal.substring(1), 8).intValue();
00148 }
00149 } else if (literal.startsWith("\\u")) {
00150 value = Integer.valueOf(literal.substring(2), 16).intValue();
00151 } else value = literal.charAt(0);
00152
00153 currentValue = IntConstant.v(value);
00154 }
00155
00156
00157
00158
00159 public void caseAComplementExp(AComplementExp node) {
00160 node.getExp().apply(this);
00161 currentValue = new ComplementExpr(currentValue);
00162 }
00163
00164
00165
00166
00167 public void caseADecIntLiteral(ADecIntLiteral node) {
00168 currentValue = IntConstant.v(Integer.parseInt(node.toString().trim()));
00169 }
00170
00171
00172
00173
00174 public void caseADecLongLiteral(ADecLongLiteral node) {
00175 String literal = node.toString().trim();
00176 literal = literal.substring(0, literal.length() - 1);
00177 currentValue = LongConstant.v(Long.parseLong(literal));
00178 }
00179
00180
00181
00182
00183 public void caseADoubleLiteral(ADoubleLiteral node) {
00184 currentValue = DoubleConstant.v(Double.valueOf(node.toString().trim()).floatValue());
00185 }
00186
00187
00188
00189
00190 public void caseAFalseLiteral(AFalseLiteral node) {
00191 currentValue = IntConstant.v(0);
00192 }
00193
00194
00195
00196
00197 public void caseAFloatLiteral(AFloatLiteral node) {
00198 currentValue = FloatConstant.v(Float.valueOf(node.toString().trim()).floatValue());
00199 }
00200
00201
00202
00203
00204 public void caseAHexIntLiteral(AHexIntLiteral node) {
00205 currentValue = IntConstant.v(Integer.parseInt(node.toString().trim(), 16));
00206 }
00207
00208
00209
00210
00211 public void caseAHexLongLiteral(AHexLongLiteral node) {
00212 String literal = node.toString().substring(2).trim();
00213 literal = literal.substring(0, literal.length() - 1);
00214 currentValue = LongConstant.v(Long.parseLong(literal, 16));
00215 }
00216
00217
00218
00219
00220 public void caseAInstanceofExp(AInstanceofExp node) {
00221 node.getExp().apply(this);
00222 currentValue = grimp.newInstanceOfExpr(currentValue, RefType.v(new Name(node.toString()).toString()));
00223 }
00224
00225
00226
00227
00228 public void caseANameExp(ANameExp node) {
00229 Object o = variablesUsed.get(node);
00230 if (o instanceof String) {
00231 currentValue = (Value) phParams.get(o);
00232 } else if (o instanceof Local) {
00233 currentValue = new LocalExpr(sm, (Local) o);
00234 } else if (o instanceof Field) {
00235 Field f = (Field) variablesUsed.get(node);
00236 try {
00237 SootClass sc = CompilationManager.getSootClassManager().getClass(f.getDeclaringClassOrInterface().toString());
00238 SootField sf = sc.getField(f.getName().toString());
00239 if (Modifier.isStatic(sf.getModifiers()))
00240 currentValue = grimp.newStaticFieldRef(sf);
00241 else
00242 currentValue = grimp.newInstanceFieldRef(ph, sf);
00243 } catch (Exception e) {
00244 throw new RuntimeException("Unexpected error: " + e);
00245 }
00246 }
00247 }
00248
00249
00250
00251
00252 public void caseANegativeExp(ANegativeExp node) {
00253 node.getExp().apply(this);
00254 currentValue = grimp.newNegExpr(currentValue);
00255 }
00256
00257
00258
00259
00260 public void caseANullLiteral(ANullLiteral node) {
00261 currentValue = NullConstant.v();
00262 }
00263
00264
00265
00266
00267 public void caseAOctIntLiteral(AOctIntLiteral node) {
00268 currentValue = IntConstant.v(Integer.parseInt(node.toString().trim(), 8));
00269 }
00270
00271
00272
00273
00274 public void caseAOctLongLiteral(AOctLongLiteral node) {
00275 String literal = node.toString().substring(1).trim();
00276 literal = literal.substring(0, literal.length() - 1);
00277 currentValue = LongConstant.v(Long.parseLong(literal, 8));
00278 }
00279
00280
00281
00282
00283 public void caseAQuestionExp(AQuestionExp node) {
00284 node.getExp().apply(this);
00285 Value conditionValue = currentValue;
00286 node.getTrueExp().apply(this);
00287 Value trueValue = currentValue;
00288 node.getFalseExp().apply(this);
00289 currentValue = new LogicalOrExpr(new LogicalAndExpr(conditionValue, trueValue),
00290 new LogicalAndExpr(new ComplementExpr(conditionValue), currentValue));
00291 }
00292
00293
00294
00295
00296 public void caseAReturnValueExp(AReturnValueExp node) {
00297 currentValue = new LocalExpr(sm, ((JimpleBody) sm.getBody(Jimple.v())).getLocal("$ret"));
00298 }
00299
00300
00301
00302
00303 public void caseAStringLiteral(AStringLiteral node) {
00304 currentValue = StringConstant.v(Util.decodeString(node.toString().trim()));
00305 }
00306
00307
00308
00309
00310 public void caseAStrongArrayNavigation(AStrongArrayNavigation node) {
00311 Value baseValue = currentValue;
00312 node.getExp().apply(this);
00313
00314 constraintValues.add(grimp.newNeExpr(baseValue, NullConstant.v()));
00315 constraintValues.add(grimp.newGeExpr(currentValue, IntConstant.v(0)));
00316 constraintValues.add(grimp.newLtExpr(currentValue, grimp.newLengthExpr(baseValue)));
00317
00318 currentValue = grimp.newArrayRef(baseValue, currentValue);
00319 }
00320
00321
00322
00323
00324 public void caseAStrongCastExp(AStrongCastExp node) {
00325 ca.mcgill.sable.soot.Type type = Util.convertType((edu.ksu.cis.bandera.jjjc.symboltable.Type) variablesUsed.get(node));
00326 node.getExp().apply(this);
00327
00328 constraintValues.add(grimp.newInstanceOfExpr(currentValue, type));
00329
00330 currentValue = grimp.newCastExpr(currentValue, type);
00331 }
00332
00333
00334
00335
00336 public void caseAStrongObjectNavigation(AStrongObjectNavigation node) {
00337 constraintValues.add(grimp.newNeExpr(currentValue, NullConstant.v()));
00338 Hashtable vu = variablesUsed;
00339 Field f = (Field) vu.get(node);
00340 try {
00341 SootClass sc = CompilationManager.getSootClassManager().getClass(f.getDeclaringClassOrInterface().toString());
00342 SootField sf = sc.getField(f.getName().toString());
00343 if (Modifier.isStatic(sf.getModifiers()))
00344 currentValue = grimp.newStaticFieldRef(sf);
00345 else
00346 currentValue = grimp.newInstanceFieldRef(currentValue, sf);
00347 } catch (Exception e) {
00348 throw new RuntimeException("Unexpected error: " + e);
00349 }
00350 }
00351
00352
00353
00354
00355 public void caseAThisExp(AThisExp node) {
00356 currentValue = ph;
00357 }
00358
00359
00360
00361
00362 public void caseATrueLiteral(ATrueLiteral node) {
00363 currentValue = IntConstant.v(1);
00364 }
00365
00366
00367
00368
00369
00370
00371
00372 public static Value process(Value placeHolder, Hashtable placeHolderParams, Predicate p) {
00373 ph = placeHolder;
00374 phParams = placeHolderParams;
00375 variablesUsed = p.getVariablesUsed();
00376
00377 if (p.getAnnotation() != null) {
00378 Annotation a = p.getAnnotation();
00379 if (a instanceof LabeledStmtAnnotation) {
00380 a = CompilationManager.getAnnotationManager().getMethodAnnotationContainingAnnotation(a);
00381 }
00382 sm = (a instanceof MethodDeclarationAnnotation) ?
00383 ((MethodDeclarationAnnotation) a).getSootMethod() :
00384 ((ConstructorDeclarationAnnotation) a).getSootMethod();
00385 }
00386
00387 Value constraintValue = null;
00388 if (p.getConstraint() != null) {
00389 PredicateProcessor pp = new PredicateProcessor();
00390 p.getConstraint().apply(pp);
00391 constraintValue = pp.currentValue;
00392 Object[] constraints = pp.constraintValues.toArray();
00393 for (int i = constraints.length - 1; i >= 0; i--) {
00394 constraintValue = new LogicalAndExpr((Value) constraints[i], constraintValue);
00395 }
00396 }
00397
00398 if (p instanceof ExpressionPredicate) return constraintValue;
00399 Vector v = new Vector();
00400 if (p instanceof ReturnPredicate) {
00401 ReturnPredicate rp = (ReturnPredicate) p;
00402 Object[] stmts = ((JimpleBody) sm.getBody(Jimple.v())).getStmtList().toArray();
00403 for (int i = 0; i < stmts.length; i++) {
00404 if ((stmts[i] instanceof ReturnStmt) || (stmts[i] instanceof ReturnVoidStmt)) {
00405 v.add(stmts[i]);
00406 }
00407 }
00408 } else if (p instanceof InvokePredicate) {
00409 Object[] stmts = ((JimpleBody) sm.getBody(Jimple.v())).getStmtList().toArray();
00410 for (int i = 0; i < stmts.length; i++) {
00411 if (!(stmts[i] instanceof IdentityStmt)) {
00412 v.add(stmts[i]);
00413 break;
00414 }
00415 }
00416 } else {
00417 v.add(p.getAnnotation().getStatements()[0]);
00418 }
00419 if (constraintValue != null) {
00420 Value result = constraintValue;
00421 if (ph != null) {
00422 Value temp = grimp.newEqExpr(ph, new LocalExpr(sm, ((JimpleBody) sm.getBody(jimple)).getLocal("JJJCTEMP$0")));
00423 result = new LogicalAndExpr(result, temp);
00424 }
00425 return new LogicalAndExpr(new LocationTestExpr(v), result);
00426 } else {
00427 Value result = new LocationTestExpr(v);
00428 if (ph != null) {
00429 Value temp = grimp.newEqExpr(ph, new LocalExpr(sm, ((JimpleBody) sm.getBody(jimple)).getLocal("JJJCTEMP$0")));
00430 result = new LogicalAndExpr(result, temp);
00431 }
00432 return result;
00433 }
00434 }
00435 }