forked from OSchip/llvm-project
[PDB] Make the native reader support modified types.
Previously for cv-qualified types, we would just ignore them and they would never get printed. Now we can enumerate them and cache them like any other symbol type. llvm-svn: 342414
This commit is contained in:
parent
8639c5d565
commit
4727ac2394
|
@ -21,7 +21,8 @@ class NativeSession;
|
|||
|
||||
class NativeTypeBuiltin : public NativeRawSymbol {
|
||||
public:
|
||||
NativeTypeBuiltin(NativeSession &PDBSession, SymIndexId Id, PDB_BuiltinType T,
|
||||
NativeTypeBuiltin(NativeSession &PDBSession, SymIndexId Id,
|
||||
codeview::ModifierOptions Mods, PDB_BuiltinType T,
|
||||
uint64_t L);
|
||||
~NativeTypeBuiltin() override;
|
||||
|
||||
|
@ -37,6 +38,7 @@ public:
|
|||
|
||||
protected:
|
||||
NativeSession &Session;
|
||||
codeview::ModifierOptions Mods;
|
||||
PDB_BuiltinType Type;
|
||||
uint64_t Length;
|
||||
};
|
||||
|
|
|
@ -18,11 +18,15 @@
|
|||
namespace llvm {
|
||||
namespace pdb {
|
||||
|
||||
class NativeTypeEnum : public NativeRawSymbol,
|
||||
public codeview::TypeVisitorCallbacks {
|
||||
class NativeTypeEnum : public NativeRawSymbol {
|
||||
public:
|
||||
NativeTypeEnum(NativeSession &Session, SymIndexId Id, codeview::TypeIndex TI,
|
||||
codeview::EnumRecord Record);
|
||||
|
||||
NativeTypeEnum(NativeSession &Session, SymIndexId Id,
|
||||
codeview::TypeIndex ModifierTI,
|
||||
codeview::ModifierRecord Modifier,
|
||||
codeview::EnumRecord EnumRecord);
|
||||
~NativeTypeEnum() override;
|
||||
|
||||
void dump(raw_ostream &OS, int Indent) const override;
|
||||
|
@ -30,11 +34,6 @@ public:
|
|||
std::unique_ptr<IPDBEnumSymbols>
|
||||
findChildren(PDB_SymType Type) const override;
|
||||
|
||||
Error visitKnownRecord(codeview::CVType &CVR,
|
||||
codeview::EnumRecord &Record) override;
|
||||
Error visitKnownMember(codeview::CVMemberRecord &CVM,
|
||||
codeview::EnumeratorRecord &Record) override;
|
||||
|
||||
PDB_BuiltinType getBuiltinType() const override;
|
||||
PDB_SymType getSymTag() const override;
|
||||
SymIndexId getUnmodifiedTypeId() const override;
|
||||
|
@ -43,6 +42,9 @@ public:
|
|||
bool hasCastOperator() const override;
|
||||
uint64_t getLength() const override;
|
||||
std::string getName() const override;
|
||||
bool isConstType() const override;
|
||||
bool isVolatileType() const override;
|
||||
bool isUnalignedType() const override;
|
||||
bool isNested() const override;
|
||||
bool hasOverloadedOperator() const override;
|
||||
bool hasNestedTypes() const override;
|
||||
|
@ -57,6 +59,7 @@ public:
|
|||
protected:
|
||||
codeview::TypeIndex Index;
|
||||
codeview::EnumRecord Record;
|
||||
Optional<codeview::ModifierRecord> Modifiers;
|
||||
};
|
||||
|
||||
} // namespace pdb
|
||||
|
|
|
@ -53,6 +53,12 @@ class SymbolCache {
|
|||
TI, std::move(Record), std::forward<Args>(ConstructorArgs)...);
|
||||
}
|
||||
|
||||
SymIndexId createSymbolForModifiedType(codeview::TypeIndex ModifierTI,
|
||||
codeview::CVType CVT);
|
||||
|
||||
SymIndexId createSimpleType(codeview::TypeIndex TI,
|
||||
codeview::ModifierOptions Mods);
|
||||
|
||||
public:
|
||||
SymbolCache(NativeSession &Session, DbiStream *Dbi);
|
||||
|
||||
|
|
|
@ -9,29 +9,44 @@
|
|||
|
||||
#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
|
||||
|
||||
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
|
||||
#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
|
||||
#include "llvm/DebugInfo/PDB/PDBSymbol.h"
|
||||
#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace pdb {
|
||||
using namespace llvm;
|
||||
using namespace llvm::codeview;
|
||||
using namespace llvm::pdb;
|
||||
|
||||
NativeEnumTypes::NativeEnumTypes(NativeSession &PDBSession,
|
||||
codeview::LazyRandomTypeCollection &Types,
|
||||
codeview::TypeLeafKind Kind)
|
||||
LazyRandomTypeCollection &Types,
|
||||
TypeLeafKind Kind)
|
||||
: Matches(), Index(0), Session(PDBSession) {
|
||||
for (auto Index = Types.getFirst(); Index;
|
||||
Index = Types.getNext(Index.getValue())) {
|
||||
if (Types.getType(Index.getValue()).kind() == Kind)
|
||||
Matches.push_back(Index.getValue());
|
||||
Optional<TypeIndex> TI = Types.getFirst();
|
||||
while (TI) {
|
||||
CVType CVT = Types.getType(*TI);
|
||||
TypeLeafKind K = CVT.kind();
|
||||
if (K == Kind)
|
||||
Matches.push_back(*TI);
|
||||
else if (K == TypeLeafKind::LF_MODIFIER) {
|
||||
ModifierRecord MR;
|
||||
if (auto EC = TypeDeserializer::deserializeAs<ModifierRecord>(CVT, MR)) {
|
||||
consumeError(std::move(EC));
|
||||
} else if (!MR.ModifiedType.isSimple()) {
|
||||
CVType UnmodifiedCVT = Types.getType(MR.ModifiedType);
|
||||
if (UnmodifiedCVT.kind() == Kind)
|
||||
Matches.push_back(*TI);
|
||||
}
|
||||
}
|
||||
TI = Types.getNext(*TI);
|
||||
}
|
||||
}
|
||||
|
||||
NativeEnumTypes::NativeEnumTypes(
|
||||
NativeSession &PDBSession, const std::vector<codeview::TypeIndex> &Matches,
|
||||
codeview::TypeLeafKind Kind)
|
||||
NativeEnumTypes::NativeEnumTypes(NativeSession &PDBSession,
|
||||
const std::vector<TypeIndex> &Matches,
|
||||
TypeLeafKind Kind)
|
||||
: Matches(Matches), Index(0), Session(PDBSession) {}
|
||||
|
||||
uint32_t NativeEnumTypes::getChildCount() const {
|
||||
|
@ -53,6 +68,3 @@ std::unique_ptr<PDBSymbol> NativeEnumTypes::getNext() {
|
|||
}
|
||||
|
||||
void NativeEnumTypes::reset() { Index = 0; }
|
||||
|
||||
} // namespace pdb
|
||||
} // namespace llvm
|
||||
|
|
|
@ -14,9 +14,10 @@ namespace llvm {
|
|||
namespace pdb {
|
||||
|
||||
NativeTypeBuiltin::NativeTypeBuiltin(NativeSession &PDBSession, SymIndexId Id,
|
||||
codeview::ModifierOptions Mods,
|
||||
PDB_BuiltinType T, uint64_t L)
|
||||
: NativeRawSymbol(PDBSession, PDB_SymType::BuiltinType, Id),
|
||||
Session(PDBSession), Type(T), Length(L) {}
|
||||
Session(PDBSession), Mods(Mods), Type(T), Length(L) {}
|
||||
|
||||
NativeTypeBuiltin::~NativeTypeBuiltin() {}
|
||||
|
||||
|
|
|
@ -28,6 +28,13 @@ NativeTypeEnum::NativeTypeEnum(NativeSession &Session, SymIndexId Id,
|
|||
: NativeRawSymbol(Session, PDB_SymType::Enum, Id), Index(Index),
|
||||
Record(std::move(Record)) {}
|
||||
|
||||
NativeTypeEnum::NativeTypeEnum(NativeSession &Session, SymIndexId Id,
|
||||
codeview::TypeIndex ModifierTI,
|
||||
codeview::ModifierRecord Modifier,
|
||||
codeview::EnumRecord EnumRecord)
|
||||
: NativeRawSymbol(Session, PDB_SymType::Enum, Id), Index(ModifierTI),
|
||||
Record(std::move(EnumRecord)), Modifiers(std::move(Modifier)) {}
|
||||
|
||||
NativeTypeEnum::~NativeTypeEnum() {}
|
||||
|
||||
void NativeTypeEnum::dump(raw_ostream &OS, int Indent) const {
|
||||
|
@ -38,6 +45,8 @@ void NativeTypeEnum::dump(raw_ostream &OS, int Indent) const {
|
|||
dumpSymbolField(OS, "lexicalParentId", 0, Indent);
|
||||
dumpSymbolField(OS, "name", getName(), Indent);
|
||||
dumpSymbolField(OS, "typeId", getTypeId(), Indent);
|
||||
if (Modifiers.hasValue())
|
||||
dumpSymbolField(OS, "unmodifiedTypeId", getUnmodifiedTypeId(), Indent);
|
||||
dumpSymbolField(OS, "length", getLength(), Indent);
|
||||
dumpSymbolField(OS, "constructor", hasConstructor(), Indent);
|
||||
dumpSymbolField(OS, "constType", isConstType(), Indent);
|
||||
|
@ -68,17 +77,6 @@ NativeTypeEnum::findChildren(PDB_SymType Type) const {
|
|||
}
|
||||
}
|
||||
|
||||
Error NativeTypeEnum::visitKnownRecord(codeview::CVType &CVR,
|
||||
codeview::EnumRecord &ER) {
|
||||
Record = ER;
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error NativeTypeEnum::visitKnownMember(codeview::CVMemberRecord &CVM,
|
||||
codeview::EnumeratorRecord &R) {
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
PDB_SymType NativeTypeEnum::getSymTag() const { return PDB_SymType::Enum; }
|
||||
|
||||
PDB_BuiltinType NativeTypeEnum::getBuiltinType() const {
|
||||
|
@ -149,9 +147,10 @@ PDB_BuiltinType NativeTypeEnum::getBuiltinType() const {
|
|||
}
|
||||
|
||||
SymIndexId NativeTypeEnum::getUnmodifiedTypeId() const {
|
||||
// FIXME: If this is const, volatile, or unaligned, we should return the
|
||||
// SymIndexId of the unmodified type here.
|
||||
return 0;
|
||||
if (!Modifiers)
|
||||
return 0;
|
||||
return Session.getSymbolCache().findSymbolByTypeIndex(
|
||||
Modifiers->ModifiedType);
|
||||
}
|
||||
|
||||
bool NativeTypeEnum::hasConstructor() const {
|
||||
|
@ -215,3 +214,24 @@ bool NativeTypeEnum::isRefUdt() const { return false; }
|
|||
bool NativeTypeEnum::isValueUdt() const { return false; }
|
||||
|
||||
bool NativeTypeEnum::isInterfaceUdt() const { return false; }
|
||||
|
||||
bool NativeTypeEnum::isConstType() const {
|
||||
if (!Modifiers)
|
||||
return false;
|
||||
return ((Modifiers->getModifiers() & ModifierOptions::Const) !=
|
||||
ModifierOptions::None);
|
||||
}
|
||||
|
||||
bool NativeTypeEnum::isVolatileType() const {
|
||||
if (!Modifiers)
|
||||
return false;
|
||||
return ((Modifiers->getModifiers() & ModifierOptions::Volatile) !=
|
||||
ModifierOptions::None);
|
||||
}
|
||||
|
||||
bool NativeTypeEnum::isUnalignedType() const {
|
||||
if (!Modifiers)
|
||||
return false;
|
||||
return ((Modifiers->getModifiers() & ModifierOptions::Unaligned) !=
|
||||
ModifierOptions::None);
|
||||
}
|
||||
|
|
|
@ -42,8 +42,6 @@ void NativeTypePointer::dump(raw_ostream &OS, int Indent) const {
|
|||
dumpSymbolField(OS, "volatileType", isVolatileType(), Indent);
|
||||
}
|
||||
|
||||
bool NativeTypePointer::isConstType() const { return false; }
|
||||
|
||||
uint64_t NativeTypePointer::getLength() const { return Record.getSize(); }
|
||||
|
||||
SymIndexId NativeTypePointer::getTypeId() const {
|
||||
|
@ -68,8 +66,21 @@ bool NativeTypePointer::isPointerToMemberFunction() const {
|
|||
return Record.getMode() == PointerMode::PointerToMemberFunction;
|
||||
}
|
||||
|
||||
bool NativeTypePointer::isRestrictedType() const { return false; }
|
||||
bool NativeTypePointer::isConstType() const {
|
||||
return (Record.getOptions() & PointerOptions::Const) != PointerOptions::None;
|
||||
}
|
||||
|
||||
bool NativeTypePointer::isVolatileType() const { return false; }
|
||||
bool NativeTypePointer::isRestrictedType() const {
|
||||
return (Record.getOptions() & PointerOptions::Restrict) !=
|
||||
PointerOptions::None;
|
||||
}
|
||||
|
||||
bool NativeTypePointer::isUnalignedType() const { return false; }
|
||||
bool NativeTypePointer::isVolatileType() const {
|
||||
return (Record.getOptions() & PointerOptions::Volatile) !=
|
||||
PointerOptions::None;
|
||||
}
|
||||
|
||||
bool NativeTypePointer::isUnalignedType() const {
|
||||
return (Record.getOptions() & PointerOptions::Unaligned) !=
|
||||
PointerOptions::None;
|
||||
}
|
||||
|
|
|
@ -60,6 +60,72 @@ SymbolCache::createTypeEnumerator(codeview::TypeLeafKind Kind) {
|
|||
new NativeEnumTypes(Session, Types, Kind));
|
||||
}
|
||||
|
||||
SymIndexId SymbolCache::createSimpleType(TypeIndex Index,
|
||||
ModifierOptions Mods) {
|
||||
// FIXME: We will eventually need to handle pointers to other simple types,
|
||||
// which are still simple types in the world of CodeView TypeIndexes.
|
||||
if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct)
|
||||
return 0;
|
||||
|
||||
const auto Kind = Index.getSimpleKind();
|
||||
const auto It = std::find_if(
|
||||
std::begin(BuiltinTypes), std::end(BuiltinTypes),
|
||||
[Kind](const BuiltinTypeEntry &Builtin) { return Builtin.Kind == Kind; });
|
||||
if (It == std::end(BuiltinTypes))
|
||||
return 0;
|
||||
SymIndexId Id = Cache.size();
|
||||
Cache.emplace_back(llvm::make_unique<NativeTypeBuiltin>(Session, Id, Mods,
|
||||
It->Type, It->Size));
|
||||
TypeIndexToSymbolId[Index] = Id;
|
||||
return Id;
|
||||
}
|
||||
|
||||
SymIndexId
|
||||
SymbolCache::createSymbolForModifiedType(codeview::TypeIndex ModifierTI,
|
||||
codeview::CVType CVT) {
|
||||
ModifierRecord Record;
|
||||
if (auto EC = TypeDeserializer::deserializeAs<ModifierRecord>(CVT, Record)) {
|
||||
consumeError(std::move(EC));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (Record.ModifiedType.isSimple())
|
||||
return createSimpleType(Record.ModifiedType, Record.Modifiers);
|
||||
|
||||
auto Tpi = Session.getPDBFile().getPDBTpiStream();
|
||||
if (!Tpi) {
|
||||
consumeError(Tpi.takeError());
|
||||
return 0;
|
||||
}
|
||||
codeview::LazyRandomTypeCollection &Types = Tpi->typeCollection();
|
||||
|
||||
codeview::CVType UnmodifiedType = Types.getType(Record.ModifiedType);
|
||||
|
||||
switch (UnmodifiedType.kind()) {
|
||||
case LF_ENUM: {
|
||||
EnumRecord ER;
|
||||
if (auto EC =
|
||||
TypeDeserializer::deserializeAs<EnumRecord>(UnmodifiedType, ER)) {
|
||||
consumeError(std::move(EC));
|
||||
return 0;
|
||||
}
|
||||
return createSymbol<NativeTypeEnum>(Record.ModifiedType, std::move(Record),
|
||||
std::move(ER));
|
||||
}
|
||||
case LF_STRUCTURE:
|
||||
case LF_UNION:
|
||||
case LF_CLASS:
|
||||
// FIXME: Handle these
|
||||
break;
|
||||
default:
|
||||
// No other types can be modified. (LF_POINTER, for example, records
|
||||
// its modifiers a different way.
|
||||
assert(false && "Invalid LF_MODIFIER record");
|
||||
break;
|
||||
}
|
||||
return createSymbolPlaceholder();
|
||||
}
|
||||
|
||||
SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) {
|
||||
// First see if it's already in our cache.
|
||||
const auto Entry = TypeIndexToSymbolId.find(Index);
|
||||
|
@ -67,25 +133,8 @@ SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) {
|
|||
return Entry->second;
|
||||
|
||||
// Symbols for built-in types are created on the fly.
|
||||
if (Index.isSimple()) {
|
||||
// FIXME: We will eventually need to handle pointers to other simple types,
|
||||
// which are still simple types in the world of CodeView TypeIndexes.
|
||||
if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct)
|
||||
return 0;
|
||||
const auto Kind = Index.getSimpleKind();
|
||||
const auto It =
|
||||
std::find_if(std::begin(BuiltinTypes), std::end(BuiltinTypes),
|
||||
[Kind](const BuiltinTypeEntry &Builtin) {
|
||||
return Builtin.Kind == Kind;
|
||||
});
|
||||
if (It == std::end(BuiltinTypes))
|
||||
return 0;
|
||||
SymIndexId Id = Cache.size();
|
||||
Cache.emplace_back(
|
||||
llvm::make_unique<NativeTypeBuiltin>(Session, Id, It->Type, It->Size));
|
||||
TypeIndexToSymbolId[Index] = Id;
|
||||
return Id;
|
||||
}
|
||||
if (Index.isSimple())
|
||||
return createSimpleType(Index, ModifierOptions::None);
|
||||
|
||||
// We need to instantiate and cache the desired type symbol.
|
||||
auto Tpi = Session.getPDBFile().getPDBTpiStream();
|
||||
|
@ -97,6 +146,7 @@ SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) {
|
|||
codeview::CVType CVT = Types.getType(Index);
|
||||
// TODO(amccarth): Make this handle all types.
|
||||
SymIndexId Id = 0;
|
||||
|
||||
switch (CVT.kind()) {
|
||||
case codeview::LF_ENUM:
|
||||
Id = createSymbolForType<NativeTypeEnum, EnumRecord>(Index, std::move(CVT));
|
||||
|
@ -105,6 +155,9 @@ SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) {
|
|||
Id = createSymbolForType<NativeTypePointer, PointerRecord>(Index,
|
||||
std::move(CVT));
|
||||
break;
|
||||
case codeview::LF_MODIFIER:
|
||||
Id = createSymbolForModifiedType(Index, std::move(CVT));
|
||||
break;
|
||||
default:
|
||||
Id = createSymbolPlaceholder();
|
||||
break;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
ENUMS: enum FooClass::NestedEnum {
|
||||
ENUMS-NEXT: }
|
||||
ENUMS: const volatile enum FooClass::NestedEnum
|
||||
|
||||
DUMP: {
|
||||
DUMP-NEXT: symIndexId: 2
|
||||
|
@ -223,3 +224,27 @@ DUMP-NEXT: unalignedType: 0
|
|||
DUMP-NEXT: isValueUdt: 0
|
||||
DUMP-NEXT: volatileType: 0
|
||||
DUMP-NEXT: }
|
||||
DUMP-NEXT: {
|
||||
DUMP-NEXT: symIndexId: 12
|
||||
DUMP-NEXT: symTag: 12
|
||||
DUMP-NEXT: baseType: 6
|
||||
DUMP-NEXT: lexicalParentId: 0
|
||||
DUMP-NEXT: name: FooClass::NestedEnum
|
||||
DUMP-NEXT: typeId: 3
|
||||
DUMP-NEXT: length: 4
|
||||
DUMP-NEXT: constructor: 0
|
||||
DUMP-NEXT: constType: 1
|
||||
DUMP-NEXT: hasAssignmentOperator: 0
|
||||
DUMP-NEXT: hasCastOperator: 0
|
||||
DUMP-NEXT: hasNestedTypes: 0
|
||||
DUMP-NEXT: overloadedOperator: 0
|
||||
DUMP-NEXT: isInterfaceUdt: 0
|
||||
DUMP-NEXT: intrinsic: 0
|
||||
DUMP-NEXT: nested: 1
|
||||
DUMP-NEXT: packed: 0
|
||||
DUMP-NEXT: isRefUdt: 0
|
||||
DUMP-NEXT: scoped: 0
|
||||
DUMP-NEXT: unalignedType: 0
|
||||
DUMP-NEXT: isValueUdt: 0
|
||||
DUMP-NEXT: volatileType: 1
|
||||
DUMP-NEXT: }
|
||||
|
|
Loading…
Reference in New Issue