X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Fgimple-low.c;h=f6deba179389d0e3019eb64da162eeb4858783eb;hp=63d501deb50ee20a34de7b6fb2b8e44d46cc20ca;hb=f48068845f391e30be9c0962ab50f70d8c7a4f4d;hpb=48e1416a24d50cacbb2a5e06a9ee61dd8cbee313 diff --git a/gcc/gimple-low.c b/gcc/gimple-low.c index 63d501deb50..f6deba17938 100644 --- a/gcc/gimple-low.c +++ b/gcc/gimple-low.c @@ -1,6 +1,6 @@ /* GIMPLE lowering pass. Converts High GIMPLE into Low GIMPLE. - Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GCC. @@ -24,22 +24,13 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tm.h" #include "tree.h" -#include "rtl.h" -#include "varray.h" #include "gimple.h" #include "tree-iterator.h" #include "tree-inline.h" -#include "diagnostic.h" -#include "langhooks.h" -#include "langhooks-def.h" #include "tree-flow.h" -#include "timevar.h" -#include "except.h" -#include "hashtab.h" #include "flags.h" #include "function.h" -#include "expr.h" -#include "toplev.h" +#include "diagnostic-core.h" #include "tree-pass.h" /* The differences between High GIMPLE and Low GIMPLE are the @@ -157,11 +148,6 @@ lower_function_body (void) x = gimple_build_label (t.label); gsi_insert_after (&i, x, GSI_CONTINUE_LINKING); - - /* Remove the line number from the representative return statement. - It now fills in for many such returns. Failure to remove this - will result in incorrect results for coverage analysis. */ - gimple_set_location (t.stmt, UNKNOWN_LOCATION); gsi_insert_after (&i, t.stmt, GSI_CONTINUE_LINKING); } @@ -183,7 +169,7 @@ lower_function_body (void) and insert. */ disp_var = create_tmp_var (ptr_type_node, "setjmpvar"); arg = build_addr (disp_label, current_function_decl); - t = implicit_built_in_decls[BUILT_IN_SETJMP_DISPATCHER]; + t = builtin_decl_implicit (BUILT_IN_SETJMP_DISPATCHER); x = gimple_build_call (t, 1, arg); gimple_call_set_lhs (x, disp_var); @@ -217,30 +203,33 @@ struct gimple_opt_pass pass_lower_cf = PROP_gimple_lcf, /* properties_provided */ 0, /* properties_destroyed */ 0, /* todo_flags_start */ - TODO_dump_func /* todo_flags_finish */ + 0 /* todo_flags_finish */ } }; + /* Verify if the type of the argument matches that of the function declaration. If we cannot verify this or there is a mismatch, return false. */ -bool -gimple_check_call_args (gimple stmt) +static bool +gimple_check_call_args (gimple stmt, tree fndecl) { - tree fndecl, parms, p; + tree parms, p; unsigned int i, nargs; + /* Calls to internal functions always match their signature. */ + if (gimple_call_internal_p (stmt)) + return true; + nargs = gimple_call_num_args (stmt); /* Get argument types for verification. */ - fndecl = gimple_call_fndecl (stmt); - parms = NULL_TREE; if (fndecl) parms = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); - else if (POINTER_TYPE_P (TREE_TYPE (gimple_call_fn (stmt)))) - parms = TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (gimple_call_fn (stmt)))); + else + parms = TYPE_ARG_TYPES (gimple_call_fntype (stmt)); /* Verify if the type of the argument matches that of the function declaration. If we cannot verify this or there is a mismatch, @@ -249,7 +238,7 @@ gimple_check_call_args (gimple stmt) { for (i = 0, p = DECL_ARGUMENTS (fndecl); i < nargs; - i++, p = TREE_CHAIN (p)) + i++, p = DECL_CHAIN (p)) { /* We cannot distinguish a varargs function from the case of excess parameters, still deferring the inlining decision @@ -287,6 +276,25 @@ gimple_check_call_args (gimple stmt) return true; } +/* Verify if the type of the argument and lhs of CALL_STMT matches + that of the function declaration CALLEE. + If we cannot verify this or there is a mismatch, return false. */ + +bool +gimple_check_call_matching_types (gimple call_stmt, tree callee) +{ + tree lhs; + + if ((DECL_RESULT (callee) + && !DECL_BY_REFERENCE (DECL_RESULT (callee)) + && (lhs = gimple_call_lhs (call_stmt)) != NULL_TREE + && !useless_type_conversion_p (TREE_TYPE (DECL_RESULT (callee)), + TREE_TYPE (lhs)) + && !fold_convertible_p (TREE_TYPE (DECL_RESULT (callee)), lhs)) + || !gimple_check_call_args (call_stmt, callee)) + return false; + return true; +} /* Lower sequence SEQ. Unlike gimplification the statements are not relowered when they are changed -- if this has to be done, the lowering routine must @@ -388,6 +396,11 @@ lower_stmt (gimple_stmt_iterator *gsi, struct lower_data *data) lower_sequence (gimple_eh_filter_failure (stmt), data); break; + case GIMPLE_EH_ELSE: + lower_sequence (gimple_eh_else_n_body (stmt), data); + lower_sequence (gimple_eh_else_e_body (stmt), data); + break; + case GIMPLE_NOP: case GIMPLE_ASM: case GIMPLE_ASSIGN: @@ -438,6 +451,10 @@ lower_stmt (gimple_stmt_iterator *gsi, struct lower_data *data) data->cannot_fallthru = false; return; + case GIMPLE_TRANSACTION: + lower_sequence (gimple_transaction_body (stmt), data); + break; + default: gcc_unreachable (); } @@ -719,6 +736,10 @@ gimple_stmt_may_fallthru (gimple stmt) return (gimple_seq_may_fallthru (gimple_try_eval (stmt)) && gimple_seq_may_fallthru (gimple_try_cleanup (stmt))); + case GIMPLE_EH_ELSE: + return (gimple_seq_may_fallthru (gimple_eh_else_n_body (stmt)) + || gimple_seq_may_fallthru (gimple_eh_else_e_body (stmt))); + case GIMPLE_CALL: /* Functions that do not return do not fall through. */ return (gimple_call_flags (stmt) & ECF_NORETURN) == 0; @@ -755,7 +776,14 @@ lower_gimple_return (gimple_stmt_iterator *gsi, struct lower_data *data) tmp_rs = *VEC_index (return_statements_t, data->return_statements, i); if (gimple_return_retval (stmt) == gimple_return_retval (tmp_rs.stmt)) - goto found; + { + /* Remove the line number from the representative return statement. + It now fills in for many such returns. Failure to remove this + will result in incorrect results for coverage analysis. */ + gimple_set_location (tmp_rs.stmt, UNKNOWN_LOCATION); + + goto found; + } } /* Not found. Create a new label and record the return statement. */ @@ -765,6 +793,9 @@ lower_gimple_return (gimple_stmt_iterator *gsi, struct lower_data *data) /* Generate a goto statement and remove the return statement. */ found: + /* When not optimizing, make sure user returns are preserved. */ + if (!optimize && gimple_has_location (stmt)) + DECL_ARTIFICIAL (tmp_rs.label) = 0; t = gimple_build_goto (tmp_rs.label); gimple_set_location (t, gimple_location (stmt)); gimple_set_block (t, gimple_block (stmt)); @@ -843,7 +874,7 @@ lower_builtin_setjmp (gimple_stmt_iterator *gsi) /* Build '__builtin_setjmp_setup (BUF, NEXT_LABEL)' and insert. */ arg = build_addr (next_label, current_function_decl); - t = implicit_built_in_decls[BUILT_IN_SETJMP_SETUP]; + t = builtin_decl_implicit (BUILT_IN_SETJMP_SETUP); g = gimple_build_call (t, 2, gimple_call_arg (stmt, 0), arg); gimple_set_location (g, loc); gimple_set_block (g, gimple_block (stmt)); @@ -852,8 +883,7 @@ lower_builtin_setjmp (gimple_stmt_iterator *gsi) /* Build 'DEST = 0' and insert. */ if (dest) { - g = gimple_build_assign (dest, fold_convert_loc (loc, TREE_TYPE (dest), - integer_zero_node)); + g = gimple_build_assign (dest, build_zero_cst (TREE_TYPE (dest))); gimple_set_location (g, loc); gimple_set_block (g, gimple_block (stmt)); gsi_insert_before (gsi, g, GSI_SAME_STMT); @@ -869,7 +899,7 @@ lower_builtin_setjmp (gimple_stmt_iterator *gsi) /* Build '__builtin_setjmp_receiver (NEXT_LABEL)' and insert. */ arg = build_addr (next_label, current_function_decl); - t = implicit_built_in_decls[BUILT_IN_SETJMP_RECEIVER]; + t = builtin_decl_implicit (BUILT_IN_SETJMP_RECEIVER); g = gimple_build_call (t, 1, arg); gimple_set_location (g, loc); gimple_set_block (g, gimple_block (stmt)); @@ -902,7 +932,7 @@ record_vars_into (tree vars, tree fn) if (fn != current_function_decl) push_cfun (DECL_STRUCT_FUNCTION (fn)); - for (; vars; vars = TREE_CHAIN (vars)) + for (; vars; vars = DECL_CHAIN (vars)) { tree var = vars; @@ -916,8 +946,9 @@ record_vars_into (tree vars, tree fn) continue; /* Record the variable. */ - cfun->local_decls = tree_cons (NULL_TREE, var, - cfun->local_decls); + add_local_decl (cfun, var); + if (gimple_referenced_vars (cfun)) + add_referenced_var (var); } if (fn != current_function_decl)