10b57cec5SDimitry Andric //===- TypeIndex.h ----------------------------------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #ifndef LLVM_DEBUGINFO_CODEVIEW_TYPEINDEX_H
100b57cec5SDimitry Andric #define LLVM_DEBUGINFO_CODEVIEW_TYPEINDEX_H
110b57cec5SDimitry Andric 
120b57cec5SDimitry Andric #include "llvm/ADT/DenseMapInfo.h"
130b57cec5SDimitry Andric #include "llvm/Support/Endian.h"
140b57cec5SDimitry Andric #include <cassert>
150b57cec5SDimitry Andric #include <cinttypes>
160b57cec5SDimitry Andric 
170b57cec5SDimitry Andric namespace llvm {
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric class ScopedPrinter;
20349cc55cSDimitry Andric class StringRef;
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric namespace codeview {
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric class TypeCollection;
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric enum class SimpleTypeKind : uint32_t {
270b57cec5SDimitry Andric   None = 0x0000,          // uncharacterized type (no type)
280b57cec5SDimitry Andric   Void = 0x0003,          // void
290b57cec5SDimitry Andric   NotTranslated = 0x0007, // type not translated by cvpack
300b57cec5SDimitry Andric   HResult = 0x0008,       // OLE/COM HRESULT
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric   SignedCharacter = 0x0010,   // 8 bit signed
330b57cec5SDimitry Andric   UnsignedCharacter = 0x0020, // 8 bit unsigned
340b57cec5SDimitry Andric   NarrowCharacter = 0x0070,   // really a char
350b57cec5SDimitry Andric   WideCharacter = 0x0071,     // wide char
360b57cec5SDimitry Andric   Character16 = 0x007a,       // char16_t
370b57cec5SDimitry Andric   Character32 = 0x007b,       // char32_t
3881ad6265SDimitry Andric   Character8 = 0x007c,        // char8_t
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric   SByte = 0x0068,       // 8 bit signed int
410b57cec5SDimitry Andric   Byte = 0x0069,        // 8 bit unsigned int
420b57cec5SDimitry Andric   Int16Short = 0x0011,  // 16 bit signed
430b57cec5SDimitry Andric   UInt16Short = 0x0021, // 16 bit unsigned
440b57cec5SDimitry Andric   Int16 = 0x0072,       // 16 bit signed int
450b57cec5SDimitry Andric   UInt16 = 0x0073,      // 16 bit unsigned int
460b57cec5SDimitry Andric   Int32Long = 0x0012,   // 32 bit signed
470b57cec5SDimitry Andric   UInt32Long = 0x0022,  // 32 bit unsigned
480b57cec5SDimitry Andric   Int32 = 0x0074,       // 32 bit signed int
490b57cec5SDimitry Andric   UInt32 = 0x0075,      // 32 bit unsigned int
500b57cec5SDimitry Andric   Int64Quad = 0x0013,   // 64 bit signed
510b57cec5SDimitry Andric   UInt64Quad = 0x0023,  // 64 bit unsigned
520b57cec5SDimitry Andric   Int64 = 0x0076,       // 64 bit signed int
530b57cec5SDimitry Andric   UInt64 = 0x0077,      // 64 bit unsigned int
540b57cec5SDimitry Andric   Int128Oct = 0x0014,   // 128 bit signed int
550b57cec5SDimitry Andric   UInt128Oct = 0x0024,  // 128 bit unsigned int
560b57cec5SDimitry Andric   Int128 = 0x0078,      // 128 bit signed int
570b57cec5SDimitry Andric   UInt128 = 0x0079,     // 128 bit unsigned int
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric   Float16 = 0x0046,                 // 16 bit real
600b57cec5SDimitry Andric   Float32 = 0x0040,                 // 32 bit real
610b57cec5SDimitry Andric   Float32PartialPrecision = 0x0045, // 32 bit PP real
620b57cec5SDimitry Andric   Float48 = 0x0044,                 // 48 bit real
630b57cec5SDimitry Andric   Float64 = 0x0041,                 // 64 bit real
640b57cec5SDimitry Andric   Float80 = 0x0042,                 // 80 bit real
650b57cec5SDimitry Andric   Float128 = 0x0043,                // 128 bit real
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric   Complex16 = 0x0056,                 // 16 bit complex
680b57cec5SDimitry Andric   Complex32 = 0x0050,                 // 32 bit complex
690b57cec5SDimitry Andric   Complex32PartialPrecision = 0x0055, // 32 bit PP complex
700b57cec5SDimitry Andric   Complex48 = 0x0054,                 // 48 bit complex
710b57cec5SDimitry Andric   Complex64 = 0x0051,                 // 64 bit complex
720b57cec5SDimitry Andric   Complex80 = 0x0052,                 // 80 bit complex
730b57cec5SDimitry Andric   Complex128 = 0x0053,                // 128 bit complex
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric   Boolean8 = 0x0030,   // 8 bit boolean
760b57cec5SDimitry Andric   Boolean16 = 0x0031,  // 16 bit boolean
770b57cec5SDimitry Andric   Boolean32 = 0x0032,  // 32 bit boolean
780b57cec5SDimitry Andric   Boolean64 = 0x0033,  // 64 bit boolean
790b57cec5SDimitry Andric   Boolean128 = 0x0034, // 128 bit boolean
800b57cec5SDimitry Andric };
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric enum class SimpleTypeMode : uint32_t {
830b57cec5SDimitry Andric   Direct = 0x00000000,        // Not a pointer
840b57cec5SDimitry Andric   NearPointer = 0x00000100,   // Near pointer
850b57cec5SDimitry Andric   FarPointer = 0x00000200,    // Far pointer
860b57cec5SDimitry Andric   HugePointer = 0x00000300,   // Huge pointer
870b57cec5SDimitry Andric   NearPointer32 = 0x00000400, // 32 bit near pointer
880b57cec5SDimitry Andric   FarPointer32 = 0x00000500,  // 32 bit far pointer
890b57cec5SDimitry Andric   NearPointer64 = 0x00000600, // 64 bit near pointer
900b57cec5SDimitry Andric   NearPointer128 = 0x00000700 // 128 bit near pointer
910b57cec5SDimitry Andric };
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric /// A 32-bit type reference. Types are indexed by their order of appearance in
940b57cec5SDimitry Andric /// .debug$T plus 0x1000. Type indices less than 0x1000 are "simple" types,
950b57cec5SDimitry Andric /// composed of a SimpleTypeMode byte followed by a SimpleTypeKind byte.
960b57cec5SDimitry Andric class TypeIndex {
970b57cec5SDimitry Andric public:
980b57cec5SDimitry Andric   static const uint32_t FirstNonSimpleIndex = 0x1000;
990b57cec5SDimitry Andric   static const uint32_t SimpleKindMask = 0x000000ff;
1000b57cec5SDimitry Andric   static const uint32_t SimpleModeMask = 0x00000700;
1010b57cec5SDimitry Andric   static const uint32_t DecoratedItemIdMask = 0x80000000;
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric public:
TypeIndex()1040b57cec5SDimitry Andric   TypeIndex() : Index(static_cast<uint32_t>(SimpleTypeKind::None)) {}
TypeIndex(uint32_t Index)1050b57cec5SDimitry Andric   explicit TypeIndex(uint32_t Index) : Index(Index) {}
TypeIndex(SimpleTypeKind Kind)1060b57cec5SDimitry Andric   explicit TypeIndex(SimpleTypeKind Kind)
1070b57cec5SDimitry Andric       : Index(static_cast<uint32_t>(Kind)) {}
TypeIndex(SimpleTypeKind Kind,SimpleTypeMode Mode)1080b57cec5SDimitry Andric   TypeIndex(SimpleTypeKind Kind, SimpleTypeMode Mode)
1090b57cec5SDimitry Andric       : Index(static_cast<uint32_t>(Kind) | static_cast<uint32_t>(Mode)) {}
1100b57cec5SDimitry Andric 
getIndex()1110b57cec5SDimitry Andric   uint32_t getIndex() const { return Index; }
setIndex(uint32_t I)1120b57cec5SDimitry Andric   void setIndex(uint32_t I) { Index = I; }
isSimple()1130b57cec5SDimitry Andric   bool isSimple() const { return Index < FirstNonSimpleIndex; }
isDecoratedItemId()1140b57cec5SDimitry Andric   bool isDecoratedItemId() const { return !!(Index & DecoratedItemIdMask); }
1150b57cec5SDimitry Andric 
isNoneType()1160b57cec5SDimitry Andric   bool isNoneType() const { return *this == None(); }
1170b57cec5SDimitry Andric 
toArrayIndex()1180b57cec5SDimitry Andric   uint32_t toArrayIndex() const {
1190b57cec5SDimitry Andric     assert(!isSimple());
120e8d8bef9SDimitry Andric     return (getIndex() & ~DecoratedItemIdMask) - FirstNonSimpleIndex;
1210b57cec5SDimitry Andric   }
1220b57cec5SDimitry Andric 
fromArrayIndex(uint32_t Index)1230b57cec5SDimitry Andric   static TypeIndex fromArrayIndex(uint32_t Index) {
1240b57cec5SDimitry Andric     return TypeIndex(Index + FirstNonSimpleIndex);
1250b57cec5SDimitry Andric   }
1260b57cec5SDimitry Andric 
fromDecoratedArrayIndex(bool IsItem,uint32_t Index)127e8d8bef9SDimitry Andric   static TypeIndex fromDecoratedArrayIndex(bool IsItem, uint32_t Index) {
128e8d8bef9SDimitry Andric     return TypeIndex((Index + FirstNonSimpleIndex) |
129e8d8bef9SDimitry Andric                      (IsItem ? DecoratedItemIdMask : 0));
130e8d8bef9SDimitry Andric   }
131e8d8bef9SDimitry Andric 
removeDecoration()132e8d8bef9SDimitry Andric   TypeIndex removeDecoration() {
133e8d8bef9SDimitry Andric     return TypeIndex(Index & ~DecoratedItemIdMask);
134e8d8bef9SDimitry Andric   }
135e8d8bef9SDimitry Andric 
getSimpleKind()1360b57cec5SDimitry Andric   SimpleTypeKind getSimpleKind() const {
1370b57cec5SDimitry Andric     assert(isSimple());
1380b57cec5SDimitry Andric     return static_cast<SimpleTypeKind>(Index & SimpleKindMask);
1390b57cec5SDimitry Andric   }
1400b57cec5SDimitry Andric 
getSimpleMode()1410b57cec5SDimitry Andric   SimpleTypeMode getSimpleMode() const {
1420b57cec5SDimitry Andric     assert(isSimple());
1430b57cec5SDimitry Andric     return static_cast<SimpleTypeMode>(Index & SimpleModeMask);
1440b57cec5SDimitry Andric   }
1450b57cec5SDimitry Andric 
makeDirect()1460b57cec5SDimitry Andric   TypeIndex makeDirect() const { return TypeIndex{getSimpleKind()}; }
1470b57cec5SDimitry Andric 
None()1480b57cec5SDimitry Andric   static TypeIndex None() { return TypeIndex(SimpleTypeKind::None); }
Void()1490b57cec5SDimitry Andric   static TypeIndex Void() { return TypeIndex(SimpleTypeKind::Void); }
VoidPointer32()1500b57cec5SDimitry Andric   static TypeIndex VoidPointer32() {
1510b57cec5SDimitry Andric     return TypeIndex(SimpleTypeKind::Void, SimpleTypeMode::NearPointer32);
1520b57cec5SDimitry Andric   }
VoidPointer64()1530b57cec5SDimitry Andric   static TypeIndex VoidPointer64() {
1540b57cec5SDimitry Andric     return TypeIndex(SimpleTypeKind::Void, SimpleTypeMode::NearPointer64);
1550b57cec5SDimitry Andric   }
1560b57cec5SDimitry Andric 
NullptrT()1570b57cec5SDimitry Andric   static TypeIndex NullptrT() {
1580b57cec5SDimitry Andric     // std::nullptr_t uses the pointer mode that doesn't indicate bit-width,
1590b57cec5SDimitry Andric     // presumably because std::nullptr_t is intended to be compatible with any
1600b57cec5SDimitry Andric     // pointer type.
1610b57cec5SDimitry Andric     return TypeIndex(SimpleTypeKind::Void, SimpleTypeMode::NearPointer);
1620b57cec5SDimitry Andric   }
1630b57cec5SDimitry Andric 
SignedCharacter()1640b57cec5SDimitry Andric   static TypeIndex SignedCharacter() {
1650b57cec5SDimitry Andric     return TypeIndex(SimpleTypeKind::SignedCharacter);
1660b57cec5SDimitry Andric   }
UnsignedCharacter()1670b57cec5SDimitry Andric   static TypeIndex UnsignedCharacter() {
1680b57cec5SDimitry Andric     return TypeIndex(SimpleTypeKind::UnsignedCharacter);
1690b57cec5SDimitry Andric   }
NarrowCharacter()1700b57cec5SDimitry Andric   static TypeIndex NarrowCharacter() {
1710b57cec5SDimitry Andric     return TypeIndex(SimpleTypeKind::NarrowCharacter);
1720b57cec5SDimitry Andric   }
WideCharacter()1730b57cec5SDimitry Andric   static TypeIndex WideCharacter() {
1740b57cec5SDimitry Andric     return TypeIndex(SimpleTypeKind::WideCharacter);
1750b57cec5SDimitry Andric   }
Int16Short()1760b57cec5SDimitry Andric   static TypeIndex Int16Short() {
1770b57cec5SDimitry Andric     return TypeIndex(SimpleTypeKind::Int16Short);
1780b57cec5SDimitry Andric   }
UInt16Short()1790b57cec5SDimitry Andric   static TypeIndex UInt16Short() {
1800b57cec5SDimitry Andric     return TypeIndex(SimpleTypeKind::UInt16Short);
1810b57cec5SDimitry Andric   }
Int32()1820b57cec5SDimitry Andric   static TypeIndex Int32() { return TypeIndex(SimpleTypeKind::Int32); }
UInt32()1830b57cec5SDimitry Andric   static TypeIndex UInt32() { return TypeIndex(SimpleTypeKind::UInt32); }
Int32Long()1840b57cec5SDimitry Andric   static TypeIndex Int32Long() { return TypeIndex(SimpleTypeKind::Int32Long); }
UInt32Long()1850b57cec5SDimitry Andric   static TypeIndex UInt32Long() {
1860b57cec5SDimitry Andric     return TypeIndex(SimpleTypeKind::UInt32Long);
1870b57cec5SDimitry Andric   }
Int64()1880b57cec5SDimitry Andric   static TypeIndex Int64() { return TypeIndex(SimpleTypeKind::Int64); }
UInt64()1890b57cec5SDimitry Andric   static TypeIndex UInt64() { return TypeIndex(SimpleTypeKind::UInt64); }
Int64Quad()1900b57cec5SDimitry Andric   static TypeIndex Int64Quad() { return TypeIndex(SimpleTypeKind::Int64Quad); }
UInt64Quad()1910b57cec5SDimitry Andric   static TypeIndex UInt64Quad() {
1920b57cec5SDimitry Andric     return TypeIndex(SimpleTypeKind::UInt64Quad);
1930b57cec5SDimitry Andric   }
1940b57cec5SDimitry Andric 
Float32()1950b57cec5SDimitry Andric   static TypeIndex Float32() { return TypeIndex(SimpleTypeKind::Float32); }
Float64()1960b57cec5SDimitry Andric   static TypeIndex Float64() { return TypeIndex(SimpleTypeKind::Float64); }
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric   TypeIndex &operator+=(unsigned N) {
1990b57cec5SDimitry Andric     Index += N;
2000b57cec5SDimitry Andric     return *this;
2010b57cec5SDimitry Andric   }
2020b57cec5SDimitry Andric 
2030b57cec5SDimitry Andric   TypeIndex &operator++() {
2040b57cec5SDimitry Andric     Index += 1;
2050b57cec5SDimitry Andric     return *this;
2060b57cec5SDimitry Andric   }
2070b57cec5SDimitry Andric 
2080b57cec5SDimitry Andric   TypeIndex operator++(int) {
2090b57cec5SDimitry Andric     TypeIndex Copy = *this;
2100b57cec5SDimitry Andric     operator++();
2110b57cec5SDimitry Andric     return Copy;
2120b57cec5SDimitry Andric   }
2130b57cec5SDimitry Andric 
2140b57cec5SDimitry Andric   TypeIndex &operator-=(unsigned N) {
2150b57cec5SDimitry Andric     assert(Index >= N);
2160b57cec5SDimitry Andric     Index -= N;
2170b57cec5SDimitry Andric     return *this;
2180b57cec5SDimitry Andric   }
2190b57cec5SDimitry Andric 
2200b57cec5SDimitry Andric   TypeIndex &operator--() {
2210b57cec5SDimitry Andric     Index -= 1;
2220b57cec5SDimitry Andric     return *this;
2230b57cec5SDimitry Andric   }
2240b57cec5SDimitry Andric 
2250b57cec5SDimitry Andric   TypeIndex operator--(int) {
2260b57cec5SDimitry Andric     TypeIndex Copy = *this;
2270b57cec5SDimitry Andric     operator--();
2280b57cec5SDimitry Andric     return Copy;
2290b57cec5SDimitry Andric   }
2300b57cec5SDimitry Andric 
2310b57cec5SDimitry Andric   friend inline bool operator==(const TypeIndex &A, const TypeIndex &B) {
2320b57cec5SDimitry Andric     return A.getIndex() == B.getIndex();
2330b57cec5SDimitry Andric   }
2340b57cec5SDimitry Andric 
2350b57cec5SDimitry Andric   friend inline bool operator!=(const TypeIndex &A, const TypeIndex &B) {
2360b57cec5SDimitry Andric     return A.getIndex() != B.getIndex();
2370b57cec5SDimitry Andric   }
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric   friend inline bool operator<(const TypeIndex &A, const TypeIndex &B) {
2400b57cec5SDimitry Andric     return A.getIndex() < B.getIndex();
2410b57cec5SDimitry Andric   }
2420b57cec5SDimitry Andric 
2430b57cec5SDimitry Andric   friend inline bool operator<=(const TypeIndex &A, const TypeIndex &B) {
2440b57cec5SDimitry Andric     return A.getIndex() <= B.getIndex();
2450b57cec5SDimitry Andric   }
2460b57cec5SDimitry Andric 
2470b57cec5SDimitry Andric   friend inline bool operator>(const TypeIndex &A, const TypeIndex &B) {
2480b57cec5SDimitry Andric     return A.getIndex() > B.getIndex();
2490b57cec5SDimitry Andric   }
2500b57cec5SDimitry Andric 
2510b57cec5SDimitry Andric   friend inline bool operator>=(const TypeIndex &A, const TypeIndex &B) {
2520b57cec5SDimitry Andric     return A.getIndex() >= B.getIndex();
2530b57cec5SDimitry Andric   }
2540b57cec5SDimitry Andric 
2550b57cec5SDimitry Andric   friend inline TypeIndex operator+(const TypeIndex &A, uint32_t N) {
2560b57cec5SDimitry Andric     TypeIndex Result(A);
2570b57cec5SDimitry Andric     Result += N;
2580b57cec5SDimitry Andric     return Result;
2590b57cec5SDimitry Andric   }
2600b57cec5SDimitry Andric 
2610b57cec5SDimitry Andric   friend inline TypeIndex operator-(const TypeIndex &A, uint32_t N) {
2620b57cec5SDimitry Andric     assert(A.getIndex() >= N);
2630b57cec5SDimitry Andric     TypeIndex Result(A);
2640b57cec5SDimitry Andric     Result -= N;
2650b57cec5SDimitry Andric     return Result;
2660b57cec5SDimitry Andric   }
2670b57cec5SDimitry Andric 
2680b57cec5SDimitry Andric   friend inline uint32_t operator-(const TypeIndex &A, const TypeIndex &B) {
2690b57cec5SDimitry Andric     assert(A >= B);
2700b57cec5SDimitry Andric     return A.toArrayIndex() - B.toArrayIndex();
2710b57cec5SDimitry Andric   }
2720b57cec5SDimitry Andric 
2730b57cec5SDimitry Andric   static StringRef simpleTypeName(TypeIndex TI);
2740b57cec5SDimitry Andric 
2750b57cec5SDimitry Andric private:
2760b57cec5SDimitry Andric   support::ulittle32_t Index;
2770b57cec5SDimitry Andric };
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric // Used for pseudo-indexing an array of type records.  An array of such records
2800b57cec5SDimitry Andric // sorted by TypeIndex can allow log(N) lookups even though such a type record
2810b57cec5SDimitry Andric // stream does not provide random access.
2820b57cec5SDimitry Andric struct TypeIndexOffset {
2830b57cec5SDimitry Andric   TypeIndex Type;
2840b57cec5SDimitry Andric   support::ulittle32_t Offset;
2850b57cec5SDimitry Andric };
2860b57cec5SDimitry Andric 
2870b57cec5SDimitry Andric void printTypeIndex(ScopedPrinter &Printer, StringRef FieldName, TypeIndex TI,
2880b57cec5SDimitry Andric                     TypeCollection &Types);
2890b57cec5SDimitry Andric }
2900b57cec5SDimitry Andric 
2910b57cec5SDimitry Andric template <> struct DenseMapInfo<codeview::TypeIndex> {
2920b57cec5SDimitry Andric   static inline codeview::TypeIndex getEmptyKey() {
2930b57cec5SDimitry Andric     return codeview::TypeIndex{DenseMapInfo<uint32_t>::getEmptyKey()};
2940b57cec5SDimitry Andric   }
2950b57cec5SDimitry Andric   static inline codeview::TypeIndex getTombstoneKey() {
2960b57cec5SDimitry Andric     return codeview::TypeIndex{DenseMapInfo<uint32_t>::getTombstoneKey()};
2970b57cec5SDimitry Andric   }
2980b57cec5SDimitry Andric   static unsigned getHashValue(const codeview::TypeIndex &TI) {
2990b57cec5SDimitry Andric     return DenseMapInfo<uint32_t>::getHashValue(TI.getIndex());
3000b57cec5SDimitry Andric   }
3010b57cec5SDimitry Andric   static bool isEqual(const codeview::TypeIndex &LHS,
3020b57cec5SDimitry Andric                       const codeview::TypeIndex &RHS) {
3030b57cec5SDimitry Andric     return LHS == RHS;
3040b57cec5SDimitry Andric   }
3050b57cec5SDimitry Andric };
3060b57cec5SDimitry Andric 
3070b57cec5SDimitry Andric } // namespace llvm
3080b57cec5SDimitry Andric 
3090b57cec5SDimitry Andric #endif
310