public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Jason Merrill <jason@redhat.com>
To: Richard Henderson <rth@redhat.com>
Cc: gcc-patches@gcc.gnu.org
Subject: followup PATCH: Gimplify VA_ARG_EXPR
Date: Thu, 10 Jun 2004 17:54:00 -0000	[thread overview]
Message-ID: <xypoenrs9hr.fsf_-_@miranda.boston.redhat.com> (raw)
In-Reply-To: <20040609210529.GA13510@redhat.com> (Richard Henderson's message of "Wed, 9 Jun 2004 14:05:29 -0700")

[-- Attachment #1: Type: text/plain, Size: 1030 bytes --]

This patch implements some of rth's suggestions, and changes the signature
of the hook to take the valist and type as args and return the object.

Tested x86_64-pc-linux-gnu, ia64-pc-linux-gnu, powerpc64-pc-linux-gnu.  Now
testing (slowly) on sparc-sun-solaris9; I'll commit that hook once it
finishes.  rth, can you verify that the alpha hook still works after this
patch?

Applied to trunk.

2004-06-10  Jason Merrill  <jason@redhat.com>

	* target.h (struct gcc_target): Change gimplify_va_arg_expr 
	hook signature.
	* tree-gimple.h: Adjust.
	* config/alpha/alpha.c (alpha_gimplify_va_arg): Adjust.
	* config/i386/i386.c (ix86_gimplify_va_arg): Adjust.
	Use fold_convert.
	* config/ia64/ia64.c (ia64_gimplify_va_arg): Adjust.
	* config/rs6000/rs6000.c (rs6000_gimplify_va_arg): Adjust.
	Use COMPLEX_EXPR for complex numbers.  Use fold_convert.
	* builtins.c (std_gimplify_va_arg_expr): Adjust.  Use fold_convert.
	(gimplify_va_arg_expr): Return GS_ERROR in error case.
	Gimplify valist rather than calling stabilize_va_list.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: Type: text/x-patch, Size: 26366 bytes --]

*** ./target.h.~1~	2004-06-09 15:26:36.000000000 -0400
--- ./target.h	2004-06-09 23:57:29.000000000 -0400
*************** struct gcc_target
*** 472,478 ****
      bool (* split_complex_arg) (tree type);
  
      /* Gimplifies a VA_ARG_EXPR.  */
!     void (* gimplify_va_arg_expr) (tree *expr_p, tree *pre_p,
  				   tree *post_p);
    } calls;
  
--- 472,478 ----
      bool (* split_complex_arg) (tree type);
  
      /* Gimplifies a VA_ARG_EXPR.  */
!     tree (* gimplify_va_arg_expr) (tree valist, tree type, tree *pre_p,
  				   tree *post_p);
    } calls;
  
