diff options
Diffstat (limited to 'clang/lib/AST/Interp/Integral.h')
-rw-r--r-- | clang/lib/AST/Interp/Integral.h | 126 |
1 files changed, 74 insertions, 52 deletions
diff --git a/clang/lib/AST/Interp/Integral.h b/clang/lib/AST/Interp/Integral.h index 46cd611ee389..8a742333ae57 100644 --- a/clang/lib/AST/Interp/Integral.h +++ b/clang/lib/AST/Interp/Integral.h @@ -53,17 +53,17 @@ template <> struct Repr<64, true> { using Type = int64_t; }; /// These wrappers are required to shared an interface between APSint and /// builtin primitive numeral types, while optimising for storage and /// allowing methods operating on primitive type to compile to fast code. -template <unsigned Bits, bool Signed> class Integral { +template <unsigned Bits, bool Signed> class Integral final { private: template <unsigned OtherBits, bool OtherSigned> friend class Integral; // The primitive representing the integral. - using T = typename Repr<Bits, Signed>::Type; - T V; + using ReprT = typename Repr<Bits, Signed>::Type; + ReprT V; /// Primitive representing limits. - static const auto Min = std::numeric_limits<T>::min(); - static const auto Max = std::numeric_limits<T>::max(); + static const auto Min = std::numeric_limits<ReprT>::min(); + static const auto Max = std::numeric_limits<ReprT>::max(); /// Construct an integral from anything that is convertible to storage. template <typename T> explicit Integral(T V) : V(V) {} @@ -107,7 +107,7 @@ public: return APSInt(APInt(Bits, static_cast<uint64_t>(V), Signed), !Signed); } APSInt toAPSInt(unsigned NumBits) const { - if (Signed) + if constexpr (Signed) return APSInt(toAPSInt().sextOrTrunc(NumBits), !Signed); else return APSInt(toAPSInt().zextOrTrunc(NumBits), !Signed); @@ -124,25 +124,27 @@ public: bool isMin() const { return *this == min(bitWidth()); } - bool isMinusOne() const { return Signed && V == T(-1); } + bool isMinusOne() const { return Signed && V == ReprT(-1); } constexpr static bool isSigned() { return Signed; } - bool isNegative() const { return V < T(0); } + bool isNegative() const { return V < ReprT(0); } bool isPositive() const { return !isNegative(); } ComparisonCategoryResult compare(const Integral &RHS) const { return Compare(V, RHS.V); } - unsigned countLeadingZeros() const { return llvm::countLeadingZeros<T>(V); } + unsigned countLeadingZeros() const { + return llvm::countLeadingZeros<ReprT>(V); + } Integral truncate(unsigned TruncBits) const { if (TruncBits >= Bits) return *this; - const T BitMask = (T(1) << T(TruncBits)) - 1; - const T SignBit = T(1) << (TruncBits - 1); - const T ExtMask = ~BitMask; + const ReprT BitMask = (ReprT(1) << ReprT(TruncBits)) - 1; + const ReprT SignBit = ReprT(1) << (TruncBits - 1); + const ReprT ExtMask = ~BitMask; return Integral((V & BitMask) | (Signed && (V & SignBit) ? ExtMask : 0)); } @@ -155,9 +157,11 @@ public: return Integral(Max); } - template <typename T> - static std::enable_if_t<std::is_integral<T>::value, Integral> from(T Value) { - return Integral(Value); + template <typename ValT> static Integral from(ValT Value) { + if constexpr (std::is_integral<ValT>::value) + return Integral(Value); + else + return Integral::from(static_cast<Integral::ReprT>(Value)); } template <unsigned SrcBits, bool SrcSign> @@ -167,7 +171,7 @@ public: } template <bool SrcSign> static Integral from(Integral<0, SrcSign> Value) { - if (SrcSign) + if constexpr (SrcSign) return Integral(Value.V.getSExtValue()); else return Integral(Value.V.getZExtValue()); @@ -180,15 +184,15 @@ public: } static bool inRange(int64_t Value, unsigned NumBits) { - return CheckRange<T, Min, Max>(Value); + return CheckRange<ReprT, Min, Max>(Value); } static bool increment(Integral A, Integral *R) { - return add(A, Integral(T(1)), A.bitWidth(), R); + return add(A, Integral(ReprT(1)), A.bitWidth(), R); } static bool decrement(Integral A, Integral *R) { - return sub(A, Integral(T(1)), A.bitWidth(), R); + return sub(A, Integral(ReprT(1)), A.bitWidth(), R); } static bool add(Integral A, Integral B, unsigned OpBits, Integral *R) { @@ -203,56 +207,74 @@ public: return CheckMulUB(A.V, B.V, R->V); } -private: - template <typename T> - static std::enable_if_t<std::is_signed<T>::value, bool> CheckAddUB(T A, T B, - T &R) { - return llvm::AddOverflow<T>(A, B, R); + static bool rem(Integral A, Integral B, unsigned OpBits, Integral *R) { + *R = Integral(A.V % B.V); + return false; + } + + static bool div(Integral A, Integral B, unsigned OpBits, Integral *R) { + *R = Integral(A.V / B.V); + return false; } - template <typename T> - static std::enable_if_t<std::is_unsigned<T>::value, bool> CheckAddUB(T A, T B, - T &R) { - R = A + B; + static bool bitAnd(Integral A, Integral B, unsigned OpBits, Integral *R) { + *R = Integral(A.V & B.V); return false; } - template <typename T> - static std::enable_if_t<std::is_signed<T>::value, bool> CheckSubUB(T A, T B, - T &R) { - return llvm::SubOverflow<T>(A, B, R); + static bool bitOr(Integral A, Integral B, unsigned OpBits, Integral *R) { + *R = Integral(A.V | B.V); + return false; } - template <typename T> - static std::enable_if_t<std::is_unsigned<T>::value, bool> CheckSubUB(T A, T B, - T &R) { - R = A - B; + static bool bitXor(Integral A, Integral B, unsigned OpBits, Integral *R) { + *R = Integral(A.V ^ B.V); return false; } - template <typename T> - static std::enable_if_t<std::is_signed<T>::value, bool> CheckMulUB(T A, T B, - T &R) { - return llvm::MulOverflow<T>(A, B, R); + static bool neg(Integral A, Integral *R) { + *R = -A; + return false; } - template <typename T> - static std::enable_if_t<std::is_unsigned<T>::value, bool> CheckMulUB(T A, T B, - T &R) { - R = A * B; + static bool comp(Integral A, Integral *R) { + *R = Integral(~A.V); return false; } - template <typename T, T Min, T Max> - static std::enable_if_t<std::is_signed<T>::value, bool> - CheckRange(int64_t V) { - return Min <= V && V <= Max; +private: + template <typename T> static bool CheckAddUB(T A, T B, T &R) { + if constexpr (std::is_signed_v<T>) { + return llvm::AddOverflow<T>(A, B, R); + } else { + R = A + B; + return false; + } } - template <typename T, T Min, T Max> - static std::enable_if_t<std::is_unsigned<T>::value, bool> - CheckRange(int64_t V) { - return V >= 0 && static_cast<uint64_t>(V) <= Max; + template <typename T> static bool CheckSubUB(T A, T B, T &R) { + if constexpr (std::is_signed_v<T>) { + return llvm::SubOverflow<T>(A, B, R); + } else { + R = A - B; + return false; + } + } + + template <typename T> static bool CheckMulUB(T A, T B, T &R) { + if constexpr (std::is_signed_v<T>) { + return llvm::MulOverflow<T>(A, B, R); + } else { + R = A * B; + return false; + } + } + template <typename T, T Min, T Max> static bool CheckRange(int64_t V) { + if constexpr (std::is_signed_v<T>) { + return Min <= V && V <= Max; + } else { + return V >= 0 && static_cast<uint64_t>(V) <= Max; + } } }; |