Coverage Report

Created: 2023-09-30 09:22

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/AST/Interp/Floating.h
Line
Count
Source (jump to first uncovered line)
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
1.12k
  Floating() : F(0.0f) {}
34
2.27k
  Floating(const APFloat &F) : F(F) {}
35
36
  // Static constructors for special floating point values.
37
87
  static Floating getInf(const llvm::fltSemantics &Sem) {
38
87
    return Floating(APFloat::getInf(Sem));
39
87
  }
40
65
  const APFloat &getAPFloat() const { return F; }
41
42
97
  bool operator<(Floating RHS) const { return F < RHS.F; }
43
70
  bool operator>(Floating RHS) const { return F > RHS.F; }
44
0
  bool operator<=(Floating RHS) const { return F <= RHS.F; }
45
0
  bool operator>=(Floating RHS) const { return F >= RHS.F; }
46
0
  bool operator==(Floating RHS) const { return F == RHS.F; }
47
0
  bool operator!=(Floating RHS) const { return F != RHS.F; }
48
264
  Floating operator-() const { return Floating(-F); }
49
50
49
  APFloat::opStatus convertToInteger(APSInt &Result) const {
51
49
    bool IsExact;
52
49
    return F.convertToInteger(Result, llvm::APFloat::rmTowardZero, &IsExact);
53
49
  }
54
55
  Floating toSemantics(const llvm::fltSemantics *Sem,
56
569
                       llvm::RoundingMode RM) const {
57
569
    APFloat Copy = F;
58
569
    bool LosesInfo;
59
569
    Copy.convert(*Sem, RM, &LosesInfo);
60
569
    (void)LosesInfo;
61
569
    return Floating(Copy);
62
569
  }
63
64
  /// Convert this Floating to one with the same semantics as \Other.
65
0
  Floating toSemantics(const Floating &Other, llvm::RoundingMode RM) const {
66
0
    return toSemantics(&Other.F.getSemantics(), RM);
67
0
  }
68
69
0
  APSInt toAPSInt(unsigned NumBits = 0) const {
70
0
    return APSInt(F.bitcastToAPInt());
71
0
  }
72
222
  APValue toAPValue() const { return APValue(F); }
73
0
  void print(llvm::raw_ostream &OS) const {
74
    // Can't use APFloat::print() since it appends a newline.
75
0
    SmallVector<char, 16> Buffer;
76
0
    F.toString(Buffer);
77
0
    OS << Buffer;
78
0
  }
79
0
  std::string toDiagnosticString(const ASTContext &Ctx) const {
80
0
    std::string NameStr;
81
0
    llvm::raw_string_ostream OS(NameStr);
82
0
    print(OS);
83
0
    return NameStr;
84
0
  }
85
86
37
  unsigned bitWidth() const { return F.semanticsSizeInBits(F.getSemantics()); }
87
88
26
  bool isSigned() const { return true; }
89
40
  bool isNegative() const { return F.isNegative(); }
90
0
  bool isPositive() const { return !F.isNegative(); }
91
319
  bool isZero() const { return F.isZero(); }
92
14
  bool isNonZero() const { return F.isNonZero(); }
93
26
  bool isMin() const { return F.isSmallest(); }
94
0
  bool isMinusOne() const { return F.isExactlyValue(-1.0); }
95
553
  bool isNan() const { return F.isNaN(); }
96
20
  bool isInf() const { return F.isInfinity(); }
97
11
  bool isFinite() const { return F.isFinite(); }
98
10
  bool isNormal() const { return F.isNormal(); }
99
22
  bool isDenormal() const { return F.isDenormal(); }
100
194
  llvm::FPClassTest classify() const { return F.classify(); }
101
52
  APFloat::fltCategory getCategory() const { return F.getCategory(); }
102
103
248
  ComparisonCategoryResult compare(const Floating &RHS) const {
104
248
    llvm::APFloatBase::cmpResult CmpRes = F.compare(RHS.F);
105
248
    switch (CmpRes) {
106
1
    case llvm::APFloatBase::cmpLessThan:
107
1
      return ComparisonCategoryResult::Less;
108
240
    case llvm::APFloatBase::cmpEqual:
109
240
      return ComparisonCategoryResult::Equal;
110
3
    case llvm::APFloatBase::cmpGreaterThan:
111
3
      return ComparisonCategoryResult::Greater;
112
4
    case llvm::APFloatBase::cmpUnordered:
113
4
      return ComparisonCategoryResult::Unordered;
114
248
    }
115
0
    llvm_unreachable("Inavlid cmpResult value");
116
0
  }
