@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); */ } }