blob: 79dc4c8e82714467056d08223d700b81f8155e5c [file] [log] [blame]
Richard Smith6ebe4512012-10-09 19:34:32 +00001//===-- ubsan_value.cc ----------------------------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Representation of a runtime value, as marshaled from the generated code to
11// the ubsan runtime.
12//
13//===----------------------------------------------------------------------===//
14
Pirama Arumuga Nainar7c915052015-04-08 08:58:29 -070015#include "ubsan_platform.h"
16#if CAN_SANITIZE_UB
Richard Smith6ebe4512012-10-09 19:34:32 +000017#include "ubsan_value.h"
Richard Smithec7962d2013-03-22 00:47:05 +000018#include "sanitizer_common/sanitizer_common.h"
19#include "sanitizer_common/sanitizer_libc.h"
Richard Smith6ebe4512012-10-09 19:34:32 +000020
21using namespace __ubsan;
22
23SIntMax Value::getSIntValue() const {
24 CHECK(getType().isSignedIntegerTy());
25 if (isInlineInt()) {
26 // Val was zero-extended to ValueHandle. Sign-extend from original width
27 // to SIntMax.
28 const unsigned ExtraBits =
29 sizeof(SIntMax) * 8 - getType().getIntegerBitWidth();
30 return SIntMax(Val) << ExtraBits >> ExtraBits;
31 }
32 if (getType().getIntegerBitWidth() == 64)
33 return *reinterpret_cast<s64*>(Val);
Chandler Carruthba3fde62012-10-13 02:30:10 +000034#if HAVE_INT128_T
Richard Smith6ebe4512012-10-09 19:34:32 +000035 if (getType().getIntegerBitWidth() == 128)
36 return *reinterpret_cast<s128*>(Val);
Richard Smith0aad69a2012-10-14 23:53:37 +000037#else
38 if (getType().getIntegerBitWidth() == 128)
39 UNREACHABLE("libclang_rt.ubsan was built without __int128 support");
Richard Smith6ebe4512012-10-09 19:34:32 +000040#endif
41 UNREACHABLE("unexpected bit width");
42}
43
44UIntMax Value::getUIntValue() const {
45 CHECK(getType().isUnsignedIntegerTy());
46 if (isInlineInt())
47 return Val;
48 if (getType().getIntegerBitWidth() == 64)
49 return *reinterpret_cast<u64*>(Val);
Chandler Carruthba3fde62012-10-13 02:30:10 +000050#if HAVE_INT128_T
Richard Smith6ebe4512012-10-09 19:34:32 +000051 if (getType().getIntegerBitWidth() == 128)
52 return *reinterpret_cast<u128*>(Val);
Richard Smith0aad69a2012-10-14 23:53:37 +000053#else
54 if (getType().getIntegerBitWidth() == 128)
55 UNREACHABLE("libclang_rt.ubsan was built without __int128 support");
Richard Smith6ebe4512012-10-09 19:34:32 +000056#endif
57 UNREACHABLE("unexpected bit width");
58}
59
60UIntMax Value::getPositiveIntValue() const {
61 if (getType().isUnsignedIntegerTy())
62 return getUIntValue();
63 SIntMax Val = getSIntValue();
64 CHECK(Val >= 0);
65 return Val;
66}
67
68/// Get the floating-point value of this object, extended to a long double.
69/// These are always passed by address (our calling convention doesn't allow
70/// them to be passed in floating-point registers, so this has little cost).
Richard Smith58561702012-10-12 22:57:15 +000071FloatMax Value::getFloatValue() const {
Richard Smith6ebe4512012-10-09 19:34:32 +000072 CHECK(getType().isFloatTy());
Richard Smithec7962d2013-03-22 00:47:05 +000073 if (isInlineFloat()) {
74 switch (getType().getFloatBitWidth()) {
Richard Smith6ebe4512012-10-09 19:34:32 +000075#if 0
Richard Smithec7962d2013-03-22 00:47:05 +000076 // FIXME: OpenCL / NEON 'half' type. LLVM can't lower the conversion
77 // from '__fp16' to 'long double'.
78 case 16: {
79 __fp16 Value;
80 internal_memcpy(&Value, &Val, 4);
81 return Value;
82 }
Richard Smith6ebe4512012-10-09 19:34:32 +000083#endif
Richard Smithec7962d2013-03-22 00:47:05 +000084 case 32: {
85 float Value;
Pirama Arumuga Nainar259f7062015-05-06 11:49:53 -070086#if defined(__BIG_ENDIAN__)
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -080087 // For big endian the float value is in the last 4 bytes.
88 // On some targets we may only have 4 bytes so we count backwards from
89 // the end of Val to account for both the 32-bit and 64-bit cases.
90 internal_memcpy(&Value, ((const char*)(&Val + 1)) - 4, 4);
Pirama Arumuga Nainar259f7062015-05-06 11:49:53 -070091#else
92 internal_memcpy(&Value, &Val, 4);
93#endif
Richard Smithec7962d2013-03-22 00:47:05 +000094 return Value;
95 }
96 case 64: {
97 double Value;
98 internal_memcpy(&Value, &Val, 8);
99 return Value;
100 }
101 }
102 } else {
103 switch (getType().getFloatBitWidth()) {
104 case 64: return *reinterpret_cast<double*>(Val);
105 case 80: return *reinterpret_cast<long double*>(Val);
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700106 case 96: return *reinterpret_cast<long double*>(Val);
Richard Smithec7962d2013-03-22 00:47:05 +0000107 case 128: return *reinterpret_cast<long double*>(Val);
108 }
Richard Smith6ebe4512012-10-09 19:34:32 +0000109 }
110 UNREACHABLE("unexpected floating point bit width");
111}
Pirama Arumuga Nainar7c915052015-04-08 08:58:29 -0700112
113#endif // CAN_SANITIZE_UB