use of com.android.dx.rop.code.RegisterSpec in project buck by facebook.
the class OutputFinisher method hasLocalInfo.
/**
* Helper for {@link #add} which scrutinizes a single
* instruction for local variable information.
*
* @param insn {@code non-null;} instruction to scrutinize
* @return {@code true} iff the instruction refers to any
* named locals
*/
private static boolean hasLocalInfo(DalvInsn insn) {
if (insn instanceof LocalSnapshot) {
RegisterSpecSet specs = ((LocalSnapshot) insn).getLocals();
int size = specs.size();
for (int i = 0; i < size; i++) {
if (hasLocalInfo(specs.get(i))) {
return true;
}
}
} else if (insn instanceof LocalStart) {
RegisterSpec spec = ((LocalStart) insn).getLocal();
if (hasLocalInfo(spec)) {
return true;
}
}
return false;
}
use of com.android.dx.rop.code.RegisterSpec in project buck by facebook.
the class OutputFinisher method align64bits.
private void align64bits(Dop[] opcodes) {
while (true) {
int notAligned64bitRegAccess = 0;
int aligned64bitRegAccess = 0;
int notAligned64bitParamAccess = 0;
int aligned64bitParamAccess = 0;
int lastParameter = unreservedRegCount + reservedCount + reservedParameterCount;
int firstParameter = lastParameter - paramSize;
// Collects the number of time that 64-bit registers are accessed aligned or not.
for (DalvInsn insn : insns) {
RegisterSpecList regs = insn.getRegisters();
for (int usedRegIdx = 0; usedRegIdx < regs.size(); usedRegIdx++) {
RegisterSpec reg = regs.get(usedRegIdx);
if (reg.isCategory2()) {
boolean isParameter = reg.getReg() >= firstParameter;
if (reg.isEvenRegister()) {
if (isParameter) {
aligned64bitParamAccess++;
} else {
aligned64bitRegAccess++;
}
} else {
if (isParameter) {
notAligned64bitParamAccess++;
} else {
notAligned64bitRegAccess++;
}
}
}
}
}
if (notAligned64bitParamAccess > aligned64bitParamAccess && notAligned64bitRegAccess > aligned64bitRegAccess) {
addReservedRegisters(1);
} else if (notAligned64bitParamAccess > aligned64bitParamAccess) {
addReservedParameters(1);
} else if (notAligned64bitRegAccess > aligned64bitRegAccess) {
addReservedRegisters(1);
// so the number of aligned become the number of unaligned.
if (paramSize != 0 && aligned64bitParamAccess > notAligned64bitParamAccess) {
addReservedParameters(1);
}
} else {
break;
}
if (!reserveRegisters(opcodes)) {
break;
}
}
}
use of com.android.dx.rop.code.RegisterSpec in project buck by facebook.
the class Form21c method isCompatible.
/** {@inheritDoc} */
@Override
public boolean isCompatible(DalvInsn insn) {
if (!(insn instanceof CstInsn)) {
return false;
}
RegisterSpecList regs = insn.getRegisters();
RegisterSpec reg;
switch(regs.size()) {
case 1:
{
reg = regs.get(0);
break;
}
case 2:
{
/*
* This format is allowed for ops that are effectively
* 2-arg but where the two args are identical.
*/
reg = regs.get(0);
if (reg.getReg() != regs.get(1).getReg()) {
return false;
}
break;
}
default:
{
return false;
}
}
if (!unsignedFitsInByte(reg.getReg())) {
return false;
}
CstInsn ci = (CstInsn) insn;
int cpi = ci.getIndex();
Constant cst = ci.getConstant();
if (!unsignedFitsInShort(cpi)) {
return false;
}
return (cst instanceof CstType) || (cst instanceof CstFieldRef) || (cst instanceof CstString);
}
use of com.android.dx.rop.code.RegisterSpec in project buck by facebook.
the class Form31c method isCompatible.
/** {@inheritDoc} */
@Override
public boolean isCompatible(DalvInsn insn) {
if (!(insn instanceof CstInsn)) {
return false;
}
RegisterSpecList regs = insn.getRegisters();
RegisterSpec reg;
switch(regs.size()) {
case 1:
{
reg = regs.get(0);
break;
}
case 2:
{
/*
* This format is allowed for ops that are effectively
* 2-arg but where the two args are identical.
*/
reg = regs.get(0);
if (reg.getReg() != regs.get(1).getReg()) {
return false;
}
break;
}
default:
{
return false;
}
}
if (!unsignedFitsInByte(reg.getReg())) {
return false;
}
CstInsn ci = (CstInsn) insn;
Constant cst = ci.getConstant();
return (cst instanceof CstType) || (cst instanceof CstFieldRef) || (cst instanceof CstString);
}
use of com.android.dx.rop.code.RegisterSpec in project buck by facebook.
the class Ropper method addReturnBlock.
/**
* Constructs and adds the return block, if necessary. The return
* block merely contains an appropriate {@code return}
* instruction.
*/
private void addReturnBlock() {
Rop returnOp = machine.getReturnOp();
if (returnOp == null) {
/*
* The method being converted never returns normally, so there's
* no need for a return block.
*/
return;
}
SourcePosition returnPos = machine.getReturnPosition();
int label = getSpecialLabel(RETURN);
if (isSynchronized()) {
InsnList insns = new InsnList(1);
Insn insn = new ThrowingInsn(Rops.MONITOR_EXIT, returnPos, RegisterSpecList.make(getSynchReg()), StdTypeList.EMPTY);
insns.set(0, insn);
insns.setImmutable();
int nextLabel = getSpecialLabel(SYNCH_RETURN);
BasicBlock bb = new BasicBlock(label, insns, IntList.makeImmutable(nextLabel), nextLabel);
addBlock(bb, IntList.EMPTY);
label = nextLabel;
}
InsnList insns = new InsnList(1);
TypeList sourceTypes = returnOp.getSources();
RegisterSpecList sources;
if (sourceTypes.size() == 0) {
sources = RegisterSpecList.EMPTY;
} else {
RegisterSpec source = RegisterSpec.make(0, sourceTypes.getType(0));
sources = RegisterSpecList.make(source);
}
Insn insn = new PlainInsn(returnOp, returnPos, null, sources);
insns.set(0, insn);
insns.setImmutable();
BasicBlock bb = new BasicBlock(label, insns, IntList.EMPTY, -1);
addBlock(bb, IntList.EMPTY);
}
Aggregations