diff options
Diffstat (limited to 'gcc/gimplify.c')
-rw-r--r-- | gcc/gimplify.c | 53 |
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. */ |