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 (InstructionEnumeration e = forwardInstrEnumerator(); e.hasMoreElements();) {
305 Instruction i = e.next();
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 InstructionEnumeration that enumerates the
376 * instructions in forward code order.
377 */
378 public InstructionEnumeration 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 InstructionEnumeration that enumerates the
388 * instructions in reverse code order.
389 */
390 public InstructionEnumeration 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 BasicBlockEnumeration that enumerates the
398 * basic blocks in an arbitrary order.
399 */
400 public BasicBlockEnumeration 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 BasicBlockEnumeration that enumerates the
409 * basic blocks in forward code order.
410 */
411 public BasicBlockEnumeration 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 BasicBlockEnumeration that enumerates the
420 * basic blocks in reverse code order.
421 */
422 public BasicBlockEnumeration 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 OperandEnumeration 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 true if the op is a parameter to the IR, false otherwise
446 */
447 public boolean isParameter(Operand op) {
448 for (OperandEnumeration e = getParameters(); e.hasMoreElements();) {
449 if (e.next().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 BasicBlockEnumeration 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 BasicBlockEnumeration {
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 public boolean hasMoreElements() { return !stack.empty(); }
525
526 public BasicBlock nextElement() { return stack.pop(); }
527
528 public BasicBlock next() {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 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 null) the scratch object on
587 * all basic blocks currently in this IR.
588 */
589 public void clearBasicBlockScratchObject() {
590 BasicBlockEnumeration e = getBasicBlocks();
591 while (e.hasMoreElements()) {
592 e.next().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 BasicBlockEnumeration e = getBasicBlocks();
653 while (e.hasMoreElements()) {
654 BasicBlock b = e.next();
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.
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.
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 (BasicBlockEnumeration e = cur.getIn(); e.hasMoreElements();) {
832 BasicBlock pred = e.next();
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 (BasicBlockEnumeration e = cur.getOut(); e.hasMoreElements();) {
840 BasicBlock succ = e.next();
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 (BasicBlockEnumeration e = cur.getOut(); e.hasMoreElements();) {
857 BasicBlock succ = e.next();
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 (BasicBlockEnumeration e = cur.getIn(); e.hasMoreElements();) {
896 BasicBlock pred = e.next();
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 (BasicBlockEnumeration e = cur.getOut(); e.hasMoreElements();) {
909 BasicBlock succ = e.next();
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.next();
945 // Perform (1) and (3)
946 IREnumeration.AllUsesEnum useOperands = new IREnumeration.AllUsesEnum(this, instruction);
947 while (useOperands.hasMoreElements()) {
948 Operand use = useOperands.next();
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.next();
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.next();
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.next();
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.next());
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.next();
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.next());
1058 }
1059 break;
1060 case BBEND_opcode:
1061 if (instructions.hasMoreElements()) {
1062 verror(where, "Unexpected instructions after BBEND " + instructions.next());
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 BasicBlockEnumeration outBlocks = curBB.getNormalOut();
1131 while (outBlocks.hasMoreElements()) {
1132 BasicBlock out = outBlocks.next();
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.next();
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.next();
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.next());
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.next());
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 BasicBlockEnumeration 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.next();
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 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 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 }