*** ./config/alpha/alpha.c.~1~	2004-06-09 17:49:25.000000000 -0400
--- ./config/alpha/alpha.c	2004-06-10 01:34:02.000000000 -0400
*************** alpha_gimplify_va_arg_1 (tree type, tree
*** 6444,6460 ****
    else if (TREE_CODE (type) == COMPLEX_TYPE)
      {
        tree real_part, imag_part, real_temp;
  
        real_part = alpha_gimplify_va_arg_1 (TREE_TYPE (type), base, offset,
! 					   pre_p, post_p);
!       append_to_statement_list (*post_p, pre_p);
!       *post_p = NULL;
! 
        /* Copy the value into a temporary, lest the formal temporary
  	 be reused out from under us.  */
!       real_temp = create_tmp_var (TREE_TYPE (real_part), NULL);
!       t = build (MODIFY_EXPR, void_type_node, real_temp, real_part);
!       gimplify_and_add (t, pre_p);
  
        imag_part = alpha_gimplify_va_arg_1 (TREE_TYPE (type), base, offset,
  					   pre_p, post_p);
--- 6444,6457 ----
    else if (TREE_CODE (type) == COMPLEX_TYPE)
      {
        tree real_part, imag_part, real_temp;
+       tree post = NULL_TREE;
  
        real_part = alpha_gimplify_va_arg_1 (TREE_TYPE (type), base, offset,
! 					   pre_p, &post);
        /* Copy the value into a temporary, lest the formal temporary
  	 be reused out from under us.  */
!       real_temp = get_initialized_tmp_var (real_part, pre_p, &post);
!       append_to_statement_list (post, pre_p);
  
        imag_part = alpha_gimplify_va_arg_1 (TREE_TYPE (type), base, offset,
  					   pre_p, post_p);
*************** alpha_gimplify_va_arg_1 (tree type, tree
*** 6491,6509 ****
    return build_fold_indirect_ref (addr);
  }
  
! static void
! alpha_gimplify_va_arg (tree *expr_p, tree *pre_p, tree *post_p)
  {
!   tree valist, type, offset_field, base_field, offset, base, t;
  
    if (TARGET_ABI_OPEN_VMS || TARGET_ABI_UNICOSMK)
!     {
!       std_gimplify_va_arg_expr (expr_p, pre_p, post_p);
!       return;
!     }
! 
!   valist = TREE_OPERAND (*expr_p, 0);
!   type = TREE_TYPE (*expr_p);
  
    base_field = TYPE_FIELDS (va_list_type_node);
    offset_field = TREE_CHAIN (base_field);
--- 6488,6500 ----
    return build_fold_indirect_ref (addr);
  }
  
! static tree
! alpha_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p)
  {
!   tree offset_field, base_field, offset, base, t, r;
  
    if (TARGET_ABI_OPEN_VMS || TARGET_ABI_UNICOSMK)
!     return std_gimplify_va_arg_expr (valist, type, pre_p, post_p);
  
    base_field = TYPE_FIELDS (va_list_type_node);
    offset_field = TREE_CHAIN (base_field);
*************** alpha_gimplify_va_arg (tree *expr_p, tre
*** 6525,6536 ****
  
    /* Find the value.  Note that this will be a stable indirection, or
       a composite of stable indirections in the case of complex.  */
!   *expr_p = alpha_gimplify_va_arg_1 (type, base, offset, pre_p, post_p);
  
    /* Stuff the offset temporary back into its field.  */
    t = build (MODIFY_EXPR, void_type_node, offset_field,
  	     fold_convert (TREE_TYPE (offset_field), offset));
    gimplify_and_add (t, pre_p);
  }
  \f
  /* Builtins.  */
--- 6516,6529 ----
  
    /* Find the value.  Note that this will be a stable indirection, or
       a composite of stable indirections in the case of complex.  */
!   r = alpha_gimplify_va_arg_1 (type, base, offset, pre_p, post_p);
  
    /* Stuff the offset temporary back into its field.  */
    t = build (MODIFY_EXPR, void_type_node, offset_field,
  	     fold_convert (TREE_TYPE (offset_field), offset));
    gimplify_and_add (t, pre_p);
+ 
+   return r;
  }
  \f
  /* Builtins.  */
*** ./config/i386/i386.c.~1~	2004-06-09 15:26:36.000000000 -0400
--- ./config/i386/i386.c	2004-06-09 23:57:55.000000000 -0400
*************** static bool ix86_expand_carry_flag_compa
*** 878,884 ****
  static tree ix86_build_builtin_va_list (void);
  static void ix86_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,
  					 tree, int *, int);
! static void ix86_gimplify_va_arg (tree *expr_p, tree *pre_p, tree *post_p);
  
  struct ix86_address
  {
--- 878,884 ----
  static tree ix86_build_builtin_va_list (void);
  static void ix86_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,
  					 tree, int *, int);
! static tree ix86_gimplify_va_arg (tree, tree, tree *, tree *);
  
  struct ix86_address
  {
*************** ix86_va_arg (tree valist, tree type)
*** 3418,3428 ****
  
  /* Lower VA_ARG_EXPR at gimplification time.  */
  
! void
! ix86_gimplify_va_arg (tree *expr_p, tree *pre_p, tree *post_p)
  {
-   tree valist = TREE_OPERAND (*expr_p, 0);
-   tree type = TREE_TYPE (*expr_p);
    static const int intreg[6] = { 0, 1, 2, 3, 4, 5 };
    tree f_gpr, f_fpr, f_ovf, f_sav;
    tree gpr, fpr, ovf, sav, t;
--- 3418,3426 ----
  
  /* Lower VA_ARG_EXPR at gimplification time.  */
  
! tree
! ix86_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p)
  {
    static const int intreg[6] = { 0, 1, 2, 3, 4, 5 };
    tree f_gpr, f_fpr, f_ovf, f_sav;
    tree gpr, fpr, ovf, sav, t;
*************** ix86_gimplify_va_arg (tree *expr_p, tree
*** 3435,3444 ****
  
    /* Only 64bit target needs something special.  */
    if (!TARGET_64BIT)
!     {
!       std_gimplify_va_arg_expr (expr_p, pre_p, post_p);
!       return;
!     }
  
    f_gpr = TYPE_FIELDS (TREE_TYPE (va_list_type_node));
    f_fpr = TREE_CHAIN (f_gpr);
--- 3433,3439 ----
  
    /* Only 64bit target needs something special.  */
    if (!TARGET_64BIT)
!     return std_gimplify_va_arg_expr (valist, type, pre_p, post_p);
  
    f_gpr = TYPE_FIELDS (TREE_TYPE (va_list_type_node));
    f_fpr = TREE_CHAIN (f_gpr);
*************** ix86_gimplify_va_arg (tree *expr_p, tree
*** 3595,3606 ****
  		  src_addr = int_addr;
  		  src_offset = REGNO (reg) * 8;
  		}
! 	      src_addr = convert (addr_type, src_addr);
  	      src_addr = fold (build2 (PLUS_EXPR, addr_type, src_addr,
  				       size_int (src_offset)));
  	      src = build_fold_indirect_ref (src_addr);
  
! 	      dest_addr = convert (addr_type, addr);
  	      dest_addr = fold (build2 (PLUS_EXPR, addr_type, dest_addr,
  					size_int (INTVAL (XEXP (slot, 1)))));
  	      dest = build_fold_indirect_ref (dest_addr);
--- 3590,3601 ----
  		  src_addr = int_addr;
  		  src_offset = REGNO (reg) * 8;
  		}
! 	      src_addr = fold_convert (addr_type, src_addr);
  	      src_addr = fold (build2 (PLUS_EXPR, addr_type, src_addr,
  				       size_int (src_offset)));
  	      src = build_fold_indirect_ref (src_addr);
  
! 	      dest_addr = fold_convert (addr_type, addr);
  	      dest_addr = fold (build2 (PLUS_EXPR, addr_type, dest_addr,
  					size_int (INTVAL (XEXP (slot, 1)))));
  	      dest = build_fold_indirect_ref (dest_addr);
*************** ix86_gimplify_va_arg (tree *expr_p, tree
*** 3661,3671 ****
      }
  
    ptrtype = build_pointer_type (type);
!   addr = convert (ptrtype, addr);
  
    if (indirect_p)
      addr = build_fold_indirect_ref (addr);
!   *expr_p = build_fold_indirect_ref (addr);
  }
  \f
  /* Return nonzero if OP is either a i387 or SSE fp register.  */
--- 3656,3666 ----
      }
  
    ptrtype = build_pointer_type (type);
!   addr = fold_convert (ptrtype, addr);
  
    if (indirect_p)
      addr = build_fold_indirect_ref (addr);
!   return build_fold_indirect_ref (addr);
  }
  \f
  /* Return nonzero if OP is either a i387 or SSE fp register.  */
