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