xref: /freebsd/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/TypeIndex.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===- TypeIndex.h ----------------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLVM_DEBUGINFO_CODEVIEW_TYPEINDEX_H
10 #define LLVM_DEBUGINFO_CODEVIEW_TYPEINDEX_H
11 
12 #include "llvm/ADT/DenseMapInfo.h"
13 #include "llvm/Support/Compiler.h"
14 #include "llvm/Support/Endian.h"
15 #include <cassert>
16 #include <cinttypes>
17 
18 namespace llvm {
19 
20 class ScopedPrinter;
21 class StringRef;
22 
23 namespace codeview {
24 
25 class TypeCollection;
26 
27 enum class SimpleTypeKind : uint32_t {
28   None = 0x0000,          // uncharacterized type (no type)
29   Void = 0x0003,          // void
30   NotTranslated = 0x0007, // type not translated by cvpack
31   HResult = 0x0008,       // OLE/COM HRESULT
32 
33   SignedCharacter = 0x0010,   // 8 bit signed
34   UnsignedCharacter = 0x0020, // 8 bit unsigned
35   NarrowCharacter = 0x0070,   // really a char
36   WideCharacter = 0x0071,     // wide char
37   Character16 = 0x007a,       // char16_t
38   Character32 = 0x007b,       // char32_t
39   Character8 = 0x007c,        // char8_t
40 
41   SByte = 0x0068,       // 8 bit signed int
42   Byte = 0x0069,        // 8 bit unsigned int
43   Int16Short = 0x0011,  // 16 bit signed
44   UInt16Short = 0x0021, // 16 bit unsigned
45   Int16 = 0x0072,       // 16 bit signed int
46   UInt16 = 0x0073,      // 16 bit unsigned int
47   Int32Long = 0x0012,   // 32 bit signed
48   UInt32Long = 0x0022,  // 32 bit unsigned
49   Int32 = 0x0074,       // 32 bit signed int
50   UInt32 = 0x0075,      // 32 bit unsigned int
51   Int64Quad = 0x0013,   // 64 bit signed
52   UInt64Quad = 0x0023,  // 64 bit unsigned
53   Int64 = 0x0076,       // 64 bit signed int
54   UInt64 = 0x0077,      // 64 bit unsigned int
55   Int128Oct = 0x0014,   // 128 bit signed int
56   UInt128Oct = 0x0024,  // 128 bit unsigned int
57   Int128 = 0x0078,      // 128 bit signed int
58   UInt128 = 0x0079,     // 128 bit unsigned int
59 
60   Float16 = 0x0046,                 // 16 bit real
61   Float32 = 0x0040,                 // 32 bit real
62   Float32PartialPrecision = 0x0045, // 32 bit PP real
63   Float48 = 0x0044,                 // 48 bit real
64   Float64 = 0x0041,                 // 64 bit real
65   Float80 = 0x0042,                 // 80 bit real
66   Float128 = 0x0043,                // 128 bit real
67 
68   Complex16 = 0x0056,                 // 16 bit complex
69   Complex32 = 0x0050,                 // 32 bit complex
70   Complex32PartialPrecision = 0x0055, // 32 bit PP complex
71   Complex48 = 0x0054,                 // 48 bit complex
72   Complex64 = 0x0051,                 // 64 bit complex
73   Complex80 = 0x0052,                 // 80 bit complex
74   Complex128 = 0x0053,                // 128 bit complex
75 
76   Boolean8 = 0x0030,   // 8 bit boolean
77   Boolean16 = 0x0031,  // 16 bit boolean
78   Boolean32 = 0x0032,  // 32 bit boolean
79   Boolean64 = 0x0033,  // 64 bit boolean
80   Boolean128 = 0x0034, // 128 bit boolean
81 };
82 
83 enum class SimpleTypeMode : uint32_t {
84   Direct = 0x00000000,        // Not a pointer
85   NearPointer = 0x00000100,   // Near pointer
86   FarPointer = 0x00000200,    // Far pointer
87   HugePointer = 0x00000300,   // Huge pointer
88   NearPointer32 = 0x00000400, // 32 bit near pointer
89   FarPointer32 = 0x00000500,  // 32 bit far pointer
90   NearPointer64 = 0x00000600, // 64 bit near pointer
91   NearPointer128 = 0x00000700 // 128 bit near pointer
92 };
93 
94 /// A 32-bit type reference. Types are indexed by their order of appearance in
95 /// .debug$T plus 0x1000. Type indices less than 0x1000 are "simple" types,
96 /// composed of a SimpleTypeMode byte followed by a SimpleTypeKind byte.
97 class TypeIndex {
98 public:
99   static const uint32_t FirstNonSimpleIndex = 0x1000;
100   static const uint32_t SimpleKindMask = 0x000000ff;
101   static const uint32_t SimpleModeMask = 0x00000700;
102   static const uint32_t DecoratedItemIdMask = 0x80000000;
103 
104 public:
TypeIndex()105   TypeIndex() : Index(static_cast<uint32_t>(SimpleTypeKind::None)) {}
TypeIndex(uint32_t Index)106   explicit TypeIndex(uint32_t Index) : Index(Index) {}
TypeIndex(SimpleTypeKind Kind)107   explicit TypeIndex(SimpleTypeKind Kind)
108       : Index(static_cast<uint32_t>(Kind)) {}
TypeIndex(SimpleTypeKind Kind,SimpleTypeMode Mode)109   TypeIndex(SimpleTypeKind Kind, SimpleTypeMode Mode)
110       : Index(static_cast<uint32_t>(Kind) | static_cast<uint32_t>(Mode)) {}
111 
getIndex()112   uint32_t getIndex() const { return Index; }
setIndex(uint32_t I)113   void setIndex(uint32_t I) { Index = I; }
isSimple()114   bool isSimple() const { return Index < FirstNonSimpleIndex; }
isDecoratedItemId()115   bool isDecoratedItemId() const { return !!(Index & DecoratedItemIdMask); }
116 
isNoneType()117   bool isNoneType() const { return *this == None(); }
118 
toArrayIndex()119   uint32_t toArrayIndex() const {
120     assert(!isSimple());
121     return (getIndex() & ~DecoratedItemIdMask) - FirstNonSimpleIndex;
122   }
123 
fromArrayIndex(uint32_t Index)124   static TypeIndex fromArrayIndex(uint32_t Index) {
125     return TypeIndex(Index + FirstNonSimpleIndex);
126   }
127 
fromDecoratedArrayIndex(bool IsItem,uint32_t Index)128   static TypeIndex fromDecoratedArrayIndex(bool IsItem, uint32_t Index) {
129     return TypeIndex((Index + FirstNonSimpleIndex) |
130                      (IsItem ? DecoratedItemIdMask : 0));
131   }
132 
removeDecoration()133   TypeIndex removeDecoration() {
134     return TypeIndex(Index & ~DecoratedItemIdMask);
135   }
136 
getSimpleKind()137   SimpleTypeKind getSimpleKind() const {
138     assert(isSimple());
139     return static_cast<SimpleTypeKind>(Index & SimpleKindMask);
140   }
141 
getSimpleMode()142   SimpleTypeMode getSimpleMode() const {
143     assert(isSimple());
144     return static_cast<SimpleTypeMode>(Index & SimpleModeMask);
145   }
146 
makeDirect()147   TypeIndex makeDirect() const { return TypeIndex{getSimpleKind()}; }
148 
None()149   static TypeIndex None() { return TypeIndex(SimpleTypeKind::None); }
Void()150   static TypeIndex Void() { return TypeIndex(SimpleTypeKind::Void); }
VoidPointer32()151   static TypeIndex VoidPointer32() {
152     return TypeIndex(SimpleTypeKind::Void, SimpleTypeMode::NearPointer32);
153   }
VoidPointer64()154   static TypeIndex VoidPointer64() {
155     return TypeIndex(SimpleTypeKind::Void, SimpleTypeMode::NearPointer64);
156   }
157 
NullptrT()158   static TypeIndex NullptrT() {
159     // std::nullptr_t uses the pointer mode that doesn't indicate bit-width,
160     // presumably because std::nullptr_t is intended to be compatible with any
161     // pointer type.
162     return TypeIndex(SimpleTypeKind::Void, SimpleTypeMode::NearPointer);
163   }
164 
SignedCharacter()165   static TypeIndex SignedCharacter() {
166     return TypeIndex(SimpleTypeKind::SignedCharacter);
167   }
UnsignedCharacter()168   static TypeIndex UnsignedCharacter() {
169     return TypeIndex(SimpleTypeKind::UnsignedCharacter);
170   }
NarrowCharacter()171   static TypeIndex NarrowCharacter() {
172     return TypeIndex(SimpleTypeKind::NarrowCharacter);
173   }
WideCharacter()174   static TypeIndex WideCharacter() {
175     return TypeIndex(SimpleTypeKind::WideCharacter);
176   }
Int16Short()177   static TypeIndex Int16Short() {
178     return TypeIndex(SimpleTypeKind::Int16Short);
179   }
UInt16Short()180   static TypeIndex UInt16Short() {
181     return TypeIndex(SimpleTypeKind::UInt16Short);
182   }
Int32()183   static TypeIndex Int32() { return TypeIndex(SimpleTypeKind::Int32); }
UInt32()184   static TypeIndex UInt32() { return TypeIndex(SimpleTypeKind::UInt32); }
Int32Long()185   static TypeIndex Int32Long() { return TypeIndex(SimpleTypeKind::Int32Long); }
UInt32Long()186   static TypeIndex UInt32Long() {
187     return TypeIndex(SimpleTypeKind::UInt32Long);
188   }
Int64()189   static TypeIndex Int64() { return TypeIndex(SimpleTypeKind::Int64); }
UInt64()190   static TypeIndex UInt64() { return TypeIndex(SimpleTypeKind::UInt64); }
Int64Quad()191   static TypeIndex Int64Quad() { return TypeIndex(SimpleTypeKind::Int64Quad); }
UInt64Quad()192   static TypeIndex UInt64Quad() {
193     return TypeIndex(SimpleTypeKind::UInt64Quad);
194   }
195 
Float32()196   static TypeIndex Float32() { return TypeIndex(SimpleTypeKind::Float32); }
Float64()197   static TypeIndex Float64() { return TypeIndex(SimpleTypeKind::Float64); }
198 
199   TypeIndex &operator+=(unsigned N) {
200     Index += N;
201     return *this;
202   }
203 
204   TypeIndex &operator++() {
205     Index += 1;
206     return *this;
207   }
208 
209   TypeIndex operator++(int) {
210     TypeIndex Copy = *this;
211     operator++();
212     return Copy;
213   }
214 
215   TypeIndex &operator-=(unsigned N) {
216     assert(Index >= N);
217     Index -= N;
218     return *this;
219   }
220 
221   TypeIndex &operator--() {
222     Index -= 1;
223     return *this;
224   }
225 
226   TypeIndex operator--(int) {
227     TypeIndex Copy = *this;
228     operator--();
229     return Copy;
230   }
231 
232   friend inline bool operator==(const TypeIndex &A, const TypeIndex &B) {
233     return A.getIndex() == B.getIndex();
234   }
235 
236   friend inline bool operator!=(const TypeIndex &A, const TypeIndex &B) {
237     return A.getIndex() != B.getIndex();
238   }
239 
240   friend inline bool operator<(const TypeIndex &A, const TypeIndex &B) {
241     return A.getIndex() < B.getIndex();
242   }
243 
244   friend inline bool operator<=(const TypeIndex &A, const TypeIndex &B) {
245     return A.getIndex() <= B.getIndex();
246   }
247 
248   friend inline bool operator>(const TypeIndex &A, const TypeIndex &B) {
249     return A.getIndex() > B.getIndex();
250   }
251 
252   friend inline bool operator>=(const TypeIndex &A, const TypeIndex &B) {
253     return A.getIndex() >= B.getIndex();
254   }
255 
256   friend inline TypeIndex operator+(const TypeIndex &A, uint32_t N) {
257     TypeIndex Result(A);
258     Result += N;
259     return Result;
260   }
261 
262   friend inline TypeIndex operator-(const TypeIndex &A, uint32_t N) {
263     assert(A.getIndex() >= N);
264     TypeIndex Result(A);
265     Result -= N;
266     return Result;
267   }
268 
269   friend inline uint32_t operator-(const TypeIndex &A, const TypeIndex &B) {
270     assert(A >= B);
271     return A.toArrayIndex() - B.toArrayIndex();
272   }
273 
274   LLVM_ABI static StringRef simpleTypeName(TypeIndex TI);
275 
276 private:
277   support::ulittle32_t Index;
278 };
279 
280 // Used for pseudo-indexing an array of type records.  An array of such records
281 // sorted by TypeIndex can allow log(N) lookups even though such a type record
282 // stream does not provide random access.
283 struct TypeIndexOffset {
284   TypeIndex Type;
285   support::ulittle32_t Offset;
286 };
287 
288 LLVM_ABI void printTypeIndex(ScopedPrinter &Printer, StringRef FieldName,
289                              TypeIndex TI, TypeCollection &Types);
290 }
291 
292 template <> struct DenseMapInfo<codeview::TypeIndex> {
293   static inline codeview::TypeIndex getEmptyKey() {
294     return codeview::TypeIndex{DenseMapInfo<uint32_t>::getEmptyKey()};
295   }
296   static inline codeview::TypeIndex getTombstoneKey() {
297     return codeview::TypeIndex{DenseMapInfo<uint32_t>::getTombstoneKey()};
298   }
299   static unsigned getHashValue(const codeview::TypeIndex &TI) {
300     return DenseMapInfo<uint32_t>::getHashValue(TI.getIndex());
301   }
302   static bool isEqual(const codeview::TypeIndex &LHS,
303                       const codeview::TypeIndex &RHS) {
304     return LHS == RHS;
305   }
306 };
307 
308 } // namespace llvm
309 
310 #endif
311