xref: /freebsd/contrib/llvm-project/lldb/source/Utility/RegisterValue.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1 //===-- RegisterValue.cpp -------------------------------------------------===//
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 #include "lldb/Utility/RegisterValue.h"
10 
11 #include "lldb/Utility/DataExtractor.h"
12 #include "lldb/Utility/Scalar.h"
13 #include "lldb/Utility/Status.h"
14 #include "lldb/Utility/Stream.h"
15 #include "lldb/Utility/StreamString.h"
16 #include "lldb/lldb-defines.h"
17 #include "lldb/lldb-private-types.h"
18 
19 #include "llvm/ADT/ArrayRef.h"
20 #include "llvm/ADT/StringRef.h"
21 
22 #include <cstdint>
23 #include <string>
24 #include <tuple>
25 #include <vector>
26 
27 #include <cassert>
28 #include <cinttypes>
29 #include <cstdio>
30 
31 using namespace lldb;
32 using namespace lldb_private;
33 
GetData(DataExtractor & data) const34 bool RegisterValue::GetData(DataExtractor &data) const {
35   return data.SetData(GetBytes(), GetByteSize(), GetByteOrder()) > 0;
36 }
37 
GetAsMemoryData(const RegisterInfo & reg_info,void * dst,uint32_t dst_len,lldb::ByteOrder dst_byte_order,Status & error) const38 uint32_t RegisterValue::GetAsMemoryData(const RegisterInfo &reg_info, void *dst,
39                                         uint32_t dst_len,
40                                         lldb::ByteOrder dst_byte_order,
41                                         Status &error) const {
42   // ReadRegister should have already been called on this object prior to
43   // calling this.
44   if (GetType() == eTypeInvalid) {
45     // No value has been read into this object...
46     error.SetErrorStringWithFormat(
47         "invalid register value type for register %s", reg_info.name);
48     return 0;
49   }
50 
51   const uint32_t src_len = reg_info.byte_size;
52 
53   // Extract the register data into a data extractor
54   DataExtractor reg_data;
55   if (!GetData(reg_data)) {
56     error.SetErrorString("invalid register value to copy into");
57     return 0;
58   }
59 
60   // Prepare a memory buffer that contains some or all of the register value
61   const uint32_t bytes_copied =
62       reg_data.CopyByteOrderedData(0,               // src offset
63                                    src_len,         // src length
64                                    dst,             // dst buffer
65                                    dst_len,         // dst length
66                                    dst_byte_order); // dst byte order
67   if (bytes_copied == 0)
68     error.SetErrorStringWithFormat(
69         "failed to copy data for register write of %s", reg_info.name);
70 
71   return bytes_copied;
72 }
73 
SetFromMemoryData(const RegisterInfo & reg_info,const void * src,uint32_t src_len,lldb::ByteOrder src_byte_order,Status & error)74 uint32_t RegisterValue::SetFromMemoryData(const RegisterInfo &reg_info,
75                                           const void *src, uint32_t src_len,
76                                           lldb::ByteOrder src_byte_order,
77                                           Status &error) {
78   // Moving from addr into a register
79   //
80   // Case 1: src_len == dst_len
81   //
82   //   |AABBCCDD| Address contents
83   //   |AABBCCDD| Register contents
84   //
85   // Case 2: src_len > dst_len
86   //
87   //   Status!  (The register should always be big enough to hold the data)
88   //
89   // Case 3: src_len < dst_len
90   //
91   //   |AABB| Address contents
92   //   |AABB0000| Register contents [on little-endian hardware]
93   //   |0000AABB| Register contents [on big-endian hardware]
94   const uint32_t dst_len = reg_info.byte_size;
95 
96   if (src_len > dst_len) {
97     error.SetErrorStringWithFormat(
98         "%u bytes is too big to store in register %s (%u bytes)", src_len,
99         reg_info.name, dst_len);
100     return 0;
101   }
102 
103   // Use a data extractor to correctly copy and pad the bytes read into the
104   // register value
105   DataExtractor src_data(src, src_len, src_byte_order, 4);
106 
107   error = SetValueFromData(reg_info, src_data, 0, true);
108   if (error.Fail())
109     return 0;
110 
111   // If SetValueFromData succeeded, we must have copied all of src_len
112   return src_len;
113 }
114 
GetScalarValue(Scalar & scalar) const115 bool RegisterValue::GetScalarValue(Scalar &scalar) const {
116   switch (m_type) {
117   case eTypeInvalid:
118     break;
119   case eTypeBytes: {
120     DataExtractor data(buffer.bytes.data(), buffer.bytes.size(),
121                        buffer.byte_order, 1);
122     if (scalar.SetValueFromData(data, lldb::eEncodingUint, buffer.bytes.size())
123             .Success())
124       return true;
125   } break;
126   case eTypeUInt8:
127   case eTypeUInt16:
128   case eTypeUInt32:
129   case eTypeUInt64:
130   case eTypeUInt128:
131   case eTypeFloat:
132   case eTypeDouble:
133   case eTypeLongDouble:
134     scalar = m_scalar;
135     return true;
136   }
137   return false;
138 }
139 
Clear()140 void RegisterValue::Clear() { m_type = eTypeInvalid; }
141 
SetType(const RegisterInfo & reg_info)142 RegisterValue::Type RegisterValue::SetType(const RegisterInfo &reg_info) {
143   // To change the type, we simply copy the data in again, using the new format
144   RegisterValue copy;
145   DataExtractor copy_data;
146   if (copy.CopyValue(*this) && copy.GetData(copy_data)) {
147     Status error = SetValueFromData(reg_info, copy_data, 0, true);
148     assert(error.Success() && "Expected SetValueFromData to succeed.");
149     UNUSED_IF_ASSERT_DISABLED(error);
150   }
151 
152   return m_type;
153 }
154 
SetValueFromData(const RegisterInfo & reg_info,DataExtractor & src,lldb::offset_t src_offset,bool partial_data_ok)155 Status RegisterValue::SetValueFromData(const RegisterInfo &reg_info,
156                                        DataExtractor &src,
157                                        lldb::offset_t src_offset,
158                                        bool partial_data_ok) {
159   Status error;
160 
161   if (src.GetByteSize() == 0) {
162     error.SetErrorString("empty data.");
163     return error;
164   }
165 
166   if (reg_info.byte_size == 0) {
167     error.SetErrorString("invalid register info.");
168     return error;
169   }
170 
171   uint32_t src_len = src.GetByteSize() - src_offset;
172 
173   if (!partial_data_ok && (src_len < reg_info.byte_size)) {
174     error.SetErrorString("not enough data.");
175     return error;
176   }
177 
178   // Cap the data length if there is more than enough bytes for this register
179   // value
180   if (src_len > reg_info.byte_size)
181     src_len = reg_info.byte_size;
182 
183   type128 int128;
184 
185   m_type = eTypeInvalid;
186   switch (reg_info.encoding) {
187   case eEncodingInvalid:
188     break;
189   case eEncodingUint:
190   case eEncodingSint:
191     if (reg_info.byte_size == 1)
192       SetUInt8(src.GetMaxU32(&src_offset, src_len));
193     else if (reg_info.byte_size <= 2)
194       SetUInt16(src.GetMaxU32(&src_offset, src_len));
195     else if (reg_info.byte_size <= 4)
196       SetUInt32(src.GetMaxU32(&src_offset, src_len));
197     else if (reg_info.byte_size <= 8)
198       SetUInt64(src.GetMaxU64(&src_offset, src_len));
199     else if (reg_info.byte_size <= 16) {
200       uint64_t data1 = src.GetU64(&src_offset);
201       uint64_t data2 = src.GetU64(&src_offset);
202       if (src.GetByteOrder() == eByteOrderBig) {
203         int128.x[0] = data1;
204         int128.x[1] = data2;
205       } else {
206         int128.x[0] = data2;
207         int128.x[1] = data1;
208       }
209       SetUInt128(llvm::APInt(128, 2, int128.x));
210     }
211     break;
212   case eEncodingIEEE754:
213     if (reg_info.byte_size == sizeof(float))
214       SetFloat(src.GetFloat(&src_offset));
215     else if (reg_info.byte_size == sizeof(double))
216       SetDouble(src.GetDouble(&src_offset));
217     else if (reg_info.byte_size == sizeof(long double))
218       SetLongDouble(src.GetLongDouble(&src_offset));
219     break;
220   case eEncodingVector: {
221     m_type = eTypeBytes;
222     assert(reg_info.byte_size <= kMaxRegisterByteSize);
223     buffer.bytes.resize(reg_info.byte_size);
224     buffer.byte_order = src.GetByteOrder();
225     if (src.CopyByteOrderedData(
226             src_offset,          // offset within "src" to start extracting data
227             src_len,             // src length
228             buffer.bytes.data(), // dst buffer
229             buffer.bytes.size(), // dst length
230             buffer.byte_order) == 0) // dst byte order
231     {
232       error.SetErrorStringWithFormat(
233           "failed to copy data for register write of %s", reg_info.name);
234       return error;
235     }
236   }
237   }
238 
239   if (m_type == eTypeInvalid)
240     error.SetErrorStringWithFormat(
241         "invalid register value type for register %s", reg_info.name);
242   return error;
243 }
244 
245 // Helper function for RegisterValue::SetValueFromString()
ParseVectorEncoding(const RegisterInfo * reg_info,llvm::StringRef vector_str,const uint32_t byte_size,RegisterValue * reg_value)246 static bool ParseVectorEncoding(const RegisterInfo *reg_info,
247                                 llvm::StringRef vector_str,
248                                 const uint32_t byte_size,
249                                 RegisterValue *reg_value) {
250   // Example: vector_str = "{0x2c 0x4b 0x2a 0x3e 0xd0 0x4f 0x2a 0x3e 0xac 0x4a
251   // 0x2a 0x3e 0x84 0x4f 0x2a 0x3e}".
252   vector_str = vector_str.trim();
253   vector_str.consume_front("{");
254   vector_str.consume_back("}");
255   vector_str = vector_str.trim();
256 
257   char Sep = ' ';
258 
259   // The first split should give us:
260   // ('0x2c', '0x4b 0x2a 0x3e 0xd0 0x4f 0x2a 0x3e 0xac 0x4a 0x2a 0x3e 0x84 0x4f
261   // 0x2a 0x3e').
262   llvm::StringRef car;
263   llvm::StringRef cdr = vector_str;
264   std::tie(car, cdr) = vector_str.split(Sep);
265   std::vector<uint8_t> bytes;
266   unsigned byte = 0;
267 
268   // Using radix auto-sensing by passing 0 as the radix. Keep on processing the
269   // vector elements as long as the parsing succeeds and the vector size is <
270   // byte_size.
271   while (!car.getAsInteger(0, byte) && bytes.size() < byte_size) {
272     bytes.push_back(byte);
273     std::tie(car, cdr) = cdr.split(Sep);
274   }
275 
276   // Check for vector of exact byte_size elements.
277   if (bytes.size() != byte_size)
278     return false;
279 
280   reg_value->SetBytes(&(bytes.front()), byte_size, eByteOrderLittle);
281   return true;
282 }
283 
UInt64ValueIsValidForByteSize(uint64_t uval64,size_t total_byte_size)284 static bool UInt64ValueIsValidForByteSize(uint64_t uval64,
285                                           size_t total_byte_size) {
286   if (total_byte_size > 8)
287     return false;
288 
289   if (total_byte_size == 8)
290     return true;
291 
292   const uint64_t max =
293       (static_cast<uint64_t>(1) << static_cast<uint64_t>(total_byte_size * 8)) -
294       1;
295   return uval64 <= max;
296 }
297 
SInt64ValueIsValidForByteSize(int64_t sval64,size_t total_byte_size)298 static bool SInt64ValueIsValidForByteSize(int64_t sval64,
299                                           size_t total_byte_size) {
300   if (total_byte_size > 8)
301     return false;
302 
303   if (total_byte_size == 8)
304     return true;
305 
306   const int64_t max = (static_cast<int64_t>(1)
307                        << static_cast<uint64_t>(total_byte_size * 8 - 1)) -
308                       1;
309   const int64_t min = ~(max);
310   return min <= sval64 && sval64 <= max;
311 }
312 
SetValueFromString(const RegisterInfo * reg_info,llvm::StringRef value_str)313 Status RegisterValue::SetValueFromString(const RegisterInfo *reg_info,
314                                          llvm::StringRef value_str) {
315   Status error;
316   if (reg_info == nullptr) {
317     error.SetErrorString("Invalid register info argument.");
318     return error;
319   }
320 
321   m_type = eTypeInvalid;
322   if (value_str.empty()) {
323     error.SetErrorString("Invalid c-string value string.");
324     return error;
325   }
326   const uint32_t byte_size = reg_info->byte_size;
327 
328   uint64_t uval64;
329   int64_t ival64;
330   float flt_val;
331   double dbl_val;
332   long double ldbl_val;
333   switch (reg_info->encoding) {
334   case eEncodingInvalid:
335     error.SetErrorString("Invalid encoding.");
336     break;
337 
338   case eEncodingUint:
339     if (byte_size > sizeof(uint64_t)) {
340       error.SetErrorStringWithFormat(
341           "unsupported unsigned integer byte size: %u", byte_size);
342       break;
343     }
344     if (value_str.getAsInteger(0, uval64)) {
345       error.SetErrorStringWithFormatv(
346           "'{0}' is not a valid unsigned integer string value", value_str);
347       break;
348     }
349 
350     if (!UInt64ValueIsValidForByteSize(uval64, byte_size)) {
351       error.SetErrorStringWithFormat(
352           "value 0x%" PRIx64
353           " is too large to fit in a %u byte unsigned integer value",
354           uval64, byte_size);
355       break;
356     }
357 
358     if (!SetUInt(uval64, reg_info->byte_size)) {
359       error.SetErrorStringWithFormat(
360           "unsupported unsigned integer byte size: %u", byte_size);
361       break;
362     }
363     break;
364 
365   case eEncodingSint:
366     if (byte_size > sizeof(long long)) {
367       error.SetErrorStringWithFormat("unsupported signed integer byte size: %u",
368                                      byte_size);
369       break;
370     }
371 
372     if (value_str.getAsInteger(0, ival64)) {
373       error.SetErrorStringWithFormatv(
374           "'{0}' is not a valid signed integer string value", value_str);
375       break;
376     }
377 
378     if (!SInt64ValueIsValidForByteSize(ival64, byte_size)) {
379       error.SetErrorStringWithFormat(
380           "value 0x%" PRIx64
381           " is too large to fit in a %u byte signed integer value",
382           ival64, byte_size);
383       break;
384     }
385 
386     if (!SetUInt(ival64, reg_info->byte_size)) {
387       error.SetErrorStringWithFormat("unsupported signed integer byte size: %u",
388                                      byte_size);
389       break;
390     }
391     break;
392 
393   case eEncodingIEEE754: {
394     std::string value_string = std::string(value_str);
395     if (byte_size == sizeof(float)) {
396       if (::sscanf(value_string.c_str(), "%f", &flt_val) != 1) {
397         error.SetErrorStringWithFormat("'%s' is not a valid float string value",
398                                        value_string.c_str());
399         break;
400       }
401       m_scalar = flt_val;
402       m_type = eTypeFloat;
403     } else if (byte_size == sizeof(double)) {
404       if (::sscanf(value_string.c_str(), "%lf", &dbl_val) != 1) {
405         error.SetErrorStringWithFormat("'%s' is not a valid float string value",
406                                        value_string.c_str());
407         break;
408       }
409       m_scalar = dbl_val;
410       m_type = eTypeDouble;
411     } else if (byte_size == sizeof(long double)) {
412       if (::sscanf(value_string.c_str(), "%Lf", &ldbl_val) != 1) {
413         error.SetErrorStringWithFormat("'%s' is not a valid float string value",
414                                        value_string.c_str());
415         break;
416       }
417       m_scalar = ldbl_val;
418       m_type = eTypeLongDouble;
419     } else {
420       error.SetErrorStringWithFormat("unsupported float byte size: %u",
421                                      byte_size);
422       return error;
423     }
424     break;
425   }
426   case eEncodingVector:
427     if (!ParseVectorEncoding(reg_info, value_str, byte_size, this))
428       error.SetErrorString("unrecognized vector encoding string value.");
429     break;
430   }
431 
432   return error;
433 }
434 
SignExtend(uint32_t sign_bitpos)435 bool RegisterValue::SignExtend(uint32_t sign_bitpos) {
436   switch (m_type) {
437   case eTypeInvalid:
438     break;
439 
440   case eTypeUInt8:
441   case eTypeUInt16:
442   case eTypeUInt32:
443   case eTypeUInt64:
444   case eTypeUInt128:
445     return m_scalar.SignExtend(sign_bitpos);
446   case eTypeFloat:
447   case eTypeDouble:
448   case eTypeLongDouble:
449   case eTypeBytes:
450     break;
451   }
452   return false;
453 }
454 
CopyValue(const RegisterValue & rhs)455 bool RegisterValue::CopyValue(const RegisterValue &rhs) {
456   if (this == &rhs)
457     return rhs.m_type != eTypeInvalid;
458 
459   m_type = rhs.m_type;
460   switch (m_type) {
461   case eTypeInvalid:
462     return false;
463   case eTypeUInt8:
464   case eTypeUInt16:
465   case eTypeUInt32:
466   case eTypeUInt64:
467   case eTypeUInt128:
468   case eTypeFloat:
469   case eTypeDouble:
470   case eTypeLongDouble:
471     m_scalar = rhs.m_scalar;
472     break;
473   case eTypeBytes:
474     buffer.bytes = rhs.buffer.bytes;
475     buffer.byte_order = rhs.buffer.byte_order;
476     break;
477   }
478   return true;
479 }
480 
GetAsUInt16(uint16_t fail_value,bool * success_ptr) const481 uint16_t RegisterValue::GetAsUInt16(uint16_t fail_value,
482                                     bool *success_ptr) const {
483   if (success_ptr)
484     *success_ptr = true;
485 
486   switch (m_type) {
487   default:
488     break;
489   case eTypeUInt8:
490   case eTypeUInt16:
491     return m_scalar.UShort(fail_value);
492   case eTypeBytes: {
493     switch (buffer.bytes.size()) {
494     default:
495       break;
496     case 1:
497     case 2:
498       return *reinterpret_cast<const uint16_t *>(buffer.bytes.data());
499     }
500   } break;
501   }
502   if (success_ptr)
503     *success_ptr = false;
504   return fail_value;
505 }
506 
GetAsUInt32(uint32_t fail_value,bool * success_ptr) const507 uint32_t RegisterValue::GetAsUInt32(uint32_t fail_value,
508                                     bool *success_ptr) const {
509   if (success_ptr)
510     *success_ptr = true;
511   switch (m_type) {
512   default:
513     break;
514   case eTypeUInt8:
515   case eTypeUInt16:
516   case eTypeUInt32:
517   case eTypeFloat:
518   case eTypeDouble:
519   case eTypeLongDouble:
520     return m_scalar.UInt(fail_value);
521   case eTypeBytes: {
522     switch (buffer.bytes.size()) {
523     default:
524       break;
525     case 1:
526     case 2:
527     case 4:
528       return *reinterpret_cast<const uint32_t *>(buffer.bytes.data());
529     }
530   } break;
531   }
532   if (success_ptr)
533     *success_ptr = false;
534   return fail_value;
535 }
536 
GetAsUInt64(uint64_t fail_value,bool * success_ptr) const537 uint64_t RegisterValue::GetAsUInt64(uint64_t fail_value,
538                                     bool *success_ptr) const {
539   if (success_ptr)
540     *success_ptr = true;
541   switch (m_type) {
542   default:
543     break;
544   case eTypeUInt8:
545   case eTypeUInt16:
546   case eTypeUInt32:
547   case eTypeUInt64:
548   case eTypeFloat:
549   case eTypeDouble:
550   case eTypeLongDouble:
551     return m_scalar.ULongLong(fail_value);
552   case eTypeBytes: {
553     switch (buffer.bytes.size()) {
554     default:
555       break;
556     case 1:
557       return *(const uint8_t *)buffer.bytes.data();
558     case 2:
559       return *reinterpret_cast<const uint16_t *>(buffer.bytes.data());
560     case 4:
561       return *reinterpret_cast<const uint32_t *>(buffer.bytes.data());
562     case 8:
563       return *reinterpret_cast<const uint64_t *>(buffer.bytes.data());
564     }
565   } break;
566   }
567   if (success_ptr)
568     *success_ptr = false;
569   return fail_value;
570 }
571 
GetAsUInt128(const llvm::APInt & fail_value,bool * success_ptr) const572 llvm::APInt RegisterValue::GetAsUInt128(const llvm::APInt &fail_value,
573                                         bool *success_ptr) const {
574   if (success_ptr)
575     *success_ptr = true;
576   switch (m_type) {
577   default:
578     break;
579   case eTypeUInt8:
580   case eTypeUInt16:
581   case eTypeUInt32:
582   case eTypeUInt64:
583   case eTypeUInt128:
584   case eTypeFloat:
585   case eTypeDouble:
586   case eTypeLongDouble:
587     return m_scalar.UInt128(fail_value);
588   case eTypeBytes: {
589     switch (buffer.bytes.size()) {
590     default:
591       break;
592     case 1:
593     case 2:
594     case 4:
595     case 8:
596     case 16:
597       return llvm::APInt(
598           BITWIDTH_INT128, NUM_OF_WORDS_INT128,
599           (reinterpret_cast<const type128 *>(buffer.bytes.data()))->x);
600     }
601   } break;
602   }
603   if (success_ptr)
604     *success_ptr = false;
605   return fail_value;
606 }
607 
GetAsFloat(float fail_value,bool * success_ptr) const608 float RegisterValue::GetAsFloat(float fail_value, bool *success_ptr) const {
609   if (success_ptr)
610     *success_ptr = true;
611   switch (m_type) {
612   default:
613     break;
614   case eTypeUInt32:
615   case eTypeUInt64:
616   case eTypeUInt128:
617   case eTypeFloat:
618   case eTypeDouble:
619   case eTypeLongDouble:
620     return m_scalar.Float(fail_value);
621   }
622   if (success_ptr)
623     *success_ptr = false;
624   return fail_value;
625 }
626 
GetAsDouble(double fail_value,bool * success_ptr) const627 double RegisterValue::GetAsDouble(double fail_value, bool *success_ptr) const {
628   if (success_ptr)
629     *success_ptr = true;
630   switch (m_type) {
631   default:
632     break;
633 
634   case eTypeUInt32:
635   case eTypeUInt64:
636   case eTypeUInt128:
637   case eTypeFloat:
638   case eTypeDouble:
639   case eTypeLongDouble:
640     return m_scalar.Double(fail_value);
641   }
642   if (success_ptr)
643     *success_ptr = false;
644   return fail_value;
645 }
646 
GetAsLongDouble(long double fail_value,bool * success_ptr) const647 long double RegisterValue::GetAsLongDouble(long double fail_value,
648                                            bool *success_ptr) const {
649   if (success_ptr)
650     *success_ptr = true;
651   switch (m_type) {
652   default:
653     break;
654 
655   case eTypeUInt32:
656   case eTypeUInt64:
657   case eTypeUInt128:
658   case eTypeFloat:
659   case eTypeDouble:
660   case eTypeLongDouble:
661     return m_scalar.LongDouble();
662   }
663   if (success_ptr)
664     *success_ptr = false;
665   return fail_value;
666 }
667 
GetBytes() const668 const void *RegisterValue::GetBytes() const {
669   switch (m_type) {
670   case eTypeInvalid:
671     break;
672   case eTypeUInt8:
673   case eTypeUInt16:
674   case eTypeUInt32:
675   case eTypeUInt64:
676   case eTypeUInt128:
677   case eTypeFloat:
678   case eTypeDouble:
679   case eTypeLongDouble:
680     m_scalar.GetBytes(buffer.bytes);
681     return buffer.bytes.data();
682   case eTypeBytes:
683     return buffer.bytes.data();
684   }
685   return nullptr;
686 }
687 
GetByteSize() const688 uint32_t RegisterValue::GetByteSize() const {
689   switch (m_type) {
690   case eTypeInvalid:
691     break;
692   case eTypeUInt8:
693     return 1;
694   case eTypeUInt16:
695     return 2;
696   case eTypeUInt32:
697   case eTypeUInt64:
698   case eTypeUInt128:
699   case eTypeFloat:
700   case eTypeDouble:
701   case eTypeLongDouble:
702     return m_scalar.GetByteSize();
703   case eTypeBytes:
704     return buffer.bytes.size();
705   }
706   return 0;
707 }
708 
SetUInt(uint64_t uint,uint32_t byte_size)709 bool RegisterValue::SetUInt(uint64_t uint, uint32_t byte_size) {
710   if (byte_size == 0) {
711     SetUInt64(uint);
712   } else if (byte_size == 1) {
713     SetUInt8(uint);
714   } else if (byte_size <= 2) {
715     SetUInt16(uint);
716   } else if (byte_size <= 4) {
717     SetUInt32(uint);
718   } else if (byte_size <= 8) {
719     SetUInt64(uint);
720   } else if (byte_size <= 16) {
721     SetUInt128(llvm::APInt(128, uint));
722   } else
723     return false;
724   return true;
725 }
726 
SetBytes(const void * bytes,size_t length,lldb::ByteOrder byte_order)727 void RegisterValue::SetBytes(const void *bytes, size_t length,
728                              lldb::ByteOrder byte_order) {
729   if (bytes && length > 0) {
730     m_type = eTypeBytes;
731     buffer.bytes.resize(length);
732     memcpy(buffer.bytes.data(), bytes, length);
733     buffer.byte_order = byte_order;
734   } else {
735     m_type = eTypeInvalid;
736     buffer.bytes.resize(0);
737   }
738 }
739 
operator ==(const RegisterValue & rhs) const740 bool RegisterValue::operator==(const RegisterValue &rhs) const {
741   if (m_type == rhs.m_type) {
742     switch (m_type) {
743     case eTypeInvalid:
744       return true;
745     case eTypeUInt8:
746     case eTypeUInt16:
747     case eTypeUInt32:
748     case eTypeUInt64:
749     case eTypeUInt128:
750     case eTypeFloat:
751     case eTypeDouble:
752     case eTypeLongDouble:
753       return m_scalar == rhs.m_scalar;
754     case eTypeBytes:
755       return buffer.bytes == rhs.buffer.bytes;
756     }
757   }
758   return false;
759 }
760 
operator !=(const RegisterValue & rhs) const761 bool RegisterValue::operator!=(const RegisterValue &rhs) const {
762   return !(*this == rhs);
763 }
764 
ClearBit(uint32_t bit)765 bool RegisterValue::ClearBit(uint32_t bit) {
766   switch (m_type) {
767   case eTypeInvalid:
768     break;
769 
770   case eTypeUInt8:
771   case eTypeUInt16:
772   case eTypeUInt32:
773   case eTypeUInt64:
774   case eTypeUInt128:
775     if (bit < (GetByteSize() * 8)) {
776       return m_scalar.ClearBit(bit);
777     }
778     break;
779 
780   case eTypeFloat:
781   case eTypeDouble:
782   case eTypeLongDouble:
783     break;
784 
785   case eTypeBytes:
786     if (buffer.byte_order == eByteOrderBig ||
787         buffer.byte_order == eByteOrderLittle) {
788       uint32_t byte_idx;
789       if (buffer.byte_order == eByteOrderBig)
790         byte_idx = buffer.bytes.size() - (bit / 8) - 1;
791       else
792         byte_idx = bit / 8;
793 
794       const uint32_t byte_bit = bit % 8;
795       if (byte_idx < buffer.bytes.size()) {
796         buffer.bytes[byte_idx] &= ~(1u << byte_bit);
797         return true;
798       }
799     }
800     break;
801   }
802   return false;
803 }
804 
SetBit(uint32_t bit)805 bool RegisterValue::SetBit(uint32_t bit) {
806   switch (m_type) {
807   case eTypeInvalid:
808     break;
809 
810   case eTypeUInt8:
811   case eTypeUInt16:
812   case eTypeUInt32:
813   case eTypeUInt64:
814   case eTypeUInt128:
815     if (bit < (GetByteSize() * 8)) {
816       return m_scalar.SetBit(bit);
817     }
818     break;
819 
820   case eTypeFloat:
821   case eTypeDouble:
822   case eTypeLongDouble:
823     break;
824 
825   case eTypeBytes:
826     if (buffer.byte_order == eByteOrderBig ||
827         buffer.byte_order == eByteOrderLittle) {
828       uint32_t byte_idx;
829       if (buffer.byte_order == eByteOrderBig)
830         byte_idx = buffer.bytes.size() - (bit / 8) - 1;
831       else
832         byte_idx = bit / 8;
833 
834       const uint32_t byte_bit = bit % 8;
835       if (byte_idx < buffer.bytes.size()) {
836         buffer.bytes[byte_idx] |= (1u << byte_bit);
837         return true;
838       }
839     }
840     break;
841   }
842   return false;
843 }
844