summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp71
-rw-r--r--llvm/lib/DebugInfo/CodeView/CMakeLists.txt1
-rw-r--r--llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp88
-rw-r--r--llvm/lib/DebugInfo/CodeView/CodeViewError.cpp2
-rw-r--r--llvm/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp18
-rw-r--r--llvm/lib/DebugInfo/CodeView/ListRecordBuilder.cpp2
-rw-r--r--llvm/lib/DebugInfo/CodeView/TypeDeserializer.cpp81
-rw-r--r--llvm/lib/DebugInfo/CodeView/TypeDumper.cpp106
-rw-r--r--llvm/lib/DebugInfo/CodeView/TypeRecord.cpp5
-rw-r--r--llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp59
-rw-r--r--llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp48
-rw-r--r--llvm/lib/DebugInfo/PDB/Raw/TpiStream.cpp25
12 files changed, 299 insertions, 207 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
index 9d5d2127359..52d7b45d37b 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
@@ -212,7 +212,7 @@ TypeIndex CodeViewDebug::getScopeIndex(const DIScope *Scope) {
// Build the fully qualified name of the scope.
std::string ScopeName = getFullyQualifiedName(Scope);
TypeIndex TI =
- TypeTable.writeStringId(StringIdRecord(TypeIndex(), ScopeName));
+ TypeTable.writeKnownType(StringIdRecord(TypeIndex(), ScopeName));
return recordTypeIndexForDINode(Scope, TI);
}
@@ -237,12 +237,12 @@ TypeIndex CodeViewDebug::getFuncIdForSubprogram(const DISubprogram *SP) {
TypeIndex ClassType = getTypeIndex(Class);
MemberFuncIdRecord MFuncId(ClassType, getMemberFunctionType(SP, Class),
DisplayName);
- TI = TypeTable.writeMemberFuncId(MFuncId);
+ TI = TypeTable.writeKnownType(MFuncId);
} else {
// Otherwise, this must be a free function.
TypeIndex ParentScope = getScopeIndex(Scope);
FuncIdRecord FuncId(ParentScope, getTypeIndex(SP->getType()), DisplayName);
- TI = TypeTable.writeFuncId(FuncId);
+ TI = TypeTable.writeKnownType(FuncId);
}
return recordTypeIndexForDINode(SP, TI);
@@ -1030,7 +1030,7 @@ TypeIndex CodeViewDebug::lowerTypeArray(const DICompositeType *Ty) {
StringRef Name = (i == 0) ? Ty->getName() : "";
// Update the element size and element type index for subsequent subranges.
ElementSize *= Count;
- ElementTypeIndex = TypeTable.writeArray(
+ ElementTypeIndex = TypeTable.writeKnownType(
ArrayRecord(ElementTypeIndex, IndexType, ElementSize, Name));
}
@@ -1174,7 +1174,7 @@ TypeIndex CodeViewDebug::lowerTypePointer(const DIDerivedType *Ty) {
// do.
PointerOptions PO = PointerOptions::None;
PointerRecord PR(PointeeTI, PK, PM, PO, Ty->getSizeInBits() / 8);
- return TypeTable.writePointer(PR);
+ return TypeTable.writeKnownType(PR);
}
static PointerToMemberRepresentation
@@ -1225,7 +1225,7 @@ TypeIndex CodeViewDebug::lowerTypeMemberPointer(const DIDerivedType *Ty) {
MemberPointerInfo MPI(
ClassTI, translatePtrToMemberRep(SizeInBytes, IsPMF, Ty->getFlags()));
PointerRecord PR(PointeeTI, PK, PM, PO, SizeInBytes, MPI);
- return TypeTable.writePointer(PR);
+ return TypeTable.writeKnownType(PR);
}
/// Given a DWARF calling convention, get the CodeView equivalent. If we don't
@@ -1272,7 +1272,7 @@ TypeIndex CodeViewDebug::lowerTypeModifier(const DIDerivedType *Ty) {
return I->second;
ModifierRecord MR(ModifiedTI, Mods);
- return TypeTable.writeModifier(MR);
+ return TypeTable.writeKnownType(MR);
}
TypeIndex CodeViewDebug::lowerTypeFunction(const DISubroutineType *Ty) {
@@ -1289,13 +1289,13 @@ TypeIndex CodeViewDebug::lowerTypeFunction(const DISubroutineType *Ty) {
}
ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
- TypeIndex ArgListIndex = TypeTable.writeArgList(ArgListRec);
+ TypeIndex ArgListIndex = TypeTable.writeKnownType(ArgListRec);
CallingConvention CC = dwarfCCToCodeView(Ty->getCC());
ProcedureRecord Procedure(ReturnTypeIndex, CC, FunctionOptions::None,
ArgTypeIndices.size(), ArgListIndex);
- return TypeTable.writeProcedure(Procedure);
+ return TypeTable.writeKnownType(Procedure);
}
TypeIndex CodeViewDebug::lowerTypeMemberFunction(const DISubroutineType *Ty,
@@ -1322,14 +1322,14 @@ TypeIndex CodeViewDebug::lowerTypeMemberFunction(const DISubroutineType *Ty,
}
ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
- TypeIndex ArgListIndex = TypeTable.writeArgList(ArgListRec);
+ TypeIndex ArgListIndex = TypeTable.writeKnownType(ArgListRec);
CallingConvention CC = dwarfCCToCodeView(Ty->getCC());
// TODO: Need to use the correct values for:
// FunctionOptions
// ThisPointerAdjustment.
- TypeIndex TI = TypeTable.writeMemberFunction(MemberFunctionRecord(
+ TypeIndex TI = TypeTable.writeKnownType(MemberFunctionRecord(
ReturnTypeIndex, ClassType, ThisTypeIndex, CC, FunctionOptions::None,
ArgTypeIndices.size(), ArgListIndex, ThisAdjustment));
@@ -1428,7 +1428,7 @@ TypeIndex CodeViewDebug::lowerTypeEnum(const DICompositeType *Ty) {
// We assume that the frontend provides all members in source declaration
// order, which is what MSVC does.
if (auto *Enumerator = dyn_cast_or_null<DIEnumerator>(Element)) {
- Fields.writeEnumerator(EnumeratorRecord(
+ Fields.writeMemberType(EnumeratorRecord(
MemberAccess::Public, APSInt::getUnsigned(Enumerator->getValue()),
Enumerator->getName()));
EnumeratorCount++;
@@ -1439,9 +1439,9 @@ TypeIndex CodeViewDebug::lowerTypeEnum(const DICompositeType *Ty) {
std::string FullName = getFullyQualifiedName(Ty);
- return TypeTable.writeEnum(EnumRecord(EnumeratorCount, CO, FTI, FullName,
- Ty->getIdentifier(),
- getTypeIndex(Ty->getBaseType())));
+ return TypeTable.writeKnownType(EnumRecord(EnumeratorCount, CO, FTI, FullName,
+ Ty->getIdentifier(),
+ getTypeIndex(Ty->getBaseType())));
}
//===----------------------------------------------------------------------===//
@@ -1536,7 +1536,7 @@ TypeIndex CodeViewDebug::lowerTypeClass(const DICompositeType *Ty) {
ClassOptions CO =
ClassOptions::ForwardReference | getCommonClassOptions(Ty);
std::string FullName = getFullyQualifiedName(Ty);
- TypeIndex FwdDeclTI = TypeTable.writeClass(ClassRecord(
+ TypeIndex FwdDeclTI = TypeTable.writeKnownType(ClassRecord(
Kind, 0, CO, HfaKind::None, WindowsRTClassKind::None, TypeIndex(),
TypeIndex(), TypeIndex(), 0, FullName, Ty->getIdentifier()));
if (!Ty->isForwardDecl())
@@ -1562,12 +1562,12 @@ TypeIndex CodeViewDebug::lowerCompleteTypeClass(const DICompositeType *Ty) {
uint64_t SizeInBytes = Ty->getSizeInBits() / 8;
- TypeIndex ClassTI = TypeTable.writeClass(ClassRecord(
+ TypeIndex ClassTI = TypeTable.writeKnownType(ClassRecord(
Kind, FieldCount, CO, HfaKind::None, WindowsRTClassKind::None, FieldTI,
TypeIndex(), VShapeTI, SizeInBytes, FullName, Ty->getIdentifier()));
- TypeTable.writeUdtSourceLine(UdtSourceLineRecord(
- ClassTI, TypeTable.writeStringId(StringIdRecord(
+ TypeTable.writeKnownType(UdtSourceLineRecord(
+ ClassTI, TypeTable.writeKnownType(StringIdRecord(
TypeIndex(0x0), getFullFilepath(Ty->getFile()))),
Ty->getLine()));
@@ -1580,9 +1580,8 @@ TypeIndex CodeViewDebug::lowerTypeUnion(const DICompositeType *Ty) {
ClassOptions CO =
ClassOptions::ForwardReference | getCommonClassOptions(Ty);
std::string FullName = getFullyQualifiedName(Ty);
- TypeIndex FwdDeclTI =
- TypeTable.writeUnion(UnionRecord(0, CO, HfaKind::None, TypeIndex(), 0,
- FullName, Ty->getIdentifier()));
+ TypeIndex FwdDeclTI = TypeTable.writeKnownType(UnionRecord(
+ 0, CO, HfaKind::None, TypeIndex(), 0, FullName, Ty->getIdentifier()));
if (!Ty->isForwardDecl())
DeferredCompleteTypes.push_back(Ty);
return FwdDeclTI;
@@ -1602,12 +1601,12 @@ TypeIndex CodeViewDebug::lowerCompleteTypeUnion(const DICompositeType *Ty) {
uint64_t SizeInBytes = Ty->getSizeInBits() / 8;
std::string FullName = getFullyQualifiedName(Ty);
- TypeIndex UnionTI = TypeTable.writeUnion(
+ TypeIndex UnionTI = TypeTable.writeKnownType(
UnionRecord(FieldCount, CO, HfaKind::None, FieldTI, SizeInBytes, FullName,
Ty->getIdentifier()));
- TypeTable.writeUdtSourceLine(UdtSourceLineRecord(
- UnionTI, TypeTable.writeStringId(StringIdRecord(
+ TypeTable.writeKnownType(UdtSourceLineRecord(
+ UnionTI, TypeTable.writeKnownType(StringIdRecord(
TypeIndex(0x0), getFullFilepath(Ty->getFile()))),
Ty->getLine()));
@@ -1634,14 +1633,14 @@ CodeViewDebug::lowerRecordFieldList(const DICompositeType *Ty) {
unsigned VBPtrOffset = 0;
// FIXME: Despite the accessor name, the offset is really in bytes.
unsigned VBTableIndex = I->getOffsetInBits() / 4;
- Fields.writeVirtualBaseClass(VirtualBaseClassRecord(
+ Fields.writeMemberType(VirtualBaseClassRecord(
translateAccessFlags(Ty->getTag(), I->getFlags()),
getTypeIndex(I->getBaseType()), getVBPTypeIndex(), VBPtrOffset,
VBTableIndex));
} else {
assert(I->getOffsetInBits() % 8 == 0 &&
"bases must be on byte boundaries");
- Fields.writeBaseClass(BaseClassRecord(
+ Fields.writeMemberType(BaseClassRecord(
translateAccessFlags(Ty->getTag(), I->getFlags()),
getTypeIndex(I->getBaseType()), I->getOffsetInBits() / 8));
}
@@ -1656,7 +1655,7 @@ CodeViewDebug::lowerRecordFieldList(const DICompositeType *Ty) {
translateAccessFlags(Ty->getTag(), Member->getFlags());
if (Member->isStaticMember()) {
- Fields.writeStaticDataMember(
+ Fields.writeMemberType(
StaticDataMemberRecord(Access, MemberBaseType, MemberName));
MemberCount++;
continue;
@@ -1672,11 +1671,11 @@ CodeViewDebug::lowerRecordFieldList(const DICompositeType *Ty) {
MemberOffsetInBits = CI->getZExtValue() + MemberInfo.BaseOffset;
}
StartBitOffset -= MemberOffsetInBits;
- MemberBaseType = TypeTable.writeBitField(BitFieldRecord(
+ MemberBaseType = TypeTable.writeKnownType(BitFieldRecord(
MemberBaseType, Member->getSizeInBits(), StartBitOffset));
}
uint64_t MemberOffsetInBytes = MemberOffsetInBits / 8;
- Fields.writeDataMember(DataMemberRecord(Access, MemberBaseType,
+ Fields.writeMemberType(DataMemberRecord(Access, MemberBaseType,
MemberOffsetInBytes, MemberName));
MemberCount++;
}
@@ -1703,11 +1702,11 @@ CodeViewDebug::lowerRecordFieldList(const DICompositeType *Ty) {
}
assert(Methods.size() > 0 && "Empty methods map entry");
if (Methods.size() == 1)
- Fields.writeOneMethod(Methods[0]);
+ Fields.writeMemberType(Methods[0]);
else {
TypeIndex MethodList =
- TypeTable.writeMethodOverloadList(MethodOverloadListRecord(Methods));
- Fields.writeOverloadedMethod(
+ TypeTable.writeKnownType(MethodOverloadListRecord(Methods));
+ Fields.writeMemberType(
OverloadedMethodRecord(Methods.size(), MethodList, Name));
}
}
@@ -1715,7 +1714,7 @@ CodeViewDebug::lowerRecordFieldList(const DICompositeType *Ty) {
// Create nested classes.
for (const DICompositeType *Nested : Info.NestedClasses) {
NestedTypeRecord R(getTypeIndex(DITypeRef(Nested)), Nested->getName());
- Fields.writeNestedType(R);
+ Fields.writeMemberType(R);
MemberCount++;
}
@@ -1728,7 +1727,7 @@ TypeIndex CodeViewDebug::getVBPTypeIndex() {
if (!VBPType.getIndex()) {
// Make a 'const int *' type.
ModifierRecord MR(TypeIndex::Int32(), ModifierOptions::Const);
- TypeIndex ModifiedTI = TypeTable.writeModifier(MR);
+ TypeIndex ModifiedTI = TypeTable.writeKnownType(MR);
PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64
: PointerKind::Near32;
@@ -1736,7 +1735,7 @@ TypeIndex CodeViewDebug::getVBPTypeIndex() {
PointerOptions PO = PointerOptions::None;
PointerRecord PR(ModifiedTI, PK, PM, PO, getPointerSizeInBytes());
- VBPType = TypeTable.writePointer(PR);
+ VBPType = TypeTable.writeKnownType(PR);
}
return VBPType;
diff --git a/llvm/lib/DebugInfo/CodeView/CMakeLists.txt b/llvm/lib/DebugInfo/CodeView/CMakeLists.txt
index d8c21953967..92ffd3d24d7 100644
--- a/llvm/lib/DebugInfo/CodeView/CMakeLists.txt
+++ b/llvm/lib/DebugInfo/CodeView/CMakeLists.txt
@@ -11,6 +11,7 @@ add_llvm_library(LLVMDebugInfoCodeView
ModuleSubstreamVisitor.cpp
RecordSerialization.cpp
SymbolDumper.cpp
+ TypeDeserializer.cpp
TypeDumper.cpp
TypeRecord.cpp
TypeRecordBuilder.cpp
diff --git a/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp b/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
index a7b7f3a2793..01dd5d4591c 100644
--- a/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
+++ b/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
@@ -8,47 +8,39 @@
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
+
#include "llvm/DebugInfo/CodeView/CodeViewError.h"
+#include "llvm/DebugInfo/Msf/ByteStream.h"
using namespace llvm;
using namespace llvm::codeview;
+CVTypeVisitor::CVTypeVisitor(TypeVisitorCallbacks &Callbacks)
+ : Callbacks(Callbacks) {}
+
template <typename T>
-static Error takeObject(ArrayRef<uint8_t> &Data, const T *&Res) {
- if (Data.size() < sizeof(*Res))
- return llvm::make_error<CodeViewError>(cv_error_code::insufficient_buffer);
- Res = reinterpret_cast<const T *>(Data.data());
- Data = Data.drop_front(sizeof(*Res));
+static Error visitKnownRecord(const CVRecord<TypeLeafKind> &Record,
+ TypeVisitorCallbacks &Callbacks) {
+ TypeRecordKind RK = static_cast<TypeRecordKind>(Record.Type);
+ T KnownRecord(RK);
+ if (auto EC = Callbacks.visitKnownRecord(Record, KnownRecord))
+ return EC;
return Error::success();
}
-CVTypeVisitor::CVTypeVisitor(TypeVisitorCallbacks &Callbacks)
- : Callbacks(Callbacks) {}
-
Error CVTypeVisitor::visitTypeRecord(const CVRecord<TypeLeafKind> &Record) {
ArrayRef<uint8_t> LeafData = Record.Data;
if (auto EC = Callbacks.visitTypeBegin(Record))
return EC;
+
switch (Record.Type) {
default:
if (auto EC = Callbacks.visitUnknownType(Record))
return EC;
break;
- case LF_FIELDLIST:
- if (auto EC = Callbacks.visitFieldListBegin(Record))
- return EC;
- if (auto EC = visitFieldList(Record))
- return EC;
- if (auto EC = Callbacks.visitFieldListEnd(Record))
- return EC;
- break;
#define TYPE_RECORD(EnumName, EnumVal, Name) \
case EnumName: { \
- TypeRecordKind RK = static_cast<TypeRecordKind>(EnumName); \
- auto ExpectedRecord = Name##Record::deserialize(RK, LeafData); \
- if (!ExpectedRecord) \
- return ExpectedRecord.takeError(); \
- if (auto EC = Callbacks.visit##Name(*ExpectedRecord)) \
+ if (auto EC = visitKnownRecord<Name##Record>(Record, Callbacks)) \
return EC; \
break; \
}
@@ -57,8 +49,10 @@ Error CVTypeVisitor::visitTypeRecord(const CVRecord<TypeLeafKind> &Record) {
#define MEMBER_RECORD(EnumName, EnumVal, Name)
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
}
+
if (auto EC = Callbacks.visitTypeEnd(Record))
return EC;
+
return Error::success();
}
@@ -70,55 +64,3 @@ Error CVTypeVisitor::visitTypeStream(const CVTypeArray &Types) {
}
return Error::success();
}
-
-Error CVTypeVisitor::skipPadding(ArrayRef<uint8_t> &Data) {
- if (Data.empty())
- return Error::success();
- uint8_t Leaf = Data.front();
- if (Leaf < LF_PAD0)
- return Error::success();
- // Leaf is greater than 0xf0. We should advance by the number of bytes in
- // the low 4 bits.
- unsigned BytesToAdvance = Leaf & 0x0F;
- if (Data.size() < BytesToAdvance) {
- return llvm::make_error<CodeViewError>(cv_error_code::corrupt_record,
- "Invalid padding bytes!");
- }
- Data = Data.drop_front(BytesToAdvance);
- return Error::success();
-}
-
-/// Visits individual member records of a field list record. Member records do
-/// not describe their own length, and need special handling.
-Error CVTypeVisitor::visitFieldList(const CVRecord<TypeLeafKind> &Record) {
- ArrayRef<uint8_t> RecordData = Record.Data;
- while (!RecordData.empty()) {
- const ulittle16_t *LeafPtr;
- if (auto EC = takeObject(RecordData, LeafPtr))
- return EC;
- TypeLeafKind Leaf = TypeLeafKind(unsigned(*LeafPtr));
- switch (Leaf) {
- default:
- // Field list records do not describe their own length, so we cannot
- // continue parsing past an unknown member type.
- if (auto EC = Callbacks.visitUnknownMember(Record))
- return llvm::make_error<CodeViewError>(cv_error_code::corrupt_record);
-#define MEMBER_RECORD(EnumName, EnumVal, Name) \
- case EnumName: { \
- TypeRecordKind RK = static_cast<TypeRecordKind>(EnumName); \
- auto ExpectedRecord = Name##Record::deserialize(RK, RecordData); \
- if (!ExpectedRecord) \
- return ExpectedRecord.takeError(); \
- if (auto EC = Callbacks.visit##Name(*ExpectedRecord)) \
- return EC; \
- break; \
- }
-#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
- MEMBER_RECORD(EnumVal, EnumVal, AliasName)
-#include "llvm/DebugInfo/CodeView/TypeRecords.def"
- }
- if (auto EC = skipPadding(RecordData))
- return EC;
- }
- return Error::success();
-}
diff --git a/llvm/lib/DebugInfo/CodeView/CodeViewError.cpp b/llvm/lib/DebugInfo/CodeView/CodeViewError.cpp
index aad1d8b25cd..e9678db7a5b 100644
--- a/llvm/lib/DebugInfo/CodeView/CodeViewError.cpp
+++ b/llvm/lib/DebugInfo/CodeView/CodeViewError.cpp
@@ -33,6 +33,8 @@ public:
return "The CodeView record is corrupted.";
case cv_error_code::operation_unsupported:
return "The requested operation is not supported.";
+ case cv_error_code::unknown_member_record:
+ return "The member record is of an unknown type.";
}
llvm_unreachable("Unrecognized cv_error_code");
}
diff --git a/llvm/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp b/llvm/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp
index 5f229e3d9f9..ac2ef3972b6 100644
--- a/llvm/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp
+++ b/llvm/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp
@@ -15,7 +15,7 @@ using namespace codeview;
FieldListRecordBuilder::FieldListRecordBuilder()
: ListRecordBuilder(TypeRecordKind::FieldList) {}
-void FieldListRecordBuilder::writeBaseClass(const BaseClassRecord &Record) {
+void FieldListRecordBuilder::writeMemberType(const BaseClassRecord &Record) {
TypeRecordBuilder &Builder = getBuilder();
Builder.writeTypeRecordKind(TypeRecordKind::BaseClass);
@@ -26,7 +26,7 @@ void FieldListRecordBuilder::writeBaseClass(const BaseClassRecord &Record) {
finishSubRecord();
}
-void FieldListRecordBuilder::writeEnumerator(const EnumeratorRecord &Record) {
+void FieldListRecordBuilder::writeMemberType(const EnumeratorRecord &Record) {
TypeRecordBuilder &Builder = getBuilder();
Builder.writeTypeRecordKind(TypeRecordKind::Enumerator);
@@ -38,7 +38,7 @@ void FieldListRecordBuilder::writeEnumerator(const EnumeratorRecord &Record) {
finishSubRecord();
}
-void FieldListRecordBuilder::writeDataMember(const DataMemberRecord &Record) {
+void FieldListRecordBuilder::writeMemberType(const DataMemberRecord &Record) {
TypeRecordBuilder &Builder = getBuilder();
Builder.writeTypeRecordKind(Record.getKind());
@@ -50,7 +50,7 @@ void FieldListRecordBuilder::writeDataMember(const DataMemberRecord &Record) {
finishSubRecord();
}
-void FieldListRecordBuilder::writeOverloadedMethod(
+void FieldListRecordBuilder::writeMemberType(
const OverloadedMethodRecord &Record) {
TypeRecordBuilder &Builder = getBuilder();
@@ -62,7 +62,7 @@ void FieldListRecordBuilder::writeOverloadedMethod(
finishSubRecord();
}
-void FieldListRecordBuilder::writeOneMethod(const OneMethodRecord &Record) {
+void FieldListRecordBuilder::writeMemberType(const OneMethodRecord &Record) {
TypeRecordBuilder &Builder = getBuilder();
uint16_t Flags = static_cast<uint16_t>(Record.getAccess());
@@ -84,7 +84,7 @@ void FieldListRecordBuilder::writeOneMethod(const OneMethodRecord &Record) {
finishSubRecord();
}
-void FieldListRecordBuilder::writeNestedType(const NestedTypeRecord &Record) {
+void FieldListRecordBuilder::writeMemberType(const NestedTypeRecord &Record) {
TypeRecordBuilder &Builder = getBuilder();
Builder.writeTypeRecordKind(Record.getKind());
@@ -95,7 +95,7 @@ void FieldListRecordBuilder::writeNestedType(const NestedTypeRecord &Record) {
finishSubRecord();
}
-void FieldListRecordBuilder::writeStaticDataMember(
+void FieldListRecordBuilder::writeMemberType(
const StaticDataMemberRecord &Record) {
TypeRecordBuilder &Builder = getBuilder();
@@ -107,7 +107,7 @@ void FieldListRecordBuilder::writeStaticDataMember(
finishSubRecord();
}
-void FieldListRecordBuilder::writeVirtualBaseClass(
+void FieldListRecordBuilder::writeMemberType(
const VirtualBaseClassRecord &Record) {
TypeRecordBuilder &Builder = getBuilder();
@@ -121,7 +121,7 @@ void FieldListRecordBuilder::writeVirtualBaseClass(
finishSubRecord();
}
-void FieldListRecordBuilder::writeVFPtr(const VFPtrRecord &Record) {
+void FieldListRecordBuilder::writeMemberType(const VFPtrRecord &Record) {
TypeRecordBuilder &Builder = getBuilder();
Builder.writeTypeRecordKind(TypeRecordKind::VFPtr);
diff --git a/llvm/lib/DebugInfo/CodeView/ListRecordBuilder.cpp b/llvm/lib/DebugInfo/CodeView/ListRecordBuilder.cpp
index eb79e8ac9a3..ab019c44c5b 100644
--- a/llvm/lib/DebugInfo/CodeView/ListRecordBuilder.cpp
+++ b/llvm/lib/DebugInfo/CodeView/ListRecordBuilder.cpp
@@ -17,7 +17,7 @@ using namespace codeview;
ListRecordBuilder::ListRecordBuilder(TypeRecordKind Kind)
: Kind(Kind), Builder(Kind) {}
-void ListRecordBuilder::writeListContinuation(const ListContinuationRecord &R) {
+void ListRecordBuilder::writeMemberType(const ListContinuationRecord &R) {
TypeRecordBuilder &Builder = getBuilder();
assert(getLastContinuationSize() < 65535 - 8 && "continuation won't fit");
diff --git a/llvm/lib/DebugInfo/CodeView/TypeDeserializer.cpp b/llvm/lib/DebugInfo/CodeView/TypeDeserializer.cpp
new file mode 100644
index 00000000000..3593458565f
--- /dev/null
+++ b/llvm/lib/DebugInfo/CodeView/TypeDeserializer.cpp
@@ -0,0 +1,81 @@
+//===- TypeDeserializer.cpp -------------------------------------*- 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/CodeView/TypeDeserializer.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+template <typename T>
+static Error takeObject(ArrayRef<uint8_t> &Data, const T *&Res) {
+ if (Data.size() < sizeof(*Res))
+ return llvm::make_error<CodeViewError>(cv_error_code::insufficient_buffer);
+ Res = reinterpret_cast<const T *>(Data.data());
+ Data = Data.drop_front(sizeof(*Res));
+ return Error::success();
+}
+
+Error TypeDeserializer::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+ FieldListRecord &Record) {
+ ArrayRef<uint8_t> FieldListRecordData = CVR.Data;
+ auto ExpectedRecord = FieldListRecord::deserialize(TypeRecordKind::FieldList,
+ FieldListRecordData);
+ if (!ExpectedRecord)
+ return ExpectedRecord.takeError();
+
+ Record = *ExpectedRecord;
+ ArrayRef<uint8_t> MemberData = Record.getFieldListData();
+
+ while (!MemberData.empty()) {
+ const ulittle16_t *LeafPtr;
+ if (auto EC = takeObject(MemberData, LeafPtr))
+ return EC;
+ TypeLeafKind Leaf = TypeLeafKind(unsigned(*LeafPtr));
+ switch (Leaf) {
+ default:
+ // Field list records do not describe their own length, so we cannot
+ // continue parsing past a type that we don't know how to deserialize.
+ if (auto EC = Recipient.visitUnknownMember(CVR))
+ return EC;
+ return llvm::make_error<CodeViewError>(
+ cv_error_code::unknown_member_record);
+#define MEMBER_RECORD(EnumName, EnumVal, Name) \
+ case EnumName: { \
+ TypeRecordKind RK = static_cast<TypeRecordKind>(Leaf); \
+ Name##Record Member(RK); \
+ if (auto EC = visitKnownMember(MemberData, Leaf, Member)) \
+ return EC; \
+ break; \
+ }
+#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
+ MEMBER_RECORD(EnumVal, EnumVal, AliasName)
+#include "llvm/DebugInfo/CodeView/TypeRecords.def"
+ }
+ if (auto EC = skipPadding(MemberData))
+ return EC;
+ }
+ return Error::success();
+}
+
+Error TypeDeserializer::skipPadding(ArrayRef<uint8_t> &Data) {
+ if (Data.empty())
+ return Error::success();
+ uint8_t Leaf = Data.front();
+ if (Leaf < LF_PAD0)
+ return Error::success();
+ // Leaf is greater than 0xf0. We should advance by the number of bytes in
+ // the low 4 bits.
+ unsigned BytesToAdvance = Leaf & 0x0F;
+ if (Data.size() < BytesToAdvance) {
+ return llvm::make_error<CodeViewError>(cv_error_code::corrupt_record,
+ "Invalid padding bytes!");
+ }
+ Data = Data.drop_front(BytesToAdvance);
+ return Error::success();
+}
diff --git a/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp b/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp
index 5ceaa59a79e..e1ec5ce9802 100644
--- a/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp
+++ b/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp
@@ -10,6 +10,7 @@
#include "llvm/DebugInfo/CodeView/TypeDumper.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/MSF/ByteStream.h"
@@ -195,8 +196,6 @@ static StringRef getLeafTypeName(TypeLeafKind LT) {
case ename: \
return #name;
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
- case LF_FIELDLIST:
- return "FieldList";
default:
break;
}
@@ -231,7 +230,13 @@ Error CVTypeDumper::visitTypeEnd(const CVRecord<TypeLeafKind> &Record) {
return Error::success();
}
-Error CVTypeDumper::visitStringId(StringIdRecord &String) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+ FieldListRecord &FieldList) {
+ return Error::success();
+}
+
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+ StringIdRecord &String) {
printTypeIndex("Id", String.getId());
W->printString("StringData", String.getString());
// Put this in CVUDTNames so it gets printed with LF_UDT_SRC_LINE.
@@ -239,7 +244,8 @@ Error CVTypeDumper::visitStringId(StringIdRecord &String) {
return Error::success();
}
-Error CVTypeDumper::visitArgList(ArgListRecord &Args) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+ ArgListRecord &Args) {
auto Indices = Args.getIndices();
uint32_t Size = Indices.size();
W->printNumber("NumArgs", Size);
@@ -257,7 +263,8 @@ Error CVTypeDumper::visitArgList(ArgListRecord &Args) {
return Error::success();
}
-Error CVTypeDumper::visitClass(ClassRecord &Class) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+ ClassRecord &Class) {
uint16_t Props = static_cast<uint16_t>(Class.getOptions());
W->printNumber("MemberCount", Class.getMemberCount());
W->printFlags("Properties", Props, makeArrayRef(ClassOptionNames));
@@ -272,7 +279,8 @@ Error CVTypeDumper::visitClass(ClassRecord &Class) {
return Error::success();
}
-Error CVTypeDumper::visitUnion(UnionRecord &Union) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+ UnionRecord &Union) {
uint16_t Props = static_cast<uint16_t>(Union.getOptions());
W->printNumber("MemberCount", Union.getMemberCount());
W->printFlags("Properties", Props, makeArrayRef(ClassOptionNames));
@@ -285,7 +293,8 @@ Error CVTypeDumper::visitUnion(UnionRecord &Union) {
return Error::success();
}
-Error CVTypeDumper::visitEnum(EnumRecord &Enum) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+ EnumRecord &Enum) {
uint16_t Props = static_cast<uint16_t>(Enum.getOptions());
W->printNumber("NumEnumerators", Enum.getMemberCount());
W->printFlags("Properties", uint16_t(Enum.getOptions()),
@@ -299,7 +308,8 @@ Error CVTypeDumper::visitEnum(EnumRecord &Enum) {
return Error::success();
}
-Error CVTypeDumper::visitArray(ArrayRecord &AT) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+ ArrayRecord &AT) {
printTypeIndex("ElementType", AT.getElementType());
printTypeIndex("IndexType", AT.getIndexType());
W->printNumber("SizeOf", AT.getSize());
@@ -308,7 +318,8 @@ Error CVTypeDumper::visitArray(ArrayRecord &AT) {
return Error::success();
}
-Error CVTypeDumper::visitVFTable(VFTableRecord &VFT) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+ VFTableRecord &VFT) {
printTypeIndex("CompleteClass", VFT.getCompleteClass());
printTypeIndex("OverriddenVFTable", VFT.getOverriddenVTable());
W->printHex("VFPtrOffset", VFT.getVFPtrOffset());
@@ -319,7 +330,8 @@ Error CVTypeDumper::visitVFTable(VFTableRecord &VFT) {
return Error::success();
}
-Error CVTypeDumper::visitMemberFuncId(MemberFuncIdRecord &Id) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+ MemberFuncIdRecord &Id) {
printTypeIndex("ClassType", Id.getClassType());
printTypeIndex("FunctionType", Id.getFunctionType());
W->printString("Name", Id.getName());
@@ -327,7 +339,8 @@ Error CVTypeDumper::visitMemberFuncId(MemberFuncIdRecord &Id) {
return Error::success();
}
-Error CVTypeDumper::visitProcedure(ProcedureRecord &Proc) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+ ProcedureRecord &Proc) {
printTypeIndex("ReturnType", Proc.getReturnType());
W->printEnum("CallingConvention", uint8_t(Proc.getCallConv()),
makeArrayRef(CallingConventions));
@@ -345,7 +358,8 @@ Error CVTypeDumper::visitProcedure(ProcedureRecord &Proc) {
return Error::success();
}
-Error CVTypeDumper::visitMemberFunction(MemberFunctionRecord &MF) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+ MemberFunctionRecord &MF) {
printTypeIndex("ReturnType", MF.getReturnType());
printTypeIndex("ClassType", MF.getClassType());
printTypeIndex("ThisType", MF.getThisType());
@@ -369,8 +383,8 @@ Error CVTypeDumper::visitMemberFunction(MemberFunctionRecord &MF) {
return Error::success();
}
-Error CVTypeDumper::visitMethodOverloadList(
- MethodOverloadListRecord &MethodList) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+ MethodOverloadListRecord &MethodList) {
for (auto &M : MethodList.getMethods()) {
ListScope S(*W, "Method");
printMemberAttributes(M.getAccess(), M.getKind(), M.getOptions());
@@ -381,7 +395,8 @@ Error CVTypeDumper::visitMethodOverloadList(
return Error::success();
}
-Error CVTypeDumper::visitFuncId(FuncIdRecord &Func) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+ FuncIdRecord &Func) {
printTypeIndex("ParentScope", Func.getParentScope());
printTypeIndex("FunctionType", Func.getFunctionType());
W->printString("Name", Func.getName());
@@ -389,7 +404,8 @@ Error CVTypeDumper::visitFuncId(FuncIdRecord &Func) {
return Error::success();
}
-Error CVTypeDumper::visitTypeServer2(TypeServer2Record &TS) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+ TypeServer2Record &TS) {
W->printBinary("Signature", TS.getGuid());
W->printNumber("Age", TS.getAge());
W->printString("Name", TS.getName());
@@ -397,7 +413,8 @@ Error CVTypeDumper::visitTypeServer2(TypeServer2Record &TS) {
return Error::success();
}
-Error CVTypeDumper::visitPointer(PointerRecord &Ptr) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+ PointerRecord &Ptr) {
printTypeIndex("PointeeType", Ptr.getReferentType());
W->printHex("PointerAttributes", uint32_t(Ptr.getOptions()));
W->printEnum("PtrType", unsigned(Ptr.getPointerKind()),
@@ -448,7 +465,8 @@ Error CVTypeDumper::visitPointer(PointerRecord &Ptr) {
return Error::success();
}
-Error CVTypeDumper::visitModifier(ModifierRecord &Mod) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+ ModifierRecord &Mod) {
uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers());
printTypeIndex("ModifiedType", Mod.getModifiedType());
W->printFlags("Modifiers", Mods, makeArrayRef(TypeModifierNames));
@@ -466,26 +484,30 @@ Error CVTypeDumper::visitModifier(ModifierRecord &Mod) {
return Error::success();
}
-Error CVTypeDumper::visitBitField(BitFieldRecord &BitField) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+ BitFieldRecord &BitField) {
printTypeIndex("Type", BitField.getType());
W->printNumber("BitSize", BitField.getBitSize());
W->printNumber("BitOffset", BitField.getBitOffset());
return Error::success();
}
-Error CVTypeDumper::visitVFTableShape(VFTableShapeRecord &Shape) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+ VFTableShapeRecord &Shape) {
W->printNumber("VFEntryCount", Shape.getEntryCount());
return Error::success();
}
-Error CVTypeDumper::visitUdtSourceLine(UdtSourceLineRecord &Line) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+ UdtSourceLineRecord &Line) {
printTypeIndex("UDT", Line.getUDT());
printTypeIndex("SourceFile", Line.getSourceFile());
W->printNumber("LineNumber", Line.getLineNumber());
return Error::success();
}
-Error CVTypeDumper::visitUdtModSourceLine(UdtModSourceLineRecord &Line) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+ UdtModSourceLineRecord &Line) {
printTypeIndex("UDT", Line.getUDT());
printTypeIndex("SourceFile", Line.getSourceFile());
W->printNumber("LineNumber", Line.getLineNumber());
@@ -493,7 +515,8 @@ Error CVTypeDumper::visitUdtModSourceLine(UdtModSourceLineRecord &Line) {
return Error::success();
}
-Error CVTypeDumper::visitBuildInfo(BuildInfoRecord &Args) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+ BuildInfoRecord &Args) {
W->printNumber("NumArgs", static_cast<uint32_t>(Args.getArgs().size()));
ListScope Arguments(*W, "Arguments");
@@ -533,7 +556,8 @@ Error CVTypeDumper::visitUnknownType(const CVRecord<TypeLeafKind> &Record) {
return Error::success();
}
-Error CVTypeDumper::visitNestedType(NestedTypeRecord &Nested) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+ NestedTypeRecord &Nested) {
DictScope S(*W, "NestedType");
printTypeIndex("Type", Nested.getNestedType());
W->printString("Name", Nested.getName());
@@ -541,7 +565,8 @@ Error CVTypeDumper::visitNestedType(NestedTypeRecord &Nested) {
return Error::success();
}
-Error CVTypeDumper::visitOneMethod(OneMethodRecord &Method) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+ OneMethodRecord &Method) {
DictScope S(*W, "OneMethod");
MethodKind K = Method.getKind();
printMemberAttributes(Method.getAccess(), K, Method.getOptions());
@@ -554,7 +579,8 @@ Error CVTypeDumper::visitOneMethod(OneMethodRecord &Method) {
return Error::success();
}
-Error CVTypeDumper::visitOverloadedMethod(OverloadedMethodRecord &Method) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+ OverloadedMethodRecord &Method) {
DictScope S(*W, "OverloadedMethod");
W->printHex("MethodCount", Method.getNumOverloads());
printTypeIndex("MethodListIndex", Method.getMethodList());
@@ -563,7 +589,8 @@ Error CVTypeDumper::visitOverloadedMethod(OverloadedMethodRecord &Method) {
return Error::success();
}
-Error CVTypeDumper::visitDataMember(DataMemberRecord &Field) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+ DataMemberRecord &Field) {
DictScope S(*W, "DataMember");
printMemberAttributes(Field.getAccess(), MethodKind::Vanilla,
MethodOptions::None);
@@ -574,7 +601,8 @@ Error CVTypeDumper::visitDataMember(DataMemberRecord &Field) {
return Error::success();
}
-Error CVTypeDumper::visitStaticDataMember(StaticDataMemberRecord &Field) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+ StaticDataMemberRecord &Field) {
DictScope S(*W, "StaticDataMember");
printMemberAttributes(Field.getAccess(), MethodKind::Vanilla,
MethodOptions::None);
@@ -584,13 +612,15 @@ Error CVTypeDumper::visitStaticDataMember(StaticDataMemberRecord &Field) {
return Error::success();
}
-Error CVTypeDumper::visitVFPtr(VFPtrRecord &VFTable) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+ VFPtrRecord &VFTable) {
DictScope S(*W, "VFPtr");
printTypeIndex("Type", VFTable.getType());
return Error::success();
}
-Error CVTypeDumper::visitEnumerator(EnumeratorRecord &Enum) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+ EnumeratorRecord &Enum) {
DictScope S(*W, "Enumerator");
printMemberAttributes(Enum.getAccess(), MethodKind::Vanilla,
MethodOptions::None);
@@ -600,7 +630,8 @@ Error CVTypeDumper::visitEnumerator(EnumeratorRecord &Enum) {
return Error::success();
}
-Error CVTypeDumper::visitBaseClass(BaseClassRecord &Base) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+ BaseClassRecord &Base) {
DictScope S(*W, "BaseClass");
printMemberAttributes(Base.getAccess(), MethodKind::Vanilla,
MethodOptions::None);
@@ -609,7 +640,8 @@ Error CVTypeDumper::visitBaseClass(BaseClassRecord &Base) {
return Error::success();
}
-Error CVTypeDumper::visitVirtualBaseClass(VirtualBaseClassRecord &Base) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+ VirtualBaseClassRecord &Base) {
DictScope S(*W, "VirtualBaseClass");
printMemberAttributes(Base.getAccess(), MethodKind::Vanilla,
MethodOptions::None);
@@ -620,7 +652,8 @@ Error CVTypeDumper::visitVirtualBaseClass(VirtualBaseClassRecord &Base) {
return Error::success();
}
-Error CVTypeDumper::visitListContinuation(ListContinuationRecord &Cont) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+ ListContinuationRecord &Cont) {
DictScope S(*W, "ListContinuation");
printTypeIndex("ContinuationIndex", Cont.getContinuationIndex());
return Error::success();
@@ -665,7 +698,8 @@ void CVTypeDumper::printTypeIndex(StringRef FieldName, TypeIndex TI) {
Error CVTypeDumper::dump(const CVRecord<TypeLeafKind> &Record) {
assert(W && "printer should not be null");
- CVTypeVisitor Visitor(*this);
+ TypeDeserializer Deserializer(*this);
+ CVTypeVisitor Visitor(Deserializer);
if (auto EC = Visitor.visitTypeRecord(Record))
return EC;
@@ -674,7 +708,9 @@ Error CVTypeDumper::dump(const CVRecord<TypeLeafKind> &Record) {
Error CVTypeDumper::dump(const CVTypeArray &Types) {
assert(W && "printer should not be null");
- CVTypeVisitor Visitor(*this);
+ TypeDeserializer Deserializer(*this);
+ CVTypeVisitor Visitor(Deserializer);
+
if (auto EC = Visitor.visitTypeStream(Types))
return EC;
return Error::success();
diff --git a/llvm/lib/DebugInfo/CodeView/TypeRecord.cpp b/llvm/lib/DebugInfo/CodeView/TypeRecord.cpp
index 4bbd2616bb5..e630be87345 100644
--- a/llvm/lib/DebugInfo/CodeView/TypeRecord.cpp
+++ b/llvm/lib/DebugInfo/CodeView/TypeRecord.cpp
@@ -114,6 +114,11 @@ NestedTypeRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
return NestedTypeRecord(L->Type, Name);
}
+Expected<FieldListRecord>
+FieldListRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
+ return FieldListRecord(Data);
+}
+
Expected<ArrayRecord> ArrayRecord::deserialize(TypeRecordKind Kind,
ArrayRef<uint8_t> &Data) {
const Layout *L = nullptr;
diff --git a/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp b/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
index 8c2bc072cd9..58c8c3fecb4 100644
--- a/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
+++ b/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
@@ -12,6 +12,7 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/FieldListRecordBuilder.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
@@ -58,7 +59,8 @@ public:
/// TypeVisitorCallbacks overrides.
#define TYPE_RECORD(EnumName, EnumVal, Name) \
- Error visit##Name(Name##Record &Record) override;
+ Error visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, \
+ Name##Record &Record) override;
#define MEMBER_RECORD(EnumName, EnumVal, Name) \
TYPE_RECORD(EnumName, EnumVal, Name)
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
@@ -70,11 +72,28 @@ public:
Error visitTypeBegin(const CVRecord<TypeLeafKind> &Record) override;
Error visitTypeEnd(const CVRecord<TypeLeafKind> &Record) override;
- Error visitFieldListEnd(const CVRecord<TypeLeafKind> &Record) override;
-
bool mergeStream(const CVTypeArray &Types);
private:
+ template <typename RecordType>
+ Error visitKnownRecordImpl(RecordType &Record) {
+ FoundBadTypeIndex |= !Record.remapTypeIndices(IndexMap);
+ IndexMap.push_back(DestStream.writeKnownType(Record));
+ return Error::success();
+ }
+
+ Error visitKnownRecordImpl(FieldListRecord &Record) {
+ // Don't do anything, this will get written in the call to visitTypeEnd().
+ return Error::success();
+ }
+
+ template <typename RecordType>
+ Error visitKnownMemberRecordImpl(RecordType &Record) {
+ FoundBadTypeIndex |= !Record.remapTypeIndices(IndexMap);
+ FieldBuilder.writeMemberType(Record);
+ return Error::success();
+ }
+
bool hadError() { return FoundBadTypeIndex; }
bool FoundBadTypeIndex = false;
@@ -93,33 +112,31 @@ private:
} // end anonymous namespace
Error TypeStreamMerger::visitTypeBegin(const CVRecord<TypeLeafKind> &Rec) {
- BeginIndexMapSize = IndexMap.size();
+ if (Rec.Type != TypeLeafKind::LF_FIELDLIST)
+ BeginIndexMapSize = IndexMap.size();
return Error::success();
}
Error TypeStreamMerger::visitTypeEnd(const CVRecord<TypeLeafKind> &Rec) {
- assert(IndexMap.size() == BeginIndexMapSize + 1);
- return Error::success();
-}
-
-Error TypeStreamMerger::visitFieldListEnd(const CVRecord<TypeLeafKind> &Rec) {
- IndexMap.push_back(DestStream.writeFieldList(FieldBuilder));
- FieldBuilder.reset();
+ if (Rec.Type == TypeLeafKind::LF_FIELDLIST) {
+ IndexMap.push_back(DestStream.writeFieldList(FieldBuilder));
+ FieldBuilder.reset();
+ } else {
+ assert(IndexMap.size() == BeginIndexMapSize + 1);
+ }
return Error::success();
}
#define TYPE_RECORD(EnumName, EnumVal, Name) \
- Error TypeStreamMerger::visit##Name(Name##Record &Record) { \
- FoundBadTypeIndex |= !Record.remapTypeIndices(IndexMap); \
- IndexMap.push_back(DestStream.write##Name(Record)); \
- return Error::success(); \
+ Error TypeStreamMerger::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, \
+ Name##Record &Record) { \
+ return visitKnownRecordImpl(Record); \
}
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#define MEMBER_RECORD(EnumName, EnumVal, Name) \
- Error TypeStreamMerger::visit##Name(Name##Record &Record) { \
- FoundBadTypeIndex |= !Record.remapTypeIndices(IndexMap); \
- FieldBuilder.write##Name(Record); \
- return Error::success(); \
+ Error TypeStreamMerger::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, \
+ Name##Record &Record) { \
+ return visitKnownMemberRecordImpl(Record); \
}
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
@@ -133,7 +150,9 @@ Error TypeStreamMerger::visitUnknownType(const CVRecord<TypeLeafKind> &Rec) {
bool TypeStreamMerger::mergeStream(const CVTypeArray &Types) {
assert(IndexMap.empty());
- CVTypeVisitor Visitor(*this);
+ TypeDeserializer Deserializer(*this);
+ CVTypeVisitor Visitor(Deserializer);
+
if (auto EC = Visitor.visitTypeStream(Types)) {
consumeError(std::move(EC));
return false;
diff --git a/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp b/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp
index 647538ee8ce..0fcf4f92d43 100644
--- a/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp
+++ b/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp
@@ -21,7 +21,7 @@ TypeTableBuilder::TypeTableBuilder() {}
TypeTableBuilder::~TypeTableBuilder() {}
-TypeIndex TypeTableBuilder::writeModifier(const ModifierRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const ModifierRecord &Record) {
TypeRecordBuilder Builder(Record.getKind());
Builder.writeTypeIndex(Record.getModifiedType());
@@ -30,7 +30,7 @@ TypeIndex TypeTableBuilder::writeModifier(const ModifierRecord &Record) {
return writeRecord(Builder);
}
-TypeIndex TypeTableBuilder::writeProcedure(const ProcedureRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const ProcedureRecord &Record) {
TypeRecordBuilder Builder(Record.getKind());
Builder.writeTypeIndex(Record.getReturnType());
@@ -42,8 +42,7 @@ TypeIndex TypeTableBuilder::writeProcedure(const ProcedureRecord &Record) {
return writeRecord(Builder);
}
-TypeIndex
-TypeTableBuilder::writeMemberFunction(const MemberFunctionRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const MemberFunctionRecord &Record) {
TypeRecordBuilder Builder(Record.getKind());
Builder.writeTypeIndex(Record.getReturnType());
@@ -58,7 +57,7 @@ TypeTableBuilder::writeMemberFunction(const MemberFunctionRecord &Record) {
return writeRecord(Builder);
}
-TypeIndex TypeTableBuilder::writeArgList(const ArgListRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const ArgListRecord &Record) {
TypeRecordBuilder Builder(Record.getKind());
Builder.writeUInt32(Record.getIndices().size());
@@ -69,7 +68,7 @@ TypeIndex TypeTableBuilder::writeArgList(const ArgListRecord &Record) {
return writeRecord(Builder);
}
-TypeIndex TypeTableBuilder::writePointer(const PointerRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const PointerRecord &Record) {
TypeRecordBuilder Builder(Record.getKind());
Builder.writeTypeIndex(Record.getReferentType());
@@ -90,7 +89,7 @@ TypeIndex TypeTableBuilder::writePointer(const PointerRecord &Record) {
return writeRecord(Builder);
}
-TypeIndex TypeTableBuilder::writeArray(const ArrayRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const ArrayRecord &Record) {
TypeRecordBuilder Builder(Record.getKind());
Builder.writeTypeIndex(Record.getElementType());
@@ -101,7 +100,7 @@ TypeIndex TypeTableBuilder::writeArray(const ArrayRecord &Record) {
return writeRecord(Builder);
}
-TypeIndex TypeTableBuilder::writeClass(const ClassRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const ClassRecord &Record) {
assert((Record.getKind() == TypeRecordKind::Struct) ||
(Record.getKind() == TypeRecordKind::Class) ||
(Record.getKind() == TypeRecordKind::Interface));
@@ -128,7 +127,7 @@ TypeIndex TypeTableBuilder::writeClass(const ClassRecord &Record) {
return writeRecord(Builder);
}
-TypeIndex TypeTableBuilder::writeUnion(const UnionRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const UnionRecord &Record) {
TypeRecordBuilder Builder(TypeRecordKind::Union);
Builder.writeUInt16(Record.getMemberCount());
uint16_t Flags =
@@ -145,7 +144,7 @@ TypeIndex TypeTableBuilder::writeUnion(const UnionRecord &Record) {
return writeRecord(Builder);
}
-TypeIndex TypeTableBuilder::writeEnum(const EnumRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const EnumRecord &Record) {
TypeRecordBuilder Builder(Record.getKind());
Builder.writeUInt16(Record.getMemberCount());
@@ -161,7 +160,7 @@ TypeIndex TypeTableBuilder::writeEnum(const EnumRecord &Record) {
return writeRecord(Builder);
}
-TypeIndex TypeTableBuilder::writeBitField(const BitFieldRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const BitFieldRecord &Record) {
TypeRecordBuilder Builder(Record.getKind());
Builder.writeTypeIndex(Record.getType());
@@ -171,8 +170,7 @@ TypeIndex TypeTableBuilder::writeBitField(const BitFieldRecord &Record) {
return writeRecord(Builder);
}
-TypeIndex
-TypeTableBuilder::writeVFTableShape(const VFTableShapeRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const VFTableShapeRecord &Record) {
TypeRecordBuilder Builder(Record.getKind());
ArrayRef<VFTableSlotKind> Slots = Record.getSlots();
@@ -189,8 +187,7 @@ TypeTableBuilder::writeVFTableShape(const VFTableShapeRecord &Record) {
return writeRecord(Builder);
}
-TypeIndex
-TypeTableBuilder::writeVFTable(const VFTableRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const VFTableRecord &Record) {
TypeRecordBuilder Builder(Record.getKind());
Builder.writeTypeIndex(Record.getCompleteClass());
Builder.writeTypeIndex(Record.getOverriddenVTable());
@@ -209,15 +206,14 @@ TypeTableBuilder::writeVFTable(const VFTableRecord &Record) {
return writeRecord(Builder);
}
-TypeIndex TypeTableBuilder::writeStringId(const StringIdRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const StringIdRecord &Record) {
TypeRecordBuilder Builder(TypeRecordKind::StringId);
Builder.writeTypeIndex(Record.getId());
Builder.writeNullTerminatedString(Record.getString());
return writeRecord(Builder);
}
-TypeIndex
-TypeTableBuilder::writeUdtSourceLine(const UdtSourceLineRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const UdtSourceLineRecord &Record) {
TypeRecordBuilder Builder(Record.getKind());
Builder.writeTypeIndex(Record.getUDT());
Builder.writeTypeIndex(Record.getSourceFile());
@@ -226,7 +222,7 @@ TypeTableBuilder::writeUdtSourceLine(const UdtSourceLineRecord &Record) {
}
TypeIndex
-TypeTableBuilder::writeUdtModSourceLine(const UdtModSourceLineRecord &Record) {
+TypeTableBuilder::writeKnownType(const UdtModSourceLineRecord &Record) {
TypeRecordBuilder Builder(Record.getKind());
Builder.writeTypeIndex(Record.getUDT());
Builder.writeTypeIndex(Record.getSourceFile());
@@ -235,7 +231,7 @@ TypeTableBuilder::writeUdtModSourceLine(const UdtModSourceLineRecord &Record) {
return writeRecord(Builder);
}
-TypeIndex TypeTableBuilder::writeFuncId(const FuncIdRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const FuncIdRecord &Record) {
TypeRecordBuilder Builder(Record.getKind());
Builder.writeTypeIndex(Record.getParentScope());
Builder.writeTypeIndex(Record.getFunctionType());
@@ -243,8 +239,7 @@ TypeIndex TypeTableBuilder::writeFuncId(const FuncIdRecord &Record) {
return writeRecord(Builder);
}
-TypeIndex
-TypeTableBuilder::writeMemberFuncId(const MemberFuncIdRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const MemberFuncIdRecord &Record) {
TypeRecordBuilder Builder(Record.getKind());
Builder.writeTypeIndex(Record.getClassType());
Builder.writeTypeIndex(Record.getFunctionType());
@@ -252,8 +247,7 @@ TypeTableBuilder::writeMemberFuncId(const MemberFuncIdRecord &Record) {
return writeRecord(Builder);
}
-TypeIndex
-TypeTableBuilder::writeBuildInfo(const BuildInfoRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const BuildInfoRecord &Record) {
TypeRecordBuilder Builder(Record.getKind());
assert(Record.getArgs().size() <= UINT16_MAX);
Builder.writeUInt16(Record.getArgs().size());
@@ -270,8 +264,8 @@ TypeIndex TypeTableBuilder::writeFieldList(FieldListRecordBuilder &FieldList) {
return FieldList.writeListRecord(*this);
}
-TypeIndex TypeTableBuilder::writeMethodOverloadList(
- const MethodOverloadListRecord &Record) {
+TypeIndex
+TypeTableBuilder::writeKnownType(const MethodOverloadListRecord &Record) {
TypeRecordBuilder Builder(Record.getKind());
for (const OneMethodRecord &Method : Record.getMethods()) {
uint16_t Flags = static_cast<uint16_t>(Method.getAccess());
@@ -294,7 +288,7 @@ TypeIndex TypeTableBuilder::writeMethodOverloadList(
return writeRecord(Builder);
}
-TypeIndex TypeTableBuilder::writeTypeServer2(const TypeServer2Record &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const TypeServer2Record &Record) {
TypeRecordBuilder Builder(Record.getKind());
Builder.writeGuid(Record.getGuid());
Builder.writeUInt32(Record.getAge());
diff --git a/llvm/lib/DebugInfo/PDB/Raw/TpiStream.cpp b/llvm/lib/DebugInfo/PDB/Raw/TpiStream.cpp
index 1398628f231..424ef0ef441 100644
--- a/llvm/lib/DebugInfo/PDB/Raw/TpiStream.cpp
+++ b/llvm/lib/DebugInfo/PDB/Raw/TpiStream.cpp
@@ -11,6 +11,7 @@
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
@@ -96,17 +97,28 @@ public:
uint32_t NumHashBuckets)
: HashValues(HashValues), NumHashBuckets(NumHashBuckets) {}
- Error visitUdtSourceLine(UdtSourceLineRecord &Rec) override {
+ Error visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+ UdtSourceLineRecord &Rec) override {
return verifySourceLine(Rec);
}
- Error visitUdtModSourceLine(UdtModSourceLineRecord &Rec) override {
+ Error visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+ UdtModSourceLineRecord &Rec) override {
return verifySourceLine(Rec);
}
- Error visitClass(ClassRecord &Rec) override { return verify(Rec); }
- Error visitEnum(EnumRecord &Rec) override { return verify(Rec); }
- Error visitUnion(UnionRecord &Rec) override { return verify(Rec); }
+ Error visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+ ClassRecord &Rec) override {
+ return verify(Rec);
+ }
+ Error visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+ EnumRecord &Rec) override {
+ return verify(Rec);
+ }
+ Error visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+ UnionRecord &Rec) override {
+ return verify(Rec);
+ }
Error visitTypeBegin(const CVRecord<TypeLeafKind> &Rec) override {
++Index;
@@ -148,7 +160,8 @@ private:
// Currently we only verify SRC_LINE records.
Error TpiStream::verifyHashValues() {
TpiHashVerifier Verifier(HashValues, Header->NumHashBuckets);
- CVTypeVisitor Visitor(Verifier);
+ TypeDeserializer Deserializer(Verifier);
+ CVTypeVisitor Visitor(Deserializer);
return Visitor.visitTypeStream(TypeRecords);
}
OpenPOWER on IntegriCloud