1 19 20 package jode.flow; 21 import jode.AssertError; 22 import jode.GlobalOptions; 23 import jode.decompiler.TabbedPrintWriter; 24 import jode.decompiler.LocalInfo; 25 import jode.decompiler.Declarable; 26 import jode.decompiler.ClassAnalyzer; 27 import jode.util.SimpleSet; 28 29 import java.util.Collections ; 30 import java.util.Iterator ; 31 import java.util.Set ; 32 33 59 60 public abstract class StructuredBlock { 61 71 72 76 Set used; 77 78 82 Set declare; 83 Set done; 84 85 88 StructuredBlock outer; 89 90 98 100 FlowBlock flowBlock; 101 102 107 Jump jump; 108 109 113 public StructuredBlock getNextBlock() { 114 if (jump != null) 115 return null; 116 if (outer != null) 117 return outer.getNextBlock(this); 118 return null; 119 } 120 121 public void setJump(Jump jump) { 122 this.jump = jump; 123 jump.prev = this; 124 } 125 126 132 public FlowBlock getNextFlowBlock() { 133 if (jump != null) 134 return jump.destination; 135 if (outer != null) 136 return outer.getNextFlowBlock(this); 137 return null; 138 } 139 140 146 public StructuredBlock getNextBlock(StructuredBlock subBlock) { 147 return getNextBlock(); 148 } 149 150 public FlowBlock getNextFlowBlock(StructuredBlock subBlock) { 151 return getNextFlowBlock(); 152 } 153 154 157 public boolean isEmpty() { 158 return false; 159 } 160 161 167 public boolean isSingleExit(StructuredBlock subBlock) { 168 return false; 169 } 170 171 177 public boolean replaceSubBlock(StructuredBlock oldBlock, 178 StructuredBlock newBlock) { 179 return false; 180 } 181 182 185 public StructuredBlock[] getSubBlocks() { 186 return new StructuredBlock[0]; 187 } 188 189 194 public boolean contains(StructuredBlock child) { 195 while (child != this && child != null) 196 child = child.outer; 197 return (child == this); 198 } 199 200 203 public final void removeJump() { 204 if (jump != null) { 205 jump.prev = null; 206 jump = null; 207 } 208 } 209 210 219 void moveDefinitions(StructuredBlock from, StructuredBlock sub) { 220 } 221 222 234 public void replace(StructuredBlock sb) { 235 outer = sb.outer; 236 setFlowBlock(sb.flowBlock); 237 if (outer != null) { 238 outer.replaceSubBlock(sb, this); 239 } else { 240 flowBlock.block = this; 241 } 242 } 243 244 248 public void swapJump(StructuredBlock block) { 249 Jump tmp = block.jump; 250 block.jump = jump; 251 jump = tmp; 252 253 jump.prev = this; 254 block.jump.prev = block; 255 } 256 257 263 public void moveJump(Jump jump) { 264 if (this.jump != null) 265 throw new AssertError("overriding with moveJump()"); 266 this.jump = jump; 267 if (jump != null) { 268 jump.prev.jump = null; 269 jump.prev = this; 270 } 271 } 272 273 278 public void copyJump(Jump jump) { 279 if (this.jump != null) 280 throw new AssertError("overriding with moveJump()"); 281 if (jump != null) { 282 this.jump = new Jump(jump); 283 this.jump.prev = this; 284 } 285 } 286 287 291 public StructuredBlock appendBlock(StructuredBlock block) { 292 if (block instanceof EmptyBlock) { 293 moveJump(block.jump); 294 return this; 295 } else { 296 SequentialBlock sequBlock = new SequentialBlock(); 297 sequBlock.replace(this); 298 sequBlock.setFirst(this); 299 sequBlock.setSecond(block); 300 return sequBlock; 301 } 302 } 303 304 308 public StructuredBlock prependBlock(StructuredBlock block) { 309 SequentialBlock sequBlock = new SequentialBlock(); 310 sequBlock.replace(this); 311 sequBlock.setFirst(block); 312 sequBlock.setSecond(this); 313 return sequBlock; 314 } 315 316 319 public final void removeBlock() { 320 321 if (outer instanceof SequentialBlock) { 322 if (outer.getSubBlocks()[1] == this) { 323 if (jump != null) 324 outer.getSubBlocks()[0].moveJump(jump); 325 outer.getSubBlocks()[0].replace(outer); 326 } else 327 outer.getSubBlocks()[1].replace(outer); 328 return; 329 } 330 331 EmptyBlock eb = new EmptyBlock(); 332 eb.moveJump(jump); 333 eb.replace(this); 334 } 335 336 343 public boolean flowMayBeChanged() { 344 return jump != null || jumpMayBeChanged(); 345 } 346 347 public boolean jumpMayBeChanged() { 348 return false; 349 } 350 351 public Set getDeclarables() { 352 return Collections.EMPTY_SET; 353 } 354 355 363 public Set propagateUsage() { 364 used = new SimpleSet(); 365 used.addAll(getDeclarables()); 366 StructuredBlock[] subs = getSubBlocks(); 367 Set allUse = new SimpleSet(); 368 allUse.addAll(used); 369 for (int i=0; i<subs.length; i++) { 370 Set childUse = subs[i].propagateUsage(); 371 374 Set intersection = new SimpleSet(); 375 intersection.addAll(childUse); 376 intersection.retainAll(allUse); 377 used.addAll(intersection); 378 allUse.addAll(childUse); 379 } 380 return allUse; 381 } 382 383 394 public VariableStack mapStackToLocal(VariableStack stack) { 395 StructuredBlock[] subBlocks = getSubBlocks(); 396 VariableStack after; 397 if (subBlocks.length == 0) 398 after = stack; 399 else { 400 after = null; 401 for (int i=0; i< subBlocks.length; i++) { 402 after = VariableStack.merge 403 (after, subBlocks[i].mapStackToLocal(stack)); 404 } 405 } 406 if (jump != null) { 407 408 jump.stackMap = after; 409 return null; 410 } 411 return after; 412 } 413 414 418 public void removePush() { 419 StructuredBlock[] subBlocks = getSubBlocks(); 420 for (int i=0; i< subBlocks.length; i++) 421 subBlocks[i].removePush(); 422 } 423 424 433 public void removeOnetimeLocals() { 434 StructuredBlock[] subBlocks = getSubBlocks(); 435 for (int i=0; i< subBlocks.length; i++) 436 subBlocks[i].removeOnetimeLocals(); 437 } 438 439 449 public void makeDeclaration(Set done) { 450 this.done = new SimpleSet(); 451 this.done.addAll(done); 452 453 declare = new SimpleSet(); 454 Iterator iter = used.iterator(); 455 next_used: 456 while (iter.hasNext()) { 457 Declarable declarable = (Declarable) iter.next(); 458 459 if (done.contains(declarable)) 461 continue next_used; 462 463 if (declarable instanceof LocalInfo) { 464 LocalInfo local = (LocalInfo) declarable; 465 466 470 String localName = local.guessName(); 471 472 Iterator doneIter = done.iterator(); 475 while (doneIter.hasNext()) { 476 Declarable previous = (Declarable) doneIter.next(); 477 if (!(previous instanceof LocalInfo)) 478 continue; 479 LocalInfo prevLocal = (LocalInfo) previous; 480 488 if (prevLocal.getMethodAnalyzer() 489 == local.getMethodAnalyzer() 490 && prevLocal.getSlot() == local.getSlot() 491 && prevLocal.getType().isOfType(local.getType()) 492 && (prevLocal.isNameGenerated() 493 || local.isNameGenerated() 494 || localName.equals(prevLocal.getName())) 495 && !prevLocal.isFinal() 496 && !local.isFinal() 497 && prevLocal.getExpression() == null 498 && local.getExpression() == null) { 499 local.combineWith(prevLocal); 500 continue next_used; 501 } 502 } 503 } 504 505 if (declarable.getName() != null) { 506 Iterator doneIter = done.iterator(); 507 while (doneIter.hasNext()) { 508 Declarable previous = (Declarable) doneIter.next(); 509 if (declarable.getName().equals(previous.getName())) { 510 511 declarable.makeNameUnique(); 512 break; 513 } 514 } 515 } 516 done.add(declarable); 517 declare.add(declarable); 518 if (declarable instanceof ClassAnalyzer) 519 ((ClassAnalyzer) declarable).makeDeclaration(done); 520 } 521 StructuredBlock[] subs = getSubBlocks(); 522 for (int i=0; i<subs.length; i++) 523 subs[i].makeDeclaration(done); 524 526 done.removeAll(declare); 527 } 528 529 public void checkConsistent() { 530 StructuredBlock[] subs = getSubBlocks(); 531 for (int i=0; i<subs.length; i++) { 532 if (subs[i].outer != this || 533 subs[i].flowBlock != flowBlock) { 534 throw new AssertError("Inconsistency"); 535 } 536 subs[i].checkConsistent(); 537 } 538 if (jump != null && jump.destination != null) { 539 Jump jumps = (Jump) flowBlock.getJumps(jump.destination); 540 for (; jumps != jump; jumps = jumps.next) { 541 if (jumps == null) 542 throw new AssertError("Inconsistency"); 543 } 544 } 545 } 546 547 551 public void setFlowBlock(FlowBlock flowBlock) { 552 if (this.flowBlock != flowBlock) { 553 this.flowBlock = flowBlock; 554 StructuredBlock[] subs = getSubBlocks(); 555 for (int i=0; i<subs.length; i++) { 556 if (subs[i] != null) 557 subs[i].setFlowBlock(flowBlock); 558 } 559 } 560 } 561 562 566 public boolean needsBraces() { 567 return true; 568 } 569 570 574 public void fillInGenSet(Set in, Set gen) { 575 576 } 577 578 583 public void fillSuccessors() { 584 if (jump != null) 585 flowBlock.addSuccessor(jump); 586 StructuredBlock[] subs = getSubBlocks(); 587 for (int i=0; i<subs.length; i++) { 588 subs[i].fillSuccessors(); 589 } 590 } 591 592 598 public void dumpSource(TabbedPrintWriter writer) 599 throws java.io.IOException 600 { 601 if ((GlobalOptions.debuggingFlags 602 & GlobalOptions.DEBUG_LOCALS) != 0) { 603 if (declare != null) 604 writer.println("declaring: "+declare); 605 if (done != null) 606 writer.println("done: "+done); 607 writer.println("using: "+used); 608 } 609 610 if (declare != null) { 611 Iterator iter = declare.iterator(); 612 while (iter.hasNext()) { 613 Declarable decl = (Declarable) iter.next(); 614 decl.dumpDeclaration(writer); 615 writer.println(";"); 616 } 617 } 618 dumpInstruction(writer); 619 620 if (jump != null) 621 jump.dumpSource(writer); 622 } 623 624 628 public abstract void dumpInstruction(TabbedPrintWriter writer) 629 throws java.io.IOException ; 630 631 public String toString() { 632 try { 633 java.io.StringWriter strw = new java.io.StringWriter (); 634 jode.decompiler.TabbedPrintWriter writer = 635 new jode.decompiler.TabbedPrintWriter(strw); 636 writer.println(super.toString()); 637 writer.tab(); 638 dumpSource(writer); 639 return strw.toString(); 640 } catch (java.io.IOException ex) { 641 return super.toString(); 642 } 643 } 644 645 public void simplify() { 646 StructuredBlock[] subs = getSubBlocks(); 647 for (int i=0; i < subs.length; i++) 648 subs[i].simplify(); 649 } 650 651 655 public boolean doTransformations() { 656 return false; 657 } 658 } 659 660 | Popular Tags |