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 
RegisterValue()56   RegisterValue() : m_scalar(static_cast<unsigned long>(0)) {}
57 
RegisterValue(uint8_t inst)58   explicit RegisterValue(uint8_t inst) : m_type(eTypeUInt8) { m_scalar = inst; }
59 
RegisterValue(uint16_t inst)60   explicit RegisterValue(uint16_t inst) : m_type(eTypeUInt16) {
61     m_scalar = inst;
62   }
63 
RegisterValue(uint32_t inst)64   explicit RegisterValue(uint32_t inst) : m_type(eTypeUInt32) {
65     m_scalar = inst;
66   }
67 
RegisterValue(uint64_t inst)68   explicit RegisterValue(uint64_t inst) : m_type(eTypeUInt64) {
69     m_scalar = inst;
70   }
71 
RegisterValue(llvm::APInt inst)72   explicit RegisterValue(llvm::APInt inst) : m_type(eTypeUInt128) {
73     m_scalar = llvm::APInt(std::move(inst));
74   }
75 
RegisterValue(float value)76   explicit RegisterValue(float value) : m_type(eTypeFloat) { m_scalar = value; }
77 
RegisterValue(double value)78   explicit RegisterValue(double value) : m_type(eTypeDouble) {
79     m_scalar = value;
80   }
81 
RegisterValue(long double value)82   explicit RegisterValue(long double value) : m_type(eTypeLongDouble) {
83     m_scalar = value;
84   }
85 
RegisterValue(llvm::ArrayRef<uint8_t> bytes,lldb::ByteOrder byte_order)86   explicit RegisterValue(llvm::ArrayRef<uint8_t> bytes,
87                          lldb::ByteOrder byte_order) {
88     SetBytes(bytes.data(), bytes.size(), byte_order);
89   }
90 
GetType()91   RegisterValue::Type GetType() const { return m_type; }
92 
93   bool CopyValue(const RegisterValue &rhs);
94 
SetType(RegisterValue::Type type)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 
SetValueToInvalid()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 
SetUInt8(uint8_t uint)200   void SetUInt8(uint8_t uint) {
201     m_type = eTypeUInt8;
202     m_scalar = uint;
203   }
204 
SetUInt16(uint16_t uint)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 
SetUInt128(llvm::APInt uint)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 
SetFloat(float f)227   void SetFloat(float f) {
228     m_type = eTypeFloat;
229     m_scalar = f;
230   }
231 
SetDouble(double f)232   void SetDouble(double f) {
233     m_type = eTypeDouble;
234     m_scalar = f;
235   }
236 
SetLongDouble(long double f)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 
GetByteOrder()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.
RegisterValueBufferRegisterValueBuffer272     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