1343181Sdim//===-- RegisterValue.cpp ---------------------------------------*- C++ -*-===//
2343181Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6343181Sdim//
7343181Sdim//===----------------------------------------------------------------------===//
8343181Sdim
9343181Sdim#include "lldb/Utility/RegisterValue.h"
10343181Sdim
11343181Sdim#include "lldb/Utility/DataExtractor.h"
12343181Sdim#include "lldb/Utility/Scalar.h"
13343181Sdim#include "lldb/Utility/Status.h"
14343181Sdim#include "lldb/Utility/Stream.h"
15343181Sdim#include "lldb/Utility/StreamString.h"
16343181Sdim#include "lldb/lldb-defines.h"
17343181Sdim#include "lldb/lldb-private-types.h"
18343181Sdim
19343181Sdim#include "llvm/ADT/ArrayRef.h"
20343181Sdim#include "llvm/ADT/StringRef.h"
21343181Sdim
22343181Sdim#include <cstdint>
23343181Sdim#include <string>
24343181Sdim#include <tuple>
25343181Sdim#include <vector>
26343181Sdim
27343181Sdim#include <assert.h>
28343181Sdim#include <inttypes.h>
29343181Sdim#include <stdio.h>
30343181Sdim
31343181Sdimusing namespace lldb;
32343181Sdimusing namespace lldb_private;
33343181Sdim
34343181Sdimbool RegisterValue::GetData(DataExtractor &data) const {
35343181Sdim  return data.SetData(GetBytes(), GetByteSize(), GetByteOrder()) > 0;
36343181Sdim}
37343181Sdim
38343181Sdimuint32_t RegisterValue::GetAsMemoryData(const RegisterInfo *reg_info, void *dst,
39343181Sdim                                        uint32_t dst_len,
40343181Sdim                                        lldb::ByteOrder dst_byte_order,
41343181Sdim                                        Status &error) const {
42343181Sdim  if (reg_info == nullptr) {
43343181Sdim    error.SetErrorString("invalid register info argument.");
44343181Sdim    return 0;
45343181Sdim  }
46343181Sdim
47343181Sdim  // ReadRegister should have already been called on this object prior to
48343181Sdim  // calling this.
49343181Sdim  if (GetType() == eTypeInvalid) {
50343181Sdim    // No value has been read into this object...
51343181Sdim    error.SetErrorStringWithFormat(
52343181Sdim        "invalid register value type for register %s", reg_info->name);
53343181Sdim    return 0;
54343181Sdim  }
55343181Sdim
56343181Sdim  if (dst_len > kMaxRegisterByteSize) {
57343181Sdim    error.SetErrorString("destination is too big");
58343181Sdim    return 0;
59343181Sdim  }
60343181Sdim
61343181Sdim  const uint32_t src_len = reg_info->byte_size;
62343181Sdim
63343181Sdim  // Extract the register data into a data extractor
64343181Sdim  DataExtractor reg_data;
65343181Sdim  if (!GetData(reg_data)) {
66343181Sdim    error.SetErrorString("invalid register value to copy into");
67343181Sdim    return 0;
68343181Sdim  }
69343181Sdim
70343181Sdim  // Prepare a memory buffer that contains some or all of the register value
71343181Sdim  const uint32_t bytes_copied =
72343181Sdim      reg_data.CopyByteOrderedData(0,               // src offset
73343181Sdim                                   src_len,         // src length
74343181Sdim                                   dst,             // dst buffer
75343181Sdim                                   dst_len,         // dst length
76343181Sdim                                   dst_byte_order); // dst byte order
77343181Sdim  if (bytes_copied == 0)
78343181Sdim    error.SetErrorStringWithFormat(
79343181Sdim        "failed to copy data for register write of %s", reg_info->name);
80343181Sdim
81343181Sdim  return bytes_copied;
82343181Sdim}
83343181Sdim
84343181Sdimuint32_t RegisterValue::SetFromMemoryData(const RegisterInfo *reg_info,
85343181Sdim                                          const void *src, uint32_t src_len,
86343181Sdim                                          lldb::ByteOrder src_byte_order,
87343181Sdim                                          Status &error) {
88343181Sdim  if (reg_info == nullptr) {
89343181Sdim    error.SetErrorString("invalid register info argument.");
90343181Sdim    return 0;
91343181Sdim  }
92343181Sdim
93343181Sdim  // Moving from addr into a register
94343181Sdim  //
95343181Sdim  // Case 1: src_len == dst_len
96343181Sdim  //
97343181Sdim  //   |AABBCCDD| Address contents
98343181Sdim  //   |AABBCCDD| Register contents
99343181Sdim  //
100343181Sdim  // Case 2: src_len > dst_len
101343181Sdim  //
102343181Sdim  //   Status!  (The register should always be big enough to hold the data)
103343181Sdim  //
104343181Sdim  // Case 3: src_len < dst_len
105343181Sdim  //
106343181Sdim  //   |AABB| Address contents
107343181Sdim  //   |AABB0000| Register contents [on little-endian hardware]
108343181Sdim  //   |0000AABB| Register contents [on big-endian hardware]
109343181Sdim  if (src_len > kMaxRegisterByteSize) {
110343181Sdim    error.SetErrorStringWithFormat(
111343181Sdim        "register buffer is too small to receive %u bytes of data.", src_len);
112343181Sdim    return 0;
113343181Sdim  }
114343181Sdim
115343181Sdim  const uint32_t dst_len = reg_info->byte_size;
116343181Sdim
117343181Sdim  if (src_len > dst_len) {
118343181Sdim    error.SetErrorStringWithFormat(
119343181Sdim        "%u bytes is too big to store in register %s (%u bytes)", src_len,
120343181Sdim        reg_info->name, dst_len);
121343181Sdim    return 0;
122343181Sdim  }
123343181Sdim
124343181Sdim  // Use a data extractor to correctly copy and pad the bytes read into the
125343181Sdim  // register value
126343181Sdim  DataExtractor src_data(src, src_len, src_byte_order, 4);
127343181Sdim
128343181Sdim  error = SetValueFromData(reg_info, src_data, 0, true);
129343181Sdim  if (error.Fail())
130343181Sdim    return 0;
131343181Sdim
132343181Sdim  // If SetValueFromData succeeded, we must have copied all of src_len
133343181Sdim  return src_len;
134343181Sdim}
135343181Sdim
136343181Sdimbool RegisterValue::GetScalarValue(Scalar &scalar) const {
137343181Sdim  switch (m_type) {
138343181Sdim  case eTypeInvalid:
139343181Sdim    break;
140343181Sdim  case eTypeBytes: {
141343181Sdim    switch (buffer.length) {
142343181Sdim    default:
143343181Sdim      break;
144343181Sdim    case 1:
145343181Sdim      scalar = *(const uint8_t *)buffer.bytes;
146343181Sdim      return true;
147343181Sdim    case 2:
148353358Sdim      scalar = *reinterpret_cast<const uint16_t *>(buffer.bytes);
149343181Sdim      return true;
150343181Sdim    case 4:
151353358Sdim      scalar = *reinterpret_cast<const uint32_t *>(buffer.bytes);
152343181Sdim      return true;
153343181Sdim    case 8:
154353358Sdim      scalar = *reinterpret_cast<const uint64_t *>(buffer.bytes);
155343181Sdim      return true;
156343181Sdim    case 16:
157343181Sdim    case 32:
158353358Sdim    case 64:
159343181Sdim      if (buffer.length % sizeof(uint64_t) == 0) {
160343181Sdim        const auto length_in_bits = buffer.length * 8;
161343181Sdim        const auto length_in_uint64 = buffer.length / sizeof(uint64_t);
162343181Sdim        scalar =
163343181Sdim            llvm::APInt(length_in_bits,
164353358Sdim                        llvm::ArrayRef<uint64_t>(
165353358Sdim                            reinterpret_cast<const uint64_t *>(buffer.bytes),
166353358Sdim                            length_in_uint64));
167343181Sdim        return true;
168343181Sdim      }
169343181Sdim      break;
170343181Sdim    }
171343181Sdim  } break;
172343181Sdim  case eTypeUInt8:
173343181Sdim  case eTypeUInt16:
174343181Sdim  case eTypeUInt32:
175343181Sdim  case eTypeUInt64:
176343181Sdim  case eTypeUInt128:
177343181Sdim  case eTypeFloat:
178343181Sdim  case eTypeDouble:
179343181Sdim  case eTypeLongDouble:
180343181Sdim    scalar = m_scalar;
181343181Sdim    return true;
182343181Sdim  }
183343181Sdim  return false;
184343181Sdim}
185343181Sdim
186343181Sdimvoid RegisterValue::Clear() { m_type = eTypeInvalid; }
187343181Sdim
188343181SdimRegisterValue::Type RegisterValue::SetType(const RegisterInfo *reg_info) {
189343181Sdim  // To change the type, we simply copy the data in again, using the new format
190343181Sdim  RegisterValue copy;
191343181Sdim  DataExtractor copy_data;
192343181Sdim  if (copy.CopyValue(*this) && copy.GetData(copy_data))
193343181Sdim    SetValueFromData(reg_info, copy_data, 0, true);
194343181Sdim
195343181Sdim  return m_type;
196343181Sdim}
197343181Sdim
198343181SdimStatus RegisterValue::SetValueFromData(const RegisterInfo *reg_info,
199343181Sdim                                       DataExtractor &src,
200343181Sdim                                       lldb::offset_t src_offset,
201343181Sdim                                       bool partial_data_ok) {
202343181Sdim  Status error;
203343181Sdim
204343181Sdim  if (src.GetByteSize() == 0) {
205343181Sdim    error.SetErrorString("empty data.");
206343181Sdim    return error;
207343181Sdim  }
208343181Sdim
209343181Sdim  if (reg_info->byte_size == 0) {
210343181Sdim    error.SetErrorString("invalid register info.");
211343181Sdim    return error;
212343181Sdim  }
213343181Sdim
214343181Sdim  uint32_t src_len = src.GetByteSize() - src_offset;
215343181Sdim
216343181Sdim  if (!partial_data_ok && (src_len < reg_info->byte_size)) {
217343181Sdim    error.SetErrorString("not enough data.");
218343181Sdim    return error;
219343181Sdim  }
220343181Sdim
221343181Sdim  // Cap the data length if there is more than enough bytes for this register
222343181Sdim  // value
223343181Sdim  if (src_len > reg_info->byte_size)
224343181Sdim    src_len = reg_info->byte_size;
225343181Sdim
226343181Sdim  // Zero out the value in case we get partial data...
227343181Sdim  memset(buffer.bytes, 0, sizeof(buffer.bytes));
228343181Sdim
229343181Sdim  type128 int128;
230343181Sdim
231343181Sdim  m_type = eTypeInvalid;
232343181Sdim  switch (reg_info->encoding) {
233343181Sdim  case eEncodingInvalid:
234343181Sdim    break;
235343181Sdim  case eEncodingUint:
236343181Sdim  case eEncodingSint:
237343181Sdim    if (reg_info->byte_size == 1)
238343181Sdim      SetUInt8(src.GetMaxU32(&src_offset, src_len));
239343181Sdim    else if (reg_info->byte_size <= 2)
240343181Sdim      SetUInt16(src.GetMaxU32(&src_offset, src_len));
241343181Sdim    else if (reg_info->byte_size <= 4)
242343181Sdim      SetUInt32(src.GetMaxU32(&src_offset, src_len));
243343181Sdim    else if (reg_info->byte_size <= 8)
244343181Sdim      SetUInt64(src.GetMaxU64(&src_offset, src_len));
245343181Sdim    else if (reg_info->byte_size <= 16) {
246343181Sdim      uint64_t data1 = src.GetU64(&src_offset);
247343181Sdim      uint64_t data2 = src.GetU64(&src_offset);
248343181Sdim      if (src.GetByteSize() == eByteOrderBig) {
249343181Sdim        int128.x[0] = data1;
250343181Sdim        int128.x[1] = data2;
251343181Sdim      } else {
252343181Sdim        int128.x[0] = data2;
253343181Sdim        int128.x[1] = data1;
254343181Sdim      }
255343181Sdim      SetUInt128(llvm::APInt(128, 2, int128.x));
256343181Sdim    }
257343181Sdim    break;
258343181Sdim  case eEncodingIEEE754:
259343181Sdim    if (reg_info->byte_size == sizeof(float))
260343181Sdim      SetFloat(src.GetFloat(&src_offset));
261343181Sdim    else if (reg_info->byte_size == sizeof(double))
262343181Sdim      SetDouble(src.GetDouble(&src_offset));
263343181Sdim    else if (reg_info->byte_size == sizeof(long double))
264343181Sdim      SetLongDouble(src.GetLongDouble(&src_offset));
265343181Sdim    break;
266343181Sdim  case eEncodingVector: {
267343181Sdim    m_type = eTypeBytes;
268343181Sdim    buffer.length = reg_info->byte_size;
269343181Sdim    buffer.byte_order = src.GetByteOrder();
270343181Sdim    assert(buffer.length <= kMaxRegisterByteSize);
271343181Sdim    if (buffer.length > kMaxRegisterByteSize)
272343181Sdim      buffer.length = kMaxRegisterByteSize;
273343181Sdim    if (src.CopyByteOrderedData(
274343181Sdim            src_offset,    // offset within "src" to start extracting data
275343181Sdim            src_len,       // src length
276343181Sdim            buffer.bytes,  // dst buffer
277343181Sdim            buffer.length, // dst length
278343181Sdim            buffer.byte_order) == 0) // dst byte order
279343181Sdim    {
280343181Sdim      error.SetErrorStringWithFormat(
281343181Sdim          "failed to copy data for register write of %s", reg_info->name);
282343181Sdim      return error;
283343181Sdim    }
284343181Sdim  }
285343181Sdim  }
286343181Sdim
287343181Sdim  if (m_type == eTypeInvalid)
288343181Sdim    error.SetErrorStringWithFormat(
289343181Sdim        "invalid register value type for register %s", reg_info->name);
290343181Sdim  return error;
291343181Sdim}
292343181Sdim
293343181Sdim// Helper function for RegisterValue::SetValueFromString()
294343181Sdimstatic bool ParseVectorEncoding(const RegisterInfo *reg_info,
295343181Sdim                                llvm::StringRef vector_str,
296343181Sdim                                const uint32_t byte_size,
297343181Sdim                                RegisterValue *reg_value) {
298343181Sdim  // Example: vector_str = "{0x2c 0x4b 0x2a 0x3e 0xd0 0x4f 0x2a 0x3e 0xac 0x4a
299343181Sdim  // 0x2a 0x3e 0x84 0x4f 0x2a 0x3e}".
300343181Sdim  vector_str = vector_str.trim();
301343181Sdim  vector_str.consume_front("{");
302343181Sdim  vector_str.consume_back("}");
303343181Sdim  vector_str = vector_str.trim();
304343181Sdim
305343181Sdim  char Sep = ' ';
306343181Sdim
307343181Sdim  // The first split should give us:
308343181Sdim  // ('0x2c', '0x4b 0x2a 0x3e 0xd0 0x4f 0x2a 0x3e 0xac 0x4a 0x2a 0x3e 0x84 0x4f
309343181Sdim  // 0x2a 0x3e').
310343181Sdim  llvm::StringRef car;
311343181Sdim  llvm::StringRef cdr = vector_str;
312343181Sdim  std::tie(car, cdr) = vector_str.split(Sep);
313343181Sdim  std::vector<uint8_t> bytes;
314343181Sdim  unsigned byte = 0;
315343181Sdim
316343181Sdim  // Using radix auto-sensing by passing 0 as the radix. Keep on processing the
317343181Sdim  // vector elements as long as the parsing succeeds and the vector size is <
318343181Sdim  // byte_size.
319343181Sdim  while (!car.getAsInteger(0, byte) && bytes.size() < byte_size) {
320343181Sdim    bytes.push_back(byte);
321343181Sdim    std::tie(car, cdr) = cdr.split(Sep);
322343181Sdim  }
323343181Sdim
324343181Sdim  // Check for vector of exact byte_size elements.
325343181Sdim  if (bytes.size() != byte_size)
326343181Sdim    return false;
327343181Sdim
328343181Sdim  reg_value->SetBytes(&(bytes.front()), byte_size, eByteOrderLittle);
329343181Sdim  return true;
330343181Sdim}
331343181Sdim
332360784Sdimstatic bool UInt64ValueIsValidForByteSize(uint64_t uval64,
333360784Sdim                                          size_t total_byte_size) {
334360784Sdim  if (total_byte_size > 8)
335360784Sdim    return false;
336360784Sdim
337360784Sdim  if (total_byte_size == 8)
338360784Sdim    return true;
339360784Sdim
340360784Sdim  const uint64_t max =
341360784Sdim      (static_cast<uint64_t>(1) << static_cast<uint64_t>(total_byte_size * 8)) -
342360784Sdim      1;
343360784Sdim  return uval64 <= max;
344360784Sdim}
345360784Sdim
346360784Sdimstatic bool SInt64ValueIsValidForByteSize(int64_t sval64,
347360784Sdim                                          size_t total_byte_size) {
348360784Sdim  if (total_byte_size > 8)
349360784Sdim    return false;
350360784Sdim
351360784Sdim  if (total_byte_size == 8)
352360784Sdim    return true;
353360784Sdim
354360784Sdim  const int64_t max = (static_cast<int64_t>(1)
355360784Sdim                       << static_cast<uint64_t>(total_byte_size * 8 - 1)) -
356360784Sdim                      1;
357360784Sdim  const int64_t min = ~(max);
358360784Sdim  return min <= sval64 && sval64 <= max;
359360784Sdim}
360360784Sdim
361343181SdimStatus RegisterValue::SetValueFromString(const RegisterInfo *reg_info,
362343181Sdim                                         llvm::StringRef value_str) {
363343181Sdim  Status error;
364343181Sdim  if (reg_info == nullptr) {
365343181Sdim    error.SetErrorString("Invalid register info argument.");
366343181Sdim    return error;
367343181Sdim  }
368343181Sdim
369343181Sdim  m_type = eTypeInvalid;
370343181Sdim  if (value_str.empty()) {
371343181Sdim    error.SetErrorString("Invalid c-string value string.");
372343181Sdim    return error;
373343181Sdim  }
374343181Sdim  const uint32_t byte_size = reg_info->byte_size;
375343181Sdim
376343181Sdim  uint64_t uval64;
377343181Sdim  int64_t ival64;
378343181Sdim  float flt_val;
379343181Sdim  double dbl_val;
380343181Sdim  long double ldbl_val;
381343181Sdim  switch (reg_info->encoding) {
382343181Sdim  case eEncodingInvalid:
383343181Sdim    error.SetErrorString("Invalid encoding.");
384343181Sdim    break;
385343181Sdim
386343181Sdim  case eEncodingUint:
387343181Sdim    if (byte_size > sizeof(uint64_t)) {
388343181Sdim      error.SetErrorStringWithFormat(
389343181Sdim          "unsupported unsigned integer byte size: %u", byte_size);
390343181Sdim      break;
391343181Sdim    }
392343181Sdim    if (value_str.getAsInteger(0, uval64)) {
393343181Sdim      error.SetErrorStringWithFormat(
394343181Sdim          "'%s' is not a valid unsigned integer string value",
395343181Sdim          value_str.str().c_str());
396343181Sdim      break;
397343181Sdim    }
398343181Sdim
399360784Sdim    if (!UInt64ValueIsValidForByteSize(uval64, byte_size)) {
400343181Sdim      error.SetErrorStringWithFormat(
401343181Sdim          "value 0x%" PRIx64
402343181Sdim          " is too large to fit in a %u byte unsigned integer value",
403343181Sdim          uval64, byte_size);
404343181Sdim      break;
405343181Sdim    }
406343181Sdim
407343181Sdim    if (!SetUInt(uval64, reg_info->byte_size)) {
408343181Sdim      error.SetErrorStringWithFormat(
409343181Sdim          "unsupported unsigned integer byte size: %u", byte_size);
410343181Sdim      break;
411343181Sdim    }
412343181Sdim    break;
413343181Sdim
414343181Sdim  case eEncodingSint:
415343181Sdim    if (byte_size > sizeof(long long)) {
416343181Sdim      error.SetErrorStringWithFormat("unsupported signed integer byte size: %u",
417343181Sdim                                     byte_size);
418343181Sdim      break;
419343181Sdim    }
420343181Sdim
421343181Sdim    if (value_str.getAsInteger(0, ival64)) {
422343181Sdim      error.SetErrorStringWithFormat(
423343181Sdim          "'%s' is not a valid signed integer string value",
424343181Sdim          value_str.str().c_str());
425343181Sdim      break;
426343181Sdim    }
427343181Sdim
428360784Sdim    if (!SInt64ValueIsValidForByteSize(ival64, byte_size)) {
429343181Sdim      error.SetErrorStringWithFormat(
430343181Sdim          "value 0x%" PRIx64
431343181Sdim          " is too large to fit in a %u byte signed integer value",
432343181Sdim          ival64, byte_size);
433343181Sdim      break;
434343181Sdim    }
435343181Sdim
436343181Sdim    if (!SetUInt(ival64, reg_info->byte_size)) {
437343181Sdim      error.SetErrorStringWithFormat("unsupported signed integer byte size: %u",
438343181Sdim                                     byte_size);
439343181Sdim      break;
440343181Sdim    }
441343181Sdim    break;
442343181Sdim
443343181Sdim  case eEncodingIEEE754: {
444343181Sdim    std::string value_string = value_str;
445343181Sdim    if (byte_size == sizeof(float)) {
446343181Sdim      if (::sscanf(value_string.c_str(), "%f", &flt_val) != 1) {
447343181Sdim        error.SetErrorStringWithFormat("'%s' is not a valid float string value",
448343181Sdim                                       value_string.c_str());
449343181Sdim        break;
450343181Sdim      }
451343181Sdim      m_scalar = flt_val;
452343181Sdim      m_type = eTypeFloat;
453343181Sdim    } else if (byte_size == sizeof(double)) {
454343181Sdim      if (::sscanf(value_string.c_str(), "%lf", &dbl_val) != 1) {
455343181Sdim        error.SetErrorStringWithFormat("'%s' is not a valid float string value",
456343181Sdim                                       value_string.c_str());
457343181Sdim        break;
458343181Sdim      }
459343181Sdim      m_scalar = dbl_val;
460343181Sdim      m_type = eTypeDouble;
461343181Sdim    } else if (byte_size == sizeof(long double)) {
462343181Sdim      if (::sscanf(value_string.c_str(), "%Lf", &ldbl_val) != 1) {
463343181Sdim        error.SetErrorStringWithFormat("'%s' is not a valid float string value",
464343181Sdim                                       value_string.c_str());
465343181Sdim        break;
466343181Sdim      }
467343181Sdim      m_scalar = ldbl_val;
468343181Sdim      m_type = eTypeLongDouble;
469343181Sdim    } else {
470343181Sdim      error.SetErrorStringWithFormat("unsupported float byte size: %u",
471343181Sdim                                     byte_size);
472343181Sdim      return error;
473343181Sdim    }
474343181Sdim    break;
475343181Sdim  }
476343181Sdim  case eEncodingVector:
477343181Sdim    if (!ParseVectorEncoding(reg_info, value_str, byte_size, this))
478343181Sdim      error.SetErrorString("unrecognized vector encoding string value.");
479343181Sdim    break;
480343181Sdim  }
481343181Sdim
482343181Sdim  return error;
483343181Sdim}
484343181Sdim
485343181Sdimbool RegisterValue::SignExtend(uint32_t sign_bitpos) {
486343181Sdim  switch (m_type) {
487343181Sdim  case eTypeInvalid:
488343181Sdim    break;
489343181Sdim
490343181Sdim  case eTypeUInt8:
491343181Sdim  case eTypeUInt16:
492343181Sdim  case eTypeUInt32:
493343181Sdim  case eTypeUInt64:
494343181Sdim  case eTypeUInt128:
495343181Sdim    return m_scalar.SignExtend(sign_bitpos);
496343181Sdim  case eTypeFloat:
497343181Sdim  case eTypeDouble:
498343181Sdim  case eTypeLongDouble:
499343181Sdim  case eTypeBytes:
500343181Sdim    break;
501343181Sdim  }
502343181Sdim  return false;
503343181Sdim}
504343181Sdim
505343181Sdimbool RegisterValue::CopyValue(const RegisterValue &rhs) {
506343181Sdim  if (this == &rhs)
507343181Sdim    return rhs.m_type != eTypeInvalid;
508343181Sdim
509343181Sdim  m_type = rhs.m_type;
510343181Sdim  switch (m_type) {
511343181Sdim  case eTypeInvalid:
512343181Sdim    return false;
513343181Sdim  case eTypeUInt8:
514343181Sdim  case eTypeUInt16:
515343181Sdim  case eTypeUInt32:
516343181Sdim  case eTypeUInt64:
517343181Sdim  case eTypeUInt128:
518343181Sdim  case eTypeFloat:
519343181Sdim  case eTypeDouble:
520343181Sdim  case eTypeLongDouble:
521343181Sdim    m_scalar = rhs.m_scalar;
522343181Sdim    break;
523343181Sdim  case eTypeBytes:
524343181Sdim    assert(rhs.buffer.length <= kMaxRegisterByteSize);
525343181Sdim    ::memcpy(buffer.bytes, rhs.buffer.bytes, kMaxRegisterByteSize);
526343181Sdim    buffer.length = rhs.buffer.length;
527343181Sdim    buffer.byte_order = rhs.buffer.byte_order;
528343181Sdim    break;
529343181Sdim  }
530343181Sdim  return true;
531343181Sdim}
532343181Sdim
533343181Sdimuint16_t RegisterValue::GetAsUInt16(uint16_t fail_value,
534343181Sdim                                    bool *success_ptr) const {
535343181Sdim  if (success_ptr)
536343181Sdim    *success_ptr = true;
537343181Sdim
538343181Sdim  switch (m_type) {
539343181Sdim  default:
540343181Sdim    break;
541343181Sdim  case eTypeUInt8:
542343181Sdim  case eTypeUInt16:
543343181Sdim    return m_scalar.UShort(fail_value);
544343181Sdim  case eTypeBytes: {
545343181Sdim    switch (buffer.length) {
546343181Sdim    default:
547343181Sdim      break;
548343181Sdim    case 1:
549343181Sdim    case 2:
550353358Sdim      return *reinterpret_cast<const uint16_t *>(buffer.bytes);
551343181Sdim    }
552343181Sdim  } break;
553343181Sdim  }
554343181Sdim  if (success_ptr)
555343181Sdim    *success_ptr = false;
556343181Sdim  return fail_value;
557343181Sdim}
558343181Sdim
559343181Sdimuint32_t RegisterValue::GetAsUInt32(uint32_t fail_value,
560343181Sdim                                    bool *success_ptr) const {
561343181Sdim  if (success_ptr)
562343181Sdim    *success_ptr = true;
563343181Sdim  switch (m_type) {
564343181Sdim  default:
565343181Sdim    break;
566343181Sdim  case eTypeUInt8:
567343181Sdim  case eTypeUInt16:
568343181Sdim  case eTypeUInt32:
569343181Sdim  case eTypeFloat:
570343181Sdim  case eTypeDouble:
571343181Sdim  case eTypeLongDouble:
572343181Sdim    return m_scalar.UInt(fail_value);
573343181Sdim  case eTypeBytes: {
574343181Sdim    switch (buffer.length) {
575343181Sdim    default:
576343181Sdim      break;
577343181Sdim    case 1:
578343181Sdim    case 2:
579343181Sdim    case 4:
580353358Sdim      return *reinterpret_cast<const uint32_t *>(buffer.bytes);
581343181Sdim    }
582343181Sdim  } break;
583343181Sdim  }
584343181Sdim  if (success_ptr)
585343181Sdim    *success_ptr = false;
586343181Sdim  return fail_value;
587343181Sdim}
588343181Sdim
589343181Sdimuint64_t RegisterValue::GetAsUInt64(uint64_t fail_value,
590343181Sdim                                    bool *success_ptr) const {
591343181Sdim  if (success_ptr)
592343181Sdim    *success_ptr = true;
593343181Sdim  switch (m_type) {
594343181Sdim  default:
595343181Sdim    break;
596343181Sdim  case eTypeUInt8:
597343181Sdim  case eTypeUInt16:
598343181Sdim  case eTypeUInt32:
599343181Sdim  case eTypeUInt64:
600343181Sdim  case eTypeFloat:
601343181Sdim  case eTypeDouble:
602343181Sdim  case eTypeLongDouble:
603343181Sdim    return m_scalar.ULongLong(fail_value);
604343181Sdim  case eTypeBytes: {
605343181Sdim    switch (buffer.length) {
606343181Sdim    default:
607343181Sdim      break;
608343181Sdim    case 1:
609343181Sdim      return *(const uint8_t *)buffer.bytes;
610343181Sdim    case 2:
611353358Sdim      return *reinterpret_cast<const uint16_t *>(buffer.bytes);
612343181Sdim    case 4:
613353358Sdim      return *reinterpret_cast<const uint32_t *>(buffer.bytes);
614343181Sdim    case 8:
615353358Sdim      return *reinterpret_cast<const uint64_t *>(buffer.bytes);
616343181Sdim    }
617343181Sdim  } break;
618343181Sdim  }
619343181Sdim  if (success_ptr)
620343181Sdim    *success_ptr = false;
621343181Sdim  return fail_value;
622343181Sdim}
623343181Sdim
624343181Sdimllvm::APInt RegisterValue::GetAsUInt128(const llvm::APInt &fail_value,
625343181Sdim                                        bool *success_ptr) const {
626343181Sdim  if (success_ptr)
627343181Sdim    *success_ptr = true;
628343181Sdim  switch (m_type) {
629343181Sdim  default:
630343181Sdim    break;
631343181Sdim  case eTypeUInt8:
632343181Sdim  case eTypeUInt16:
633343181Sdim  case eTypeUInt32:
634343181Sdim  case eTypeUInt64:
635343181Sdim  case eTypeUInt128:
636343181Sdim  case eTypeFloat:
637343181Sdim  case eTypeDouble:
638343181Sdim  case eTypeLongDouble:
639343181Sdim    return m_scalar.UInt128(fail_value);
640343181Sdim  case eTypeBytes: {
641343181Sdim    switch (buffer.length) {
642343181Sdim    default:
643343181Sdim      break;
644343181Sdim    case 1:
645343181Sdim    case 2:
646343181Sdim    case 4:
647343181Sdim    case 8:
648343181Sdim    case 16:
649343181Sdim      return llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128,
650353358Sdim                         (reinterpret_cast<const type128 *>(buffer.bytes))->x);
651343181Sdim    }
652343181Sdim  } break;
653343181Sdim  }
654343181Sdim  if (success_ptr)
655343181Sdim    *success_ptr = false;
656343181Sdim  return fail_value;
657343181Sdim}
658343181Sdim
659343181Sdimfloat RegisterValue::GetAsFloat(float fail_value, bool *success_ptr) const {
660343181Sdim  if (success_ptr)
661343181Sdim    *success_ptr = true;
662343181Sdim  switch (m_type) {
663343181Sdim  default:
664343181Sdim    break;
665343181Sdim  case eTypeUInt32:
666343181Sdim  case eTypeUInt64:
667343181Sdim  case eTypeUInt128:
668343181Sdim  case eTypeFloat:
669343181Sdim  case eTypeDouble:
670343181Sdim  case eTypeLongDouble:
671343181Sdim    return m_scalar.Float(fail_value);
672343181Sdim  }
673343181Sdim  if (success_ptr)
674343181Sdim    *success_ptr = false;
675343181Sdim  return fail_value;
676343181Sdim}
677343181Sdim
678343181Sdimdouble RegisterValue::GetAsDouble(double fail_value, bool *success_ptr) const {
679343181Sdim  if (success_ptr)
680343181Sdim    *success_ptr = true;
681343181Sdim  switch (m_type) {
682343181Sdim  default:
683343181Sdim    break;
684343181Sdim
685343181Sdim  case eTypeUInt32:
686343181Sdim  case eTypeUInt64:
687343181Sdim  case eTypeUInt128:
688343181Sdim  case eTypeFloat:
689343181Sdim  case eTypeDouble:
690343181Sdim  case eTypeLongDouble:
691343181Sdim    return m_scalar.Double(fail_value);
692343181Sdim  }
693343181Sdim  if (success_ptr)
694343181Sdim    *success_ptr = false;
695343181Sdim  return fail_value;
696343181Sdim}
697343181Sdim
698343181Sdimlong double RegisterValue::GetAsLongDouble(long double fail_value,
699343181Sdim                                           bool *success_ptr) const {
700343181Sdim  if (success_ptr)
701343181Sdim    *success_ptr = true;
702343181Sdim  switch (m_type) {
703343181Sdim  default:
704343181Sdim    break;
705343181Sdim
706343181Sdim  case eTypeUInt32:
707343181Sdim  case eTypeUInt64:
708343181Sdim  case eTypeUInt128:
709343181Sdim  case eTypeFloat:
710343181Sdim  case eTypeDouble:
711343181Sdim  case eTypeLongDouble:
712343181Sdim    return m_scalar.LongDouble();
713343181Sdim  }
714343181Sdim  if (success_ptr)
715343181Sdim    *success_ptr = false;
716343181Sdim  return fail_value;
717343181Sdim}
718343181Sdim
719343181Sdimconst void *RegisterValue::GetBytes() const {
720343181Sdim  switch (m_type) {
721343181Sdim  case eTypeInvalid:
722343181Sdim    break;
723343181Sdim  case eTypeUInt8:
724343181Sdim  case eTypeUInt16:
725343181Sdim  case eTypeUInt32:
726343181Sdim  case eTypeUInt64:
727343181Sdim  case eTypeUInt128:
728343181Sdim  case eTypeFloat:
729343181Sdim  case eTypeDouble:
730343181Sdim  case eTypeLongDouble:
731343181Sdim    return m_scalar.GetBytes();
732343181Sdim  case eTypeBytes:
733343181Sdim    return buffer.bytes;
734343181Sdim  }
735343181Sdim  return nullptr;
736343181Sdim}
737343181Sdim
738343181Sdimuint32_t RegisterValue::GetByteSize() const {
739343181Sdim  switch (m_type) {
740343181Sdim  case eTypeInvalid:
741343181Sdim    break;
742343181Sdim  case eTypeUInt8:
743343181Sdim    return 1;
744343181Sdim  case eTypeUInt16:
745343181Sdim    return 2;
746343181Sdim  case eTypeUInt32:
747343181Sdim  case eTypeUInt64:
748343181Sdim  case eTypeUInt128:
749343181Sdim  case eTypeFloat:
750343181Sdim  case eTypeDouble:
751343181Sdim  case eTypeLongDouble:
752343181Sdim    return m_scalar.GetByteSize();
753343181Sdim  case eTypeBytes:
754343181Sdim    return buffer.length;
755343181Sdim  }
756343181Sdim  return 0;
757343181Sdim}
758343181Sdim
759343181Sdimbool RegisterValue::SetUInt(uint64_t uint, uint32_t byte_size) {
760343181Sdim  if (byte_size == 0) {
761343181Sdim    SetUInt64(uint);
762343181Sdim  } else if (byte_size == 1) {
763343181Sdim    SetUInt8(uint);
764343181Sdim  } else if (byte_size <= 2) {
765343181Sdim    SetUInt16(uint);
766343181Sdim  } else if (byte_size <= 4) {
767343181Sdim    SetUInt32(uint);
768343181Sdim  } else if (byte_size <= 8) {
769343181Sdim    SetUInt64(uint);
770343181Sdim  } else if (byte_size <= 16) {
771343181Sdim    SetUInt128(llvm::APInt(128, uint));
772343181Sdim  } else
773343181Sdim    return false;
774343181Sdim  return true;
775343181Sdim}
776343181Sdim
777343181Sdimvoid RegisterValue::SetBytes(const void *bytes, size_t length,
778343181Sdim                             lldb::ByteOrder byte_order) {
779343181Sdim  // If this assertion fires off we need to increase the size of buffer.bytes,
780343181Sdim  // or make it something that is allocated on the heap. Since the data buffer
781343181Sdim  // is in a union, we can't make it a collection class like SmallVector...
782343181Sdim  if (bytes && length > 0) {
783343181Sdim    assert(length <= sizeof(buffer.bytes) &&
784343181Sdim           "Storing too many bytes in a RegisterValue.");
785343181Sdim    m_type = eTypeBytes;
786343181Sdim    buffer.length = length;
787343181Sdim    memcpy(buffer.bytes, bytes, length);
788343181Sdim    buffer.byte_order = byte_order;
789343181Sdim  } else {
790343181Sdim    m_type = eTypeInvalid;
791343181Sdim    buffer.length = 0;
792343181Sdim  }
793343181Sdim}
794343181Sdim
795343181Sdimbool RegisterValue::operator==(const RegisterValue &rhs) const {
796343181Sdim  if (m_type == rhs.m_type) {
797343181Sdim    switch (m_type) {
798343181Sdim    case eTypeInvalid:
799343181Sdim      return true;
800343181Sdim    case eTypeUInt8:
801343181Sdim    case eTypeUInt16:
802343181Sdim    case eTypeUInt32:
803343181Sdim    case eTypeUInt64:
804343181Sdim    case eTypeUInt128:
805343181Sdim    case eTypeFloat:
806343181Sdim    case eTypeDouble:
807343181Sdim    case eTypeLongDouble:
808343181Sdim      return m_scalar == rhs.m_scalar;
809343181Sdim    case eTypeBytes:
810343181Sdim      if (buffer.length != rhs.buffer.length)
811343181Sdim        return false;
812343181Sdim      else {
813343181Sdim        uint8_t length = buffer.length;
814343181Sdim        if (length > kMaxRegisterByteSize)
815343181Sdim          length = kMaxRegisterByteSize;
816343181Sdim        return memcmp(buffer.bytes, rhs.buffer.bytes, length) == 0;
817343181Sdim      }
818343181Sdim      break;
819343181Sdim    }
820343181Sdim  }
821343181Sdim  return false;
822343181Sdim}
823343181Sdim
824343181Sdimbool RegisterValue::operator!=(const RegisterValue &rhs) const {
825343181Sdim  return !(*this == rhs);
826343181Sdim}
827343181Sdim
828343181Sdimbool RegisterValue::ClearBit(uint32_t bit) {
829343181Sdim  switch (m_type) {
830343181Sdim  case eTypeInvalid:
831343181Sdim    break;
832343181Sdim
833343181Sdim  case eTypeUInt8:
834343181Sdim  case eTypeUInt16:
835343181Sdim  case eTypeUInt32:
836343181Sdim  case eTypeUInt64:
837343181Sdim  case eTypeUInt128:
838343181Sdim    if (bit < (GetByteSize() * 8)) {
839343181Sdim      return m_scalar.ClearBit(bit);
840343181Sdim    }
841343181Sdim    break;
842343181Sdim
843343181Sdim  case eTypeFloat:
844343181Sdim  case eTypeDouble:
845343181Sdim  case eTypeLongDouble:
846343181Sdim    break;
847343181Sdim
848343181Sdim  case eTypeBytes:
849343181Sdim    if (buffer.byte_order == eByteOrderBig ||
850343181Sdim        buffer.byte_order == eByteOrderLittle) {
851343181Sdim      uint32_t byte_idx;
852343181Sdim      if (buffer.byte_order == eByteOrderBig)
853343181Sdim        byte_idx = buffer.length - (bit / 8) - 1;
854343181Sdim      else
855343181Sdim        byte_idx = bit / 8;
856343181Sdim
857343181Sdim      const uint32_t byte_bit = bit % 8;
858343181Sdim      if (byte_idx < buffer.length) {
859343181Sdim        buffer.bytes[byte_idx] &= ~(1u << byte_bit);
860343181Sdim        return true;
861343181Sdim      }
862343181Sdim    }
863343181Sdim    break;
864343181Sdim  }
865343181Sdim  return false;
866343181Sdim}
867343181Sdim
868343181Sdimbool RegisterValue::SetBit(uint32_t bit) {
869343181Sdim  switch (m_type) {
870343181Sdim  case eTypeInvalid:
871343181Sdim    break;
872343181Sdim
873343181Sdim  case eTypeUInt8:
874343181Sdim  case eTypeUInt16:
875343181Sdim  case eTypeUInt32:
876343181Sdim  case eTypeUInt64:
877343181Sdim  case eTypeUInt128:
878343181Sdim    if (bit < (GetByteSize() * 8)) {
879343181Sdim      return m_scalar.SetBit(bit);
880343181Sdim    }
881343181Sdim    break;
882343181Sdim
883343181Sdim  case eTypeFloat:
884343181Sdim  case eTypeDouble:
885343181Sdim  case eTypeLongDouble:
886343181Sdim    break;
887343181Sdim
888343181Sdim  case eTypeBytes:
889343181Sdim    if (buffer.byte_order == eByteOrderBig ||
890343181Sdim        buffer.byte_order == eByteOrderLittle) {
891343181Sdim      uint32_t byte_idx;
892343181Sdim      if (buffer.byte_order == eByteOrderBig)
893343181Sdim        byte_idx = buffer.length - (bit / 8) - 1;
894343181Sdim      else
895343181Sdim        byte_idx = bit / 8;
896343181Sdim
897343181Sdim      const uint32_t byte_bit = bit % 8;
898343181Sdim      if (byte_idx < buffer.length) {
899343181Sdim        buffer.bytes[byte_idx] |= (1u << byte_bit);
900343181Sdim        return true;
901343181Sdim      }
902343181Sdim    }
903343181Sdim    break;
904343181Sdim  }
905343181Sdim  return false;
906343181Sdim}
907