Home | History | Annotate | Line # | Download | only in CodeView
      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:
    103   TypeIndex() : Index(static_cast<uint32_t>(SimpleTypeKind::None)) {}
    104   explicit TypeIndex(uint32_t Index) : Index(Index) {}
    105   explicit TypeIndex(SimpleTypeKind Kind)
    106       : Index(static_cast<uint32_t>(Kind)) {}
    107   TypeIndex(SimpleTypeKind Kind, SimpleTypeMode Mode)
    108       : Index(static_cast<uint32_t>(Kind) | static_cast<uint32_t>(Mode)) {}
    109 
    110   uint32_t getIndex() const { return Index; }
    111   void setIndex(uint32_t I) { Index = I; }
    112   bool isSimple() const { return Index < FirstNonSimpleIndex; }
    113   bool isDecoratedItemId() const { return !!(Index & DecoratedItemIdMask); }
    114 
    115   bool isNoneType() const { return *this == None(); }
    116 
    117   uint32_t toArrayIndex() const {
    118     assert(!isSimple());
    119     return (getIndex() & ~DecoratedItemIdMask) - FirstNonSimpleIndex;
    120   }
    121 
    122   static TypeIndex fromArrayIndex(uint32_t Index) {
    123     return TypeIndex(Index + FirstNonSimpleIndex);
    124   }
    125 
    126   static TypeIndex fromDecoratedArrayIndex(bool IsItem, uint32_t Index) {
    127     return TypeIndex((Index + FirstNonSimpleIndex) |
    128                      (IsItem ? DecoratedItemIdMask : 0));
    129   }
    130 
    131   TypeIndex removeDecoration() {
    132     return TypeIndex(Index & ~DecoratedItemIdMask);
    133   }
    134 
    135   SimpleTypeKind getSimpleKind() const {
    136     assert(isSimple());
    137     return static_cast<SimpleTypeKind>(Index & SimpleKindMask);
    138   }
    139 
    140   SimpleTypeMode getSimpleMode() const {
    141     assert(isSimple());
    142     return static_cast<SimpleTypeMode>(Index & SimpleModeMask);
    143   }
    144 
    145   TypeIndex makeDirect() const { return TypeIndex{getSimpleKind()}; }
    146 
    147   static TypeIndex None() { return TypeIndex(SimpleTypeKind::None); }
    148   static TypeIndex Void() { return TypeIndex(SimpleTypeKind::Void); }
    149   static TypeIndex VoidPointer32() {
    150     return TypeIndex(SimpleTypeKind::Void, SimpleTypeMode::NearPointer32);
    151   }
    152   static TypeIndex VoidPointer64() {
    153     return TypeIndex(SimpleTypeKind::Void, SimpleTypeMode::NearPointer64);
    154   }
    155 
    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 
    163   static TypeIndex SignedCharacter() {
    164     return TypeIndex(SimpleTypeKind::SignedCharacter);
    165   }
    166   static TypeIndex UnsignedCharacter() {
    167     return TypeIndex(SimpleTypeKind::UnsignedCharacter);
    168   }
    169   static TypeIndex NarrowCharacter() {
    170     return TypeIndex(SimpleTypeKind::NarrowCharacter);
    171   }
    172   static TypeIndex WideCharacter() {
    173     return TypeIndex(SimpleTypeKind::WideCharacter);
    174   }
    175   static TypeIndex Int16Short() {
    176     return TypeIndex(SimpleTypeKind::Int16Short);
    177   }
    178   static TypeIndex UInt16Short() {
    179     return TypeIndex(SimpleTypeKind::UInt16Short);
    180   }
    181   static TypeIndex Int32() { return TypeIndex(SimpleTypeKind::Int32); }
    182   static TypeIndex UInt32() { return TypeIndex(SimpleTypeKind::UInt32); }
    183   static TypeIndex Int32Long() { return TypeIndex(SimpleTypeKind::Int32Long); }
    184   static TypeIndex UInt32Long() {
    185     return TypeIndex(SimpleTypeKind::UInt32Long);
    186   }
    187   static TypeIndex Int64() { return TypeIndex(SimpleTypeKind::Int64); }
    188   static TypeIndex UInt64() { return TypeIndex(SimpleTypeKind::UInt64); }
    189   static TypeIndex Int64Quad() { return TypeIndex(SimpleTypeKind::Int64Quad); }
    190   static TypeIndex UInt64Quad() {
    191     return TypeIndex(SimpleTypeKind::UInt64Quad);
    192   }
    193 
    194   static TypeIndex Float32() { return TypeIndex(SimpleTypeKind::Float32); }
    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