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