#include "ubsan_value.h"
using namespace __ubsan;
SIntMax Value::getSIntValue() const {
CHECK(getType().isSignedIntegerTy());
if (isInlineInt()) {
const unsigned ExtraBits =
sizeof(SIntMax) * 8 - getType().getIntegerBitWidth();
return SIntMax(Val) << ExtraBits >> ExtraBits;
}
if (getType().getIntegerBitWidth() == 64)
return *reinterpret_cast<s64*>(Val);
#if HAVE_INT128_T
if (getType().getIntegerBitWidth() == 128)
return *reinterpret_cast<s128*>(Val);
#else
if (getType().getIntegerBitWidth() == 128)
UNREACHABLE("libclang_rt.ubsan was built without __int128 support");
#endif
UNREACHABLE("unexpected bit width");
}
UIntMax Value::getUIntValue() const {
CHECK(getType().isUnsignedIntegerTy());
if (isInlineInt())
return Val;
if (getType().getIntegerBitWidth() == 64)
return *reinterpret_cast<u64*>(Val);
#if HAVE_INT128_T
if (getType().getIntegerBitWidth() == 128)
return *reinterpret_cast<u128*>(Val);
#else
if (getType().getIntegerBitWidth() == 128)
UNREACHABLE("libclang_rt.ubsan was built without __int128 support");
#endif
UNREACHABLE("unexpected bit width");
}
UIntMax Value::getPositiveIntValue() const {
if (getType().isUnsignedIntegerTy())
return getUIntValue();
SIntMax Val = getSIntValue();
CHECK(Val >= 0);
return Val;
}
FloatMax Value::getFloatValue() const {
CHECK(getType().isFloatTy());
switch (getType().getFloatBitWidth()) {
#if 0
case 16: return *reinterpret_cast<__fp16*>(Val);
#endif
case 32: return *reinterpret_cast<float*>(Val);
case 64: return *reinterpret_cast<double*>(Val);
case 80: return *reinterpret_cast<long double*>(Val);
case 128: return *reinterpret_cast<long double*>(Val);
}
UNREACHABLE("unexpected floating point bit width");
}