180814287SRaphael Isemann //===-- Scalar.cpp --------------------------------------------------------===//
2d821c997SPavel Labath //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6d821c997SPavel Labath //
7d821c997SPavel Labath //===----------------------------------------------------------------------===//
8d821c997SPavel Labath 
9d821c997SPavel Labath #include "lldb/Utility/Scalar.h"
10d0fa52ccSPavel Labath #include "lldb/Utility/DataBufferHeap.h"
11d821c997SPavel Labath #include "lldb/Utility/DataExtractor.h"
12d821c997SPavel Labath #include "lldb/Utility/Endian.h"
13d821c997SPavel Labath #include "lldb/Utility/Status.h"
14d821c997SPavel Labath #include "lldb/Utility/Stream.h"
15b07a7997SPavel Labath #include "lldb/Utility/StreamString.h"
16672d2c12SJonas Devlieghere #include "lldb/lldb-types.h"
178270a903SPavel Labath #include "llvm/ADT/APSInt.h"
18d821c997SPavel Labath #include "llvm/ADT/SmallString.h"
19d821c997SPavel Labath 
20d821c997SPavel Labath #include <cinttypes>
21d821c997SPavel Labath #include <cstdio>
22d821c997SPavel Labath 
23d821c997SPavel Labath using namespace lldb;
24d821c997SPavel Labath using namespace lldb_private;
25d821c997SPavel Labath 
2688c82474SPavel Labath using llvm::APFloat;
271847f4ddSPavel Labath using llvm::APInt;
28219ccdfdSPavel Labath using llvm::APSInt;
2988c82474SPavel Labath 
GetPromoKey() const308a8a2dd3SPavel Labath Scalar::PromotionKey Scalar::GetPromoKey() const {
319b50546bSPavel Labath   switch (m_type) {
329b50546bSPavel Labath   case e_void:
339b50546bSPavel Labath     return PromotionKey{e_void, 0, false};
349b50546bSPavel Labath   case e_int:
359b50546bSPavel Labath     return PromotionKey{e_int, m_integer.getBitWidth(), m_integer.isUnsigned()};
369b50546bSPavel Labath   case e_float:
378a8a2dd3SPavel Labath     return GetFloatPromoKey(m_float.getSemantics());
388a8a2dd3SPavel Labath   }
398a8a2dd3SPavel Labath   llvm_unreachable("Unhandled category!");
408a8a2dd3SPavel Labath }
418a8a2dd3SPavel Labath 
GetFloatPromoKey(const llvm::fltSemantics & sem)428a8a2dd3SPavel Labath Scalar::PromotionKey Scalar::GetFloatPromoKey(const llvm::fltSemantics &sem) {
438a8a2dd3SPavel Labath   static const llvm::fltSemantics *const order[] = {
448a8a2dd3SPavel Labath       &APFloat::IEEEsingle(), &APFloat::IEEEdouble(),
458a8a2dd3SPavel Labath       &APFloat::x87DoubleExtended()};
468a8a2dd3SPavel Labath   for (const auto &entry : llvm::enumerate(order)) {
478a8a2dd3SPavel Labath     if (entry.value() == &sem)
489b50546bSPavel Labath       return PromotionKey{e_float, entry.index(), false};
498a8a2dd3SPavel Labath   }
508a8a2dd3SPavel Labath   llvm_unreachable("Unsupported semantics!");
5167cdb899SPavel Labath }
52228ea815SPavel Labath 
53d821c997SPavel Labath // Promote to max type currently follows the ANSI C rule for type promotion in
54d821c997SPavel Labath // expressions.
PromoteToMaxType(Scalar & lhs,Scalar & rhs)5567cdb899SPavel Labath Scalar::Type Scalar::PromoteToMaxType(Scalar &lhs, Scalar &rhs) {
5667cdb899SPavel Labath   const auto &Promote = [](Scalar &a, const Scalar &b) {
579b50546bSPavel Labath     switch (b.GetType()) {
589b50546bSPavel Labath     case e_void:
598a8a2dd3SPavel Labath       break;
609b50546bSPavel Labath     case e_int:
61219ccdfdSPavel Labath       a.IntegralPromote(b.m_integer.getBitWidth(), b.m_integer.isSigned());
628a8a2dd3SPavel Labath       break;
639b50546bSPavel Labath     case e_float:
648a8a2dd3SPavel Labath       a.FloatPromote(b.m_float.getSemantics());
658a8a2dd3SPavel Labath     }
6667cdb899SPavel Labath   };
6767cdb899SPavel Labath 
688a8a2dd3SPavel Labath   PromotionKey lhs_key = lhs.GetPromoKey();
698a8a2dd3SPavel Labath   PromotionKey rhs_key = rhs.GetPromoKey();
70d821c997SPavel Labath 
7167cdb899SPavel Labath   if (lhs_key > rhs_key)
7267cdb899SPavel Labath     Promote(rhs, lhs);
7367cdb899SPavel Labath   else if (rhs_key > lhs_key)
7467cdb899SPavel Labath     Promote(lhs, rhs);
75d821c997SPavel Labath 
76d821c997SPavel Labath   // Make sure our type promotion worked as expected
778a8a2dd3SPavel Labath   if (lhs.GetPromoKey() == rhs.GetPromoKey())
788a8a2dd3SPavel Labath     return lhs.GetType(); // Return the resulting type
79d821c997SPavel Labath 
80d821c997SPavel Labath   // Return the void type (zero) if we fail to promote either of the values.
81d821c997SPavel Labath   return Scalar::e_void;
82d821c997SPavel Labath }
83d821c997SPavel Labath 
GetData(DataExtractor & data,size_t limit_byte_size) const84d821c997SPavel Labath bool Scalar::GetData(DataExtractor &data, size_t limit_byte_size) const {
85d821c997SPavel Labath   size_t byte_size = GetByteSize();
86d0fa52ccSPavel Labath   if (byte_size == 0) {
87d0fa52ccSPavel Labath     data.Clear();
88d0fa52ccSPavel Labath     return false;
89d0fa52ccSPavel Labath   }
90d0fa52ccSPavel Labath   auto buffer_up = std::make_unique<DataBufferHeap>(byte_size, 0);
91d0fa52ccSPavel Labath   GetBytes(buffer_up->GetData());
92d0fa52ccSPavel Labath   lldb::offset_t offset = 0;
93d821c997SPavel Labath 
94d821c997SPavel Labath   if (limit_byte_size < byte_size) {
95d821c997SPavel Labath     if (endian::InlHostByteOrder() == eByteOrderLittle) {
96d821c997SPavel Labath       // On little endian systems if we want fewer bytes from the current
97d821c997SPavel Labath       // type we just specify fewer bytes since the LSByte is first...
98d821c997SPavel Labath       byte_size = limit_byte_size;
99d821c997SPavel Labath     } else if (endian::InlHostByteOrder() == eByteOrderBig) {
100d821c997SPavel Labath       // On big endian systems if we want fewer bytes from the current type
101d821c997SPavel Labath       // have to advance our initial byte pointer and trim down the number of
102d821c997SPavel Labath       // bytes since the MSByte is first
103d0fa52ccSPavel Labath       offset = byte_size - limit_byte_size;
104d821c997SPavel Labath       byte_size = limit_byte_size;
105d821c997SPavel Labath     }
106d821c997SPavel Labath   }
107d821c997SPavel Labath 
108d0fa52ccSPavel Labath   data.SetData(std::move(buffer_up), offset, byte_size);
109d0fa52ccSPavel Labath   data.SetByteOrder(endian::InlHostByteOrder());
110d821c997SPavel Labath   return true;
111d821c997SPavel Labath }
112d821c997SPavel Labath 
GetBytes(llvm::MutableArrayRef<uint8_t> storage) const113d0fa52ccSPavel Labath void Scalar::GetBytes(llvm::MutableArrayRef<uint8_t> storage) const {
114d0fa52ccSPavel Labath   assert(storage.size() >= GetByteSize());
115d0fa52ccSPavel Labath 
1160d5fc822SJonas Devlieghere   const auto &store = [&](const llvm::APInt &val) {
117228ea815SPavel Labath     StoreIntToMemory(val, storage.data(), (val.getBitWidth() + 7) / 8);
118228ea815SPavel Labath   };
1199b50546bSPavel Labath   switch (m_type) {
1209b50546bSPavel Labath   case e_void:
121d821c997SPavel Labath     break;
1229b50546bSPavel Labath   case e_int:
123228ea815SPavel Labath     store(m_integer);
124d0fa52ccSPavel Labath     break;
1259b50546bSPavel Labath   case e_float:
126228ea815SPavel Labath     store(m_float.bitcastToAPInt());
127d0fa52ccSPavel Labath     break;
12851d46bd4SDavide Italiano   }
129d821c997SPavel Labath }
130d821c997SPavel Labath 
GetByteSize() const131d821c997SPavel Labath size_t Scalar::GetByteSize() const {
132d821c997SPavel Labath   switch (m_type) {
133d821c997SPavel Labath   case e_void:
134d821c997SPavel Labath     break;
135219ccdfdSPavel Labath   case e_int:
136d821c997SPavel Labath     return (m_integer.getBitWidth() / 8);
137d821c997SPavel Labath   case e_float:
1388a8a2dd3SPavel Labath     return m_float.bitcastToAPInt().getBitWidth() / 8;
139d821c997SPavel Labath   }
140d821c997SPavel Labath   return 0;
141d821c997SPavel Labath }
142d821c997SPavel Labath 
IsZero() const143d821c997SPavel Labath bool Scalar::IsZero() const {
1449b50546bSPavel Labath   switch (m_type) {
1459b50546bSPavel Labath   case e_void:
146d821c997SPavel Labath     break;
1479b50546bSPavel Labath   case e_int:
148228ea815SPavel Labath     return m_integer.isNullValue();
1499b50546bSPavel Labath   case e_float:
150d821c997SPavel Labath     return m_float.isZero();
151d821c997SPavel Labath   }
152d821c997SPavel Labath   return false;
153d821c997SPavel Labath }
154d821c997SPavel Labath 
GetValue(Stream * s,bool show_type) const155d821c997SPavel Labath void Scalar::GetValue(Stream *s, bool show_type) const {
156d821c997SPavel Labath   if (show_type)
157d821c997SPavel Labath     s->Printf("(%s) ", GetTypeAsCString());
158d821c997SPavel Labath 
1599b50546bSPavel Labath   switch (m_type) {
1609b50546bSPavel Labath   case e_void:
161d821c997SPavel Labath     break;
1629b50546bSPavel Labath   case e_int:
163b1603cb6SRaphael Isemann     s->PutCString(llvm::toString(m_integer, 10));
164d821c997SPavel Labath     break;
1659b50546bSPavel Labath   case e_float:
166d821c997SPavel Labath     llvm::SmallString<24> string;
167d821c997SPavel Labath     m_float.toString(string);
168228ea815SPavel Labath     s->PutCString(string);
169d821c997SPavel Labath     break;
170d821c997SPavel Labath   }
171d821c997SPavel Labath }
172d821c997SPavel Labath 
TruncOrExtendTo(uint16_t bits,bool sign)17316e17ca1SPavel Labath void Scalar::TruncOrExtendTo(uint16_t bits, bool sign) {
174219ccdfdSPavel Labath   m_integer.setIsSigned(sign);
175219ccdfdSPavel Labath   m_integer = m_integer.extOrTrunc(bits);
1769b23df63SAdrian Prantl }
1779b23df63SAdrian Prantl 
IntegralPromote(uint16_t bits,bool sign)17867cdb899SPavel Labath bool Scalar::IntegralPromote(uint16_t bits, bool sign) {
1799b50546bSPavel Labath   switch (m_type) {
1809b50546bSPavel Labath   case e_void:
1819b50546bSPavel Labath   case e_float:
18267cdb899SPavel Labath     break;
1839b50546bSPavel Labath   case e_int:
1849b50546bSPavel Labath     if (GetPromoKey() > PromotionKey(e_int, bits, !sign))
18567cdb899SPavel Labath       break;
186219ccdfdSPavel Labath     m_integer = m_integer.extOrTrunc(bits);
187219ccdfdSPavel Labath     m_integer.setIsSigned(sign);
18867cdb899SPavel Labath     return true;
18967cdb899SPavel Labath   }
19067cdb899SPavel Labath   return false;
19167cdb899SPavel Labath }
19267cdb899SPavel Labath 
FloatPromote(const llvm::fltSemantics & semantics)1938a8a2dd3SPavel Labath bool Scalar::FloatPromote(const llvm::fltSemantics &semantics) {
194d821c997SPavel Labath   bool success = false;
1959b50546bSPavel Labath   switch (m_type) {
1969b50546bSPavel Labath   case e_void:
197d821c997SPavel Labath     break;
1989b50546bSPavel Labath   case e_int:
1998a8a2dd3SPavel Labath     m_float = llvm::APFloat(semantics);
200219ccdfdSPavel Labath     m_float.convertFromAPInt(m_integer, m_integer.isSigned(),
201d821c997SPavel Labath                              llvm::APFloat::rmNearestTiesToEven);
202d821c997SPavel Labath     success = true;
203d821c997SPavel Labath     break;
2049b50546bSPavel Labath   case e_float:
2058a8a2dd3SPavel Labath     if (GetFloatPromoKey(semantics) < GetFloatPromoKey(m_float.getSemantics()))
206d821c997SPavel Labath       break;
207d821c997SPavel Labath     bool ignore;
208d821c997SPavel Labath     success = true;
2098a8a2dd3SPavel Labath     m_float.convert(semantics, llvm::APFloat::rmNearestTiesToEven, &ignore);
210d821c997SPavel Labath   }
211d821c997SPavel Labath 
212d821c997SPavel Labath   if (success)
2138a8a2dd3SPavel Labath     m_type = e_float;
214d821c997SPavel Labath   return success;
215d821c997SPavel Labath }
216d821c997SPavel Labath 
GetValueTypeAsCString(Scalar::Type type)217d821c997SPavel Labath const char *Scalar::GetValueTypeAsCString(Scalar::Type type) {
218d821c997SPavel Labath   switch (type) {
219d821c997SPavel Labath   case e_void:
220d821c997SPavel Labath     return "void";
221219ccdfdSPavel Labath   case e_int:
222219ccdfdSPavel Labath     return "int";
223d821c997SPavel Labath   case e_float:
224d821c997SPavel Labath     return "float";
225d821c997SPavel Labath   }
226d821c997SPavel Labath   return "???";
227d821c997SPavel Labath }
228d821c997SPavel Labath 
IsSigned() const229219ccdfdSPavel Labath bool Scalar::IsSigned() const {
230219ccdfdSPavel Labath   switch (m_type) {
231219ccdfdSPavel Labath   case e_void:
232219ccdfdSPavel Labath     return false;
233219ccdfdSPavel Labath   case e_int:
234219ccdfdSPavel Labath     return m_integer.isSigned();
235219ccdfdSPavel Labath   case e_float:
236219ccdfdSPavel Labath     return true;
237219ccdfdSPavel Labath   }
238219ccdfdSPavel Labath   llvm_unreachable("Unrecognized type!");
239219ccdfdSPavel Labath }
240219ccdfdSPavel Labath 
MakeSigned()241d821c997SPavel Labath bool Scalar::MakeSigned() {
242d821c997SPavel Labath   bool success = false;
243d821c997SPavel Labath 
244d821c997SPavel Labath   switch (m_type) {
245d821c997SPavel Labath   case e_void:
246d821c997SPavel Labath     break;
247219ccdfdSPavel Labath   case e_int:
248219ccdfdSPavel Labath     m_integer.setIsSigned(true);
249d821c997SPavel Labath     success = true;
250d821c997SPavel Labath     break;
251d821c997SPavel Labath   case e_float:
252d821c997SPavel Labath     success = true;
253d821c997SPavel Labath     break;
254d821c997SPavel Labath   }
255d821c997SPavel Labath 
256d821c997SPavel Labath   return success;
257d821c997SPavel Labath }
258d821c997SPavel Labath 
MakeUnsigned()259d821c997SPavel Labath bool Scalar::MakeUnsigned() {
260d821c997SPavel Labath   bool success = false;
261d821c997SPavel Labath 
262d821c997SPavel Labath   switch (m_type) {
263d821c997SPavel Labath   case e_void:
264d821c997SPavel Labath     break;
265219ccdfdSPavel Labath   case e_int:
266219ccdfdSPavel Labath     m_integer.setIsUnsigned(true);
267d821c997SPavel Labath     success = true;
268d821c997SPavel Labath     break;
269d821c997SPavel Labath   case e_float:
270d821c997SPavel Labath     success = true;
271d821c997SPavel Labath     break;
272d821c997SPavel Labath   }
273d821c997SPavel Labath 
274d821c997SPavel Labath   return success;
275d821c997SPavel Labath }
276d821c997SPavel Labath 
ToAPInt(const llvm::APFloat & f,unsigned bits,bool is_unsigned)27752495b98SPavel Labath static llvm::APInt ToAPInt(const llvm::APFloat &f, unsigned bits,
27852495b98SPavel Labath                            bool is_unsigned) {
27952495b98SPavel Labath   llvm::APSInt result(bits, is_unsigned);
28052495b98SPavel Labath   bool isExact;
28152495b98SPavel Labath   f.convertToInteger(result, llvm::APFloat::rmTowardZero, &isExact);
28252495b98SPavel Labath   return std::move(result);
28352495b98SPavel Labath }
28452495b98SPavel Labath 
GetAs(T fail_value) const285b725142cSPavel Labath template <typename T> T Scalar::GetAs(T fail_value) const {
2869b50546bSPavel Labath   switch (m_type) {
2879b50546bSPavel Labath   case e_void:
288d821c997SPavel Labath     break;
2899b50546bSPavel Labath   case e_int: {
290219ccdfdSPavel Labath     APSInt ext = m_integer.extOrTrunc(sizeof(T) * 8);
291219ccdfdSPavel Labath     if (ext.isSigned())
292219ccdfdSPavel Labath       return ext.getSExtValue();
293219ccdfdSPavel Labath     return ext.getZExtValue();
294219ccdfdSPavel Labath   }
2959b50546bSPavel Labath   case e_float:
29652495b98SPavel Labath     return ToAPInt(m_float, sizeof(T) * 8, std::is_unsigned<T>::value)
29752495b98SPavel Labath         .getSExtValue();
298d821c997SPavel Labath   }
299d821c997SPavel Labath   return fail_value;
300d821c997SPavel Labath }
301d821c997SPavel Labath 
SChar(signed char fail_value) const30248ca1559SPavel Labath signed char Scalar::SChar(signed char fail_value) const {
303b725142cSPavel Labath   return GetAs<signed char>(fail_value);
30448ca1559SPavel Labath }
30548ca1559SPavel Labath 
UChar(unsigned char fail_value) const30648ca1559SPavel Labath unsigned char Scalar::UChar(unsigned char fail_value) const {
307b725142cSPavel Labath   return GetAs<unsigned char>(fail_value);
30848ca1559SPavel Labath }
30948ca1559SPavel Labath 
SShort(short fail_value) const310d821c997SPavel Labath short Scalar::SShort(short fail_value) const {
311b725142cSPavel Labath   return GetAs<short>(fail_value);
312d821c997SPavel Labath }
313d821c997SPavel Labath 
UShort(unsigned short fail_value) const314d821c997SPavel Labath unsigned short Scalar::UShort(unsigned short fail_value) const {
315b725142cSPavel Labath   return GetAs<unsigned short>(fail_value);
316d821c997SPavel Labath }
317d821c997SPavel Labath 
SInt(int fail_value) const318b725142cSPavel Labath int Scalar::SInt(int fail_value) const { return GetAs<int>(fail_value); }
319d821c997SPavel Labath 
UInt(unsigned int fail_value) const320d821c997SPavel Labath unsigned int Scalar::UInt(unsigned int fail_value) const {
321b725142cSPavel Labath   return GetAs<unsigned int>(fail_value);
322d821c997SPavel Labath }
323d821c997SPavel Labath 
SLong(long fail_value) const324b725142cSPavel Labath long Scalar::SLong(long fail_value) const { return GetAs<long>(fail_value); }
325d821c997SPavel Labath 
ULong(unsigned long fail_value) const326d821c997SPavel Labath unsigned long Scalar::ULong(unsigned long fail_value) const {
327b725142cSPavel Labath   return GetAs<unsigned long>(fail_value);
328d821c997SPavel Labath }
329d821c997SPavel Labath 
SLongLong(long long fail_value) const330d821c997SPavel Labath long long Scalar::SLongLong(long long fail_value) const {
331b725142cSPavel Labath   return GetAs<long long>(fail_value);
332d821c997SPavel Labath }
333d821c997SPavel Labath 
ULongLong(unsigned long long fail_value) const334d821c997SPavel Labath unsigned long long Scalar::ULongLong(unsigned long long fail_value) const {
335b725142cSPavel Labath   return GetAs<unsigned long long>(fail_value);
336d821c997SPavel Labath }
337d821c997SPavel Labath 
SInt128(const llvm::APInt & fail_value) const33848ca1559SPavel Labath llvm::APInt Scalar::SInt128(const llvm::APInt &fail_value) const {
3399b50546bSPavel Labath   switch (m_type) {
3409b50546bSPavel Labath   case e_void:
341d821c997SPavel Labath     break;
3429b50546bSPavel Labath   case e_int:
343d821c997SPavel Labath     return m_integer;
3449b50546bSPavel Labath   case e_float:
34552495b98SPavel Labath     return ToAPInt(m_float, 128, /*is_unsigned=*/false);
346d821c997SPavel Labath   }
347d821c997SPavel Labath   return fail_value;
348d821c997SPavel Labath }
349d821c997SPavel Labath 
UInt128(const llvm::APInt & fail_value) const350d821c997SPavel Labath llvm::APInt Scalar::UInt128(const llvm::APInt &fail_value) const {
3519b50546bSPavel Labath   switch (m_type) {
3529b50546bSPavel Labath   case e_void:
353d821c997SPavel Labath     break;
3549b50546bSPavel Labath   case e_int:
355d821c997SPavel Labath     return m_integer;
3569b50546bSPavel Labath   case e_float:
35752495b98SPavel Labath     return ToAPInt(m_float, 128, /*is_unsigned=*/true);
358d821c997SPavel Labath   }
359d821c997SPavel Labath   return fail_value;
360d821c997SPavel Labath }
361d821c997SPavel Labath 
Float(float fail_value) const362d821c997SPavel Labath float Scalar::Float(float fail_value) const {
3639b50546bSPavel Labath   switch (m_type) {
3649b50546bSPavel Labath   case e_void:
365d821c997SPavel Labath     break;
3669b50546bSPavel Labath   case e_int:
367219ccdfdSPavel Labath     if (m_integer.isSigned())
368b725142cSPavel Labath       return llvm::APIntOps::RoundSignedAPIntToFloat(m_integer);
369d821c997SPavel Labath     return llvm::APIntOps::RoundAPIntToFloat(m_integer);
370b725142cSPavel Labath 
3719b50546bSPavel Labath   case e_float: {
37288c82474SPavel Labath     APFloat result = m_float;
37388c82474SPavel Labath     bool losesInfo;
37488c82474SPavel Labath     result.convert(APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven,
37588c82474SPavel Labath                    &losesInfo);
37688c82474SPavel Labath     return result.convertToFloat();
37788c82474SPavel Labath   }
378d821c997SPavel Labath   }
379d821c997SPavel Labath   return fail_value;
380d821c997SPavel Labath }
381d821c997SPavel Labath 
Double(double fail_value) const382d821c997SPavel Labath double Scalar::Double(double fail_value) const {
3839b50546bSPavel Labath   switch (m_type) {
3849b50546bSPavel Labath   case e_void:
385d821c997SPavel Labath     break;
3869b50546bSPavel Labath   case e_int:
387219ccdfdSPavel Labath     if (m_integer.isSigned())
388b725142cSPavel Labath       return llvm::APIntOps::RoundSignedAPIntToDouble(m_integer);
389d821c997SPavel Labath     return llvm::APIntOps::RoundAPIntToDouble(m_integer);
390b725142cSPavel Labath 
3919b50546bSPavel Labath   case e_float: {
39288c82474SPavel Labath     APFloat result = m_float;
39388c82474SPavel Labath     bool losesInfo;
39488c82474SPavel Labath     result.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven,
39588c82474SPavel Labath                    &losesInfo);
39688c82474SPavel Labath     return result.convertToDouble();
39788c82474SPavel Labath   }
398d821c997SPavel Labath   }
399d821c997SPavel Labath   return fail_value;
400d821c997SPavel Labath }
401d821c997SPavel Labath 
LongDouble(long double fail_value) const402d821c997SPavel Labath long double Scalar::LongDouble(long double fail_value) const {
40388c82474SPavel Labath   /// No way to get more precision at the moment.
40488c82474SPavel Labath   return static_cast<long double>(Double(fail_value));
405d821c997SPavel Labath }
406d821c997SPavel Labath 
operator +=(Scalar rhs)40740d77426SPavel Labath Scalar &Scalar::operator+=(Scalar rhs) {
40840d77426SPavel Labath   Scalar copy = *this;
40940d77426SPavel Labath   if ((m_type = PromoteToMaxType(copy, rhs)) != Scalar::e_void) {
4109b50546bSPavel Labath     switch (m_type) {
4119b50546bSPavel Labath     case e_void:
412d821c997SPavel Labath       break;
4139b50546bSPavel Labath     case e_int:
41440d77426SPavel Labath       m_integer = copy.m_integer + rhs.m_integer;
415d821c997SPavel Labath       break;
416d821c997SPavel Labath 
4179b50546bSPavel Labath     case e_float:
41840d77426SPavel Labath       m_float = copy.m_float + rhs.m_float;
419d821c997SPavel Labath       break;
420d821c997SPavel Labath     }
421d821c997SPavel Labath   }
422d821c997SPavel Labath   return *this;
423d821c997SPavel Labath }
424d821c997SPavel Labath 
operator <<=(const Scalar & rhs)425d821c997SPavel Labath Scalar &Scalar::operator<<=(const Scalar &rhs) {
4269b50546bSPavel Labath   if (m_type == e_int && rhs.m_type == e_int)
427219ccdfdSPavel Labath     static_cast<APInt &>(m_integer) <<= rhs.m_integer;
428228ea815SPavel Labath   else
429d821c997SPavel Labath     m_type = e_void;
430d821c997SPavel Labath   return *this;
431d821c997SPavel Labath }
432d821c997SPavel Labath 
ShiftRightLogical(const Scalar & rhs)433d821c997SPavel Labath bool Scalar::ShiftRightLogical(const Scalar &rhs) {
4349b50546bSPavel Labath   if (m_type == e_int && rhs.m_type == e_int) {
435d821c997SPavel Labath     m_integer = m_integer.lshr(rhs.m_integer);
436228ea815SPavel Labath     return true;
437d821c997SPavel Labath   }
438228ea815SPavel Labath   m_type = e_void;
439228ea815SPavel Labath   return false;
440d821c997SPavel Labath }
441d821c997SPavel Labath 
operator >>=(const Scalar & rhs)442d821c997SPavel Labath Scalar &Scalar::operator>>=(const Scalar &rhs) {
443d821c997SPavel Labath   switch (m_type) {
444d821c997SPavel Labath   case e_void:
445d821c997SPavel Labath   case e_float:
446d821c997SPavel Labath     m_type = e_void;
447d821c997SPavel Labath     break;
448d821c997SPavel Labath 
449219ccdfdSPavel Labath   case e_int:
450d821c997SPavel Labath     switch (rhs.m_type) {
451d821c997SPavel Labath     case e_void:
452d821c997SPavel Labath     case e_float:
453d821c997SPavel Labath       m_type = e_void;
454d821c997SPavel Labath       break;
455219ccdfdSPavel Labath     case e_int:
456d821c997SPavel Labath       m_integer = m_integer.ashr(rhs.m_integer);
457d821c997SPavel Labath       break;
458d821c997SPavel Labath     }
459d821c997SPavel Labath     break;
460d821c997SPavel Labath   }
461d821c997SPavel Labath   return *this;
462d821c997SPavel Labath }
463d821c997SPavel Labath 
operator &=(const Scalar & rhs)464d821c997SPavel Labath Scalar &Scalar::operator&=(const Scalar &rhs) {
4659b50546bSPavel Labath   if (m_type == e_int && rhs.m_type == e_int)
466d821c997SPavel Labath     m_integer &= rhs.m_integer;
467228ea815SPavel Labath   else
468228ea815SPavel Labath     m_type = e_void;
469d821c997SPavel Labath   return *this;
470d821c997SPavel Labath }
471d821c997SPavel Labath 
AbsoluteValue()472d821c997SPavel Labath bool Scalar::AbsoluteValue() {
473d821c997SPavel Labath   switch (m_type) {
474d821c997SPavel Labath   case e_void:
475d821c997SPavel Labath     break;
476d821c997SPavel Labath 
477219ccdfdSPavel Labath   case e_int:
478d821c997SPavel Labath     if (m_integer.isNegative())
479d821c997SPavel Labath       m_integer = -m_integer;
480d821c997SPavel Labath     return true;
481d821c997SPavel Labath 
482d821c997SPavel Labath   case e_float:
483d821c997SPavel Labath     m_float.clearSign();
484d821c997SPavel Labath     return true;
485d821c997SPavel Labath   }
486d821c997SPavel Labath   return false;
487d821c997SPavel Labath }
488d821c997SPavel Labath 
UnaryNegate()489d821c997SPavel Labath bool Scalar::UnaryNegate() {
4909b50546bSPavel Labath   switch (m_type) {
4919b50546bSPavel Labath   case e_void:
492d821c997SPavel Labath     break;
4939b50546bSPavel Labath   case e_int:
494d821c997SPavel Labath     m_integer = -m_integer;
495d821c997SPavel Labath     return true;
4969b50546bSPavel Labath   case e_float:
497d821c997SPavel Labath     m_float.changeSign();
498d821c997SPavel Labath     return true;
499d821c997SPavel Labath   }
500d821c997SPavel Labath   return false;
501d821c997SPavel Labath }
502d821c997SPavel Labath 
OnesComplement()503d821c997SPavel Labath bool Scalar::OnesComplement() {
5049b50546bSPavel Labath   if (m_type == e_int) {
505d821c997SPavel Labath     m_integer = ~m_integer;
506d821c997SPavel Labath     return true;
507d821c997SPavel Labath   }
508228ea815SPavel Labath 
509d821c997SPavel Labath   return false;
510d821c997SPavel Labath }
511d821c997SPavel Labath 
operator +(const Scalar & lhs,const Scalar & rhs)512d821c997SPavel Labath const Scalar lldb_private::operator+(const Scalar &lhs, const Scalar &rhs) {
513228ea815SPavel Labath   Scalar result = lhs;
514228ea815SPavel Labath   result += rhs;
515d821c997SPavel Labath   return result;
516d821c997SPavel Labath }
517d821c997SPavel Labath 
operator -(Scalar lhs,Scalar rhs)51840d77426SPavel Labath const Scalar lldb_private::operator-(Scalar lhs, Scalar rhs) {
519d821c997SPavel Labath   Scalar result;
52067cdb899SPavel Labath   if ((result.m_type = Scalar::PromoteToMaxType(lhs, rhs)) != Scalar::e_void) {
5219b50546bSPavel Labath     switch (result.m_type) {
5229b50546bSPavel Labath     case Scalar::e_void:
523d821c997SPavel Labath       break;
5249b50546bSPavel Labath     case Scalar::e_int:
52540d77426SPavel Labath       result.m_integer = lhs.m_integer - rhs.m_integer;
526d821c997SPavel Labath       break;
5279b50546bSPavel Labath     case Scalar::e_float:
52840d77426SPavel Labath       result.m_float = lhs.m_float - rhs.m_float;
529d821c997SPavel Labath       break;
530d821c997SPavel Labath     }
531d821c997SPavel Labath   }
532d821c997SPavel Labath   return result;
533d821c997SPavel Labath }
534d821c997SPavel Labath 
operator /(Scalar lhs,Scalar rhs)53540d77426SPavel Labath const Scalar lldb_private::operator/(Scalar lhs, Scalar rhs) {
536d821c997SPavel Labath   Scalar result;
53767cdb899SPavel Labath   if ((result.m_type = Scalar::PromoteToMaxType(lhs, rhs)) != Scalar::e_void &&
53840d77426SPavel Labath       !rhs.IsZero()) {
5399b50546bSPavel Labath     switch (result.m_type) {
5409b50546bSPavel Labath     case Scalar::e_void:
541d821c997SPavel Labath       break;
5429b50546bSPavel Labath     case Scalar::e_int:
543219ccdfdSPavel Labath       result.m_integer = lhs.m_integer / rhs.m_integer;
544d821c997SPavel Labath       return result;
5459b50546bSPavel Labath     case Scalar::e_float:
54640d77426SPavel Labath       result.m_float = lhs.m_float / rhs.m_float;
547d821c997SPavel Labath       return result;
548d821c997SPavel Labath     }
549d821c997SPavel Labath   }
550d821c997SPavel Labath   // For division only, the only way it should make it here is if a promotion
551d821c997SPavel Labath   // failed, or if we are trying to do a divide by zero.
552d821c997SPavel Labath   result.m_type = Scalar::e_void;
553d821c997SPavel Labath   return result;
554d821c997SPavel Labath }
555d821c997SPavel Labath 
operator *(Scalar lhs,Scalar rhs)55640d77426SPavel Labath const Scalar lldb_private::operator*(Scalar lhs, Scalar rhs) {
557d821c997SPavel Labath   Scalar result;
55867cdb899SPavel Labath   if ((result.m_type = Scalar::PromoteToMaxType(lhs, rhs)) != Scalar::e_void) {
5599b50546bSPavel Labath     switch (result.m_type) {
5609b50546bSPavel Labath     case Scalar::e_void:
561d821c997SPavel Labath       break;
5629b50546bSPavel Labath     case Scalar::e_int:
56340d77426SPavel Labath       result.m_integer = lhs.m_integer * rhs.m_integer;
564d821c997SPavel Labath       break;
5659b50546bSPavel Labath     case Scalar::e_float:
56640d77426SPavel Labath       result.m_float = lhs.m_float * rhs.m_float;
567d821c997SPavel Labath       break;
568d821c997SPavel Labath     }
569d821c997SPavel Labath   }
570d821c997SPavel Labath   return result;
571d821c997SPavel Labath }
572d821c997SPavel Labath 
operator &(Scalar lhs,Scalar rhs)57340d77426SPavel Labath const Scalar lldb_private::operator&(Scalar lhs, Scalar rhs) {
574d821c997SPavel Labath   Scalar result;
57567cdb899SPavel Labath   if ((result.m_type = Scalar::PromoteToMaxType(lhs, rhs)) != Scalar::e_void) {
5769b50546bSPavel Labath     if (result.m_type == Scalar::e_int)
57740d77426SPavel Labath       result.m_integer = lhs.m_integer & rhs.m_integer;
578228ea815SPavel Labath     else
579d821c997SPavel Labath       result.m_type = Scalar::e_void;
580d821c997SPavel Labath   }
581d821c997SPavel Labath   return result;
582d821c997SPavel Labath }
583d821c997SPavel Labath 
operator |(Scalar lhs,Scalar rhs)58440d77426SPavel Labath const Scalar lldb_private::operator|(Scalar lhs, Scalar rhs) {
585d821c997SPavel Labath   Scalar result;
58667cdb899SPavel Labath   if ((result.m_type = Scalar::PromoteToMaxType(lhs, rhs)) != Scalar::e_void) {
5879b50546bSPavel Labath     if (result.m_type == Scalar::e_int)
58840d77426SPavel Labath       result.m_integer = lhs.m_integer | rhs.m_integer;
589228ea815SPavel Labath     else
590d821c997SPavel Labath       result.m_type = Scalar::e_void;
591d821c997SPavel Labath   }
592d821c997SPavel Labath   return result;
593d821c997SPavel Labath }
594d821c997SPavel Labath 
operator %(Scalar lhs,Scalar rhs)59540d77426SPavel Labath const Scalar lldb_private::operator%(Scalar lhs, Scalar rhs) {
596d821c997SPavel Labath   Scalar result;
59767cdb899SPavel Labath   if ((result.m_type = Scalar::PromoteToMaxType(lhs, rhs)) != Scalar::e_void) {
5989b50546bSPavel Labath     if (!rhs.IsZero() && result.m_type == Scalar::e_int) {
599219ccdfdSPavel Labath       result.m_integer = lhs.m_integer % rhs.m_integer;
600d821c997SPavel Labath       return result;
601d821c997SPavel Labath     }
602d821c997SPavel Labath   }
603d821c997SPavel Labath   result.m_type = Scalar::e_void;
604d821c997SPavel Labath   return result;
605d821c997SPavel Labath }
606d821c997SPavel Labath 
operator ^(Scalar lhs,Scalar rhs)60740d77426SPavel Labath const Scalar lldb_private::operator^(Scalar lhs, Scalar rhs) {
608d821c997SPavel Labath   Scalar result;
60967cdb899SPavel Labath   if ((result.m_type = Scalar::PromoteToMaxType(lhs, rhs)) != Scalar::e_void) {
6109b50546bSPavel Labath     if (result.m_type == Scalar::e_int)
61140d77426SPavel Labath       result.m_integer = lhs.m_integer ^ rhs.m_integer;
612228ea815SPavel Labath     else
613d821c997SPavel Labath       result.m_type = Scalar::e_void;
614d821c997SPavel Labath   }
615d821c997SPavel Labath   return result;
616d821c997SPavel Labath }
617d821c997SPavel Labath 
operator <<(const Scalar & lhs,const Scalar & rhs)618d821c997SPavel Labath const Scalar lldb_private::operator<<(const Scalar &lhs, const Scalar &rhs) {
619d821c997SPavel Labath   Scalar result = lhs;
620d821c997SPavel Labath   result <<= rhs;
621d821c997SPavel Labath   return result;
622d821c997SPavel Labath }
623d821c997SPavel Labath 
operator >>(const Scalar & lhs,const Scalar & rhs)624d821c997SPavel Labath const Scalar lldb_private::operator>>(const Scalar &lhs, const Scalar &rhs) {
625d821c997SPavel Labath   Scalar result = lhs;
626d821c997SPavel Labath   result >>= rhs;
627d821c997SPavel Labath   return result;
628d821c997SPavel Labath }
629d821c997SPavel Labath 
SetValueFromCString(const char * value_str,Encoding encoding,size_t byte_size)630d821c997SPavel Labath Status Scalar::SetValueFromCString(const char *value_str, Encoding encoding,
631d821c997SPavel Labath                                    size_t byte_size) {
632d821c997SPavel Labath   Status error;
633d821c997SPavel Labath   if (value_str == nullptr || value_str[0] == '\0') {
634d821c997SPavel Labath     error.SetErrorString("Invalid c-string value string.");
635d821c997SPavel Labath     return error;
636d821c997SPavel Labath   }
637d821c997SPavel Labath   switch (encoding) {
638d821c997SPavel Labath   case eEncodingInvalid:
639d821c997SPavel Labath     error.SetErrorString("Invalid encoding.");
640d821c997SPavel Labath     break;
641d821c997SPavel Labath 
642d821c997SPavel Labath   case eEncodingSint:
6431847f4ddSPavel Labath   case eEncodingUint: {
6441847f4ddSPavel Labath     llvm::StringRef str = value_str;
6451847f4ddSPavel Labath     bool is_signed = encoding == eEncodingSint;
6461847f4ddSPavel Labath     bool is_negative = is_signed && str.consume_front("-");
6471847f4ddSPavel Labath     APInt integer;
6481847f4ddSPavel Labath     if (str.getAsInteger(0, integer)) {
6491847f4ddSPavel Labath       error.SetErrorStringWithFormatv(
6501847f4ddSPavel Labath           "'{0}' is not a valid integer string value", value_str);
651d821c997SPavel Labath       break;
652d821c997SPavel Labath     }
6531847f4ddSPavel Labath     bool fits;
6541847f4ddSPavel Labath     if (is_signed) {
6551847f4ddSPavel Labath       integer = integer.zext(integer.getBitWidth() + 1);
6561847f4ddSPavel Labath       if (is_negative)
6571847f4ddSPavel Labath         integer.negate();
6581847f4ddSPavel Labath       fits = integer.isSignedIntN(byte_size * 8);
6591847f4ddSPavel Labath     } else
6601847f4ddSPavel Labath       fits = integer.isIntN(byte_size * 8);
6611847f4ddSPavel Labath     if (!fits) {
6621847f4ddSPavel Labath       error.SetErrorStringWithFormatv(
6631847f4ddSPavel Labath           "value {0} is too large to fit in a {1} byte integer value",
6641847f4ddSPavel Labath           value_str, byte_size);
665d821c997SPavel Labath       break;
6661847f4ddSPavel Labath     }
667219ccdfdSPavel Labath     m_type = e_int;
668219ccdfdSPavel Labath     m_integer =
669219ccdfdSPavel Labath         APSInt(std::move(integer), !is_signed).extOrTrunc(8 * byte_size);
6701847f4ddSPavel Labath     break;
6711847f4ddSPavel Labath   }
672d821c997SPavel Labath 
6731847f4ddSPavel Labath   case eEncodingIEEE754: {
6748a8a2dd3SPavel Labath     // FIXME: It's not possible to unambiguously map a byte size to a floating
6758a8a2dd3SPavel Labath     // point type. This function should be refactored to take an explicit
6768a8a2dd3SPavel Labath     // semantics argument.
6778a8a2dd3SPavel Labath     const llvm::fltSemantics &sem =
6788a8a2dd3SPavel Labath         byte_size <= 4 ? APFloat::IEEEsingle()
6798a8a2dd3SPavel Labath                        : byte_size <= 8 ? APFloat::IEEEdouble()
6808a8a2dd3SPavel Labath                                         : APFloat::x87DoubleExtended();
6818a8a2dd3SPavel Labath     APFloat f(sem);
6821847f4ddSPavel Labath     if (llvm::Expected<APFloat::opStatus> op =
6831847f4ddSPavel Labath             f.convertFromString(value_str, APFloat::rmNearestTiesToEven)) {
6848a8a2dd3SPavel Labath       m_type = e_float;
6851847f4ddSPavel Labath       m_float = std::move(f);
6861847f4ddSPavel Labath     } else
6871847f4ddSPavel Labath       error = op.takeError();
6881847f4ddSPavel Labath     break;
6891847f4ddSPavel Labath   }
690d821c997SPavel Labath 
691d821c997SPavel Labath   case eEncodingVector:
692d821c997SPavel Labath     error.SetErrorString("vector encoding unsupported.");
693d821c997SPavel Labath     break;
694d821c997SPavel Labath   }
695d821c997SPavel Labath   if (error.Fail())
696d821c997SPavel Labath     m_type = e_void;
697d821c997SPavel Labath 
698d821c997SPavel Labath   return error;
699d821c997SPavel Labath }
700d821c997SPavel Labath 
SetValueFromData(const DataExtractor & data,lldb::Encoding encoding,size_t byte_size)7017fadd700SPavel Labath Status Scalar::SetValueFromData(const DataExtractor &data,
7027fadd700SPavel Labath                                 lldb::Encoding encoding, size_t byte_size) {
703d821c997SPavel Labath   Status error;
704d821c997SPavel Labath   switch (encoding) {
705d821c997SPavel Labath   case lldb::eEncodingInvalid:
706d821c997SPavel Labath     error.SetErrorString("invalid encoding");
707d821c997SPavel Labath     break;
708d821c997SPavel Labath   case lldb::eEncodingVector:
709d821c997SPavel Labath     error.SetErrorString("vector encoding unsupported");
710d821c997SPavel Labath     break;
7117fadd700SPavel Labath   case lldb::eEncodingUint:
712d821c997SPavel Labath   case lldb::eEncodingSint: {
7137fadd700SPavel Labath     if (data.GetByteSize() < byte_size)
7147fadd700SPavel Labath       return Status("insufficient data");
715219ccdfdSPavel Labath     m_type = e_int;
716219ccdfdSPavel Labath     m_integer =
717*735f4671SChris Lattner         APSInt(APInt::getZero(8 * byte_size), encoding == eEncodingUint);
7187fadd700SPavel Labath     if (data.GetByteOrder() == endian::InlHostByteOrder()) {
7197fadd700SPavel Labath       llvm::LoadIntFromMemory(m_integer, data.GetDataStart(), byte_size);
7207fadd700SPavel Labath     } else {
7217fadd700SPavel Labath       std::vector<uint8_t> buffer(byte_size);
7227fadd700SPavel Labath       std::copy_n(data.GetDataStart(), byte_size, buffer.rbegin());
7237fadd700SPavel Labath       llvm::LoadIntFromMemory(m_integer, buffer.data(), byte_size);
7247fadd700SPavel Labath     }
725d821c997SPavel Labath     break;
726d821c997SPavel Labath   }
727d821c997SPavel Labath   case lldb::eEncodingIEEE754: {
728d821c997SPavel Labath     lldb::offset_t offset = 0;
729d821c997SPavel Labath 
730d821c997SPavel Labath     if (byte_size == sizeof(float))
73124374aefSJonas Devlieghere       operator=(data.GetFloat(&offset));
732d821c997SPavel Labath     else if (byte_size == sizeof(double))
73324374aefSJonas Devlieghere       operator=(data.GetDouble(&offset));
734d821c997SPavel Labath     else if (byte_size == sizeof(long double))
73524374aefSJonas Devlieghere       operator=(data.GetLongDouble(&offset));
736d821c997SPavel Labath     else
737d821c997SPavel Labath       error.SetErrorStringWithFormat("unsupported float byte size: %" PRIu64 "",
73824374aefSJonas Devlieghere                                      static_cast<uint64_t>(byte_size));
739d821c997SPavel Labath   } break;
740d821c997SPavel Labath   }
741d821c997SPavel Labath 
742d821c997SPavel Labath   return error;
743d821c997SPavel Labath }
744d821c997SPavel Labath 
SignExtend(uint32_t sign_bit_pos)745d821c997SPavel Labath bool Scalar::SignExtend(uint32_t sign_bit_pos) {
746d821c997SPavel Labath   const uint32_t max_bit_pos = GetByteSize() * 8;
747d821c997SPavel Labath 
748d821c997SPavel Labath   if (sign_bit_pos < max_bit_pos) {
749d821c997SPavel Labath     switch (m_type) {
750d821c997SPavel Labath     case Scalar::e_void:
751d821c997SPavel Labath     case Scalar::e_float:
752d821c997SPavel Labath       return false;
753d821c997SPavel Labath 
754219ccdfdSPavel Labath     case Scalar::e_int:
755d821c997SPavel Labath       if (max_bit_pos == sign_bit_pos)
756d821c997SPavel Labath         return true;
757d821c997SPavel Labath       else if (sign_bit_pos < (max_bit_pos - 1)) {
758d821c997SPavel Labath         llvm::APInt sign_bit = llvm::APInt::getSignMask(sign_bit_pos + 1);
759d821c997SPavel Labath         llvm::APInt bitwize_and = m_integer & sign_bit;
760d821c997SPavel Labath         if (bitwize_and.getBoolValue()) {
761219ccdfdSPavel Labath           llvm::APInt mask =
762d821c997SPavel Labath               ~(sign_bit) + llvm::APInt(m_integer.getBitWidth(), 1);
763219ccdfdSPavel Labath           m_integer |= APSInt(std::move(mask), m_integer.isUnsigned());
764d821c997SPavel Labath         }
765d821c997SPavel Labath         return true;
766d821c997SPavel Labath       }
767d821c997SPavel Labath       break;
768d821c997SPavel Labath     }
769d821c997SPavel Labath   }
770d821c997SPavel Labath   return false;
771d821c997SPavel Labath }
772d821c997SPavel Labath 
GetAsMemoryData(void * dst,size_t dst_len,lldb::ByteOrder dst_byte_order,Status & error) const773d821c997SPavel Labath size_t Scalar::GetAsMemoryData(void *dst, size_t dst_len,
774d821c997SPavel Labath                                lldb::ByteOrder dst_byte_order,
775d821c997SPavel Labath                                Status &error) const {
776d821c997SPavel Labath   // Get a data extractor that points to the native scalar data
777d821c997SPavel Labath   DataExtractor data;
778d821c997SPavel Labath   if (!GetData(data)) {
779d821c997SPavel Labath     error.SetErrorString("invalid scalar value");
780d821c997SPavel Labath     return 0;
781d821c997SPavel Labath   }
782d821c997SPavel Labath 
783d821c997SPavel Labath   const size_t src_len = data.GetByteSize();
784d821c997SPavel Labath 
785d821c997SPavel Labath   // Prepare a memory buffer that contains some or all of the register value
786d821c997SPavel Labath   const size_t bytes_copied =
787d821c997SPavel Labath       data.CopyByteOrderedData(0,               // src offset
788d821c997SPavel Labath                                src_len,         // src length
789d821c997SPavel Labath                                dst,             // dst buffer
790d821c997SPavel Labath                                dst_len,         // dst length
791d821c997SPavel Labath                                dst_byte_order); // dst byte order
792d821c997SPavel Labath   if (bytes_copied == 0)
793d821c997SPavel Labath     error.SetErrorString("failed to copy data");
794d821c997SPavel Labath 
795d821c997SPavel Labath   return bytes_copied;
796d821c997SPavel Labath }
797d821c997SPavel Labath 
ExtractBitfield(uint32_t bit_size,uint32_t bit_offset)798d821c997SPavel Labath bool Scalar::ExtractBitfield(uint32_t bit_size, uint32_t bit_offset) {
799d821c997SPavel Labath   if (bit_size == 0)
800d821c997SPavel Labath     return true;
801d821c997SPavel Labath 
802d821c997SPavel Labath   switch (m_type) {
803d821c997SPavel Labath   case Scalar::e_void:
804d821c997SPavel Labath   case Scalar::e_float:
805d821c997SPavel Labath     break;
806d821c997SPavel Labath 
807219ccdfdSPavel Labath   case Scalar::e_int:
808219ccdfdSPavel Labath     m_integer >>= bit_offset;
809219ccdfdSPavel Labath     m_integer = m_integer.extOrTrunc(bit_size).extOrTrunc(8 * GetByteSize());
810d821c997SPavel Labath     return true;
811d821c997SPavel Labath   }
812d821c997SPavel Labath   return false;
813d821c997SPavel Labath }
814d821c997SPavel Labath 
operator ==(Scalar lhs,Scalar rhs)81540d77426SPavel Labath bool lldb_private::operator==(Scalar lhs, Scalar rhs) {
816d821c997SPavel Labath   // If either entry is void then we can just compare the types
817d821c997SPavel Labath   if (lhs.m_type == Scalar::e_void || rhs.m_type == Scalar::e_void)
818d821c997SPavel Labath     return lhs.m_type == rhs.m_type;
819d821c997SPavel Labath 
820d821c997SPavel Labath   llvm::APFloat::cmpResult result;
82167cdb899SPavel Labath   switch (Scalar::PromoteToMaxType(lhs, rhs)) {
822d821c997SPavel Labath   case Scalar::e_void:
823d821c997SPavel Labath     break;
824219ccdfdSPavel Labath   case Scalar::e_int:
82540d77426SPavel Labath     return lhs.m_integer == rhs.m_integer;
826d821c997SPavel Labath   case Scalar::e_float:
82740d77426SPavel Labath     result = lhs.m_float.compare(rhs.m_float);
828d821c997SPavel Labath     if (result == llvm::APFloat::cmpEqual)
829d821c997SPavel Labath       return true;
830d821c997SPavel Labath   }
831d821c997SPavel Labath   return false;
832d821c997SPavel Labath }
833d821c997SPavel Labath 
operator !=(const Scalar & lhs,const Scalar & rhs)834d821c997SPavel Labath bool lldb_private::operator!=(const Scalar &lhs, const Scalar &rhs) {
83518a0ce98SDavide Italiano   return !(lhs == rhs);
836d821c997SPavel Labath }
837d821c997SPavel Labath 
operator <(Scalar lhs,Scalar rhs)83840d77426SPavel Labath bool lldb_private::operator<(Scalar lhs, Scalar rhs) {
839d821c997SPavel Labath   if (lhs.m_type == Scalar::e_void || rhs.m_type == Scalar::e_void)
840d821c997SPavel Labath     return false;
841d821c997SPavel Labath 
842d821c997SPavel Labath   llvm::APFloat::cmpResult result;
84367cdb899SPavel Labath   switch (Scalar::PromoteToMaxType(lhs, rhs)) {
844d821c997SPavel Labath   case Scalar::e_void:
845d821c997SPavel Labath     break;
846219ccdfdSPavel Labath   case Scalar::e_int:
847219ccdfdSPavel Labath     return lhs.m_integer < rhs.m_integer;
848d821c997SPavel Labath   case Scalar::e_float:
84940d77426SPavel Labath     result = lhs.m_float.compare(rhs.m_float);
850d821c997SPavel Labath     if (result == llvm::APFloat::cmpLessThan)
851d821c997SPavel Labath       return true;
852d821c997SPavel Labath   }
853d821c997SPavel Labath   return false;
854d821c997SPavel Labath }
855d821c997SPavel Labath 
operator <=(const Scalar & lhs,const Scalar & rhs)856d821c997SPavel Labath bool lldb_private::operator<=(const Scalar &lhs, const Scalar &rhs) {
857ff92a1a7SDavide Italiano   return !(rhs < lhs);
858d821c997SPavel Labath }
859d821c997SPavel Labath 
operator >(const Scalar & lhs,const Scalar & rhs)860d821c997SPavel Labath bool lldb_private::operator>(const Scalar &lhs, const Scalar &rhs) {
861ff92a1a7SDavide Italiano   return rhs < lhs;
862d821c997SPavel Labath }
863d821c997SPavel Labath 
operator >=(const Scalar & lhs,const Scalar & rhs)864d821c997SPavel Labath bool lldb_private::operator>=(const Scalar &lhs, const Scalar &rhs) {
865ff92a1a7SDavide Italiano   return !(lhs < rhs);
866d821c997SPavel Labath }
867d821c997SPavel Labath 
ClearBit(uint32_t bit)868d821c997SPavel Labath bool Scalar::ClearBit(uint32_t bit) {
869d821c997SPavel Labath   switch (m_type) {
870d821c997SPavel Labath   case e_void:
871d821c997SPavel Labath     break;
872219ccdfdSPavel Labath   case e_int:
873d821c997SPavel Labath     m_integer.clearBit(bit);
874d821c997SPavel Labath     return true;
875d821c997SPavel Labath   case e_float:
876d821c997SPavel Labath     break;
877d821c997SPavel Labath   }
878d821c997SPavel Labath   return false;
879d821c997SPavel Labath }
880d821c997SPavel Labath 
SetBit(uint32_t bit)881d821c997SPavel Labath bool Scalar::SetBit(uint32_t bit) {
882d821c997SPavel Labath   switch (m_type) {
883d821c997SPavel Labath   case e_void:
884d821c997SPavel Labath     break;
885219ccdfdSPavel Labath   case e_int:
886d821c997SPavel Labath     m_integer.setBit(bit);
887d821c997SPavel Labath     return true;
888d821c997SPavel Labath   case e_float:
889d821c997SPavel Labath     break;
890d821c997SPavel Labath   }
891d821c997SPavel Labath   return false;
892d821c997SPavel Labath }
893b07a7997SPavel Labath 
operator <<(llvm::raw_ostream & os,const Scalar & scalar)894b07a7997SPavel Labath llvm::raw_ostream &lldb_private::operator<<(llvm::raw_ostream &os, const Scalar &scalar) {
895b07a7997SPavel Labath   StreamString s;
896b07a7997SPavel Labath   scalar.GetValue(&s, /*show_type*/ true);
897b07a7997SPavel Labath   return os << s.GetString();
898b07a7997SPavel Labath }
899