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