001/* 002 * This file is part of the Jikes RVM project (http://jikesrvm.org). 003 * 004 * This file is licensed to You under the Eclipse Public License (EPL); 005 * You may not use this file except in compliance with the License. You 006 * may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/eclipse-1.0.php 009 * 010 * See the COPYRIGHT.txt file distributed with this work for information 011 * regarding copyright ownership. 012 */ 013package org.jikesrvm.compilers.opt.ir; 014 015import static org.jikesrvm.compilers.opt.ir.Operators.ATHROW_opcode; 016import static org.jikesrvm.compilers.opt.ir.Operators.BBEND_opcode; 017import static org.jikesrvm.compilers.opt.ir.Operators.DOUBLE_IFCMP_opcode; 018import static org.jikesrvm.compilers.opt.ir.Operators.FLOAT_IFCMP_opcode; 019import static org.jikesrvm.compilers.opt.ir.Operators.GOTO_opcode; 020import static org.jikesrvm.compilers.opt.ir.Operators.INT_IFCMP2_opcode; 021import static org.jikesrvm.compilers.opt.ir.Operators.INT_IFCMP_opcode; 022import static org.jikesrvm.compilers.opt.ir.Operators.IR_PROLOGUE; 023import static org.jikesrvm.compilers.opt.ir.Operators.LABEL; 024import static org.jikesrvm.compilers.opt.ir.Operators.LABEL_opcode; 025import static org.jikesrvm.compilers.opt.ir.Operators.LONG_IFCMP_opcode; 026import static org.jikesrvm.compilers.opt.ir.Operators.LOOKUPSWITCH_opcode; 027import static org.jikesrvm.compilers.opt.ir.Operators.LOWTABLESWITCH; 028import static org.jikesrvm.compilers.opt.ir.Operators.PHI_opcode; 029import static org.jikesrvm.compilers.opt.ir.Operators.REF_IFCMP_opcode; 030import static org.jikesrvm.compilers.opt.ir.Operators.RETURN_opcode; 031import static org.jikesrvm.compilers.opt.ir.Operators.TABLESWITCH_opcode; 032import static org.jikesrvm.runtime.UnboxedSizeConstants.LOG_BYTES_IN_ADDRESS; 033 034import java.util.ArrayList; 035import java.util.Enumeration; 036import java.util.HashMap; 037import java.util.HashSet; 038import java.util.Map; 039import java.util.Stack; 040 041import org.jikesrvm.VM; 042import org.jikesrvm.classloader.NormalMethod; 043import org.jikesrvm.classloader.TypeReference; 044import org.jikesrvm.compilers.common.CompiledMethod; 045import org.jikesrvm.compilers.common.CompiledMethods; 046import org.jikesrvm.compilers.opt.DefUse; 047import org.jikesrvm.compilers.opt.OptOptions; 048import org.jikesrvm.compilers.opt.OptimizingCompilerException; 049import org.jikesrvm.compilers.opt.bc2ir.GenerationContext; 050import org.jikesrvm.compilers.opt.controlflow.Dominators; 051import org.jikesrvm.compilers.opt.controlflow.LTDominators; 052import org.jikesrvm.compilers.opt.driver.CompilationPlan; 053import org.jikesrvm.compilers.opt.driver.CompilerPhase; 054import org.jikesrvm.compilers.opt.driver.InstrumentationPlan; 055import org.jikesrvm.compilers.opt.inlining.InlineOracle; 056import org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand; 057import org.jikesrvm.compilers.opt.ir.operand.ConditionOperand; 058import org.jikesrvm.compilers.opt.ir.operand.HeapOperand; 059import org.jikesrvm.compilers.opt.ir.operand.InlinedOsrTypeInfoOperand; 060import org.jikesrvm.compilers.opt.ir.operand.Operand; 061import org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand; 062import org.jikesrvm.compilers.opt.ir.operand.ia32.BURSManagedFPROperand; 063import org.jikesrvm.compilers.opt.ir.operand.ia32.IA32ConditionOperand; 064import org.jikesrvm.compilers.opt.ir.operand.ppc.PowerPCConditionOperand; 065import org.jikesrvm.compilers.opt.ir.operand.ppc.PowerPCTrapOperand; 066import org.jikesrvm.compilers.opt.liveness.LiveInterval; 067import org.jikesrvm.compilers.opt.regalloc.GenericStackManager; 068import org.jikesrvm.compilers.opt.runtimesupport.OptCompiledMethod; 069import org.jikesrvm.compilers.opt.ssa.HeapVariable; 070import org.jikesrvm.compilers.opt.ssa.SSAOptions; 071import org.jikesrvm.util.BitVector; 072import org.vmmagic.pragma.NoInline; 073 074/** 075 * An <code>IR</code> object (IR is short for Intermediate Representation) 076 * contains all the per-compilation information associated with 077 * a method that is being compiled. 078 * <p> 079 * <code>IR</code> objects are intended to be transitory. 080 * They are created to compile a particular method under a 081 * given {@link CompilationPlan compilation plan} 082 * and are discarded once the compilation plan has been completed. 083 * <p> 084 * The primary component of the IR is the 085 * {@link ControlFlowGraph <em>FCFG</em>} (factored control flow graph) 086 * The FCFG contains 087 * {@link Instruction intermediate language instructions} 088 * grouped into {@link BasicBlock factored basic blocks}. 089 * In addition to the FCFG, an <code>IR</code> object also 090 * contains a variety of other supporting and derived data structures. 091 * 092 * @see ControlFlowGraph 093 * @see BasicBlock 094 * @see Instruction 095 * @see Operator 096 * @see Operand 097 */ 098public final class IR { 099 100 /** 101 * Control for (dynamic) IR invariant checking. 102 * By default, SANITY_CHECK == {@link VM#VerifyAssertions}. 103 * When SANITY_CHECK is <code>true</code>, critical invariants 104 * are checked by complex routines that depend on them, 105 * and {@link #verify(String) verify} is invoked several times 106 * during compilation. 107 */ 108 public static final boolean SANITY_CHECK = VM.VerifyAssertions; 109 110 /** 111 * Control for (dynamic) IR invariant checking. 112 * By default PARANOID is <code>false</code>. 113 * PARANOID must not be true unless {@link VM#VerifyAssertions} 114 * is also <code>true</code>. 115 * When PARANOID is <code>true</code> many IR utility functions 116 * check the invariants on which they depend, and 117 * {@link #verify(String,boolean)} is invoked as each 118 * compilation phase is 119 * {@link CompilerPhase#performPhase(IR) performed}. 120 */ 121 public static final boolean PARANOID = false && SANITY_CHECK; 122 123 /** Part of an enumerated type used to encode IR Level */ 124 public static final byte UNFORMED = 0; 125 /** Part of an enumerated type used to encode IR Level */ 126 public static final byte HIR = 1; 127 /** Part of an enumerated type used to encode IR Level */ 128 public static final byte LIR = 2; 129 /** Part of an enumerated type used to encode IR Level */ 130 public static final byte MIR = 3; 131 132 /** 133 * The {@link NormalMethod} object corresponding to the 134 * method being compiled. Other methods may have been inlined into 135 * the IR during compilation, so method really only represents the 136 * primary or outermost method being compiled. 137 */ 138 public final NormalMethod method; 139 140 /** 141 * The specialized parameters to be used in place of those defined 142 * in the NormalMethod. 143 */ 144 public final TypeReference[] params; 145 146 /** 147 * @return The {@link NormalMethod} object corresponding to the 148 * method being compiled. Other methods may have been inlined into 149 * the IR during compilation, so method really only represents the 150 * primary or outermost method being compiled. 151 */ 152 public NormalMethod getMethod() { 153 return method; 154 } 155 156 /** 157 * The compiled method created to hold the result of this compilation. 158 */ 159 public final OptCompiledMethod compiledMethod; 160 161 /** 162 * The compiler {@link OptOptions options} that apply 163 * to the current compilation. 164 */ 165 public final OptOptions options; 166 167 /** 168 * {@link SSAOptions Options} that define the SSA properties 169 * desired the next time we enter SSA form. 170 */ 171 public SSAOptions desiredSSAOptions; 172 173 /** 174 * {@link SSAOptions Options} that define the SSA properties 175 * currently carried by the IR. Compiler phases that are invoked 176 * on SSA form should update this object to reflect transformations 177 * on SSA form. 178 */ 179 public SSAOptions actualSSAOptions; 180 181 public boolean inSSAForm() { 182 return (actualSSAOptions != null) && actualSSAOptions.getScalarValid(); 183 } 184 185 public boolean inSSAFormAwaitingReEntry() { 186 return (actualSSAOptions != null) && !actualSSAOptions.getScalarValid(); 187 } 188 189 /** 190 * The root {@link GenerationContext generation context} 191 * for the current compilation. 192 */ 193 public GenerationContext gc; 194 195 /** 196 * The {@link InlineOracle inlining oracle} to be used for the 197 * current compilation. 198 * TODO: It would make more sense to have the inlining oracle be 199 * a component of the generation context, but as things currently 200 * stand the IR is created before the generation context. We might be 201 * able to restructure things such that the generation context is 202 * created in the IR constructor and then eliminate this field, 203 * replacing all uses with gc.inlinePlan instead. 204 */ 205 public final InlineOracle inlinePlan; 206 207 /** 208 * Information specifying what instrumentation should be performed 209 * during compilation of this method. 210 */ 211 public final InstrumentationPlan instrumentationPlan; 212 213 /** 214 * The {@link ControlFlowGraph FCFG} (Factored Control Flow Graph) 215 */ 216 public ControlFlowGraph cfg; 217 218 /** 219 * The {@link GenericRegisterPool register pool} 220 */ 221 public GenericRegisterPool regpool; 222 223 /** 224 * The {@link GenericStackManager stack manager}. 225 */ 226 public final GenericStackManager stackManager; 227 228 /** 229 * The IR is tagged to identify its level (stage). 230 * As compilation continues, the level monotonically 231 * increases from {@link #UNFORMED} to {@link #HIR} 232 * to {@link #LIR} to {@link #MIR}. 233 */ 234 public byte IRStage = UNFORMED; 235 236 /** 237 * Was liveness for handlers computed? 238 */ 239 private boolean handlerLivenessComputed = false; 240 241 /** 242 * Information about liveness, {@code null} if not yet computed. 243 */ 244 private LiveInterval livenessInformation; 245 246 /** 247 * Information about dominators as used for global code placement 248 * during SSA. This dominator information is not to be confused 249 * with the dominator information that is used to leave SSA form. 250 * The field will be {@code null} if the dominator information 251 * was not computed yet. 252 */ 253 private Dominators dominators; 254 255 /** 256 * Information about dominators as used for leaving SSA form. 257 * This dominator information is not to be confused 258 * with the dominator information that is used to do global code 259 * placement in the SSA form. 260 * The field will be {@code null} if the dominator information 261 * was not computed yet. 262 */ 263 private LTDominators ltDominators; 264 265 /** 266 * Pointer to the HIRInfo for this method. 267 * Valid only if {@link #IRStage}>=HIR 268 */ 269 public HIRInfo HIRInfo; 270 271 /** 272 * Pointer to the LIRInfo for this method. 273 * Valid only if {@link #IRStage}>=LIR. 274 */ 275 public LIRInfo LIRInfo; 276 277 /** 278 * Pointer to the MIRInfo for this method. 279 * Valid only if {@link #IRStage}>=MIR. 280 */ 281 public MIRInfo MIRInfo; 282 283 /** 284 * Backing store for {@link #getBasicBlock(int)}. 285 */ 286 private BasicBlock[] basicBlockMap; 287 288 /** 289 * Does this IR include a syscall? 290 * Initialized during lir to mir conversion; 291 */ 292 private boolean hasSysCall = false; 293 294 public boolean hasSysCall() { 295 return hasSysCall; 296 } 297 298 public void setHasSysCall(boolean b) { 299 hasSysCall = b; 300 } 301 302 { 303 if (VM.BuildForIA32) { 304 stackManager = new org.jikesrvm.compilers.opt.regalloc.ia32.StackManager(); 305 } else { 306 if (VM.VerifyAssertions) VM._assert(VM.BuildForPowerPC); 307 stackManager = new org.jikesrvm.compilers.opt.regalloc.ppc.StackManager(); 308 } 309 } 310 311 /** 312 * @param m The method to compile 313 * @param ip The inlining oracle to use for the compilation 314 * @param opts The options to use for the compilation 315 */ 316 public IR(NormalMethod m, InlineOracle ip, OptOptions opts) { 317 method = m; 318 params = null; 319 options = opts; 320 inlinePlan = ip; 321 instrumentationPlan = null; 322 compiledMethod = (OptCompiledMethod) CompiledMethods.createCompiledMethod(method, CompiledMethod.OPT); 323 } 324 325 /** 326 * @param m The method to compile 327 * @param cp The compilation plan to execute 328 */ 329 public IR(NormalMethod m, CompilationPlan cp) { 330 method = m; 331 params = cp.params; 332 options = cp.options; 333 inlinePlan = cp.inlinePlan; 334 instrumentationPlan = cp.instrumentationPlan; 335 compiledMethod = (OptCompiledMethod) CompiledMethods.createCompiledMethod(method, CompiledMethod.OPT); 336 } 337 338 /** 339 * Print the instructions in this IR to System.out. 340 */ 341 public void printInstructions() { 342 for (Enumeration<Instruction> e = forwardInstrEnumerator(); e.hasMoreElements();) { 343 Instruction i = e.nextElement(); 344 System.out.print(i.bcIndex + "\t" + i); 345 346 // Print block frequency with the label instruction 347 if (i.operator() == LABEL) { 348 BasicBlock bb = i.getBasicBlock(); 349 System.out.print(" Frequency: " + bb.getExecutionFrequency()); 350 } 351 352 System.out.println(); 353 } 354 } 355 356 /** 357 * Should {@code strictfp} be adhered to for the given instructions? 358 * <p> 359 * Note: we currently don't support {@code strictfp} at all, so this method 360 * is unused. 361 * 362 * @param is a sequence of instruction 363 * @return {@code true} if any of the instructions requires 364 * {@code strictfp} 365 */ 366 public static boolean strictFP(Instruction... is) { 367 for (Instruction i : is) { 368 if (i.position.method.isStrictFP()) { 369 return true; 370 } 371 } 372 return false; 373 } 374 375 /** 376 * Return the first instruction with respect to 377 * the current code linearization order. 378 * 379 * @return the first instruction in the code order 380 */ 381 public Instruction firstInstructionInCodeOrder() { 382 return firstBasicBlockInCodeOrder().firstInstruction(); 383 } 384 385 /** 386 * Return the last instruction with respect to 387 * the current code linearization order. 388 * 389 * @return the last instruction in the code order 390 */ 391 public Instruction lastInstructionInCodeOrder() { 392 return lastBasicBlockInCodeOrder().lastInstruction(); 393 } 394 395 /** 396 * Return the first basic block with respect to 397 * the current code linearization order. 398 * 399 * @return the first basic block in the code order 400 */ 401 public BasicBlock firstBasicBlockInCodeOrder() { 402 return cfg.firstInCodeOrder(); 403 } 404 405 /** 406 * Return the last basic block with respect to 407 * the current code linearization order. 408 * 409 * @return the last basic block in the code order 410 */ 411 public BasicBlock lastBasicBlockInCodeOrder() { 412 return cfg.lastInCodeOrder(); 413 } 414 415 /** 416 * Forward (with respect to the current code linearization order) 417 * iteration over all the instructions in this IR. 418 * The IR must <em>not</em> be modified during the iteration. 419 * 420 * @return an enumeration that enumerates the 421 * instructions in forward code order. 422 */ 423 public Enumeration<Instruction> forwardInstrEnumerator() { 424 return IREnumeration.forwardGlobalIE(this); 425 } 426 427 /** 428 * Reverse (with respect to the current code linearization order) 429 * iteration over all the instructions in this IR. 430 * The IR must <em>not</em> be modified during the iteration. 431 * 432 * @return an enumeration that enumerates the 433 * instructions in reverse code order. 434 */ 435 public Enumeration<Instruction> reverseInstrEnumerator() { 436 return IREnumeration.reverseGlobalIE(this); 437 } 438 439 /** 440 * Enumerate the basic blocks in the IR in an arbitrary order. 441 * 442 * @return an enumeration of {@link BasicBlock}s that enumerates the 443 * basic blocks in an arbitrary order. 444 */ 445 public Enumeration<BasicBlock> getBasicBlocks() { 446 return IREnumeration.forwardBE(this); 447 } 448 449 /** 450 * Forward (with respect to the current code linearization order) 451 * iteration overal all the basic blocks in the IR. 452 * 453 * @return an enumeration of {@link BasicBlock}s that enumerates the 454 * basic blocks in forward code order. 455 */ 456 public Enumeration<BasicBlock> forwardBlockEnumerator() { 457 return IREnumeration.forwardBE(this); 458 } 459 460 /** 461 * Reverse (with respect to the current code linearization order) 462 * iteration overal all the basic blocks in the IR. 463 * 464 * @return an enumeration of {@link BasicBlock}s that enumerates the 465 * basic blocks in reverse code order. 466 */ 467 public Enumeration<BasicBlock> reverseBlockEnumerator() { 468 return IREnumeration.reverseBE(this); 469 } 470 471 /** 472 * Return an enumeration of the parameters to the IR 473 * Warning: Only valid before register allocation (see CallingConvention) 474 * 475 * @return the parameters of the IR. 476 */ 477 public Enumeration<Operand> getParameters() { 478 for (Instruction s = firstInstructionInCodeOrder(); true; s = s.nextInstructionInCodeOrder()) { 479 if (s.operator() == IR_PROLOGUE) { 480 return s.getDefs(); 481 } 482 } 483 } 484 485 /** 486 * Is the operand a parameter of the IR? 487 * Warning: Only valid before register allocation (see CallingConvention) 488 * 489 * @param op the operand to check 490 * @return {@code true} if the op is a parameter to the IR, {@code false} otherwise 491 */ 492 public boolean isParameter(Operand op) { 493 for (Enumeration<Operand> e = getParameters(); e.hasMoreElements();) { 494 if (e.nextElement().similar(op)) return true; 495 } 496 return false; 497 } 498 499 /** 500 * How many bytes of parameters does this method take? 501 * 502 * @return number of bytes that are necessary to hold the method's 503 * parameters, including space for the {@code this} parameter 504 * if applicable 505 * 506 */ 507 public int incomingParameterBytes() { 508 int nWords = method.getParameterWords(); 509 // getParameterWords() does not include the implicit 'this' parameter. 510 if (!method.isStatic()) nWords++; 511 return nWords << LOG_BYTES_IN_ADDRESS; 512 } 513 514 /** 515 * Recompute the basic block map, so can use getBasicBlock(int) 516 * to index into the basic blocks quickly. 517 * TODO: think about possibly keeping the basic block map up-to-date 518 * automatically (Use a hashtable, perhaps?). 519 */ 520 public void resetBasicBlockMap() { 521 basicBlockMap = new BasicBlock[getMaxBasicBlockNumber() + 1]; 522 for (Enumeration<BasicBlock> bbEnum = cfg.basicBlocks(); bbEnum.hasMoreElements();) { 523 BasicBlock block = bbEnum.nextElement(); 524 basicBlockMap[block.getNumber()] = block; 525 } 526 } 527 528 /** 529 * Get the basic block with a given number. 530 * PRECONDITION: {@link #resetBasicBlockMap} has been called 531 * before calling this function, but after making any changes to 532 * the set of basic blocks in the IR. 533 * 534 * @param number the number of the basic block to retrieve 535 * @return that requested block 536 */ 537 public BasicBlock getBasicBlock(int number) { 538 if (VM.VerifyAssertions) VM._assert(basicBlockMap != null); 539 return basicBlockMap[number]; 540 } 541 542 /** 543 * Get an enumeration of all the basic blocks whose numbers 544 * appear in the given BitSet. 545 * PRECONDITION: {@link #resetBasicBlockMap} has been called 546 * before calling this function, but after making any changes to 547 * the set of basic blocks in the IR. 548 * 549 * @param bits The BitSet that defines which basic blocks to 550 * enumerate. 551 * @return an enumeration of said blocks. 552 */ 553 public Enumeration<BasicBlock> getBasicBlocks(BitVector bits) { 554 return new BitSetBBEnum(this, bits); 555 } 556 557 // TODO: It would be easy to avoid creating the Stack if we switch to 558 // the "advance" pattern used in BasicBlock.BBEnum. 559 // TODO: Make this an anonymous local class. 560 private static final class BitSetBBEnum implements Enumeration<BasicBlock> { 561 private final Stack<BasicBlock> stack; 562 563 BitSetBBEnum(IR ir, BitVector bits) { 564 stack = new Stack<BasicBlock>(); 565 int size = bits.length(); 566 Enumeration<BasicBlock> bbEnum = ir.getBasicBlocks(); 567 while (bbEnum.hasMoreElements()) { 568 BasicBlock block = bbEnum.nextElement(); 569 int number = block.getNumber(); 570 if (number < size && bits.get(number)) stack.push(block); 571 } 572 } 573 574 @Override 575 public boolean hasMoreElements() { 576 return !stack.empty(); 577 } 578 579 @Override 580 public BasicBlock nextElement() { 581 return stack.pop(); 582 } 583 } 584 585 /** 586 * Counts all the instructions currently in this IR. 587 * 588 * @return the number of instructions 589 */ 590 public int countInstructions() { 591 int num = 0; 592 for (Instruction instr = firstInstructionInCodeOrder(); instr != null; instr = 593 instr.nextInstructionInCodeOrder(), num++) { 594 } 595 return num; 596 } 597 598 /** 599 * Densely numbers all the instructions currently in this IR 600 * from 0...numInstr-1. 601 * 602 * @return a map that maps each instruction to its number 603 */ 604 public Map<Instruction, Integer> numberInstructionsViaMap() { 605 HashMap<Instruction, Integer> instructionNumbers = new HashMap<Instruction, Integer>(); 606 607 int num = 0; 608 for (Instruction instr = firstInstructionInCodeOrder(); instr != null; instr = 609 instr.nextInstructionInCodeOrder(), num++) { 610 instructionNumbers.put(instr, Integer.valueOf(num)); 611 } 612 return instructionNumbers; 613 } 614 615 /** 616 * Returns the number of symbolic registers for this IR. 617 * 618 * @return number of symbolic registers that were allocated 619 * for this IR object 620 */ 621 public int getNumberOfSymbolicRegisters() { 622 return regpool.getNumberOfSymbolicRegisters(); 623 } 624 625 /** 626 * @return the largest basic block number assigned to 627 * a block in the IR. Will return -1 if no 628 * block numbers have been assigned. 629 */ 630 public int getMaxBasicBlockNumber() { 631 if (cfg == null) { 632 return -1; 633 } else { 634 return cfg.numberOfNodes(); 635 } 636 } 637 638 /** 639 * Prune the exceptional out edges for each basic block in the IR. 640 */ 641 public void pruneExceptionalOut() { 642 if (hasReachableExceptionHandlers()) { 643 for (Enumeration<BasicBlock> e = getBasicBlocks(); e.hasMoreElements();) { 644 BasicBlock bb = e.nextElement(); 645 bb.pruneExceptionalOut(this); 646 } 647 } 648 } 649 650 /** 651 * @return <code>true</code> if it is possible that the IR contains 652 * an exception handler, <code>false</code> if it is not. 653 * Note this method may conservatively return <code>true</code> 654 * even if the IR does not actually contain a reachable 655 * exception handler. 656 */ 657 public boolean hasReachableExceptionHandlers() { 658 return gc.generatedExceptionHandlers(); 659 } 660 661 /** 662 * Partially convert the FCFG into a more traditional 663 * CFG by splitting all nodes that contain PEIs and that 664 * have reachable exception handlers into multiple basic 665 * blocks such that the instructions in the block have 666 * the expected post-dominance relationship. Note, we do 667 * not bother to unfactor basic blocks that do not have reachable 668 * exception handlers because the fact that the post-dominance 669 * relationship between instructions does not hold in these blocks 670 * does not matter (at least for intraprocedural analyses). 671 * For more information {@link BasicBlock see}. 672 */ 673 public void unfactor() { 674 Enumeration<BasicBlock> e = getBasicBlocks(); 675 while (e.hasMoreElements()) { 676 BasicBlock b = e.nextElement(); 677 b.unfactor(this); 678 } 679 } 680 681 public boolean getHandlerLivenessComputed() { 682 return handlerLivenessComputed; 683 } 684 685 public void setHandlerLivenessComputed(boolean value) { 686 handlerLivenessComputed = value; 687 } 688 689 public LiveInterval getLivenessInformation() { 690 return livenessInformation; 691 } 692 693 public void setLivenessInformation(LiveInterval liveInterval) { 694 this.livenessInformation = liveInterval; 695 } 696 697 public Dominators getDominators() { 698 return dominators; 699 } 700 701 public void setDominators(Dominators dominators) { 702 this.dominators = dominators; 703 } 704 705 public LTDominators getLtDominators() { 706 return ltDominators; 707 } 708 709 public void setLtDominators(LTDominators ltDominators) { 710 this.ltDominators = ltDominators; 711 } 712 713 /** 714 * Verify that the IR is well-formed.<p> 715 * NB: this is expensive -- be sure to guard invocations with 716 * debugging flags. 717 * 718 * @param where phrase identifying invoking compilation phase 719 */ 720 public void verify(String where) { 721 verify(where, true); 722 } 723 724 /** 725 * Verify that the IR is well-formed.<p> 726 * NB: this is expensive -- be sure to guard invocations with 727 * debugging flags. 728 * 729 * @param where phrase identifying invoking compilation phase 730 * @param checkCFG should the CFG invariants be checked 731 * (they can become invalid in "late" MIR). 732 */ 733 public void verify(String where, boolean checkCFG) { 734 // Check basic block and the containing instruction construction 735 verifyBBConstruction(where); 736 737 if (checkCFG) { 738 // Check CFG invariants 739 verifyCFG(where); 740 } 741 742 if (IRStage < MIR) { 743 // In HIR or LIR: 744 // Simple def-use tests 745 if (VM.BuildForPowerPC) { 746 // only on PPC as def use doesn't consider def-use 747 verifyRegisterDefs(where); 748 } 749 750 // Verify registers aren't in use for 2 different types 751 verifyRegisterTypes(where); 752 } 753 754 if (PARANOID) { 755 // Follow CFG checking use follows def (ultra-expensive) 756 verifyUseFollowsDef(where); 757 758 // Simple sanity checks on instructions 759 verifyInstructions(where); 760 } 761 762 // Make sure CFG is in fit state for dominators 763 // TODO: Enable this check; currently finds some broken IR 764 // that we need to fix. 765 // verifyAllBlocksAreReachable(where); 766 } 767 768 /** 769 * Verify basic block construction from the basic block and 770 * instruction information. 771 * 772 * @param where phrase identifying invoking compilation phase 773 */ 774 private void verifyBBConstruction(String where) { 775 // First, verify that the basic blocks are properly chained together 776 // and that each basic block's instruction list is properly constructed. 777 BasicBlock cur = cfg.firstInCodeOrder(); 778 BasicBlock prev = null; 779 while (cur != null) { 780 if (cur.getPrev() != prev) { 781 verror(where, "Prev link of " + cur + " does not point to " + prev); 782 } 783 784 // Verify cur's start and end instructions 785 Instruction s = cur.start; 786 Instruction e = cur.end; 787 if (s == null) { 788 verror(where, "Bblock " + cur + " has null start instruction"); 789 } 790 if (e == null) { 791 verror(where, "Bblock " + cur + " has null end instruction"); 792 } 793 794 // cur has start and end instructions, 795 // make sure that they are locally ok. 796 if (!s.isBbFirst()) { 797 verror(where, "Instr " + s + " is first instr of " + cur + " but is not BB_FIRST"); 798 } 799 if (s.getBasicBlock() != cur) { 800 verror(where, "Instr " + s + " is first instr of " + cur + " but points to BBlock " + s.getBasicBlock()); 801 } 802 if (!e.isBbLast()) { 803 verror(where, "Instr " + e + " is last instr of " + cur + " but is not BB_LAST"); 804 } 805 if (e.getBasicBlock() != cur) { 806 verror(where, "Instr " + e + " is last instr of " + cur + " but points to BBlock " + e.getBasicBlock()); 807 } 808 809 // Now check the integrity of the block's instruction list 810 if (s.getPrev() != null) { 811 verror(where, "Instr " + s + " is the first instr of " + cur + " but has a predecessor " + s.getPrev()); 812 } 813 if (e.getNext() != null) { 814 verror(where, "Instr " + s + " is the last instr of " + cur + " but has a successor " + e.getNext()); 815 } 816 Instruction pp = s; 817 Instruction p = s.getNext(); 818 boolean foundBranch = false; 819 while (p != e) { 820 if (p == null) { 821 verror(where, "Fell off the instruction list in " + cur + " before finding " + e); 822 } 823 if (p.getPrev() != pp) { 824 verror(where, "Instr " + pp + " has next " + p + " but " + p + " has prev " + p.getPrev()); 825 } 826 if (!p.isBbInside()) { 827 verror(where, "Instr " + p + " should be inside " + cur + " but is not BBInside"); 828 } 829 if (foundBranch && !p.isBranch()) { 830 printInstructions(); 831 verror(where, "Non branch " + p + " after branch " + pp + " in " + cur); 832 } 833 if (p.isBranch() && p.operator() != LOWTABLESWITCH) { 834 foundBranch = true; 835 if (p.isUnconditionalBranch() && p.getNext() != e) { 836 printInstructions(); 837 verror(where, "Unconditional branch " + p + " does not end its basic block " + cur); 838 } 839 } 840 pp = p; 841 p = p.getNext(); 842 } 843 if (p.getPrev() != pp) { 844 verror(where, "Instr " + pp + " has next " + p + " but " + p + " has prev " + p.getPrev()); 845 } 846 847 prev = cur; 848 cur = (BasicBlock) cur.getNext(); 849 } 850 } 851 852 /** 853 * Verify control flow graph construction 854 * 855 * @param where phrase identifying invoking compilation phase 856 */ 857 private void verifyCFG(String where) { 858 // Check that the CFG links are well formed 859 final boolean VERIFY_CFG_EDGES = false; 860 int blockCountEstimate = getMaxBasicBlockNumber(); 861 HashSet<BasicBlock> seenBlocks = new HashSet<BasicBlock>(blockCountEstimate); 862 HashSet<BasicBlock> origOutSet = null; 863 if (VERIFY_CFG_EDGES) origOutSet = new HashSet<BasicBlock>(); 864 865 for (BasicBlock cur = cfg.firstInCodeOrder(); cur != null; cur = (BasicBlock) cur.getNext()) { 866 867 // Check incoming edges 868 for (Enumeration<BasicBlock> e = cur.getIn(); e.hasMoreElements();) { 869 BasicBlock pred = e.nextElement(); 870 if (!pred.pointsOut(cur)) { 871 verror(where, pred + " is an inEdge of " + cur + " but " + cur + " is not an outEdge of " + pred); 872 } 873 } 874 875 // Check outgoing edges 876 for (Enumeration<BasicBlock> e = cur.getOut(); e.hasMoreElements();) { 877 BasicBlock succ = e.nextElement(); 878 if (!succ.pointsIn(cur)) { 879 verror(where, succ + " is an outEdge of " + cur + " but " + cur + " is not an inEdge of " + succ); 880 } 881 // Remember the original out edges for CFG edge verification 882 if (VERIFY_CFG_EDGES && IRStage <= LIR) origOutSet.add(succ); 883 } 884 885 if (VERIFY_CFG_EDGES && IRStage <= LIR) { 886 // Next, check that the CFG links are semantically correct 887 // (ie that the CFG links and branch instructions agree) 888 // This done by calling recomputeNormalOut() and confirming 889 // that nothing changes. 890 cur.recomputeNormalOut(this); 891 892 // Confirm outgoing edges didn't change 893 for (Enumeration<BasicBlock> e = cur.getOut(); e.hasMoreElements();) { 894 BasicBlock succ = e.nextElement(); 895 if (!origOutSet.contains(succ) && !succ.isExit() // Sometimes recomput is conservative in adding edge to exit 896 // because it relies soley on the mayThrowUncaughtException 897 // flag. 898 ) { 899 cur.printExtended(); 900 verror(where, 901 "An edge in the cfg was incorrect. " + 902 succ + 903 " was not originally an out edge of " + 904 cur + 905 " but it was after calling recomputeNormalOut()"); 906 } 907 origOutSet.remove(succ); // we saw it, so remove it 908 } 909 // See if there were any edges that we didn't see the second 910 // time around 911 if (!origOutSet.isEmpty()) { 912 BasicBlock missing = origOutSet.iterator().next(); 913 914 cur.printExtended(); 915 verror(where, 916 "An edge in the cfg was incorrect. " + 917 missing + 918 " was originally an out edge of " + 919 cur + 920 " but not after calling recomputeNormalOut()"); 921 } 922 } 923 924 // remember this block because it is the bblist 925 seenBlocks.add(cur); 926 } 927 928 // Check to make sure that all blocks connected 929 // (via a CFG edge) to a block 930 // that is in the bblist are also in the bblist 931 for (BasicBlock cur = cfg.firstInCodeOrder(); cur != null; cur = (BasicBlock) cur.getNext()) { 932 for (Enumeration<BasicBlock> e = cur.getIn(); e.hasMoreElements();) { 933 BasicBlock pred = e.nextElement(); 934 if (!seenBlocks.contains(pred)) { 935 verror(where, 936 "In Method " + 937 method.getName() + 938 ", " + 939 pred + 940 " is an inEdge of " + 941 cur + 942 " but it is not in the CFG!"); 943 } 944 } 945 for (Enumeration<BasicBlock> e = cur.getOut(); e.hasMoreElements();) { 946 BasicBlock succ = e.nextElement(); 947 if (!seenBlocks.contains(succ)) { 948 // the EXIT block is never in the BB list 949 if (succ != cfg.exit()) { 950 verror(where, 951 "In Method " + 952 method.getName() + 953 ", " + 954 succ + 955 " is an outEdge of " + 956 cur + 957 " but it is not in the CFG!"); 958 } 959 } 960 } 961 } 962 } 963 964 /** 965 * Verify that every instruction: 966 * <ul> 967 * <li>1) has operands that back reference it</li> 968 * <li>2) is valid for its position in the basic block</li> 969 * <li>3) if we are MIR, has no guard operands</li> 970 * <li>4) test instruction is canonical</li> 971 * </ul> 972 * 973 * @param where phrase identifying invoking compilation phase 974 */ 975 private void verifyInstructions(String where) { 976 Enumeration<BasicBlock> bbEnum = cfg.basicBlocks(); 977 while (bbEnum.hasMoreElements()) { 978 BasicBlock block = bbEnum.nextElement(); 979 IREnumeration.AllInstructionsEnum instructions = new IREnumeration.AllInstructionsEnum(this, block); 980 boolean startingInstructionsPassed = false; 981 while (instructions.hasMoreElements()) { 982 Instruction instruction = instructions.nextElement(); 983 // Perform (1) and (3) 984 IREnumeration.AllUsesEnum useOperands = new IREnumeration.AllUsesEnum(this, instruction); 985 while (useOperands.hasMoreElements()) { 986 Operand use = useOperands.nextElement(); 987 if (use.instruction != instruction) { 988 verror(where, 989 "In block " + 990 block + 991 " for instruction " + 992 instruction + 993 " the back link in the use of operand " + 994 use + 995 " is invalid and references " + 996 use 997 .instruction); 998 } 999 if ((IRStage >= MIR) && (use.isRegister()) && (use.asRegister().getRegister().isValidation())) { 1000 verror(where, 1001 "In block " + 1002 block + 1003 " for instruction " + 1004 instruction + 1005 " the use operand " + 1006 use + 1007 " is invalid as it is a validation register and this IR is in MIR form"); 1008 } 1009 } 1010 IREnumeration.AllDefsEnum defOperands = new IREnumeration.AllDefsEnum(this, instruction); 1011 while (defOperands.hasMoreElements()) { 1012 Operand def = defOperands.nextElement(); 1013 if (def.instruction != instruction) { 1014 verror(where, 1015 "In block " + 1016 block + 1017 " for instruction " + 1018 instruction + 1019 " the back link in the def of operand " + 1020 def + 1021 " is invalid and references " + 1022 def 1023 .instruction); 1024 } 1025 if ((IRStage >= MIR) && (def.isRegister()) && (def.asRegister().getRegister().isValidation())) { 1026 verror(where, 1027 "In block " + 1028 block + 1029 " for instruction " + 1030 instruction + 1031 " the def operand " + 1032 def + 1033 " is invalid as it is a validation register and this IR is in MIR form"); 1034 } 1035 } 1036 // Perform (4) 1037 if (Binary.conforms(instruction) && instruction.operator().isCommutative()) { 1038 if (Binary.getVal1(instruction).isConstant()) { 1039 verror(where, "Non-canonical commutative operation " + instruction); 1040 } 1041 } 1042 // Perform (2) 1043 // test for starting instructions 1044 if (!startingInstructionsPassed) { 1045 if (Label.conforms(instruction)) { 1046 continue; 1047 } 1048 if (Phi.conforms(instruction)) { 1049 if ((!inSSAForm()) && (!inSSAFormAwaitingReEntry())) { 1050 verror(where, "Phi node encountered but SSA not computed"); 1051 } 1052 continue; 1053 } 1054 startingInstructionsPassed = true; 1055 } 1056 // main instruction location test 1057 switch (instruction.getOpcode()) { 1058 // Label and phi nodes must be at the start of a BB 1059 case PHI_opcode: 1060 case LABEL_opcode: 1061 verror(where, "Unexpected instruction in the middle of a basic block " + instruction); 1062 // BBend, Goto, IfCmp, TableSwitch, Return, Trap and Athrow 1063 // must all appear at the end of a basic block 1064 case INT_IFCMP_opcode: 1065 case INT_IFCMP2_opcode: 1066 case LONG_IFCMP_opcode: 1067 case FLOAT_IFCMP_opcode: 1068 case DOUBLE_IFCMP_opcode: 1069 case REF_IFCMP_opcode: 1070 instruction = instructions.nextElement(); 1071 if (!Goto.conforms(instruction) && !BBend.conforms(instruction)) { 1072 if ((VM.BuildForIA32 && !org.jikesrvm.compilers.opt.ir.ia32.MIR_Branch.conforms(instruction)) || 1073 (VM.BuildForPowerPC && !org.jikesrvm.compilers.opt.ir.ppc.MIR_Branch.conforms(instruction))) { 1074 verror(where, "Unexpected instruction after IFCMP " + instruction); 1075 } 1076 } 1077 if (Goto.conforms(instruction) || 1078 ((VM.BuildForIA32 && org.jikesrvm.compilers.opt.ir.ia32.MIR_Branch.conforms(instruction)) || 1079 (VM.BuildForPowerPC && org.jikesrvm.compilers.opt.ir.ppc.MIR_Branch.conforms(instruction)))) { 1080 instruction = instructions.nextElement(); 1081 if (!BBend.conforms(instruction)) { 1082 verror(where, "Unexpected instruction after GOTO/MIR_BRANCH " + instruction); 1083 } 1084 } 1085 if (instructions.hasMoreElements()) { 1086 verror(where, "Unexpected instructions after BBEND " + instructions.nextElement()); 1087 } 1088 break; 1089 case TABLESWITCH_opcode: 1090 case LOOKUPSWITCH_opcode: 1091 case ATHROW_opcode: 1092 case RETURN_opcode: 1093 // TODO: Traps should be at the end of basic blocks but 1094 // Simplify reduces instructions to traps not respecting 1095 // this. Uses of Simplify should eliminate unreachable 1096 // instructions when an instruction not at the end of a 1097 // basic block is reduced into a trap. When this happens 1098 // please uncomment the next line: 1099 //case TRAP_opcode: 1100 case GOTO_opcode: 1101 Instruction next = instructions.nextElement(); 1102 if (!BBend.conforms(next)) { 1103 verror(where, "Unexpected instruction after " + instruction + "\n" + next); 1104 } 1105 if (instructions.hasMoreElements()) { 1106 verror(where, "Unexpected instructions after BBEND " + instructions.nextElement()); 1107 } 1108 break; 1109 case BBEND_opcode: 1110 if (instructions.hasMoreElements()) { 1111 verror(where, "Unexpected instructions after BBEND " + instructions.nextElement()); 1112 } 1113 break; 1114 default: 1115 } 1116 } 1117 } 1118 } 1119 1120 /** 1121 * Verify that every block in the CFG is reachable as failing to do 1122 * so will cause EnterSSA.insertPhiFunctions to possibly access 1123 * elements in DominanceFrontier.getIteratedDominanceFrontier 1124 * and then DominanceFrontier.getDominanceFrontier that aren't 1125 * defined. Also verify that blocks reached over an exception out 1126 * edge are not also reachable on normal out edges as this will 1127 * confuse liveness analysis. 1128 * 1129 * @param where phrase identifying invoking compilation phase 1130 */ 1131 @SuppressWarnings("unused") 1132 // used when needed for debugging 1133 private void verifyAllBlocksAreReachable(String where) { 1134 BitVector reachableNormalBlocks = new BitVector(cfg.numberOfNodes()); 1135 BitVector reachableExceptionBlocks = new BitVector(cfg.numberOfNodes()); 1136 resetBasicBlockMap(); 1137 verifyAllBlocksAreReachable(where, cfg.entry(), reachableNormalBlocks, reachableExceptionBlocks, false); 1138 boolean hasUnreachableBlocks = false; 1139 StringBuilder unreachablesString = new StringBuilder(); 1140 for (int j = 0; j < cfg.numberOfNodes(); j++) { 1141 if (!reachableNormalBlocks.get(j) && !reachableExceptionBlocks.get(j)) { 1142 hasUnreachableBlocks = true; 1143 if (basicBlockMap[j] != null) { 1144 basicBlockMap[j].printExtended(); 1145 } 1146 unreachablesString.append(" BB").append(j); 1147 } 1148 } 1149 if (hasUnreachableBlocks) { 1150 verror(where, "Unreachable blocks in the CFG which will confuse dominators:" + unreachablesString); 1151 } 1152 } 1153 1154 /** 1155 * Verify that every block in the CFG is reachable as failing to do 1156 * so will cause EnterSSA.insertPhiFunctions to possibly access 1157 * elements in DominanceFrontier.getIteratedDominanceFrontier 1158 * and then DominanceFrontier.getDominanceFrontier that aren't 1159 * defined. Also verify that blocks reached over an exception out 1160 * edge are not also reachable on normal out edges as this will 1161 * confuse liveness analysis. 1162 * 1163 * @param where location of verify in compilation 1164 * @param curBB the current BB to work on 1165 * @param visitedNormalBBs the blocks already visited (to avoid cycles) on normal out edges 1166 * @param visitedExceptionalBBs the blocks already visited (to avoid cycles) on exceptional out edges 1167 * @param fromExceptionEdge should paths from exceptions be validated? 1168 */ 1169 private void verifyAllBlocksAreReachable(String where, BasicBlock curBB, BitVector visitedNormalBBs, 1170 BitVector visitedExceptionalBBs, boolean fromExceptionEdge) { 1171 // Set visited information 1172 if (fromExceptionEdge) { 1173 visitedExceptionalBBs.set(curBB.getNumber()); 1174 } else { 1175 visitedNormalBBs.set(curBB.getNumber()); 1176 } 1177 1178 // Recurse to next BBs 1179 Enumeration<BasicBlock> outBlocks = curBB.getNormalOut(); 1180 while (outBlocks.hasMoreElements()) { 1181 BasicBlock out = outBlocks.nextElement(); 1182 if (!visitedNormalBBs.get(out.getNumber())) { 1183 verifyAllBlocksAreReachable(where, out, visitedNormalBBs, visitedExceptionalBBs, false); 1184 } 1185 } 1186 outBlocks = curBB.getExceptionalOut(); 1187 while (outBlocks.hasMoreElements()) { 1188 BasicBlock out = outBlocks.nextElement(); 1189 if (!visitedExceptionalBBs.get(out.getNumber())) { 1190 verifyAllBlocksAreReachable(where, out, visitedNormalBBs, visitedExceptionalBBs, true); 1191 } 1192 if (visitedNormalBBs.get(out.getNumber())) { 1193 curBB.printExtended(); 1194 out.printExtended(); 1195 verror(where, 1196 "Basic block " + 1197 curBB + 1198 " reaches " + 1199 out + 1200 " by normal and exceptional out edges thereby breaking a liveness analysis assumption."); 1201 } 1202 } 1203 if (curBB.mayThrowUncaughtException()) { 1204 visitedExceptionalBBs.set(cfg.exit().getNumber()); 1205 if (!cfg.exit().isExit()) { 1206 cfg.exit().printExtended(); 1207 verror(where, "The exit block is reachable by an exception edge and contains instructions."); 1208 } 1209 } 1210 } 1211 1212 /** 1213 * Verify that every non-physical, non-parameter symbolic register 1214 * that has a use also has at least one def 1215 * 1216 * @param where phrase identifying invoking compilation phase 1217 */ 1218 private void verifyRegisterDefs(String where) { 1219 DefUse.computeDU(this); 1220 //TODO: (SJF)I hate the register list interface. Re-do it. 1221 for (Register r = regpool.getFirstSymbolicRegister(); r != null; r = r.getNext()) { 1222 if (r.isPhysical()) continue; 1223 if (r.useList != null) { 1224 if (r.defList == null) { 1225 printInstructions(); 1226 verror(where, "verifyRegisterDefs: " + r + " has use but no defs"); 1227 } 1228 } 1229 } 1230 } 1231 1232 /** 1233 * Verify that no register is used as a long type and an int type 1234 * PRECONDITION: register lists computed 1235 * 1236 * @param where phrase identifying invoking compilation phase 1237 */ 1238 private void verifyRegisterTypes(String where) { 1239 for (Register r = regpool.getFirstSymbolicRegister(); r != null; r = r.getNext()) { 1240 // don't worry about physical registers 1241 if (r.isPhysical()) continue; 1242 1243 int types = 0; 1244 if (r.isLong()) types++; 1245 if (r.isDouble()) types++; 1246 if (r.isInteger()) types++; 1247 if (r.isAddress()) types++; 1248 if (r.isFloat()) types++; 1249 if (types > 1) { 1250 verror(where, "Register " + r + " has incompatible types."); 1251 } 1252 } 1253 } 1254 1255 /** 1256 * Checks whether uses follow definitions and that in SSA form 1257 * variables aren't multiply defined 1258 * 1259 * @param where phrase identifying invoking compilation phase 1260 */ 1261 private void verifyUseFollowsDef(String where) { 1262 // Create set of defined variables and add registers that will be 1263 // defined before entry to the IR 1264 HashSet<Object> definedVariables = new HashSet<Object>(); 1265 // NB the last two args determine how thorough we're going to test 1266 // things 1267 verifyUseFollowsDef(where, 1268 definedVariables, 1269 cfg.entry(), 1270 new BitVector(cfg.numberOfNodes()), 1271 new ArrayList<BasicBlock>(), 1272 5, 1273 // <-- maximum number of basic blocks followed 1274 true 1275 // <-- follow exception as well as normal out edges? 1276 ); 1277 } 1278 1279 /** 1280 * Check whether uses follow definitions and in SSA form that 1281 * variables aren't multiply defined 1282 * 1283 * @param where location of verify in compilation 1284 * @param definedVariables variables already defined on this path 1285 * @param curBB the current BB to work on 1286 * @param visitedBBs the blocks already visited (to avoid cycles) 1287 * @param path a record of the path taken to reach this basic block 1288 * @param maxPathLength the maximum number of basic blocks that will be followed 1289 * @param traceExceptionEdges should paths from exceptions be validated? 1290 */ 1291 private void verifyUseFollowsDef(String where, HashSet<Object> definedVariables, BasicBlock curBB, 1292 BitVector visitedBBs, ArrayList<BasicBlock> path, int maxPathLength, 1293 boolean traceExceptionEdges) { 1294 if (path.size() > maxPathLength) { 1295 return; 1296 } 1297 path.add(curBB); 1298 // Process instructions in block 1299 IREnumeration.AllInstructionsEnum instructions = new IREnumeration.AllInstructionsEnum(this, curBB); 1300 while (instructions.hasMoreElements()) { 1301 Instruction instruction = instructions.nextElement(); 1302 // Special phi handling case 1303 if (Phi.conforms(instruction)) { 1304 if ((!inSSAForm()) && (!inSSAFormAwaitingReEntry())) { 1305 verror(where, "Phi node encountered but SSA not computed"); 1306 } 1307 // Find predecessors that we have already visited 1308 for (int i = 0; i < Phi.getNumberOfPreds(instruction); i++) { 1309 BasicBlock phi_pred = Phi.getPred(instruction, i).block; 1310 if (phi_pred.getNumber() > basicBlockMap.length) { 1311 verror(where, "Phi predecessor not a valid basic block " + phi_pred); 1312 } 1313 if ((curBB != phi_pred) && path.contains(phi_pred)) { 1314 // This predecessor has been visited on this path so the 1315 // variable should be defined 1316 Object variable = getVariableUse(where, Phi.getValue(instruction, i)); 1317 if ((variable != null) && (!definedVariables.contains(variable))) { 1318 StringBuilder pathString = new StringBuilder(); 1319 for (int j = 0; j < path.size(); j++) { 1320 pathString.append(path.get(j).getNumber()); 1321 if (j < (path.size() - 1)) { 1322 pathString.append("->"); 1323 } 1324 } 1325 verror(where, "Use of " + variable + " before definition: " + instruction + "\npath: " + pathString); 1326 } 1327 } 1328 } 1329 } else { 1330 // General use follows def test 1331 IREnumeration.AllUsesEnum useOperands = new IREnumeration.AllUsesEnum(this, instruction); 1332 while (useOperands.hasMoreElements()) { 1333 Object variable = getVariableUse(where, useOperands.nextElement()); 1334 if ((variable != null) && (!definedVariables.contains(variable))) { 1335 if (instruction.operator().toString().indexOf("xor") != -1) 1336 continue; 1337 StringBuilder pathString = new StringBuilder(); 1338 for (int i = 0; i < path.size(); i++) { 1339 pathString.append(path.get(i).getNumber()); 1340 if (i < (path.size() - 1)) { 1341 pathString.append("->"); 1342 } 1343 } 1344 verror(where, "Use of " + variable + " before definition: " + instruction + "\npath: " + pathString); 1345 } 1346 } 1347 } 1348 // Add definitions to defined variables 1349 IREnumeration.AllDefsEnum defOperands = new IREnumeration.AllDefsEnum(this, instruction); 1350 while (defOperands.hasMoreElements()) { 1351 Object variable = getVariableDef(where, defOperands.nextElement()); 1352 // Check that a variable isn't defined twice when we believe we're in SSA form 1353 if (variable != null) { 1354 if ((inSSAForm()) && (!inSSAFormAwaitingReEntry())) { 1355 if (definedVariables.contains(variable)) { 1356 verror(where, "Single assignment broken - multiple definitions of " + variable); 1357 } 1358 } 1359 definedVariables.add(variable); 1360 } 1361 } 1362 } 1363 // Recurse to next BBs 1364 visitedBBs.set(curBB.getNumber()); 1365 Enumeration<BasicBlock> outBlocks; 1366 if (traceExceptionEdges) { 1367 outBlocks = curBB.getOut(); // <-- very slow 1368 } else { 1369 outBlocks = curBB.getNormalOut(); 1370 } 1371 while (outBlocks.hasMoreElements()) { 1372 BasicBlock out = outBlocks.nextElement(); 1373 if (!visitedBBs.get(out.getNumber())) { 1374 verifyUseFollowsDef(where, 1375 new HashSet<Object>(definedVariables), 1376 out, 1377 new BitVector(visitedBBs), 1378 new ArrayList<BasicBlock>(path), 1379 maxPathLength, 1380 traceExceptionEdges); 1381 visitedBBs.set(out.getNumber()); 1382 } 1383 } 1384 } 1385 1386 /** 1387 * Get the variable used by this operand 1388 * 1389 * @param where the verification location 1390 * @param operand the operand to pull a variable from 1391 * @return {@code null} if the variable should be ignored otherwise the variable 1392 */ 1393 private Object getVariableUse(String where, Operand operand) { 1394 if (operand.isConstant() || 1395 (operand instanceof ConditionOperand) || 1396 operand.isStringConstant() || 1397 operand.isType() || 1398 operand.isMethod() || 1399 operand.isBranch() || 1400 (operand instanceof BranchProfileOperand) || 1401 operand.isLocation() || 1402 operand.isStackLocation() || 1403 operand.isMemory() || 1404 (operand instanceof TrapCodeOperand) || 1405 (operand instanceof InlinedOsrTypeInfoOperand) || 1406 (VM.BuildForIA32 && operand instanceof IA32ConditionOperand) || 1407 (VM.BuildForPowerPC && operand instanceof PowerPCConditionOperand) || 1408 (VM.BuildForIA32 && operand instanceof BURSManagedFPROperand) || 1409 (VM.BuildForPowerPC && operand instanceof PowerPCTrapOperand)) { 1410 return null; 1411 } else if (operand.isRegister()) { 1412 Register register = operand.asRegister().getRegister(); 1413 // ignore physical registers 1414 return (register.isPhysical()) ? null : register; 1415 } else if (operand.isBlock()) { 1416 Enumeration<BasicBlock> blocks = cfg.basicBlocks(); 1417 while (blocks.hasMoreElements()) { 1418 if (operand.asBlock().block == blocks.nextElement()) { 1419 return null; 1420 } 1421 } 1422 verror(where, "Basic block not found in CFG for BasicBlockOperand: " + operand); 1423 return null; 1424 } else if (operand instanceof HeapOperand) { 1425 if (!actualSSAOptions.getHeapValid()) { 1426 return null; 1427 } 1428 HeapVariable<?> variable = ((HeapOperand<?>) operand).getHeapVariable(); 1429 if (variable.getNumber() > 0) { 1430 return variable; 1431 } else { 1432 // definition 0 comes in from outside the IR 1433 return null; 1434 } 1435 } else { 1436 verror(where, "Use: Unknown variable of " + operand.getClass() + " with operand: " + operand); 1437 return null; 1438 } 1439 } 1440 1441 /** 1442 * Get the variable defined by this operand 1443 * 1444 * @param where the verification location 1445 * @param operand the operand to pull a variable from 1446 * @return {@code null} if the variable should be ignored otherwise the variable 1447 */ 1448 private Object getVariableDef(String where, Operand operand) { 1449 if (operand.isRegister()) { 1450 Register register = operand.asRegister().getRegister(); 1451 // ignore physical registers 1452 return (register.isPhysical()) ? null : register; 1453 } else if (operand instanceof HeapOperand) { 1454 if (!actualSSAOptions.getHeapValid()) { 1455 return null; 1456 } 1457 return ((HeapOperand<?>) operand).getHeapVariable(); 1458 } else if (VM.BuildForIA32 && operand instanceof BURSManagedFPROperand) { 1459 return ((BURSManagedFPROperand) operand).regNum; 1460 } else if (operand.isStackLocation() || operand.isMemory()) { 1461 // it would be nice to handle these but they have multiple 1462 // constituent parts :-( 1463 return null; 1464 } else { 1465 verror(where, "Def: Unknown variable of " + operand.getClass() + " with operand: " + operand); 1466 return null; 1467 } 1468 } 1469 1470 /** 1471 * Generate error 1472 * 1473 * @param where phrase identifying invoking compilation phase 1474 * @param msg error message 1475 */ 1476 @NoInline 1477 private void verror(String where, String msg) { 1478 CompilerPhase.dumpIR(this, "Verify: " + where + ": " + method, true); 1479 VM.sysWriteln("VERIFY: " + where + " " + msg); 1480 throw new OptimizingCompilerException("VERIFY: " + where, msg); 1481 } 1482 1483}