*** ./config/ia64/ia64.c.~1~	2004-06-09 15:26:36.000000000 -0400
--- ./config/ia64/ia64.c	2004-06-09 23:57:29.000000000 -0400
*************** static void ia64_vms_init_libfuncs (void
*** 274,280 ****
  static tree ia64_handle_model_attribute (tree *, tree, tree, int, bool *);
  static void ia64_encode_section_info (tree, rtx, int);
  static rtx ia64_struct_value_rtx (tree, int);
! static void ia64_gimplify_va_arg (tree *, tree *, tree *);
  
  \f
  /* Table of valid machine attributes.  */
--- 274,280 ----
  static tree ia64_handle_model_attribute (tree *, tree, tree, int, bool *);
  static void ia64_encode_section_info (tree, rtx, int);
  static rtx ia64_struct_value_rtx (tree, int);
! static tree ia64_gimplify_va_arg (tree, tree, tree *, tree *);
  
  \f
  /* Table of valid machine attributes.  */
*************** ia64_va_arg (tree valist, tree type)
*** 3993,4011 ****
    return std_expand_builtin_va_arg (valist, type);
  }
  
! static void
! ia64_gimplify_va_arg (tree *expr_p, tree *pre_p, tree *post_p)
  {
-   tree valist = TREE_OPERAND (*expr_p, 0);
-   tree type = TREE_TYPE (*expr_p);
- 
    /* Variable sized types are passed by reference.  */
    if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
      {
!       TREE_TYPE (*expr_p) = build_pointer_type (type);
!       std_gimplify_va_arg_expr (expr_p, pre_p, post_p);
!       *expr_p = build_fold_indirect_ref (*expr_p);
!       return;
      }
  
    /* Aggregate arguments with alignment larger than 8 bytes start at
--- 3993,4007 ----
    return std_expand_builtin_va_arg (valist, type);
  }
  
! static tree
! ia64_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p)
  {
    /* Variable sized types are passed by reference.  */
    if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
      {
!       tree ptrtype = build_pointer_type (type);
!       tree addr = std_gimplify_va_arg_expr (valist, ptrtype, pre_p, post_p);
!       return build_fold_indirect_ref (addr);
      }
  
    /* Aggregate arguments with alignment larger than 8 bytes start at
*************** ia64_gimplify_va_arg (tree *expr_p, tree
*** 4023,4029 ****
        gimplify_and_add (t, pre_p);
      }
  
!   std_gimplify_va_arg_expr (expr_p, pre_p, post_p);
  }
  \f
  /* Return 1 if function return value returned in memory.  Return 0 if it is
--- 4019,4025 ----
        gimplify_and_add (t, pre_p);
      }
  
!   return std_gimplify_va_arg_expr (valist, type, pre_p, post_p);
  }
  \f
  /* Return 1 if function return value returned in memory.  Return 0 if it is
*** ./config/rs6000/rs6000.c.~1~	2004-06-09 15:26:36.000000000 -0400
--- ./config/rs6000/rs6000.c	2004-06-10 01:34:59.000000000 -0400
*************** static tree get_prev_label (tree functio
*** 440,446 ****
  #endif
  
  static tree rs6000_build_builtin_va_list (void);
! static void rs6000_gimplify_va_arg (tree *, tree *, tree *);
  
  /* Hash table stuff for keeping track of TOC entries.  */
  
--- 440,446 ----
  #endif
  
  static tree rs6000_build_builtin_va_list (void);
! static tree rs6000_gimplify_va_arg (tree, tree, tree *, tree *);
  
  /* Hash table stuff for keeping track of TOC entries.  */
  
*************** rs6000_va_arg (tree valist, tree type)
*** 5292,5302 ****
    return addr_rtx;
  }
  
