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 | |
24 | namespace lldb_private { |
25 | class ; |
26 | class Stream; |
27 | struct RegisterInfo; |
28 | |
29 | class RegisterValue { |
30 | public: |
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 ®_info); |
98 | |
99 | bool (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 ®_info, void *dst, |
109 | uint32_t dst_len, lldb::ByteOrder dst_byte_order, |
110 | Status &error) const; |
111 | |
112 | uint32_t SetFromMemoryData(const RegisterInfo ®_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 (const RegisterInfo ®_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 | |
266 | protected: |
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 | |