gimple va_arg for mips

Richard Henderson rth@redhat.com
Sat Jul 10 03:55:00 GMT 2004


On Fri, Jul 09, 2004 at 12:12:17PM -0700, Richard Henderson wrote:
> You're right.  I think this check was supposed to be for ARGS_GROW_DOWNWARD.
> I wonder how this has gone unnoticed so long...  I'll fix it.

Like so.  Fully tested on i686; I'll build a mips-sim sometime
this weekend, but feel free to beat me to it.


r~


        * builtins.c (std_gimplify_va_arg_expr): Deny ARGS_GROW_DOWNWARD.
        Always align upward to arg boundary.  Use size_in_bytes/round_up.
        Maintain type-correctness of constants.
        * stor-layout.c (round_up, round_down): Special-case powers of 2.

Index: builtins.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/builtins.c,v
retrieving revision 1.355
diff -c -p -d -r1.355 builtins.c
*** builtins.c	9 Jul 2004 23:04:32 -0000	1.355
--- builtins.c	10 Jul 2004 01:49:24 -0000
*************** expand_builtin_va_arg (tree valist, tree
*** 4473,4544 ****
  tree
  std_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p, tree *post_p)
  {
!   tree addr, t, type_size = NULL;
!   tree align, alignm1, malign;
!   tree rounded_size;
!   tree valist_tmp;
!   HOST_WIDE_INT boundary;
  
    /* Compute the rounded size of the type.  */
!   align = size_int (PARM_BOUNDARY / BITS_PER_UNIT);
!   alignm1 = size_int (PARM_BOUNDARY / BITS_PER_UNIT - 1);
!   malign = size_int (-(PARM_BOUNDARY / BITS_PER_UNIT));
    boundary = FUNCTION_ARG_BOUNDARY (TYPE_MODE (type), type);
  
    valist_tmp = get_initialized_tmp_var (valist, pre_p, NULL);
  
    /* va_list pointer is aligned to PARM_BOUNDARY.  If argument actually
       requires greater alignment, we must perform dynamic alignment.  */
- 
    if (boundary > PARM_BOUNDARY)
      {
!       if (!PAD_VARARGS_DOWN)
! 	{
! 	  t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
! 		      build2 (PLUS_EXPR, TREE_TYPE (valist), valist_tmp,
! 			      build_int_2 (boundary / BITS_PER_UNIT - 1, 0)));
! 	  gimplify_and_add (t, pre_p);
! 	}
        t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
! 		  build2 (BIT_AND_EXPR, TREE_TYPE (valist), valist_tmp,
! 			  build_int_2 (~(boundary / BITS_PER_UNIT - 1), -1)));
        gimplify_and_add (t, pre_p);
-     }
-   if (type == error_mark_node
-       || (type_size = TYPE_SIZE_UNIT (TYPE_MAIN_VARIANT (type))) == NULL
-       || TREE_OVERFLOW (type_size))
-     rounded_size = size_zero_node;
-   else
-     {
-       rounded_size = fold (build2 (PLUS_EXPR, sizetype, type_size, alignm1));
-       rounded_size = fold (build2 (BIT_AND_EXPR, sizetype,
- 				   rounded_size, malign));
      }
  
    /* Reduce rounded_size so it's sharable with the postqueue.  */
    gimplify_expr (&rounded_size, pre_p, post_p, is_gimple_val, fb_rvalue);
  
    /* Get AP.  */
    addr = valist_tmp;
!   if (PAD_VARARGS_DOWN && ! integer_zerop (rounded_size))
      {
        /* Small args are padded downward.  */
!       addr = fold (build2 (PLUS_EXPR, TREE_TYPE (addr), addr,
! 				fold (build3 (COND_EXPR, sizetype,
! 					      fold (build2 (GT_EXPR, sizetype,
! 							    rounded_size,
! 							    align)),
! 					      size_zero_node,
! 					      fold (build2 (MINUS_EXPR,
! 							    sizetype,
! 							    rounded_size,
! 							    type_size))))));
      }
  
    /* Compute new value for AP.  */
!   t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist,
! 	      fold (build2 (PLUS_EXPR, TREE_TYPE (valist),
! 			    valist_tmp, rounded_size)));
    gimplify_and_add (t, pre_p);
  
    addr = fold_convert (build_pointer_type (type), addr);
