1 //===-- ubsan_value.h -------------------------------------------*- C++ -*-===//
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
6 //===----------------------------------------------------------------------===//
8 // Representation of data which is passed from the compiler-generated calls into
11 //===----------------------------------------------------------------------===//
15 // For now, only support linux and darwin. Other platforms should be easy to
16 // add, and probably work as-is.
17 #if !defined(__linux__) && !defined(__APPLE__)
18 #error "UBSan not supported for this platform!"
21 #include "sanitizer_common/sanitizer_atomic.h"
22 #include "sanitizer_common/sanitizer_common.h"
24 // FIXME: Move this out to a config header.
26 __extension__
typedef __int128 s128
;
27 __extension__
typedef unsigned __int128 u128
;
28 #define HAVE_INT128_T 1
30 #define HAVE_INT128_T 0
36 /// \brief Largest integer types we support.
45 /// \brief Largest floating-point type we support.
46 typedef long double FloatMax
;
48 /// \brief A description of a source location. This corresponds to Clang's
49 /// \c PresumedLoc type.
50 class SourceLocation
{
56 SourceLocation() : Filename(), Line(), Column() {}
57 SourceLocation(const char *Filename
, unsigned Line
, unsigned Column
)
58 : Filename(Filename
), Line(Line
), Column(Column
) {}
60 /// \brief Determine whether the source location is known.
61 bool isInvalid() const { return !Filename
; }
63 /// \brief Atomically acquire a copy, disabling original in-place.
64 /// Exactly one call to acquire() returns a copy that isn't disabled.
65 SourceLocation
acquire() {
66 u32 OldColumn
= __sanitizer::atomic_exchange(
67 (__sanitizer::atomic_uint32_t
*)&Column
, ~u32(0),
68 __sanitizer::memory_order_relaxed
);
69 return SourceLocation(Filename
, Line
, OldColumn
);
72 /// \brief Determine if this Location has been disabled.
73 /// Disabled SourceLocations are invalid to use.
75 return Column
== ~u32(0);
78 /// \brief Get the presumed filename for the source location.
79 const char *getFilename() const { return Filename
; }
80 /// \brief Get the presumed line number.
81 unsigned getLine() const { return Line
; }
82 /// \brief Get the column within the presumed line.
83 unsigned getColumn() const { return Column
; }
87 /// \brief A description of a type.
88 class TypeDescriptor
{
89 /// A value from the \c Kind enumeration, specifying what flavor of type we
93 /// A \c Type-specific value providing information which allows us to
94 /// interpret the meaning of a ValueHandle of this type.
97 /// The name of the type follows, in a format suitable for including in
103 /// An integer type. Lowest bit is 1 for a signed value, 0 for an unsigned
104 /// value. Remaining bits are log_2(bit width). The value representation is
105 /// the integer itself if it fits into a ValueHandle, and a pointer to the
106 /// integer otherwise.
108 /// A floating-point type. Low 16 bits are bit width. The value
109 /// representation is that of bitcasting the floating-point value to an
112 /// Any other type. The value representation is unspecified.
116 const char *getTypeName() const { return TypeName
; }
118 Kind
getKind() const {
119 return static_cast<Kind
>(TypeKind
);
122 bool isIntegerTy() const { return getKind() == TK_Integer
; }
123 bool isSignedIntegerTy() const {
124 return isIntegerTy() && (TypeInfo
& 1);
126 bool isUnsignedIntegerTy() const {
127 return isIntegerTy() && !(TypeInfo
& 1);
129 unsigned getIntegerBitWidth() const {
130 CHECK(isIntegerTy());
131 return 1 << (TypeInfo
>> 1);
134 bool isFloatTy() const { return getKind() == TK_Float
; }
135 unsigned getFloatBitWidth() const {
141 /// \brief An opaque handle to a value.
142 typedef uptr ValueHandle
;
145 /// \brief Representation of an operand value provided by the instrumented code.
147 /// This is a combination of a TypeDescriptor (which is emitted as constant data
148 /// as an operand to a handler function) and a ValueHandle (which is passed at
149 /// runtime when a check failure occurs).
151 /// The type of the value.
152 const TypeDescriptor
&Type
;
153 /// The encoded value itself.
156 /// Is \c Val a (zero-extended) integer?
157 bool isInlineInt() const {
158 CHECK(getType().isIntegerTy());
159 const unsigned InlineBits
= sizeof(ValueHandle
) * 8;
160 const unsigned Bits
= getType().getIntegerBitWidth();
161 return Bits
<= InlineBits
;
164 /// Is \c Val a (zero-extended) integer representation of a float?
165 bool isInlineFloat() const {
166 CHECK(getType().isFloatTy());
167 const unsigned InlineBits
= sizeof(ValueHandle
) * 8;
168 const unsigned Bits
= getType().getFloatBitWidth();
169 return Bits
<= InlineBits
;
173 Value(const TypeDescriptor
&Type
, ValueHandle Val
) : Type(Type
), Val(Val
) {}
175 const TypeDescriptor
&getType() const { return Type
; }
177 /// \brief Get this value as a signed integer.
178 SIntMax
getSIntValue() const;
180 /// \brief Get this value as an unsigned integer.
181 UIntMax
getUIntValue() const;
183 /// \brief Decode this value, which must be a positive or unsigned integer.
184 UIntMax
getPositiveIntValue() const;
186 /// Is this an integer with value -1?
187 bool isMinusOne() const {
188 return getType().isSignedIntegerTy() && getSIntValue() == -1;
191 /// Is this a negative integer?
192 bool isNegative() const {
193 return getType().isSignedIntegerTy() && getSIntValue() < 0;
196 /// \brief Get this value as a floating-point quantity.
197 FloatMax
getFloatValue() const;
200 } // namespace __ubsan
202 #endif // UBSAN_VALUE_H