From 953783e00c9934bc41077108fffeb1e2a17b00df Mon Sep 17 00:00:00 2001 From: Nadav Rotem Date: Mon, 1 Apr 2013 15:53:30 +0000 Subject: Add support for vector data types in the LLVM interpreter. Patch by: Veselov, Yuri git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@178469 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/ExecutionEngine/ExecutionEngine.cpp | 151 +++++++++++++++++++++++++++++++- 1 file changed, 148 insertions(+), 3 deletions(-) (limited to 'lib/ExecutionEngine/ExecutionEngine.cpp') diff --git a/lib/ExecutionEngine/ExecutionEngine.cpp b/lib/ExecutionEngine/ExecutionEngine.cpp index 3d59d251a0..906a3a3fda 100644 --- a/lib/ExecutionEngine/ExecutionEngine.cpp +++ b/lib/ExecutionEngine/ExecutionEngine.cpp @@ -535,6 +535,8 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) { if (isa(C)) { GenericValue Result; switch (C->getType()->getTypeID()) { + default: + break; case Type::IntegerTyID: case Type::X86_FP80TyID: case Type::FP128TyID: @@ -543,7 +545,16 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) { // with the correct bit width. Result.IntVal = APInt(C->getType()->getPrimitiveSizeInBits(), 0); break; - default: + case Type::VectorTyID: + // if the whole vector is 'undef' just reserve memory for the value. + const VectorType* VTy = dyn_cast(C->getType()); + const Type *ElemTy = VTy->getElementType(); + unsigned int elemNum = VTy->getNumElements(); + Result.AggregateVal.resize(elemNum); + if (ElemTy->isIntegerTy()) + for (unsigned int i = 0; i < elemNum; ++i) + Result.AggregateVal[i].IntVal = + APInt(ElemTy->getPrimitiveSizeInBits(), 0); break; } return Result; @@ -825,6 +836,101 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) { else llvm_unreachable("Unknown constant pointer type!"); break; + case Type::VectorTyID: { + unsigned elemNum; + Type* ElemTy; + const ConstantDataVector *CDV = dyn_cast(C); + const ConstantVector *CV = dyn_cast(C); + const ConstantAggregateZero *CAZ = dyn_cast(C); + + if (CDV) { + elemNum = CDV->getNumElements(); + ElemTy = CDV->getElementType(); + } else if (CV || CAZ) { + VectorType* VTy = dyn_cast(C->getType()); + elemNum = VTy->getNumElements(); + ElemTy = VTy->getElementType(); + } else { + llvm_unreachable("Unknown constant vector type!"); + } + + Result.AggregateVal.resize(elemNum); + // Check if vector holds floats. + if(ElemTy->isFloatTy()) { + if (CAZ) { + GenericValue floatZero; + floatZero.FloatVal = 0.f; + std::fill(Result.AggregateVal.begin(), Result.AggregateVal.end(), + floatZero); + break; + } + if(CV) { + for (unsigned i = 0; i < elemNum; ++i) + if (!isa(CV->getOperand(i))) + Result.AggregateVal[i].FloatVal = cast( + CV->getOperand(i))->getValueAPF().convertToFloat(); + break; + } + if(CDV) + for (unsigned i = 0; i < elemNum; ++i) + Result.AggregateVal[i].FloatVal = CDV->getElementAsFloat(i); + + break; + } + // Check if vector holds doubles. + if (ElemTy->isDoubleTy()) { + if (CAZ) { + GenericValue doubleZero; + doubleZero.DoubleVal = 0.0; + std::fill(Result.AggregateVal.begin(), Result.AggregateVal.end(), + doubleZero); + break; + } + if(CV) { + for (unsigned i = 0; i < elemNum; ++i) + if (!isa(CV->getOperand(i))) + Result.AggregateVal[i].DoubleVal = cast( + CV->getOperand(i))->getValueAPF().convertToDouble(); + break; + } + if(CDV) + for (unsigned i = 0; i < elemNum; ++i) + Result.AggregateVal[i].DoubleVal = CDV->getElementAsDouble(i); + + break; + } + // Check if vector holds integers. + if (ElemTy->isIntegerTy()) { + if (CAZ) { + GenericValue intZero; + intZero.IntVal = APInt(ElemTy->getScalarSizeInBits(), 0ull); + std::fill(Result.AggregateVal.begin(), Result.AggregateVal.end(), + intZero); + break; + } + if(CV) { + for (unsigned i = 0; i < elemNum; ++i) + if (!isa(CV->getOperand(i))) + Result.AggregateVal[i].IntVal = cast( + CV->getOperand(i))->getValue(); + else { + Result.AggregateVal[i].IntVal = + APInt(CV->getOperand(i)->getType()->getPrimitiveSizeInBits(), 0); + } + break; + } + if(CDV) + for (unsigned i = 0; i < elemNum; ++i) + Result.AggregateVal[i].IntVal = APInt( + CDV->getElementType()->getPrimitiveSizeInBits(), + CDV->getElementAsInteger(i)); + + break; + } + llvm_unreachable("Unknown constant pointer type!"); + } + break; + default: SmallString<256> Msg; raw_svector_ostream OS(Msg); @@ -866,6 +972,9 @@ void ExecutionEngine::StoreValueToMemory(const GenericValue &Val, const unsigned StoreBytes = getDataLayout()->getTypeStoreSize(Ty); switch (Ty->getTypeID()) { + default: + dbgs() << "Cannot store value of type " << *Ty << "!\n"; + break; case Type::IntegerTyID: StoreIntToMemory(Val.IntVal, (uint8_t*)Ptr, StoreBytes); break; @@ -885,8 +994,19 @@ void ExecutionEngine::StoreValueToMemory(const GenericValue &Val, *((PointerTy*)Ptr) = Val.PointerVal; break; - default: - dbgs() << "Cannot store value of type " << *Ty << "!\n"; + case Type::VectorTyID: + for (unsigned i = 0; i < Val.AggregateVal.size(); ++i) { + if (cast(Ty)->getElementType()->isDoubleTy()) + *(((double*)Ptr)+i) = Val.AggregateVal[i].DoubleVal; + if (cast(Ty)->getElementType()->isFloatTy()) + *(((float*)Ptr)+i) = Val.AggregateVal[i].FloatVal; + if (cast(Ty)->getElementType()->isIntegerTy()) { + unsigned numOfBytes =(Val.AggregateVal[i].IntVal.getBitWidth()+7)/8; + StoreIntToMemory(Val.AggregateVal[i].IntVal, + (uint8_t*)Ptr + numOfBytes*i, numOfBytes); + } + } + break; } if (sys::isLittleEndianHost() != getDataLayout()->isLittleEndian()) @@ -951,6 +1071,31 @@ void ExecutionEngine::LoadValueFromMemory(GenericValue &Result, Result.IntVal = APInt(80, y); break; } + case Type::VectorTyID: { + const VectorType *VT = cast(Ty); + const Type *ElemT = VT->getElementType(); + const unsigned numElems = VT->getNumElements(); + if (ElemT->isFloatTy()) { + Result.AggregateVal.resize(numElems); + for (unsigned i = 0; i < numElems; ++i) + Result.AggregateVal[i].FloatVal = *((float*)Ptr+i); + } + if (ElemT->isDoubleTy()) { + Result.AggregateVal.resize(numElems); + for (unsigned i = 0; i < numElems; ++i) + Result.AggregateVal[i].DoubleVal = *((double*)Ptr+i); + } + if (ElemT->isIntegerTy()) { + GenericValue intZero; + const unsigned elemBitWidth = cast(ElemT)->getBitWidth(); + intZero.IntVal = APInt(elemBitWidth, 0); + Result.AggregateVal.resize(numElems, intZero); + for (unsigned i = 0; i < numElems; ++i) + LoadIntFromMemory(Result.AggregateVal[i].IntVal, + (uint8_t*)Ptr+((elemBitWidth+7)/8)*i, (elemBitWidth+7)/8); + } + break; + } default: SmallString<256> Msg; raw_svector_ostream OS(Msg); -- cgit v1.2.3-70-g09d2 From 21a01d1ea89dba97c4f9e1f9f41485729a4046bc Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Mon, 15 Apr 2013 14:44:24 +0000 Subject: Make the host endianness check an integer constant expression. I will remove the isBigEndianHost function once I update clang. The ifdef logic is designed to * not use configure/cmake to avoid breaking -arch i686 -arch ppc. * default to little endian * be as small as possible It looks like sys/endian.h is the preferred header on most modern BSD systems, but it is better to change this in a followup patch as machine/endian.h is available on FreeBSD, OpenBSD, NetBSD and OS X. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@179527 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/ADT/Hashing.h | 4 ++-- include/llvm/Support/Endian.h | 2 +- include/llvm/Support/Host.h | 26 +++++++++++++++-------- lib/ExecutionEngine/ExecutionEngine.cpp | 6 +++--- lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h | 6 +++--- lib/Object/MachOObject.cpp | 2 +- lib/Support/DataExtractor.cpp | 2 +- lib/Support/FoldingSet.cpp | 4 ++-- 8 files changed, 30 insertions(+), 22 deletions(-) (limited to 'lib/ExecutionEngine/ExecutionEngine.cpp') diff --git a/include/llvm/ADT/Hashing.h b/include/llvm/ADT/Hashing.h index cda31a261d..e434417da7 100644 --- a/include/llvm/ADT/Hashing.h +++ b/include/llvm/ADT/Hashing.h @@ -151,7 +151,7 @@ namespace detail { inline uint64_t fetch64(const char *p) { uint64_t result; memcpy(&result, p, sizeof(result)); - if (sys::isBigEndianHost()) + if (sys::IsBigEndianHost) return sys::SwapByteOrder(result); return result; } @@ -159,7 +159,7 @@ inline uint64_t fetch64(const char *p) { inline uint32_t fetch32(const char *p) { uint32_t result; memcpy(&result, p, sizeof(result)); - if (sys::isBigEndianHost()) + if (sys::IsBigEndianHost) return sys::SwapByteOrder(result); return result; } diff --git a/include/llvm/Support/Endian.h b/include/llvm/Support/Endian.h index d438facfa4..0d35849883 100644 --- a/include/llvm/Support/Endian.h +++ b/include/llvm/Support/Endian.h @@ -37,7 +37,7 @@ namespace detail { namespace endian { template inline value_type byte_swap(value_type value) { - if (endian != native && sys::isBigEndianHost() != (endian == big)) + if (endian != native && sys::IsBigEndianHost != (endian == big)) return sys::SwapByteOrder(value); return value; } diff --git a/include/llvm/Support/Host.h b/include/llvm/Support/Host.h index 3a44405739..2731529dfd 100644 --- a/include/llvm/Support/Host.h +++ b/include/llvm/Support/Host.h @@ -15,22 +15,30 @@ #define LLVM_SUPPORT_HOST_H #include "llvm/ADT/StringMap.h" + +#if defined(__linux__) +#include +#else +#ifndef _MSC_VER +#include +#endif +#endif + #include namespace llvm { namespace sys { - inline bool isLittleEndianHost() { - union { - int i; - char c; - }; - i = 1; - return c; - } +#if BYTE_ORDER == BIG_ENDIAN + static const bool IsBigEndianHost = true; +#else + static const bool IsBigEndianHost = false; +#endif + + static const bool IsLittleEndianHost = !IsBigEndianHost; inline bool isBigEndianHost() { - return !isLittleEndianHost(); + return IsBigEndianHost; } /// getDefaultTargetTriple() - Return the default target triple the compiler diff --git a/lib/ExecutionEngine/ExecutionEngine.cpp b/lib/ExecutionEngine/ExecutionEngine.cpp index 906a3a3fda..e43ba4f1dd 100644 --- a/lib/ExecutionEngine/ExecutionEngine.cpp +++ b/lib/ExecutionEngine/ExecutionEngine.cpp @@ -948,7 +948,7 @@ static void StoreIntToMemory(const APInt &IntVal, uint8_t *Dst, assert((IntVal.getBitWidth()+7)/8 >= StoreBytes && "Integer too small!"); const uint8_t *Src = (const uint8_t *)IntVal.getRawData(); - if (sys::isLittleEndianHost()) { + if (sys::IsLittleEndianHost) { // 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); @@ -1009,7 +1009,7 @@ void ExecutionEngine::StoreValueToMemory(const GenericValue &Val, break; } - if (sys::isLittleEndianHost() != getDataLayout()->isLittleEndian()) + if (sys::IsLittleEndianHost != getDataLayout()->isLittleEndian()) // Host and target are different endian - reverse the stored bytes. std::reverse((uint8_t*)Ptr, StoreBytes + (uint8_t*)Ptr); } @@ -1021,7 +1021,7 @@ static void LoadIntFromMemory(APInt &IntVal, uint8_t *Src, unsigned LoadBytes) { uint8_t *Dst = reinterpret_cast( const_cast(IntVal.getRawData())); - if (sys::isLittleEndianHost()) + 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); diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h index f100994577..555ea96943 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h @@ -202,14 +202,14 @@ protected: void writeInt16BE(uint8_t *Addr, uint16_t Value) { - if (sys::isLittleEndianHost()) + if (sys::IsLittleEndianHost) Value = sys::SwapByteOrder(Value); *Addr = (Value >> 8) & 0xFF; *(Addr+1) = Value & 0xFF; } void writeInt32BE(uint8_t *Addr, uint32_t Value) { - if (sys::isLittleEndianHost()) + if (sys::IsLittleEndianHost) Value = sys::SwapByteOrder(Value); *Addr = (Value >> 24) & 0xFF; *(Addr+1) = (Value >> 16) & 0xFF; @@ -218,7 +218,7 @@ protected: } void writeInt64BE(uint8_t *Addr, uint64_t Value) { - if (sys::isLittleEndianHost()) + if (sys::IsLittleEndianHost) Value = sys::SwapByteOrder(Value); *Addr = (Value >> 56) & 0xFF; *(Addr+1) = (Value >> 48) & 0xFF; diff --git a/lib/Object/MachOObject.cpp b/lib/Object/MachOObject.cpp index c9c341a207..d88f96f298 100644 --- a/lib/Object/MachOObject.cpp +++ b/lib/Object/MachOObject.cpp @@ -61,7 +61,7 @@ static void ReadInMemoryStruct(const MachOObject &MOO, MachOObject::MachOObject(MemoryBuffer *Buffer_, bool IsLittleEndian_, bool Is64Bit_) : Buffer(Buffer_), IsLittleEndian(IsLittleEndian_), Is64Bit(Is64Bit_), - IsSwappedEndian(IsLittleEndian != sys::isLittleEndianHost()), + IsSwappedEndian(IsLittleEndian != sys::IsLittleEndianHost), HasStringTable(false), LoadCommands(0), NumLoadedCommands(0) { // Load the common header. memcpy(&Header, Buffer->getBuffer().data(), sizeof(Header)); diff --git a/lib/Support/DataExtractor.cpp b/lib/Support/DataExtractor.cpp index 3d5cce0535..a564d211b1 100644 --- a/lib/Support/DataExtractor.cpp +++ b/lib/Support/DataExtractor.cpp @@ -20,7 +20,7 @@ static T getU(uint32_t *offset_ptr, const DataExtractor *de, uint32_t offset = *offset_ptr; if (de->isValidOffsetForDataOfSize(offset, sizeof(val))) { std::memcpy(&val, &Data[offset], sizeof(val)); - if (sys::isLittleEndianHost() != isLittleEndian) + if (sys::IsLittleEndianHost != isLittleEndian) val = sys::SwapByteOrder(val); // Advance the offset diff --git a/lib/Support/FoldingSet.cpp b/lib/Support/FoldingSet.cpp index 36e33b5aaf..145f12dc1e 100644 --- a/lib/Support/FoldingSet.cpp +++ b/lib/Support/FoldingSet.cpp @@ -101,7 +101,7 @@ void FoldingSetNodeID::AddString(StringRef String) { // Otherwise do it the hard way. // To be compatible with above bulk transfer, we need to take endianness // into account. - if (sys::isBigEndianHost()) { + if (sys::IsBigEndianHost) { for (Pos += 4; Pos <= Size; Pos += 4) { unsigned V = ((unsigned char)String[Pos - 4] << 24) | ((unsigned char)String[Pos - 3] << 16) | @@ -110,7 +110,7 @@ void FoldingSetNodeID::AddString(StringRef String) { Bits.push_back(V); } } else { - assert(sys::isLittleEndianHost() && "Unexpected host endianness"); + assert(sys::IsLittleEndianHost && "Unexpected host endianness"); for (Pos += 4; Pos <= Size; Pos += 4) { unsigned V = ((unsigned char)String[Pos - 1] << 24) | ((unsigned char)String[Pos - 2] << 16) | -- cgit v1.2.3-70-g09d2