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 | |
24 | using namespace lldb; |
25 | using namespace lldb_private; |
26 | |
27 | using llvm::APFloat; |
28 | using llvm::APInt; |
29 | using llvm::APSInt; |
30 | |
31 | Scalar::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(semantics: m_float.getSemantics()); |
39 | } |
40 | llvm_unreachable("Unhandled category!" ); |
41 | } |
42 | |
43 | Scalar::PromotionKey Scalar::GetFloatPromoKey(const llvm::fltSemantics &sem) { |
44 | static const llvm::fltSemantics *const order[] = { |
45 | &APFloat::IEEEsingle(), &APFloat::IEEEdouble(), |
46 | &APFloat::x87DoubleExtended()}; |
47 | for (const auto &entry : llvm::enumerate(First: 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. |
56 | Scalar::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(bits: b.m_integer.getBitWidth(), sign: b.m_integer.isSigned()); |
63 | break; |
64 | case e_float: |
65 | a.FloatPromote(semantics: 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 | |
85 | bool Scalar::(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>(args&: byte_size, args: 0); |
92 | GetBytes(storage: 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(data_sp: std::move(buffer_up), offset, length: byte_size); |
110 | data.SetByteOrder(endian::InlHostByteOrder()); |
111 | return true; |
112 | } |
113 | |
114 | void Scalar::GetBytes(llvm::MutableArrayRef<uint8_t> storage) const { |
115 | assert(storage.size() >= GetByteSize()); |
116 | |
117 | const auto &store = [&](const llvm::APInt &val) { |
118 | StoreIntToMemory(IntVal: val, Dst: storage.data(), StoreBytes: (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 | |
132 | size_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 | |
144 | bool 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 | |
156 | void Scalar::GetValue(Stream &s, bool show_type) const { |
157 | if (show_type) |
158 | s.Printf(format: "(%s) " , GetTypeAsCString()); |
159 | |
160 | switch (m_type) { |
161 | case e_void: |
162 | break; |
163 | case e_int: |
164 | s.PutCString(cstr: llvm::toString(I: m_integer, Radix: 10)); |
165 | break; |
166 | case e_float: |
167 | llvm::SmallString<24> string; |
168 | m_float.toString(Str&: string); |
169 | s.PutCString(cstr: string); |
170 | break; |
171 | } |
172 | } |
173 | |
174 | void Scalar::TruncOrExtendTo(uint16_t bits, bool sign) { |
175 | m_integer.setIsSigned(sign); |
176 | m_integer = m_integer.extOrTrunc(width: bits); |
177 | } |
178 | |
179 | bool 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(width: bits); |
188 | m_integer.setIsSigned(sign); |
189 | return true; |
190 | } |
191 | return false; |
192 | } |
193 | |
194 | bool 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(Input: m_integer, IsSigned: m_integer.isSigned(), |
202 | RM: llvm::APFloat::rmNearestTiesToEven); |
203 | success = true; |
204 | break; |
205 | case e_float: |
206 | if (GetFloatPromoKey(sem: semantics) < GetFloatPromoKey(sem: m_float.getSemantics())) |
207 | break; |
208 | bool ignore; |
209 | success = true; |
210 | m_float.convert(ToSemantics: semantics, RM: llvm::APFloat::rmNearestTiesToEven, losesInfo: &ignore); |
211 | } |
212 | |
213 | if (success) |
214 | m_type = e_float; |
215 | return success; |
216 | } |
217 | |
218 | const 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 | |
230 | bool 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 | |
242 | bool 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 | |
260 | bool 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 | |
278 | static 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&: result, RM: llvm::APFloat::rmTowardZero, IsExact: &isExact); |
283 | return std::move(result); |
284 | } |
285 | |
286 | template <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(width: 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 | |
303 | signed char Scalar::SChar(signed char fail_value) const { |
304 | return GetAs<signed char>(fail_value); |
305 | } |
306 | |
307 | unsigned char Scalar::UChar(unsigned char fail_value) const { |
308 | return GetAs<unsigned char>(fail_value); |
309 | } |
310 | |
311 | short Scalar::SShort(short fail_value) const { |
312 | return GetAs<short>(fail_value); |
313 | } |
314 | |
315 | unsigned short Scalar::UShort(unsigned short fail_value) const { |
316 | return GetAs<unsigned short>(fail_value); |
317 | } |
318 | |
319 | int Scalar::SInt(int fail_value) const { return GetAs<int>(fail_value); } |
320 | |
321 | unsigned int Scalar::UInt(unsigned int fail_value) const { |
322 | return GetAs<unsigned int>(fail_value); |
323 | } |
324 | |
325 | long Scalar::SLong(long fail_value) const { return GetAs<long>(fail_value); } |
326 | |
327 | unsigned long Scalar::ULong(unsigned long fail_value) const { |
328 | return GetAs<unsigned long>(fail_value); |
329 | } |
330 | |
331 | long long Scalar::SLongLong(long long fail_value) const { |
332 | return GetAs<long long>(fail_value); |
333 | } |
334 | |
335 | unsigned long long Scalar::ULongLong(unsigned long long fail_value) const { |
336 | return GetAs<unsigned long long>(fail_value); |
337 | } |
338 | |
339 | llvm::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(f: m_float, bits: 128, /*is_unsigned=*/false); |
347 | } |
348 | return fail_value; |
349 | } |
350 | |
351 | llvm::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(f: m_float, bits: 128, /*is_unsigned=*/true); |
359 | } |
360 | return fail_value; |
361 | } |
362 | |
363 | float 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(APIVal: m_integer); |
370 | return llvm::APIntOps::RoundAPIntToFloat(APIVal: m_integer); |
371 | |
372 | case e_float: { |
373 | APFloat result = m_float; |
374 | bool losesInfo; |
375 | result.convert(ToSemantics: APFloat::IEEEsingle(), RM: APFloat::rmNearestTiesToEven, |
376 | losesInfo: &losesInfo); |
377 | return result.convertToFloat(); |
378 | } |
379 | } |
380 | return fail_value; |
381 | } |
382 | |
383 | double 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(APIVal: m_integer); |
390 | return llvm::APIntOps::RoundAPIntToDouble(APIVal: m_integer); |
391 | |
392 | case e_float: { |
393 | APFloat result = m_float; |
394 | bool losesInfo; |
395 | result.convert(ToSemantics: APFloat::IEEEdouble(), RM: APFloat::rmNearestTiesToEven, |
396 | losesInfo: &losesInfo); |
397 | return result.convertToDouble(); |
398 | } |
399 | } |
400 | return fail_value; |
401 | } |
402 | |
403 | long double Scalar::LongDouble(long double fail_value) const { |
404 | /// No way to get more precision at the moment. |
405 | return static_cast<long double>(Double(fail_value)); |
406 | } |
407 | |
408 | Scalar &Scalar::operator+=(Scalar rhs) { |
409 | Scalar copy = *this; |
410 | if ((m_type = PromoteToMaxType(lhs&: 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 | |
426 | Scalar &Scalar::operator<<=(const Scalar &rhs) { |
427 | if (m_type == e_int && rhs.m_type == e_int) |
428 | static_cast<APInt &>(m_integer) <<= rhs.m_integer; |
429 | else |
430 | m_type = e_void; |
431 | return *this; |
432 | } |
433 | |
434 | bool Scalar::ShiftRightLogical(const Scalar &rhs) { |
435 | if (m_type == e_int && rhs.m_type == e_int) { |
436 | m_integer = m_integer.lshr(ShiftAmt: rhs.m_integer); |
437 | return true; |
438 | } |
439 | m_type = e_void; |
440 | return false; |
441 | } |
442 | |
443 | Scalar &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(ShiftAmt: rhs.m_integer); |
458 | break; |
459 | } |
460 | break; |
461 | } |
462 | return *this; |
463 | } |
464 | |
465 | Scalar &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 | |
473 | bool 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 | |
490 | bool 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 | |
504 | bool Scalar::OnesComplement() { |
505 | if (m_type == e_int) { |
506 | m_integer = ~m_integer; |
507 | return true; |
508 | } |
509 | |
510 | return false; |
511 | } |
512 | |
513 | const Scalar lldb_private::operator+(const Scalar &lhs, const Scalar &rhs) { |
514 | Scalar result = lhs; |
515 | result += rhs; |
516 | return result; |
517 | } |
518 | |
519 | const 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 | |
536 | const 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 | |
557 | const 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 | |
574 | const 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 | |
585 | const 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 | |
596 | const 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 | |
608 | const 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 | |
619 | const Scalar lldb_private::operator<<(const Scalar &lhs, const Scalar &rhs) { |
620 | Scalar result = lhs; |
621 | result <<= rhs; |
622 | return result; |
623 | } |
624 | |
625 | const Scalar lldb_private::operator>>(const Scalar &lhs, const Scalar &rhs) { |
626 | Scalar result = lhs; |
627 | result >>= rhs; |
628 | return result; |
629 | } |
630 | |
631 | Status 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(Prefix: "-" ); |
648 | APInt integer; |
649 | if (str.getAsInteger(Radix: 0, Result&: integer)) { |
650 | error.SetErrorStringWithFormatv( |
651 | format: "'{0}' is not a valid integer string value" , args&: value_str); |
652 | break; |
653 | } |
654 | bool fits; |
655 | if (is_signed) { |
656 | integer = integer.zext(width: integer.getBitWidth() + 1); |
657 | if (is_negative) |
658 | integer.negate(); |
659 | fits = integer.isSignedIntN(N: byte_size * 8); |
660 | } else |
661 | fits = integer.isIntN(N: byte_size * 8); |
662 | if (!fits) { |
663 | error.SetErrorStringWithFormatv( |
664 | format: "value {0} is too large to fit in a {1} byte integer value" , |
665 | args&: value_str, args&: byte_size); |
666 | break; |
667 | } |
668 | m_type = e_int; |
669 | m_integer = |
670 | APSInt(std::move(integer), !is_signed).extOrTrunc(width: 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 | |
702 | Status Scalar::(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(numBits: 8 * byte_size), encoding == eEncodingUint); |
719 | if (data.GetByteOrder() == endian::InlHostByteOrder()) { |
720 | llvm::LoadIntFromMemory(IntVal&: m_integer, Src: data.GetDataStart(), LoadBytes: byte_size); |
721 | } else { |
722 | std::vector<uint8_t> buffer(byte_size); |
723 | std::copy_n(first: data.GetDataStart(), n: byte_size, result: buffer.rbegin()); |
724 | llvm::LoadIntFromMemory(IntVal&: m_integer, Src: buffer.data(), LoadBytes: 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_ptr: &offset)); |
733 | else if (byte_size == sizeof(double)) |
734 | operator=(data.GetDouble(offset_ptr: &offset)); |
735 | else if (byte_size == sizeof(long double)) |
736 | operator=(data.GetLongDouble(offset_ptr: &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 | |
746 | bool 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(BitWidth: 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 | |
774 | size_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(src_offset: 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 | |
799 | bool Scalar::(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(width: bit_size).extOrTrunc(width: 8 * GetByteSize()); |
811 | return true; |
812 | } |
813 | return false; |
814 | } |
815 | |
816 | llvm::APFloat Scalar::CreateAPFloatFromAPSInt(lldb::BasicType basic_type) { |
817 | switch (basic_type) { |
818 | case lldb::eBasicTypeFloat: |
819 | return llvm::APFloat( |
820 | m_integer.isSigned() |
821 | ? llvm::APIntOps::RoundSignedAPIntToFloat(APIVal: m_integer) |
822 | : llvm::APIntOps::RoundAPIntToFloat(APIVal: m_integer)); |
823 | case lldb::eBasicTypeDouble: |
824 | // No way to get more precision at the moment. |
825 | case lldb::eBasicTypeLongDouble: |
826 | return llvm::APFloat( |
827 | m_integer.isSigned() |
828 | ? llvm::APIntOps::RoundSignedAPIntToDouble(APIVal: m_integer) |
829 | : llvm::APIntOps::RoundAPIntToDouble(APIVal: m_integer)); |
830 | default: |
831 | const llvm::fltSemantics &sem = APFloat::IEEEsingle(); |
832 | return llvm::APFloat::getNaN(Sem: sem); |
833 | } |
834 | } |
835 | |
836 | llvm::APFloat Scalar::CreateAPFloatFromAPFloat(lldb::BasicType basic_type) { |
837 | switch (basic_type) { |
838 | case lldb::eBasicTypeFloat: { |
839 | bool loses_info; |
840 | m_float.convert(ToSemantics: llvm::APFloat::IEEEsingle(), |
841 | RM: llvm::APFloat::rmNearestTiesToEven, losesInfo: &loses_info); |
842 | return m_float; |
843 | } |
844 | case lldb::eBasicTypeDouble: |
845 | // No way to get more precision at the moment. |
846 | case lldb::eBasicTypeLongDouble: { |
847 | bool loses_info; |
848 | m_float.convert(ToSemantics: llvm::APFloat::IEEEdouble(), |
849 | RM: llvm::APFloat::rmNearestTiesToEven, losesInfo: &loses_info); |
850 | return m_float; |
851 | } |
852 | default: |
853 | const llvm::fltSemantics &sem = APFloat::IEEEsingle(); |
854 | return llvm::APFloat::getNaN(Sem: sem); |
855 | } |
856 | } |
857 | |
858 | bool lldb_private::operator==(Scalar lhs, Scalar rhs) { |
859 | // If either entry is void then we can just compare the types |
860 | if (lhs.m_type == Scalar::e_void || rhs.m_type == Scalar::e_void) |
861 | return lhs.m_type == rhs.m_type; |
862 | |
863 | llvm::APFloat::cmpResult result; |
864 | switch (Scalar::PromoteToMaxType(lhs, rhs)) { |
865 | case Scalar::e_void: |
866 | break; |
867 | case Scalar::e_int: |
868 | return lhs.m_integer == rhs.m_integer; |
869 | case Scalar::e_float: |
870 | result = lhs.m_float.compare(RHS: rhs.m_float); |
871 | if (result == llvm::APFloat::cmpEqual) |
872 | return true; |
873 | } |
874 | return false; |
875 | } |
876 | |
877 | bool lldb_private::operator!=(const Scalar &lhs, const Scalar &rhs) { |
878 | return !(lhs == rhs); |
879 | } |
880 | |
881 | bool lldb_private::operator<(Scalar lhs, Scalar rhs) { |
882 | if (lhs.m_type == Scalar::e_void || rhs.m_type == Scalar::e_void) |
883 | return false; |
884 | |
885 | llvm::APFloat::cmpResult result; |
886 | switch (Scalar::PromoteToMaxType(lhs, rhs)) { |
887 | case Scalar::e_void: |
888 | break; |
889 | case Scalar::e_int: |
890 | return lhs.m_integer < rhs.m_integer; |
891 | case Scalar::e_float: |
892 | result = lhs.m_float.compare(RHS: rhs.m_float); |
893 | if (result == llvm::APFloat::cmpLessThan) |
894 | return true; |
895 | } |
896 | return false; |
897 | } |
898 | |
899 | bool lldb_private::operator<=(const Scalar &lhs, const Scalar &rhs) { |
900 | return !(rhs < lhs); |
901 | } |
902 | |
903 | bool lldb_private::operator>(const Scalar &lhs, const Scalar &rhs) { |
904 | return rhs < lhs; |
905 | } |
906 | |
907 | bool lldb_private::operator>=(const Scalar &lhs, const Scalar &rhs) { |
908 | return !(lhs < rhs); |
909 | } |
910 | |
911 | bool Scalar::ClearBit(uint32_t bit) { |
912 | switch (m_type) { |
913 | case e_void: |
914 | break; |
915 | case e_int: |
916 | m_integer.clearBit(BitPosition: bit); |
917 | return true; |
918 | case e_float: |
919 | break; |
920 | } |
921 | return false; |
922 | } |
923 | |
924 | bool Scalar::SetBit(uint32_t bit) { |
925 | switch (m_type) { |
926 | case e_void: |
927 | break; |
928 | case e_int: |
929 | m_integer.setBit(bit); |
930 | return true; |
931 | case e_float: |
932 | break; |
933 | } |
934 | return false; |
935 | } |
936 | |
937 | llvm::raw_ostream &lldb_private::operator<<(llvm::raw_ostream &os, const Scalar &scalar) { |
938 | StreamString s; |
939 | scalar.GetValue(s, /*show_type*/ true); |
940 | return os << s.GetString(); |
941 | } |
942 | |