mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 20:39:47 +00:00
[PDB] Make the native reader support enumerators.
Previously we would dump the names of enum types, but not their enumerator values. This adds support for enumerator values. In doing so, we have to introduce a general purpose mechanism for caching symbol indices of field list members. Unlike global types, FieldList members do not have a TypeIndex. So instead, we identify them by the pair {TypeIndexOfFieldList, IndexInFieldList}. llvm-svn: 342415
This commit is contained in:
parent
1ff1310572
commit
210ae53b0e
@ -29,6 +29,21 @@ public:
|
||||
virtual void reset() = 0;
|
||||
};
|
||||
|
||||
template <typename ChildType>
|
||||
class NullEnumerator : public IPDBEnumChildren<ChildType> {
|
||||
virtual uint32_t getChildCount() const override { return 0; }
|
||||
virtual std::unique_ptr<ChildType>
|
||||
getChildAtIndex(uint32_t Index) const override {
|
||||
assert(false);
|
||||
return nullptr;
|
||||
}
|
||||
virtual std::unique_ptr<ChildType> getNext() override {
|
||||
assert(false);
|
||||
return nullptr;
|
||||
}
|
||||
virtual void reset() override {}
|
||||
};
|
||||
|
||||
} // end namespace pdb
|
||||
} // end namespace llvm
|
||||
|
||||
|
50
include/llvm/DebugInfo/PDB/Native/NativeSymbolEnumerator.h
Normal file
50
include/llvm/DebugInfo/PDB/Native/NativeSymbolEnumerator.h
Normal file
@ -0,0 +1,50 @@
|
||||
//===- NativeSymbolEnumerator.h - info about enumerator values --*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVESYMBOLENUMERATOR_H
|
||||
#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVESYMBOLENUMERATOR_H
|
||||
|
||||
#include "llvm/DebugInfo/CodeView/CodeView.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace pdb {
|
||||
class NativeTypeEnum;
|
||||
|
||||
class NativeSymbolEnumerator : public NativeRawSymbol {
|
||||
public:
|
||||
NativeSymbolEnumerator(NativeSession &Session, SymIndexId Id,
|
||||
const NativeTypeEnum &Parent,
|
||||
codeview::EnumeratorRecord Record);
|
||||
|
||||
~NativeSymbolEnumerator() override;
|
||||
|
||||
void dump(raw_ostream &OS, int Indent) const override;
|
||||
|
||||
SymIndexId getClassParentId() const override;
|
||||
SymIndexId getLexicalParentId() const override;
|
||||
std::string getName() const override;
|
||||
SymIndexId getTypeId() const override;
|
||||
PDB_DataKind getDataKind() const override;
|
||||
PDB_LocType getLocationType() const override;
|
||||
bool isConstType() const override;
|
||||
bool isVolatileType() const override;
|
||||
bool isUnalignedType() const override;
|
||||
Variant getValue() const override;
|
||||
|
||||
protected:
|
||||
const NativeTypeEnum &Parent;
|
||||
codeview::EnumeratorRecord Record;
|
||||
};
|
||||
|
||||
} // namespace pdb
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEENUM_H
|
@ -18,6 +18,8 @@
|
||||
namespace llvm {
|
||||
namespace pdb {
|
||||
|
||||
class NativeTypeBuiltin;
|
||||
|
||||
class NativeTypeEnum : public NativeRawSymbol {
|
||||
public:
|
||||
NativeTypeEnum(NativeSession &Session, SymIndexId Id, codeview::TypeIndex TI,
|
||||
@ -56,6 +58,8 @@ public:
|
||||
bool isValueUdt() const override;
|
||||
bool isInterfaceUdt() const override;
|
||||
|
||||
const NativeTypeBuiltin &getUnderlyingBuiltinType() const;
|
||||
|
||||
protected:
|
||||
codeview::TypeIndex Index;
|
||||
codeview::EnumRecord Record;
|
||||
|
@ -31,6 +31,8 @@ class SymbolCache {
|
||||
|
||||
std::vector<std::unique_ptr<NativeRawSymbol>> Cache;
|
||||
DenseMap<codeview::TypeIndex, SymIndexId> TypeIndexToSymbolId;
|
||||
DenseMap<std::pair<codeview::TypeIndex, uint32_t>, SymIndexId>
|
||||
FieldListMembersToSymbolId;
|
||||
std::vector<SymIndexId> Compilands;
|
||||
|
||||
SymIndexId createSymbolPlaceholder() {
|
||||
@ -77,6 +79,23 @@ public:
|
||||
|
||||
SymIndexId findSymbolByTypeIndex(codeview::TypeIndex TI);
|
||||
|
||||
template <typename ConcreteSymbolT, typename... Args>
|
||||
SymIndexId getOrCreateFieldListMember(codeview::TypeIndex FieldListTI,
|
||||
uint32_t Index,
|
||||
Args &&... ConstructorArgs) {
|
||||
SymIndexId SymId = Cache.size();
|
||||
std::pair<codeview::TypeIndex, uint32_t> Key{FieldListTI, Index};
|
||||
auto Result = FieldListMembersToSymbolId.try_emplace(Key, SymId);
|
||||
if (Result.second) {
|
||||
auto NewSymbol = llvm::make_unique<ConcreteSymbolT>(
|
||||
Session, SymId, std::forward<Args>(ConstructorArgs)...);
|
||||
Cache.push_back(std::move(NewSymbol));
|
||||
} else {
|
||||
SymId = Result.first->second;
|
||||
}
|
||||
return SymId;
|
||||
}
|
||||
|
||||
std::unique_ptr<PDBSymbolCompiland> getOrCreateCompiland(uint32_t Index);
|
||||
uint32_t getNumCompilands() const;
|
||||
|
||||
|
@ -336,6 +336,36 @@ enum PDB_VariantType {
|
||||
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;
|
||||
}
|
||||
|
@ -51,6 +51,7 @@ add_pdb_impl_folder(Native
|
||||
Native/NativeEnumTypes.cpp
|
||||
Native/NativeExeSymbol.cpp
|
||||
Native/NativeRawSymbol.cpp
|
||||
Native/NativeSymbolEnumerator.cpp
|
||||
Native/NativeTypeBuiltin.cpp
|
||||
Native/NativeTypeEnum.cpp
|
||||
Native/NativeTypePointer.cpp
|
||||
|
@ -141,6 +141,15 @@ PrivateGetDIAValue(IDiaSymbol *Symbol,
|
||||
return IdResult;
|
||||
}
|
||||
|
||||
template <typename PrintType, typename ArgType>
|
||||
void DumpDIAValueAs(llvm::raw_ostream &OS, int Indent, StringRef Name,
|
||||
IDiaSymbol *Symbol,
|
||||
HRESULT (__stdcall IDiaSymbol::*Method)(ArgType *)) {
|
||||
ArgType Value;
|
||||
if (S_OK == (Symbol->*Method)(&Value))
|
||||
dumpSymbolField(OS, Name, static_cast<PrintType>(Value), Indent);
|
||||
}
|
||||
|
||||
template <typename ArgType>
|
||||
void DumpDIAValue(llvm::raw_ostream &OS, int Indent, StringRef Name,
|
||||
IDiaSymbol *Symbol,
|
||||
@ -194,6 +203,10 @@ DIARawSymbol::DIARawSymbol(const DIASession &PDBSession,
|
||||
DumpDIAValue(Stream, Indent, StringRef{#Method}, Symbol, \
|
||||
&IDiaSymbol::get_##Method);
|
||||
|
||||
#define RAW_METHOD_DUMP_AS(Stream, Method, Type) \
|
||||
DumpDIAValueAs<Type>(Stream, Indent, StringRef{#Method}, Symbol, \
|
||||
&IDiaSymbol::get_##Method);
|
||||
|
||||
void DIARawSymbol::dump(raw_ostream &OS, int Indent) const {
|
||||
RAW_METHOD_DUMP(OS, symIndexId);
|
||||
RAW_METHOD_DUMP(OS, symTag);
|
||||
@ -267,12 +280,12 @@ void DIARawSymbol::dump(raw_ostream &OS, int Indent) const {
|
||||
RAW_METHOD_DUMP(OS, virtualBaseDispIndex);
|
||||
RAW_METHOD_DUMP(OS, virtualBaseOffset);
|
||||
RAW_METHOD_DUMP(OS, virtualTableShapeId);
|
||||
RAW_METHOD_DUMP(OS, dataKind);
|
||||
RAW_METHOD_DUMP_AS(OS, dataKind, PDB_DataKind);
|
||||
RAW_METHOD_DUMP(OS, guid);
|
||||
RAW_METHOD_DUMP(OS, offset);
|
||||
RAW_METHOD_DUMP(OS, thisAdjust);
|
||||
RAW_METHOD_DUMP(OS, virtualBasePointerOffset);
|
||||
RAW_METHOD_DUMP(OS, locationType);
|
||||
RAW_METHOD_DUMP_AS(OS, locationType, PDB_LocType);
|
||||
RAW_METHOD_DUMP(OS, machineType);
|
||||
RAW_METHOD_DUMP(OS, thunkOrdinal);
|
||||
RAW_METHOD_DUMP(OS, length);
|
||||
|
116
lib/DebugInfo/PDB/Native/NativeSymbolEnumerator.cpp
Normal file
116
lib/DebugInfo/PDB/Native/NativeSymbolEnumerator.cpp
Normal file
@ -0,0 +1,116 @@
|
||||
//===- NativeSymbolEnumerator.cpp - info about enumerators ------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/DebugInfo/PDB/Native/NativeSymbolEnumerator.h"
|
||||
|
||||
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::codeview;
|
||||
using namespace llvm::pdb;
|
||||
|
||||
NativeSymbolEnumerator::NativeSymbolEnumerator(
|
||||
NativeSession &Session, SymIndexId Id, const NativeTypeEnum &Parent,
|
||||
codeview::EnumeratorRecord Record)
|
||||
: NativeRawSymbol(Session, PDB_SymType::Data, Id), Parent(Parent),
|
||||
Record(std::move(Record)) {}
|
||||
|
||||
NativeSymbolEnumerator::~NativeSymbolEnumerator() {}
|
||||
|
||||
void NativeSymbolEnumerator::dump(raw_ostream &OS, int Indent) const {
|
||||
NativeRawSymbol::dump(OS, Indent);
|
||||
dumpSymbolField(OS, "classParentId", getClassParentId(), Indent);
|
||||
dumpSymbolField(OS, "lexicalParentId", getLexicalParentId(), Indent);
|
||||
dumpSymbolField(OS, "name", getName(), Indent);
|
||||
dumpSymbolField(OS, "typeId", getTypeId(), Indent);
|
||||
dumpSymbolField(OS, "dataKind", getDataKind(), Indent);
|
||||
dumpSymbolField(OS, "locationType", getLocationType(), Indent);
|
||||
dumpSymbolField(OS, "constType", isConstType(), Indent);
|
||||
dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent);
|
||||
dumpSymbolField(OS, "volatileType", isVolatileType(), Indent);
|
||||
dumpSymbolField(OS, "value", getValue(), Indent);
|
||||
}
|
||||
|
||||
SymIndexId NativeSymbolEnumerator::getClassParentId() const {
|
||||
return Parent.getSymIndexId();
|
||||
}
|
||||
|
||||
SymIndexId NativeSymbolEnumerator::getLexicalParentId() const { return 0; }
|
||||
|
||||
std::string NativeSymbolEnumerator::getName() const { return Record.Name; }
|
||||
|
||||
SymIndexId NativeSymbolEnumerator::getTypeId() const {
|
||||
return Parent.getTypeId();
|
||||
}
|
||||
|
||||
PDB_DataKind NativeSymbolEnumerator::getDataKind() const {
|
||||
return PDB_DataKind::Constant;
|
||||
}
|
||||
|
||||
PDB_LocType NativeSymbolEnumerator::getLocationType() const {
|
||||
return PDB_LocType::Constant;
|
||||
}
|
||||
|
||||
bool NativeSymbolEnumerator::isConstType() const { return false; }
|
||||
|
||||
bool NativeSymbolEnumerator::isVolatileType() const { return false; }
|
||||
|
||||
bool NativeSymbolEnumerator::isUnalignedType() const { return false; }
|
||||
|
||||
Variant NativeSymbolEnumerator::getValue() const {
|
||||
const NativeTypeBuiltin &BT = Parent.getUnderlyingBuiltinType();
|
||||
|
||||
switch (BT.getBuiltinType()) {
|
||||
case PDB_BuiltinType::Int:
|
||||
case PDB_BuiltinType::Long:
|
||||
case PDB_BuiltinType::Char: {
|
||||
assert(Record.Value.isSignedIntN(BT.getLength() * 8));
|
||||
int64_t N = Record.Value.getSExtValue();
|
||||
switch (BT.getLength()) {
|
||||
case 1:
|
||||
return Variant{static_cast<int8_t>(N)};
|
||||
case 2:
|
||||
return Variant{static_cast<int16_t>(N)};
|
||||
case 4:
|
||||
return Variant{static_cast<int32_t>(N)};
|
||||
case 8:
|
||||
return Variant{static_cast<int64_t>(N)};
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PDB_BuiltinType::UInt:
|
||||
case PDB_BuiltinType::ULong: {
|
||||
assert(Record.Value.isIntN(BT.getLength() * 8));
|
||||
uint64_t U = Record.Value.getZExtValue();
|
||||
switch (BT.getLength()) {
|
||||
case 1:
|
||||
return Variant{static_cast<uint8_t>(U)};
|
||||
case 2:
|
||||
return Variant{static_cast<uint16_t>(U)};
|
||||
case 4:
|
||||
return Variant{static_cast<uint32_t>(U)};
|
||||
case 8:
|
||||
return Variant{static_cast<uint64_t>(U)};
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PDB_BuiltinType::Bool: {
|
||||
assert(Record.Value.isIntN(BT.getLength() * 8));
|
||||
uint64_t U = Record.Value.getZExtValue();
|
||||
return Variant{static_cast<bool>(U)};
|
||||
}
|
||||
default:
|
||||
assert(false && "Invalid enumeration type");
|
||||
break;
|
||||
}
|
||||
|
||||
return Variant{Record.Value.getSExtValue()};
|
||||
}
|
@ -12,7 +12,11 @@
|
||||
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/NativeSymbolEnumerator.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
|
||||
#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
|
||||
|
||||
#include "llvm/Support/FormatVariadic.h"
|
||||
@ -23,6 +27,95 @@ using namespace llvm;
|
||||
using namespace llvm::codeview;
|
||||
using namespace llvm::pdb;
|
||||
|
||||
namespace {
|
||||
// Yea, this is a pretty terrible class name. But if we have an enum:
|
||||
//
|
||||
// enum Foo {
|
||||
// A,
|
||||
// B
|
||||
// };
|
||||
//
|
||||
// then A and B are the "enumerators" of the "enum" Foo. And we need
|
||||
// to enumerate them.
|
||||
class NativeEnumEnumEnumerators : public IPDBEnumSymbols, TypeVisitorCallbacks {
|
||||
public:
|
||||
NativeEnumEnumEnumerators(NativeSession &Session,
|
||||
const NativeTypeEnum &ClassParent,
|
||||
const codeview::EnumRecord &CVEnum);
|
||||
|
||||
uint32_t getChildCount() const override;
|
||||
std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override;
|
||||
std::unique_ptr<PDBSymbol> getNext() override;
|
||||
void reset() override;
|
||||
|
||||
private:
|
||||
Error visitKnownMember(CVMemberRecord &CVM,
|
||||
EnumeratorRecord &Record) override;
|
||||
Error visitKnownMember(CVMemberRecord &CVM,
|
||||
ListContinuationRecord &Record) override;
|
||||
|
||||
NativeSession &Session;
|
||||
const NativeTypeEnum &ClassParent;
|
||||
const codeview::EnumRecord &CVEnum;
|
||||
std::vector<EnumeratorRecord> Enumerators;
|
||||
Optional<TypeIndex> ContinuationIndex;
|
||||
uint32_t Index = 0;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
NativeEnumEnumEnumerators::NativeEnumEnumEnumerators(
|
||||
NativeSession &Session, const NativeTypeEnum &ClassParent,
|
||||
const codeview::EnumRecord &CVEnum)
|
||||
: Session(Session), ClassParent(ClassParent), CVEnum(CVEnum) {
|
||||
TpiStream &Tpi = cantFail(Session.getPDBFile().getPDBTpiStream());
|
||||
LazyRandomTypeCollection &Types = Tpi.typeCollection();
|
||||
|
||||
ContinuationIndex = CVEnum.FieldList;
|
||||
while (ContinuationIndex) {
|
||||
CVType FieldList = Types.getType(*ContinuationIndex);
|
||||
assert(FieldList.kind() == LF_FIELDLIST);
|
||||
ContinuationIndex.reset();
|
||||
cantFail(visitMemberRecordStream(FieldList.data(), *this));
|
||||
}
|
||||
}
|
||||
|
||||
Error NativeEnumEnumEnumerators::visitKnownMember(CVMemberRecord &CVM,
|
||||
EnumeratorRecord &Record) {
|
||||
Enumerators.push_back(Record);
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error NativeEnumEnumEnumerators::visitKnownMember(
|
||||
CVMemberRecord &CVM, ListContinuationRecord &Record) {
|
||||
ContinuationIndex = Record.ContinuationIndex;
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
uint32_t NativeEnumEnumEnumerators::getChildCount() const {
|
||||
return Enumerators.size();
|
||||
}
|
||||
|
||||
std::unique_ptr<PDBSymbol>
|
||||
NativeEnumEnumEnumerators::getChildAtIndex(uint32_t Index) const {
|
||||
if (Index >= getChildCount())
|
||||
return nullptr;
|
||||
|
||||
SymIndexId Id =
|
||||
Session.getSymbolCache()
|
||||
.getOrCreateFieldListMember<NativeSymbolEnumerator>(
|
||||
CVEnum.FieldList, Index, ClassParent, Enumerators[Index]);
|
||||
return Session.getSymbolCache().getSymbolById(Id);
|
||||
}
|
||||
|
||||
std::unique_ptr<PDBSymbol> NativeEnumEnumEnumerators::getNext() {
|
||||
if (Index >= getChildCount())
|
||||
return nullptr;
|
||||
|
||||
return getChildAtIndex(Index++);
|
||||
}
|
||||
|
||||
void NativeEnumEnumEnumerators::reset() { Index = 0; }
|
||||
|
||||
NativeTypeEnum::NativeTypeEnum(NativeSession &Session, SymIndexId Id,
|
||||
TypeIndex Index, EnumRecord Record)
|
||||
: NativeRawSymbol(Session, PDB_SymType::Enum, Id), Index(Index),
|
||||
@ -67,14 +160,20 @@ void NativeTypeEnum::dump(raw_ostream &OS, int Indent) const {
|
||||
|
||||
std::unique_ptr<IPDBEnumSymbols>
|
||||
NativeTypeEnum::findChildren(PDB_SymType Type) const {
|
||||
switch (Type) {
|
||||
case PDB_SymType::Data: {
|
||||
// TODO(amccarth) : Provide an actual implementation.
|
||||
return nullptr;
|
||||
}
|
||||
default:
|
||||
return nullptr;
|
||||
if (Type != PDB_SymType::Data)
|
||||
return llvm::make_unique<NullEnumerator<PDBSymbol>>();
|
||||
|
||||
const NativeTypeEnum *ClassParent = nullptr;
|
||||
if (!Modifiers)
|
||||
ClassParent = this;
|
||||
else {
|
||||
NativeRawSymbol &NRS =
|
||||
Session.getSymbolCache().getNativeSymbolById(getUnmodifiedTypeId());
|
||||
assert(NRS.getSymTag() == PDB_SymType::Enum);
|
||||
ClassParent = static_cast<NativeTypeEnum *>(&NRS);
|
||||
}
|
||||
return llvm::make_unique<NativeEnumEnumEnumerators>(Session, *ClassParent,
|
||||
Record);
|
||||
}
|
||||
|
||||
PDB_SymType NativeTypeEnum::getSymTag() const { return PDB_SymType::Enum; }
|
||||
@ -86,8 +185,9 @@ PDB_BuiltinType NativeTypeEnum::getBuiltinType() const {
|
||||
|
||||
// This indicates a corrupt record.
|
||||
if (!Underlying.isSimple() ||
|
||||
Underlying.getSimpleMode() != SimpleTypeMode::Direct)
|
||||
Underlying.getSimpleMode() != SimpleTypeMode::Direct) {
|
||||
return PDB_BuiltinType::None;
|
||||
}
|
||||
|
||||
switch (Underlying.getSimpleKind()) {
|
||||
case SimpleTypeKind::Boolean128:
|
||||
@ -98,6 +198,7 @@ PDB_BuiltinType NativeTypeEnum::getBuiltinType() const {
|
||||
return PDB_BuiltinType::Bool;
|
||||
case SimpleTypeKind::NarrowCharacter:
|
||||
case SimpleTypeKind::UnsignedCharacter:
|
||||
case SimpleTypeKind::SignedCharacter:
|
||||
return PDB_BuiltinType::Char;
|
||||
case SimpleTypeKind::WideCharacter:
|
||||
return PDB_BuiltinType::WCharT;
|
||||
@ -149,6 +250,7 @@ PDB_BuiltinType NativeTypeEnum::getBuiltinType() const {
|
||||
SymIndexId NativeTypeEnum::getUnmodifiedTypeId() const {
|
||||
if (!Modifiers)
|
||||
return 0;
|
||||
|
||||
return Session.getSymbolCache().findSymbolByTypeIndex(
|
||||
Modifiers->ModifiedType);
|
||||
}
|
||||
@ -235,3 +337,8 @@ bool NativeTypeEnum::isUnalignedType() const {
|
||||
return ((Modifiers->getModifiers() & ModifierOptions::Unaligned) !=
|
||||
ModifierOptions::None);
|
||||
}
|
||||
|
||||
const NativeTypeBuiltin &NativeTypeEnum::getUnderlyingBuiltinType() const {
|
||||
return Session.getSymbolCache().getNativeSymbolById<NativeTypeBuiltin>(
|
||||
getTypeId());
|
||||
}
|
||||
|
@ -26,14 +26,17 @@ static const struct BuiltinTypeEntry {
|
||||
PDB_BuiltinType Type;
|
||||
uint32_t Size;
|
||||
} BuiltinTypes[] = {
|
||||
{codeview::SimpleTypeKind::Int16Short, PDB_BuiltinType::Int, 2},
|
||||
{codeview::SimpleTypeKind::UInt16Short, PDB_BuiltinType::UInt, 2},
|
||||
{codeview::SimpleTypeKind::Int32, PDB_BuiltinType::Int, 4},
|
||||
{codeview::SimpleTypeKind::UInt32, PDB_BuiltinType::UInt, 4},
|
||||
{codeview::SimpleTypeKind::Int32Long, PDB_BuiltinType::Int, 4},
|
||||
{codeview::SimpleTypeKind::UInt32Long, PDB_BuiltinType::UInt, 4},
|
||||
{codeview::SimpleTypeKind::Int64Quad, PDB_BuiltinType::Int, 8},
|
||||
{codeview::SimpleTypeKind::UInt64Quad, PDB_BuiltinType::UInt, 8},
|
||||
{codeview::SimpleTypeKind::NarrowCharacter, PDB_BuiltinType::Char, 1},
|
||||
{codeview::SimpleTypeKind::SignedCharacter, PDB_BuiltinType::Char, 1},
|
||||
{codeview::SimpleTypeKind::UnsignedCharacter, PDB_BuiltinType::UInt, 1},
|
||||
{codeview::SimpleTypeKind::UInt16Short, PDB_BuiltinType::UInt, 2},
|
||||
{codeview::SimpleTypeKind::Boolean8, PDB_BuiltinType::Bool, 1}
|
||||
// This table can be grown as necessary, but these are the only types we've
|
||||
// needed so far.
|
||||
@ -169,6 +172,8 @@ SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) {
|
||||
|
||||
std::unique_ptr<PDBSymbol>
|
||||
SymbolCache::getSymbolById(SymIndexId SymbolId) const {
|
||||
assert(SymbolId < Cache.size());
|
||||
|
||||
// Id 0 is reserved.
|
||||
if (SymbolId == 0)
|
||||
return nullptr;
|
||||
|
@ -293,7 +293,7 @@ raw_ostream &llvm::pdb::operator<<(raw_ostream &OS, const Variant &Value) {
|
||||
OS << Value.Value.Single;
|
||||
break;
|
||||
case PDB_VariantType::UInt16:
|
||||
OS << Value.Value.Double;
|
||||
OS << Value.Value.UInt16;
|
||||
break;
|
||||
case PDB_VariantType::UInt32:
|
||||
OS << Value.Value.UInt32;
|
||||
|
110
test/DebugInfo/PDB/Inputs/every-enum.cpp
Normal file
110
test/DebugInfo/PDB/Inputs/every-enum.cpp
Normal file
@ -0,0 +1,110 @@
|
||||
// Build with "cl.exe /Zi /GR- /GX- every-enum.cpp /link /debug /nodefaultlib /incremental:no /entry:main"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// clang-format off
|
||||
void *__purecall = 0;
|
||||
|
||||
void __cdecl operator delete(void *,unsigned int) {}
|
||||
void __cdecl operator delete(void *,unsigned __int64) {}
|
||||
|
||||
|
||||
enum I8 : int8_t {
|
||||
I8A = INT8_MIN,
|
||||
I8B = 0,
|
||||
I8C = INT8_MAX
|
||||
};
|
||||
|
||||
enum I16 : int16_t {
|
||||
I16A = INT16_MIN,
|
||||
I16B = 0,
|
||||
I16C = INT16_MAX,
|
||||
};
|
||||
|
||||
enum I32 : int32_t {
|
||||
I32A = INT32_MIN,
|
||||
I32B = 0,
|
||||
I32C = INT32_MAX,
|
||||
};
|
||||
|
||||
enum I64 : int64_t {
|
||||
I64A = INT64_MIN,
|
||||
I64B = 0,
|
||||
I64C = INT64_MAX,
|
||||
};
|
||||
|
||||
enum U8 : uint8_t {
|
||||
U8A = 0,
|
||||
U8B = UINT8_MAX
|
||||
};
|
||||
|
||||
enum U16 : uint16_t {
|
||||
U16A = 0,
|
||||
U16B = UINT16_MAX,
|
||||
};
|
||||
|
||||
enum U32 : uint32_t {
|
||||
U32A = 0,
|
||||
U32B = UINT32_MAX,
|
||||
};
|
||||
|
||||
enum U64 : uint64_t {
|
||||
U64A = 0,
|
||||
U64B = UINT64_MAX,
|
||||
};
|
||||
|
||||
enum Char16 : char16_t {
|
||||
C16A = u'a',
|
||||
C16B = u'b',
|
||||
};
|
||||
|
||||
enum Char32 : char32_t {
|
||||
C32A = U'a',
|
||||
C32B = U'b',
|
||||
};
|
||||
|
||||
enum WChar : wchar_t {
|
||||
WCA = L'a',
|
||||
WCB = L'b',
|
||||
};
|
||||
|
||||
enum Bool : bool {
|
||||
BA = true,
|
||||
BB = false
|
||||
};
|
||||
|
||||
enum class EC {
|
||||
A = 1,
|
||||
B = 2
|
||||
};
|
||||
|
||||
struct Struct {
|
||||
enum Nested {
|
||||
A = 1,
|
||||
B = 2
|
||||
};
|
||||
};
|
||||
|
||||
template<typename T> void f(T t) {}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
f(I8A);
|
||||
f(I16A);
|
||||
f(I32A);
|
||||
f(I64A);
|
||||
f(U8A);
|
||||
f(U16A);
|
||||
f(U32A);
|
||||
f(U64A);
|
||||
|
||||
f(C16A);
|
||||
f(C32A);
|
||||
f(WCA);
|
||||
f(BA);
|
||||
|
||||
|
||||
f(EC::A);
|
||||
f(Struct::A);
|
||||
|
||||
f<const volatile EC>(EC::A);
|
||||
}
|
BIN
test/DebugInfo/PDB/Inputs/every-enum.pdb
Normal file
BIN
test/DebugInfo/PDB/Inputs/every-enum.pdb
Normal file
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -970,6 +970,14 @@ static void dumpDia(StringRef Path) {
|
||||
while (auto Child = Children->getNext()) {
|
||||
outs() << "{";
|
||||
Child->defaultDump(outs(), 2);
|
||||
if (auto Enum = dyn_cast<PDBSymbolTypeEnum>(Child.get())) {
|
||||
auto Enumerators = Enum->findAllChildren<PDBSymbolData>();
|
||||
while (auto Enumerator = Enumerators->getNext()) {
|
||||
outs() << " {";
|
||||
Enumerator->defaultDump(outs(), 4);
|
||||
outs() << "\n }\n";
|
||||
}
|
||||
}
|
||||
outs() << "\n}\n";
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user