From 4a7cb16f83d70f77b4ba3a022486cedb3679394a Mon Sep 17 00:00:00 2001 From: Andrew MacLeod <amacleod@redhat.com> Date: Thu, 24 Oct 2013 19:02:44 +0000 Subject: [PATCH] builtins.c (dummy_object, [...]): Move to gimplify.c. * builtins.c (dummy_object, gimplify_va_arg_expr): Move to gimplify.c. * gimplify.c (build_va_arg_indirect_ref, std_gimplify_va_arg_expr): Move to targhooks.c. (dummy_object, gimplify_va_arg_expr): Relocate from builtins.c. * targhooks.c (build_va_arg_indirect_ref, std_gimplify_va_arg_expr): Relocate from gimplify.c. * targhooks.h: Add 2 prototypes. * tree.h. Delete 2 prototypes. From-SVN: r204032 --- gcc/ChangeLog | 11 +++ gcc/builtins.c | 104 ---------------------------- gcc/gimplify.c | 175 +++++++++++++++++++++++------------------------- gcc/targhooks.c | 116 ++++++++++++++++++++++++++++++++ gcc/targhooks.h | 2 + gcc/tree.h | 2 - 6 files changed, 211 insertions(+), 199 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1b3b1ea9aaef..3f23ec6937d3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2013-10-24 Andrew MacLeod <amacleod@redhat.com> + + * builtins.c (dummy_object, gimplify_va_arg_expr): Move to gimplify.c. + * gimplify.c (build_va_arg_indirect_ref, std_gimplify_va_arg_expr): + Move to targhooks.c. + (dummy_object, gimplify_va_arg_expr): Relocate from builtins.c. + * targhooks.c (build_va_arg_indirect_ref, std_gimplify_va_arg_expr): + Relocate from gimplify.c. + * targhooks.h: Add 2 prototypes. + * tree.h: Delete 2 prototypes. + 2013-10-24 Igor Shevlyakov <igor.shevlyakov@gmail.com> * tree-ssa-loop-ivopts.c (multiplier_allowed_in_address_p ): Check both diff --git a/gcc/builtins.c b/gcc/builtins.c index df6f4af3d8a0..b380c2c6d0b7 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -4234,110 +4234,6 @@ expand_builtin_va_start (tree exp) return const0_rtx; } - -/* Return a dummy expression of type TYPE in order to keep going after an - error. */ - -static tree -dummy_object (tree type) -{ - tree t = build_int_cst (build_pointer_type (type), 0); - return build2 (MEM_REF, type, t, t); -} - -/* Gimplify __builtin_va_arg, aka VA_ARG_EXPR, which is not really a - builtin function, but a very special sort of operator. */ - -enum gimplify_status -gimplify_va_arg_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) -{ - tree promoted_type, have_va_type; - tree valist = TREE_OPERAND (*expr_p, 0); - tree type = TREE_TYPE (*expr_p); - tree t; - location_t loc = EXPR_LOCATION (*expr_p); - - /* Verify that valist is of the proper type. */ - have_va_type = TREE_TYPE (valist); - if (have_va_type == error_mark_node) - return GS_ERROR; - have_va_type = targetm.canonical_va_list_type (have_va_type); - - if (have_va_type == NULL_TREE) - { - error_at (loc, "first argument to %<va_arg%> not of type %<va_list%>"); - return GS_ERROR; - } - - /* Generate a diagnostic for requesting data of a type that cannot - be passed through `...' due to type promotion at the call site. */ - if ((promoted_type = lang_hooks.types.type_promotes_to (type)) - != type) - { - static bool gave_help; - bool warned; - - /* Unfortunately, this is merely undefined, rather than a constraint - violation, so we cannot make this an error. If this call is never - executed, the program is still strictly conforming. */ - warned = warning_at (loc, 0, - "%qT is promoted to %qT when passed through %<...%>", - type, promoted_type); - if (!gave_help && warned) - { - gave_help = true; - inform (loc, "(so you should pass %qT not %qT to %<va_arg%>)", - promoted_type, type); - } - - /* We can, however, treat "undefined" any way we please. - Call abort to encourage the user to fix the program. */ - if (warned) - inform (loc, "if this code is reached, the program will abort"); - /* Before the abort, allow the evaluation of the va_list - expression to exit or longjmp. */ - gimplify_and_add (valist, pre_p); - t = build_call_expr_loc (loc, - builtin_decl_implicit (BUILT_IN_TRAP), 0); - gimplify_and_add (t, pre_p); - - /* This is dead code, but go ahead and finish so that the - mode of the result comes out right. */ - *expr_p = dummy_object (type); - return GS_ALL_DONE; - } - else - { - /* Make it easier for the backends by protecting the valist argument - from multiple evaluations. */ - if (TREE_CODE (have_va_type) == ARRAY_TYPE) - { - /* For this case, the backends will be expecting a pointer to - TREE_TYPE (abi), but it's possible we've - actually been given an array (an actual TARGET_FN_ABI_VA_LIST). - So fix it. */ - if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE) - { - tree p1 = build_pointer_type (TREE_TYPE (have_va_type)); - valist = fold_convert_loc (loc, p1, - build_fold_addr_expr_loc (loc, valist)); - } - - 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.gimplify_va_arg_expr) - /* FIXME: Once most targets are converted we should merely - assert this is non-null. */ - return GS_ALL_DONE; - - *expr_p = targetm.gimplify_va_arg_expr (valist, type, pre_p, post_p); - return GS_OK; - } -} - /* Expand EXP, a call to __builtin_va_end. */ static rtx diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 8d7844005bf0..d5b535d2bfb1 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -9258,118 +9258,107 @@ 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 +/* Return a dummy expression of type TYPE in order to keep going after an + error. */ -/* 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) +static tree +dummy_object (tree type) { - 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; + tree t = build_int_cst (build_pointer_type (type), 0); + return build2 (MEM_REF, type, t, t); } -/* The "standard" implementation of va_arg: read the value from the - current (padded) address and increment by the (padded) size. */ +/* Gimplify __builtin_va_arg, aka VA_ARG_EXPR, which is not really a + builtin function, but a very special sort of operator. */ -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); +enum gimplify_status +gimplify_va_arg_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) +{ + tree promoted_type, have_va_type; + tree valist = TREE_OPERAND (*expr_p, 0); + tree type = TREE_TYPE (*expr_p); + tree t; + location_t loc = EXPR_LOCATION (*expr_p); - align = PARM_BOUNDARY / BITS_PER_UNIT; - boundary = targetm.calls.function_arg_boundary (TYPE_MODE (type), type); + /* Verify that valist is of the proper type. */ + have_va_type = TREE_TYPE (valist); + if (have_va_type == error_mark_node) + return GS_ERROR; + have_va_type = targetm.canonical_va_list_type (have_va_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; + if (have_va_type == NULL_TREE) + { + error_at (loc, "first argument to %<va_arg%> not of type %<va_list%>"); + return GS_ERROR; + } - boundary /= BITS_PER_UNIT; + /* Generate a diagnostic for requesting data of a type that cannot + be passed through `...' due to type promotion at the call site. */ + if ((promoted_type = lang_hooks.types.type_promotes_to (type)) + != type) + { + static bool gave_help; + bool warned; - /* Hoist the valist value into a temporary for the moment. */ - valist_tmp = get_initialized_tmp_var (valist, pre_p, NULL); + /* Unfortunately, this is merely undefined, rather than a constraint + violation, so we cannot make this an error. If this call is never + executed, the program is still strictly conforming. */ + warned = warning_at (loc, 0, + "%qT is promoted to %qT when passed through %<...%>", + type, promoted_type); + if (!gave_help && warned) + { + gave_help = true; + inform (loc, "(so you should pass %qT not %qT to %<va_arg%>)", + promoted_type, type); + } - /* 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)); + /* We can, however, treat "undefined" any way we please. + Call abort to encourage the user to fix the program. */ + if (warned) + inform (loc, "if this code is reached, the program will abort"); + /* Before the abort, allow the evaluation of the va_list + expression to exit or longjmp. */ + gimplify_and_add (valist, pre_p); + t = build_call_expr_loc (loc, + builtin_decl_implicit (BUILT_IN_TRAP), 0); 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); + /* This is dead code, but go ahead and finish so that the + mode of the result comes out right. */ + *expr_p = dummy_object (type); + return GS_ALL_DONE; } 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; - } + /* Make it easier for the backends by protecting the valist argument + from multiple evaluations. */ + if (TREE_CODE (have_va_type) == ARRAY_TYPE) + { + /* For this case, the backends will be expecting a pointer to + TREE_TYPE (abi), but it's possible we've + actually been given an array (an actual TARGET_FN_ABI_VA_LIST). + So fix it. */ + if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE) + { + tree p1 = build_pointer_type (TREE_TYPE (have_va_type)); + valist = fold_convert_loc (loc, p1, + build_fold_addr_expr_loc (loc, valist)); + } - /* Compute the rounded size of the type. */ - type_size = size_in_bytes (type); - rounded_size = round_up (type_size, align); + 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); - /* Reduce rounded_size so it's sharable with the postqueue. */ - gimplify_expr (&rounded_size, pre_p, post_p, is_gimple_val, fb_rvalue); + if (!targetm.gimplify_va_arg_expr) + /* FIXME: Once most targets are converted we should merely + assert this is non-null. */ + return GS_ALL_DONE; - /* 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); + *expr_p = targetm.gimplify_va_arg_expr (valist, type, pre_p, post_p); + return GS_OK; } - - /* 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/targhooks.c b/gcc/targhooks.c index 2504436ecf10..bee404d52f7f 100644 --- a/gcc/targhooks.c +++ b/gcc/targhooks.c @@ -72,6 +72,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-ssanames.h" #include "tree-ssa-alias.h" #include "insn-codes.h" +#include "tree-mudflap.h" bool @@ -1565,4 +1566,119 @@ default_canonicalize_comparison (int *, rtx *, rtx *, bool) { } +#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-targhooks.h" diff --git a/gcc/targhooks.h b/gcc/targhooks.h index b3bd15503cde..48de2a8b53cd 100644 --- a/gcc/targhooks.h +++ b/gcc/targhooks.h @@ -202,3 +202,5 @@ extern void default_asm_output_ident_directive (const char*); extern enum machine_mode default_cstore_mode (enum insn_code); extern bool default_member_type_forces_blk (const_tree, enum machine_mode); +extern tree build_va_arg_indirect_ref (tree); +extern tree std_gimplify_va_arg_expr (tree, tree, gimple_seq *, gimple_seq *); diff --git a/gcc/tree.h b/gcc/tree.h index 2f4514d6a744..7732d6926d0f 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -4508,8 +4508,6 @@ extern tree build_call_expr_loc (location_t, tree, int, ...); extern tree build_call_expr (tree, int, ...); extern tree mathfn_built_in (tree, enum built_in_function fn); extern tree c_strlen (tree, int); -extern tree std_gimplify_va_arg_expr (tree, tree, gimple_seq *, gimple_seq *); -extern tree build_va_arg_indirect_ref (tree); extern tree build_string_literal (int, const char *); extern bool validate_arglist (const_tree, ...); extern rtx builtin_memset_read_str (void *, HOST_WIDE_INT, enum machine_mode); -- GitLab