tree.def (VTABLE_REF): Remove.
authorRichard Henderson <rth@gcc.gnu.org>
Wed, 23 Jun 2004 00:26:04 +0000 (17:26 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Wed, 23 Jun 2004 00:26:04 +0000 (17:26 -0700)
        * tree.def (VTABLE_REF): Remove.
        (OBJ_TYPE_REF): New.
        (TRY_CATCH_EXPR, TRY_FINALLY_EXPR): Set type 's'.
        * expr.c (expand_expr_real_1): Replace VTABLE_REF with OBJ_TYPE_REF.
        * fold-const.c (non_lvalue): Likewise.
        * gimplify.c (gimplify_expr): Likewise.
        (gimplify_call_expr): Use is_gimple_call_addr.
        * langhooks-def.h (LANG_HOOKS_FOLD_OBJ_TYPE_REF): New.
        * langhooks.h (fold_obj_type_ref): New.
        * tree-gimple.c (is_gimple_call_addr): New.
        * tree-gimple.h (is_gimple_call_addr): Declare.
        * tree-inline.c (inlinable_function_p): Fix merge error.
        (estimate_num_insns_1): Replace VTABLE_REF with OBJ_TYPE_REF.
        * tree-pretty-print.c (dump_generic_node): Likewise.
        (print_call_name): Handle OBJ_TYPE_REF.
        * tree-ssa-ccp.c (fold_stmt): Fold OBJ_TYPE_REF.
        * tree-ssa-operands.c (get_expr_operands): Handle OBJ_TYPE_REF.
        * tree.h (OBJ_TYPE_REF_EXPR): New.
        (OBJ_TYPE_REF_OBJECT, OBJ_TYPE_REF_TOKEN): New.
        * doc/c-tree.texi (VTABLE_REF): Remove.
        * objc/objc-act.c (build_objc_method_call): Build an OBJ_TYPE_REF.
cp/
        * class.c (build_vfn_ref): Take a pointer not object.  Build
        an OBJ_TYPE_REF.
        (cp_fold_obj_type_ref): New.
        * call.c (build_over_call): Update build_vfn_ref call.
        * cp-lang.c (LANG_HOOKS_FOLD_OBJ_TYPE_REF): New.
        * cp-tree.h (cp_fold_obj_type_ref): Declare.
testsuite/
        * g++.dg/opt/devirt1.C: New.

From-SVN: r83531

23 files changed:
gcc/ChangeLog
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/cp-lang.c
gcc/cp/cp-tree.h
gcc/doc/c-tree.texi
gcc/expr.c
gcc/fold-const.c
gcc/gimplify.c
gcc/langhooks-def.h
gcc/langhooks.h
gcc/objc/objc-act.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/opt/devirt1.C [new file with mode: 0644]
gcc/tree-gimple.c
gcc/tree-gimple.h
gcc/tree-inline.c
gcc/tree-pretty-print.c
gcc/tree-ssa-ccp.c
gcc/tree-ssa-operands.c
gcc/tree.def
gcc/tree.h

index 33baa770363b0d144c1e728594c2c349469444dd..d53095a9c71d8b35357555a831069e2cff84a366 100644 (file)
@@ -1,3 +1,27 @@
+2004-06-22  Richard Henderson  <rth@redhat.com>
+
+       * tree.def (VTABLE_REF): Remove.
+       (OBJ_TYPE_REF): New.
+       (TRY_CATCH_EXPR, TRY_FINALLY_EXPR): Set type 's'.
+       * expr.c (expand_expr_real_1): Replace VTABLE_REF with OBJ_TYPE_REF.
+       * fold-const.c (non_lvalue): Likewise.
+       * gimplify.c (gimplify_expr): Likewise.
+       (gimplify_call_expr): Use is_gimple_call_addr.
+       * langhooks-def.h (LANG_HOOKS_FOLD_OBJ_TYPE_REF): New.
+       * langhooks.h (fold_obj_type_ref): New.
+       * tree-gimple.c (is_gimple_call_addr): New.
+       * tree-gimple.h (is_gimple_call_addr): Declare.
+       * tree-inline.c (inlinable_function_p): Fix merge error.
+       (estimate_num_insns_1): Replace VTABLE_REF with OBJ_TYPE_REF.
+       * tree-pretty-print.c (dump_generic_node): Likewise.
+       (print_call_name): Handle OBJ_TYPE_REF.
+       * tree-ssa-ccp.c (fold_stmt): Fold OBJ_TYPE_REF.
+       * tree-ssa-operands.c (get_expr_operands): Handle OBJ_TYPE_REF.
+       * tree.h (OBJ_TYPE_REF_EXPR): New.
+       (OBJ_TYPE_REF_OBJECT, OBJ_TYPE_REF_TOKEN): New.
+       * doc/c-tree.texi (VTABLE_REF): Remove.
+       * objc/objc-act.c (build_objc_method_call): Build an OBJ_TYPE_REF.
+
 2004-06-22  Richard Henderson  <rth@redhat.com>
 
        PR middle-end/16026
index 1f2eda9b6a08976bc535551fc47f91df410d8ff7..f67eb221408fbe69b9010f2a27334b93f5dffb2a 100644 (file)
@@ -1,3 +1,12 @@
+2004-06-22  Richard Henderson  <rth@redhat.com>
+
+       * class.c (build_vfn_ref): Take a pointer not object.  Build
+       an OBJ_TYPE_REF.
+       (cp_fold_obj_type_ref): New.
+       * call.c (build_over_call): Update build_vfn_ref call.
+       * cp-lang.c (LANG_HOOKS_FOLD_OBJ_TYPE_REF): New.
+       * cp-tree.h (cp_fold_obj_type_ref): Declare.
+
 2004-06-21  Jason Merrill  <jason@redhat.com>
 
        PR c++/16112
index 0c247b8127a435a313d711c6f2d401bbc52abbc0..2a659cce1ef052e8d3b558b32306bb563d5d1915 100644 (file)
@@ -4835,7 +4835,7 @@ build_over_call (struct z_candidate *cand, int flags)
       if (DECL_CONTEXT (fn) && TYPE_JAVA_INTERFACE (DECL_CONTEXT (fn)))
        fn = build_java_interface_fn_ref (fn, *p);
       else
-       fn = build_vfn_ref (build_indirect_ref (*p, 0), DECL_VINDEX (fn));
+       fn = build_vfn_ref (*p, DECL_VINDEX (fn));
       TREE_TYPE (fn) = t;
     }
   else if (DECL_INLINE (fn))
