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