X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gcc%2Ftree-mudflap.c;h=381b029d45f06a524e4299bb5d05eaabc4983c96;hb=30402573869ec1e624da994d10a9501e9b500d80;hp=dae12874dad6c6fe951b0fa5768725f257856995;hpb=ba4d8f9d37bf11be3a98504812447cd9bbaad708;p=gcc.git diff --git a/gcc/tree-mudflap.c b/gcc/tree-mudflap.c index dae12874dad..381b029d45f 100644 --- a/gcc/tree-mudflap.c +++ b/gcc/tree-mudflap.c @@ -1,5 +1,5 @@ /* Mudflap: narrow-pointer bounds-checking by tree rewriting. - Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. Contributed by Frank Ch. Eigler and Graydon Hoare @@ -62,7 +62,7 @@ static tree mf_file_function_line_tree (location_t); /* Indirection-related instrumentation. */ static void mf_decl_cache_locals (void); static void mf_decl_clear_locals (void); -static void mf_xform_derefs (void); +static void mf_xform_statements (void); static unsigned int execute_mudflap_function_ops (void); /* Addressable variables instrumentation. */ @@ -295,7 +295,8 @@ static GTY (()) tree mf_set_options_fndecl; static inline tree mf_make_builtin (enum tree_code category, const char *name, tree type) { - tree decl = mf_mark (build_decl (category, get_identifier (name), type)); + tree decl = mf_mark (build_decl (UNKNOWN_LOCATION, + category, get_identifier (name), type)); TREE_PUBLIC (decl) = 1; DECL_EXTERNAL (decl) = 1; lang_hooks.decls.pushdecl (decl); @@ -315,8 +316,10 @@ mf_make_mf_cache_struct_type (tree field_type) /* There is, abominably, no language-independent way to construct a RECORD_TYPE. So we have to call the basic type construction primitives by hand. */ - tree fieldlo = build_decl (FIELD_DECL, get_identifier ("low"), field_type); - tree fieldhi = build_decl (FIELD_DECL, get_identifier ("high"), field_type); + tree fieldlo = build_decl (UNKNOWN_LOCATION, + FIELD_DECL, get_identifier ("low"), field_type); + tree fieldhi = build_decl (UNKNOWN_LOCATION, + FIELD_DECL, get_identifier ("high"), field_type); tree struct_type = make_node (RECORD_TYPE); DECL_CONTEXT (fieldlo) = struct_type; @@ -413,13 +416,19 @@ mudflap_init (void) /* ------------------------------------------------------------------------ */ -/* Memory reference transforms. Perform the mudflap indirection-related - tree transforms on the current function. - - This is the second part of the mudflap instrumentation. It works on +/* This is the second part of the mudflap instrumentation. It works on low-level GIMPLE using the CFG, because we want to run this pass after tree optimizations have been performed, but we have to preserve the CFG - for expansion from trees to RTL. */ + for expansion from trees to RTL. + Below is the list of transformations performed on statements in the + current function. + + 1) Memory reference transforms: Perform the mudflap indirection-related + tree transforms on memory references. + + 2) Mark BUILTIN_ALLOCA calls not inlineable. + + */ static unsigned int execute_mudflap_function_ops (void) @@ -438,7 +447,7 @@ execute_mudflap_function_ops (void) if (! flag_mudflap_threads) mf_decl_cache_locals (); - mf_xform_derefs (); + mf_xform_statements (); if (! flag_mudflap_threads) mf_decl_clear_locals (); @@ -447,6 +456,26 @@ execute_mudflap_function_ops (void) return 0; } +/* Insert a gimple_seq SEQ on all the outgoing edges out of BB. Note that + if BB has more than one edge, STMT will be replicated for each edge. + Also, abnormal edges will be ignored. */ + +static void +insert_edge_copies_seq (gimple_seq seq, basic_block bb) +{ + edge e; + edge_iterator ei; + unsigned n_copies = -1; + + FOR_EACH_EDGE (e, ei, bb->succs) + if (!(e->flags & EDGE_ABNORMAL)) + n_copies++; + + FOR_EACH_EDGE (e, ei, bb->succs) + if (!(e->flags & EDGE_ABNORMAL)) + gsi_insert_seq_on_edge (e, n_copies-- > 0 ? gimple_seq_copy (seq) : seq); +} + /* Create and initialize local shadow variables for the lookup cache globals. Put their decls in the *_l globals for use by mf_build_check_statement_for. */ @@ -459,11 +488,11 @@ mf_decl_cache_locals (void) /* Build the cache vars. */ mf_cache_shift_decl_l - = mf_mark (create_tmp_var (TREE_TYPE (mf_cache_shift_decl), + = mf_mark (make_rename_temp (TREE_TYPE (mf_cache_shift_decl), "__mf_lookup_shift_l")); mf_cache_mask_decl_l - = mf_mark (create_tmp_var (TREE_TYPE (mf_cache_mask_decl), + = mf_mark (make_rename_temp (TREE_TYPE (mf_cache_mask_decl), "__mf_lookup_mask_l")); /* Build initialization nodes for the cache vars. We just load the @@ -546,13 +575,14 @@ mf_build_check_statement_for (tree base, tree limit, } /* Build our local variables. */ - mf_elem = create_tmp_var (mf_cache_structptr_type, "__mf_elem"); - mf_base = create_tmp_var (mf_uintptr_type, "__mf_base"); - mf_limit = create_tmp_var (mf_uintptr_type, "__mf_limit"); + mf_elem = make_rename_temp (mf_cache_structptr_type, "__mf_elem"); + mf_base = make_rename_temp (mf_uintptr_type, "__mf_base"); + mf_limit = make_rename_temp (mf_uintptr_type, "__mf_limit"); /* Build: __mf_base = (uintptr_t) . */ seq = gimple_seq_alloc (); - t = fold_convert (mf_uintptr_type, unshare_expr (base)); + t = fold_convert_loc (location, mf_uintptr_type, + unshare_expr (base)); t = force_gimple_operand (t, &stmts, false, NULL_TREE); gimple_seq_add_seq (&seq, stmts); g = gimple_build_assign (mf_base, t); @@ -560,7 +590,8 @@ mf_build_check_statement_for (tree base, tree limit, gimple_seq_add_stmt (&seq, g); /* Build: __mf_limit = (uintptr_t) . */ - t = fold_convert (mf_uintptr_type, unshare_expr (limit)); + t = fold_convert_loc (location, mf_uintptr_type, + unshare_expr (limit)); t = force_gimple_operand (t, &stmts, false, NULL_TREE); gimple_seq_add_seq (&seq, stmts); g = gimple_build_assign (mf_limit, t); @@ -627,14 +658,14 @@ mf_build_check_statement_for (tree base, tree limit, t = build2 (TRUTH_OR_EXPR, boolean_type_node, t, u); t = force_gimple_operand (t, &stmts, false, NULL_TREE); gimple_seq_add_seq (&seq, stmts); - cond = create_tmp_var (boolean_type_node, "__mf_unlikely_cond"); + cond = make_rename_temp (boolean_type_node, "__mf_unlikely_cond"); g = gimple_build_assign (cond, t); gimple_set_location (g, location); gimple_seq_add_stmt (&seq, g); /* Build the conditional jump. 'cond' is just a temporary so we can simply build a void COND_EXPR. We do need labels in both arms though. */ - g = gimple_build_cond (NE_EXPR, cond, integer_zero_node, NULL_TREE, + g = gimple_build_cond (NE_EXPR, cond, boolean_false_node, NULL_TREE, NULL_TREE); gimple_set_location (g, location); gimple_seq_add_stmt (&seq, g); @@ -664,9 +695,10 @@ mf_build_check_statement_for (tree base, tree limit, /* u is a string, so it is already a gimple value. */ u = mf_file_function_line_tree (location); /* NB: we pass the overall [base..limit] range to mf_check. */ - v = fold_build2 (PLUS_EXPR, integer_type_node, - fold_build2 (MINUS_EXPR, mf_uintptr_type, mf_limit, mf_base), - integer_one_node); + v = fold_build2_loc (location, PLUS_EXPR, mf_uintptr_type, + fold_build2_loc (location, + MINUS_EXPR, mf_uintptr_type, mf_limit, mf_base), + build_int_cst (mf_uintptr_type, 1)); v = force_gimple_operand (v, &stmts, true, NULL_TREE); gimple_seq_add_seq (&seq, stmts); g = gimple_build_call (mf_check_fndecl, 4, mf_base, v, dirflag, u); @@ -834,16 +866,16 @@ mf_xform_derefs_1 (gimple_stmt_iterator *iter, tree *tp, if (elt) elt = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (elt)), elt); - addr = fold_convert (ptr_type_node, elt ? elt : base); - addr = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, - addr, fold_convert (sizetype, - byte_position (field))); + addr = fold_convert_loc (location, ptr_type_node, elt ? elt : base); + addr = fold_build2_loc (location, POINTER_PLUS_EXPR, ptr_type_node, + addr, fold_convert_loc (location, sizetype, + byte_position (field))); } else addr = build1 (ADDR_EXPR, build_pointer_type (type), t); - limit = fold_build2 (MINUS_EXPR, mf_uintptr_type, - fold_build2 (PLUS_EXPR, mf_uintptr_type, + limit = fold_build2_loc (location, MINUS_EXPR, mf_uintptr_type, + fold_build2_loc (location, PLUS_EXPR, mf_uintptr_type, convert (mf_uintptr_type, addr), size), integer_one_node); @@ -853,8 +885,9 @@ mf_xform_derefs_1 (gimple_stmt_iterator *iter, tree *tp, case INDIRECT_REF: addr = TREE_OPERAND (t, 0); base = addr; - limit = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, - fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, base, + limit = fold_build2_loc (location, POINTER_PLUS_EXPR, ptr_type_node, + fold_build2_loc (location, + POINTER_PLUS_EXPR, ptr_type_node, base, size), size_int (-1)); break; @@ -862,8 +895,9 @@ mf_xform_derefs_1 (gimple_stmt_iterator *iter, tree *tp, case TARGET_MEM_REF: addr = tree_mem_ref_addr (ptr_type_node, t); base = addr; - limit = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, - fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, base, + limit = fold_build2_loc (location, POINTER_PLUS_EXPR, ptr_type_node, + fold_build2_loc (location, + POINTER_PLUS_EXPR, ptr_type_node, base, size), size_int (-1)); break; @@ -885,21 +919,26 @@ mf_xform_derefs_1 (gimple_stmt_iterator *iter, tree *tp, bpu = bitsize_int (BITS_PER_UNIT); ofs = convert (bitsizetype, TREE_OPERAND (t, 2)); - rem = size_binop (TRUNC_MOD_EXPR, ofs, bpu); - ofs = fold_convert (sizetype, size_binop (TRUNC_DIV_EXPR, ofs, bpu)); + rem = size_binop_loc (location, TRUNC_MOD_EXPR, ofs, bpu); + ofs = fold_convert_loc (location, + sizetype, + size_binop_loc (location, + TRUNC_DIV_EXPR, ofs, bpu)); size = convert (bitsizetype, TREE_OPERAND (t, 1)); - size = size_binop (PLUS_EXPR, size, rem); - size = size_binop (CEIL_DIV_EXPR, size, bpu); + size = size_binop_loc (location, PLUS_EXPR, size, rem); + size = size_binop_loc (location, CEIL_DIV_EXPR, size, bpu); size = convert (sizetype, size); addr = TREE_OPERAND (TREE_OPERAND (t, 0), 0); addr = convert (ptr_type_node, addr); - addr = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, addr, ofs); + addr = fold_build2_loc (location, POINTER_PLUS_EXPR, + ptr_type_node, addr, ofs); base = addr; - limit = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, - fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, + limit = fold_build2_loc (location, POINTER_PLUS_EXPR, ptr_type_node, + fold_build2_loc (location, + POINTER_PLUS_EXPR, ptr_type_node, base, size), size_int (-1)); } @@ -911,9 +950,12 @@ mf_xform_derefs_1 (gimple_stmt_iterator *iter, tree *tp, mf_build_check_statement_for (base, limit, iter, location, dirflag); } - +/* Transform + 1) Memory references. + 2) BUILTIN_ALLOCA calls. +*/ static void -mf_xform_derefs (void) +mf_xform_statements (void) { basic_block bb, next; gimple_stmt_iterator i; @@ -951,6 +993,14 @@ mf_xform_derefs (void) } break; + case GIMPLE_CALL: + { + tree fndecl = gimple_call_fndecl (s); + if (fndecl && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_ALLOCA)) + gimple_call_set_cannot_inline (s, true); + } + break; + default: ; } @@ -1061,8 +1111,8 @@ mx_register_decls (tree decl, gimple_seq seq, location_t location) { if (!DECL_ARTIFICIAL (decl)) warning (OPT_Wmudflap, - "mudflap cannot track %qs in stub function", - IDENTIFIER_POINTER (DECL_NAME (decl))); + "mudflap cannot track %qE in stub function", + DECL_NAME (decl)); } else { @@ -1305,8 +1355,8 @@ mudflap_finish_file (void) if (! COMPLETE_TYPE_P (TREE_TYPE (obj))) { warning (OPT_Wmudflap, - "mudflap cannot track unknown size extern %qs", - IDENTIFIER_POINTER (DECL_NAME (obj))); + "mudflap cannot track unknown size extern %qE", + DECL_NAME (obj)); continue; } @@ -1346,7 +1396,7 @@ struct gimple_opt_pass pass_mudflap_1 = NULL, /* sub */ NULL, /* next */ 0, /* static_pass_number */ - 0, /* tv_id */ + TV_NONE, /* tv_id */ PROP_gimple_any, /* properties_required */ 0, /* properties_provided */ 0, /* properties_destroyed */ @@ -1365,13 +1415,13 @@ struct gimple_opt_pass pass_mudflap_2 = NULL, /* sub */ NULL, /* next */ 0, /* static_pass_number */ - 0, /* tv_id */ - PROP_gimple_leh, /* properties_required */ + TV_NONE, /* tv_id */ + PROP_ssa | PROP_cfg | PROP_gimple_leh,/* properties_required */ 0, /* properties_provided */ 0, /* properties_destroyed */ 0, /* todo_flags_start */ TODO_verify_flow | TODO_verify_stmts - | TODO_dump_func /* todo_flags_finish */ + | TODO_dump_func | TODO_update_ssa /* todo_flags_finish */ } };