Hi Jan,

Jan Rinze wrote:
> Hi all,
>
> I am a bit worried and confused about this patch:
>
>   

This patch made the way we align and size structs and bitfields match 
the way MSFT does with
their tools. That is part of the ABI we must match. I'll give you an 
example where this was failing before the
patch.

Take an dll built with ex MSVC, with contents like this:

struct my_struct
{
    size_t size_of_my_struct; /* This technique is very common in Win32 
world. It is mostly used to check the version
                                               of my_struct being used */
    char v1_field;
/*    char v2_field;    Field would be added in v2 of the dll.*/
};

/* only showing v1 of the dll.  */
__declspec(dllexport) BOOL my_funct(struct my_struct* s)
{
    if (s->size_of_my_struct != sizeof (struct my_struct))
    {
       return FALSE;
    }
    /* do actual work. */
    return TRUE;
}

And then called by an app built with mingw32ce, would never work 
correctly, since the sizeofs
wouldn't match.

Or imagine compiling a dll with a MSFT compiler that takes a foo4 
pointer as a parameter in one of its exported functions.
Then imagine you built an app in cegcc or mingw32ce, that uses that dll.
Accessing the y member on the app and on the dll would access different 
offsets! Bang!

Or this:

In a MSVC compiled dll:
struct small
{
    char a;
};

__declspec(dllexport) struct small* alloc_small(void)
{
    return malloc (sizeof (struct small)); /* mallocs 1 byte. */
}

In a mingw32ce app using the above dll:

__declspec(dllimport) struct small* alloc_small(void);

int main()
{
    struct small* sm = alloc_small();
    memset (sm, 0, sizeof (struct small)); /* clears 4 bytes, outch! */
}

> Op di 31-10-2006, om 00:59 schreef Pedro Alves:
>   
>> Hi all,
>>
>> I am commiting this patch that cleans up gcc's support of Windows CE for 
>> arm.
>>
>> This patch fixes some major bugs/annoyances we had:
>>
>>  - __declspec(dllexport/dllimport) was so broken that it was hurting.
>> We weren't passing -export= in .drectve properly,
>> so the linker would default to exporting everything. If you used .def 
>> files, this would go unnoticed.
>>
>>  - We had some major violations of WinCE's ABI:
>>
>> Currently this test gives wrong results:
>> struct abi_check_doubles { char a; double d; };
>> struct foo0 { char x; };
>> struct foo1 { char x;char :0; char y; };
>> struct foo2 { char x; int :0; int :0; int :0; int :0; char y; };
>> struct foo3 { char x; char :1; char y; };
>> struct foo4 { char x; int :1; char y; };
>>
>> int main()
>> {
>>     printf ("Size of foo0 is %d, should be 1\n", sizeof (struct foo0));
>>     printf ("Size of foo1 is %d, should be 2\n", sizeof (struct foo1));
>>     printf ("Size of foo2 is %d, should be 2\n", sizeof (struct foo2));
>>     printf ("Size of foo3 is %d, should be 3\n", sizeof (struct foo3));
>>     printf ("Size of foo4 is %d, should be 12\n", sizeof (struct foo4));
>>     return 0;
>> }
>>
>> The right results where taken from compiling the test case with MSVC.
>> Note that this is a simplified test case.
>> If you where experiencing weird crashes before while calling/interfacing 
>> MSVC/eVC compiled code,
>> including the system dlls, this may very well be the reason.
>>
>> This patch also brings gcc support very close to what should be 
>> submitted upstream.
>>     
>
> compiling the above on an ARM-Linux box yields:
>
> $> ./test
> Size of foo0 is 4, should be 1
> Size of foo1 is 4, should be 2
> Size of foo2 is 8, should be 2
> Size of foo3 is 4, should be 3
> Size of foo4 is 4, should be 12
>
> This is with  
>
> $> gcc --version
> gcc (GCC) 3.4.3
> Copyright (C) 2004 Free Software Foundation, Inc.
> This is free software; see the source for copying conditions.  There is
> NO
> warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
> PURPOSE.
>  
> We should note that this can break a lot of other stuff. We had rather
> be using the __packed__ attributed here.
>
>   
But WinCE is not arm-linux. Arm-linux uses it's own ABI (or ABIs for the 
matter, AAPCS, EABI, EEABI-linux, etc.)
We must follow the ABI WinCE uses. For instance, All linux ABIs let 
small structs be passed in registers, while
WinCE mandates that *all* structs be passed through the stack.

