1*06c3fb27SDimitry Andric //===--- Floating.h - Types for the constexpr VM ----------------*- C++ -*-===// 2*06c3fb27SDimitry Andric // 3*06c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*06c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*06c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*06c3fb27SDimitry Andric // 7*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 8*06c3fb27SDimitry Andric // 9*06c3fb27SDimitry Andric // Defines the VM types and helpers operating on types. 10*06c3fb27SDimitry Andric // 11*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 12*06c3fb27SDimitry Andric 13*06c3fb27SDimitry Andric #ifndef LLVM_CLANG_AST_INTERP_FLOATING_H 14*06c3fb27SDimitry Andric #define LLVM_CLANG_AST_INTERP_FLOATING_H 15*06c3fb27SDimitry Andric 16*06c3fb27SDimitry Andric #include "Primitives.h" 17*06c3fb27SDimitry Andric #include "clang/AST/APValue.h" 18*06c3fb27SDimitry Andric #include "llvm/ADT/APFloat.h" 19*06c3fb27SDimitry Andric 20*06c3fb27SDimitry Andric namespace clang { 21*06c3fb27SDimitry Andric namespace interp { 22*06c3fb27SDimitry Andric 23*06c3fb27SDimitry Andric using APFloat = llvm::APFloat; 24*06c3fb27SDimitry Andric using APSInt = llvm::APSInt; 25*06c3fb27SDimitry Andric 26*06c3fb27SDimitry Andric class Floating final { 27*06c3fb27SDimitry Andric private: 28*06c3fb27SDimitry Andric // The underlying value storage. 29*06c3fb27SDimitry Andric APFloat F; 30*06c3fb27SDimitry Andric 31*06c3fb27SDimitry Andric public: 32*06c3fb27SDimitry Andric /// Zero-initializes a Floating. 33*06c3fb27SDimitry Andric Floating() : F(0.0f) {} 34*06c3fb27SDimitry Andric Floating(const APFloat &F) : F(F) {} 35*06c3fb27SDimitry Andric 36*06c3fb27SDimitry Andric // Static constructors for special floating point values. 37*06c3fb27SDimitry Andric static Floating getInf(const llvm::fltSemantics &Sem) { 38*06c3fb27SDimitry Andric return Floating(APFloat::getInf(Sem)); 39*06c3fb27SDimitry Andric } 40*06c3fb27SDimitry Andric const APFloat &getAPFloat() const { return F; } 41*06c3fb27SDimitry Andric 42*06c3fb27SDimitry Andric bool operator<(Floating RHS) const { return F < RHS.F; } 43*06c3fb27SDimitry Andric bool operator>(Floating RHS) const { return F > RHS.F; } 44*06c3fb27SDimitry Andric bool operator<=(Floating RHS) const { return F <= RHS.F; } 45*06c3fb27SDimitry Andric bool operator>=(Floating RHS) const { return F >= RHS.F; } 46*06c3fb27SDimitry Andric bool operator==(Floating RHS) const { return F == RHS.F; } 47*06c3fb27SDimitry Andric bool operator!=(Floating RHS) const { return F != RHS.F; } 48*06c3fb27SDimitry Andric Floating operator-() const { return Floating(-F); } 49*06c3fb27SDimitry Andric 50*06c3fb27SDimitry Andric APFloat::opStatus convertToInteger(APSInt &Result) const { 51*06c3fb27SDimitry Andric bool IsExact; 52*06c3fb27SDimitry Andric return F.convertToInteger(Result, llvm::APFloat::rmTowardZero, &IsExact); 53*06c3fb27SDimitry Andric } 54*06c3fb27SDimitry Andric 55*06c3fb27SDimitry Andric Floating toSemantics(const llvm::fltSemantics *Sem, 56*06c3fb27SDimitry Andric llvm::RoundingMode RM) const { 57*06c3fb27SDimitry Andric APFloat Copy = F; 58*06c3fb27SDimitry Andric bool LosesInfo; 59*06c3fb27SDimitry Andric Copy.convert(*Sem, RM, &LosesInfo); 60*06c3fb27SDimitry Andric (void)LosesInfo; 61*06c3fb27SDimitry Andric return Floating(Copy); 62*06c3fb27SDimitry Andric } 63*06c3fb27SDimitry Andric 64*06c3fb27SDimitry Andric /// Convert this Floating to one with the same semantics as \Other. 65*06c3fb27SDimitry Andric Floating toSemantics(const Floating &Other, llvm::RoundingMode RM) const { 66*06c3fb27SDimitry Andric return toSemantics(&Other.F.getSemantics(), RM); 67*06c3fb27SDimitry Andric } 68*06c3fb27SDimitry Andric 69*06c3fb27SDimitry Andric APSInt toAPSInt(unsigned NumBits = 0) const { 70*06c3fb27SDimitry Andric return APSInt(F.bitcastToAPInt()); 71*06c3fb27SDimitry Andric } 72*06c3fb27SDimitry Andric APValue toAPValue() const { return APValue(F); } 73*06c3fb27SDimitry Andric void print(llvm::raw_ostream &OS) const { 74*06c3fb27SDimitry Andric // Can't use APFloat::print() since it appends a newline. 75*06c3fb27SDimitry Andric SmallVector<char, 16> Buffer; 76*06c3fb27SDimitry Andric F.toString(Buffer); 77*06c3fb27SDimitry Andric OS << Buffer; 78*06c3fb27SDimitry Andric } 79*06c3fb27SDimitry Andric 80*06c3fb27SDimitry Andric unsigned bitWidth() const { return F.semanticsSizeInBits(F.getSemantics()); } 81*06c3fb27SDimitry Andric 82*06c3fb27SDimitry Andric bool isSigned() const { return true; } 83*06c3fb27SDimitry Andric bool isNegative() const { return F.isNegative(); } 84*06c3fb27SDimitry Andric bool isPositive() const { return !F.isNegative(); } 85*06c3fb27SDimitry Andric bool isZero() const { return F.isZero(); } 86*06c3fb27SDimitry Andric bool isNonZero() const { return F.isNonZero(); } 87*06c3fb27SDimitry Andric bool isMin() const { return F.isSmallest(); } 88*06c3fb27SDimitry Andric bool isMinusOne() const { return F.isExactlyValue(-1.0); } 89*06c3fb27SDimitry Andric bool isNan() const { return F.isNaN(); } 90*06c3fb27SDimitry Andric bool isFinite() const { return F.isFinite(); } 91*06c3fb27SDimitry Andric 92*06c3fb27SDimitry Andric ComparisonCategoryResult compare(const Floating &RHS) const { 93*06c3fb27SDimitry Andric return Compare(F, RHS.F); 94*06c3fb27SDimitry Andric } 95*06c3fb27SDimitry Andric 96*06c3fb27SDimitry Andric static APFloat::opStatus fromIntegral(APSInt Val, 97*06c3fb27SDimitry Andric const llvm::fltSemantics &Sem, 98*06c3fb27SDimitry Andric llvm::RoundingMode RM, 99*06c3fb27SDimitry Andric Floating &Result) { 100*06c3fb27SDimitry Andric APFloat F = APFloat(Sem); 101*06c3fb27SDimitry Andric APFloat::opStatus Status = F.convertFromAPInt(Val, Val.isSigned(), RM); 102*06c3fb27SDimitry Andric Result = Floating(F); 103*06c3fb27SDimitry Andric return Status; 104*06c3fb27SDimitry Andric } 105*06c3fb27SDimitry Andric 106*06c3fb27SDimitry Andric // ------- 107*06c3fb27SDimitry Andric 108*06c3fb27SDimitry Andric static APFloat::opStatus add(const Floating &A, const Floating &B, 109*06c3fb27SDimitry Andric llvm::RoundingMode RM, Floating *R) { 110*06c3fb27SDimitry Andric *R = Floating(A.F); 111*06c3fb27SDimitry Andric return R->F.add(B.F, RM); 112*06c3fb27SDimitry Andric } 113*06c3fb27SDimitry Andric 114*06c3fb27SDimitry Andric static APFloat::opStatus increment(const Floating &A, llvm::RoundingMode RM, 115*06c3fb27SDimitry Andric Floating *R) { 116*06c3fb27SDimitry Andric APFloat One(A.F.getSemantics(), 1); 117*06c3fb27SDimitry Andric *R = Floating(A.F); 118*06c3fb27SDimitry Andric return R->F.add(One, RM); 119*06c3fb27SDimitry Andric } 120*06c3fb27SDimitry Andric 121*06c3fb27SDimitry Andric static APFloat::opStatus sub(const Floating &A, const Floating &B, 122*06c3fb27SDimitry Andric llvm::RoundingMode RM, Floating *R) { 123*06c3fb27SDimitry Andric *R = Floating(A.F); 124*06c3fb27SDimitry Andric return R->F.subtract(B.F, RM); 125*06c3fb27SDimitry Andric } 126*06c3fb27SDimitry Andric 127*06c3fb27SDimitry Andric static APFloat::opStatus decrement(const Floating &A, llvm::RoundingMode RM, 128*06c3fb27SDimitry Andric Floating *R) { 129*06c3fb27SDimitry Andric APFloat One(A.F.getSemantics(), 1); 130*06c3fb27SDimitry Andric *R = Floating(A.F); 131*06c3fb27SDimitry Andric return R->F.subtract(One, RM); 132*06c3fb27SDimitry Andric } 133*06c3fb27SDimitry Andric 134*06c3fb27SDimitry Andric static APFloat::opStatus mul(const Floating &A, const Floating &B, 135*06c3fb27SDimitry Andric llvm::RoundingMode RM, Floating *R) { 136*06c3fb27SDimitry Andric *R = Floating(A.F); 137*06c3fb27SDimitry Andric return R->F.multiply(B.F, RM); 138*06c3fb27SDimitry Andric } 139*06c3fb27SDimitry Andric 140*06c3fb27SDimitry Andric static APFloat::opStatus div(const Floating &A, const Floating &B, 141*06c3fb27SDimitry Andric llvm::RoundingMode RM, Floating *R) { 142*06c3fb27SDimitry Andric *R = Floating(A.F); 143*06c3fb27SDimitry Andric return R->F.divide(B.F, RM); 144*06c3fb27SDimitry Andric } 145*06c3fb27SDimitry Andric 146*06c3fb27SDimitry Andric static bool neg(const Floating &A, Floating *R) { 147*06c3fb27SDimitry Andric *R = -A; 148*06c3fb27SDimitry Andric return false; 149*06c3fb27SDimitry Andric } 150*06c3fb27SDimitry Andric }; 151*06c3fb27SDimitry Andric 152*06c3fb27SDimitry Andric llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, Floating F); 153*06c3fb27SDimitry Andric Floating getSwappedBytes(Floating F); 154*06c3fb27SDimitry Andric 155*06c3fb27SDimitry Andric } // namespace interp 156*06c3fb27SDimitry Andric } // namespace clang 157*06c3fb27SDimitry Andric 158*06c3fb27SDimitry Andric #endif 159