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);
next prev parent 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).