@SuppressWarnings("unchecked") public void transformProcedure(Procedure proc) { List<ReturnStatement> ret_stmts = (new DFIterator<ReturnStatement>(proc, ReturnStatement.class)).getList(); CompoundStatement body = proc.getBody(); List ret_type = proc.getReturnType(); // Remove scope qualifiers not necessary in type resolution while (ret_type.remove(Specifier.INLINE)) ; while (ret_type.remove(Specifier.STATIC)) ; while (ret_type.remove(Specifier.EXTERN)) ; boolean ret_type_void = (ret_type.contains(Specifier.VOID) && ret_type.size() == 1); Identifier ret_id = null; // add a variable _ret_val of the same type as the procedure return type if (!ret_type_void) { // check for implicit int (TODO - differentiate this from constructors) if (ret_type.isEmpty()) { ret_type.add(Specifier.INT); } ret_id = SymbolTools.getTemp(body, ret_type, "_ret_val"); } // add a labeled return statement to the end of the procedure String done_label = "_done"; body.addStatement(new Label(new NameID(done_label))); if (!ret_type_void) { body.addStatement(new ReturnStatement(ret_id.clone())); } else { body.addStatement(new ReturnStatement()); } // redirect the preexisting return statements to the labeled return for (ReturnStatement ret_stmt : ret_stmts) { // Identify the parent compound statement. CompoundStatement comp_stmt = IRTools.getAncestorOfType(ret_stmt, CompoundStatement.class); // Add goto statement. Statement goto_stmt = new GotoStatement(new NameID(done_label)); comp_stmt.addStatementAfter(ret_stmt, goto_stmt); // Add temporary assignments. if (!ret_type_void) { Statement new_stmt = new ExpressionStatement( new AssignmentExpression( ret_id.clone(), AssignmentOperator.NORMAL, ret_stmt.getExpression().clone())); comp_stmt.addStatementBefore(goto_stmt, new_stmt); } // Remove the original return statement. comp_stmt.removeStatement(ret_stmt); // Add comments. /* CommentAnnotation info = new CommentAnnotation("Normalized Return: " + ret_stmt); info.setOneLiner(true); goto_stmt.annotateBefore(info); */ } }
/** * Returns the string dump of this call site. * * @return string dump. */ public String toString() { StringBuilder sb = new StringBuilder(80); sb.append(id).append(" ").append(caller.getName()).append("-->"); sb.append(fcall.getName()); if (PrintTools.getVerbosity() >= 3) { sb.append(" (").append(System.identityHashCode(fcall)).append(")"); } if (callee == null) { sb.append(" <lib>"); } else if (temp_assignments != null) { // normalized arguments String args = temp_assignments.toString().replaceAll("\n", " "); sb.append(" ").append(args); } if (PrintTools.getVerbosity() >= 3) { sb.append("\n parent = ").append(fcall.getParent()); sb.append("\n fcall = ").append(fcall); sb.append("\n args = ").append(arguments); sb.append("\n params = ").append(getParameters()); sb.append("\n nargs = ").append(norm_arguments); sb.append("\n exception = ").append(exception); } return sb.toString(); }
/** * Performs normalization of the non-identifier arguments. It creates a temporary compound * statement filled with the temporary assignments to set of identifiers that takes the original * arugments as RHS. */ @SuppressWarnings("unchecked") protected void normalizeArguments() { if (exception != 0) { // no normalization is possible. return; } temp_assignments = new CompoundStatement(); norm_arguments = new ArrayList<Expression>(4); for (int i = 0; i < arguments.size(); i++) { Symbol param = getParameters().get(i); Expression arg = Symbolic.simplify(arguments.get(i)); // Allows normalization of identifers which are global array names. if (arg instanceof Identifier) { Symbol base = ((Identifier) arg).getSymbol(); if (SymbolTools.isGlobal(base) && SymbolTools.isArray(base)) { arg = new UnaryExpression( UnaryOperator.ADDRESS_OF, new ArrayAccess(arg.clone(), new IntegerLiteral(0))); } } Expression new_arg = arg; if (!(arg instanceof Literal || arg instanceof Identifier)) { arg = normalize(arg, param); List type_spec = param.getTypeSpecifiers(); List array_spec = param.getArraySpecifiers(); // Assumes there is only one element in array_spec. if (!array_spec.isEmpty()) { type_spec.add(PointerSpecifier.UNQUALIFIED); } new_arg = SymbolTools.getTemp(temp_assignments, type_spec, "arg"); Expression assign = new AssignmentExpression(new_arg, AssignmentOperator.NORMAL, arg.clone()); temp_assignments.addStatement(new ExpressionStatement(assign)); } norm_arguments.add(new_arg); } }