! void
! rs6000_gimplify_va_arg (tree *expr_p, tree *pre_p, tree *post_p)
  {
-   tree valist = TREE_OPERAND (*expr_p, 0);
-   tree type = TREE_TYPE (*expr_p);
    tree f_gpr, f_fpr, f_res, f_ovf, f_sav;
    tree gpr, fpr, ovf, sav, reg, t, u;
    int indirect_p, size, rsize, n_reg, sav_ofs, sav_scale;
--- 5292,5300 ----
    return addr_rtx;
  }
  
! tree
! rs6000_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p)
  {
    tree f_gpr, f_fpr, f_res, f_ovf, f_sav;
    tree gpr, fpr, ovf, sav, reg, t, u;
    int indirect_p, size, rsize, n_reg, sav_ofs, sav_scale;
*************** rs6000_gimplify_va_arg (tree *expr_p, tr
*** 5318,5327 ****
  		      build_int_2 (POINTER_SIZE / BITS_PER_UNIT, 0));
  	  t = build1 (NOP_EXPR, build_pointer_type (ptrtype), t);
  	  t = build_fold_indirect_ref (t);
! 	  t = build_fold_indirect_ref (t);
! 
! 	  *expr_p = t;
! 	  return;
  	}
        if (targetm.calls.split_complex_arg
  	  && TREE_CODE (type) == COMPLEX_TYPE)
--- 5316,5322 ----
  		      build_int_2 (POINTER_SIZE / BITS_PER_UNIT, 0));
  	  t = build1 (NOP_EXPR, build_pointer_type (ptrtype), t);
  	  t = build_fold_indirect_ref (t);
! 	  return build_fold_indirect_ref (t);
  	}
        if (targetm.calls.split_complex_arg
  	  && TREE_CODE (type) == COMPLEX_TYPE)
