Christian Werner wrote:
> Pedro Alves wrote:
> 
>> I've built a cc1.exe with the attached patch applied, and I now get the
>> same alignments as the OP reported MSVC choses.  I'm doing a full
>> gcc build now.
>>
>> The patch also forces 64-bit alignment on doubles, but I haven't
>> tested it yet - bonus points if someone tests it and compares it to
>> MSVC.
>>
>> Cheers,
>> Pedro Alves
>>
>>
>> Index: gcc/gcc/config/arm/wince-pe.h
>> ===================================================================
>> --- gcc/gcc/config/arm/wince-pe.h    (revision 838)
>> +++ gcc/gcc/config/arm/wince-pe.h    (working copy)
>> @@ -229,6 +229,13 @@
>>  #undef  DEFAULT_STRUCTURE_SIZE_BOUNDARY
>>  #define DEFAULT_STRUCTURE_SIZE_BOUNDARY 8
>>  
>> +/* Force alignment of doubles to 64-bit.  */
>> +#undef ARM_DOUBLEWORD_ALIGN
>> +#define ARM_DOUBLEWORD_ALIGN        1
>> +
>> +#undef BIGGEST_ALIGNMENT
>> +#define BIGGEST_ALIGNMENT 64
>> +
>>  #undef TREE
>>  
>>  #ifndef BUFSIZ
> 
> Compiling SQLite 3.5.x (CVS version as of 2007-11-13) using CeGCC (SVN rev 
> 1064)
> worked OOTB. However running the resulting SQLite 3 shell (sqlite3.exe) on a 
> WM 5
> device with PXA 270 CPU gave strange results when selecting the sqlite_master
> schema until I reverted the above patch.
> 
> IMO the problem is related to 64 bit alignment of vararg parameters on stack.
> SQLite heavily uses long long internally for all integral computations and
> sqlite3_snprintf() (similar to C library's snprintf()) with format %lld gives
> wrong results. It seems to me that the argument for %lld was shifted towards
> a higher memory address by 4 bytes, thus I reverted the patch, and then it 
> worked.
> 

It was a thinko on my part.  The ARM_DOUBLEWORD_ALIGN has the effect
of forcing every double word into a even register pair (r0,r1),
(r2,r3), etc., while MSVC has no problem in putting double words
on odd register pairs (r1,r2), etc.

 From arm.c:
   /* Put doubleword aligned quantities in even register pairs.  */
   if (pcum->nregs & 1
       && ARM_DOUBLEWORD_ALIGN
       && arm_needs_doubleword_align (mode, type))
     pcum->nregs++;

---

void test5(const char *s, long double dd)
{
     printf(s, dd);
}

void test4(void)
{
     test5("asdf\n", 0);
}

000001b8 <test4>:
  1b8:   e59f0008        ldr     r0, [pc, #8]    ; 1c8 <test4+0x10>
  1bc:   e3a01000        mov     r1, #0  ; 0x0
  1c0:   e3a02000        mov     r2, #0  ; 0x0
  1c4:   ea000000        b       8 <printf+0x8>
  1c8:   000000a8        andeq   r0, r0, r8, lsr #1

---

I didn't keep an old gcc binary around, but we were outputting
something like:

000001b8 <test4>:
  1b8:   e59f0008        ldr     r0, [pc, #8]    ; 1c8 <test4+0x10>
  1bc:   e3a01000        mov     r2, #0  ; 0x0
  1c0:   e3a02000        mov     r3, #0  ; 0x0
  1c4:   ea000000        b       8 <printf+0x8>
  1c8:   000000a8        andeq   r0, r0, r8, lsr #1

---

The correct thing to do, is:

#define ARM_DOUBLEWORD_ALIGN 0
#define BIGGEST_ALIGNMENT 64

I'm going to commit a patch to make that change, once
I finish rebuilding mingw32ce from scratch.  Actually, that
macro effects a few other things, so I'll take me a bit
longer to be sure everything it alright, but we can fix
it later as problems are found.

I've been using the test below to compare what we output
with MSVC.

I'd appreciate if people tried to rebuild things
with that change, especially if you interface with
MSVC/eVC built libs.

Cheers,
Pedro Alves

#include <stdio.h>
#include <windows.h>

#ifdef __GNUC__
#define LL(X) X ## LL
#else
#define LL(X) X ## i64
#endif

struct T1
{
   unsigned short f1;
   int f2;
   char f3;
   char f4;
};

struct T2
{
   unsigned short f1;
   __int64 f2;
   char f3;
   char f4;
};

struct T3
{
   unsigned short f1;
   double f2;
   char f3;
   char f4;
};

int main2 ()
{
#define poffset(T, F) \
   printf("offsetof (%s::%s) = %i\n", #T, #F, offsetof (T, F))

   printf("sizeof (struct T1) = %i\n", sizeof (struct T1));
   poffset(struct T1, f1);
   poffset(struct T1, f2);
   poffset(struct T1, f3);
   poffset(struct T1, f4);

   printf("sizeof (struct T2) = %i\n", sizeof (struct T2));
   poffset(struct T2, f1);
   poffset(struct T2, f2);
   poffset(struct T2, f3);
   poffset(struct T2, f4);

   printf("sizeof (struct T3) = %i\n", sizeof (struct T3));
   poffset(struct T3, f1);
   poffset(struct T3, f2);
   poffset(struct T3, f3);
   poffset(struct T3, f4);

   return 0;
}

struct ddd
{
     __int64 dd;
};

void test7(const char *s, struct ddd dd)
{
     printf("dd = %I64x\n", dd);
}

struct ddd dd = { 0x0100000002000000ll };

void test6(void)
{
     test7("asdf\n", dd);
}

void test5(const char *s, long double dd)
{
     printf(s, dd);
}

void test4(void)
{
     test5("asdf\n", 0);
}

void test3(const char *s, unsigned __int64 ll)
{
     printf(s, ll);
}

void test2(void)
{
     test3("asdf\n", 64);
}

void test(void)
{
   printf("%I64x\n", (unsigned __int64) LL(0x0000000100000002));
}

int main ()
{
   main2 ();
   test ();

   printf ("test6\n");
   test6 ();

   printf("%I64x\n", (__int64)LL(0x0000000100000002));
   printf("%d\n", 2);
   printf("%I64d %d %I64d\n", (__int64)42, 43, (__int64)44);
   return 0;
}

> The strange thing is: on a PXA 255 Windows Mobile 2003 device I did not 
> observe
> any sqlite3_snprintf() problems regardless of the expansion of the 
> ARM_DOUBLEWORD_ALIGN
> macro.
> 

No idea here.  I've done the testing on a the Mofile 2003 emulator
and indeed I saw the problem.

-- 
Pedro Alves



-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Cegcc-devel mailing list
Cegcc-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/cegcc-devel

Reply via email to