brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.7 KiB · cc918dc Raw
310 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8//9// Defines the VM types and helpers operating on types.10//11//===----------------------------------------------------------------------===//12 13#ifndef LLVM_CLANG_AST_INTERP_FLOATING_H14#define LLVM_CLANG_AST_INTERP_FLOATING_H15 16#include "Primitives.h"17#include "clang/AST/APValue.h"18#include "llvm/ADT/APFloat.h"19 20// XXX This is just a debugging help. Setting this to 1 will heap-allocate ALL21// floating values.22#define ALLOCATE_ALL 023 24namespace clang {25namespace interp {26 27using APFloat = llvm::APFloat;28using APSInt = llvm::APSInt;29using APInt = llvm::APInt;30 31/// If a Floating is constructed from Memory, it DOES NOT OWN THAT MEMORY.32/// It will NOT copy the memory (unless, of course, copy() is called) and it33/// won't alllocate anything. The allocation should happen via InterpState or34/// Program.35class Floating final {36private:37  union {38    uint64_t Val = 0;39    uint64_t *Memory;40  };41  llvm::APFloatBase::Semantics Semantics;42 43  APFloat getValue() const {44    unsigned BitWidth = bitWidth();45    if (singleWord())46      return APFloat(getSemantics(), APInt(BitWidth, Val));47    unsigned NumWords = numWords();48    return APFloat(getSemantics(),49                   APInt(BitWidth, llvm::ArrayRef(Memory, NumWords)));50  }51 52public:53  Floating() = default;54  Floating(llvm::APFloatBase::Semantics Semantics)55      : Val(0), Semantics(Semantics) {}56  Floating(const APFloat &F) {57 58    Semantics = llvm::APFloatBase::SemanticsToEnum(F.getSemantics());59    this->copy(F);60  }61  Floating(uint64_t *Memory, llvm::APFloatBase::Semantics Semantics)62      : Memory(Memory), Semantics(Semantics) {}63 64  APFloat getAPFloat() const { return getValue(); }65 66  bool operator<(Floating RHS) const { return getValue() < RHS.getValue(); }67  bool operator>(Floating RHS) const { return getValue() > RHS.getValue(); }68  bool operator<=(Floating RHS) const { return getValue() <= RHS.getValue(); }69  bool operator>=(Floating RHS) const { return getValue() >= RHS.getValue(); }70 71  APFloat::opStatus convertToInteger(APSInt &Result) const {72    bool IsExact;73    return getValue().convertToInteger(Result, llvm::APFloat::rmTowardZero,74                                       &IsExact);75  }76 77  void toSemantics(const llvm::fltSemantics *Sem, llvm::RoundingMode RM,78                   Floating *Result) const {79    APFloat Copy = getValue();80    bool LosesInfo;81    Copy.convert(*Sem, RM, &LosesInfo);82    (void)LosesInfo;83    Result->copy(Copy);84  }85 86  APSInt toAPSInt(unsigned NumBits = 0) const {87    return APSInt(getValue().bitcastToAPInt());88  }89  APValue toAPValue(const ASTContext &) const { return APValue(getValue()); }90  void print(llvm::raw_ostream &OS) const {91    // Can't use APFloat::print() since it appends a newline.92    SmallVector<char, 16> Buffer;93    getValue().toString(Buffer);94    OS << Buffer;95  }96  std::string toDiagnosticString(const ASTContext &Ctx) const {97    std::string NameStr;98    llvm::raw_string_ostream OS(NameStr);99    print(OS);100    return NameStr;101  }102 103  unsigned bitWidth() const {104    return llvm::APFloatBase::semanticsSizeInBits(getSemantics());105  }106  unsigned numWords() const { return llvm::APInt::getNumWords(bitWidth()); }107  bool singleWord() const {108#if ALLOCATE_ALL109    return false;110#endif111    return numWords() == 1;112  }113  static bool singleWord(const llvm::fltSemantics &Sem) {114#if ALLOCATE_ALL115    return false;116#endif117    return APInt::getNumWords(llvm::APFloatBase::getSizeInBits(Sem)) == 1;118  }119  const llvm::fltSemantics &getSemantics() const {120    return llvm::APFloatBase::EnumToSemantics(Semantics);121  }122 123  void copy(const APFloat &F) {124    if (singleWord()) {125      Val = F.bitcastToAPInt().getZExtValue();126    } else {127      assert(Memory);128      std::memcpy(Memory, F.bitcastToAPInt().getRawData(),129                  numWords() * sizeof(uint64_t));130    }131  }132 133  void take(uint64_t *NewMemory) {134    if (singleWord())135      return;136 137    if (Memory)138      std::memcpy(NewMemory, Memory, numWords() * sizeof(uint64_t));139    Memory = NewMemory;140  }141 142  bool isSigned() const { return true; }143  bool isNegative() const { return getValue().isNegative(); }144  bool isZero() const { return getValue().isZero(); }145  bool isNonZero() const { return getValue().isNonZero(); }146  bool isMin() const { return getValue().isSmallest(); }147  bool isMinusOne() const { return getValue().isExactlyValue(-1.0); }148  bool isNan() const { return getValue().isNaN(); }149  bool isSignaling() const { return getValue().isSignaling(); }150  bool isInf() const { return getValue().isInfinity(); }151  bool isFinite() const { return getValue().isFinite(); }152  bool isNormal() const { return getValue().isNormal(); }153  bool isDenormal() const { return getValue().isDenormal(); }154  llvm::FPClassTest classify() const { return getValue().classify(); }155  APFloat::fltCategory getCategory() const { return getValue().getCategory(); }156 157  ComparisonCategoryResult compare(const Floating &RHS) const {158    llvm::APFloatBase::cmpResult CmpRes = getValue().compare(RHS.getValue());159    switch (CmpRes) {160    case llvm::APFloatBase::cmpLessThan:161      return ComparisonCategoryResult::Less;162    case llvm::APFloatBase::cmpEqual:163      return ComparisonCategoryResult::Equal;164    case llvm::APFloatBase::cmpGreaterThan:165      return ComparisonCategoryResult::Greater;166    case llvm::APFloatBase::cmpUnordered:167      return ComparisonCategoryResult::Unordered;168    }169    llvm_unreachable("Inavlid cmpResult value");170  }171 172  static APFloat::opStatus fromIntegral(APSInt Val,173                                        const llvm::fltSemantics &Sem,174                                        llvm::RoundingMode RM,175                                        Floating *Result) {176    APFloat F = APFloat(Sem);177    APFloat::opStatus Status = F.convertFromAPInt(Val, Val.isSigned(), RM);178    Result->copy(F);179    return Status;180  }181 182  static void bitcastFromMemory(const std::byte *Buff,183                                const llvm::fltSemantics &Sem,184                                Floating *Result) {185    size_t Size = APFloat::semanticsSizeInBits(Sem);186    llvm::APInt API(Size, true);187    llvm::LoadIntFromMemory(API, (const uint8_t *)Buff, Size / 8);188    Result->copy(APFloat(Sem, API));189  }190 191  void bitcastToMemory(std::byte *Buff) const {192    llvm::APInt API = getValue().bitcastToAPInt();193    llvm::StoreIntToMemory(API, (uint8_t *)Buff, bitWidth() / 8);194  }195 196  // === Serialization support ===197  size_t bytesToSerialize() const {198    return sizeof(Semantics) + (numWords() * sizeof(uint64_t));199  }200 201  void serialize(std::byte *Buff) const {202    std::memcpy(Buff, &Semantics, sizeof(Semantics));203    if (singleWord()) {204      std::memcpy(Buff + sizeof(Semantics), &Val, sizeof(uint64_t));205    } else {206      std::memcpy(Buff + sizeof(Semantics), Memory,207                  numWords() * sizeof(uint64_t));208    }209  }210 211  static llvm::APFloatBase::Semantics212  deserializeSemantics(const std::byte *Buff) {213    return *reinterpret_cast<const llvm::APFloatBase::Semantics *>(Buff);214  }215 216  static void deserialize(const std::byte *Buff, Floating *Result) {217    llvm::APFloatBase::Semantics Semantics;218    std::memcpy(&Semantics, Buff, sizeof(Semantics));219 220    unsigned BitWidth = llvm::APFloat::semanticsSizeInBits(221        llvm::APFloatBase::EnumToSemantics(Semantics));222    unsigned NumWords = llvm::APInt::getNumWords(BitWidth);223 224    Result->Semantics = Semantics;225    if (NumWords == 1 && !ALLOCATE_ALL) {226      std::memcpy(&Result->Val, Buff + sizeof(Semantics), sizeof(uint64_t));227    } else {228      assert(Result->Memory);229      std::memcpy(Result->Memory, Buff + sizeof(Semantics),230                  NumWords * sizeof(uint64_t));231    }232  }233 234  // -------235 236  static APFloat::opStatus add(const Floating &A, const Floating &B,237                               llvm::RoundingMode RM, Floating *R) {238    APFloat LHS = A.getValue();239    APFloat RHS = B.getValue();240 241    auto Status = LHS.add(RHS, RM);242    R->copy(LHS);243    return Status;244  }245 246  static APFloat::opStatus increment(const Floating &A, llvm::RoundingMode RM,247                                     Floating *R) {248    APFloat One(A.getSemantics(), 1);249    APFloat LHS = A.getValue();250 251    auto Status = LHS.add(One, RM);252    R->copy(LHS);253    return Status;254  }255 256  static APFloat::opStatus sub(const Floating &A, const Floating &B,257                               llvm::RoundingMode RM, Floating *R) {258    APFloat LHS = A.getValue();259    APFloat RHS = B.getValue();260 261    auto Status = LHS.subtract(RHS, RM);262    R->copy(LHS);263    return Status;264  }265 266  static APFloat::opStatus decrement(const Floating &A, llvm::RoundingMode RM,267                                     Floating *R) {268    APFloat One(A.getSemantics(), 1);269    APFloat LHS = A.getValue();270 271    auto Status = LHS.subtract(One, RM);272    R->copy(LHS);273    return Status;274  }275 276  static APFloat::opStatus mul(const Floating &A, const Floating &B,277                               llvm::RoundingMode RM, Floating *R) {278 279    APFloat LHS = A.getValue();280    APFloat RHS = B.getValue();281 282    auto Status = LHS.multiply(RHS, RM);283    R->copy(LHS);284    return Status;285  }286 287  static APFloat::opStatus div(const Floating &A, const Floating &B,288                               llvm::RoundingMode RM, Floating *R) {289    APFloat LHS = A.getValue();290    APFloat RHS = B.getValue();291 292    auto Status = LHS.divide(RHS, RM);293    R->copy(LHS);294    return Status;295  }296 297  static bool neg(const Floating &A, Floating *R) {298    R->copy(-A.getValue());299    return false;300  }301};302 303llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, Floating F);304Floating getSwappedBytes(Floating F);305 306} // namespace interp307} // namespace clang308 309#endif310