1353944Sdim//===-- ubsan_value.cpp ---------------------------------------------------===// 2353944Sdim// 3353944Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353944Sdim// See https://llvm.org/LICENSE.txt for license information. 5353944Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6353944Sdim// 7353944Sdim//===----------------------------------------------------------------------===// 8353944Sdim// 9353944Sdim// Representation of a runtime value, as marshaled from the generated code to 10353944Sdim// the ubsan runtime. 11353944Sdim// 12353944Sdim//===----------------------------------------------------------------------===// 13353944Sdim 14353944Sdim#include "ubsan_platform.h" 15353944Sdim#if CAN_SANITIZE_UB 16353944Sdim#include "ubsan_value.h" 17353944Sdim#include "sanitizer_common/sanitizer_common.h" 18353944Sdim#include "sanitizer_common/sanitizer_libc.h" 19353944Sdim 20353944Sdimusing namespace __ubsan; 21353944Sdim 22353944SdimSIntMax Value::getSIntValue() const { 23353944Sdim CHECK(getType().isSignedIntegerTy()); 24353944Sdim if (isInlineInt()) { 25353944Sdim // Val was zero-extended to ValueHandle. Sign-extend from original width 26353944Sdim // to SIntMax. 27353944Sdim const unsigned ExtraBits = 28353944Sdim sizeof(SIntMax) * 8 - getType().getIntegerBitWidth(); 29353944Sdim return SIntMax(Val) << ExtraBits >> ExtraBits; 30353944Sdim } 31353944Sdim if (getType().getIntegerBitWidth() == 64) 32353944Sdim return *reinterpret_cast<s64*>(Val); 33353944Sdim#if HAVE_INT128_T 34353944Sdim if (getType().getIntegerBitWidth() == 128) 35353944Sdim return *reinterpret_cast<s128*>(Val); 36353944Sdim#else 37353944Sdim if (getType().getIntegerBitWidth() == 128) 38353944Sdim UNREACHABLE("libclang_rt.ubsan was built without __int128 support"); 39353944Sdim#endif 40353944Sdim UNREACHABLE("unexpected bit width"); 41353944Sdim} 42353944Sdim 43353944SdimUIntMax Value::getUIntValue() const { 44353944Sdim CHECK(getType().isUnsignedIntegerTy()); 45353944Sdim if (isInlineInt()) 46353944Sdim return Val; 47353944Sdim if (getType().getIntegerBitWidth() == 64) 48353944Sdim return *reinterpret_cast<u64*>(Val); 49353944Sdim#if HAVE_INT128_T 50353944Sdim if (getType().getIntegerBitWidth() == 128) 51353944Sdim return *reinterpret_cast<u128*>(Val); 52353944Sdim#else 53353944Sdim if (getType().getIntegerBitWidth() == 128) 54353944Sdim UNREACHABLE("libclang_rt.ubsan was built without __int128 support"); 55353944Sdim#endif 56353944Sdim UNREACHABLE("unexpected bit width"); 57353944Sdim} 58353944Sdim 59353944SdimUIntMax Value::getPositiveIntValue() const { 60353944Sdim if (getType().isUnsignedIntegerTy()) 61353944Sdim return getUIntValue(); 62353944Sdim SIntMax Val = getSIntValue(); 63353944Sdim CHECK(Val >= 0); 64353944Sdim return Val; 65353944Sdim} 66353944Sdim 67353944Sdim/// Get the floating-point value of this object, extended to a long double. 68353944Sdim/// These are always passed by address (our calling convention doesn't allow 69353944Sdim/// them to be passed in floating-point registers, so this has little cost). 70353944SdimFloatMax Value::getFloatValue() const { 71353944Sdim CHECK(getType().isFloatTy()); 72353944Sdim if (isInlineFloat()) { 73353944Sdim switch (getType().getFloatBitWidth()) { 74353944Sdim#if 0 75353944Sdim // FIXME: OpenCL / NEON 'half' type. LLVM can't lower the conversion 76353944Sdim // from '__fp16' to 'long double'. 77353944Sdim case 16: { 78353944Sdim __fp16 Value; 79353944Sdim internal_memcpy(&Value, &Val, 4); 80353944Sdim return Value; 81353944Sdim } 82353944Sdim#endif 83353944Sdim case 32: { 84353944Sdim float Value; 85353944Sdim#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 86353944Sdim // For big endian the float value is in the last 4 bytes. 87353944Sdim // On some targets we may only have 4 bytes so we count backwards from 88353944Sdim // the end of Val to account for both the 32-bit and 64-bit cases. 89353944Sdim internal_memcpy(&Value, ((const char*)(&Val + 1)) - 4, 4); 90353944Sdim#else 91353944Sdim internal_memcpy(&Value, &Val, 4); 92353944Sdim#endif 93353944Sdim return Value; 94353944Sdim } 95353944Sdim case 64: { 96353944Sdim double Value; 97353944Sdim internal_memcpy(&Value, &Val, 8); 98353944Sdim return Value; 99353944Sdim } 100353944Sdim } 101353944Sdim } else { 102353944Sdim switch (getType().getFloatBitWidth()) { 103353944Sdim case 64: return *reinterpret_cast<double*>(Val); 104353944Sdim case 80: return *reinterpret_cast<long double*>(Val); 105353944Sdim case 96: return *reinterpret_cast<long double*>(Val); 106353944Sdim case 128: return *reinterpret_cast<long double*>(Val); 107353944Sdim } 108353944Sdim } 109353944Sdim UNREACHABLE("unexpected floating point bit width"); 110353944Sdim} 111353944Sdim 112353944Sdim#endif // CAN_SANITIZE_UB 113