blob: f17c58989db9c0bb65e63a7676d9512c5154b776 [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
15#include "ubsan_value.h"
16
17using namespace __ubsan;
18
19SIntMax Value::getSIntValue() const {
20 CHECK(getType().isSignedIntegerTy());
21 if (isInlineInt()) {
22 // Val was zero-extended to ValueHandle. Sign-extend from original width
23 // to SIntMax.
24 const unsigned ExtraBits =
25 sizeof(SIntMax) * 8 - getType().getIntegerBitWidth();
26 return SIntMax(Val) << ExtraBits >> ExtraBits;
27 }
28 if (getType().getIntegerBitWidth() == 64)
29 return *reinterpret_cast<s64*>(Val);
Chandler Carruthba3fde62012-10-13 02:30:10 +000030#if HAVE_INT128_T
Richard Smith6ebe4512012-10-09 19:34:32 +000031 if (getType().getIntegerBitWidth() == 128)
32 return *reinterpret_cast<s128*>(Val);
Richard Smith0aad69a2012-10-14 23:53:37 +000033#else
34 if (getType().getIntegerBitWidth() == 128)
35 UNREACHABLE("libclang_rt.ubsan was built without __int128 support");
Richard Smith6ebe4512012-10-09 19:34:32 +000036#endif
37 UNREACHABLE("unexpected bit width");
38}
39
40UIntMax Value::getUIntValue() const {
41 CHECK(getType().isUnsignedIntegerTy());
42 if (isInlineInt())
43 return Val;
44 if (getType().getIntegerBitWidth() == 64)
45 return *reinterpret_cast<u64*>(Val);
Chandler Carruthba3fde62012-10-13 02:30:10 +000046#if HAVE_INT128_T
Richard Smith6ebe4512012-10-09 19:34:32 +000047 if (getType().getIntegerBitWidth() == 128)
48 return *reinterpret_cast<u128*>(Val);
Richard Smith0aad69a2012-10-14 23:53:37 +000049#else
50 if (getType().getIntegerBitWidth() == 128)
51 UNREACHABLE("libclang_rt.ubsan was built without __int128 support");
Richard Smith6ebe4512012-10-09 19:34:32 +000052#endif
53 UNREACHABLE("unexpected bit width");
54}
55
56UIntMax Value::getPositiveIntValue() const {
57 if (getType().isUnsignedIntegerTy())
58 return getUIntValue();
59 SIntMax Val = getSIntValue();
60 CHECK(Val >= 0);
61 return Val;
62}
63
64/// Get the floating-point value of this object, extended to a long double.
65/// These are always passed by address (our calling convention doesn't allow
66/// them to be passed in floating-point registers, so this has little cost).
Richard Smith58561702012-10-12 22:57:15 +000067FloatMax Value::getFloatValue() const {
Richard Smith6ebe4512012-10-09 19:34:32 +000068 CHECK(getType().isFloatTy());
69 switch (getType().getFloatBitWidth()) {
70#if 0
71 // FIXME: OpenCL / NEON 'half' type. LLVM can't lower the conversion
72 // from this to 'long double'.
73 case 16: return *reinterpret_cast<__fp16*>(Val);
74#endif
75 case 32: return *reinterpret_cast<float*>(Val);
76 case 64: return *reinterpret_cast<double*>(Val);
77 case 80: return *reinterpret_cast<long double*>(Val);
78 case 128: return *reinterpret_cast<long double*>(Val);
79 }
80 UNREACHABLE("unexpected floating point bit width");
81}