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