public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* Darwin gcc 3.3 sizeof of C++ structures with long long ints is strange
@ 2003-02-07 16:18 Kevin B. Hendricks
  2003-03-19 12:30 ` Andrew Haley
  0 siblings, 1 reply; 7+ messages in thread
From: Kevin B. Hendricks @ 2003-02-07 16:18 UTC (permalink / raw)
  To: gcc

Hi,

I am exploring the use of gcc 3.3 (based on CVS from yesterday) to build 
OpenOffice.org under MacOSX/Darwin (we have had troubles with Apple's gcc 
3.1 that don't seem to happen under gcc 3.3)?

Unfortunately, the following structure alignment program shows the size of 
structure C5 is 4 bytes larger than expected. 

If you look at the code the key issue is that C5 uses a long long int type.  
If I replace the long long int with a double (both are 8 bytes in size) 
the expected size is achieved.

Will someone familar with C++ structure alignment and Darwin please take a 
look at this testcase for me?

Is there something funny happening with long long ints here?

Thanks,

Kevin

My gcc 3.3 build is installed in /usr/local/
This is on MacOSX 10.2.3

 setenv PATH /usr/local/bin:${PATH}
 setenv DYLD_LIBRARY_PATH /usr/local/lib

[khendricksmac:~] kbhend% /usr/local/bin/g++ -DMAX4 -DADJUST_ALIGN -O2 -o 
datatest datatest.cxx

[khendricksmac:~] kbhend% ./datatest
> sizeof(AlignSize_Impl) = 12; __alignof__ (AlignSize_Impl) = 4
> sizeof(M) = 8; __alignof__ (M) = 4
> sizeof(N) = 12; __alignof__ (N) = 4
> sizeof(N2) = 12; __alignof__ (N2) = 4
> sizeof(O) = 16; __alignof__ (O) = 4
> sizeof(D) = 8; __alignof__ (D) = 4
> sizeof(C1) = 2; __alignof__ (C1) = 2
> sizeof(C2) = 8; __alignof__ (C2) = 4
> sizeof(C3) = 20; __alignof__ (C3) = 4
> sizeof(C4) = 32; __alignof__ (C4) = 4
> sizeof(C5) = 48; __alignof__ (C5) = 8
### sizeof(C5) = 48 instead of expected 44!!!
> sizeof(C6) = 64; __alignof__ (C6) = 8
### sizeof(C6) = 64 instead of expected 52!!!
### OFFSET_OF(C6, c6) = 8 instead of expected 4!!!
### OFFSET_OF(C6, b6) = 56 instead of expected 48!!!
> sizeof(O2) = 24; __alignof__ (O2) = 4
> sizeof(Char3) = 3; __alignof__ (Char3) = 1
> sizeof(P) = 20; __alignof__ (P) = 4


Here is the testcase the issue seems to happen with long long types only
(see the C5 structure defintion)

cat datatest.cxx

#include <stdlib.h>
#include <stdio.h>


typedef struct _Any
{
        void * pType;
        void * pData;
        void * pReserved;
} uno_Any;

typedef _Any Any;


// Patching the gcc 3 incompatible alignment change for linux
// This pragma macro is appended to every first member of a struct,
// iff the struct inherits from a base struct and the first member
// of this structure  is not a double or [unsigned] long long.

#ifdef ADJUST_ALIGN

#define CPPU_GCC3_ALIGN( base_struct ) __attribute__ ((aligned (__alignof__ 
(base_struct))))

#else

#define CPPU_GCC3_ALIGN( base_struct )

#endif


typedef enum {
        My_BYTE,
        MY_CHAR,
        MY_INT,
        MY_LONG,
        MY_LONGLONG,
        MY_FLOAT,
        MY_DOUBLE
} TypeClass;



#ifdef MAX4
#define MAX_ALIGNMENT_4
#endif

#define OFFSET_OF( s, m ) ((size_t)((char *)&((s *)16)->m -16))

#define BINTEST_VERIFY( c ) \
    if (! (c)) { fprintf( stderr, "### binary compatibility test failed: " 
#c " [line %d]!!!\n", __LINE__ ); /* abort();*/ }

#define BINTEST_VERIFYOFFSET( s, m, n ) \
    if (OFFSET_OF(s, m) != n) { fprintf( stderr, "### OFFSET_OF(" #s ", "  
#m ") = %d instead of expected %d!!!\n", OFFSET_OF(s, m), n ); /* 
abort();*/ }

#define BINTEST_VERIFYSIZE( s, n ) \
    fprintf( stderr, "> sizeof(" #s ") = %d; __alignof__ (" #s ") = %d\n", 
sizeof(s), __alignof__ (s) ); \
    if (sizeof(s) != n) { fprintf( stderr, "### sizeof(" #s ") = %d instead 
of expected %d!!!\n", sizeof(s), n ); /* abort();*/ }


struct C1
{
    signed short n1;
};
struct C2 : public C1
{
    signed long n2 CPPU_GCC3_ALIGN( C1 );
};
struct C3 : public C2
{
    double d3;
    signed long n3;
};
struct C4 : public C3
{
    signed long n4 CPPU_GCC3_ALIGN( C3 );
    double d4;
};

struct C5 : public C4
{
    signed long long n5;
    unsigned char b5;
};


struct C6 : public C1
{
    C5 c6 CPPU_GCC3_ALIGN( C1 );
    unsigned char b6;
};

struct D
{
    signed short d;
    signed long e;
};
struct E
{
    unsigned char a;
    unsigned char b;
    unsigned char c;
    signed short d;
    signed long e;
};

struct M
{
        signed long     n;
        signed short    o;
};

struct N : public M
{
        signed short    p CPPU_GCC3_ALIGN( M );
};
struct N2
{
    M m;
        signed short    p;
};

struct O : public M
{
        double  p;
};
struct O2 : public O
{
        double  p2;
};

struct P : public N
{
        double  p2;
};

struct empty
{
};

struct second : public empty
{
        int a;
};

struct AlignSize_Impl
{
        signed short    nInt16;
        double          dDouble;
};

struct Char1
{
    char c1;
};
struct Char2 : public Char1
{
    char c2 CPPU_GCC3_ALIGN( Char1 );
};
struct Char3 : public Char2
{
    char c3 CPPU_GCC3_ALIGN( Char2 );
};
struct Char4
{
    Char3 chars;
    char c;
};

class BinaryCompatible_Impl
{
public:
        BinaryCompatible_Impl();
};

BinaryCompatible_Impl::BinaryCompatible_Impl()
{
#ifdef MAX_ALIGNMENT_4
    // max alignment is 4
    BINTEST_VERIFYOFFSET( AlignSize_Impl, dDouble, 4 );
    BINTEST_VERIFYSIZE( AlignSize_Impl, 12 );
#else
    // max alignment is 8
    BINTEST_VERIFYOFFSET( AlignSize_Impl, dDouble, 8 );
    BINTEST_VERIFYSIZE( AlignSize_Impl, 16 );
#endif

    // enum
    BINTEST_VERIFY( sizeof( TypeClass ) == sizeof( signed long ) );

    // any
    BINTEST_VERIFY( sizeof(void *) >= sizeof(signed long) );
    BINTEST_VERIFY( sizeof( Any ) == sizeof( _Any ) );
    BINTEST_VERIFY( sizeof( Any ) == sizeof( void * ) * 3 );
    BINTEST_VERIFYOFFSET( Any, pType, 0 );
    BINTEST_VERIFYOFFSET( Any, pData, 4 );
    BINTEST_VERIFYOFFSET( Any, pReserved, 8 );

    // struct
    BINTEST_VERIFYSIZE( M, 8 );
    BINTEST_VERIFYOFFSET( M, o, 4 );
    BINTEST_VERIFYSIZE( N, 12 );
    BINTEST_VERIFYOFFSET( N, p, 8 );
    BINTEST_VERIFYSIZE( N2, 12 );
    BINTEST_VERIFYOFFSET( N2, p, 8 );
    BINTEST_VERIFYSIZE( O, 16 );
    BINTEST_VERIFYSIZE( D, 8 );
    BINTEST_VERIFYOFFSET( D, e, 4 );
    BINTEST_VERIFYOFFSET( E, d, 4 );
    BINTEST_VERIFYOFFSET( E, e, 8 );

    BINTEST_VERIFYSIZE( C1, 2 );
    BINTEST_VERIFYSIZE( C2, 8 );
    BINTEST_VERIFYOFFSET( C2, n2, 4 );

#ifdef MAX_ALIGNMENT_4
    BINTEST_VERIFYSIZE( C3, 20 );
    BINTEST_VERIFYOFFSET( C3, d3, 8 );
    BINTEST_VERIFYOFFSET( C3, n3, 16 );
    BINTEST_VERIFYSIZE( C4, 32 );
    BINTEST_VERIFYOFFSET( C4, n4, 20 );
    BINTEST_VERIFYOFFSET( C4, d4, 24 );
    BINTEST_VERIFYSIZE( C5, 44 );
    BINTEST_VERIFYOFFSET( C5, n5, 32 );
    BINTEST_VERIFYOFFSET( C5, b5, 40 );
    BINTEST_VERIFYSIZE( C6, 52 );
    BINTEST_VERIFYOFFSET( C6, c6, 4 );
    BINTEST_VERIFYOFFSET( C6, b6, 48 );
#else
    BINTEST_VERIFYSIZE( C3, 24 );
    BINTEST_VERIFYOFFSET( C3, d3, 8 );
    BINTEST_VERIFYOFFSET( C3, n3, 16 );
    BINTEST_VERIFYSIZE( C4, 40 );
    BINTEST_VERIFYOFFSET( C4, n4, 24 );
    BINTEST_VERIFYOFFSET( C4, d4, 32 );
    BINTEST_VERIFYSIZE( C5, 56 );
    BINTEST_VERIFYOFFSET( C5, n5, 40 );
    BINTEST_VERIFYOFFSET( C5, b5, 48 );
    BINTEST_VERIFYSIZE( C6, 72 );
    BINTEST_VERIFYOFFSET( C6, c6, 8 );
    BINTEST_VERIFYOFFSET( C6, b6, 64 );
#endif

    BINTEST_VERIFYSIZE( O2, 24 );
    BINTEST_VERIFYOFFSET( O2, p2, 16 );

    BINTEST_VERIFYSIZE( Char3, 3 );
    BINTEST_VERIFYOFFSET( Char4, c, 3 );

#ifdef MAX_ALIGNMENT_4
    // max alignment is 4
    BINTEST_VERIFYSIZE( P, 20 );
#else
    // alignment of P is 8, because of P[] ...
    BINTEST_VERIFYSIZE( P, 24 );
    BINTEST_VERIFYSIZE( second, sizeof( int ) );
#endif
}

static BinaryCompatible_Impl aTest;

int main ()
{
  exit(0);
}

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Darwin gcc 3.3 sizeof of C++ structures with long long ints is strange
  2003-02-07 16:18 Darwin gcc 3.3 sizeof of C++ structures with long long ints is strange Kevin B. Hendricks
@ 2003-03-19 12:30 ` Andrew Haley
  2003-03-19 14:22   ` Kevin B. Hendricks
  2003-03-19 19:21   ` Kevin B. Hendricks
  0 siblings, 2 replies; 7+ messages in thread
