private void insertCopy(TryCatchJoint joint) { Set<Variable> variableSet = new HashSet<>(joint.getSourceVariables()); BasicBlock block = joint.getSource(); DefinitionExtractor defExtractor = new DefinitionExtractor(); for (int i = block.getInstructions().size() - 1; i >= 0; --i) { Instruction insn = block.getInstructions().get(i); insn.acceptVisitor(defExtractor); for (Variable definedVar : defExtractor.getDefinedVariables()) { if (variableSet.remove(definedVar)) { AssignInstruction copyInsn = new AssignInstruction(); copyInsn.setReceiver(joint.getReceiver()); copyInsn.setAssignee(definedVar); block.getInstructions().add(i, copyInsn); } } } for (Variable enteringVar : variableSet) { AssignInstruction copyInsn = new AssignInstruction(); copyInsn.setReceiver(joint.getReceiver()); copyInsn.setAssignee(enteringVar); block.getInstructions().add(0, copyInsn); } }
private void removeRedundantCopies( Program program, List<MutableGraphNode> interferenceGraph, DisjointSet congruenceClasses) { for (int i = 0; i < program.basicBlockCount(); ++i) { BasicBlock block = program.basicBlockAt(i); for (int j = 0; j < block.getInstructions().size(); ++j) { Instruction insn = block.getInstructions().get(j); if (!(insn instanceof AssignInstruction)) { continue; } AssignInstruction assignment = (AssignInstruction) insn; boolean interfere = false; int copyClass = congruenceClasses.find(assignment.getReceiver().getIndex()); int origClass = congruenceClasses.find(assignment.getAssignee().getIndex()); for (MutableGraphEdge edge : interferenceGraph.get(origClass).getEdges()) { if (edge.getFirst() == edge.getSecond()) { continue; } int neighbour = congruenceClasses.find(edge.getSecond().getTag()); if (neighbour == copyClass || neighbour == origClass) { interfere = true; break; } } if (!interfere) { int newClass = congruenceClasses.union(copyClass, origClass); block.getInstructions().set(j, new EmptyInstruction()); if (newClass == interferenceGraph.size()) { MutableGraphNode newNode = new MutableGraphNode(interferenceGraph.size()); interferenceGraph.add(newNode); } for (MutableGraphEdge edge : interferenceGraph.get(origClass).getEdges().toArray(new MutableGraphEdge[0])) { if (edge.getFirst() == interferenceGraph.get(origClass)) { edge.setFirst(interferenceGraph.get(newClass)); } if (edge.getSecond() == interferenceGraph.get(origClass)) { edge.setSecond(interferenceGraph.get(newClass)); } } for (MutableGraphEdge edge : interferenceGraph.get(copyClass).getEdges().toArray(new MutableGraphEdge[0])) { if (edge.getFirst() == interferenceGraph.get(copyClass)) { edge.setFirst(interferenceGraph.get(newClass)); } if (edge.getSecond() == interferenceGraph.get(copyClass)) { edge.setSecond(interferenceGraph.get(newClass)); } } interferenceGraph.set(copyClass, interferenceGraph.get(newClass)); interferenceGraph.set(origClass, interferenceGraph.get(newClass)); } } } }
private DisjointSet buildPhiCongruenceClasses(Program program) { DisjointSet classes = new DisjointSet(); for (int i = 0; i < program.variableCount(); ++i) { classes.create(); } for (int i = 0; i < program.basicBlockCount(); ++i) { BasicBlock block = program.basicBlockAt(i); for (Phi phi : block.getPhis()) { for (Incoming incoming : phi.getIncomings()) { classes.union(phi.getReceiver().getIndex(), incoming.getValue().getIndex()); } } for (TryCatchJoint joint : block.getTryCatchJoints()) { for (Variable sourceVar : joint.getSourceVariables()) { classes.union(sourceVar.getIndex(), joint.getReceiver().getIndex()); } } } return classes; }
Statement generateJumpStatement(BasicBlock target) { if (nextBlock == target && blockMap[target.getIndex()] == null) { return null; } Decompiler.Block block = blockMap[target.getIndex()]; if (block == null) { throw new IllegalStateException("Could not find block for basic block $" + target.getIndex()); } if (target.getIndex() == indexer.nodeAt(block.end)) { BreakStatement breakStmt = new BreakStatement(); breakStmt.setLocation(currentLocation); breakStmt.setTarget(block.statement); return breakStmt; } else { ContinueStatement contStmt = new ContinueStatement(); contStmt.setLocation(currentLocation); contStmt.setTarget(block.statement); return contStmt; } }
private void insertCopy(Incoming incoming, Map<BasicBlock, BasicBlock> blockMap) { final Phi phi = incoming.getPhi(); Program program = phi.getBasicBlock().getProgram(); AssignInstruction copyInstruction = new AssignInstruction(); Variable firstCopy = program.createVariable(); copyInstruction.setReceiver(firstCopy); copyInstruction.setAssignee(incoming.getValue()); BasicBlock source = blockMap.get(incoming.getSource()); if (source == null) { source = incoming.getSource(); } else { incoming.setSource(source); } if (!(incoming.getSource().getLastInstruction() instanceof JumpInstruction)) { final BasicBlock copyBlock = program.createBasicBlock(); JumpInstruction jumpInstruction = new JumpInstruction(); jumpInstruction.setTarget(phi.getBasicBlock()); copyBlock.getInstructions().add(jumpInstruction); incoming .getSource() .getLastInstruction() .acceptVisitor( new BasicBlockMapper( block -> block == phi.getBasicBlock().getIndex() ? copyBlock.getIndex() : block)); blockMap.put(source, copyBlock); incoming.setSource(copyBlock); source = copyBlock; } source.getInstructions().add(source.getInstructions().size() - 1, copyInstruction); incoming.setValue(copyInstruction.getReceiver()); }
private void transformBasicBlock(BasicBlock block) { List<Instruction> instructions = block.getInstructions(); for (int i = 0; i < instructions.size(); ++i) { Instruction insn = instructions.get(i); if (insn instanceof InvokeInstruction) { InvokeInstruction invoke = (InvokeInstruction) insn; List<Instruction> replacement = transformInvoke(invoke); if (replacement != null) { instructions.set(i, new EmptyInstruction()); instructions.addAll(i, replacement); i += replacement.size(); } } } }
private void insertJointArgumentsCopies(Program program) { for (int i = 0; i < program.basicBlockCount(); ++i) { BasicBlock block = program.basicBlockAt(i); block.getTryCatchJoints().forEach(this::insertCopy); } }