From 974aedcce8d3eb6d46493c1e597b75743cb4c3db Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Wed, 22 Nov 2017 16:06:18 +0000 Subject: re PR c++/60336 (empty struct value is passed differently in C and C++) PR c++/60336 PR middle-end/67239 PR target/68355 * c-decl.c (grokdeclarator): Set DECL_PADDING_P on unnamed bit-fields. * class.c (layout_class_type): Set DECL_PADDING_P on padding. * decl.c (cxx_init_decl_processing): Set TRANSLATION_UNIT_WARN_EMPTY_P. (grokdeclarator): Set DECL_PADDING_P on unnamed bit-fields. * lto.c (compare_tree_sccs_1): Compare TYPE_EMPTY_P and DECL_PADDING_P. * calls.c (initialize_argument_information): Call warn_parameter_passing_abi target hook. (store_one_arg): Use 0 for empty record size. Don't push 0 size argument onto stack. (must_pass_in_stack_var_size_or_pad): Return false for empty types. * common.opt: Update -fabi-version description. * config/i386/i386.c (init_cumulative_args): Set cum->warn_empty. (ix86_gimplify_va_arg): Call arg_int_size_in_bytes instead of int_size_in_bytes. (ix86_is_empty_record): New function. (ix86_warn_parameter_passing_abi): New function. (TARGET_EMPTY_RECORD_P): Redefine. (TARGET_WARN_PARAMETER_PASSING_ABI): Redefine. * config/i386/i386.h (CUMULATIVE_ARGS): Add warn_empty. * doc/tm.texi: Regenerated. * doc/tm.texi.in (TARGET_EMPTY_RECORD_P, TARGET_WARN_PARAMETER_PASSING_ABI): Add. * dwarf2out.c (get_ultimate_context): Move to tree.c. * explow.c (hard_function_value): Call arg_int_size_in_bytes instead of int_size_in_bytes. * expr.c (copy_blkmode_to_reg): Likewise. * function.c (aggregate_value_p): Return 0 for empty types. (assign_parm_find_entry_rtl): Call warn_parameter_passing_abi target hook. (locate_and_pad_parm): Call arg size_in_bytes instead size_in_bytes. * lto-streamer-out.c (hash_tree): Hash TYPE_EMPTY_P and DECL_PADDING_P. * stor-layout.c (finalize_type_size): Set TYPE_EMPTY_P. * target.def (empty_record_p, warn_parameter_passing_abi): New target hooks. * targhooks.c (hook_void_CUMULATIVE_ARGS_tree): New hook. (std_gimplify_va_arg_expr): Skip empty records. Call arg_size_in_bytes instead size_in_bytes. * targhooks.h (hook_void_CUMULATIVE_ARGS_tree): Declare. * tree-core.h (tree_type_common): Add empty_flag. (tree_decl_common): Update comments. * tree-streamer-in.c (unpack_ts_decl_common_value_fields): Stream DECL_PADDING_P. (unpack_ts_type_common_value_fields): Stream TYPE_EMPTY_P. * tree-streamer-out.c (pack_ts_decl_common_value_fields): Stream DECL_PADDING_P. (pack_ts_type_common_value_fields): Stream TYPE_EMPTY_P. * tree.c (default_is_empty_type): New function. (default_is_empty_record): New function. (arg_int_size_in_bytes): New function. (arg_size_in_bytes): New function. (get_ultimate_context): New function. * tree.h: Define TYPE_EMPTY_P, DECL_PADDING_P and TRANSLATION_UNIT_WARN_EMPTY_P. (default_is_empty_record, arg_int_size_in_bytes, arg_size_in_bytes, get_ultimate_context): Declare. * g++.dg/abi/empty12.C: New test. * g++.dg/abi/empty12.h: New test. * g++.dg/abi/empty12a.c: New test. * g++.dg/abi/empty13.C: New test. * g++.dg/abi/empty13.h: New test. * g++.dg/abi/empty13a.c: New test. * g++.dg/abi/empty14.C: New test. * g++.dg/abi/empty14.h: New test. * g++.dg/abi/empty14a.c: New test. * g++.dg/abi/empty15.C: New test. * g++.dg/abi/empty15.h: New test. * g++.dg/abi/empty15a.c: New test. * g++.dg/abi/empty16.C: New test. * g++.dg/abi/empty16.h: New test. * g++.dg/abi/empty16a.c: New test. * g++.dg/abi/empty17.C: New test. * g++.dg/abi/empty17.h: New test. * g++.dg/abi/empty17a.c: New test. * g++.dg/abi/empty18.C: New test. * g++.dg/abi/empty18.h: New test. * g++.dg/abi/empty18a.c: New test. * g++.dg/abi/empty19.C: New test. * g++.dg/abi/empty19.h: New test. * g++.dg/abi/empty19a.c: New test. * g++.dg/abi/empty20.C: New test. * g++.dg/abi/empty21.C: New test. * g++.dg/abi/empty22.C: New test. * g++.dg/abi/empty22.h: New test. * g++.dg/abi/empty22a.c: New test. * g++.dg/abi/empty23.C: New test. * g++.dg/abi/empty24.C: New test. * g++.dg/abi/empty25.C: New test. * g++.dg/abi/empty25.h: New test. * g++.dg/abi/empty25a.c: New test. * g++.dg/abi/empty26.C: New test. * g++.dg/abi/empty26.h: New test. * g++.dg/abi/empty26a.c: New test. * g++.dg/abi/empty27.C: New test. * g++.dg/abi/empty28.C: New test. * g++.dg/abi/pr60336-1.C: New test. * g++.dg/abi/pr60336-10.C: New test. * g++.dg/abi/pr60336-11.C: New test. * g++.dg/abi/pr60336-12.C: New test. * g++.dg/abi/pr60336-2.C: New test. * g++.dg/abi/pr60336-3.C: New test. * g++.dg/abi/pr60336-4.C: New test. * g++.dg/abi/pr60336-5.C: New test. * g++.dg/abi/pr60336-6.C: New test. * g++.dg/abi/pr60336-7.C: New test. * g++.dg/abi/pr60336-8.C: New test. * g++.dg/abi/pr60336-9.C: New test. * g++.dg/abi/pr68355.C: New test. * g++.dg/lto/pr60336_0.C: New test. Co-Authored-By: H.J. Lu Co-Authored-By: Jason Merrill From-SVN: r255066 --- gcc/calls.c | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) (limited to 'gcc/calls.c') diff --git a/gcc/calls.c b/gcc/calls.c index 64f9f50..8ae9899 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -2002,6 +2002,8 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED, args[i].unsignedp = unsignedp; args[i].mode = mode; + targetm.calls.warn_parameter_passing_abi (args_so_far, type); + args[i].reg = targetm.calls.function_arg (args_so_far, mode, type, argpos < n_named_args); @@ -5514,7 +5516,11 @@ store_one_arg (struct arg_data *arg, rtx argblock, int flags, Note that in C the default argument promotions will prevent such mismatches. */ - size = GET_MODE_SIZE (arg->mode); + if (TYPE_EMPTY_P (TREE_TYPE (pval))) + size = 0; + else + size = GET_MODE_SIZE (arg->mode); + /* Compute how much space the push instruction will push. On many machines, pushing a byte will advance the stack pointer by a halfword. */ @@ -5546,10 +5552,12 @@ store_one_arg (struct arg_data *arg, rtx argblock, int flags, /* This isn't already where we want it on the stack, so put it there. This can either be done with push or copy insns. */ - if (!emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), NULL_RTX, - parm_align, partial, reg, used - size, argblock, - ARGS_SIZE_RTX (arg->locate.offset), reg_parm_stack_space, - ARGS_SIZE_RTX (arg->locate.alignment_pad), true)) + if (used + && !emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), + NULL_RTX, parm_align, partial, reg, used - size, + argblock, ARGS_SIZE_RTX (arg->locate.offset), + reg_parm_stack_space, + ARGS_SIZE_RTX (arg->locate.alignment_pad), true)) sibcall_failure = 1; /* Unless this is a partially-in-register argument, the argument is now @@ -5582,9 +5590,9 @@ store_one_arg (struct arg_data *arg, rtx argblock, int flags, /* PUSH_ROUNDING has no effect on us, because emit_push_insn for BLKmode is careful to avoid it. */ excess = (arg->locate.size.constant - - int_size_in_bytes (TREE_TYPE (pval)) + - arg_int_size_in_bytes (TREE_TYPE (pval)) + partial); - size_rtx = expand_expr (size_in_bytes (TREE_TYPE (pval)), + size_rtx = expand_expr (arg_size_in_bytes (TREE_TYPE (pval)), NULL_RTX, TYPE_MODE (sizetype), EXPAND_NORMAL); } @@ -5660,10 +5668,12 @@ store_one_arg (struct arg_data *arg, rtx argblock, int flags, } } - emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), size_rtx, - parm_align, partial, reg, excess, argblock, - ARGS_SIZE_RTX (arg->locate.offset), reg_parm_stack_space, - ARGS_SIZE_RTX (arg->locate.alignment_pad), false); + if (!CONST_INT_P (size_rtx) || INTVAL (size_rtx) != 0) + emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), size_rtx, + parm_align, partial, reg, excess, argblock, + ARGS_SIZE_RTX (arg->locate.offset), + reg_parm_stack_space, + ARGS_SIZE_RTX (arg->locate.alignment_pad), false); /* Unless this is a partially-in-register argument, the argument is now in the stack. @@ -5741,6 +5751,9 @@ must_pass_in_stack_var_size_or_pad (machine_mode mode, const_tree type) if (TREE_ADDRESSABLE (type)) return true; + if (TYPE_EMPTY_P (type)) + return false; + /* If the padding and mode of the type is such that a copy into a register would put it into the wrong part of the register. */ if (mode == BLKmode -- cgit v1.1