public OutlinedStatementReductionOpportunity(ExprStmt stmt, FunctionDefinition outlined, VisitationDepth depth) { super(depth); assert stmt.getExpr() instanceof BinaryExpr; assert outlined.getBody().getNumStmts() == 1; assert outlined.getBody().getStmt(0) instanceof ReturnStmt; this.stmt = stmt; this.outlined = outlined; }
private void doRemoveReturns() throws CannotRemoveReturnsException { if (!containsReturn(fd.getBody())) { // No return to remove return; } if (numReturnStmts(fd.getBody()) == 1 && fd.getBody() .getStmt(fd.getBody().getNumStmts() - 1) instanceof ReturnStmt) { // Only one return at end -- removing it doesn't simplify things return; } if (containsSwitch(fd)) { throw new CannotRemoveReturnsException("Switch statements not yet supported."); } addReturnInstrumentation(); replaceReturnStatements(); addSpecialDeclarations(); }
@Override public void visitFunctionDefinition(FunctionDefinition functionDefinition) { visitChildFromParent(this::visitFunctionPrototype, functionDefinition.getPrototype(), functionDefinition); visitChildFromParent(this::visitBlockStmt, functionDefinition.getBody(), functionDefinition); }
@Override public void visitFunctionDefinition(FunctionDefinition functionDefinition) { assert enclosingFunction == null; enclosingFunction = functionDefinition; pushScope(); addEncounteredParametersToScope = true; visitFunctionPrototype(functionDefinition.getPrototype()); addEncounteredParametersToScope = false; visit(functionDefinition.getBody()); popScope(); enclosingFunction = null; }
private void addGlobalInitializers(FunctionDefinition mainFunction) { assert mainFunction.getPrototype().getName().equals("main"); for (int i = globalsToBeReInitialized.size() - 1; i >= 0; i--) { for (int j = globalsToBeReInitialized.get(i).getNumDecls() - 1; j >= 0; j--) { final VariableDeclInfo vdi = globalsToBeReInitialized.get(i).getDeclInfo(j); if (!(vdi.getInitializer() instanceof ScalarInitializer)) { throw new RuntimeException("Only know how to deal with scalar initializers at present."); } mainFunction.getBody().insertStmt(0, new ExprStmt(new BinaryExpr(new VariableIdentifierExpr(vdi.getName()), ((ScalarInitializer) vdi.getInitializer()).getExpr(), BinOp.ASSIGN))); vdi.setInitializer(null); } } }
private void addSpecialDeclarations() { if (fd.getPrototype().getReturnType().getWithoutQualifiers() != VoidType.VOID) { fd.getBody().insertStmt(0, new DeclarationStmt( new VariablesDeclaration(fd.getPrototype().getReturnType().getWithoutQualifiers(), new VariableDeclInfo(makeReturnValueName(), null, null)))); fd.getBody().addStmt(new ReturnStmt(makeReturnValue())); } fd.getBody().insertStmt(0, new DeclarationStmt( new VariablesDeclaration(BasicType.BOOL, new VariableDeclInfo(makeHasReturnedName(), null, new ScalarInitializer(BoolConstantExpr.FALSE))))); }
@Override public void applyReductionImpl() { final BinaryExpr assignment = (BinaryExpr) stmt.getExpr(); final Expr expr = ((ReturnStmt) outlined.getBody().getStmt(0)).getExpr().clone(); Map<String, Expr> paramReplacement = new HashMap<>(); for (int i = 0; i < outlined.getPrototype().getNumParameters(); i++) { Expr actualParam = ((FunctionCallExpr) assignment.getRhs()).getArg(i); assert actualParam != null; paramReplacement.put(outlined.getPrototype().getParameter(i).getName(), actualParam); } assert assignment.getOp() == BinOp.ASSIGN; stmt.setExpr(new BinaryExpr(assignment.getLhs(), applySubstitutionDestructive(expr, paramReplacement), BinOp.ASSIGN)); }
private List<Stmt> getInlinedStmts(FunctionDefinition functionDefinition, Optional<String> returnVariableName) { final List<Stmt> inlinedStmts = new ArrayList<>(); for (int i = 0; i < functionDefinition.getPrototype().getNumParameters(); i++) { ParameterDecl pd = functionDefinition.getPrototype().getParameter(i); inlinedStmts.add(new DeclarationStmt( new VariablesDeclaration( pd.getType().getWithoutQualifiers(), new VariableDeclInfo(pd.getName(), null, new ScalarInitializer(call.getArg(i).clone()))))); } for (Stmt stmt : functionDefinition.getBody().getStmts()) { if (stmt instanceof ReturnStmt) { if (((ReturnStmt) stmt).hasExpr()) { inlinedStmts.add(new ExprStmt( new BinaryExpr( new VariableIdentifierExpr(returnVariableName.get()), (((ReturnStmt) stmt).getExpr()), BinOp.ASSIGN))); } } else { inlinedStmts.add(stmt); } } return inlinedStmts; }