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