[pdb] Get rid of Data and RawData in CVType.

The `CVType` had two redundant fields which were confusing and
error-prone to fill out.  By treating member records as a distinct
type from leaf records, we are able to simplify this quite a bit.

Reviewed By: rnk
Differential Revision: https://reviews.llvm.org/D24432

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@281556 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Zachary Turner 2016-09-14 23:00:16 +00:00
parent a9d16c9445
commit b5689e754e
18 changed files with 283 additions and 130 deletions

View File

@ -22,14 +22,27 @@
namespace llvm {
namespace codeview {
template <typename Kind> struct CVRecord {
uint32_t Length;
template <typename Kind> class CVRecord {
public:
CVRecord() {}
CVRecord(Kind K, ArrayRef<uint8_t> Data) : Type(K), RecordData(Data) {}
uint32_t length() const { return RecordData.size(); }
Kind kind() const { return Type; }
ArrayRef<uint8_t> data() const { return RecordData; }
ArrayRef<uint8_t> content() const {
return RecordData.drop_front(sizeof(RecordPrefix));
}
Optional<uint32_t> hash() const { return Hash; }
void setHash(uint32_t Value) { Hash = Value; }
Kind Type;
ArrayRef<uint8_t> Data;
ArrayRef<uint8_t> RawData;
ArrayRef<uint8_t> RecordData;
Optional<uint32_t> Hash;
};
}
namespace msf {
template <typename Kind>
@ -43,17 +56,17 @@ struct VarStreamArrayExtractor<codeview::CVRecord<Kind>> {
if (auto EC = Reader.readObject(Prefix))
return EC;
Item.Length = Prefix->RecordLen;
if (Item.Length < 2)
if (Prefix->RecordLen < 2)
return make_error<CodeViewError>(cv_error_code::corrupt_record);
Item.Type = static_cast<Kind>(uint16_t(Prefix->RecordKind));
Kind K = static_cast<Kind>(uint16_t(Prefix->RecordKind));
Reader.setOffset(Offset);
ArrayRef<uint8_t> RawData;
if (auto EC =
Reader.readBytes(Item.RawData, Item.Length + sizeof(uint16_t)))
Reader.readBytes(RawData, Prefix->RecordLen + sizeof(uint16_t)))
return EC;
Item.Data = Item.RawData.slice(sizeof(RecordPrefix));
Len = Prefix->RecordLen + 2;
Item = codeview::CVRecord<Kind>(K, RawData);
Len = Item.length();
return Error::success();
}
};

View File

@ -47,7 +47,7 @@ public:
#include "CVSymbolTypes.def"
void visitSymbolRecord(const CVRecord<SymbolKind> &Record) {
ArrayRef<uint8_t> Data = Record.Data;
ArrayRef<uint8_t> Data = Record.content();
auto *DerivedThis = static_cast<Derived *>(this);
DerivedThis->visitSymbolBegin(Record.Type, Data);
uint32_t RecordOffset = Delegate ? Delegate->getRecordOffset(Data) : 0;
@ -70,7 +70,7 @@ public:
SYMBOL_RECORD(EnumVal, EnumVal, AliasName)
#include "CVSymbolTypes.def"
}
DerivedThis->visitSymbolEnd(Record.Type, Record.Data);
DerivedThis->visitSymbolEnd(Record.Type, Record.content());
}
/// Visits the symbol records in Data. Sets the error flag on parse failures.

View File

@ -23,7 +23,8 @@ class CVTypeVisitor {
public:
explicit CVTypeVisitor(TypeVisitorCallbacks &Callbacks);
Error visitTypeRecord(CVRecord<TypeLeafKind> &Record);
Error visitTypeRecord(CVType &Record);
Error visitMemberRecord(CVMemberRecord &Record);
/// Visits the type records in Data. Sets the error flag on parse failures.
Error visitTypeStream(const CVTypeArray &Types);

View File

@ -20,12 +20,13 @@ public:
TypeDeserializer() {}
#define TYPE_RECORD(EnumName, EnumVal, Name) \
Error visitKnownRecord(CVRecord<TypeLeafKind> &CVR, Name##Record &Record) \
override { \
Error visitKnownRecord(CVType &CVR, Name##Record &Record) override { \
return defaultVisitKnownRecord(CVR, Record); \
}
#define MEMBER_RECORD(EnumName, EnumVal, Name) \
TYPE_RECORD(EnumName, EnumVal, Name)
Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override { \
return defaultVisitKnownMember(CVR, Record); \
}
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "TypeRecords.def"
@ -44,13 +45,19 @@ protected:
}
private:
template <typename T>
Error defaultVisitKnownRecord(CVRecord<TypeLeafKind> &CVR, T &Record) {
ArrayRef<uint8_t> RD = CVR.Data;
template <typename T> Error defaultVisitKnownRecord(CVType &CVR, T &Record) {
ArrayRef<uint8_t> RD = CVR.content();
if (auto EC = deserializeRecord(RD, CVR.Type, Record))
return EC;
return Error::success();
}
template <typename T>
Error defaultVisitKnownMember(CVMemberRecord &CVMR, T &Record) {
ArrayRef<uint8_t> RD = CVMR.Data;
if (auto EC = deserializeRecord(RD, CVMR.Kind, Record))
return EC;
return Error::success();
}
};
}
}

