/** * @param ropMethod rop-form method to convert from * @param paramWidth the total width, in register-units, of the * method's parameters * @param isStatic {@code true} if this method has no {@code this} * pointer argument */ public static SsaMethod newFromRopMethod(RopMethod ropMethod, int paramWidth, boolean isStatic) { SsaMethod result = new SsaMethod(ropMethod, paramWidth, isStatic); result.convertRopToSsaBlocks(ropMethod); return result; }
/** * @return rop label of primary successor */ public int getPrimarySuccessorRopLabel() { return parent.blockIndexToRopLabel(primarySuccessor); }
/** * Returns the list of all source uses (not results) for a register. * * @param reg register in question * @return unmodifiable instruction list */ public List<SsaInsn> getUseListForRegister(int reg) { if (unmodifiableUseList == null) { buildUseList(); } return unmodifiableUseList[reg]; }
/** * Removes all blocks containing only GOTOs from the control flow. * Although much of this work will be done later when converting * from rop to dex, not all simplification cases can be handled * there. Furthermore, any no-op block between the exit block and * blocks containing the real return or throw statements must be * removed. */ private void removeEmptyGotos() { final ArrayList<SsaBasicBlock> blocks = ssaMeth.getBlocks(); ssaMeth.forEachBlockDepthFirst(false, new SsaBasicBlock.Visitor() { @Override public void visitBlock(SsaBasicBlock b, SsaBasicBlock parent) { ArrayList<SsaInsn> insns = b.getInsns(); if ((insns.size() == 1) && (insns.get(0).getOpcode() == Rops.GOTO)) { BitSet preds = (BitSet) b.getPredecessors().clone(); for (int i = preds.nextSetBit(0); i >= 0; i = preds.nextSetBit(i + 1)) { SsaBasicBlock pb = blocks.get(i); pb.replaceSuccessor(b.getIndex(), b.getPrimarySuccessorIndex()); } } } }); }
ssaMeth.forEachBlockDepthFirstDom(new SsaBasicBlock.Visitor() { public void visitBlock (SsaBasicBlock block, SsaBasicBlock unused) { ssaMeth.setNewRegCount(nextSsaReg); ssaMeth.onInsnsChanged();
HashSet<SsaInsn> deletedInsns = new HashSet<SsaInsn>(); BitSet reachable = ssaMeth.computeReachability(); ArrayList<SsaBasicBlock> blocks = ssaMeth.getBlocks(); int blockIndex = 0; ssaMeth.deleteInsns(deletedInsns);
ssaMeth.forEachInsn(new NoSideEffectVisitor(worklist)); || isCircularNoSideEffect(regV, null)) { SsaInsn insnS = ssaMeth.getDefinitionForRegister(regV); ssaMeth.getDefinitionForRegister( source.getReg()))) { ssaMeth.deleteInsns(deletedInsns);
? meth.getExitBlock() : meth.getEntryBlock(); meth.forEachBlockDepthFirst(postdom, walker);
/** * Returns the insn that defines the given register * @param reg register in question * @return insn (actual instance from code) that defined this reg or null * if reg is not defined. */ public SsaInsn getDefinitionForRegister(int reg) { if (backMode) { throw new RuntimeException("No def list in back mode"); } if (definitionList != null) { return definitionList[reg]; } definitionList = new SsaInsn[getRegCount()]; forEachInsn(new SsaInsn.Visitor() { public void visitMoveInsn (NormalSsaInsn insn) { definitionList[insn.getResult().getReg()] = insn; } public void visitPhiInsn (PhiInsn phi) { definitionList[phi.getResult().getReg()] = phi; } public void visitNonMoveInsn (NormalSsaInsn insn) { RegisterSpec result = insn.getResult(); if (result != null) { definitionList[insn.getResult().getReg()] = insn; } } }); return definitionList[reg]; }
result.predecessors = SsaMethod.bitSetFromLabelList( ropBlocks, rmeth.labelToPredecessors(bb.getLabel())); = SsaMethod.bitSetFromLabelList(ropBlocks, bb.getSuccessors()); = SsaMethod.indexListFromLabelList(ropBlocks, bb.getSuccessors());
BitSet regsUsedAsSources = new BitSet(parent.getRegCount()); BitSet regsUsedAsResults = new BitSet(parent.getRegCount()); parent.borrowSpareRegister(result.getCategory()));
SsaInsn def = ssaMeth.getDefinitionForRegister(e); SsaInsn prev = getInsnForMove(def); List<SsaInsn> useList = ssaMeth.getUseListForRegister(e); for (SsaInsn use : useList) { ssaMeth.deleteInsns(deletedInsns); ssaMeth.onInsnsChanged();
int spareRegister = parent.borrowSpareRegister( originalResultSpec.getCategory()); parent.returnSpareRegisters();
ssaMeth.forEachBlockDepthFirstDom(new SsaBasicBlock.Visitor() { public void visitBlock (SsaBasicBlock block, SsaBasicBlock unused) {
ssaMeth.forEachBlockDepthFirstDom(new SsaBasicBlock.Visitor() { public void visitBlock (SsaBasicBlock block, SsaBasicBlock unused) { ssaMeth.setNewRegCount(nextSsaReg); ssaMeth.onInsnsChanged();
HashSet<SsaInsn> deletedInsns = new HashSet<SsaInsn>(); ssaMeth.computeReachability(); for (SsaBasicBlock block : ssaMeth.getBlocks()) { if (block.isReachable()) continue; ssaMeth.deleteInsns(deletedInsns);
ssaMeth.forEachInsn(new NoSideEffectVisitor(worklist)); || isCircularNoSideEffect(regV, null)) { SsaInsn insnS = ssaMeth.getDefinitionForRegister(regV); ssaMeth.getDefinitionForRegister( source.getReg()))) { ssaMeth.deleteInsns(deletedInsns);
? meth.getExitBlock() : meth.getEntryBlock(); meth.forEachBlockDepthFirst(postdom, walker);
/** * Removes all blocks containing only GOTOs from the control flow. * Although much of this work will be done later when converting * from rop to dex, not all simplification cases can be handled * there. Furthermore, any no-op block between the exit block and * blocks containing the real return or throw statements must be * removed. */ private void removeEmptyGotos() { final ArrayList<SsaBasicBlock> blocks = ssaMeth.getBlocks(); ssaMeth.forEachBlockDepthFirst(false, new SsaBasicBlock.Visitor() { public void visitBlock(SsaBasicBlock b, SsaBasicBlock parent) { ArrayList<SsaInsn> insns = b.getInsns(); if ((insns.size() == 1) && (insns.get(0).getOpcode() == Rops.GOTO)) { BitSet preds = (BitSet) b.getPredecessors().clone(); for (int i = preds.nextSetBit(0); i >= 0; i = preds.nextSetBit(i + 1)) { SsaBasicBlock pb = blocks.get(i); pb.replaceSuccessor(b.getIndex(), b.getPrimarySuccessorIndex()); } } } }); }
/** * Returns the insn that defines the given register * @param reg register in question * @return insn (actual instance from code) that defined this reg or null * if reg is not defined. */ public SsaInsn getDefinitionForRegister(int reg) { if (backMode) { throw new RuntimeException("No def list in back mode"); } if (definitionList != null) { return definitionList[reg]; } definitionList = new SsaInsn[getRegCount()]; forEachInsn(new SsaInsn.Visitor() { public void visitMoveInsn (NormalSsaInsn insn) { definitionList[insn.getResult().getReg()] = insn; } public void visitPhiInsn (PhiInsn phi) { definitionList[phi.getResult().getReg()] = phi; } public void visitNonMoveInsn (NormalSsaInsn insn) { RegisterSpec result = insn.getResult(); if (result != null) { definitionList[insn.getResult().getReg()] = insn; } } }); return definitionList[reg]; }