aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimplify.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/gimplify.c')
-rw-r--r--gcc/gimplify.c53
1 files changed, 35 insertions, 18 deletions
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 623d33d..322d0ba 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -4658,9 +4658,11 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
tree type = TREE_TYPE (call);
tree ap = CALL_EXPR_ARG (call, 0);
tree tag = CALL_EXPR_ARG (call, 1);
+ tree do_deref = CALL_EXPR_ARG (call, 2);
tree newcall = build_call_expr_internal_loc (EXPR_LOCATION (call),
- IFN_VA_ARG, type, 3, ap,
- tag, vlasize);
+ IFN_VA_ARG, type, 4, ap,
+ tag, do_deref,
+ vlasize);
tree *call_p = &(TREE_OPERAND (*from_p, 0));
*call_p = newcall;
}
@@ -9304,8 +9306,8 @@ dummy_object (tree type)
and TYPE. */
tree
-gimplify_va_arg_internal (tree valist, tree type, location_t loc,
- gimple_seq *pre_p, gimple_seq *post_p)
+gimplify_va_arg_internal (tree valist, tree type, gimple_seq *pre_p,
+ gimple_seq *post_p)
{
tree have_va_type = TREE_TYPE (valist);
tree cano_type = targetm.canonical_va_list_type (have_va_type);
@@ -9317,17 +9319,7 @@ gimplify_va_arg_internal (tree valist, tree type, location_t loc,
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));
- }
-
+ gcc_assert (TREE_CODE (TREE_TYPE (valist)) != ARRAY_TYPE);
gimplify_expr (&valist, pre_p, post_p, is_gimple_val, fb_rvalue);
}
else
@@ -9346,7 +9338,7 @@ gimplify_va_arg_expr (tree *expr_p, gimple_seq *pre_p,
tree promoted_type, have_va_type;
tree valist = TREE_OPERAND (*expr_p, 0);
tree type = TREE_TYPE (*expr_p);
- tree t, tag, ap;
+ tree t, tag, ap, do_deref;
location_t loc = EXPR_LOCATION (*expr_p);
/* Verify that valist is of the proper type. */
@@ -9400,9 +9392,34 @@ gimplify_va_arg_expr (tree *expr_p, gimple_seq *pre_p,
}
/* Transform a VA_ARG_EXPR into an VA_ARG internal function. */
- ap = build_fold_addr_expr_loc (loc, valist);
+ if (TREE_CODE (have_va_type) == ARRAY_TYPE)
+ {
+ if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
+ {
+ /* Take the address, but don't strip it. Gimplify_va_arg_internal
+ expects a pointer to array element type. */
+ ap = build_fold_addr_expr_loc (loc, valist);
+ do_deref = integer_zero_node;
+ }
+ else
+ {
+ /* Don't take the address. Gimplify_va_arg_internal expects a pointer
+ to array element type, and we already have that.
+ See also comment in build_va_arg. */
+ ap = valist;
+ do_deref = integer_zero_node;
+ }
+ }
+ else
+ {
+ /* No special handling. Take the address here, note that it needs to be
+ stripped before calling gimplify_va_arg_internal. */
+ ap = build_fold_addr_expr_loc (loc, valist);
+ do_deref = integer_one_node;
+ }
tag = build_int_cst (build_pointer_type (type), 0);
- *expr_p = build_call_expr_internal_loc (loc, IFN_VA_ARG, type, 2, ap, tag);
+ *expr_p = build_call_expr_internal_loc (loc, IFN_VA_ARG, type, 3, ap, tag,
+ do_deref);
/* Clear the tentatively set PROP_gimple_lva, to indicate that IFN_VA_ARG
needs to be expanded. */