OSDN Git Service

* config/rs6000/rs6000-protos.h (altivec_resolve_overloaded_builtin):
[pf3gnuchains/gcc-fork.git] / gcc / tree-mudflap.c
index 3f77b2c..cfba33d 100644 (file)
@@ -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 <fche@redhat.com>
    and Graydon Hoare <graydon@redhat.com>
@@ -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;
@@ -447,6 +450,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 +482,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
@@ -503,7 +526,7 @@ mf_build_check_statement_for (tree base, tree limit,
   tree mf_elem;
   tree mf_limit;
   gimple g;
-  gimple_seq seq;
+  gimple_seq seq, stmts;
 
   /* We first need to split the current basic block, and start altering
      the CFG.  This allows us to insert the statements we're about to
@@ -546,21 +569,23 @@ 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) <base address expression>.  */
   seq = gimple_seq_alloc ();
   t = fold_convert (mf_uintptr_type, unshare_expr (base));
-  gimplify_expr (&t, &seq, &seq, is_gimple_reg_rhs, fb_rvalue);
+  t = force_gimple_operand (t, &stmts, false, NULL_TREE);
+  gimple_seq_add_seq (&seq, stmts);
   g = gimple_build_assign (mf_base, t);
   gimple_set_location (g, location);
   gimple_seq_add_stmt (&seq, g);
 
   /* Build: __mf_limit = (uintptr_t) <limit address expression>.  */
   t = fold_convert (mf_uintptr_type, unshare_expr (limit));
-  gimplify_expr (&t, &seq, &seq, is_gimple_reg_rhs, fb_rvalue);
+  t = force_gimple_operand (t, &stmts, false, NULL_TREE);
+  gimple_seq_add_seq (&seq, stmts);
   g = gimple_build_assign (mf_limit, t);
   gimple_set_location (g, location);
   gimple_seq_add_stmt (&seq, g);
@@ -577,7 +602,8 @@ mf_build_check_statement_for (tree base, tree limit,
               TREE_TYPE (TREE_TYPE (mf_cache_array_decl)),
               mf_cache_array_decl, t, NULL_TREE, NULL_TREE);
   t = build1 (ADDR_EXPR, mf_cache_structptr_type, t);
-  gimplify_expr (&t, &seq, &seq, is_gimple_reg_rhs, fb_rvalue);
+  t = force_gimple_operand (t, &stmts, false, NULL_TREE);
+  gimple_seq_add_seq (&seq, stmts);
   g = gimple_build_assign (mf_elem, t);
   gimple_set_location (g, location);
   gimple_seq_add_stmt (&seq, g);
@@ -622,15 +648,16 @@ mf_build_check_statement_for (tree base, tree limit,
      result of the evaluation of 't' in a temporary variable which we
      can use as the condition for the conditional jump.  */
   t = build2 (TRUTH_OR_EXPR, boolean_type_node, t, u);
-  gimplify_expr (&t, &seq, &seq, is_gimple_reg_rhs, fb_rvalue);
-  cond = create_tmp_var (boolean_type_node, "__mf_unlikely_cond");
+  t = force_gimple_operand (t, &stmts, false, NULL_TREE);
+  gimple_seq_add_seq (&seq, stmts);
+  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);
@@ -660,15 +687,25 @@ 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,
+  v = fold_build2 (PLUS_EXPR, mf_uintptr_type,
                   fold_build2 (MINUS_EXPR, mf_uintptr_type, mf_limit, mf_base),
-                  integer_one_node);
-  gimplify_expr (&v, &seq, &seq, is_gimple_mem_rhs, fb_rvalue);
+                  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);
   gimple_seq_add_stmt (&seq, g);
 
   if (! flag_mudflap_threads)
     {
+      if (stmt_ends_bb_p (g))
+       {
+         gsi = gsi_start_bb (then_bb);
+         gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING);
+         e = split_block (then_bb, g);
+         then_bb = e->dest;
+         seq = gimple_seq_alloc ();
+       }
+
       g = gimple_build_assign (mf_cache_shift_decl_l, mf_cache_shift_decl);
       gimple_seq_add_stmt (&seq, g);
 
@@ -773,6 +810,13 @@ mf_xform_derefs_1 (gimple_stmt_iterator *iter, tree *tp,
                base = TREE_OPERAND (var, 0);
                 break;
               }
+            else if (TREE_CODE (var) == VIEW_CONVERT_EXPR)
+             {
+               var = TREE_OPERAND (var, 0);
+               if (CONSTANT_CLASS_P (var)
+                   && TREE_CODE (var) != STRING_CST)
+                 return;
+             }
             else 
               {
                 gcc_assert (TREE_CODE (var) == VAR_DECL 
@@ -1040,8 +1084,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
            {
@@ -1284,8 +1328,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;
             }
           
@@ -1325,7 +1369,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 */
@@ -1344,13 +1388,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 */
  }
 };