View File

@ -63,19 +63,20 @@ public:
ScopedPrinter *getPrinter() { return W; }
/// Action to take on unknown types. By default, they are ignored.
Error visitUnknownType(CVRecord<TypeLeafKind> &Record) override;
Error visitUnknownMember(CVRecord<TypeLeafKind> &Record) override;
Error visitUnknownType(CVType &Record) override;
Error visitUnknownMember(CVMemberRecord &Record) override;
/// Paired begin/end actions for all types. Receives all record data,
/// including the fixed-length record prefix.
Error visitTypeBegin(CVRecord<TypeLeafKind> &Record) override;
Error visitTypeEnd(CVRecord<TypeLeafKind> &Record) override;
Error visitTypeBegin(CVType &Record) override;
Error visitTypeEnd(CVType &Record) override;
Error visitMemberBegin(CVMemberRecord &Record) override;
Error visitMemberEnd(CVMemberRecord &Record) override;
#define TYPE_RECORD(EnumName, EnumVal, Name) \
Error visitKnownRecord(CVRecord<TypeLeafKind> &CVR, Name##Record &Record) \
override;
Error visitKnownRecord(CVType &CVR, Name##Record &Record) override;
#define MEMBER_RECORD(EnumName, EnumVal, Name) \
TYPE_RECORD(EnumName, EnumVal, Name)
Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override;
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "TypeRecords.def"

View File

@ -29,6 +29,11 @@ using llvm::support::ulittle16_t;
using llvm::support::ulittle32_t;
typedef CVRecord<TypeLeafKind> CVType;
struct CVMemberRecord {
TypeLeafKind Kind;
ArrayRef<uint8_t> Data;
};
typedef msf::VarStreamArray<CVType> CVTypeArray;
/// Equvalent to CV_fldattr_t in cvinfo.h.

View File

@ -51,7 +51,8 @@ public:
}
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#define MEMBER_RECORD(EnumName, EnumVal, Name) \
virtual Error visitKnownRecord(CVType &CVR, Name##Record &Record) override { \
virtual Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) \
override { \
visitMemberRecordImpl(Record); \
return Error::success(); \
}
@ -61,10 +62,7 @@ public:
private:
void updateCVRecord(CVType &Record) {
StringRef S = TypeTableBuilder.getRecords().back();
ArrayRef<uint8_t> Data(S.bytes_begin(), S.bytes_end());
Record.RawData = Data;
Record.Data = Record.RawData.drop_front(sizeof(RecordPrefix));
Record.Length = Data.size() - sizeof(ulittle16_t);
Record.RecordData = ArrayRef<uint8_t>(S.bytes_begin(), S.bytes_end());
}
template <typename RecordKind>
void visitKnownRecordImpl(CVType &CVR, RecordKind &Record) {

View File

@ -30,7 +30,7 @@ public:
return Error::success();
}
virtual Error visitUnknownMember(CVRecord<TypeLeafKind> &Record) override {
virtual Error visitUnknownMember(CVMemberRecord &Record) override {
for (auto Visitor : Pipeline) {
if (auto EC = Visitor->visitUnknownMember(Record))
return EC;
@ -38,14 +38,14 @@ public:
return Error::success();
}
virtual Error visitTypeBegin(CVRecord<TypeLeafKind> &Record) override {
virtual Error visitTypeBegin(CVType &Record) override {
for (auto Visitor : Pipeline) {
if (auto EC = Visitor->visitTypeBegin(Record))
return EC;
}
return Error::success();
}
virtual Error visitTypeEnd(CVRecord<TypeLeafKind> &Record) override {
virtual Error visitTypeEnd(CVType &Record) override {
for (auto Visitor : Pipeline) {
if (auto EC = Visitor->visitTypeEnd(Record))
return EC;
@ -53,13 +53,27 @@ public:
return Error::success();
}
virtual Error visitMemberBegin(CVMemberRecord &Record) override {
for (auto Visitor : Pipeline) {
if (auto EC = Visitor->visitMemberBegin(Record))
return EC;
}
return Error::success();
}
virtual Error visitMemberEnd(CVMemberRecord &Record) override {
for (auto Visitor : Pipeline) {
if (auto EC = Visitor->visitMemberEnd(Record))
return EC;
}
return Error::success();
}
void addCallbackToPipeline(TypeVisitorCallbacks &Callbacks) {
Pipeline.push_back(&Callbacks);
}
#define TYPE_RECORD(EnumName, EnumVal, Name) \
Error visitKnownRecord(CVRecord<TypeLeafKind> &CVR, Name##Record &Record) \
override { \
Error visitKnownRecord(CVType &CVR, Name##Record &Record) override { \
for (auto Visitor : Pipeline) { \
if (auto EC = Visitor->visitKnownRecord(CVR, Record)) \
return EC; \
@ -67,7 +81,14 @@ public:
return Error::success(); \
}
#define MEMBER_RECORD(EnumName, EnumVal, Name) \
TYPE_RECORD(EnumName, EnumVal, Name)
Error visitKnownMember(CVMemberRecord &CVMR, Name##Record &Record) \
override { \
for (auto Visitor : Pipeline) { \
if (auto EC = Visitor->visitKnownMember(CVMR, Record)) \
return EC; \
} \
return Error::success(); \
}
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "llvm/DebugInfo/CodeView/TypeRecords.def"

View File

@ -25,30 +25,32 @@ public:
virtual ~TypeVisitorCallbacks() {}
/// Action to take on unknown types. By default, they are ignored.
virtual Error visitUnknownType(CVRecord<TypeLeafKind> &Record) {
return Error::success();
}
virtual Error visitUnknownMember(CVRecord<TypeLeafKind> &Record) {
return Error::success();
}
virtual Error visitUnknownType(CVType &Record) { return Error::success(); }
/// Paired begin/end actions for all types. Receives all record data,
/// including the fixed-length record prefix. visitTypeBegin() should return
/// the type of the Record, or an error if it cannot be determined.
virtual Error visitTypeBegin(CVRecord<TypeLeafKind> &Record) {
virtual Error visitTypeBegin(CVType &Record) { return Error::success(); }
virtual Error visitTypeEnd(CVType &Record) { return Error::success(); }
virtual Error visitUnknownMember(CVMemberRecord &Record) {
return Error::success();
}
virtual Error visitTypeEnd(CVRecord<TypeLeafKind> &Record) {
virtual Error visitMemberBegin(CVMemberRecord &Record) {
return Error::success();
}
virtual Error visitMemberEnd(CVMemberRecord &Record) {
return Error::success();
}
#define TYPE_RECORD(EnumName, EnumVal, Name) \
virtual Error visitKnownRecord(CVRecord<TypeLeafKind> &CVR, \
Name##Record &Record) { \
virtual Error visitKnownRecord(CVType &CVR, Name##Record &Record) { \
return Error::success(); \
}
#define MEMBER_RECORD(EnumName, EnumVal, Name) \
TYPE_RECORD(EnumName, EnumVal, Name)
virtual Error visitKnownMember(CVMemberRecord &CVM, Name##Record &Record) { \
return Error::success(); \
}
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "TypeRecords.def"

View File

@ -32,11 +32,9 @@ class ReadableStreamRef;
class WritableStream;
template <> struct SequencedItemTraits<llvm::codeview::CVType> {
static size_t length(const codeview::CVType &Item) {
return Item.RawData.size();
}
static size_t length(const codeview::CVType &Item) { return Item.length(); }
static ArrayRef<uint8_t> bytes(const codeview::CVType &Item) {
return Item.RawData;
return Item.data();
}
};
}

View File

@ -42,8 +42,8 @@ static Error skipPadding(ArrayRef<uint8_t> &Data) {
}
template <typename T>
static Expected<CVType> deserializeMemberRecord(ArrayRef<uint8_t> &Data,
TypeLeafKind Kind) {
static Expected<CVMemberRecord> deserializeMemberRecord(ArrayRef<uint8_t> &Data,
TypeLeafKind Kind) {
ArrayRef<uint8_t> OldData = Data;
TypeRecordKind RK = static_cast<TypeRecordKind>(Kind);
auto ExpectedRecord = T::deserialize(RK, Data);
@ -53,20 +53,17 @@ static Expected<CVType> deserializeMemberRecord(ArrayRef<uint8_t> &Data,
if (auto EC = skipPadding(Data))
return std::move(EC);
CVType CVR;
CVR.Type = Kind;
CVR.Length = OldData.size() - Data.size();
CVR.Data = OldData.slice(0, CVR.Length);
CVR.RawData = CVR.Data;
return CVR;
CVMemberRecord CVMR;
CVMR.Kind = Kind;
CVMR.Data = OldData.drop_back(Data.size());
return CVMR;
}
CVTypeVisitor::CVTypeVisitor(TypeVisitorCallbacks &Callbacks)
: Callbacks(Callbacks) {}
template <typename T>
static Error visitKnownRecord(CVRecord<TypeLeafKind> &Record,
TypeVisitorCallbacks &Callbacks) {
static Error visitKnownRecord(CVType &Record, TypeVisitorCallbacks &Callbacks) {
TypeRecordKind RK = static_cast<TypeRecordKind>(Record.Type);
T KnownRecord(RK);
if (auto EC = Callbacks.visitKnownRecord(Record, KnownRecord))
@ -74,7 +71,17 @@ static Error visitKnownRecord(CVRecord<TypeLeafKind> &Record,
return Error::success();
}
Error CVTypeVisitor::visitTypeRecord(CVRecord<TypeLeafKind> &Record) {
template <typename T>
static Error visitKnownMember(CVMemberRecord &Record,
TypeVisitorCallbacks &Callbacks) {
TypeRecordKind RK = static_cast<TypeRecordKind>(Record.Kind);
T KnownRecord(RK);
if (auto EC = Callbacks.visitKnownMember(Record, KnownRecord))
return EC;
return Error::success();
}
Error CVTypeVisitor::visitTypeRecord(CVType &Record) {
if (auto EC = Callbacks.visitTypeBegin(Record))
return EC;
@ -91,10 +98,8 @@ Error CVTypeVisitor::visitTypeRecord(CVRecord<TypeLeafKind> &Record) {
}
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
TYPE_RECORD(EnumVal, EnumVal, AliasName)
#define MEMBER_RECORD(EnumName, EnumVal, Name) \
TYPE_RECORD(EnumName, EnumVal, Name)
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
MEMBER_RECORD(EnumName, EnumVal, AliasName)
#define MEMBER_RECORD(EnumName, EnumVal, Name)
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
}
@ -104,6 +109,34 @@ Error CVTypeVisitor::visitTypeRecord(CVRecord<TypeLeafKind> &Record) {
return Error::success();
}
Error CVTypeVisitor::visitMemberRecord(CVMemberRecord &Record) {
if (auto EC = Callbacks.visitMemberBegin(Record))
return EC;
switch (Record.Kind) {
default:
if (auto EC = Callbacks.visitUnknownMember(Record))
return EC;
break;
#define MEMBER_RECORD(EnumName, EnumVal, Name) \
case EnumName: { \
if (auto EC = visitKnownMember<Name##Record>(Record, Callbacks)) \
return EC; \
break; \
}
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
MEMBER_RECORD(EnumVal, EnumVal, AliasName)
#define TYPE_RECORD(EnumName, EnumVal, Name)
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
}
if (auto EC = Callbacks.visitMemberEnd(Record))
return EC;
return Error::success();
}
/// Visits the type records in Data. Sets the error flag on parse failures.
Error CVTypeVisitor::visitTypeStream(const CVTypeArray &Types) {
for (auto I : Types) {
@ -119,12 +152,12 @@ static Error visitKnownMember(ArrayRef<uint8_t> &Data, TypeLeafKind Leaf,
auto ExpectedRecord = deserializeMemberRecord<MR>(Data, Leaf);
if (!ExpectedRecord)
return ExpectedRecord.takeError();
CVType &Record = *ExpectedRecord;
if (auto EC = Callbacks.visitTypeBegin(Record))
CVMemberRecord &Record = *ExpectedRecord;
if (auto EC = Callbacks.visitMemberBegin(Record))
return EC;
if (auto EC = visitKnownRecord<MR>(Record, Callbacks))
if (auto EC = visitKnownMember<MR>(Record, Callbacks))
return EC;
if (auto EC = Callbacks.visitTypeEnd(Record))
if (auto EC = Callbacks.visitMemberEnd(Record))
return EC;
return Error::success();
}

View File

@ -204,15 +204,12 @@ static StringRef getLeafTypeName(TypeLeafKind LT) {
}
Error CVTypeDumper::visitTypeBegin(CVRecord<TypeLeafKind> &Record) {
assert(!IsInFieldList);
// Reset Name to the empty string. If the visitor sets it, we know it.
Name = "";
W->startLine() << getLeafTypeName(Record.Type);
if (!IsInFieldList) {
// If this is a field list member, don't record its type index because it
// doesn't have one. Only the outer field list has a type index.
W->getOStream() << " (" << HexNumber(getNextTypeIndex()) << ")";
}
W->getOStream() << " (" << HexNumber(getNextTypeIndex()) << ")";
W->getOStream() << " {\n";
W->indent();
W->printEnum("TypeLeafKind", unsigned(Record.Type),
@ -220,7 +217,6 @@ Error CVTypeDumper::visitTypeBegin(CVRecord<TypeLeafKind> &Record) {
if (Record.Type == LF_FIELDLIST) {
// Record that we're in a field list so that members do not get assigned
// type indices.
assert(!IsInFieldList);
IsInFieldList = true;
}
return Error::success();
@ -231,15 +227,37 @@ Error CVTypeDumper::visitTypeEnd(CVRecord<TypeLeafKind> &Record) {
assert(IsInFieldList);
IsInFieldList = false;
}
assert(!IsInFieldList);
if (!IsInFieldList) {
// Record every type that is not a field list member, even if Name is empty.
// CVUDTNames is indexed by type index, and must have one entry for every
// type. Field list members are not recorded, and are only referenced by
// their containing field list record.
recordType(Name);
}
// Record every type that is not a field list member, even if Name is empty.
// CVUDTNames is indexed by type index, and must have one entry for every
// type. Field list members are not recorded, and are only referenced by
// their containing field list record.
recordType(Name);
if (PrintRecordBytes)
W->printBinaryBlock("LeafData", getBytesAsCharacters(Record.content()));
W->unindent();
W->startLine() << "}\n";
return Error::success();
}
Error CVTypeDumper::visitMemberBegin(CVMemberRecord &Record) {
assert(IsInFieldList);
// Reset Name to the empty string. If the visitor sets it, we know it.
Name = "";
W->startLine() << getLeafTypeName(Record.Kind);
W->getOStream() << " {\n";
W->indent();
W->printEnum("TypeLeafKind", unsigned(Record.Kind),
makeArrayRef(LeafTypeNames));
return Error::success();
}
Error CVTypeDumper::visitMemberEnd(CVMemberRecord &Record) {
assert(IsInFieldList);
if (PrintRecordBytes)
W->printBinaryBlock("LeafData", getBytesAsCharacters(Record.Data));
@ -573,18 +591,18 @@ void CVTypeDumper::printMemberAttributes(MemberAccess Access, MethodKind Kind,
}
}
Error CVTypeDumper::visitUnknownMember(CVRecord<TypeLeafKind> &Record) {
W->printHex("UnknownMember", unsigned(Record.Type));
Error CVTypeDumper::visitUnknownMember(CVMemberRecord &Record) {
W->printHex("UnknownMember", unsigned(Record.Kind));
return Error::success();
}
Error CVTypeDumper::visitUnknownType(CVRecord<TypeLeafKind> &Record) {
W->printEnum("Kind", uint16_t(Record.Type), makeArrayRef(LeafTypeNames));
W->printNumber("Length", uint32_t(Record.Data.size()));
W->printEnum("Kind", uint16_t(Record.kind()), makeArrayRef(LeafTypeNames));
W->printNumber("Length", uint32_t(Record.content().size()));
return Error::success();
}
Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
NestedTypeRecord &Nested) {
printTypeIndex("Type", Nested.getNestedType());
W->printString("Name", Nested.getName());
@ -592,7 +610,7 @@ Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
return Error::success();
}
Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
OneMethodRecord &Method) {
MethodKind K = Method.getKind();
printMemberAttributes(Method.getAccess(), K, Method.getOptions());
@ -605,7 +623,7 @@ Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
return Error::success();
}
Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
OverloadedMethodRecord &Method) {
W->printHex("MethodCount", Method.getNumOverloads());
printTypeIndex("MethodListIndex", Method.getMethodList());
@ -614,7 +632,7 @@ Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
return Error::success();
}
Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
DataMemberRecord &Field) {
printMemberAttributes(Field.getAccess(), MethodKind::Vanilla,
MethodOptions::None);
@ -625,7 +643,7 @@ Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
return Error::success();
}
Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
StaticDataMemberRecord &Field) {
printMemberAttributes(Field.getAccess(), MethodKind::Vanilla,
MethodOptions::None);
@ -635,13 +653,13 @@ Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
return Error::success();
}
Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
VFPtrRecord &VFTable) {
printTypeIndex("Type", VFTable.getType());
return Error::success();
}
Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
EnumeratorRecord &Enum) {
printMemberAttributes(Enum.getAccess(), MethodKind::Vanilla,
MethodOptions::None);
@ -651,7 +669,7 @@ Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
return Error::success();
}
Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
BaseClassRecord &Base) {
printMemberAttributes(Base.getAccess(), MethodKind::Vanilla,
MethodOptions::None);
@ -660,7 +678,7 @@ Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
return Error::success();
}
Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
VirtualBaseClassRecord &Base) {
printMemberAttributes(Base.getAccess(), MethodKind::Vanilla,
MethodOptions::None);
@ -671,7 +689,7 @@ Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
return Error::success();
}
Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
ListContinuationRecord &Cont) {
printTypeIndex("ContinuationIndex", Cont.getContinuationIndex());
return Error::success();

View File

@ -60,18 +60,18 @@ public:
/// TypeVisitorCallbacks overrides.
#define TYPE_RECORD(EnumName, EnumVal, Name) \
Error visitKnownRecord(CVRecord<TypeLeafKind> &CVR, Name##Record &Record) \
override;
Error visitKnownRecord(CVType &CVR, Name##Record &Record) override;
#define MEMBER_RECORD(EnumName, EnumVal, Name) \
TYPE_RECORD(EnumName, EnumVal, Name)
Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override;
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
Error visitUnknownType(CVRecord<TypeLeafKind> &Record) override;
Error visitUnknownType(CVType &Record) override;
Error visitTypeBegin(CVRecord<TypeLeafKind> &Record) override;
Error visitTypeEnd(CVRecord<TypeLeafKind> &Record) override;
Error visitTypeBegin(CVType &Record) override;
Error visitTypeEnd(CVType &Record) override;
Error visitMemberEnd(CVMemberRecord &Record) override;
bool mergeStream(const CVTypeArray &Types);
@ -137,27 +137,30 @@ Error TypeStreamMerger::visitTypeEnd(CVRecord<TypeLeafKind> &Rec) {
IndexMap.push_back(DestStream.writeFieldList(FieldBuilder));
FieldBuilder.reset();
IsInFieldList = false;
} else if (!IsInFieldList) {
assert(IndexMap.size() == BeginIndexMapSize + 1);
}
return Error::success();
}
Error TypeStreamMerger::visitMemberEnd(CVMemberRecord &Rec) {
assert(IndexMap.size() == BeginIndexMapSize + 1);
return Error::success();
}
#define TYPE_RECORD(EnumName, EnumVal, Name) \
Error TypeStreamMerger::visitKnownRecord(CVRecord<TypeLeafKind> &CVR, \
Error TypeStreamMerger::visitKnownRecord(CVType &CVR, \
Name##Record &Record) { \
return visitKnownRecordImpl(Record); \
}
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#define MEMBER_RECORD(EnumName, EnumVal, Name) \
Error TypeStreamMerger::visitKnownRecord(CVRecord<TypeLeafKind> &CVR, \
Error TypeStreamMerger::visitKnownMember(CVMemberRecord &CVR, \
Name##Record &Record) { \
return visitKnownMemberRecordImpl(Record); \
}
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
Error TypeStreamMerger::visitUnknownType(CVRecord<TypeLeafKind> &Rec) {
Error TypeStreamMerger::visitUnknownType(CVType &Rec) {
// We failed to translate a type. Translate this index as "not translated".
IndexMap.push_back(
TypeIndex(SimpleTypeKind::NotTranslated, SimpleTypeMode::Direct));

View File

@ -58,15 +58,15 @@ void TpiHashUpdater::visitKnownRecordImpl(CVType &CVR,
}
void TpiHashUpdater::visitKnownRecordImpl(CVType &CVR, ClassRecord &Rec) {
CVR.Hash = getTpiHash(Rec, CVR.RawData);
CVR.Hash = getTpiHash(Rec, CVR.data());
}
void TpiHashUpdater::visitKnownRecordImpl(CVType &CVR, EnumRecord &Rec) {
CVR.Hash = getTpiHash(Rec, CVR.RawData);
CVR.Hash = getTpiHash(Rec, CVR.data());
}
void TpiHashUpdater::visitKnownRecordImpl(CVType &CVR, UnionRecord &Rec) {
CVR.Hash = getTpiHash(Rec, CVR.RawData);
CVR.Hash = getTpiHash(Rec, CVR.data());
}
Error TpiHashVerifier::visitKnownRecord(CVType &CVR, UdtSourceLineRecord &Rec) {
@ -79,17 +79,17 @@ Error TpiHashVerifier::visitKnownRecord(CVType &CVR,
}
Error TpiHashVerifier::visitKnownRecord(CVType &CVR, ClassRecord &Rec) {
if (getTpiHash(Rec, CVR.RawData) % NumHashBuckets != HashValues[Index])
if (getTpiHash(Rec, CVR.data()) % NumHashBuckets != HashValues[Index])
return errorInvalidHash();
return Error::success();
}
Error TpiHashVerifier::visitKnownRecord(CVType &CVR, EnumRecord &Rec) {
if (getTpiHash(Rec, CVR.RawData) % NumHashBuckets != HashValues[Index])
if (getTpiHash(Rec, CVR.data()) % NumHashBuckets != HashValues[Index])
return errorInvalidHash();
return Error::success();
}
Error TpiHashVerifier::visitKnownRecord(CVType &CVR, UnionRecord &Rec) {
if (getTpiHash(Rec, CVR.RawData) % NumHashBuckets != HashValues[Index])
if (getTpiHash(Rec, CVR.data()) % NumHashBuckets != HashValues[Index])
return errorInvalidHash();
return Error::success();
}

View File

@ -15,7 +15,9 @@
#include "llvm/DebugInfo/CodeView/EnumTables.h"
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeSerializationVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
#include "llvm/DebugInfo/PDB/Raw/TpiHashing.h"
using namespace llvm;
using namespace llvm::codeview;
@ -27,33 +29,33 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(OneMethodRecord)
LLVM_YAML_IS_SEQUENCE_VECTOR(VFTableSlotKind)
LLVM_YAML_IS_SEQUENCE_VECTOR(StringRef)
LLVM_YAML_IS_SEQUENCE_VECTOR(CVType)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbTpiRecord)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbTpiFieldListRecord)
namespace {
struct FieldListRecordSplitter : public TypeVisitorCallbacks {
public:
explicit FieldListRecordSplitter(
std::vector<llvm::pdb::yaml::PdbTpiRecord> &Records)
std::vector<llvm::pdb::yaml::PdbTpiFieldListRecord> &Records)
: Records(Records) {}
#define TYPE_RECORD(EnumName, EnumVal, Name)
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#define MEMBER_RECORD(EnumName, EnumVal, Name) \
Error visitKnownRecord(CVType &CVT, Name##Record &Record) override { \
visitKnownRecordImpl(CVT); \
Error visitKnownMember(CVMemberRecord &CVT, Name##Record &Record) override { \
visitKnownMemberImpl(CVT); \
return Error::success(); \
}
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
private:
void visitKnownRecordImpl(CVType &CVT) {
llvm::pdb::yaml::PdbTpiRecord R;
void visitKnownMemberImpl(CVMemberRecord &CVT) {
llvm::pdb::yaml::PdbTpiFieldListRecord R;
R.Record = CVT;
Records.push_back(std::move(R));
}
std::vector<llvm::pdb::yaml::PdbTpiRecord> &Records;
std::vector<llvm::pdb::yaml::PdbTpiFieldListRecord> &Records;
};
}
@ -525,14 +527,20 @@ void ScalarEnumerationTraits<TypeLeafKind>::enumeration(IO &io,
}
Error llvm::codeview::yaml::YamlTypeDumperCallbacks::visitTypeBegin(
CVRecord<TypeLeafKind> &CVR) {
CVType &CVR) {
YamlIO.mapRequired("Kind", CVR.Type);
return Error::success();
}
Error llvm::codeview::yaml::YamlTypeDumperCallbacks::visitMemberBegin(
CVMemberRecord &Record) {
YamlIO.mapRequired("Kind", Record.Kind);
return Error::success();
}
void llvm::codeview::yaml::YamlTypeDumperCallbacks::visitKnownRecordImpl(
const char *Name, CVType &CVR, FieldListRecord &FieldList) {
std::vector<llvm::pdb::yaml::PdbTpiRecord> FieldListRecords;
std::vector<llvm::pdb::yaml::PdbTpiFieldListRecord> FieldListRecords;
if (YamlIO.outputting()) {
// If we are outputting, then `FieldList.Data` contains a huge chunk of data
// representing the serialized list of members. We need to split it up into
@ -551,3 +559,36 @@ void llvm::codeview::yaml::YamlTypeDumperCallbacks::visitKnownRecordImpl(
}
YamlIO.mapRequired("FieldList", FieldListRecords, Context);
}
namespace llvm {
namespace yaml {
template <>
struct MappingContextTraits<pdb::yaml::PdbTpiFieldListRecord,
pdb::yaml::SerializationContext> {
static void mapping(IO &IO, pdb::yaml::PdbTpiFieldListRecord &Obj,
pdb::yaml::SerializationContext &Context) {
codeview::TypeVisitorCallbackPipeline Pipeline;
codeview::TypeDeserializer Deserializer;
codeview::TypeSerializationVisitor Serializer(Context.FieldListBuilder,
Context.TypeTableBuilder);
pdb::TpiHashUpdater Hasher;
if (IO.outputting()) {
// For PDB to Yaml, deserialize into a high level record type, then dump
// it.
Pipeline.addCallbackToPipeline(Deserializer);
Pipeline.addCallbackToPipeline(Context.Dumper);
} else {
// For Yaml to PDB, extract from the high level record type, then write it
// to bytes.
Pipeline.addCallbackToPipeline(Context.Dumper);
Pipeline.addCallbackToPipeline(Serializer);
Pipeline.addCallbackToPipeline(Hasher);
}
codeview::CVTypeVisitor Visitor(Pipeline);
consumeError(Visitor.visitMemberRecord(Obj.Record));
}
};
}
}

View File

@ -29,7 +29,8 @@ public:
llvm::pdb::yaml::SerializationContext &Context)
: YamlIO(IO), Context(Context) {}
virtual Error visitTypeBegin(CVRecord<TypeLeafKind> &Record) override;
virtual Error visitTypeBegin(CVType &Record) override;
virtual Error visitMemberBegin(CVMemberRecord &Record) override;
#define TYPE_RECORD(EnumName, EnumVal, Name) \
Error visitKnownRecord(CVRecord<TypeLeafKind> &CVR, Name##Record &Record) \
@ -38,12 +39,19 @@ public:
return Error::success(); \
}
#define MEMBER_RECORD(EnumName, EnumVal, Name) \
TYPE_RECORD(EnumName, EnumVal, Name)
Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override { \
visitKnownMemberImpl(#Name, Record); \
return Error::success(); \
}
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
private:
template <typename T> void visitKnownMemberImpl(const char *Name, T &Record) {
YamlIO.mapRequired(Name, Record);
}
template <typename T>
void visitKnownRecordImpl(const char *Name, CVType &Type, T &Record) {
YamlIO.mapRequired(Name, Record);

View File

@ -497,7 +497,7 @@ Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) {
}
if (DumpRecordBytes)
P.printBinaryBlock("Bytes", Type.Data);
P.printBinaryBlock("Bytes", Type.content());
}
dumpTpiHash(P, *Tpi);
if (HadError)
@ -604,7 +604,7 @@ Error LLVMOutputStyle::dumpDbiStream() {
if (opts::raw::DumpModuleSyms)
SD.dump(S);
if (opts::raw::DumpSymRecordBytes)
P.printBinaryBlock("Bytes", S.Data);
P.printBinaryBlock("Bytes", S.content());
}
if (HadError)
return make_error<RawError>(
@ -813,7 +813,7 @@ Error LLVMOutputStyle::dumpPublicsStream() {
SD.dump(S);
if (opts::raw::DumpSymRecordBytes)
P.printBinaryBlock("Bytes", S.Data);
P.printBinaryBlock("Bytes", S.content());
}
if (HadError)
return make_error<RawError>(

View File

@ -75,6 +75,10 @@ struct PdbTpiRecord {
codeview::CVType Record;
};
struct PdbTpiFieldListRecord {
codeview::CVMemberRecord Record;
};
struct PdbTpiStream {
PdbRaw_TpiVer Version;
std::vector<PdbTpiRecord> Records;