diff options
-rw-r--r-- | autoconf/configure.ac | 5 | ||||
-rwxr-xr-x | configure | 70 | ||||
-rw-r--r-- | include/llvm/Config/config.h.in | 6 | ||||
-rw-r--r-- | include/llvm/Target/TargetData.h | 11 | ||||
-rw-r--r-- | lib/ExecutionEngine/ExecutionEngine.cpp | 71 | ||||
-rw-r--r-- | test/ExecutionEngine/2007-12-10-APIntLoadStore.ll | 19 |
6 files changed, 129 insertions, 53 deletions
diff --git a/autoconf/configure.ac b/autoconf/configure.ac index 979e3a8986..fe16b5073e 100644 --- a/autoconf/configure.ac +++ b/autoconf/configure.ac @@ -227,7 +227,10 @@ dnl Define a substitution, ARCH, for the target architecture AC_SUBST(ARCH,$llvm_cv_target_arch) dnl Check for the endianness of the target -AC_C_BIGENDIAN(AC_SUBST([ENDIAN],[big]),AC_SUBST([ENDIAN],[little])) +AC_C_BIGENDIAN([AC_SUBST([ENDIAN],[big]), + AC_DEFINE([MSB_FIRST], [1], [Define if this target is big endian])], + [AC_SUBST([ENDIAN],[little]), + AC_DEFINE([LSB_FIRST], [1], [Define if this target is little endian])]) dnl Check for build platform executable suffix if we're crosscompiling if test "$cross_compiling" = yes; then @@ -828,7 +828,6 @@ NOLINKALL LLVM_ON_UNIX LLVM_ON_WIN32 ARCH -ENDIAN CC CFLAGS LDFLAGS @@ -839,6 +838,7 @@ OBJEXT CPP GREP EGREP +ENDIAN LLVM_CROSS_COMPILING BUILD_CC BUILD_EXEEXT @@ -4183,9 +4183,19 @@ echo "${ECHO_T}$ac_cv_c_bigendian" >&6; } case $ac_cv_c_bigendian in yes) ENDIAN=big +, + +cat >>confdefs.h <<\_ACEOF +#define MSB_FIRST 1 +_ACEOF ;; no) ENDIAN=little +, + +cat >>confdefs.h <<\_ACEOF +#define LSB_FIRST 1 +_ACEOF ;; *) { { echo "$as_me:$LINENO: error: unknown endianness @@ -8220,7 +8230,9 @@ if test "${enable_ltdl_install+set}" = set; then fi - if test x"${enable_ltdl_install-no}" != xno; then + + +if test x"${enable_ltdl_install-no}" != xno; then INSTALL_LTDL_TRUE= INSTALL_LTDL_FALSE='#' else @@ -8228,7 +8240,9 @@ else INSTALL_LTDL_FALSE= fi - if test x"${enable_ltdl_convenience-no}" != xno; then + + +if test x"${enable_ltdl_convenience-no}" != xno; then CONVENIENCE_LTDL_TRUE= CONVENIENCE_LTDL_FALSE='#' else @@ -9867,7 +9881,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<EOF -#line 9870 "configure" +#line 9884 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -11802,7 +11816,7 @@ ia64-*-hpux*) ;; *-*-irix6*) # Find out which ABI we are using. - echo '#line 11805 "configure"' > conftest.$ac_ext + echo '#line 11819 "configure"' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? @@ -13442,11 +13456,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:13445: $lt_compile\"" >&5) + (eval echo "\"\$as_me:13459: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:13449: \$? = $ac_status" >&5 + echo "$as_me:13463: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -13710,11 +13724,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:13713: $lt_compile\"" >&5) + (eval echo "\"\$as_me:13727: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:13717: \$? = $ac_status" >&5 + echo "$as_me:13731: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -13814,11 +13828,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:13817: $lt_compile\"" >&5) + (eval echo "\"\$as_me:13831: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:13821: \$? = $ac_status" >&5 + echo "$as_me:13835: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -16122,7 +16136,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<EOF -#line 16125 "configure" +#line 16139 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -16222,7 +16236,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<EOF -#line 16225 "configure" +#line 16239 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -18558,11 +18572,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:18561: $lt_compile\"" >&5) + (eval echo "\"\$as_me:18575: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:18565: \$? = $ac_status" >&5 + echo "$as_me:18579: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -18662,11 +18676,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:18665: $lt_compile\"" >&5) + (eval echo "\"\$as_me:18679: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:18669: \$? = $ac_status" >&5 + echo "$as_me:18683: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -20232,11 +20246,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:20235: $lt_compile\"" >&5) + (eval echo "\"\$as_me:20249: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:20239: \$? = $ac_status" >&5 + echo "$as_me:20253: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -20336,11 +20350,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:20339: $lt_compile\"" >&5) + (eval echo "\"\$as_me:20353: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:20343: \$? = $ac_status" >&5 + echo "$as_me:20357: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -22539,11 +22553,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:22542: $lt_compile\"" >&5) + (eval echo "\"\$as_me:22556: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:22546: \$? = $ac_status" >&5 + echo "$as_me:22560: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -22807,11 +22821,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:22810: $lt_compile\"" >&5) + (eval echo "\"\$as_me:22824: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:22814: \$? = $ac_status" >&5 + echo "$as_me:22828: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -22911,11 +22925,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:22914: $lt_compile\"" >&5) + (eval echo "\"\$as_me:22928: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:22918: \$? = $ac_status" >&5 + echo "$as_me:22932: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -32755,7 +32769,6 @@ NOLINKALL!$NOLINKALL$ac_delim LLVM_ON_UNIX!$LLVM_ON_UNIX$ac_delim LLVM_ON_WIN32!$LLVM_ON_WIN32$ac_delim ARCH!$ARCH$ac_delim -ENDIAN!$ENDIAN$ac_delim CC!$CC$ac_delim CFLAGS!$CFLAGS$ac_delim LDFLAGS!$LDFLAGS$ac_delim @@ -32766,6 +32779,7 @@ OBJEXT!$OBJEXT$ac_delim CPP!$CPP$ac_delim GREP!$GREP$ac_delim EGREP!$EGREP$ac_delim +ENDIAN!$ENDIAN$ac_delim LLVM_CROSS_COMPILING!$LLVM_CROSS_COMPILING$ac_delim BUILD_CC!$BUILD_CC$ac_delim BUILD_EXEEXT!$BUILD_EXEEXT$ac_delim diff --git a/include/llvm/Config/config.h.in b/include/llvm/Config/config.h.in index 32e154a695..64858f26b9 100644 --- a/include/llvm/Config/config.h.in +++ b/include/llvm/Config/config.h.in @@ -494,6 +494,9 @@ /* Installation prefix directory */ #undef LLVM_PREFIX +/* Define if this target is little endian */ +#undef LSB_FIRST + /* Define if the OS needs help to load dependent libraries for dlopen(). */ #undef LTDL_DLOPEN_DEPLIBS @@ -511,6 +514,9 @@ /* Define to the system default library search path. */ #undef LTDL_SYSSEARCHPATH +/* Define if this target is big endian */ +#undef MSB_FIRST + /* Define if /dev/zero should be used when mapping RWX memory, or undefine if its not necessary */ #undef NEED_DEV_ZERO_FOR_MMAP diff --git a/include/llvm/Target/TargetData.h b/include/llvm/Target/TargetData.h index 3136a38ac0..fd52ef380a 100644 --- a/include/llvm/Target/TargetData.h +++ b/include/llvm/Target/TargetData.h @@ -23,6 +23,7 @@ #include "llvm/Pass.h" #include "llvm/Support/DataTypes.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Config/config.h" #include <string> namespace llvm { @@ -142,6 +143,16 @@ public: bool isLittleEndian() const { return LittleEndian; } bool isBigEndian() const { return !LittleEndian; } + /// Host endianness... + bool hostIsLittleEndian() const { +#ifdef LSB_FIRST + return true; +#else + return false; +#endif + } + bool hostIsBigEndian() const { return !hostIsLittleEndian(); } + /// getStringRepresentation - Return the string representation of the /// TargetData. This representation is in the same format accepted by the /// string constructor above. diff --git a/lib/ExecutionEngine/ExecutionEngine.cpp b/lib/ExecutionEngine/ExecutionEngine.cpp index 02b94cc1fd..2c7a7dd144 100644 --- a/lib/ExecutionEngine/ExecutionEngine.cpp +++ b/lib/ExecutionEngine/ExecutionEngine.cpp @@ -633,20 +633,27 @@ void ExecutionEngine::StoreValueToMemory(const GenericValue &Val, GenericValue * switch (Ty->getTypeID()) { case Type::IntegerTyID: { unsigned BitWidth = cast<IntegerType>(Ty)->getBitWidth(); - GenericValue TmpVal = Val; - if (BitWidth <= 8) - *((uint8_t*)Ptr) = uint8_t(Val.IntVal.getZExtValue()); - else if (BitWidth <= 16) { - *((uint16_t*)Ptr) = uint16_t(Val.IntVal.getZExtValue()); - } else if (BitWidth <= 32) { - *((uint32_t*)Ptr) = uint32_t(Val.IntVal.getZExtValue()); - } else if (BitWidth <= 64) { - *((uint64_t*)Ptr) = uint64_t(Val.IntVal.getZExtValue()); - } else { - uint64_t *Dest = (uint64_t*)Ptr; - const uint64_t *Src = Val.IntVal.getRawData(); - for (uint32_t i = 0; i < Val.IntVal.getNumWords(); ++i) - Dest[i] = Src[i]; + unsigned StoreBytes = (BitWidth + 7)/8; + uint8_t *Src = (uint8_t *)Val.IntVal.getRawData(); + uint8_t *Dst = (uint8_t *)Ptr; + + if (getTargetData()->hostIsLittleEndian()) + // Little-endian host - the source is ordered from LSB to MSB. + // Order the destination from LSB to MSB: Do a straight copy. + memcpy(Dst, Src, StoreBytes); + else { + // Big-endian host - the source is an array of 64 bit words ordered from + // LSW to MSW. Each word is ordered from MSB to LSB. + // Order the destination from MSB to LSB: Reverse the word order, but not + // the bytes in a word. + while (StoreBytes > sizeof(uint64_t)) { + StoreBytes -= sizeof(uint64_t); + // May not be aligned so use memcpy. + memcpy(Dst + StoreBytes, Src, sizeof(uint64_t)); + Src += sizeof(uint64_t); + } + + memcpy(Dst, Src + sizeof(uint64_t) - StoreBytes, StoreBytes); } break; } @@ -683,16 +690,32 @@ void ExecutionEngine::LoadValueFromMemory(GenericValue &Result, switch (Ty->getTypeID()) { case Type::IntegerTyID: { unsigned BitWidth = cast<IntegerType>(Ty)->getBitWidth(); - if (BitWidth <= 8) - Result.IntVal = APInt(BitWidth, *((uint8_t*)Ptr)); - else if (BitWidth <= 16) { - Result.IntVal = APInt(BitWidth, *((uint16_t*)Ptr)); - } else if (BitWidth <= 32) { - Result.IntVal = APInt(BitWidth, *((uint32_t*)Ptr)); - } else if (BitWidth <= 64) { - Result.IntVal = APInt(BitWidth, *((uint64_t*)Ptr)); - } else - Result.IntVal = APInt(BitWidth, (BitWidth+63)/64, (uint64_t*)Ptr); + unsigned LoadBytes = (BitWidth + 7)/8; + + // An APInt with all words initially zero. + Result.IntVal = APInt(BitWidth, 0); + + uint8_t *Src = (uint8_t *)Ptr; + uint8_t *Dst = (uint8_t *)Result.IntVal.getRawData(); + + if (getTargetData()->hostIsLittleEndian()) + // Little-endian host - the destination must be ordered from LSB to MSB. + // The source is ordered from LSB to MSB: Do a straight copy. + memcpy(Dst, Src, LoadBytes); + else { + // Big-endian - the destination is an array of 64 bit words ordered from + // LSW to MSW. Each word must be ordered from MSB to LSB. The source is + // ordered from MSB to LSB: Reverse the word order, but not the bytes in + // a word. + while (LoadBytes > sizeof(uint64_t)) { + LoadBytes -= sizeof(uint64_t); + // May not be aligned so use memcpy. + memcpy(Dst, Src + LoadBytes, sizeof(uint64_t)); + Dst += sizeof(uint64_t); + } + + memcpy(Dst + sizeof(uint64_t) - LoadBytes, Src, LoadBytes); + } break; } case Type::FloatTyID: diff --git a/test/ExecutionEngine/2007-12-10-APIntLoadStore.ll b/test/ExecutionEngine/2007-12-10-APIntLoadStore.ll new file mode 100644 index 0000000000..7a337f90cb --- /dev/null +++ b/test/ExecutionEngine/2007-12-10-APIntLoadStore.ll @@ -0,0 +1,19 @@ +; RUN: llvm-as < %s -o - | lli -force-interpreter +; PR1836 + +define i32 @main() { +entry: + %retval = alloca i32 ; <i32*> [#uses=2] + %tmp = alloca i32 ; <i32*> [#uses=2] + %x = alloca i75, align 16 ; <i75*> [#uses=1] + %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0] + store i75 999, i75* %x, align 16 + store i32 0, i32* %tmp, align 4 + %tmp1 = load i32* %tmp, align 4 ; <i32> [#uses=1] + store i32 %tmp1, i32* %retval, align 4 + br label %return + +return: ; preds = %entry + %retval2 = load i32* %retval ; <i32> [#uses=1] + ret i32 %retval2 +} |