This is the mail archive of the gcc@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]

PATCH to avoid copying tail padding (was: GCC 3.2)


Here's the patch I'm applying to the trunk.  The patch for 3.2.1 will be a
bit different.

2002-08-02  Jason Merrill  <jason@redhat.com>

	* langhooks-def.h (LANG_HOOKS_EXPR_SIZE): New macro.
	* langhooks.c (lhd_expr_size): Define default.
	* langhooks.h (struct lang_hooks): Add expr_size.
	* explow.c (expr_size): Call it.
	* expr.c (store_expr): Don't copy an expression of size zero.
	(expand_expr) [CONSTRUCTOR]: Use expr_size to calculate how much
	to store.
	* Makefile.in (builtins.o): Depend on langhooks.h.
cp/
	* cp-lang.c (LANG_HOOKS_EXPR_SIZE): Define.
	(cp_expr_size): New fn.
	* call.c (build_over_call): Lose empty class hackery.
	(convert_arg_to_ellipsis): Promote non-POD warning to error.
	* typeck.c (build_modify_expr): Don't use save_expr on an lvalue.

*** ./cp/call.c.~1~	Fri Aug  2 10:20:58 2002
--- ./cp/call.c	Fri Aug  2 12:18:19 2002
*************** convert_arg_to_ellipsis (arg)
*** 4111,4119 ****
    
    if (arg != error_mark_node && ! pod_type_p (TREE_TYPE (arg)))
      {
!       /* Undefined behaviour [expr.call] 5.2.2/7.  */
!       warning ("cannot pass objects of non-POD type `%#T' through `...'",
! 		  TREE_TYPE (arg));
      }
  
    return arg;
--- 4111,4122 ----
    
    if (arg != error_mark_node && ! pod_type_p (TREE_TYPE (arg)))
      {
!       /* Undefined behaviour [expr.call] 5.2.2/7.  We used to just warn
! 	 here and do a bitwise copy, but now cp_expr_size will abort if we
! 	 try to do that.  */
!       error ("cannot pass objects of non-POD type `%#T' through `...'",
! 	     TREE_TYPE (arg));
!       arg = error_mark_node;
      }
  
    return arg;
*************** build_over_call (cand, args, flags)
*** 4436,4450 ****
  	  else if (TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn)))
  	    return build_target_expr_with_type (arg, DECL_CONTEXT (fn));
  	}
!       else if ((!real_lvalue_p (arg)
! 		|| TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn)))
! 	       /* Empty classes have padding which can be hidden
! 	          inside an (empty) base of the class. This must not
! 	          be touched as it might overlay things. When the
! 	          gcc core learns about empty classes, we can treat it
! 	          like other classes. */
! 	       && !(is_empty_class (DECL_CONTEXT (fn))
! 		    && TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn))))
  	{
  	  tree address;
  	  tree to = stabilize_reference
--- 4439,4446 ----
  	  else if (TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn)))
  	    return build_target_expr_with_type (arg, DECL_CONTEXT (fn));
  	}
!       else if (!real_lvalue_p (arg)
! 	       || TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn)))
  	{
  	  tree address;
  	  tree to = stabilize_reference
*************** build_over_call (cand, args, flags)
*** 4466,4489 ****
  	(build_indirect_ref (TREE_VALUE (converted_args), 0));
  
        arg = build_indirect_ref (TREE_VALUE (TREE_CHAIN (converted_args)), 0);
!       if (is_empty_class (TREE_TYPE (to)))
! 	{
! 	  TREE_USED (arg) = 1;
! 
! 	  val = build (COMPOUND_EXPR, DECL_CONTEXT (fn), arg, to);
! 	  /* Even though the assignment may not actually result in any
! 	     code being generated, we do not want to warn about the
! 	     assignment having no effect.  That would be confusing to
! 	     users who may be performing the assignment as part of a
! 	     generic algorithm, for example.
! 	     
! 	     Ideally, the notions of having side-effects and of being
! 	     useless would be orthogonal.  */
! 	  TREE_SIDE_EFFECTS (val) = 1;
! 	  TREE_NO_UNUSED_WARNING (val) = 1;
! 	}
!       else
! 	val = build (MODIFY_EXPR, TREE_TYPE (to), to, arg);
        return val;
      }
  
