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