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