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