*************** rs6000_gimplify_va_arg (tree *expr_p, tr
*** 5332,5383 ****
  
  	  if (elem_size < UNITS_PER_WORD)
  	    {
! 	      tree real_part, imag_addr, dest_real, rr;
  	      tree post = NULL_TREE;
  
! 	      /* This is a bit tricky because we can't just feed the
! 		 VA_ARG_EXPRs back into gimplify_expr; if we did,
! 		 gimplify_va_arg_expr would complain about trying to pass a
! 		 float. */
! 	      real_part = build1 (VA_ARG_EXPR, elem_type, valist);
! 	      rs6000_gimplify_va_arg (&real_part, pre_p, &post);
! 	      gimplify_expr (&real_part, pre_p, &post, is_gimple_val,
! 			     fb_rvalue);
  	      append_to_statement_list (post, pre_p);
  
! 	      imag_addr = build1 (VA_ARG_EXPR, elem_type, valist);
! 	      rs6000_gimplify_va_arg (&imag_addr, pre_p, post_p);
! 	      imag_addr = build_fold_addr_expr (imag_addr);
! 	      gimplify_expr (&imag_addr, pre_p, post_p, is_gimple_val,
! 			     fb_rvalue);
  
! 	      /* We're not returning the value here, but the address.
! 		 real_part and imag_part are not contiguous, and we know
! 		 there is space available to pack real_part next to
! 		 imag_part.  float _Complex is not promoted to
! 		 double _Complex by the default promotion rules that
! 		 promote float to double.  */
! 	      if (2 * elem_size > UNITS_PER_WORD)
! 		abort ();
! 
! 	      dest_real = fold (build2 (MINUS_EXPR, TREE_TYPE (imag_addr),
! 					imag_addr, ssize_int (elem_size)));
! 	      gimplify_expr (&dest_real, pre_p, post_p, is_gimple_val,
! 			     fb_rvalue);
! 
! 	      rr = build_fold_indirect_ref (dest_real);
! 	      rr = build2 (MODIFY_EXPR, void_type_node, rr, real_part);
! 	      gimplify_and_add (rr, pre_p);
! 
! 	      dest_real = convert (build_pointer_type (type), dest_real);
! 	      *expr_p = build_fold_indirect_ref (dest_real);
! 
! 	      return;
  	    }
  	}
  
!       std_gimplify_va_arg_expr (expr_p, pre_p, post_p);
!       return;
      }
  
    f_gpr = TYPE_FIELDS (TREE_TYPE (va_list_type_node));
--- 5327,5350 ----
  
  	  if (elem_size < UNITS_PER_WORD)
  	    {
! 	      tree real_part, imag_part;
  	      tree post = NULL_TREE;
  
! 	      real_part = rs6000_gimplify_va_arg (valist, elem_type, pre_p,
! 						  &post);
! 	      /* Copy the value into a temporary, lest the formal temporary
! 		 be reused out from under us.  */
! 	      real_part = get_initialized_tmp_var (real_part, pre_p, &post);
  	      append_to_statement_list (post, pre_p);
  
! 	      imag_part = rs6000_gimplify_va_arg (valist, elem_type, pre_p,
! 						  post_p);
  
! 	      return build (COMPLEX_EXPR, type, real_part, imag_part);
  	    }
  	}
  
!       return std_gimplify_va_arg_expr (valist, type, pre_p, post_p);
      }
  
    f_gpr = TYPE_FIELDS (TREE_TYPE (va_list_type_node));
*************** rs6000_gimplify_va_arg (tree *expr_p, tr
*** 5520,5532 ****
  
    if (indirect_p)
      {
!       addr = convert (build_pointer_type (ptrtype), addr);
        addr = build_fold_indirect_ref (addr);
      }
    else
!     addr = convert (ptrtype, addr);
  
!   *expr_p = build_fold_indirect_ref (addr);
  }
  
  /* Builtins.  */
--- 5487,5499 ----
  
    if (indirect_p)
      {
!       addr = fold_convert (build_pointer_type (ptrtype), addr);
        addr = build_fold_indirect_ref (addr);
      }
    else
!     addr = fold_convert (ptrtype, addr);
  
!   return build_fold_indirect_ref (addr);
  }
  
  /* Builtins.  */
