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