1 19 20 package jode.flow; 21 import jode.decompiler.TabbedPrintWriter; 22 import jode.type.Type; 23 import jode.decompiler.LocalInfo; 24 import jode.expr.Expression; 25 import jode.expr.ConstOperator; 26 import jode.expr.StoreInstruction; 27 import jode.expr.LocalStoreOperator; 28 import jode.expr.CombineableOperator; 29 import jode.util.SimpleSet; 30 31 import java.util.Set ; 32 33 36 public class LoopBlock extends StructuredBlock implements BreakableBlock { 37 38 public static final int WHILE = 0; 39 public static final int DOWHILE = 1; 40 public static final int FOR = 2; 41 public static final int POSSFOR = 3; 42 43 public static final Expression TRUE = 44 new ConstOperator(Boolean.TRUE); 45 public static final Expression FALSE = 46 new ConstOperator(Boolean.FALSE); 47 48 51 Expression cond; 52 55 VariableStack condStack; 56 59 InstructionBlock initBlock; 60 63 InstructionBlock incrBlock; 64 65 68 Expression initInstr; 69 72 Expression incrInstr; 73 74 77 boolean isDeclaration; 78 79 82 int type; 83 84 87 StructuredBlock bodyBlock; 88 89 92 VariableStack breakedStack; 93 94 97 VariableStack continueStack; 98 99 120 121 128 public StructuredBlock getNextBlock(StructuredBlock subBlock) { 129 return this; 130 } 131 132 public FlowBlock getNextFlowBlock(StructuredBlock subBlock) { 133 return null; 134 } 135 136 public LoopBlock(int type, Expression cond) { 137 this.type = type; 138 this.cond = cond; 139 this.mayChangeJump = (cond == TRUE); 140 } 141 142 public void setBody(StructuredBlock body) { 143 bodyBlock = body; 144 bodyBlock.outer = this; 145 body.setFlowBlock(flowBlock); 146 } 147 148 public void setInit(InstructionBlock initBlock) { 149 if (type == POSSFOR) { 150 this.initBlock = initBlock; 151 } else if (type == FOR) { 152 this.initInstr = initBlock.getInstruction(); 153 initBlock.removeBlock(); 154 } 155 } 156 157 public boolean conditionMatches(CombineableOperator combinable) { 158 return (type == POSSFOR || cond.containsMatchingLoad(combinable)); 159 } 160 161 162 public Expression getCondition() { 163 return cond; 164 } 165 166 public void setCondition(Expression cond) { 167 this.cond = cond; 168 if (type == POSSFOR) { 169 171 if (cond.containsMatchingLoad((CombineableOperator) 172 incrBlock.getInstruction())) { 173 type = FOR; 174 incrInstr = incrBlock.getInstruction(); 175 incrBlock.removeBlock(); 176 if (initBlock != null) { 177 if (cond.containsMatchingLoad 178 ((CombineableOperator) initBlock.getInstruction())) { 179 initInstr = initBlock.getInstruction(); 180 initBlock.removeBlock(); 181 } 182 } 183 } else { 184 187 type = WHILE; 188 } 189 initBlock = incrBlock = null; 190 } 191 mayChangeJump = false; 192 } 193 194 public int getType() { 195 return type; 196 } 197 198 public void setType(int type) { 199 this.type = type; 200 } 201 202 208 public boolean replaceSubBlock(StructuredBlock oldBlock, 209 StructuredBlock newBlock) { 210 if (bodyBlock == oldBlock) 211 bodyBlock = newBlock; 212 else 213 return false; 214 return true; 215 } 216 217 220 public StructuredBlock[] getSubBlocks() { 221 return new StructuredBlock[] { bodyBlock }; 222 } 223 224 228 public void removeLocallyDeclareable(Set set) { 229 if (type == FOR && initInstr instanceof StoreInstruction) { 230 StoreInstruction storeOp = (StoreInstruction) initInstr; 231 if (storeOp.getLValue() instanceof LocalStoreOperator) { 232 LocalInfo local = 233 ((LocalStoreOperator) storeOp.getLValue()).getLocalInfo(); 234 set.remove(local); 235 } 236 } 237 } 238 239 public Set getDeclarables() { 240 Set used = new SimpleSet(); 241 if (type == FOR) { 242 incrInstr.fillDeclarables(used); 243 if (initInstr != null) 244 initInstr.fillDeclarables(used); 245 } 246 cond.fillDeclarables(used); 247 return used; 248 } 249 250 255 public void checkDeclaration(Set declareSet) { 256 if (initInstr instanceof StoreInstruction 257 && (((StoreInstruction)initInstr).getLValue() 258 instanceof LocalStoreOperator)) { 259 StoreInstruction storeOp = (StoreInstruction) initInstr; 260 LocalInfo local = 261 ((LocalStoreOperator) storeOp.getLValue()).getLocalInfo(); 262 if (declareSet.contains(local)) { 263 267 isDeclaration = true; 268 declareSet.remove(local); 269 } 270 } 271 } 272 273 279 public void makeDeclaration(Set done) { 280 if (type == FOR) { 281 if (initInstr != null) 282 initInstr.makeDeclaration(done); 283 incrInstr.makeDeclaration(done); 284 } 285 cond.makeDeclaration(done); 286 super.makeDeclaration(done); 287 if (type == FOR && initInstr != null) 288 checkDeclaration(declare); 289 } 290 291 public void dumpSource(TabbedPrintWriter writer) 292 throws java.io.IOException 293 { 294 super.dumpSource(writer); 295 } 296 297 public void dumpInstruction(TabbedPrintWriter writer) 298 throws java.io.IOException 299 { 300 if (label != null) { 301 writer.untab(); 302 writer.println(label+":"); 303 writer.tab(); 304 } 305 boolean needBrace = bodyBlock.needsBraces(); 306 switch (type) { 307 case POSSFOR: 308 309 case WHILE: 310 if (cond == TRUE) 311 312 writer.print("for (;;)"); 313 else { 314 writer.print("while ("); 315 cond.dumpExpression(writer.EXPL_PAREN, writer); 316 writer.print(")"); 317 } 318 break; 319 case DOWHILE: 320 writer.print("do"); 321 break; 322 case FOR: 323 writer.print("for ("); 324 writer.startOp(writer.EXPL_PAREN, 0); 325 if (initInstr != null) { 326 if (isDeclaration) { 327 StoreInstruction store = (StoreInstruction) initInstr; 328 LocalInfo local = ((LocalStoreOperator) store 329 .getLValue()).getLocalInfo(); 330 writer.startOp(writer.NO_PAREN, 1); 331 local.dumpDeclaration(writer); 332 writer.breakOp(); 333 writer.print(" = "); 334 store.getSubExpressions()[1] 335 .makeInitializer(local.getType()); 336 store.getSubExpressions()[1].dumpExpression(writer, 100); 337 writer.endOp(); 338 } else 339 initInstr.dumpExpression(writer.NO_PAREN, writer); 340 } else { 341 writer.print("/**/"); 342 } 343 writer.print("; "); 344 writer.breakOp(); 345 cond.dumpExpression(writer.IMPL_PAREN, writer); 346 writer.print("; "); 347 writer.breakOp(); 348 incrInstr.dumpExpression(writer.NO_PAREN, writer); 349 writer.endOp(); 350 writer.print(")"); 351 break; 352 } 353 if (needBrace) 354 writer.openBrace(); 355 else 356 writer.println(); 357 writer.tab(); 358 bodyBlock.dumpSource(writer); 359 writer.untab(); 360 if (type == DOWHILE) { 361 if (needBrace) 362 writer.closeBraceContinue(); 363 writer.print("while ("); 364 cond.dumpExpression(writer.EXPL_PAREN, writer); 365 writer.println(");"); 366 } else if (needBrace) 367 writer.closeBrace(); 368 } 369 370 boolean mayChangeJump = true; 371 372 375 static int serialno = 0; 376 377 380 String label = null; 381 382 386 public String getLabel() { 387 if (label == null) 388 label = "while_"+(serialno++)+"_"; 389 return label; 390 } 391 392 395 public void setBreaked() { 396 mayChangeJump = false; 397 } 398 399 407 public VariableStack mapStackToLocal(VariableStack stack) { 408 if (type == DOWHILE) { 409 VariableStack afterBody = bodyBlock.mapStackToLocal(stack); 410 if (afterBody != null) 411 mergeContinueStack(afterBody); 412 413 if (continueStack != null) { 414 VariableStack newStack; 415 int params = cond.getFreeOperandCount(); 416 if (params > 0) { 417 condStack = continueStack.peek(params); 418 newStack = continueStack.pop(params); 419 } else 420 newStack = continueStack; 421 422 if (cond != TRUE) 423 mergeBreakedStack(newStack); 424 if (cond != FALSE) 425 stack.merge(newStack); 426 } 427 } else { 428 continueStack = stack; 429 VariableStack newStack; 430 int params = cond.getFreeOperandCount(); 431 if (params > 0) { 432 condStack = stack.peek(params); 433 newStack = stack.pop(params); 434 } else 435 newStack = stack; 436 if (cond != TRUE) 437 breakedStack = newStack; 438 VariableStack afterBody = bodyBlock.mapStackToLocal(newStack); 439 if (afterBody != null) 440 mergeContinueStack(afterBody); 441 } 442 return breakedStack; 443 } 444 445 450 public void mergeContinueStack(VariableStack stack) { 451 if (continueStack == null) 452 continueStack = stack; 453 else 454 continueStack.merge(stack); 455 } 456 457 462 public void mergeBreakedStack(VariableStack stack) { 463 if (breakedStack != null) 464 breakedStack.merge(stack); 465 else 466 breakedStack = stack; 467 } 468 469 public void removePush() { 470 if (condStack != null) 471 cond = condStack.mergeIntoExpression(cond); 472 bodyBlock.removePush(); 473 } 474 475 484 public void removeOnetimeLocals() { 485 cond = cond.removeOnetimeLocals(); 486 if (type == FOR) { 487 if (initInstr != null) 488 initInstr.removeOnetimeLocals(); 489 incrInstr.removeOnetimeLocals(); 490 } 491 super.removeOnetimeLocals(); 492 } 493 494 499 public void replaceBreakContinue(BreakableBlock block) { 500 java.util.Stack todo = new java.util.Stack (); 501 todo.push(block); 502 while (!todo.isEmpty()) { 503 StructuredBlock[] subs = 504 ((StructuredBlock)todo.pop()).getSubBlocks(); 505 for (int i=0; i<subs.length; i++) { 506 if (subs[i] instanceof BreakBlock) { 507 BreakBlock breakblk = (BreakBlock) subs[i]; 508 if (breakblk.breaksBlock == block) { 509 new ContinueBlock(this, breakblk.label != null) 510 .replace(breakblk); 511 } 512 } 513 todo.push(subs[i]); 514 } 515 } 516 } 517 518 523 public boolean jumpMayBeChanged() { 524 return mayChangeJump; 525 } 526 527 public void simplify() { 528 cond = cond.simplify(); 529 if (type == FOR) { 530 incrInstr = incrInstr.simplify(); 531 if (initInstr != null) 532 initInstr = initInstr.simplify(); 533 } 534 super.simplify(); 535 } 536 537 public boolean doTransformations() { 538 return ((initBlock == null && type == POSSFOR) 539 || (initInstr == null && type == FOR)) 540 && CreateForInitializer.transform(this, flowBlock.lastModified); 541 } 542 } 543 544 | Popular Tags |