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 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 lldb::ByteOrder byte_order) { 88 SetBytes(bytes.data(), bytes.size(), byte_order); 89 } 90 91 RegisterValue::Type GetType() const { return m_type; } 92 93 bool CopyValue(const RegisterValue &rhs); 94 95 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 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 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 200 void SetUInt8(uint8_t uint) { 201 m_type = eTypeUInt8; 202 m_scalar = uint; 203 } 204 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 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 227 void SetFloat(float f) { 228 m_type = eTypeFloat; 229 m_scalar = f; 230 } 231 232 void SetDouble(double f) { 233 m_type = eTypeDouble; 234 m_scalar = f; 235 } 236 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 ®_info, DataExtractor &data, 252 lldb::offset_t offset, bool partial_data_ok); 253 254 const void *GetBytes() const; 255 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. 272 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