index 1853d4faadfbdd24722ea3c80f0aa814f5d2ad3c..d58577f496f8c59bec2706d4e046dbcb2b2d89bd 100644 (file)
@@ -542,13 +542,15 @@ build_vtbl_ref (tree instance, tree idx)
   return aref;
 }
 
-/* Given an object INSTANCE, return an expression which yields a
-   function pointer corresponding to vtable element INDEX.  */
+/* Given a stable object pointer INSTANCE_PTR, return an expression which
+   yields a function pointer corresponding to vtable element INDEX.  */
 
 tree
-build_vfn_ref (tree instance, tree idx)
+build_vfn_ref (tree instance_ptr, tree idx)
 {
-  tree aref = build_vtbl_ref_1 (instance, idx);
+  tree aref;
+
+  aref = build_vtbl_ref_1 (build_indirect_ref (instance_ptr, 0), idx);
 
   /* When using function descriptors, the address of the
      vtable entry is treated as a function pointer.  */
@@ -556,6 +558,9 @@ build_vfn_ref (tree instance, tree idx)
     aref = build1 (NOP_EXPR, TREE_TYPE (aref),
                   build_unary_op (ADDR_EXPR, aref, /*noconvert=*/1));
 
+  /* Remember this as a method reference, for later devirtualization.  */
+  aref = build (OBJ_TYPE_REF, TREE_TYPE (aref), aref, instance_ptr, idx);
+
   return aref;
 }
 
@@ -7912,3 +7917,31 @@ build_rtti_vtbl_entries (tree binfo, vtbl_init_data* vid)
   *vid->last_init = build_tree_list (NULL_TREE, init);
   vid->last_init = &TREE_CHAIN (*vid->last_init);
 }
