1 19 20 package soot.shimple.toolkits.scalar; 21 22 import soot.*; 23 import soot.util.*; 24 import soot.options.*; 25 import soot.jimple.*; 26 import soot.shimple.*; 27 import soot.toolkits.scalar.*; 28 import soot.toolkits.graph.*; 29 import java.util.*; 30 import soot.shimple.toolkits.scalar.SEvaluator.MetaConstant; 31 import soot.shimple.toolkits.scalar.SEvaluator.TopConstant; 32 import soot.shimple.toolkits.scalar.SEvaluator.BottomConstant; 33 34 47 public class SConstantPropagatorAndFolder extends BodyTransformer 48 { 49 public SConstantPropagatorAndFolder(Singletons.Global g) {} 50 51 public static SConstantPropagatorAndFolder v() 52 { return G.v().soot_shimple_toolkits_scalar_SConstantPropagatorAndFolder(); } 53 54 protected ShimpleBody sb; 55 protected boolean debug; 56 57 protected void internalTransform(Body b, String phaseName, Map options) 58 { 59 if(!(b instanceof ShimpleBody)) 60 throw new RuntimeException ("SConstantPropagatorAndFolder requires a ShimpleBody."); 61 62 this.sb = (ShimpleBody) b; 63 64 if(!sb.isSSA()) 65 throw new RuntimeException ("ShimpleBody is not in proper SSA form as required by SConstantPropagatorAndFolder. You may need to rebuild it or use ConstantPropagatorAndFolder instead."); 66 67 boolean pruneCFG = PhaseOptions.getBoolean(options, "prune-cfg"); 68 debug = Options.v().debug(); 69 debug |= sb.getOptions().debug(); 70 71 if (Options.v().verbose()) 72 G.v().out.println("[" + sb.getMethod().getName() + 73 "] Propagating and folding constants (SSA)..."); 74 75 SCPFAnalysis scpf = new SCPFAnalysis(new ExceptionalUnitGraph(sb)); 77 78 propagateResults(scpf.getResults()); 79 if(pruneCFG){ 80 removeStmts(scpf.getDeadStmts()); 81 replaceStmts(scpf.getStmtsToReplace()); 82 } 83 } 84 85 90 protected void propagateResults(Map localToConstant) 91 { 92 Chain units = sb.getUnits(); 93 Chain locals = sb.getLocals(); 94 ShimpleLocalDefs localDefs = new ShimpleLocalDefs(sb); 95 ShimpleLocalUses localUses = new ShimpleLocalUses(sb); 96 97 Iterator localsIt = locals.iterator(); 98 while(localsIt.hasNext()){ 99 Local local = (Local) localsIt.next(); 100 Constant constant = (Constant) localToConstant.get(local); 101 102 if(constant instanceof MetaConstant) 103 continue; 104 105 { 107 DefinitionStmt stmt = 108 (DefinitionStmt) localDefs.getDefsOf(local).get(0); 109 110 ValueBox defSrcBox = stmt.getRightOpBox(); 111 Value defSrc = defSrcBox.getValue(); 112 113 if(defSrcBox.canContainValue(constant)){ 114 defSrcBox.setValue(constant); 115 116 if(defSrc instanceof UnitBoxOwner) 118 ((UnitBoxOwner)defSrc).clearUnitBoxes(); 119 } 120 else if(debug) 121 G.v().out.println("Warning: Couldn't propagate constant " + constant + " to box " + defSrcBox.getValue() + " in unit " + stmt); 122 } 123 124 { 126 Iterator usesIt = localUses.getUsesOf(local).iterator(); 127 128 while(usesIt.hasNext()){ 129 UnitValueBoxPair pair = (UnitValueBoxPair) usesIt.next(); 130 ValueBox useBox = pair.getValueBox(); 131 132 if(useBox.canContainValue(constant)) 133 useBox.setValue(constant); 134 else if(debug) 135 G.v().out.println("Warning: Couldn't propagate constant " + constant + " to box " + useBox.getValue() + " in unit " + pair.getUnit()); 136 } 137 } 138 } 139 } 140 141 144 protected void removeStmts(List deadStmts) 145 { 146 Chain units = sb.getUnits(); 147 Iterator deadIt = deadStmts.iterator(); 148 while(deadIt.hasNext()){ 149 Unit dead = (Unit) deadIt.next(); 150 units.remove(dead); 151 dead.clearUnitBoxes(); 152 } 153 } 154 155 159 protected void replaceStmts(Map stmtsToReplace) 160 { 161 Chain units = sb.getUnits(); 162 Iterator stmtsIt = stmtsToReplace.keySet().iterator(); 163 while(stmtsIt.hasNext()){ 164 Unit booted = (Unit) stmtsIt.next(); 167 Unit replacement = (Unit) stmtsToReplace.get(booted); 168 units.swapWith(booted, replacement); 169 } 170 } 171 } 172 173 211 class SCPFAnalysis extends ForwardBranchedFlowAnalysis 212 { 213 protected FlowSet emptySet; 214 215 219 protected Map localToConstant; 220 221 225 protected Map stmtToReplacement; 226 227 230 protected List deadStmts; 231 232 233 236 public Map getResults() 237 { 238 return localToConstant; 239 } 240 241 244 public List getDeadStmts() 245 { 246 return deadStmts; 247 } 248 249 253 public Map getStmtsToReplace() 254 { 255 return stmtToReplacement; 256 } 257 258 public SCPFAnalysis(UnitGraph graph) 259 { 260 super(graph); 261 emptySet = new ArraySparseSet(); 262 stmtToReplacement = new HashMap(); 263 deadStmts = new ArrayList(); 264 265 { 268 Chain locals = graph.getBody().getLocals(); 269 Iterator localsIt = locals.iterator(); 270 localToConstant = new HashMap(graph.size() * 2 + 1, 0.7f); 271 272 while(localsIt.hasNext()){ 273 Local local = (Local) localsIt.next(); 274 localToConstant.put(local, TopConstant.v()); 275 } 276 } 277 278 doAnalysis(); 279 } 280 281 protected boolean treatTrapHandlersAsEntries() 286 { 287 return true; 288 } 289 290 295 protected Object entryInitialFlow() 296 { 297 FlowSet entrySet = (FlowSet) emptySet.emptySet(); 298 entrySet.add(TopConstant.v()); 299 return entrySet; 300 } 301 302 305 protected Object newInitialFlow() 306 { 307 return emptySet.emptySet(); 308 } 309 310 314 protected void merge(Object in1, Object in2, Object out) 315 { 316 FlowSet fin1 = (FlowSet) in1; 317 FlowSet fin2 = (FlowSet) in2; 318 FlowSet fout = (FlowSet) out; 319 320 fin1.union(fin2, fout); 321 } 322 323 326 protected void copy(Object source, Object dest) 327 { 328 FlowSet fource = (FlowSet) source; 329 FlowSet fest = (FlowSet) dest; 330 331 fource.copy(fest); 332 } 333 334 346 protected void flowThrough(Object in, Unit s, List fallOut, List branchOuts) 347 { 348 FlowSet fin = (FlowSet) ((FlowSet)in).clone(); 349 350 if(fin.isEmpty()) 352 return; 353 354 Pair pair = processDefinitionStmt(s); 357 358 if(pair != null) 359 fin.add(pair); 360 361 if(!s.branches() && s.fallsThrough()){ 363 Iterator fallOutIt = fallOut.iterator(); 364 while(fallOutIt.hasNext()){ 365 FlowSet fallSet = (FlowSet) fallOutIt.next(); 366 fallSet.union(fin); 367 } 368 369 return; 370 } 371 372 373 374 boolean conservative = true; 375 boolean fall = false; 376 boolean branch = false; 377 FlowSet oneBranch = null; 378 379 IFSTMT: 380 { 381 if(s instanceof IfStmt){ 382 IfStmt ifStmt = (IfStmt) s; 383 Value cond = ifStmt.getCondition(); 384 Constant constant = 385 SEvaluator.getFuzzyConstantValueOf(cond, localToConstant); 386 387 if(constant instanceof BottomConstant){ 389 deadStmts.remove(ifStmt); 390 stmtToReplacement.remove(ifStmt); 391 break IFSTMT; 392 } 393 394 if(constant instanceof TopConstant) 396 return; 397 398 399 400 conservative = false; 401 402 Constant trueC = IntConstant.v(1); 403 Constant falseC = IntConstant.v(0); 404 405 if(constant.equals(trueC)){ 406 branch = true; 407 GotoStmt gotoStmt = 408 Jimple.v().newGotoStmt(ifStmt.getTargetBox()); 409 stmtToReplacement.put(ifStmt, gotoStmt); 410 } 411 412 if(constant.equals(falseC)){ 413 fall = true; 414 deadStmts.add(ifStmt); 415 } 416 } 417 } 419 TABLESWITCHSTMT: 420 { 421 if(s instanceof TableSwitchStmt){ 422 TableSwitchStmt table = (TableSwitchStmt) s; 423 Value keyV = table.getKey(); 424 Constant keyC = 425 SEvaluator.getFuzzyConstantValueOf(keyV, localToConstant); 426 427 if(keyC instanceof BottomConstant){ 429 stmtToReplacement.remove(table); 430 break TABLESWITCHSTMT; 431 } 432 433 if(keyC instanceof TopConstant) 435 return; 436 437 if(!(keyC instanceof IntConstant)) 439 break TABLESWITCHSTMT; 440 441 442 443 conservative = false; 444 445 int key = ((IntConstant)keyC).value; 446 int low = table.getLowIndex(); 447 int high = table.getHighIndex(); 448 int index = key - low; 449 450 UnitBox branchBox = null; 451 if(index < 0 || index > high) 452 branchBox = table.getDefaultTargetBox(); 453 else 454 branchBox = table.getTargetBox(index); 455 456 GotoStmt gotoStmt = Jimple.v().newGotoStmt(branchBox); 457 stmtToReplacement.put(table, gotoStmt); 458 459 List unitBoxes = table.getUnitBoxes(); 460 int setIndex = unitBoxes.indexOf(branchBox); 461 oneBranch = (FlowSet) branchOuts.get(setIndex); 462 } 463 } 465 LOOKUPSWITCHSTMT: 466 { 467 if(s instanceof LookupSwitchStmt){ 468 LookupSwitchStmt lookup = (LookupSwitchStmt) s; 469 Value keyV = lookup.getKey(); 470 Constant keyC = 471 SEvaluator.getFuzzyConstantValueOf(keyV, localToConstant); 472 473 if(keyC instanceof BottomConstant){ 475 stmtToReplacement.remove(lookup); 476 break LOOKUPSWITCHSTMT; 477 } 478 479 if(keyC instanceof TopConstant) 481 return; 482 483 if(!(keyC instanceof IntConstant)) 485 break LOOKUPSWITCHSTMT; 486 487 488 489 conservative = false; 490 491 int index = lookup.getLookupValues().indexOf(keyC); 492 493 UnitBox branchBox = null; 494 if(index == -1) 495 branchBox = lookup.getDefaultTargetBox(); 496 else 497 branchBox = lookup.getTargetBox(index); 498 499 GotoStmt gotoStmt = Jimple.v().newGotoStmt(branchBox); 500 stmtToReplacement.put(lookup, gotoStmt); 501 502 List unitBoxes = lookup.getUnitBoxes(); 503 int setIndex = unitBoxes.indexOf(branchBox); 504 oneBranch = (FlowSet) branchOuts.get(setIndex); 505 } 506 } 508 if(conservative){ 510 fall = s.fallsThrough(); 511 branch = s.branches(); 512 } 513 514 if(fall){ 515 Iterator fallOutIt = fallOut.iterator(); 516 while(fallOutIt.hasNext()){ 517 FlowSet fallSet = (FlowSet) fallOutIt.next(); 518 fallSet.union(fin); 519 } 520 } 521 522 if(branch){ 523 Iterator branchOutsIt = branchOuts.iterator(); 524 while(branchOutsIt.hasNext()){ 525 FlowSet branchSet = (FlowSet) branchOutsIt.next(); 526 branchSet.union(fin); 527 } 528 } 529 530 if(oneBranch != null){ 531 oneBranch.union(fin); 532 } 533 } 534 535 539 protected Pair processDefinitionStmt(Unit u) 540 { 541 if(!(u instanceof DefinitionStmt)) 542 return null; 543 544 DefinitionStmt dStmt = (DefinitionStmt) u; 545 546 Local local; 547 548 { 549 Value value = dStmt.getLeftOp(); 550 if(!(value instanceof Local)) 551 return null; 552 local = (Local) value; 553 } 554 555 556 557 Value rightOp = dStmt.getRightOp(); 558 Constant constant = 559 SEvaluator.getFuzzyConstantValueOf(rightOp, localToConstant); 560 561 if(!merge(local, constant)) 562 return null; 563 564 return new Pair(u, localToConstant.get(local)); 565 } 566 567 573 protected boolean merge(Local local, Constant constant) 574 { 575 Constant current = (Constant) localToConstant.get(local); 576 577 if(current instanceof BottomConstant) 578 return false; 579 580 if(current instanceof TopConstant){ 581 localToConstant.put(local, constant); 582 return true; 583 } 584 585 if(current.equals(constant)) 586 return false; 587 588 localToConstant.put(local, BottomConstant.v()); 590 return true; 591 } 592 } 593 | Popular Tags |