@Override public void visit(BinaryBranchingInstruction insn) { int a = insn.getFirstOperand().getIndex(); int b = insn.getSecondOperand().getIndex(); BasicBlock consequent = insn.getConsequent(); BasicBlock alternative = insn.getAlternative(); switch (insn.getCondition()) { case EQUAL: branch( withLocation(Expr.binary(BinaryOperation.EQUALS, Expr.var(a), Expr.var(b))), consequent, alternative); break; case REFERENCE_EQUAL: branch( withLocation(Expr.binary(BinaryOperation.STRICT_EQUALS, Expr.var(a), Expr.var(b))), consequent, alternative); break; case NOT_EQUAL: branch( withLocation(Expr.binary(BinaryOperation.NOT_EQUALS, Expr.var(a), Expr.var(b))), consequent, alternative); break; case REFERENCE_NOT_EQUAL: branch( withLocation(Expr.binary(BinaryOperation.STRICT_NOT_EQUALS, Expr.var(a), Expr.var(b))), consequent, alternative); break; } }
@Override public void visit(BranchingInstruction insn) { switch (insn.getCondition()) { case EQUAL: branch( compare(BinaryOperation.EQUALS, insn.getOperand()), insn.getConsequent(), insn.getAlternative()); break; case NOT_EQUAL: branch( compare(BinaryOperation.NOT_EQUALS, insn.getOperand()), insn.getConsequent(), insn.getAlternative()); break; case GREATER: branch( compare(BinaryOperation.GREATER, insn.getOperand()), insn.getConsequent(), insn.getAlternative()); break; case GREATER_OR_EQUAL: branch( compare(BinaryOperation.GREATER_OR_EQUALS, insn.getOperand()), insn.getConsequent(), insn.getAlternative()); break; case LESS: branch( compare(BinaryOperation.LESS, insn.getOperand()), insn.getConsequent(), insn.getAlternative()); break; case LESS_OR_EQUAL: branch( compare(BinaryOperation.LESS_OR_EQUALS, insn.getOperand()), insn.getConsequent(), insn.getAlternative()); break; case NOT_NULL: branch( Expr.binary( BinaryOperation.STRICT_NOT_EQUALS, Expr.var(insn.getOperand().getIndex()), Expr.constant(null)), insn.getConsequent(), insn.getAlternative()); break; case NULL: branch( Expr.binary( BinaryOperation.STRICT_EQUALS, Expr.var(insn.getOperand().getIndex()), Expr.constant(null)), insn.getConsequent(), insn.getAlternative()); break; } }
@Override public void visit(WhileStatement statement) { if (statement.getBody().size() == 1 && statement.getBody().get(0) instanceof WhileStatement) { WhileStatement innerLoop = (WhileStatement) statement.getBody().get(0); BreakToContinueReplacer replacer = new BreakToContinueReplacer(innerLoop, statement); replacer.visitSequence(innerLoop.getBody()); statement.getBody().clear(); statement.getBody().addAll(innerLoop.getBody()); } List<Statement> statements = processSequence(statement.getBody()); for (int i = 0; i < statements.size(); ++i) { if (statements.get(i) instanceof ContinueStatement) { ContinueStatement continueStmt = (ContinueStatement) statements.get(i); if (continueStmt.getTarget() == statement) { statements.subList(i, statements.size()).clear(); break; } } } statement.getBody().clear(); statement.getBody().addAll(statements); if (statement.getCondition() != null) { List<Statement> sequenceBackup = resultSequence; resultSequence = new ArrayList<>(); statement.getCondition().acceptVisitor(this); statement.setCondition(resultExpr); resultSequence = sequenceBackup; } while (true) { if (!statement.getBody().isEmpty() && statement.getBody().get(0) instanceof ConditionalStatement) { ConditionalStatement cond = (ConditionalStatement) statement.getBody().get(0); if (cond.getConsequent().size() == 1 && cond.getConsequent().get(0) instanceof BreakStatement) { BreakStatement breakStmt = (BreakStatement) cond.getConsequent().get(0); if (breakStmt.getTarget() == statement) { statement.getBody().remove(0); if (statement.getCondition() != null) { Expr newCondition = Expr.binary( BinaryOperation.AND, statement.getCondition(), ExprOptimizer.invert(cond.getCondition())); newCondition.setLocation(statement.getCondition().getLocation()); statement.setCondition(newCondition); } else { statement.setCondition(ExprOptimizer.invert(cond.getCondition())); } continue; } } } break; } resultStmt = statement; }
private void eliminateRedundantBreaks(List<Statement> statements, IdentifiedStatement exit) { if (statements.isEmpty()) { return; } Statement last = statements.get(statements.size() - 1); if (last instanceof BreakStatement && exit != null) { IdentifiedStatement target = ((BreakStatement) last).getTarget(); if (exit == target) { statements.remove(statements.size() - 1); } } if (statements.isEmpty()) { return; } for (int i = 0; i < statements.size(); ++i) { Statement stmt = statements.get(i); if (stmt instanceof ConditionalStatement) { ConditionalStatement cond = (ConditionalStatement) stmt; check_conditional: { last = cond.getConsequent().isEmpty() ? null : cond.getConsequent().get(cond.getConsequent().size() - 1); if (last instanceof BreakStatement) { BreakStatement breakStmt = (BreakStatement) last; if (exit != null && exit == breakStmt.getTarget()) { cond.getConsequent().remove(cond.getConsequent().size() - 1); List<Statement> remaining = statements.subList(i + 1, statements.size()); cond.getAlternative().addAll(remaining); remaining.clear(); break check_conditional; } } last = cond.getAlternative().isEmpty() ? null : cond.getAlternative().get(cond.getAlternative().size() - 1); if (last instanceof BreakStatement) { BreakStatement breakStmt = (BreakStatement) last; if (exit != null && exit == breakStmt.getTarget()) { cond.getAlternative().remove(cond.getAlternative().size() - 1); List<Statement> remaining = statements.subList(i + 1, statements.size()); cond.getConsequent().addAll(remaining); remaining.clear(); } } } if (i == statements.size() - 1) { eliminateRedundantBreaks(cond.getConsequent(), exit); eliminateRedundantBreaks(cond.getAlternative(), exit); } normalizeConditional(cond); if (cond.getConsequent().size() == 1 && cond.getConsequent().get(0) instanceof ConditionalStatement) { ConditionalStatement innerCond = (ConditionalStatement) cond.getConsequent().get(0); if (innerCond.getAlternative().isEmpty()) { if (cond.getAlternative().isEmpty()) { cond.getConsequent().clear(); cond.getConsequent().addAll(innerCond.getConsequent()); cond.setCondition( Expr.binary( BinaryOperation.AND, cond.getCondition(), innerCond.getCondition(), cond.getCondition().getLocation())); --i; } else if (cond.getAlternative().size() != 1 || !(cond.getAlternative().get(0) instanceof ConditionalStatement)) { cond.setCondition(ExprOptimizer.invert(cond.getCondition())); cond.getConsequent().clear(); cond.getConsequent().addAll(cond.getAlternative()); cond.getAlternative().clear(); cond.getAlternative().add(innerCond); --i; } } } } else if (stmt instanceof BlockStatement) { BlockStatement nestedBlock = (BlockStatement) stmt; eliminateRedundantBreaks(nestedBlock.getBody(), nestedBlock); } else if (stmt instanceof WhileStatement) { WhileStatement whileStmt = (WhileStatement) stmt; eliminateRedundantBreaks(whileStmt.getBody(), null); } else if (stmt instanceof SwitchStatement) { SwitchStatement switchStmt = (SwitchStatement) stmt; for (SwitchClause clause : switchStmt.getClauses()) { eliminateRedundantBreaks(clause.getBody(), null); } eliminateRedundantBreaks(switchStmt.getDefaultClause(), null); } } }
private Expr compare(BinaryOperation op, Variable value) { Expr expr = Expr.binary(op, Expr.var(value.getIndex()), Expr.constant(0)); expr.setLocation(currentLocation); return expr; }
private void intBinary(int first, int second, Variable result, BinaryOperation op) { assign(castToInteger(Expr.binary(op, Expr.var(first), Expr.var(second))), result); }
private Expr castToInteger(Expr value) { return Expr.binary(BinaryOperation.BITWISE_OR, value, Expr.constant(0)); }