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}&gt;=HIR
268   */
269  public HIRInfo HIRInfo;
270
271  /**
272   * Pointer to the LIRInfo for this method.
273   * Valid only if {@link #IRStage}&gt;=LIR.
274   */
275  public LIRInfo LIRInfo;
276
277  /**
278   * Pointer to the MIRInfo for this method.
279   * Valid only if {@link #IRStage}&gt;=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}