use of com.android.dx.rop.code.RegisterSpec in project buck by facebook.
the class PhiInsn method updateSourcesToDefinitions.
/**
* 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.<p>
*
* Note that local association of operands are preserved in this step.
*
* @param ssaMeth method that contains this insn
*/
public void updateSourcesToDefinitions(SsaMethod ssaMeth) {
for (Operand o : operands) {
RegisterSpec def = ssaMeth.getDefinitionForRegister(o.regSpec.getReg()).getResult();
o.regSpec = o.regSpec.withType(def.getType());
}
sources = null;
}
use of com.android.dx.rop.code.RegisterSpec in project buck by facebook.
the class PhiTypeResolver method run.
/**
* Runs the phi-type resolver.
*/
private void run() {
int regCount = ssaMeth.getRegCount();
for (int reg = 0; reg < regCount; reg++) {
SsaInsn definsn = ssaMeth.getDefinitionForRegister(reg);
if (definsn != null && (definsn.getResult().getBasicType() == Type.BT_VOID)) {
worklist.set(reg);
}
}
int reg;
while (0 <= (reg = worklist.nextSetBit(0))) {
worklist.clear(reg);
/*
* definitions on the worklist have a type of BT_VOID, which
* must have originated from a PhiInsn.
*/
PhiInsn definsn = (PhiInsn) ssaMeth.getDefinitionForRegister(reg);
if (resolveResultType(definsn)) {
/*
* If the result type has changed, re-resolve all phis
* that use this.
*/
List<SsaInsn> useList = ssaMeth.getUseListForRegister(reg);
int sz = useList.size();
for (int i = 0; i < sz; i++) {
SsaInsn useInsn = useList.get(i);
RegisterSpec resultReg = useInsn.getResult();
if (resultReg != null && useInsn instanceof PhiInsn) {
worklist.set(resultReg.getReg());
}
}
}
}
}
use of com.android.dx.rop.code.RegisterSpec in project J2ME-Loader by nikita36078.
the class Ropper method addSynchExceptionHandlerBlock.
/**
* Constructs and adds, if necessary, the catch-all exception handler
* block to deal with unwinding the lock taken on entry to a synchronized
* method.
*/
private void addSynchExceptionHandlerBlock() {
if (!synchNeedsExceptionHandler) {
/*
* The method being converted either isn't synchronized or
* can't possibly throw exceptions in its main body, so
* there's no need for a synchronized method exception
* handler.
*/
return;
}
SourcePosition pos = method.makeSourcePosistion(0);
RegisterSpec exReg = RegisterSpec.make(0, Type.THROWABLE);
BasicBlock bb;
Insn insn;
InsnList insns = new InsnList(2);
insn = new PlainInsn(Rops.opMoveException(Type.THROWABLE), pos, exReg, RegisterSpecList.EMPTY);
insns.set(0, insn);
insn = new ThrowingInsn(Rops.MONITOR_EXIT, pos, RegisterSpecList.make(getSynchReg()), StdTypeList.EMPTY);
insns.set(1, insn);
insns.setImmutable();
int label2 = getSpecialLabel(SYNCH_CATCH_2);
bb = new BasicBlock(getSpecialLabel(SYNCH_CATCH_1), insns, IntList.makeImmutable(label2), label2);
addBlock(bb, IntList.EMPTY);
insns = new InsnList(1);
insn = new ThrowingInsn(Rops.THROW, pos, RegisterSpecList.make(exReg), StdTypeList.EMPTY);
insns.set(0, insn);
insns.setImmutable();
bb = new BasicBlock(label2, insns, IntList.EMPTY, -1);
addBlock(bb, IntList.EMPTY);
}
use of com.android.dx.rop.code.RegisterSpec in project J2ME-Loader by nikita36078.
the class Ropper method addSetupBlocks.
/**
* Constructs and adds the blocks that perform setup for the rest of
* the method. This includes a first block which merely contains
* assignments from parameters to the same-numbered registers and
* a possible second block which deals with synchronization.
*/
private void addSetupBlocks() {
LocalVariableList localVariables = method.getLocalVariables();
SourcePosition pos = method.makeSourcePosistion(0);
Prototype desc = method.getEffectiveDescriptor();
StdTypeList params = desc.getParameterTypes();
int sz = params.size();
InsnList insns = new InsnList(sz + 1);
int at = 0;
for (int i = 0; i < sz; i++) {
Type one = params.get(i);
LocalVariableList.Item local = localVariables.pcAndIndexToLocal(0, at);
RegisterSpec result = (local == null) ? RegisterSpec.make(at, one) : RegisterSpec.makeLocalOptional(at, one, local.getLocalItem());
Insn insn = new PlainCstInsn(Rops.opMoveParam(one), pos, result, RegisterSpecList.EMPTY, CstInteger.make(at));
insns.set(i, insn);
at += one.getCategory();
}
insns.set(sz, new PlainInsn(Rops.GOTO, pos, null, RegisterSpecList.EMPTY));
insns.setImmutable();
boolean synch = isSynchronized();
int label = synch ? getSpecialLabel(SYNCH_SETUP_1) : 0;
BasicBlock bb = new BasicBlock(getSpecialLabel(PARAM_ASSIGNMENT), insns, IntList.makeImmutable(label), label);
addBlock(bb, IntList.EMPTY);
if (synch) {
RegisterSpec synchReg = getSynchReg();
Insn insn;
if (isStatic()) {
insn = new ThrowingCstInsn(Rops.CONST_OBJECT, pos, RegisterSpecList.EMPTY, StdTypeList.EMPTY, method.getDefiningClass());
insns = new InsnList(1);
insns.set(0, insn);
} else {
insns = new InsnList(2);
insn = new PlainCstInsn(Rops.MOVE_PARAM_OBJECT, pos, synchReg, RegisterSpecList.EMPTY, CstInteger.VALUE_0);
insns.set(0, insn);
insns.set(1, new PlainInsn(Rops.GOTO, pos, null, RegisterSpecList.EMPTY));
}
int label2 = getSpecialLabel(SYNCH_SETUP_2);
insns.setImmutable();
bb = new BasicBlock(label, insns, IntList.makeImmutable(label2), label2);
addBlock(bb, IntList.EMPTY);
insns = new InsnList(isStatic() ? 2 : 1);
if (isStatic()) {
insns.set(0, new PlainInsn(Rops.opMoveResultPseudo(synchReg), pos, synchReg, RegisterSpecList.EMPTY));
}
insn = new ThrowingInsn(Rops.MONITOR_ENTER, pos, RegisterSpecList.make(synchReg), StdTypeList.EMPTY);
insns.set(isStatic() ? 1 : 0, insn);
insns.setImmutable();
bb = new BasicBlock(label2, insns, IntList.makeImmutable(0), 0);
addBlock(bb, IntList.EMPTY);
}
}
use of com.android.dx.rop.code.RegisterSpec in project J2ME-Loader by nikita36078.
the class RopperMachine method getSources.
/**
* Helper for {@link #run}, which gets the list of sources for the.
* instruction.
*
* @param opcode the opcode being translated
* @param stackPointer {@code >= 0;} the stack pointer after the
* instruction's arguments have been popped
* @return {@code non-null;} the sources
*/
private RegisterSpecList getSources(int opcode, int stackPointer) {
int count = argCount();
if (count == 0) {
// We get an easy out if there aren't any sources.
return RegisterSpecList.EMPTY;
}
int localIndex = getLocalIndex();
RegisterSpecList sources;
if (localIndex >= 0) {
// The instruction is operating on a local variable.
sources = new RegisterSpecList(1);
sources.set(0, RegisterSpec.make(localIndex, arg(0)));
} else {
sources = new RegisterSpecList(count);
int regAt = stackPointer;
for (int i = 0; i < count; i++) {
RegisterSpec spec = RegisterSpec.make(regAt, arg(i));
sources.set(i, spec);
regAt += spec.getCategory();
}
switch(opcode) {
case ByteOps.IASTORE:
{
/*
* The Java argument order for array stores is
* (array, index, value), but the rop argument
* order is (value, array, index). The following
* code gets the right arguments in the right
* places.
*/
if (count != 3) {
throw new RuntimeException("shouldn't happen");
}
RegisterSpec array = sources.get(0);
RegisterSpec index = sources.get(1);
RegisterSpec value = sources.get(2);
sources.set(0, value);
sources.set(1, array);
sources.set(2, index);
break;
}
case ByteOps.PUTFIELD:
{
/*
* Similar to above: The Java argument order for
* putfield is (object, value), but the rop
* argument order is (value, object).
*/
if (count != 2) {
throw new RuntimeException("shouldn't happen");
}
RegisterSpec obj = sources.get(0);
RegisterSpec value = sources.get(1);
sources.set(0, value);
sources.set(1, obj);
break;
}
}
}
sources.setImmutable();
return sources;
}
Aggregations