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