00001 package edu.ksu.cis.bandera.prog;
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 import ca.mcgill.sable.soot.*;
00038 import java.util.*;
00039 import ca.mcgill.sable.soot.jimple.*;
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 public class BlockMap extends HashMap implements Cloneable {
00052
00053
00054
00055 public final static int BLOCKLEVEL = 0;
00056
00057
00058
00059
00060 public final static int STMTLEVEL = 1;
00061
00062
00063
00064
00065
00066 public final static int HAMMOCK = 2;
00067
00068
00069
00070
00071 public static String returnVariable = "$RESULT$";
00072 protected Index initBlock;
00073 protected List finalBlocks;
00074 protected Map stmtToIndex;
00075 protected JimpleBody listBody;
00076 protected ca.mcgill.sable.util.List locals;
00077 protected StmtList stmtList;
00078 protected SootMethod method;
00079 protected Map nameToLocal;
00080
00081
00082
00083
00084
00085
00086 public BlockMap() {
00087 super();
00088 stmtToIndex = new HashMap();
00089 locals = new ca.mcgill.sable.util.VectorList();
00090 nameToLocal = new HashMap();
00091 finalBlocks = new ArrayList();
00092 }
00093
00094
00095
00096
00097
00098
00099
00100 public BlockMap(SootMethod m, int flags)
00101 {
00102 this();
00103
00104 boolean hammock = (flags & HAMMOCK) > 0;
00105 boolean stmtLevel = (flags & STMTLEVEL) > 0;
00106
00107 method = m;
00108
00109 if (stmtLevel)
00110 setupStmtLevel(hammock);
00111 else
00112 setupBlockLevel(hammock);
00113 }
00114
00115
00116
00117
00118
00119 public void addLocal(Local l)
00120 {
00121 locals.add(l);
00122 }
00123
00124
00125
00126
00127
00128
00129
00130
00131 public ca.mcgill.sable.util.List collapse() {
00132 Vector pending = new Vector();
00133 ca.mcgill.sable.util.List stmtList = new ca.mcgill.sable.util.ArrayList();
00134 List visited = new ArrayList();
00135 Iterator it, jt;
00136 Index index;
00137 BasicBlock bb = null, previous = null;
00138 Map indexToStmt = new HashMap();
00139 int count = 0;
00140 setJumps();
00141 it = keySet().iterator();
00142 while (it.hasNext()) {
00143 bb = (BasicBlock) get(it.next());
00144 indexToStmt.put(bb.getIndex(), bb.get(0));
00145 }
00146 pending.addElement(initBlock);
00147 while (pending.size() > 0) {
00148 index = (Index) pending.firstElement();
00149 pending.removeElementAt(0);
00150 if (!visited.contains(index)) {
00151 visited.add(index);
00152 bb = (BasicBlock) get(index);
00153 if (bb == null)
00154 System.out.println("Null basic block: why?");
00155 else {
00156 stmtList.addAll(bb.get());
00157 switch (bb.getSuccs().size()) {
00158 case 1 :
00159 if (visited.contains(bb.getSuccs(0)))
00160 stmtList.add(Jimple.v().newGotoStmt((Stmt) indexToStmt.get(bb.getSuccs(0))));
00161 else
00162 pending.insertElementAt(bb.getSuccs(0), 0);
00163 break;
00164 case 2 :
00165 if (!visited.contains(bb.getSuccs(0)))
00166 pending.addElement(bb.getSuccs(0));
00167 if (visited.contains(bb.getSuccs(1)))
00168 stmtList.add(Jimple.v().newGotoStmt((Stmt) indexToStmt.get(bb.getSuccs(1))));
00169 else
00170 pending.insertElementAt(bb.getSuccs(1), 0);
00171 break;
00172 }
00173 previous = bb;
00174 }
00175 }
00176 }
00177 return stmtList;
00178 }
00179 protected void compress() {
00180 Iterator it;
00181
00182
00183 {
00184 BasicBlock bb1, bb2;
00185 Index index;
00186 it = keySet().iterator();
00187 Iterator jt;
00188 while (it.hasNext()) {
00189 bb1 = (BasicBlock) get(it.next());
00190 jt = bb1.getSuccs().iterator();
00191 while (jt.hasNext()) {
00192 bb2 = (BasicBlock) get(jt.next());
00193 bb2.addPreds(bb1.getIndex());
00194 }
00195 }
00196 }
00197 Set s = new HashSet();
00198 s.addAll(keySet());
00199 it = s.iterator();
00200 while (it.hasNext()) {
00201 BasicBlock bb = (BasicBlock) get(it.next());
00202 if (bb.get().size() == 0) {
00203 if (bb.getIndex().equals(initBlock))
00204 initBlock = bb.getSuccs(0);
00205 BasicBlock tmp;
00206 Iterator jt;
00207 jt = bb.getPreds().iterator();
00208 while (jt.hasNext()) {
00209 tmp = (BasicBlock) get(jt.next());
00210 tmp.changeSuccs(bb.getIndex(), bb.getSuccs(0));
00211 }
00212 tmp = (BasicBlock) get(bb.getSuccs(0));
00213 tmp.changePreds(bb.getIndex(), bb.getPreds());
00214 remove(bb.getIndex());
00215 }
00216 }
00217 }
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228 public SootMethod createMethod(String name, ca.mcgill.sable.util.List params, Type ret) {
00229 SootMethod method = new SootMethod(name, params, ret);
00230 JimpleBody body = (JimpleBody) Jimple.v().newBody(method);
00231 ca.mcgill.sable.util.Iterator it = locals.iterator();
00232 while (it.hasNext())
00233 body.addLocal((Local) it.next());
00234 ca.mcgill.sable.util.Iterator it2 = collapse().iterator();
00235 StmtList stmtList = body.getStmtList();
00236 while (it2.hasNext())
00237 stmtList.add(it2.next());
00238 method.storeBody(Jimple.v(), body);
00239
00240
00241
00242 return method;
00243 }
00244
00245
00246
00247
00248
00249 public List getFinalBlocks()
00250 {
00251 return finalBlocks;
00252 }
00253
00254
00255
00256 public Index getInit()
00257 {
00258 return initBlock;
00259 }
00260
00261
00262
00263 public JimpleBody getListBody()
00264 {
00265 return listBody;
00266 }
00267
00268
00269
00270
00271
00272
00273 public Local getLocal(String name, Type t)
00274 {
00275 Map types;
00276
00277 if ((types = (Map)nameToLocal.get(name)) == null)
00278 {
00279 Map tmp = new HashMap();
00280 Local l = Jimple.v().newLocal(name, t);
00281 tmp.put(t, l);
00282 nameToLocal.put(name, tmp);
00283 locals.add(l);
00284 }
00285 else
00286 if (types.get(t) == null)
00287 {
00288 Local l = Jimple.v().newLocal(name, t);
00289 types.put(t, l);
00290 locals.add(l);
00291 }
00292
00293 return (Local)((Map)nameToLocal.get(name)).get(t);
00294 }
00295
00296
00297
00298 public ca.mcgill.sable.util.List getLocals()
00299 {
00300 return locals;
00301 }
00302
00303
00304
00305 public Map getStmtToIndex()
00306 {
00307 return stmtToIndex;
00308 }
00309
00310
00311
00312 public void setInit(Index i)
00313 {
00314 initBlock = i;
00315 }
00316
00317
00318
00319
00320
00321
00322
00323 protected void setJumps() {
00324 Iterator it;
00325 int s;
00326 Stmt last;
00327 final Map indexToStmt = new HashMap();
00328 compress();
00329 it = keySet().iterator();
00330 while (it.hasNext()) {
00331 BasicBlock bb = (BasicBlock) get(it.next());
00332 indexToStmt.put(bb.getIndex(), bb.get(0));
00333 stmtToIndex.put(bb.get(0), bb.getIndex());
00334 }
00335 it = keySet().iterator();
00336 while (it.hasNext()) {
00337 final BasicBlock bb = (BasicBlock) get(it.next());
00338 AbstractStmtSwitch asw = new AbstractStmtSwitch() {
00339 public void caseGotoStmt(GotoStmt s) {
00340 s.setTarget((Stmt) indexToStmt.get(bb.getSuccs(0)));
00341 }
00342 public void caseIfStmt(IfStmt s) {
00343 s.setTarget((Stmt) indexToStmt.get(bb.getSuccs(0)));
00344 }
00345 };
00346 if (bb.getGoOn() != null) {
00347 Iterator jt = bb.getGoOn().iterator();
00348 while (jt.hasNext()) {
00349 last = (Stmt) jt.next();
00350 last.apply(asw);
00351 }
00352 } else {
00353 last = bb.get(bb.get().size() - 1);
00354 last.apply(asw);
00355 }
00356 }
00357
00358
00359 {
00360 BasicBlock bb1, bb2;
00361 Index index;
00362 it = keySet().iterator();
00363 Iterator jt;
00364 while (it.hasNext()) {
00365 bb1 = (BasicBlock) get(it.next());
00366 jt = bb1.getSuccs().iterator();
00367 while (jt.hasNext()) {
00368 bb2 = (BasicBlock) get(jt.next());
00369 bb2.addPreds(bb1.getIndex());
00370 }
00371 }
00372 }
00373 }
00374
00375
00376
00377 public void setLocals(ca.mcgill.sable.util.List l) {
00378 locals = l;
00379 }
00380 protected void setupBlockLevel(boolean hammock) {
00381 JimpleBody body = listBody = (JimpleBody) method.getBody(Jimple.v());
00382 stmtList = body.getStmtList();
00383
00384 Map stmtToName = new HashMap(stmtList.size() * 2 + 1, 0.7f);
00385 StmtGraph stmtGraph = new BriefStmtGraph(stmtList);
00386 BasicBlock bb, finalBlock;
00387 int blockCount = 0;
00388 Local returnValue = null;
00389 ca.mcgill.sable.util.Iterator it = body.getLocals().iterator();
00390
00391 while (it.hasNext())
00392 locals.add(it.next());
00393
00394
00395 if (hammock) {
00396 Stmt returnStmt;
00397
00398
00399 finalBlock = new BasicBlock(new Index(blockCount++));
00400
00401
00402 if (method.getReturnType() instanceof VoidType)
00403 finalBlock.addStmt(Jimple.v().newReturnVoidStmt());
00404 else {
00405 if (method.getReturnType() instanceof BooleanType)
00406 returnValue = Jimple.v().newLocal(method.getReturnType().toString() + returnVariable, IntType.v());
00407 else
00408 returnValue = Jimple.v().newLocal(method.getReturnType().toString() + returnVariable, method.getReturnType());
00409 finalBlock.addStmt(Jimple.v().newReturnStmt(returnValue));
00410 locals.add(returnValue);
00411 }
00412
00413
00414 stmtToIndex.put(finalBlock.get(0), finalBlock.getIndex());
00415 put(finalBlock.getIndex(), finalBlock);
00416 } else
00417 finalBlock = null;
00418
00419
00420
00421 {
00422 ca.mcgill.sable.util.Iterator boxIt = body.getUnitBoxes().iterator();
00423 Set labelStmts = new HashSet();
00424
00425
00426 {
00427 while (boxIt.hasNext()) {
00428 UnitBox box = (UnitBox) boxIt.next();
00429 Stmt stmt = (Stmt) box.getUnit();
00430 labelStmts.add(stmt);
00431 }
00432 }
00433
00434
00435 {
00436 int labelCount = 0;
00437 ca.mcgill.sable.util.Iterator stmtIt = stmtList.iterator();
00438 while (stmtIt.hasNext()) {
00439 Stmt s = (Stmt) stmtIt.next();
00440 if (labelStmts.contains(s))
00441 stmtToName.put(s, "label" + (labelCount++));
00442 }
00443 }
00444 }
00445 bb = new BasicBlock(new Index(blockCount++));
00446 put(bb.getIndex(), bb);
00447 initBlock = bb.getIndex();
00448 stmtToIndex.put(stmtList.get(0), bb.getIndex());
00449 for (int j = 0; j < stmtList.size(); j++) {
00450 Stmt s = ((Stmt) stmtList.get(j));
00451
00452
00453
00454
00455
00456 {
00457 if (j != 0) {
00458 Stmt previousStmt = (Stmt) stmtList.get(j - 1);
00459 if (stmtGraph.getSuccsOf(previousStmt).size() != 1 || stmtGraph.getPredsOf(s).size() != 1 || stmtToName.containsKey(s)) {
00460 ca.mcgill.sable.util.Iterator succsIterator = stmtGraph.getSuccsOf(previousStmt).iterator();
00461 while (succsIterator.hasNext()) {
00462 Stmt stmt = (Stmt) succsIterator.next();
00463 if (!stmtToIndex.containsKey(stmt))
00464 stmtToIndex.put(stmt, new Index(blockCount++));
00465 bb.addSuccs((Index) stmtToIndex.get(stmt));
00466 }
00467
00468
00469 if (!stmtToIndex.containsKey(s))
00470 stmtToIndex.put(s, new Index(blockCount++));
00471 bb = new BasicBlock((Index) stmtToIndex.get(s));
00472 put(bb.getIndex(), bb);
00473 if (!hammock && stmtGraph.getSuccsOf(s).size() == 0)
00474 finalBlocks.add(bb.getIndex());
00475 } else {
00476
00477
00478
00479 ca.mcgill.sable.util.List succs = stmtGraph.getSuccsOf(previousStmt);
00480 if (succs.get(0) != s) {
00481 ca.mcgill.sable.util.Iterator succsIterator = stmtGraph.getSuccsOf(previousStmt).iterator();
00482 while (succsIterator.hasNext()) {
00483 Stmt stmt = (Stmt) succsIterator.next();
00484 if (!stmtToIndex.containsKey(stmt))
00485 stmtToIndex.put(stmt, new Index(blockCount++));
00486 bb.addSuccs((Index) stmtToIndex.get(stmt));
00487 }
00488
00489
00490 if (!stmtToIndex.containsKey(s))
00491 stmtToIndex.put(s, new Index(blockCount++));
00492 bb = new BasicBlock((Index) stmtToIndex.get(s));
00493 put(bb.getIndex(), bb);
00494 }
00495 }
00496 }
00497 }
00498 {
00499 if (s instanceof GotoStmt)
00500 bb.addStmt(s);
00501 else
00502 if (s instanceof ReturnStmt && hammock) {
00503 if (returnValue != null) {
00504 Stmt stmt = Jimple.v().newAssignStmt(returnValue, ((ReturnStmt) s).getReturnValue());
00505 bb.addStmt(stmt);
00506 }
00507 bb.addSuccs(finalBlock.getIndex());
00508 } else
00509 bb.addStmt(s);
00510 }
00511 }
00512 ca.mcgill.sable.util.Iterator succsIterator = stmtGraph.getSuccsOf((Stmt) stmtList.get(stmtList.size() - 1)).iterator();
00513 while (succsIterator.hasNext()) {
00514 Stmt stmt = (Stmt) succsIterator.next();
00515 if (!stmtToIndex.containsKey(stmt))
00516 stmtToIndex.put(stmt, new Index(blockCount++));
00517 bb.addSuccs((Index) stmtToIndex.get(stmt));
00518 }
00519
00520
00521 {
00522 BasicBlock bb1, bb2;
00523 Index index;
00524 Iterator it2 = keySet().iterator();
00525 Iterator jt;
00526 while (it2.hasNext()) {
00527 bb1 = (BasicBlock) get(it2.next());
00528 jt = bb1.getSuccs().iterator();
00529 while (jt.hasNext()) {
00530 bb2 = (BasicBlock) get(jt.next());
00531 bb2.addPreds(bb1.getIndex());
00532 }
00533 }
00534 }
00535 }
00536 protected void setupStmtLevel(boolean hammock) {
00537 JimpleBody body = listBody = (JimpleBody) method.getBody(Jimple.v());
00538 stmtList = body.getStmtList();
00539
00540 Map stmtToName = new HashMap(stmtList.size() * 2 + 1, 0.7f);
00541 StmtGraph stmtGraph = new BriefStmtGraph(stmtList);
00542 BasicBlock bb = null, finalBlock;
00543 int blockCount = 0;
00544 Local returnValue = null;
00545 ca.mcgill.sable.util.Iterator it = body.getLocals().iterator();
00546 while (it.hasNext())
00547
00548
00549
00550 locals.add(it.next());
00551
00552
00553 {
00554 ca.mcgill.sable.util.Iterator boxIt = body.getUnitBoxes().iterator();
00555 Set labelStmts = new HashSet();
00556
00557
00558 {
00559 while (boxIt.hasNext()) {
00560 UnitBox box = (UnitBox) boxIt.next();
00561 Stmt stmt = (Stmt) box.getUnit();
00562 labelStmts.add(stmt);
00563 }
00564 }
00565
00566
00567 {
00568 int labelCount = 0;
00569 ca.mcgill.sable.util.Iterator stmtIt = stmtList.iterator();
00570 while (stmtIt.hasNext()) {
00571 Stmt s = (Stmt) stmtIt.next();
00572 if (labelStmts.contains(s))
00573 stmtToName.put(s, "label" + (labelCount++));
00574 }
00575 }
00576 }
00577 if (hammock)
00578
00579
00580
00581 {
00582 Stmt returnStmt;
00583
00584
00585 finalBlock = new BasicBlock(new Index(blockCount++));
00586
00587
00588 if (method.getReturnType() instanceof VoidType)
00589 finalBlock.addStmt(Jimple.v().newReturnVoidStmt());
00590 else {
00591 if (method.getReturnType() instanceof BooleanType)
00592 returnValue = Jimple.v().newLocal(method.getReturnType().toString() + returnVariable, IntType.v());
00593 else
00594 returnValue = Jimple.v().newLocal(method.getReturnType().toString() + returnVariable, method.getReturnType());
00595 finalBlock.addStmt(Jimple.v().newReturnStmt(returnValue));
00596 locals.add(returnValue);
00597 }
00598
00599
00600 stmtToIndex.put(finalBlock.get(0), finalBlock.getIndex());
00601 put(finalBlock.getIndex(), finalBlock);
00602 } else
00603 finalBlock = null;
00604 for (int j = 0; j < stmtList.size(); j++) {
00605 boolean noGoto = false;
00606 Stmt s = ((Stmt) stmtList.get(j));
00607 if (!noGoto) {
00608 if (!stmtToIndex.containsKey(s))
00609 stmtToIndex.put(s, new Index(blockCount++));
00610 bb = new BasicBlock((Index) stmtToIndex.get(s));
00611 ca.mcgill.sable.util.Iterator succsIterator = stmtGraph.getSuccsOf(s).iterator();
00612 while (succsIterator.hasNext()) {
00613 Stmt stmt = (Stmt) succsIterator.next();
00614 if (!stmtToIndex.containsKey(stmt))
00615 stmtToIndex.put(stmt, new Index(blockCount++));
00616 bb.addSuccs((Index) stmtToIndex.get(stmt));
00617 }
00618 } else {
00619 noGoto = false;
00620 stmtToIndex.put(s, bb.getIndex());
00621 ca.mcgill.sable.util.Iterator succsIterator = stmtGraph.getSuccsOf(s).iterator();
00622 while (succsIterator.hasNext()) {
00623 Stmt stmt = (Stmt) succsIterator.next();
00624 if (!stmtToIndex.containsKey(stmt))
00625 stmtToIndex.put(stmt, new Index(blockCount++));
00626 bb.addSuccs((Index) stmtToIndex.get(stmt));
00627 }
00628 }
00629 put(bb.getIndex(), bb);
00630 if (j == 0)
00631 initBlock = bb.getIndex();
00632 stmtToIndex.put(stmtList.get(0), bb.getIndex());
00633 if (s instanceof GotoStmt)
00634 noGoto = true;
00635 else
00636 if (s instanceof ReturnStmt)
00637 if (hammock) {
00638 if (returnValue != null) {
00639 Stmt stmt = Jimple.v().newAssignStmt(returnValue, ((ReturnStmt) s).getReturnValue());
00640 bb.addStmt(stmt);
00641 }
00642 bb.addSuccs(finalBlock.getIndex());
00643 } else
00644 finalBlocks.add(bb);
00645 else
00646 bb.addStmt(s);
00647 }
00648
00649
00650 {
00651 BasicBlock bb1, bb2;
00652 Index index;
00653 Iterator it2 = keySet().iterator();
00654 Iterator jt;
00655 while (it2.hasNext()) {
00656 bb1 = (BasicBlock) get(it2.next());
00657 jt = bb1.getSuccs().iterator();
00658 while (jt.hasNext()) {
00659 bb2 = (BasicBlock) get(jt.next());
00660 bb2.addPreds(bb1.getIndex());
00661 }
00662 }
00663 }
00664 }
00665 public String toString()
00666 {
00667 Index index;
00668 String s = "";
00669 Iterator i;
00670
00671
00672
00673 i = keySet().iterator();
00674
00675
00676 while (i.hasNext())
00677 {
00678 index = (Index)i.next();
00679
00680 s += get(index);
00681 }
00682
00683 return s;
00684 }
00685 }