--- 4462,4468 ----
  	(build_indirect_ref (TREE_VALUE (converted_args), 0));
  
        arg = build_indirect_ref (TREE_VALUE (TREE_CHAIN (converted_args)), 0);
!       val = build (MODIFY_EXPR, TREE_TYPE (to), to, arg);
        return val;
      }
  
*** ./cp/typeck.c.~1~	Fri Aug  2 10:21:01 2002
--- ./cp/typeck.c	Fri Aug  2 10:22:57 2002
*************** build_modify_expr (lhs, modifycode, rhs)
*** 5077,5084 ****
  	   except that the RHS goes through a save-expr
  	   so the code to compute it is only emitted once.  */
  	tree cond;
  
! 	rhs = save_expr (rhs);
  	
  	/* Check this here to avoid odd errors when trying to convert
  	   a throw to the type of the COND_EXPR.  */
--- 5077,5085 ----
  	   except that the RHS goes through a save-expr
  	   so the code to compute it is only emitted once.  */
  	tree cond;
+ 	tree preeval = NULL_TREE;
  
! 	rhs = stabilize_expr (rhs, &preeval);
  	
  	/* Check this here to avoid odd errors when trying to convert
  	   a throw to the type of the COND_EXPR.  */
*************** build_modify_expr (lhs, modifycode, rhs)
*** 5098,5107 ****
  	  return cond;
  	/* Make sure the code to compute the rhs comes out
  	   before the split.  */
! 	return build (COMPOUND_EXPR, TREE_TYPE (lhs),
! 		      /* Cast to void to suppress warning
! 			 from warn_if_unused_value.  */
! 		      cp_convert (void_type_node, rhs), cond);
        }
        
      case OFFSET_REF:
--- 5099,5105 ----
  	  return cond;
  	/* Make sure the code to compute the rhs comes out
  	   before the split.  */
! 	return build (COMPOUND_EXPR, TREE_TYPE (lhs), preeval, cond);
        }
        
      case OFFSET_REF:
*** ./cp/cp-lang.c.~1~	Fri Jul 26 16:56:17 2002
--- ./cp/cp-lang.c	Fri Aug  2 10:22:58 2002
*************** Boston, MA 02111-1307, USA.  */
*** 31,36 ****
--- 31,37 ----
  static HOST_WIDE_INT cxx_get_alias_set PARAMS ((tree));
  static bool ok_to_generate_alias_set_for_type PARAMS ((tree));
  static bool cxx_warn_unused_global_decl PARAMS ((tree));
+ static tree cp_expr_size PARAMS ((tree));
  
  #undef LANG_HOOKS_NAME
  #define LANG_HOOKS_NAME "GNU C++"
*************** static bool cxx_warn_unused_global_decl 
*** 133,138 ****
--- 134,141 ----
  #define LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN cp_dump_tree
  #undef LANG_HOOKS_TREE_DUMP_TYPE_QUALS_FN
  #define LANG_HOOKS_TREE_DUMP_TYPE_QUALS_FN cp_type_quals
+ #undef LANG_HOOKS_EXPR_SIZE
+ #define LANG_HOOKS_EXPR_SIZE cp_expr_size
  
  #undef LANG_HOOKS_MAKE_TYPE
  #define LANG_HOOKS_MAKE_TYPE cxx_make_type
*************** cxx_warn_unused_global_decl (decl)
*** 280,282 ****
--- 283,310 ----
  
    return true;
  }
