This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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))

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]