summaryrefslogtreecommitdiffstats
path: root/llvm/lib/DebugInfo
diff options
context:
space:
mode:
authorZachary Turner <zturner@google.com>2016-11-02 17:05:19 +0000
committerZachary Turner <zturner@google.com>2016-11-02 17:05:19 +0000
commit7251ede7c5ee82d25e309b6a30952a6b5e7c1f89 (patch)
tree3b4fb352c4fb41db708e3778d3e1aef75a47eed0 /llvm/lib/DebugInfo
parent368972c3b3b8ad62fa064b495223809074c39115 (diff)
downloadbcm5719-llvm-7251ede7c5ee82d25e309b6a30952a6b5e7c1f89.tar.gz
bcm5719-llvm-7251ede7c5ee82d25e309b6a30952a6b5e7c1f89.zip
Add CodeViewRecordIO for reading and writing.
Using a pattern similar to that of YamlIO, this allows us to have a single codepath for translating codeview records to and from serialized byte streams. The current patch only hooks this up to the reading of CodeView type records. A subsequent patch will hook it up for writing of CodeView type records, and then a third patch will hook up the reading and writing of CodeView symbols. Differential Revision: https://reviews.llvm.org/D26040 llvm-svn: 285836
Diffstat (limited to 'llvm/lib/DebugInfo')
-rw-r--r--llvm/lib/DebugInfo/CodeView/CMakeLists.txt2
-rw-r--r--llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp66
-rw-r--r--llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp186
-rw-r--r--llvm/lib/DebugInfo/CodeView/TypeDumper.cpp7
-rw-r--r--llvm/lib/DebugInfo/CodeView/TypeRecord.cpp378
-rw-r--r--llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp417
-rw-r--r--llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp9
-rw-r--r--llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp8
-rw-r--r--llvm/lib/DebugInfo/MSF/StreamWriter.cpp20
9 files changed, 657 insertions, 436 deletions
diff --git a/llvm/lib/DebugInfo/CodeView/CMakeLists.txt b/llvm/lib/DebugInfo/CodeView/CMakeLists.txt
index a0700804301..4bbc48d111f 100644
--- a/llvm/lib/DebugInfo/CodeView/CMakeLists.txt
+++ b/llvm/lib/DebugInfo/CodeView/CMakeLists.txt
@@ -1,5 +1,6 @@
add_llvm_library(LLVMDebugInfoCodeView
CodeViewError.cpp
+ CodeViewRecordIO.cpp
CVSymbolVisitor.cpp
CVTypeVisitor.cpp
EnumTables.cpp
@@ -15,6 +16,7 @@ add_llvm_library(LLVMDebugInfoCodeView
TypeDumper.cpp
TypeRecord.cpp
TypeRecordBuilder.cpp
+ TypeRecordMapping.cpp
TypeStreamMerger.cpp
TypeTableBuilder.cpp
diff --git a/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp b/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
index 2dee8988df9..5f5d5fe35ef 100644
--- a/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
+++ b/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
@@ -10,44 +10,29 @@
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/CodeViewError.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
#include "llvm/DebugInfo/MSF/ByteStream.h"
using namespace llvm;
using namespace llvm::codeview;
-static Error skipPadding(msf::StreamReader &Reader) {
- if (Reader.empty())
- return Error::success();
-
- 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;
- return Reader.skip(BytesToAdvance);
-}
-
template <typename T>
static Expected<CVMemberRecord>
-deserializeMemberRecord(msf::StreamReader &Reader, TypeLeafKind Kind) {
- msf::StreamReader OldReader = Reader;
- TypeRecordKind RK = static_cast<TypeRecordKind>(Kind);
- auto ExpectedRecord = T::deserialize(RK, Reader);
- if (!ExpectedRecord)
- return ExpectedRecord.takeError();
- assert(Reader.bytesRemaining() < OldReader.bytesRemaining());
- if (auto EC = skipPadding(Reader))
- return std::move(EC);
+deserializeMemberRecord(FieldListDeserializer &Deserializer,
+ msf::StreamReader &Reader, TypeLeafKind Kind) {
+ T MR(static_cast<TypeRecordKind>(Kind));
+ CVMemberRecord CVR;
+ CVR.Kind = Kind;
- CVMemberRecord CVMR;
- CVMR.Kind = Kind;
-
- uint32_t RecordLength = OldReader.bytesRemaining() - Reader.bytesRemaining();
- if (auto EC = OldReader.readBytes(CVMR.Data, RecordLength))
+ if (auto EC = Deserializer.visitMemberBegin(CVR))
+ return std::move(EC);
+ if (auto EC = Deserializer.visitKnownMember(CVR, MR))
+ return std::move(EC);
+ if (auto EC = Deserializer.visitMemberEnd(CVR))
return std::move(EC);
- return CVMR;
+ return CVR;
}
CVTypeVisitor::CVTypeVisitor(TypeVisitorCallbacks &Callbacks)
@@ -138,22 +123,28 @@ Error CVTypeVisitor::visitTypeStream(const CVTypeArray &Types) {
}
template <typename MR>
-static Error visitKnownMember(msf::StreamReader &Reader, TypeLeafKind Leaf,
+static Error visitKnownMember(FieldListDeserializer &Deserializer,
+ msf::StreamReader &Reader, TypeLeafKind Leaf,
TypeVisitorCallbacks &Callbacks) {
- auto ExpectedRecord = deserializeMemberRecord<MR>(Reader, Leaf);
- if (!ExpectedRecord)
- return ExpectedRecord.takeError();
- CVMemberRecord &Record = *ExpectedRecord;
- if (auto EC = Callbacks.visitMemberBegin(Record))
+ MR Record(static_cast<TypeRecordKind>(Leaf));
+ CVMemberRecord CVR;
+ CVR.Kind = Leaf;
+
+ if (auto EC = Callbacks.visitMemberBegin(CVR))
return EC;
- if (auto EC = visitKnownMember<MR>(Record, Callbacks))
+ if (auto EC = Callbacks.visitKnownMember(CVR, Record))
return EC;
- if (auto EC = Callbacks.visitMemberEnd(Record))
+ if (auto EC = Callbacks.visitMemberEnd(CVR))
return EC;
return Error::success();
}
Error CVTypeVisitor::visitFieldListMemberStream(msf::StreamReader Reader) {
+ FieldListDeserializer Deserializer(Reader);
+ TypeVisitorCallbackPipeline Pipeline;
+ Pipeline.addCallbackToPipeline(Deserializer);
+ Pipeline.addCallbackToPipeline(Callbacks);
+
TypeLeafKind Leaf;
while (!Reader.empty()) {
if (auto EC = Reader.readEnum(Leaf))
@@ -168,7 +159,8 @@ Error CVTypeVisitor::visitFieldListMemberStream(msf::StreamReader Reader) {
cv_error_code::unknown_member_record);
#define MEMBER_RECORD(EnumName, EnumVal, Name) \
case EnumName: { \
- if (auto EC = visitKnownMember<Name##Record>(Reader, Leaf, Callbacks)) \
+ if (auto EC = visitKnownMember<Name##Record>(Deserializer, Reader, Leaf, \
+ Pipeline)) \
return EC; \
break; \
}
diff --git a/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp b/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp
new file mode 100644
index 00000000000..7841e4f2f6a
--- /dev/null
+++ b/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp
@@ -0,0 +1,186 @@
+//===- CodeViewRecordIO.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/CodeViewRecordIO.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
+#include "llvm/DebugInfo/MSF/StreamReader.h"
+#include "llvm/DebugInfo/MSF/StreamWriter.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+Error CodeViewRecordIO::beginRecord(uint16_t Kind) {
+ assert(!CurrentRecord.hasValue() && "There is already a record active!");
+ CurrentRecord.emplace();
+
+ CurrentRecord->Kind = Kind;
+ return Error::success();
+}
+
+Error CodeViewRecordIO::endRecord() {
+ assert(CurrentRecord.hasValue() && "Not in a record!");
+ CurrentRecord.reset();
+ return Error::success();
+}
+
+Error CodeViewRecordIO::skipPadding() {
+ assert(!isWriting() && "Cannot skip padding while writing!");
+
+ if (Reader->bytesRemaining() == 0)
+ return Error::success();
+
+ 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;
+ return Reader->skip(BytesToAdvance);
+}
+
+Error CodeViewRecordIO::mapByteVectorTail(ArrayRef<uint8_t> &Bytes) {
+ if (isWriting()) {
+ if (auto EC = Writer->writeBytes(Bytes))
+ return EC;
+ } else {
+ if (auto EC = Reader->readBytes(Bytes, Reader->bytesRemaining()))
+ return EC;
+ }
+ return Error::success();
+}
+
+Error CodeViewRecordIO::mapInteger(TypeIndex &TypeInd) {
+ if (isWriting()) {
+ if (auto EC = Writer->writeInteger(TypeInd.getIndex()))
+ return EC;
+ return Error::success();
+ }
+
+ uint32_t I;
+ if (auto EC = Reader->readInteger(I))
+ return EC;
+ TypeInd.setIndex(I);
+ return Error::success();
+}
+
+Error CodeViewRecordIO::mapEncodedInteger(int64_t &Value) {
+ if (isWriting()) {
+ if (Value >= 0) {
+ if (auto EC = writeEncodedUnsignedInteger(static_cast<uint64_t>(Value)))
+ return EC;
+ } else {
+ if (auto EC = writeEncodedSignedInteger(Value))
+ return EC;
+ }
+ } else {
+ APSInt N;
+ if (auto EC = consume(*Reader, N))
+ return EC;
+ Value = N.getExtValue();
+ }
+
+ return Error::success();
+}
+
+Error CodeViewRecordIO::mapEncodedInteger(uint64_t &Value) {
+ if (isWriting()) {
+ if (auto EC = writeEncodedUnsignedInteger(Value))
+ return EC;
+ } else {
+ APSInt N;
+ if (auto EC = consume(*Reader, N))
+ return EC;
+ Value = N.getZExtValue();
+ }
+ return Error::success();
+}
+
+Error CodeViewRecordIO::mapEncodedInteger(APSInt &Value) {
+ if (isWriting()) {
+ if (Value.isSigned())
+ return writeEncodedSignedInteger(Value.getSExtValue());
+ return writeEncodedUnsignedInteger(Value.getZExtValue());
+ }
+
+ return consume(*Reader, Value);
+}
+
+Error CodeViewRecordIO::mapStringZ(StringRef &Value) {
+ if (isWriting()) {
+ if (auto EC = Writer->writeZeroString(Value))
+ return EC;
+ } else {
+ if (auto EC = Reader->readZeroString(Value))
+ return EC;
+ }
+ return Error::success();
+}
+
+Error CodeViewRecordIO::mapGuid(StringRef &Guid) {
+ if (isWriting()) {
+ assert(Guid.size() == 16 && "Invalid Guid Size!");
+ if (auto EC = Writer->writeFixedString(Guid))
+ return EC;
+ } else {
+ if (auto EC = Reader->readFixedString(Guid, 16))
+ return EC;
+ }
+ return Error::success();
+}
+
+Error CodeViewRecordIO::writeEncodedSignedInteger(const int64_t &Value) {
+ assert(Value < 0 && "Encoded integer is not signed!");
+ if (Value >= std::numeric_limits<int8_t>::min()) {
+ if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_CHAR)))
+ return EC;
+ if (auto EC = Writer->writeInteger(static_cast<int8_t>(Value)))
+ return EC;
+ } else if (Value >= std::numeric_limits<int16_t>::min()) {
+ if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_SHORT)))
+ return EC;
+ if (auto EC = Writer->writeInteger(static_cast<int16_t>(Value)))
+ return EC;
+ } else if (Value >= std::numeric_limits<int32_t>::min()) {
+ if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_LONG)))
+ return EC;
+ if (auto EC = Writer->writeInteger(static_cast<int32_t>(Value)))
+ return EC;
+ } else {
+ if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_QUADWORD)))
+ return EC;
+ if (auto EC = Writer->writeInteger(Value))
+ return EC;
+ }
+ return Error::success();
+}
+
+Error CodeViewRecordIO::writeEncodedUnsignedInteger(const uint64_t &Value) {
+ if (Value < LF_NUMERIC) {
+ if (auto EC = Writer->writeInteger(static_cast<uint16_t>(Value)))
+ return EC;
+ } else if (Value <= std::numeric_limits<uint16_t>::max()) {
+ if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_USHORT)))
+ return EC;
+ if (auto EC = Writer->writeInteger(static_cast<uint16_t>(Value)))
+ return EC;
+ } else if (Value <= std::numeric_limits<uint32_t>::max()) {
+ if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_ULONG)))
+ return EC;
+ if (auto EC = Writer->writeInteger(static_cast<uint32_t>(Value)))
+ return EC;
+ } else {
+ if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_UQUADWORD)))
+ return EC;
+ if (auto EC = Writer->writeInteger(Value))
+ return EC;
+ }
+
+ return Error::success();
+}
diff --git a/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp b/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp
index 1e7af16e841..84abad91c53 100644
--- a/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp
+++ b/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp
@@ -268,12 +268,7 @@ Error CVTypeDumper::visitMemberEnd(CVMemberRecord &Record) {
Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
FieldListRecord &FieldList) {
- TypeDeserializer Deserializer;
- TypeVisitorCallbackPipeline Pipeline;
- Pipeline.addCallbackToPipeline(Deserializer);
- Pipeline.addCallbackToPipeline(*this);
-
- CVTypeVisitor Visitor(Pipeline);
+ CVTypeVisitor Visitor(*this);
if (auto EC = Visitor.visitFieldListMemberStream(FieldList.Data))
return EC;
diff --git a/llvm/lib/DebugInfo/CodeView/TypeRecord.cpp b/llvm/lib/DebugInfo/CodeView/TypeRecord.cpp
index 7a2dc8fa803..b951c068ca8 100644
--- a/llvm/lib/DebugInfo/CodeView/TypeRecord.cpp
+++ b/llvm/lib/DebugInfo/CodeView/TypeRecord.cpp
@@ -17,384 +17,6 @@ using namespace llvm;
using namespace llvm::codeview;
//===----------------------------------------------------------------------===//
-// Type record deserialization
-//===----------------------------------------------------------------------===//
-
-Expected<MemberPointerInfo>
-MemberPointerInfo::deserialize(msf::StreamReader &Reader) {
- const Layout *L = nullptr;
- if (auto EC = Reader.readObject(L))
- return std::move(EC);
-
- TypeIndex T = L->ClassType;
- uint16_t R = L->Representation;
- PointerToMemberRepresentation PMR =
- static_cast<PointerToMemberRepresentation>(R);
- return MemberPointerInfo(T, PMR);
-}
-
-Expected<ModifierRecord>
-ModifierRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
- const Layout *L = nullptr;
- if (auto EC = Reader.readObject(L))
- return std::move(EC);
-
- TypeIndex M = L->ModifiedType;
- uint16_t O = L->Modifiers;
- ModifierOptions MO = static_cast<ModifierOptions>(O);
- return ModifierRecord(M, MO);
-}
-
-Expected<ProcedureRecord>
-ProcedureRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
- const Layout *L = nullptr;
- if (auto EC = Reader.readObject(L))
- return std::move(EC);
- return ProcedureRecord(L->ReturnType, L->CallConv, L->Options,
- L->NumParameters, L->ArgListType);
-}
-
-Expected<MemberFunctionRecord>
-MemberFunctionRecord::deserialize(TypeRecordKind Kind,
- msf::StreamReader &Reader) {
- const Layout *L = nullptr;
- 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,
- msf::StreamReader &Reader) {
- const Layout *L = nullptr;
- StringRef Name;
- CV_DESERIALIZE(Reader, L, Name);
- return MemberFuncIdRecord(L->ClassType, L->FunctionType, Name);
-}
-
-Expected<ArgListRecord> ArgListRecord::deserialize(TypeRecordKind Kind,
- msf::StreamReader &Reader) {
- if (Kind != TypeRecordKind::StringList && Kind != TypeRecordKind::ArgList)
- return make_error<CodeViewError>(
- cv_error_code::corrupt_record,
- "ArgListRecord contains unexpected TypeRecordKind");
-
- const Layout *L = nullptr;
- ArrayRef<TypeIndex> Indices;
- CV_DESERIALIZE(Reader, L, CV_ARRAY_FIELD_N(Indices, L->NumArgs));
- return ArgListRecord(Kind, Indices);
-}
-
-Expected<PointerRecord> PointerRecord::deserialize(TypeRecordKind Kind,
- msf::StreamReader &Reader) {
- const Layout *L = nullptr;
- if (auto EC = Reader.readObject(L))
- return std::move(EC);
-
- PointerKind PtrKind = L->getPtrKind();
- PointerMode Mode = L->getPtrMode();
- uint32_t Opts = L->Attrs;
- PointerOptions Options = static_cast<PointerOptions>(Opts);
- uint8_t Size = L->getPtrSize();
-
- if (L->isPointerToMember()) {
- if (auto ExpectedMPI = MemberPointerInfo::deserialize(Reader))
- return PointerRecord(L->PointeeType, PtrKind, Mode, Options, Size,
- *ExpectedMPI);
- else
- return ExpectedMPI.takeError();
- }
-
- return PointerRecord(L->PointeeType, PtrKind, Mode, Options, Size);
-}
-
-Expected<NestedTypeRecord>
-NestedTypeRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
- const Layout *L = nullptr;
- StringRef Name;
- CV_DESERIALIZE(Reader, L, Name);
- return NestedTypeRecord(L->Type, Name);
-}
-
-Expected<FieldListRecord>
-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,
- msf::StreamReader &Reader) {
- const Layout *L = nullptr;
- uint64_t Size;
- StringRef Name;
- CV_DESERIALIZE(Reader, L, CV_NUMERIC_FIELD(Size), Name);
- return ArrayRecord(L->ElementType, L->IndexType, Size, Name);
-}
-
-Expected<ClassRecord> ClassRecord::deserialize(TypeRecordKind Kind,
- msf::StreamReader &Reader) {
- uint64_t Size = 0;
- StringRef Name;
- StringRef UniqueName;
- uint16_t Props;
- const Layout *L = nullptr;
-
- CV_DESERIALIZE(Reader, L, CV_NUMERIC_FIELD(Size), Name,
- CV_CONDITIONAL_FIELD(UniqueName, L->hasUniqueName()));
-
- Props = L->Properties;
- uint16_t WrtValue = (Props & WinRTKindMask) >> WinRTKindShift;
- WindowsRTClassKind WRT = static_cast<WindowsRTClassKind>(WrtValue);
- uint16_t HfaMask = (Props & HfaKindMask) >> HfaKindShift;
- HfaKind Hfa = static_cast<HfaKind>(HfaMask);
-
- ClassOptions Options = static_cast<ClassOptions>(Props);
- return ClassRecord(Kind, L->MemberCount, Options, Hfa, WRT, L->FieldList,
- L->DerivedFrom, L->VShape, Size, Name, UniqueName);
-}
-
-Expected<UnionRecord> UnionRecord::deserialize(TypeRecordKind Kind,
- msf::StreamReader &Reader) {
- uint64_t Size = 0;
- StringRef Name;
- StringRef UniqueName;
- uint16_t Props;
-
- const Layout *L = nullptr;
- CV_DESERIALIZE(Reader, L, CV_NUMERIC_FIELD(Size), Name,
- CV_CONDITIONAL_FIELD(UniqueName, L->hasUniqueName()));
-
- Props = L->Properties;
-
- uint16_t HfaMask = (Props & HfaKindMask) >> HfaKindShift;
- HfaKind Hfa = static_cast<HfaKind>(HfaMask);
- ClassOptions Options = static_cast<ClassOptions>(Props);
- return UnionRecord(L->MemberCount, Options, Hfa, L->FieldList, Size, Name,
- UniqueName);
-}
-
-Expected<EnumRecord> EnumRecord::deserialize(TypeRecordKind Kind,
- msf::StreamReader &Reader) {
- const Layout *L = nullptr;
- StringRef Name;
- StringRef UniqueName;
- CV_DESERIALIZE(Reader, L, Name,
- CV_CONDITIONAL_FIELD(UniqueName, L->hasUniqueName()));
-
- uint16_t P = L->Properties;
- ClassOptions Options = static_cast<ClassOptions>(P);
- return EnumRecord(L->NumEnumerators, Options, L->FieldListType, Name,
- UniqueName, L->UnderlyingType);
-}
-
-Expected<BitFieldRecord>
-BitFieldRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
- const Layout *L = nullptr;
- CV_DESERIALIZE(Reader, L);
- return BitFieldRecord(L->Type, L->BitSize, L->BitOffset);
-}
-
-Expected<VFTableShapeRecord>
-VFTableShapeRecord::deserialize(TypeRecordKind Kind,
- msf::StreamReader &Reader) {
- const Layout *L = nullptr;
- if (auto EC = Reader.readObject(L))
- return std::move(EC);
-
- std::vector<VFTableSlotKind> Slots;
- uint16_t Count = L->VFEntryCount;
- while (Count > 0) {
- // Process up to 2 nibbles at a time (if there are at least 2 remaining)
- 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 & 0xF0) >> 4;
- Slots.push_back(static_cast<VFTableSlotKind>(Value));
- --Count;
- }
- }
-
- return VFTableShapeRecord(Slots);
-}
-
-Expected<TypeServer2Record>
-TypeServer2Record::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
- const Layout *L = nullptr;
- StringRef Name;
- CV_DESERIALIZE(Reader, L, Name);
- return TypeServer2Record(StringRef(L->Guid, 16), L->Age, Name);
-}
-
-Expected<StringIdRecord>
-StringIdRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
- const Layout *L = nullptr;
- StringRef Name;
- CV_DESERIALIZE(Reader, L, Name);
- return StringIdRecord(L->id, Name);
-}
-
-Expected<FuncIdRecord> FuncIdRecord::deserialize(TypeRecordKind Kind,
- msf::StreamReader &Reader) {
- const Layout *L = nullptr;
- StringRef Name;
- CV_DESERIALIZE(Reader, L, Name);
- return FuncIdRecord(L->ParentScope, L->FunctionType, Name);
-}
-
-Expected<UdtSourceLineRecord>
-UdtSourceLineRecord::deserialize(TypeRecordKind Kind,
- msf::StreamReader &Reader) {
- const Layout *L = nullptr;
- CV_DESERIALIZE(Reader, L);
- return UdtSourceLineRecord(L->UDT, L->SourceFile, L->LineNumber);
-}
-
-Expected<BuildInfoRecord>
-BuildInfoRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
- const Layout *L = nullptr;
- ArrayRef<TypeIndex> Indices;
- CV_DESERIALIZE(Reader, L, CV_ARRAY_FIELD_N(Indices, L->NumArgs));
- return BuildInfoRecord(Indices);
-}
-
-Expected<VFTableRecord> VFTableRecord::deserialize(TypeRecordKind Kind,
- msf::StreamReader &Reader) {
- const Layout *L = nullptr;
- StringRef Name;
- std::vector<StringRef> 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, msf::StreamReader &Reader) {
- const Layout *L = nullptr;
- StringRef Name;
- int32_t VFTableOffset = -1;
-
- CV_DESERIALIZE(Reader, L, CV_CONDITIONAL_FIELD(
- VFTableOffset, L->Attrs.isIntroducedVirtual()),
- Name);
-
- MethodOptions Options = L->Attrs.getFlags();
- MethodKind MethKind = L->Attrs.getMethodKind();
- MemberAccess Access = L->Attrs.getAccess();
- OneMethodRecord Method(L->Type, MethKind, Options, Access, VFTableOffset,
- Name);
- // Validate the vftable offset.
- if (Method.isIntroducingVirtual() && Method.getVFTableOffset() < 0)
- return make_error<CodeViewError>(cv_error_code::corrupt_record,
- "Invalid VFTableOffset");
- return Method;
-}
-
-Expected<MethodOverloadListRecord>
-MethodOverloadListRecord::deserialize(TypeRecordKind Kind,
- msf::StreamReader &Reader) {
- std::vector<OneMethodRecord> Methods;
- while (!Reader.empty()) {
- const Layout *L = nullptr;
- int32_t VFTableOffset = -1;
- CV_DESERIALIZE(
- Reader, L,
- CV_CONDITIONAL_FIELD(VFTableOffset, L->Attrs.isIntroducedVirtual()));
-
- MethodOptions Options = L->Attrs.getFlags();
- MethodKind MethKind = L->Attrs.getMethodKind();
- MemberAccess Access = L->Attrs.getAccess();
-
- Methods.emplace_back(L->Type, MethKind, Options, Access, VFTableOffset,
- StringRef());
-
- // Validate the vftable offset.
- auto &Method = Methods.back();
- if (Method.isIntroducingVirtual() && Method.getVFTableOffset() < 0)
- return make_error<CodeViewError>(cv_error_code::corrupt_record,
- "Invalid VFTableOffset");
- }
- return MethodOverloadListRecord(Methods);
-}
-
-Expected<OverloadedMethodRecord>
-OverloadedMethodRecord::deserialize(TypeRecordKind Kind,
- msf::StreamReader &Reader) {
- const Layout *L = nullptr;
- StringRef Name;
- CV_DESERIALIZE(Reader, L, Name);
- return OverloadedMethodRecord(L->MethodCount, L->MethList, Name);
-}
-
-Expected<DataMemberRecord>
-DataMemberRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
- const Layout *L = nullptr;
- uint64_t Offset;
- StringRef 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,
- msf::StreamReader &Reader) {
- const Layout *L = nullptr;
- StringRef Name;
- CV_DESERIALIZE(Reader, L, Name);
- return StaticDataMemberRecord(L->Attrs.getAccess(), L->Type, Name);
-}
-
-Expected<EnumeratorRecord>
-EnumeratorRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
- const Layout *L = nullptr;
- APSInt Value;
- StringRef Name;
- CV_DESERIALIZE(Reader, L, Value, Name);
- return EnumeratorRecord(L->Attrs.getAccess(), Value, Name);
-}
-
-Expected<VFPtrRecord> VFPtrRecord::deserialize(TypeRecordKind Kind,
- msf::StreamReader &Reader) {
- const Layout *L = nullptr;
- if (auto EC = Reader.readObject(L))
- return std::move(EC);
- return VFPtrRecord(L->Type);
-}
-
-Expected<BaseClassRecord>
-BaseClassRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
- const Layout *L = nullptr;
- uint64_t Offset;
- CV_DESERIALIZE(Reader, L, CV_NUMERIC_FIELD(Offset));
- return BaseClassRecord(L->Attrs.getAccess(), L->BaseType, Offset);
-}
-
-Expected<VirtualBaseClassRecord>
-VirtualBaseClassRecord::deserialize(TypeRecordKind Kind,
- msf::StreamReader &Reader) {
- const Layout *L = nullptr;
- uint64_t Offset;
- uint64_t Index;
- CV_DESERIALIZE(Reader, L, CV_NUMERIC_FIELD(Offset), CV_NUMERIC_FIELD(Index));
- return VirtualBaseClassRecord(Kind, L->Attrs.getAccess(), L->BaseType,
- L->VBPtrType, Offset, Index);
-}
-
-Expected<ListContinuationRecord>
-ListContinuationRecord::deserialize(TypeRecordKind Kind,
- msf::StreamReader &Reader) {
- const Layout *L = nullptr;
- CV_DESERIALIZE(Reader, L);
- return ListContinuationRecord(L->ContinuationIndex);
-}
-
-//===----------------------------------------------------------------------===//
// Type index remapping
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp b/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp
new file mode 100644
index 00000000000..d85a643c6d2
--- /dev/null
+++ b/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp
@@ -0,0 +1,417 @@
+//===- TypeRecordMapping.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/TypeRecordMapping.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+#define error(X) \
+ if (auto EC = X) \
+ return EC;
+
+namespace {
+struct MapStringZ {
+ Error operator()(CodeViewRecordIO &IO, StringRef &S) const {
+ return IO.mapStringZ(S);
+ }
+};
+
+struct MapInteger {
+ template <typename T> Error operator()(CodeViewRecordIO &IO, T &N) const {
+ return IO.mapInteger(N);
+ }
+};
+
+struct MapEnum {
+ template <typename T> Error operator()(CodeViewRecordIO &IO, T &N) const {
+ return IO.mapEnum(N);
+ }
+};
+
+struct MapOneMethodRecord {
+ explicit MapOneMethodRecord(bool IsFromOverloadList)
+ : IsFromOverloadList(IsFromOverloadList) {}
+
+ Error operator()(CodeViewRecordIO &IO, OneMethodRecord &Method) const {
+ error(IO.mapInteger(Method.Attrs.Attrs));
+ if (IsFromOverloadList) {
+ uint16_t Padding = 0;
+ error(IO.mapInteger(Padding));
+ }
+ error(IO.mapInteger(Method.Type));
+ if (Method.isIntroducingVirtual()) {
+ error(IO.mapInteger(Method.VFTableOffset));
+ } else if (!IO.isWriting())
+ Method.VFTableOffset = -1;
+
+ if (!IsFromOverloadList)
+ error(IO.mapStringZ(Method.Name));
+
+ return Error::success();
+ }
+
+private:
+ bool IsFromOverloadList;
+};
+}
+
+static Error mapNameAndUniqueName(CodeViewRecordIO &IO, StringRef &Name,
+ StringRef &UniqueName, bool HasUniqueName) {
+ error(IO.mapStringZ(Name));
+ if (HasUniqueName)
+ error(IO.mapStringZ(UniqueName));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitTypeBegin(CVType &CVR) {
+ error(IO.beginRecord(CVR.Type));
+ TypeKind = CVR.Type;
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitTypeEnd(CVType &Record) {
+ error(IO.endRecord());
+ TypeKind.reset();
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitMemberBegin(CVMemberRecord &Record) {
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitMemberEnd(CVMemberRecord &Record) {
+ if (!IO.isWriting()) {
+ if (auto EC = IO.skipPadding())
+ return EC;
+ }
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ModifierRecord &Record) {
+ error(IO.mapInteger(Record.ModifiedType));
+ error(IO.mapEnum(Record.Modifiers));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
+ ProcedureRecord &Record) {
+ error(IO.mapInteger(Record.ReturnType));
+ error(IO.mapEnum(Record.CallConv));
+ error(IO.mapEnum(Record.Options));
+ error(IO.mapInteger(Record.ParameterCount));
+ error(IO.mapInteger(Record.ArgumentList));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
+ MemberFunctionRecord &Record) {
+ error(IO.mapInteger(Record.ReturnType));
+ error(IO.mapInteger(Record.ClassType));
+ error(IO.mapInteger(Record.ThisType));
+ error(IO.mapEnum(Record.CallConv));
+ error(IO.mapEnum(Record.Options));
+ error(IO.mapInteger(Record.ParameterCount));
+ error(IO.mapInteger(Record.ArgumentList));
+ error(IO.mapInteger(Record.ThisPointerAdjustment));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ArgListRecord &Record) {
+ error(IO.mapVectorN<uint32_t>(Record.StringIndices, MapInteger()));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR, PointerRecord &Record) {
+ error(IO.mapInteger(Record.ReferentType));
+ error(IO.mapInteger(Record.Attrs));
+
+ if (Record.isPointerToMember()) {
+ if (!IO.isWriting())
+ Record.MemberInfo.emplace();
+
+ MemberPointerInfo &M = *Record.MemberInfo;
+ error(IO.mapInteger(M.ContainingType));
+ error(IO.mapEnum(M.Representation));
+ }
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ArrayRecord &Record) {
+ error(IO.mapInteger(Record.ElementType));
+ error(IO.mapInteger(Record.IndexType));
+ error(IO.mapEncodedInteger(Record.Size));
+ error(IO.mapStringZ(Record.Name));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ClassRecord &Record) {
+ assert((CVR.Type == TypeLeafKind::LF_STRUCTURE) ||
+ (CVR.Type == TypeLeafKind::LF_CLASS) ||
+ (CVR.Type == TypeLeafKind::LF_INTERFACE));
+
+ error(IO.mapInteger(Record.MemberCount));
+ error(IO.mapEnum(Record.Options));
+ error(IO.mapInteger(Record.FieldList));
+ error(IO.mapInteger(Record.DerivationList));
+ error(IO.mapInteger(Record.VTableShape));
+ error(IO.mapEncodedInteger(Record.Size));
+ error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName,
+ Record.hasUniqueName()));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR, UnionRecord &Record) {
+ error(IO.mapInteger(Record.MemberCount));
+ error(IO.mapEnum(Record.Options));
+ error(IO.mapInteger(Record.FieldList));
+ error(IO.mapEncodedInteger(Record.Size));
+ error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName,
+ Record.hasUniqueName()));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR, EnumRecord &Record) {
+ error(IO.mapInteger(Record.MemberCount));
+ error(IO.mapEnum(Record.Options));
+ error(IO.mapInteger(Record.UnderlyingType));
+ error(IO.mapInteger(Record.FieldList));
+ error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName,
+ Record.hasUniqueName()));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR, BitFieldRecord &Record) {
+ error(IO.mapInteger(Record.Type));
+ error(IO.mapInteger(Record.BitSize));
+ error(IO.mapInteger(Record.BitOffset));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
+ VFTableShapeRecord &Record) {
+ uint16_t Size;
+ if (IO.isWriting()) {
+ ArrayRef<VFTableSlotKind> Slots = Record.getSlots();
+ Size = Slots.size();
+ error(IO.mapInteger(Size));
+
+ for (size_t SlotIndex = 0; SlotIndex < Slots.size(); SlotIndex += 2) {
+ uint8_t Byte = static_cast<uint8_t>(Slots[SlotIndex]) << 4;
+ if ((SlotIndex + 1) < Slots.size()) {
+ Byte |= static_cast<uint8_t>(Slots[SlotIndex + 1]);
+ }
+ error(IO.mapInteger(Byte));
+ }
+ } else {
+ error(IO.mapInteger(Size));
+ for (uint16_t I = 0; I < Size; I += 2) {
+ uint8_t Byte;
+ error(IO.mapInteger(Byte));
+ Record.Slots.push_back(static_cast<VFTableSlotKind>(Byte & 0xF));
+ if ((I + 1) < Size)
+ Record.Slots.push_back(static_cast<VFTableSlotKind>(Byte >> 4));
+ }
+ }
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR, VFTableRecord &Record) {
+ error(IO.mapInteger(Record.CompleteClass));
+ error(IO.mapInteger(Record.OverriddenVFTable));
+ error(IO.mapInteger(Record.VFPtrOffset));
+ uint32_t NamesLen = 0;
+ if (IO.isWriting()) {
+ for (auto Name : Record.MethodNames)
+ NamesLen += Name.size() + 1;
+ }
+ error(IO.mapInteger(NamesLen));
+ error(IO.mapVectorTail(Record.MethodNames, MapStringZ()));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR, StringIdRecord &Record) {
+ error(IO.mapInteger(Record.Id));
+ error(IO.mapStringZ(Record.String));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
+ UdtSourceLineRecord &Record) {
+ error(IO.mapInteger(Record.UDT));
+ error(IO.mapInteger(Record.SourceFile));
+ error(IO.mapInteger(Record.LineNumber));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
+ UdtModSourceLineRecord &Record) {
+ error(IO.mapInteger(Record.UDT));
+ error(IO.mapInteger(Record.SourceFile));
+ error(IO.mapInteger(Record.LineNumber));
+ error(IO.mapInteger(Record.Module));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR, FuncIdRecord &Record) {
+ error(IO.mapInteger(Record.ParentScope));
+ error(IO.mapInteger(Record.FunctionType));
+ error(IO.mapStringZ(Record.Name));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
+ MemberFuncIdRecord &Record) {
+ error(IO.mapInteger(Record.ClassType));
+ error(IO.mapInteger(Record.FunctionType));
+ error(IO.mapStringZ(Record.Name));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
+ BuildInfoRecord &Record) {
+ error(IO.mapVectorN<uint16_t>(Record.ArgIndices, MapInteger()));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
+ MethodOverloadListRecord &Record) {
+ // TODO: Split the list into multiple records if it's longer than 64KB, using
+ // a subrecord of TypeRecordKind::Index to chain the records together.
+ error(IO.mapVectorTail(Record.Methods, MapOneMethodRecord(true)));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
+ FieldListRecord &Record) {
+ error(IO.mapByteVectorTail(Record.Data));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
+ TypeServer2Record &Record) {
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
+ BaseClassRecord &Record) {
+ error(IO.mapInteger(Record.Attrs.Attrs));
+ error(IO.mapInteger(Record.Type));
+ error(IO.mapEncodedInteger(Record.Offset));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
+ EnumeratorRecord &Record) {
+ error(IO.mapInteger(Record.Attrs.Attrs));
+
+ // FIXME: Handle full APInt such as __int128.
+ error(IO.mapEncodedInteger(Record.Value));
+ error(IO.mapStringZ(Record.Name));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
+ DataMemberRecord &Record) {
+ error(IO.mapInteger(Record.Attrs.Attrs));
+ error(IO.mapInteger(Record.Type));
+ error(IO.mapEncodedInteger(Record.FieldOffset));
+ error(IO.mapStringZ(Record.Name));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
+ OverloadedMethodRecord &Record) {
+ error(IO.mapInteger(Record.NumOverloads));
+ error(IO.mapInteger(Record.MethodList));
+ error(IO.mapStringZ(Record.Name));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
+ OneMethodRecord &Record) {
+ MapOneMethodRecord Mapper(false);
+ return Mapper(IO, Record);
+}
+
+Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
+ NestedTypeRecord &Record) {
+ uint16_t Padding = 0;
+ error(IO.mapInteger(Padding));
+ error(IO.mapInteger(Record.Type));
+ error(IO.mapStringZ(Record.Name));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
+ StaticDataMemberRecord &Record) {
+
+ error(IO.mapInteger(Record.Attrs.Attrs));
+ error(IO.mapInteger(Record.Type));
+ error(IO.mapStringZ(Record.Name));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
+ VirtualBaseClassRecord &Record) {
+
+ error(IO.mapInteger(Record.Attrs.Attrs));
+ error(IO.mapInteger(Record.BaseType));
+ error(IO.mapInteger(Record.VBPtrType));
+ error(IO.mapEncodedInteger(Record.VBPtrOffset));
+ error(IO.mapEncodedInteger(Record.VTableIndex));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
+ VFPtrRecord &Record) {
+ uint16_t Padding = 0;
+ error(IO.mapInteger(Padding));
+ error(IO.mapInteger(Record.Type));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
+ ListContinuationRecord &Record) {
+ uint16_t Padding = 0;
+ error(IO.mapInteger(Padding));
+ error(IO.mapInteger(Record.ContinuationIndex));
+
+ return Error::success();
+}
diff --git a/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp b/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
index acd7f74a3cc..551a98a67c8 100644
--- a/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
+++ b/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
@@ -84,14 +84,7 @@ private:
}
Error visitKnownRecordImpl(FieldListRecord &Record) {
- // Don't do anything, this will get written in the call to visitTypeEnd().
- TypeVisitorCallbackPipeline Pipeline;
- TypeDeserializer Deserializer;
-
- Pipeline.addCallbackToPipeline(Deserializer);
- Pipeline.addCallbackToPipeline(*this);
-
- CVTypeVisitor Visitor(Pipeline);
+ CVTypeVisitor Visitor(*this);
if (auto EC = Visitor.visitFieldListMemberStream(Record.Data))
return EC;
diff --git a/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp b/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp
index fcf27962102..1bd0b3f4382 100644
--- a/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp
+++ b/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp
@@ -72,13 +72,7 @@ TypeIndex TypeTableBuilder::writeKnownType(const PointerRecord &Record) {
TypeRecordBuilder Builder(Record.getKind());
Builder.writeTypeIndex(Record.getReferentType());
- uint32_t flags = static_cast<uint32_t>(Record.getOptions()) |
- (Record.getSize() << PointerRecord::PointerSizeShift) |
- (static_cast<uint32_t>(Record.getMode())
- << PointerRecord::PointerModeShift) |
- (static_cast<uint32_t>(Record.getPointerKind())
- << PointerRecord::PointerKindShift);
- Builder.writeUInt32(flags);
+ Builder.writeUInt32(Record.Attrs);
if (Record.isPointerToMember()) {
const MemberPointerInfo &M = Record.getMemberInfo();
diff --git a/llvm/lib/DebugInfo/MSF/StreamWriter.cpp b/llvm/lib/DebugInfo/MSF/StreamWriter.cpp
index a91cffe840f..cdae7c5acc0 100644
--- a/llvm/lib/DebugInfo/MSF/StreamWriter.cpp
+++ b/llvm/lib/DebugInfo/MSF/StreamWriter.cpp
@@ -25,6 +25,8 @@ Error StreamWriter::writeBytes(ArrayRef<uint8_t> Buffer) {
return Error::success();
}
+Error StreamWriter::writeInteger(uint8_t Int) { return writeObject(Int); }
+
Error StreamWriter::writeInteger(uint16_t Int) {
return writeObject(support::ulittle16_t(Int));
}
@@ -33,6 +35,24 @@ Error StreamWriter::writeInteger(uint32_t Int) {
return writeObject(support::ulittle32_t(Int));
}
+Error StreamWriter::writeInteger(uint64_t Int) {
+ return writeObject(support::ulittle64_t(Int));
+}
+
+Error StreamWriter::writeInteger(int8_t Int) { return writeObject(Int); }
+
+Error StreamWriter::writeInteger(int16_t Int) {
+ return writeObject(support::little16_t(Int));
+}
+
+Error StreamWriter::writeInteger(int32_t Int) {
+ return writeObject(support::little32_t(Int));
+}
+
+Error StreamWriter::writeInteger(int64_t Int) {
+ return writeObject(support::little64_t(Int));
+}
+
Error StreamWriter::writeZeroString(StringRef Str) {
if (auto EC = writeFixedString(Str))
return EC;
OpenPOWER on IntegriCloud