ubsan_value.cc revision 58561700a4abad310911a24a867da49a14fae91e
1//===-- 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);
30#ifdef HAVE_INT128_T
31  if (getType().getIntegerBitWidth() == 128)
32    return *reinterpret_cast<s128*>(Val);
33#endif
34  UNREACHABLE("unexpected bit width");
35}
36
37UIntMax Value::getUIntValue() const {
38  CHECK(getType().isUnsignedIntegerTy());
39  if (isInlineInt())
40    return Val;
41  if (getType().getIntegerBitWidth() == 64)
42    return *reinterpret_cast<u64*>(Val);
43#ifdef HAVE_INT128_T
44  if (getType().getIntegerBitWidth() == 128)
45    return *reinterpret_cast<u128*>(Val);
46#endif
47  UNREACHABLE("unexpected bit width");
48}
49
50UIntMax Value::getPositiveIntValue() const {
51  if (getType().isUnsignedIntegerTy())
52    return getUIntValue();
53  SIntMax Val = getSIntValue();
54  CHECK(Val >= 0);
55  return Val;
56}
57
58/// Get the floating-point value of this object, extended to a long double.
59/// These are always passed by address (our calling convention doesn't allow
60/// them to be passed in floating-point registers, so this has little cost).
61FloatMax Value::getFloatValue() const {
62  CHECK(getType().isFloatTy());
63  switch (getType().getFloatBitWidth()) {
64#if 0
65  // FIXME: OpenCL / NEON 'half' type. LLVM can't lower the conversion
66  //        from this to 'long double'.
67  case 16: return *reinterpret_cast<__fp16*>(Val);
68#endif
69  case 32: return *reinterpret_cast<float*>(Val);
70  case 64: return *reinterpret_cast<double*>(Val);
71  case 80: return *reinterpret_cast<long double*>(Val);
72  case 128: return *reinterpret_cast<long double*>(Val);
73  }
74  UNREACHABLE("unexpected floating point bit width");
75}
76