--- 4473,4533 ----
  tree
  std_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p, tree *post_p)
  {
!   tree addr, t, type_size, rounded_size, valist_tmp;
!   unsigned int align, boundary;
! 
! #ifdef ARGS_GROW_DOWNWARD
!   /* All of the alignment and movement below is for args-grow-up machines.
!      As of 2004, there are only 3 ARGS_GROW_DOWNWARD targets, and they all
!      implement their own specialized gimplify_va_arg_expr routines.  */
!   abort ();
! #endif
  
    /* Compute the rounded size of the type.  */
!   align = PARM_BOUNDARY / BITS_PER_UNIT;
    boundary = FUNCTION_ARG_BOUNDARY (TYPE_MODE (type), type);
  
+   /* Hoist the valist value into a temporary for the moment.  */
    valist_tmp = get_initialized_tmp_var (valist, pre_p, NULL);
  
    /* va_list pointer is aligned to PARM_BOUNDARY.  If argument actually
       requires greater alignment, we must perform dynamic alignment.  */
    if (boundary > PARM_BOUNDARY)
      {
!       unsigned byte_bound = boundary / BITS_PER_UNIT;
! 
!       t = fold_convert (TREE_TYPE (valist), size_int (byte_bound - 1));
        t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
! 		  build2 (PLUS_EXPR, TREE_TYPE (valist), valist_tmp, t));
!       gimplify_and_add (t, pre_p);
! 
!       t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
! 		  build2 (BIT_AND_EXPR, TREE_TYPE (valist), valist_tmp, t));
        gimplify_and_add (t, pre_p);
      }
  
+   type_size = size_in_bytes (type);
+   rounded_size = round_up (type_size, align);
+ 
    /* Reduce rounded_size so it's sharable with the postqueue.  */
    gimplify_expr (&rounded_size, pre_p, post_p, is_gimple_val, fb_rvalue);
  
    /* Get AP.  */
    addr = valist_tmp;
!   if (PAD_VARARGS_DOWN && !integer_zerop (rounded_size))
      {
        /* Small args are padded downward.  */
!       t = fold (build2 (GT_EXPR, sizetype, rounded_size, size_int (align)));
!       t = fold (build3 (COND_EXPR, sizetype, t, size_zero_node,
! 			size_binop (MINUS_EXPR, rounded_size, type_size)));
!       t = fold_convert (TREE_TYPE (addr), t);
!       addr = build2 (PLUS_EXPR, TREE_TYPE (addr), addr, t);
      }
  
    /* Compute new value for AP.  */
!   t = fold_convert (TREE_TYPE (valist), rounded_size);
!   t = build2 (PLUS_EXPR, TREE_TYPE (valist), valist_tmp, t);
!   t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
    gimplify_and_add (t, pre_p);
  
    addr = fold_convert (build_pointer_type (type), addr);
Index: stor-layout.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/stor-layout.c,v
retrieving revision 1.194
diff -c -p -d -r1.194 stor-layout.c
*** stor-layout.c	3 Jul 2004 00:15:43 -0000	1.194
--- stor-layout.c	10 Jul 2004 01:49:24 -0000
*************** get_mode_alignment (enum machine_mode mo
*** 274,282 ****
  tree
  round_up (tree value, int divisor)
  {
!   tree arg = size_int_type (divisor, TREE_TYPE (value));
  
!   return size_binop (MULT_EXPR, size_binop (CEIL_DIV_EXPR, value, arg), arg);
  }
  
  /* Likewise, but round down.  */
--- 274,297 ----
  tree
  round_up (tree value, int divisor)
  {
!   tree t;
  
!   /* If divisor is a power of two, simplify this to bit manipulation.  */
!   if (divisor == (divisor & -divisor))
!     {
!       t = size_int_type (divisor - 1, TREE_TYPE (value));
!       value = size_binop (PLUS_EXPR, value, t);
!       t = size_int_type (-divisor, TREE_TYPE (value));
!       value = size_binop (BIT_AND_EXPR, value, t);
!     }
!   else
!     {
!       t = size_int_type (divisor, TREE_TYPE (value));
!       value = size_binop (CEIL_DIV_EXPR, value, t);
!       value = size_binop (MULT_EXPR, value, t);
!     }
! 
!   return value;
  }
  
  /* Likewise, but round down.  */
*************** round_up (tree value, int divisor)
*** 284,292 ****
  tree
  round_down (tree value, int divisor)
  {
!   tree arg = size_int_type (divisor, TREE_TYPE (value));
  
!   return size_binop (MULT_EXPR, size_binop (FLOOR_DIV_EXPR, value, arg), arg);
  }
  
  /* Subroutine of layout_decl: Force alignment required for the data type.
--- 299,320 ----
  tree
  round_down (tree value, int divisor)
  {
!   tree t;
  
!   /* If divisor is a power of two, simplify this to bit manipulation.  */
!   if (divisor == (divisor & -divisor))
!     {
!       t = size_int_type (-divisor, TREE_TYPE (value));
!       value = size_binop (BIT_AND_EXPR, value, t);
!     }
!   else
!     {
!       t = size_int_type (divisor, TREE_TYPE (value));
!       value = size_binop (FLOOR_DIV_EXPR, value, t);
!       value = size_binop (MULT_EXPR, value, t);
!     }
! 
!   return value;
  }
  
  /* Subroutine of layout_decl: Force alignment required for the data type.



More information about the Gcc-patches mailing list