From: Andrew Haley @ 2003-03-19 12:30 UTC (permalink / raw)
  To: Kevin B. Hendricks; +Cc: gcc

Kevin B. Hendricks writes:
 > 
 > I am exploring the use of gcc 3.3 (based on CVS from yesterday) to build 
 > OpenOffice.org under MacOSX/Darwin (we have had troubles with Apple's gcc 
 > 3.1 that don't seem to happen under gcc 3.3)?
 > 
 > Unfortunately, the following structure alignment program shows the size of 
 > structure C5 is 4 bytes larger than expected. 
 > 
 > If you look at the code the key issue is that C5 uses a long long int type.  
 > If I replace the long long int with a double (both are 8 bytes in size) 
 > the expected size is achieved.
 > 
 > Will someone familar with C++ structure alignment and Darwin please take a 
 > look at this testcase for me?
 > 
 > Is there something funny happening with long long ints here?

You may be aware that the way C++ structs are laid out in memory has
changed as a result of the multivendor C++ ABI.

It looks to me like sizeof(C5) is rounded up to a multiple of C5's
alignment.  This is not very strange.  If you don't want this to
happen, you can use __attribute__ ((packed)).

Andrew.


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Darwin gcc 3.3 sizeof of C++ structures with long long ints is strange
  2003-03-19 12:30 ` Andrew Haley
@ 2003-03-19 14:22   ` Kevin B. Hendricks
  2003-03-20  0:14     ` David Edelsohn
  2003-03-19 19:21   ` Kevin B. Hendricks
  1 sibling, 1 reply; 7+ messages in thread
From: Kevin B. Hendricks @ 2003-03-19 14:22 UTC (permalink / raw)
  To: Andrew Haley; +Cc: gcc

Hi,

This alignment issue does not exist in Apple's gcc 3.1 using 
-malign-natural  and does not exist in Apple's gcc 2.95 version either.

I talked to Geoff Keating about ti and he felt that the alignment 
constraint of long long ints and the comment found in the gnu gcc 3.3 code 
was wrong ands that long long ints should NOT have higher alignment 
constraints than doubles.

So the problem is you are not aligning it to max 4 purely (long long ints 
are the exception) nor are you using natural alignment (8 for double and 
long long int).

So you ar enot abi compatible with anyone (apple's gcc versions included).

I have simply changed this in my own gcc 3.3 builds for Apple. Geoff was 
actually looking for a volunteer to somehow rationalize the gnu gcc long 
long int alignment for darwin with Apple's alignments.

Kevin


On March 19, 2003 05:20 am, Andrew Haley wrote:
> Kevin B. Hendricks writes:
>  > 
>  > I am exploring the use of gcc 3.3 (based on CVS from yesterday) to 
build 
>  > OpenOffice.org under MacOSX/Darwin (we have had troubles with Apple's 
gcc 
>  > 3.1 that don't seem to happen under gcc 3.3)?
>  > 
>  > Unfortunately, the following structure alignment program shows the 
size of 
>  > structure C5 is 4 bytes larger than expected. 
>  > 
>  > If you look at the code the key issue is that C5 uses a long long int 
type.  
>  > If I replace the long long int with a double (both are 8 bytes in 
size) 
>  > the expected size is achieved.
>  > 
>  > Will someone familar with C++ structure alignment and Darwin please 
take a 
>  > look at this testcase for me?
>  > 
>  > Is there something funny happening with long long ints here?
> 
> You may be aware that the way C++ structs are laid out in memory has
> changed as a result of the multivendor C++ ABI.
> 
> It looks to me like sizeof(C5) is rounded up to a multiple of C5's
> alignment.  This is not very strange.  If you don't want this to
> happen, you can use __attribute__ ((packed)).
> 
> Andrew.
> 
> 
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Darwin gcc 3.3 sizeof of C++ structures with long long ints is strange
  2003-03-19 12:30 ` Andrew Haley
  2003-03-19 14:22   ` Kevin B. Hendricks
@ 2003-03-19 19:21   ` Kevin B. Hendricks
  1 sibling, 0 replies; 7+ messages in thread
From: Kevin B. Hendricks @ 2003-03-19 19:21 UTC (permalink / raw)
  To: Andrew Haley; +Cc: gcc

Hi Andrew,

This is what Geoff sent to me originally and what I modified to get back to 
a layout more consistent with everyone else's.  The ZI sent test code has 
to pass for any platform porting OOo and does so for PPC Linux, S390 
Linux, x86 Linux, Irix, NetBSD, FreeBSD, Apple gcc 2.95, Apple gcc 3.1 
with -malign-natural, WIN, Solaris, etc.

Since gnu gcc 3.3 does not support -malign-natural, and does not follow the 
max4 convention that Apple's gcc 2.95 did, the only solution was to fix 
the "strange" (but as you point out technically correct) alignment just 
used for long long ints to be more consistent with max 4.  All of the 
other platforms do not treat alignment of doubles and long long ints 
differently in C++ structures.

The other solution would be to add -malign-natural support to gnu gcc 3.3. 
for Darwin.

I hope this explains things a bit better.

Kevin


---snip---
Re: some Darwin C++ stucture size issues
Date: 15/02/03 08:29 pm
From: Geoff Keating <geoffk@geoffk.org>
To: kevin.hendricks@sympatico.ca

The problem you're seeing is most likely due to something in the
ADJUST_FIELD_ALIGN or maybe ROUND_TYPE_ALIGN macro in
config/rs6000/darwin.h in GCC.  To save you a checkout, the Apple
compiler has:

/* APPLE LOCAL begin Macintosh alignment 2002-2-26 ff */
/* This now supports the Macintosh power, mac68k, and natural
   alignment modes.  It now has one more parameter than the standard
   version of the ADJUST_FIELD_ALIGN macro.

   The macro works as follows: We use the computed alignment of the
   field if we are in the natural alignment mode or if the field is
   a vector.  Otherwise, if we are in the mac68k alignment mode, we
   use the minimum of the computed alignment and 16 (pegging at
   2-byte alignment).  If we are in the power mode, we peg at 32
   (word alignment) unless it is the first field of the struct, in
   which case we use the computed alignment.  */
#undef ADJUST_FIELD_ALIGN
#define ADJUST_FIELD_ALIGN(FIELD, COMPUTED, FIRST_FIELD_P)      \
  (TARGET_ALIGN_NATURAL ? (COMPUTED) :                          \
   (((COMPUTED) == RS6000_VECTOR_ALIGNMENT)                     \
    ? RS6000_VECTOR_ALIGNMENT                                   \
    : (MIN ((COMPUTED),                                         \
            (TARGET_ALIGN_MAC68K ? 16                           \
                                 : ((FIRST_FIELD_P) ? (COMPUTED) \
                                                    : 32))))))

I'm pretty sure that's not the same as FSF GCC, which has:

/* Darwin word-aligns FP doubles but doubleword-aligns 64-bit ints.  */
#define ADJUST_FIELD_ALIGN(FIELD, COMPUTED) \
  (TYPE_MODE (TREE_CODE (TREE_TYPE (FIELD)) == ARRAY_TYPE \
              ? get_inner_array_type (FIELD) \
              : TREE_TYPE (FIELD)) == DFmode \
   ? MIN ((COMPUTED), 32) : (COMPUTED))

In particular, I think the comment is wrong.

-- 
- Geoffrey Keating <geoffk@geoffk.org>

On March 19, 2003 05:20 am, Andrew Haley wrote:
> Kevin B. Hendricks writes:
>  > 
>  > I am exploring the use of gcc 3.3 (based on CVS from yesterday) to 
build 
>  > OpenOffice.org under MacOSX/Darwin (we have had troubles with Apple's 
gcc 
>  > 3.1 that don't seem to happen under gcc 3.3)?
>  > 
>  > Unfortunately, the following structure alignment program shows the 
size of 
>  > structure C5 is 4 bytes larger than expected. 
>  > 
>  > If you look at the code the key issue is that C5 uses a long long int 
type.  
>  > If I replace the long long int with a double (both are 8 bytes in 
size) 
>  > the expected size is achieved.
>  > 
>  > Will someone familar with C++ structure alignment and Darwin please 
take a 
>  > look at this testcase for me?
>  > 
>  > Is there something funny happening with long long ints here?
> 
> You may be aware that the way C++ structs are laid out in memory has
> changed as a result of the multivendor C++ ABI.
> 
> It looks to me like sizeof(C5) is rounded up to a multiple of C5's
> alignment.  This is not very strange.  If you don't want this to
> happen, you can use __attribute__ ((packed)).
> 
> Andrew.
> 
> 
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Darwin gcc 3.3 sizeof of C++ structures with long long ints is strange
  2003-03-19 14:22   ` Kevin B. Hendricks
@ 2003-03-20  0:14     ` David Edelsohn
  2003-03-20  5:28       ` Kevin B. Hendricks
  0 siblings, 1 reply; 7+ messages in thread
From: David Edelsohn @ 2003-03-20  0:14 UTC (permalink / raw)
  To: Kevin B. Hendricks; +Cc: Andrew Haley, gcc

	The Apple PowerMac alignment was the same as AIX.  Unless Apple
has changed their ABI, doubles are not naturally aligned, but long long
ints are.

David

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Darwin gcc 3.3 sizeof of C++ structures with long long ints is strange
  2003-03-20  0:14     ` David Edelsohn
@ 2003-03-20  5:28       ` Kevin B. Hendricks
  2003-03-20  8:04         ` David Edelsohn
  0 siblings, 1 reply; 7+ messages in thread
From: Kevin B. Hendricks @ 2003-03-20  5:28 UTC (permalink / raw)
  To: David Edelsohn; +Cc: Andrew Haley, gcc

Hi,

That's interesting to know.  That means any AIX port of OOo would run into 
the same difficulties.  Does the AIX gcc version support anything like 
-malign-natural does for Apple's gcc 3.1 (byte aligned to 1, short aligned 
to 2, int aligned to 4, double and long long int aligned to 8)?

Any particular reason for treating long long ints differently from doubles?

Thanks,

Kevin

On March 19, 2003 06:52 pm, David Edelsohn wrote:
> The Apple PowerMac alignment was the same as AIX.  Unless Apple
> has changed their ABI, doubles are not naturally aligned, but long long
> ints are.
> 
> David
> 
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Darwin gcc 3.3 sizeof of C++ structures with long long ints is strange
  2003-03-20  5:28       ` Kevin B. Hendricks
@ 2003-03-20  8:04         ` David Edelsohn
  0 siblings, 0 replies; 7+ messages in thread
From: David Edelsohn @ 2003-03-20  8:04 UTC (permalink / raw)
  To: Kevin B. Hendricks; +Cc: Andrew Haley, gcc

>>>>> Kevin B Hendricks writes:

Kevin> That's interesting to know.  That means any AIX port of OOo would run into 
Kevin> the same difficulties.  Does the AIX gcc version support anything like 
Kevin> -malign-natural does for Apple's gcc 3.1 (byte aligned to 1, short aligned 
Kevin> to 2, int aligned to 4, double and long long int aligned to 8)?

Kevin> Any particular reason for treating long long ints differently from doubles?

	The AIX port of GCC does not have the equivalent of
-malign-natural.  IBM's Visual Age compiler may have a similar option
which could be provided for AIX GCC as well.

	At the time the AIX ABI was being developed (late 1980's), 64-bit
"long long int" extension did not exist and double was the only 64-bit
quantity.  The RIOS implementation of the POWER architecture could handle
word-aligned doubles, so the ABI architects decided why make "double" the
odd-ball with stricter alignment than all other types.  By the time "long
long int" was introduced, they decided to be more forward-thinking, but
they could not break the ABI and correct "double" alignment.

David

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2003-03-20  5:44 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-02-07 16:18 Darwin gcc 3.3 sizeof of C++ structures with long long ints is strange Kevin B. Hendricks
2003-03-19 12:30 ` Andrew Haley
2003-03-19 14:22   ` Kevin B. Hendricks
2003-03-20  0:14     ` David Edelsohn
2003-03-20  5:28       ` Kevin B. Hendricks
2003-03-20  8:04         ` David Edelsohn
2003-03-19 19:21   ` Kevin B. Hendricks

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).