1 //===-- Scalar.cpp --------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "lldb/Utility/Scalar.h"
10 #include "lldb/Utility/DataBufferHeap.h"
11 #include "lldb/Utility/DataExtractor.h"
12 #include "lldb/Utility/Endian.h"
13 #include "lldb/Utility/Status.h"
14 #include "lldb/Utility/Stream.h"
15 #include "lldb/Utility/StreamString.h"
16 #include "lldb/lldb-types.h"
17 #include "llvm/ADT/APSInt.h"
18 #include "llvm/ADT/SmallString.h"
19 #include "llvm/ADT/StringExtras.h"
25 using namespace lldb_private
;
31 Scalar::PromotionKey
Scalar::GetPromoKey() const {
34 return PromotionKey
{e_void
, 0, false};
36 return PromotionKey
{e_int
, m_integer
.getBitWidth(), m_integer
.isUnsigned()};
38 return GetFloatPromoKey(m_float
.getSemantics());
40 llvm_unreachable("Unhandled category!");
43 Scalar::PromotionKey
Scalar::GetFloatPromoKey(const llvm::fltSemantics
&sem
) {
44 static const llvm::fltSemantics
*const order
[] = {
45 &APFloat::IEEEsingle(), &APFloat::IEEEdouble(),
46 &APFloat::x87DoubleExtended()};
47 for (const auto &entry
: llvm::enumerate(order
)) {
48 if (entry
.value() == &sem
)
49 return PromotionKey
{e_float
, entry
.index(), false};
51 llvm_unreachable("Unsupported semantics!");
54 // Promote to max type currently follows the ANSI C rule for type promotion in
56 Scalar::Type
Scalar::PromoteToMaxType(Scalar
&lhs
, Scalar
&rhs
) {
57 const auto &Promote
= [](Scalar
&a
, const Scalar
&b
) {
58 switch (b
.GetType()) {
62 a
.IntegralPromote(b
.m_integer
.getBitWidth(), b
.m_integer
.isSigned());
65 a
.FloatPromote(b
.m_float
.getSemantics());
69 PromotionKey lhs_key
= lhs
.GetPromoKey();
70 PromotionKey rhs_key
= rhs
.GetPromoKey();
72 if (lhs_key
> rhs_key
)
74 else if (rhs_key
> lhs_key
)
77 // Make sure our type promotion worked as expected
78 if (lhs
.GetPromoKey() == rhs
.GetPromoKey())
79 return lhs
.GetType(); // Return the resulting type
81 // Return the void type (zero) if we fail to promote either of the values.
82 return Scalar::e_void
;
85 bool Scalar::GetData(DataExtractor
&data
, size_t limit_byte_size
) const {
86 size_t byte_size
= GetByteSize();
91 auto buffer_up
= std::make_unique
<DataBufferHeap
>(byte_size
, 0);
92 GetBytes(buffer_up
->GetData());
93 lldb::offset_t offset
= 0;
95 if (limit_byte_size
< byte_size
) {
96 if (endian::InlHostByteOrder() == eByteOrderLittle
) {
97 // On little endian systems if we want fewer bytes from the current
98 // type we just specify fewer bytes since the LSByte is first...
99 byte_size
= limit_byte_size
;
100 } else if (endian::InlHostByteOrder() == eByteOrderBig
) {
101 // On big endian systems if we want fewer bytes from the current type
102 // have to advance our initial byte pointer and trim down the number of
103 // bytes since the MSByte is first
104 offset
= byte_size
- limit_byte_size
;
105 byte_size
= limit_byte_size
;
109 data
.SetData(std::move(buffer_up
), offset
, byte_size
);
110 data
.SetByteOrder(endian::InlHostByteOrder());
114 void Scalar::GetBytes(llvm::MutableArrayRef
<uint8_t> storage
) const {
115 assert(storage
.size() >= GetByteSize());
117 const auto &store
= [&](const llvm::APInt
&val
) {
118 StoreIntToMemory(val
, storage
.data(), (val
.getBitWidth() + 7) / 8);
127 store(m_float
.bitcastToAPInt());
132 size_t Scalar::GetByteSize() const {
137 return (m_integer
.getBitWidth() + 7) / 8;
139 return (m_float
.bitcastToAPInt().getBitWidth() + 7) / 8;
144 bool Scalar::IsZero() const {
149 return m_integer
.isZero();
151 return m_float
.isZero();
156 void Scalar::GetValue(Stream
&s
, bool show_type
) const {
158 s
.Printf("(%s) ", GetTypeAsCString());
164 s
.PutCString(llvm::toString(m_integer
, 10));
167 llvm::SmallString
<24> string
;
168 m_float
.toString(string
);
169 s
.PutCString(string
);
174 void Scalar::TruncOrExtendTo(uint16_t bits
, bool sign
) {
175 m_integer
.setIsSigned(sign
);
176 m_integer
= m_integer
.extOrTrunc(bits
);
179 bool Scalar::IntegralPromote(uint16_t bits
, bool sign
) {
185 if (GetPromoKey() > PromotionKey(e_int
, bits
, !sign
))
187 m_integer
= m_integer
.extOrTrunc(bits
);
188 m_integer
.setIsSigned(sign
);
194 bool Scalar::FloatPromote(const llvm::fltSemantics
&semantics
) {
195 bool success
= false;
200 m_float
= llvm::APFloat(semantics
);
201 m_float
.convertFromAPInt(m_integer
, m_integer
.isSigned(),
202 llvm::APFloat::rmNearestTiesToEven
);
206 if (GetFloatPromoKey(semantics
) < GetFloatPromoKey(m_float
.getSemantics()))
210 m_float
.convert(semantics
, llvm::APFloat::rmNearestTiesToEven
, &ignore
);
218 const char *Scalar::GetValueTypeAsCString(Scalar::Type type
) {
230 bool Scalar::IsSigned() const {
235 return m_integer
.isSigned();
239 llvm_unreachable("Unrecognized type!");
242 bool Scalar::MakeSigned() {
243 bool success
= false;
249 m_integer
.setIsSigned(true);
260 bool Scalar::MakeUnsigned() {
261 bool success
= false;
267 m_integer
.setIsUnsigned(true);
278 static llvm::APInt
ToAPInt(const llvm::APFloat
&f
, unsigned bits
,
280 llvm::APSInt
result(bits
, is_unsigned
);
282 f
.convertToInteger(result
, llvm::APFloat::rmTowardZero
, &isExact
);
283 return std::move(result
);
286 template <typename T
> T
Scalar::GetAs(T fail_value
) const {
291 APSInt ext
= m_integer
.extOrTrunc(sizeof(T
) * 8);
293 return ext
.getSExtValue();
294 return ext
.getZExtValue();
297 return ToAPInt(m_float
, sizeof(T
) * 8, std::is_unsigned
<T
>::value
)
303 signed char Scalar::SChar(signed char fail_value
) const {
304 return GetAs
<signed char>(fail_value
);
307 unsigned char Scalar::UChar(unsigned char fail_value
) const {
308 return GetAs
<unsigned char>(fail_value
);
311 short Scalar::SShort(short fail_value
) const {
312 return GetAs
<short>(fail_value
);
315 unsigned short Scalar::UShort(unsigned short fail_value
) const {
316 return GetAs
<unsigned short>(fail_value
);
319 int Scalar::SInt(int fail_value
) const { return GetAs
<int>(fail_value
); }
321 unsigned int Scalar::UInt(unsigned int fail_value
) const {
322 return GetAs
<unsigned int>(fail_value
);
325 long Scalar::SLong(long fail_value
) const { return GetAs
<long>(fail_value
); }
327 unsigned long Scalar::ULong(unsigned long fail_value
) const {
328 return GetAs
<unsigned long>(fail_value
);
331 long long Scalar::SLongLong(long long fail_value
) const {
332 return GetAs
<long long>(fail_value
);
335 unsigned long long Scalar::ULongLong(unsigned long long fail_value
) const {
336 return GetAs
<unsigned long long>(fail_value
);
339 llvm::APInt
Scalar::SInt128(const llvm::APInt
&fail_value
) const {
346 return ToAPInt(m_float
, 128, /*is_unsigned=*/false);
351 llvm::APInt
Scalar::UInt128(const llvm::APInt
&fail_value
) const {
358 return ToAPInt(m_float
, 128, /*is_unsigned=*/true);
363 float Scalar::Float(float fail_value
) const {
368 if (m_integer
.isSigned())
369 return llvm::APIntOps::RoundSignedAPIntToFloat(m_integer
);
370 return llvm::APIntOps::RoundAPIntToFloat(m_integer
);
373 APFloat result
= m_float
;
375 result
.convert(APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven
,
377 return result
.convertToFloat();
383 double Scalar::Double(double fail_value
) const {
388 if (m_integer
.isSigned())
389 return llvm::APIntOps::RoundSignedAPIntToDouble(m_integer
);
390 return llvm::APIntOps::RoundAPIntToDouble(m_integer
);
393 APFloat result
= m_float
;
395 result
.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven
,
397 return result
.convertToDouble();
403 long double Scalar::LongDouble(long double fail_value
) const {
404 /// No way to get more precision at the moment.
405 return static_cast<long double>(Double(fail_value
));
408 Scalar
&Scalar::operator+=(Scalar rhs
) {
410 if ((m_type
= PromoteToMaxType(copy
, rhs
)) != Scalar::e_void
) {
415 m_integer
= copy
.m_integer
+ rhs
.m_integer
;
419 m_float
= copy
.m_float
+ rhs
.m_float
;
426 Scalar
&Scalar::operator<<=(const Scalar
&rhs
) {
427 if (m_type
== e_int
&& rhs
.m_type
== e_int
)
428 static_cast<APInt
&>(m_integer
) <<= rhs
.m_integer
;
434 bool Scalar::ShiftRightLogical(const Scalar
&rhs
) {
435 if (m_type
== e_int
&& rhs
.m_type
== e_int
) {
436 m_integer
= m_integer
.lshr(rhs
.m_integer
);
443 Scalar
&Scalar::operator>>=(const Scalar
&rhs
) {
451 switch (rhs
.m_type
) {
457 m_integer
= m_integer
.ashr(rhs
.m_integer
);
465 Scalar
&Scalar::operator&=(const Scalar
&rhs
) {
466 if (m_type
== e_int
&& rhs
.m_type
== e_int
)
467 m_integer
&= rhs
.m_integer
;
473 bool Scalar::AbsoluteValue() {
479 if (m_integer
.isNegative())
480 m_integer
= -m_integer
;
490 bool Scalar::UnaryNegate() {
495 m_integer
= -m_integer
;
498 m_float
.changeSign();
504 bool Scalar::OnesComplement() {
505 if (m_type
== e_int
) {
506 m_integer
= ~m_integer
;
513 const Scalar
lldb_private::operator+(const Scalar
&lhs
, const Scalar
&rhs
) {
519 const Scalar
lldb_private::operator-(Scalar lhs
, Scalar rhs
) {
521 if ((result
.m_type
= Scalar::PromoteToMaxType(lhs
, rhs
)) != Scalar::e_void
) {
522 switch (result
.m_type
) {
526 result
.m_integer
= lhs
.m_integer
- rhs
.m_integer
;
528 case Scalar::e_float
:
529 result
.m_float
= lhs
.m_float
- rhs
.m_float
;
536 const Scalar
lldb_private::operator/(Scalar lhs
, Scalar rhs
) {
538 if ((result
.m_type
= Scalar::PromoteToMaxType(lhs
, rhs
)) != Scalar::e_void
&&
540 switch (result
.m_type
) {
544 result
.m_integer
= lhs
.m_integer
/ rhs
.m_integer
;
546 case Scalar::e_float
:
547 result
.m_float
= lhs
.m_float
/ rhs
.m_float
;
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
;
557 const Scalar
lldb_private::operator*(Scalar lhs
, Scalar rhs
) {
559 if ((result
.m_type
= Scalar::PromoteToMaxType(lhs
, rhs
)) != Scalar::e_void
) {
560 switch (result
.m_type
) {
564 result
.m_integer
= lhs
.m_integer
* rhs
.m_integer
;
566 case Scalar::e_float
:
567 result
.m_float
= lhs
.m_float
* rhs
.m_float
;
574 const Scalar
lldb_private::operator&(Scalar lhs
, Scalar rhs
) {
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
;
580 result
.m_type
= Scalar::e_void
;
585 const Scalar
lldb_private::operator|(Scalar lhs
, Scalar rhs
) {
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
;
591 result
.m_type
= Scalar::e_void
;
596 const Scalar
lldb_private::operator%(Scalar lhs
, Scalar rhs
) {
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
;
604 result
.m_type
= Scalar::e_void
;
608 const Scalar
lldb_private::operator^(Scalar lhs
, Scalar rhs
) {
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
;
614 result
.m_type
= Scalar::e_void
;
619 const Scalar
lldb_private::operator<<(const Scalar
&lhs
, const Scalar
&rhs
) {
625 const Scalar
lldb_private::operator>>(const Scalar
&lhs
, const Scalar
&rhs
) {
631 Status
Scalar::SetValueFromCString(const char *value_str
, Encoding encoding
,
634 if (value_str
== nullptr || value_str
[0] == '\0') {
635 return Status::FromErrorString("Invalid c-string value string.");
638 case eEncodingInvalid
:
639 return Status::FromErrorString("Invalid encoding.");
643 case eEncodingUint
: {
644 llvm::StringRef str
= value_str
;
645 bool is_signed
= encoding
== eEncodingSint
;
646 bool is_negative
= is_signed
&& str
.consume_front("-");
648 if (str
.getAsInteger(0, integer
)) {
649 error
= Status::FromErrorStringWithFormatv(
650 "'{0}' is not a valid integer string value", value_str
);
655 integer
= integer
.zext(integer
.getBitWidth() + 1);
658 fits
= integer
.isSignedIntN(byte_size
* 8);
660 fits
= integer
.isIntN(byte_size
* 8);
662 error
= Status::FromErrorStringWithFormatv(
663 "value {0} is too large to fit in a {1} byte integer value",
664 value_str
, byte_size
);
669 APSInt(std::move(integer
), !is_signed
).extOrTrunc(8 * byte_size
);
673 case eEncodingIEEE754
: {
674 // FIXME: It's not possible to unambiguously map a byte size to a floating
675 // point type. This function should be refactored to take an explicit
676 // semantics argument.
677 const llvm::fltSemantics
&sem
=
678 byte_size
<= 4 ? APFloat::IEEEsingle()
679 : byte_size
<= 8 ? APFloat::IEEEdouble()
680 : APFloat::x87DoubleExtended();
682 if (llvm::Expected
<APFloat::opStatus
> op
=
683 f
.convertFromString(value_str
, APFloat::rmNearestTiesToEven
)) {
685 m_float
= std::move(f
);
687 error
= Status::FromError(op
.takeError());
691 case eEncodingVector
:
692 return Status::FromErrorString("vector encoding unsupported.");
701 Status
Scalar::SetValueFromData(const DataExtractor
&data
,
702 lldb::Encoding encoding
, size_t byte_size
) {
705 case lldb::eEncodingInvalid
:
706 return Status::FromErrorString("invalid encoding");
708 case lldb::eEncodingVector
:
709 return Status::FromErrorString("vector encoding unsupported");
711 case lldb::eEncodingUint
:
712 case lldb::eEncodingSint
: {
713 if (data
.GetByteSize() < byte_size
)
714 return Status::FromErrorString("insufficient data");
717 APSInt(APInt::getZero(8 * byte_size
), encoding
== eEncodingUint
);
718 if (data
.GetByteOrder() == endian::InlHostByteOrder()) {
719 llvm::LoadIntFromMemory(m_integer
, data
.GetDataStart(), byte_size
);
721 std::vector
<uint8_t> buffer(byte_size
);
722 std::copy_n(data
.GetDataStart(), byte_size
, buffer
.rbegin());
723 llvm::LoadIntFromMemory(m_integer
, buffer
.data(), byte_size
);
727 case lldb::eEncodingIEEE754
: {
728 lldb::offset_t offset
= 0;
730 if (byte_size
== sizeof(float))
731 operator=(data
.GetFloat(&offset
));
732 else if (byte_size
== sizeof(double))
733 operator=(data
.GetDouble(&offset
));
734 else if (byte_size
== sizeof(long double))
735 operator=(data
.GetLongDouble(&offset
));
737 return Status::FromErrorStringWithFormatv(
738 "unsupported float byte size: {0}", static_cast<uint64_t>(byte_size
));
745 bool Scalar::SignExtend(uint32_t sign_bit_pos
) {
746 const uint32_t max_bit_pos
= GetByteSize() * 8;
748 if (sign_bit_pos
< max_bit_pos
) {
751 case Scalar::e_float
:
755 if (sign_bit_pos
< (max_bit_pos
- 1)) {
756 llvm::APInt sign_bit
= llvm::APInt::getSignMask(sign_bit_pos
+ 1);
757 llvm::APInt bitwize_and
= m_integer
& sign_bit
;
758 if (bitwize_and
.getBoolValue()) {
760 ~(sign_bit
) + llvm::APInt(m_integer
.getBitWidth(), 1);
761 m_integer
|= APSInt(std::move(mask
), m_integer
.isUnsigned());
771 size_t Scalar::GetAsMemoryData(void *dst
, size_t dst_len
,
772 lldb::ByteOrder dst_byte_order
,
773 Status
&error
) const {
774 // Get a data extractor that points to the native scalar data
776 if (!GetData(data
)) {
777 error
= Status::FromErrorString("invalid scalar value");
781 const size_t src_len
= data
.GetByteSize();
783 // Prepare a memory buffer that contains some or all of the register value
784 const size_t bytes_copied
=
785 data
.CopyByteOrderedData(0, // src offset
786 src_len
, // src length
788 dst_len
, // dst length
789 dst_byte_order
); // dst byte order
790 if (bytes_copied
== 0)
791 error
= Status::FromErrorString("failed to copy data");
796 bool Scalar::ExtractBitfield(uint32_t bit_size
, uint32_t bit_offset
) {
802 case Scalar::e_float
:
806 m_integer
>>= bit_offset
;
807 m_integer
= m_integer
.extOrTrunc(bit_size
).extOrTrunc(8 * GetByteSize());
813 llvm::APFloat
Scalar::CreateAPFloatFromAPSInt(lldb::BasicType basic_type
) {
814 switch (basic_type
) {
815 case lldb::eBasicTypeFloat
:
816 return llvm::APFloat(
818 ? llvm::APIntOps::RoundSignedAPIntToFloat(m_integer
)
819 : llvm::APIntOps::RoundAPIntToFloat(m_integer
));
820 case lldb::eBasicTypeDouble
:
821 // No way to get more precision at the moment.
822 case lldb::eBasicTypeLongDouble
:
823 return llvm::APFloat(
825 ? llvm::APIntOps::RoundSignedAPIntToDouble(m_integer
)
826 : llvm::APIntOps::RoundAPIntToDouble(m_integer
));
828 const llvm::fltSemantics
&sem
= APFloat::IEEEsingle();
829 return llvm::APFloat::getNaN(sem
);
833 llvm::APFloat
Scalar::CreateAPFloatFromAPFloat(lldb::BasicType basic_type
) {
834 switch (basic_type
) {
835 case lldb::eBasicTypeFloat
: {
837 m_float
.convert(llvm::APFloat::IEEEsingle(),
838 llvm::APFloat::rmNearestTiesToEven
, &loses_info
);
841 case lldb::eBasicTypeDouble
:
842 // No way to get more precision at the moment.
843 case lldb::eBasicTypeLongDouble
: {
845 m_float
.convert(llvm::APFloat::IEEEdouble(),
846 llvm::APFloat::rmNearestTiesToEven
, &loses_info
);
850 const llvm::fltSemantics
&sem
= APFloat::IEEEsingle();
851 return llvm::APFloat::getNaN(sem
);
855 APFloat::cmpResult
lldb_private::compare(Scalar lhs
, Scalar rhs
) {
856 // If either entry is void then we can just compare the types
857 if (lhs
.m_type
== Scalar::e_void
|| rhs
.m_type
== Scalar::e_void
)
858 return lhs
.m_type
== rhs
.m_type
? APFloat::cmpEqual
: APFloat::cmpUnordered
;
860 switch (Scalar::PromoteToMaxType(lhs
, rhs
)) {
864 if (lhs
.m_integer
< rhs
.m_integer
)
865 return APFloat::cmpLessThan
;
866 if (lhs
.m_integer
> rhs
.m_integer
)
867 return APFloat::cmpGreaterThan
;
868 return APFloat::cmpEqual
;
869 case Scalar::e_float
:
870 return lhs
.m_float
.compare(rhs
.m_float
);
872 return APFloat::cmpUnordered
;
875 bool lldb_private::operator==(const Scalar
&lhs
, const Scalar
&rhs
) {
876 return compare(lhs
, rhs
) == APFloat::cmpEqual
;
879 bool lldb_private::operator!=(const Scalar
&lhs
, const Scalar
&rhs
) {
880 return compare(lhs
, rhs
) != APFloat::cmpEqual
;
883 bool lldb_private::operator<(const Scalar
&lhs
, const Scalar
&rhs
) {
884 return compare(lhs
, rhs
) == APFloat::cmpLessThan
;
887 bool lldb_private::operator<=(const Scalar
&lhs
, const Scalar
&rhs
) {
888 APFloat::cmpResult Res
= compare(lhs
, rhs
);
889 return Res
== APFloat::cmpLessThan
|| Res
== APFloat::cmpEqual
;
892 bool lldb_private::operator>(const Scalar
&lhs
, const Scalar
&rhs
) {
893 return compare(lhs
, rhs
) == APFloat::cmpGreaterThan
;
896 bool lldb_private::operator>=(const Scalar
&lhs
, const Scalar
&rhs
) {
897 APFloat::cmpResult Res
= compare(lhs
, rhs
);
898 return Res
== APFloat::cmpGreaterThan
|| Res
== APFloat::cmpEqual
;
901 bool Scalar::ClearBit(uint32_t bit
) {
906 m_integer
.clearBit(bit
);
914 bool Scalar::SetBit(uint32_t bit
) {
919 m_integer
.setBit(bit
);
927 llvm::raw_ostream
&lldb_private::operator<<(llvm::raw_ostream
&os
, const Scalar
&scalar
) {
929 scalar
.GetValue(s
, /*show_type*/ true);
930 return os
<< s
.GetString();