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#include "sanitizer_common/sanitizer_common.h"
17#include "sanitizer_common/sanitizer_libc.h"
18
19using namespace __ubsan;
20
21SIntMax Value::getSIntValue() const {
22  CHECK(getType().isSignedIntegerTy());
23  if (isInlineInt()) {
24    // Val was zero-extended to ValueHandle. Sign-extend from original width
25    // to SIntMax.
26    const unsigned ExtraBits =
27      sizeof(SIntMax) * 8 - getType().getIntegerBitWidth();
28    return SIntMax(Val) << ExtraBits >> ExtraBits;
29  }
30  if (getType().getIntegerBitWidth() == 64)
31    return *reinterpret_cast<s64*>(Val);
32#if HAVE_INT128_T
33  if (getType().getIntegerBitWidth() == 128)
34    return *reinterpret_cast<s128*>(Val);
35#else
36  if (getType().getIntegerBitWidth() == 128)
37    UNREACHABLE("libclang_rt.ubsan was built without __int128 support");
38#endif
39  UNREACHABLE("unexpected bit width");
40}
41
42UIntMax Value::getUIntValue() const {
43  CHECK(getType().isUnsignedIntegerTy());
44  if (isInlineInt())
45    return Val;
46  if (getType().getIntegerBitWidth() == 64)
47    return *reinterpret_cast<u64*>(Val);
48#if HAVE_INT128_T
49  if (getType().getIntegerBitWidth() == 128)
50    return *reinterpret_cast<u128*>(Val);
51#else
52  if (getType().getIntegerBitWidth() == 128)
53    UNREACHABLE("libclang_rt.ubsan was built without __int128 support");
54#endif
55  UNREACHABLE("unexpected bit width");
56}
57
58UIntMax Value::getPositiveIntValue() const {
59  if (getType().isUnsignedIntegerTy())
60    return getUIntValue();
61  SIntMax Val = getSIntValue();
62  CHECK(Val >= 0);
63  return Val;
64}
65
66/// Get the floating-point value of this object, extended to a long double.
67/// These are always passed by address (our calling convention doesn't allow
68/// them to be passed in floating-point registers, so this has little cost).
69FloatMax Value::getFloatValue() const {
70  CHECK(getType().isFloatTy());
71  if (isInlineFloat()) {
72    switch (getType().getFloatBitWidth()) {
73#if 0
74      // FIXME: OpenCL / NEON 'half' type. LLVM can't lower the conversion
75      //        from '__fp16' to 'long double'.
76      case 16: {
77        __fp16 Value;
78        internal_memcpy(&Value, &Val, 4);
79        return Value;
80      }
81#endif
82      case 32: {
83        float Value;
84        internal_memcpy(&Value, &Val, 4);
85        return Value;
86      }
87      case 64: {
88        double Value;
89        internal_memcpy(&Value, &Val, 8);
90        return Value;
91      }
92    }
93  } else {
94    switch (getType().getFloatBitWidth()) {
95    case 64: return *reinterpret_cast<double*>(Val);
96    case 80: return *reinterpret_cast<long double*>(Val);
97    case 96: return *reinterpret_cast<long double*>(Val);
98    case 128: return *reinterpret_cast<long double*>(Val);
99    }
100  }
101  UNREACHABLE("unexpected floating point bit width");
102}
103