/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Eclipse Public License (EPL); * You may not use this file except in compliance with the License. You * may obtain a copy of the License at * * http://www.opensource.org/licenses/eclipse-1.0.php * * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. */ package org.jikesrvm.compilers.opt.ir; import static org.jikesrvm.compilers.opt.ir.Operators.PHI; import java.util.Enumeration; import java.util.Iterator; import org.jikesrvm.classloader.TypeReference; import org.jikesrvm.compilers.opt.ir.operand.HeapOperand; import org.jikesrvm.compilers.opt.ir.operand.Operand; import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand; import org.vmmagic.pragma.NoInline; /** * This class is not meant to be instantiated.<p> * It simply serves as a place to collect the implementation of * primitive IR enumerations.<p> * None of these functions are meant to be called directly from * anywhere except IR, Instruction, and BasicBlock.<p> * General clients should use the higher level interfaces provided * by those classes. */ public abstract class IREnumeration { /** * Forward intra basic block instruction enumerations from * from start...last inclusive.<p> * * NB: start and last _must_ be in the same basic block * and must be in the proper relative order. * This code does _not_ check this invariant, and will * simply fail by eventually thowing a NoSuchElementException * if it is not met. Caller's must be sure the invariants are met. * * @param start the instruction to start with * @param end the instruction to end with * @return an enumeration of the instructions from start to end */ public static Enumeration<Instruction> forwardIntraBlockIE(final Instruction start, final Instruction end) { return new Enumeration<Instruction>() { private Instruction current = start; private final Instruction last = end; @Override public boolean hasMoreElements() { return current != null; } @Override public Instruction nextElement() { Instruction res = current; if (current == last) { current = null; } else { try { current = current.getNext(); } catch (NullPointerException e) { fail("forwardIntraBlockIE"); } } return res; } }; } /** * Reverse intra basic block instruction enumerations from * from start...last inclusive.<p> * * NB: start and last _must_ be in the same basic block * and must be in the proper relative order. * This code does _not_ check this invariant, and will * simply fail by eventually thowing a NoSuchElementException * if it is not met. Caller's must be sure the invariants are met. * * @param start the instruction to start with * @param end the instruction to end with * @return an enumeration of the instructions from start to end */ public static Enumeration<Instruction> reverseIntraBlockIE(final Instruction start, final Instruction end) { return new Enumeration<Instruction>() { private Instruction current = start; private final Instruction last = end; @Override public boolean hasMoreElements() { return current != null; } @Override public Instruction nextElement() { Instruction res = current; if (current == last) { current = null; } else { try { current = current.getPrev(); } catch (NullPointerException e) { fail("reverseIntraBlockIE"); } } return res; } }; } /** * A forward enumeration of all the instructions in the IR. * * @param ir the IR to walk over * @return a forward enumeration of the insturctions in ir */ public static Enumeration<Instruction> forwardGlobalIE(final IR ir) { return new Enumeration<Instruction>() { private Instruction current = ir.firstInstructionInCodeOrder(); @Override public boolean hasMoreElements() { return current != null; } @Override public Instruction nextElement() { try { Instruction res = current; current = current.nextInstructionInCodeOrder(); return res; } catch (NullPointerException e) { fail("forwardGlobalIR"); return null; } } }; } /** * A reverse enumeration of all the instructions in the IR. * * @param ir the IR to walk over * @return a forward enumeration of the insturctions in ir */ public static Enumeration<Instruction> reverseGlobalIE(final IR ir) { return new Enumeration<Instruction>() { private Instruction current = ir.lastInstructionInCodeOrder(); @Override public boolean hasMoreElements() { return current != null; } @Override public Instruction nextElement() { try { Instruction res = current; current = current.prevInstructionInCodeOrder(); return res; } catch (NullPointerException e) { fail("forwardGlobalIR"); return null; } } }; } /** * A forward enumeration of all the basic blocks in the IR. * * @param ir the IR to walk over * @return a forward enumeration of the basic blocks in ir */ public static Enumeration<BasicBlock> forwardBE(final IR ir) { return new Enumeration<BasicBlock>() { private BasicBlock current = ir.firstBasicBlockInCodeOrder(); @Override public boolean hasMoreElements() { return current != null; } @Override public BasicBlock nextElement() { try { BasicBlock res = current; current = current.nextBasicBlockInCodeOrder(); return res; } catch (NullPointerException e) { fail("forwardBE"); return null; } } }; } /** * A reverse enumeration of all the basic blocks in the IR. * * @param ir the IR to walk over * @return a reverse enumeration of the basic blocks in ir */ public static Enumeration<BasicBlock> reverseBE(final IR ir) { return new Enumeration<BasicBlock>() { private BasicBlock current = ir.lastBasicBlockInCodeOrder(); @Override public boolean hasMoreElements() { return current != null; } @Override public BasicBlock nextElement() { try { BasicBlock res = current; current = current.prevBasicBlockInCodeOrder(); return res; } catch (NullPointerException e) { fail("forwardBE"); return null; } } }; } /** * This class implements an enumeration of instructions over * all instructions for a basic block. This enumeration includes * explicit instructions in the IR and implicit phi instructions for * heap variables, which are stored only in this lookaside * structure. * @see org.jikesrvm.compilers.opt.ssa.SSADictionary */ public static final class AllInstructionsEnum implements Enumeration<Instruction> { /** * An enumeration of the explicit instructions in the IR for a * basic block */ private final Enumeration<Instruction> explicitInstructions; /** * An enumeration of the implicit instructions in the IR for a * basic block. These instructions appear only in the SSA * dictionary lookaside structure. */ private final Iterator<Instruction> implicitInstructions; /** * The label instruction for the basic block - the label is * special as we want it to appear in the enumeration before the * implicit SSA instructions */ private Instruction labelInstruction; /** * Construct an enumeration for all instructions, both implicit and * explicit in the IR, for a given basic block * * @param ir the containing IR * @param block the basic block whose instructions this enumerates */ public AllInstructionsEnum(IR ir, BasicBlock block) { explicitInstructions = block.forwardInstrEnumerator(); if (ir.inSSAForm()) { implicitInstructions = ir.HIRInfo.dictionary.getHeapPhiInstructions(block); } else { implicitInstructions = null; } labelInstruction = explicitInstructions.nextElement(); } /** * Are there more elements in the enumeration? * * @return {@code true} or {@code false} */ @Override public boolean hasMoreElements() { return (((implicitInstructions != null) && implicitInstructions.hasNext()) || explicitInstructions.hasMoreElements()); } @Override public Instruction nextElement() { if (labelInstruction != null) { Instruction temp = labelInstruction; labelInstruction = null; return temp; } else if ((implicitInstructions != null) && implicitInstructions.hasNext()) { return implicitInstructions.next(); } else { return explicitInstructions.nextElement(); } } } /** * This class implements an {@link Enumeration} of {@link Operand}s. It used * for holding the definitions of a particular instruction and being * used as an enumeration for iterating over. It differs from other * enumerations of Operand as it iterates over both implicit * and explicit operands. * @see org.jikesrvm.compilers.opt.ssa.SSADictionary */ public static final class AllDefsEnum implements Enumeration<Operand> { /** * Enumeration of non-heap operands defined by the instruction */ private final Enumeration<Operand> instructionOperands; /** * Array of heap operands defined by the instruction */ private final HeapOperand<?>[] heapOperands; /** * Current heap operand we're upto for the enumeration */ private int curHeapOperand; /** * Implicit definitions from the operator */ private final Enumeration<Register> implicitDefs; /** * Defining instruction */ private final Instruction instr; /** * Construct/initialize object * * @param ir Containing IR * @param instr Instruction to get definitions for */ public AllDefsEnum(IR ir, Instruction instr) { this.instr = instr; instructionOperands = instr.getDefs(); if (instr.operator().getNumberOfImplicitDefs() > 0) { implicitDefs = GenericPhysicalDefUse.enumerate(instr.operator().implicitDefs, ir); } else { implicitDefs = null; } if (ir.inSSAForm() && (instr.operator() != PHI)) { // Phi instructions store the heap SSA in the actual // instruction heapOperands = ir.HIRInfo.dictionary.getHeapDefs(instr); } else { heapOperands = null; } } /** * Are there any more elements in the enumeration */ @Override public boolean hasMoreElements() { return ((instructionOperands.hasMoreElements()) || ((heapOperands != null) && (curHeapOperand < heapOperands.length)) || ((implicitDefs != null) && (implicitDefs.hasMoreElements()))); } @Override public Operand nextElement() { if (instructionOperands.hasMoreElements()) { return instructionOperands.nextElement(); } else { if ((implicitDefs != null) && implicitDefs.hasMoreElements()) { RegisterOperand rop = new RegisterOperand(implicitDefs.nextElement(), TypeReference.Int); rop.instruction = instr; return rop; } else { if (curHeapOperand >= heapOperands.length) { fail("Regular and heap operands exhausted"); } HeapOperand<?> result = heapOperands[curHeapOperand]; curHeapOperand++; return result; } } } } /** * This class implements an {@link Enumeration} of {@link Operand}. It used * for holding the uses of a particular instruction and being used * as an enumeration for iterating over. It differs from other * enumerations of Operand as it iterates over both implicit * and explicit operands. * @see org.jikesrvm.compilers.opt.ssa.SSADictionary */ public static final class AllUsesEnum implements Enumeration<Operand> { /** * Enumeration of non-heap operands defined by the instruction */ private final Enumeration<Operand> instructionOperands; /** * Array of heap operands defined by the instruction */ private final HeapOperand<?>[] heapOperands; /** * Current heap operand we're upto for the enumeration */ private int curHeapOperand; /** * Implicit uses from the operator */ private final Enumeration<Register> implicitUses; /** * Defining instruction */ private final Instruction instr; /** * Construct/initialize object * * @param ir Containing IR * @param instr Instruction to get uses for */ public AllUsesEnum(IR ir, Instruction instr) { this.instr = instr; instructionOperands = instr.getUses(); if (instr.operator().getNumberOfImplicitUses() > 0) { implicitUses = GenericPhysicalDefUse.enumerate(instr.operator().implicitUses, ir); } else { implicitUses = null; } if (ir.inSSAForm() && (instr.operator() != PHI)) { // Phi instructions store the heap SSA in the actual // instruction heapOperands = ir.HIRInfo.dictionary.getHeapUses(instr); } else { heapOperands = null; } } /** * Are there any more elements in the enumeration */ @Override public boolean hasMoreElements() { return ((instructionOperands.hasMoreElements()) || ((heapOperands != null) && (curHeapOperand < heapOperands.length)) || ((implicitUses != null) && (implicitUses.hasMoreElements()))); } @Override public Operand nextElement() { if (instructionOperands.hasMoreElements()) { return instructionOperands.nextElement(); } else { if ((implicitUses != null) && implicitUses.hasMoreElements()) { RegisterOperand rop = new RegisterOperand(implicitUses.nextElement(), TypeReference.Int); rop.instruction = instr; return rop; } else { if (curHeapOperand >= heapOperands.length) { fail("Regular and heap operands exhausted"); } HeapOperand<?> result = heapOperands[curHeapOperand]; curHeapOperand++; return result; } } } } @NoInline private static void fail(String msg) throws java.util.NoSuchElementException { throw new java.util.NoSuchElementException(msg); } }