+
+/* Fold a OBJ_TYPE_REF expression to the address of a function.
+   KNOWN_TYPE carries the true type of OBJ_TYPE_REF_OBJECT(REF).  */
+
+tree
+cp_fold_obj_type_ref (tree ref, tree known_type)
+{
+  HOST_WIDE_INT index = tree_low_cst (OBJ_TYPE_REF_TOKEN (ref), 1);
+  HOST_WIDE_INT i = 0;
+  tree v = TYPE_BINFO_VIRTUALS (known_type); 
+  tree fndecl;
+
+  while (i != index)
+    {
+      i += (TARGET_VTABLE_USES_DESCRIPTORS
+           ? TARGET_VTABLE_USES_DESCRIPTORS : 1);
+      v = TREE_CHAIN (v);
+    }
+
+  fndecl = BV_FN (v);
+
+#ifdef ENABLE_CHECKING
+  if (!tree_int_cst_equal (OBJ_TYPE_REF_TOKEN (ref), DECL_VINDEX (fndecl)))
+    abort ();
+#endif
+
+  return build_address (fndecl);
+}
index 757ca08e845db45f949c3e8746c81fbd61970ad7..5af5b97333d80b6ab06aacf52cca7e111370580a 100644 (file)
@@ -182,6 +182,8 @@ static void cxx_initialize_diagnostics (diagnostic_context *);
 #define LANG_HOOKS_REGISTER_BUILTIN_TYPE c_register_builtin_type
 #undef LANG_HOOKS_GIMPLIFY_EXPR
 #define LANG_HOOKS_GIMPLIFY_EXPR cp_gimplify_expr
+#undef LANG_HOOKS_FOLD_OBJ_TYPE_REF
+#define LANG_HOOKS_FOLD_OBJ_TYPE_REF cp_fold_obj_type_ref
 
 /* Each front end provides its own hooks, for toplev.c.  */
 const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
index e29e084e0bb20582730cfe0742a2280019e972a7..36d98c60195bdcdc47eb49198137e48b20b21e4d 100644 (file)
@@ -3678,6 +3678,7 @@ extern tree get_vtt_name                        (tree);
 extern tree get_primary_binfo                   (tree);
 extern void debug_class                                (tree);
 extern void debug_thunks                       (tree);
+extern tree cp_fold_obj_type_ref               (tree, tree);
 
 /* in cvt.c */
 extern tree convert_to_reference (tree, tree, int, int, tree);
index dae858a42924e9b97aa3ee4d123d36301b229844..92e87aa4157488eea005a7c0322dfe74942c5890 100644 (file)
@@ -1742,7 +1742,6 @@ This macro returns the attributes on the type @var{type}.
 @tindex SAVE_EXPR
 @tindex TARGET_EXPR
 @tindex AGGR_INIT_EXPR
-@tindex VTABLE_REF
 @tindex VA_ARG_EXPR
 
 The internal representation for expressions is for the most part quite
@@ -2345,17 +2344,6 @@ list.
 
 In either case, the expression is void.
 
-@item VTABLE_REF
-A @code{VTABLE_REF} indicates that the interior expression computes
-a value that is a vtable entry.  It is used with @option{-fvtable-gc}
-to track the reference through to front end to the middle end, at
-which point we transform this to a @code{REG_VTABLE_REF} note, which
-survives the balance of code generation.
-
-The first operand is the expression that computes the vtable reference.
-The second operand is the @code{VAR_DECL} of the vtable.  The third
-operand is an @code{INTEGER_CST} of the byte offset into the vtable.
-
 @item VA_ARG_EXPR
 This node is used to implement support for the C/C++ variable argument-list
 mechanism.  It represents expressions like @code{va_arg (ap, type)}.
index 989a5fa6dca55a15b5489b77a4a20ce571a4f227..259eac1c989a02007fa963f7556f7279e7d85dd1 100644 (file)
@@ -7495,42 +7495,8 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
        return target;
       }
 