+ 
+ /* Langhook for expr_size: Tell the backend that the value of an expression
+    of non-POD class type does not include any tail padding; a derived class
+    might have allocated something there.  */
+ 
+ static tree
+ cp_expr_size (exp)
+      tree exp;
+ {
+   if (CLASS_TYPE_P (TREE_TYPE (exp)))
+     {
+       /* The backend should not be interested in the size of an expression
+ 	 of a type with both of these set; all copies of such types must go
+ 	 through a constructor or assignment op.  */
+       if (TYPE_HAS_COMPLEX_INIT_REF (TREE_TYPE (exp))
+ 	  && TYPE_HAS_COMPLEX_ASSIGN_REF (TREE_TYPE (exp)))
+ 	abort ();
+       /* This would be wrong for a type with virtual bases, but they are
+ 	 caught by the abort above.  */
+       return CLASSTYPE_SIZE_UNIT (TREE_TYPE (exp));
+     }
+   else
+     /* Use the default code.  */
+     return lhd_expr_size (exp);
+ }
*** ./Makefile.in.~1~	Fri Aug  2 10:20:21 2002
--- ./Makefile.in	Fri Aug  2 10:22:58 2002
*************** expr.o : expr.c $(CONFIG_H) $(SYSTEM_H) 
*** 1427,1433 ****
  builtins.o : builtins.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
     $(TARGET_H) function.h $(REGS_H) $(EXPR_H) $(OPTABS_H) insn-config.h \
     $(RECOG_H) output.h typeclass.h hard-reg-set.h toplev.h hard-reg-set.h \
!    except.h $(TM_P_H) $(PREDICT_H) libfuncs.h real.h
  calls.o : calls.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
     $(EXPR_H) langhooks.h \
     libfuncs.h $(REGS_H) toplev.h output.h function.h $(TIMEVAR_H) $(TM_P_H)
--- 1427,1433 ----
  builtins.o : builtins.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
     $(TARGET_H) function.h $(REGS_H) $(EXPR_H) $(OPTABS_H) insn-config.h \
     $(RECOG_H) output.h typeclass.h hard-reg-set.h toplev.h hard-reg-set.h \
!    except.h $(TM_P_H) $(PREDICT_H) libfuncs.h real.h langhooks.h
  calls.o : calls.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
     $(EXPR_H) langhooks.h \
     libfuncs.h $(REGS_H) toplev.h output.h function.h $(TIMEVAR_H) $(TM_P_H)
*** ./explow.c.~1~	Wed Jul 24 17:17:07 2002
--- ./explow.c	Fri Aug  2 10:22:58 2002
*************** Software Foundation, 59 Temple Place - S
*** 34,39 ****
--- 34,40 ----
  #include "insn-config.h"
  #include "ggc.h"
  #include "recog.h"
+ #include "langhooks.h"
  
  static rtx break_out_memory_refs	PARAMS ((rtx));
  static void emit_stack_probe		PARAMS ((rtx));
*************** rtx
*** 285,304 ****
  expr_size (exp)
       tree exp;
  {
!   tree size;
! 
!   if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'd'
!       && DECL_SIZE_UNIT (exp) != 0)
!     size = DECL_SIZE_UNIT (exp);
!   else
!     size = size_in_bytes (TREE_TYPE (exp));
  
    if (TREE_CODE (size) != INTEGER_CST
        && contains_placeholder_p (size))
      size = build (WITH_RECORD_EXPR, sizetype, size, exp);
  
    return expand_expr (size, NULL_RTX, TYPE_MODE (sizetype), 0);
