On Wed, Dec 9, 2015 at 10:53 AM, H.J. Lu <hjl.to...@gmail.com> wrote: > On Wed, Dec 9, 2015 at 6:05 AM, Richard Biener > <richard.guent...@gmail.com> wrote: >> On Tue, Dec 8, 2015 at 5:22 PM, H.J. Lu <hjl.to...@gmail.com> wrote: >>> On Mon, Nov 23, 2015 at 12:53 PM, H.J. Lu <hjl.to...@gmail.com> wrote: >>>> On Mon, Nov 23, 2015 at 1:57 AM, Richard Biener >>>> <richard.guent...@gmail.com> wrote: >>>>> On Sat, Nov 21, 2015 at 12:46 AM, H.J. Lu <hjl.to...@gmail.com> wrote: >>>>>> On Fri, Nov 20, 2015 at 2:17 PM, Jason Merrill <ja...@redhat.com> wrote: >>>>>>> On 11/20/2015 01:52 PM, H.J. Lu wrote: >>>>>>>> >>>>>>>> On Tue, Nov 17, 2015 at 4:22 AM, Richard Biener >>>>>>>> <richard.guent...@gmail.com> wrote: >>>>>>>>> >>>>>>>>> On Tue, Nov 17, 2015 at 12:01 PM, H.J. Lu <hjl.to...@gmail.com> wrote: >>>>>>>>>> >>>>>>>>>> Empty record should be returned and passed the same way in C and C++. >>>>>>>>>> This patch adds LANG_HOOKS_EMPTY_RECORD_P for C++ empty class, which >>>>>>>>>> defaults to return false. For C++, LANG_HOOKS_EMPTY_RECORD_P is >>>>>>>>>> defined >>>>>>>>>> to is_really_empty_class, which returns true for C++ empty classes. >>>>>>>>>> For >>>>>>>>>> LTO, we stream out a bit to indicate if a record is empty and we >>>>>>>>>> store >>>>>>>>>> it in TYPE_LANG_FLAG_0 when streaming in. get_ref_base_and_extent is >>>>>>>>>> changed to set bitsize to 0 for empty records. Middle-end and x86 >>>>>>>>>> backend are updated to ignore empty records for parameter passing and >>>>>>>>>> function value return. Other targets may need similar changes. >>>>>>>>> >>>>>>>>> >>>>>>>>> Please avoid a new langhook for this and instead claim a bit in >>>>>>>>> tree_type_common >>>>>>>>> like for example restrict_flag (double-check it is unused for >>>>>>>>> non-pointers). >>>>>>>> >>>>>>>> >>>>>>>> There is no bit in tree_type_common I can overload. restrict_flag is >>>>>>>> checked for non-pointers to issue an error when it is used on >>>>>>>> non-pointers: >>>>>>>> >>>>>>>> >>>>>>>> /export/gnu/import/git/sources/gcc/gcc/testsuite/g++.dg/template/qualttp20.C:19:38: >>>>>>>> error: ‘__restrict__’ qualifiers cannot be applied to ‘AS::L’ >>>>>>>> typedef typename T::L __restrict__ r;// { dg-error "'__restrict__' >>>>>>>> qualifiers cannot" "" } >>>>>>> >>>>>>> >>>>>>> The C++ front end only needs to check TYPE_RESTRICT for this purpose on >>>>>>> front-end-specific type codes like TEMPLATE_TYPE_PARM; cp_type_quals >>>>>>> could >>>>>>> handle that specifically if you change TYPE_RESTRICT to only apply to >>>>>>> pointers. >>>>>>> >>>>>> >>>>>> restrict_flag is also checked in this case: >>>>>> >>>>>> [hjl@gnu-6 gcc]$ cat x.i >>>>>> struct dummy { }; >>>>>> >>>>>> struct dummy >>>>>> foo (struct dummy __restrict__ i) >>>>>> { >>>>>> return i; >>>>>> } >>>>>> [hjl@gnu-6 gcc]$ gcc -S x.i -Wall >>>>>> x.i:4:13: error: invalid use of ‘restrict’ >>>>>> foo (struct dummy __restrict__ i) >>>>>> ^ >>>>>> x.i:4:13: error: invalid use of ‘restrict’ >>>>>> [hjl@gnu-6 gcc]$ >>>>>> >>>>>> restrict_flag can't also be used to indicate `i' is an empty record. >>>>> >>>>> I'm sure this error can be done during parsing w/o relying on >>>>> TYPE_RESTRICT. >>>>> >>>>> But well, use any other free bit (but do not enlarge >>>>> tree_type_common). Eventually >>>>> you can free up a bit by putting sth into type_lang_specific currently >>>>> using bits >>>>> in tree_type_common. >>>> >>>> There are no bits in tree_type_common I can move. Instead, >>>> this patch overloads side_effects_flag in tree_base. Tested on >>>> Linux/x86-64. OK for trunk? >> >> I'm fine with using side_effects_flag for this. >> >> I miss an explanation of where this detail of the ABI is documented and >> wonder >> if the term "empty record" is also used in that document and how it is >> documented. >> >> Thus >> >> +/* Nonzero in a type considered an empty record. */ >> +#define TYPE_EMPTY_RECORD(NODE) \ >> + (TYPE_CHECK (NODE)->base.side_effects_flag) >> >> should refer to the ABI where is defined what an "empty record" is and how >> it is handled by the backend(s). > > Empty C++ class is a corner case which isn't covered in psABI nor C++ ABI. > There is no mention of "empty record" in GCC documentation. But there are > plenty of "empty class" in gcc/cp. This change affects all targets. C++ ABI > should specify how it should be passed. > >> +/* Return true if type T is an empty record. */ >> + >> +static inline bool >> +type_is_empty_record_p (const_tree t) >> +{ >> + return TYPE_EMPTY_RECORD (TYPE_MAIN_VARIANT (t)); >> >> the type checker should probably check the bit is consistent across >> variants so it can be tested on any of them. > > TYPE_EMPTY_RECORD is only relevant for parameter passing. For > > struct foo; > typedef foo bar; > > TYPE_EMPTY_RECORD has no impact. Since call only uses > the main variant type, checking TYPE_MAIN_VARIANT is sufficient. > >> You fail to adjust other targets gimplification hooks which suggests >> this is a detail of the x86 psABI and not the C++ ABI? If so I miss >> a -Wpsabi warning for this change. > > My change is generic. The only x86 specific change is > > diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c > index d30fbff..308d9a4e 100644 > --- a/gcc/config/i386/i386.c > +++ b/gcc/config/i386/i386.c > @@ -10292,7 +10292,8 @@ ix86_gimplify_va_arg (tree valist, tree type, > gimple_seq > *pre_p, > indirect_p = pass_by_reference (NULL, TYPE_MODE (type), type, false); > if (indirect_p) > type = build_pointer_type (type); > - size = int_size_in_bytes (type); > + bool empty_record = type && type_is_empty_record_p (type); > + size = empty_record ? 0 : int_size_in_bytes (type); > rsize = CEIL (size, UNITS_PER_WORD); > > nat_mode = type_natural_mode (type, NULL, false); > > which is for 64-bit variadic functions. I added a testcase, > g++.dg/pr60336-2.C, for it. There are also other variadic tests > in g++.dg/compat. If a target doesn't use std_gimplify_va_arg_expr, > it needs similar change. I see that TARGET_GIMPLIFY_VA_ARG_EXPR > is also defined in > > aarch64/aarch64.c > alpha/alpha.c > arm/arm.c > epiphany/epiphany.c > ia64/ia64.c > mep/mep.c > mips/mips.c > msp430/msp430.c > pa/pa.c > rs6000/rs6000.c > s390/s390.c > sh/sh.c > sparc/sparc.c > spu/spu.c > stormy16/stormy16.c > tilegx/tilegx.c > tilepro/tilepro.c > visium/visium.c > xtensa/xtensa.c > > I will prepare a separate patch for those targets to try. >
Here is a patch for other backends to properly pass C++ empty class. One can check out hjl/pr60336/master branch from https://github.com/hjl-tools/gcc to get both generic and target-dependent patches. -- H.J.
From 7332cc2ab12c46639fa029ba2af023c654db7a93 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" <hjl.to...@gmail.com> Date: Wed, 9 Dec 2015 12:48:07 -0800 Subject: [PATCH] Properly pass C++ empty class Use 0 for empty record size in TARGET_GIMPLIFY_VA_ARG_EXPR. PR c++/60336 PR middle-end/67239 PR target/68355 * config/aarch64/aarch64.c (aarch64_gimplify_va_arg_expr): Use 0 for empty record size. * config/mep/mep.c (mep_gimplify_va_arg_expr): Likewise. * config/mips/mips.c (mips_std_gimplify_va_arg_expr): Likewise. (mips_gimplify_va_arg_expr): Likewise. * config/msp430/msp430.c (msp430_gimplify_va_arg_expr): Likewise. * config/pa/pa.c (hppa_gimplify_va_arg_expr): Likewise. * config/rs6000/rs6000.c (rs6000_gimplify_va_arg): Likewise. * config/s390/s390.c (s390_gimplify_va_arg): Likewise. * config/sh/sh.c (sh_gimplify_va_arg_expr): Likewise. * config/sparc/sparc.c (sparc_gimplify_va_arg): Likewise. * config/spu/spu.c (spu_gimplify_va_arg_expr): Likewise. * config/stormy16/stormy16.c (xstormy16_gimplify_va_arg_expr): Likewise. * config/visium/visium.c (visium_gimplify_va_arg): Likewise. * config/xtensa/xtensa.c (xtensa_gimplify_va_arg_expr): Likewise. * config/alpha/alpha.c (alpha_setup_incoming_varargs): Replace targetm.calls.function_arg_advance with function_arg_advance. (alpha_gimplify_va_arg_1): Use 0 for empty record size. * config/microblaze/microblaze.c (microblaze_expand_prologue): Replace targetm.calls.function_arg with function_arg. Replace targetm.calls.function_arg_advance with function_arg_advance. * config/tilegx/tilegx.c (tilegx_setup_incoming_varargs): Replace targetm.calls.function_arg_advance with function_arg_advance. (tilegx_gimplify_va_arg_expr): Use 0 for empty record size. * config/tilepro/tilepro.c (tilepro_setup_incoming_varargs): Replace targetm.calls.function_arg_advance with function_arg_advance. (tilepro_gimplify_va_arg_expr): Use 0 for empty record size. --- gcc/config/aarch64/aarch64.c | 3 ++- gcc/config/alpha/alpha.c | 6 +++--- gcc/config/mep/mep.c | 3 ++- gcc/config/microblaze/microblaze.c | 11 +++++------ gcc/config/mips/mips.c | 6 ++++-- gcc/config/msp430/msp430.c | 3 ++- gcc/config/pa/pa.c | 3 ++- gcc/config/rs6000/rs6000.c | 3 ++- gcc/config/s390/s390.c | 3 ++- gcc/config/sh/sh.c | 3 ++- gcc/config/sparc/sparc.c | 3 ++- gcc/config/spu/spu.c | 3 ++- gcc/config/stormy16/stormy16.c | 6 ++++-- gcc/config/tilegx/tilegx.c | 7 ++++--- gcc/config/tilepro/tilepro.c | 7 ++++--- gcc/config/visium/visium.c | 3 ++- gcc/config/xtensa/xtensa.c | 3 ++- 17 files changed, 46 insertions(+), 30 deletions(-) diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 1e1b864..cfb9f66 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -9618,7 +9618,8 @@ aarch64_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p, stack = build3 (COMPONENT_REF, TREE_TYPE (f_stack), unshare_expr (valist), f_stack, NULL_TREE); - size = int_size_in_bytes (type); + bool empty_record = type && type_is_empty_record_p (type); + size = empty_record ? 0 : int_size_in_bytes (type); align = aarch64_function_arg_alignment (mode, type) / BITS_PER_UNIT; dw_align = false; diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index 4cfae82..d5d2f66 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -6117,8 +6117,7 @@ alpha_setup_incoming_varargs (cumulative_args_t pcum, machine_mode mode, CUMULATIVE_ARGS cum = *get_cumulative_args (pcum); /* Skip the current argument. */ - targetm.calls.function_arg_advance (pack_cumulative_args (&cum), mode, type, - true); + function_arg_advance (pack_cumulative_args (&cum), mode, type, true); #if TARGET_ABI_OPEN_VMS /* For VMS, we allocate space for all 6 arg registers plus a count. @@ -6304,7 +6303,8 @@ alpha_gimplify_va_arg_1 (tree type, tree base, tree offset, gimple_seq_add_seq (pre_p, internal_post); /* Update the offset field. */ - type_size = TYPE_SIZE_UNIT (TYPE_MAIN_VARIANT (type)); + bool empty_record = type && type_is_empty_record_p (type); + type_size = empty_record ? 0 : TYPE_SIZE_UNIT (TYPE_MAIN_VARIANT (type)); if (type_size == NULL || TREE_OVERFLOW (type_size)) t = size_zero_node; else diff --git a/gcc/config/mep/mep.c b/gcc/config/mep/mep.c index 5ab56bd..65aec24 100644 --- a/gcc/config/mep/mep.c +++ b/gcc/config/mep/mep.c @@ -3525,7 +3525,8 @@ mep_gimplify_va_arg_expr (tree valist, tree type, ivc2_vec = TARGET_IVC2 && VECTOR_TYPE_P (type); - size = int_size_in_bytes (type); + bool empty_record = type && type_is_empty_record_p (type); + size = empty_record ? 0 : int_size_in_bytes (type); by_reference = (size > (ivc2_vec ? 8 : 4)) || (size <= 0); if (by_reference) diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c index aebbc3b..7a7c397 100644 --- a/gcc/config/microblaze/microblaze.c +++ b/gcc/config/microblaze/microblaze.c @@ -2795,8 +2795,8 @@ microblaze_expand_prologue (void) passed_mode = Pmode; } - entry_parm = targetm.calls.function_arg (args_so_far, passed_mode, - passed_type, true); + entry_parm = function_arg (args_so_far, passed_mode, passed_type, + true); if (entry_parm) { @@ -2816,8 +2816,7 @@ microblaze_expand_prologue (void) break; } - targetm.calls.function_arg_advance (args_so_far, passed_mode, - passed_type, true); + function_arg_advance (args_so_far, passed_mode, passed_type, true); next_arg = TREE_CHAIN (cur_arg); if (next_arg == 0) @@ -2831,8 +2830,8 @@ microblaze_expand_prologue (void) /* Split parallel insn into a sequence of insns. */ - next_arg_reg = targetm.calls.function_arg (args_so_far, VOIDmode, - void_type_node, true); + next_arg_reg = function_arg (args_so_far, VOIDmode, void_type_node, + true); if (next_arg_reg != 0 && GET_CODE (next_arg_reg) == PARALLEL) { rtvec adjust = XVEC (next_arg_reg, 0); diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 6145944..61c6d0c 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -6308,7 +6308,8 @@ mips_std_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p, } /* Compute the rounded size of the type. */ - type_size = size_in_bytes (type); + bool empty_record = type && type_is_empty_record_p (type); + type_size = empty_record ? 0 : size_in_bytes (type); rounded_size = round_up (type_size, align); /* Reduce rounded_size so it's sharable with the postqueue. */ @@ -6397,7 +6398,8 @@ mips_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p, ovfl = build3 (COMPONENT_REF, TREE_TYPE (f_ovfl), valist, f_ovfl, NULL_TREE); - size = int_size_in_bytes (type); + bool empty_record = type && type_is_empty_record_p (type); + size = empty_record ? 0 : int_size_in_bytes (type); if (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT && GET_MODE_SIZE (TYPE_MODE (type)) <= UNITS_PER_FPVALUE) diff --git a/gcc/config/msp430/msp430.c b/gcc/config/msp430/msp430.c index 88301c8..1726f5b 100644 --- a/gcc/config/msp430/msp430.c +++ b/gcc/config/msp430/msp430.c @@ -1451,7 +1451,8 @@ msp430_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p, } /* Compute the rounded size of the type. */ - type_size = size_in_bytes (type); + bool empty_record = type && type_is_empty_record_p (type); + type_size = empty_record ? 0 : size_in_bytes (type); rounded_size = round_up (type_size, align); /* Reduce rounded_size so it's sharable with the postqueue. */ diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c index b8caab5..ef956cf 100644 --- a/gcc/config/pa/pa.c +++ b/gcc/config/pa/pa.c @@ -6305,7 +6305,8 @@ hppa_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p, type = ptr; ptr = build_pointer_type (type); } - size = int_size_in_bytes (type); + bool empty_record = type && type_is_empty_record_p (type); + size = empty_record ? 0 : int_size_in_bytes (type); valist_type = TREE_TYPE (valist); /* Args grow down. Not handled by generic routines. */ diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 6b22f93..ef829ed 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -11983,7 +11983,8 @@ rs6000_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p, sav = build3 (COMPONENT_REF, TREE_TYPE (f_sav), unshare_expr (valist), f_sav, NULL_TREE); - size = int_size_in_bytes (type); + bool empty_record = type && type_is_empty_record_p (type); + size = empty_record ? 0 : int_size_in_bytes (type); rsize = (size + 3) / 4; align = 1; diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index f8928b9..6f6639f 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -11569,7 +11569,8 @@ s390_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p, valist = unshare_expr (valist); ovf = build3 (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf, NULL_TREE); - size = int_size_in_bytes (type); + bool empty_record = type && type_is_empty_record_p (type); + size = empty_record ? 0 : int_size_in_bytes (type); s390_check_type_for_vector_abi (type, true, false); diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index 919ea1c..f1f66f9 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -8765,7 +8765,8 @@ sh_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p, if (pass_by_ref) type = build_pointer_type (type); - size = int_size_in_bytes (type); + bool empty_record = type && type_is_empty_record_p (type); + size = empty_record ? 0 : int_size_in_bytes (type); rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD; pptr_type_node = build_pointer_type (ptr_type_node); diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index 55ddacf..559bc69 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -7425,7 +7425,8 @@ sparc_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p, else { indirect = false; - size = int_size_in_bytes (type); + bool empty_record = type && type_is_empty_record_p (type); + size = empty_record ? 0 : int_size_in_bytes (type); rsize = ROUND_UP (size, UNITS_PER_WORD); align = 0; diff --git a/gcc/config/spu/spu.c b/gcc/config/spu/spu.c index 31502fb..1b24b12 100644 --- a/gcc/config/spu/spu.c +++ b/gcc/config/spu/spu.c @@ -4028,7 +4028,8 @@ spu_gimplify_va_arg_expr (tree valist, tree type, gimple_seq * pre_p, false); if (pass_by_reference_p) type = build_pointer_type (type); - size = int_size_in_bytes (type); + bool empty_record = type && type_is_empty_record_p (type); + size = empty_record ? 0 : int_size_in_bytes (type); rsize = ((size + UNITS_PER_WORD - 1) / UNITS_PER_WORD) * UNITS_PER_WORD; /* build conditional expression to calculate addr. The expression diff --git a/gcc/config/stormy16/stormy16.c b/gcc/config/stormy16/stormy16.c index f626853..bff3e27 100644 --- a/gcc/config/stormy16/stormy16.c +++ b/gcc/config/stormy16/stormy16.c @@ -1337,8 +1337,10 @@ xstormy16_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p, count = build3 (COMPONENT_REF, TREE_TYPE (f_count), valist, f_count, NULL_TREE); + bool empty_record = type && type_is_empty_record_p (type); must_stack = targetm.calls.must_pass_in_stack (TYPE_MODE (type), type); - size_tree = round_up (size_in_bytes (type), UNITS_PER_WORD); + size_tree = round_up (empty_record ? integer_zero_node : size_in_bytes (type), + UNITS_PER_WORD); gimplify_expr (&size_tree, pre_p, NULL, is_gimple_val, fb_rvalue); size_of_reg_args = NUM_ARGUMENT_REGISTERS * UNITS_PER_WORD; @@ -1374,7 +1376,7 @@ xstormy16_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p, /* Arguments larger than a word might need to skip over some registers, since arguments are either passed entirely in registers or entirely on the stack. */ - size = PUSH_ROUNDING (int_size_in_bytes (type)); + size = PUSH_ROUNDING (empty_record ? 0 : int_size_in_bytes (type)); if (size > 2 || size < 0 || must_stack) { tree r, u; diff --git a/gcc/config/tilegx/tilegx.c b/gcc/config/tilegx/tilegx.c index d221062..cdacd36 100644 --- a/gcc/config/tilegx/tilegx.c +++ b/gcc/config/tilegx/tilegx.c @@ -396,8 +396,8 @@ tilegx_setup_incoming_varargs (cumulative_args_t cum, /* The caller has advanced CUM up to, but not beyond, the last named argument. Advance a local copy of CUM past the last "real" named argument, to find out how many registers are left over. */ - targetm.calls.function_arg_advance (pack_cumulative_args (&local_cum), - mode, type, true); + function_arg_advance (pack_cumulative_args (&local_cum), mode, type, + true); first_reg = local_cum; if (local_cum < TILEGX_NUM_ARG_REGS) @@ -473,7 +473,8 @@ tilegx_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p, if (pass_by_reference_p) type = build_pointer_type (type); - size = int_size_in_bytes (type); + bool empty_record = type && type_is_empty_record_p (type); + size = empty_record ? 0 : int_size_in_bytes (type); rsize = ((size + UNITS_PER_WORD - 1) / UNITS_PER_WORD) * UNITS_PER_WORD; /* If the alignment of the type is greater than the default for a diff --git a/gcc/config/tilepro/tilepro.c b/gcc/config/tilepro/tilepro.c index 248b24e..1549c32 100644 --- a/gcc/config/tilepro/tilepro.c +++ b/gcc/config/tilepro/tilepro.c @@ -348,8 +348,8 @@ tilepro_setup_incoming_varargs (cumulative_args_t cum, /* The caller has advanced CUM up to, but not beyond, the last named argument. Advance a local copy of CUM past the last "real" named argument, to find out how many registers are left over. */ - targetm.calls.function_arg_advance (pack_cumulative_args (&local_cum), - mode, type, true); + function_arg_advance (pack_cumulative_args (&local_cum), mode, type, + true); first_reg = local_cum; if (local_cum < TILEPRO_NUM_ARG_REGS) @@ -421,7 +421,8 @@ tilepro_gimplify_va_arg_expr (tree valist, tree type, gimple_seq * pre_p, if (pass_by_reference_p) type = build_pointer_type (type); - size = int_size_in_bytes (type); + bool empty_record = type && type_is_empty_record_p (type); + size = empty_record ? 0 : int_size_in_bytes (type); rsize = ((size + UNITS_PER_WORD - 1) / UNITS_PER_WORD) * UNITS_PER_WORD; /* If the alignment of the type is greater than the default for a diff --git a/gcc/config/visium/visium.c b/gcc/config/visium/visium.c index 0bf275c..4f252d0 100644 --- a/gcc/config/visium/visium.c +++ b/gcc/config/visium/visium.c @@ -1529,7 +1529,8 @@ visium_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p, return build_va_arg_indirect_ref (t); } - size = int_size_in_bytes (type); + bool empty_record = type && type_is_empty_record_p (type); + size = empty_record ? 0 : int_size_in_bytes (type); rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD; f_ovfl = TYPE_FIELDS (va_list_type_node); f_gbase = TREE_CHAIN (f_ovfl); diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c index 0f58655..43911a1 100644 --- a/gcc/config/xtensa/xtensa.c +++ b/gcc/config/xtensa/xtensa.c @@ -3161,7 +3161,8 @@ xtensa_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p, ndx = build3 (COMPONENT_REF, TREE_TYPE (f_ndx), unshare_expr (valist), f_ndx, NULL_TREE); - type_size = size_in_bytes (type); + bool empty_record = type && type_is_empty_record_p (type); + type_size = empty_record ? 0 : size_in_bytes (type); va_size = round_up (type_size, UNITS_PER_WORD); gimplify_expr (&va_size, pre_p, NULL, is_gimple_val, fb_rvalue); -- 2.5.0