/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/include/lldb/Utility/RegisterValue.h
Line | Count | Source (jump to first uncovered line) |
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 DataExtractor; |
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 | 1.51M | 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 | 4 | lldb::ByteOrder byte_order) { |
88 | 4 | SetBytes(bytes.data(), bytes.size(), byte_order); |
89 | 4 | } |
90 | | |
91 | 177k | RegisterValue::Type GetType() const { return m_type; } |
92 | | |
93 | | bool CopyValue(const RegisterValue &rhs); |
94 | | |
95 | 0 | void SetType(RegisterValue::Type type) { m_type = type; } |
96 | | |
97 | | RegisterValue::Type SetType(const RegisterInfo ®_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 ®_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 | 2 | bool *success_ptr = nullptr) const { |
120 | 2 | if (m_type == eTypeUInt8) { |
121 | 2 | if (success_ptr) |
122 | 0 | *success_ptr = true; |
123 | 2 | return m_scalar.UChar(fail_value); |
124 | 2 | } |
125 | 0 | if (success_ptr) |
126 | 0 | *success_ptr = true; |
127 | 0 | return fail_value; |
128 | 2 | } |
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 | 0 | 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 | 1 | void operator=(uint8_t uint) { |
161 | 1 | m_type = eTypeUInt8; |
162 | 1 | m_scalar = uint; |
163 | 1 | } |
164 | | |
165 | 0 | void operator=(uint16_t uint) { |
166 | 0 | m_type = eTypeUInt16; |
167 | 0 | m_scalar = uint; |
168 | 0 | } |
169 | | |
170 | 0 | void operator=(uint32_t uint) { |
171 | 0 | m_type = eTypeUInt32; |
172 | 0 | m_scalar = uint; |
173 | 0 | } |
174 | | |
175 | 178k | void operator=(uint64_t uint) { |
176 | 178k | m_type = eTypeUInt64; |
177 | 178k | m_scalar = uint; |
178 | 178k | } |
179 | | |
180 | 0 | void operator=(llvm::APInt uint) { |
181 | 0 | m_type = eTypeUInt128; |
182 | 0 | m_scalar = llvm::APInt(std::move(uint)); |
183 | 0 | } |
184 | | |
185 | 0 | void operator=(float f) { |
186 | 0 | m_type = eTypeFloat; |
187 | 0 | m_scalar = f; |
188 | 0 | } |
189 | | |
190 | 0 | void operator=(double f) { |
191 | 0 | m_type = eTypeDouble; |
192 | 0 | m_scalar = f; |
193 | 0 | } |
194 | | |
195 | 0 | void operator=(long double f) { |
196 | 0 | m_type = eTypeLongDouble; |
197 | 0 | m_scalar = f; |
198 | 0 | } |
199 | | |
200 | 907 | void SetUInt8(uint8_t uint) { |
201 | 907 | m_type = eTypeUInt8; |
202 | 907 | m_scalar = uint; |
203 | 907 | } |
204 | | |
205 | 1.02k | void SetUInt16(uint16_t uint) { |
206 | 1.02k | m_type = eTypeUInt16; |
207 | 1.02k | m_scalar = uint; |
208 | 1.02k | } |
209 | | |
210 | 2.96k | void SetUInt32(uint32_t uint, Type t = eTypeUInt32) { |
211 | 2.96k | m_type = t; |
212 | 2.96k | m_scalar = uint; |
213 | 2.96k | } |
214 | | |
215 | 1.01M | void SetUInt64(uint64_t uint, Type t = eTypeUInt64) { |
216 | 1.01M | m_type = t; |
217 | 1.01M | m_scalar = uint; |
218 | 1.01M | } |
219 | | |
220 | 0 | void SetUInt128(llvm::APInt uint) { |
221 | 0 | m_type = eTypeUInt128; |
222 | 0 | m_scalar = std::move(uint); |
223 | 0 | } |
224 | | |
225 | | bool SetUInt(uint64_t uint, uint32_t byte_size); |
226 | | |
227 | 311 | void SetFloat(float f) { |
228 | 311 | m_type = eTypeFloat; |
229 | 311 | m_scalar = f; |
230 | 311 | } |
231 | | |
232 | 259 | void SetDouble(double f) { |
233 | 259 | m_type = eTypeDouble; |
234 | 259 | m_scalar = f; |
235 | 259 | } |
236 | | |
237 | 0 | void SetLongDouble(long double f) { |
238 | 0 | m_type = eTypeLongDouble; |
239 | 0 | m_scalar = f; |
240 | 0 | } |
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 ®_info, DataExtractor &data, |
252 | | lldb::offset_t offset, bool partial_data_ok); |
253 | | |
254 | | const void *GetBytes() const; |
255 | | |
256 | 19.0k | lldb::ByteOrder GetByteOrder() const { |
257 | 19.0k | if (m_type == eTypeBytes) |
258 | 2.56k | return buffer.byte_order; |
259 | 16.5k | return endian::InlHostByteOrder(); |
260 | 19.0k | } |
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 | 1.51M | 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 |