From: Joern Rennecke Date: Fri, 19 Aug 2005 12:25:58 +0000 (+0100) Subject: sh.c (find_sole_member): New function. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=21bdb106e797193b1d02abcacd6f27bb61bb12ec;p=gcc.git sh.c (find_sole_member): New function. * sh.c (find_sole_member): New function. (sh_gimplify_va_arg_expr): Use it. Allow RECORD_TYPE mode mismatch if the record's alignment is larger than the size of its only member. From-SVN: r103275 --- diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index ed132f6c82d..9d39ac6a373 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -6632,6 +6632,27 @@ sh_va_start (tree valist, rtx nextarg) expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); } +/* TYPE is a RECORD_TYPE. If there is only a single non-zero-sized + member, return it. */ +static tree +find_sole_member (tree type) +{ + tree field, member = NULL_TREE; + + for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) + { + if (TREE_CODE (field) != FIELD_DECL) + continue; + if (!DECL_SIZE (field)) + return NULL_TREE; + if (integer_zerop (DECL_SIZE (field))) + continue; + if (member) + return NULL_TREE; + member = field; + } + return member; +} /* Implement `va_arg'. */ static tree @@ -6657,6 +6678,7 @@ sh_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p, tree next_o, next_o_limit, next_fp, next_fp_limit, next_stack; int pass_as_float; tree lab_false; + tree member; f_next_o = TYPE_FIELDS (va_list_type_node); f_next_o_limit = TREE_CHAIN (f_next_o); @@ -6679,22 +6701,22 @@ sh_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p, like their member. This is relevant if the latter has a REAL_TYPE or COMPLEX_TYPE type. */ while (TREE_CODE (type) == RECORD_TYPE - && TYPE_FIELDS (type) - && TREE_CODE (TYPE_FIELDS (type)) == FIELD_DECL - && (TREE_CODE (TREE_TYPE (TYPE_FIELDS (type))) == REAL_TYPE - || TREE_CODE (TREE_TYPE (TYPE_FIELDS (type))) == COMPLEX_TYPE - || TREE_CODE (TREE_TYPE (TYPE_FIELDS (type))) == RECORD_TYPE) - && TREE_CHAIN (TYPE_FIELDS (type)) == NULL_TREE) + && (member = find_sole_member (type)) + && (TREE_CODE (TREE_TYPE (member)) == REAL_TYPE + || TREE_CODE (TREE_TYPE (member)) == COMPLEX_TYPE + || TREE_CODE (TREE_TYPE (member)) == RECORD_TYPE)) { - tree field_type = TREE_TYPE (TYPE_FIELDS (type)); + tree field_type = TREE_TYPE (member); if (TYPE_MODE (type) == TYPE_MODE (field_type)) type = field_type; else { - gcc_assert (TYPE_ALIGN (type) - < GET_MODE_ALIGNMENT (TYPE_MODE (field_type))); - break; + gcc_assert ((TYPE_ALIGN (type) + < GET_MODE_ALIGNMENT (TYPE_MODE (field_type))) + || (TYPE_ALIGN (type) + > GET_MODE_BITSIZE (TYPE_MODE (field_type)))); + break; } }