[Bug middle-end/83487] [8 Regression] ICE in expand_call, at calls.c:4098
jakub at gcc dot gnu.org
gcc-bugzilla@gcc.gnu.org
Thu Dec 21 13:21:00 GMT 2017
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83487
Jakub Jelinek <jakub at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |hjl.tools at gmail dot com,
| |hubicka at gcc dot gnu.org,
| |jason at gcc dot gnu.org,
| |matz at gcc dot gnu.org
--- Comment #14 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Anyway, have the TYPE_EMPTY_P changes been cross-checked with the x86-64 psABI
and other compilers? The psABI is at least vague in this regard.
One thing is that we consider TYPE_EMPTY_P even aggregates larger than 16
bytes, like C++
struct B {};
struct C { struct B c[128]; };
where the psABI says it is passed in MEMORY.
I presume it has been intentional change, but will the psABI be updated here so
that other compilers know that they need to change too?
Another thing is for aggregates <= 16 bytes, the psABI algorithm is that it is
NO_CLASS for both 8byte halves if it is TYPE_EMPTY_P aggregate, and doesn't say
where it is passed.
Testcase for compiler compatibility:
pr83487.h:
#ifdef ALIGNED
struct __attribute__ ((aligned (ALIGNED))) A {};
#else
struct A {};
#endif
struct B {};
#ifdef LARGE
struct C { struct B c[128]; };
#else
struct C {};
#endif
pr83487-1.C:
#include "pr83487.h"
extern
#ifdef __cplusplus
"C"
#endif
void abort ();
void
f1 (int i, int j, int k, int l, int m, int n, int o, struct A)
{
if (i != 6 || j != 0 || k != 1 || l != 2 || m != 3 || n != 4 || o != 5)
abort ();
}
void
f3 (int i, int j, int k, int l, int m, int n, int o, struct A, int p, int q)
{
if (i != 6 || j != 0 || k != 1 || l != 2 || m != 3 || n != 4 || o != 5 || p
!= 7 || q != 8)
abort ();
}
void
f5 (int i, int j, int k, int l, int m, int n, int o, struct B, int p, int q)
{
if (i != 6 || j != 0 || k != 1 || l != 2 || m != 3 || n != 4 || o != 5 || p
!= 7 || q != 8)
abort ();
}
void
f7 (int i, int j, int k, int l, int m, int n, int o, struct C, int p, int q)
{
if (i != 6 || j != 0 || k != 1 || l != 2 || m != 3 || n != 4 || o != 5 || p
!= 7 || q != 8)
abort ();
}
void
f9 (int o, struct A)
{
if (o != 5)
abort ();
}
void
f11 (int o, struct A, int p, int q)
{
if (o != 5 || p != 7 || q != 8)
abort ();
}
void
f13 (int o, struct B, int p, int q)
{
if (o != 5 || p != 7 || q != 8)
abort ();
}
void
f15 (int o, struct C, int p, int q)
{
if (o != 5 || p != 7 || q != 8)
abort ();
}
pr83487-2.C:
#include "pr83487.h"
struct A a;
struct B b;
struct C c;
extern void f1 (int i, int j, int k, int l, int m, int n, int o, struct A);
extern void f3 (int i, int j, int k, int l, int m, int n, int o, struct A, int
p, int q);
extern void f5 (int i, int j, int k, int l, int m, int n, int o, struct B, int
p, int q);
extern void f7 (int i, int j, int k, int l, int m, int n, int o, struct C, int
p, int q);
extern void f9 (int o, struct A);
extern void f11 (int o, struct A, int p, int q);
extern void f13 (int o, struct B, int p, int q);
extern void f15 (int o, struct C, int p, int q);
int
main ()
{
f1 (6, 0, 1, 2, 3, 4, 5, a);
f3 (6, 0, 1, 2, 3, 4, 5, a, 7, 8);
f5 (6, 0, 1, 2, 3, 4, 5, b, 7, 8);
f7 (6, 0, 1, 2, 3, 4, 5, c, 7, 8);
f9 (5, a);
f11 (5, a, 7, 8);
f13 (5, b, 7, 8);
f15 (5, c, 7, 8);
return 0;
}
Now, comparing clang r319307 with g++ with the above patch, without any
#defines it seems the two compilers are compatible, ditto with -DALIGNED=16,
with -DALIGNED=128 or -DLARGE they are not, because the aggregates then are >
16 bytes long and are passed in MEMORY by clang++ and in NO_CLASS by g++ (and
it honors alignment).
So, I think the #c13 change is correct, but we need to decide if TYPE_EMPTY_P
should be set on > 16 byte types or not and if it should be, adjust the psABI
to say so.
More information about the Gcc-bugs
mailing list