xref: /openbsd/gnu/llvm/lldb/source/Utility/Scalar.cpp (revision f6aab3d8)
1 //===-- Scalar.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/Scalar.h"
10 #include "lldb/Utility/DataBufferHeap.h"
11 #include "lldb/Utility/DataExtractor.h"
12 #include "lldb/Utility/Endian.h"
13 #include "lldb/Utility/Status.h"
14 #include "lldb/Utility/Stream.h"
15 #include "lldb/Utility/StreamString.h"
16 #include "lldb/lldb-types.h"
17 #include "llvm/ADT/APSInt.h"
18 #include "llvm/ADT/SmallString.h"
19 
20 #include <cinttypes>
21 #include <cstdio>
22 
23 using namespace lldb;
24 using namespace lldb_private;
25 
26 using llvm::APFloat;
27 using llvm::APInt;
28 using llvm::APSInt;
29 
GetPromoKey() const30 Scalar::PromotionKey Scalar::GetPromoKey() const {
31   switch (m_type) {
32   case e_void:
33     return PromotionKey{e_void, 0, false};
34   case e_int:
35     return PromotionKey{e_int, m_integer.getBitWidth(), m_integer.isUnsigned()};
36   case e_float:
37     return GetFloatPromoKey(m_float.getSemantics());
38   }
39   llvm_unreachable("Unhandled category!");
40 }
41 
GetFloatPromoKey(const llvm::fltSemantics & sem)42 Scalar::PromotionKey Scalar::GetFloatPromoKey(const llvm::fltSemantics &sem) {
43   static const llvm::fltSemantics *const order[] = {
44       &APFloat::IEEEsingle(), &APFloat::IEEEdouble(),
45       &APFloat::x87DoubleExtended()};
46   for (const auto &entry : llvm::enumerate(order)) {
47     if (entry.value() == &sem)
48       return PromotionKey{e_float, entry.index(), false};
49   }
50   llvm_unreachable("Unsupported semantics!");
51 }
52 
53 // Promote to max type currently follows the ANSI C rule for type promotion in
54 // expressions.
PromoteToMaxType(Scalar & lhs,Scalar & rhs)55 Scalar::Type Scalar::PromoteToMaxType(Scalar &lhs, Scalar &rhs) {
56   const auto &Promote = [](Scalar &a, const Scalar &b) {
57     switch (b.GetType()) {
58     case e_void:
59       break;
60     case e_int:
61       a.IntegralPromote(b.m_integer.getBitWidth(), b.m_integer.isSigned());
62       break;
63     case e_float:
64       a.FloatPromote(b.m_float.getSemantics());
65     }
66   };
67 
68   PromotionKey lhs_key = lhs.GetPromoKey();
69   PromotionKey rhs_key = rhs.GetPromoKey();
70 
71   if (lhs_key > rhs_key)
72     Promote(rhs, lhs);
73   else if (rhs_key > lhs_key)
74     Promote(lhs, rhs);
75 
76   // Make sure our type promotion worked as expected
77   if (lhs.GetPromoKey() == rhs.GetPromoKey())
78     return lhs.GetType(); // Return the resulting type
79 
80   // Return the void type (zero) if we fail to promote either of the values.
81   return Scalar::e_void;
82 }
83 
GetData(DataExtractor & data,size_t limit_byte_size) const84 bool Scalar::GetData(DataExtractor &data, size_t limit_byte_size) const {
85   size_t byte_size = GetByteSize();
86   if (byte_size == 0) {
87     data.Clear();
88     return false;
89   }
90   auto buffer_up = std::make_unique<DataBufferHeap>(byte_size, 0);
91   GetBytes(buffer_up->GetData());
92   lldb::offset_t offset = 0;
93 
94   if (limit_byte_size < byte_size) {
95     if (endian::InlHostByteOrder() == eByteOrderLittle) {
96       // On little endian systems if we want fewer bytes from the current
97       // type we just specify fewer bytes since the LSByte is first...
98       byte_size = limit_byte_size;
99     } else if (endian::InlHostByteOrder() == eByteOrderBig) {
100       // On big endian systems if we want fewer bytes from the current type
101       // have to advance our initial byte pointer and trim down the number of
102       // bytes since the MSByte is first
103       offset = byte_size - limit_byte_size;
104       byte_size = limit_byte_size;
105     }
106   }
107 
108   data.SetData(std::move(buffer_up), offset, byte_size);
109   data.SetByteOrder(endian::InlHostByteOrder());
110   return true;
111 }
112 
GetBytes(llvm::MutableArrayRef<uint8_t> storage) const113 void Scalar::GetBytes(llvm::MutableArrayRef<uint8_t> storage) const {
114   assert(storage.size() >= GetByteSize());
115 
116   const auto &store = [&](const llvm::APInt &val) {
117     StoreIntToMemory(val, storage.data(), (val.getBitWidth() + 7) / 8);
118   };
119   switch (m_type) {
120   case e_void:
121     break;
122   case e_int:
123     store(m_integer);
124     break;
125   case e_float:
126     store(m_float.bitcastToAPInt());
127     break;
128   }
129 }
130 
GetByteSize() const131 size_t Scalar::GetByteSize() const {
132   switch (m_type) {
133   case e_void:
134     break;
135   case e_int:
136     return (m_integer.getBitWidth() / 8);
137   case e_float:
138     return m_float.bitcastToAPInt().getBitWidth() / 8;
139   }
140   return 0;
141 }
142 
IsZero() const143 bool Scalar::IsZero() const {
144   switch (m_type) {
145   case e_void:
146     break;
147   case e_int:
148     return m_integer.isNullValue();
149   case e_float:
150     return m_float.isZero();
151   }
152   return false;
153 }
154 
GetValue(Stream * s,bool show_type) const155 void Scalar::GetValue(Stream *s, bool show_type) const {
156   if (show_type)
157     s->Printf("(%s) ", GetTypeAsCString());
158 
159   switch (m_type) {
160   case e_void:
161     break;
162   case e_int:
163     s->PutCString(llvm::toString(m_integer, 10));
164     break;
165   case e_float:
166     llvm::SmallString<24> string;
167     m_float.toString(string);
168     s->PutCString(string);
169     break;
170   }
171 }
172 
TruncOrExtendTo(uint16_t bits,bool sign)173 void Scalar::TruncOrExtendTo(uint16_t bits, bool sign) {
174   m_integer.setIsSigned(sign);
175   m_integer = m_integer.extOrTrunc(bits);
176 }
177 
IntegralPromote(uint16_t bits,bool sign)178 bool Scalar::IntegralPromote(uint16_t bits, bool sign) {
179   switch (m_type) {
180   case e_void:
181   case e_float:
182     break;
183   case e_int:
184     if (GetPromoKey() > PromotionKey(e_int, bits, !sign))
185       break;
186     m_integer = m_integer.extOrTrunc(bits);
187     m_integer.setIsSigned(sign);
188     return true;
189   }
190   return false;
191 }
192 
FloatPromote(const llvm::fltSemantics & semantics)193 bool Scalar::FloatPromote(const llvm::fltSemantics &semantics) {
194   bool success = false;
195   switch (m_type) {
196   case e_void:
197     break;
198   case e_int:
199     m_float = llvm::APFloat(semantics);
200     m_float.convertFromAPInt(m_integer, m_integer.isSigned(),
201                              llvm::APFloat::rmNearestTiesToEven);
202     success = true;
203     break;
204   case e_float:
205     if (GetFloatPromoKey(semantics) < GetFloatPromoKey(m_float.getSemantics()))
206       break;
207     bool ignore;
208     success = true;
209     m_float.convert(semantics, llvm::APFloat::rmNearestTiesToEven, &ignore);
210   }
211 
212   if (success)
213     m_type = e_float;
214   return success;
215 }
216 
GetValueTypeAsCString(Scalar::Type type)217 const char *Scalar::GetValueTypeAsCString(Scalar::Type type) {
218   switch (type) {
219   case e_void:
220     return "void";
221   case e_int:
222     return "int";
223   case e_float:
224     return "float";
225   }
226   return "???";
227 }
228 
IsSigned() const229 bool Scalar::IsSigned() const {
230   switch (m_type) {
231   case e_void:
232     return false;
233   case e_int:
234     return m_integer.isSigned();
235   case e_float:
236     return true;
237   }
238   llvm_unreachable("Unrecognized type!");
239 }
240 
MakeSigned()241 bool Scalar::MakeSigned() {
242   bool success = false;
243 
244   switch (m_type) {
245   case e_void:
246     break;
247   case e_int:
248     m_integer.setIsSigned(true);
249     success = true;
250     break;
251   case e_float:
252     success = true;
253     break;
254   }
255 
256   return success;
257 }
258 
MakeUnsigned()259 bool Scalar::MakeUnsigned() {
260   bool success = false;
261 
262   switch (m_type) {
263   case e_void:
264     break;
265   case e_int:
266     m_integer.setIsUnsigned(true);
267     success = true;
268     break;
269   case e_float:
270     success = true;
271     break;
272   }
273 
274   return success;
275 }
276 
ToAPInt(const llvm::APFloat & f,unsigned bits,bool is_unsigned)277 static llvm::APInt ToAPInt(const llvm::APFloat &f, unsigned bits,
278                            bool is_unsigned) {
279   llvm::APSInt result(bits, is_unsigned);
280   bool isExact;
281   f.convertToInteger(result, llvm::APFloat::rmTowardZero, &isExact);
282   return std::move(result);
283 }
284 
GetAs(T fail_value) const285 template <typename T> T Scalar::GetAs(T fail_value) const {
286   switch (m_type) {
287   case e_void:
288     break;
289   case e_int: {
290     APSInt ext = m_integer.extOrTrunc(sizeof(T) * 8);
291     if (ext.isSigned())
292       return ext.getSExtValue();
293     return ext.getZExtValue();
294   }
295   case e_float:
296     return ToAPInt(m_float, sizeof(T) * 8, std::is_unsigned<T>::value)
297         .getSExtValue();
298   }
299   return fail_value;
300 }
301 
SChar(signed char fail_value) const302 signed char Scalar::SChar(signed char fail_value) const {
303   return GetAs<signed char>(fail_value);
304 }
305 
UChar(unsigned char fail_value) const306 unsigned char Scalar::UChar(unsigned char fail_value) const {
307   return GetAs<unsigned char>(fail_value);
308 }
309 
SShort(short fail_value) const310 short Scalar::SShort(short fail_value) const {
311   return GetAs<short>(fail_value);
312 }
313 
UShort(unsigned short fail_value) const314 unsigned short Scalar::UShort(unsigned short fail_value) const {
315   return GetAs<unsigned short>(fail_value);
316 }
317 
SInt(int fail_value) const318 int Scalar::SInt(int fail_value) const { return GetAs<int>(fail_value); }
319 
UInt(unsigned int fail_value) const320 unsigned int Scalar::UInt(unsigned int fail_value) const {
321   return GetAs<unsigned int>(fail_value);
322 }
323 
SLong(long fail_value) const324 long Scalar::SLong(long fail_value) const { return GetAs<long>(fail_value); }
325 
ULong(unsigned long fail_value) const326 unsigned long Scalar::ULong(unsigned long fail_value) const {
327   return GetAs<unsigned long>(fail_value);
328 }
329 
SLongLong(long long fail_value) const330 long long Scalar::SLongLong(long long fail_value) const {
331   return GetAs<long long>(fail_value);
332 }
333 
ULongLong(unsigned long long fail_value) const334 unsigned long long Scalar::ULongLong(unsigned long long fail_value) const {
335   return GetAs<unsigned long long>(fail_value);
336 }
337 
SInt128(const llvm::APInt & fail_value) const338 llvm::APInt Scalar::SInt128(const llvm::APInt &fail_value) const {
339   switch (m_type) {
340   case e_void:
341     break;
342   case e_int:
343     return m_integer;
344   case e_float:
345     return ToAPInt(m_float, 128, /*is_unsigned=*/false);
346   }
347   return fail_value;
348 }
349 
UInt128(const llvm::APInt & fail_value) const350 llvm::APInt Scalar::UInt128(const llvm::APInt &fail_value) const {
351   switch (m_type) {
352   case e_void:
353     break;
354   case e_int:
355     return m_integer;
356   case e_float:
357     return ToAPInt(m_float, 128, /*is_unsigned=*/true);
358   }
359   return fail_value;
360 }
361 
Float(float fail_value) const362 float Scalar::Float(float fail_value) const {
363   switch (m_type) {
364   case e_void:
365     break;
366   case e_int:
367     if (m_integer.isSigned())
368       return llvm::APIntOps::RoundSignedAPIntToFloat(m_integer);
369     return llvm::APIntOps::RoundAPIntToFloat(m_integer);
370 
371   case e_float: {
372     APFloat result = m_float;
373     bool losesInfo;
374     result.convert(APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven,
375                    &losesInfo);
376     return result.convertToFloat();
377   }
378   }
379   return fail_value;
380 }
381 
Double(double fail_value) const382 double Scalar::Double(double fail_value) const {
383   switch (m_type) {
384   case e_void:
385     break;
386   case e_int:
387     if (m_integer.isSigned())
388       return llvm::APIntOps::RoundSignedAPIntToDouble(m_integer);
389     return llvm::APIntOps::RoundAPIntToDouble(m_integer);
390 
391   case e_float: {
392     APFloat result = m_float;
393     bool losesInfo;
394     result.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven,
395                    &losesInfo);
396     return result.convertToDouble();
397   }
398   }
399   return fail_value;
400 }
401 
LongDouble(long double fail_value) const402 long double Scalar::LongDouble(long double fail_value) const {
403   /// No way to get more precision at the moment.
404   return static_cast<long double>(Double(fail_value));
405 }
406 
operator +=(Scalar rhs)407 Scalar &Scalar::operator+=(Scalar rhs) {
408   Scalar copy = *this;
409   if ((m_type = PromoteToMaxType(copy, rhs)) != Scalar::e_void) {
410     switch (m_type) {
411     case e_void:
412       break;
413     case e_int:
414       m_integer = copy.m_integer + rhs.m_integer;
415       break;
416 
417     case e_float:
418       m_float = copy.m_float + rhs.m_float;
419       break;
420     }
421   }
422   return *this;
423 }
424 
operator <<=(const Scalar & rhs)425 Scalar &Scalar::operator<<=(const Scalar &rhs) {
426   if (m_type == e_int && rhs.m_type == e_int)
427     static_cast<APInt &>(m_integer) <<= rhs.m_integer;
428   else
429     m_type = e_void;
430   return *this;
431 }
432 
ShiftRightLogical(const Scalar & rhs)433 bool Scalar::ShiftRightLogical(const Scalar &rhs) {
434   if (m_type == e_int && rhs.m_type == e_int) {
435     m_integer = m_integer.lshr(rhs.m_integer);
436     return true;
437   }
438   m_type = e_void;
439   return false;
440 }
441 
operator >>=(const Scalar & rhs)442 Scalar &Scalar::operator>>=(const Scalar &rhs) {
443   switch (m_type) {
444   case e_void:
445   case e_float:
446     m_type = e_void;
447     break;
448 
449   case e_int:
450     switch (rhs.m_type) {
451     case e_void:
452     case e_float:
453       m_type = e_void;
454       break;
455     case e_int:
456       m_integer = m_integer.ashr(rhs.m_integer);
457       break;
458     }
459     break;
460   }
461   return *this;
462 }
463 
operator &=(const Scalar & rhs)464 Scalar &Scalar::operator&=(const Scalar &rhs) {
465   if (m_type == e_int && rhs.m_type == e_int)
466     m_integer &= rhs.m_integer;
467   else
468     m_type = e_void;
469   return *this;
470 }
471 
AbsoluteValue()472 bool Scalar::AbsoluteValue() {
473   switch (m_type) {
474   case e_void:
475     break;
476 
477   case e_int:
478     if (m_integer.isNegative())
479       m_integer = -m_integer;
480     return true;
481 
482   case e_float:
483     m_float.clearSign();
484     return true;
485   }
486   return false;
487 }
488 
UnaryNegate()489 bool Scalar::UnaryNegate() {
490   switch (m_type) {
491   case e_void:
492     break;
493   case e_int:
494     m_integer = -m_integer;
495     return true;
496   case e_float:
497     m_float.changeSign();
498     return true;
499   }
500   return false;
501 }
502 
OnesComplement()503 bool Scalar::OnesComplement() {
504   if (m_type == e_int) {
505     m_integer = ~m_integer;
506     return true;
507   }
508 
509   return false;
510 }
511 
operator +(const Scalar & lhs,const Scalar & rhs)512 const Scalar lldb_private::operator+(const Scalar &lhs, const Scalar &rhs) {
513   Scalar result = lhs;
514   result += rhs;
515   return result;
516 }
517 
operator -(Scalar lhs,Scalar rhs)518 const Scalar lldb_private::operator-(Scalar lhs, Scalar rhs) {
519   Scalar result;
520   if ((result.m_type = Scalar::PromoteToMaxType(lhs, rhs)) != Scalar::e_void) {
521     switch (result.m_type) {
522     case Scalar::e_void:
523       break;
524     case Scalar::e_int:
525       result.m_integer = lhs.m_integer - rhs.m_integer;
526       break;
527     case Scalar::e_float:
528       result.m_float = lhs.m_float - rhs.m_float;
529       break;
530     }
531   }
532   return result;
533 }
534 
operator /(Scalar lhs,Scalar rhs)535 const Scalar lldb_private::operator/(Scalar lhs, Scalar rhs) {
536   Scalar result;
537   if ((result.m_type = Scalar::PromoteToMaxType(lhs, rhs)) != Scalar::e_void &&
538       !rhs.IsZero()) {
539     switch (result.m_type) {
540     case Scalar::e_void:
541       break;
542     case Scalar::e_int:
543       result.m_integer = lhs.m_integer / rhs.m_integer;
544       return result;
545     case Scalar::e_float:
546       result.m_float = lhs.m_float / rhs.m_float;
547       return result;
548     }
549   }
550   // For division only, the only way it should make it here is if a promotion
551   // failed, or if we are trying to do a divide by zero.
552   result.m_type = Scalar::e_void;
553   return result;
554 }
555 
operator *(Scalar lhs,Scalar rhs)556 const Scalar lldb_private::operator*(Scalar lhs, Scalar rhs) {
557   Scalar result;
558   if ((result.m_type = Scalar::PromoteToMaxType(lhs, rhs)) != Scalar::e_void) {
559     switch (result.m_type) {
560     case Scalar::e_void:
561       break;
562     case Scalar::e_int:
563       result.m_integer = lhs.m_integer * rhs.m_integer;
564       break;
565     case Scalar::e_float:
566       result.m_float = lhs.m_float * rhs.m_float;
567       break;
568     }
569   }
570   return result;
571 }
572 
operator &(Scalar lhs,Scalar rhs)573 const Scalar lldb_private::operator&(Scalar lhs, Scalar rhs) {
574   Scalar result;
575   if ((result.m_type = Scalar::PromoteToMaxType(lhs, rhs)) != Scalar::e_void) {
576     if (result.m_type == Scalar::e_int)
577       result.m_integer = lhs.m_integer & rhs.m_integer;
578     else
579       result.m_type = Scalar::e_void;
580   }
581   return result;
582 }
583 
operator |(Scalar lhs,Scalar rhs)584 const Scalar lldb_private::operator|(Scalar lhs, Scalar rhs) {
585   Scalar result;
586   if ((result.m_type = Scalar::PromoteToMaxType(lhs, rhs)) != Scalar::e_void) {
587     if (result.m_type == Scalar::e_int)
588       result.m_integer = lhs.m_integer | rhs.m_integer;
589     else
590       result.m_type = Scalar::e_void;
591   }
592   return result;
593 }
594 
operator %(Scalar lhs,Scalar rhs)595 const Scalar lldb_private::operator%(Scalar lhs, Scalar rhs) {
596   Scalar result;
597   if ((result.m_type = Scalar::PromoteToMaxType(lhs, rhs)) != Scalar::e_void) {
598     if (!rhs.IsZero() && result.m_type == Scalar::e_int) {
599       result.m_integer = lhs.m_integer % rhs.m_integer;
600       return result;
601     }
602   }
603   result.m_type = Scalar::e_void;
604   return result;
605 }
606 
operator ^(Scalar lhs,Scalar rhs)607 const Scalar lldb_private::operator^(Scalar lhs, Scalar rhs) {
608   Scalar result;
609   if ((result.m_type = Scalar::PromoteToMaxType(lhs, rhs)) != Scalar::e_void) {
610     if (result.m_type == Scalar::e_int)
611       result.m_integer = lhs.m_integer ^ rhs.m_integer;
612     else
613       result.m_type = Scalar::e_void;
614   }
615   return result;
616 }
617 
operator <<(const Scalar & lhs,const Scalar & rhs)618 const Scalar lldb_private::operator<<(const Scalar &lhs, const Scalar &rhs) {
619   Scalar result = lhs;
620   result <<= rhs;
621   return result;
622 }
623 
operator >>(const Scalar & lhs,const Scalar & rhs)624 const Scalar lldb_private::operator>>(const Scalar &lhs, const Scalar &rhs) {
625   Scalar result = lhs;
626   result >>= rhs;
627   return result;
628 }
629 
SetValueFromCString(const char * value_str,Encoding encoding,size_t byte_size)630 Status Scalar::SetValueFromCString(const char *value_str, Encoding encoding,
631                                    size_t byte_size) {
632   Status error;
633   if (value_str == nullptr || value_str[0] == '\0') {
634     error.SetErrorString("Invalid c-string value string.");
635     return error;
636   }
637   switch (encoding) {
638   case eEncodingInvalid:
639     error.SetErrorString("Invalid encoding.");
640     break;
641 
642   case eEncodingSint:
643   case eEncodingUint: {
644     llvm::StringRef str = value_str;
645     bool is_signed = encoding == eEncodingSint;
646     bool is_negative = is_signed && str.consume_front("-");
647     APInt integer;
648     if (str.getAsInteger(0, integer)) {
649       error.SetErrorStringWithFormatv(
650           "'{0}' is not a valid integer string value", value_str);
651       break;
652     }
653     bool fits;
654     if (is_signed) {
655       integer = integer.zext(integer.getBitWidth() + 1);
656       if (is_negative)
657         integer.negate();
658       fits = integer.isSignedIntN(byte_size * 8);
659     } else
660       fits = integer.isIntN(byte_size * 8);
661     if (!fits) {
662       error.SetErrorStringWithFormatv(
663           "value {0} is too large to fit in a {1} byte integer value",
664           value_str, byte_size);
665       break;
666     }
667     m_type = e_int;
668     m_integer =
669         APSInt(std::move(integer), !is_signed).extOrTrunc(8 * byte_size);
670     break;
671   }
672 
673   case eEncodingIEEE754: {
674     // FIXME: It's not possible to unambiguously map a byte size to a floating
675     // point type. This function should be refactored to take an explicit
676     // semantics argument.
677     const llvm::fltSemantics &sem =
678         byte_size <= 4 ? APFloat::IEEEsingle()
679                        : byte_size <= 8 ? APFloat::IEEEdouble()
680                                         : APFloat::x87DoubleExtended();
681     APFloat f(sem);
682     if (llvm::Expected<APFloat::opStatus> op =
683             f.convertFromString(value_str, APFloat::rmNearestTiesToEven)) {
684       m_type = e_float;
685       m_float = std::move(f);
686     } else
687       error = op.takeError();
688     break;
689   }
690 
691   case eEncodingVector:
692     error.SetErrorString("vector encoding unsupported.");
693     break;
694   }
695   if (error.Fail())
696     m_type = e_void;
697 
698   return error;
699 }
700 
SetValueFromData(const DataExtractor & data,lldb::Encoding encoding,size_t byte_size)701 Status Scalar::SetValueFromData(const DataExtractor &data,
702                                 lldb::Encoding encoding, size_t byte_size) {
703   Status error;
704   switch (encoding) {
705   case lldb::eEncodingInvalid:
706     error.SetErrorString("invalid encoding");
707     break;
708   case lldb::eEncodingVector:
709     error.SetErrorString("vector encoding unsupported");
710     break;
711   case lldb::eEncodingUint:
712   case lldb::eEncodingSint: {
713     if (data.GetByteSize() < byte_size)
714       return Status("insufficient data");
715     m_type = e_int;
716     m_integer =
717         APSInt(APInt::getZero(8 * byte_size), encoding == eEncodingUint);
718     if (data.GetByteOrder() == endian::InlHostByteOrder()) {
719       llvm::LoadIntFromMemory(m_integer, data.GetDataStart(), byte_size);
720     } else {
721       std::vector<uint8_t> buffer(byte_size);
722       std::copy_n(data.GetDataStart(), byte_size, buffer.rbegin());
723       llvm::LoadIntFromMemory(m_integer, buffer.data(), byte_size);
724     }
725     break;
726   }
727   case lldb::eEncodingIEEE754: {
728     lldb::offset_t offset = 0;
729 
730     if (byte_size == sizeof(float))
731       operator=(data.GetFloat(&offset));
732     else if (byte_size == sizeof(double))
733       operator=(data.GetDouble(&offset));
734     else if (byte_size == sizeof(long double))
735       operator=(data.GetLongDouble(&offset));
736     else
737       error.SetErrorStringWithFormat("unsupported float byte size: %" PRIu64 "",
738                                      static_cast<uint64_t>(byte_size));
739   } break;
740   }
741 
742   return error;
743 }
744 
SignExtend(uint32_t sign_bit_pos)745 bool Scalar::SignExtend(uint32_t sign_bit_pos) {
746   const uint32_t max_bit_pos = GetByteSize() * 8;
747 
748   if (sign_bit_pos < max_bit_pos) {
749     switch (m_type) {
750     case Scalar::e_void:
751     case Scalar::e_float:
752       return false;
753 
754     case Scalar::e_int:
755       if (max_bit_pos == sign_bit_pos)
756         return true;
757       else if (sign_bit_pos < (max_bit_pos - 1)) {
758         llvm::APInt sign_bit = llvm::APInt::getSignMask(sign_bit_pos + 1);
759         llvm::APInt bitwize_and = m_integer & sign_bit;
760         if (bitwize_and.getBoolValue()) {
761           llvm::APInt mask =
762               ~(sign_bit) + llvm::APInt(m_integer.getBitWidth(), 1);
763           m_integer |= APSInt(std::move(mask), m_integer.isUnsigned());
764         }
765         return true;
766       }
767       break;
768     }
769   }
770   return false;
771 }
772 
GetAsMemoryData(void * dst,size_t dst_len,lldb::ByteOrder dst_byte_order,Status & error) const773 size_t Scalar::GetAsMemoryData(void *dst, size_t dst_len,
774                                lldb::ByteOrder dst_byte_order,
775                                Status &error) const {
776   // Get a data extractor that points to the native scalar data
777   DataExtractor data;
778   if (!GetData(data)) {
779     error.SetErrorString("invalid scalar value");
780     return 0;
781   }
782 
783   const size_t src_len = data.GetByteSize();
784 
785   // Prepare a memory buffer that contains some or all of the register value
786   const size_t bytes_copied =
787       data.CopyByteOrderedData(0,               // src offset
788                                src_len,         // src length
789                                dst,             // dst buffer
790                                dst_len,         // dst length
791                                dst_byte_order); // dst byte order
792   if (bytes_copied == 0)
793     error.SetErrorString("failed to copy data");
794 
795   return bytes_copied;
796 }
797 
ExtractBitfield(uint32_t bit_size,uint32_t bit_offset)798 bool Scalar::ExtractBitfield(uint32_t bit_size, uint32_t bit_offset) {
799   if (bit_size == 0)
800     return true;
801 
802   switch (m_type) {
803   case Scalar::e_void:
804   case Scalar::e_float:
805     break;
806 
807   case Scalar::e_int:
808     m_integer >>= bit_offset;
809     m_integer = m_integer.extOrTrunc(bit_size).extOrTrunc(8 * GetByteSize());
810     return true;
811   }
812   return false;
813 }
814 
operator ==(Scalar lhs,Scalar rhs)815 bool lldb_private::operator==(Scalar lhs, Scalar rhs) {
816   // If either entry is void then we can just compare the types
817   if (lhs.m_type == Scalar::e_void || rhs.m_type == Scalar::e_void)
818     return lhs.m_type == rhs.m_type;
819 
820   llvm::APFloat::cmpResult result;
821   switch (Scalar::PromoteToMaxType(lhs, rhs)) {
822   case Scalar::e_void:
823     break;
824   case Scalar::e_int:
825     return lhs.m_integer == rhs.m_integer;
826   case Scalar::e_float:
827     result = lhs.m_float.compare(rhs.m_float);
828     if (result == llvm::APFloat::cmpEqual)
829       return true;
830   }
831   return false;
832 }
833 
operator !=(const Scalar & lhs,const Scalar & rhs)834 bool lldb_private::operator!=(const Scalar &lhs, const Scalar &rhs) {
835   return !(lhs == rhs);
836 }
837 
operator <(Scalar lhs,Scalar rhs)838 bool lldb_private::operator<(Scalar lhs, Scalar rhs) {
839   if (lhs.m_type == Scalar::e_void || rhs.m_type == Scalar::e_void)
840     return false;
841 
842   llvm::APFloat::cmpResult result;
843   switch (Scalar::PromoteToMaxType(lhs, rhs)) {
844   case Scalar::e_void:
845     break;
846   case Scalar::e_int:
847     return lhs.m_integer < rhs.m_integer;
848   case Scalar::e_float:
849     result = lhs.m_float.compare(rhs.m_float);
850     if (result == llvm::APFloat::cmpLessThan)
851       return true;
852   }
853   return false;
854 }
855 
operator <=(const Scalar & lhs,const Scalar & rhs)856 bool lldb_private::operator<=(const Scalar &lhs, const Scalar &rhs) {
857   return !(rhs < lhs);
858 }
859 
operator >(const Scalar & lhs,const Scalar & rhs)860 bool lldb_private::operator>(const Scalar &lhs, const Scalar &rhs) {
861   return rhs < lhs;
862 }
863 
operator >=(const Scalar & lhs,const Scalar & rhs)864 bool lldb_private::operator>=(const Scalar &lhs, const Scalar &rhs) {
865   return !(lhs < rhs);
866 }
867 
ClearBit(uint32_t bit)868 bool Scalar::ClearBit(uint32_t bit) {
869   switch (m_type) {
870   case e_void:
871     break;
872   case e_int:
873     m_integer.clearBit(bit);
874     return true;
875   case e_float:
876     break;
877   }
878   return false;
879 }
880 
SetBit(uint32_t bit)881 bool Scalar::SetBit(uint32_t bit) {
882   switch (m_type) {
883   case e_void:
884     break;
885   case e_int:
886     m_integer.setBit(bit);
887     return true;
888   case e_float:
889     break;
890   }
891   return false;
892 }
893 
operator <<(llvm::raw_ostream & os,const Scalar & scalar)894 llvm::raw_ostream &lldb_private::operator<<(llvm::raw_ostream &os, const Scalar &scalar) {
895   StreamString s;
896   scalar.GetValue(&s, /*show_type*/ true);
897   return os << s.GetString();
898 }
899