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