OSDN Git Service

* gcc-interface/decl.c (gnat_to_gnu_entity) <E_Array_Subtype>: Tidy
[pf3gnuchains/gcc-fork.git] / gcc / gimple.c
index a91e83a..9223aaa 100644 (file)
@@ -1,6 +1,6 @@
 /* Gimple IR support functions.
 
-   Copyright 2007, 2008 Free Software Foundation, Inc.
+   Copyright 2007, 2008, 2009 Free Software Foundation, Inc.
    Contributed by Aldy Hernandez <aldyh@redhat.com>
 
 This file is part of GCC.
@@ -25,14 +25,15 @@ along with GCC; see the file COPYING3.  If not see
 #include "tm.h"
 #include "tree.h"
 #include "ggc.h"
-#include "errors.h"
 #include "hard-reg-set.h"
 #include "basic-block.h"
 #include "gimple.h"
+#include "toplev.h"
 #include "diagnostic.h"
 #include "tree-flow.h"
 #include "value-prof.h"
 #include "flags.h"
+#include "demangle.h"
 
 #define DEFGSCODE(SYM, NAME, STRUCT)   NAME,
 const char *const gimple_code_name[] = {
@@ -45,7 +46,7 @@ const char *const gimple_code_name[] = {
    operands vector the size of the structure minus the size of the 1
    element tree array at the end (see gimple_ops).  */
 #define DEFGSCODE(SYM, NAME, STRUCT)   (sizeof (STRUCT) - sizeof (tree)),
