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