00001 package edu.ksu.cis.bandera.abstraction.typeinference;
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
00036
00037
00038 import java.util.*;
00039 import ca.mcgill.sable.soot.*;
00040 import ca.mcgill.sable.soot.jimple.*;
00041 import edu.ksu.cis.bandera.jext.*;
00042 import edu.ksu.cis.bandera.abstraction.*;
00043 import edu.ksu.cis.bandera.abstraction.gui.*;
00044 import edu.ksu.cis.bandera.abstraction.util.*;
00045 public class TypeInference extends IRNodes {
00046 private static final Jimple jimple = Jimple.v();
00047 private CoercionManager coercionManager;
00048 private TypeTable nodes;
00049 private List constraints;
00050 private List params;
00051 private LeftAssignExprSwitch lswitch;
00052 private TypeStructure returnValue;
00053 private Hashtable method2params = new Hashtable();
00054 private Hashtable method2return = new Hashtable();
00055 private Hashtable local2method = new Hashtable();
00056 private SootMethod currentMethod;
00057 private RefHashTable ast2TypeStruct = new RefHashTable();
00058 private TypeDependencyGraph tdg = new TypeDependencyGraph();
00059 private Hashtable errors = new Hashtable();
00060 private HashSet methodsInheritance = new HashSet();
00061 private Hashtable interfaceMethodMethod = new Hashtable();
00062 private Vector conflicts = new Vector();
00063
00064
00065
00066
00067 public TypeInference() {
00068 nodes = new TypeTable();
00069 constraints = new Vector();
00070 params = new Vector();
00071 this.coercionManager = new CoercionManager(AbstractionLibraryManager.getAbstractions());
00072 }
00073 public void caseAddExpr(AddExpr v) {
00074 doOp(v);
00075 }
00076 public void caseAndExpr(AndExpr v) {
00077 doOp(v);
00078 }
00079 public void caseArrayRef(ArrayRef v) {
00080 TypeStructure varnode = getTypeStructure(v);
00081 ArrayTypeStructure var = (ArrayTypeStructure) getTypeStructure(v.getBase());
00082 TypeStructure index = var.getIndex();
00083 v.getIndex().apply(this);
00084 constraints.addAll(index.genEqualConstraints((TypeStructure) getResult()));
00085 TypeStructure base = var.getElements();
00086 constraints.addAll(varnode.genEqualConstraints(base));
00087 TypeStructure ts = getCoercedTypeStructure(v);
00088 constraints.addAll(ts.genCoerceConstraints(varnode));
00089 setResult(varnode);
00090 }
00091 public void caseAssignStmt(AssignStmt stmt) {
00092 doDefinitionStmt(stmt);
00093 }
00094
00095
00096
00097
00098 public void caseCastExpr(CastExpr v) {
00099 v.getOp().apply(this);
00100 TypeStructure opts = (TypeStructure) getResult();
00101 TypeStructure ts = getTypeStructure(v);
00102 if (v.getType() instanceof BaseType)
00103 constraints.addAll(ts.genEqualConstraints(opts));
00104 setResult(ts);
00105 }
00106
00107
00108
00109
00110
00111 public void caseCaughtExceptionRef(CaughtExceptionRef v) {
00112 TypeStructure ts = getTypeStructure(v);
00113 setResult(ts);
00114 }
00115
00116
00117
00118
00119
00120 public void caseChooseExpr(ChooseExpr v) {
00121 BaseTypeStructure ts = (BaseTypeStructure) getTypeStructure(v);
00122 Abstraction t = ConcreteIntegralAbstraction.v();
00123 tdg.addType(t);
00124 tdg.combine(tdg.getTypeVariable(t), ts.getVar());
00125 setResult(ts);
00126 }
00127 public void caseCmpExpr(CmpExpr v) {
00128 doOp(v);
00129 }
00130 public void caseCmpgExpr(CmpgExpr v) {
00131 doOp(v);
00132 }
00133 public void caseCmplExpr(CmplExpr v) {
00134 doOp(v);
00135 }
00136 public void caseDivExpr(DivExpr v) {
00137 doOp(v);
00138 }
00139 public void caseDoubleConstant(DoubleConstant v) {
00140 TypeStructure cts = getCoercedTypeStructure(v);
00141 TypeStructure ts = getTypeStructure(v);
00142 constraints.addAll(cts.genCoerceConstraints(ts));
00143 setResult(cts);
00144 }
00145 public void caseEnterMonitorStmt(EnterMonitorStmt stmt) {
00146 stmt.getOp().apply(this);
00147 setResult(null);
00148 }
00149 public void caseEqExpr(EqExpr v) {
00150 doTest(v);
00151 }
00152 public void caseExitMonitorStmt(ExitMonitorStmt stmt) {
00153 stmt.getOp().apply(this);
00154 setResult(null);
00155 }
00156 public void caseFloatConstant(FloatConstant v) {
00157 TypeStructure cts = getCoercedTypeStructure(v);
00158 TypeStructure ts = getTypeStructure(v);
00159 constraints.addAll(cts.genCoerceConstraints(ts));
00160 setResult(cts);
00161 }
00162 public void caseGeExpr(GeExpr v) {
00163 doTest(v);
00164 }
00165 public void caseGotoStmt(GotoStmt stmt) {
00166 setResult(null);
00167 }
00168 public void caseGtExpr(GtExpr v) {
00169 doTest(v);
00170 }
00171 public void caseIdentityStmt(IdentityStmt stmt) {
00172 doDefinitionStmt(stmt);
00173 }
00174 public void caseIfStmt(IfStmt stmt) {
00175 stmt.getCondition().apply(this);
00176 }
00177
00178
00179
00180
00181 public void caseInstanceFieldRef(InstanceFieldRef v) {
00182 doFieldRef(v);
00183 }
00184 public void caseIntConstant(IntConstant v) {
00185 TypeStructure cts = getCoercedTypeStructure(v);
00186 TypeStructure ts = getTypeStructure(v);
00187 constraints.addAll(cts.genCoerceConstraints(ts));
00188 setResult(cts);
00189 }
00190
00191
00192
00193
00194 public void caseInterfaceInvokeExpr(InterfaceInvokeExpr v) {
00195 SootMethod sm = v.getMethod();
00196 v.setMethod((SootMethod) interfaceMethodMethod.get(sm));
00197 doInvokeExpr(v);
00198 v.setMethod(sm);
00199 }
00200
00201
00202
00203
00204
00205 public void caseInvokeStmt(InvokeStmt s) {
00206 s.getInvokeExpr().apply(this);
00207 }
00208 public void caseLeExpr(LeExpr v) {
00209 doTest(v);
00210 }
00211 public void caseLengthExpr(LengthExpr v) {
00212 ArrayTypeStructure var = (ArrayTypeStructure) getTypeStructure(v.getOp());
00213 TypeStructure varnode = getTypeStructure(v);
00214 constraints.addAll(varnode.genEqualConstraints(var.getIndex()));
00215 setResult(varnode);
00216 }
00217 public void caseLocal(Local v) {
00218 local2method.put(v, currentMethod);
00219 TypeStructure node = getCoercedTypeStructure(v);
00220 TypeStructure varnode = getTypeStructure(v);
00221 constraints.addAll(node.genCoerceConstraints(varnode));
00222 setResult(node);
00223 }
00224 public void caseLongConstant(LongConstant v) {
00225 TypeStructure cts = getCoercedTypeStructure(v);
00226 TypeStructure ts = getTypeStructure(v);
00227 constraints.addAll(cts.genCoerceConstraints(ts));
00228 setResult(cts);
00229 }
00230
00231
00232
00233
00234 public void caseLookupSwitchStmt(LookupSwitchStmt stmt) {
00235 stmt.getKey().apply(this);
00236 }
00237 public void caseLtExpr(LtExpr v) {
00238 doTest(v);
00239 }
00240 public void caseMulExpr(MulExpr v) {
00241 doOp(v);
00242 }
00243 public void caseNeExpr(NeExpr v) {
00244 doTest(v);
00245 }
00246 public void caseNegExpr(NegExpr v) {
00247 v.getOp().apply(this);
00248 TypeStructure op = (TypeStructure) getResult();
00249 TypeStructure varnode = getTypeStructure(v);
00250 constraints.addAll(varnode.genEqualConstraints(op));
00251 setResult(varnode);
00252 }
00253
00254
00255
00256
00257 public void caseNewArrayExpr(NewArrayExpr v) {
00258 ArrayTypeStructure node = (ArrayTypeStructure) getTypeStructure(v);
00259 v.getSize().apply(this);
00260 TypeStructure index = node.getIndex();
00261 constraints.addAll(index.genEqualConstraints((TypeStructure) getResult()));
00262 setResult(node);
00263 }
00264
00265
00266
00267
00268 public void caseNewExpr(NewExpr v) {
00269 TypeStructure varnode = getTypeStructure(v);
00270 setResult(varnode);
00271 }
00272 public void caseNewMultiArrayExpr(NewMultiArrayExpr v) {
00273 defaultCase(v);
00274 }
00275 public void caseNopStmt(NopStmt stmt) {
00276 setResult(null);
00277 }
00278 public void caseNullConstant(NullConstant v) {
00279 setResult(getTypeStructure(NullConstant.v()));
00280 }
00281 public void caseOrExpr(OrExpr v) {
00282 doOp(v);
00283 }
00284 public void caseParameterRef(ParameterRef v) {
00285 SootMethod method = v.getMethod();
00286 List l;
00287 if ((l = (Vector) method2params.get(method)) == null) {
00288 l = new Vector();
00289 method2params.put(method, l);
00290 }
00291 if (!l.contains(v))
00292 l.add(v);
00293 TypeStructure varnode = getTypeStructure(v);
00294 constraints.addAll(varnode.genEqualConstraints((TypeStructure) params.get(v.getIndex() + 1)));
00295 setResult(varnode);
00296 }
00297 public void caseRemExpr(RemExpr v) {
00298 doOp(v);
00299 }
00300 public void caseReturnStmt(ReturnStmt stmt) {
00301 if (returnValue != null) {
00302 stmt.getReturnValue().apply(this);
00303 constraints.addAll(returnValue.genCoerceConstraints((TypeStructure) getResult()));
00304 }
00305 setResult(null);
00306 }
00307
00308
00309
00310
00311
00312 public void caseReturnVoidStmt(ReturnVoidStmt s) {
00313 setResult(null);
00314 }
00315 public void caseShlExpr(ShlExpr v) {
00316 doOp(v);
00317 }
00318 public void caseShrExpr(ShrExpr v) {
00319 doOp(v);
00320 }
00321
00322
00323
00324
00325 public void caseSpecialInvokeExpr(SpecialInvokeExpr v) {
00326 doInvokeExpr(v);
00327 }
00328
00329
00330
00331
00332
00333 public void caseStaticFieldRef(StaticFieldRef v) {
00334 doFieldRef(v);
00335 }
00336
00337
00338
00339
00340 public void caseStaticInvokeExpr(StaticInvokeExpr v) {
00341 doInvokeExpr(v);
00342 }
00343 public void caseStringConstant(StringConstant v) {
00344 TypeStructure varnode = getTypeStructure(v);
00345 setResult(varnode);
00346 }
00347 public void caseSubExpr(SubExpr v) {
00348 doOp(v);
00349 }
00350 public void caseThisRef(ThisRef v) {
00351 TypeStructure ts = getTypeStructure(v);
00352 setResult(ts);
00353 }
00354 public void caseThrowStmt(ThrowStmt stmt) {
00355 setResult(null);
00356 }
00357 public void caseUshrExpr(UshrExpr v) {
00358 doOp(v);
00359 }
00360
00361
00362
00363
00364 public void caseVirtualInvokeExpr(VirtualInvokeExpr v) {
00365 SootMethod sm = v.getMethod();
00366 if (interfaceMethodMethod.get(sm) != null) {
00367 v.setMethod((SootMethod) interfaceMethodMethod.get(sm));
00368 }
00369 doInvokeExpr(v);
00370 v.setMethod(sm);
00371 }
00372 public void caseXorExpr(XorExpr v) {
00373 doOp(v);
00374 }
00375
00376
00377
00378
00379
00380
00381
00382 public void createConstraints(SootMethod method, List params, TypeStructure ret) {
00383 System.out.print(".");
00384 if (method2params.get(method) != null) {
00385 List p = (List) method2params.get(method);
00386 Iterator i = p.iterator();
00387 while (i.hasNext()) {
00388 ParameterRef param = (ParameterRef) i.next();
00389 TypeStructure varnode = getTypeStructure(param);
00390 constraints.addAll(varnode.genEqualConstraints((TypeStructure) params.get(param.getIndex() + 1)));
00391 }
00392 if ((ret != null) && !(method.getReturnType() instanceof VoidType))
00393 constraints.addAll(ret.genEqualConstraints((TypeStructure) method2return.get(method)));
00394 return;
00395 }
00396 if ((ret != null) && !(method.getReturnType() instanceof VoidType))
00397 method2return.put(method, ret);
00398 SootMethod oldMethod = currentMethod;
00399 currentMethod = method;
00400 lswitch = new LeftAssignExprSwitch(constraints, this, null, null);
00401 TypeStructure oldRet = returnValue;
00402 returnValue = ret;
00403 this.params = params;
00404 try {
00405 JimpleBody body = (JimpleBody) method.getBody(Jimple.v());
00406 StmtList stmts = body.getStmtList();
00407 ca.mcgill.sable.util.Iterator i = stmts.iterator();
00408 Stmt current;
00409 while (i.hasNext()) {
00410 current = (Stmt) i.next();
00411 current.apply(this);
00412 }
00413 } catch(Exception e)
00414 {
00415 }
00416 returnValue = oldRet;
00417 currentMethod = oldMethod;
00418 }
00419
00420
00421
00422
00423 private void createInheritanceConstraints(SootMethod sm) {
00424 if (methodsInheritance.contains(sm) || !sm.isBodyStored(jimple) || sm.isStatic() || "<init>".equals(sm.getName()) || "<clinit>".equals(sm.getName())) return;
00425 HashSet overwrittenMethods = new HashSet();
00426 SootClass sc = sm.getDeclaringClass();
00427 ca.mcgill.sable.util.List parmTypes = sm.getParameterTypes();
00428 String name = sm.getName();
00429 SootMethod origSootMethod = sm;
00430 do {
00431 overwrittenMethods.add(sm);
00432 sm = null;
00433 while (sc.hasSuperClass() && (sm == null)) {
00434 for (ca.mcgill.sable.util.Iterator i = sc.getInterfaces().iterator(); i.hasNext();) {
00435 SootClass scInterface = (SootClass) i.next();
00436 if (scInterface.declaresMethod(name, parmTypes)) {
00437 interfaceMethodMethod.put(scInterface.getMethod(name, parmTypes), sc.getMethod(name, parmTypes));
00438 }
00439 }
00440 sc = sc.getSuperClass();
00441 if (sc.declaresMethod(name, parmTypes)) {
00442 sm = sc.getMethod(name, parmTypes);
00443 if (Modifier.isAbstract(sm.getModifiers())) {
00444 interfaceMethodMethod.put(sm, origSootMethod);
00445 sm = null;
00446 } else if (!sm.isBodyStored(jimple) || sm.isStatic() || "<init>".equals(sm.getName()) || "<clinit>".equals(sm.getName())) sm = null;
00447 } else sm = null;
00448 }
00449 } while (sm != null && !methodsInheritance.contains(sm));
00450 if (sm != null) overwrittenMethods.add(sm);
00451
00452 methodsInheritance.addAll(overwrittenMethods);
00453 Iterator i = overwrittenMethods.iterator();
00454 sm = (SootMethod) i.next();
00455 TypeStructure[] args = new TypeStructure[sm.getParameterCount()];
00456 TypeStructure ret = createInheritanceConstraintsMethod(sm, args);
00457 while (i.hasNext()) {
00458 sm = (SootMethod) i.next();
00459 TypeStructure[] tempArgs = new TypeStructure[sm.getParameterCount()];
00460 TypeStructure tempRet = createInheritanceConstraintsMethod(sm, tempArgs);
00461 for (int j = 0; j < args.length; j++) {
00462 constraints.addAll(args[j].genEqualConstraints(tempArgs[j]));
00463 }
00464 if (ret != null)
00465 constraints.addAll(ret.genEqualConstraints(tempRet));
00466 }
00467 }
00468
00469
00470
00471
00472
00473
00474 private TypeStructure createInheritanceConstraintsMethod(SootMethod sm, TypeStructure[] args) {
00475 Object[] stmts = ((JimpleBody) sm.getBody(jimple)).getStmtList().toArray();
00476 Vector returnTypeStructures = new Vector();
00477
00478 for (int i = 0; i < stmts.length; i++) {
00479 if (stmts[i] instanceof ReturnStmt) {
00480 returnTypeStructures.add(getTypeStructure((((ReturnStmt) stmts[i]).getReturnValue())));
00481 } else if (stmts[i] instanceof IdentityStmt) {
00482 IdentityStmt is = (IdentityStmt) stmts[i];
00483 if (is.getRightOp() instanceof ParameterRef) {
00484 args[((ParameterRef) is.getRightOp()).getIndex()] = getTypeStructure(is.getLeftOp());
00485 }
00486 }
00487 }
00488
00489 if (returnTypeStructures.size() == 0)
00490 return null;
00491
00492 TypeStructure ts = (TypeStructure) returnTypeStructures.remove(0);
00493 for (Iterator i = returnTypeStructures.iterator(); i.hasNext();) {
00494 constraints.addAll(ts.genEqualConstraints((TypeStructure) i.next()));
00495 }
00496 method2return.put(sm, ts);
00497 return ts;
00498 }
00499 public void defaultCase(Object v) {
00500 System.out.println("Default Case: " + v + "\t" + v.getClass());
00501 if (v instanceof Expr)
00502 throw new RuntimeException("Unhandled expression " + v + ":" + v.getClass() + " in type inference.");
00503 System.out.println("Unknown in type inference: " + v.getClass());
00504 }
00505
00506
00507
00508
00509
00510 public void doDefinitionStmt(DefinitionStmt stmt) {
00511 stmt.getLeftOp().apply(lswitch);
00512 TypeStructure left = (TypeStructure) lswitch.getResult();
00513 stmt.getRightOp().apply(this);
00514 TypeStructure right = (TypeStructure) getResult();
00515 constraints.addAll(left.genEqualConstraints(right));
00516 }
00517
00518
00519
00520
00521
00522 public void doFieldRef(FieldRef v) {
00523 TypeStructure fts = getTypeStructure(v.getField());
00524 TypeStructure ts = getTypeStructure(v);
00525 constraints.addAll(fts.genEqualConstraints(ts));
00526 setResult(ts);
00527 }
00528
00529
00530
00531
00532
00533 public void doInvokeExpr(InvokeExpr v) {
00534 TypeStructure varnode;
00535 if (v.getMethod().getReturnType() instanceof RefType) {
00536 varnode = getTypeStructure(v);
00537 } else
00538 if (!(v.getMethod().getReturnType() instanceof VoidType)) {
00539 varnode = getTypeStructure(v);
00540 } else {
00541 varnode = null;
00542 }
00543 if (!Util.hasJavaPrefix(v.getMethod().getDeclaringClass().toString()) && !"Bandera".equals(v.getMethod().getDeclaringClass().toString())) {
00544 Vector p = new Vector();
00545 if (v instanceof NonStaticInvokeExpr) {
00546 ((NonStaticInvokeExpr) v).getBase().apply(this);
00547 p.add(getResult());
00548 } else {
00549 p.add(new Object());
00550 }
00551 for (int i = 0; i < v.getArgCount(); i++) {
00552 v.getArg(i).apply(this);
00553 p.add(getResult());
00554 }
00555 createConstraints(v.getMethod(), p, varnode);
00556 }
00557 setResult(varnode);
00558 }
00559 public void doOp(BinopExpr v) {
00560 v.getOp1().apply(this);
00561 TypeStructure left = (TypeStructure) getResult();
00562 v.getOp2().apply(this);
00563 TypeStructure right = (TypeStructure) getResult();
00564 TypeStructure ts = getTypeStructure(v);
00565 constraints.addAll(ts.genEqualConstraints(left));
00566 constraints.addAll(ts.genEqualConstraints(right));
00567 constraints.addAll(left.genEqualConstraints(right));
00568 setResult(ts);
00569 }
00570
00571
00572
00573
00574 public void doTest(ConditionExpr v) {
00575 v.getOp1().apply(this);
00576 TypeStructure left = (TypeStructure) getResult();
00577 v.getOp2().apply(this);
00578 TypeStructure right = (TypeStructure) getResult();
00579
00580
00581 TypeStructure ts = getTypeStructure(v);
00582
00583 constraints.addAll(left.genEqualConstraints(right));
00584 if ((left instanceof BaseTypeStructure)
00585 && (right instanceof BaseTypeStructure)
00586 && (ts instanceof BaseTypeStructure)) {
00587 constraints.addAll(left.genEqualConstraints(ts));
00588 constraints.addAll(right.genEqualConstraints(ts));
00589 }
00590 setResult(ts);
00591 }
00592
00593
00594
00595
00596
00597 public Abstraction getAbstraction(Type vType) {
00598 if (vType instanceof NullType) {
00599 return ClassAbstraction.v("java.lang.Object");
00600 } else if (vType instanceof ArrayType) {
00601 return ArrayAbstraction.v(getAbstraction(((ArrayType) vType).baseType), ConcreteIntegralAbstraction.v());
00602 } else if (vType instanceof RefType) {
00603 return ClassAbstraction.v(((RefType) vType).className);
00604 } else if ((vType instanceof FloatType) || (vType instanceof DoubleType)) {
00605 return ConcreteRealAbstraction.v();
00606 } else if (vType instanceof BaseType) {
00607 return ConcreteIntegralAbstraction.v();
00608 } else return null;
00609 }
00610
00611
00612
00613
00614
00615
00616 public TypeStructure getCoercedTypeStructure(Value v) {
00617 TypeStructure ats = getTypeStructure(v.getType());
00618 setAST(ats, "a(" + v + ")");
00619 return ats;
00620 }
00621
00622
00623
00624
00625
00626
00627 public TypeStructure getCoercedTypeStructure(SootField f) {
00628 TypeStructure ats = getTypeStructure(f.getType());
00629 setAST(ats, "a(" + f + ")");
00630 return ats;
00631 }
00632
00633
00634
00635
00636 public java.util.Hashtable getErrors() {
00637 return errors;
00638 }
00639
00640
00641
00642
00643 public java.util.Hashtable getInterfaceMethodMethod() {
00644 return interfaceMethodMethod;
00645 }
00646
00647
00648
00649
00650
00651 public Object getType(TypeStructure ts) {
00652 Object t;
00653 if (ts instanceof ObjectTypeStructure) {
00654 t = tdg.getType(((ObjectTypeStructure) ts).getVar());
00655 } else
00656 if (ts instanceof BaseTypeStructure) {
00657 t = tdg.getType(((BaseTypeStructure) ts).getVar());
00658 } else {
00659 Abstraction components = (Abstraction) getType(((ArrayTypeStructure) ts).getElements());
00660 IntegralAbstraction index = (IntegralAbstraction) getType(((ArrayTypeStructure) ts).getIndex());
00661 t = ArrayAbstraction.v(components, index);
00662 }
00663 return t;
00664 }
00665
00666
00667
00668
00669
00670
00671 public Object getType(Object o) {
00672 if (o instanceof SootField) {
00673 return ((SootField) o).getType();
00674 } else
00675 if (o instanceof Value) {
00676 return ((Value) o).getType();
00677 } else
00678 System.out.println("Unknown type " + o);
00679 return null;
00680 }
00681
00682
00683
00684
00685
00686
00687 public TypeStructure getTypeStructure(Value v) {
00688 TypeStructure ats = (TypeStructure) ast2TypeStruct.get(v);
00689 if (ats == null) {
00690 ats = getTypeStructure(v.getType());
00691 ast2TypeStruct.put(v, ats);
00692 setAST(ats, v);
00693 }
00694 return ats;
00695 }
00696
00697
00698
00699
00700
00701
00702 public TypeStructure getTypeStructure(SootField f) {
00703 TypeStructure ats = (TypeStructure) ast2TypeStruct.get(f);
00704 if (ats == null) {
00705 ats = getTypeStructure(f.getType());
00706 ast2TypeStruct.put(f, ats);
00707 setAST(ats, f);
00708 }
00709 return ats;
00710 }
00711
00712
00713
00714
00715
00716
00717 public TypeStructure getTypeStructure(TypeVariable tv) {
00718 TypeStructure ats;
00719 if (tv.getType() instanceof ArrayType) {
00720 System.out.println("What am I doing here?");
00721 ats = null;
00722 } else
00723 if (tv.getType() instanceof RefType || tv.getType() instanceof NullType) {
00724 ats = new ObjectTypeStructure(tv);
00725 tdg.add(tv);
00726 } else
00727 if (tv.getType() instanceof ArrayAbstraction) {
00728 ats = new ObjectTypeStructure(tv);
00729 tdg.add(tv);
00730 } else {
00731 ats = new BaseTypeStructure(tv);
00732 tdg.add(tv);
00733 }
00734 return ats;
00735 }
00736
00737
00738
00739
00740
00741
00742 public TypeStructure getTypeStructure(Object t) {
00743 TypeStructure ats;
00744 if (t instanceof ArrayType) {
00745 ArrayType at = (ArrayType) t;
00746 TypeStructure index = getTypeStructure(ConcreteIntegralAbstraction.v());
00747 TypeStructure elements = getTypeStructure(at.baseType);
00748 ats = new ArrayTypeStructure(elements, index);
00749 } else
00750 if (t instanceof RefType || t instanceof NullType) {
00751 TypeVariable tv = new TypeVariable(t);
00752 ats = new ObjectTypeStructure(tv);
00753 tdg.add(tv);
00754 } else
00755 if (t instanceof ArrayAbstraction) {
00756 TypeVariable tv = new TypeVariable(t);
00757 ats = new ObjectTypeStructure(tv);
00758 tdg.add(tv);
00759 } else {
00760 TypeVariable tv = new TypeVariable(t);
00761 ats = new BaseTypeStructure(tv);
00762 tdg.add(tv);
00763 }
00764 return ats;
00765 }
00766
00767
00768
00769
00770
00771
00772 public void setAST(TypeStructure ts, Object ast) {
00773 if (ts instanceof BaseTypeStructure)
00774 ((BaseTypeStructure) ts).getVar().setAST(ast);
00775 else
00776 if (ts instanceof ObjectTypeStructure)
00777 ((ObjectTypeStructure) ts).getVar().setAST(ast);
00778 else {
00779 ArrayTypeStructure ats = (ArrayTypeStructure) ts;
00780 setAST(ats.getIndex(), ast);
00781 setAST(ats.getElements(), ast);
00782 }
00783 }
00784
00785
00786
00787
00788 public void setErrors(java.util.Hashtable newErrors) {
00789 errors = newErrors;
00790 }
00791 public int solveCoercions() {
00792 System.out.println("\tRemoving Cycles.");
00793 tdg.removeCycles();
00794 System.out.println("\tGet Connected.");
00795 Set connected = tdg.getNotSingleConnected();
00796 System.out.println("Bubbling Data.");
00797 Iterator i = connected.iterator();
00798 while (i.hasNext()) {
00799 boolean types = false;
00800 Vector q = new Vector();
00801 Set vars = new HashSet();
00802 Set roots = (Set) i.next();
00803 q.addAll(roots);
00804 TypeVariable o;
00805 while (q.size() > 0 && !types) {
00806 o = (TypeVariable) q.remove(0);
00807 if (!vars.contains(o)) {
00808 vars.add(o);
00809 if (tdg.getType(o) != null) {
00810 types = true;
00811 } else
00812 q.addAll(tdg.getChildren(o));
00813 }
00814 }
00815 if (!types) {
00816 if (vars.size() > 0) {
00817 Object vType = ((TypeVariable) vars.toArray()[0]).getType();
00818 if (vType instanceof RefType) {
00819 Object t = ClassAbstraction.v(((RefType) vType).className);
00820 tdg.addType(t);
00821 Vector v = new Vector(vars);
00822 while (v.size() > 0)
00823 tdg.combine(tdg.getTypeVariable(t), (TypeVariable) v.remove(0));
00824 } else
00825 if (vType instanceof NullType) {
00826 tdg.addType(vType);
00827 Vector v = new Vector(vars);
00828 while (v.size() > 0)
00829 tdg.combine(tdg.getTypeVariable(vType), (TypeVariable) v.remove(0));
00830 } else
00831 if ((vType instanceof FloatType) || (vType instanceof DoubleType)) {
00832 Object t = ConcreteRealAbstraction.v();
00833 tdg.addType(t);
00834 Vector v = new Vector(vars);
00835 while (v.size() > 0)
00836 tdg.combine(tdg.getTypeVariable(t), (TypeVariable) v.remove(0));
00837 } else
00838 if (vType instanceof BaseType) {
00839 Object t = ConcreteIntegralAbstraction.v();
00840 tdg.addType(t);
00841 Vector v = new Vector(vars);
00842 while (v.size() > 0)
00843 tdg.combine(tdg.getTypeVariable(t), (TypeVariable) v.remove(0));
00844 } else {
00845 tdg.addType(vType);
00846 Vector v = new Vector(vars);
00847 while (v.size() > 0)
00848 tdg.combine(tdg.getTypeVariable(vType), (TypeVariable) v.remove(0));
00849 }
00850 }
00851 } else {
00852 Set children;
00853 Iterator j;
00854 Vector v;
00855 Object t, t2;
00856 Vector list = new Vector(roots);
00857 Stack s = new Stack();
00858 Stack c = new Stack();
00859 while (list.size() > 0) {
00860 o = (TypeVariable) list.remove(0);
00861 s.push(o);
00862 c.push(new Vector(tdg.getChildren(o)));
00863 while (!s.empty()) {
00864 o = (TypeVariable) s.peek();
00865 v = (Vector) c.peek();
00866 if (tdg.isLeaf(o)) {
00867 t = tdg.getType(o);
00868 if (t == null) {
00869 t = o.getType();
00870 if ((t instanceof FloatType) || (t instanceof DoubleType)) {
00871 t = ConcreteRealAbstraction.v();
00872 tdg.addType(t);
00873 tdg.combine(tdg.getTypeVariable(t), (TypeVariable) o);
00874 } else
00875 if (t instanceof BaseType) {
00876 t = ConcreteIntegralAbstraction.v();
00877 tdg.addType(t);
00878 tdg.combine(tdg.getTypeVariable(t), (TypeVariable) o);
00879 } else
00880 if (t instanceof RefType) {
00881 t = ClassAbstraction.v(((RefType) t).className);
00882 tdg.addType(t);
00883 tdg.combine(tdg.getTypeVariable(t), (TypeVariable) o);
00884 } else
00885 if (t instanceof ArrayType) {
00886 System.out.println("What to do in arrays.");
00887 } else {
00888 System.out.println("I shouldn't be printing this.");
00889 }
00890 }
00891 s.pop();
00892 c.pop();
00893 } else
00894 if (v.size() > 0) {
00895 o = (TypeVariable) v.remove(0);
00896 s.push(o);
00897 c.push(new Vector(tdg.getChildren(o)));
00898 } else {
00899
00900 s.pop();
00901 c.pop();
00902 children = new HashSet();
00903 j = tdg.getChildren(o).iterator();
00904 while (j.hasNext()) {
00905 t = tdg.getType((TypeVariable) j.next());
00906 if (t == null)
00907 System.out.println("Error: No type here.");
00908 else
00909 children.add(t);
00910 }
00911 t = tdg.getType(o);
00912 t2 = coercionManager.lub(children);
00913 if (t2 == null) {
00914 System.out.println("Error lub for " + children + "\n\tt=" + t);
00915 System.out.println("\t" + o + "\t" + tdg.getChildren(o));
00916 } else
00917 if (t == null) {
00918 tdg.addType(t2);
00919 tdg.combine(tdg.getTypeVariable(t2), (TypeVariable) o);
00920 } else
00921 if (!coercionManager.coerciable((Abstraction) t2, (Abstraction) t)) {
00922 System.out.println("Trying to coerce " + t2 + " to " + t + " which I say is impossible.");
00923 conflicts.add(t2 + " to " + t);
00924 }
00925 }
00926 }
00927 }
00928 }
00929 }
00930 return 0;
00931 }
00932 public void solveConstraints() {
00933 List con = new Vector();
00934 Constraint c;
00935 for (Iterator i = constraints.iterator(); i.hasNext();) {
00936 c = (Constraint) i.next();
00937 if (c instanceof EqualConstraint) {
00938 EqualConstraint e = (EqualConstraint) c;
00939 TypeVariable l = e.getLeft();
00940 TypeVariable r = e.getRight();
00941 tdg.quickCombine(l, r);
00942 } else {
00943 con.add(c);
00944 }
00945 }
00946 for (Iterator i = con.iterator(); i.hasNext();) {
00947 c = (Constraint) i.next();
00948 if (c instanceof CoerceConstraint) {
00949 CoerceConstraint a = (CoerceConstraint) c;
00950 TypeVariable l = a.getLeft();
00951 TypeVariable r = a.getRight();
00952 tdg.addChild(l, r);
00953 } else {
00954 System.out.println("Warning: *** unknown constraint in TypeInference.solveConstraints() ***");
00955 }
00956 }
00957 constraints = con;
00958 }
00959
00960
00961
00962
00963
00964 public TypeTable type(SootClassManager scm, Hashtable options) {
00965 for (Enumeration e = options.keys(); e.hasMoreElements();) {
00966 Object o = e.nextElement();
00967 if (o instanceof SootField) {
00968 SootField sf = (SootField) o;
00969 TypeStructure n = getTypeStructure(sf);
00970 TypeVariable tv = tdg.addType(options.get(sf));
00971 constraints.addAll(n.genEqualConstraints(getTypeStructure(tv)));
00972 }
00973 }
00974 for (Enumeration e = options.keys(); e.hasMoreElements();) {
00975 Object o = e.nextElement();
00976 if (o instanceof LocalMethod) {
00977 LocalMethod lm = (LocalMethod) o;
00978 TypeStructure n = getTypeStructure(lm.getLocal());
00979 Object t = options.get(new LocalMethod(lm.getMethod(), lm.getLocal()));
00980 TypeVariable tv = tdg.addType(t);
00981 constraints.addAll(n.genEqualConstraints(getTypeStructure(tv)));
00982 }
00983 }
00984 for (Enumeration e = options.keys(); e.hasMoreElements();) {
00985 Object o = e.nextElement();
00986 if (o instanceof SootClass) {
00987 SootClass sc = (SootClass) o;
00988 for (ca.mcgill.sable.util.Iterator i = sc.getMethods().iterator(); i.hasNext();) {
00989 SootMethod sm = (SootMethod) i.next();
00990 createInheritanceConstraints(sm);
00991 }
00992 }
00993 }
00994 for (Enumeration e = options.keys(); e.hasMoreElements();) {
00995 Object o = e.nextElement();
00996 if (o instanceof SootClass) {
00997 SootClass sc = (SootClass) o;
00998 for (ca.mcgill.sable.util.Iterator i = sc.getMethods().iterator(); i.hasNext();) {
00999 SootMethod sm = (SootMethod) i.next();
01000 Vector p = new Vector();
01001 if (sm.isStatic()) {
01002 p.add(new Object());
01003 } else {
01004 Object t = ClassAbstraction.v(sm.getDeclaringClass().getName());
01005 TypeStructure v = getTypeStructure(t);
01006 tdg.addType(t);
01007 p.add(v);
01008 }
01009 for (ca.mcgill.sable.util.Iterator j = sm.getParameterTypes().iterator(); j.hasNext();) {
01010 p.add(getTypeStructure(j.next()));
01011 }
01012 createConstraints(sm, p, getTypeStructure(sm.getReturnType()));
01013 }
01014 }
01015 }
01016
01017 System.out.println("Solving Constraints.");
01018 solveConstraints();
01019 System.out.println("Solving Coercions.");
01020 solveCoercions();
01021
01022 System.out.println("Assign Types.");
01023 List unknowns = new Vector();
01024 Iterator i = ast2TypeStruct.keySet().iterator();
01025 Object t;
01026 Object n;
01027 TypeStructure tv;
01028 while (i.hasNext()) {
01029 n = i.next();
01030 tv = (TypeStructure) ast2TypeStruct.get(n);
01031 t = getType(tv);
01032 if (t == null) {
01033 Type vType = n instanceof Value? ((Value) n).getType() : ((SootField) n).getType();
01034 Abstraction a = getAbstraction(vType);
01035 if (a != null)
01036 nodes.put(n, a);
01037 else
01038 unknowns.add(n);
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061 } else {
01062 if (t instanceof ArrayAbstraction) {
01063 ArrayType vType = (ArrayType) (n instanceof Value? ((Value) n).getType() : ((SootField) n).getType());
01064 ArrayAbstraction aa = (ArrayAbstraction) t;
01065 IntegralAbstraction indexAbstraction = aa.getIndexAbstraction();
01066 if (indexAbstraction == null) indexAbstraction = ConcreteIntegralAbstraction.v();
01067 Abstraction elementAbstraction = aa.getElementAbstraction();
01068 if (elementAbstraction == null) elementAbstraction = getAbstraction(vType.baseType);
01069 t = ArrayAbstraction.v(elementAbstraction, indexAbstraction);
01070 }
01071 nodes.put(n, t);
01072 }
01073 }
01074
01075
01076
01077 if (unknowns.size() != 0) {
01078 errors.put("Unknowns", unknowns);
01079 }
01080 if (conflicts.size() != 0) {
01081 errors.put("Conflicts", conflicts);
01082 }
01083
01084
01085
01086
01087 return nodes;
01088 }
01089 }