This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: more get_member_function_from_ptrfunc cleanup
- From: Jason Merrill <jason at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 09 May 2002 18:15:51 +0100
- Subject: C++ PATCH: more get_member_function_from_ptrfunc cleanup
While thinking about PMF optimization, I decided to tidy the function up a
bit. The only significant effect of this patch is to switch from using a
BIT_AND_EXPR to a MINUS_EXPR for extracting the vtable index, which should
produce tighter code.
Tested i686-pc-linux-gnu, applied trunk only.
2002-05-09 Jason Merrill <jason@redhat.com>
* typeck.c (get_member_function_from_ptrfunc): Reorganize.
Use subtraction rather than a bitmask to get the index.
* cvt.c (cp_convert_to_pointer): Bail on an error_mark_node.
*** typeck.c.~1~ Thu May 9 11:25:48 2002
--- typeck.c Thu May 9 18:06:22 2002
*************** build_x_function_call (function, params,
*** 2821,2827 ****
}
/* Resolve a pointer to member function. INSTANCE is the object
! instance to use, if the member points to a virtual member. */
tree
get_member_function_from_ptrfunc (instance_ptrptr, function)
--- 2821,2834 ----
}
/* Resolve a pointer to member function. INSTANCE is the object
! instance to use, if the member points to a virtual member.
!
! This used to avoid checking for virtual functions if basetype
! has no virtual functions, according to an earlier ANSI draft.
! With the final ISO C++ rules, such an optimization is
! incorrect: A pointer to a derived member can be static_cast
! to pointer-to-base-member, as long as the dynamic object
! later has the right member. */
tree
get_member_function_from_ptrfunc (instance_ptrptr, function)
*************** get_member_function_from_ptrfunc (instan
*** 2833,2853 ****
if (TYPE_PTRMEMFUNC_P (TREE_TYPE (function)))
{
! tree fntype, idx, e1, delta, delta2, e2, e3, vtbl;
! tree instance, basetype;
! tree mask;
tree instance_ptr = *instance_ptrptr;
!
! if (instance_ptr == error_mark_node
! && TREE_CODE (function) == PTRMEM_CST)
{
! /* Extracting the function address from a pmf is only
! allowed with -Wno-pmf-conversions. It only works for
! pmf constants. */
! e1 = build_addr_func (PTRMEM_CST_MEMBER (function));
! e1 = convert (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (function)), e1);
! return e1;
}
if (TREE_SIDE_EFFECTS (instance_ptr))
--- 2840,2865 ----
if (TYPE_PTRMEMFUNC_P (TREE_TYPE (function)))
{
! tree idx, delta, e1, e2, e3, vtbl, basetype;
! tree fntype = TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (function));
tree instance_ptr = *instance_ptrptr;
! if (instance_ptr == error_mark_node)
{
! if (TREE_CODE (function) == PTRMEM_CST)
! {
! /* Extracting the function address from a pmf is only
! allowed with -Wno-pmf-conversions. It only works for
! pmf constants. */
! e1 = build_addr_func (PTRMEM_CST_MEMBER (function));
! e1 = convert (fntype, e1);
! return e1;
! }
! else
! {
! error ("object missing in use of `%E'", function);
! return error_mark_node;
! }
}
if (TREE_SIDE_EFFECTS (instance_ptr))
*************** get_member_function_from_ptrfunc (instan
*** 2856,2919 ****
if (TREE_SIDE_EFFECTS (function))
function = save_expr (function);
! fntype = TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (function));
! basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (fntype));
!
! /* Convert down to the right base, before using the instance. */
! instance = lookup_base (TREE_TYPE (TREE_TYPE (instance_ptr)), basetype,
! ba_check, NULL);
! instance = build_base_path (PLUS_EXPR, instance_ptr, instance, 1);
! if (instance == error_mark_node && instance_ptr != error_mark_node)
! return instance;
!
e3 = PFN_FROM_PTRMEMFUNC (function);
!
! vtbl = build1 (NOP_EXPR, build_pointer_type (ptr_type_node), instance);
! TREE_CONSTANT (vtbl) = TREE_CONSTANT (instance);
!
! delta = cp_convert (ptrdiff_type_node,
! build_component_ref (function, delta_identifier,
! NULL_TREE, 0));
!
! /* This used to avoid checking for virtual functions if basetype
! has no virtual functions, according to an earlier ANSI draft.
! With the final ISO C++ rules, such an optimization is
! incorrect: A pointer to a derived member can be static_cast
! to pointer-to-base-member, as long as the dynamic object
! later has the right member. */
!
idx = build1 (NOP_EXPR, vtable_index_type, e3);
switch (TARGET_PTRMEMFUNC_VBIT_LOCATION)
{
case ptrmemfunc_vbit_in_pfn:
- /* Mask out the virtual bit from the index. */
e1 = cp_build_binary_op (BIT_AND_EXPR, idx, integer_one_node);
! mask = build1 (NOP_EXPR, vtable_index_type, build_int_2 (~1, ~0));
! idx = cp_build_binary_op (BIT_AND_EXPR, idx, mask);
break;
case ptrmemfunc_vbit_in_delta:
! e1 = cp_build_binary_op (BIT_AND_EXPR,
! delta, integer_one_node);
! delta = cp_build_binary_op (RSHIFT_EXPR,
! build1 (NOP_EXPR, vtable_index_type,
! delta),
! integer_one_node);
break;
default:
abort ();
}
! /* DELTA2 is the amount by which to adjust the `this' pointer
! to find the vtbl. */
! delta2 = delta;
! vtbl = build
! (PLUS_EXPR,
! build_pointer_type (build_pointer_type (vtable_entry_type)),
! vtbl, cp_convert (ptrdiff_type_node, delta2));
vtbl = build_indirect_ref (vtbl, NULL);
e2 = fold (build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, idx));
e2 = build_indirect_ref (e2, NULL);
--- 2868,2914 ----
if (TREE_SIDE_EFFECTS (function))
function = save_expr (function);
! /* Start by extracting all the information from the PMF itself. */
e3 = PFN_FROM_PTRMEMFUNC (function);
! delta = build_component_ref (function, delta_identifier, NULL_TREE, 0);
idx = build1 (NOP_EXPR, vtable_index_type, e3);
switch (TARGET_PTRMEMFUNC_VBIT_LOCATION)
{
case ptrmemfunc_vbit_in_pfn:
e1 = cp_build_binary_op (BIT_AND_EXPR, idx, integer_one_node);
! idx = cp_build_binary_op (MINUS_EXPR, idx, integer_one_node);
break;
case ptrmemfunc_vbit_in_delta:
! e1 = cp_build_binary_op (BIT_AND_EXPR, delta, integer_one_node);
! delta = cp_build_binary_op (RSHIFT_EXPR, delta, integer_one_node);
break;
default:
abort ();
}
! /* Convert down to the right base before using the instance. First
! use the type... */
! basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (fntype));
! basetype = lookup_base (TREE_TYPE (TREE_TYPE (instance_ptr)),
! basetype, ba_check, NULL);
! instance_ptr = build_base_path (PLUS_EXPR, instance_ptr, basetype, 1);
! if (instance_ptr == error_mark_node)
! return error_mark_node;
! /* ...and then the delta in the PMF. */
! instance_ptr = build (PLUS_EXPR, TREE_TYPE (instance_ptr),
! instance_ptr, delta);
!
! /* Hand back the adjusted 'this' argument to our caller. */
! *instance_ptrptr = instance_ptr;
!
! /* Next extract the vtable pointer from the object. */
! vtbl = build1 (NOP_EXPR, build_pointer_type (vtbl_ptr_type_node),
! instance_ptr);
vtbl = build_indirect_ref (vtbl, NULL);
+ /* Finally, extract the function pointer from the vtable. */
e2 = fold (build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, idx));
e2 = build_indirect_ref (e2, NULL);
*************** get_member_function_from_ptrfunc (instan
*** 2932,2945 ****
e1 = build (COMPOUND_EXPR, TREE_TYPE (e1),
instance_ptr, e1);
- *instance_ptrptr = build (PLUS_EXPR, TREE_TYPE (instance_ptr),
- instance_ptr, delta);
-
- if (instance_ptr == error_mark_node
- && TREE_CODE (e1) != ADDR_EXPR
- && TREE_CODE (TREE_OPERAND (e1, 0)) != FUNCTION_DECL)
- error ("object missing in `%E'", function);
-
function = e1;
}
return function;
--- 2927,2932 ----
*** cvt.c.~1~ Thu Apr 25 01:19:30 2002
--- cvt.c Thu May 9 12:00:42 2002
*************** cp_convert_to_pointer (type, expr, force
*** 130,135 ****
--- 130,138 ----
intype = TREE_TYPE (expr);
}
+ if (expr == error_mark_node)
+ return error_mark_node;
+
form = TREE_CODE (intype);
if (POINTER_TYPE_P (intype))