-    case VTABLE_REF:
-      {
-       rtx insn, before = get_last_insn (), vtbl_ref;
-
-       /* Evaluate the interior expression.  */
-       subtarget = expand_expr (TREE_OPERAND (exp, 0), target,
-                                tmode, modifier);
-
-       /* Get or create an instruction off which to hang a note.  */
-       if (REG_P (subtarget))
-         {
-           target = subtarget;
-           insn = get_last_insn ();
-           if (insn == before)
-             abort ();
-           if (! INSN_P (insn))
-             insn = prev_nonnote_insn (insn);
-         }
-       else
-         {
-           target = gen_reg_rtx (GET_MODE (subtarget));
-           insn = emit_move_insn (target, subtarget);
-         }
-
-       /* Collect the data for the note.  */
-       vtbl_ref = XEXP (DECL_RTL (TREE_OPERAND (exp, 1)), 0);
-       vtbl_ref = plus_constant (vtbl_ref,
-                                 tree_low_cst (TREE_OPERAND (exp, 2), 0));
-       /* Discard the initial CONST that was added.  */
-       vtbl_ref = XEXP (vtbl_ref, 0);
-
-       REG_NOTES (insn)
-         = gen_rtx_EXPR_LIST (REG_VTABLE_REF, vtbl_ref, REG_NOTES (insn));
-
-       return target;
-      }
+    case OBJ_TYPE_REF:
+      return expand_expr (OBJ_TYPE_REF_EXPR (exp), target, tmode, modifier);
 
       /* Intended for a reference to a buffer of a file-object in Pascal.
         But it's not certain that a special tree code will really be
index 3d4cccaaa6b7426aeb934d080dc368090b9b0ec8..8a09795c624ea856238e5ead0a7e63d821924657 100644 (file)
@@ -2022,7 +2022,7 @@ non_lvalue (tree x)
   case ARRAY_RANGE_REF:
   case BIT_FIELD_REF:
   case BUFFER_REF:
-  case VTABLE_REF:
+  case OBJ_TYPE_REF:
 
   case REALPART_EXPR:
   case IMAGPART_EXPR:
index 36492720ff96d83f9096e9a4b787104aa8370717..f65dd4cdbcdf34c5abc2fc1b53739061696e812b 100644 (file)
@@ -2179,7 +2179,7 @@ gimplify_call_expr (tree *expr_p, tree *pre_p, bool (*gimple_test_f) (tree))
      the calling expression must occur before the actual call.  Force
      gimplify_expr to use an internal post queue.  */
   ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, NULL,
-                      is_gimple_val, fb_rvalue);
+                      is_gimple_call_addr, fb_rvalue);
 
   if (PUSH_ARGS_REVERSED)
     TREE_OPERAND (*expr_p, 1) = nreverse (TREE_OPERAND (*expr_p, 1));
@@ -3709,12 +3709,15 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
          ret = GS_ALL_DONE;
          break;
 
-       case VTABLE_REF:
-         /* This moves much of the actual computation out of the
-            VTABLE_REF.  Perhaps this should be revisited once we want to
-            do clever things with VTABLE_REFs.  */
-         ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
-                              is_gimple_min_lval, fb_lvalue);
+       case OBJ_TYPE_REF:
+         {
+           enum gimplify_status r0, r1;
+           r0 = gimplify_expr (&OBJ_TYPE_REF_OBJECT (*expr_p), pre_p, post_p,
+                               is_gimple_val, fb_rvalue);
+           r1 = gimplify_expr (&OBJ_TYPE_REF_EXPR (*expr_p), pre_p, post_p,
+                               is_gimple_val, fb_rvalue);
+           ret = MIN (r0, r1);
+         }
          break;
 
        case MIN_EXPR:
index cf52b87e0279da09d7df4af01eab7064c2e9bbf3..60642990794123ab40fbe83dd1ff719f343cc260 100644 (file)
@@ -200,6 +200,7 @@ extern int lhd_gimplify_expr (tree *, tree *, tree *);
 
 /* Hooks for tree gimplification.  */
 #define LANG_HOOKS_GIMPLIFY_EXPR lhd_gimplify_expr
+#define LANG_HOOKS_FOLD_OBJ_TYPE_REF NULL
 #define LANG_HOOKS_GIMPLE_BEFORE_INLINING true
 
 /* Tree dump hooks.  */
