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

source code of lldb/include/lldb/Utility/RegisterValue.h