1//===-- Scalar.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_SCALAR_H 10#define LLDB_UTILITY_SCALAR_H 11 12#include "lldb/Utility/Status.h" 13#include "lldb/lldb-enumerations.h" 14#include "lldb/lldb-private-types.h" 15#include "lldb/Utility/LLDBAssert.h" 16#include "llvm/ADT/APFloat.h" 17#include "llvm/ADT/APInt.h" 18#include <cstddef> 19#include <cstdint> 20 21namespace lldb_private { 22class DataExtractor; 23class Stream; 24} // namespace lldb_private 25 26#define NUM_OF_WORDS_INT128 2 27#define BITWIDTH_INT128 128 28#define NUM_OF_WORDS_INT256 4 29#define BITWIDTH_INT256 256 30#define NUM_OF_WORDS_INT512 8 31#define BITWIDTH_INT512 512 32 33namespace lldb_private { 34 35// A class designed to hold onto values and their corresponding types. 36// Operators are defined and Scalar objects will correctly promote their types 37// and values before performing these operations. Type promotion currently 38// follows the ANSI C type promotion rules. 39class Scalar { 40public: 41 // FIXME: These are host types which seems to be an odd choice. 42 enum Type { 43 e_void = 0, 44 e_sint, 45 e_uint, 46 e_slong, 47 e_ulong, 48 e_slonglong, 49 e_ulonglong, 50 e_sint128, 51 e_uint128, 52 e_sint256, 53 e_uint256, 54 e_sint512, 55 e_uint512, 56 e_float, 57 e_double, 58 e_long_double 59 }; 60 61 // Constructors and Destructors 62 Scalar(); 63 Scalar(int v) : m_type(e_sint), m_float(static_cast<float>(0)) { 64 m_integer = llvm::APInt(sizeof(int) * 8, v, true); 65 } 66 Scalar(unsigned int v) : m_type(e_uint), m_float(static_cast<float>(0)) { 67 m_integer = llvm::APInt(sizeof(int) * 8, v); 68 } 69 Scalar(long v) : m_type(e_slong), m_float(static_cast<float>(0)) { 70 m_integer = llvm::APInt(sizeof(long) * 8, v, true); 71 } 72 Scalar(unsigned long v) : m_type(e_ulong), m_float(static_cast<float>(0)) { 73 m_integer = llvm::APInt(sizeof(long) * 8, v); 74 } 75 Scalar(long long v) : m_type(e_slonglong), m_float(static_cast<float>(0)) { 76 m_integer = llvm::APInt(sizeof(long long) * 8, v, true); 77 } 78 Scalar(unsigned long long v) 79 : m_type(e_ulonglong), m_float(static_cast<float>(0)) { 80 m_integer = llvm::APInt(sizeof(long long) * 8, v); 81 } 82 Scalar(float v) : m_type(e_float), m_float(v) { m_float = llvm::APFloat(v); } 83 Scalar(double v) : m_type(e_double), m_float(v) { 84 m_float = llvm::APFloat(v); 85 } 86 Scalar(long double v, bool ieee_quad) 87 : m_type(e_long_double), m_float(static_cast<float>(0)), 88 m_ieee_quad(ieee_quad) { 89 if (ieee_quad) 90 m_float = 91 llvm::APFloat(llvm::APFloat::IEEEquad(), 92 llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, 93 (reinterpret_cast<type128 *>(&v))->x)); 94 else 95 m_float = 96 llvm::APFloat(llvm::APFloat::x87DoubleExtended(), 97 llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, 98 (reinterpret_cast<type128 *>(&v))->x)); 99 } 100 Scalar(llvm::APInt v) : m_type(), m_float(static_cast<float>(0)) { 101 m_integer = llvm::APInt(v); 102 m_type = GetBestTypeForBitSize(m_integer.getBitWidth(), true); 103 } 104 // Scalar(const RegisterValue& reg_value); 105 virtual ~Scalar(); 106 107 /// Return the most efficient Scalar::Type for the requested bit size. 108 static Type GetBestTypeForBitSize(size_t bit_size, bool sign); 109 110 bool SignExtend(uint32_t bit_pos); 111 112 bool ExtractBitfield(uint32_t bit_size, uint32_t bit_offset); 113 114 bool SetBit(uint32_t bit); 115 116 bool ClearBit(uint32_t bit); 117 118 const void *GetBytes() const; 119 120 size_t GetByteSize() const; 121 122 bool GetData(DataExtractor &data, size_t limit_byte_size = UINT32_MAX) const; 123 124 size_t GetAsMemoryData(void *dst, size_t dst_len, 125 lldb::ByteOrder dst_byte_order, Status &error) const; 126 127 bool IsZero() const; 128 129 void Clear() { 130 m_type = e_void; 131 m_integer.clearAllBits(); 132 } 133 134 const char *GetTypeAsCString() const; 135 136 void GetValue(Stream *s, bool show_type) const; 137 138 bool IsValid() const { 139 return (m_type >= e_sint) && (m_type <= e_long_double); 140 } 141 142 /// Convert integer to \p type, limited to \p bits size. 143 void TruncOrExtendTo(Scalar::Type type, uint16_t bits); 144 145 bool Promote(Scalar::Type type); 146 147 bool MakeSigned(); 148 149 bool MakeUnsigned(); 150 151 static const char *GetValueTypeAsCString(Scalar::Type value_type); 152 153 static Scalar::Type 154 GetValueTypeForSignedIntegerWithByteSize(size_t byte_size); 155 156 static Scalar::Type 157 GetValueTypeForUnsignedIntegerWithByteSize(size_t byte_size); 158 159 static Scalar::Type GetValueTypeForFloatWithByteSize(size_t byte_size); 160 161 // All operators can benefits from the implicit conversions that will happen 162 // automagically by the compiler, so no temporary objects will need to be 163 // created. As a result, we currently don't need a variety of overloaded set 164 // value accessors. 165 Scalar &operator=(const int i); 166 Scalar &operator=(unsigned int v); 167 Scalar &operator=(long v); 168 Scalar &operator=(unsigned long v); 169 Scalar &operator=(long long v); 170 Scalar &operator=(unsigned long long v); 171 Scalar &operator=(float v); 172 Scalar &operator=(double v); 173 Scalar &operator=(long double v); 174 Scalar &operator=(llvm::APInt v); 175 Scalar &operator+=(const Scalar &rhs); 176 Scalar &operator<<=(const Scalar &rhs); // Shift left 177 Scalar &operator>>=(const Scalar &rhs); // Shift right (arithmetic) 178 Scalar &operator&=(const Scalar &rhs); 179 180 // Shifts the current value to the right without maintaining the current sign 181 // of the value (if it is signed). 182 bool ShiftRightLogical(const Scalar &rhs); // Returns true on success 183 184 // Takes the absolute value of the current value if it is signed, else the 185 // value remains unchanged. Returns false if the contained value has a void 186 // type. 187 bool AbsoluteValue(); // Returns true on success 188 // Negates the current value (even for unsigned values). Returns false if the 189 // contained value has a void type. 190 bool UnaryNegate(); // Returns true on success 191 // Inverts all bits in the current value as long as it isn't void or a 192 // float/double/long double type. Returns false if the contained value has a 193 // void/float/double/long double type, else the value is inverted and true is 194 // returned. 195 bool OnesComplement(); // Returns true on success 196 197 // Access the type of the current value. 198 Scalar::Type GetType() const { return m_type; } 199 200 // Returns a casted value of the current contained data without modifying the 201 // current value. FAIL_VALUE will be returned if the type of the value is 202 // void or invalid. 203 int SInt(int fail_value = 0) const; 204 205 unsigned char UChar(unsigned char fail_value = 0) const; 206 207 signed char SChar(char fail_value = 0) const; 208 209 unsigned short UShort(unsigned short fail_value = 0) const; 210 211 short SShort(short fail_value = 0) const; 212 213 unsigned int UInt(unsigned int fail_value = 0) const; 214 215 long SLong(long fail_value = 0) const; 216 217 unsigned long ULong(unsigned long fail_value = 0) const; 218 219 long long SLongLong(long long fail_value = 0) const; 220 221 unsigned long long ULongLong(unsigned long long fail_value = 0) const; 222 223 llvm::APInt SInt128(llvm::APInt &fail_value) const; 224 225 llvm::APInt UInt128(const llvm::APInt &fail_value) const; 226 227 float Float(float fail_value = 0.0f) const; 228 229 double Double(double fail_value = 0.0) const; 230 231 long double LongDouble(long double fail_value = 0.0) const; 232 233 Status SetValueFromCString(const char *s, lldb::Encoding encoding, 234 size_t byte_size); 235 236 Status SetValueFromData(DataExtractor &data, lldb::Encoding encoding, 237 size_t byte_size); 238 239 static bool UIntValueIsValidForSize(uint64_t uval64, size_t total_byte_size) { 240 if (total_byte_size > 8) 241 return false; 242 243 if (total_byte_size == 8) 244 return true; 245 246 const uint64_t max = (static_cast<uint64_t>(1) 247 << static_cast<uint64_t>(total_byte_size * 8)) - 248 1; 249 return uval64 <= max; 250 } 251 252 static bool SIntValueIsValidForSize(int64_t sval64, size_t total_byte_size) { 253 if (total_byte_size > 8) 254 return false; 255 256 if (total_byte_size == 8) 257 return true; 258 259 const int64_t max = (static_cast<int64_t>(1) 260 << static_cast<uint64_t>(total_byte_size * 8 - 1)) - 261 1; 262 const int64_t min = ~(max); 263 return min <= sval64 && sval64 <= max; 264 } 265 266protected: 267 typedef char schar_t; 268 typedef unsigned char uchar_t; 269 typedef short sshort_t; 270 typedef unsigned short ushort_t; 271 typedef int sint_t; 272 typedef unsigned int uint_t; 273 typedef long slong_t; 274 typedef unsigned long ulong_t; 275 typedef long long slonglong_t; 276 typedef unsigned long long ulonglong_t; 277 typedef float float_t; 278 typedef double double_t; 279 typedef long double long_double_t; 280 281 // Classes that inherit from Scalar can see and modify these 282 Scalar::Type m_type; 283 llvm::APInt m_integer; 284 llvm::APFloat m_float; 285 bool m_ieee_quad = false; 286 287private: 288 friend const Scalar operator+(const Scalar &lhs, const Scalar &rhs); 289 friend const Scalar operator-(const Scalar &lhs, const Scalar &rhs); 290 friend const Scalar operator/(const Scalar &lhs, const Scalar &rhs); 291 friend const Scalar operator*(const Scalar &lhs, const Scalar &rhs); 292 friend const Scalar operator&(const Scalar &lhs, const Scalar &rhs); 293 friend const Scalar operator|(const Scalar &lhs, const Scalar &rhs); 294 friend const Scalar operator%(const Scalar &lhs, const Scalar &rhs); 295 friend const Scalar operator^(const Scalar &lhs, const Scalar &rhs); 296 friend const Scalar operator<<(const Scalar &lhs, const Scalar &rhs); 297 friend const Scalar operator>>(const Scalar &lhs, const Scalar &rhs); 298 friend bool operator==(const Scalar &lhs, const Scalar &rhs); 299 friend bool operator!=(const Scalar &lhs, const Scalar &rhs); 300 friend bool operator<(const Scalar &lhs, const Scalar &rhs); 301 friend bool operator<=(const Scalar &lhs, const Scalar &rhs); 302 friend bool operator>(const Scalar &lhs, const Scalar &rhs); 303 friend bool operator>=(const Scalar &lhs, const Scalar &rhs); 304}; 305 306// Split out the operators into a format where the compiler will be able to 307// implicitly convert numbers into Scalar objects. 308// 309// This allows code like: 310// Scalar two(2); 311// Scalar four = two * 2; 312// Scalar eight = 2 * four; // This would cause an error if the 313// // operator* was implemented as a 314// // member function. 315// SEE: 316// Item 19 of "Effective C++ Second Edition" by Scott Meyers 317// Differentiate among members functions, non-member functions, and 318// friend functions 319const Scalar operator+(const Scalar &lhs, const Scalar &rhs); 320const Scalar operator-(const Scalar &lhs, const Scalar &rhs); 321const Scalar operator/(const Scalar &lhs, const Scalar &rhs); 322const Scalar operator*(const Scalar &lhs, const Scalar &rhs); 323const Scalar operator&(const Scalar &lhs, const Scalar &rhs); 324const Scalar operator|(const Scalar &lhs, const Scalar &rhs); 325const Scalar operator%(const Scalar &lhs, const Scalar &rhs); 326const Scalar operator^(const Scalar &lhs, const Scalar &rhs); 327const Scalar operator<<(const Scalar &lhs, const Scalar &rhs); 328const Scalar operator>>(const Scalar &lhs, const Scalar &rhs); 329bool operator==(const Scalar &lhs, const Scalar &rhs); 330bool operator!=(const Scalar &lhs, const Scalar &rhs); 331bool operator<(const Scalar &lhs, const Scalar &rhs); 332bool operator<=(const Scalar &lhs, const Scalar &rhs); 333bool operator>(const Scalar &lhs, const Scalar &rhs); 334bool operator>=(const Scalar &lhs, const Scalar &rhs); 335 336llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const Scalar &scalar); 337 338} // namespace lldb_private 339 340#endif // LLDB_UTILITY_SCALAR_H 341