use of soot.toDex.instructions.Insn in project soot by Sable.
the class RegisterAssigner method renumParamRegsToHigh.
private void renumParamRegsToHigh(List<Insn> insns, List<LocalRegisterAssignmentInformation> parameterInstructionsList) {
int regCount = regAlloc.getRegCount();
int paramRegCount = regAlloc.getParamRegCount();
if (paramRegCount == 0 || paramRegCount == regCount) {
// no params or no locals -> nothing to do
return;
}
for (Insn insn : insns) {
for (Register r : insn.getRegs()) {
renumParamRegToHigh(r, regCount, paramRegCount);
}
}
for (LocalRegisterAssignmentInformation parameter : parameterInstructionsList) {
renumParamRegToHigh(parameter.getRegister(), regCount, paramRegCount);
}
}
use of soot.toDex.instructions.Insn in project soot by Sable.
the class RegisterAssigner method reserveRegisters.
/**
* Reserves low registers in case we later find an instruction that has
* short operands. We can then move the real operands into the reserved low
* ones and use those instead.
*
* @param insns
* @param insnsStmtMap
* @param parameterInstructionsList
*/
private void reserveRegisters(List<Insn> insns, Map<Insn, Stmt> insnsStmtMap, List<LocalRegisterAssignmentInformation> parameterInstructionsList) {
// reserve registers as long as new ones are needed
int reservedRegs = 0;
while (true) {
int regsNeeded = getRegsNeeded(reservedRegs, insns, insnsStmtMap);
int regsToReserve = regsNeeded - reservedRegs;
if (regsToReserve <= 0) {
break;
}
regAlloc.increaseRegCount(regsToReserve);
// "reservation": shift the old regs to higher numbers
for (Insn insn : insns) {
shiftRegs(insn, regsToReserve);
}
for (LocalRegisterAssignmentInformation info : parameterInstructionsList) {
Register r = info.getRegister();
r.setNumber(r.getNumber() + regsToReserve);
}
reservedRegs += regsToReserve;
}
}
use of soot.toDex.instructions.Insn in project soot by Sable.
the class RegisterAssigner method getRegsNeeded.
/**
* Gets the maximum number of registers needed by a single instruction in
* the given list of instructions.
*
* @param regsAlreadyReserved
* @param insns
* @param insnsStmtMap
* @return
*/
private int getRegsNeeded(int regsAlreadyReserved, List<Insn> insns, Map<Insn, Stmt> insnsStmtMap) {
// we only need regs that weren't
int regsNeeded = regsAlreadyReserved;
// reserved yet
for (int i = 0; i < insns.size(); i++) {
Insn insn = insns.get(i);
if (insn instanceof AddressInsn) {
// needs no regs/fitting
continue;
}
// first try to find a better opcode
Insn fittingInsn = findFittingInsn(insn);
if (fittingInsn != null) {
// use the fitting instruction and continue with next one
insns.set(i, fittingInsn);
insnsStmtMap.put(fittingInsn, insnsStmtMap.get(insn));
insnsStmtMap.remove(insn);
continue;
}
// no fitting instruction -> save if we need more registers
int newRegsNeeded = insn.getMinimumRegsNeeded();
if (newRegsNeeded > regsNeeded) {
regsNeeded = newRegsNeeded;
}
}
return regsNeeded;
}
use of soot.toDex.instructions.Insn in project soot by Sable.
the class StmtVisitor method reduceInstructions.
/**
* Reduces the instruction list by removing unnecessary instruction pairs
* such as move v0 v1; move v1 v0;
* @param trapReferences
*/
private void reduceInstructions(Set<Unit> trapReferences) {
for (int i = 0; i < this.insns.size() - 1; i++) {
Insn curInsn = this.insns.get(i);
// Only consider real instructions
if (curInsn instanceof AddressInsn)
continue;
if (!isReducableMoveInstruction(curInsn.getOpcode()))
continue;
// Skip over following address instructions
Insn nextInsn = null;
int nextIndex = -1;
for (int j = i + 1; j < this.insns.size(); j++) {
Insn candidate = this.insns.get(j);
if (candidate instanceof AddressInsn)
continue;
nextInsn = candidate;
nextIndex = j;
break;
}
if (nextInsn == null || !isReducableMoveInstruction(nextInsn.getOpcode()))
continue;
// jump targets to the successor
if (nextIndex == this.insns.size() - 1)
continue;
// Check if we have a <- b; b <- a;
Register firstTarget = curInsn.getRegs().get(0);
Register firstSource = curInsn.getRegs().get(1);
Register secondTarget = nextInsn.getRegs().get(0);
Register secondSource = nextInsn.getRegs().get(1);
if (firstTarget.equals(secondSource) && secondTarget.equals(firstSource)) {
Stmt nextStmt = insnStmtMap.get(nextInsn);
// instructions may depend on the register being set.
if (nextStmt == null || (!isJumpTarget(nextStmt) && !trapReferences.contains(nextStmt))) {
insns.remove(nextIndex);
if (nextStmt != null) {
Insn nextInst = this.insns.get(nextIndex + 1);
insnStmtMap.remove(nextInsn);
insnStmtMap.put(nextInst, nextStmt);
}
}
}
}
}
use of soot.toDex.instructions.Insn in project soot by Sable.
the class StmtVisitor method caseAssignStmt.
@Override
public void caseAssignStmt(AssignStmt stmt) {
// If this is the beginning of an array initialization, we shortcut the
// normal translation process
List<Value> arrayValues = arrayInitDetector.getValuesForArrayInit(stmt);
if (arrayValues != null) {
Insn insn = buildArrayFillInsn((ArrayRef) stmt.getLeftOp(), arrayValues);
if (insn != null) {
addInsn(insn, stmt);
return;
}
}
if (arrayInitDetector.getIgnoreUnits().contains(stmt)) {
return;
}
constantV.setOrigStmt(stmt);
exprV.setOrigStmt(stmt);
Value lhs = stmt.getLeftOp();
if (lhs instanceof ConcreteRef) {
// special cases that lead to *put* opcodes
Value source = stmt.getRightOp();
addInsn(buildPutInsn((ConcreteRef) lhs, source), stmt);
return;
}
// other cases, where lhs is a local
if (!(lhs instanceof Local)) {
throw new Error("left-hand side of AssignStmt is not a Local: " + lhs.getClass());
}
Local lhsLocal = (Local) lhs;
final Insn newInsn;
Register lhsReg = regAlloc.asLocal(lhsLocal);
Value rhs = stmt.getRightOp();
if (rhs instanceof Local) {
// move rhs local to lhs local, if different
Local rhsLocal = (Local) rhs;
if (lhsLocal == rhsLocal) {
return;
}
Register sourceReg = regAlloc.asLocal(rhsLocal);
newInsn = buildMoveInsn(lhsReg, sourceReg);
addInsn(newInsn, stmt);
} else if (rhs instanceof Constant) {
// move rhs constant into the lhs local
constantV.setDestination(lhsReg);
rhs.apply(constantV);
newInsn = insns.get(insns.size() - 1);
} else if (rhs instanceof ConcreteRef) {
newInsn = buildGetInsn((ConcreteRef) rhs, lhsReg);
addInsn(newInsn, stmt);
} else {
// evaluate rhs expression, saving the result in the lhs local
exprV.setDestinationReg(lhsReg);
rhs.apply(exprV);
if (rhs instanceof InvokeExpr) {
// do the actual "assignment" for an invocation: move its result
// to the lhs reg (it was not used yet)
Insn moveResultInsn = buildMoveResultInsn(lhsReg);
int invokeInsnIndex = exprV.getLastInvokeInstructionPosition();
insns.add(invokeInsnIndex + 1, moveResultInsn);
}
newInsn = insns.get(insns.size() - 1);
}
this.insnRegisterMap.put(newInsn, LocalRegisterAssignmentInformation.v(lhsReg, lhsLocal));
}
Aggregations