Page MenuHomePhabricator

No OneTemporary

File Metadata

Created
Fri, Jan 24, 4:01 PM
Index: compiler-rt/trunk/lib/ubsan/ubsan_value.cc
===================================================================
--- compiler-rt/trunk/lib/ubsan/ubsan_value.cc (revision 177688)
+++ compiler-rt/trunk/lib/ubsan/ubsan_value.cc (revision 177689)
@@ -1,81 +1,101 @@
//===-- ubsan_value.cc ----------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Representation of a runtime value, as marshaled from the generated code to
// the ubsan runtime.
//
//===----------------------------------------------------------------------===//
#include "ubsan_value.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_libc.h"
using namespace __ubsan;
SIntMax Value::getSIntValue() const {
CHECK(getType().isSignedIntegerTy());
if (isInlineInt()) {
// Val was zero-extended to ValueHandle. Sign-extend from original width
// to SIntMax.
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;
}
/// Get the floating-point value of this object, extended to a long double.
/// These are always passed by address (our calling convention doesn't allow
/// them to be passed in floating-point registers, so this has little cost).
FloatMax Value::getFloatValue() const {
CHECK(getType().isFloatTy());
- switch (getType().getFloatBitWidth()) {
+ if (isInlineFloat()) {
+ switch (getType().getFloatBitWidth()) {
#if 0
- // FIXME: OpenCL / NEON 'half' type. LLVM can't lower the conversion
- // from this to 'long double'.
- case 16: return *reinterpret_cast<__fp16*>(Val);
+ // FIXME: OpenCL / NEON 'half' type. LLVM can't lower the conversion
+ // from '__fp16' to 'long double'.
+ case 16: {
+ __fp16 Value;
+ internal_memcpy(&Value, &Val, 4);
+ return Value;
+ }
#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);
+ case 32: {
+ float Value;
+ internal_memcpy(&Value, &Val, 4);
+ return Value;
+ }
+ case 64: {
+ double Value;
+ internal_memcpy(&Value, &Val, 8);
+ return Value;
+ }
+ }
+ } else {
+ switch (getType().getFloatBitWidth()) {
+ 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");
}
Index: compiler-rt/trunk/lib/ubsan/ubsan_value.h
===================================================================
--- compiler-rt/trunk/lib/ubsan/ubsan_value.h (revision 177688)
+++ compiler-rt/trunk/lib/ubsan/ubsan_value.h (revision 177689)
@@ -1,195 +1,204 @@
//===-- ubsan_value.h -------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Representation of data which is passed from the compiler-generated calls into
// the ubsan runtime.
//
//===----------------------------------------------------------------------===//
#ifndef UBSAN_VALUE_H
#define UBSAN_VALUE_H
// For now, only support linux and darwin. Other platforms should be easy to
// add, and probably work as-is.
#if !defined(__linux__) && !defined(__APPLE__)
#error "UBSan not supported for this platform!"
#endif
#include "sanitizer_common/sanitizer_atomic.h"
#include "sanitizer_common/sanitizer_common.h"
// FIXME: Move this out to a config header.
#if __SIZEOF_INT128__
typedef __int128 s128;
typedef unsigned __int128 u128;
#define HAVE_INT128_T 1
#else
#define HAVE_INT128_T 0
#endif
namespace __ubsan {
/// \brief Largest integer types we support.
#if HAVE_INT128_T
typedef s128 SIntMax;
typedef u128 UIntMax;
#else
typedef s64 SIntMax;
typedef u64 UIntMax;
#endif
/// \brief Largest floating-point type we support.
typedef long double FloatMax;
/// \brief A description of a source location. This corresponds to Clang's
/// \c PresumedLoc type.
class SourceLocation {
const char *Filename;
u32 Line;
u32 Column;
public:
SourceLocation() : Filename(), Line(), Column() {}
SourceLocation(const char *Filename, unsigned Line, unsigned Column)
: Filename(Filename), Line(Line), Column(Column) {}
/// \brief Determine whether the source location is known.
bool isInvalid() const { return !Filename; }
/// \brief Atomically acquire a copy, disabling original in-place.
/// Exactly one call to acquire() returns a copy that isn't disabled.
SourceLocation acquire() {
u32 OldColumn = __sanitizer::atomic_exchange(
(__sanitizer::atomic_uint32_t *)&Column, ~u32(0),
__sanitizer::memory_order_relaxed);
return SourceLocation(Filename, Line, OldColumn);
}
/// \brief Determine if this Location has been disabled.
/// Disabled SourceLocations are invalid to use.
bool isDisabled() {
return Column == ~u32(0);
}
/// \brief Get the presumed filename for the source location.
const char *getFilename() const { return Filename; }
/// \brief Get the presumed line number.
unsigned getLine() const { return Line; }
/// \brief Get the column within the presumed line.
unsigned getColumn() const { return Column; }
};
/// \brief A description of a type.
class TypeDescriptor {
/// A value from the \c Kind enumeration, specifying what flavor of type we
/// have.
u16 TypeKind;
/// A \c Type-specific value providing information which allows us to
/// interpret the meaning of a ValueHandle of this type.
u16 TypeInfo;
/// The name of the type follows, in a format suitable for including in
/// diagnostics.
char TypeName[1];
public:
enum Kind {
/// An integer type. Lowest bit is 1 for a signed value, 0 for an unsigned
/// value. Remaining bits are log_2(bit width). The value representation is
/// the integer itself if it fits into a ValueHandle, and a pointer to the
/// integer otherwise.
TK_Integer = 0x0000,
/// A floating-point type. Low 16 bits are bit width. The value
- /// representation is a pointer to the floating-point value.
+ /// representation is that of bitcasting the floating-point value to an
+ /// integer type.
TK_Float = 0x0001,
/// Any other type. The value representation is unspecified.
TK_Unknown = 0xffff
};
const char *getTypeName() const { return TypeName; }
Kind getKind() const {
return static_cast<Kind>(TypeKind);
}
bool isIntegerTy() const { return getKind() == TK_Integer; }
bool isSignedIntegerTy() const {
return isIntegerTy() && (TypeInfo & 1);
}
bool isUnsignedIntegerTy() const {
return isIntegerTy() && !(TypeInfo & 1);
}
unsigned getIntegerBitWidth() const {
CHECK(isIntegerTy());
return 1 << (TypeInfo >> 1);
}
bool isFloatTy() const { return getKind() == TK_Float; }
unsigned getFloatBitWidth() const {
CHECK(isFloatTy());
return TypeInfo;
}
};
/// \brief An opaque handle to a value.
typedef uptr ValueHandle;
/// \brief Representation of an operand value provided by the instrumented code.
///
/// This is a combination of a TypeDescriptor (which is emitted as constant data
/// as an operand to a handler function) and a ValueHandle (which is passed at
/// runtime when a check failure occurs).
class Value {
/// The type of the value.
const TypeDescriptor &Type;
/// The encoded value itself.
ValueHandle Val;
/// Is \c Val a (zero-extended) integer?
bool isInlineInt() const {
CHECK(getType().isIntegerTy());
const unsigned InlineBits = sizeof(ValueHandle) * 8;
const unsigned Bits = getType().getIntegerBitWidth();
return Bits <= InlineBits;
}
+ /// Is \c Val a (zero-extended) integer representation of a float?
+ bool isInlineFloat() const {
+ CHECK(getType().isFloatTy());
+ const unsigned InlineBits = sizeof(ValueHandle) * 8;
+ const unsigned Bits = getType().getFloatBitWidth();
+ return Bits <= InlineBits;
+ }
+
public:
Value(const TypeDescriptor &Type, ValueHandle Val) : Type(Type), Val(Val) {}
const TypeDescriptor &getType() const { return Type; }
/// \brief Get this value as a signed integer.
SIntMax getSIntValue() const;
/// \brief Get this value as an unsigned integer.
UIntMax getUIntValue() const;
/// \brief Decode this value, which must be a positive or unsigned integer.
UIntMax getPositiveIntValue() const;
/// Is this an integer with value -1?
bool isMinusOne() const {
return getType().isSignedIntegerTy() && getSIntValue() == -1;
}
/// Is this a negative integer?
bool isNegative() const {
return getType().isSignedIntegerTy() && getSIntValue() < 0;
}
/// \brief Get this value as a floating-point quantity.
FloatMax getFloatValue() const;
};
} // namespace __ubsan
#endif // UBSAN_VALUE_H

Event Timeline