-const size_t gimple_ops_offset_[] = {
+EXPORTED_CONST size_t gimple_ops_offset_[] = {
 #include "gimple.def"
 };
 #undef DEFGSCODE
@@ -102,7 +103,7 @@ gss_for_code (enum gimple_code code)
     case GIMPLE_COND:
     case GIMPLE_GOTO:
     case GIMPLE_LABEL:
-    case GIMPLE_CHANGE_DYNAMIC_TYPE:
+    case GIMPLE_DEBUG:
     case GIMPLE_SWITCH:                        return GSS_WITH_OPS;
     case GIMPLE_ASM:                   return GSS_ASM;
     case GIMPLE_BIND:                  return GSS_BIND;
@@ -190,8 +191,6 @@ gimple_size (enum gimple_code code)
       return sizeof (struct gimple_statement_omp_atomic_store);
     case GIMPLE_WITH_CLEANUP_EXPR:
       return sizeof (struct gimple_statement_wce);
-    case GIMPLE_CHANGE_DYNAMIC_TYPE:
-      return sizeof (struct gimple_statement_with_ops);
     case GIMPLE_PREDICT:
       return sizeof (struct gimple_statement_base);
     default:
@@ -256,7 +255,7 @@ gimple_set_subcode (gimple g, unsigned subcode)
   gimple_build_with_ops_stat (c, s, n MEM_STAT_INFO)
 
 static gimple
-gimple_build_with_ops_stat (enum gimple_code code, enum tree_code subcode,
+gimple_build_with_ops_stat (enum gimple_code code, unsigned subcode,
                            unsigned num_ops MEM_STAT_DECL)
 {
   gimple s = gimple_alloc_stat (code, num_ops PASS_MEM_STAT);
@@ -271,7 +270,7 @@ gimple_build_with_ops_stat (enum gimple_code code, enum tree_code subcode,
 gimple
 gimple_build_return (tree retval)
 {
-  gimple s = gimple_build_with_ops (GIMPLE_RETURN, 0, 1);
+  gimple s = gimple_build_with_ops (GIMPLE_RETURN, ERROR_MARK, 1);
   if (retval)
     gimple_return_set_retval (s, retval);
   return s;
@@ -284,7 +283,7 @@ gimple_build_return (tree retval)
 static inline gimple
 gimple_build_call_1 (tree fn, unsigned nargs)
 {
-  gimple s = gimple_build_with_ops (GIMPLE_CALL, 0, nargs + 3);
+  gimple s = gimple_build_with_ops (GIMPLE_CALL, ERROR_MARK, nargs + 3);
   if (TREE_CODE (fn) == FUNCTION_DECL)
     fn = build_fold_addr_expr (fn);
   gimple_set_op (s, 1, fn);
@@ -360,6 +359,7 @@ gimple_build_call_from_tree (tree t)
   gimple_call_set_return_slot_opt (call, CALL_EXPR_RETURN_SLOT_OPT (t));
   gimple_call_set_from_thunk (call, CALL_FROM_THUNK_P (t));
   gimple_call_set_va_arg_pack (call, CALL_EXPR_VA_ARG_PACK (t));
+  gimple_set_no_warning (call, TREE_NO_WARNING (t));
 
   return call;
 }
@@ -429,7 +429,7 @@ gimple_build_assign_with_ops_stat (enum tree_code subcode, tree lhs, tree op1,
      code).  */
   num_ops = get_gimple_rhs_num_ops (subcode) + 1;
   
-  p = gimple_build_with_ops_stat (GIMPLE_ASSIGN, subcode, num_ops
+  p = gimple_build_with_ops_stat (GIMPLE_ASSIGN, (unsigned)subcode, num_ops
                                  PASS_MEM_STAT);
   gimple_assign_set_lhs (p, lhs);
   gimple_assign_set_rhs1 (p, op1);
@@ -451,7 +451,7 @@ gimple_build_assign_with_ops_stat (enum tree_code subcode, tree lhs, tree op1,
 
    This function returns the newly created GIMPLE_ASSIGN tuple.  */
 
-inline gimple
+gimple
 gimplify_assign (tree dst, tree src, gimple_seq *seq_p)
 { 
   tree t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
@@ -489,6 +489,7 @@ void
 gimple_cond_get_ops_from_tree (tree cond, enum tree_code *code_p,
                                tree *lhs_p, tree *rhs_p)
 {
+  location_t loc = EXPR_LOCATION (cond);
   gcc_assert (TREE_CODE_CLASS (TREE_CODE (cond)) == tcc_comparison
              || TREE_CODE (cond) == TRUTH_NOT_EXPR
              || is_gimple_min_invariant (cond)
@@ -501,14 +502,14 @@ gimple_cond_get_ops_from_tree (tree cond, enum tree_code *code_p,
     {
       *code_p = EQ_EXPR;
       gcc_assert (*lhs_p && *rhs_p == NULL_TREE);
-      *rhs_p = fold_convert (TREE_TYPE (*lhs_p), integer_zero_node);
+      *rhs_p = fold_convert_loc (loc, TREE_TYPE (*lhs_p), integer_zero_node);
     }
   /* Canonicalize conditionals of the form 'if (VAL)'  */
   else if (TREE_CODE_CLASS (*code_p) != tcc_comparison)
     {
       *code_p = NE_EXPR;
       gcc_assert (*lhs_p && *rhs_p == NULL_TREE);
-      *rhs_p = fold_convert (TREE_TYPE (*lhs_p), integer_zero_node);
+      *rhs_p = fold_convert_loc (loc, TREE_TYPE (*lhs_p), integer_zero_node);
     }
 }
 
@@ -544,7 +545,7 @@ gimple_cond_set_condition_from_tree (gimple stmt, tree cond)
 gimple
 gimple_build_label (tree label)
 {
-  gimple p = gimple_build_with_ops (GIMPLE_LABEL, 0, 1);
+  gimple p = gimple_build_with_ops (GIMPLE_LABEL, ERROR_MARK, 1);
   gimple_label_set_label (p, label);
   return p;
 }
@@ -554,7 +555,7 @@ gimple_build_label (tree label)
 gimple
 gimple_build_goto (tree dest)
 {
-  gimple p = gimple_build_with_ops (GIMPLE_GOTO, 0, 1);
+  gimple p = gimple_build_with_ops (GIMPLE_GOTO, ERROR_MARK, 1);
   gimple_goto_set_dest (p, dest);
   return p;
 }
@@ -600,7 +601,8 @@ gimple_build_asm_1 (const char *string, unsigned ninputs, unsigned noutputs,
   gimple p;
   int size = strlen (string);
 
-  p = gimple_build_with_ops (GIMPLE_ASM, 0, ninputs + noutputs + nclobbers);
+  p = gimple_build_with_ops (GIMPLE_ASM, ERROR_MARK,
+                            ninputs + noutputs + nclobbers);
 
   p->gimple_asm.ni = ninputs;
   p->gimple_asm.no = noutputs;
@@ -776,7 +778,8 @@ static inline gimple
 gimple_build_switch_1 (unsigned nlabels, tree index, tree default_label)
 {
   /* nlabels + 1 default label + 1 index.  */
-  gimple p = gimple_build_with_ops (GIMPLE_SWITCH, 0, nlabels + 1 + 1);
+  gimple p = gimple_build_with_ops (GIMPLE_SWITCH, ERROR_MARK,
+                                   nlabels + 1 + 1);
   gimple_switch_set_index (p, index);
   gimple_switch_set_default_label (p, default_label);
   return p;
@@ -830,6 +833,29 @@ gimple_build_switch_vec (tree index, tree default_label, VEC(tree, heap) *args)
 }
 
 
+/* Build a new GIMPLE_DEBUG_BIND statement.
+
+   VAR is bound to VALUE; block and location are taken from STMT.  */
+
+gimple
+gimple_build_debug_bind_stat (tree var, tree value, gimple stmt MEM_STAT_DECL)
+{
+  gimple p = gimple_build_with_ops_stat (GIMPLE_DEBUG,
+                                        (unsigned)GIMPLE_DEBUG_BIND, 2
+                                        PASS_MEM_STAT);
+
+  gimple_debug_bind_set_var (p, var);
+  gimple_debug_bind_set_value (p, value);
+  if (stmt)
+    {
+      gimple_set_block (p, gimple_block (stmt));
+      gimple_set_location (p, gimple_location (stmt));
+    }
+
+  return p;
+}
+
+
 /* Build a GIMPLE_OMP_CRITICAL statement.
 
    BODY is the sequence of statements for which only one thread can execute.
@@ -1040,20 +1066,6 @@ gimple_build_omp_single (gimple_seq body, tree clauses)
 }
 
 
-/* Build a GIMPLE_CHANGE_DYNAMIC_TYPE statement.  TYPE is the new type
-   for the location PTR.  */
-
-gimple
-gimple_build_cdt (tree type, tree ptr)
-{
-  gimple p = gimple_build_with_ops (GIMPLE_CHANGE_DYNAMIC_TYPE, 0, 2);
-  gimple_cdt_set_new_type (p, type);
-  gimple_cdt_set_location (p, ptr);
-
-  return p;
-}
-
-
 /* Build a GIMPLE_OMP_ATOMIC_LOAD statement.  */
 
 gimple
@@ -1226,11 +1238,11 @@ empty_body_p (gimple_seq body)
 {
   gimple_stmt_iterator i;
 
-
   if (gimple_seq_empty_p (body))
     return true;
   for (i = gsi_start (body); !gsi_end_p (i); gsi_next (&i))
-    if (!empty_stmt_p (gsi_stmt (i)))
+    if (!empty_stmt_p (gsi_stmt (i))
+       && !is_gimple_debug (gsi_stmt (i)))
       return false;
 
   return true;
@@ -1458,16 +1470,6 @@ walk_gimple_op (gimple stmt, walk_tree_fn callback_op,
        return ret;
       break;
 
-    case GIMPLE_CHANGE_DYNAMIC_TYPE:
-      ret = walk_tree (gimple_cdt_location_ptr (stmt), callback_op, wi, pset);
-      if (ret)
-       return ret;
-
-      ret = walk_tree (gimple_cdt_new_type_ptr (stmt), callback_op, wi, pset);
-      if (ret)
-       return ret;
-      break;
-
     case GIMPLE_ASM:
       ret = walk_gimple_asm (stmt, callback_op, wi);
       if (ret)
@@ -1921,10 +1923,11 @@ gimple_set_bb (gimple stmt, basic_block bb)
 tree
 gimple_fold (const_gimple stmt)
 {
+  location_t loc = gimple_location (stmt);
   switch (gimple_code (stmt))
     {
     case GIMPLE_COND:
-      return fold_binary (gimple_cond_code (stmt),
+      return fold_binary_loc (loc, gimple_cond_code (stmt),
                          boolean_type_node,
                          gimple_cond_lhs (stmt),
                          gimple_cond_rhs (stmt));
@@ -1933,11 +1936,11 @@ gimple_fold (const_gimple stmt)
       switch (get_gimple_rhs_class (gimple_assign_rhs_code (stmt)))
        {
        case GIMPLE_UNARY_RHS:
-         return fold_unary (gimple_assign_rhs_code (stmt),
+         return fold_unary_loc (loc, gimple_assign_rhs_code (stmt),
                             TREE_TYPE (gimple_assign_lhs (stmt)),
                             gimple_assign_rhs1 (stmt));
        case GIMPLE_BINARY_RHS:
-         return fold_binary (gimple_assign_rhs_code (stmt),
+         return fold_binary_loc (loc, gimple_assign_rhs_code (stmt),
                              TREE_TYPE (gimple_assign_lhs (stmt)),
                              gimple_assign_rhs1 (stmt),
                              gimple_assign_rhs2 (stmt));
@@ -2246,6 +2249,9 @@ gimple_has_side_effects (const_gimple s)
 {
   unsigned i;
 
+  if (is_gimple_debug (s))
+    return false;
+
   /* We don't have to scan the arguments to check for
      volatile arguments, though, at present, we still
      do a scan to check for TREE_SIDE_EFFECTS.  */
@@ -2339,6 +2345,8 @@ gimple_rhs_has_side_effects (const_gimple s)
            return true;
          }
     }
+  else if (is_gimple_debug (s))
+    return false;
   else
     {
       /* For statements without an LHS, examine all arguments.  */
@@ -2747,7 +2755,6 @@ is_gimple_stmt (tree t)
     case TRY_FINALLY_EXPR:
     case EH_FILTER_EXPR:
     case CATCH_EXPR:
-    case CHANGE_DYNAMIC_TYPE_EXPR:
     case ASM_EXPR:
     case RESX_EXPR:
     case STATEMENT_LIST:
@@ -2803,13 +2810,7 @@ is_gimple_id (tree t)
 bool
 is_gimple_reg_type (tree type)
 {
-  /* In addition to aggregate types, we also exclude complex types if not
-     optimizing because they can be subject to partial stores in GNU C by
-     means of the __real__ and __imag__ operators and we cannot promote
-     them to total stores (see gimplify_modify_expr_complex_part).  */
-  return !(AGGREGATE_TYPE_P (type)
-          || (TREE_CODE (type) == COMPLEX_TYPE && !optimize));
-
+  return !AGGREGATE_TYPE_P (type);
 }
 
 /* Return true if T is a non-aggregate register variable.  */
@@ -2823,12 +2824,6 @@ is_gimple_reg (tree t)
   if (!is_gimple_variable (t))
     return false;
 
-  /* Complex and vector values must have been put into SSA-like form.
-     That is, no assignments to the individual components.  */
-  if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
-      || TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
-    return DECL_GIMPLE_REG_P (t);
-
   if (!is_gimple_reg_type (TREE_TYPE (t)))
     return false;
 
@@ -2855,6 +2850,12 @@ is_gimple_reg (tree t)
   if (TREE_CODE (t) == VAR_DECL && DECL_HARD_REGISTER (t))
     return false;
 
+  /* Complex and vector values must have been put into SSA-like form.
+     That is, no assignments to the individual components.  */
+  if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
+      || TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
+    return DECL_GIMPLE_REG_P (t);
+
   return true;
 }
 
@@ -3229,17 +3230,25 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data,
            ret |= visit_store (stmt, lhs, data);
        }
       rhs = gimple_assign_rhs1 (stmt);
+      while (handled_component_p (rhs))
+       rhs = TREE_OPERAND (rhs, 0);
       if (visit_addr)
        {
          if (TREE_CODE (rhs) == ADDR_EXPR)
            ret |= visit_addr (stmt, TREE_OPERAND (rhs, 0), data);
          else if (TREE_CODE (rhs) == TARGET_MEM_REF
+                   && TMR_BASE (rhs) != NULL_TREE
                   && TREE_CODE (TMR_BASE (rhs)) == ADDR_EXPR)
            ret |= visit_addr (stmt, TREE_OPERAND (TMR_BASE (rhs), 0), data);
          else if (TREE_CODE (rhs) == OBJ_TYPE_REF
                   && TREE_CODE (OBJ_TYPE_REF_OBJECT (rhs)) == ADDR_EXPR)
            ret |= visit_addr (stmt, TREE_OPERAND (OBJ_TYPE_REF_OBJECT (rhs),
                                                   0), data);
+          lhs = gimple_assign_lhs (stmt);
+         if (TREE_CODE (lhs) == TARGET_MEM_REF
+              && TMR_BASE (lhs) != NULL_TREE
+              && TREE_CODE (TMR_BASE (lhs)) == ADDR_EXPR)
+            ret |= visit_addr (stmt, TREE_OPERAND (TMR_BASE (lhs), 0), data);
        }
       if (visit_load)
        {
@@ -3250,8 +3259,7 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data,
     }
   else if (visit_addr
           && (is_gimple_assign (stmt)
-              || gimple_code (stmt) == GIMPLE_COND
-              || gimple_code (stmt) == GIMPLE_CHANGE_DYNAMIC_TYPE))
+              || gimple_code (stmt) == GIMPLE_COND))
     {
       for (i = 0; i < gimple_num_ops (stmt); ++i)
        if (gimple_op (stmt, i)
@@ -3289,6 +3297,11 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data,
          && TREE_CODE (gimple_call_chain (stmt)) == ADDR_EXPR)
        ret |= visit_addr (stmt, TREE_OPERAND (gimple_call_chain (stmt), 0),
                           data);
+      if (visit_addr
+         && gimple_call_return_slot_opt_p (stmt)
+         && gimple_call_lhs (stmt) != NULL_TREE
+         && TREE_ADDRESSABLE (TREE_TYPE (gimple_call_lhs (stmt))))
+       ret |= visit_addr (stmt, gimple_call_lhs (stmt), data);
     }
   else if (gimple_code (stmt) == GIMPLE_ASM)
     {
@@ -3415,4 +3428,75 @@ gimple_ior_addresses_taken (bitmap addresses_taken, gimple stmt)
                                        gimple_ior_addresses_taken_1);
 }
 
+
+/* Return a printable name for symbol DECL.  */
+
+const char *
+gimple_decl_printable_name (tree decl, int verbosity)
+{
+  gcc_assert (decl && DECL_NAME (decl));
+
+  if (DECL_ASSEMBLER_NAME_SET_P (decl))
+    {
+      const char *str, *mangled_str;
+      int dmgl_opts = DMGL_NO_OPTS;
+
+      if (verbosity >= 2)
+       {
+         dmgl_opts = DMGL_VERBOSE
+                     | DMGL_TYPES
+                     | DMGL_ANSI
+                     | DMGL_GNU_V3
+                     | DMGL_RET_POSTFIX;
+         if (TREE_CODE (decl) == FUNCTION_DECL)
+           dmgl_opts |= DMGL_PARAMS;
+       }
+
+      mangled_str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+      str = cplus_demangle_v3 (mangled_str, dmgl_opts);
+      return (str) ? str : mangled_str;
+    }
+
+  return IDENTIFIER_POINTER (DECL_NAME (decl));
+}
+
+
+/* Fold a OBJ_TYPE_REF expression to the address of a function.
+   KNOWN_TYPE carries the true type of OBJ_TYPE_REF_OBJECT(REF).  Adapted
+   from cp_fold_obj_type_ref, but it tolerates types with no binfo
+   data.  */
+
+tree
+gimple_fold_obj_type_ref (tree ref, tree known_type)
+{
+  HOST_WIDE_INT index;
+  HOST_WIDE_INT i;
+  tree v;
+  tree fndecl;
+
+  if (TYPE_BINFO (known_type) == NULL_TREE)
+    return NULL_TREE;
+
+  v = BINFO_VIRTUALS (TYPE_BINFO (known_type));
+  index = tree_low_cst (OBJ_TYPE_REF_TOKEN (ref), 1);
+  i = 0;
+  while (i != index)
+    {
+      i += (TARGET_VTABLE_USES_DESCRIPTORS
+           ? TARGET_VTABLE_USES_DESCRIPTORS : 1);
+      v = TREE_CHAIN (v);
+    }
+
+  fndecl = TREE_VALUE (v);
+
+#ifdef ENABLE_CHECKING
+  gcc_assert (tree_int_cst_equal (OBJ_TYPE_REF_TOKEN (ref),
+                                 DECL_VINDEX (fndecl)));
+#endif
+
+  cgraph_node (fndecl)->local.vtable_method = true;
+
+  return build_fold_addr_expr (fndecl);
+}
+
 #include "gt-gimple.h"