text: //===- PDBTypes.h - Defines enums for various fields contained in PDB ----====//
  //
  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  // See https://llvm.org/LICENSE.txt for license information.
  // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  //
  //===----------------------------------------------------------------------===//
  
  #ifndef LLVM_DEBUGINFO_PDB_PDBTYPES_H
  #define LLVM_DEBUGINFO_PDB_PDBTYPES_H
  
  #include "llvm/DebugInfo/CodeView/CodeView.h"
  #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
  #include "llvm/DebugInfo/PDB/IPDBFrameData.h"
  #include "llvm/DebugInfo/PDB/Native/RawTypes.h"
  #include <cctype>
  #include <cstddef>
  #include <cstdint>
  #include <cstring>
  #include <functional>
  
  namespace llvm {
  namespace pdb {
  
  typedef uint32_t SymIndexId;
  
  class IPDBDataStream;
  class IPDBInjectedSource;
  class IPDBLineNumber;
  class IPDBSectionContrib;
  class IPDBSession;
  class IPDBSourceFile;
  class IPDBTable;
  class PDBSymDumper;
  class PDBSymbol;
  class PDBSymbolExe;
  class PDBSymbolCompiland;
  class PDBSymbolCompilandDetails;
  class PDBSymbolCompilandEnv;
  class PDBSymbolFunc;
  class PDBSymbolBlock;
  class PDBSymbolData;
  class PDBSymbolAnnotation;
  class PDBSymbolLabel;
  class PDBSymbolPublicSymbol;
  class PDBSymbolTypeUDT;
  class PDBSymbolTypeEnum;
  class PDBSymbolTypeFunctionSig;
  class PDBSymbolTypePointer;
  class PDBSymbolTypeArray;
  class PDBSymbolTypeBuiltin;
  class PDBSymbolTypeTypedef;
  class PDBSymbolTypeBaseClass;
  class PDBSymbolTypeFriend;
  class PDBSymbolTypeFunctionArg;
  class PDBSymbolFuncDebugStart;
  class PDBSymbolFuncDebugEnd;
  class PDBSymbolUsingNamespace;
  class PDBSymbolTypeVTableShape;
  class PDBSymbolTypeVTable;
  class PDBSymbolCustom;
  class PDBSymbolThunk;
  class PDBSymbolTypeCustom;
  class PDBSymbolTypeManaged;
  class PDBSymbolTypeDimension;
  class PDBSymbolUnknown;
  
  using IPDBEnumSymbols = IPDBEnumChildren<PDBSymbol>;
  using IPDBEnumSourceFiles = IPDBEnumChildren<IPDBSourceFile>;
  using IPDBEnumDataStreams = IPDBEnumChildren<IPDBDataStream>;
  using IPDBEnumLineNumbers = IPDBEnumChildren<IPDBLineNumber>;
  using IPDBEnumTables = IPDBEnumChildren<IPDBTable>;
  using IPDBEnumInjectedSources = IPDBEnumChildren<IPDBInjectedSource>;
  using IPDBEnumSectionContribs = IPDBEnumChildren<IPDBSectionContrib>;
  using IPDBEnumFrameData = IPDBEnumChildren<IPDBFrameData>;
  
  /// Specifies which PDB reader implementation is to be used.  Only a value
  /// of PDB_ReaderType::DIA is currently supported, but Native is in the works.
  enum class PDB_ReaderType {
    DIA = 0,
    Native = 1,
  };
  
  /// An enumeration indicating the type of data contained in this table.
  enum class PDB_TableType {
    TableInvalid = 0,
    Symbols,
    SourceFiles,
    LineNumbers,
    SectionContribs,
    Segments,
    InjectedSources,
    FrameData,
    InputAssemblyFiles,
    Dbg
  };
  
  /// Defines flags used for enumerating child symbols.  This corresponds to the
  /// NameSearchOptions enumeration which is documented here:
  /// https://msdn.microsoft.com/en-us/library/yat28ads.aspx
  enum PDB_NameSearchFlags {
    NS_Default = 0x0,
    NS_CaseSensitive = 0x1,
    NS_CaseInsensitive = 0x2,
    NS_FileNameExtMatch = 0x4,
    NS_Regex = 0x8,
    NS_UndecoratedName = 0x10,
  
    // For backward compatibility.
    NS_CaseInFileNameExt = NS_CaseInsensitive | NS_FileNameExtMatch,
    NS_CaseRegex = NS_Regex | NS_CaseSensitive,
    NS_CaseInRex = NS_Regex | NS_CaseInsensitive
  };
  
  /// Specifies the hash algorithm that a source file from a PDB was hashed with.
  /// This corresponds to the CV_SourceChksum_t enumeration and are documented
  /// here: https://msdn.microsoft.com/en-us/library/e96az21x.aspx
  enum class PDB_Checksum { None = 0, MD5 = 1, SHA1 = 2, SHA256 = 3 };
  
  /// These values correspond to the CV_CPU_TYPE_e enumeration, and are documented
  /// here: https://msdn.microsoft.com/en-us/library/b2fc64ek.aspx
  using PDB_Cpu = codeview::CPUType;
  
  enum class PDB_Machine {
    Invalid = 0xffff,
    Unknown = 0x0,
    Am33 = 0x13,
    Amd64 = 0x8664,
    Arm = 0x1C0,
    Arm64 = 0xaa64,
    ArmNT = 0x1C4,
    Ebc = 0xEBC,
    x86 = 0x14C,
    Ia64 = 0x200,
    M32R = 0x9041,
    Mips16 = 0x266,
    MipsFpu = 0x366,
    MipsFpu16 = 0x466,
    PowerPC = 0x1F0,
    PowerPCFP = 0x1F1,
    R4000 = 0x166,
    SH3 = 0x1A2,
    SH3DSP = 0x1A3,
    SH4 = 0x1A6,
    SH5 = 0x1A8,
    Thumb = 0x1C2,
    WceMipsV2 = 0x169
  };
  
  // A struct with an inner unnamed enum with explicit underlying type resuls
  // in an enum class that can implicitly convert to the underlying type, which
  // is convenient for this enum.
  struct PDB_SourceCompression {
    enum : uint32_t {
      // No compression. Produced e.g. by `link.exe /natvis:foo.natvis`.
      None,
      // Not known what produces this.
      RunLengthEncoded,
      // Not known what produces this.
      Huffman,
      // Not known what produces this.
      LZ,
      // Produced e.g. by `csc /debug`. The encoded data is its own mini-stream
      // with the following layout (in little endian):
      //   GUID LanguageTypeGuid;
      //   GUID LanguageVendorGuid;
      //   GUID DocumentTypeGuid;
      //   GUID HashFunctionGuid;
      //   uint32_t HashDataSize;
      //   uint32_t CompressedDataSize;
      // Followed by HashDataSize bytes containing a hash checksum,
      // followed by CompressedDataSize bytes containing source contents.
      //
      // CompressedDataSize can be 0, in this case only the hash data is present.
      // (CompressedDataSize is != 0 e.g. if `/embed` is passed to csc.exe.)
      // The compressed data format is:
      //   uint32_t UncompressedDataSize;
      // If UncompressedDataSize is 0, the data is stored uncompressed and
      // CompressedDataSize stores the uncompressed size.
      // If UncompressedDataSize is != 0, then the data is in raw deflate
      // encoding as described in rfc1951.
      //
      // A GUID is 16 bytes, stored in the usual
      //   uint32_t
      //   uint16_t
      //   uint16_t
      //   uint8_t[24]
      // layout.
      //
      // Well-known GUIDs for LanguageTypeGuid are:
      //   63a08714-fc37-11d2-904c-00c04fa302a1 C
      //   3a12d0b7-c26c-11d0-b442-00a0244a1dd2 C++
      //   3f5162f8-07c6-11d3-9053-00c04fa302a1 C#
      //   af046cd1-d0e1-11d2-977c-00a0c9b4d50c Cobol
      //   ab4f38c9-b6e6-43ba-be3b-58080b2ccce3 F#
      //   3a12d0b4-c26c-11d0-b442-00a0244a1dd2 Java
      //   3a12d0b6-c26c-11d0-b442-00a0244a1dd2 JScript
      //   af046cd2-d0e1-11d2-977c-00a0c9b4d50c Pascal
      //   3a12d0b8-c26c-11d0-b442-00a0244a1dd2 Visual Basic
      //
      // Well-known GUIDs for LanguageVendorGuid are:
      //   994b45c4-e6e9-11d2-903f-00c04fa302a1 Microsoft
      //
      // Well-known GUIDs for DocumentTypeGuid are:
      //   5a869d0b-6611-11d3-bd2a-0000f80849bd Text
      //
      // Well-known GUIDs for HashFunctionGuid are:
      //   406ea660-64cf-4c82-b6f0-42d48172a799 MD5    (HashDataSize is 16)
      //   ff1816ec-aa5e-4d10-87f7-6f4963833460 SHA1   (HashDataSize is 20)
      //   8829d00f-11b8-4213-878b-770e8597ac16 SHA256 (HashDataSize is 32)
      DotNet = 101,
    };
  };
  
  /// These values correspond to the CV_call_e enumeration, and are documented
  /// at the following locations:
  ///   https://msdn.microsoft.com/en-us/library/b2fc64ek.aspx
  ///   https://msdn.microsoft.com/en-us/library/windows/desktop/ms680207(v=vs.85).aspx
  using PDB_CallingConv = codeview::CallingConvention;
  
  /// These values correspond to the CV_CFL_LANG enumeration, and are documented
  /// here: https://msdn.microsoft.com/en-us/library/bw3aekw6.aspx
  using PDB_Lang = codeview::SourceLanguage;
  
  /// These values correspond to the DataKind enumeration, and are documented
  /// here: https://msdn.microsoft.com/en-us/library/b2x2t313.aspx
  enum class PDB_DataKind {
    Unknown,
    Local,
    StaticLocal,
    Param,
    ObjectPtr,
    FileStatic,
    Global,
    Member,
    StaticMember,
    Constant
  };
  
  /// These values correspond to the SymTagEnum enumeration, and are documented
  /// here: https://msdn.microsoft.com/en-us/library/bkedss5f.aspx
  enum class PDB_SymType {
    None,
    Exe,
    Compiland,
    CompilandDetails,
    CompilandEnv,
    Function,
    Block,
    Data,
    Annotation,
    Label,
    PublicSymbol,
    UDT,
    Enum,
    FunctionSig,
    PointerType,
    ArrayType,
    BuiltinType,
    Typedef,
    BaseClass,
    Friend,
    FunctionArg,
    FuncDebugStart,
    FuncDebugEnd,
    UsingNamespace,
    VTableShape,
    VTable,
    Custom,
    Thunk,
    CustomType,
    ManagedType,
    Dimension,
    CallSite,
    InlineSite,
    BaseInterface,
    VectorType,
    MatrixType,
    HLSLType,
    Caller,
    Callee,
    Export,
    HeapAllocationSite,
    CoffGroup,
    Inlinee,
    Max
  };
  
  /// These values correspond to the LocationType enumeration, and are documented
  /// here: https://msdn.microsoft.com/en-us/library/f57kaez3.aspx
  enum class PDB_LocType {
    Null,
    Static,
    TLS,
    RegRel,
    ThisRel,
    Enregistered,
    BitField,
    Slot,
    IlRel,
    MetaData,
    Constant,
    RegRelAliasIndir,
    Max
  };
  
  /// These values correspond to the UdtKind enumeration, and are documented
  /// here: https://msdn.microsoft.com/en-us/library/wcstk66t.aspx
  enum class PDB_UdtType { Struct, Class, Union, Interface };
  
  /// These values correspond to the StackFrameTypeEnum enumeration, and are
  /// documented here: https://msdn.microsoft.com/en-us/library/bc5207xw.aspx.
  enum class PDB_StackFrameType : uint16_t {
    FPO,
    KernelTrap,
    KernelTSS,
    EBP,
    FrameData,
    Unknown = 0xffff
  };
  
  /// These values correspond to the MemoryTypeEnum enumeration, and are
  /// documented here: https://msdn.microsoft.com/en-us/library/ms165609.aspx.
  enum class PDB_MemoryType : uint16_t {
    Code,
    Data,
    Stack,
    HeapCode,
    Any = 0xffff
  };
  
  /// These values correspond to the Basictype enumeration, and are documented
  /// here: https://msdn.microsoft.com/en-us/library/4szdtzc3.aspx
  enum class PDB_BuiltinType {
    None = 0,
    Void = 1,
    Char = 2,
    WCharT = 3,
    Int = 6,
    UInt = 7,
    Float = 8,
    BCD = 9,
    Bool = 10,
    Long = 13,
    ULong = 14,
    Currency = 25,
    Date = 26,
    Variant = 27,
    Complex = 28,
    Bitfield = 29,
    BSTR = 30,
    HResult = 31,
    Char16 = 32,
    Char32 = 33
  };
  
  /// These values correspond to the flags that can be combined to control the
  /// return of an undecorated name for a C++ decorated name, and are documented
  /// here: https://msdn.microsoft.com/en-us/library/kszfk0fs.aspx
  enum PDB_UndnameFlags : uint32_t {
    Undname_Complete = 0x0,
    Undname_NoLeadingUnderscores = 0x1,
    Undname_NoMsKeywords = 0x2,
    Undname_NoFuncReturns = 0x4,
    Undname_NoAllocModel = 0x8,
    Undname_NoAllocLang = 0x10,
    Undname_Reserved1 = 0x20,
    Undname_Reserved2 = 0x40,
    Undname_NoThisType = 0x60,
    Undname_NoAccessSpec = 0x80,
    Undname_NoThrowSig = 0x100,
    Undname_NoMemberType = 0x200,
    Undname_NoReturnUDTModel = 0x400,
    Undname_32BitDecode = 0x800,
    Undname_NameOnly = 0x1000,
    Undname_TypeOnly = 0x2000,
    Undname_HaveParams = 0x4000,
    Undname_NoECSU = 0x8000,
    Undname_NoIdentCharCheck = 0x10000,
    Undname_NoPTR64 = 0x20000
  };
  
  enum class PDB_MemberAccess { Private = 1, Protected = 2, Public = 3 };
  
  struct VersionInfo {
    uint32_t Major;
    uint32_t Minor;
    uint32_t Build;
    uint32_t QFE;
  };
  
  enum PDB_VariantType {
    Empty,
    Unknown,
    Int8,
    Int16,
    Int32,
    Int64,
    Single,
    Double,
    UInt8,
    UInt16,
    UInt32,
    UInt64,
    Bool,
    String
  };
  
  struct Variant {
    Variant() = default;
  
    explicit Variant(bool V) : Type(PDB_VariantType::Bool) { Value.Bool = V; }
    explicit Variant(int8_t V) : Type(PDB_VariantType::Int8) { Value.Int8 = V; }
    explicit Variant(int16_t V) : Type(PDB_VariantType::Int16) {
      Value.Int16 = V;
    }
    explicit Variant(int32_t V) : Type(PDB_VariantType::Int32) {
      Value.Int32 = V;
    }
    explicit Variant(int64_t V) : Type(PDB_VariantType::Int64) {
      Value.Int64 = V;
    }
    explicit Variant(float V) : Type(PDB_VariantType::Single) {
      Value.Single = V;
    }
    explicit Variant(double V) : Type(PDB_VariantType::Double) {
      Value.Double = V;
    }
    explicit Variant(uint8_t V) : Type(PDB_VariantType::UInt8) {
      Value.UInt8 = V;
    }
    explicit Variant(uint16_t V) : Type(PDB_VariantType::UInt16) {
      Value.UInt16 = V;
    }
    explicit Variant(uint32_t V) : Type(PDB_VariantType::UInt32) {
      Value.UInt32 = V;
    }
    explicit Variant(uint64_t V) : Type(PDB_VariantType::UInt64) {
      Value.UInt64 = V;
    }
  
    Variant(const Variant &Other) {
      *this = Other;
    }
  
    ~Variant() {
      if (Type == PDB_VariantType::String)
        delete[] Value.String;
    }
  
    PDB_VariantType Type = PDB_VariantType::Empty;
    union {
      bool Bool;
      int8_t Int8;
      int16_t Int16;
      int32_t Int32;
      int64_t Int64;
      float Single;
      double Double;
      uint8_t UInt8;
      uint16_t UInt16;
      uint32_t UInt32;
      uint64_t UInt64;
      char *String;
    } Value;
  
  #define VARIANT_EQUAL_CASE(Enum)                                               \
    case PDB_VariantType::Enum:                                                  \
      return Value.Enum == Other.Value.Enum;
  
    bool operator==(const Variant &Other) const {
      if (Type != Other.Type)
        return false;
      switch (Type) {
        VARIANT_EQUAL_CASE(Bool)
        VARIANT_EQUAL_CASE(Int8)
        VARIANT_EQUAL_CASE(Int16)
        VARIANT_EQUAL_CASE(Int32)
        VARIANT_EQUAL_CASE(Int64)
        VARIANT_EQUAL_CASE(Single)
        VARIANT_EQUAL_CASE(Double)
        VARIANT_EQUAL_CASE(UInt8)
        VARIANT_EQUAL_CASE(UInt16)
        VARIANT_EQUAL_CASE(UInt32)
        VARIANT_EQUAL_CASE(UInt64)
        VARIANT_EQUAL_CASE(String)
      default:
        return true;
      }
    }
  
  #undef VARIANT_EQUAL_CASE
  
    bool operator!=(const Variant &Other) const { return !(*this == Other); }
    Variant &operator=(const Variant &Other) {
      if (this == &Other)
        return *this;
      if (Type == PDB_VariantType::String)
        delete[] Value.String;
      Type = Other.Type;
      Value = Other.Value;
      if (Other.Type == PDB_VariantType::String &&
          Other.Value.String != nullptr) {
        Value.String = new char[strlen(Other.Value.String) + 1];
        ::strcpy(Value.String, Other.Value.String);
      }
      return *this;
    }
  };
  
  } // end namespace pdb
  } // end namespace llvm
  
  namespace std {
  
  template <> struct hash<llvm::pdb::PDB_SymType> {
    using argument_type = llvm::pdb::PDB_SymType;
    using result_type = std::size_t;
  
    result_type operator()(const argument_type &Arg) const {
      return std::hash<int>()(static_cast<int>(Arg));
    }
  };
  
  } // end namespace std
  
  #endif // LLVM_DEBUGINFO_PDB_PDBTYPES_H
  