https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63495

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |NEW
   Last reconfirmed|                            |2014-10-09
                 CC|                            |jakub at gcc dot gnu.org,
                   |                            |jsm28 at gcc dot gnu.org
     Ever confirmed|0                           |1

--- Comment #1 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
This started with r205685.

The problem is in the x86 32-bit ABI, which decreases alignment of fields to 32
bits if the field has integral mode, or DFmode/DCmode or complex integral mode.

int
x86_field_alignment (tree field, int computed)
{
  enum machine_mode mode;
  tree type = TREE_TYPE (field);

  if (TARGET_64BIT || TARGET_ALIGN_DOUBLE)
    return computed;
  mode = TYPE_MODE (strip_array_types (type));
  if (mode == DFmode || mode == DCmode
      || GET_MODE_CLASS (mode) == MODE_INT
      || GET_MODE_CLASS (mode) == MODE_COMPLEX_INT)
    return MIN (32, computed);
  return computed;
}

When the struct has only a single field, it is QImode, therefore despite the
user forced alignment the alignment is lowered to 32 bits.

Now, when actually laying out struct s fields, such as:
struct T { char a; struct s s; } t = { 1, { 2 } };
it actually is given 64-bit alignment, because ADJUST_FIELD_ALIGN is not used
in that case:
      if (! packed_p && ! DECL_USER_ALIGN (decl))
        {
          /* Some targets (i.e. i386, VMS) limit struct field alignment
             to a lower boundary than alignment of variables unless
             it was overridden by attribute aligned.  */
#ifdef BIGGEST_FIELD_ALIGNMENT
          DECL_ALIGN (decl)
            = MIN (DECL_ALIGN (decl), (unsigned) BIGGEST_FIELD_ALIGNMENT);
#endif
#ifdef ADJUST_FIELD_ALIGN
          DECL_ALIGN (decl) = ADJUST_FIELD_ALIGN (decl, DECL_ALIGN (decl));
#endif
        }

As do_type_align for FIELD_DECLs sets DECL_USER_ALIGN:
static inline void
do_type_align (tree type, tree decl)
{
  if (TYPE_ALIGN (type) > DECL_ALIGN (decl))
    {
      DECL_ALIGN (decl) = TYPE_ALIGN (type);
      if (TREE_CODE (decl) == FIELD_DECL)
        DECL_USER_ALIGN (decl) = TYPE_USER_ALIGN (type);
    }
}

if TYPE_USER_ALIGN is set, IMHO ADJUST_FIELD_ALIGN and corresponding 
BIGGEST_FIELD_ALIGNMENT will never be used.

Reply via email to