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