Re: [PATCH] Classify non-POD struct types more or less correctly on AMD64

Mark Kettenis
2004-01-11T12:38:18Z

[ This might interest GCC folks. The problem we're facing here is
that on AMD64, and other targets that return small structures in
registers, it isn't clear how small C++ classes are returned. Some
are returned in registers and some are returned in memory. The
AMD64 ABI explicitly says that non-POD structures and unions are
returned in memory, but GCC doesn't seem to be ABI-compliant here.
Is this considered to be a bug? ]

Date: Sat, 10 Jan 2004 23:10:09 -0500
From: Daniel Jacobowitz <drow@mvista.com>

Looking at that function it looks like it will even return some classes
with baseclasses in registers. I won't excerpt it here, as it's quite
large. But it iterates over the baseclasses. If none of them are
larger than 16 bytes (a given, if the derived class isn't larger than
16 bytes) or of a variable size (C++ classes are never variably sized I
don't think) or of TFmode/TCmode (128-bit long doubles), I believe that
the aggregate will be returned in registers.

That function just implements the rules for normal C structures. Th
rules are a bit more complex than you say above, but that bit is
implemented correctly in GDB. At least that's the intention. The
decision to not pass certain C++ classes in registers is made
somewhere else, most notably in cp/class.c:finish_struct_bits(), where
TYPE_MODE is set to BLKmode, and TREE_ADDRESSABLE is set. Both
conditions are enough to get the type returned in memory instead of
registers. However, there are more places where TREE_ADDRESSABLE is
tweaked.

The 1996 ANSI C++ draft has the following statement about non-POD-ness:

"A POD-struct is an aggregate class that has no non-static data members
of type pointer to member, non-POD-struct, non-POD- union (or array of
such types) or reference, and has no user-defined copy assignment
operator and no user-defined destructor. Similarly, a POD-union is an
aggregate union that has no non-static data members of type pointer to
member, non-POD-struct, non-POD-union (or array of such types) or
reference, and has no user-defined copy assignment operator and no
user-defined destructor. A POD class is a class that is either a
POD-struct or a POD-union."

So it doesn't say anything about baseclasses. So the code I checked
in is defenitely wrong :-(.

IOW it doesn't look to me as if GCC implements the non-POD rule. You
might wish to try returning a simple non-POD derived class and see what
GCC generates.

Looks very much like it. I can make a class with a user-defined copy
assignment operator that gets returned in registers by GCC. So GCC
doesn't correctly implement the ABI :-(.

The same problem exist on other targets though. I've seen problems on
64-bit SPARC and FreeBSD/i386 too. The FreeBSD/i386 case is
interesting since the other i386 platforms are OK. This is because
FreeBSD uses a different ABI, where -freg-struct-return is the
default. The System V psABI says that all aggregate types are
returned in memory (-fpcc-struct-return). This is probably the reason
why GCC has so many bugs related to returning small structs; the
majority of people hacking on GNU/Linux IA-32 boxen doesn't see the
problems.

Mark