xref: /aosp_15_r20/external/compiler-rt/lib/ubsan/ubsan_value.h (revision 7c3d14c8b49c529e04be81a3ce6f5cc23712e4c6)
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