- 
  }
  
  /* Return a copy of X in which all memory references
--- 286,298 ----
  expr_size (exp)
       tree exp;
  {
!   tree size = (*lang_hooks.expr_size) (exp);
  
    if (TREE_CODE (size) != INTEGER_CST
        && contains_placeholder_p (size))
      size = build (WITH_RECORD_EXPR, sizetype, size, exp);
  
    return expand_expr (size, NULL_RTX, TYPE_MODE (sizetype), 0);
  }
  
  /* Return a copy of X in which all memory references
*** ./expr.c.~1~	Fri Aug  2 10:20:27 2002
--- ./expr.c	Fri Aug  2 10:22:58 2002
*************** store_expr (exp, target, want_value)
*** 4241,4246 ****
--- 4241,4248 ----
         || (temp != target && (side_effects_p (temp)
  			      || side_effects_p (target))))
        && TREE_CODE (exp) != ERROR_MARK
+       /* If there's nothing to copy, don't bother.  */
+       && expr_size (exp) != const0_rtx
        && ! dont_store_target
  	 /* If store_expr stores a DECL whose DECL_RTL(exp) == TARGET,
  	    but TARGET is not valid memory reference, TEMP will differ
*************** expand_expr (exp, target, tmode, modifie
*** 6810,6817 ****
  						       * TYPE_QUAL_CONST))),
  			     0, TREE_ADDRESSABLE (exp), 1);
  
! 	  store_constructor (exp, target, 0,
! 			     int_size_in_bytes (TREE_TYPE (exp)));
  	  return target;
  	}
  
--- 6812,6818 ----
  						       * TYPE_QUAL_CONST))),
  			     0, TREE_ADDRESSABLE (exp), 1);
  
! 	  store_constructor (exp, target, 0, INTVAL (expr_size (exp)));
  	  return target;
  	}
  
*** ./langhooks-def.h.~1~	Wed Jul 24 17:17:16 2002
--- ./langhooks-def.h	Fri Aug  2 10:22:58 2002
*************** extern void lhd_set_decl_assembler_name 
*** 62,67 ****
--- 62,68 ----
  extern bool lhd_warn_unused_global_decl PARAMS ((tree));
  extern void lhd_incomplete_type_error PARAMS ((tree, tree));
  extern tree lhd_type_promotes_to PARAMS ((tree));
+ extern tree lhd_expr_size PARAMS ((tree));
  
  /* Declarations of default tree inlining hooks.  */
  tree lhd_tree_inlining_walk_subtrees		PARAMS ((tree *, int *,
*************** tree lhd_tree_inlining_convert_parm_for_
*** 109,114 ****
--- 110,116 ----
  #define LANG_HOOKS_PRINT_IDENTIFIER	lhd_print_tree_nothing
  #define LANG_HOOKS_PRINT_ERROR_FUNCTION lhd_print_error_function
  #define LANG_HOOKS_DECL_PRINTABLE_NAME	lhd_decl_printable_name
+ #define LANG_HOOKS_EXPR_SIZE		lhd_expr_size
  
  #define LANG_HOOKS_FUNCTION_INIT	lhd_do_nothing_f
  #define LANG_HOOKS_FUNCTION_FINAL	lhd_do_nothing_f
*************** int lhd_tree_dump_type_quals			PARAMS ((
*** 247,252 ****
--- 249,255 ----
    LANG_HOOKS_PRINT_IDENTIFIER, \
    LANG_HOOKS_DECL_PRINTABLE_NAME, \
    LANG_HOOKS_PRINT_ERROR_FUNCTION, \
+   LANG_HOOKS_EXPR_SIZE, \
    LANG_HOOKS_ATTRIBUTE_TABLE, \
    LANG_HOOKS_COMMON_ATTRIBUTE_TABLE, \
    LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE, \
*** ./langhooks.c.~1~	Fri Jun  7 13:14:46 2002
--- ./langhooks.c	Fri Aug  2 10:22:58 2002
*************** lhd_tree_dump_type_quals (t)
*** 421,423 ****
--- 421,437 ----
  {
    return TYPE_QUALS (t);
  }
+ 
+ /* lang_hooks.expr_size: Determine the size of the value of an expression T
+    in a language-specific way.  Returns a tree for the size in bytes.  */
+ 
+ tree
+ lhd_expr_size (exp)
+      tree exp;
+ {
+   if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'd'
+       && DECL_SIZE_UNIT (exp) != 0)
+     return DECL_SIZE_UNIT (exp);
+   else
+     return size_in_bytes (TREE_TYPE (exp));
+ }
*** ./langhooks.h.~1~	Wed Jul 24 17:17:16 2002
--- ./langhooks.h	Fri Aug  2 10:22:58 2002
*************** struct lang_hooks
*** 328,333 ****
--- 328,339 ----
    void (*print_error_function) PARAMS ((struct diagnostic_context *,
  					const char *));
  
+   /* Called from expr_size to calculate the size of the value of an
+      expression in a language-dependent way.  Returns a tree for the size
+      in bytes.  A frontend can call lhd_expr_size to get the default
+      semantics in cases that it doesn't want to handle specially.  */
+   tree (*expr_size) PARAMS ((tree));
+ 
    /* Pointers to machine-independent attribute tables, for front ends
       using attribs.c.  If one is NULL, it is ignored.  Respectively, a
       table of attributes specific to the language, a table of

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