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, 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) {
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);
111 return true;
112}
113
114void 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
132size_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
144bool 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
156void 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
174void Scalar::TruncOrExtendTo(uint16_t bits, bool sign) {
175 m_integer.setIsSigned(sign);
176 m_integer = m_integer.extOrTrunc(bits);
177}
178
179bool 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
194bool 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
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
230bool 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
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
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
278static 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
286template <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
303signed char Scalar::SChar(signed char fail_value) const {
304 return GetAs<signed char>(fail_value);
305}
306
307unsigned char Scalar::UChar(unsigned char fail_value) const {
308 return GetAs<unsigned char>(fail_value);
309}
310
311short Scalar::SShort(short fail_value) const {
312 return GetAs<short>(fail_value);
313}
314
315unsigned short Scalar::UShort(unsigned short fail_value) const {
316 return GetAs<unsigned short>(fail_value);
317}
318
319int Scalar::SInt(int fail_value) const { return GetAs<int>(fail_value); }
320
321unsigned int Scalar::UInt(unsigned int fail_value) const {
322 return GetAs<unsigned int>(fail_value);
323}
324
325long Scalar::SLong(long fail_value) const { return GetAs<long>(fail_value); }
326
327unsigned long Scalar::ULong(unsigned long fail_value) const {
328 return GetAs<unsigned long>(fail_value);
329}
330
331long long Scalar::SLongLong(long long fail_value) const {
332 return GetAs<long long>(fail_value);
333}
334
335unsigned long long Scalar::ULongLong(unsigned long long fail_value) const {
336 return GetAs<unsigned long long>(fail_value);
337}
338
339llvm::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
351llvm::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
363float 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
383double 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
403long 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
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
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
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
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
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
474 switch (m_type) {
475 case e_void:
476 break;
477
478 case e_int:
479 if (m_integer.isNegative())
481 return true;
482
483 case e_float:
484 m_float.clearSign();
485 return true;
486 }
487 return false;
488}
489
491 switch (m_type) {
492 case e_void:
493 break;
494 case e_int:
496 return true;
497 case e_float:
498 m_float.changeSign();
499 return true;
500 }
501 return false;
502}
503
505 if (m_type == e_int) {
506 m_integer = ~m_integer;
507 return true;
508 }
509
510 return false;
511}
512
513const Scalar lldb_private::operator+(const Scalar &lhs, const Scalar &rhs) {
514 Scalar result = lhs;
515 result += rhs;
516 return result;
517}
518
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
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
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
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
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
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
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
619const Scalar lldb_private::operator<<(const Scalar &lhs, const Scalar &rhs) {
620 Scalar result = lhs;
621 result <<= rhs;
622 return result;
623}
624
625const Scalar lldb_private::operator>>(const Scalar &lhs, const Scalar &rhs) {
626 Scalar result = lhs;
627 result >>= rhs;
628 return result;
629}
630
631Status Scalar::SetValueFromCString(const char *value_str, Encoding encoding,
632 size_t byte_size) {
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
703 lldb::Encoding encoding, size_t byte_size) {
705 switch (encoding) {
707 error.SetErrorString("invalid encoding");
708 break;
710 error.SetErrorString("vector encoding unsupported");
711 break;
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 }
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
746bool 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 (max_bit_pos == sign_bit_pos)
757 return true;
758 else if (sign_bit_pos < (max_bit_pos - 1)) {
759 llvm::APInt sign_bit = llvm::APInt::getSignMask(sign_bit_pos + 1);
760 llvm::APInt bitwize_and = m_integer & sign_bit;
761 if (bitwize_and.getBoolValue()) {
762 llvm::APInt mask =
763 ~(sign_bit) + llvm::APInt(m_integer.getBitWidth(), 1);
764 m_integer |= APSInt(std::move(mask), m_integer.isUnsigned());
765 }
766 return true;
767 }
768 break;
769 }
770 }
771 return false;
772}
773
774size_t Scalar::GetAsMemoryData(void *dst, size_t dst_len,
775 lldb::ByteOrder dst_byte_order,
776 Status &error) const {
777 // Get a data extractor that points to the native scalar data
778 DataExtractor data;
779 if (!GetData(data)) {
780 error.SetErrorString("invalid scalar value");
781 return 0;
782 }
783
784 const size_t src_len = data.GetByteSize();
785
786 // Prepare a memory buffer that contains some or all of the register value
787 const size_t bytes_copied =
788 data.CopyByteOrderedData(0, // src offset
789 src_len, // src length
790 dst, // dst buffer
791 dst_len, // dst length
792 dst_byte_order); // dst byte order
793 if (bytes_copied == 0)
794 error.SetErrorString("failed to copy data");
795
796 return bytes_copied;
797}
798
799bool Scalar::ExtractBitfield(uint32_t bit_size, uint32_t bit_offset) {
800 if (bit_size == 0)
801 return true;
802
803 switch (m_type) {
804 case Scalar::e_void:
805 case Scalar::e_float:
806 break;
807
808 case Scalar::e_int:
809 m_integer >>= bit_offset;
810 m_integer = m_integer.extOrTrunc(bit_size).extOrTrunc(8 * GetByteSize());
811 return true;
812 }
813 return false;
814}
815
817 switch (basic_type) {
819 return llvm::APFloat(
820 m_integer.isSigned()
821 ? llvm::APIntOps::RoundSignedAPIntToFloat(m_integer)
822 : llvm::APIntOps::RoundAPIntToFloat(m_integer));
824 // No way to get more precision at the moment.
826 return llvm::APFloat(
827 m_integer.isSigned()
828 ? llvm::APIntOps::RoundSignedAPIntToDouble(m_integer)
829 : llvm::APIntOps::RoundAPIntToDouble(m_integer));
830 default:
831 const llvm::fltSemantics &sem = APFloat::IEEEsingle();
832 return llvm::APFloat::getNaN(sem);
833 }
834}
835
837 switch (basic_type) {
839 bool loses_info;
840 m_float.convert(llvm::APFloat::IEEEsingle(),
841 llvm::APFloat::rmNearestTiesToEven, &loses_info);
842 return m_float;
843 }
845 // No way to get more precision at the moment.
847 bool loses_info;
848 m_float.convert(llvm::APFloat::IEEEdouble(),
849 llvm::APFloat::rmNearestTiesToEven, &loses_info);
850 return m_float;
851 }
852 default:
853 const llvm::fltSemantics &sem = APFloat::IEEEsingle();
854 return llvm::APFloat::getNaN(sem);
855 }
856}
857
859 // If either entry is void then we can just compare the types
860 if (lhs.m_type == Scalar::e_void || rhs.m_type == Scalar::e_void)
861 return lhs.m_type == rhs.m_type;
862
863 llvm::APFloat::cmpResult result;
864 switch (Scalar::PromoteToMaxType(lhs, rhs)) {
865 case Scalar::e_void:
866 break;
867 case Scalar::e_int:
868 return lhs.m_integer == rhs.m_integer;
869 case Scalar::e_float:
870 result = lhs.m_float.compare(rhs.m_float);
871 if (result == llvm::APFloat::cmpEqual)
872 return true;
873 }
874 return false;
875}
876
877bool lldb_private::operator!=(const Scalar &lhs, const Scalar &rhs) {
878 return !(lhs == rhs);
879}
880
882 if (lhs.m_type == Scalar::e_void || rhs.m_type == Scalar::e_void)
883 return false;
884
885 llvm::APFloat::cmpResult result;
886 switch (Scalar::PromoteToMaxType(lhs, rhs)) {
887 case Scalar::e_void:
888 break;
889 case Scalar::e_int:
890 return lhs.m_integer < rhs.m_integer;
891 case Scalar::e_float:
892 result = lhs.m_float.compare(rhs.m_float);
893 if (result == llvm::APFloat::cmpLessThan)
894 return true;
895 }
896 return false;
897}
898
899bool lldb_private::operator<=(const Scalar &lhs, const Scalar &rhs) {
900 return !(rhs < lhs);
901}
902
903bool lldb_private::operator>(const Scalar &lhs, const Scalar &rhs) {
904 return rhs < lhs;
905}
906
907bool lldb_private::operator>=(const Scalar &lhs, const Scalar &rhs) {
908 return !(lhs < rhs);
909}
910
911bool Scalar::ClearBit(uint32_t bit) {
912 switch (m_type) {
913 case e_void:
914 break;
915 case e_int:
916 m_integer.clearBit(bit);
917 return true;
918 case e_float:
919 break;
920 }
921 return false;
922}
923
924bool Scalar::SetBit(uint32_t bit) {
925 switch (m_type) {
926 case e_void:
927 break;
928 case e_int:
929 m_integer.setBit(bit);
930 return true;
931 case e_float:
932 break;
933 }
934 return false;
935}
936
937llvm::raw_ostream &lldb_private::operator<<(llvm::raw_ostream &os, const Scalar &scalar) {
938 StreamString s;
939 scalar.GetValue(s, /*show_type*/ true);
940 return os << s.GetString();
941}
static llvm::raw_ostream & error(Stream &strm)
#define bit
#define integer
static llvm::APInt ToAPInt(const llvm::APFloat &f, unsigned bits, bool is_unsigned)
Definition: Scalar.cpp:278
An data extractor class.
Definition: DataExtractor.h:48
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:321
llvm::APFloat CreateAPFloatFromAPFloat(lldb::BasicType basic_type)
Definition: Scalar.cpp:836
void GetValue(Stream &s, bool show_type) const
Definition: Scalar.cpp:156
llvm::APFloat CreateAPFloatFromAPSInt(lldb::BasicType basic_type)
Definition: Scalar.cpp:816
const char * GetTypeAsCString() const
Definition: Scalar.h:103
bool IntegralPromote(uint16_t bits, bool sign)
Definition: Scalar.cpp:179
bool SetBit(uint32_t bit)
Definition: Scalar.cpp:924
int SInt(int fail_value=0) const
Definition: Scalar.cpp:319
long SLong(long fail_value=0) const
Definition: Scalar.cpp:325
size_t GetByteSize() const
Definition: Scalar.cpp:132
unsigned char UChar(unsigned char fail_value=0) const
Definition: Scalar.cpp:307
Status SetValueFromData(const DataExtractor &data, lldb::Encoding encoding, size_t byte_size)
Definition: Scalar.cpp:702
llvm::APFloat m_float
Definition: Scalar.h:197
bool SignExtend(uint32_t bit_pos)
Definition: Scalar.cpp:746
short SShort(short fail_value=0) const
Definition: Scalar.cpp:311
bool IsZero() const
Definition: Scalar.cpp:144
T GetAs(T fail_value) const
Definition: Scalar.cpp:286
llvm::APSInt m_integer
Definition: Scalar.h:196
void TruncOrExtendTo(uint16_t bits, bool sign)
Convert to an integer with bits and the given signedness.
Definition: Scalar.cpp:174
unsigned long long ULongLong(unsigned long long fail_value=0) const
Definition: Scalar.cpp:335
Scalar::Type GetType() const
Definition: Scalar.h:149
unsigned long ULong(unsigned long fail_value=0) const
Definition: Scalar.cpp:327
bool IsSigned() const
Definition: Scalar.cpp:230
size_t GetAsMemoryData(void *dst, size_t dst_len, lldb::ByteOrder dst_byte_order, Status &error) const
Definition: Scalar.cpp:774
void GetBytes(llvm::MutableArrayRef< uint8_t > storage) const
Store the binary representation of this value into the given storage.
Definition: Scalar.cpp:114
bool GetData(DataExtractor &data, size_t limit_byte_size=UINT32_MAX) const
Definition: Scalar.cpp:85
signed char SChar(signed char fail_value=0) const
Definition: Scalar.cpp:303
bool FloatPromote(const llvm::fltSemantics &semantics)
Definition: Scalar.cpp:194
bool ClearBit(uint32_t bit)
Definition: Scalar.cpp:911
static PromotionKey GetFloatPromoKey(const llvm::fltSemantics &semantics)
Definition: Scalar.cpp:43
float Float(float fail_value=0.0f) const
Definition: Scalar.cpp:363
Scalar & operator&=(const Scalar &rhs)
Definition: Scalar.cpp:465
Scalar::Type m_type
Definition: Scalar.h:195
long long SLongLong(long long fail_value=0) const
Definition: Scalar.cpp:331
static const char * GetValueTypeAsCString(Scalar::Type value_type)
Definition: Scalar.cpp:218
bool ExtractBitfield(uint32_t bit_size, uint32_t bit_offset)
Definition: Scalar.cpp:799
std::tuple< Type, unsigned, bool > PromotionKey
Definition: Scalar.h:203
double Double(double fail_value=0.0) const
Definition: Scalar.cpp:383
Scalar & operator<<=(const Scalar &rhs)
Definition: Scalar.cpp:426
Status SetValueFromCString(const char *s, lldb::Encoding encoding, size_t byte_size)
Definition: Scalar.cpp:631
static Type PromoteToMaxType(Scalar &lhs, Scalar &rhs)
Definition: Scalar.cpp:56
llvm::APInt SInt128(const llvm::APInt &fail_value) const
Definition: Scalar.cpp:339
unsigned short UShort(unsigned short fail_value=0) const
Definition: Scalar.cpp:315
Scalar & operator+=(Scalar rhs)
Definition: Scalar.cpp:408
bool ShiftRightLogical(const Scalar &rhs)
Definition: Scalar.cpp:434
PromotionKey GetPromoKey() const
Definition: Scalar.cpp:31
long double LongDouble(long double fail_value=0.0) const
Definition: Scalar.cpp:403
Scalar & operator>>=(const Scalar &rhs)
Definition: Scalar.cpp:443
llvm::APInt UInt128(const llvm::APInt &fail_value) const
Definition: Scalar.cpp:351
An error handling class.
Definition: Status.h:44
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.
Definition: SBAttachInfo.h:14
const Scalar operator&(Scalar lhs, Scalar rhs)
Definition: Scalar.cpp:574
const Scalar operator*(Scalar lhs, Scalar rhs)
Definition: Scalar.cpp:557
bool operator<=(const Scalar &lhs, const Scalar &rhs)
Definition: Scalar.cpp:899
const Scalar operator/(Scalar lhs, Scalar rhs)
Definition: Scalar.cpp:536
bool operator!=(const Address &lhs, const Address &rhs)
Definition: Address.cpp:1029
bool operator>(const Address &lhs, const Address &rhs)
Definition: Address.cpp:1007
const Scalar operator>>(const Scalar &lhs, const Scalar &rhs)
Definition: Scalar.cpp:625
const Scalar operator%(Scalar lhs, Scalar rhs)
Definition: Scalar.cpp:596
Stream & operator<<(Stream &s, const Mangled &obj)
AdaptedConstIterator< C, E, A > operator+(typename AdaptedConstIterator< C, E, A >::BackingIterator::difference_type offset, AdaptedConstIterator< C, E, A > &rhs)
Definition: Iterable.h:132
const Scalar operator^(Scalar lhs, Scalar rhs)
Definition: Scalar.cpp:608
bool operator==(const Address &lhs, const Address &rhs)
Definition: Address.cpp:1023
const Scalar operator|(Scalar lhs, Scalar rhs)
Definition: Scalar.cpp:585
bool operator<(const Address &lhs, const Address &rhs)
Definition: Address.cpp:992
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:907
AdaptedConstIterator< C, E, A >::BackingIterator::difference_type operator-(AdaptedConstIterator< C, E, A > &lhs, AdaptedConstIterator< C, E, A > &rhs)
Definition: Iterable.h:141
Definition: SBAddress.h:15
BasicType
Basic types enumeration for the public API SBType::GetBasicType().
@ eBasicTypeDouble
@ eBasicTypeLongDouble
uint64_t offset_t
Definition: lldb-types.h:83
Encoding
Register encoding definitions.
@ eEncodingIEEE754
float
@ eEncodingVector
vector registers
@ eEncodingUint
unsigned integer
@ eEncodingInvalid
@ eEncodingSint
signed integer
ByteOrder
Byte ordering definitions.
@ eByteOrderLittle