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 
23 namespace lldb_private {
24 class DataExtractor;
25 class Stream;
26 struct RegisterInfo;
27 
28 class RegisterValue {
29 public:
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 
RegisterValue()46   RegisterValue()
47       : m_type(eTypeInvalid), m_scalar(static_cast<unsigned long>(0)) {}
48 
RegisterValue(uint8_t inst)49   explicit RegisterValue(uint8_t inst) : m_type(eTypeUInt8) { m_scalar = inst; }
50 
RegisterValue(uint16_t inst)51   explicit RegisterValue(uint16_t inst) : m_type(eTypeUInt16) {
52     m_scalar = inst;
53   }
54 
RegisterValue(uint32_t inst)55   explicit RegisterValue(uint32_t inst) : m_type(eTypeUInt32) {
56     m_scalar = inst;
57   }
58 
RegisterValue(uint64_t inst)59   explicit RegisterValue(uint64_t inst) : m_type(eTypeUInt64) {
60     m_scalar = inst;
61   }
62 
RegisterValue(llvm::APInt inst)63   explicit RegisterValue(llvm::APInt inst) : m_type(eTypeUInt128) {
64     m_scalar = llvm::APInt(std::move(inst));
65   }
66 
RegisterValue(float value)67   explicit RegisterValue(float value) : m_type(eTypeFloat) { m_scalar = value; }
68 
RegisterValue(double value)69   explicit RegisterValue(double value) : m_type(eTypeDouble) {
70     m_scalar = value;
71   }
72 
RegisterValue(long double value)73   explicit RegisterValue(long double value) : m_type(eTypeLongDouble) {
74     m_scalar = value;
75   }
76 
RegisterValue(llvm::ArrayRef<uint8_t> bytes,lldb::ByteOrder byte_order)77   explicit RegisterValue(llvm::ArrayRef<uint8_t> bytes,
78                          lldb::ByteOrder byte_order) {
79     SetBytes(bytes.data(), bytes.size(), byte_order);
80   }
81 
GetType()82   RegisterValue::Type GetType() const { return m_type; }
83 
84   bool CopyValue(const RegisterValue &rhs);
85 
SetType(RegisterValue::Type type)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 
SetValueToInvalid()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 
SetUInt8(uint8_t uint)191   void SetUInt8(uint8_t uint) {
192     m_type = eTypeUInt8;
193     m_scalar = uint;
194   }
195 
SetUInt16(uint16_t uint)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 
SetUInt128(llvm::APInt uint)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 
SetFloat(float f)218   void SetFloat(float f) {
219     m_type = eTypeFloat;
220     m_scalar = f;
221   }
222 
SetDouble(double f)223   void SetDouble(double f) {
224     m_type = eTypeDouble;
225     m_scalar = f;
226   }
227 
SetLongDouble(long double f)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 
GetByteOrder()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 
GetMaxByteSize()255   static uint32_t GetMaxByteSize() { return kMaxRegisterByteSize; }
256 
257   void Clear();
258 
259 protected:
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