diff --git a/CMakeLists.txt b/CMakeLists.txt index fadc83d5..280979f2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -278,6 +278,19 @@ else() set(EXTRA_CXXFLAGS "-fexceptions") endif() +# +# Check endianess. +# There is no realiable way to delegate the work to the compiler. +# E.g. gcc up to version 4.6 defines __LITTLE_ENDIAN, but not 4.7 +# +include(TestBigEndian) +test_big_endian(BIGENDIAN) +if(${BIGENDIAN}) + add_definitions(-D__BIG_ENDIAN__) +else() + add_definitions(-D__LITTLE_ENDIAN__) +endif() + # # Set up the main ldc/ldc2 target. # diff --git a/dmd2/constfold.c b/dmd2/constfold.c index b114885e..8d60920a 100644 --- a/dmd2/constfold.c +++ b/dmd2/constfold.c @@ -1628,7 +1628,16 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2) size_t len = (t->ty == tn->ty) ? 1 : utf_codeLength(sz, v); s = mem.malloc((len + 1) * sz); if (t->ty == tn->ty) +#if IN_LLVM +#if __LITTLE_ENDIAN__ memcpy((unsigned char *)s, &v, sz); +#else + memcpy((unsigned char *)s, + (unsigned char *)&v + (sizeof(dinteger_t) - sz), sz); +#endif +#else + memcpy((unsigned char *)s, &v, sz); +#endif else utf_encode(sz, s, v); @@ -1752,7 +1761,16 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2) s = mem.malloc((len + 1) * sz); memcpy(s, es1->string, es1->len * sz); if (homoConcat) +#if IN_LLVM +#if __LITTLE_ENDIAN__ memcpy((unsigned char *)s + (sz * es1->len), &v, sz); +#else + memcpy((unsigned char *)s + (sz * es1->len), + (unsigned char *)&v + (sizeof(dinteger_t) - sz), sz); +#endif +#else + memcpy((unsigned char *)s + (sz * es1->len), &v, sz); +#endif else utf_encode(sz, (unsigned char *)s + (sz * es1->len), v); @@ -1776,7 +1794,16 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2) dinteger_t v = e1->toInteger(); s = mem.malloc((len + 1) * sz); +#if IN_LLVM +#if __LITTLE_ENDIAN__ memcpy((unsigned char *)s, &v, sz); +#else + memcpy((unsigned char *)s, + (unsigned char *)&v + (sizeof(dinteger_t) - sz), sz); +#endif +#else + memcpy((unsigned char *)s, &v, sz); +#endif memcpy((unsigned char *)s + sz, es2->string, es2->len * sz); // Add terminating 0 diff --git a/dmd2/interpret.c b/dmd2/interpret.c index b213d624..8627f24f 100644 --- a/dmd2/interpret.c +++ b/dmd2/interpret.c @@ -990,7 +990,16 @@ Expression *ctfeCat(Type *type, Expression *e1, Expression *e2) if (es2e->op != TOKint64) return EXP_CANT_INTERPRET; dinteger_t v = es2e->toInteger(); +#if IN_LLVM +#if __LITTLE_ENDIAN__ memcpy((unsigned char *)s + i * sz, &v, sz); +#else + memcpy((unsigned char *)s + i * sz, + (unsigned char *)&v + (sizeof(dinteger_t) - sz), sz); +#endif +#else + memcpy((unsigned char *)s + i * sz, &v, sz); +#endif } // Add terminating 0 @@ -1020,7 +1029,16 @@ Expression *ctfeCat(Type *type, Expression *e1, Expression *e2) if (es2e->op != TOKint64) return EXP_CANT_INTERPRET; dinteger_t v = es2e->toInteger(); +#if IN_LLVM +#if __LITTLE_ENDIAN__ memcpy((unsigned char *)s + (es1->len + i) * sz, &v, sz); +#else + memcpy((unsigned char *)s + (es1->len + i) * sz, + (unsigned char *) &v + (sizeof(dinteger_t) - sz), sz); +#endif +#else + memcpy((unsigned char *)s + (es1->len + i) * sz, &v, sz); +#endif } // Add terminating 0 diff --git a/dmd2/module.c b/dmd2/module.c index 4d363c9d..cbc281f4 100644 --- a/dmd2/module.c +++ b/dmd2/module.c @@ -544,20 +544,46 @@ bool Module::read(Loc loc) inline unsigned readwordLE(unsigned short *p) { +#if IN_LLVM +#if __LITTLE_ENDIAN__ + return *p; +#else + return (((unsigned char *)p)[1] << 8) | ((unsigned char *)p)[0]; +#endif +#else #if LITTLE_ENDIAN return *p; #else return (((unsigned char *)p)[1] << 8) | ((unsigned char *)p)[0]; #endif +#endif } inline unsigned readwordBE(unsigned short *p) { +#if IN_LLVM +#if __BIG_ENDIAN__ + return *p; +#else return (((unsigned char *)p)[0] << 8) | ((unsigned char *)p)[1]; +#endif +#else + return (((unsigned char *)p)[0] << 8) | ((unsigned char *)p)[1]; +#endif } inline unsigned readlongLE(unsigned *p) { +#if IN_LLVM +#if __LITTLE_ENDIAN__ + return *p; +#else + return ((unsigned char *)p)[0] | + (((unsigned char *)p)[1] << 8) | + (((unsigned char *)p)[2] << 16) | + (((unsigned char *)p)[3] << 24); +#endif +#else #if LITTLE_ENDIAN return *p; #else @@ -566,14 +592,26 @@ inline unsigned readlongLE(unsigned *p) (((unsigned char *)p)[2] << 16) | (((unsigned char *)p)[3] << 24); #endif +#endif } inline unsigned readlongBE(unsigned *p) { +#if IN_LLVM +#if __BIG_ENDIAN__ + return *p; +#else return ((unsigned char *)p)[3] | (((unsigned char *)p)[2] << 8) | (((unsigned char *)p)[1] << 16) | (((unsigned char *)p)[0] << 24); +#endif +#else + return ((unsigned char *)p)[3] | + (((unsigned char *)p)[2] << 8) | + (((unsigned char *)p)[1] << 16) | + (((unsigned char *)p)[0] << 24); +#endif } #if IN_LLVM diff --git a/dmd2/root/stringtable.c b/dmd2/root/stringtable.c index 58dcd0b6..edb68c86 100644 --- a/dmd2/root/stringtable.c +++ b/dmd2/root/stringtable.c @@ -35,29 +35,54 @@ hash_t calcHash(const char *str, size_t len) case 2: hash *= 37; +#if IN_LLVM +#if __LITTLE_ENDIAN__ + hash += *(const uint16_t *)str; +#else + hash += str[0] * 256 + str[1]; +#endif +#else #if LITTLE_ENDIAN hash += *(const uint16_t *)str; #else hash += str[0] * 256 + str[1]; +#endif #endif return hash; case 3: hash *= 37; +#if IN_LLVM +#if __LITTLE_ENDIAN__ + hash += (*(const uint16_t *)str << 8) + + ((const uint8_t *)str)[2]; +#else + hash += (str[0] * 256 + str[1]) * 256 + str[2]; +#endif +#else #if LITTLE_ENDIAN hash += (*(const uint16_t *)str << 8) + ((const uint8_t *)str)[2]; #else hash += (str[0] * 256 + str[1]) * 256 + str[2]; +#endif #endif return hash; default: hash *= 37; +#if IN_LLVM +#if __LITTLE_ENDIAN__ + hash += *(const uint32_t *)str; +#else + hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3]; +#endif +#else #if LITTLE_ENDIAN hash += *(const uint32_t *)str; #else hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3]; +#endif #endif str += 4; len -= 4;