1*700637cbSDimitry Andric //===--- Integral.h - Wrapper for numeric types for the VM ------*- C++ -*-===// 2*700637cbSDimitry Andric // 3*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*700637cbSDimitry Andric // 7*700637cbSDimitry Andric //===----------------------------------------------------------------------===// 8*700637cbSDimitry Andric // 9*700637cbSDimitry Andric // Defines the VM types and helpers operating on types. 10*700637cbSDimitry Andric // 11*700637cbSDimitry Andric //===----------------------------------------------------------------------===// 12*700637cbSDimitry Andric 13*700637cbSDimitry Andric #ifndef LLVM_CLANG_AST_INTERP_INTEGRAL_H 14*700637cbSDimitry Andric #define LLVM_CLANG_AST_INTERP_INTEGRAL_H 15*700637cbSDimitry Andric 16*700637cbSDimitry Andric #include "clang/AST/APValue.h" 17*700637cbSDimitry Andric #include "clang/AST/ComparisonCategories.h" 18*700637cbSDimitry Andric #include "llvm/ADT/APSInt.h" 19*700637cbSDimitry Andric #include "llvm/Support/MathExtras.h" 20*700637cbSDimitry Andric #include "llvm/Support/raw_ostream.h" 21*700637cbSDimitry Andric #include <cstddef> 22*700637cbSDimitry Andric #include <cstdint> 23*700637cbSDimitry Andric 24*700637cbSDimitry Andric #include "Primitives.h" 25*700637cbSDimitry Andric 26*700637cbSDimitry Andric namespace clang { 27*700637cbSDimitry Andric namespace interp { 28*700637cbSDimitry Andric 29*700637cbSDimitry Andric using APInt = llvm::APInt; 30*700637cbSDimitry Andric using APSInt = llvm::APSInt; 31*700637cbSDimitry Andric 32*700637cbSDimitry Andric template <bool Signed> class IntegralAP; 33*700637cbSDimitry Andric 34*700637cbSDimitry Andric // Helper structure to select the representation. 35*700637cbSDimitry Andric template <unsigned Bits, bool Signed> struct Repr; 36*700637cbSDimitry Andric template <> struct Repr<8, false> { 37*700637cbSDimitry Andric using Type = uint8_t; 38*700637cbSDimitry Andric }; 39*700637cbSDimitry Andric template <> struct Repr<16, false> { 40*700637cbSDimitry Andric using Type = uint16_t; 41*700637cbSDimitry Andric }; 42*700637cbSDimitry Andric template <> struct Repr<32, false> { 43*700637cbSDimitry Andric using Type = uint32_t; 44*700637cbSDimitry Andric }; 45*700637cbSDimitry Andric template <> struct Repr<64, false> { 46*700637cbSDimitry Andric using Type = uint64_t; 47*700637cbSDimitry Andric }; 48*700637cbSDimitry Andric template <> struct Repr<8, true> { 49*700637cbSDimitry Andric using Type = int8_t; 50*700637cbSDimitry Andric }; 51*700637cbSDimitry Andric template <> struct Repr<16, true> { 52*700637cbSDimitry Andric using Type = int16_t; 53*700637cbSDimitry Andric }; 54*700637cbSDimitry Andric template <> struct Repr<32, true> { 55*700637cbSDimitry Andric using Type = int32_t; 56*700637cbSDimitry Andric }; 57*700637cbSDimitry Andric template <> struct Repr<64, true> { 58*700637cbSDimitry Andric using Type = int64_t; 59*700637cbSDimitry Andric }; 60*700637cbSDimitry Andric 61*700637cbSDimitry Andric /// Wrapper around numeric types. 62*700637cbSDimitry Andric /// 63*700637cbSDimitry Andric /// These wrappers are required to shared an interface between APSint and 64*700637cbSDimitry Andric /// builtin primitive numeral types, while optimising for storage and 65*700637cbSDimitry Andric /// allowing methods operating on primitive type to compile to fast code. 66*700637cbSDimitry Andric template <unsigned Bits, bool Signed> class Integral final { 67*700637cbSDimitry Andric private: 68*700637cbSDimitry Andric template <unsigned OtherBits, bool OtherSigned> friend class Integral; 69*700637cbSDimitry Andric 70*700637cbSDimitry Andric // The primitive representing the integral. 71*700637cbSDimitry Andric using ReprT = typename Repr<Bits, Signed>::Type; 72*700637cbSDimitry Andric ReprT V; 73*700637cbSDimitry Andric static_assert(std::is_trivially_copyable_v<ReprT>); 74*700637cbSDimitry Andric 75*700637cbSDimitry Andric /// Primitive representing limits. 76*700637cbSDimitry Andric static const auto Min = std::numeric_limits<ReprT>::min(); 77*700637cbSDimitry Andric static const auto Max = std::numeric_limits<ReprT>::max(); 78*700637cbSDimitry Andric 79*700637cbSDimitry Andric /// Construct an integral from anything that is convertible to storage. 80*700637cbSDimitry Andric template <typename T> explicit Integral(T V) : V(V) {} 81*700637cbSDimitry Andric 82*700637cbSDimitry Andric public: 83*700637cbSDimitry Andric using AsUnsigned = Integral<Bits, false>; 84*700637cbSDimitry Andric 85*700637cbSDimitry Andric /// Zero-initializes an integral. 86*700637cbSDimitry Andric Integral() : V(0) {} 87*700637cbSDimitry Andric 88*700637cbSDimitry Andric /// Constructs an integral from another integral. 89*700637cbSDimitry Andric template <unsigned SrcBits, bool SrcSign> 90*700637cbSDimitry Andric explicit Integral(Integral<SrcBits, SrcSign> V) : V(V.V) {} 91*700637cbSDimitry Andric 92*700637cbSDimitry Andric /// Construct an integral from a value based on signedness. 93*700637cbSDimitry Andric explicit Integral(const APSInt &V) 94*700637cbSDimitry Andric : V(V.isSigned() ? V.getSExtValue() : V.getZExtValue()) {} 95*700637cbSDimitry Andric 96*700637cbSDimitry Andric bool operator<(Integral RHS) const { return V < RHS.V; } 97*700637cbSDimitry Andric bool operator>(Integral RHS) const { return V > RHS.V; } 98*700637cbSDimitry Andric bool operator<=(Integral RHS) const { return V <= RHS.V; } 99*700637cbSDimitry Andric bool operator>=(Integral RHS) const { return V >= RHS.V; } 100*700637cbSDimitry Andric bool operator==(Integral RHS) const { return V == RHS.V; } 101*700637cbSDimitry Andric bool operator!=(Integral RHS) const { return V != RHS.V; } 102*700637cbSDimitry Andric bool operator>=(unsigned RHS) const { 103*700637cbSDimitry Andric return static_cast<unsigned>(V) >= RHS; 104*700637cbSDimitry Andric } 105*700637cbSDimitry Andric 106*700637cbSDimitry Andric bool operator>(unsigned RHS) const { 107*700637cbSDimitry Andric return V >= 0 && static_cast<unsigned>(V) > RHS; 108*700637cbSDimitry Andric } 109*700637cbSDimitry Andric 110*700637cbSDimitry Andric Integral operator-() const { return Integral(-V); } 111*700637cbSDimitry Andric Integral operator-(const Integral &Other) const { 112*700637cbSDimitry Andric return Integral(V - Other.V); 113*700637cbSDimitry Andric } 114*700637cbSDimitry Andric Integral operator~() const { return Integral(~V); } 115*700637cbSDimitry Andric 116*700637cbSDimitry Andric template <unsigned DstBits, bool DstSign> 117*700637cbSDimitry Andric explicit operator Integral<DstBits, DstSign>() const { 118*700637cbSDimitry Andric return Integral<DstBits, DstSign>(V); 119*700637cbSDimitry Andric } 120*700637cbSDimitry Andric 121*700637cbSDimitry Andric template <typename Ty, typename = std::enable_if_t<std::is_integral_v<Ty>>> 122*700637cbSDimitry Andric explicit operator Ty() const { 123*700637cbSDimitry Andric return V; 124*700637cbSDimitry Andric } 125*700637cbSDimitry Andric 126*700637cbSDimitry Andric APSInt toAPSInt() const { 127*700637cbSDimitry Andric return APSInt(APInt(Bits, static_cast<uint64_t>(V), Signed), !Signed); 128*700637cbSDimitry Andric } 129*700637cbSDimitry Andric APSInt toAPSInt(unsigned BitWidth) const { 130*700637cbSDimitry Andric return APSInt(toAPInt(BitWidth), !Signed); 131*700637cbSDimitry Andric } 132*700637cbSDimitry Andric APInt toAPInt(unsigned BitWidth) const { 133*700637cbSDimitry Andric if constexpr (Signed) 134*700637cbSDimitry Andric return APInt(Bits, static_cast<uint64_t>(V), Signed) 135*700637cbSDimitry Andric .sextOrTrunc(BitWidth); 136*700637cbSDimitry Andric else 137*700637cbSDimitry Andric return APInt(Bits, static_cast<uint64_t>(V), Signed) 138*700637cbSDimitry Andric .zextOrTrunc(BitWidth); 139*700637cbSDimitry Andric } 140*700637cbSDimitry Andric APValue toAPValue(const ASTContext &) const { return APValue(toAPSInt()); } 141*700637cbSDimitry Andric 142*700637cbSDimitry Andric Integral<Bits, false> toUnsigned() const { 143*700637cbSDimitry Andric return Integral<Bits, false>(*this); 144*700637cbSDimitry Andric } 145*700637cbSDimitry Andric 146*700637cbSDimitry Andric constexpr static unsigned bitWidth() { return Bits; } 147*700637cbSDimitry Andric 148*700637cbSDimitry Andric bool isZero() const { return !V; } 149*700637cbSDimitry Andric 150*700637cbSDimitry Andric bool isMin() const { return *this == min(bitWidth()); } 151*700637cbSDimitry Andric 152*700637cbSDimitry Andric bool isMinusOne() const { return Signed && V == ReprT(-1); } 153*700637cbSDimitry Andric 154*700637cbSDimitry Andric constexpr static bool isSigned() { return Signed; } 155*700637cbSDimitry Andric 156*700637cbSDimitry Andric bool isNegative() const { return V < ReprT(0); } 157*700637cbSDimitry Andric bool isPositive() const { return !isNegative(); } 158*700637cbSDimitry Andric 159*700637cbSDimitry Andric ComparisonCategoryResult compare(const Integral &RHS) const { 160*700637cbSDimitry Andric return Compare(V, RHS.V); 161*700637cbSDimitry Andric } 162*700637cbSDimitry Andric 163*700637cbSDimitry Andric void bitcastToMemory(std::byte *Dest) const { 164*700637cbSDimitry Andric std::memcpy(Dest, &V, sizeof(V)); 165*700637cbSDimitry Andric } 166*700637cbSDimitry Andric 167*700637cbSDimitry Andric static Integral bitcastFromMemory(const std::byte *Src, unsigned BitWidth) { 168*700637cbSDimitry Andric assert(BitWidth == sizeof(ReprT) * 8); 169*700637cbSDimitry Andric ReprT V; 170*700637cbSDimitry Andric 171*700637cbSDimitry Andric std::memcpy(&V, Src, sizeof(ReprT)); 172*700637cbSDimitry Andric return Integral(V); 173*700637cbSDimitry Andric } 174*700637cbSDimitry Andric 175*700637cbSDimitry Andric std::string toDiagnosticString(const ASTContext &Ctx) const { 176*700637cbSDimitry Andric std::string NameStr; 177*700637cbSDimitry Andric llvm::raw_string_ostream OS(NameStr); 178*700637cbSDimitry Andric OS << V; 179*700637cbSDimitry Andric return NameStr; 180*700637cbSDimitry Andric } 181*700637cbSDimitry Andric 182*700637cbSDimitry Andric unsigned countLeadingZeros() const { 183*700637cbSDimitry Andric if constexpr (!Signed) 184*700637cbSDimitry Andric return llvm::countl_zero<ReprT>(V); 185*700637cbSDimitry Andric if (isPositive()) 186*700637cbSDimitry Andric return llvm::countl_zero<typename AsUnsigned::ReprT>( 187*700637cbSDimitry Andric static_cast<typename AsUnsigned::ReprT>(V)); 188*700637cbSDimitry Andric llvm_unreachable("Don't call countLeadingZeros() on negative values."); 189*700637cbSDimitry Andric } 190*700637cbSDimitry Andric 191*700637cbSDimitry Andric Integral truncate(unsigned TruncBits) const { 192*700637cbSDimitry Andric assert(TruncBits >= 1); 193*700637cbSDimitry Andric if (TruncBits >= Bits) 194*700637cbSDimitry Andric return *this; 195*700637cbSDimitry Andric const ReprT BitMask = (ReprT(1) << ReprT(TruncBits)) - 1; 196*700637cbSDimitry Andric const ReprT SignBit = ReprT(1) << (TruncBits - 1); 197*700637cbSDimitry Andric const ReprT ExtMask = ~BitMask; 198*700637cbSDimitry Andric return Integral((V & BitMask) | (Signed && (V & SignBit) ? ExtMask : 0)); 199*700637cbSDimitry Andric } 200*700637cbSDimitry Andric 201*700637cbSDimitry Andric void print(llvm::raw_ostream &OS) const { OS << V; } 202*700637cbSDimitry Andric 203*700637cbSDimitry Andric static Integral min(unsigned NumBits) { return Integral(Min); } 204*700637cbSDimitry Andric static Integral max(unsigned NumBits) { return Integral(Max); } 205*700637cbSDimitry Andric 206*700637cbSDimitry Andric template <typename ValT> static Integral from(ValT Value) { 207*700637cbSDimitry Andric if constexpr (std::is_integral<ValT>::value) 208*700637cbSDimitry Andric return Integral(Value); 209*700637cbSDimitry Andric else 210*700637cbSDimitry Andric return Integral::from(static_cast<Integral::ReprT>(Value)); 211*700637cbSDimitry Andric } 212*700637cbSDimitry Andric 213*700637cbSDimitry Andric template <unsigned SrcBits, bool SrcSign> 214*700637cbSDimitry Andric static std::enable_if_t<SrcBits != 0, Integral> 215*700637cbSDimitry Andric from(Integral<SrcBits, SrcSign> Value) { 216*700637cbSDimitry Andric return Integral(Value.V); 217*700637cbSDimitry Andric } 218*700637cbSDimitry Andric 219*700637cbSDimitry Andric static Integral zero(unsigned BitWidth = 0) { return from(0); } 220*700637cbSDimitry Andric 221*700637cbSDimitry Andric template <typename T> static Integral from(T Value, unsigned NumBits) { 222*700637cbSDimitry Andric return Integral(Value); 223*700637cbSDimitry Andric } 224*700637cbSDimitry Andric 225*700637cbSDimitry Andric static bool inRange(int64_t Value, unsigned NumBits) { 226*700637cbSDimitry Andric return CheckRange<ReprT, Min, Max>(Value); 227*700637cbSDimitry Andric } 228*700637cbSDimitry Andric 229*700637cbSDimitry Andric static bool increment(Integral A, Integral *R) { 230*700637cbSDimitry Andric return add(A, Integral(ReprT(1)), A.bitWidth(), R); 231*700637cbSDimitry Andric } 232*700637cbSDimitry Andric 233*700637cbSDimitry Andric static bool decrement(Integral A, Integral *R) { 234*700637cbSDimitry Andric return sub(A, Integral(ReprT(1)), A.bitWidth(), R); 235*700637cbSDimitry Andric } 236*700637cbSDimitry Andric 237*700637cbSDimitry Andric static bool add(Integral A, Integral B, unsigned OpBits, Integral *R) { 238*700637cbSDimitry Andric return CheckAddUB(A.V, B.V, R->V); 239*700637cbSDimitry Andric } 240*700637cbSDimitry Andric 241*700637cbSDimitry Andric static bool sub(Integral A, Integral B, unsigned OpBits, Integral *R) { 242*700637cbSDimitry Andric return CheckSubUB(A.V, B.V, R->V); 243*700637cbSDimitry Andric } 244*700637cbSDimitry Andric 245*700637cbSDimitry Andric static bool mul(Integral A, Integral B, unsigned OpBits, Integral *R) { 246*700637cbSDimitry Andric return CheckMulUB(A.V, B.V, R->V); 247*700637cbSDimitry Andric } 248*700637cbSDimitry Andric 249*700637cbSDimitry Andric static bool rem(Integral A, Integral B, unsigned OpBits, Integral *R) { 250*700637cbSDimitry Andric *R = Integral(A.V % B.V); 251*700637cbSDimitry Andric return false; 252*700637cbSDimitry Andric } 253*700637cbSDimitry Andric 254*700637cbSDimitry Andric static bool div(Integral A, Integral B, unsigned OpBits, Integral *R) { 255*700637cbSDimitry Andric *R = Integral(A.V / B.V); 256*700637cbSDimitry Andric return false; 257*700637cbSDimitry Andric } 258*700637cbSDimitry Andric 259*700637cbSDimitry Andric static bool bitAnd(Integral A, Integral B, unsigned OpBits, Integral *R) { 260*700637cbSDimitry Andric *R = Integral(A.V & B.V); 261*700637cbSDimitry Andric return false; 262*700637cbSDimitry Andric } 263*700637cbSDimitry Andric 264*700637cbSDimitry Andric static bool bitOr(Integral A, Integral B, unsigned OpBits, Integral *R) { 265*700637cbSDimitry Andric *R = Integral(A.V | B.V); 266*700637cbSDimitry Andric return false; 267*700637cbSDimitry Andric } 268*700637cbSDimitry Andric 269*700637cbSDimitry Andric static bool bitXor(Integral A, Integral B, unsigned OpBits, Integral *R) { 270*700637cbSDimitry Andric *R = Integral(A.V ^ B.V); 271*700637cbSDimitry Andric return false; 272*700637cbSDimitry Andric } 273*700637cbSDimitry Andric 274*700637cbSDimitry Andric static bool neg(Integral A, Integral *R) { 275*700637cbSDimitry Andric if (Signed && A.isMin()) 276*700637cbSDimitry Andric return true; 277*700637cbSDimitry Andric 278*700637cbSDimitry Andric *R = -A; 279*700637cbSDimitry Andric return false; 280*700637cbSDimitry Andric } 281*700637cbSDimitry Andric 282*700637cbSDimitry Andric static bool comp(Integral A, Integral *R) { 283*700637cbSDimitry Andric *R = Integral(~A.V); 284*700637cbSDimitry Andric return false; 285*700637cbSDimitry Andric } 286*700637cbSDimitry Andric 287*700637cbSDimitry Andric template <unsigned RHSBits, bool RHSSign> 288*700637cbSDimitry Andric static void shiftLeft(const Integral A, const Integral<RHSBits, RHSSign> B, 289*700637cbSDimitry Andric unsigned OpBits, Integral *R) { 290*700637cbSDimitry Andric *R = Integral::from(A.V << B.V, OpBits); 291*700637cbSDimitry Andric } 292*700637cbSDimitry Andric 293*700637cbSDimitry Andric template <unsigned RHSBits, bool RHSSign> 294*700637cbSDimitry Andric static void shiftRight(const Integral A, const Integral<RHSBits, RHSSign> B, 295*700637cbSDimitry Andric unsigned OpBits, Integral *R) { 296*700637cbSDimitry Andric *R = Integral::from(A.V >> B.V, OpBits); 297*700637cbSDimitry Andric } 298*700637cbSDimitry Andric 299*700637cbSDimitry Andric private: 300*700637cbSDimitry Andric template <typename T> static bool CheckAddUB(T A, T B, T &R) { 301*700637cbSDimitry Andric if constexpr (std::is_signed_v<T>) { 302*700637cbSDimitry Andric return llvm::AddOverflow<T>(A, B, R); 303*700637cbSDimitry Andric } else { 304*700637cbSDimitry Andric R = A + B; 305*700637cbSDimitry Andric return false; 306*700637cbSDimitry Andric } 307*700637cbSDimitry Andric } 308*700637cbSDimitry Andric 309*700637cbSDimitry Andric template <typename T> static bool CheckSubUB(T A, T B, T &R) { 310*700637cbSDimitry Andric if constexpr (std::is_signed_v<T>) { 311*700637cbSDimitry Andric return llvm::SubOverflow<T>(A, B, R); 312*700637cbSDimitry Andric } else { 313*700637cbSDimitry Andric R = A - B; 314*700637cbSDimitry Andric return false; 315*700637cbSDimitry Andric } 316*700637cbSDimitry Andric } 317*700637cbSDimitry Andric 318*700637cbSDimitry Andric template <typename T> static bool CheckMulUB(T A, T B, T &R) { 319*700637cbSDimitry Andric if constexpr (std::is_signed_v<T>) { 320*700637cbSDimitry Andric return llvm::MulOverflow<T>(A, B, R); 321*700637cbSDimitry Andric } else { 322*700637cbSDimitry Andric R = A * B; 323*700637cbSDimitry Andric return false; 324*700637cbSDimitry Andric } 325*700637cbSDimitry Andric } 326*700637cbSDimitry Andric template <typename T, T Min, T Max> static bool CheckRange(int64_t V) { 327*700637cbSDimitry Andric if constexpr (std::is_signed_v<T>) { 328*700637cbSDimitry Andric return Min <= V && V <= Max; 329*700637cbSDimitry Andric } else { 330*700637cbSDimitry Andric return V >= 0 && static_cast<uint64_t>(V) <= Max; 331*700637cbSDimitry Andric } 332*700637cbSDimitry Andric } 333*700637cbSDimitry Andric }; 334*700637cbSDimitry Andric 335*700637cbSDimitry Andric template <unsigned Bits, bool Signed> 336*700637cbSDimitry Andric llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, Integral<Bits, Signed> I) { 337*700637cbSDimitry Andric I.print(OS); 338*700637cbSDimitry Andric return OS; 339*700637cbSDimitry Andric } 340*700637cbSDimitry Andric 341*700637cbSDimitry Andric } // namespace interp 342*700637cbSDimitry Andric } // namespace clang 343*700637cbSDimitry Andric 344*700637cbSDimitry Andric #endif 345