Coverage Report

Created: 2023-05-31 04:38

/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
195
  Floating() : F(0.0f) {}
34
335
  Floating(const APFloat &F) : F(F) {}
35
36
  // Static constructors for special floating point values.
37
0
  static Floating getInf(const llvm::fltSemantics &Sem) {
38
0
    return Floating(APFloat::getInf(Sem));
39
0
  }
40
1
  const APFloat &getAPFloat() const { return F; }
41
42
0
  bool operator<(Floating RHS) const { return F < RHS.F; }
43
0
  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
1
  Floating operator-() const { return Floating(-F); }
49
50
9
  APFloat::opStatus convertToInteger(APSInt &Result) const {
51
9
    bool IsExact;
52
9
    return F.convertToInteger(Result, llvm::APFloat::rmTowardZero, &IsExact);
53
9
  }
54
55
  Floating toSemantics(const llvm::fltSemantics *Sem,
56
41
                       llvm::RoundingMode RM) const {
57
41
    APFloat Copy = F;
58
41
    bool LosesInfo;
59
41
    Copy.convert(*Sem, RM, &LosesInfo);
60
41
    (void)LosesInfo;
61
41
    return Floating(Copy);
62
41
  }
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
58
  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
80
0
  unsigned bitWidth() const { return F.semanticsSizeInBits(F.getSemantics()); }
81
82
25
  bool isSigned() const { return true; }
83
0
  bool isNegative() const { return F.isNegative(); }
84
0
  bool isPositive() const { return !F.isNegative(); }
85
26
  bool isZero() const { return F.isZero(); }
86
2
  bool isNonZero() const { return F.isNonZero(); }
87
25
  bool isMin() const { return F.isSmallest(); }
88
0
  bool isMinusOne() const { return F.isExactlyValue(-1.0); }
89
0
  bool isNan() const { return F.isNaN(); }
90
1
  bool isFinite() const { return F.isFinite(); }
91
92
35
  ComparisonCategoryResult compare(const Floating &RHS) const {
93
35
    return Compare(F, RHS.F);
94
35
  }
95
96
  static APFloat::opStatus fromIntegral(APSInt Val,
97
                                        const llvm::fltSemantics &Sem,
98
                                        llvm::RoundingMode RM,
99
39
                                        Floating &Result) {
100
39
    APFloat F = APFloat(Sem);
101
39
    APFloat::opStatus Status = F.convertFromAPInt(Val, Val.isSigned(), RM);
102
39
    Result = Floating(F);
103
39
    return Status;
104
39
  }
105
106
  // -------
107
108
  static APFloat::opStatus add(const Floating &A, const Floating &B,
109
36
                               llvm::RoundingMode RM, Floating *R) {
110
36
    *R = Floating(A.F);
111
36
    return R->F.add(B.F, RM);
112
36
  }
113
114
  static APFloat::opStatus increment(const Floating &A, llvm::RoundingMode RM,
115
4
                                     Floating *R) {
116
4
    APFloat One(A.F.getSemantics(), 1);
117
4
    *R = Floating(A.F);
118
4
    return R->F.add(One, RM);
119
4
  }
120
121
  static APFloat::opStatus sub(const Floating &A, const Floating &B,
122
2
                               llvm::RoundingMode RM, Floating *R) {
123
2
    *R = Floating(A.F);
124
2
    return R->F.subtract(B.F, RM);
125
2
  }
126
127
  static APFloat::opStatus decrement(const Floating &A, llvm::RoundingMode RM,
128
2
                                     Floating *R) {
129
2
    APFloat One(A.F.getSemantics(), 1);
130
2
    *R = Floating(A.F);
131
2
    return R->F.subtract(One, RM);
132
2
  }
133
134
  static APFloat::opStatus mul(const Floating &A, const Floating &B,
135
15
                               llvm::RoundingMode RM, Floating *R) {
136
15
    *R = Floating(A.F);
137
15
    return R->F.multiply(B.F, RM);
138
15
  }
139
140
  static APFloat::opStatus div(const Floating &A, const Floating &B,
141
25
                               llvm::RoundingMode RM, Floating *R) {
142
25
    *R = Floating(A.F);
143
25
    return R->F.divide(B.F, RM);
144
25
  }
145
146
1
  static bool neg(const Floating &A, Floating *R) {
147
1
    *R = -A;
148
1
    return false;
149
1
  }
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