> struct abi_check_doubles { char a; double d; };
> struct __attribute__((__packed__)) foo0 { char x; };
> struct __attribute__((__packed__)) foo1 { char x;char :0; char y; };
> struct __attribute__((__packed__)) foo2 { char x; int :0; int :0; int
> :0; int :0; char y; };
> struct __attribute__((__packed__)) foo3 { char x; char :1; char y; };
> struct __attribute__((__packed__)) foo4 { char x; int :1; char y; };
>                                                                               
>   
> int main()
> {
>     printf ("Size of foo0 is %d, should be 1\n", sizeof (struct foo0));
>     printf ("Size of foo1 is %d, should be 2\n", sizeof (struct foo1));
>     printf ("Size of foo2 is %d, should be 2\n", sizeof (struct foo2));
>     printf ("Size of foo3 is %d, should be 3\n", sizeof (struct foo3));
>     printf ("Size of foo4 is %d, should be 12\n", sizeof (struct foo4));
>     return 0;
> }
>
> Will yield:
>
> ./test
> Size of foo0 is 1, should be 1
> Size of foo1 is 2, should be 2
> Size of foo2 is 2, should be 2
> Size of foo3 is 3, should be 3
> Size of foo4 is 3, should be 12
>
> Where the foo4 is 3 in my opinion is fully correct.. 12 is pretty large
> for 2 chars and 1 bit...
>
>   
Again it is the WinCE's ABI. Not my fault. :) Notice that the difference 
between foo3 and foo4 is the type of
the bitfield. On windows targets, the type matters. So on those cases 
you get:

struct foo3
{ 
  char x; /* 1 == sizeof (char) */
  char :1; /* 1 == sizeof (char) */
  char y; /* 1 == sizeof (char) */
};

struct foo4
{
  char x;  /* 1 == sizeof (char) */
              /* 3 == pad to align the next field, which has a 4 byte 
natural alignment. */
  int :1;    /* 4 == sizeof (int) */
  char y;  /* 1 == sizeof (char) */
              /* 3 == pad to align the struct size to the maximum 
alignment of all the members, which is 4 (int) */
};

On the other cases, a special rule about zero sized bitfields enter the 
game.

> The compiler can do this behaviour on all structs when we have
> -fpack-struct when invoking gcc. The manual of gcc however warns about
> the behaviour and the resulting binary incompatibilities.
>
>   
When you use -fpack-struct, you are effectively changing the ABI 
(Aplication Binary Interface).
You must never match two different ABI's in the same program, hence the 
warning.
In embedded apps where you have control over everything, you can get 
away with -fpack-struct,
but only if you compile everything with it, else, you have the same ABI 
mismatch problems.

> I am not sure about the behaviour of eVC in this respect but the packing
> of integers on an ARM processor is pretty much going to slowdown memory
> access by a factor of at least four! (each byte is read separately when
> unaligned memory access is done.)
>
>   
That's a bit of a simplification :) Optimization also has it's saying here.

> I will need to do some more checking on this in respect to eVC.
>
>   
I tested this on MSVC 2005, and I would be very surprised if eVC gave 
different results,
but I would be very interested in confirming this.

You can get a lot more info on this by googling for "-ms-bitfields" option.
Here is a link the patch that introduced support for it in gcc,
if you are interested.
http://gcc.gnu.org/ml/gcc-patches/1999-06n/msg00702.html

Hope this helps,

Cheers,
Pedro Alves


-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Cegcc-devel mailing list
Cegcc-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/cegcc-devel

Reply via email to