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