*** ./config/sparc/sparc.c.~1~	2004-06-09 15:26:36.000000000 -0400
--- ./config/sparc/sparc.c	2004-06-10 00:14:50.000000000 -0400
*************** Boston, MA 02111-1307, USA.  */
*** 47,52 ****
--- 47,53 ----
  #include "target.h"
  #include "target-def.h"
  #include "cfglayout.h"
+ #include "tree-gimple.h"
  
  /* Global variables for machine-dependent things.  */
  
*************** static bool sparc_promote_prototypes (tr
*** 181,186 ****
--- 182,188 ----
  static rtx sparc_struct_value_rtx (tree, int);
  static bool sparc_return_in_memory (tree, tree);
  static bool sparc_strict_argument_naming (CUMULATIVE_ARGS *);
+ static tree sparc_gimplify_va_arg (tree, tree, tree *, tree *);
  \f
  /* Option handling.  */
  
*************** enum processor_type sparc_cpu;
*** 289,294 ****
--- 291,299 ----
  #undef TARGET_STRICT_ARGUMENT_NAMING
  #define TARGET_STRICT_ARGUMENT_NAMING sparc_strict_argument_naming
  
+ #undef TARGET_GIMPLIFY_VA_ARG_EXPR
+ #define TARGET_GIMPLIFY_VA_ARG_EXPR sparc_gimplify_va_arg
+ 
  struct gcc_target targetm = TARGET_INITIALIZER;
  \f
  /* Validate and override various options, and do some machine dependent
*************** sparc_va_arg (tree valist, tree type)
*** 6041,6046 ****
--- 6046,6144 ----
  
    return addr_rtx;
  }
+ 
+ tree
+ sparc_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p)
+ {
+   HOST_WIDE_INT size, rsize, align;
+   tree addr, incr;
+   bool indirect;
+   tree ptrtype = build_pointer_type (type);
+ 
+   if (function_arg_pass_by_reference (0, TYPE_MODE (type), type, 0))
+     {
+       indirect = true;
+       size = rsize = UNITS_PER_WORD;
+       align = 0;
+     }
+   else
+     {
+       indirect = false;
+       size = int_size_in_bytes (type);
+       rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD;
+       align = 0;
+     
+       if (TARGET_ARCH64)
+ 	{
+ 	  /* For SPARC64, objects requiring 16-byte alignment get it.  */
+ 	  if (TYPE_ALIGN (type) >= 2 * (unsigned) BITS_PER_WORD)
+ 	    align = 2 * UNITS_PER_WORD;
+ 
+ 	  /* SPARC-V9 ABI states that structures up to 16 bytes in size
+ 	     are given whole slots as needed.  */
+ 	  if (AGGREGATE_TYPE_P (type))
+ 	    {
+ 	      if (size == 0)
+ 		size = rsize = UNITS_PER_WORD;
+ 	      else
+ 		size = rsize;
+ 	    }
+ 	}
+     }
+ 
+   incr = valist;
+   if (align)
+     {
+       incr = fold (build2 (PLUS_EXPR, ptr_type_node, incr,
+ 			   build_int_2 (align - 1, 0)));
+       incr = fold (build2 (BIT_AND_EXPR, ptr_type_node, incr,
+ 			   build_int_2 (-align, -1)));
+     }
+ 
+   gimplify_expr (&incr, pre_p, post_p, is_gimple_val, fb_rvalue);
+   addr = incr;
+ 
+   if (BYTES_BIG_ENDIAN && size < rsize)
+     {
+       addr = fold (build2 (PLUS_EXPR, ptr_type_node, incr,
+ 			   build_int_2 (rsize - size, 0)));
+     }
+   incr = fold (build2 (PLUS_EXPR, ptr_type_node, incr,
+ 		       build_int_2 (rsize, 0)));
+ 
+   incr = build2 (MODIFY_EXPR, ptr_type_node, valist, incr);
+   gimplify_and_add (incr, pre_p);
+ 
+   if (indirect)
+     {
+       addr = fold_convert (build_pointer_type (ptrtype), addr);
+       addr = build_fold_indirect_ref (addr);
+     }
+   /* If the address isn't aligned properly for the type,
+      we may need to copy to a temporary.  
+      FIXME: This is inefficient.  Usually we can do this
+      in registers.  */
+   else if (align == 0
+ 	   && TYPE_ALIGN (type) > BITS_PER_WORD)
+     {
+       tree tmp = create_tmp_var (type, "va_arg_tmp");
+       tree dest_addr = build_fold_addr_expr (tmp);
+ 
+       incr = build_function_call_expr
+ 	(implicit_built_in_decls[BUILT_IN_MEMCPY],
+ 	 tree_cons (NULL_TREE, dest_addr,
+ 		    tree_cons (NULL_TREE, addr,
+ 			       tree_cons (NULL_TREE, size_int (rsize),
+ 					  NULL_TREE))));
+ 
+       gimplify_and_add (incr, pre_p);
+       addr = dest_addr;
+     }
+   else
+     addr = fold_convert (ptrtype, addr);
+ 
+   return build_fold_indirect_ref (addr);
+ }
  \f
  /* Return the string to output a conditional branch to LABEL, which is
     the operand number of the label.  OP is the conditional expression.
*** ./doc/tm.texi.~1~	2004-06-09 15:26:36.000000000 -0400
--- ./doc/tm.texi	2004-06-10 01:29:00.000000000 -0400
*************** The default value of this hook is @code{
*** 3864,3869 ****
--- 3864,3882 ----
  false.
  @end deftypefn
  
+ @deftypefn {Target Hook} tree TARGET_GIMPLIFY_VA_ARG_EXPR (tree @var{valist}, tree @var{type}, tree *@var{pre_p}, tree *@var{post_p})
+ This hook performs target-specific gimplification of
+ @code{VA_ARG_EXPR}.  The first two parameters correspond to the
+ arguments to @code{va_arg}; the latter two are as in
+ @code{gimplify.c:gimplify_expr}.
+ 
+ You only need to define this hook if you also define
+ @code{EXPAND_BUILTIN_VA_ARG}; it is pretty easy to reuse the same code
+ for both.  One significant difference is that
+ @code{EXPAND_BUILTIN_VA_ARG} returns an address, whereas this hook
+ produces an expression of type @var{type}, usually an @code{INDIRECT_REF}.
+ @end deftypefn
+ 
  @node Scalar Return
  @subsection How Scalar Function Values Are Returned
  @cindex return values in registers
*** ./builtins.c.~1~	2004-06-09 15:26:36.000000000 -0400
--- ./builtins.c	2004-06-10 11:41:41.000000000 -0400
*************** expand_builtin_va_arg (tree valist, tree
*** 4362,4385 ****
  
  /* Like std_expand_builtin_va_arg, but gimplify instead of expanding.  */
  
