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
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 in
55// 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 expected
78  if (lhs.GetPromoKey() == rhs.GetPromoKey())
79    return lhs.GetType(); // Return the resulting type
80
81  // Return the void type (zero) if we fail to promote either of the values.
82  return Scalar::e_void;
83}
84
85bool Scalar::GetData(DataExtractor &data, size_t limit_byte_size) const {
86  size_t byte_size = GetByteSize();
87  if (byte_size == 0) {
88    data.Clear();
89    return false;
90  }
91  auto buffer_up = std::make_unique<DataBufferHeap>(byte_size, 0);
92  GetBytes(buffer_up->GetData());
93  lldb::offset_t offset = 0;
94
95  if (limit_byte_size < byte_size) {
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;
106    }
107  }
108
109  data.SetData(std::move(buffer_up), offset, byte_size);
110  data.SetByteOrder(endian::InlHostByteOrder());
111  return true;
112}
113
114void Scalar::GetBytes(llvm::MutableArrayRef<uint8_t> storage) const {
115  assert(storage.size() >= GetByteSize());
116
117  const auto &store = [&](const llvm::APInt &val) {
118    StoreIntToMemory(val, storage.data(), (val.getBitWidth() + 7) / 8);
119  };
120  switch (m_type) {
121  case e_void:
122    break;
123  case e_int:
124    store(m_integer);
125    break;
126  case e_float:
127    store(m_float.bitcastToAPInt());
128    break;
129  }
130}
131
132size_t Scalar::GetByteSize() const {
133  switch (m_type) {
134  case e_void:
135    break;
136  case e_int:
137    return (m_integer.getBitWidth() / 8);
138  case e_float:
139    return m_float.bitcastToAPInt().getBitWidth() / 8;
140  }
141  return 0;
142}
143
144bool Scalar::IsZero() const {
145  switch (m_type) {
146  case e_void:
147    break;
148  case e_int:
149    return m_integer.isZero();
150  case e_float:
151    return m_float.isZero();
152  }
153  return false;
154}
155
156void Scalar::GetValue(Stream &s, bool show_type) const {
157  if (show_type)
158    s.Printf("(%s) ", GetTypeAsCString());
159
160  switch (m_type) {
161  case e_void:
162    break;
163  case e_int:
164    s.PutCString(llvm::toString(m_integer, 10));
165    break;
166  case e_float:
167    llvm::SmallString<24> string;
168    m_float.toString(string);
169    s.PutCString(string);
170    break;
171  }
172}
173
174void Scalar::TruncOrExtendTo(uint16_t bits, bool sign) {
175  m_integer.setIsSigned(sign);
176  m_integer = m_integer.extOrTrunc(bits);
177}
178
179bool Scalar::IntegralPromote(uint16_t bits, bool sign) {
180  switch (m_type) {
181  case e_void:
182  case e_float:
183    break;
184  case e_int:
185    if (GetPromoKey() > PromotionKey(e_int, bits, !sign))
186      break;
187    m_integer = m_integer.extOrTrunc(bits);
188    m_integer.setIsSigned(sign);
189    return true;
190  }
191  return false;
192}
193
194bool Scalar::FloatPromote(const llvm::fltSemantics &semantics) {
195  bool success = false;
196  switch (m_type) {
197  case e_void:
198    break;
199  case e_int:
200    m_float = llvm::APFloat(semantics);
201    m_float.convertFromAPInt(m_integer, m_integer.isSigned(),
202                             llvm::APFloat::rmNearestTiesToEven);
203    success = true;
204    break;
205  case e_float:
206    if (GetFloatPromoKey(semantics) < GetFloatPromoKey(m_float.getSemantics()))
207      break;
208    bool ignore;
209    success = true;
210    m_float.convert(semantics, llvm::APFloat::rmNearestTiesToEven, &ignore);
211  }
212
213  if (success)
214    m_type = e_float;
215  return success;
216}
217
218const char *Scalar::GetValueTypeAsCString(Scalar::Type type) {
219  switch (type) {
220  case e_void:
221    return "void";
222  case e_int:
223    return "int";
224  case e_float:
225    return "float";
226  }
227  return "???";
228}
229
230bool Scalar::IsSigned() const {
231  switch (m_type) {
232  case e_void:
233    return false;
234  case e_int:
235    return m_integer.isSigned();
236  case e_float:
237    return true;
238  }
239  llvm_unreachable("Unrecognized type!");
240}
241
242bool Scalar::MakeSigned() {
243  bool success = false;
244
245  switch (m_type) {
246  case e_void:
247    break;
248  case e_int:
249    m_integer.setIsSigned(true);
250    success = true;
251    break;
252  case e_float:
253    success = true;
254    break;
255  }
256
257  return success;
258}
259
260bool Scalar::MakeUnsigned() {
261  bool success = false;
262
263  switch (m_type) {
264  case e_void:
265    break;
266  case e_int:
267    m_integer.setIsUnsigned(true);
268    success = true;
269    break;
270  case e_float:
271    success = true;
272    break;
273  }
274
275  return success;
276}
277
278static llvm::APInt ToAPInt(const llvm::APFloat &f, unsigned bits,
279                           bool is_unsigned) {
280  llvm::APSInt result(bits, is_unsigned);
281  bool isExact;
282  f.convertToInteger(result, llvm::APFloat::rmTowardZero, &isExact);
283  return std::move(result);
284}
285
286template <typename T> T Scalar::GetAs(T fail_value) const {
287  switch (m_type) {
288  case e_void:
289    break;
290  case e_int: {
291    APSInt ext = m_integer.extOrTrunc(sizeof(T) * 8);
292    if (ext.isSigned())
293      return ext.getSExtValue();
294    return ext.getZExtValue();
295  }
296  case e_float:
297    return ToAPInt(m_float, sizeof(T) * 8, std::is_unsigned<T>::value)
298        .getSExtValue();
299  }
300  return fail_value;
301}
302
303signed char Scalar::SChar(signed char fail_value) const {
304  return GetAs<signed char>(fail_value);
305}
306
307unsigned char Scalar::UChar(unsigned char fail_value) const {
308  return GetAs<unsigned char>(fail_value);
309}
310
311short Scalar::SShort(short fail_value) const {
312  return GetAs<short>(fail_value);
313}
314
315unsigned short Scalar::UShort(unsigned short fail_value) const {
316  return GetAs<unsigned short>(fail_value);
317}
318
319int Scalar::SInt(int fail_value) const { return GetAs<int>(fail_value); }
320
321unsigned int Scalar::UInt(unsigned int fail_value) const {
322  return GetAs<unsigned int>(fail_value);
323}
324
325long Scalar::SLong(long fail_value) const { return GetAs<long>(fail_value); }
326
327unsigned long Scalar::ULong(unsigned long fail_value) const {
328  return GetAs<unsigned long>(fail_value);
329}
330
331long long Scalar::SLongLong(long long fail_value) const {
332  return GetAs<long long>(fail_value);
333}
334
335unsigned long long Scalar::ULongLong(unsigned long long fail_value) const {
336  return GetAs<unsigned long long>(fail_value);
337}
338
339llvm::APInt Scalar::SInt128(const llvm::APInt &fail_value) const {
340  switch (m_type) {
341  case e_void:
342    break;
343  case e_int:
344    return m_integer;
345  case e_float:
346    return ToAPInt(m_float, 128, /*is_unsigned=*/false);
347  }
348  return fail_value;
349}
350
351llvm::APInt Scalar::UInt128(const llvm::APInt &fail_value) const {
352  switch (m_type) {
353  case e_void:
354    break;
355  case e_int:
356    return m_integer;
357  case e_float:
358    return ToAPInt(m_float, 128, /*is_unsigned=*/true);
359  }
360  return fail_value;
361}
362
363float Scalar::Float(float fail_value) const {
364  switch (m_type) {
365  case e_void:
366    break;
367  case e_int:
368    if (m_integer.isSigned())
369      return llvm::APIntOps::RoundSignedAPIntToFloat(m_integer);
370    return llvm::APIntOps::RoundAPIntToFloat(m_integer);
371
372  case e_float: {
373    APFloat result = m_float;
374    bool losesInfo;
375    result.convert(APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven,
376                   &losesInfo);
377    return result.convertToFloat();
378  }
379  }
380  return fail_value;
381}
382
383double Scalar::Double(double fail_value) const {
384  switch (m_type) {
385  case e_void:
386    break;
387  case e_int:
388    if (m_integer.isSigned())
389      return llvm::APIntOps::RoundSignedAPIntToDouble(m_integer);
390    return llvm::APIntOps::RoundAPIntToDouble(m_integer);
391
392  case e_float: {
393    APFloat result = m_float;
394    bool losesInfo;
395    result.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven,
396                   &losesInfo);
397    return result.convertToDouble();
398  }
399  }
400  return fail_value;
401}
402
403long double Scalar::LongDouble(long double fail_value) const {
404  /// No way to get more precision at the moment.
405  return static_cast<long double>(Double(fail_value));
406}
407
408Scalar &Scalar::operator+=(Scalar rhs) {
409  Scalar copy = *this;
410  if ((m_type = PromoteToMaxType(copy, rhs)) != Scalar::e_void) {
411    switch (m_type) {
412    case e_void:
413      break;
414    case e_int:
415      m_integer = copy.m_integer + rhs.m_integer;
416      break;
417
418    case e_float:
419      m_float = copy.m_float + rhs.m_float;
420      break;
421    }
422  }
423  return *this;
424}
425
426Scalar &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;
429  else
430    m_type = e_void;
431  return *this;
432}
433
434bool 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);
437    return true;
438  }
439  m_type = e_void;
440  return false;
441}
442
443Scalar &Scalar::operator>>=(const Scalar &rhs) {
444  switch (m_type) {
445  case e_void:
446  case e_float:
447    m_type = e_void;
448    break;
449
450  case e_int:
451    switch (rhs.m_type) {
452    case e_void:
453    case e_float:
454      m_type = e_void;
455      break;
456    case e_int:
457      m_integer = m_integer.ashr(rhs.m_integer);
458      break;
459    }
460    break;
461  }
462  return *this;
463}
464
465Scalar &Scalar::operator&=(const Scalar &rhs) {
466  if (m_type == e_int && rhs.m_type == e_int)
467    m_integer &= rhs.m_integer;
468  else
469    m_type = e_void;
470  return *this;
471}
472
473bool Scalar::AbsoluteValue() {
474  switch (m_type) {
475  case e_void:
476    break;
477
478  case e_int:
479    if (m_integer.isNegative())
480      m_integer = -m_integer;
481    return true;
482
483  case e_float:
484    m_float.clearSign();
485    return true;
486  }
487  return false;
488}
489
490bool Scalar::UnaryNegate() {
491  switch (m_type) {
492  case e_void:
493    break;
494  case e_int:
495    m_integer = -m_integer;
496    return true;
497  case e_float:
498    m_float.changeSign();
499    return true;
500  }
501  return false;
502}
503
504bool Scalar::OnesComplement() {
505  if (m_type == e_int) {
506    m_integer = ~m_integer;
507    return true;
508  }
509
510  return false;
511}
512
513const Scalar lldb_private::operator+(const Scalar &lhs, const Scalar &rhs) {
514  Scalar result = lhs;
515  result += rhs;
516  return result;
517}
518
519const Scalar lldb_private::operator-(Scalar lhs, Scalar rhs) {
520  Scalar result;
521  if ((result.m_type = Scalar::PromoteToMaxType(lhs, rhs)) != Scalar::e_void) {
522    switch (result.m_type) {
523    case Scalar::e_void:
524      break;
525    case Scalar::e_int:
526      result.m_integer = lhs.m_integer - rhs.m_integer;
527      break;
528    case Scalar::e_float:
529      result.m_float = lhs.m_float - rhs.m_float;
530      break;
531    }
532  }
533  return result;
534}
535
536const Scalar lldb_private::operator/(Scalar lhs, Scalar rhs) {
537  Scalar result;
538  if ((result.m_type = Scalar::PromoteToMaxType(lhs, rhs)) != Scalar::e_void &&
539      !rhs.IsZero()) {
540    switch (result.m_type) {
541    case Scalar::e_void:
542      break;
543    case Scalar::e_int:
544      result.m_integer = lhs.m_integer / rhs.m_integer;
545      return result;
546    case Scalar::e_float:
547      result.m_float = lhs.m_float / rhs.m_float;
548      return result;
549    }
550  }
551  // For division only, the only way it should make it here is if a promotion
552  // failed, or if we are trying to do a divide by zero.
553  result.m_type = Scalar::e_void;
554  return result;
555}
556
557const Scalar lldb_private::operator*(Scalar lhs, Scalar rhs) {
558  Scalar result;
559  if ((result.m_type = Scalar::PromoteToMaxType(lhs, rhs)) != Scalar::e_void) {
560    switch (result.m_type) {
561    case Scalar::e_void:
562      break;
563    case Scalar::e_int:
564      result.m_integer = lhs.m_integer * rhs.m_integer;
565      break;
566    case Scalar::e_float:
567      result.m_float = lhs.m_float * rhs.m_float;
568      break;
569    }
570  }
571  return result;
572}
573
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    if (result.m_type == Scalar::e_int)
578      result.m_integer = lhs.m_integer & rhs.m_integer;
579    else
580      result.m_type = Scalar::e_void;
581  }
582  return result;
583}
584
585const Scalar lldb_private::operator|(Scalar lhs, Scalar rhs) {
586  Scalar result;
587  if ((result.m_type = Scalar::PromoteToMaxType(lhs, rhs)) != Scalar::e_void) {
588    if (result.m_type == Scalar::e_int)
589      result.m_integer = lhs.m_integer | rhs.m_integer;
590    else
591      result.m_type = Scalar::e_void;
592  }
593  return result;
594}
595
596const Scalar lldb_private::operator%(Scalar lhs, Scalar rhs) {
597  Scalar result;
598  if ((result.m_type = Scalar::PromoteToMaxType(lhs, rhs)) != Scalar::e_void) {
599    if (!rhs.IsZero() && result.m_type == Scalar::e_int) {
600      result.m_integer = lhs.m_integer % rhs.m_integer;
601      return result;
602    }
603  }
604  result.m_type = Scalar::e_void;
605  return result;
606}
607
608const Scalar lldb_private::operator^(Scalar lhs, Scalar rhs) {
609  Scalar result;
610  if ((result.m_type = Scalar::PromoteToMaxType(lhs, rhs)) != Scalar::e_void) {
611    if (result.m_type == Scalar::e_int)
612      result.m_integer = lhs.m_integer ^ rhs.m_integer;
613    else
614      result.m_type = Scalar::e_void;
615  }
616  return result;
617}
618
619const Scalar lldb_private::operator<<(const Scalar &lhs, const Scalar &rhs) {
620  Scalar result = lhs;
621  result <<= rhs;
622  return result;
623}
624
625const Scalar lldb_private::operator>>(const Scalar &lhs, const Scalar &rhs) {
626  Scalar result = lhs;
627  result >>= rhs;
628  return result;
629}
630
631Status Scalar::SetValueFromCString(const char *value_str, Encoding encoding,
632                                   size_t byte_size) {
633  Status error;
634  if (value_str == nullptr || value_str[0] == '\0') {
635    error.SetErrorString("Invalid c-string value string.");
636    return error;
637  }
638  switch (encoding) {
639  case eEncodingInvalid:
640    error.SetErrorString("Invalid encoding.");
641    break;
642
643  case eEncodingSint:
644  case eEncodingUint: {
645    llvm::StringRef str = value_str;
646    bool is_signed = encoding == eEncodingSint;
647    bool is_negative = is_signed && str.consume_front("-");
648    APInt integer;
649    if (str.getAsInteger(0, integer)) {
650      error.SetErrorStringWithFormatv(
651          "'{0}' is not a valid integer string value", value_str);
652      break;
653    }
654    bool fits;
655    if (is_signed) {
656      integer = integer.zext(integer.getBitWidth() + 1);
657      if (is_negative)
658        integer.negate();
659      fits = integer.isSignedIntN(byte_size * 8);
660    } else
661      fits = integer.isIntN(byte_size * 8);
662    if (!fits) {
663      error.SetErrorStringWithFormatv(
664          "value {0} is too large to fit in a {1} byte integer value",
665          value_str, byte_size);
666      break;
667    }
668    m_type = e_int;
669    m_integer =
670        APSInt(std::move(integer), !is_signed).extOrTrunc(8 * byte_size);
671    break;
672  }
673
674  case eEncodingIEEE754: {
675    // FIXME: It's not possible to unambiguously map a byte size to a floating
676    // point type. This function should be refactored to take an explicit
677    // semantics argument.
678    const llvm::fltSemantics &sem =
679        byte_size <= 4 ? APFloat::IEEEsingle()
680                       : byte_size <= 8 ? APFloat::IEEEdouble()
681                                        : APFloat::x87DoubleExtended();
682    APFloat f(sem);
683    if (llvm::Expected<APFloat::opStatus> op =
684            f.convertFromString(value_str, APFloat::rmNearestTiesToEven)) {
685      m_type = e_float;
686      m_float = std::move(f);
687    } else
688      error = op.takeError();
689    break;
690  }
691
692  case eEncodingVector:
693    error.SetErrorString("vector encoding unsupported.");
694    break;
695  }
696  if (error.Fail())
697    m_type = e_void;
698
699  return error;
700}
701
702Status Scalar::SetValueFromData(const DataExtractor &data,
703                                lldb::Encoding encoding, size_t byte_size) {
704  Status error;
705  switch (encoding) {
706  case lldb::eEncodingInvalid:
707    error.SetErrorString("invalid encoding");
708    break;
709  case lldb::eEncodingVector:
710    error.SetErrorString("vector encoding unsupported");
711    break;
712  case lldb::eEncodingUint:
713  case lldb::eEncodingSint: {
714    if (data.GetByteSize() < byte_size)
715      return Status("insufficient data");
716    m_type = e_int;
717    m_integer =
718        APSInt(APInt::getZero(8 * byte_size), encoding == eEncodingUint);
719    if (data.GetByteOrder() == endian::InlHostByteOrder()) {
720      llvm::LoadIntFromMemory(m_integer, data.GetDataStart(), byte_size);
721    } else {
722      std::vector<uint8_t> buffer(byte_size);
723      std::copy_n(data.GetDataStart(), byte_size, buffer.rbegin());
724      llvm::LoadIntFromMemory(m_integer, buffer.data(), byte_size);
725    }
726    break;
727  }
728  case lldb::eEncodingIEEE754: {
729    lldb::offset_t offset = 0;
730
731    if (byte_size == sizeof(float))
732      operator=(data.GetFloat(&offset));
733    else if (byte_size == sizeof(double))
734      operator=(data.GetDouble(&offset));
735    else if (byte_size == sizeof(long double))
736      operator=(data.GetLongDouble(&offset));
737    else
738      error.SetErrorStringWithFormat("unsupported float byte size: %" PRIu64 "",
739                                     static_cast<uint64_t>(byte_size));
740  } break;
741  }
742
743  return error;
744}
745
746bool Scalar::SignExtend(uint32_t sign_bit_pos) {
747  const uint32_t max_bit_pos = GetByteSize() * 8;
748
749  if (sign_bit_pos < max_bit_pos) {
750    switch (m_type) {
751    case Scalar::e_void:
752    case Scalar::e_float:
753      return false;
754
755    case Scalar::e_int:
756      if (max_bit_pos == sign_bit_pos)
757        return true;
758      else if (sign_bit_pos < (max_bit_pos - 1)) {
759        llvm::APInt sign_bit = llvm::APInt::getSignMask(sign_bit_pos + 1);
760        llvm::APInt bitwize_and = m_integer & sign_bit;
761        if (bitwize_and.getBoolValue()) {
762          llvm::APInt mask =
763              ~(sign_bit) + llvm::APInt(m_integer.getBitWidth(), 1);
764          m_integer |= APSInt(std::move(mask), m_integer.isUnsigned());
765        }
766        return true;
767      }
768      break;
769    }
770  }
771  return false;
772}
773
774size_t Scalar::GetAsMemoryData(void *dst, size_t dst_len,
775                               lldb::ByteOrder dst_byte_order,
776                               Status &error) const {
777  // Get a data extractor that points to the native scalar data
778  DataExtractor data;
779  if (!GetData(data)) {
780    error.SetErrorString("invalid scalar value");
781    return 0;
782  }
783
784  const size_t src_len = data.GetByteSize();
785
786  // Prepare a memory buffer that contains some or all of the register value
787  const size_t bytes_copied =
788      data.CopyByteOrderedData(0,               // src offset
789                               src_len,         // src length
790                               dst,             // dst buffer
791                               dst_len,         // dst length
792                               dst_byte_order); // dst byte order
793  if (bytes_copied == 0)
794    error.SetErrorString("failed to copy data");
795
796  return bytes_copied;
797}
798
799bool Scalar::ExtractBitfield(uint32_t bit_size, uint32_t bit_offset) {
800  if (bit_size == 0)
801    return true;
802
803  switch (m_type) {
804  case Scalar::e_void:
805  case Scalar::e_float:
806    break;
807
808  case Scalar::e_int:
809    m_integer >>= bit_offset;
810    m_integer = m_integer.extOrTrunc(bit_size).extOrTrunc(8 * GetByteSize());
811    return true;
812  }
813  return false;
814}
815
816bool lldb_private::operator==(Scalar lhs, Scalar rhs) {
817  // If either entry is void then we can just compare the types
818  if (lhs.m_type == Scalar::e_void || rhs.m_type == Scalar::e_void)
819    return lhs.m_type == rhs.m_type;
820
821  llvm::APFloat::cmpResult result;
822  switch (Scalar::PromoteToMaxType(lhs, rhs)) {
823  case Scalar::e_void:
824    break;
825  case Scalar::e_int:
826    return lhs.m_integer == rhs.m_integer;
827  case Scalar::e_float:
828    result = lhs.m_float.compare(rhs.m_float);
829    if (result == llvm::APFloat::cmpEqual)
830      return true;
831  }
832  return false;
833}
834
835bool lldb_private::operator!=(const Scalar &lhs, const Scalar &rhs) {
836  return !(lhs == rhs);
837}
838
839bool lldb_private::operator<(Scalar lhs, Scalar rhs) {
840  if (lhs.m_type == Scalar::e_void || rhs.m_type == Scalar::e_void)
841    return false;
842
843  llvm::APFloat::cmpResult result;
844  switch (Scalar::PromoteToMaxType(lhs, rhs)) {
845  case Scalar::e_void:
846    break;
847  case Scalar::e_int:
848    return lhs.m_integer < rhs.m_integer;
849  case Scalar::e_float:
850    result = lhs.m_float.compare(rhs.m_float);
851    if (result == llvm::APFloat::cmpLessThan)
852      return true;
853  }
854  return false;
855}
856
857bool lldb_private::operator<=(const Scalar &lhs, const Scalar &rhs) {
858  return !(rhs < lhs);
859}
860
861bool lldb_private::operator>(const Scalar &lhs, const Scalar &rhs) {
862  return rhs < lhs;
863}
864
865bool lldb_private::operator>=(const Scalar &lhs, const Scalar &rhs) {
866  return !(lhs < rhs);
867}
868
869bool Scalar::ClearBit(uint32_t bit) {
870  switch (m_type) {
871  case e_void:
872    break;
873  case e_int:
874    m_integer.clearBit(bit);
875    return true;
876  case e_float:
877    break;
878  }
879  return false;
880}
881
882bool Scalar::SetBit(uint32_t bit) {
883  switch (m_type) {
884  case e_void:
885    break;
886  case e_int:
887    m_integer.setBit(bit);
888    return true;
889  case e_float:
890    break;
891  }
892  return false;
893}
894
895llvm::raw_ostream &lldb_private::operator<<(llvm::raw_ostream &os, const Scalar &scalar) {
896  StreamString s;
897  scalar.GetValue(s, /*show_type*/ true);
898  return os << s.GetString();
899}
900