1*ee754c2dSkamil //===-- ubsan_value.h -------------------------------------------*- C++ -*-===//
2*ee754c2dSkamil //
3*ee754c2dSkamil //                     The LLVM Compiler Infrastructure
4*ee754c2dSkamil //
5*ee754c2dSkamil // This file is distributed under the University of Illinois Open Source
6*ee754c2dSkamil // License. See LICENSE.TXT for details.
7*ee754c2dSkamil //
8*ee754c2dSkamil //===----------------------------------------------------------------------===//
9*ee754c2dSkamil //
10*ee754c2dSkamil // Representation of data which is passed from the compiler-generated calls into
11*ee754c2dSkamil // the ubsan runtime.
12*ee754c2dSkamil //
13*ee754c2dSkamil //===----------------------------------------------------------------------===//
14*ee754c2dSkamil #ifndef UBSAN_VALUE_H
15*ee754c2dSkamil #define UBSAN_VALUE_H
16*ee754c2dSkamil 
17*ee754c2dSkamil #include "sanitizer_common/sanitizer_atomic.h"
18*ee754c2dSkamil #include "sanitizer_common/sanitizer_common.h"
19*ee754c2dSkamil 
20*ee754c2dSkamil // FIXME: Move this out to a config header.
21*ee754c2dSkamil #if __SIZEOF_INT128__
22*ee754c2dSkamil __extension__ typedef __int128 s128;
23*ee754c2dSkamil __extension__ typedef unsigned __int128 u128;
24*ee754c2dSkamil #define HAVE_INT128_T 1
25*ee754c2dSkamil #else
26*ee754c2dSkamil #define HAVE_INT128_T 0
27*ee754c2dSkamil #endif
28*ee754c2dSkamil 
29*ee754c2dSkamil namespace __ubsan {
30*ee754c2dSkamil 
31*ee754c2dSkamil /// \brief Largest integer types we support.
32*ee754c2dSkamil #if HAVE_INT128_T
33*ee754c2dSkamil typedef s128 SIntMax;
34*ee754c2dSkamil typedef u128 UIntMax;
35*ee754c2dSkamil #else
36*ee754c2dSkamil typedef s64 SIntMax;
37*ee754c2dSkamil typedef u64 UIntMax;
38*ee754c2dSkamil #endif
39*ee754c2dSkamil 
40*ee754c2dSkamil /// \brief Largest floating-point type we support.
41*ee754c2dSkamil typedef long double FloatMax;
42*ee754c2dSkamil 
43*ee754c2dSkamil /// \brief A description of a source location. This corresponds to Clang's
44*ee754c2dSkamil /// \c PresumedLoc type.
45*ee754c2dSkamil class SourceLocation {
46*ee754c2dSkamil   const char *Filename;
47*ee754c2dSkamil   u32 Line;
48*ee754c2dSkamil   u32 Column;
49*ee754c2dSkamil 
50*ee754c2dSkamil public:
SourceLocation()51*ee754c2dSkamil   SourceLocation() : Filename(), Line(), Column() {}
SourceLocation(const char * Filename,unsigned Line,unsigned Column)52*ee754c2dSkamil   SourceLocation(const char *Filename, unsigned Line, unsigned Column)
53*ee754c2dSkamil     : Filename(Filename), Line(Line), Column(Column) {}
54*ee754c2dSkamil 
55*ee754c2dSkamil   /// \brief Determine whether the source location is known.
isInvalid()56*ee754c2dSkamil   bool isInvalid() const { return !Filename; }
57*ee754c2dSkamil 
58*ee754c2dSkamil   /// \brief Atomically acquire a copy, disabling original in-place.
59*ee754c2dSkamil   /// Exactly one call to acquire() returns a copy that isn't disabled.
acquire()60*ee754c2dSkamil   SourceLocation acquire() {
61*ee754c2dSkamil     u32 OldColumn = __sanitizer::atomic_exchange(
62*ee754c2dSkamil                         (__sanitizer::atomic_uint32_t *)&Column, ~u32(0),
63*ee754c2dSkamil                         __sanitizer::memory_order_relaxed);
64*ee754c2dSkamil     return SourceLocation(Filename, Line, OldColumn);
65*ee754c2dSkamil   }
66*ee754c2dSkamil 
67*ee754c2dSkamil   /// \brief Determine if this Location has been disabled.
68*ee754c2dSkamil   /// Disabled SourceLocations are invalid to use.
isDisabled()69*ee754c2dSkamil   bool isDisabled() {
70*ee754c2dSkamil     return Column == ~u32(0);
71*ee754c2dSkamil   }
72*ee754c2dSkamil 
73*ee754c2dSkamil   /// \brief Get the presumed filename for the source location.
getFilename()74*ee754c2dSkamil   const char *getFilename() const { return Filename; }
75*ee754c2dSkamil   /// \brief Get the presumed line number.
getLine()76*ee754c2dSkamil   unsigned getLine() const { return Line; }
77*ee754c2dSkamil   /// \brief Get the column within the presumed line.
getColumn()78*ee754c2dSkamil   unsigned getColumn() const { return Column; }
79*ee754c2dSkamil };
80*ee754c2dSkamil 
81*ee754c2dSkamil 
82*ee754c2dSkamil /// \brief A description of a type.
83*ee754c2dSkamil class TypeDescriptor {
84*ee754c2dSkamil   /// A value from the \c Kind enumeration, specifying what flavor of type we
85*ee754c2dSkamil   /// have.
86*ee754c2dSkamil   u16 TypeKind;
87*ee754c2dSkamil 
88*ee754c2dSkamil   /// A \c Type-specific value providing information which allows us to
89*ee754c2dSkamil   /// interpret the meaning of a ValueHandle of this type.
90*ee754c2dSkamil   u16 TypeInfo;
91*ee754c2dSkamil 
92*ee754c2dSkamil   /// The name of the type follows, in a format suitable for including in
93*ee754c2dSkamil   /// diagnostics.
94*ee754c2dSkamil   char TypeName[1];
95*ee754c2dSkamil 
96*ee754c2dSkamil public:
97*ee754c2dSkamil   enum Kind {
98*ee754c2dSkamil     /// An integer type. Lowest bit is 1 for a signed value, 0 for an unsigned
99*ee754c2dSkamil     /// value. Remaining bits are log_2(bit width). The value representation is
100*ee754c2dSkamil     /// the integer itself if it fits into a ValueHandle, and a pointer to the
101*ee754c2dSkamil     /// integer otherwise.
102*ee754c2dSkamil     TK_Integer = 0x0000,
103*ee754c2dSkamil     /// A floating-point type. Low 16 bits are bit width. The value
104*ee754c2dSkamil     /// representation is that of bitcasting the floating-point value to an
105*ee754c2dSkamil     /// integer type.
106*ee754c2dSkamil     TK_Float = 0x0001,
107*ee754c2dSkamil     /// Any other type. The value representation is unspecified.
108*ee754c2dSkamil     TK_Unknown = 0xffff
109*ee754c2dSkamil   };
110*ee754c2dSkamil 
getTypeName()111*ee754c2dSkamil   const char *getTypeName() const { return TypeName; }
112*ee754c2dSkamil 
getKind()113*ee754c2dSkamil   Kind getKind() const {
114*ee754c2dSkamil     return static_cast<Kind>(TypeKind);
115*ee754c2dSkamil   }
116*ee754c2dSkamil 
isIntegerTy()117*ee754c2dSkamil   bool isIntegerTy() const { return getKind() == TK_Integer; }
isSignedIntegerTy()118*ee754c2dSkamil   bool isSignedIntegerTy() const {
119*ee754c2dSkamil     return isIntegerTy() && (TypeInfo & 1);
120*ee754c2dSkamil   }
isUnsignedIntegerTy()121*ee754c2dSkamil   bool isUnsignedIntegerTy() const {
122*ee754c2dSkamil     return isIntegerTy() && !(TypeInfo & 1);
123*ee754c2dSkamil   }
getIntegerBitWidth()124*ee754c2dSkamil   unsigned getIntegerBitWidth() const {
125*ee754c2dSkamil     CHECK(isIntegerTy());
126*ee754c2dSkamil     return 1 << (TypeInfo >> 1);
127*ee754c2dSkamil   }
128*ee754c2dSkamil 
isFloatTy()129*ee754c2dSkamil   bool isFloatTy() const { return getKind() == TK_Float; }
getFloatBitWidth()130*ee754c2dSkamil   unsigned getFloatBitWidth() const {
131*ee754c2dSkamil     CHECK(isFloatTy());
132*ee754c2dSkamil     return TypeInfo;
133*ee754c2dSkamil   }
134*ee754c2dSkamil };
135*ee754c2dSkamil 
136*ee754c2dSkamil /// \brief An opaque handle to a value.
137*ee754c2dSkamil typedef uptr ValueHandle;
138*ee754c2dSkamil 
139*ee754c2dSkamil 
140*ee754c2dSkamil /// \brief Representation of an operand value provided by the instrumented code.
141*ee754c2dSkamil ///
142*ee754c2dSkamil /// This is a combination of a TypeDescriptor (which is emitted as constant data
143*ee754c2dSkamil /// as an operand to a handler function) and a ValueHandle (which is passed at
144*ee754c2dSkamil /// runtime when a check failure occurs).
145*ee754c2dSkamil class Value {
146*ee754c2dSkamil   /// The type of the value.
147*ee754c2dSkamil   const TypeDescriptor &Type;
148*ee754c2dSkamil   /// The encoded value itself.
149*ee754c2dSkamil   ValueHandle Val;
150*ee754c2dSkamil 
151*ee754c2dSkamil   /// Is \c Val a (zero-extended) integer?
isInlineInt()152*ee754c2dSkamil   bool isInlineInt() const {
153*ee754c2dSkamil     CHECK(getType().isIntegerTy());
154*ee754c2dSkamil     const unsigned InlineBits = sizeof(ValueHandle) * 8;
155*ee754c2dSkamil     const unsigned Bits = getType().getIntegerBitWidth();
156*ee754c2dSkamil     return Bits <= InlineBits;
157*ee754c2dSkamil   }
158*ee754c2dSkamil 
159*ee754c2dSkamil   /// Is \c Val a (zero-extended) integer representation of a float?
isInlineFloat()160*ee754c2dSkamil   bool isInlineFloat() const {
161*ee754c2dSkamil     CHECK(getType().isFloatTy());
162*ee754c2dSkamil     const unsigned InlineBits = sizeof(ValueHandle) * 8;
163*ee754c2dSkamil     const unsigned Bits = getType().getFloatBitWidth();
164*ee754c2dSkamil     return Bits <= InlineBits;
165*ee754c2dSkamil   }
166*ee754c2dSkamil 
167*ee754c2dSkamil public:
Value(const TypeDescriptor & Type,ValueHandle Val)168*ee754c2dSkamil   Value(const TypeDescriptor &Type, ValueHandle Val) : Type(Type), Val(Val) {}
169*ee754c2dSkamil 
getType()170*ee754c2dSkamil   const TypeDescriptor &getType() const { return Type; }
171*ee754c2dSkamil 
172*ee754c2dSkamil   /// \brief Get this value as a signed integer.
173*ee754c2dSkamil   SIntMax getSIntValue() const;
174*ee754c2dSkamil 
175*ee754c2dSkamil   /// \brief Get this value as an unsigned integer.
176*ee754c2dSkamil   UIntMax getUIntValue() const;
177*ee754c2dSkamil 
178*ee754c2dSkamil   /// \brief Decode this value, which must be a positive or unsigned integer.
179*ee754c2dSkamil   UIntMax getPositiveIntValue() const;
180*ee754c2dSkamil 
181*ee754c2dSkamil   /// Is this an integer with value -1?
isMinusOne()182*ee754c2dSkamil   bool isMinusOne() const {
183*ee754c2dSkamil     return getType().isSignedIntegerTy() && getSIntValue() == -1;
184*ee754c2dSkamil   }
185*ee754c2dSkamil 
186*ee754c2dSkamil   /// Is this a negative integer?
isNegative()187*ee754c2dSkamil   bool isNegative() const {
188*ee754c2dSkamil     return getType().isSignedIntegerTy() && getSIntValue() < 0;
189*ee754c2dSkamil   }
190*ee754c2dSkamil 
191*ee754c2dSkamil   /// \brief Get this value as a floating-point quantity.
192*ee754c2dSkamil   FloatMax getFloatValue() const;
193*ee754c2dSkamil };
194*ee754c2dSkamil 
195*ee754c2dSkamil } // namespace __ubsan
196*ee754c2dSkamil 
197*ee754c2dSkamil #endif // UBSAN_VALUE_H
198