FileDocCategorySizeDatePackage
PhiInsn.javaAPI DocAndroid 5.1 API11376Thu Mar 12 22:18:30 GMT 2015com.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 final int
ropResultReg
result register. The original result register of the phi insn is needed during the renaming process after the new result register has already been chosen.
private final ArrayList
operands
{@code non-null;} operands of the instruction; built up by {@link #addPhiOperand}
private com.android.dx.rop.code.RegisterSpecList
sources
{@code null-ok;} source registers; constructed lazily
Constructors Summary
public PhiInsn(com.android.dx.rop.code.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(resultReg, block);
        ropResultReg = resultReg.getReg();
    
public 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.

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

        v.visitPhiInsn(this);
    
public voidaddPhiOperand(com.android.dx.rop.code.RegisterSpec registerSpec, SsaBasicBlock predBlock)
Adds 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()));

        // Un-cache sources, 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 {@code PhiInsn}s.

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

param
type {@code non-null;} new TypeBearer
param
local {@code null-ok;} new local info, if available

        setResult(RegisterSpec.makeLocalOptional(
                          getResult().getReg(), type, local));
    
public com.android.dx.ssa.PhiInsnclone()
{@inheritDoc}

        throw new UnsupportedOperationException("can't clone phi");
    
public com.android.dx.rop.code.RopgetOpcode()
{@inheritDoc} Always returns null for {@code PhiInsn}s.

        return null;
    
public com.android.dx.rop.code.InsngetOriginalRopInsn()
{@inheritDoc} Always returns null for {@code PhiInsn}s.

        return null;
    
public intgetRopResultReg()
Gets the original rop-form result reg. This is useful during renaming.

return
the original rop-form result reg

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

return
{@code non-null;} 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) {
                getBlock().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 {@code 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 = new ArrayList<SsaBasicBlock>();

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

        return ret;
    
public voidremovePhiRegister(com.android.dx.rop.code.RegisterSpec registerSpec)
Removes all operand uses of a register from this phi instruction.

param
registerSpec register spec, including type and reg of operand

        ArrayList<Operand> operandsToRemove = new ArrayList<Operand>();
        for (Operand o : operands) {
            if (o.regSpec.getReg() == registerSpec.getReg()) {
                operandsToRemove.add(o);
            }
        }

        operands.removeAll(operandsToRemove);

        // Un-cache sources, in case someone has already called getSources().
        sources = null;
    
public java.lang.StringtoHuman()
{@inheritDoc}

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

param
extra {@code 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(": phi");

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

        RegisterSpec result = getResult();

        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 com.android.dx.rop.code.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");
    
public 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;