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