@@ -315,6 +316,7 @@ extern tree lhd_make_node (enum tree_code);
   LANG_HOOKS_DECLS, \
   LANG_HOOKS_FOR_TYPES_INITIALIZER, \
   LANG_HOOKS_GIMPLIFY_EXPR, \
+  LANG_HOOKS_FOLD_OBJ_TYPE_REF, \
   LANG_HOOKS_GIMPLE_BEFORE_INLINING \
 }
 
index 880ed7c238059e676371951e535a6f07ff3c0fca..a8c0ccac2a79649965400fb13a6c8387cce03f4a 100644 (file)
@@ -419,6 +419,10 @@ struct lang_hooks
      enum gimplify_status, though we can't see that type here.  */
   int (*gimplify_expr) (tree *, tree *, tree *);
 
+  /* Fold an OBJ_TYPE_REF expression to the address of a function.
+     KNOWN_TYPE carries the true type of the OBJ_TYPE_REF_OBJECT.  */
+  tree (*fold_obj_type_ref) (tree, tree);
+
   /* True if the front end has gimplified the function before running the
      inliner, false if the front end generates GENERIC directly.  */
   bool gimple_before_inlining;
index bf739565cad9ec47378d68db4d79b31ddd823298..9664273529db715eb88764a979d5aa77b77992d9 100644 (file)
@@ -5866,6 +5866,7 @@ build_objc_method_call (int super_flag, tree method_prototype,
        (ret_type,
        get_arg_type_list
        (method_prototype, METHOD_REF, super_flag)));
+  tree method, t;
 
   lookup_object = build_c_cast (rcv_p, lookup_object);
 
@@ -5886,38 +5887,33 @@ build_objc_method_call (int super_flag, tree method_prototype,
       method_params = tree_cons (NULL_TREE, lookup_object,
                                 tree_cons (NULL_TREE, selector,
                                            method_params));
-      TREE_USED (sender) = 1;
-      assemble_external (sender);
-      /* We want to cast the sender, not convert it.  */
-      return build_function_call (build_c_cast (sender_cast, sender),
-                                 method_params);
+      method = build_fold_addr_expr (sender);
     }
   else
     {
       /* This is the portable (GNU) way.  */
-      tree method, object;
+      tree object;
 
       /* First, call the lookup function to get a pointer to the method,
         then cast the pointer, then call it with the method arguments.
         Use SAVE_EXPR to avoid evaluating the receiver twice.  */
       lookup_object = save_expr (lookup_object);
       object = (super_flag ? self_decl : lookup_object);
-      TREE_USED (sender) = 1;
-      assemble_external (sender);
-      method
-       = build_function_call (sender,
-                              tree_cons (NULL_TREE, lookup_object,
-                                         tree_cons (NULL_TREE, selector,
-                                                    NULL_TREE)));
+
+      t = tree_cons (NULL_TREE, selector, NULL_TREE);
+      t = tree_cons (NULL_TREE, lookup_object, t);
+      method = build_function_call (sender, t);
 
       /* Pass the object to the method.  */
-      TREE_USED (method) = 1;
-      assemble_external (method);
-      return build_function_call
-            (build_c_cast (sender_cast, method),
-             tree_cons (NULL_TREE, object,
-                        tree_cons (NULL_TREE, selector, method_params)));
+      method_params = tree_cons (NULL_TREE, object,
+                                tree_cons (NULL_TREE, selector,
+                                           method_params));
     }
+
+  /* ??? Selector is not at this point something we can use inside
+     the compiler itself.  Set it to garbage for the nonce.  */
+  t = build (OBJ_TYPE_REF, sender_cast, method, lookup_object, size_zero_node);
+  return build_function_call (t, method_params);
 }
 \f
 static void
@@ -7607,7 +7603,8 @@ comp_method_with_proto (tree method, tree proto)
     function1_template = make_node (FUNCTION_TYPE);
 
   /* Install argument types - normally set by build_function_type.  */
-  TYPE_ARG_TYPES (function1_template) = get_arg_type_list (proto, METHOD_DEF, 0);
+  TYPE_ARG_TYPES (function1_template)
+    = get_arg_type_list (proto, METHOD_DEF, 0);
 
   /* install return type */
   TREE_TYPE (function1_template) = groktypename (TREE_TYPE (proto));
