From 45bb5c5333fba7e9909cca178d785bf2c1d2b0c1 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Tue, 24 Jan 2012 04:43:41 +0000 Subject: [PATCH] implement the ConstantDataSequential accessor methods. No need for 'getOperand' :) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@148778 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Constants.h | 7 +++ lib/VMCore/Constants.cpp | 96 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 100 insertions(+), 3 deletions(-) diff --git a/include/llvm/Constants.h b/include/llvm/Constants.h index 022ac2d3939..1fc33084943 100644 --- a/include/llvm/Constants.h +++ b/include/llvm/Constants.h @@ -597,6 +597,10 @@ public: inline SequentialType *getType() const { return reinterpret_cast(Value::getType()); } + + /// getElementType - Return the element type of the array/vector. + Type *getElementType() const; + /// Methods for support type inquiry through isa, cast, and dyn_cast: /// @@ -605,6 +609,9 @@ public: return V->getValueID() == ConstantDataArrayVal || V->getValueID() == ConstantDataVectorVal; } +private: + uint64_t getElementByteSize() const; + const char *getElementPointer(unsigned Elt) const; }; //===----------------------------------------------------------------------===// diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp index 3b52a7cdeb9..86087e4efba 100644 --- a/lib/VMCore/Constants.cpp +++ b/lib/VMCore/Constants.cpp @@ -1919,6 +1919,40 @@ GetElementPtrConstantExpr(Constant *C, const std::vector &IdxList, void ConstantDataArray::anchor() {} void ConstantDataVector::anchor() {} +/// getElementType - Return the element type of the array/vector. +Type *ConstantDataSequential::getElementType() const { + return getType()->getElementType(); +} + +/// isElementTypeConstantDataCompatible - Return true if this type is valid for +/// a ConstantDataSequential. This is i8/i16/i32/i64/float/double. +static bool isElementTypeConstantDataCompatible(const Type *Ty) { + if (Ty->isFloatTy() || Ty->isDoubleTy()) return true; + if (const IntegerType *IT = dyn_cast(Ty)) { + switch (IT->getBitWidth()) { + case 8: + case 16: + case 32: + case 64: + return true; + default: break; + } + } + return false; +} + +/// getElementByteSize - Return the size in bytes of the elements in the data. +uint64_t ConstantDataSequential::getElementByteSize() const { + return getElementType()->getPrimitiveSizeInBits()/8; +} + +/// getElementPointer - Return the start of the specified element. +const char *ConstantDataSequential::getElementPointer(unsigned Elt) const { + assert(Elt < getElementType()->getNumElements() && "Invalid Elt"); + return DataElements+Elt*getElementByteSize(); +} + + /// isAllZeros - return true if the array is empty or all zeros. static bool isAllZeros(StringRef Arr) { for (StringRef::iterator I = Arr.begin(), E = Arr.end(); I != E; ++I) @@ -1931,6 +1965,8 @@ static bool isAllZeros(StringRef Arr) { /// the correct element type. We take the bytes in as an StringRef because /// we *want* an underlying "char*" to avoid TBAA type punning violations. Constant *ConstantDataSequential::getImpl(StringRef Elements, Type *Ty) { + assert(isElementTypeConstantDataCompatible(cast(Ty)-> + getElementType())); // If the elements are all zero, return a CAZ, which is more dense. if (isAllZeros(Elements)) return ConstantAggregateZero::get(Ty); @@ -1959,9 +1995,7 @@ Constant *ConstantDataSequential::getImpl(StringRef Elements, Type *Ty) { } void ConstantDataSequential::destroyConstant() { - uint64_t ByteSize = - getType()->getElementType()->getPrimitiveSizeInBits()/8 * - getType()->getElementType()->getNumElements(); + uint64_t ByteSize = getElementByteSize() * getElementType()->getNumElements(); // Remove the constant from the StringMap. StringMap &CDSConstants = @@ -2059,6 +2093,62 @@ Constant *ConstantDataVector::get(ArrayRef Elts, LLVMContext &Context) { return getImpl(StringRef((char*)Elts.data(), Elts.size()*8), Ty); } +/// getElementAsInteger - If this is a sequential container of integers (of +/// any size), return the specified element in the low bits of a uint64_t. +uint64_t ConstantDataSequential::getElementAsInteger(unsigned Elt) const { + assert(isa(getElementType()) && + "Accessor can only be used when element is an integer"); + const char *EltPtr = getElementPointer(Elt); + + // The data is stored in host byte order, make sure to cast back to the right + // type to load with the right endianness. + switch (cast(getElementType())->getBitWidth()) { + default: assert(0 && "Invalid bitwidth for CDS"); + case 8: return *(uint8_t*)EltPtr; + case 16: return *(uint16_t*)EltPtr; + case 32: return *(uint32_t*)EltPtr; + case 64: return *(uint64_t*)EltPtr; + } +} + +/// getElementAsAPFloat - If this is a sequential container of floating point +/// type, return the specified element as an APFloat. +APFloat ConstantDataSequential::getElementAsAPFloat(unsigned Elt) const { + const char *EltPtr = getElementPointer(Elt); + + switch (getElementType()->getTypeID()) { + default: assert("Accessor can only be used when element is float/double!"); + case Type::FloatTyID: return APFloat(*(float*)EltPtr); + case Type::DoubleTyID: return APFloat(*(double*)EltPtr); + } +} + +/// getElementAsFloat - If this is an sequential container of floats, return +/// the specified element as a float. +float ConstantDataSequential::getElementAsFloat(unsigned Elt) const { + assert(getElementType()->isFloatTy() && + "Accessor can only be used when element is a 'float'"); + return *(float*)getElementPointer(Elt); +} + +/// getElementAsDouble - If this is an sequential container of doubles, return +/// the specified element as a float. +double ConstantDataSequential::getElementAsDouble(unsigned Elt) const { + assert(getElementType()->isDoubleTy() && + "Accessor can only be used when element is a 'float'"); + return *(double*)getElementPointer(Elt); +} + +/// getElementAsConstant - Return a Constant for a specified index's element. +/// Note that this has to compute a new constant to return, so it isn't as +/// efficient as getElementAsInteger/Float/Double. +Constant *ConstantDataSequential::getElementAsConstant(unsigned Elt) const { + if (getElementType()->isFloatTy() || getElementType()->isDoubleTy()) + return ConstantFP::get(getContext(), getElementAsAPFloat(Elt)); + + return ConstantInt::get(getElementType(), getElementAsInteger(Elt)); +} +