This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[rfc] METHOD_REF tree node; devirtualizing calls
- From: Richard Henderson <rth at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org, Jason Merrill <jason at redhat dot com>, Ziemowit Laski <zlaski at apple dot com>
- Date: Sat, 19 Jun 2004 11:08:27 -0700
- Subject: [rfc] METHOD_REF tree node; devirtualizing calls
The following passes bootstrap, but I don't know how much that really
means it helps. We are in fact able to devirtualize
// { 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); }
which is certainly more than we could do before.
For Objective-C, -fnext-runtime, we no longer make an indirect call
when not optimizing (we never did when optimizing, afaik), which I
suppose is what Zem was complaining about.
Can anyone think of anything they'd like to see METHOD_REF handle
which it doesn't now?
r~
* tree.def: Remove VTABLE_REF, add METHOD_REF.
* expr.c (expand_expr_real_1): Likewise.
* fold-const.c (non_lvalue): Likewise.
* gimplify.c (gimplify_expr): Likewise.
(gimplify_call_expr): Use is_gimple_call_addr.
* langhooks.h (fold_method_ref): New.
* langhooks-def.h (LANG_HOOKS_FOLD_METHOD_REF): New.
* tree-gimple.c (is_gimple_call_addr): New.
* tree-gimple.h (is_gimple_call_addr): Declare.
* tree-inline.c (inlinable_function_p): Remove dead code.
(estimate_num_insns_1): Remove VTABLE_REF, add METHOD_REF.
* tree-pretty-print.c (dump_generic_node): Likewise.
(print_call_name): Add METHOD_REF.
* tree-ssa-ccp.c (fold_stmt): Fold METHOD_REF.
* tree-ssa-operands.c (get_expr_operands): Add METHOD_REF.
* tree.h (METHOD_REF_EXPR): New.
(METHOD_REF_OBJECT, METHOD_REF_TOKEN): New.
* doc/c-tree.texi (VTABLE_REF): Remove.
* objc/objc-act.c (OBJC_METHOD_DEF): Rename from METHOD_DEF.
(OBJC_METHOD_REF): Rename from METHOD_REF.
(build_objc_method_call): Build a METHOD_REF node.
cp/
* call.c (build_over_call): Don't dereference vfn_ref object here.
* class.c (build_vfn_ref): Do it here. Build a METHOD_REF node.
(cp_bold_method_ref): New.
* cp-lang.c (LANG_HOOKS_FOLD_METHOD_REF): New.
* cp-tree.h (cp_fold_method_ref): Declare.
Index: gcc/expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.654
diff -c -p -d -u -r1.654 expr.c
--- gcc/expr.c 19 Jun 2004 15:33:05 -0000 1.654
+++ gcc/expr.c 19 Jun 2004 17:43:56 -0000
@@ -7440,42 +7440,8 @@ expand_expr_real_1 (tree exp, rtx target
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 METHOD_REF:
+ return expand_expr (METHOD_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: gcc/fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.402
diff -c -p -d -u -r1.402 fold-const.c
--- gcc/fold-const.c 19 Jun 2004 00:17:25 -0000 1.402
+++ gcc/fold-const.c 19 Jun 2004 17:43:56 -0000
@@ -2021,7 +2021,7 @@ non_lvalue (tree x)
case BIT_FIELD_REF:
case BUFFER_REF:
case ARRAY_RANGE_REF:
- case VTABLE_REF:
+ case METHOD_REF:
case REALPART_EXPR:
case IMAGPART_EXPR:
Index: gcc/gimplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gimplify.c,v
retrieving revision 2.18
diff -c -p -d -u -r2.18 gimplify.c
--- gcc/gimplify.c 19 Jun 2004 05:39:14 -0000 2.18
+++ gcc/gimplify.c 19 Jun 2004 17:43:57 -0000
@@ -2007,7 +2007,7 @@ gimplify_call_expr (tree *expr_p, 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));
@@ -3417,12 +3417,15 @@ gimplify_expr (tree *expr_p, tree *pre_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 METHOD_REF:
+ {
+ enum gimplify_status r0, r1;
+ r0 = gimplify_expr (&METHOD_REF_OBJECT (*expr_p), pre_p, post_p,
+ is_gimple_val, fb_rvalue);
+ r1 = gimplify_expr (&METHOD_REF_EXPR (*expr_p), pre_p, post_p,
+ is_gimple_val, fb_rvalue);
+ ret = MIN (r0, r1);
+ }
break;
case MIN_EXPR:
Index: gcc/langhooks-def.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/langhooks-def.h,v
retrieving revision 1.78
diff -c -p -d -u -r1.78 langhooks-def.h
--- gcc/langhooks-def.h 16 Jun 2004 01:21:26 -0000 1.78
+++ gcc/langhooks-def.h 19 Jun 2004 17:43:57 -0000
@@ -200,6 +200,7 @@ extern int lhd_gimplify_expr (tree *, tr
/* Hooks for tree gimplification. */
#define LANG_HOOKS_GIMPLIFY_EXPR lhd_gimplify_expr
+#define LANG_HOOKS_FOLD_METHOD_REF NULL
#define LANG_HOOKS_GIMPLE_BEFORE_INLINING true
/* Tree dump hooks. */
@@ -315,6 +316,7 @@ extern tree lhd_make_node (enum tree_cod
LANG_HOOKS_DECLS, \
LANG_HOOKS_FOR_TYPES_INITIALIZER, \
LANG_HOOKS_GIMPLIFY_EXPR, \
+ LANG_HOOKS_FOLD_METHOD_REF, \
LANG_HOOKS_GIMPLE_BEFORE_INLINING \
}
Index: gcc/langhooks.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/langhooks.h,v
retrieving revision 1.84
diff -c -p -d -u -r1.84 langhooks.h
--- gcc/langhooks.h 16 Jun 2004 01:21:26 -0000 1.84
+++ gcc/langhooks.h 19 Jun 2004 17:43:57 -0000
@@ -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 a METHOD_REF expression to the address of a function.
+ KNOWN_TYPE carries the true type of the METHOD_REF_OBJECT. */
+ tree (*fold_method_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: gcc/tree-gimple.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-gimple.c,v
retrieving revision 2.5
diff -c -p -d -u -r2.5 tree-gimple.c
--- gcc/tree-gimple.c 8 Jun 2004 16:29:57 -0000 2.5
+++ gcc/tree-gimple.c 19 Jun 2004 17:43:57 -0000
@@ -111,7 +111,7 @@ Boston, MA 02111-1307, USA. */
op0 -> lhs
op1 -> rhs
call-stmt: CALL_EXPR
- op0 -> ID | '&' ID
+ op0 -> ID | '&' ID | METHOD_REF
op1 -> arglist
addr-expr-arg : compref | ID
@@ -141,6 +141,7 @@ Boston, MA 02111-1307, USA. */
| unop val
| val binop val
| '(' cast ')' val
+ | method_ref
(cast here stands for all valid C typecasts)
@@ -223,6 +224,7 @@ is_gimple_rhs (tree t)
case STRING_CST:
case COMPLEX_CST:
case VECTOR_CST:
+ case METHOD_REF:
return 1;
default:
@@ -474,6 +476,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) == METHOD_REF
+ || is_gimple_val (t));
+}
/* If T makes a function call, return the corresponding CALL_EXPR operand.
Otherwise, return NULL_TREE. */
Index: gcc/tree-gimple.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-gimple.h,v
retrieving revision 2.6
diff -c -p -d -u -r2.6 tree-gimple.h
--- gcc/tree-gimple.h 16 Jun 2004 01:21:26 -0000 2.6
+++ gcc/tree-gimple.h 19 Jun 2004 17:43:57 -0000
@@ -75,6 +75,8 @@ bool is_gimple_constructor_elt (tree);
/* Returns true iff T is a variable that does not need to live in memory. */
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. */
tree get_call_expr_in (tree t);
Index: gcc/tree-inline.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-inline.c,v
retrieving revision 1.109
diff -c -p -d -u -r1.109 tree-inline.c
--- gcc/tree-inline.c 17 Jun 2004 05:13:25 -0000 1.109
+++ gcc/tree-inline.c 19 Jun 2004 17:43:57 -0000
@@ -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 *wal
case BUFFER_REF:
case ARRAY_REF:
case ARRAY_RANGE_REF:
- case VTABLE_REF:
+ case METHOD_REF:
case EXC_PTR_EXPR: /* ??? */
case FILTER_EXPR: /* ??? */
case COMPOUND_EXPR:
Index: gcc/tree-pretty-print.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-pretty-print.c,v
retrieving revision 2.9
diff -c -p -d -u -r2.9 tree-pretty-print.c
--- gcc/tree-pretty-print.c 16 Jun 2004 23:03:29 -0000 2.9
+++ gcc/tree-pretty-print.c 19 Jun 2004 17:43:57 -0000
@@ -1350,14 +1350,15 @@ dump_generic_node (pretty_printer *buffe
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 METHOD_REF:
+ pp_string (buffer, "METHOD_REF(");
+ dump_generic_node (buffer, METHOD_REF_EXPR (node), spc, flags, false);
+ pp_character (buffer, ';');
+ dump_generic_node (buffer, METHOD_REF_OBJECT (node), spc, flags, false);
+ pp_character (buffer, '-');
pp_character (buffer, '>');
+ dump_generic_node (buffer, METHOD_REF_TOKEN (node), spc, flags, false);
+ pp_character (buffer, ')');
break;
case PHI_NODE:
@@ -1862,6 +1863,7 @@ print_call_name (pretty_printer *buffer,
break;
case SSA_NAME:
+ case METHOD_REF:
dump_generic_node (buffer, op0, 0, 0, false);
break;
Index: gcc/tree-ssa-ccp.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-ccp.c,v
retrieving revision 2.11
diff -c -p -d -u -r2.11 tree-ssa-ccp.c
--- gcc/tree-ssa-ccp.c 18 Jun 2004 14:05:19 -0000 2.11
+++ gcc/tree-ssa-ccp.c 19 Jun 2004 17:43:57 -0000
@@ -1986,13 +1986,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 METHOD_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) == METHOD_REF
+ && lang_hooks.fold_method_ref
+ && TREE_CODE (METHOD_REF_OBJECT (callee)) == ADDR_EXPR
+ && DECL_P (TREE_OPERAND (METHOD_REF_OBJECT (callee), 0)))
+ {
+ tree t;
+
+ t = TREE_TYPE (TREE_OPERAND (METHOD_REF_OBJECT (callee), 0));
+ t = lang_hooks.fold_method_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: gcc/tree-ssa-operands.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-operands.c,v
retrieving revision 2.9
diff -c -p -d -u -r2.9 tree-ssa-operands.c
--- gcc/tree-ssa-operands.c 17 Jun 2004 18:13:18 -0000 2.9
+++ gcc/tree-ssa-operands.c 19 Jun 2004 17:43:57 -0000
@@ -1167,7 +1167,8 @@ get_expr_operands (tree stmt, tree *expr
|| code == TRUTH_AND_EXPR
|| code == TRUTH_OR_EXPR
|| code == TRUTH_XOR_EXPR
- || code == COMPOUND_EXPR)
+ || code == COMPOUND_EXPR
+ || code == METHOD_REF)
{
tree op0 = TREE_OPERAND (expr, 0);
tree op1 = TREE_OPERAND (expr, 1);
Index: gcc/tree.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.def,v
retrieving revision 1.80
diff -c -p -d -u -r1.80 tree.def
--- gcc/tree.def 18 Jun 2004 02:59:16 -0000 1.80
+++ gcc/tree.def 19 Jun 2004 17:43:57 -0000
@@ -382,12 +382,16 @@ DEFTREECODE (ARRAY_REF, "array_ref", 'r'
of the range is taken from the type of the expression. */
DEFTREECODE (ARRAY_RANGE_REF, "array_range_ref", 'r', 2)
-/* 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 virtual method lookup. Operands are:
+ METHOD_REF_EXPR: An expression that evaluates the value to use in case
+ we do not devirtualize.
+ METHOD_REF_OBJECT: Is the object on whose behalf the method is being
+ called. If method devirtualization is done, this how we will infer
+ the true type of the object.
+ METHOD_REF_TOKEN: Something front-end specific used to locate the
+ devirtualized function. Never touched by the middle-end. Good choices
+ would be either an identifier or a vtable index. */
+DEFTREECODE (METHOD_REF, "method_ref", 'e', 3)
/* The exception object from the runtime. */
DEFTREECODE (EXC_PTR_EXPR, "exc_ptr_expr", 'e', 0)
@@ -785,12 +789,12 @@ DEFTREECODE (VA_ARG_EXPR, "va_arg_expr",
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)
/* These types of expressions have no useful value,
and always have side effects. */
Index: gcc/tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.522
diff -c -p -d -u -r1.522 tree.h
--- gcc/tree.h 18 Jun 2004 07:33:08 -0000 1.522
+++ gcc/tree.h 19 Jun 2004 17:43:57 -0000
@@ -1115,6 +1115,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))
+/* METHOD_REF accessors. */
+#define METHOD_REF_EXPR(NODE) TREE_OPERAND (METHOD_REF_CHECK (NODE), 0)
+#define METHOD_REF_OBJECT(NODE) TREE_OPERAND (METHOD_REF_CHECK (NODE), 1)
+#define METHOD_REF_TOKEN(NODE) TREE_OPERAND (METHOD_REF_CHECK (NODE), 2)
+
struct tree_exp GTY(())
{
struct tree_common common;
Index: gcc/cp/call.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.481
diff -c -p -d -u -r1.481 call.c
--- gcc/cp/call.c 16 Jun 2004 01:21:29 -0000 1.481
+++ gcc/cp/call.c 19 Jun 2004 17:43:58 -0000
@@ -4836,7 +4836,7 @@ build_over_call (struct z_candidate *can
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: gcc/cp/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v
retrieving revision 1.617
diff -c -p -d -u -r1.617 class.c
--- gcc/cp/class.c 17 Jun 2004 21:11:37 -0000 1.617
+++ gcc/cp/class.c 19 Jun 2004 17:43:58 -0000
@@ -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 (METHOD_REF, TREE_TYPE (aref), aref, instance_ptr, idx);
+
return aref;
}
@@ -7912,3 +7917,31 @@ build_rtti_vtbl_entries (tree binfo, vtb
*vid->last_init = build_tree_list (NULL_TREE, init);
vid->last_init = &TREE_CHAIN (*vid->last_init);
}
+
+/* Fold a METHOD_REF expression to the address of a function.
+ KNOWN_TYPE carries the true type of METHOD_REF_OBJECT(REF). */
+
+tree
+cp_fold_method_ref (tree ref, tree known_type)
+{
+ HOST_WIDE_INT index = tree_low_cst (METHOD_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 (METHOD_REF_TOKEN (ref), DECL_VINDEX (fndecl)))
+ abort ();
+#endif
+
+ return build_address (fndecl);
+}
Index: gcc/cp/cp-lang.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-lang.c,v
retrieving revision 1.80
diff -c -p -d -u -r1.80 cp-lang.c
--- gcc/cp/cp-lang.c 16 Jun 2004 01:21:29 -0000 1.80
+++ gcc/cp/cp-lang.c 19 Jun 2004 17:43:58 -0000
@@ -182,6 +182,8 @@ static void cxx_initialize_diagnostics (
#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_METHOD_REF
+#define LANG_HOOKS_FOLD_METHOD_REF cp_fold_method_ref
/* Each front end provides its own hooks, for toplev.c. */
const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
Index: gcc/cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.979
diff -c -p -d -u -r1.979 cp-tree.h
--- gcc/cp/cp-tree.h 17 Jun 2004 21:11:38 -0000 1.979
+++ gcc/cp/cp-tree.h 19 Jun 2004 17:43:59 -0000
@@ -3602,6 +3602,7 @@ extern tree get_vtt_name
extern tree get_primary_binfo (tree);
extern void debug_class (tree);
extern void debug_thunks (tree);
+extern tree cp_fold_method_ref (tree, tree);
/* in cvt.c */
extern tree convert_to_reference (tree, tree, int, int, tree);
Index: gcc/doc/c-tree.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/c-tree.texi,v
retrieving revision 1.58
diff -c -p -d -u -r1.58 c-tree.texi
--- gcc/doc/c-tree.texi 17 Jun 2004 22:35:54 -0000 1.58
+++ gcc/doc/c-tree.texi 19 Jun 2004 17:43:59 -0000
@@ -1742,7 +1742,6 @@ This macro returns the attributes on the
@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: gcc/objc/objc-act.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/objc/objc-act.c,v
retrieving revision 1.222
diff -c -p -d -u -r1.222 objc-act.c
--- gcc/objc/objc-act.c 18 Jun 2004 01:20:52 -0000 1.222
+++ gcc/objc/objc-act.c 19 Jun 2004 17:43:59 -0000
@@ -5398,12 +5398,12 @@ build_method_decl (enum tree_code code,
return method_decl;
}
-#define METHOD_DEF 0
-#define METHOD_REF 1
+#define OBJC_METHOD_DEF 0
+#define OBJC_METHOD_REF 1
/* Used by `build_objc_method_call' and `comp_proto_with_proto'. Return
- an argument list for method METH. CONTEXT is either METHOD_DEF or
- METHOD_REF, saying whether we are trying to define a method or call
+ an argument list for method METH. CONTEXT is either OBJC_METHOD_DEF or
+ OBJC_METHOD_REF, saying whether we are trying to define a method or call
one. SUPERFLAG says this is for a send to super; this makes a
difference for the NeXT calling sequence in which the lookup and
the method call are done together. If METH is null, user-defined
@@ -5417,7 +5417,7 @@ get_arg_type_list (tree meth, int contex
/* Receiver type. */
if (flag_next_runtime && superflag)
arglist = build_tree_list (NULL_TREE, super_type);
- else if (context == METHOD_DEF)
+ else if (context == OBJC_METHOD_DEF)
arglist = build_tree_list (NULL_TREE, TREE_TYPE (self_decl));
else
arglist = build_tree_list (NULL_TREE, id_type);
@@ -5852,7 +5852,8 @@ build_objc_method_call (int super_flag,
(build_function_type
(ret_type,
get_arg_type_list
- (method_prototype, METHOD_REF, super_flag)));
+ (method_prototype, OBJC_METHOD_REF, super_flag)));
+ tree method, t;
lookup_object = build_c_cast (rcv_p, lookup_object);
@@ -5873,38 +5874,33 @@ build_objc_method_call (int super_flag,
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 (METHOD_REF, sender_cast, method, lookup_object, size_zero_node);
+ return build_function_call (t, method_params);
}
static void
@@ -7594,7 +7590,8 @@ comp_method_with_proto (tree method, tre
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, OBJC_METHOD_DEF, 0);
/* install return type */
TREE_TYPE (function1_template) = groktypename (TREE_TYPE (proto));
@@ -7643,8 +7640,8 @@ comp_proto_with_proto (tree proto1, tree
return 0;
/* Compare argument types. */
- for (type1 = get_arg_type_list (proto1, METHOD_REF, 0),
- type2 = get_arg_type_list (proto2, METHOD_REF, 0);
+ for (type1 = get_arg_type_list (proto1, OBJC_METHOD_REF, 0),
+ type2 = get_arg_type_list (proto2, OBJC_METHOD_REF, 0);
type1 && type2;
type1 = TREE_CHAIN (type1), type2 = TREE_CHAIN (type2))
{