index ab024eccbea40fad18cc000444a65aab5165e975..de2afeab752dcf93d6e843bb953337ab7fbd95ec 100644 (file)
@@ -1,4 +1,8 @@
-2004-06-22 Kelley Cook <kcook@gcc.gnu.org>
+2006-06-22  Richard Henderson  <rth@redhat.com>
+
+       * g++.dg/opt/devirt1.C: New.
+
+2004-06-22  Kelley Cook <kcook@gcc.gnu.org>
 
        * g++.dg/opt/pr15551.C: New testcase.
 
diff --git a/gcc/testsuite/g++.dg/opt/devirt1.C b/gcc/testsuite/g++.dg/opt/devirt1.C
new file mode 100644 (file)
index 0000000..617db05
--- /dev/null
@@ -0,0 +1,7 @@
+// { dg-do compile }
+// { dg-options "-O" }
+// { dg-final { scan-assembler "xyzzy" } }
+
+struct S { S(); virtual void xyzzy(); };
+inline void foo(S *s) { s->xyzzy(); }
+void bar() { S s; foo(&s); }
index 7c992b36adcdca8d3cd51eb1f8b05c08f4ee339f..2deee183964398d9f7c02c13dc1a6a4a7227c00b 100644 (file)
@@ -111,7 +111,7 @@ Boston, MA 02111-1307, USA.  */
        op0 -> lhs
        op1 -> rhs
    call-stmt: CALL_EXPR
-     op0 -> ID | '&' ID
+     op0 -> ID | '&' ID | OBJ_TYPE_REF
      op1 -> arglist
 
    addr-expr-arg : compref | ID
@@ -158,6 +158,7 @@ Boston, MA 02111-1307, USA.  */
              | unop val
              | val binop val
              | '(' cast ')' val
+             | method_ref
 
              (cast here stands for all valid C typecasts)
 
@@ -240,6 +241,7 @@ is_gimple_rhs (tree t)
     case STRING_CST:
     case COMPLEX_CST:
     case VECTOR_CST:
+    case OBJ_TYPE_REF:
       return 1;
 
     default:
@@ -493,6 +495,14 @@ is_gimple_cast (tree t)
           || TREE_CODE (t) == FIX_ROUND_EXPR);
 }
 
+/* Return true if T is a valid op0 of a CALL_EXPR.  */
+
+bool
+is_gimple_call_addr (tree t)
+{
+  return (TREE_CODE (t) == OBJ_TYPE_REF
+         || is_gimple_val (t));
+}
 
 /* If T makes a function call, return the corresponding CALL_EXPR operand.
    Otherwise, return NULL_TREE.  */
index 98f46951af4b525f1c629d6874a751e7d5ec5ec3..9e6209d7afae58497951cc088c1be6bb2805222f 100644 (file)
@@ -75,6 +75,8 @@ extern bool is_gimple_constructor_elt (tree);
 /* Returns true iff T is a variable that does not need to live in memory.  */
 extern bool is_gimple_non_addressable (tree t);
 
+/* Returns true iff T is a valid call address expression.  */
+bool is_gimple_call_addr (tree);
 /* If T makes a function call, returns the CALL_EXPR operand.  */
 extern tree get_call_expr_in (tree t);
 
index deb73605ca2591541ac4c3b510ee5e7f64e4df92..1d6e4c4dbaef1c46b12bd6ec2b07e2849d4d57b5 100644 (file)
@@ -1136,12 +1136,6 @@ inlinable_function_p (tree fn)
   else if (!DECL_INLINE (fn) && !flag_unit_at_a_time)
     inlinable = false;
 
