949 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/Utility/Scalar.h"10#include "lldb/Utility/DataBufferHeap.h"11#include "lldb/Utility/DataExtractor.h"12#include "lldb/Utility/Endian.h"13#include "lldb/Utility/Status.h"14#include "lldb/Utility/Stream.h"15#include "lldb/Utility/StreamString.h"16#include "lldb/lldb-types.h"17#include "llvm/ADT/APSInt.h"18#include "llvm/ADT/SmallString.h"19#include "llvm/ADT/StringExtras.h"20 21#include <cinttypes>22#include <cstdio>23 24using namespace lldb;25using namespace lldb_private;26 27using llvm::APFloat;28using llvm::APInt;29using llvm::APSInt;30 31Scalar::PromotionKey Scalar::GetPromoKey() const {32 switch (m_type) {33 case e_void:34 return PromotionKey{e_void, 0, false};35 case e_int:36 return PromotionKey{e_int, m_integer.getBitWidth(), m_integer.isUnsigned()};37 case e_float:38 return GetFloatPromoKey(m_float.getSemantics());39 }40 llvm_unreachable("Unhandled category!");41}42 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 in55// expressions.56Scalar::Type Scalar::PromoteToMaxType(Scalar &lhs, Scalar &rhs) {57 const auto &Promote = [](Scalar &a, const Scalar &b) {58 switch (b.GetType()) {59 case e_void:60 break;61 case e_int:62 a.IntegralPromote(b.m_integer.getBitWidth(), b.m_integer.isSigned());63 break;64 case e_float:65 a.FloatPromote(b.m_float.getSemantics());66 }67 };68 69 PromotionKey lhs_key = lhs.GetPromoKey();70 PromotionKey rhs_key = rhs.GetPromoKey();71 72 if (lhs_key > rhs_key)73 Promote(rhs, lhs);74 else if (rhs_key > lhs_key)75 Promote(lhs, rhs);76 77 // Make sure our type promotion worked as expected78 if (lhs.GetPromoKey() == rhs.GetPromoKey())79 return lhs.GetType(); // Return the resulting type80 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);94 data.SetByteOrder(endian::InlHostByteOrder());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 105 if (endian::InlHostByteOrder() == lldb::eByteOrderBig) {106 // On big endian systems if we want fewer bytes from the current type107 // we have to advance our initial byte pointer since the MSByte is108 // 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);114 data.SetByteOrder(endian::InlHostByteOrder());115 } else {116 // Extend created buffer size and insert the data bytes with an offset117 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);121 data.SetByteOrder(endian::InlHostByteOrder());122 }123 return true;124 }125 126 // On little endian systems MSBytes get trimmed or extended automatically by127 // 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);133 data.SetByteOrder(endian::InlHostByteOrder());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 248const char *Scalar::GetValueTypeAsCString(Scalar::Type type) {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 272bool Scalar::MakeSigned() {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 290bool Scalar::MakeUnsigned() {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 438Scalar &Scalar::operator+=(Scalar rhs) {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 456Scalar &Scalar::operator<<=(const Scalar &rhs) {457 if (m_type == e_int && rhs.m_type == e_int)458 static_cast<APInt &>(m_integer) <<= rhs.m_integer;459 else460 m_type = e_void;461 return *this;462}463 464bool Scalar::ShiftRightLogical(const Scalar &rhs) {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 473Scalar &Scalar::operator>>=(const Scalar &rhs) {474 if (m_type == e_int && rhs.m_type == e_int)475 m_integer >>= rhs.m_integer.getZExtValue();476 else477 m_type = e_void;478 return *this;479}480 481Scalar &Scalar::operator&=(const Scalar &rhs) {482 if (m_type == e_int && rhs.m_type == e_int)483 m_integer &= rhs.m_integer;484 else485 m_type = e_void;486 return *this;487}488 489bool Scalar::AbsoluteValue() {490 switch (m_type) {491 case e_void:492 break;493 494 case e_int:495 if (m_integer.isNegative())496 m_integer = -m_integer;497 return true;498 499 case e_float:500 m_float.clearSign();501 return true;502 }503 return false;504}505 506bool Scalar::UnaryNegate() {507 switch (m_type) {508 case e_void:509 break;510 case e_int:511 m_integer = -m_integer;512 return true;513 case e_float:514 m_float.changeSign();515 return true;516 }517 return false;518}519 520bool Scalar::OnesComplement() {521 if (m_type == e_int) {522 m_integer = ~m_integer;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 535const Scalar lldb_private::operator-(Scalar lhs, Scalar rhs) {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 552const Scalar lldb_private::operator/(Scalar lhs, Scalar rhs) {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 promotion569 // failed, or if we are trying to do a divide by zero.570 result.m_type = Scalar::e_void;571 return result;572}573 574const Scalar lldb_private::operator*(Scalar lhs, Scalar rhs) {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 591const Scalar lldb_private::operator&(Scalar lhs, Scalar rhs) {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 else597 result.m_type = Scalar::e_void;598 }599 return result;600}601 602const Scalar lldb_private::operator|(Scalar lhs, Scalar rhs) {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 else608 result.m_type = Scalar::e_void;609 }610 return result;611}612 613const Scalar lldb_private::operator%(Scalar lhs, Scalar rhs) {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 625const Scalar lldb_private::operator^(Scalar lhs, Scalar rhs) {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 else631 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) {650 Status error;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)) {666 error = Status::FromErrorStringWithFormatv(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 } else677 fits = integer.isIntN(byte_size * 8);678 if (!fits) {679 error = Status::FromErrorStringWithFormatv(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 floating692 // point type. This function should be refactored to take an explicit693 // 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 } else704 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 718Status Scalar::SetValueFromData(const DataExtractor &data,719 lldb::Encoding encoding, size_t byte_size) {720 Status error;721 switch (encoding) {722 case lldb::eEncodingInvalid:723 return Status::FromErrorString("invalid encoding");724 break;725 case lldb::eEncodingVector:726 return Status::FromErrorString("vector encoding unsupported");727 break;728 case lldb::eEncodingUint: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 }744 case lldb::eEncodingIEEE754: {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 else754 return Status::FromErrorStringWithFormatv(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 data792 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 value801 const size_t bytes_copied =802 data.CopyByteOrderedData(0, // src offset803 src_len, // src length804 dst, // dst buffer805 dst_len, // dst length806 dst_byte_order); // dst byte order807 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 830llvm::APFloat Scalar::CreateAPFloatFromAPSInt(lldb::BasicType basic_type) {831 switch (basic_type) {832 case lldb::eBasicTypeFloat:833 return llvm::APFloat(834 m_integer.isSigned()835 ? llvm::APIntOps::RoundSignedAPIntToFloat(m_integer)836 : llvm::APIntOps::RoundAPIntToFloat(m_integer));837 case lldb::eBasicTypeDouble:838 // No way to get more precision at the moment.839 case lldb::eBasicTypeLongDouble: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 850llvm::APFloat Scalar::CreateAPFloatFromAPFloat(lldb::BasicType basic_type) {851 switch (basic_type) {852 case lldb::eBasicTypeFloat: {853 bool loses_info;854 m_float.convert(llvm::APFloat::IEEEsingle(),855 llvm::APFloat::rmNearestTiesToEven, &loses_info);856 return m_float;857 }858 case lldb::eBasicTypeDouble:859 // No way to get more precision at the moment.860 case lldb::eBasicTypeLongDouble: {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 types874 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}949