Coverage Report

Created: 2023-09-30 09:22

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/include/lldb/Utility/Scalar.h
Line
Count
Source (jump to first uncovered line)
1
//===-- Scalar.h ------------------------------------------------*- 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
#ifndef LLDB_UTILITY_SCALAR_H
10
#define LLDB_UTILITY_SCALAR_H
11
12
#include "lldb/Utility/LLDBAssert.h"
13
#include "lldb/Utility/Status.h"
14
#include "lldb/lldb-enumerations.h"
15
#include "lldb/lldb-private-types.h"
16
#include "llvm/ADT/APFloat.h"
17
#include "llvm/ADT/APSInt.h"
18
#include <cstddef>
19
#include <cstdint>
20
#include <utility>
21
22
namespace lldb_private {
23
24
class DataExtractor;
25
class Stream;
26
27
0
#define NUM_OF_WORDS_INT128 2
28
0
#define BITWIDTH_INT128 128
29
30
// A class designed to hold onto values and their corresponding types.
31
// Operators are defined and Scalar objects will correctly promote their types
32
// and values before performing these operations. Type promotion currently
33
// follows the ANSI C type promotion rules.
34
class Scalar {
35
  template<typename T>
36
3.58M
  static llvm::APSInt MakeAPSInt(T v) {
37
3.58M
    static_assert(std::is_integral<T>::value);
38
3.58M
    static_assert(sizeof(T) <= sizeof(uint64_t), "Conversion loses precision!");
39
3.58M
    return llvm::APSInt(
40
3.58M
        llvm::APInt(sizeof(T) * 8, uint64_t(v), std::is_signed<T>::value),
41
3.58M
        std::is_unsigned<T>::value);
42
3.58M
  }
llvm::APSInt lldb_private::Scalar::MakeAPSInt<int>(int)
Line
Count
Source
36
135k
  static llvm::APSInt MakeAPSInt(T v) {
37
135k
    static_assert(std::is_integral<T>::value);
38
135k
    static_assert(sizeof(T) <= sizeof(uint64_t), "Conversion loses precision!");
39
135k
    return llvm::APSInt(
40
135k
        llvm::APInt(sizeof(T) * 8, uint64_t(v), std::is_signed<T>::value),
41
135k
        std::is_unsigned<T>::value);
42
135k
  }
llvm::APSInt lldb_private::Scalar::MakeAPSInt<unsigned int>(unsigned int)
Line
Count
Source
36
47.6k
  static llvm::APSInt MakeAPSInt(T v) {
37
47.6k
    static_assert(std::is_integral<T>::value);
38
47.6k
    static_assert(sizeof(T) <= sizeof(uint64_t), "Conversion loses precision!");
39
47.6k
    return llvm::APSInt(
40
47.6k
        llvm::APInt(sizeof(T) * 8, uint64_t(v), std::is_signed<T>::value),
41
47.6k
        std::is_unsigned<T>::value);
42
47.6k
  }
llvm::APSInt lldb_private::Scalar::MakeAPSInt<long>(long)
Line
Count
Source
36
188
  static llvm::APSInt MakeAPSInt(T v) {
37
188
    static_assert(std::is_integral<T>::value);
38
188
    static_assert(sizeof(T) <= sizeof(uint64_t), "Conversion loses precision!");
39
188
    return llvm::APSInt(
40
188
        llvm::APInt(sizeof(T) * 8, uint64_t(v), std::is_signed<T>::value),
41
188
        std::is_unsigned<T>::value);
42
188
  }
llvm::APSInt lldb_private::Scalar::MakeAPSInt<unsigned long>(unsigned long)
Line
Count
Source
36
1.55M
  static llvm::APSInt MakeAPSInt(T v) {
37
1.55M
    static_assert(std::is_integral<T>::value);
38
1.55M
    static_assert(sizeof(T) <= sizeof(uint64_t), "Conversion loses precision!");
39
1.55M
    return llvm::APSInt(
40
1.55M
        llvm::APInt(sizeof(T) * 8, uint64_t(v), std::is_signed<T>::value),
41
1.55M
        std::is_unsigned<T>::value);
42
1.55M
  }
llvm::APSInt lldb_private::Scalar::MakeAPSInt<long long>(long long)
Line
Count
Source
36
13.0k
  static llvm::APSInt MakeAPSInt(T v) {
37
13.0k
    static_assert(std::is_integral<T>::value);
38
13.0k
    static_assert(sizeof(T) <= sizeof(uint64_t), "Conversion loses precision!");
39
13.0k
    return llvm::APSInt(
40
13.0k
        llvm::APInt(sizeof(T) * 8, uint64_t(v), std::is_signed<T>::value),
41
13.0k
        std::is_unsigned<T>::value);
42
13.0k
  }
llvm::APSInt lldb_private::Scalar::MakeAPSInt<unsigned long long>(unsigned long long)
Line
Count
Source
36
1.83M
  static llvm::APSInt MakeAPSInt(T v) {
37
1.83M
    static_assert(std::is_integral<T>::value);
38
1.83M
    static_assert(sizeof(T) <= sizeof(uint64_t), "Conversion loses precision!");
39
1.83M
    return llvm::APSInt(
40
1.83M
        llvm::APInt(sizeof(T) * 8, uint64_t(v), std::is_signed<T>::value),
41
1.83M
        std::is_unsigned<T>::value);
42
1.83M
  }
43
44
public:
45
  enum Type {
46
    e_void = 0,
47
    e_int,
48
    e_float,
49
  };
50
51
  // Constructors and Destructors
52
2.18M
  Scalar() : m_float(0.0f) {}
53
135k
  Scalar(int v) : m_type(e_int), m_integer(MakeAPSInt(v)), m_float(0.0f) {}
54
  Scalar(unsigned int v)
55
47.6k
      : m_type(e_int), m_integer(MakeAPSInt(v)), m_float(0.0f) {}
56
188
  Scalar(long v) : m_type(e_int), m_integer(MakeAPSInt(v)), m_float(0.0f) {}
57
  Scalar(unsigned long v)
58
1.55M
      : m_type(e_int), m_integer(MakeAPSInt(v)), m_float(0.0f) {}
59
  Scalar(long long v)
60
13.0k
      : m_type(e_int), m_integer(MakeAPSInt(v)), m_float(0.0f) {}
61
  Scalar(unsigned long long v)
62
1.83M
      : m_type(e_int), m_integer(MakeAPSInt(v)), m_float(0.0f) {}
63
394
  Scalar(float v) : m_type(e_float), m_float(v) {}
64
419
  Scalar(double v) : m_type(e_float), m_float(v) {}
65
15
  Scalar(long double v) : m_type(e_float), m_float(double(v)) {
66
15
    bool ignore;
67
15
    m_float.convert(llvm::APFloat::x87DoubleExtended(),
68
15
                    llvm::APFloat::rmNearestTiesToEven, &ignore);
69
15
  }
70
  Scalar(llvm::APInt v)
71
839k
      : m_type(e_int), m_integer(std::move(v), false), m_float(0.0f) {}
72
  Scalar(llvm::APSInt v)
73
103
      : m_type(e_int), m_integer(std::move(v)), m_float(0.0f) {}
74
75
  bool SignExtend(uint32_t bit_pos);
76
77
  bool ExtractBitfield(uint32_t bit_size, uint32_t bit_offset);
78
79
  bool SetBit(uint32_t bit);
80
81
  bool ClearBit(uint32_t bit);
82
83
  /// Store the binary representation of this value into the given storage.
84
  /// Exactly GetByteSize() bytes will be stored, and the buffer must be large
85
  /// enough to hold this data.
86
  void GetBytes(llvm::MutableArrayRef<uint8_t> storage) const;
87
88
  size_t GetByteSize() const;
89
90
  bool GetData(DataExtractor &data, size_t limit_byte_size = UINT32_MAX) const;
91
92
  size_t GetAsMemoryData(void *dst, size_t dst_len,
93
                         lldb::ByteOrder dst_byte_order, Status &error) const;
94
95
  bool IsZero() const;
96
97
7.25k
  void Clear() {
98
7.25k
    m_type = e_void;
99
7.25k
    m_integer.clearAllBits();
100
7.25k
  }
101
102
2
  const char *GetTypeAsCString() const { return GetValueTypeAsCString(m_type); }
103
104
  void GetValue(Stream *s, bool show_type) const;
105
106
43.1k
  bool IsValid() const { return (m_type >= e_int) && (m_type <= e_float); }
107
108
  /// Convert to an integer with \p bits and the given signedness.
109
  void TruncOrExtendTo(uint16_t bits, bool sign);
110
111
  bool IntegralPromote(uint16_t bits, bool sign);
112
  bool FloatPromote(const llvm::fltSemantics &semantics);
113
114
  bool IsSigned() const;
115
  bool MakeSigned();
116
117
  bool MakeUnsigned();
118
119
  static const char *GetValueTypeAsCString(Scalar::Type value_type);
120
121
  // All operators can benefits from the implicit conversions that will happen
122
  // automagically by the compiler, so no temporary objects will need to be
123
  // created. As a result, we currently don't need a variety of overloaded set
124
  // value accessors.
125
  Scalar &operator+=(Scalar rhs);
126
  Scalar &operator<<=(const Scalar &rhs); // Shift left
127
  Scalar &operator>>=(const Scalar &rhs); // Shift right (arithmetic)
128
  Scalar &operator&=(const Scalar &rhs);
129
130
  // Shifts the current value to the right without maintaining the current sign
131
  // of the value (if it is signed).
132
  bool ShiftRightLogical(const Scalar &rhs); // Returns true on success
133
134
  // Takes the absolute value of the current value if it is signed, else the
135
  // value remains unchanged. Returns false if the contained value has a void
136
  // type.
137
  bool AbsoluteValue(); // Returns true on success
138
  // Negates the current value (even for unsigned values). Returns false if the
139
  // contained value has a void type.
140
  bool UnaryNegate(); // Returns true on success
141
  // Inverts all bits in the current value as long as it isn't void or a
142
  // float/double/long double type. Returns false if the contained value has a
143
  // void/float/double/long double type, else the value is inverted and true is
144
  // returned.
145
  bool OnesComplement(); // Returns true on success
146
147
  // Access the type of the current value.
148
391k
  Scalar::Type GetType() const { return m_type; }
149
150
  // Returns a casted value of the current contained data without modifying the
151
  // current value. FAIL_VALUE will be returned if the type of the value is
152
  // void or invalid.
153
  int SInt(int fail_value = 0) const;
154
155
  unsigned char UChar(unsigned char fail_value = 0) const;
156
157
  signed char SChar(signed char fail_value = 0) const;
158
159
  unsigned short UShort(unsigned short fail_value = 0) const;
160
161
  short SShort(short fail_value = 0) const;
162
163
  unsigned int UInt(unsigned int fail_value = 0) const;
164
165
  long SLong(long fail_value = 0) const;
166
167
  unsigned long ULong(unsigned long fail_value = 0) const;
168
169
  long long SLongLong(long long fail_value = 0) const;
170
171
  unsigned long long ULongLong(unsigned long long fail_value = 0) const;
172
173
  llvm::APInt SInt128(const llvm::APInt &fail_value) const;
174
175
  llvm::APInt UInt128(const llvm::APInt &fail_value) const;
176
177
  float Float(float fail_value = 0.0f) const;
178
179
  double Double(double fail_value = 0.0) const;
180
181
  long double LongDouble(long double fail_value = 0.0) const;
182
183
  Status SetValueFromCString(const char *s, lldb::Encoding encoding,
184
                             size_t byte_size);
185
186
  Status SetValueFromData(const DataExtractor &data, lldb::Encoding encoding,
187
                          size_t byte_size);
188
189
protected:
190
  Scalar::Type m_type = e_void;
191
  llvm::APSInt m_integer;
192
  llvm::APFloat m_float;
193
194
  template <typename T> T GetAs(T fail_value) const;
195
196
  static Type PromoteToMaxType(Scalar &lhs, Scalar &rhs);
197
198
  using PromotionKey = std::tuple<Type, unsigned, bool>;
199
  PromotionKey GetPromoKey() const;
200
201
  static PromotionKey GetFloatPromoKey(const llvm::fltSemantics &semantics);
202
203
private:
204
  friend const Scalar operator+(const Scalar &lhs, const Scalar &rhs);
205
  friend const Scalar operator-(Scalar lhs, Scalar rhs);
206
  friend const Scalar operator/(Scalar lhs, Scalar rhs);
207
  friend const Scalar operator*(Scalar lhs, Scalar rhs);
208
  friend const Scalar operator&(Scalar lhs, Scalar rhs);
209
  friend const Scalar operator|(Scalar lhs, Scalar rhs);
210
  friend const Scalar operator%(Scalar lhs, Scalar rhs);
211
  friend const Scalar operator^(Scalar lhs, Scalar rhs);
212
  friend const Scalar operator<<(const Scalar &lhs, const Scalar &rhs);
213
  friend const Scalar operator>>(const Scalar &lhs, const Scalar &rhs);
214
  friend bool operator==(Scalar lhs, Scalar rhs);
215
  friend bool operator!=(const Scalar &lhs, const Scalar &rhs);
216
  friend bool operator<(Scalar lhs, Scalar rhs);
217
  friend bool operator<=(const Scalar &lhs, const Scalar &rhs);
218
  friend bool operator>(const Scalar &lhs, const Scalar &rhs);
219
  friend bool operator>=(const Scalar &lhs, const Scalar &rhs);
220
};
221
222
// Split out the operators into a format where the compiler will be able to
223
// implicitly convert numbers into Scalar objects.
224
//
225
// This allows code like:
226
//      Scalar two(2);
227
//      Scalar four = two * 2;
228
//      Scalar eight = 2 * four;    // This would cause an error if the
229
//                                  // operator* was implemented as a
230
//                                  // member function.
231
// SEE:
232
//  Item 19 of "Effective C++ Second Edition" by Scott Meyers
233
//  Differentiate among members functions, non-member functions, and
234
//  friend functions
235
const Scalar operator+(const Scalar &lhs, const Scalar &rhs);
236
const Scalar operator-(Scalar lhs, Scalar rhs);
237
const Scalar operator/(Scalar lhs, Scalar rhs);
238
const Scalar operator*(Scalar lhs, Scalar rhs);
239
const Scalar operator&(Scalar lhs, Scalar rhs);
240
const Scalar operator|(Scalar lhs, Scalar rhs);
241
const Scalar operator%(Scalar lhs, Scalar rhs);
242
const Scalar operator^(Scalar lhs, Scalar rhs);
243
const Scalar operator<<(const Scalar &lhs, const Scalar &rhs);
244
const Scalar operator>>(const Scalar &lhs, const Scalar &rhs);
245
bool operator==(Scalar lhs, Scalar rhs);
246
bool operator!=(const Scalar &lhs, const Scalar &rhs);
247
bool operator<(Scalar lhs, Scalar rhs);
248
bool operator<=(const Scalar &lhs, const Scalar &rhs);
249
bool operator>(const Scalar &lhs, const Scalar &rhs);
250
bool operator>=(const Scalar &lhs, const Scalar &rhs);
251
252
llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const Scalar &scalar);
253
254
} // namespace lldb_private
255
256
#endif // LLDB_UTILITY_SCALAR_H