Home | History | Annotate | Download | only in ubsan
      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 
     17 using namespace __ubsan;
     18 
     19 SIntMax 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 #if HAVE_INT128_T
     31   if (getType().getIntegerBitWidth() == 128)
     32     return *reinterpret_cast<s128*>(Val);
     33 #else
     34   if (getType().getIntegerBitWidth() == 128)
     35     UNREACHABLE("libclang_rt.ubsan was built without __int128 support");
     36 #endif
     37   UNREACHABLE("unexpected bit width");
     38 }
     39 
     40 UIntMax Value::getUIntValue() const {
     41   CHECK(getType().isUnsignedIntegerTy());
     42   if (isInlineInt())
     43     return Val;
     44   if (getType().getIntegerBitWidth() == 64)
     45     return *reinterpret_cast<u64*>(Val);
     46 #if HAVE_INT128_T
     47   if (getType().getIntegerBitWidth() == 128)
     48     return *reinterpret_cast<u128*>(Val);
     49 #else
     50   if (getType().getIntegerBitWidth() == 128)
     51     UNREACHABLE("libclang_rt.ubsan was built without __int128 support");
     52 #endif
     53   UNREACHABLE("unexpected bit width");
     54 }
     55 
     56 UIntMax 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).
     67 FloatMax Value::getFloatValue() const {
     68   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 }
     82