FileDocCategorySizeDatePackage
PhiInsn.javaAPI DocAndroid 1.5 API10026Wed May 06 22:41:02 BST 2009com.android.dx.ssa

PhiInsn

public final class PhiInsn extends SsaInsn
A Phi instruction (magical post-control-flow-merge) instruction in SSA form. Will be converted to moves in predecessor blocks before conversion back to ROP form.

Fields Summary
private int
ropResultReg
the original result register of the phi insn is needed during the renaming process after the new result register has already been chosen.
private ArrayList
operands
private RegisterSpecList
sources
Constructors Summary
PhiInsn(RegisterSpec resultReg, SsaBasicBlock block)
Constructs a new phi insn with no operands.

param
resultReg the result reg for this phi insn
param
block block containing this insn.

        super(block);
        this.result = resultReg;
        ropResultReg = resultReg.getReg();
    
PhiInsn(int resultReg, SsaBasicBlock block)
Makes a phi insn with a void result type.

param
resultReg the result register for this phi insn.
param
block block containing this insn.

        super(block);

        /*
         * The type here is bogus: the type depends on the operand and
         * will be derived later.
         */
        this.result = RegisterSpec.make(resultReg, Type.VOID);
        ropResultReg = resultReg;
    
Methods Summary
public voidaccept(SsaInsn.Visitor v)
{@inheritDoc}

        v.visitPhiInsn(this);
    
public voidaddPhiOperand(RegisterSpec registerSpec, SsaBasicBlock predBlock)
Add an operand to this phi instruction

param
registerSpec register spec, including type and reg of operand
param
predBlock Predecessor block to be associated with this operand

        operands.add(new Operand(registerSpec, predBlock.getIndex(),
                predBlock.getRopLabel()));
        
        // in case someone has already called getSources()
        sources = null;
    
public booleanareAllOperandsEqual()

return
true if all operands use the same register

        if (operands.size() == 0 ) {
            // this should never happen
            return true;
        }

        int firstReg = operands.get(0).regSpec.getReg();
        for (Operand o: operands) {
            if (firstReg != o.regSpec.getReg()) {
                return false;
            }
        }

        return true;
    
public booleancanThrow()
{@inheritDoc} Always returns false for PhiInsns

        return false;
    
voidchangeResultType(com.android.dx.rop.type.TypeBearer type, LocalItem local)
Changes the result type. Used during phi type resolution

param
type non-null; new TypeBearer
param
local null-ok; new local info, if available

        result = RegisterSpec.makeLocalOptional(result.getReg(), type, local);
    
public com.android.dx.ssa.PhiInsnclone()

        throw new UnsupportedOperationException("can't clone phi");
    
public RopgetOpcode()
{@inheritDoc} Always returns null for PhiInsns

        return null;
    
public InsngetOriginalRopInsn()
{@inheritDoc} Always returns null for PhiInsns

        return null;
    
intgetRopResultReg()

return
the original rop-form result reg. Useful during renaming.

        return ropResultReg;
    
public RegisterSpecListgetSources()
Gets sources. Constructed lazily from phi operand data structures and then cached.

return
sources list


        if (sources != null) {
            return sources;
        }

        if (operands.size() == 0) {
            // How'd this happen? A phi insn with no operand?
            return RegisterSpecList.EMPTY;
        }

        int szSources = operands.size();
        sources = new RegisterSpecList(szSources);

        for (int i = 0; i < szSources; i++) {
            Operand o = operands.get(i);

            sources.set(i, o.regSpec);
        }

        sources.setImmutable();
        return sources;
    
public booleanhasSideEffect()
{@inheritDoc}

        return Optimizer.getPreserveLocals() && getLocalAssignment() != null;
    
public booleanisPhiOrMove()
{@inheritDoc}

        return true;    
    
public booleanisRegASource(int reg)
{@inheritDoc}

        /*
         * Avoid creating a sources list in case it has not already been
         * created
         */

        for (Operand o: operands) {
            if (o.regSpec.getReg() == reg) {
                return true;
            }
        }

        return false;
    
public final voidmapSourceRegisters(RegisterMapper mapper)
{@inheritDoc}

        for (Operand o: operands) {
            RegisterSpec old = o.regSpec;
            o.regSpec = mapper.map(old);
            if (old != o.regSpec) {
                block.getParent().onSourceChanged(this, old, o.regSpec);
            }
        }
        sources = null;
    
public intpredBlockIndexForSourcesIndex(int sourcesIndex)
Gets the index of the pred block associated with the RegisterSpec at the particular getSources() index.

param
sourcesIndex index of source in getSources()
return
block index

        return operands.get(sourcesIndex).blockIndex;
    
public java.util.ListpredBlocksForReg(int reg, SsaMethod ssaMeth)
Returns the list of predecessor blocks associated with all operands that have reg as an operand register.

param
reg register to look up
param
ssaMeth method we're operating on
return
List of predecessor blocks, empty if none

        ArrayList<SsaBasicBlock> ret 
            = (ArrayList<SsaBasicBlock>)new ArrayList();

        for (Operand o: operands) {
            if (o.regSpec.getReg() == reg) {
                ret.add(ssaMeth.getBlocks().get(o.blockIndex));
            }
        }

        return ret;
    
public java.lang.StringtoHuman()

return
human-readable string for listing dumps

        return toHumanWithInline(null);
    
protected final java.lang.StringtoHumanWithInline(java.lang.String extra)
Returns human-readable string for listing dumps. Allows sub-classes to specify extra text

param
extra null-ok; the argument to print after the opcode
return
human-readable string for listing dumps

        StringBuffer sb = new StringBuffer(80);

        sb.append(SourcePosition.NO_INFO);
        sb.append(": ");
        sb.append("phi");       

        if (extra != null) {
            sb.append("(");
            sb.append(extra);
            sb.append(")");
        }

        if (result == null) {
            sb.append(" .");
        } else {
            sb.append(" ");
            sb.append(result.toHuman());
        }

        sb.append(" <-");

        int sz = getSources().size();
        if (sz == 0) {
            sb.append(" .");
        } else {
            for (int i = 0; i < sz; i++) {
                sb.append(" ");
                sb.append(sources.get(i).toHuman()
                        + "[b="
                        + Hex.u2(operands.get(i).ropLabel)  + "]");
            }
        }

        return sb.toString();
    
public InsntoRopInsn()
Always throws an exeption, since a phi insn may not be converted back to rop form

return
always throws exception

        throw new IllegalArgumentException(
                "Cannot convert phi insns to rop form");
    
voidupdateSourcesToDefinitions(SsaMethod ssaMeth)
Updates the TypeBearers of all the sources (phi operands) to be the current TypeBearer of the register-defining instruction's result. This is used during phi-type resolution.

Note that local association of operands are preserved in this step.

param
ssaMeth method that contains this insn


        for (Operand o: operands) {
            RegisterSpec def 
                = ssaMeth.getDefinitionForRegister(
                    o.regSpec.getReg()).getResult();

            o.regSpec = o.regSpec.withType(def.getType());
        }

        sources = null;