-///
-void ExecutionEngine::StoreValueToMemory(GenericValue Val, GenericValue *Ptr,
- const Type *Ty) {
- if (getTargetData()->isLittleEndian()) {
- switch (Ty->getTypeID()) {
- case Type::IntegerTyID: {
- unsigned BitWidth = cast<IntegerType>(Ty)->getBitWidth();
- uint64_t BitMask = cast<IntegerType>(Ty)->getBitMask();
- GenericValue TmpVal = Val;
- if (BitWidth <= 8)
- Ptr->Untyped[0] = Val.Int8Val & BitMask;
- else if (BitWidth <= 16) {
- TmpVal.Int16Val &= BitMask;
- Ptr->Untyped[0] = TmpVal.Int16Val & 255;
- Ptr->Untyped[1] = (TmpVal.Int16Val >> 8) & 255;
- } else if (BitWidth <= 32) {
- TmpVal.Int32Val &= BitMask;
- Ptr->Untyped[0] = TmpVal.Int32Val & 255;
- Ptr->Untyped[1] = (TmpVal.Int32Val >> 8) & 255;
- Ptr->Untyped[2] = (TmpVal.Int32Val >> 16) & 255;
- Ptr->Untyped[3] = (TmpVal.Int32Val >> 24) & 255;
- } else if (BitWidth <= 64) {
- TmpVal.Int64Val &= BitMask;
- Ptr->Untyped[0] = (unsigned char)(TmpVal.Int64Val );
- Ptr->Untyped[1] = (unsigned char)(TmpVal.Int64Val >> 8);
- Ptr->Untyped[2] = (unsigned char)(TmpVal.Int64Val >> 16);
- Ptr->Untyped[3] = (unsigned char)(TmpVal.Int64Val >> 24);
- Ptr->Untyped[4] = (unsigned char)(TmpVal.Int64Val >> 32);
- Ptr->Untyped[5] = (unsigned char)(TmpVal.Int64Val >> 40);
- Ptr->Untyped[6] = (unsigned char)(TmpVal.Int64Val >> 48);
- Ptr->Untyped[7] = (unsigned char)(TmpVal.Int64Val >> 56);
- } else {
- uint64_t *Dest = (uint64_t*)Ptr;
- const uint64_t *Src = Val.APIntVal->getRawData();
- for (uint32_t i = 0; i < Val.APIntVal->getNumWords(); ++i)
- Dest[i] = Src[i];
- }
- break;
- }
-Store4BytesLittleEndian:
- case Type::FloatTyID:
- Ptr->Untyped[0] = Val.Int32Val & 255;
- Ptr->Untyped[1] = (Val.Int32Val >> 8) & 255;
- Ptr->Untyped[2] = (Val.Int32Val >> 16) & 255;
- Ptr->Untyped[3] = (Val.Int32Val >> 24) & 255;
- break;
- case Type::PointerTyID:
- if (getTargetData()->getPointerSize() == 4)
- goto Store4BytesLittleEndian;
- /* FALL THROUGH */
- case Type::DoubleTyID:
- Ptr->Untyped[0] = (unsigned char)(Val.Int64Val );
- Ptr->Untyped[1] = (unsigned char)(Val.Int64Val >> 8);
- Ptr->Untyped[2] = (unsigned char)(Val.Int64Val >> 16);
- Ptr->Untyped[3] = (unsigned char)(Val.Int64Val >> 24);
- Ptr->Untyped[4] = (unsigned char)(Val.Int64Val >> 32);
- Ptr->Untyped[5] = (unsigned char)(Val.Int64Val >> 40);
- Ptr->Untyped[6] = (unsigned char)(Val.Int64Val >> 48);
- Ptr->Untyped[7] = (unsigned char)(Val.Int64Val >> 56);
- break;
- default:
- cerr << "Cannot store value of type " << *Ty << "!\n";
- }
- } else {
- switch (Ty->getTypeID()) {
- case Type::IntegerTyID: {
- unsigned BitWidth = cast<IntegerType>(Ty)->getBitWidth();
- uint64_t BitMask = cast<IntegerType>(Ty)->getBitMask();
- GenericValue TmpVal = Val;
- if (BitWidth <= 8)
- Ptr->Untyped[0] = Val.Int8Val & BitMask;
- else if (BitWidth <= 16) {
- TmpVal.Int16Val &= BitMask;
- Ptr->Untyped[1] = TmpVal.Int16Val & 255;
- Ptr->Untyped[0] = (TmpVal.Int16Val >> 8) & 255;
- } else if (BitWidth <= 32) {
- TmpVal.Int32Val &= BitMask;
- Ptr->Untyped[3] = TmpVal.Int32Val & 255;
- Ptr->Untyped[2] = (TmpVal.Int32Val >> 8) & 255;
- Ptr->Untyped[1] = (TmpVal.Int32Val >> 16) & 255;
- Ptr->Untyped[0] = (TmpVal.Int32Val >> 24) & 255;
- } else if (BitWidth <= 64) {
- TmpVal.Int64Val &= BitMask;
- Ptr->Untyped[7] = (unsigned char)(TmpVal.Int64Val );
- Ptr->Untyped[6] = (unsigned char)(TmpVal.Int64Val >> 8);
- Ptr->Untyped[5] = (unsigned char)(TmpVal.Int64Val >> 16);
- Ptr->Untyped[4] = (unsigned char)(TmpVal.Int64Val >> 24);
- Ptr->Untyped[3] = (unsigned char)(TmpVal.Int64Val >> 32);
- Ptr->Untyped[2] = (unsigned char)(TmpVal.Int64Val >> 40);
- Ptr->Untyped[1] = (unsigned char)(TmpVal.Int64Val >> 48);
- Ptr->Untyped[0] = (unsigned char)(TmpVal.Int64Val >> 56);
- } else {
- uint64_t *Dest = (uint64_t*)Ptr;
- const uint64_t *Src = Val.APIntVal->getRawData();
- for (uint32_t i = 0; i < Val.APIntVal->getNumWords(); ++i)
- Dest[i] = Src[i];
- }
- break;
- }
- Store4BytesBigEndian:
- case Type::FloatTyID:
- Ptr->Untyped[3] = Val.Int32Val & 255;
- Ptr->Untyped[2] = (Val.Int32Val >> 8) & 255;
- Ptr->Untyped[1] = (Val.Int32Val >> 16) & 255;
- Ptr->Untyped[0] = (Val.Int32Val >> 24) & 255;
- break;
- case Type::PointerTyID:
- if (getTargetData()->getPointerSize() == 4)
- goto Store4BytesBigEndian;
- /* FALL THROUGH */
- case Type::DoubleTyID:
- Ptr->Untyped[7] = (unsigned char)(Val.Int64Val );
- Ptr->Untyped[6] = (unsigned char)(Val.Int64Val >> 8);
- Ptr->Untyped[5] = (unsigned char)(Val.Int64Val >> 16);
- Ptr->Untyped[4] = (unsigned char)(Val.Int64Val >> 24);
- Ptr->Untyped[3] = (unsigned char)(Val.Int64Val >> 32);
- Ptr->Untyped[2] = (unsigned char)(Val.Int64Val >> 40);
- Ptr->Untyped[1] = (unsigned char)(Val.Int64Val >> 48);
- Ptr->Untyped[0] = (unsigned char)(Val.Int64Val >> 56);
- break;
- default:
- cerr << "Cannot store value of type " << *Ty << "!\n";
+void ExecutionEngine::StoreValueToMemory(const GenericValue &Val,
+ GenericValue *Ptr, const Type *Ty) {
+ const unsigned StoreBytes = getTargetData()->getTypeStoreSize(Ty);
+
+ switch (Ty->getTypeID()) {
+ case Type::IntegerTyID:
+ StoreIntToMemory(Val.IntVal, (uint8_t*)Ptr, StoreBytes);
+ break;
+ case Type::FloatTyID:
+ *((float*)Ptr) = Val.FloatVal;
+ break;
+ case Type::DoubleTyID:
+ *((double*)Ptr) = Val.DoubleVal;
+ break;
+ case Type::X86_FP80TyID:
+ memcpy(Ptr, Val.IntVal.getRawData(), 10);
+ break;
+ case Type::PointerTyID:
+ // Ensure 64 bit target pointers are fully initialized on 32 bit hosts.
+ if (StoreBytes != sizeof(PointerTy))
+ memset(Ptr, 0, StoreBytes);
+
+ *((PointerTy*)Ptr) = Val.PointerVal;
+ break;
+ default:
+ cerr << "Cannot store value of type " << *Ty << "!\n";
+ }
+
+ if (sys::isLittleEndianHost() != getTargetData()->isLittleEndian())
+ // Host and target are different endian - reverse the stored bytes.
+ std::reverse((uint8_t*)Ptr, StoreBytes + (uint8_t*)Ptr);
+}
+
+/// LoadIntFromMemory - Loads the integer stored in the LoadBytes bytes starting
+/// from Src into IntVal, which is assumed to be wide enough and to hold zero.
+static void LoadIntFromMemory(APInt &IntVal, uint8_t *Src, unsigned LoadBytes) {
+ assert((IntVal.getBitWidth()+7)/8 >= LoadBytes && "Integer too small!");
+ uint8_t *Dst = (uint8_t *)IntVal.getRawData();
+
+ if (sys::isLittleEndianHost())
+ // 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);