From 09c41ee4024d965815267df8b5c613a3e6cb855a Mon Sep 17 00:00:00 2001 From: amacleod Date: Thu, 10 Oct 2013 12:16:24 +0000 Subject: [PATCH] 2013-10-10 Andrew MacLeod * tree-flow.h: Move some prototypes to gimple.h. (gimple_fold_indirect_ref): Move prototype to gimple-fold.h. * gimple.h: Relocate some prototypes from tree-flow.h * builtins.c (std_gimplify_va_arg_expr, build_va_arg_indirect_ref): Move to gimplify.c. * gimplify.c (gimple_fold_indirect_ref): Move to gimple-fold.c. (build_va_arg_indirect_ref): Relocate and make static. (std_gimplify_va_arg_expr): Relocate here. * gimple-fold.c (gimple_fold_indirect_ref): Relocate here. * gimple-fold.h (gimple_fold_indirect_ref): Add prototype. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@203357 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 13 +++ gcc/builtins.c | 113 -------------------------- gcc/gimple-fold.c | 122 ++++++++++++++++++++++++++++ gcc/gimple-fold.h | 1 + gcc/gimple.h | 9 ++- gcc/gimplify.c | 236 ++++++++++++++++++++++++++---------------------------- gcc/tree-flow.h | 11 --- 7 files changed, 258 insertions(+), 247 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 87ba2a2..901af0b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2013-10-10 Andrew MacLeod + + * tree-flow.h: Move some prototypes to gimple.h. + (gimple_fold_indirect_ref): Move prototype to gimple-fold.h. + * gimple.h: Relocate some prototypes from tree-flow.h + * builtins.c (std_gimplify_va_arg_expr, build_va_arg_indirect_ref): + Move to gimplify.c. + * gimplify.c (gimple_fold_indirect_ref): Move to gimple-fold.c. + (build_va_arg_indirect_ref): Relocate and make static. + (std_gimplify_va_arg_expr): Relocate here. + * gimple-fold.c (gimple_fold_indirect_ref): Relocate here. + * gimple-fold.h (gimple_fold_indirect_ref): Add prototype. + 2013-10-10 Andreas Krebbel * doc/md.texi: Document the mnemonic attribute. diff --git a/gcc/builtins.c b/gcc/builtins.c index 3b16d59..5df5c54 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -43,7 +43,6 @@ along with GCC; see the file COPYING3. If not see #include "target.h" #include "langhooks.h" #include "basic-block.h" -#include "tree-mudflap.h" #include "tree-ssa.h" #include "value-prof.h" #include "diagnostic-core.h" @@ -51,9 +50,6 @@ along with GCC; see the file COPYING3. If not see #include "ubsan.h" -#ifndef PAD_VARARGS_DOWN -#define PAD_VARARGS_DOWN BYTES_BIG_ENDIAN -#endif static tree do_mpc_arg1 (tree, tree, int (*)(mpc_ptr, mpc_srcptr, mpc_rnd_t)); struct target_builtins default_target_builtins; @@ -4237,115 +4233,6 @@ expand_builtin_va_start (tree exp) return const0_rtx; } -/* The "standard" implementation of va_arg: read the value from the - current (padded) address and increment by the (padded) size. */ - -tree -std_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p, - gimple_seq *post_p) -{ - tree addr, t, type_size, rounded_size, valist_tmp; - unsigned HOST_WIDE_INT align, boundary; - bool indirect; - -#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. */ - gcc_unreachable (); -#endif - - indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false); - if (indirect) - type = build_pointer_type (type); - - align = PARM_BOUNDARY / BITS_PER_UNIT; - boundary = targetm.calls.function_arg_boundary (TYPE_MODE (type), type); - - /* When we align parameter on stack for caller, if the parameter - alignment is beyond MAX_SUPPORTED_STACK_ALIGNMENT, it will be - aligned at MAX_SUPPORTED_STACK_ALIGNMENT. We will match callee - here with caller. */ - if (boundary > MAX_SUPPORTED_STACK_ALIGNMENT) - boundary = MAX_SUPPORTED_STACK_ALIGNMENT; - - boundary /= BITS_PER_UNIT; - - /* 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 > align - && !integer_zerop (TYPE_SIZE (type))) - { - t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp, - fold_build_pointer_plus_hwi (valist_tmp, boundary - 1)); - gimplify_and_add (t, pre_p); - - t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp, - fold_build2 (BIT_AND_EXPR, TREE_TYPE (valist), - valist_tmp, - build_int_cst (TREE_TYPE (valist), -boundary))); - gimplify_and_add (t, pre_p); - } - else - boundary = align; - - /* If the actual alignment is less than the alignment of the type, - adjust the type accordingly so that we don't assume strict alignment - when dereferencing the pointer. */ - boundary *= BITS_PER_UNIT; - if (boundary < TYPE_ALIGN (type)) - { - type = build_variant_type_copy (type); - TYPE_ALIGN (type) = boundary; - } - - /* Compute the rounded size of the type. */ - 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_loc (input_location, 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)); - addr = fold_build_pointer_plus (addr, t); - } - - /* Compute new value for AP. */ - t = fold_build_pointer_plus (valist_tmp, rounded_size); - t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t); - gimplify_and_add (t, pre_p); - - addr = fold_convert (build_pointer_type (type), addr); - - if (indirect) - addr = build_va_arg_indirect_ref (addr); - - return build_va_arg_indirect_ref (addr); -} - -/* Build an indirect-ref expression over the given TREE, which represents a - piece of a va_arg() expansion. */ -tree -build_va_arg_indirect_ref (tree addr) -{ - addr = build_simple_mem_ref_loc (EXPR_LOCATION (addr), addr); - - if (flag_mudflap) /* Don't instrument va_arg INDIRECT_REF. */ - mf_mark (addr); - - return addr; -} /* Return a dummy expression of type TYPE in order to keep going after an error. */ diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index 9892c86..33e677f 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -3321,3 +3321,125 @@ gimple_val_nonnegative_real_p (tree val) return false; } + +/* Given a pointer value OP0, return a simplified version of an + indirection through OP0, or NULL_TREE if no simplification is + possible. Note that the resulting type may be different from + the type pointed to in the sense that it is still compatible + from the langhooks point of view. */ + +tree +gimple_fold_indirect_ref (tree t) +{ + tree ptype = TREE_TYPE (t), type = TREE_TYPE (ptype); + tree sub = t; + tree subtype; + + STRIP_NOPS (sub); + subtype = TREE_TYPE (sub); + if (!POINTER_TYPE_P (subtype)) + return NULL_TREE; + + if (TREE_CODE (sub) == ADDR_EXPR) + { + tree op = TREE_OPERAND (sub, 0); + tree optype = TREE_TYPE (op); + /* *&p => p */ + if (useless_type_conversion_p (type, optype)) + return op; + + /* *(foo *)&fooarray => fooarray[0] */ + if (TREE_CODE (optype) == ARRAY_TYPE + && TREE_CODE (TYPE_SIZE (TREE_TYPE (optype))) == INTEGER_CST + && useless_type_conversion_p (type, TREE_TYPE (optype))) + { + tree type_domain = TYPE_DOMAIN (optype); + tree min_val = size_zero_node; + if (type_domain && TYPE_MIN_VALUE (type_domain)) + min_val = TYPE_MIN_VALUE (type_domain); + if (TREE_CODE (min_val) == INTEGER_CST) + return build4 (ARRAY_REF, type, op, min_val, NULL_TREE, NULL_TREE); + } + /* *(foo *)&complexfoo => __real__ complexfoo */ + else if (TREE_CODE (optype) == COMPLEX_TYPE + && useless_type_conversion_p (type, TREE_TYPE (optype))) + return fold_build1 (REALPART_EXPR, type, op); + /* *(foo *)&vectorfoo => BIT_FIELD_REF */ + else if (TREE_CODE (optype) == VECTOR_TYPE + && useless_type_conversion_p (type, TREE_TYPE (optype))) + { + tree part_width = TYPE_SIZE (type); + tree index = bitsize_int (0); + return fold_build3 (BIT_FIELD_REF, type, op, part_width, index); + } + } + + /* *(p + CST) -> ... */ + if (TREE_CODE (sub) == POINTER_PLUS_EXPR + && TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST) + { + tree addr = TREE_OPERAND (sub, 0); + tree off = TREE_OPERAND (sub, 1); + tree addrtype; + + STRIP_NOPS (addr); + addrtype = TREE_TYPE (addr); + + /* ((foo*)&vectorfoo)[1] -> BIT_FIELD_REF */ + if (TREE_CODE (addr) == ADDR_EXPR + && TREE_CODE (TREE_TYPE (addrtype)) == VECTOR_TYPE + && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (addrtype))) + && host_integerp (off, 1)) + { + unsigned HOST_WIDE_INT offset = tree_low_cst (off, 1); + tree part_width = TYPE_SIZE (type); + unsigned HOST_WIDE_INT part_widthi + = tree_low_cst (part_width, 0) / BITS_PER_UNIT; + unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT; + tree index = bitsize_int (indexi); + if (offset / part_widthi + <= TYPE_VECTOR_SUBPARTS (TREE_TYPE (addrtype))) + return fold_build3 (BIT_FIELD_REF, type, TREE_OPERAND (addr, 0), + part_width, index); + } + + /* ((foo*)&complexfoo)[1] -> __imag__ complexfoo */ + if (TREE_CODE (addr) == ADDR_EXPR + && TREE_CODE (TREE_TYPE (addrtype)) == COMPLEX_TYPE + && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (addrtype)))) + { + tree size = TYPE_SIZE_UNIT (type); + if (tree_int_cst_equal (size, off)) + return fold_build1 (IMAGPART_EXPR, type, TREE_OPERAND (addr, 0)); + } + + /* *(p + CST) -> MEM_REF . */ + if (TREE_CODE (addr) != ADDR_EXPR + || DECL_P (TREE_OPERAND (addr, 0))) + return fold_build2 (MEM_REF, type, + addr, + build_int_cst_wide (ptype, + TREE_INT_CST_LOW (off), + TREE_INT_CST_HIGH (off))); + } + + /* *(foo *)fooarrptr => (*fooarrptr)[0] */ + if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE + && TREE_CODE (TYPE_SIZE (TREE_TYPE (TREE_TYPE (subtype)))) == INTEGER_CST + && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (subtype)))) + { + tree type_domain; + tree min_val = size_zero_node; + tree osub = sub; + sub = gimple_fold_indirect_ref (sub); + if (! sub) + sub = build1 (INDIRECT_REF, TREE_TYPE (subtype), osub); + type_domain = TYPE_DOMAIN (TREE_TYPE (sub)); + if (type_domain && TYPE_MIN_VALUE (type_domain)) + min_val = TYPE_MIN_VALUE (type_domain); + if (TREE_CODE (min_val) == INTEGER_CST) + return build4 (ARRAY_REF, type, sub, min_val, NULL_TREE, NULL_TREE); + } + + return NULL_TREE; +} diff --git a/gcc/gimple-fold.h b/gcc/gimple-fold.h index 9b818fc..7a631a9 100644 --- a/gcc/gimple-fold.h +++ b/gcc/gimple-fold.h @@ -39,5 +39,6 @@ extern tree fold_const_aggregate_ref_1 (tree, tree (*) (tree)); extern tree fold_const_aggregate_ref (tree); extern tree gimple_get_virt_method_for_binfo (HOST_WIDE_INT, tree); extern bool gimple_val_nonnegative_real_p (tree); +extern tree gimple_fold_indirect_ref (tree); #endif /* GCC_GIMPLE_FOLD_H */ diff --git a/gcc/gimple.h b/gcc/gimple.h index e8e98ad..ca7e394 100644 --- a/gcc/gimple.h +++ b/gcc/gimple.h @@ -5354,6 +5354,14 @@ void gsi_commit_one_edge_insert (edge, basic_block *); void gsi_commit_edge_inserts (void); gimple gimple_call_copy_skip_args (gimple, bitmap); +/* In gimplify.c. */ +tree force_gimple_operand_1 (tree, gimple_seq *, gimple_predicate, tree); +tree force_gimple_operand (tree, gimple_seq *, bool, tree); +tree force_gimple_operand_gsi_1 (gimple_stmt_iterator *, tree, + gimple_predicate, tree, + bool, enum gsi_iterator_update); +tree force_gimple_operand_gsi (gimple_stmt_iterator *, tree, bool, tree, + bool, enum gsi_iterator_update); /* Convenience routines to walk all statements of a gimple function. Note that this is useful exclusively before the code is converted @@ -5478,5 +5486,4 @@ gimple_seq_set_location (gimple_seq seq, location_t loc) #define PERCENT(x,y) ((float)(x) * 100.0 / (float)(y)) - #endif /* GCC_GIMPLE_H */ diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 86bda77..95287be 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -45,6 +45,7 @@ along with GCC; see the file COPYING3. If not see #include "langhooks-def.h" /* FIXME: for lhd_set_decl_assembler_name */ #include "tree-pass.h" /* FIXME: only for PROP_gimple_any */ +#include "tree-mudflap.h" enum gimplify_omp_var_data { @@ -4262,128 +4263,6 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, /* Given a pointer value OP0, return a simplified version of an indirection through OP0, or NULL_TREE if no simplification is - possible. Note that the resulting type may be different from - the type pointed to in the sense that it is still compatible - from the langhooks point of view. */ - -tree -gimple_fold_indirect_ref (tree t) -{ - tree ptype = TREE_TYPE (t), type = TREE_TYPE (ptype); - tree sub = t; - tree subtype; - - STRIP_NOPS (sub); - subtype = TREE_TYPE (sub); - if (!POINTER_TYPE_P (subtype)) - return NULL_TREE; - - if (TREE_CODE (sub) == ADDR_EXPR) - { - tree op = TREE_OPERAND (sub, 0); - tree optype = TREE_TYPE (op); - /* *&p => p */ - if (useless_type_conversion_p (type, optype)) - return op; - - /* *(foo *)&fooarray => fooarray[0] */ - if (TREE_CODE (optype) == ARRAY_TYPE - && TREE_CODE (TYPE_SIZE (TREE_TYPE (optype))) == INTEGER_CST - && useless_type_conversion_p (type, TREE_TYPE (optype))) - { - tree type_domain = TYPE_DOMAIN (optype); - tree min_val = size_zero_node; - if (type_domain && TYPE_MIN_VALUE (type_domain)) - min_val = TYPE_MIN_VALUE (type_domain); - if (TREE_CODE (min_val) == INTEGER_CST) - return build4 (ARRAY_REF, type, op, min_val, NULL_TREE, NULL_TREE); - } - /* *(foo *)&complexfoo => __real__ complexfoo */ - else if (TREE_CODE (optype) == COMPLEX_TYPE - && useless_type_conversion_p (type, TREE_TYPE (optype))) - return fold_build1 (REALPART_EXPR, type, op); - /* *(foo *)&vectorfoo => BIT_FIELD_REF */ - else if (TREE_CODE (optype) == VECTOR_TYPE - && useless_type_conversion_p (type, TREE_TYPE (optype))) - { - tree part_width = TYPE_SIZE (type); - tree index = bitsize_int (0); - return fold_build3 (BIT_FIELD_REF, type, op, part_width, index); - } - } - - /* *(p + CST) -> ... */ - if (TREE_CODE (sub) == POINTER_PLUS_EXPR - && TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST) - { - tree addr = TREE_OPERAND (sub, 0); - tree off = TREE_OPERAND (sub, 1); - tree addrtype; - - STRIP_NOPS (addr); - addrtype = TREE_TYPE (addr); - - /* ((foo*)&vectorfoo)[1] -> BIT_FIELD_REF */ - if (TREE_CODE (addr) == ADDR_EXPR - && TREE_CODE (TREE_TYPE (addrtype)) == VECTOR_TYPE - && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (addrtype))) - && host_integerp (off, 1)) - { - unsigned HOST_WIDE_INT offset = tree_low_cst (off, 1); - tree part_width = TYPE_SIZE (type); - unsigned HOST_WIDE_INT part_widthi - = tree_low_cst (part_width, 0) / BITS_PER_UNIT; - unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT; - tree index = bitsize_int (indexi); - if (offset / part_widthi - <= TYPE_VECTOR_SUBPARTS (TREE_TYPE (addrtype))) - return fold_build3 (BIT_FIELD_REF, type, TREE_OPERAND (addr, 0), - part_width, index); - } - - /* ((foo*)&complexfoo)[1] -> __imag__ complexfoo */ - if (TREE_CODE (addr) == ADDR_EXPR - && TREE_CODE (TREE_TYPE (addrtype)) == COMPLEX_TYPE - && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (addrtype)))) - { - tree size = TYPE_SIZE_UNIT (type); - if (tree_int_cst_equal (size, off)) - return fold_build1 (IMAGPART_EXPR, type, TREE_OPERAND (addr, 0)); - } - - /* *(p + CST) -> MEM_REF . */ - if (TREE_CODE (addr) != ADDR_EXPR - || DECL_P (TREE_OPERAND (addr, 0))) - return fold_build2 (MEM_REF, type, - addr, - build_int_cst_wide (ptype, - TREE_INT_CST_LOW (off), - TREE_INT_CST_HIGH (off))); - } - - /* *(foo *)fooarrptr => (*fooarrptr)[0] */ - if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE - && TREE_CODE (TYPE_SIZE (TREE_TYPE (TREE_TYPE (subtype)))) == INTEGER_CST - && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (subtype)))) - { - tree type_domain; - tree min_val = size_zero_node; - tree osub = sub; - sub = gimple_fold_indirect_ref (sub); - if (! sub) - sub = build1 (INDIRECT_REF, TREE_TYPE (subtype), osub); - type_domain = TYPE_DOMAIN (TREE_TYPE (sub)); - if (type_domain && TYPE_MIN_VALUE (type_domain)) - min_val = TYPE_MIN_VALUE (type_domain); - if (TREE_CODE (min_val) == INTEGER_CST) - return build4 (ARRAY_REF, type, sub, min_val, NULL_TREE, NULL_TREE); - } - - return NULL_TREE; -} - -/* Given a pointer value OP0, return a simplified version of an - indirection through OP0, or NULL_TREE if no simplification is possible. This may only be applied to a rhs of an expression. Note that the resulting type may be different from the type pointed to in the sense that it is still compatible from the langhooks @@ -8842,5 +8721,118 @@ force_gimple_operand_gsi (gimple_stmt_iterator *gsi, tree expr, var, before, m); } +#ifndef PAD_VARARGS_DOWN +#define PAD_VARARGS_DOWN BYTES_BIG_ENDIAN +#endif + +/* Build an indirect-ref expression over the given TREE, which represents a + piece of a va_arg() expansion. */ +tree +build_va_arg_indirect_ref (tree addr) +{ + addr = build_simple_mem_ref_loc (EXPR_LOCATION (addr), addr); + + if (flag_mudflap) /* Don't instrument va_arg INDIRECT_REF. */ + mf_mark (addr); + + return addr; +} + +/* The "standard" implementation of va_arg: read the value from the + current (padded) address and increment by the (padded) size. */ + +tree +std_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p, + gimple_seq *post_p) +{ + tree addr, t, type_size, rounded_size, valist_tmp; + unsigned HOST_WIDE_INT align, boundary; + bool indirect; + +#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. */ + gcc_unreachable (); +#endif + + indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false); + if (indirect) + type = build_pointer_type (type); + + align = PARM_BOUNDARY / BITS_PER_UNIT; + boundary = targetm.calls.function_arg_boundary (TYPE_MODE (type), type); + + /* When we align parameter on stack for caller, if the parameter + alignment is beyond MAX_SUPPORTED_STACK_ALIGNMENT, it will be + aligned at MAX_SUPPORTED_STACK_ALIGNMENT. We will match callee + here with caller. */ + if (boundary > MAX_SUPPORTED_STACK_ALIGNMENT) + boundary = MAX_SUPPORTED_STACK_ALIGNMENT; + + boundary /= BITS_PER_UNIT; + + /* 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 > align + && !integer_zerop (TYPE_SIZE (type))) + { + t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp, + fold_build_pointer_plus_hwi (valist_tmp, boundary - 1)); + gimplify_and_add (t, pre_p); + + t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp, + fold_build2 (BIT_AND_EXPR, TREE_TYPE (valist), + valist_tmp, + build_int_cst (TREE_TYPE (valist), -boundary))); + gimplify_and_add (t, pre_p); + } + else + boundary = align; + + /* If the actual alignment is less than the alignment of the type, + adjust the type accordingly so that we don't assume strict alignment + when dereferencing the pointer. */ + boundary *= BITS_PER_UNIT; + if (boundary < TYPE_ALIGN (type)) + { + type = build_variant_type_copy (type); + TYPE_ALIGN (type) = boundary; + } + + /* Compute the rounded size of the type. */ + 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_loc (input_location, 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)); + addr = fold_build_pointer_plus (addr, t); + } + + /* Compute new value for AP. */ + t = fold_build_pointer_plus (valist_tmp, rounded_size); + t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t); + gimplify_and_add (t, pre_p); + + addr = fold_convert (build_pointer_type (type), addr); + + if (indirect) + addr = build_va_arg_indirect_ref (addr); + + return build_va_arg_indirect_ref (addr); +} #include "gt-gimplify.h" diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h index c4678d9..5ea5d06 100644 --- a/gcc/tree-flow.h +++ b/gcc/tree-flow.h @@ -159,15 +159,4 @@ extern tree gimplify_build1 (gimple_stmt_iterator *, enum tree_code, extern void extract_true_false_edges_from_block (basic_block, edge *, edge *); extern unsigned int execute_fixup_cfg (void); -/* In gimplify.c */ -tree force_gimple_operand_1 (tree, gimple_seq *, gimple_predicate, tree); -tree force_gimple_operand (tree, gimple_seq *, bool, tree); -tree force_gimple_operand_gsi_1 (gimple_stmt_iterator *, tree, - gimple_predicate, tree, - bool, enum gsi_iterator_update); -tree force_gimple_operand_gsi (gimple_stmt_iterator *, tree, bool, tree, - bool, enum gsi_iterator_update); -tree gimple_fold_indirect_ref (tree); - - #endif /* _TREE_FLOW_H */ -- 2.7.4