! void
! std_gimplify_va_arg_expr (tree *expr_p, tree *pre_p, tree *post_p)
  {
    tree addr, t, type_size = NULL;
    tree align, alignm1;
    tree rounded_size;
    HOST_WIDE_INT boundary;
-   tree valist = TREE_OPERAND (*expr_p, 0);
-   tree type = TREE_TYPE (*expr_p);
  
    /* Compute the rounded size of the type.  */
    align = size_int (PARM_BOUNDARY / BITS_PER_UNIT);
    alignm1 = size_int (PARM_BOUNDARY / BITS_PER_UNIT - 1);
    boundary = FUNCTION_ARG_BOUNDARY (TYPE_MODE (type), type);
  
-   /* Reduce valist it so it's sharable with the postqueue.  */
-   gimplify_expr (&valist, pre_p, post_p, is_gimple_min_lval, fb_lvalue);
- 
    /* va_list pointer is aligned to PARM_BOUNDARY.  If argument actually
       requires greater alignment, we must perform dynamic alignment.  */
  
--- 4362,4380 ----
  
  /* Like std_expand_builtin_va_arg, but gimplify instead of expanding.  */
  
! 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;
    tree rounded_size;
    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);
    boundary = FUNCTION_ARG_BOUNDARY (TYPE_MODE (type), type);
  
    /* va_list pointer is aligned to PARM_BOUNDARY.  If argument actually
       requires greater alignment, we must perform dynamic alignment.  */
  
*************** std_gimplify_va_arg_expr (tree *expr_p, 
*** 4432,4440 ****
  							    type_size))))));
      }
  
