From 1eff70451fbb079c1d5b8f45ff8c8a2b8f74d7ba Mon Sep 17 00:00:00 2001 From: Duncan Sands Date: Mon, 10 Dec 2007 17:43:13 +0000 Subject: Fix PR1836: in the interpreter, read and write apints using the minimum possible number of bytes. For little endian targets run on little endian machines, apints are stored in memory from LSB to MSB as before. For big endian targets on big endian machines they are stored from MSB to LSB which wasn't always the case before (if the target and host endianness doesn't match values are stored according to the host's endianness). Doing this requires knowing the endianness of the host, which is determined when configuring - thanks go to Anton for this. Only having access to little endian machines I was unable to properly test the big endian part, which is also the most complicated... git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@44796 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/ExecutionEngine/ExecutionEngine.cpp | 71 ++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 24 deletions(-) (limited to 'lib/ExecutionEngine/ExecutionEngine.cpp') 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(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(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: -- cgit v1.2.3-18-g5258