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