aix: ABI struct alignment (PR99557)
authorDavid Edelsohn <dje.gcc@gmail.com>
Sun, 14 Mar 2021 19:09:21 +0000 (15:09 -0400)
committerDavid Edelsohn <dje.gcc@gmail.com>
Fri, 26 Mar 2021 23:56:12 +0000 (19:56 -0400)
commit42a21b4cb540be93548a6ff6d4cb4a73ab1665be
treec2bc50b613ad33db76a0db5a0dd76f4897212640
parent1cdfc98a9981768c475fabf069ba4d3e460deb2a
aix: ABI struct alignment (PR99557)

The AIX power alignment rules apply the natural alignment of the
"first member" if it is of a floating-point data type (or is an aggregate
whose recursively "first" member or element is such a type). The alignment
associated with these types for subsequent members use an alignment value
where the floating-point data type is considered to have 4-byte alignment.

GCC had been stripping array type but had not recursively looked
within structs and unions.  This also applies to classes and
subclasses and, therefore, becomes more prominent with C++.

For example,

struct A {
  double x[2];
  int y;
};
struct B {
  int i;
  struct A a;
};

struct A has double-word alignment for the bare type, but
word alignment and offset within struct B despite the alignment of
struct A.  If struct A were the first member of struct B, struct B
would have double-word alignment.  One must search for the innermost
first member to increase the alignment if double and then search for
the innermost first member to reduce the alignment if the TYPE had
double-word alignment solely because the innermost first member was
double.

This patch recursively looks through the first member to apply the
double-word alignment to the struct / union as a whole and to apply
the word alignment to the struct or union as a member within a struct
or union.

This is an ABI change for GCC on AIX, but GCC on AIX had not correctly
implemented the AIX ABI and had not been compatible with the IBM XL
compiler.

Bootstrapped on powerpc-ibm-aix7.2.3.0.

gcc/ChangeLog:

* config/rs6000/aix.h (ADJUST_FIELD_ALIGN): Call function.
* config/rs6000/rs6000-protos.h (rs6000_special_adjust_field_align):
Declare.
* config/rs6000/rs6000.c (rs6000_special_adjust_field_align): New.
(rs6000_special_round_type_align): Recursively check innermost first
field.

gcc/testsuite/ChangeLog:

* gcc.target/powerpc/pr99557.c: New.
gcc/config/rs6000/aix.h
gcc/config/rs6000/rs6000-protos.h
gcc/config/rs6000/rs6000.c
gcc/testsuite/gcc.target/powerpc/pr99557.c [new file with mode: 0644]