Scalar.h revision 343181
1343181Sdim//===-- Scalar.h ------------------------------------------------*- C++ -*-===// 2343181Sdim// 3343181Sdim// The LLVM Compiler Infrastructure 4343181Sdim// 5343181Sdim// This file is distributed under the University of Illinois Open Source 6343181Sdim// License. See LICENSE.TXT for details. 7343181Sdim// 8343181Sdim//===----------------------------------------------------------------------===// 9343181Sdim 10343181Sdim#ifndef LLDB_UTILITY_SCALAR_H 11343181Sdim#define LLDB_UTILITY_SCALAR_H 12343181Sdim 13343181Sdim#include "lldb/Utility/Status.h" 14343181Sdim#include "lldb/lldb-enumerations.h" 15343181Sdim#include "lldb/lldb-private-types.h" 16343181Sdim#include "llvm/ADT/APFloat.h" 17343181Sdim#include "llvm/ADT/APInt.h" 18343181Sdim#include <cstddef> 19343181Sdim#include <cstdint> 20343181Sdim 21343181Sdimnamespace lldb_private { 22343181Sdimclass DataExtractor; 23343181Sdimclass Stream; 24343181Sdim} // namespace lldb_private 25343181Sdim 26343181Sdim#define NUM_OF_WORDS_INT128 2 27343181Sdim#define BITWIDTH_INT128 128 28343181Sdim#define NUM_OF_WORDS_INT256 4 29343181Sdim#define BITWIDTH_INT256 256 30343181Sdim 31343181Sdimnamespace lldb_private { 32343181Sdim 33343181Sdim//---------------------------------------------------------------------- 34343181Sdim// A class designed to hold onto values and their corresponding types. 35343181Sdim// Operators are defined and Scalar objects will correctly promote their types 36343181Sdim// and values before performing these operations. Type promotion currently 37343181Sdim// follows the ANSI C type promotion rules. 38343181Sdim//---------------------------------------------------------------------- 39343181Sdimclass Scalar { 40343181Sdimpublic: 41343181Sdim enum Type { 42343181Sdim e_void = 0, 43343181Sdim e_sint, 44343181Sdim e_uint, 45343181Sdim e_slong, 46343181Sdim e_ulong, 47343181Sdim e_slonglong, 48343181Sdim e_ulonglong, 49343181Sdim e_sint128, 50343181Sdim e_uint128, 51343181Sdim e_sint256, 52343181Sdim e_uint256, 53343181Sdim e_float, 54343181Sdim e_double, 55343181Sdim e_long_double 56343181Sdim }; 57343181Sdim 58343181Sdim //------------------------------------------------------------------ 59343181Sdim // Constructors and Destructors 60343181Sdim //------------------------------------------------------------------ 61343181Sdim Scalar(); 62343181Sdim Scalar(int v) : m_type(e_sint), m_float((float)0) { 63343181Sdim m_integer = llvm::APInt(sizeof(int) * 8, v, true); 64343181Sdim } 65343181Sdim Scalar(unsigned int v) : m_type(e_uint), m_float((float)0) { 66343181Sdim m_integer = llvm::APInt(sizeof(int) * 8, v); 67343181Sdim } 68343181Sdim Scalar(long v) : m_type(e_slong), m_float((float)0) { 69343181Sdim m_integer = llvm::APInt(sizeof(long) * 8, v, true); 70343181Sdim } 71343181Sdim Scalar(unsigned long v) : m_type(e_ulong), m_float((float)0) { 72343181Sdim m_integer = llvm::APInt(sizeof(long) * 8, v); 73343181Sdim } 74343181Sdim Scalar(long long v) : m_type(e_slonglong), m_float((float)0) { 75343181Sdim m_integer = llvm::APInt(sizeof(long long) * 8, v, true); 76343181Sdim } 77343181Sdim Scalar(unsigned long long v) : m_type(e_ulonglong), m_float((float)0) { 78343181Sdim m_integer = llvm::APInt(sizeof(long long) * 8, v); 79343181Sdim } 80343181Sdim Scalar(float v) : m_type(e_float), m_float(v) { m_float = llvm::APFloat(v); } 81343181Sdim Scalar(double v) : m_type(e_double), m_float(v) { 82343181Sdim m_float = llvm::APFloat(v); 83343181Sdim } 84343181Sdim Scalar(long double v, bool ieee_quad) 85343181Sdim : m_type(e_long_double), m_float((float)0), m_ieee_quad(ieee_quad) { 86343181Sdim if (ieee_quad) 87343181Sdim m_float = llvm::APFloat(llvm::APFloat::IEEEquad(), 88343181Sdim llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, 89343181Sdim ((type128 *)&v)->x)); 90343181Sdim else 91343181Sdim m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(), 92343181Sdim llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, 93343181Sdim ((type128 *)&v)->x)); 94343181Sdim } 95343181Sdim Scalar(llvm::APInt v) : m_type(), m_float((float)0) { 96343181Sdim m_integer = llvm::APInt(v); 97343181Sdim switch (m_integer.getBitWidth()) { 98343181Sdim case 8: 99343181Sdim case 16: 100343181Sdim case 32: 101343181Sdim if (m_integer.isSignedIntN(sizeof(sint_t) * 8)) 102343181Sdim m_type = e_sint; 103343181Sdim else 104343181Sdim m_type = e_uint; 105343181Sdim break; 106343181Sdim case 64: 107343181Sdim if (m_integer.isSignedIntN(sizeof(slonglong_t) * 8)) 108343181Sdim m_type = e_slonglong; 109343181Sdim else 110343181Sdim m_type = e_ulonglong; 111343181Sdim break; 112343181Sdim case 128: 113343181Sdim if (m_integer.isSignedIntN(BITWIDTH_INT128)) 114343181Sdim m_type = e_sint128; 115343181Sdim else 116343181Sdim m_type = e_uint128; 117343181Sdim break; 118343181Sdim case 256: 119343181Sdim if (m_integer.isSignedIntN(BITWIDTH_INT256)) 120343181Sdim m_type = e_sint256; 121343181Sdim else 122343181Sdim m_type = e_uint256; 123343181Sdim break; 124343181Sdim } 125343181Sdim } 126343181Sdim Scalar(const Scalar &rhs); 127343181Sdim // Scalar(const RegisterValue& reg_value); 128343181Sdim virtual ~Scalar(); 129343181Sdim 130343181Sdim bool SignExtend(uint32_t bit_pos); 131343181Sdim 132343181Sdim bool ExtractBitfield(uint32_t bit_size, uint32_t bit_offset); 133343181Sdim 134343181Sdim bool SetBit(uint32_t bit); 135343181Sdim 136343181Sdim bool ClearBit(uint32_t bit); 137343181Sdim 138343181Sdim const void *GetBytes() const; 139343181Sdim 140343181Sdim size_t GetByteSize() const; 141343181Sdim 142343181Sdim bool GetData(DataExtractor &data, size_t limit_byte_size = UINT32_MAX) const; 143343181Sdim 144343181Sdim size_t GetAsMemoryData(void *dst, size_t dst_len, 145343181Sdim lldb::ByteOrder dst_byte_order, Status &error) const; 146343181Sdim 147343181Sdim bool IsZero() const; 148343181Sdim 149343181Sdim void Clear() { 150343181Sdim m_type = e_void; 151343181Sdim m_integer.clearAllBits(); 152343181Sdim } 153343181Sdim 154343181Sdim const char *GetTypeAsCString() const; 155343181Sdim 156343181Sdim void GetValue(Stream *s, bool show_type) const; 157343181Sdim 158343181Sdim bool IsValid() const { 159343181Sdim return (m_type >= e_sint) && (m_type <= e_long_double); 160343181Sdim } 161343181Sdim 162343181Sdim bool Promote(Scalar::Type type); 163343181Sdim 164343181Sdim bool MakeSigned(); 165343181Sdim 166343181Sdim bool MakeUnsigned(); 167343181Sdim 168343181Sdim static const char *GetValueTypeAsCString(Scalar::Type value_type); 169343181Sdim 170343181Sdim static Scalar::Type 171343181Sdim GetValueTypeForSignedIntegerWithByteSize(size_t byte_size); 172343181Sdim 173343181Sdim static Scalar::Type 174343181Sdim GetValueTypeForUnsignedIntegerWithByteSize(size_t byte_size); 175343181Sdim 176343181Sdim static Scalar::Type GetValueTypeForFloatWithByteSize(size_t byte_size); 177343181Sdim 178343181Sdim //---------------------------------------------------------------------- 179343181Sdim // All operators can benefits from the implicit conversions that will happen 180343181Sdim // automagically by the compiler, so no temporary objects will need to be 181343181Sdim // created. As a result, we currently don't need a variety of overloaded set 182343181Sdim // value accessors. 183343181Sdim //---------------------------------------------------------------------- 184343181Sdim Scalar &operator=(const int i); 185343181Sdim Scalar &operator=(unsigned int v); 186343181Sdim Scalar &operator=(long v); 187343181Sdim Scalar &operator=(unsigned long v); 188343181Sdim Scalar &operator=(long long v); 189343181Sdim Scalar &operator=(unsigned long long v); 190343181Sdim Scalar &operator=(float v); 191343181Sdim Scalar &operator=(double v); 192343181Sdim Scalar &operator=(long double v); 193343181Sdim Scalar &operator=(llvm::APInt v); 194343181Sdim Scalar &operator=(const Scalar &rhs); // Assignment operator 195343181Sdim Scalar &operator+=(const Scalar &rhs); 196343181Sdim Scalar &operator<<=(const Scalar &rhs); // Shift left 197343181Sdim Scalar &operator>>=(const Scalar &rhs); // Shift right (arithmetic) 198343181Sdim Scalar &operator&=(const Scalar &rhs); 199343181Sdim 200343181Sdim //---------------------------------------------------------------------- 201343181Sdim // Shifts the current value to the right without maintaining the current sign 202343181Sdim // of the value (if it is signed). 203343181Sdim //---------------------------------------------------------------------- 204343181Sdim bool ShiftRightLogical(const Scalar &rhs); // Returns true on success 205343181Sdim 206343181Sdim //---------------------------------------------------------------------- 207343181Sdim // Takes the absolute value of the current value if it is signed, else the 208343181Sdim // value remains unchanged. Returns false if the contained value has a void 209343181Sdim // type. 210343181Sdim //---------------------------------------------------------------------- 211343181Sdim bool AbsoluteValue(); // Returns true on success 212343181Sdim //---------------------------------------------------------------------- 213343181Sdim // Negates the current value (even for unsigned values). Returns false if the 214343181Sdim // contained value has a void type. 215343181Sdim //---------------------------------------------------------------------- 216343181Sdim bool UnaryNegate(); // Returns true on success 217343181Sdim //---------------------------------------------------------------------- 218343181Sdim // Inverts all bits in the current value as long as it isn't void or a 219343181Sdim // float/double/long double type. Returns false if the contained value has a 220343181Sdim // void/float/double/long double type, else the value is inverted and true is 221343181Sdim // returned. 222343181Sdim //---------------------------------------------------------------------- 223343181Sdim bool OnesComplement(); // Returns true on success 224343181Sdim 225343181Sdim //---------------------------------------------------------------------- 226343181Sdim // Access the type of the current value. 227343181Sdim //---------------------------------------------------------------------- 228343181Sdim Scalar::Type GetType() const { return m_type; } 229343181Sdim 230343181Sdim //---------------------------------------------------------------------- 231343181Sdim // Returns a casted value of the current contained data without modifying the 232343181Sdim // current value. FAIL_VALUE will be returned if the type of the value is 233343181Sdim // void or invalid. 234343181Sdim //---------------------------------------------------------------------- 235343181Sdim int SInt(int fail_value = 0) const; 236343181Sdim 237343181Sdim unsigned char UChar(unsigned char fail_value = 0) const; 238343181Sdim 239343181Sdim signed char SChar(char fail_value = 0) const; 240343181Sdim 241343181Sdim unsigned short UShort(unsigned short fail_value = 0) const; 242343181Sdim 243343181Sdim short SShort(short fail_value = 0) const; 244343181Sdim 245343181Sdim unsigned int UInt(unsigned int fail_value = 0) const; 246343181Sdim 247343181Sdim long SLong(long fail_value = 0) const; 248343181Sdim 249343181Sdim unsigned long ULong(unsigned long fail_value = 0) const; 250343181Sdim 251343181Sdim long long SLongLong(long long fail_value = 0) const; 252343181Sdim 253343181Sdim unsigned long long ULongLong(unsigned long long fail_value = 0) const; 254343181Sdim 255343181Sdim llvm::APInt SInt128(llvm::APInt &fail_value) const; 256343181Sdim 257343181Sdim llvm::APInt UInt128(const llvm::APInt &fail_value) const; 258343181Sdim 259343181Sdim llvm::APInt SInt256(llvm::APInt &fail_value) const; 260343181Sdim 261343181Sdim llvm::APInt UInt256(const llvm::APInt &fail_value) const; 262343181Sdim 263343181Sdim float Float(float fail_value = 0.0f) const; 264343181Sdim 265343181Sdim double Double(double fail_value = 0.0) const; 266343181Sdim 267343181Sdim long double LongDouble(long double fail_value = 0.0) const; 268343181Sdim 269343181Sdim Status SetValueFromCString(const char *s, lldb::Encoding encoding, 270343181Sdim size_t byte_size); 271343181Sdim 272343181Sdim Status SetValueFromData(DataExtractor &data, lldb::Encoding encoding, 273343181Sdim size_t byte_size); 274343181Sdim 275343181Sdim static bool UIntValueIsValidForSize(uint64_t uval64, size_t total_byte_size) { 276343181Sdim if (total_byte_size > 8) 277343181Sdim return false; 278343181Sdim 279343181Sdim if (total_byte_size == 8) 280343181Sdim return true; 281343181Sdim 282343181Sdim const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1; 283343181Sdim return uval64 <= max; 284343181Sdim } 285343181Sdim 286343181Sdim static bool SIntValueIsValidForSize(int64_t sval64, size_t total_byte_size) { 287343181Sdim if (total_byte_size > 8) 288343181Sdim return false; 289343181Sdim 290343181Sdim if (total_byte_size == 8) 291343181Sdim return true; 292343181Sdim 293343181Sdim const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1; 294343181Sdim const int64_t min = ~(max); 295343181Sdim return min <= sval64 && sval64 <= max; 296343181Sdim } 297343181Sdim 298343181Sdimprotected: 299343181Sdim typedef char schar_t; 300343181Sdim typedef unsigned char uchar_t; 301343181Sdim typedef short sshort_t; 302343181Sdim typedef unsigned short ushort_t; 303343181Sdim typedef int sint_t; 304343181Sdim typedef unsigned int uint_t; 305343181Sdim typedef long slong_t; 306343181Sdim typedef unsigned long ulong_t; 307343181Sdim typedef long long slonglong_t; 308343181Sdim typedef unsigned long long ulonglong_t; 309343181Sdim typedef float float_t; 310343181Sdim typedef double double_t; 311343181Sdim typedef long double long_double_t; 312343181Sdim 313343181Sdim //------------------------------------------------------------------ 314343181Sdim // Classes that inherit from Scalar can see and modify these 315343181Sdim //------------------------------------------------------------------ 316343181Sdim Scalar::Type m_type; 317343181Sdim llvm::APInt m_integer; 318343181Sdim llvm::APFloat m_float; 319343181Sdim bool m_ieee_quad = false; 320343181Sdim 321343181Sdimprivate: 322343181Sdim friend const Scalar operator+(const Scalar &lhs, const Scalar &rhs); 323343181Sdim friend const Scalar operator-(const Scalar &lhs, const Scalar &rhs); 324343181Sdim friend const Scalar operator/(const Scalar &lhs, const Scalar &rhs); 325343181Sdim friend const Scalar operator*(const Scalar &lhs, const Scalar &rhs); 326343181Sdim friend const Scalar operator&(const Scalar &lhs, const Scalar &rhs); 327343181Sdim friend const Scalar operator|(const Scalar &lhs, const Scalar &rhs); 328343181Sdim friend const Scalar operator%(const Scalar &lhs, const Scalar &rhs); 329343181Sdim friend const Scalar operator^(const Scalar &lhs, const Scalar &rhs); 330343181Sdim friend const Scalar operator<<(const Scalar &lhs, const Scalar &rhs); 331343181Sdim friend const Scalar operator>>(const Scalar &lhs, const Scalar &rhs); 332343181Sdim friend bool operator==(const Scalar &lhs, const Scalar &rhs); 333343181Sdim friend bool operator!=(const Scalar &lhs, const Scalar &rhs); 334343181Sdim friend bool operator<(const Scalar &lhs, const Scalar &rhs); 335343181Sdim friend bool operator<=(const Scalar &lhs, const Scalar &rhs); 336343181Sdim friend bool operator>(const Scalar &lhs, const Scalar &rhs); 337343181Sdim friend bool operator>=(const Scalar &lhs, const Scalar &rhs); 338343181Sdim}; 339343181Sdim 340343181Sdim//---------------------------------------------------------------------- 341343181Sdim// Split out the operators into a format where the compiler will be able to 342343181Sdim// implicitly convert numbers into Scalar objects. 343343181Sdim// 344343181Sdim// This allows code like: 345343181Sdim// Scalar two(2); 346343181Sdim// Scalar four = two * 2; 347343181Sdim// Scalar eight = 2 * four; // This would cause an error if the 348343181Sdim// // operator* was implemented as a 349343181Sdim// // member function. 350343181Sdim// SEE: 351343181Sdim// Item 19 of "Effective C++ Second Edition" by Scott Meyers 352343181Sdim// Differentiate among members functions, non-member functions, and 353343181Sdim// friend functions 354343181Sdim//---------------------------------------------------------------------- 355343181Sdimconst Scalar operator+(const Scalar &lhs, const Scalar &rhs); 356343181Sdimconst Scalar operator-(const Scalar &lhs, const Scalar &rhs); 357343181Sdimconst Scalar operator/(const Scalar &lhs, const Scalar &rhs); 358343181Sdimconst Scalar operator*(const Scalar &lhs, const Scalar &rhs); 359343181Sdimconst Scalar operator&(const Scalar &lhs, const Scalar &rhs); 360343181Sdimconst Scalar operator|(const Scalar &lhs, const Scalar &rhs); 361343181Sdimconst Scalar operator%(const Scalar &lhs, const Scalar &rhs); 362343181Sdimconst Scalar operator^(const Scalar &lhs, const Scalar &rhs); 363343181Sdimconst Scalar operator<<(const Scalar &lhs, const Scalar &rhs); 364343181Sdimconst Scalar operator>>(const Scalar &lhs, const Scalar &rhs); 365343181Sdimbool operator==(const Scalar &lhs, const Scalar &rhs); 366343181Sdimbool operator!=(const Scalar &lhs, const Scalar &rhs); 367343181Sdimbool operator<(const Scalar &lhs, const Scalar &rhs); 368343181Sdimbool operator<=(const Scalar &lhs, const Scalar &rhs); 369343181Sdimbool operator>(const Scalar &lhs, const Scalar &rhs); 370343181Sdimbool operator>=(const Scalar &lhs, const Scalar &rhs); 371343181Sdim 372343181Sdim} // namespace lldb_private 373343181Sdim 374343181Sdim#endif // LLDB_UTILITY_SCALAR_H 375