Path: blob/main/contrib/llvm-project/clang/lib/AST/Interp/Floating.h
35292 views
//===--- Floating.h - Types for the constexpr VM ----------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// Defines the VM types and helpers operating on types.9//10//===----------------------------------------------------------------------===//1112#ifndef LLVM_CLANG_AST_INTERP_FLOATING_H13#define LLVM_CLANG_AST_INTERP_FLOATING_H1415#include "Primitives.h"16#include "clang/AST/APValue.h"17#include "llvm/ADT/APFloat.h"1819namespace clang {20namespace interp {2122using APFloat = llvm::APFloat;23using APSInt = llvm::APSInt;2425class Floating final {26private:27// The underlying value storage.28APFloat F;2930public:31/// Zero-initializes a Floating.32Floating() : F(0.0f) {}33Floating(const APFloat &F) : F(F) {}3435// Static constructors for special floating point values.36static Floating getInf(const llvm::fltSemantics &Sem) {37return Floating(APFloat::getInf(Sem));38}39const APFloat &getAPFloat() const { return F; }4041bool operator<(Floating RHS) const { return F < RHS.F; }42bool operator>(Floating RHS) const { return F > RHS.F; }43bool operator<=(Floating RHS) const { return F <= RHS.F; }44bool operator>=(Floating RHS) const { return F >= RHS.F; }45bool operator==(Floating RHS) const { return F == RHS.F; }46bool operator!=(Floating RHS) const { return F != RHS.F; }47Floating operator-() const { return Floating(-F); }4849APFloat::opStatus convertToInteger(APSInt &Result) const {50bool IsExact;51return F.convertToInteger(Result, llvm::APFloat::rmTowardZero, &IsExact);52}5354Floating toSemantics(const llvm::fltSemantics *Sem,55llvm::RoundingMode RM) const {56APFloat Copy = F;57bool LosesInfo;58Copy.convert(*Sem, RM, &LosesInfo);59(void)LosesInfo;60return Floating(Copy);61}6263/// Convert this Floating to one with the same semantics as \Other.64Floating toSemantics(const Floating &Other, llvm::RoundingMode RM) const {65return toSemantics(&Other.F.getSemantics(), RM);66}6768APSInt toAPSInt(unsigned NumBits = 0) const {69return APSInt(F.bitcastToAPInt());70}71APValue toAPValue(const ASTContext &) const { return APValue(F); }72void print(llvm::raw_ostream &OS) const {73// Can't use APFloat::print() since it appends a newline.74SmallVector<char, 16> Buffer;75F.toString(Buffer);76OS << Buffer;77}78std::string toDiagnosticString(const ASTContext &Ctx) const {79std::string NameStr;80llvm::raw_string_ostream OS(NameStr);81print(OS);82return NameStr;83}8485unsigned bitWidth() const { return F.semanticsSizeInBits(F.getSemantics()); }8687bool isSigned() const { return true; }88bool isNegative() const { return F.isNegative(); }89bool isPositive() const { return !F.isNegative(); }90bool isZero() const { return F.isZero(); }91bool isNonZero() const { return F.isNonZero(); }92bool isMin() const { return F.isSmallest(); }93bool isMinusOne() const { return F.isExactlyValue(-1.0); }94bool isNan() const { return F.isNaN(); }95bool isSignaling() const { return F.isSignaling(); }96bool isInf() const { return F.isInfinity(); }97bool isFinite() const { return F.isFinite(); }98bool isNormal() const { return F.isNormal(); }99bool isDenormal() const { return F.isDenormal(); }100llvm::FPClassTest classify() const { return F.classify(); }101APFloat::fltCategory getCategory() const { return F.getCategory(); }102103ComparisonCategoryResult compare(const Floating &RHS) const {104llvm::APFloatBase::cmpResult CmpRes = F.compare(RHS.F);105switch (CmpRes) {106case llvm::APFloatBase::cmpLessThan:107return ComparisonCategoryResult::Less;108case llvm::APFloatBase::cmpEqual:109return ComparisonCategoryResult::Equal;110case llvm::APFloatBase::cmpGreaterThan:111return ComparisonCategoryResult::Greater;112case llvm::APFloatBase::cmpUnordered:113return ComparisonCategoryResult::Unordered;114}115llvm_unreachable("Inavlid cmpResult value");116}117118static APFloat::opStatus fromIntegral(APSInt Val,119const llvm::fltSemantics &Sem,120llvm::RoundingMode RM,121Floating &Result) {122APFloat F = APFloat(Sem);123APFloat::opStatus Status = F.convertFromAPInt(Val, Val.isSigned(), RM);124Result = Floating(F);125return Status;126}127128static Floating bitcastFromMemory(const std::byte *Buff,129const llvm::fltSemantics &Sem) {130size_t Size = APFloat::semanticsSizeInBits(Sem);131llvm::APInt API(Size, true);132llvm::LoadIntFromMemory(API, (const uint8_t *)Buff, Size / 8);133134return Floating(APFloat(Sem, API));135}136137// === Serialization support ===138size_t bytesToSerialize() const {139return sizeof(llvm::fltSemantics *) +140(APFloat::semanticsSizeInBits(F.getSemantics()) / 8);141}142143void serialize(std::byte *Buff) const {144// Semantics followed by an APInt.145*reinterpret_cast<const llvm::fltSemantics **>(Buff) = &F.getSemantics();146147llvm::APInt API = F.bitcastToAPInt();148llvm::StoreIntToMemory(API, (uint8_t *)(Buff + sizeof(void *)),149bitWidth() / 8);150}151152static Floating deserialize(const std::byte *Buff) {153const llvm::fltSemantics *Sem;154std::memcpy((void *)&Sem, Buff, sizeof(void *));155return bitcastFromMemory(Buff + sizeof(void *), *Sem);156}157158static Floating abs(const Floating &F) {159APFloat V = F.F;160if (V.isNegative())161V.changeSign();162return Floating(V);163}164165// -------166167static APFloat::opStatus add(const Floating &A, const Floating &B,168llvm::RoundingMode RM, Floating *R) {169*R = Floating(A.F);170return R->F.add(B.F, RM);171}172173static APFloat::opStatus increment(const Floating &A, llvm::RoundingMode RM,174Floating *R) {175APFloat One(A.F.getSemantics(), 1);176*R = Floating(A.F);177return R->F.add(One, RM);178}179180static APFloat::opStatus sub(const Floating &A, const Floating &B,181llvm::RoundingMode RM, Floating *R) {182*R = Floating(A.F);183return R->F.subtract(B.F, RM);184}185186static APFloat::opStatus decrement(const Floating &A, llvm::RoundingMode RM,187Floating *R) {188APFloat One(A.F.getSemantics(), 1);189*R = Floating(A.F);190return R->F.subtract(One, RM);191}192193static APFloat::opStatus mul(const Floating &A, const Floating &B,194llvm::RoundingMode RM, Floating *R) {195*R = Floating(A.F);196return R->F.multiply(B.F, RM);197}198199static APFloat::opStatus div(const Floating &A, const Floating &B,200llvm::RoundingMode RM, Floating *R) {201*R = Floating(A.F);202return R->F.divide(B.F, RM);203}204205static bool neg(const Floating &A, Floating *R) {206*R = -A;207return false;208}209};210211llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, Floating F);212Floating getSwappedBytes(Floating F);213214} // namespace interp215} // namespace clang216217#endif218219220