117
118
  static APFloat::opStatus fromIntegral(APSInt Val,
119
                                        const llvm::fltSemantics &Sem,
120
                                        llvm::RoundingMode RM,
121
143
                                        Floating &Result) {
122
143
    APFloat F = APFloat(Sem);
123
143
    APFloat::opStatus Status = F.convertFromAPInt(Val, Val.isSigned(), RM);
124
143
    Result = Floating(F);
125
143
    return Status;
126
143
  }
127
128
  static Floating bitcastFromMemory(const std::byte *Buff,
129
61
                                    const llvm::fltSemantics &Sem) {
130
61
    size_t Size = APFloat::semanticsSizeInBits(Sem);
131
61
    llvm::APInt API(Size, true);
132
61
    llvm::LoadIntFromMemory(API, (const uint8_t *)Buff, Size / 8);
133
134
61
    return Floating(APFloat(Sem, API));
135
61
  }
136
137
  // === Serialization support ===
138
98
  size_t bytesToSerialize() const {
139
98
    return sizeof(llvm::fltSemantics *) +
140
98
           (APFloat::semanticsSizeInBits(F.getSemantics()) / 8);
141
98
  }
142
143
37
  void serialize(std::byte *Buff) const {
144
    // Semantics followed by an APInt.
145
37
    *reinterpret_cast<const llvm::fltSemantics **>(Buff) = &F.getSemantics();
146
147
37
    llvm::APInt API = F.bitcastToAPInt();
148
37
    llvm::StoreIntToMemory(API, (uint8_t *)(Buff + sizeof(void *)),
149
37
                           bitWidth() / 8);
150
37
  }
151
152
61
  static Floating deserialize(const std::byte *Buff) {
153
61
    const llvm::fltSemantics *Sem;
154
61
    std::memcpy((void *)&Sem, Buff, sizeof(void *));
155
61
    return bitcastFromMemory(Buff + sizeof(void *), *Sem);
156
61
  }
157
158
5
  static Floating abs(const Floating &F) {
159
5
    APFloat V = F.F;
160
5
    if (V.isNegative())
161
5
      V.changeSign();
162
5
    return Floating(V);
163
5
  }
164
165
  // -------
166
167
  static APFloat::opStatus add(const Floating &A, const Floating &B,
168
97
                               llvm::RoundingMode RM, Floating *R) {
169
97
    *R = Floating(A.F);
170
97
    return R->F.add(B.F, RM);
171
97
  }
172
173
  static APFloat::opStatus increment(const Floating &A, llvm::RoundingMode RM,
174
4
                                     Floating *R) {
175
4
    APFloat One(A.F.getSemantics(), 1);
176
4
    *R = Floating(A.F);
177
4
    return R->F.add(One, RM);
178
4
  }
179
180
  static APFloat::opStatus sub(const Floating &A, const Floating &B,
181
2
                               llvm::RoundingMode RM, Floating *R) {
182
2
    *R = Floating(A.F);
183
2
    return R->F.subtract(B.F, RM);
184
2
  }
185
186
  static APFloat::opStatus decrement(const Floating &A, llvm::RoundingMode RM,
187
2
                                     Floating *R) {
188
2
    APFloat One(A.F.getSemantics(), 1);
189
2
    *R = Floating(A.F);
190
2
    return R->F.subtract(One, RM);
191
2
  }
192
193
  static APFloat::opStatus mul(const Floating &A, const Floating &B,
194
15
                               llvm::RoundingMode RM, Floating *R) {
195
15
    *R = Floating(A.F);
196
15
    return R->F.multiply(B.F, RM);
197
15
  }
198
199
  static APFloat::opStatus div(const Floating &A, const Floating &B,
200
26
                               llvm::RoundingMode RM, Floating *R) {
201
26
    *R = Floating(A.F);
202
26
    return R->F.divide(B.F, RM);
203
26
  }
204
205
264
  static bool neg(const Floating &A, Floating *R) {
206
264
    *R = -A;
207
264
    return false;
208
264
  }
209
};
210
211
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, Floating F);
212
Floating getSwappedBytes(Floating F);
213
214
} // namespace interp
215
} // namespace clang
216
217
#endif