1*5f757f3fSDimitry Andric //===--- Integral.h - Wrapper for numeric types for the VM ------*- C++ -*-===// 2*5f757f3fSDimitry Andric // 3*5f757f3fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*5f757f3fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*5f757f3fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*5f757f3fSDimitry Andric // 7*5f757f3fSDimitry Andric //===----------------------------------------------------------------------===// 8*5f757f3fSDimitry Andric // 9*5f757f3fSDimitry Andric // Defines the VM types and helpers operating on types. 10*5f757f3fSDimitry Andric // 11*5f757f3fSDimitry Andric //===----------------------------------------------------------------------===// 12*5f757f3fSDimitry Andric 13*5f757f3fSDimitry Andric #ifndef LLVM_CLANG_AST_INTERP_INTEGRAL_AP_H 14*5f757f3fSDimitry Andric #define LLVM_CLANG_AST_INTERP_INTEGRAL_AP_H 15*5f757f3fSDimitry Andric 16*5f757f3fSDimitry Andric #include "clang/AST/APValue.h" 17*5f757f3fSDimitry Andric #include "clang/AST/ComparisonCategories.h" 18*5f757f3fSDimitry Andric #include "llvm/ADT/APSInt.h" 19*5f757f3fSDimitry Andric #include "llvm/Support/MathExtras.h" 20*5f757f3fSDimitry Andric #include "llvm/Support/raw_ostream.h" 21*5f757f3fSDimitry Andric #include <cstddef> 22*5f757f3fSDimitry Andric #include <cstdint> 23*5f757f3fSDimitry Andric 24*5f757f3fSDimitry Andric #include "Primitives.h" 25*5f757f3fSDimitry Andric 26*5f757f3fSDimitry Andric namespace clang { 27*5f757f3fSDimitry Andric namespace interp { 28*5f757f3fSDimitry Andric 29*5f757f3fSDimitry Andric using APInt = llvm::APInt; 30*5f757f3fSDimitry Andric using APSInt = llvm::APSInt; 31*5f757f3fSDimitry Andric template <unsigned Bits, bool Signed> class Integral; 32*5f757f3fSDimitry Andric 33*5f757f3fSDimitry Andric template <bool Signed> class IntegralAP final { 34*5f757f3fSDimitry Andric private: 35*5f757f3fSDimitry Andric friend IntegralAP<!Signed>; 36*5f757f3fSDimitry Andric APInt V; 37*5f757f3fSDimitry Andric 38*5f757f3fSDimitry Andric template <typename T, bool InputSigned> 39*5f757f3fSDimitry Andric static T truncateCast(const APInt &V) { 40*5f757f3fSDimitry Andric constexpr unsigned BitSize = sizeof(T) * 8; 41*5f757f3fSDimitry Andric if (BitSize >= V.getBitWidth()) { 42*5f757f3fSDimitry Andric APInt Extended; 43*5f757f3fSDimitry Andric if constexpr (InputSigned) 44*5f757f3fSDimitry Andric Extended = V.sext(BitSize); 45*5f757f3fSDimitry Andric else 46*5f757f3fSDimitry Andric Extended = V.zext(BitSize); 47*5f757f3fSDimitry Andric return std::is_signed_v<T> ? Extended.getSExtValue() 48*5f757f3fSDimitry Andric : Extended.getZExtValue(); 49*5f757f3fSDimitry Andric } 50*5f757f3fSDimitry Andric 51*5f757f3fSDimitry Andric return std::is_signed_v<T> ? V.trunc(BitSize).getSExtValue() 52*5f757f3fSDimitry Andric : V.trunc(BitSize).getZExtValue(); 53*5f757f3fSDimitry Andric } 54*5f757f3fSDimitry Andric 55*5f757f3fSDimitry Andric public: 56*5f757f3fSDimitry Andric using AsUnsigned = IntegralAP<false>; 57*5f757f3fSDimitry Andric 58*5f757f3fSDimitry Andric template <typename T> 59*5f757f3fSDimitry Andric IntegralAP(T Value, unsigned BitWidth) 60*5f757f3fSDimitry Andric : V(APInt(BitWidth, static_cast<uint64_t>(Value), Signed)) {} 61*5f757f3fSDimitry Andric 62*5f757f3fSDimitry Andric IntegralAP(APInt V) : V(V) {} 63*5f757f3fSDimitry Andric /// Arbitrary value for uninitialized variables. 64*5f757f3fSDimitry Andric IntegralAP() : IntegralAP(-1, 1024) {} 65*5f757f3fSDimitry Andric 66*5f757f3fSDimitry Andric IntegralAP operator-() const { return IntegralAP(-V); } 67*5f757f3fSDimitry Andric IntegralAP operator-(const IntegralAP &Other) const { 68*5f757f3fSDimitry Andric return IntegralAP(V - Other.V); 69*5f757f3fSDimitry Andric } 70*5f757f3fSDimitry Andric bool operator>(const IntegralAP &RHS) const { 71*5f757f3fSDimitry Andric if constexpr (Signed) 72*5f757f3fSDimitry Andric return V.ugt(RHS.V); 73*5f757f3fSDimitry Andric return V.sgt(RHS.V); 74*5f757f3fSDimitry Andric } 75*5f757f3fSDimitry Andric bool operator>=(IntegralAP RHS) const { 76*5f757f3fSDimitry Andric if constexpr (Signed) 77*5f757f3fSDimitry Andric return V.uge(RHS.V); 78*5f757f3fSDimitry Andric return V.sge(RHS.V); 79*5f757f3fSDimitry Andric } 80*5f757f3fSDimitry Andric bool operator<(IntegralAP RHS) const { 81*5f757f3fSDimitry Andric if constexpr (Signed) 82*5f757f3fSDimitry Andric return V.slt(RHS.V); 83*5f757f3fSDimitry Andric return V.slt(RHS.V); 84*5f757f3fSDimitry Andric } 85*5f757f3fSDimitry Andric bool operator<=(IntegralAP RHS) const { 86*5f757f3fSDimitry Andric if constexpr (Signed) 87*5f757f3fSDimitry Andric return V.ult(RHS.V); 88*5f757f3fSDimitry Andric return V.ult(RHS.V); 89*5f757f3fSDimitry Andric } 90*5f757f3fSDimitry Andric 91*5f757f3fSDimitry Andric template <typename Ty, typename = std::enable_if_t<std::is_integral_v<Ty>>> 92*5f757f3fSDimitry Andric explicit operator Ty() const { 93*5f757f3fSDimitry Andric return truncateCast<Ty, Signed>(V); 94*5f757f3fSDimitry Andric } 95*5f757f3fSDimitry Andric 96*5f757f3fSDimitry Andric template <typename T> static IntegralAP from(T Value, unsigned NumBits = 0) { 97*5f757f3fSDimitry Andric assert(NumBits > 0); 98*5f757f3fSDimitry Andric APInt Copy = APInt(NumBits, static_cast<uint64_t>(Value), Signed); 99*5f757f3fSDimitry Andric 100*5f757f3fSDimitry Andric return IntegralAP<Signed>(Copy); 101*5f757f3fSDimitry Andric } 102*5f757f3fSDimitry Andric 103*5f757f3fSDimitry Andric template <bool InputSigned> 104*5f757f3fSDimitry Andric static IntegralAP from(IntegralAP<InputSigned> V, unsigned NumBits = 0) { 105*5f757f3fSDimitry Andric if (NumBits == 0) 106*5f757f3fSDimitry Andric NumBits = V.bitWidth(); 107*5f757f3fSDimitry Andric 108*5f757f3fSDimitry Andric if constexpr (InputSigned) 109*5f757f3fSDimitry Andric return IntegralAP<Signed>(V.V.sextOrTrunc(NumBits)); 110*5f757f3fSDimitry Andric return IntegralAP<Signed>(V.V.zextOrTrunc(NumBits)); 111*5f757f3fSDimitry Andric } 112*5f757f3fSDimitry Andric 113*5f757f3fSDimitry Andric template <unsigned Bits, bool InputSigned> 114*5f757f3fSDimitry Andric static IntegralAP from(Integral<Bits, InputSigned> I, unsigned BitWidth) { 115*5f757f3fSDimitry Andric APInt Copy = APInt(BitWidth, static_cast<uint64_t>(I), InputSigned); 116*5f757f3fSDimitry Andric 117*5f757f3fSDimitry Andric return IntegralAP<Signed>(Copy); 118*5f757f3fSDimitry Andric } 119*5f757f3fSDimitry Andric 120*5f757f3fSDimitry Andric static IntegralAP zero(int32_t BitWidth) { 121*5f757f3fSDimitry Andric APInt V = APInt(BitWidth, 0LL, Signed); 122*5f757f3fSDimitry Andric return IntegralAP(V); 123*5f757f3fSDimitry Andric } 124*5f757f3fSDimitry Andric 125*5f757f3fSDimitry Andric constexpr unsigned bitWidth() const { return V.getBitWidth(); } 126*5f757f3fSDimitry Andric 127*5f757f3fSDimitry Andric APSInt toAPSInt(unsigned Bits = 0) const { 128*5f757f3fSDimitry Andric if (Bits == 0) 129*5f757f3fSDimitry Andric Bits = bitWidth(); 130*5f757f3fSDimitry Andric 131*5f757f3fSDimitry Andric if constexpr (Signed) 132*5f757f3fSDimitry Andric return APSInt(V.sext(Bits), !Signed); 133*5f757f3fSDimitry Andric else 134*5f757f3fSDimitry Andric return APSInt(V.zext(Bits), !Signed); 135*5f757f3fSDimitry Andric } 136*5f757f3fSDimitry Andric APValue toAPValue() const { return APValue(toAPSInt()); } 137*5f757f3fSDimitry Andric 138*5f757f3fSDimitry Andric bool isZero() const { return V.isZero(); } 139*5f757f3fSDimitry Andric bool isPositive() const { return V.isNonNegative(); } 140*5f757f3fSDimitry Andric bool isNegative() const { return !V.isNonNegative(); } 141*5f757f3fSDimitry Andric bool isMin() const { return V.isMinValue(); } 142*5f757f3fSDimitry Andric bool isMax() const { return V.isMaxValue(); } 143*5f757f3fSDimitry Andric static constexpr bool isSigned() { return Signed; } 144*5f757f3fSDimitry Andric bool isMinusOne() const { return Signed && V == -1; } 145*5f757f3fSDimitry Andric 146*5f757f3fSDimitry Andric unsigned countLeadingZeros() const { return V.countl_zero(); } 147*5f757f3fSDimitry Andric 148*5f757f3fSDimitry Andric void print(llvm::raw_ostream &OS) const { OS << V; } 149*5f757f3fSDimitry Andric std::string toDiagnosticString(const ASTContext &Ctx) const { 150*5f757f3fSDimitry Andric std::string NameStr; 151*5f757f3fSDimitry Andric llvm::raw_string_ostream OS(NameStr); 152*5f757f3fSDimitry Andric print(OS); 153*5f757f3fSDimitry Andric return NameStr; 154*5f757f3fSDimitry Andric } 155*5f757f3fSDimitry Andric 156*5f757f3fSDimitry Andric IntegralAP truncate(unsigned BitWidth) const { 157*5f757f3fSDimitry Andric return IntegralAP(V.trunc(BitWidth)); 158*5f757f3fSDimitry Andric } 159*5f757f3fSDimitry Andric 160*5f757f3fSDimitry Andric IntegralAP<false> toUnsigned() const { 161*5f757f3fSDimitry Andric APInt Copy = V; 162*5f757f3fSDimitry Andric return IntegralAP<false>(Copy); 163*5f757f3fSDimitry Andric } 164*5f757f3fSDimitry Andric 165*5f757f3fSDimitry Andric ComparisonCategoryResult compare(const IntegralAP &RHS) const { 166*5f757f3fSDimitry Andric assert(Signed == RHS.isSigned()); 167*5f757f3fSDimitry Andric assert(bitWidth() == RHS.bitWidth()); 168*5f757f3fSDimitry Andric if constexpr (Signed) { 169*5f757f3fSDimitry Andric if (V.slt(RHS.V)) 170*5f757f3fSDimitry Andric return ComparisonCategoryResult::Less; 171*5f757f3fSDimitry Andric if (V.sgt(RHS.V)) 172*5f757f3fSDimitry Andric return ComparisonCategoryResult::Greater; 173*5f757f3fSDimitry Andric return ComparisonCategoryResult::Equal; 174*5f757f3fSDimitry Andric } 175*5f757f3fSDimitry Andric 176*5f757f3fSDimitry Andric assert(!Signed); 177*5f757f3fSDimitry Andric if (V.ult(RHS.V)) 178*5f757f3fSDimitry Andric return ComparisonCategoryResult::Less; 179*5f757f3fSDimitry Andric if (V.ugt(RHS.V)) 180*5f757f3fSDimitry Andric return ComparisonCategoryResult::Greater; 181*5f757f3fSDimitry Andric return ComparisonCategoryResult::Equal; 182*5f757f3fSDimitry Andric } 183*5f757f3fSDimitry Andric 184*5f757f3fSDimitry Andric static bool increment(IntegralAP A, IntegralAP *R) { 185*5f757f3fSDimitry Andric IntegralAP<Signed> One(1, A.bitWidth()); 186*5f757f3fSDimitry Andric return add(A, One, A.bitWidth() + 1, R); 187*5f757f3fSDimitry Andric } 188*5f757f3fSDimitry Andric 189*5f757f3fSDimitry Andric static bool decrement(IntegralAP A, IntegralAP *R) { 190*5f757f3fSDimitry Andric IntegralAP<Signed> One(1, A.bitWidth()); 191*5f757f3fSDimitry Andric return sub(A, One, A.bitWidth() + 1, R); 192*5f757f3fSDimitry Andric } 193*5f757f3fSDimitry Andric 194*5f757f3fSDimitry Andric static bool add(IntegralAP A, IntegralAP B, unsigned OpBits, IntegralAP *R) { 195*5f757f3fSDimitry Andric return CheckAddSubMulUB<std::plus>(A, B, OpBits, R); 196*5f757f3fSDimitry Andric } 197*5f757f3fSDimitry Andric 198*5f757f3fSDimitry Andric static bool sub(IntegralAP A, IntegralAP B, unsigned OpBits, IntegralAP *R) { 199*5f757f3fSDimitry Andric return CheckAddSubMulUB<std::minus>(A, B, OpBits, R); 200*5f757f3fSDimitry Andric } 201*5f757f3fSDimitry Andric 202*5f757f3fSDimitry Andric static bool mul(IntegralAP A, IntegralAP B, unsigned OpBits, IntegralAP *R) { 203*5f757f3fSDimitry Andric return CheckAddSubMulUB<std::multiplies>(A, B, OpBits, R); 204*5f757f3fSDimitry Andric } 205*5f757f3fSDimitry Andric 206*5f757f3fSDimitry Andric static bool rem(IntegralAP A, IntegralAP B, unsigned OpBits, IntegralAP *R) { 207*5f757f3fSDimitry Andric // FIXME: Implement. 208*5f757f3fSDimitry Andric assert(false); 209*5f757f3fSDimitry Andric return false; 210*5f757f3fSDimitry Andric } 211*5f757f3fSDimitry Andric 212*5f757f3fSDimitry Andric static bool div(IntegralAP A, IntegralAP B, unsigned OpBits, IntegralAP *R) { 213*5f757f3fSDimitry Andric // FIXME: Implement. 214*5f757f3fSDimitry Andric assert(false); 215*5f757f3fSDimitry Andric return false; 216*5f757f3fSDimitry Andric } 217*5f757f3fSDimitry Andric 218*5f757f3fSDimitry Andric static bool bitAnd(IntegralAP A, IntegralAP B, unsigned OpBits, 219*5f757f3fSDimitry Andric IntegralAP *R) { 220*5f757f3fSDimitry Andric *R = IntegralAP(A.V & B.V); 221*5f757f3fSDimitry Andric return false; 222*5f757f3fSDimitry Andric } 223*5f757f3fSDimitry Andric 224*5f757f3fSDimitry Andric static bool bitOr(IntegralAP A, IntegralAP B, unsigned OpBits, 225*5f757f3fSDimitry Andric IntegralAP *R) { 226*5f757f3fSDimitry Andric *R = IntegralAP(A.V | B.V); 227*5f757f3fSDimitry Andric return false; 228*5f757f3fSDimitry Andric } 229*5f757f3fSDimitry Andric 230*5f757f3fSDimitry Andric static bool bitXor(IntegralAP A, IntegralAP B, unsigned OpBits, 231*5f757f3fSDimitry Andric IntegralAP *R) { 232*5f757f3fSDimitry Andric *R = IntegralAP(A.V ^ B.V); 233*5f757f3fSDimitry Andric return false; 234*5f757f3fSDimitry Andric } 235*5f757f3fSDimitry Andric 236*5f757f3fSDimitry Andric static bool neg(const IntegralAP &A, IntegralAP *R) { 237*5f757f3fSDimitry Andric APInt AI = A.V; 238*5f757f3fSDimitry Andric AI.negate(); 239*5f757f3fSDimitry Andric *R = IntegralAP(AI); 240*5f757f3fSDimitry Andric return false; 241*5f757f3fSDimitry Andric } 242*5f757f3fSDimitry Andric 243*5f757f3fSDimitry Andric static bool comp(IntegralAP A, IntegralAP *R) { 244*5f757f3fSDimitry Andric *R = IntegralAP(~A.V); 245*5f757f3fSDimitry Andric return false; 246*5f757f3fSDimitry Andric } 247*5f757f3fSDimitry Andric 248*5f757f3fSDimitry Andric static void shiftLeft(const IntegralAP A, const IntegralAP B, unsigned OpBits, 249*5f757f3fSDimitry Andric IntegralAP *R) { 250*5f757f3fSDimitry Andric *R = IntegralAP(A.V.shl(B.V.getZExtValue())); 251*5f757f3fSDimitry Andric } 252*5f757f3fSDimitry Andric 253*5f757f3fSDimitry Andric static void shiftRight(const IntegralAP A, const IntegralAP B, 254*5f757f3fSDimitry Andric unsigned OpBits, IntegralAP *R) { 255*5f757f3fSDimitry Andric unsigned ShiftAmount = B.V.getZExtValue(); 256*5f757f3fSDimitry Andric if constexpr (Signed) 257*5f757f3fSDimitry Andric *R = IntegralAP(A.V.ashr(ShiftAmount)); 258*5f757f3fSDimitry Andric else 259*5f757f3fSDimitry Andric *R = IntegralAP(A.V.lshr(ShiftAmount)); 260*5f757f3fSDimitry Andric } 261*5f757f3fSDimitry Andric 262*5f757f3fSDimitry Andric private: 263*5f757f3fSDimitry Andric template <template <typename T> class Op> 264*5f757f3fSDimitry Andric static bool CheckAddSubMulUB(const IntegralAP &A, const IntegralAP &B, 265*5f757f3fSDimitry Andric unsigned BitWidth, IntegralAP *R) { 266*5f757f3fSDimitry Andric if constexpr (!Signed) { 267*5f757f3fSDimitry Andric R->V = Op<APInt>{}(A.V, B.V); 268*5f757f3fSDimitry Andric return false; 269*5f757f3fSDimitry Andric } 270*5f757f3fSDimitry Andric 271*5f757f3fSDimitry Andric const APSInt &LHS = A.toAPSInt(); 272*5f757f3fSDimitry Andric const APSInt &RHS = B.toAPSInt(); 273*5f757f3fSDimitry Andric APSInt Value = Op<APSInt>{}(LHS.extend(BitWidth), RHS.extend(BitWidth)); 274*5f757f3fSDimitry Andric APSInt Result = Value.trunc(LHS.getBitWidth()); 275*5f757f3fSDimitry Andric R->V = Result; 276*5f757f3fSDimitry Andric 277*5f757f3fSDimitry Andric return Result.extend(BitWidth) != Value; 278*5f757f3fSDimitry Andric } 279*5f757f3fSDimitry Andric }; 280*5f757f3fSDimitry Andric 281*5f757f3fSDimitry Andric template <bool Signed> 282*5f757f3fSDimitry Andric inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, 283*5f757f3fSDimitry Andric IntegralAP<Signed> I) { 284*5f757f3fSDimitry Andric I.print(OS); 285*5f757f3fSDimitry Andric return OS; 286*5f757f3fSDimitry Andric } 287*5f757f3fSDimitry Andric 288*5f757f3fSDimitry Andric } // namespace interp 289*5f757f3fSDimitry Andric } // namespace clang 290*5f757f3fSDimitry Andric 291*5f757f3fSDimitry Andric #endif 292