summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorZachary Turner <zturner@google.com>2016-10-20 18:31:19 +0000
committerZachary Turner <zturner@google.com>2016-10-20 18:31:19 +0000
commit4d49eb9fa0bb4ddc87329192ca24ffebedd05e1b (patch)
tree79095d7ef7bcc737b2e8854662d25ffa834b0b9c /llvm/lib
parentf70a906a11d68f716a7337341b4dddb418081a3f (diff)
downloadbcm5719-llvm-4d49eb9fa0bb4ddc87329192ca24ffebedd05e1b.tar.gz
bcm5719-llvm-4d49eb9fa0bb4ddc87329192ca24ffebedd05e1b.zip
[CodeView] Refactor serialization to use StreamInterface.
This was all using ArrayRef<>s before which presents a problem when you want to serialize to or deserialize from an actual PDB stream. An ArrayRef<> is really just a special case of what can be handled with StreamInterface though (e.g. by using a ByteStream), so changing this to use StreamInterface allows us to plug in a PDB stream and get all the record serialization and deserialization for free on a MappedBlockStream. Subsequent patches will try to remove TypeTableBuilder and TypeRecordBuilder in favor of class that operate on Streams as well, which should allow us to completely merge the reading and writing codepaths for both types and symbols. Differential Revision: https://reviews.llvm.org/D25831 llvm-svn: 284762
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp62
-rw-r--r--llvm/lib/DebugInfo/CodeView/RecordSerialization.cpp173
-rw-r--r--llvm/lib/DebugInfo/CodeView/TypeRecord.cpp161
-rw-r--r--llvm/lib/DebugInfo/MSF/StreamReader.cpp63
4 files changed, 242 insertions, 217 deletions
diff --git a/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp b/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
index deefa8d4ef0..2dee8988df9 100644
--- a/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
+++ b/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
@@ -15,47 +15,38 @@
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();
-}
-
-static Error skipPadding(ArrayRef<uint8_t> &Data) {
- if (Data.empty())
+static Error skipPadding(msf::StreamReader &Reader) {
+ if (Reader.empty())
return Error::success();
- uint8_t Leaf = Data.front();
+
+ uint8_t Leaf = Reader.peek();
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();
+ return Reader.skip(BytesToAdvance);
}
template <typename T>
-static Expected<CVMemberRecord> deserializeMemberRecord(ArrayRef<uint8_t> &Data,
- TypeLeafKind Kind) {
- ArrayRef<uint8_t> OldData = Data;
+static Expected<CVMemberRecord>
+deserializeMemberRecord(msf::StreamReader &Reader, TypeLeafKind Kind) {
+ msf::StreamReader OldReader = Reader;
TypeRecordKind RK = static_cast<TypeRecordKind>(Kind);
- auto ExpectedRecord = T::deserialize(RK, Data);
+ auto ExpectedRecord = T::deserialize(RK, Reader);
if (!ExpectedRecord)
return ExpectedRecord.takeError();
- assert(Data.size() < OldData.size());
- if (auto EC = skipPadding(Data))
+ assert(Reader.bytesRemaining() < OldReader.bytesRemaining());
+ if (auto EC = skipPadding(Reader))
return std::move(EC);
CVMemberRecord CVMR;
CVMR.Kind = Kind;
- CVMR.Data = OldData.drop_back(Data.size());
+
+ uint32_t RecordLength = OldReader.bytesRemaining() - Reader.bytesRemaining();
+ if (auto EC = OldReader.readBytes(CVMR.Data, RecordLength))
+ return std::move(EC);
+
return CVMR;
}
@@ -147,9 +138,9 @@ Error CVTypeVisitor::visitTypeStream(const CVTypeArray &Types) {
}
template <typename MR>
-static Error visitKnownMember(ArrayRef<uint8_t> &Data, TypeLeafKind Leaf,
+static Error visitKnownMember(msf::StreamReader &Reader, TypeLeafKind Leaf,
TypeVisitorCallbacks &Callbacks) {
- auto ExpectedRecord = deserializeMemberRecord<MR>(Data, Leaf);
+ auto ExpectedRecord = deserializeMemberRecord<MR>(Reader, Leaf);
if (!ExpectedRecord)
return ExpectedRecord.takeError();
CVMemberRecord &Record = *ExpectedRecord;
@@ -162,13 +153,12 @@ static Error visitKnownMember(ArrayRef<uint8_t> &Data, TypeLeafKind Leaf,
return Error::success();
}
-Error CVTypeVisitor::visitFieldListMemberStream(ArrayRef<uint8_t> Data) {
- while (!Data.empty()) {
- const support::ulittle16_t *LeafValue;
- if (auto EC = takeObject(Data, LeafValue))
+Error CVTypeVisitor::visitFieldListMemberStream(msf::StreamReader Reader) {
+ TypeLeafKind Leaf;
+ while (!Reader.empty()) {
+ if (auto EC = Reader.readEnum(Leaf))
return EC;
- TypeLeafKind Leaf = static_cast<TypeLeafKind>(uint16_t(*LeafValue));
CVType Record;
switch (Leaf) {
default:
@@ -178,7 +168,7 @@ Error CVTypeVisitor::visitFieldListMemberStream(ArrayRef<uint8_t> Data) {
cv_error_code::unknown_member_record);
#define MEMBER_RECORD(EnumName, EnumVal, Name) \
case EnumName: { \
- if (auto EC = visitKnownMember<Name##Record>(Data, Leaf, Callbacks)) \
+ if (auto EC = visitKnownMember<Name##Record>(Reader, Leaf, Callbacks)) \
return EC; \
break; \
}
@@ -189,3 +179,9 @@ Error CVTypeVisitor::visitFieldListMemberStream(ArrayRef<uint8_t> Data) {
}
return Error::success();
}
+
+Error CVTypeVisitor::visitFieldListMemberStream(ArrayRef<uint8_t> Data) {
+ msf::ByteStream S(Data);
+ msf::StreamReader SR(S);
+ return visitFieldListMemberStream(SR);
+}
diff --git a/llvm/lib/DebugInfo/CodeView/RecordSerialization.cpp b/llvm/lib/DebugInfo/CodeView/RecordSerialization.cpp
index 9386d29f223..6f29caa9bbf 100644
--- a/llvm/lib/DebugInfo/CodeView/RecordSerialization.cpp
+++ b/llvm/lib/DebugInfo/CodeView/RecordSerialization.cpp
@@ -16,6 +16,7 @@
#include "llvm/ADT/APSInt.h"
#include "llvm/DebugInfo/CodeView/CodeViewError.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/MSF/ByteStream.h"
using namespace llvm;
using namespace llvm::codeview;
@@ -32,114 +33,88 @@ StringRef llvm::codeview::getBytesAsCString(ArrayRef<uint8_t> LeafData) {
return getBytesAsCharacters(LeafData).split('\0').first;
}
-Error llvm::codeview::consume(ArrayRef<uint8_t> &Data, APSInt &Num) {
+Error llvm::codeview::consume(msf::StreamReader &Reader, APSInt &Num) {
// Used to avoid overload ambiguity on APInt construtor.
bool FalseVal = false;
- if (Data.size() < 2)
- return make_error<CodeViewError>(
- cv_error_code::insufficient_buffer,
- "Buffer does not contain enough data for an APSInt");
- uint16_t Short = *reinterpret_cast<const ulittle16_t *>(Data.data());
- Data = Data.drop_front(2);
+ uint16_t Short;
+ if (auto EC = Reader.readInteger(Short))
+ return EC;
+
if (Short < LF_NUMERIC) {
Num = APSInt(APInt(/*numBits=*/16, Short, /*isSigned=*/false),
/*isUnsigned=*/true);
return Error::success();
}
+
switch (Short) {
- case LF_CHAR:
- if (Data.size() < 1)
- return make_error<CodeViewError>(
- cv_error_code::insufficient_buffer,
- "Buffer does not contain enough data for an LF_CHAR");
- Num = APSInt(APInt(/*numBits=*/8,
- *reinterpret_cast<const int8_t *>(Data.data()),
- /*isSigned=*/true),
- /*isUnsigned=*/false);
- Data = Data.drop_front(1);
+ case LF_CHAR: {
+ int8_t N;
+ if (auto EC = Reader.readInteger(N))
+ return EC;
+ Num = APSInt(APInt(8, N, true), false);
return Error::success();
- case LF_SHORT:
- if (Data.size() < 2)
- return make_error<CodeViewError>(
- cv_error_code::insufficient_buffer,
- "Buffer does not contain enough data for an LF_SHORT");
- Num = APSInt(APInt(/*numBits=*/16,
- *reinterpret_cast<const little16_t *>(Data.data()),
- /*isSigned=*/true),
- /*isUnsigned=*/false);
- Data = Data.drop_front(2);
+ }
+ case LF_SHORT: {
+ int16_t N;
+ if (auto EC = Reader.readInteger(N))
+ return EC;
+ Num = APSInt(APInt(16, N, true), false);
return Error::success();
- case LF_USHORT:
- if (Data.size() < 2)
- return make_error<CodeViewError>(
- cv_error_code::insufficient_buffer,
- "Buffer does not contain enough data for an LF_USHORT");
- Num = APSInt(APInt(/*numBits=*/16,
- *reinterpret_cast<const ulittle16_t *>(Data.data()),
- /*isSigned=*/false),
- /*isUnsigned=*/true);
- Data = Data.drop_front(2);
+ }
+ case LF_USHORT: {
+ uint16_t N;
+ if (auto EC = Reader.readInteger(N))
+ return EC;
+ Num = APSInt(APInt(16, N, false), true);
return Error::success();
- case LF_LONG:
- if (Data.size() < 4)
- return make_error<CodeViewError>(
- cv_error_code::insufficient_buffer,
- "Buffer does not contain enough data for an LF_LONG");
- Num = APSInt(APInt(/*numBits=*/32,
- *reinterpret_cast<const little32_t *>(Data.data()),
- /*isSigned=*/true),
- /*isUnsigned=*/false);
- Data = Data.drop_front(4);
+ }
+ case LF_LONG: {
+ int32_t N;
+ if (auto EC = Reader.readInteger(N))
+ return EC;
+ Num = APSInt(APInt(32, N, true), false);
return Error::success();
- case LF_ULONG:
- if (Data.size() < 4)
- return make_error<CodeViewError>(
- cv_error_code::insufficient_buffer,
- "Buffer does not contain enough data for an LF_ULONG");
- Num = APSInt(APInt(/*numBits=*/32,
- *reinterpret_cast<const ulittle32_t *>(Data.data()),
- /*isSigned=*/FalseVal),
- /*isUnsigned=*/true);
- Data = Data.drop_front(4);
+ }
+ case LF_ULONG: {
+ uint32_t N;
+ if (auto EC = Reader.readInteger(N))
+ return EC;
+ Num = APSInt(APInt(32, N, FalseVal), true);
return Error::success();
- case LF_QUADWORD:
- if (Data.size() < 8)
- return make_error<CodeViewError>(
- cv_error_code::insufficient_buffer,
- "Buffer does not contain enough data for an LF_QUADWORD");
- Num = APSInt(APInt(/*numBits=*/64,
- *reinterpret_cast<const little64_t *>(Data.data()),
- /*isSigned=*/true),
- /*isUnsigned=*/false);
- Data = Data.drop_front(8);
+ }
+ case LF_QUADWORD: {
+ int64_t N;
+ if (auto EC = Reader.readInteger(N))
+ return EC;
+ Num = APSInt(APInt(64, N, true), false);
return Error::success();
- case LF_UQUADWORD:
- if (Data.size() < 8)
- return make_error<CodeViewError>(
- cv_error_code::insufficient_buffer,
- "Buffer does not contain enough data for an LF_UQUADWORD");
- Num = APSInt(APInt(/*numBits=*/64,
- *reinterpret_cast<const ulittle64_t *>(Data.data()),
- /*isSigned=*/false),
- /*isUnsigned=*/true);
- Data = Data.drop_front(8);
+ }
+ case LF_UQUADWORD: {
+ uint64_t N;
+ if (auto EC = Reader.readInteger(N))
+ return EC;
+ Num = APSInt(APInt(64, N, false), true);
return Error::success();
}
+ }
return make_error<CodeViewError>(cv_error_code::corrupt_record,
"Buffer contains invalid APSInt type");
}
Error llvm::codeview::consume(StringRef &Data, APSInt &Num) {
ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end());
- auto EC = consume(Bytes, Num);
- Data = StringRef(reinterpret_cast<const char *>(Bytes.data()), Bytes.size());
+ msf::ByteStream S(Bytes);
+ msf::StreamReader SR(S);
+ auto EC = consume(SR, Num);
+ Data = Data.take_back(SR.bytesRemaining());
return EC;
}
/// Decode a numeric leaf value that is known to be a uint64_t.
-Error llvm::codeview::consume_numeric(ArrayRef<uint8_t> &Data, uint64_t &Num) {
+Error llvm::codeview::consume_numeric(msf::StreamReader &Reader,
+ uint64_t &Num) {
APSInt N;
- if (auto EC = consume(Data, N))
+ if (auto EC = consume(Reader, N))
return EC;
if (N.isSigned() || !N.isIntN(64))
return make_error<CodeViewError>(cv_error_code::corrupt_record,
@@ -148,41 +123,27 @@ Error llvm::codeview::consume_numeric(ArrayRef<uint8_t> &Data, uint64_t &Num) {
return Error::success();
}
-Error llvm::codeview::consume(ArrayRef<uint8_t> &Data, uint32_t &Item) {
- const support::ulittle32_t *IntPtr;
- if (auto EC = consumeObject(Data, IntPtr))
- return EC;
- Item = *IntPtr;
- return Error::success();
+Error llvm::codeview::consume(msf::StreamReader &Reader, uint32_t &Item) {
+ return Reader.readInteger(Item);
}
Error llvm::codeview::consume(StringRef &Data, uint32_t &Item) {
ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end());
- auto EC = consume(Bytes, Item);
- Data = StringRef(reinterpret_cast<const char *>(Bytes.data()), Bytes.size());
+ msf::ByteStream S(Bytes);
+ msf::StreamReader SR(S);
+ auto EC = consume(SR, Item);
+ Data = Data.take_back(SR.bytesRemaining());
return EC;
}
-Error llvm::codeview::consume(ArrayRef<uint8_t> &Data, int32_t &Item) {
- const support::little32_t *IntPtr;
- if (auto EC = consumeObject(Data, IntPtr))
- return EC;
- Item = *IntPtr;
- return Error::success();
+Error llvm::codeview::consume(msf::StreamReader &Reader, int32_t &Item) {
+ return Reader.readInteger(Item);
}
-Error llvm::codeview::consume(ArrayRef<uint8_t> &Data, StringRef &Item) {
- if (Data.empty())
+Error llvm::codeview::consume(msf::StreamReader &Reader, StringRef &Item) {
+ if (Reader.empty())
return make_error<CodeViewError>(cv_error_code::corrupt_record,
"Null terminated string buffer is empty!");
- StringRef Rest;
- std::tie(Item, Rest) = getBytesAsCharacters(Data).split('\0');
- // We expect this to be null terminated. If it was not, it is an error.
- if (Data.size() == Item.size())
- return make_error<CodeViewError>(cv_error_code::corrupt_record,
- "Expected null terminator!");
-
- Data = ArrayRef<uint8_t>(Rest.bytes_begin(), Rest.bytes_end());
- return Error::success();
+ return Reader.readZeroString(Item);
}
diff --git a/llvm/lib/DebugInfo/CodeView/TypeRecord.cpp b/llvm/lib/DebugInfo/CodeView/TypeRecord.cpp
index 47aa04fe76a..a7a1bb9228c 100644
--- a/llvm/lib/DebugInfo/CodeView/TypeRecord.cpp
+++ b/llvm/lib/DebugInfo/CodeView/TypeRecord.cpp
@@ -11,6 +11,7 @@
#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/MSF/ByteStream.h"
+#include "llvm/DebugInfo/MSF/StreamReader.h"
using namespace llvm;
using namespace llvm::codeview;
@@ -20,9 +21,9 @@ using namespace llvm::codeview;
//===----------------------------------------------------------------------===//
Expected<MemberPointerInfo>
-MemberPointerInfo::deserialize(ArrayRef<uint8_t> &Data) {
+MemberPointerInfo::deserialize(msf::StreamReader &Reader) {
const Layout *L = nullptr;
- if (auto EC = consumeObject(Data, L))
+ if (auto EC = Reader.readObject(L))
return std::move(EC);
TypeIndex T = L->ClassType;
@@ -32,10 +33,10 @@ MemberPointerInfo::deserialize(ArrayRef<uint8_t> &Data) {
return MemberPointerInfo(T, PMR);
}
-Expected<ModifierRecord> ModifierRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
+Expected<ModifierRecord>
+ModifierRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
const Layout *L = nullptr;
- if (auto EC = consumeObject(Data, L))
+ if (auto EC = Reader.readObject(L))
return std::move(EC);
TypeIndex M = L->ModifiedType;
@@ -45,9 +46,9 @@ Expected<ModifierRecord> ModifierRecord::deserialize(TypeRecordKind Kind,
}
Expected<ProcedureRecord>
-ProcedureRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
+ProcedureRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
const Layout *L = nullptr;
- if (auto EC = consumeObject(Data, L))
+ if (auto EC = Reader.readObject(L))
return std::move(EC);
return ProcedureRecord(L->ReturnType, L->CallConv, L->Options,
L->NumParameters, L->ArgListType);
@@ -55,24 +56,25 @@ ProcedureRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
Expected<MemberFunctionRecord>
MemberFunctionRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Layout *L = nullptr;
- CV_DESERIALIZE(Data, L);
+ CV_DESERIALIZE(Reader, L);
return MemberFunctionRecord(L->ReturnType, L->ClassType, L->ThisType,
L->CallConv, L->Options, L->NumParameters,
L->ArgListType, L->ThisAdjustment);
}
Expected<MemberFuncIdRecord>
-MemberFuncIdRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
+MemberFuncIdRecord::deserialize(TypeRecordKind Kind,
+ msf::StreamReader &Reader) {
const Layout *L = nullptr;
StringRef Name;
- CV_DESERIALIZE(Data, L, Name);
+ CV_DESERIALIZE(Reader, L, Name);
return MemberFuncIdRecord(L->ClassType, L->FunctionType, Name);
}
Expected<ArgListRecord> ArgListRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
if (Kind != TypeRecordKind::StringList && Kind != TypeRecordKind::ArgList)
return make_error<CodeViewError>(
cv_error_code::corrupt_record,
@@ -80,14 +82,14 @@ Expected<ArgListRecord> ArgListRecord::deserialize(TypeRecordKind Kind,
const Layout *L = nullptr;
ArrayRef<TypeIndex> Indices;
- CV_DESERIALIZE(Data, L, CV_ARRAY_FIELD_N(Indices, L->NumArgs));
+ CV_DESERIALIZE(Reader, L, CV_ARRAY_FIELD_N(Indices, L->NumArgs));
return ArgListRecord(Kind, Indices);
}
Expected<PointerRecord> PointerRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Layout *L = nullptr;
- if (auto EC = consumeObject(Data, L))
+ if (auto EC = Reader.readObject(L))
return std::move(EC);
PointerKind PtrKind = L->getPtrKind();
@@ -97,7 +99,7 @@ Expected<PointerRecord> PointerRecord::deserialize(TypeRecordKind Kind,
uint8_t Size = L->getPtrSize();
if (L->isPointerToMember()) {
- if (auto ExpectedMPI = MemberPointerInfo::deserialize(Data))
+ if (auto ExpectedMPI = MemberPointerInfo::deserialize(Reader))
return PointerRecord(L->PointeeType, PtrKind, Mode, Options, Size,
*ExpectedMPI);
else
@@ -108,38 +110,39 @@ Expected<PointerRecord> PointerRecord::deserialize(TypeRecordKind Kind,
}
Expected<NestedTypeRecord>
-NestedTypeRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
+NestedTypeRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
const Layout *L = nullptr;
StringRef Name;
- CV_DESERIALIZE(Data, L, Name);
+ CV_DESERIALIZE(Reader, L, Name);
return NestedTypeRecord(L->Type, Name);
}
Expected<FieldListRecord>
-FieldListRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
- auto FieldListData = Data;
- Data = ArrayRef<uint8_t>();
- return FieldListRecord(FieldListData);
+FieldListRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
+ ArrayRef<uint8_t> Data;
+ if (auto EC = Reader.readBytes(Data, Reader.bytesRemaining()))
+ return std::move(EC);
+ return FieldListRecord(Data);
}
Expected<ArrayRecord> ArrayRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Layout *L = nullptr;
uint64_t Size;
StringRef Name;
- CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Size), Name);
+ CV_DESERIALIZE(Reader, L, CV_NUMERIC_FIELD(Size), Name);
return ArrayRecord(L->ElementType, L->IndexType, Size, Name);
}
Expected<ClassRecord> ClassRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
uint64_t Size = 0;
StringRef Name;
StringRef UniqueName;
uint16_t Props;
const Layout *L = nullptr;
- CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Size), Name,
+ CV_DESERIALIZE(Reader, L, CV_NUMERIC_FIELD(Size), Name,
CV_CONDITIONAL_FIELD(UniqueName, L->hasUniqueName()));
Props = L->Properties;
@@ -154,14 +157,14 @@ Expected<ClassRecord> ClassRecord::deserialize(TypeRecordKind Kind,
}
Expected<UnionRecord> UnionRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
uint64_t Size = 0;
StringRef Name;
StringRef UniqueName;
uint16_t Props;
const Layout *L = nullptr;
- CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Size), Name,
+ CV_DESERIALIZE(Reader, L, CV_NUMERIC_FIELD(Size), Name,
CV_CONDITIONAL_FIELD(UniqueName, L->hasUniqueName()));
Props = L->Properties;
@@ -174,11 +177,11 @@ Expected<UnionRecord> UnionRecord::deserialize(TypeRecordKind Kind,
}
Expected<EnumRecord> EnumRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Layout *L = nullptr;
StringRef Name;
StringRef UniqueName;
- CV_DESERIALIZE(Data, L, Name,
+ CV_DESERIALIZE(Reader, L, Name,
CV_CONDITIONAL_FIELD(UniqueName, L->hasUniqueName()));
uint16_t P = L->Properties;
@@ -187,97 +190,98 @@ Expected<EnumRecord> EnumRecord::deserialize(TypeRecordKind Kind,
UniqueName, L->UnderlyingType);
}
-Expected<BitFieldRecord> BitFieldRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
+Expected<BitFieldRecord>
+BitFieldRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
const Layout *L = nullptr;
- CV_DESERIALIZE(Data, L);
+ CV_DESERIALIZE(Reader, L);
return BitFieldRecord(L->Type, L->BitSize, L->BitOffset);
}
Expected<VFTableShapeRecord>
-VFTableShapeRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
+VFTableShapeRecord::deserialize(TypeRecordKind Kind,
+ msf::StreamReader &Reader) {
const Layout *L = nullptr;
- if (auto EC = consumeObject(Data, L))
+ if (auto EC = Reader.readObject(L))
return std::move(EC);
std::vector<VFTableSlotKind> Slots;
uint16_t Count = L->VFEntryCount;
while (Count > 0) {
- if (Data.empty())
- return make_error<CodeViewError>(cv_error_code::corrupt_record,
- "VTableShapeRecord contains no entries");
-
// Process up to 2 nibbles at a time (if there are at least 2 remaining)
- uint8_t Value = Data[0] & 0x0F;
+ uint8_t Data;
+ if (auto EC = Reader.readInteger(Data))
+ return std::move(EC);
+
+ uint8_t Value = Data & 0x0F;
Slots.push_back(static_cast<VFTableSlotKind>(Value));
if (--Count > 0) {
- Value = (Data[0] & 0xF0) >> 4;
+ Value = (Data & 0xF0) >> 4;
Slots.push_back(static_cast<VFTableSlotKind>(Value));
--Count;
}
- Data = Data.slice(1);
}
return VFTableShapeRecord(Slots);
}
Expected<TypeServer2Record>
-TypeServer2Record::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
+TypeServer2Record::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
const Layout *L = nullptr;
StringRef Name;
- CV_DESERIALIZE(Data, L, Name);
+ CV_DESERIALIZE(Reader, L, Name);
return TypeServer2Record(StringRef(L->Guid, 16), L->Age, Name);
}
-Expected<StringIdRecord> StringIdRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
+Expected<StringIdRecord>
+StringIdRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
const Layout *L = nullptr;
StringRef Name;
- CV_DESERIALIZE(Data, L, Name);
+ CV_DESERIALIZE(Reader, L, Name);
return StringIdRecord(L->id, Name);
}
Expected<FuncIdRecord> FuncIdRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Layout *L = nullptr;
StringRef Name;
- CV_DESERIALIZE(Data, L, Name);
+ CV_DESERIALIZE(Reader, L, Name);
return FuncIdRecord(L->ParentScope, L->FunctionType, Name);
}
Expected<UdtSourceLineRecord>
-UdtSourceLineRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
+UdtSourceLineRecord::deserialize(TypeRecordKind Kind,
+ msf::StreamReader &Reader) {
const Layout *L = nullptr;
- CV_DESERIALIZE(Data, L);
+ CV_DESERIALIZE(Reader, L);
return UdtSourceLineRecord(L->UDT, L->SourceFile, L->LineNumber);
}
Expected<BuildInfoRecord>
-BuildInfoRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
+BuildInfoRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
const Layout *L = nullptr;
ArrayRef<TypeIndex> Indices;
- CV_DESERIALIZE(Data, L, CV_ARRAY_FIELD_N(Indices, L->NumArgs));
+ CV_DESERIALIZE(Reader, L, CV_ARRAY_FIELD_N(Indices, L->NumArgs));
return BuildInfoRecord(Indices);
}
Expected<VFTableRecord> VFTableRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Layout *L = nullptr;
StringRef Name;
std::vector<StringRef> Names;
- CV_DESERIALIZE(Data, L, Name, CV_ARRAY_FIELD_TAIL(Names));
+ CV_DESERIALIZE(Reader, L, Name, CV_ARRAY_FIELD_TAIL(Names));
return VFTableRecord(L->CompleteClass, L->OverriddenVFTable, L->VFPtrOffset,
Name, Names);
}
Expected<OneMethodRecord>
-OneMethodRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
+OneMethodRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
const Layout *L = nullptr;
StringRef Name;
int32_t VFTableOffset = -1;
- CV_DESERIALIZE(Data, L, CV_CONDITIONAL_FIELD(VFTableOffset,
- L->Attrs.isIntroducedVirtual()),
+ CV_DESERIALIZE(Reader, L, CV_CONDITIONAL_FIELD(
+ VFTableOffset, L->Attrs.isIntroducedVirtual()),
Name);
MethodOptions Options = L->Attrs.getFlags();
@@ -294,13 +298,14 @@ OneMethodRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
Expected<MethodOverloadListRecord>
MethodOverloadListRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
std::vector<OneMethodRecord> Methods;
- while (!Data.empty()) {
+ while (!Reader.empty()) {
const Layout *L = nullptr;
int32_t VFTableOffset = -1;
- CV_DESERIALIZE(Data, L, CV_CONDITIONAL_FIELD(
- VFTableOffset, L->Attrs.isIntroducedVirtual()));
+ CV_DESERIALIZE(
+ Reader, L,
+ CV_CONDITIONAL_FIELD(VFTableOffset, L->Attrs.isIntroducedVirtual()));
MethodOptions Options = L->Attrs.getFlags();
MethodKind MethKind = L->Attrs.getMethodKind();
@@ -320,72 +325,72 @@ MethodOverloadListRecord::deserialize(TypeRecordKind Kind,
Expected<OverloadedMethodRecord>
OverloadedMethodRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Layout *L = nullptr;
StringRef Name;
- CV_DESERIALIZE(Data, L, Name);
+ CV_DESERIALIZE(Reader, L, Name);
return OverloadedMethodRecord(L->MethodCount, L->MethList, Name);
}
Expected<DataMemberRecord>
-DataMemberRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
+DataMemberRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
const Layout *L = nullptr;
uint64_t Offset;
StringRef Name;
- CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Offset), Name);
+ CV_DESERIALIZE(Reader, L, CV_NUMERIC_FIELD(Offset), Name);
return DataMemberRecord(L->Attrs.getAccess(), L->Type, Offset, Name);
}
Expected<StaticDataMemberRecord>
StaticDataMemberRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Layout *L = nullptr;
StringRef Name;
- CV_DESERIALIZE(Data, L, Name);
+ CV_DESERIALIZE(Reader, L, Name);
return StaticDataMemberRecord(L->Attrs.getAccess(), L->Type, Name);
}
Expected<EnumeratorRecord>
-EnumeratorRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
+EnumeratorRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
const Layout *L = nullptr;
APSInt Value;
StringRef Name;
- CV_DESERIALIZE(Data, L, Value, Name);
+ CV_DESERIALIZE(Reader, L, Value, Name);
return EnumeratorRecord(L->Attrs.getAccess(), Value, Name);
}
Expected<VFPtrRecord> VFPtrRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Layout *L = nullptr;
- if (auto EC = consumeObject(Data, L))
+ if (auto EC = Reader.readObject(L))
return std::move(EC);
return VFPtrRecord(L->Type);
}
Expected<BaseClassRecord>
-BaseClassRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
+BaseClassRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
const Layout *L = nullptr;
uint64_t Offset;
- CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Offset));
+ CV_DESERIALIZE(Reader, L, CV_NUMERIC_FIELD(Offset));
return BaseClassRecord(L->Attrs.getAccess(), L->BaseType, Offset);
}
Expected<VirtualBaseClassRecord>
VirtualBaseClassRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Layout *L = nullptr;
uint64_t Offset;
uint64_t Index;
- CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Offset), CV_NUMERIC_FIELD(Index));
+ CV_DESERIALIZE(Reader, L, CV_NUMERIC_FIELD(Offset), CV_NUMERIC_FIELD(Index));
return VirtualBaseClassRecord(L->Attrs.getAccess(), L->BaseType, L->VBPtrType,
Offset, Index);
}
Expected<ListContinuationRecord>
ListContinuationRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Layout *L = nullptr;
- CV_DESERIALIZE(Data, L);
+ CV_DESERIALIZE(Reader, L);
return ListContinuationRecord(L->ContinuationIndex);
}
diff --git a/llvm/lib/DebugInfo/MSF/StreamReader.cpp b/llvm/lib/DebugInfo/MSF/StreamReader.cpp
index eb3d3e82d4d..b85fd14a3b7 100644
--- a/llvm/lib/DebugInfo/MSF/StreamReader.cpp
+++ b/llvm/lib/DebugInfo/MSF/StreamReader.cpp
@@ -31,6 +31,14 @@ Error StreamReader::readBytes(ArrayRef<uint8_t> &Buffer, uint32_t Size) {
return Error::success();
}
+Error StreamReader::readInteger(uint8_t &Dest) {
+ const uint8_t *P;
+ if (auto EC = readObject(P))
+ return EC;
+ Dest = *P;
+ return Error::success();
+}
+
Error StreamReader::readInteger(uint16_t &Dest) {
const support::ulittle16_t *P;
if (auto EC = readObject(P))
@@ -47,6 +55,46 @@ Error StreamReader::readInteger(uint32_t &Dest) {
return Error::success();
}
+Error StreamReader::readInteger(uint64_t &Dest) {
+ const support::ulittle64_t *P;
+ if (auto EC = readObject(P))
+ return EC;
+ Dest = *P;
+ return Error::success();
+}
+
+Error StreamReader::readInteger(int8_t &Dest) {
+ const int8_t *P;
+ if (auto EC = readObject(P))
+ return EC;
+ Dest = *P;
+ return Error::success();
+}
+
+Error StreamReader::readInteger(int16_t &Dest) {
+ const support::little16_t *P;
+ if (auto EC = readObject(P))
+ return EC;
+ Dest = *P;
+ return Error::success();
+}
+
+Error StreamReader::readInteger(int32_t &Dest) {
+ const support::little32_t *P;
+ if (auto EC = readObject(P))
+ return EC;
+ Dest = *P;
+ return Error::success();
+}
+
+Error StreamReader::readInteger(int64_t &Dest) {
+ const support::little64_t *P;
+ if (auto EC = readObject(P))
+ return EC;
+ Dest = *P;
+ return Error::success();
+}
+
Error StreamReader::readZeroString(StringRef &Dest) {
uint32_t Length = 0;
// First compute the length of the string by reading 1 byte at a time.
@@ -91,3 +139,18 @@ Error StreamReader::readStreamRef(ReadableStreamRef &Ref, uint32_t Length) {
Offset += Length;
return Error::success();
}
+
+Error StreamReader::skip(uint32_t Amount) {
+ if (Amount > bytesRemaining())
+ return make_error<MSFError>(msf_error_code::insufficient_buffer);
+ Offset += Amount;
+ return Error::success();
+}
+
+uint8_t StreamReader::peek() const {
+ ArrayRef<uint8_t> Buffer;
+ auto EC = Stream.readBytes(Offset, 1, Buffer);
+ assert(!EC && "Cannot peek an empty buffer!");
+ llvm::consumeError(std::move(EC));
+ return Buffer[0];
+}
OpenPOWER on IntegriCloud