-#ifdef INLINER_FOR_JAVA
-  /* Synchronized methods can't be inlined.  This is a bug.  */
-  else if (METHOD_SYNCHRONIZED (fn))
-    inlinable = false;
-#endif /* INLINER_FOR_JAVA */
-
   else if (inline_forbidden_p (fn))
     {
       /* See if we should warn about uninlinable functions.  Previously,
@@ -1203,7 +1197,7 @@ estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data)
     case BUFFER_REF:
     case ARRAY_REF:
     case ARRAY_RANGE_REF:
-    case VTABLE_REF:
+    case OBJ_TYPE_REF:
     case EXC_PTR_EXPR: /* ??? */
     case FILTER_EXPR: /* ??? */
     case COMPOUND_EXPR:
index 52aa18194171c920e6f62fd2dbd412bb03db639f..6ebf07564c7c0504b9b83e48008cb1901d41675a 100644 (file)
@@ -1367,14 +1367,15 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
       pp_character (buffer, ':');
       break;
 
-    case VTABLE_REF:
-      pp_string (buffer, "VTABLE_REF <(");
-      dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
-      pp_string (buffer, "),");
-      dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
-      pp_character (buffer, ',');
-      dump_generic_node (buffer, TREE_OPERAND (node, 2), spc, flags, false);
+    case OBJ_TYPE_REF:
+      pp_string (buffer, "OBJ_TYPE_REF(");
+      dump_generic_node (buffer, OBJ_TYPE_REF_EXPR (node), spc, flags, false);
+      pp_character (buffer, ';');
+      dump_generic_node (buffer, OBJ_TYPE_REF_OBJECT (node), spc, flags, false);
+      pp_character (buffer, '-');
       pp_character (buffer, '>');
+      dump_generic_node (buffer, OBJ_TYPE_REF_TOKEN (node), spc, flags, false);
+      pp_character (buffer, ')');
       break;
 
     case PHI_NODE:
@@ -1880,6 +1881,7 @@ print_call_name (pretty_printer *buffer, tree node)
       break;
 
     case SSA_NAME:
+    case OBJ_TYPE_REF:
       dump_generic_node (buffer, op0, 0, 0, false);
       break;
 
index 658a2cb9061be819002a733aaf293d8f3b4132e5..ef0c12be3783b9e55b03b733d6532e256549d50e 100644 (file)
@@ -2037,13 +2037,41 @@ fold_stmt (tree *stmt_p)
     return changed;
   result = NULL_TREE;
 
-  /* Check for builtins that CCP can handle using information not
-     available in the generic fold routines.  */
   if (TREE_CODE (rhs) == CALL_EXPR)
     {
-      tree callee = get_callee_fndecl (rhs);
+      tree callee;
+
+      /* Check for builtins that CCP can handle using information not
+        available in the generic fold routines.  */
+      callee = get_callee_fndecl (rhs);
       if (callee && DECL_BUILT_IN (callee))
        result = ccp_fold_builtin (stmt, rhs);
+      else
+       {
+         /* Check for resolvable OBJ_TYPE_REF.  The only sorts we can resolve
+            here are when we've propagated the address of a decl into the
+            object slot.  */
+         /* ??? Should perhaps do this in fold proper.  However, doing it
+            there requires that we create a new CALL_EXPR, and that requires
+            copying EH region info to the new node.  Easier to just do it
+            here where we can just smash the call operand.  */
+         callee = TREE_OPERAND (rhs, 0);
+         if (TREE_CODE (callee) == OBJ_TYPE_REF
+             && lang_hooks.fold_obj_type_ref
+             && TREE_CODE (OBJ_TYPE_REF_OBJECT (callee)) == ADDR_EXPR
+             && DECL_P (TREE_OPERAND (OBJ_TYPE_REF_OBJECT (callee), 0)))
+           {
+             tree t;
+
+             t = TREE_TYPE (TREE_OPERAND (OBJ_TYPE_REF_OBJECT (callee), 0));
+             t = lang_hooks.fold_obj_type_ref (callee, t);
+             if (t)
+               {
+                 TREE_OPERAND (rhs, 0) = t;
+                 changed = true;
+               }
+           }
+       }
     }
 
   /* If we couldn't fold the RHS, hand over to the generic fold routines.  */
index 08330abd51f9934577a342f9a6565dbadc62c6a6..68da398c9ef7588f8166536ccebbaa21957f519c 100644 (file)
@@ -1169,7 +1169,8 @@ get_expr_operands (tree stmt, tree *expr_p, int flags, voperands_t prev_vops)
       || code == TRUTH_AND_EXPR
       || code == TRUTH_OR_EXPR
       || code == TRUTH_XOR_EXPR
-      || code == COMPOUND_EXPR)
+      || code == COMPOUND_EXPR
+      || code == OBJ_TYPE_REF)
     {
       tree op0 = TREE_OPERAND (expr, 0);
       tree op1 = TREE_OPERAND (expr, 1);
index 12a6394c5b109ef6936455a9517419b598c4e63c..57596a2b45827add95517ff7a3d8877a36d9481c 100644 (file)
@@ -387,12 +387,17 @@ DEFTREECODE (ARRAY_REF, "array_ref", 'r', 4)
    of the range is taken from the type of the expression.  */
 DEFTREECODE (ARRAY_RANGE_REF, "array_range_ref", 'r', 4)
 
-/* Vtable indexing.  Carries data useful for emitting information
-   for vtable garbage collection.
-   Operand 0: an array_ref (or equivalent expression)
-   Operand 1: the vtable base (must be a var_decl)
-   Operand 2: index into vtable (must be an integer_cst).  */
-DEFTREECODE (VTABLE_REF, "vtable_ref", 'r', 3)
+/* Used to represent lookup of runtime type dependent data.  Often this is
+   a reference to a vtable, but it needn't be.  Operands are:
+   OBJ_TYPE_REF_EXPR: An expression that evaluates the value to use.
+   OBJ_TYPE_REF_OBJECT: Is the object on whose behalf the lookup is
+   being performed.  Through this the optimizers may be able to statically
+   determine the dynamic type of the object.
+   OBJ_TYPE_REF_TOKEN: Something front-end specific used to resolve the
+   reference to something simpler, usually to the address of a DECL.
+   Never touched by the middle-end.  Good choices would be either an
+   identifier or a vtable index.  */
+DEFTREECODE (OBJ_TYPE_REF, "obj_type_ref", 'e', 3)
 
 /* The exception object from the runtime.  */
 DEFTREECODE (EXC_PTR_EXPR, "exc_ptr_expr", 'e', 0)
@@ -790,12 +795,12 @@ DEFTREECODE (VA_ARG_EXPR, "va_arg_expr", 'e', 1)
 
    This differs from TRY_FINALLY_EXPR in that operand 2 is not evaluated
    on a normal or jump exit, only on an exception.  */
-DEFTREECODE (TRY_CATCH_EXPR, "try_catch_expr", 'e', 2)
+DEFTREECODE (TRY_CATCH_EXPR, "try_catch_expr", 's', 2)
 
 /* Evaluate the first operand.
    The second operand is a cleanup expression which is evaluated
    on any exit (normal, exception, or jump out) from this expression.  */
-DEFTREECODE (TRY_FINALLY_EXPR, "try_finally", 'e', 2)
+DEFTREECODE (TRY_FINALLY_EXPR, "try_finally", 's', 2)
 \f
 /* These types of expressions have no useful value,
    and always have side effects.  */
index 9b753a341f6ef2d3dad02ce82d8c2697d30ead57..c404b84d1bcd7be588703ebeabc3eec8e606cd9d 100644 (file)
@@ -1114,6 +1114,11 @@ struct tree_vec GTY(())
 #define EH_FILTER_FAILURE(NODE)        TREE_OPERAND (EH_FILTER_EXPR_CHECK (NODE), 1)
 #define EH_FILTER_MUST_NOT_THROW(NODE) TREE_STATIC (EH_FILTER_EXPR_CHECK (NODE))
 
+/* OBJ_TYPE_REF accessors.  */
+#define OBJ_TYPE_REF_EXPR(NODE)          TREE_OPERAND (OBJ_TYPE_REF_CHECK (NODE), 0)
+#define OBJ_TYPE_REF_OBJECT(NODE) TREE_OPERAND (OBJ_TYPE_REF_CHECK (NODE), 1)
+#define OBJ_TYPE_REF_TOKEN(NODE)  TREE_OPERAND (OBJ_TYPE_REF_CHECK (NODE), 2)
+
 struct tree_exp GTY(())
 {
   struct tree_common common;