-   addr = convert (build_pointer_type (type), addr);
-   *expr_p = build1 (INDIRECT_REF, type, addr);
- 
    /* Compute new value for AP.  */
    if (! integer_zerop (rounded_size))
      {
--- 4427,4432 ----
*************** std_gimplify_va_arg_expr (tree *expr_p, 
*** 4444,4449 ****
--- 4436,4444 ----
        gimplify_stmt (&t);
        append_to_statement_list (t, post_p);
      }
+ 
+   addr = fold_convert (build_pointer_type (type), addr);
+   return build_fold_indirect_ref (addr);
  }
  
  /* Return a dummy expression of type TYPE in order to keep going after an
*************** gimplify_va_arg_expr (tree *expr_p, tree
*** 4487,4494 ****
    if (TYPE_MAIN_VARIANT (want_va_type) != TYPE_MAIN_VARIANT (have_va_type))
      {
        error ("first argument to `va_arg' not of type `va_list'");
!       *expr_p = dummy_object (type);
!       return GS_ALL_DONE;
      }
  
    /* Generate a diagnostic for requesting data of a type that cannot
--- 4482,4488 ----
    if (TYPE_MAIN_VARIANT (want_va_type) != TYPE_MAIN_VARIANT (have_va_type))
      {
        error ("first argument to `va_arg' not of type `va_list'");
!       return GS_ERROR;
      }
  
    /* Generate a diagnostic for requesting data of a type that cannot
*************** gimplify_va_arg_expr (tree *expr_p, tree
*** 4526,4539 ****
      {
        /* Make it easier for the backends by protecting the valist argument
           from multiple evaluations.  */
!       valist = stabilize_va_list (valist, 0);
!       TREE_OPERAND (*expr_p, 0) = valist;
  
        if (!targetm.calls.gimplify_va_arg_expr)
  	/* Once most targets are converted this should abort.  */
  	return GS_ALL_DONE;
  
!       targetm.calls.gimplify_va_arg_expr (expr_p, pre_p, post_p);
        return GS_OK;
      }
  }
--- 4520,4546 ----
      {
        /* Make it easier for the backends by protecting the valist argument
           from multiple evaluations.  */
!       if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
! 	{
! 	  /* For this case, the backends will be expecting a pointer to
! 	     TREE_TYPE (va_list_type_node), but it's possible we've
! 	     actually been given an array (an actual va_list_type_node).
! 	     So fix it.  */
! 	  if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
! 	    {
! 	      tree p1 = build_pointer_type (TREE_TYPE (va_list_type_node));
! 	      valist = build_fold_addr_expr_with_type (valist, p1);
! 	    }
! 	  gimplify_expr (&valist, pre_p, post_p, is_gimple_val, fb_rvalue);
! 	}
!       else
! 	gimplify_expr (&valist, pre_p, post_p, is_gimple_min_lval, fb_lvalue);
  
        if (!targetm.calls.gimplify_va_arg_expr)
  	/* Once most targets are converted this should abort.  */
  	return GS_ALL_DONE;
  
!       *expr_p = targetm.calls.gimplify_va_arg_expr (valist, type, pre_p, post_p);
        return GS_OK;
      }
  }
*** ./tree-gimple.h.~1~	2004-06-09 15:26:36.000000000 -0400
--- ./tree-gimple.h	2004-06-09 23:57:29.000000000 -0400
*************** tree alloc_stmt_list (void);
*** 123,129 ****
  void free_stmt_list (tree);
  tree force_labels_r (tree *, int *, void *);
  enum gimplify_status gimplify_va_arg_expr (tree *, tree *, tree *);
! void std_gimplify_va_arg_expr (tree *, tree *, tree *);
  
  /* In tree-nested.c.  */
  extern void lower_nested_functions (tree);
--- 123,129 ----
  void free_stmt_list (tree);
  tree force_labels_r (tree *, int *, void *);
  enum gimplify_status gimplify_va_arg_expr (tree *, tree *, tree *);
! tree std_gimplify_va_arg_expr (tree, tree, tree *, tree *);
  
  /* In tree-nested.c.  */
  extern void lower_nested_functions (tree);

  reply	other threads:[~2004-06-10 15:47 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-06-09  7:21 Jason Merrill
2004-06-09 21:39 ` Richard Henderson
2004-06-09 22:01   ` Jason Merrill
2004-06-09 22:30     ` Richard Henderson
2004-06-10 17:54       ` Jason Merrill [this message]
2004-06-14  5:51         ` followup " Jason Merrill

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=xypoenrs9hr.fsf_-_@miranda.boston.redhat.com \
    --to=jason@redhat.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=rth@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).