Home | History | Annotate | Line # | Download | only in ubsan
      1  1.1  kamil //===-- ubsan_value.cc ----------------------------------------------------===//
      2  1.1  kamil //
      3  1.1  kamil //                     The LLVM Compiler Infrastructure
      4  1.1  kamil //
      5  1.1  kamil // This file is distributed under the University of Illinois Open Source
      6  1.1  kamil // License. See LICENSE.TXT for details.
      7  1.1  kamil //
      8  1.1  kamil //===----------------------------------------------------------------------===//
      9  1.1  kamil //
     10  1.1  kamil // Representation of a runtime value, as marshaled from the generated code to
     11  1.1  kamil // the ubsan runtime.
     12  1.1  kamil //
     13  1.1  kamil //===----------------------------------------------------------------------===//
     14  1.1  kamil 
     15  1.1  kamil #include "ubsan_platform.h"
     16  1.1  kamil #if CAN_SANITIZE_UB
     17  1.1  kamil #include "ubsan_value.h"
     18  1.1  kamil #include "sanitizer_common/sanitizer_common.h"
     19  1.1  kamil #include "sanitizer_common/sanitizer_libc.h"
     20  1.1  kamil 
     21  1.1  kamil using namespace __ubsan;
     22  1.1  kamil 
     23  1.1  kamil SIntMax Value::getSIntValue() const {
     24  1.1  kamil   CHECK(getType().isSignedIntegerTy());
     25  1.1  kamil   if (isInlineInt()) {
     26  1.1  kamil     // Val was zero-extended to ValueHandle. Sign-extend from original width
     27  1.1  kamil     // to SIntMax.
     28  1.1  kamil     const unsigned ExtraBits =
     29  1.1  kamil       sizeof(SIntMax) * 8 - getType().getIntegerBitWidth();
     30  1.1  kamil     return SIntMax(Val) << ExtraBits >> ExtraBits;
     31  1.1  kamil   }
     32  1.1  kamil   if (getType().getIntegerBitWidth() == 64)
     33  1.1  kamil     return *reinterpret_cast<s64*>(Val);
     34  1.1  kamil #if HAVE_INT128_T
     35  1.1  kamil   if (getType().getIntegerBitWidth() == 128)
     36  1.1  kamil     return *reinterpret_cast<s128*>(Val);
     37  1.1  kamil #else
     38  1.1  kamil   if (getType().getIntegerBitWidth() == 128)
     39  1.1  kamil     UNREACHABLE("libclang_rt.ubsan was built without __int128 support");
     40  1.1  kamil #endif
     41  1.1  kamil   UNREACHABLE("unexpected bit width");
     42  1.1  kamil }
     43  1.1  kamil 
     44  1.1  kamil UIntMax Value::getUIntValue() const {
     45  1.1  kamil   CHECK(getType().isUnsignedIntegerTy());
     46  1.1  kamil   if (isInlineInt())
     47  1.1  kamil     return Val;
     48  1.1  kamil   if (getType().getIntegerBitWidth() == 64)
     49  1.1  kamil     return *reinterpret_cast<u64*>(Val);
     50  1.1  kamil #if HAVE_INT128_T
     51  1.1  kamil   if (getType().getIntegerBitWidth() == 128)
     52  1.1  kamil     return *reinterpret_cast<u128*>(Val);
     53  1.1  kamil #else
     54  1.1  kamil   if (getType().getIntegerBitWidth() == 128)
     55  1.1  kamil     UNREACHABLE("libclang_rt.ubsan was built without __int128 support");
     56  1.1  kamil #endif
     57  1.1  kamil   UNREACHABLE("unexpected bit width");
     58  1.1  kamil }
     59  1.1  kamil 
     60  1.1  kamil UIntMax Value::getPositiveIntValue() const {
     61  1.1  kamil   if (getType().isUnsignedIntegerTy())
     62  1.1  kamil     return getUIntValue();
     63  1.1  kamil   SIntMax Val = getSIntValue();
     64  1.1  kamil   CHECK(Val >= 0);
     65  1.1  kamil   return Val;
     66  1.1  kamil }
     67  1.1  kamil 
     68  1.1  kamil /// Get the floating-point value of this object, extended to a long double.
     69  1.1  kamil /// These are always passed by address (our calling convention doesn't allow
     70  1.1  kamil /// them to be passed in floating-point registers, so this has little cost).
     71  1.1  kamil FloatMax Value::getFloatValue() const {
     72  1.1  kamil   CHECK(getType().isFloatTy());
     73  1.1  kamil   if (isInlineFloat()) {
     74  1.1  kamil     switch (getType().getFloatBitWidth()) {
     75  1.1  kamil #if 0
     76  1.1  kamil       // FIXME: OpenCL / NEON 'half' type. LLVM can't lower the conversion
     77  1.1  kamil       //        from '__fp16' to 'long double'.
     78  1.1  kamil       case 16: {
     79  1.1  kamil         __fp16 Value;
     80  1.1  kamil         internal_memcpy(&Value, &Val, 4);
     81  1.1  kamil         return Value;
     82  1.1  kamil       }
     83  1.1  kamil #endif
     84  1.1  kamil       case 32: {
     85  1.1  kamil         float Value;
     86  1.1  kamil #if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
     87  1.1  kamil        // For big endian the float value is in the last 4 bytes.
     88  1.1  kamil        // On some targets we may only have 4 bytes so we count backwards from
     89  1.1  kamil        // the end of Val to account for both the 32-bit and 64-bit cases.
     90  1.1  kamil        internal_memcpy(&Value, ((const char*)(&Val + 1)) - 4, 4);
     91  1.1  kamil #else
     92  1.1  kamil        internal_memcpy(&Value, &Val, 4);
     93  1.1  kamil #endif
     94  1.1  kamil         return Value;
     95  1.1  kamil       }
     96  1.1  kamil       case 64: {
     97  1.1  kamil         double Value;
     98  1.1  kamil         internal_memcpy(&Value, &Val, 8);
     99  1.1  kamil         return Value;
    100  1.1  kamil       }
    101  1.1  kamil     }
    102  1.1  kamil   } else {
    103  1.1  kamil     switch (getType().getFloatBitWidth()) {
    104  1.1  kamil     case 64: return *reinterpret_cast<double*>(Val);
    105  1.1  kamil     case 80: return *reinterpret_cast<long double*>(Val);
    106  1.1  kamil     case 96: return *reinterpret_cast<long double*>(Val);
    107  1.1  kamil     case 128: return *reinterpret_cast<long double*>(Val);
    108  1.1  kamil     }
    109  1.1  kamil   }
    110  1.1  kamil   UNREACHABLE("unexpected floating point bit width");
    111  1.1  kamil }
    112  1.1  kamil 
    113  1.1  kamil #endif  // CAN_SANITIZE_UB
    114