#include "llvm/Constant.h"
#include "llvm/Type.h"
+#include "llvm/ADT/APInt.h"
namespace llvm {
class ConstantInt : public Constant {
static ConstantInt *TheTrueVal, *TheFalseVal;
ConstantInt(const ConstantInt &); // DO NOT IMPLEMENT
- ConstantInt(const IntegerType *Ty, uint64_t V);
- uint64_t Val;
+ ConstantInt(const IntegerType *Ty, const APInt& V);
+ APInt Val;
public:
+ /// Return the constant as an APInt value reference. This allows clients to
+ /// obtain a copy of the value, with all its precision in tact.
+ /// @brief Return the constant's value.
+ inline const APInt& getValue() const {
+ return Val;
+ }
+
/// Return the constant as a 64-bit unsigned integer value after it
- /// has been zero extended as appropriate for the type of this constant.
+ /// has been zero extended as appropriate for the type of this constant. Note
+ /// that this method can assert if the value does not fit in 64 bits.
+ /// @deprecated
/// @brief Return the zero extended value.
inline uint64_t getZExtValue() const {
- return Val;
+ return Val.getZExtValue();
}
/// Return the constant as a 64-bit integer value after it has been sign
- /// sign extended as appropriate for the type of this constant.
+ /// sign extended as appropriate for the type of this constant. Note that
+ /// this method can assert if the value does not fit in 64 bits.
+ /// @deprecated
/// @brief Return the sign extended value.
inline int64_t getSExtValue() const {
- unsigned Size = Value::getType()->getPrimitiveSizeInBits();
- return (int64_t(Val) << (64-Size)) >> (64-Size);
+ return Val.getSExtValue();
}
+
/// A helper method that can be used to determine if the constant contained
/// within is equal to a constant. This only works for very small values,
/// because this is all that can be represented with all types.
/// @brief Determine if this constant's value is same as an unsigned char.
- bool equalsInt(unsigned char V) const {
- assert(V <= 127 &&
- "equalsInt: Can only be used with very small positive constants!");
+ bool equalsInt(uint64_t V) const {
return Val == V;
}
/// sized/signed value for the type Ty.
/// @brief Get a ConstantInt for a specific value.
static ConstantInt *get(const Type *Ty, int64_t V);
+ static ConstantInt *get(const Type *Ty, const APInt& V);
/// getType - Specialize the getType() method to always return an IntegerType,
/// which reduces the amount of casting needed in parts of the compiler.
/// @returns true iff this constant's bits are all set to true.
/// @brief Determine if the value is all ones.
bool isAllOnesValue() const {
- return getSExtValue() == -1;
+ return Val.isAllOnesValue();
}
/// This function will return true iff this constant represents the largest
/// by this type.
/// @brief Determine if the value is maximal.
bool isMaxValue(bool isSigned) const {
- if (isSigned) {
- int64_t V = getSExtValue();
- if (V < 0) return false; // Be careful about wrap-around on 'long's
- ++V;
- return !isValueValidForType(Value::getType(), V) || V < 0;
- }
- return isAllOnesValue();
+ if (isSigned)
+ return Val.isMaxSignedValue();
+ else
+ return Val.isMaxValue();
}
/// This function will return true iff this constant represents the smallest
/// this type.
/// @brief Determine if the value is minimal.
bool isMinValue(bool isSigned) const {
- if (isSigned) {
- int64_t V = getSExtValue();
- if (V > 0) return false; // Be careful about wrap-around on 'long's
- --V;
- return !isValueValidForType(Value::getType(), V) || V > 0;
- }
- return getZExtValue() == 0;
+ if (isSigned)
+ return Val.isMinSignedValue();
+ else
+ return Val.isMinValue();
}
/// @returns the value for an integer constant of the given type that has all
// ConstantInt
//===----------------------------------------------------------------------===//
-ConstantInt::ConstantInt(const IntegerType *Ty, uint64_t V)
+ConstantInt::ConstantInt(const IntegerType *Ty, const APInt& V)
: Constant(Ty, ConstantIntVal, 0, 0), Val(V) {
+ assert(V.getBitWidth() == Ty->getBitWidth() && "Invalid constant for type");
}
ConstantInt *ConstantInt::TheTrueVal = 0;
namespace {
- struct DenseMapInt64KeyInfo {
- typedef std::pair<uint64_t, const Type*> KeyTy;
- static inline KeyTy getEmptyKey() { return KeyTy(0, 0); }
- static inline KeyTy getTombstoneKey() { return KeyTy(1, 0); }
+ struct DenseMapAPIntKeyInfo {
+ struct KeyTy {
+ APInt val;
+ const Type* type;
+ KeyTy(const APInt& V, const Type* Ty) : val(V), type(Ty) {}
+ KeyTy(const KeyTy& that) : val(that.val), type(that.type) {}
+ bool operator==(const KeyTy& that) const {
+ return type == that.type && this->val == that.val;
+ }
+ bool operator!=(const KeyTy& that) const {
+ return !this->operator==(that);
+ }
+ };
+ static inline KeyTy getEmptyKey() { return KeyTy(APInt(1,0), 0); }
+ static inline KeyTy getTombstoneKey() { return KeyTy(APInt(1,1), 0); }
static unsigned getHashValue(const KeyTy &Key) {
- return DenseMapKeyInfo<void*>::getHashValue(Key.second) ^ Key.first;
+ return DenseMapKeyInfo<void*>::getHashValue(Key.type) ^
+ Key.val.getHashValue();
}
static bool isPod() { return true; }
};
}
-typedef DenseMap<DenseMapInt64KeyInfo::KeyTy, ConstantInt*,
- DenseMapInt64KeyInfo> IntMapTy;
+typedef DenseMap<DenseMapAPIntKeyInfo::KeyTy, ConstantInt*,
+ DenseMapAPIntKeyInfo> IntMapTy;
static ManagedStatic<IntMapTy> IntConstants;
-// Get a ConstantInt from an int64_t. Note here that we canoncialize the value
-// to a uint64_t value that has been zero extended down to the size of the
-// integer type of the ConstantInt. This allows the getZExtValue method to
-// just return the stored value while getSExtValue has to convert back to sign
-// extended. getZExtValue is more common in LLVM than getSExtValue().
ConstantInt *ConstantInt::get(const Type *Ty, int64_t V) {
const IntegerType *ITy = cast<IntegerType>(Ty);
- V &= ITy->getBitMask();
- ConstantInt *&Slot = (*IntConstants)[std::make_pair(uint64_t(V), Ty)];
- if (Slot) return Slot;
+ APInt Tmp(ITy->getBitWidth(), V);
+ return get(Ty, Tmp);
+}
+
+// Get a ConstantInt from a Type and APInt. Note that the value stored in
+// the DenseMap as the key is a DensMapAPIntKeyInfo::KeyTy which has provided
+// operator== and operator!= to ensure that the DenseMap doesn't attempt to
+// compare APInt's of different widths, which would violate an APInt class
+// invariant which generates an assertion.
+ConstantInt *ConstantInt::get(const Type *Ty, const APInt& V) {
+ const IntegerType *ITy = cast<IntegerType>(Ty);
+ assert(ITy->getBitWidth() == V.getBitWidth() && "Invalid type for constant");
+ // get an existing value or the insertion position
+ DenseMapAPIntKeyInfo::KeyTy Key(V, Ty);
+ ConstantInt *&Slot = (*IntConstants)[Key];
+ // if it exists, return it.
+ if (Slot)
+ return Slot;
+ // otherwise create a new one, insert it, and return it.
return Slot = new ConstantInt(ITy, V);
}
namespace {
+ struct DenseMapInt64KeyInfo {
+ typedef std::pair<uint64_t, const Type*> KeyTy;
+ static inline KeyTy getEmptyKey() { return KeyTy(0, 0); }
+ static inline KeyTy getTombstoneKey() { return KeyTy(1, 0); }
+ static unsigned getHashValue(const KeyTy &Key) {
+ return DenseMapKeyInfo<void*>::getHashValue(Key.second) ^ Key.first;
+ }
+ static bool isPod() { return true; }
+ };
struct DenseMapInt32KeyInfo {
typedef std::pair<uint32_t, const Type*> KeyTy;
static inline KeyTy getEmptyKey() { return KeyTy(0, 0); }