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