blob: b9e2562bfc2b1b01f8399b69c74dca31e87ea82a [file] [log] [blame]
//===- TypeIndex.h ----------------------------------------------*- C++ -*-===//
//
// 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_CODEVIEW_TYPEINDEX_H
#define LLVM_DEBUGINFO_CODEVIEW_TYPEINDEX_H
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/Support/Endian.h"
#include <cassert>
#include <cinttypes>
#include <functional>
namespace llvm {
class ScopedPrinter;
namespace codeview {
class TypeCollection;
enum class SimpleTypeKind : uint32_t {
None = 0x0000, // uncharacterized type (no type)
Void = 0x0003, // void
NotTranslated = 0x0007, // type not translated by cvpack
HResult = 0x0008, // OLE/COM HRESULT
SignedCharacter = 0x0010, // 8 bit signed
UnsignedCharacter = 0x0020, // 8 bit unsigned
NarrowCharacter = 0x0070, // really a char
WideCharacter = 0x0071, // wide char
Character16 = 0x007a, // char16_t
Character32 = 0x007b, // char32_t
SByte = 0x0068, // 8 bit signed int
Byte = 0x0069, // 8 bit unsigned int
Int16Short = 0x0011, // 16 bit signed
UInt16Short = 0x0021, // 16 bit unsigned
Int16 = 0x0072, // 16 bit signed int
UInt16 = 0x0073, // 16 bit unsigned int
Int32Long = 0x0012, // 32 bit signed
UInt32Long = 0x0022, // 32 bit unsigned
Int32 = 0x0074, // 32 bit signed int
UInt32 = 0x0075, // 32 bit unsigned int
Int64Quad = 0x0013, // 64 bit signed
UInt64Quad = 0x0023, // 64 bit unsigned
Int64 = 0x0076, // 64 bit signed int
UInt64 = 0x0077, // 64 bit unsigned int
Int128Oct = 0x0014, // 128 bit signed int
UInt128Oct = 0x0024, // 128 bit unsigned int
Int128 = 0x0078, // 128 bit signed int
UInt128 = 0x0079, // 128 bit unsigned int
Float16 = 0x0046, // 16 bit real
Float32 = 0x0040, // 32 bit real
Float32PartialPrecision = 0x0045, // 32 bit PP real
Float48 = 0x0044, // 48 bit real
Float64 = 0x0041, // 64 bit real
Float80 = 0x0042, // 80 bit real
Float128 = 0x0043, // 128 bit real
Complex16 = 0x0056, // 16 bit complex
Complex32 = 0x0050, // 32 bit complex
Complex32PartialPrecision = 0x0055, // 32 bit PP complex
Complex48 = 0x0054, // 48 bit complex
Complex64 = 0x0051, // 64 bit complex
Complex80 = 0x0052, // 80 bit complex
Complex128 = 0x0053, // 128 bit complex
Boolean8 = 0x0030, // 8 bit boolean
Boolean16 = 0x0031, // 16 bit boolean
Boolean32 = 0x0032, // 32 bit boolean
Boolean64 = 0x0033, // 64 bit boolean
Boolean128 = 0x0034, // 128 bit boolean
};
enum class SimpleTypeMode : uint32_t {
Direct = 0x00000000, // Not a pointer
NearPointer = 0x00000100, // Near pointer
FarPointer = 0x00000200, // Far pointer
HugePointer = 0x00000300, // Huge pointer
NearPointer32 = 0x00000400, // 32 bit near pointer
FarPointer32 = 0x00000500, // 32 bit far pointer
NearPointer64 = 0x00000600, // 64 bit near pointer
NearPointer128 = 0x00000700 // 128 bit near pointer
};
/// A 32-bit type reference. Types are indexed by their order of appearance in
/// .debug$T plus 0x1000. Type indices less than 0x1000 are "simple" types,
/// composed of a SimpleTypeMode byte followed by a SimpleTypeKind byte.
class TypeIndex {
public:
static const uint32_t FirstNonSimpleIndex = 0x1000;
static const uint32_t SimpleKindMask = 0x000000ff;
static const uint32_t SimpleModeMask = 0x00000700;
static const uint32_t DecoratedItemIdMask = 0x80000000;
public:
TypeIndex() : Index(static_cast<uint32_t>(SimpleTypeKind::None)) {}
explicit TypeIndex(uint32_t Index) : Index(Index) {}
explicit TypeIndex(SimpleTypeKind Kind)
: Index(static_cast<uint32_t>(Kind)) {}
TypeIndex(SimpleTypeKind Kind, SimpleTypeMode Mode)
: Index(static_cast<uint32_t>(Kind) | static_cast<uint32_t>(Mode)) {}
uint32_t getIndex() const { return Index; }
void setIndex(uint32_t I) { Index = I; }
bool isSimple() const { return Index < FirstNonSimpleIndex; }
bool isDecoratedItemId() const { return !!(Index & DecoratedItemIdMask); }
bool isNoneType() const { return *this == None(); }
uint32_t toArrayIndex() const {
assert(!isSimple());
return getIndex() - FirstNonSimpleIndex;
}
static TypeIndex fromArrayIndex(uint32_t Index) {
return TypeIndex(Index + FirstNonSimpleIndex);
}
SimpleTypeKind getSimpleKind() const {
assert(isSimple());
return static_cast<SimpleTypeKind>(Index & SimpleKindMask);
}
SimpleTypeMode getSimpleMode() const {
assert(isSimple());
return static_cast<SimpleTypeMode>(Index & SimpleModeMask);
}
TypeIndex makeDirect() const { return TypeIndex{getSimpleKind()}; }
static TypeIndex None() { return TypeIndex(SimpleTypeKind::None); }
static TypeIndex Void() { return TypeIndex(SimpleTypeKind::Void); }
static TypeIndex VoidPointer32() {
return TypeIndex(SimpleTypeKind::Void, SimpleTypeMode::NearPointer32);
}
static TypeIndex VoidPointer64() {
return TypeIndex(SimpleTypeKind::Void, SimpleTypeMode::NearPointer64);
}
static TypeIndex NullptrT() {
// std::nullptr_t uses the pointer mode that doesn't indicate bit-width,
// presumably because std::nullptr_t is intended to be compatible with any
// pointer type.
return TypeIndex(SimpleTypeKind::Void, SimpleTypeMode::NearPointer);
}
static TypeIndex SignedCharacter() {
return TypeIndex(SimpleTypeKind::SignedCharacter);
}
static TypeIndex UnsignedCharacter() {
return TypeIndex(SimpleTypeKind::UnsignedCharacter);
}
static TypeIndex NarrowCharacter() {
return TypeIndex(SimpleTypeKind::NarrowCharacter);
}
static TypeIndex WideCharacter() {
return TypeIndex(SimpleTypeKind::WideCharacter);
}
static TypeIndex Int16Short() {
return TypeIndex(SimpleTypeKind::Int16Short);
}
static TypeIndex UInt16Short() {
return TypeIndex(SimpleTypeKind::UInt16Short);
}
static TypeIndex Int32() { return TypeIndex(SimpleTypeKind::Int32); }
static TypeIndex UInt32() { return TypeIndex(SimpleTypeKind::UInt32); }
static TypeIndex Int32Long() { return TypeIndex(SimpleTypeKind::Int32Long); }
static TypeIndex UInt32Long() {
return TypeIndex(SimpleTypeKind::UInt32Long);
}
static TypeIndex Int64() { return TypeIndex(SimpleTypeKind::Int64); }
static TypeIndex UInt64() { return TypeIndex(SimpleTypeKind::UInt64); }
static TypeIndex Int64Quad() { return TypeIndex(SimpleTypeKind::Int64Quad); }
static TypeIndex UInt64Quad() {
return TypeIndex(SimpleTypeKind::UInt64Quad);
}
static TypeIndex Float32() { return TypeIndex(SimpleTypeKind::Float32); }
static TypeIndex Float64() { return TypeIndex(SimpleTypeKind::Float64); }
TypeIndex &operator+=(unsigned N) {
Index += N;
return *this;
}
TypeIndex &operator++() {
Index += 1;
return *this;
}
TypeIndex operator++(int) {
TypeIndex Copy = *this;
operator++();
return Copy;
}
TypeIndex &operator-=(unsigned N) {
assert(Index >= N);
Index -= N;
return *this;
}
TypeIndex &operator--() {
Index -= 1;
return *this;
}
TypeIndex operator--(int) {
TypeIndex Copy = *this;
operator--();
return Copy;
}
friend inline bool operator==(const TypeIndex &A, const TypeIndex &B) {
return A.getIndex() == B.getIndex();
}
friend inline bool operator!=(const TypeIndex &A, const TypeIndex &B) {
return A.getIndex() != B.getIndex();
}
friend inline bool operator<(const TypeIndex &A, const TypeIndex &B) {
return A.getIndex() < B.getIndex();
}
friend inline bool operator<=(const TypeIndex &A, const TypeIndex &B) {
return A.getIndex() <= B.getIndex();
}
friend inline bool operator>(const TypeIndex &A, const TypeIndex &B) {
return A.getIndex() > B.getIndex();
}
friend inline bool operator>=(const TypeIndex &A, const TypeIndex &B) {
return A.getIndex() >= B.getIndex();
}
friend inline TypeIndex operator+(const TypeIndex &A, uint32_t N) {
TypeIndex Result(A);
Result += N;
return Result;
}
friend inline TypeIndex operator-(const TypeIndex &A, uint32_t N) {
assert(A.getIndex() >= N);
TypeIndex Result(A);
Result -= N;
return Result;
}
friend inline uint32_t operator-(const TypeIndex &A, const TypeIndex &B) {
assert(A >= B);
return A.toArrayIndex() - B.toArrayIndex();
}
static StringRef simpleTypeName(TypeIndex TI);
private:
support::ulittle32_t Index;
};
// Used for pseudo-indexing an array of type records. An array of such records
// sorted by TypeIndex can allow log(N) lookups even though such a type record
// stream does not provide random access.
struct TypeIndexOffset {
TypeIndex Type;
support::ulittle32_t Offset;
};
void printTypeIndex(ScopedPrinter &Printer, StringRef FieldName, TypeIndex TI,
TypeCollection &Types);
}
template <> struct DenseMapInfo<codeview::TypeIndex> {
static inline codeview::TypeIndex getEmptyKey() {
return codeview::TypeIndex{DenseMapInfo<uint32_t>::getEmptyKey()};
}
static inline codeview::TypeIndex getTombstoneKey() {
return codeview::TypeIndex{DenseMapInfo<uint32_t>::getTombstoneKey()};
}
static unsigned getHashValue(const codeview::TypeIndex &TI) {
return DenseMapInfo<uint32_t>::getHashValue(TI.getIndex());
}
static bool isEqual(const codeview::TypeIndex &LHS,
const codeview::TypeIndex &RHS) {
return LHS == RHS;
}
};
} // namespace llvm
#endif