1//===-- RegisterValue.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_REGISTERVALUE_H
10#define LLDB_UTILITY_REGISTERVALUE_H
11
12#include "lldb/Utility/Endian.h"
13#include "lldb/Utility/Scalar.h"
14#include "lldb/Utility/Status.h"
15#include "lldb/lldb-enumerations.h"
16#include "lldb/lldb-types.h"
17#include "llvm/ADT/APInt.h"
18#include "llvm/ADT/StringRef.h"
19#include <cstdint>
20#include <cstring>
21#include <utility>
22
23namespace lldb_private {
24class DataExtractor;
25class Stream;
26struct RegisterInfo;
27
28class RegisterValue {
29public:
30  // big enough to support up to 256 byte AArch64 SVE
31  enum { kMaxRegisterByteSize = 256u };
32
33  enum Type {
34    eTypeInvalid,
35    eTypeUInt8,
36    eTypeUInt16,
37    eTypeUInt32,
38    eTypeUInt64,
39    eTypeUInt128,
40    eTypeFloat,
41    eTypeDouble,
42    eTypeLongDouble,
43    eTypeBytes
44  };
45
46  RegisterValue() : m_scalar(static_cast<unsigned long>(0)) {}
47
48  explicit RegisterValue(uint8_t inst) : m_type(eTypeUInt8) { m_scalar = inst; }
49
50  explicit RegisterValue(uint16_t inst) : m_type(eTypeUInt16) {
51    m_scalar = inst;
52  }
53
54  explicit RegisterValue(uint32_t inst) : m_type(eTypeUInt32) {
55    m_scalar = inst;
56  }
57
58  explicit RegisterValue(uint64_t inst) : m_type(eTypeUInt64) {
59    m_scalar = inst;
60  }
61
62  explicit RegisterValue(llvm::APInt inst) : m_type(eTypeUInt128) {
63    m_scalar = llvm::APInt(std::move(inst));
64  }
65
66  explicit RegisterValue(float value) : m_type(eTypeFloat) { m_scalar = value; }
67
68  explicit RegisterValue(double value) : m_type(eTypeDouble) {
69    m_scalar = value;
70  }
71
72  explicit RegisterValue(long double value) : m_type(eTypeLongDouble) {
73    m_scalar = value;
74  }
75
76  explicit RegisterValue(llvm::ArrayRef<uint8_t> bytes,
77                         lldb::ByteOrder byte_order) {
78    SetBytes(bytes.data(), bytes.size(), byte_order);
79  }
80
81  RegisterValue::Type GetType() const { return m_type; }
82
83  bool CopyValue(const RegisterValue &rhs);
84
85  void SetType(RegisterValue::Type type) { m_type = type; }
86
87  RegisterValue::Type SetType(const RegisterInfo &reg_info);
88
89  bool GetData(DataExtractor &data) const;
90
91  // Copy the register value from this object into a buffer in "dst" and obey
92  // the "dst_byte_order" when copying the data. Also watch out in case
93  // "dst_len" is longer or shorter than the register value described by
94  // "reg_info" and only copy the least significant bytes of the register
95  // value, or pad the destination with zeroes if the register byte size is
96  // shorter that "dst_len" (all while correctly abiding the "dst_byte_order").
97  // Returns the number of bytes copied into "dst".
98  uint32_t GetAsMemoryData(const RegisterInfo &reg_info, void *dst,
99                           uint32_t dst_len, lldb::ByteOrder dst_byte_order,
100                           Status &error) const;
101
102  uint32_t SetFromMemoryData(const RegisterInfo &reg_info, const void *src,
103                             uint32_t src_len, lldb::ByteOrder src_byte_order,
104                             Status &error);
105
106  bool GetScalarValue(Scalar &scalar) const;
107
108  uint8_t GetAsUInt8(uint8_t fail_value = UINT8_MAX,
109                     bool *success_ptr = nullptr) const {
110    if (m_type == eTypeUInt8) {
111      if (success_ptr)
112        *success_ptr = true;
113      return m_scalar.UChar(fail_value);
114    }
115    if (success_ptr)
116      *success_ptr = true;
117    return fail_value;
118  }
119
120  uint16_t GetAsUInt16(uint16_t fail_value = UINT16_MAX,
121                       bool *success_ptr = nullptr) const;
122
123  uint32_t GetAsUInt32(uint32_t fail_value = UINT32_MAX,
124                       bool *success_ptr = nullptr) const;
125
126  uint64_t GetAsUInt64(uint64_t fail_value = UINT64_MAX,
127                       bool *success_ptr = nullptr) const;
128
129  llvm::APInt GetAsUInt128(const llvm::APInt &fail_value,
130                           bool *success_ptr = nullptr) const;
131
132  float GetAsFloat(float fail_value = 0.0f, bool *success_ptr = nullptr) const;
133
134  double GetAsDouble(double fail_value = 0.0,
135                     bool *success_ptr = nullptr) const;
136
137  long double GetAsLongDouble(long double fail_value = 0.0,
138                              bool *success_ptr = nullptr) const;
139
140  void SetValueToInvalid() { m_type = eTypeInvalid; }
141
142  bool ClearBit(uint32_t bit);
143
144  bool SetBit(uint32_t bit);
145
146  bool operator==(const RegisterValue &rhs) const;
147
148  bool operator!=(const RegisterValue &rhs) const;
149
150  void operator=(uint8_t uint) {
151    m_type = eTypeUInt8;
152    m_scalar = uint;
153  }
154
155  void operator=(uint16_t uint) {
156    m_type = eTypeUInt16;
157    m_scalar = uint;
158  }
159
160  void operator=(uint32_t uint) {
161    m_type = eTypeUInt32;
162    m_scalar = uint;
163  }
164
165  void operator=(uint64_t uint) {
166    m_type = eTypeUInt64;
167    m_scalar = uint;
168  }
169
170  void operator=(llvm::APInt uint) {
171    m_type = eTypeUInt128;
172    m_scalar = llvm::APInt(std::move(uint));
173  }
174
175  void operator=(float f) {
176    m_type = eTypeFloat;
177    m_scalar = f;
178  }
179
180  void operator=(double f) {
181    m_type = eTypeDouble;
182    m_scalar = f;
183  }
184
185  void operator=(long double f) {
186    m_type = eTypeLongDouble;
187    m_scalar = f;
188  }
189
190  void SetUInt8(uint8_t uint) {
191    m_type = eTypeUInt8;
192    m_scalar = uint;
193  }
194
195  void SetUInt16(uint16_t uint) {
196    m_type = eTypeUInt16;
197    m_scalar = uint;
198  }
199
200  void SetUInt32(uint32_t uint, Type t = eTypeUInt32) {
201    m_type = t;
202    m_scalar = uint;
203  }
204
205  void SetUInt64(uint64_t uint, Type t = eTypeUInt64) {
206    m_type = t;
207    m_scalar = uint;
208  }
209
210  void SetUInt128(llvm::APInt uint) {
211    m_type = eTypeUInt128;
212    m_scalar = std::move(uint);
213  }
214
215  bool SetUInt(uint64_t uint, uint32_t byte_size);
216
217  void SetFloat(float f) {
218    m_type = eTypeFloat;
219    m_scalar = f;
220  }
221
222  void SetDouble(double f) {
223    m_type = eTypeDouble;
224    m_scalar = f;
225  }
226
227  void SetLongDouble(long double f) {
228    m_type = eTypeLongDouble;
229    m_scalar = f;
230  }
231
232  void SetBytes(const void *bytes, size_t length, lldb::ByteOrder byte_order);
233
234  bool SignExtend(uint32_t sign_bitpos);
235
236  Status SetValueFromString(const RegisterInfo *reg_info,
237                            llvm::StringRef value_str);
238  Status SetValueFromString(const RegisterInfo *reg_info,
239                            const char *value_str) = delete;
240
241  Status SetValueFromData(const RegisterInfo &reg_info, DataExtractor &data,
242                          lldb::offset_t offset, bool partial_data_ok);
243
244  const void *GetBytes() const;
245
246  lldb::ByteOrder GetByteOrder() const {
247    if (m_type == eTypeBytes)
248      return buffer.byte_order;
249    return endian::InlHostByteOrder();
250  }
251
252  uint32_t GetByteSize() const;
253
254  static uint32_t GetMaxByteSize() { return kMaxRegisterByteSize; }
255
256  void Clear();
257
258protected:
259  RegisterValue::Type m_type = eTypeInvalid;
260  Scalar m_scalar;
261
262  struct {
263    mutable uint8_t
264        bytes[kMaxRegisterByteSize]; // This must be big enough to hold any
265                                     // register for any supported target.
266    uint16_t length = 0;
267    lldb::ByteOrder byte_order = lldb::eByteOrderInvalid;
268  } buffer;
269};
270
271} // namespace lldb_private
272
273#endif // LLDB_UTILITY_REGISTERVALUE_H
274