Home | History | Annotate | Download | only in CodeView
      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 
    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 
    114   bool isNoneType() const { return *this == None(); }
    115 
    116   uint32_t toArrayIndex() const {
    117     assert(!isSimple());
    118     return getIndex() - FirstNonSimpleIndex;
    119   }
    120 
    121   static TypeIndex fromArrayIndex(uint32_t Index) {
    122     return TypeIndex(Index + FirstNonSimpleIndex);
    123   }
    124 
    125   SimpleTypeKind getSimpleKind() const {
    126     assert(isSimple());
    127     return static_cast<SimpleTypeKind>(Index & SimpleKindMask);
    128   }
    129 
    130   SimpleTypeMode getSimpleMode() const {
    131     assert(isSimple());
    132     return static_cast<SimpleTypeMode>(Index & SimpleModeMask);
    133   }
    134 
    135   static TypeIndex None() { return TypeIndex(SimpleTypeKind::None); }
    136   static TypeIndex Void() { return TypeIndex(SimpleTypeKind::Void); }
    137   static TypeIndex VoidPointer32() {
    138     return TypeIndex(SimpleTypeKind::Void, SimpleTypeMode::NearPointer32);
    139   }
    140   static TypeIndex VoidPointer64() {
    141     return TypeIndex(SimpleTypeKind::Void, SimpleTypeMode::NearPointer64);
    142   }
    143 
    144   static TypeIndex SignedCharacter() {
    145     return TypeIndex(SimpleTypeKind::SignedCharacter);
    146   }
    147   static TypeIndex UnsignedCharacter() {
    148     return TypeIndex(SimpleTypeKind::UnsignedCharacter);
    149   }
    150   static TypeIndex NarrowCharacter() {
    151     return TypeIndex(SimpleTypeKind::NarrowCharacter);
    152   }
    153   static TypeIndex WideCharacter() {
    154     return TypeIndex(SimpleTypeKind::WideCharacter);
    155   }
    156   static TypeIndex Int16Short() {
    157     return TypeIndex(SimpleTypeKind::Int16Short);
    158   }
    159   static TypeIndex UInt16Short() {
    160     return TypeIndex(SimpleTypeKind::UInt16Short);
    161   }
    162   static TypeIndex Int32() { return TypeIndex(SimpleTypeKind::Int32); }
    163   static TypeIndex UInt32() { return TypeIndex(SimpleTypeKind::UInt32); }
    164   static TypeIndex Int32Long() { return TypeIndex(SimpleTypeKind::Int32Long); }
    165   static TypeIndex UInt32Long() {
    166     return TypeIndex(SimpleTypeKind::UInt32Long);
    167   }
    168   static TypeIndex Int64() { return TypeIndex(SimpleTypeKind::Int64); }
    169   static TypeIndex UInt64() { return TypeIndex(SimpleTypeKind::UInt64); }
    170   static TypeIndex Int64Quad() { return TypeIndex(SimpleTypeKind::Int64Quad); }
    171   static TypeIndex UInt64Quad() {
    172     return TypeIndex(SimpleTypeKind::UInt64Quad);
    173   }
    174 
    175   static TypeIndex Float32() { return TypeIndex(SimpleTypeKind::Float32); }
    176   static TypeIndex Float64() { return TypeIndex(SimpleTypeKind::Float64); }
    177 
    178   TypeIndex &operator+=(unsigned N) {
    179     Index += N;
    180     return *this;
    181   }
    182 
    183   TypeIndex &operator++() {
    184     Index += 1;
    185     return *this;
    186   }
    187 
    188   TypeIndex operator++(int) {
    189     TypeIndex Copy = *this;
    190     operator++();
    191     return Copy;
    192   }
    193 
    194   TypeIndex &operator-=(unsigned N) {
    195     assert(Index >= N);
    196     Index -= N;
    197     return *this;
    198   }
    199 
    200   TypeIndex &operator--() {
    201     Index -= 1;
    202     return *this;
    203   }
    204 
    205   TypeIndex operator--(int) {
    206     TypeIndex Copy = *this;
    207     operator--();
    208     return Copy;
    209   }
    210 
    211   friend inline bool operator==(const TypeIndex &A, const TypeIndex &B) {
    212     return A.getIndex() == B.getIndex();
    213   }
    214 
    215   friend inline bool operator!=(const TypeIndex &A, const TypeIndex &B) {
    216     return A.getIndex() != B.getIndex();
    217   }
    218 
    219   friend inline bool operator<(const TypeIndex &A, const TypeIndex &B) {
    220     return A.getIndex() < B.getIndex();
    221   }
    222 
    223   friend inline bool operator<=(const TypeIndex &A, const TypeIndex &B) {
    224     return A.getIndex() <= B.getIndex();
    225   }
    226 
    227   friend inline bool operator>(const TypeIndex &A, const TypeIndex &B) {
    228     return A.getIndex() > B.getIndex();
    229   }
    230 
    231   friend inline bool operator>=(const TypeIndex &A, const TypeIndex &B) {
    232     return A.getIndex() >= B.getIndex();
    233   }
    234 
    235   friend inline TypeIndex operator+(const TypeIndex &A, uint32_t N) {
    236     TypeIndex Result(A);
    237     Result += N;
    238     return Result;
    239   }
    240 
    241   friend inline TypeIndex operator-(const TypeIndex &A, uint32_t N) {
    242     assert(A.getIndex() >= N);
    243     TypeIndex Result(A);
    244     Result -= N;
    245     return Result;
    246   }
    247 
    248   friend inline uint32_t operator-(const TypeIndex &A, const TypeIndex &B) {
    249     assert(A >= B);
    250     return A.toArrayIndex() - B.toArrayIndex();
    251   }
    252 
    253   static StringRef simpleTypeName(TypeIndex TI);
    254 
    255 private:
    256   support::ulittle32_t Index;
    257 };
    258 
    259 // Used for pseudo-indexing an array of type records.  An array of such records
    260 // sorted by TypeIndex can allow log(N) lookups even though such a type record
    261 // stream does not provide random access.
    262 struct TypeIndexOffset {
    263   TypeIndex Type;
    264   support::ulittle32_t Offset;
    265 };
    266 
    267 void printTypeIndex(ScopedPrinter &Printer, StringRef FieldName, TypeIndex TI,
    268                     TypeCollection &Types);
    269 }
    270 
    271 template <> struct DenseMapInfo<codeview::TypeIndex> {
    272   static inline codeview::TypeIndex getEmptyKey() {
    273     return codeview::TypeIndex{DenseMapInfo<uint32_t>::getEmptyKey()};
    274   }
    275   static inline codeview::TypeIndex getTombstoneKey() {
    276     return codeview::TypeIndex{DenseMapInfo<uint32_t>::getTombstoneKey()};
    277   }
    278   static unsigned getHashValue(const codeview::TypeIndex &TI) {
    279     return DenseMapInfo<uint32_t>::getHashValue(TI.getIndex());
    280   }
    281   static bool isEqual(const codeview::TypeIndex &LHS,
    282                       const codeview::TypeIndex &RHS) {
    283     return LHS == RHS;
    284   }
    285 };
    286 
    287 } // namespace llvm
    288 
    289 #endif
    290