summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/lib/DebugInfo/CodeView
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/DebugInfo/CodeView')
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/ByteStream.cpp79
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/CVSymbolVisitor.cpp73
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/CVTypeDumper.cpp73
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp147
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/CodeViewError.cpp4
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp242
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/EnumTables.cpp10
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp132
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/ListRecordBuilder.cpp102
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/MemoryTypeTableBuilder.cpp46
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/MethodListRecordBuilder.cpp49
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/ModuleSubstream.cpp11
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/ModuleSubstreamVisitor.cpp30
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/RecordSerialization.cpp192
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/StreamReader.cpp93
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/StreamWriter.cpp77
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp539
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp464
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/TypeDatabase.cpp114
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/TypeDatabaseVisitor.cpp289
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp (renamed from contrib/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp)370
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/TypeRecord.cpp367
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/TypeRecordBuilder.cpp113
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp467
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/TypeSerializer.cpp243
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp94
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp303
27 files changed, 2633 insertions, 2090 deletions
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/ByteStream.cpp b/contrib/llvm/lib/DebugInfo/CodeView/ByteStream.cpp
deleted file mode 100644
index 2c43bc6..0000000
--- a/contrib/llvm/lib/DebugInfo/CodeView/ByteStream.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-//===- ByteStream.cpp - Reads stream data from a byte sequence ------------===//
-//
-// 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/ByteStream.h"
-#include "llvm/DebugInfo/CodeView/CodeViewError.h"
-#include "llvm/DebugInfo/CodeView/StreamReader.h"
-#include <cstring>
-
-using namespace llvm;
-using namespace llvm::codeview;
-
-static Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Src,
- ArrayRef<uint8_t> Dest) {
- return make_error<CodeViewError>(cv_error_code::operation_unsupported,
- "ByteStream is immutable.");
-}
-
-static Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Src,
- MutableArrayRef<uint8_t> Dest) {
- if (Dest.size() < Src.size())
- return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
- if (Offset > Src.size() - Dest.size())
- return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
-
- ::memcpy(Dest.data() + Offset, Src.data(), Src.size());
- return Error::success();
-}
-
-template <bool Writable>
-Error ByteStream<Writable>::readBytes(uint32_t Offset, uint32_t Size,
- ArrayRef<uint8_t> &Buffer) const {
- if (Offset > Data.size())
- return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
- if (Data.size() < Size + Offset)
- return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
- Buffer = Data.slice(Offset, Size);
- return Error::success();
-}
-
-template <bool Writable>
-Error ByteStream<Writable>::readLongestContiguousChunk(
- uint32_t Offset, ArrayRef<uint8_t> &Buffer) const {
- if (Offset >= Data.size())
- return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
- Buffer = Data.slice(Offset);
- return Error::success();
-}
-
-template <bool Writable>
-Error ByteStream<Writable>::writeBytes(uint32_t Offset,
- ArrayRef<uint8_t> Buffer) const {
- return ::writeBytes(Offset, Buffer, Data);
-}
-
-template <bool Writable> uint32_t ByteStream<Writable>::getLength() const {
- return Data.size();
-}
-
-template <bool Writable> Error ByteStream<Writable>::commit() const {
- return Error::success();
-}
-
-template <bool Writable> StringRef ByteStream<Writable>::str() const {
- const char *CharData = reinterpret_cast<const char *>(Data.data());
- return StringRef(CharData, Data.size());
-}
-
-namespace llvm {
-namespace codeview {
-template class ByteStream<true>;
-template class ByteStream<false>;
-}
-}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/CVSymbolVisitor.cpp b/contrib/llvm/lib/DebugInfo/CodeView/CVSymbolVisitor.cpp
new file mode 100644
index 0000000..75cfd0d
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/CodeView/CVSymbolVisitor.cpp
@@ -0,0 +1,73 @@
+//===- CVSymbolVisitor.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/CVSymbolVisitor.h"
+
+#include "llvm/DebugInfo/CodeView/CodeViewError.h"
+#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
+#include "llvm/DebugInfo/MSF/ByteStream.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();
+}
+
+CVSymbolVisitor::CVSymbolVisitor(SymbolVisitorCallbacks &Callbacks)
+ : Callbacks(Callbacks) {}
+
+template <typename T>
+static Error visitKnownRecord(CVSymbol &Record,
+ SymbolVisitorCallbacks &Callbacks) {
+ SymbolRecordKind RK = static_cast<SymbolRecordKind>(Record.Type);
+ T KnownRecord(RK);
+ if (auto EC = Callbacks.visitKnownRecord(Record, KnownRecord))
+ return EC;
+ return Error::success();
+}
+
+Error CVSymbolVisitor::visitSymbolRecord(CVSymbol &Record) {
+ if (auto EC = Callbacks.visitSymbolBegin(Record))
+ return EC;
+
+ switch (Record.Type) {
+ default:
+ if (auto EC = Callbacks.visitUnknownSymbol(Record))
+ return EC;
+ break;
+#define SYMBOL_RECORD(EnumName, EnumVal, Name) \
+ case EnumName: { \
+ if (auto EC = visitKnownRecord<Name>(Record, Callbacks)) \
+ return EC; \
+ break; \
+ }
+#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
+ SYMBOL_RECORD(EnumVal, EnumVal, AliasName)
+#include "llvm/DebugInfo/CodeView/CVSymbolTypes.def"
+ }
+
+ if (auto EC = Callbacks.visitSymbolEnd(Record))
+ return EC;
+
+ return Error::success();
+}
+
+Error CVSymbolVisitor::visitSymbolStream(const CVSymbolArray &Symbols) {
+ for (auto I : Symbols) {
+ if (auto EC = visitSymbolRecord(I))
+ return EC;
+ }
+ return Error::success();
+}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/CVTypeDumper.cpp b/contrib/llvm/lib/DebugInfo/CodeView/CVTypeDumper.cpp
new file mode 100644
index 0000000..fcd239c
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/CodeView/CVTypeDumper.cpp
@@ -0,0 +1,73 @@
+//===-- CVTypeDumper.cpp - CodeView type info dumper ------------*- 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/CVTypeDumper.h"
+#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
+#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
+#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
+#include "llvm/DebugInfo/MSF/ByteStream.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+Error CVTypeDumper::dump(const CVType &Record, TypeVisitorCallbacks &Dumper) {
+ TypeDatabaseVisitor DBV(TypeDB);
+ TypeDeserializer Deserializer;
+ TypeVisitorCallbackPipeline Pipeline;
+ Pipeline.addCallbackToPipeline(Deserializer);
+ Pipeline.addCallbackToPipeline(DBV);
+ Pipeline.addCallbackToPipeline(Dumper);
+
+ CVTypeVisitor Visitor(Pipeline);
+
+ CVType RecordCopy = Record;
+ if (auto EC = Visitor.visitTypeRecord(RecordCopy))
+ return EC;
+ return Error::success();
+}
+
+Error CVTypeDumper::dump(const CVTypeArray &Types,
+ TypeVisitorCallbacks &Dumper) {
+ TypeDatabaseVisitor DBV(TypeDB);
+ TypeDeserializer Deserializer;
+ TypeVisitorCallbackPipeline Pipeline;
+ Pipeline.addCallbackToPipeline(Deserializer);
+ Pipeline.addCallbackToPipeline(DBV);
+ Pipeline.addCallbackToPipeline(Dumper);
+
+ CVTypeVisitor Visitor(Pipeline);
+
+ if (auto EC = Visitor.visitTypeStream(Types))
+ return EC;
+ return Error::success();
+}
+
+Error CVTypeDumper::dump(ArrayRef<uint8_t> Data, TypeVisitorCallbacks &Dumper) {
+ msf::ByteStream Stream(Data);
+ CVTypeArray Types;
+ msf::StreamReader Reader(Stream);
+ if (auto EC = Reader.readArray(Types, Reader.getLength()))
+ return EC;
+
+ return dump(Types, Dumper);
+}
+
+void CVTypeDumper::printTypeIndex(ScopedPrinter &Printer, StringRef FieldName,
+ TypeIndex TI, TypeDatabase &DB) {
+ StringRef TypeName;
+ if (!TI.isNoneType())
+ TypeName = DB.getTypeName(TI);
+ if (!TypeName.empty())
+ Printer.printHex(FieldName, TypeName, TI.getIndex());
+ else
+ Printer.printHex(FieldName, TI.getIndex());
+}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp b/contrib/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
index 09f7221..5171e24 100644
--- a/contrib/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
+++ b/contrib/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
@@ -9,115 +9,128 @@
#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;
+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(CVType &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) {}
+template <typename T>
+static Error visitKnownMember(CVMemberRecord &Record,
+ TypeVisitorCallbacks &Callbacks) {
+ TypeRecordKind RK = static_cast<TypeRecordKind>(Record.Kind);
+ T KnownRecord(RK);
+ if (auto EC = Callbacks.visitKnownMember(Record, KnownRecord))
+ return EC;
+ return Error::success();
+}
-Error CVTypeVisitor::visitTypeRecord(const CVRecord<TypeLeafKind> &Record) {
- ArrayRef<uint8_t> LeafData = Record.Data;
+Error CVTypeVisitor::visitTypeRecord(CVType &Record) {
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 Result = Name##Record::deserialize(RK, LeafData); \
- if (Result.getError()) \
- return llvm::make_error<CodeViewError>(cv_error_code::corrupt_record); \
- if (auto EC = Callbacks.visit##Name(*Result)) \
+ if (auto EC = visitKnownRecord<Name##Record>(Record, Callbacks)) \
return EC; \
break; \
}
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
TYPE_RECORD(EnumVal, EnumVal, AliasName)
#define MEMBER_RECORD(EnumName, EnumVal, Name)
+#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
}
+
if (auto EC = Callbacks.visitTypeEnd(Record))
return EC;
- return Error::success();
-}
-/// Visits the type records in Data. Sets the error flag on parse failures.
-Error CVTypeVisitor::visitTypeStream(const CVTypeArray &Types) {
- for (const auto &I : Types) {
- if (auto EC = visitTypeRecord(I))
- return EC;
- }
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();
-}
+static Error visitMemberRecord(CVMemberRecord &Record,
+ TypeVisitorCallbacks &Callbacks) {
+ if (auto EC = Callbacks.visitMemberBegin(Record))
+ return EC;
-/// 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))
+ switch (Record.Kind) {
+ default:
+ if (auto EC = Callbacks.visitUnknownMember(Record))
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);
+ break;
#define MEMBER_RECORD(EnumName, EnumVal, Name) \
case EnumName: { \
- TypeRecordKind RK = static_cast<TypeRecordKind>(EnumName); \
- auto Result = Name##Record::deserialize(RK, RecordData); \
- if (Result.getError()) \
- return llvm::make_error<CodeViewError>(cv_error_code::corrupt_record); \
- if (auto EC = Callbacks.visit##Name(*Result)) \
+ if (auto EC = visitKnownMember<Name##Record>(Record, Callbacks)) \
return EC; \
break; \
}
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
MEMBER_RECORD(EnumVal, EnumVal, AliasName)
+#define TYPE_RECORD(EnumName, EnumVal, Name)
+#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
- }
- if (auto EC = skipPadding(RecordData))
+ }
+
+ if (auto EC = Callbacks.visitMemberEnd(Record))
+ return EC;
+
+ return Error::success();
+}
+
+Error CVTypeVisitor::visitMemberRecord(CVMemberRecord &Record) {
+ return ::visitMemberRecord(Record, Callbacks);
+}
+
+/// Visits the type records in Data. Sets the error flag on parse failures.
+Error CVTypeVisitor::visitTypeStream(const CVTypeArray &Types) {
+ for (auto I : Types) {
+ if (auto EC = visitTypeRecord(I))
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))
+ return EC;
+
+ CVMemberRecord Record;
+ Record.Kind = Leaf;
+ if (auto EC = ::visitMemberRecord(Record, Pipeline))
+ return EC;
+ }
+
+ return Error::success();
+}
+
+Error CVTypeVisitor::visitFieldListMemberStream(ArrayRef<uint8_t> Data) {
+ msf::ByteStream S(Data);
+ msf::StreamReader SR(S);
+ return visitFieldListMemberStream(SR);
+}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/CodeViewError.cpp b/contrib/llvm/lib/DebugInfo/CodeView/CodeViewError.cpp
index aad1d8b..55c10c0 100644
--- a/contrib/llvm/lib/DebugInfo/CodeView/CodeViewError.cpp
+++ b/contrib/llvm/lib/DebugInfo/CodeView/CodeViewError.cpp
@@ -20,7 +20,7 @@ namespace {
// deal with the Error value directly, rather than converting to error_code.
class CodeViewErrorCategory : public std::error_category {
public:
- const char *name() const LLVM_NOEXCEPT override { return "llvm.codeview"; }
+ const char *name() const noexcept override { return "llvm.codeview"; }
std::string message(int Condition) const override {
switch (static_cast<cv_error_code>(Condition)) {
@@ -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/contrib/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp b/contrib/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp
new file mode 100644
index 0000000..9bd85cf
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp
@@ -0,0 +1,242 @@
+//===- 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(Optional<uint32_t> MaxLength) {
+ RecordLimit Limit;
+ Limit.MaxLength = MaxLength;
+ Limit.BeginOffset = getCurrentOffset();
+ Limits.push_back(Limit);
+ return Error::success();
+}
+
+Error CodeViewRecordIO::endRecord() {
+ assert(!Limits.empty() && "Not in a record!");
+ Limits.pop_back();
+ return Error::success();
+}
+
+uint32_t CodeViewRecordIO::maxFieldLength() const {
+ assert(!Limits.empty() && "Not in a record!");
+
+ // The max length of the next field is the minimum of all lengths that would
+ // be allowed by any of the sub-records we're in. In practice, we can only
+ // ever be at most 1 sub-record deep (in a FieldList), but this works for
+ // the general case.
+ uint32_t Offset = getCurrentOffset();
+ Optional<uint32_t> Min = Limits.front().bytesRemaining(Offset);
+ for (auto X : makeArrayRef(Limits).drop_front()) {
+ Optional<uint32_t> ThisMin = X.bytesRemaining(Offset);
+ if (ThisMin.hasValue())
+ Min = (Min.hasValue()) ? std::min(*Min, *ThisMin) : *ThisMin;
+ }
+ assert(Min.hasValue() && "Every field must have a maximum length!");
+
+ return *Min;
+}
+
+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::mapByteVectorTail(std::vector<uint8_t> &Bytes) {
+ ArrayRef<uint8_t> BytesRef(Bytes);
+ if (auto EC = mapByteVectorTail(BytesRef))
+ return EC;
+ if (!isWriting())
+ Bytes.assign(BytesRef.begin(), BytesRef.end());
+
+ 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()) {
+ // Truncate if we attempt to write too much.
+ StringRef S = Value.take_front(maxFieldLength() - 1);
+ if (auto EC = Writer->writeZeroString(S))
+ return EC;
+ } else {
+ if (auto EC = Reader->readZeroString(Value))
+ return EC;
+ }
+ return Error::success();
+}
+
+Error CodeViewRecordIO::mapGuid(StringRef &Guid) {
+ constexpr uint32_t GuidSize = 16;
+ if (maxFieldLength() < GuidSize)
+ return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
+
+ 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::mapStringZVectorZ(std::vector<StringRef> &Value) {
+ if (isWriting()) {
+ for (auto V : Value) {
+ if (auto EC = mapStringZ(V))
+ return EC;
+ }
+ if (auto EC = Writer->writeInteger(uint8_t(0)))
+ return EC;
+ } else {
+ StringRef S;
+ if (auto EC = mapStringZ(S))
+ return EC;
+ while (!S.empty()) {
+ Value.push_back(S);
+ if (auto EC = mapStringZ(S))
+ 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/contrib/llvm/lib/DebugInfo/CodeView/EnumTables.cpp b/contrib/llvm/lib/DebugInfo/CodeView/EnumTables.cpp
index d59271b..0e20bcb 100644
--- a/contrib/llvm/lib/DebugInfo/CodeView/EnumTables.cpp
+++ b/contrib/llvm/lib/DebugInfo/CodeView/EnumTables.cpp
@@ -24,6 +24,12 @@ static const EnumEntry<SymbolKind> SymbolTypeNames[] = {
#undef CV_SYMBOL
};
+static const EnumEntry<TypeLeafKind> TypeLeafNames[] = {
+#define CV_TYPE(name, val) {#name, name},
+#include "llvm/DebugInfo/CodeView/TypeRecords.def"
+#undef CV_TYPE
+};
+
static const EnumEntry<uint16_t> RegisterNames[] = {
CV_ENUM_CLASS_ENT(RegisterId, Unknown),
CV_ENUM_CLASS_ENT(RegisterId, VFrame),
@@ -324,6 +330,10 @@ ArrayRef<EnumEntry<SymbolKind>> getSymbolTypeNames() {
return makeArrayRef(SymbolTypeNames);
}
+ArrayRef<EnumEntry<TypeLeafKind>> getTypeLeafNames() {
+ return makeArrayRef(TypeLeafNames);
+}
+
ArrayRef<EnumEntry<uint16_t>> getRegisterNames() {
return makeArrayRef(RegisterNames);
}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp b/contrib/llvm/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp
deleted file mode 100644
index 5f229e3..0000000
--- a/contrib/llvm/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp
+++ /dev/null
@@ -1,132 +0,0 @@
-//===-- FieldListRecordBuilder.cpp ----------------------------------------===//
-//
-// 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/FieldListRecordBuilder.h"
-
-using namespace llvm;
-using namespace codeview;
-
-FieldListRecordBuilder::FieldListRecordBuilder()
- : ListRecordBuilder(TypeRecordKind::FieldList) {}
-
-void FieldListRecordBuilder::writeBaseClass(const BaseClassRecord &Record) {
- TypeRecordBuilder &Builder = getBuilder();
-
- Builder.writeTypeRecordKind(TypeRecordKind::BaseClass);
- Builder.writeUInt16(static_cast<uint16_t>(Record.getAccess()));
- Builder.writeTypeIndex(Record.getBaseType());
- Builder.writeEncodedUnsignedInteger(Record.getBaseOffset());
-
- finishSubRecord();
-}
-
-void FieldListRecordBuilder::writeEnumerator(const EnumeratorRecord &Record) {
- TypeRecordBuilder &Builder = getBuilder();
-
- Builder.writeTypeRecordKind(TypeRecordKind::Enumerator);
- Builder.writeUInt16(static_cast<uint16_t>(Record.getAccess()));
- // FIXME: Handle full APInt such as __int128.
- Builder.writeEncodedUnsignedInteger(Record.getValue().getZExtValue());
- Builder.writeNullTerminatedString(Record.getName());
-
- finishSubRecord();
-}
-
-void FieldListRecordBuilder::writeDataMember(const DataMemberRecord &Record) {
- TypeRecordBuilder &Builder = getBuilder();
-
- Builder.writeTypeRecordKind(Record.getKind());
- Builder.writeUInt16(static_cast<uint16_t>(Record.getAccess()));
- Builder.writeTypeIndex(Record.getType());
- Builder.writeEncodedUnsignedInteger(Record.getFieldOffset());
- Builder.writeNullTerminatedString(Record.getName());
-
- finishSubRecord();
-}
-
-void FieldListRecordBuilder::writeOverloadedMethod(
- const OverloadedMethodRecord &Record) {
- TypeRecordBuilder &Builder = getBuilder();
-
- Builder.writeTypeRecordKind(TypeRecordKind::OverloadedMethod);
- Builder.writeUInt16(Record.getNumOverloads());
- Builder.writeTypeIndex(Record.getMethodList());
- Builder.writeNullTerminatedString(Record.getName());
-
- finishSubRecord();
-}
-
-void FieldListRecordBuilder::writeOneMethod(const OneMethodRecord &Record) {
- TypeRecordBuilder &Builder = getBuilder();
-
- uint16_t Flags = static_cast<uint16_t>(Record.getAccess());
- Flags |= static_cast<uint16_t>(Record.getKind()) << MethodKindShift;
- Flags |= static_cast<uint16_t>(Record.getOptions());
-
- Builder.writeTypeRecordKind(TypeRecordKind::OneMethod);
- Builder.writeUInt16(Flags);
- Builder.writeTypeIndex(Record.getType());
- if (Record.isIntroducingVirtual()) {
- assert(Record.getVFTableOffset() >= 0);
- Builder.writeInt32(Record.getVFTableOffset());
- } else {
- assert(Record.getVFTableOffset() == -1);
- }
-
- Builder.writeNullTerminatedString(Record.getName());
-
- finishSubRecord();
-}
-
-void FieldListRecordBuilder::writeNestedType(const NestedTypeRecord &Record) {
- TypeRecordBuilder &Builder = getBuilder();
-
- Builder.writeTypeRecordKind(Record.getKind());
- Builder.writeUInt16(0);
- Builder.writeTypeIndex(Record.getNestedType());
- Builder.writeNullTerminatedString(Record.getName());
-
- finishSubRecord();
-}
-
-void FieldListRecordBuilder::writeStaticDataMember(
- const StaticDataMemberRecord &Record) {
- TypeRecordBuilder &Builder = getBuilder();
-
- Builder.writeTypeRecordKind(Record.getKind());
- Builder.writeUInt16(static_cast<uint16_t>(Record.getAccess()));
- Builder.writeTypeIndex(Record.getType());
- Builder.writeNullTerminatedString(Record.getName());
-
- finishSubRecord();
-}
-
-void FieldListRecordBuilder::writeVirtualBaseClass(
- const VirtualBaseClassRecord &Record) {
- TypeRecordBuilder &Builder = getBuilder();
-
- Builder.writeTypeRecordKind(Record.getKind());
- Builder.writeUInt16(static_cast<uint16_t>(Record.getAccess()));
- Builder.writeTypeIndex(Record.getBaseType());
- Builder.writeTypeIndex(Record.getVBPtrType());
- Builder.writeEncodedInteger(Record.getVBPtrOffset());
- Builder.writeEncodedUnsignedInteger(Record.getVTableIndex());
-
- finishSubRecord();
-}
-
-void FieldListRecordBuilder::writeVFPtr(const VFPtrRecord &Record) {
- TypeRecordBuilder &Builder = getBuilder();
-
- Builder.writeTypeRecordKind(TypeRecordKind::VFPtr);
- Builder.writeUInt16(0);
- Builder.writeTypeIndex(Record.getType());
-
- finishSubRecord();
-}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/ListRecordBuilder.cpp b/contrib/llvm/lib/DebugInfo/CodeView/ListRecordBuilder.cpp
deleted file mode 100644
index eb79e8a..0000000
--- a/contrib/llvm/lib/DebugInfo/CodeView/ListRecordBuilder.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-//===-- ListRecordBuilder.cpp ---------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/SmallString.h"
-#include "llvm/DebugInfo/CodeView/ListRecordBuilder.h"
-#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
-
-using namespace llvm;
-using namespace codeview;
-
-ListRecordBuilder::ListRecordBuilder(TypeRecordKind Kind)
- : Kind(Kind), Builder(Kind) {}
-
-void ListRecordBuilder::writeListContinuation(const ListContinuationRecord &R) {
- TypeRecordBuilder &Builder = getBuilder();
-
- assert(getLastContinuationSize() < 65535 - 8 && "continuation won't fit");
-
- Builder.writeTypeRecordKind(TypeRecordKind::ListContinuation);
- Builder.writeUInt16(0);
- Builder.writeTypeIndex(R.getContinuationIndex());
-
- // End the current segment manually so that nothing comes after the
- // continuation.
- ContinuationOffsets.push_back(Builder.size());
- SubrecordStart = Builder.size();
-}
-
-void ListRecordBuilder::finishSubRecord() {
- // The type table inserts a 16 bit size field before each list, so factor that
- // into our alignment padding.
- uint32_t Remainder =
- (Builder.size() + 2 * (ContinuationOffsets.size() + 1)) % 4;
- if (Remainder != 0) {
- for (int32_t PaddingBytesLeft = 4 - Remainder; PaddingBytesLeft > 0;
- --PaddingBytesLeft) {
- Builder.writeUInt8(LF_PAD0 + PaddingBytesLeft);
- }
- }
-
- // Check if this subrecord makes the current segment not fit in 64K minus the
- // space for a continuation record (8 bytes). If the segment does not fit,
- // back up and insert a continuation record, sliding the current subrecord
- // down.
- if (getLastContinuationSize() > 65535 - 8) {
- assert(SubrecordStart != 0 && "can't slide from the start!");
- SmallString<128> SubrecordCopy(
- Builder.str().slice(SubrecordStart, Builder.size()));
- assert(SubrecordCopy.size() < 65530 && "subrecord is too large to slide!");
- Builder.truncate(SubrecordStart);
-
- // Write a placeholder continuation record.
- Builder.writeTypeRecordKind(TypeRecordKind::ListContinuation);
- Builder.writeUInt16(0);
- Builder.writeUInt32(0);
- ContinuationOffsets.push_back(Builder.size());
- assert(Builder.size() == SubrecordStart + 8 && "wrong continuation size");
- assert(getLastContinuationSize() < 65535 && "segment too big");
-
- // Start a new list record of the appropriate kind, and copy the previous
- // subrecord into place.
- Builder.writeTypeRecordKind(Kind);
- Builder.writeBytes(SubrecordCopy);
- }
-
- SubrecordStart = Builder.size();
-}
-
-TypeIndex ListRecordBuilder::writeListRecord(TypeTableBuilder &Table) {
- // Get the continuation segments as a reversed vector of StringRefs for
- // convenience.
- SmallVector<StringRef, 1> Segments;
- StringRef Data = str();
- size_t LastEnd = 0;
- for (size_t SegEnd : ContinuationOffsets) {
- Segments.push_back(Data.slice(LastEnd, SegEnd));
- LastEnd = SegEnd;
- }
- Segments.push_back(Data.slice(LastEnd, Builder.size()));
-
- // Pop the last record off and emit it directly.
- StringRef LastRec = Segments.pop_back_val();
- TypeIndex ContinuationIndex = Table.writeRecord(LastRec);
-
- // Emit each record with a continuation in reverse order, so that each one
- // references the previous record.
- for (StringRef Rec : reverse(Segments)) {
- assert(*reinterpret_cast<const ulittle16_t *>(Rec.data()) ==
- unsigned(Kind));
- ulittle32_t *ContinuationPtr =
- reinterpret_cast<ulittle32_t *>(const_cast<char *>(Rec.end())) - 1;
- *ContinuationPtr = ContinuationIndex.getIndex();
- ContinuationIndex = Table.writeRecord(Rec);
- }
- return ContinuationIndex;
-}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/MemoryTypeTableBuilder.cpp b/contrib/llvm/lib/DebugInfo/CodeView/MemoryTypeTableBuilder.cpp
deleted file mode 100644
index 8b9e73b..0000000
--- a/contrib/llvm/lib/DebugInfo/CodeView/MemoryTypeTableBuilder.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-//===-- MemoryTypeTableBuilder.cpp ----------------------------------------===//
-//
-// 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/MemoryTypeTableBuilder.h"
-#include "llvm/DebugInfo/CodeView/TypeIndex.h"
-
-using namespace llvm;
-using namespace codeview;
-
-TypeIndex MemoryTypeTableBuilder::writeRecord(StringRef Data) {
- assert(Data.size() <= UINT16_MAX);
- auto I = HashedRecords.find(Data);
- if (I != HashedRecords.end()) {
- return I->second;
- }
-
- // The record provided by the user lacks the 2 byte size field prefix and is
- // not padded to 4 bytes. Ultimately, that is what gets emitted in the object
- // file, so pad it out now.
- const int SizeOfRecLen = 2;
- const int Align = 4;
- int TotalSize = alignTo(Data.size() + SizeOfRecLen, Align);
- assert(TotalSize - SizeOfRecLen <= UINT16_MAX);
- char *Mem =
- reinterpret_cast<char *>(RecordStorage.Allocate(TotalSize, Align));
- *reinterpret_cast<ulittle16_t *>(Mem) = uint16_t(TotalSize - SizeOfRecLen);
- memcpy(Mem + SizeOfRecLen, Data.data(), Data.size());
- for (int I = Data.size() + SizeOfRecLen; I < TotalSize; ++I)
- Mem[I] = LF_PAD0 + (TotalSize - I);
-
- TypeIndex TI(static_cast<uint32_t>(Records.size()) +
- TypeIndex::FirstNonSimpleIndex);
-
- // Use only the data supplied by the user as a key to the hash table, so that
- // future lookups will succeed.
- HashedRecords.insert(std::make_pair(StringRef(Mem + SizeOfRecLen, Data.size()), TI));
- Records.push_back(StringRef(Mem, TotalSize));
-
- return TI;
-}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/MethodListRecordBuilder.cpp b/contrib/llvm/lib/DebugInfo/CodeView/MethodListRecordBuilder.cpp
deleted file mode 100644
index ae089a3..0000000
--- a/contrib/llvm/lib/DebugInfo/CodeView/MethodListRecordBuilder.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-//===-- MethodListRecordBuilder.cpp ---------------------------------------===//
-//
-// 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/MethodListRecordBuilder.h"
-#include "llvm/DebugInfo/CodeView/FieldListRecordBuilder.h"
-
-using namespace llvm;
-using namespace codeview;
-
-MethodListRecordBuilder::MethodListRecordBuilder()
- : ListRecordBuilder(TypeRecordKind::MethodOverloadList) {}
-
-void MethodListRecordBuilder::writeMethod(MemberAccess Access, MethodKind Kind,
- MethodOptions Options, TypeIndex Type,
- int32_t VTableSlotOffset) {
- TypeRecordBuilder &Builder = getBuilder();
-
- uint16_t Flags = static_cast<uint16_t>(Access);
- Flags |= static_cast<uint16_t>(Kind) << MethodKindShift;
- Flags |= static_cast<uint16_t>(Options);
-
- Builder.writeUInt16(Flags);
- Builder.writeUInt16(0);
- Builder.writeTypeIndex(Type);
- switch (Kind) {
- case MethodKind::IntroducingVirtual:
- case MethodKind::PureIntroducingVirtual:
- assert(VTableSlotOffset >= 0);
- Builder.writeInt32(VTableSlotOffset);
- break;
-
- default:
- assert(VTableSlotOffset == -1);
- break;
- }
-
- // TODO: Fail if too big?
-}
-
-void MethodListRecordBuilder::writeMethod(const MethodInfo &Method) {
- writeMethod(Method.getAccess(), Method.getKind(), Method.getOptions(),
- Method.getType(), Method.getVTableSlotOffset());
-}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/ModuleSubstream.cpp b/contrib/llvm/lib/DebugInfo/CodeView/ModuleSubstream.cpp
index 2e31ed6..768ebaa 100644
--- a/contrib/llvm/lib/DebugInfo/CodeView/ModuleSubstream.cpp
+++ b/contrib/llvm/lib/DebugInfo/CodeView/ModuleSubstream.cpp
@@ -9,17 +9,20 @@
#include "llvm/DebugInfo/CodeView/ModuleSubstream.h"
-#include "llvm/DebugInfo/CodeView/StreamReader.h"
+#include "llvm/DebugInfo/MSF/StreamReader.h"
using namespace llvm;
using namespace llvm::codeview;
+using namespace llvm::msf;
ModuleSubstream::ModuleSubstream() : Kind(ModuleSubstreamKind::None) {}
-ModuleSubstream::ModuleSubstream(ModuleSubstreamKind Kind, StreamRef Data)
+ModuleSubstream::ModuleSubstream(ModuleSubstreamKind Kind,
+ ReadableStreamRef Data)
: Kind(Kind), Data(Data) {}
-Error ModuleSubstream::initialize(StreamRef Stream, ModuleSubstream &Info) {
+Error ModuleSubstream::initialize(ReadableStreamRef Stream,
+ ModuleSubstream &Info) {
const ModuleSubsectionHeader *Header;
StreamReader Reader(Stream);
if (auto EC = Reader.readObject(Header))
@@ -39,4 +42,4 @@ uint32_t ModuleSubstream::getRecordLength() const {
ModuleSubstreamKind ModuleSubstream::getSubstreamKind() const { return Kind; }
-StreamRef ModuleSubstream::getRecordData() const { return Data; }
+ReadableStreamRef ModuleSubstream::getRecordData() const { return Data; }
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/ModuleSubstreamVisitor.cpp b/contrib/llvm/lib/DebugInfo/CodeView/ModuleSubstreamVisitor.cpp
index 6f237ee..5247932 100644
--- a/contrib/llvm/lib/DebugInfo/CodeView/ModuleSubstreamVisitor.cpp
+++ b/contrib/llvm/lib/DebugInfo/CodeView/ModuleSubstreamVisitor.cpp
@@ -8,50 +8,54 @@
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h"
+#include "llvm/DebugInfo/MSF/StreamReader.h"
+#include "llvm/DebugInfo/MSF/StreamRef.h"
using namespace llvm;
using namespace llvm::codeview;
+using namespace llvm::msf;
-Error IModuleSubstreamVisitor::visitSymbols(StreamRef Data) {
+Error IModuleSubstreamVisitor::visitSymbols(ReadableStreamRef Data) {
return visitUnknown(ModuleSubstreamKind::Symbols, Data);
}
-Error IModuleSubstreamVisitor::visitLines(StreamRef Data,
+Error IModuleSubstreamVisitor::visitLines(ReadableStreamRef Data,
const LineSubstreamHeader *Header,
const LineInfoArray &Lines) {
return visitUnknown(ModuleSubstreamKind::Lines, Data);
}
-Error IModuleSubstreamVisitor::visitStringTable(StreamRef Data) {
+Error IModuleSubstreamVisitor::visitStringTable(ReadableStreamRef Data) {
return visitUnknown(ModuleSubstreamKind::StringTable, Data);
}
Error IModuleSubstreamVisitor::visitFileChecksums(
- StreamRef Data, const FileChecksumArray &Checksums) {
+ ReadableStreamRef Data, const FileChecksumArray &Checksums) {
return visitUnknown(ModuleSubstreamKind::FileChecksums, Data);
}
-Error IModuleSubstreamVisitor::visitFrameData(StreamRef Data) {
+Error IModuleSubstreamVisitor::visitFrameData(ReadableStreamRef Data) {
return visitUnknown(ModuleSubstreamKind::FrameData, Data);
}
-Error IModuleSubstreamVisitor::visitInlineeLines(StreamRef Data) {
+Error IModuleSubstreamVisitor::visitInlineeLines(ReadableStreamRef Data) {
return visitUnknown(ModuleSubstreamKind::InlineeLines, Data);
}
-Error IModuleSubstreamVisitor::visitCrossScopeImports(StreamRef Data) {
+Error IModuleSubstreamVisitor::visitCrossScopeImports(ReadableStreamRef Data) {
return visitUnknown(ModuleSubstreamKind::CrossScopeExports, Data);
}
-Error IModuleSubstreamVisitor::visitCrossScopeExports(StreamRef Data) {
+Error IModuleSubstreamVisitor::visitCrossScopeExports(ReadableStreamRef Data) {
return visitUnknown(ModuleSubstreamKind::CrossScopeImports, Data);
}
-Error IModuleSubstreamVisitor::visitILLines(StreamRef Data) {
+Error IModuleSubstreamVisitor::visitILLines(ReadableStreamRef Data) {
return visitUnknown(ModuleSubstreamKind::ILLines, Data);
}
-Error IModuleSubstreamVisitor::visitFuncMDTokenMap(StreamRef Data) {
+Error IModuleSubstreamVisitor::visitFuncMDTokenMap(ReadableStreamRef Data) {
return visitUnknown(ModuleSubstreamKind::FuncMDTokenMap, Data);
}
-Error IModuleSubstreamVisitor::visitTypeMDTokenMap(StreamRef Data) {
+Error IModuleSubstreamVisitor::visitTypeMDTokenMap(ReadableStreamRef Data) {
return visitUnknown(ModuleSubstreamKind::TypeMDTokenMap, Data);
}
-Error IModuleSubstreamVisitor::visitMergedAssemblyInput(StreamRef Data) {
+Error IModuleSubstreamVisitor::visitMergedAssemblyInput(
+ ReadableStreamRef Data) {
return visitUnknown(ModuleSubstreamKind::MergedAssemblyInput, Data);
}
-Error IModuleSubstreamVisitor::visitCoffSymbolRVA(StreamRef Data) {
+Error IModuleSubstreamVisitor::visitCoffSymbolRVA(ReadableStreamRef Data) {
return visitUnknown(ModuleSubstreamKind::CoffSymbolRVA, Data);
}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/RecordSerialization.cpp b/contrib/llvm/lib/DebugInfo/CodeView/RecordSerialization.cpp
index ab9206a..6f29caa 100644
--- a/contrib/llvm/lib/DebugInfo/CodeView/RecordSerialization.cpp
+++ b/contrib/llvm/lib/DebugInfo/CodeView/RecordSerialization.cpp
@@ -14,7 +14,9 @@
#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
#include "llvm/ADT/APInt.h"
#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;
@@ -31,141 +33,117 @@ StringRef llvm::codeview::getBytesAsCString(ArrayRef<uint8_t> LeafData) {
return getBytesAsCharacters(LeafData).split('\0').first;
}
-std::error_code 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 std::make_error_code(std::errc::illegal_byte_sequence);
- 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 std::error_code();
+ return Error::success();
}
+
switch (Short) {
- case LF_CHAR:
- if (Data.size() < 1)
- return std::make_error_code(std::errc::illegal_byte_sequence);
- Num = APSInt(APInt(/*numBits=*/8,
- *reinterpret_cast<const int8_t *>(Data.data()),
- /*isSigned=*/true),
- /*isUnsigned=*/false);
- Data = Data.drop_front(1);
- return std::error_code();
- case LF_SHORT:
- if (Data.size() < 2)
- return std::make_error_code(std::errc::illegal_byte_sequence);
- Num = APSInt(APInt(/*numBits=*/16,
- *reinterpret_cast<const little16_t *>(Data.data()),
- /*isSigned=*/true),
- /*isUnsigned=*/false);
- Data = Data.drop_front(2);
- return std::error_code();
- case LF_USHORT:
- if (Data.size() < 2)
- return std::make_error_code(std::errc::illegal_byte_sequence);
- Num = APSInt(APInt(/*numBits=*/16,
- *reinterpret_cast<const ulittle16_t *>(Data.data()),
- /*isSigned=*/false),
- /*isUnsigned=*/true);
- Data = Data.drop_front(2);
- return std::error_code();
- case LF_LONG:
- if (Data.size() < 4)
- return std::make_error_code(std::errc::illegal_byte_sequence);
- Num = APSInt(APInt(/*numBits=*/32,
- *reinterpret_cast<const little32_t *>(Data.data()),
- /*isSigned=*/true),
- /*isUnsigned=*/false);
- Data = Data.drop_front(4);
- return std::error_code();
- case LF_ULONG:
- if (Data.size() < 4)
- return std::make_error_code(std::errc::illegal_byte_sequence);
- Num = APSInt(APInt(/*numBits=*/32,
- *reinterpret_cast<const ulittle32_t *>(Data.data()),
- /*isSigned=*/FalseVal),
- /*isUnsigned=*/true);
- Data = Data.drop_front(4);
- return std::error_code();
- case LF_QUADWORD:
- if (Data.size() < 8)
- return std::make_error_code(std::errc::illegal_byte_sequence);
- Num = APSInt(APInt(/*numBits=*/64,
- *reinterpret_cast<const little64_t *>(Data.data()),
- /*isSigned=*/true),
- /*isUnsigned=*/false);
- Data = Data.drop_front(8);
- return std::error_code();
- case LF_UQUADWORD:
- if (Data.size() < 8)
- return std::make_error_code(std::errc::illegal_byte_sequence);
- Num = APSInt(APInt(/*numBits=*/64,
- *reinterpret_cast<const ulittle64_t *>(Data.data()),
- /*isSigned=*/false),
- /*isUnsigned=*/true);
- Data = Data.drop_front(8);
- return std::error_code();
+ 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: {
+ int16_t N;
+ if (auto EC = Reader.readInteger(N))
+ return EC;
+ Num = APSInt(APInt(16, N, true), false);
+ return Error::success();
+ }
+ case LF_USHORT: {
+ uint16_t N;
+ if (auto EC = Reader.readInteger(N))
+ return EC;
+ Num = APSInt(APInt(16, N, false), true);
+ return Error::success();
}
- return std::make_error_code(std::errc::illegal_byte_sequence);
+ 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: {
+ uint32_t N;
+ if (auto EC = Reader.readInteger(N))
+ return EC;
+ Num = APSInt(APInt(32, N, FalseVal), true);
+ return Error::success();
+ }
+ 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: {
+ 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");
}
-std::error_code llvm::codeview::consume(StringRef &Data, APSInt &Num) {
+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.
-std::error_code 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 std::make_error_code(std::errc::illegal_byte_sequence);
+ return make_error<CodeViewError>(cv_error_code::corrupt_record,
+ "Data is not a numeric value!");
Num = N.getLimitedValue();
- return std::error_code();
+ return Error::success();
}
-std::error_code 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 std::error_code();
+Error llvm::codeview::consume(msf::StreamReader &Reader, uint32_t &Item) {
+ return Reader.readInteger(Item);
}
-std::error_code llvm::codeview::consume(StringRef &Data, uint32_t &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;
}
-std::error_code 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 std::error_code();
+Error llvm::codeview::consume(msf::StreamReader &Reader, int32_t &Item) {
+ return Reader.readInteger(Item);
}
-std::error_code llvm::codeview::consume(ArrayRef<uint8_t> &Data,
- StringRef &Item) {
- if (Data.empty())
- return std::make_error_code(std::errc::illegal_byte_sequence);
-
- 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 std::make_error_code(std::errc::illegal_byte_sequence);
+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!");
- Data = ArrayRef<uint8_t>(Rest.bytes_begin(), Rest.bytes_end());
- return std::error_code();
+ return Reader.readZeroString(Item);
}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/StreamReader.cpp b/contrib/llvm/lib/DebugInfo/CodeView/StreamReader.cpp
deleted file mode 100644
index 64e4548..0000000
--- a/contrib/llvm/lib/DebugInfo/CodeView/StreamReader.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-//===- StreamReader.cpp - Reads bytes and objects from a stream -----------===//
-//
-// 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/StreamReader.h"
-
-#include "llvm/DebugInfo/CodeView/CodeViewError.h"
-#include "llvm/DebugInfo/CodeView/StreamRef.h"
-
-using namespace llvm;
-using namespace llvm::codeview;
-
-StreamReader::StreamReader(StreamRef S) : Stream(S), Offset(0) {}
-
-Error StreamReader::readLongestContiguousChunk(ArrayRef<uint8_t> &Buffer) {
- if (auto EC = Stream.readLongestContiguousChunk(Offset, Buffer))
- return EC;
- Offset += Buffer.size();
- return Error::success();
-}
-
-Error StreamReader::readBytes(ArrayRef<uint8_t> &Buffer, uint32_t Size) {
- if (auto EC = Stream.readBytes(Offset, Size, Buffer))
- return EC;
- Offset += Size;
- return Error::success();
-}
-
-Error StreamReader::readInteger(uint16_t &Dest) {
- const support::ulittle16_t *P;
- if (auto EC = readObject(P))
- return EC;
- Dest = *P;
- return Error::success();
-}
-
-Error StreamReader::readInteger(uint32_t &Dest) {
- const support::ulittle32_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.
- uint32_t OriginalOffset = getOffset();
- const char *C;
- do {
- if (auto EC = readObject(C))
- return EC;
- if (*C != '\0')
- ++Length;
- } while (*C != '\0');
- // Now go back and request a reference for that many bytes.
- uint32_t NewOffset = getOffset();
- setOffset(OriginalOffset);
-
- ArrayRef<uint8_t> Data;
- if (auto EC = readBytes(Data, Length))
- return EC;
- Dest = StringRef(reinterpret_cast<const char *>(Data.begin()), Data.size());
-
- // Now set the offset back to where it was after we calculated the length.
- setOffset(NewOffset);
- return Error::success();
-}
-
-Error StreamReader::readFixedString(StringRef &Dest, uint32_t Length) {
- ArrayRef<uint8_t> Bytes;
- if (auto EC = readBytes(Bytes, Length))
- return EC;
- Dest = StringRef(reinterpret_cast<const char *>(Bytes.begin()), Bytes.size());
- return Error::success();
-}
-
-Error StreamReader::readStreamRef(StreamRef &Ref) {
- return readStreamRef(Ref, bytesRemaining());
-}
-
-Error StreamReader::readStreamRef(StreamRef &Ref, uint32_t Length) {
- if (bytesRemaining() < Length)
- return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
- Ref = Stream.slice(Offset, Length);
- Offset += Length;
- return Error::success();
-}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/StreamWriter.cpp b/contrib/llvm/lib/DebugInfo/CodeView/StreamWriter.cpp
deleted file mode 100644
index f61c6b5..0000000
--- a/contrib/llvm/lib/DebugInfo/CodeView/StreamWriter.cpp
+++ /dev/null
@@ -1,77 +0,0 @@
-//===- StreamWrite.cpp - Writes bytes and objects to a stream -------------===//
-//
-// 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/StreamWriter.h"
-
-#include "llvm/DebugInfo/CodeView/CodeViewError.h"
-#include "llvm/DebugInfo/CodeView/StreamReader.h"
-#include "llvm/DebugInfo/CodeView/StreamRef.h"
-
-using namespace llvm;
-using namespace llvm::codeview;
-
-StreamWriter::StreamWriter(StreamRef S) : Stream(S), Offset(0) {}
-
-Error StreamWriter::writeBytes(ArrayRef<uint8_t> Buffer) {
- if (auto EC = Stream.writeBytes(Offset, Buffer))
- return EC;
- Offset += Buffer.size();
- return Error::success();
-}
-
-Error StreamWriter::writeInteger(uint16_t Int) {
- return writeObject(support::ulittle16_t(Int));
-}
-
-Error StreamWriter::writeInteger(uint32_t Int) {
- return writeObject(support::ulittle32_t(Int));
-}
-
-Error StreamWriter::writeZeroString(StringRef Str) {
- if (auto EC = writeFixedString(Str))
- return EC;
- if (auto EC = writeObject('\0'))
- return EC;
-
- return Error::success();
-}
-
-Error StreamWriter::writeFixedString(StringRef Str) {
- ArrayRef<uint8_t> Bytes(Str.bytes_begin(), Str.bytes_end());
- if (auto EC = Stream.writeBytes(Offset, Bytes))
- return EC;
-
- Offset += Str.size();
- return Error::success();
-}
-
-Error StreamWriter::writeStreamRef(StreamRef Ref) {
- if (auto EC = writeStreamRef(Ref, Ref.getLength()))
- return EC;
- Offset += Ref.getLength();
- return Error::success();
-}
-
-Error StreamWriter::writeStreamRef(StreamRef Ref, uint32_t Length) {
- Ref = Ref.slice(0, Length);
-
- StreamReader SrcReader(Ref);
- // This is a bit tricky. If we just call readBytes, we are requiring that it
- // return us the entire stream as a contiguous buffer. For large streams this
- // will allocate a huge amount of space from the pool. Instead, iterate over
- // each contiguous chunk until we've consumed the entire stream.
- while (SrcReader.bytesRemaining() > 0) {
- ArrayRef<uint8_t> Chunk;
- if (auto EC = SrcReader.readLongestContiguousChunk(Chunk))
- return EC;
- if (auto EC = writeBytes(Chunk))
- return EC;
- }
- return Error::success();
-}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp b/contrib/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp
index 6763c3d..fd54fba 100644
--- a/contrib/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp
+++ b/contrib/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp
@@ -11,11 +11,15 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
+#include "llvm/DebugInfo/CodeView/CVTypeDumper.h"
#include "llvm/DebugInfo/CodeView/EnumTables.h"
+#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
#include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
-#include "llvm/DebugInfo/CodeView/TypeDumper.h"
+#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h"
+#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/ScopedPrinter.h"
#include <system_error>
@@ -26,29 +30,30 @@ using namespace llvm::codeview;
namespace {
/// Use this private dumper implementation to keep implementation details about
/// the visitor out of SymbolDumper.h.
-class CVSymbolDumperImpl : public CVSymbolVisitor<CVSymbolDumperImpl> {
+class CVSymbolDumperImpl : public SymbolVisitorCallbacks {
public:
- CVSymbolDumperImpl(CVTypeDumper &CVTD, SymbolDumpDelegate *ObjDelegate,
+ CVSymbolDumperImpl(TypeDatabase &TypeDB, SymbolDumpDelegate *ObjDelegate,
ScopedPrinter &W, bool PrintRecordBytes)
- : CVSymbolVisitor(ObjDelegate), CVTD(CVTD), ObjDelegate(ObjDelegate),
- W(W), PrintRecordBytes(PrintRecordBytes), InFunctionScope(false) {}
+ : TypeDB(TypeDB), ObjDelegate(ObjDelegate), W(W),
+ PrintRecordBytes(PrintRecordBytes), InFunctionScope(false) {}
/// CVSymbolVisitor overrides.
#define SYMBOL_RECORD(EnumName, EnumVal, Name) \
- void visit##Name(SymbolKind Kind, Name &Record);
+ Error visitKnownRecord(CVSymbol &CVR, Name &Record) override;
#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "llvm/DebugInfo/CodeView/CVSymbolTypes.def"
- void visitSymbolBegin(SymbolKind Kind, ArrayRef<uint8_t> Data);
- void visitSymbolEnd(SymbolKind Kind, ArrayRef<uint8_t> OriginalSymData);
- void visitUnknownSymbol(SymbolKind Kind, ArrayRef<uint8_t> Data);
+ Error visitSymbolBegin(CVSymbol &Record) override;
+ Error visitSymbolEnd(CVSymbol &Record) override;
+ Error visitUnknownSymbol(CVSymbol &Record) override;
private:
void printLocalVariableAddrRange(const LocalVariableAddrRange &Range,
uint32_t RelocationOffset);
void printLocalVariableAddrGap(ArrayRef<LocalVariableAddrGap> Gaps);
+ void printTypeIndex(StringRef FieldName, TypeIndex TI);
- CVTypeDumper &CVTD;
+ TypeDatabase &TypeDB;
SymbolDumpDelegate *ObjDelegate;
ScopedPrinter &W;
@@ -76,376 +81,395 @@ void CVSymbolDumperImpl::printLocalVariableAddrGap(
}
}
-void CVSymbolDumperImpl::visitSymbolBegin(SymbolKind Kind,
- ArrayRef<uint8_t> Data) {}
+void CVSymbolDumperImpl::printTypeIndex(StringRef FieldName, TypeIndex TI) {
+ CVTypeDumper::printTypeIndex(W, FieldName, TI, TypeDB);
+}
+
+Error CVSymbolDumperImpl::visitSymbolBegin(CVSymbol &CVR) {
+ return Error::success();
+}
-void CVSymbolDumperImpl::visitSymbolEnd(SymbolKind Kind,
- ArrayRef<uint8_t> OriginalSymData) {
+Error CVSymbolDumperImpl::visitSymbolEnd(CVSymbol &CVR) {
if (PrintRecordBytes && ObjDelegate)
- ObjDelegate->printBinaryBlockWithRelocs("SymData", OriginalSymData);
+ ObjDelegate->printBinaryBlockWithRelocs("SymData", CVR.content());
+ return Error::success();
}
-void CVSymbolDumperImpl::visitBlockSym(SymbolKind Kind, BlockSym &Block) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, BlockSym &Block) {
DictScope S(W, "BlockStart");
StringRef LinkageName;
- W.printHex("PtrParent", Block.Header.PtrParent);
- W.printHex("PtrEnd", Block.Header.PtrEnd);
- W.printHex("CodeSize", Block.Header.CodeSize);
+ W.printHex("PtrParent", Block.Parent);
+ W.printHex("PtrEnd", Block.End);
+ W.printHex("CodeSize", Block.CodeSize);
if (ObjDelegate) {
ObjDelegate->printRelocatedField("CodeOffset", Block.getRelocationOffset(),
- Block.Header.CodeOffset, &LinkageName);
+ Block.CodeOffset, &LinkageName);
}
- W.printHex("Segment", Block.Header.Segment);
+ W.printHex("Segment", Block.Segment);
W.printString("BlockName", Block.Name);
W.printString("LinkageName", LinkageName);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitThunk32Sym(SymbolKind Kind, Thunk32Sym &Thunk) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, Thunk32Sym &Thunk) {
DictScope S(W, "Thunk32");
- W.printNumber("Parent", Thunk.Header.Parent);
- W.printNumber("End", Thunk.Header.End);
- W.printNumber("Next", Thunk.Header.Next);
- W.printNumber("Off", Thunk.Header.Off);
- W.printNumber("Seg", Thunk.Header.Seg);
- W.printNumber("Len", Thunk.Header.Len);
- W.printEnum("Ordinal", Thunk.Header.Ord, getThunkOrdinalNames());
-}
-
-void CVSymbolDumperImpl::visitTrampolineSym(SymbolKind Kind,
- TrampolineSym &Tramp) {
+ W.printNumber("Parent", Thunk.Parent);
+ W.printNumber("End", Thunk.End);
+ W.printNumber("Next", Thunk.Next);
+ W.printNumber("Off", Thunk.Offset);
+ W.printNumber("Seg", Thunk.Segment);
+ W.printNumber("Len", Thunk.Length);
+ W.printEnum("Ordinal", uint8_t(Thunk.Thunk), getThunkOrdinalNames());
+ return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+ TrampolineSym &Tramp) {
DictScope S(W, "Trampoline");
- W.printEnum("Type", Tramp.Header.Type, getTrampolineNames());
- W.printNumber("Size", Tramp.Header.Size);
- W.printNumber("ThunkOff", Tramp.Header.ThunkOff);
- W.printNumber("TargetOff", Tramp.Header.TargetOff);
- W.printNumber("ThunkSection", Tramp.Header.ThunkSection);
- W.printNumber("TargetSection", Tramp.Header.TargetSection);
+ W.printEnum("Type", uint16_t(Tramp.Type), getTrampolineNames());
+ W.printNumber("Size", Tramp.Size);
+ W.printNumber("ThunkOff", Tramp.ThunkOffset);
+ W.printNumber("TargetOff", Tramp.TargetOffset);
+ W.printNumber("ThunkSection", Tramp.ThunkSection);
+ W.printNumber("TargetSection", Tramp.TargetSection);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitSectionSym(SymbolKind Kind, SectionSym &Section) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, SectionSym &Section) {
DictScope S(W, "Section");
- W.printNumber("SectionNumber", Section.Header.SectionNumber);
- W.printNumber("Alignment", Section.Header.Alignment);
- W.printNumber("Reserved", Section.Header.Reserved);
- W.printNumber("Rva", Section.Header.Rva);
- W.printNumber("Length", Section.Header.Length);
- W.printFlags("Characteristics", Section.Header.Characteristics,
+ W.printNumber("SectionNumber", Section.SectionNumber);
+ W.printNumber("Alignment", Section.Alignment);
+ W.printNumber("Rva", Section.Rva);
+ W.printNumber("Length", Section.Length);
+ W.printFlags("Characteristics", Section.Characteristics,
getImageSectionCharacteristicNames(),
COFF::SectionCharacteristics(0x00F00000));
W.printString("Name", Section.Name);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitCoffGroupSym(SymbolKind Kind,
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
CoffGroupSym &CoffGroup) {
DictScope S(W, "COFF Group");
- W.printNumber("Size", CoffGroup.Header.Size);
- W.printFlags("Characteristics", CoffGroup.Header.Characteristics,
+ W.printNumber("Size", CoffGroup.Size);
+ W.printFlags("Characteristics", CoffGroup.Characteristics,
getImageSectionCharacteristicNames(),
COFF::SectionCharacteristics(0x00F00000));
- W.printNumber("Offset", CoffGroup.Header.Offset);
- W.printNumber("Segment", CoffGroup.Header.Segment);
+ W.printNumber("Offset", CoffGroup.Offset);
+ W.printNumber("Segment", CoffGroup.Segment);
W.printString("Name", CoffGroup.Name);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitBPRelativeSym(SymbolKind Kind,
- BPRelativeSym &BPRel) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+ BPRelativeSym &BPRel) {
DictScope S(W, "BPRelativeSym");
- W.printNumber("Offset", BPRel.Header.Offset);
- CVTD.printTypeIndex("Type", BPRel.Header.Type);
+ W.printNumber("Offset", BPRel.Offset);
+ printTypeIndex("Type", BPRel.Type);
W.printString("VarName", BPRel.Name);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitBuildInfoSym(SymbolKind Kind,
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
BuildInfoSym &BuildInfo) {
DictScope S(W, "BuildInfo");
- W.printNumber("BuildId", BuildInfo.Header.BuildId);
+ W.printNumber("BuildId", BuildInfo.BuildId);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitCallSiteInfoSym(SymbolKind Kind,
- CallSiteInfoSym &CallSiteInfo) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+ CallSiteInfoSym &CallSiteInfo) {
DictScope S(W, "CallSiteInfo");
StringRef LinkageName;
if (ObjDelegate) {
- ObjDelegate->printRelocatedField(
- "CodeOffset", CallSiteInfo.getRelocationOffset(),
- CallSiteInfo.Header.CodeOffset, &LinkageName);
+ ObjDelegate->printRelocatedField("CodeOffset",
+ CallSiteInfo.getRelocationOffset(),
+ CallSiteInfo.CodeOffset, &LinkageName);
}
- W.printHex("Segment", CallSiteInfo.Header.Segment);
- W.printHex("Reserved", CallSiteInfo.Header.Reserved);
- CVTD.printTypeIndex("Type", CallSiteInfo.Header.Type);
+ W.printHex("Segment", CallSiteInfo.Segment);
+ printTypeIndex("Type", CallSiteInfo.Type);
if (!LinkageName.empty())
W.printString("LinkageName", LinkageName);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitEnvBlockSym(SymbolKind Kind,
- EnvBlockSym &EnvBlock) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+ EnvBlockSym &EnvBlock) {
DictScope S(W, "EnvBlock");
- W.printNumber("Reserved", EnvBlock.Header.Reserved);
ListScope L(W, "Entries");
for (auto Entry : EnvBlock.Fields) {
W.printString(Entry);
}
+ return Error::success();
}
-void CVSymbolDumperImpl::visitFileStaticSym(SymbolKind Kind,
- FileStaticSym &FileStatic) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+ FileStaticSym &FileStatic) {
DictScope S(W, "FileStatic");
- W.printNumber("Index", FileStatic.Header.Index);
- W.printNumber("ModFilenameOffset", FileStatic.Header.ModFilenameOffset);
- W.printFlags("Flags", uint16_t(FileStatic.Header.Flags), getLocalFlagNames());
+ W.printNumber("Index", FileStatic.Index);
+ W.printNumber("ModFilenameOffset", FileStatic.ModFilenameOffset);
+ W.printFlags("Flags", uint16_t(FileStatic.Flags), getLocalFlagNames());
W.printString("Name", FileStatic.Name);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitExportSym(SymbolKind Kind, ExportSym &Export) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ExportSym &Export) {
DictScope S(W, "Export");
- W.printNumber("Ordinal", Export.Header.Ordinal);
- W.printFlags("Flags", Export.Header.Flags, getExportSymFlagNames());
+ W.printNumber("Ordinal", Export.Ordinal);
+ W.printFlags("Flags", uint16_t(Export.Flags), getExportSymFlagNames());
W.printString("Name", Export.Name);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitCompile2Sym(SymbolKind Kind,
- Compile2Sym &Compile2) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+ Compile2Sym &Compile2) {
DictScope S(W, "CompilerFlags2");
- W.printEnum("Language", Compile2.Header.getLanguage(),
- getSourceLanguageNames());
- W.printFlags("Flags", Compile2.Header.flags & ~0xff,
- getCompileSym2FlagNames());
- W.printEnum("Machine", unsigned(Compile2.Header.Machine), getCPUTypeNames());
+ W.printEnum("Language", Compile2.getLanguage(), getSourceLanguageNames());
+ W.printFlags("Flags", Compile2.getFlags(), getCompileSym2FlagNames());
+ W.printEnum("Machine", unsigned(Compile2.Machine), getCPUTypeNames());
std::string FrontendVersion;
{
raw_string_ostream Out(FrontendVersion);
- Out << Compile2.Header.VersionFrontendMajor << '.'
- << Compile2.Header.VersionFrontendMinor << '.'
- << Compile2.Header.VersionFrontendBuild;
+ Out << Compile2.VersionFrontendMajor << '.' << Compile2.VersionFrontendMinor
+ << '.' << Compile2.VersionFrontendBuild;
}
std::string BackendVersion;
{
raw_string_ostream Out(BackendVersion);
- Out << Compile2.Header.VersionBackendMajor << '.'
- << Compile2.Header.VersionBackendMinor << '.'
- << Compile2.Header.VersionBackendBuild;
+ Out << Compile2.VersionBackendMajor << '.' << Compile2.VersionBackendMinor
+ << '.' << Compile2.VersionBackendBuild;
}
W.printString("FrontendVersion", FrontendVersion);
W.printString("BackendVersion", BackendVersion);
W.printString("VersionName", Compile2.Version);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitCompile3Sym(SymbolKind Kind,
- Compile3Sym &Compile3) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+ Compile3Sym &Compile3) {
DictScope S(W, "CompilerFlags3");
- W.printEnum("Language", Compile3.Header.getLanguage(),
- getSourceLanguageNames());
- W.printFlags("Flags", Compile3.Header.flags & ~0xff,
- getCompileSym3FlagNames());
- W.printEnum("Machine", unsigned(Compile3.Header.Machine), getCPUTypeNames());
+ W.printEnum("Language", Compile3.getLanguage(), getSourceLanguageNames());
+ W.printFlags("Flags", Compile3.getFlags(), getCompileSym3FlagNames());
+ W.printEnum("Machine", unsigned(Compile3.Machine), getCPUTypeNames());
std::string FrontendVersion;
{
raw_string_ostream Out(FrontendVersion);
- Out << Compile3.Header.VersionFrontendMajor << '.'
- << Compile3.Header.VersionFrontendMinor << '.'
- << Compile3.Header.VersionFrontendBuild << '.'
- << Compile3.Header.VersionFrontendQFE;
+ Out << Compile3.VersionFrontendMajor << '.' << Compile3.VersionFrontendMinor
+ << '.' << Compile3.VersionFrontendBuild << '.'
+ << Compile3.VersionFrontendQFE;
}
std::string BackendVersion;
{
raw_string_ostream Out(BackendVersion);
- Out << Compile3.Header.VersionBackendMajor << '.'
- << Compile3.Header.VersionBackendMinor << '.'
- << Compile3.Header.VersionBackendBuild << '.'
- << Compile3.Header.VersionBackendQFE;
+ Out << Compile3.VersionBackendMajor << '.' << Compile3.VersionBackendMinor
+ << '.' << Compile3.VersionBackendBuild << '.'
+ << Compile3.VersionBackendQFE;
}
W.printString("FrontendVersion", FrontendVersion);
W.printString("BackendVersion", BackendVersion);
W.printString("VersionName", Compile3.Version);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitConstantSym(SymbolKind Kind,
- ConstantSym &Constant) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+ ConstantSym &Constant) {
DictScope S(W, "Constant");
- CVTD.printTypeIndex("Type", Constant.Header.Type);
+ printTypeIndex("Type", Constant.Type);
W.printNumber("Value", Constant.Value);
W.printString("Name", Constant.Name);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitDataSym(SymbolKind Kind, DataSym &Data) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, DataSym &Data) {
DictScope S(W, "DataSym");
- W.printEnum("Kind", uint16_t(Kind), getSymbolTypeNames());
+ W.printEnum("Kind", uint16_t(CVR.kind()), getSymbolTypeNames());
StringRef LinkageName;
if (ObjDelegate) {
ObjDelegate->printRelocatedField("DataOffset", Data.getRelocationOffset(),
- Data.Header.DataOffset, &LinkageName);
+ Data.DataOffset, &LinkageName);
}
- CVTD.printTypeIndex("Type", Data.Header.Type);
+ printTypeIndex("Type", Data.Type);
W.printString("DisplayName", Data.Name);
if (!LinkageName.empty())
W.printString("LinkageName", LinkageName);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitDefRangeFramePointerRelFullScopeSym(
- SymbolKind Kind,
+Error CVSymbolDumperImpl::visitKnownRecord(
+ CVSymbol &CVR,
DefRangeFramePointerRelFullScopeSym &DefRangeFramePointerRelFullScope) {
DictScope S(W, "DefRangeFramePointerRelFullScope");
- W.printNumber("Offset", DefRangeFramePointerRelFullScope.Header.Offset);
+ W.printNumber("Offset", DefRangeFramePointerRelFullScope.Offset);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitDefRangeFramePointerRelSym(
- SymbolKind Kind, DefRangeFramePointerRelSym &DefRangeFramePointerRel) {
+Error CVSymbolDumperImpl::visitKnownRecord(
+ CVSymbol &CVR, DefRangeFramePointerRelSym &DefRangeFramePointerRel) {
DictScope S(W, "DefRangeFramePointerRel");
- W.printNumber("Offset", DefRangeFramePointerRel.Header.Offset);
- printLocalVariableAddrRange(DefRangeFramePointerRel.Header.Range,
+ W.printNumber("Offset", DefRangeFramePointerRel.Offset);
+ printLocalVariableAddrRange(DefRangeFramePointerRel.Range,
DefRangeFramePointerRel.getRelocationOffset());
printLocalVariableAddrGap(DefRangeFramePointerRel.Gaps);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitDefRangeRegisterRelSym(
- SymbolKind Kind, DefRangeRegisterRelSym &DefRangeRegisterRel) {
+Error CVSymbolDumperImpl::visitKnownRecord(
+ CVSymbol &CVR, DefRangeRegisterRelSym &DefRangeRegisterRel) {
DictScope S(W, "DefRangeRegisterRel");
- W.printNumber("BaseRegister", DefRangeRegisterRel.Header.BaseRegister);
+ W.printNumber("BaseRegister", DefRangeRegisterRel.Hdr.Register);
W.printBoolean("HasSpilledUDTMember",
DefRangeRegisterRel.hasSpilledUDTMember());
W.printNumber("OffsetInParent", DefRangeRegisterRel.offsetInParent());
- W.printNumber("BasePointerOffset",
- DefRangeRegisterRel.Header.BasePointerOffset);
- printLocalVariableAddrRange(DefRangeRegisterRel.Header.Range,
+ W.printNumber("BasePointerOffset", DefRangeRegisterRel.Hdr.BasePointerOffset);
+ printLocalVariableAddrRange(DefRangeRegisterRel.Range,
DefRangeRegisterRel.getRelocationOffset());
printLocalVariableAddrGap(DefRangeRegisterRel.Gaps);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitDefRangeRegisterSym(
- SymbolKind Kind, DefRangeRegisterSym &DefRangeRegister) {
+Error CVSymbolDumperImpl::visitKnownRecord(
+ CVSymbol &CVR, DefRangeRegisterSym &DefRangeRegister) {
DictScope S(W, "DefRangeRegister");
- W.printNumber("Register", DefRangeRegister.Header.Register);
- W.printNumber("MayHaveNoName", DefRangeRegister.Header.MayHaveNoName);
- printLocalVariableAddrRange(DefRangeRegister.Header.Range,
+ W.printNumber("Register", DefRangeRegister.Hdr.Register);
+ W.printNumber("MayHaveNoName", DefRangeRegister.Hdr.MayHaveNoName);
+ printLocalVariableAddrRange(DefRangeRegister.Range,
DefRangeRegister.getRelocationOffset());
printLocalVariableAddrGap(DefRangeRegister.Gaps);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitDefRangeSubfieldRegisterSym(
- SymbolKind Kind, DefRangeSubfieldRegisterSym &DefRangeSubfieldRegister) {
+Error CVSymbolDumperImpl::visitKnownRecord(
+ CVSymbol &CVR, DefRangeSubfieldRegisterSym &DefRangeSubfieldRegister) {
DictScope S(W, "DefRangeSubfieldRegister");
- W.printNumber("Register", DefRangeSubfieldRegister.Header.Register);
- W.printNumber("MayHaveNoName", DefRangeSubfieldRegister.Header.MayHaveNoName);
- W.printNumber("OffsetInParent",
- DefRangeSubfieldRegister.Header.OffsetInParent);
- printLocalVariableAddrRange(DefRangeSubfieldRegister.Header.Range,
+ W.printNumber("Register", DefRangeSubfieldRegister.Hdr.Register);
+ W.printNumber("MayHaveNoName", DefRangeSubfieldRegister.Hdr.MayHaveNoName);
+ W.printNumber("OffsetInParent", DefRangeSubfieldRegister.Hdr.OffsetInParent);
+ printLocalVariableAddrRange(DefRangeSubfieldRegister.Range,
DefRangeSubfieldRegister.getRelocationOffset());
printLocalVariableAddrGap(DefRangeSubfieldRegister.Gaps);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitDefRangeSubfieldSym(
- SymbolKind Kind, DefRangeSubfieldSym &DefRangeSubfield) {
+Error CVSymbolDumperImpl::visitKnownRecord(
+ CVSymbol &CVR, DefRangeSubfieldSym &DefRangeSubfield) {
DictScope S(W, "DefRangeSubfield");
if (ObjDelegate) {
StringRef StringTable = ObjDelegate->getStringTable();
- auto ProgramStringTableOffset = DefRangeSubfield.Header.Program;
+ auto ProgramStringTableOffset = DefRangeSubfield.Program;
if (ProgramStringTableOffset >= StringTable.size())
- return parseError();
+ return llvm::make_error<CodeViewError>(
+ "String table offset outside of bounds of String Table!");
StringRef Program =
StringTable.drop_front(ProgramStringTableOffset).split('\0').first;
W.printString("Program", Program);
}
- W.printNumber("OffsetInParent", DefRangeSubfield.Header.OffsetInParent);
- printLocalVariableAddrRange(DefRangeSubfield.Header.Range,
+ W.printNumber("OffsetInParent", DefRangeSubfield.OffsetInParent);
+ printLocalVariableAddrRange(DefRangeSubfield.Range,
DefRangeSubfield.getRelocationOffset());
printLocalVariableAddrGap(DefRangeSubfield.Gaps);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitDefRangeSym(SymbolKind Kind,
- DefRangeSym &DefRange) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+ DefRangeSym &DefRange) {
DictScope S(W, "DefRange");
if (ObjDelegate) {
StringRef StringTable = ObjDelegate->getStringTable();
- auto ProgramStringTableOffset = DefRange.Header.Program;
+ auto ProgramStringTableOffset = DefRange.Program;
if (ProgramStringTableOffset >= StringTable.size())
- return parseError();
+ return llvm::make_error<CodeViewError>(
+ "String table offset outside of bounds of String Table!");
StringRef Program =
StringTable.drop_front(ProgramStringTableOffset).split('\0').first;
W.printString("Program", Program);
}
- printLocalVariableAddrRange(DefRange.Header.Range,
- DefRange.getRelocationOffset());
+ printLocalVariableAddrRange(DefRange.Range, DefRange.getRelocationOffset());
printLocalVariableAddrGap(DefRange.Gaps);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitFrameCookieSym(SymbolKind Kind,
- FrameCookieSym &FrameCookie) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+ FrameCookieSym &FrameCookie) {
DictScope S(W, "FrameCookie");
StringRef LinkageName;
if (ObjDelegate) {
- ObjDelegate->printRelocatedField(
- "CodeOffset", FrameCookie.getRelocationOffset(),
- FrameCookie.Header.CodeOffset, &LinkageName);
+ ObjDelegate->printRelocatedField("CodeOffset",
+ FrameCookie.getRelocationOffset(),
+ FrameCookie.CodeOffset, &LinkageName);
}
- W.printHex("Register", FrameCookie.Header.Register);
- W.printEnum("CookieKind", uint16_t(FrameCookie.Header.CookieKind),
+ W.printHex("Register", FrameCookie.Register);
+ W.printEnum("CookieKind", uint16_t(FrameCookie.CookieKind),
getFrameCookieKindNames());
- W.printHex("Flags", FrameCookie.Header.Flags);
+ W.printHex("Flags", FrameCookie.Flags);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitFrameProcSym(SymbolKind Kind,
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
FrameProcSym &FrameProc) {
DictScope S(W, "FrameProc");
- W.printHex("TotalFrameBytes", FrameProc.Header.TotalFrameBytes);
- W.printHex("PaddingFrameBytes", FrameProc.Header.PaddingFrameBytes);
- W.printHex("OffsetToPadding", FrameProc.Header.OffsetToPadding);
+ W.printHex("TotalFrameBytes", FrameProc.TotalFrameBytes);
+ W.printHex("PaddingFrameBytes", FrameProc.PaddingFrameBytes);
+ W.printHex("OffsetToPadding", FrameProc.OffsetToPadding);
W.printHex("BytesOfCalleeSavedRegisters",
- FrameProc.Header.BytesOfCalleeSavedRegisters);
- W.printHex("OffsetOfExceptionHandler",
- FrameProc.Header.OffsetOfExceptionHandler);
+ FrameProc.BytesOfCalleeSavedRegisters);
+ W.printHex("OffsetOfExceptionHandler", FrameProc.OffsetOfExceptionHandler);
W.printHex("SectionIdOfExceptionHandler",
- FrameProc.Header.SectionIdOfExceptionHandler);
- W.printFlags("Flags", FrameProc.Header.Flags, getFrameProcSymFlagNames());
+ FrameProc.SectionIdOfExceptionHandler);
+ W.printFlags("Flags", static_cast<uint32_t>(FrameProc.Flags),
+ getFrameProcSymFlagNames());
+ return Error::success();
}
-void CVSymbolDumperImpl::visitHeapAllocationSiteSym(
- SymbolKind Kind, HeapAllocationSiteSym &HeapAllocSite) {
+Error CVSymbolDumperImpl::visitKnownRecord(
+ CVSymbol &CVR, HeapAllocationSiteSym &HeapAllocSite) {
DictScope S(W, "HeapAllocationSite");
StringRef LinkageName;
if (ObjDelegate) {
- ObjDelegate->printRelocatedField(
- "CodeOffset", HeapAllocSite.getRelocationOffset(),
- HeapAllocSite.Header.CodeOffset, &LinkageName);
+ ObjDelegate->printRelocatedField("CodeOffset",
+ HeapAllocSite.getRelocationOffset(),
+ HeapAllocSite.CodeOffset, &LinkageName);
}
- W.printHex("Segment", HeapAllocSite.Header.Segment);
- W.printHex("CallInstructionSize", HeapAllocSite.Header.CallInstructionSize);
- CVTD.printTypeIndex("Type", HeapAllocSite.Header.Type);
+ W.printHex("Segment", HeapAllocSite.Segment);
+ W.printHex("CallInstructionSize", HeapAllocSite.CallInstructionSize);
+ printTypeIndex("Type", HeapAllocSite.Type);
if (!LinkageName.empty())
W.printString("LinkageName", LinkageName);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitInlineSiteSym(SymbolKind Kind,
- InlineSiteSym &InlineSite) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+ InlineSiteSym &InlineSite) {
DictScope S(W, "InlineSite");
- W.printHex("PtrParent", InlineSite.Header.PtrParent);
- W.printHex("PtrEnd", InlineSite.Header.PtrEnd);
- CVTD.printTypeIndex("Inlinee", InlineSite.Header.Inlinee);
+ W.printHex("PtrParent", InlineSite.Parent);
+ W.printHex("PtrEnd", InlineSite.End);
+ printTypeIndex("Inlinee", InlineSite.Inlinee);
ListScope BinaryAnnotations(W, "BinaryAnnotations");
for (auto &Annotation : InlineSite.annotations()) {
switch (Annotation.OpCode) {
case BinaryAnnotationsOpCode::Invalid:
- return parseError();
+ return llvm::make_error<CodeViewError>(
+ "Invalid binary annotation opcode!");
case BinaryAnnotationsOpCode::CodeOffset:
case BinaryAnnotationsOpCode::ChangeCodeOffset:
case BinaryAnnotationsOpCode::ChangeCodeLength:
@@ -486,157 +510,180 @@ void CVSymbolDumperImpl::visitInlineSiteSym(SymbolKind Kind,
}
}
}
+ return Error::success();
}
-void CVSymbolDumperImpl::visitRegisterSym(SymbolKind Kind,
- RegisterSym &Register) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+ RegisterSym &Register) {
DictScope S(W, "RegisterSym");
- W.printNumber("Type", Register.Header.Index);
- W.printEnum("Seg", uint16_t(Register.Header.Register), getRegisterNames());
+ W.printNumber("Type", Register.Index);
+ W.printEnum("Seg", uint16_t(Register.Register), getRegisterNames());
W.printString("Name", Register.Name);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitPublicSym32(SymbolKind Kind,
- PublicSym32 &Public) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, PublicSym32 &Public) {
DictScope S(W, "PublicSym");
- W.printNumber("Type", Public.Header.Index);
- W.printNumber("Seg", Public.Header.Seg);
- W.printNumber("Off", Public.Header.Off);
+ W.printNumber("Type", Public.Index);
+ W.printNumber("Seg", Public.Segment);
+ W.printNumber("Off", Public.Offset);
W.printString("Name", Public.Name);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitProcRefSym(SymbolKind Kind, ProcRefSym &ProcRef) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ProcRefSym &ProcRef) {
DictScope S(W, "ProcRef");
- W.printNumber("SumName", ProcRef.Header.SumName);
- W.printNumber("SymOffset", ProcRef.Header.SymOffset);
- W.printNumber("Mod", ProcRef.Header.Mod);
+ W.printNumber("SumName", ProcRef.SumName);
+ W.printNumber("SymOffset", ProcRef.SymOffset);
+ W.printNumber("Mod", ProcRef.Module);
W.printString("Name", ProcRef.Name);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitLabelSym(SymbolKind Kind, LabelSym &Label) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, LabelSym &Label) {
DictScope S(W, "Label");
StringRef LinkageName;
if (ObjDelegate) {
ObjDelegate->printRelocatedField("CodeOffset", Label.getRelocationOffset(),
- Label.Header.CodeOffset, &LinkageName);
+ Label.CodeOffset, &LinkageName);
}
- W.printHex("Segment", Label.Header.Segment);
- W.printHex("Flags", Label.Header.Flags);
- W.printFlags("Flags", Label.Header.Flags, getProcSymFlagNames());
+ W.printHex("Segment", Label.Segment);
+ W.printHex("Flags", uint8_t(Label.Flags));
+ W.printFlags("Flags", uint8_t(Label.Flags), getProcSymFlagNames());
W.printString("DisplayName", Label.Name);
if (!LinkageName.empty())
W.printString("LinkageName", LinkageName);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitLocalSym(SymbolKind Kind, LocalSym &Local) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, LocalSym &Local) {
DictScope S(W, "Local");
- CVTD.printTypeIndex("Type", Local.Header.Type);
- W.printFlags("Flags", uint16_t(Local.Header.Flags), getLocalFlagNames());
+ printTypeIndex("Type", Local.Type);
+ W.printFlags("Flags", uint16_t(Local.Flags), getLocalFlagNames());
W.printString("VarName", Local.Name);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitObjNameSym(SymbolKind Kind, ObjNameSym &ObjName) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ObjNameSym &ObjName) {
DictScope S(W, "ObjectName");
- W.printHex("Signature", ObjName.Header.Signature);
+ W.printHex("Signature", ObjName.Signature);
W.printString("ObjectName", ObjName.Name);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitProcSym(SymbolKind Kind, ProcSym &Proc) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ProcSym &Proc) {
DictScope S(W, "ProcStart");
if (InFunctionScope)
- return parseError();
+ return llvm::make_error<CodeViewError>(
+ "Visiting a ProcSym while inside function scope!");
InFunctionScope = true;
StringRef LinkageName;
- W.printEnum("Kind", uint16_t(Kind), getSymbolTypeNames());
- W.printHex("PtrParent", Proc.Header.PtrParent);
- W.printHex("PtrEnd", Proc.Header.PtrEnd);
- W.printHex("PtrNext", Proc.Header.PtrNext);
- W.printHex("CodeSize", Proc.Header.CodeSize);
- W.printHex("DbgStart", Proc.Header.DbgStart);
- W.printHex("DbgEnd", Proc.Header.DbgEnd);
- CVTD.printTypeIndex("FunctionType", Proc.Header.FunctionType);
+ W.printEnum("Kind", uint16_t(CVR.kind()), getSymbolTypeNames());
+ W.printHex("PtrParent", Proc.Parent);
+ W.printHex("PtrEnd", Proc.End);
+ W.printHex("PtrNext", Proc.Next);
+ W.printHex("CodeSize", Proc.CodeSize);
+ W.printHex("DbgStart", Proc.DbgStart);
+ W.printHex("DbgEnd", Proc.DbgEnd);
+ printTypeIndex("FunctionType", Proc.FunctionType);
if (ObjDelegate) {
ObjDelegate->printRelocatedField("CodeOffset", Proc.getRelocationOffset(),
- Proc.Header.CodeOffset, &LinkageName);
+ Proc.CodeOffset, &LinkageName);
}
- W.printHex("Segment", Proc.Header.Segment);
- W.printFlags("Flags", static_cast<uint8_t>(Proc.Header.Flags),
+ W.printHex("Segment", Proc.Segment);
+ W.printFlags("Flags", static_cast<uint8_t>(Proc.Flags),
getProcSymFlagNames());
W.printString("DisplayName", Proc.Name);
if (!LinkageName.empty())
W.printString("LinkageName", LinkageName);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitScopeEndSym(SymbolKind Kind,
- ScopeEndSym &ScopeEnd) {
- if (Kind == SymbolKind::S_END)
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+ ScopeEndSym &ScopeEnd) {
+ if (CVR.kind() == SymbolKind::S_END)
DictScope S(W, "BlockEnd");
- else if (Kind == SymbolKind::S_PROC_ID_END)
+ else if (CVR.kind() == SymbolKind::S_PROC_ID_END)
DictScope S(W, "ProcEnd");
- else if (Kind == SymbolKind::S_INLINESITE_END)
+ else if (CVR.kind() == SymbolKind::S_INLINESITE_END)
DictScope S(W, "InlineSiteEnd");
InFunctionScope = false;
+ return Error::success();
}
-void CVSymbolDumperImpl::visitCallerSym(SymbolKind Kind, CallerSym &Caller) {
- ListScope S(W, Kind == S_CALLEES ? "Callees" : "Callers");
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, CallerSym &Caller) {
+ ListScope S(W, CVR.kind() == S_CALLEES ? "Callees" : "Callers");
for (auto FuncID : Caller.Indices)
- CVTD.printTypeIndex("FuncID", FuncID);
+ printTypeIndex("FuncID", FuncID);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitRegRelativeSym(SymbolKind Kind,
- RegRelativeSym &RegRel) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+ RegRelativeSym &RegRel) {
DictScope S(W, "RegRelativeSym");
- W.printHex("Offset", RegRel.Header.Offset);
- CVTD.printTypeIndex("Type", RegRel.Header.Type);
- W.printHex("Register", RegRel.Header.Register);
+ W.printHex("Offset", RegRel.Offset);
+ printTypeIndex("Type", RegRel.Type);
+ W.printHex("Register", RegRel.Register);
W.printString("VarName", RegRel.Name);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitThreadLocalDataSym(SymbolKind Kind,
- ThreadLocalDataSym &Data) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+ ThreadLocalDataSym &Data) {
DictScope S(W, "ThreadLocalDataSym");
StringRef LinkageName;
if (ObjDelegate) {
ObjDelegate->printRelocatedField("DataOffset", Data.getRelocationOffset(),
- Data.Header.DataOffset, &LinkageName);
+ Data.DataOffset, &LinkageName);
}
- CVTD.printTypeIndex("Type", Data.Header.Type);
+ printTypeIndex("Type", Data.Type);
W.printString("DisplayName", Data.Name);
if (!LinkageName.empty())
W.printString("LinkageName", LinkageName);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitUDTSym(SymbolKind Kind, UDTSym &UDT) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, UDTSym &UDT) {
DictScope S(W, "UDT");
- CVTD.printTypeIndex("Type", UDT.Header.Type);
+ printTypeIndex("Type", UDT.Type);
W.printString("UDTName", UDT.Name);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitUnknownSymbol(SymbolKind Kind,
- ArrayRef<uint8_t> Data) {
+Error CVSymbolDumperImpl::visitUnknownSymbol(CVSymbol &CVR) {
DictScope S(W, "UnknownSym");
- W.printEnum("Kind", uint16_t(Kind), getSymbolTypeNames());
- W.printNumber("Length", uint32_t(Data.size()));
+ W.printEnum("Kind", uint16_t(CVR.kind()), getSymbolTypeNames());
+ W.printNumber("Length", CVR.length());
+ return Error::success();
}
-bool CVSymbolDumper::dump(const CVRecord<SymbolKind> &Record) {
- CVSymbolDumperImpl Dumper(CVTD, ObjDelegate.get(), W, PrintRecordBytes);
- Dumper.visitSymbolRecord(Record);
- return !Dumper.hadError();
+Error CVSymbolDumper::dump(CVRecord<SymbolKind> &Record) {
+ SymbolVisitorCallbackPipeline Pipeline;
+ SymbolDeserializer Deserializer(ObjDelegate.get());
+ CVSymbolDumperImpl Dumper(TypeDB, ObjDelegate.get(), W, PrintRecordBytes);
+
+ Pipeline.addCallbackToPipeline(Deserializer);
+ Pipeline.addCallbackToPipeline(Dumper);
+ CVSymbolVisitor Visitor(Pipeline);
+ return Visitor.visitSymbolRecord(Record);
}
-bool CVSymbolDumper::dump(const CVSymbolArray &Symbols) {
- CVSymbolDumperImpl Dumper(CVTD, ObjDelegate.get(), W, PrintRecordBytes);
- Dumper.visitSymbolStream(Symbols);
- return !Dumper.hadError();
+Error CVSymbolDumper::dump(const CVSymbolArray &Symbols) {
+ SymbolVisitorCallbackPipeline Pipeline;
+ SymbolDeserializer Deserializer(ObjDelegate.get());
+ CVSymbolDumperImpl Dumper(TypeDB, ObjDelegate.get(), W, PrintRecordBytes);
+
+ Pipeline.addCallbackToPipeline(Deserializer);
+ Pipeline.addCallbackToPipeline(Dumper);
+ CVSymbolVisitor Visitor(Pipeline);
+ return Visitor.visitSymbolStream(Symbols);
}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp b/contrib/llvm/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp
new file mode 100644
index 0000000..bb17314
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp
@@ -0,0 +1,464 @@
+//===- SymbolRecordMapping.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/SymbolRecordMapping.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+#define error(X) \
+ if (auto EC = X) \
+ return EC;
+
+namespace {
+struct MapGap {
+ Error operator()(CodeViewRecordIO &IO, LocalVariableAddrGap &Gap) const {
+ error(IO.mapInteger(Gap.GapStartOffset));
+ error(IO.mapInteger(Gap.Range));
+ return Error::success();
+ }
+};
+}
+
+static Error mapLocalVariableAddrRange(CodeViewRecordIO &IO,
+ LocalVariableAddrRange &Range) {
+ error(IO.mapInteger(Range.OffsetStart));
+ error(IO.mapInteger(Range.ISectStart));
+ error(IO.mapInteger(Range.Range));
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitSymbolBegin(CVSymbol &Record) {
+ error(IO.beginRecord(MaxRecordLength - sizeof(RecordPrefix)));
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitSymbolEnd(CVSymbol &Record) {
+ error(IO.endRecord());
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, BlockSym &Block) {
+
+ error(IO.mapInteger(Block.Parent));
+ error(IO.mapInteger(Block.End));
+ error(IO.mapInteger(Block.CodeSize));
+ error(IO.mapInteger(Block.CodeOffset));
+ error(IO.mapInteger(Block.Segment));
+ error(IO.mapStringZ(Block.Name));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, Thunk32Sym &Thunk) {
+
+ error(IO.mapInteger(Thunk.Parent));
+ error(IO.mapInteger(Thunk.End));
+ error(IO.mapInteger(Thunk.Next));
+ error(IO.mapInteger(Thunk.Offset));
+ error(IO.mapInteger(Thunk.Segment));
+ error(IO.mapInteger(Thunk.Length));
+ error(IO.mapEnum(Thunk.Thunk));
+ error(IO.mapStringZ(Thunk.Name));
+ error(IO.mapByteVectorTail(Thunk.VariantData));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ TrampolineSym &Tramp) {
+
+ error(IO.mapEnum(Tramp.Type));
+ error(IO.mapInteger(Tramp.Size));
+ error(IO.mapInteger(Tramp.ThunkOffset));
+ error(IO.mapInteger(Tramp.TargetOffset));
+ error(IO.mapInteger(Tramp.ThunkSection));
+ error(IO.mapInteger(Tramp.TargetSection));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ SectionSym &Section) {
+ uint8_t Padding = 0;
+
+ error(IO.mapInteger(Section.SectionNumber));
+ error(IO.mapInteger(Section.Alignment));
+ error(IO.mapInteger(Padding));
+ error(IO.mapInteger(Section.Rva));
+ error(IO.mapInteger(Section.Length));
+ error(IO.mapInteger(Section.Characteristics));
+ error(IO.mapStringZ(Section.Name));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ CoffGroupSym &CoffGroup) {
+
+ error(IO.mapInteger(CoffGroup.Size));
+ error(IO.mapInteger(CoffGroup.Characteristics));
+ error(IO.mapInteger(CoffGroup.Offset));
+ error(IO.mapInteger(CoffGroup.Segment));
+ error(IO.mapStringZ(CoffGroup.Name));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ BPRelativeSym &BPRel) {
+
+ error(IO.mapInteger(BPRel.Offset));
+ error(IO.mapInteger(BPRel.Type));
+ error(IO.mapStringZ(BPRel.Name));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ BuildInfoSym &BuildInfo) {
+
+ error(IO.mapInteger(BuildInfo.BuildId));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ CallSiteInfoSym &CallSiteInfo) {
+ uint16_t Padding = 0;
+
+ error(IO.mapInteger(CallSiteInfo.CodeOffset));
+ error(IO.mapInteger(CallSiteInfo.Segment));
+ error(IO.mapInteger(Padding));
+ error(IO.mapInteger(CallSiteInfo.Type));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ EnvBlockSym &EnvBlock) {
+
+ uint8_t Reserved = 0;
+ error(IO.mapInteger(Reserved));
+ error(IO.mapStringZVectorZ(EnvBlock.Fields));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ FileStaticSym &FileStatic) {
+
+ error(IO.mapInteger(FileStatic.Index));
+ error(IO.mapInteger(FileStatic.ModFilenameOffset));
+ error(IO.mapEnum(FileStatic.Flags));
+ error(IO.mapStringZ(FileStatic.Name));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, ExportSym &Export) {
+
+ error(IO.mapInteger(Export.Ordinal));
+ error(IO.mapEnum(Export.Flags));
+ error(IO.mapStringZ(Export.Name));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ Compile2Sym &Compile2) {
+
+ error(IO.mapEnum(Compile2.Flags));
+ error(IO.mapEnum(Compile2.Machine));
+ error(IO.mapInteger(Compile2.VersionFrontendMajor));
+ error(IO.mapInteger(Compile2.VersionFrontendMinor));
+ error(IO.mapInteger(Compile2.VersionFrontendBuild));
+ error(IO.mapInteger(Compile2.VersionBackendMajor));
+ error(IO.mapInteger(Compile2.VersionBackendMinor));
+ error(IO.mapInteger(Compile2.VersionBackendBuild));
+ error(IO.mapStringZ(Compile2.Version));
+ error(IO.mapStringZVectorZ(Compile2.ExtraStrings));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ Compile3Sym &Compile3) {
+
+ error(IO.mapEnum(Compile3.Flags));
+ error(IO.mapEnum(Compile3.Machine));
+ error(IO.mapInteger(Compile3.VersionFrontendMajor));
+ error(IO.mapInteger(Compile3.VersionFrontendMinor));
+ error(IO.mapInteger(Compile3.VersionFrontendBuild));
+ error(IO.mapInteger(Compile3.VersionFrontendQFE));
+ error(IO.mapInteger(Compile3.VersionBackendMajor));
+ error(IO.mapInteger(Compile3.VersionBackendMinor));
+ error(IO.mapInteger(Compile3.VersionBackendBuild));
+ error(IO.mapInteger(Compile3.VersionBackendQFE));
+ error(IO.mapStringZ(Compile3.Version));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ ConstantSym &Constant) {
+
+ error(IO.mapInteger(Constant.Type));
+ error(IO.mapEncodedInteger(Constant.Value));
+ error(IO.mapStringZ(Constant.Name));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, DataSym &Data) {
+
+ error(IO.mapInteger(Data.Type));
+ error(IO.mapInteger(Data.DataOffset));
+ error(IO.mapInteger(Data.Segment));
+ error(IO.mapStringZ(Data.Name));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(
+ CVSymbol &CVR, DefRangeFramePointerRelSym &DefRangeFramePointerRel) {
+
+ error(IO.mapInteger(DefRangeFramePointerRel.Offset));
+ error(mapLocalVariableAddrRange(IO, DefRangeFramePointerRel.Range));
+ error(IO.mapVectorTail(DefRangeFramePointerRel.Gaps, MapGap()));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(
+ CVSymbol &CVR,
+ DefRangeFramePointerRelFullScopeSym &DefRangeFramePointerRelFullScope) {
+
+ error(IO.mapInteger(DefRangeFramePointerRelFullScope.Offset));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(
+ CVSymbol &CVR, DefRangeRegisterRelSym &DefRangeRegisterRel) {
+
+ error(IO.mapObject(DefRangeRegisterRel.Hdr.Register));
+ error(IO.mapObject(DefRangeRegisterRel.Hdr.Flags));
+ error(IO.mapObject(DefRangeRegisterRel.Hdr.BasePointerOffset));
+ error(mapLocalVariableAddrRange(IO, DefRangeRegisterRel.Range));
+ error(IO.mapVectorTail(DefRangeRegisterRel.Gaps, MapGap()));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(
+ CVSymbol &CVR, DefRangeRegisterSym &DefRangeRegister) {
+
+ error(IO.mapObject(DefRangeRegister.Hdr.Register));
+ error(IO.mapObject(DefRangeRegister.Hdr.MayHaveNoName));
+ error(mapLocalVariableAddrRange(IO, DefRangeRegister.Range));
+ error(IO.mapVectorTail(DefRangeRegister.Gaps, MapGap()));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(
+ CVSymbol &CVR, DefRangeSubfieldRegisterSym &DefRangeSubfieldRegister) {
+
+ error(IO.mapObject(DefRangeSubfieldRegister.Hdr.Register));
+ error(IO.mapObject(DefRangeSubfieldRegister.Hdr.MayHaveNoName));
+ error(IO.mapObject(DefRangeSubfieldRegister.Hdr.OffsetInParent));
+ error(mapLocalVariableAddrRange(IO, DefRangeSubfieldRegister.Range));
+ error(IO.mapVectorTail(DefRangeSubfieldRegister.Gaps, MapGap()));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(
+ CVSymbol &CVR, DefRangeSubfieldSym &DefRangeSubfield) {
+
+ error(IO.mapInteger(DefRangeSubfield.Program));
+ error(IO.mapInteger(DefRangeSubfield.OffsetInParent));
+ error(mapLocalVariableAddrRange(IO, DefRangeSubfield.Range));
+ error(IO.mapVectorTail(DefRangeSubfield.Gaps, MapGap()));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ DefRangeSym &DefRange) {
+
+ error(IO.mapInteger(DefRange.Program));
+ error(mapLocalVariableAddrRange(IO, DefRange.Range));
+ error(IO.mapVectorTail(DefRange.Gaps, MapGap()));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ FrameCookieSym &FrameCookie) {
+
+ error(IO.mapInteger(FrameCookie.CodeOffset));
+ error(IO.mapInteger(FrameCookie.Register));
+ error(IO.mapInteger(FrameCookie.CookieKind));
+ error(IO.mapInteger(FrameCookie.Flags));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ FrameProcSym &FrameProc) {
+ error(IO.mapInteger(FrameProc.TotalFrameBytes));
+ error(IO.mapInteger(FrameProc.PaddingFrameBytes));
+ error(IO.mapInteger(FrameProc.OffsetToPadding));
+ error(IO.mapInteger(FrameProc.BytesOfCalleeSavedRegisters));
+ error(IO.mapInteger(FrameProc.OffsetOfExceptionHandler));
+ error(IO.mapInteger(FrameProc.SectionIdOfExceptionHandler));
+ error(IO.mapEnum(FrameProc.Flags));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(
+ CVSymbol &CVR, HeapAllocationSiteSym &HeapAllocSite) {
+
+ error(IO.mapInteger(HeapAllocSite.CodeOffset));
+ error(IO.mapInteger(HeapAllocSite.Segment));
+ error(IO.mapInteger(HeapAllocSite.CallInstructionSize));
+ error(IO.mapInteger(HeapAllocSite.Type));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ InlineSiteSym &InlineSite) {
+
+ error(IO.mapInteger(InlineSite.Parent));
+ error(IO.mapInteger(InlineSite.End));
+ error(IO.mapInteger(InlineSite.Inlinee));
+ error(IO.mapByteVectorTail(InlineSite.AnnotationData));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ RegisterSym &Register) {
+
+ error(IO.mapInteger(Register.Index));
+ error(IO.mapEnum(Register.Register));
+ error(IO.mapStringZ(Register.Name));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ PublicSym32 &Public) {
+
+ error(IO.mapInteger(Public.Index));
+ error(IO.mapInteger(Public.Offset));
+ error(IO.mapInteger(Public.Segment));
+ error(IO.mapStringZ(Public.Name));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ ProcRefSym &ProcRef) {
+
+ error(IO.mapInteger(ProcRef.SumName));
+ error(IO.mapInteger(ProcRef.SymOffset));
+ error(IO.mapInteger(ProcRef.Module));
+ error(IO.mapStringZ(ProcRef.Name));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, LabelSym &Label) {
+
+ error(IO.mapInteger(Label.CodeOffset));
+ error(IO.mapInteger(Label.Segment));
+ error(IO.mapEnum(Label.Flags));
+ error(IO.mapStringZ(Label.Name));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, LocalSym &Local) {
+ error(IO.mapInteger(Local.Type));
+ error(IO.mapEnum(Local.Flags));
+ error(IO.mapStringZ(Local.Name));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ ObjNameSym &ObjName) {
+
+ error(IO.mapInteger(ObjName.Signature));
+ error(IO.mapStringZ(ObjName.Name));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, ProcSym &Proc) {
+ error(IO.mapInteger(Proc.Parent));
+ error(IO.mapInteger(Proc.End));
+ error(IO.mapInteger(Proc.Next));
+ error(IO.mapInteger(Proc.CodeSize));
+ error(IO.mapInteger(Proc.DbgStart));
+ error(IO.mapInteger(Proc.DbgEnd));
+ error(IO.mapInteger(Proc.FunctionType));
+ error(IO.mapInteger(Proc.CodeOffset));
+ error(IO.mapInteger(Proc.Segment));
+ error(IO.mapEnum(Proc.Flags));
+ error(IO.mapStringZ(Proc.Name));
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ ScopeEndSym &ScopeEnd) {
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, CallerSym &Caller) {
+ error(IO.mapVectorN<uint32_t>(
+ Caller.Indices,
+ [](CodeViewRecordIO &IO, TypeIndex &N) { return IO.mapInteger(N); }));
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ RegRelativeSym &RegRel) {
+
+ error(IO.mapInteger(RegRel.Offset));
+ error(IO.mapInteger(RegRel.Type));
+ error(IO.mapInteger(RegRel.Register));
+ error(IO.mapStringZ(RegRel.Name));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ ThreadLocalDataSym &Data) {
+
+ error(IO.mapInteger(Data.Type));
+ error(IO.mapInteger(Data.DataOffset));
+ error(IO.mapInteger(Data.Segment));
+ error(IO.mapStringZ(Data.Name));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, UDTSym &UDT) {
+
+ error(IO.mapInteger(UDT.Type));
+ error(IO.mapStringZ(UDT.Name));
+
+ return Error::success();
+}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/TypeDatabase.cpp b/contrib/llvm/lib/DebugInfo/CodeView/TypeDatabase.cpp
new file mode 100644
index 0000000..c7f7255
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/CodeView/TypeDatabase.cpp
@@ -0,0 +1,114 @@
+//===- TypeDatabase.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/TypeDatabase.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+namespace {
+struct SimpleTypeEntry {
+ StringRef Name;
+ SimpleTypeKind Kind;
+};
+}
+
+/// The names here all end in "*". If the simple type is a pointer type, we
+/// return the whole name. Otherwise we lop off the last character in our
+/// StringRef.
+static const SimpleTypeEntry SimpleTypeNames[] = {
+ {"void*", SimpleTypeKind::Void},
+ {"<not translated>*", SimpleTypeKind::NotTranslated},
+ {"HRESULT*", SimpleTypeKind::HResult},
+ {"signed char*", SimpleTypeKind::SignedCharacter},
+ {"unsigned char*", SimpleTypeKind::UnsignedCharacter},
+ {"char*", SimpleTypeKind::NarrowCharacter},
+ {"wchar_t*", SimpleTypeKind::WideCharacter},
+ {"char16_t*", SimpleTypeKind::Character16},
+ {"char32_t*", SimpleTypeKind::Character32},
+ {"__int8*", SimpleTypeKind::SByte},
+ {"unsigned __int8*", SimpleTypeKind::Byte},
+ {"short*", SimpleTypeKind::Int16Short},
+ {"unsigned short*", SimpleTypeKind::UInt16Short},
+ {"__int16*", SimpleTypeKind::Int16},
+ {"unsigned __int16*", SimpleTypeKind::UInt16},
+ {"long*", SimpleTypeKind::Int32Long},
+ {"unsigned long*", SimpleTypeKind::UInt32Long},
+ {"int*", SimpleTypeKind::Int32},
+ {"unsigned*", SimpleTypeKind::UInt32},
+ {"__int64*", SimpleTypeKind::Int64Quad},
+ {"unsigned __int64*", SimpleTypeKind::UInt64Quad},
+ {"__int64*", SimpleTypeKind::Int64},
+ {"unsigned __int64*", SimpleTypeKind::UInt64},
+ {"__int128*", SimpleTypeKind::Int128},
+ {"unsigned __int128*", SimpleTypeKind::UInt128},
+ {"__half*", SimpleTypeKind::Float16},
+ {"float*", SimpleTypeKind::Float32},
+ {"float*", SimpleTypeKind::Float32PartialPrecision},
+ {"__float48*", SimpleTypeKind::Float48},
+ {"double*", SimpleTypeKind::Float64},
+ {"long double*", SimpleTypeKind::Float80},
+ {"__float128*", SimpleTypeKind::Float128},
+ {"_Complex float*", SimpleTypeKind::Complex32},
+ {"_Complex double*", SimpleTypeKind::Complex64},
+ {"_Complex long double*", SimpleTypeKind::Complex80},
+ {"_Complex __float128*", SimpleTypeKind::Complex128},
+ {"bool*", SimpleTypeKind::Boolean8},
+ {"__bool16*", SimpleTypeKind::Boolean16},
+ {"__bool32*", SimpleTypeKind::Boolean32},
+ {"__bool64*", SimpleTypeKind::Boolean64},
+};
+
+/// Gets the type index for the next type record.
+TypeIndex TypeDatabase::getNextTypeIndex() const {
+ return TypeIndex(TypeIndex::FirstNonSimpleIndex + CVUDTNames.size());
+}
+
+/// Records the name of a type, and reserves its type index.
+void TypeDatabase::recordType(StringRef Name, CVType Data) {
+ CVUDTNames.push_back(Name);
+ TypeRecords.push_back(Data);
+}
+
+/// Saves the name in a StringSet and creates a stable StringRef.
+StringRef TypeDatabase::saveTypeName(StringRef TypeName) {
+ return TypeNameStorage.save(TypeName);
+}
+
+StringRef TypeDatabase::getTypeName(TypeIndex Index) const {
+ if (Index.isNoneType())
+ return "<no type>";
+
+ if (Index.isSimple()) {
+ // This is a simple type.
+ for (const auto &SimpleTypeName : SimpleTypeNames) {
+ if (SimpleTypeName.Kind == Index.getSimpleKind()) {
+ if (Index.getSimpleMode() == SimpleTypeMode::Direct)
+ return SimpleTypeName.Name.drop_back(1);
+ // Otherwise, this is a pointer type. We gloss over the distinction
+ // between near, far, 64, 32, etc, and just give a pointer type.
+ return SimpleTypeName.Name;
+ }
+ }
+ return "<unknown simple type>";
+ }
+
+ uint32_t I = Index.getIndex() - TypeIndex::FirstNonSimpleIndex;
+ if (I < CVUDTNames.size())
+ return CVUDTNames[I];
+
+ return "<unknown UDT>";
+}
+
+bool TypeDatabase::containsTypeIndex(TypeIndex Index) const {
+ uint32_t I = Index.getIndex() - TypeIndex::FirstNonSimpleIndex;
+ return I < CVUDTNames.size();
+}
+
+uint32_t TypeDatabase::size() const { return CVUDTNames.size(); }
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/TypeDatabaseVisitor.cpp b/contrib/llvm/lib/DebugInfo/CodeView/TypeDatabaseVisitor.cpp
new file mode 100644
index 0000000..d9d5639
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/CodeView/TypeDatabaseVisitor.cpp
@@ -0,0 +1,289 @@
+//===- TypeDatabaseVisitor.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/TypeDatabaseVisitor.h"
+
+#include "llvm/ADT/SmallString.h"
+
+using namespace llvm;
+
+using namespace llvm::codeview;
+
+Error TypeDatabaseVisitor::visitTypeBegin(CVRecord<TypeLeafKind> &Record) {
+ assert(!IsInFieldList);
+ // Reset Name to the empty string. If the visitor sets it, we know it.
+ Name = "";
+
+ if (Record.Type == LF_FIELDLIST) {
+ // Record that we're in a field list so that members do not get assigned
+ // type indices.
+ IsInFieldList = true;
+ }
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitTypeEnd(CVType &CVR) {
+ if (CVR.Type == LF_FIELDLIST) {
+ assert(IsInFieldList);
+ IsInFieldList = false;
+ }
+ assert(!IsInFieldList);
+
+ // Record every type that is not a field list member, even if Name is empty.
+ // CVUDTNames is indexed by type index, and must have one entry for every
+ // type. Field list members are not recorded, and are only referenced by
+ // their containing field list record.
+ TypeDB.recordType(Name, CVR);
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitMemberBegin(CVMemberRecord &Record) {
+ assert(IsInFieldList);
+ // Reset Name to the empty string. If the visitor sets it, we know it.
+ Name = "";
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitMemberEnd(CVMemberRecord &Record) {
+ assert(IsInFieldList);
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR,
+ FieldListRecord &FieldList) {
+ Name = "<field list>";
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
+ StringIdRecord &String) {
+ // Put this in the database so it gets printed with LF_UDT_SRC_LINE.
+ Name = String.getString();
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, ArgListRecord &Args) {
+ auto Indices = Args.getIndices();
+ uint32_t Size = Indices.size();
+ SmallString<256> TypeName("(");
+ for (uint32_t I = 0; I < Size; ++I) {
+ StringRef ArgTypeName = TypeDB.getTypeName(Indices[I]);
+ TypeName.append(ArgTypeName);
+ if (I + 1 != Size)
+ TypeName.append(", ");
+ }
+ TypeName.push_back(')');
+ Name = TypeDB.saveTypeName(TypeName);
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, ClassRecord &Class) {
+ Name = Class.getName();
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, UnionRecord &Union) {
+ Name = Union.getName();
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, EnumRecord &Enum) {
+ Name = Enum.getName();
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, ArrayRecord &AT) {
+ Name = AT.getName();
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, VFTableRecord &VFT) {
+ Name = VFT.getName();
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR,
+ MemberFuncIdRecord &Id) {
+ Name = Id.getName();
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR,
+ ProcedureRecord &Proc) {
+ StringRef ReturnTypeName = TypeDB.getTypeName(Proc.getReturnType());
+ StringRef ArgListTypeName = TypeDB.getTypeName(Proc.getArgumentList());
+ SmallString<256> TypeName(ReturnTypeName);
+ TypeName.push_back(' ');
+ TypeName.append(ArgListTypeName);
+ Name = TypeDB.saveTypeName(TypeName);
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR,
+ MemberFunctionRecord &MF) {
+ StringRef ReturnTypeName = TypeDB.getTypeName(MF.getReturnType());
+ StringRef ClassTypeName = TypeDB.getTypeName(MF.getClassType());
+ StringRef ArgListTypeName = TypeDB.getTypeName(MF.getArgumentList());
+ SmallString<256> TypeName(ReturnTypeName);
+ TypeName.push_back(' ');
+ TypeName.append(ClassTypeName);
+ TypeName.append("::");
+ TypeName.append(ArgListTypeName);
+ Name = TypeDB.saveTypeName(TypeName);
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, FuncIdRecord &Func) {
+ Name = Func.getName();
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR,
+ TypeServer2Record &TS) {
+ Name = TS.getName();
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) {
+
+ if (Ptr.isPointerToMember()) {
+ const MemberPointerInfo &MI = Ptr.getMemberInfo();
+
+ StringRef PointeeName = TypeDB.getTypeName(Ptr.getReferentType());
+ StringRef ClassName = TypeDB.getTypeName(MI.getContainingType());
+ SmallString<256> TypeName(PointeeName);
+ TypeName.push_back(' ');
+ TypeName.append(ClassName);
+ TypeName.append("::*");
+ Name = TypeDB.saveTypeName(TypeName);
+ } else {
+ SmallString<256> TypeName;
+ if (Ptr.isConst())
+ TypeName.append("const ");
+ if (Ptr.isVolatile())
+ TypeName.append("volatile ");
+ if (Ptr.isUnaligned())
+ TypeName.append("__unaligned ");
+
+ TypeName.append(TypeDB.getTypeName(Ptr.getReferentType()));
+
+ if (Ptr.getMode() == PointerMode::LValueReference)
+ TypeName.append("&");
+ else if (Ptr.getMode() == PointerMode::RValueReference)
+ TypeName.append("&&");
+ else if (Ptr.getMode() == PointerMode::Pointer)
+ TypeName.append("*");
+
+ if (!TypeName.empty())
+ Name = TypeDB.saveTypeName(TypeName);
+ }
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, ModifierRecord &Mod) {
+ uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers());
+
+ StringRef ModifiedName = TypeDB.getTypeName(Mod.getModifiedType());
+ SmallString<256> TypeName;
+ if (Mods & uint16_t(ModifierOptions::Const))
+ TypeName.append("const ");
+ if (Mods & uint16_t(ModifierOptions::Volatile))
+ TypeName.append("volatile ");
+ if (Mods & uint16_t(ModifierOptions::Unaligned))
+ TypeName.append("__unaligned ");
+ TypeName.append(ModifiedName);
+ Name = TypeDB.saveTypeName(TypeName);
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR,
+ VFTableShapeRecord &Shape) {
+ Name = TypeDB.saveTypeName("<vftable " + utostr(Shape.getEntryCount()) +
+ " methods>");
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR,
+ NestedTypeRecord &Nested) {
+ Name = Nested.getName();
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR,
+ OneMethodRecord &Method) {
+ Name = Method.getName();
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR,
+ OverloadedMethodRecord &Method) {
+ Name = Method.getName();
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR,
+ DataMemberRecord &Field) {
+ Name = Field.getName();
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR,
+ StaticDataMemberRecord &Field) {
+ Name = Field.getName();
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR,
+ EnumeratorRecord &Enum) {
+ Name = Enum.getName();
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR,
+ BaseClassRecord &Base) {
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR,
+ VirtualBaseClassRecord &VBase) {
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR,
+ ListContinuationRecord &Cont) {
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownRecord(
+ CVType &CVR, UdtModSourceLineRecord &ModSourceLine) {
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR,
+ UdtSourceLineRecord &SourceLine) {
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, BitFieldRecord &BF) {
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownRecord(
+ CVType &CVR, MethodOverloadListRecord &Overloads) {
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, BuildInfoRecord &BI) {
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR,
+ VFPtrRecord &VFP) {
+ return Error::success();
+}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp b/contrib/llvm/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp
index 345e2a49..033585b 100644
--- a/contrib/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp
+++ b/contrib/llvm/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp
@@ -1,4 +1,5 @@
-//===-- TypeDumper.cpp - CodeView type info dumper --------------*- C++ -*-===//
+//===-- TypeDumpVisitor.cpp - CodeView type info dumper -----------*- C++
+//-*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,63 +8,23 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/DebugInfo/CodeView/TypeDumper.h"
+#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
+
#include "llvm/ADT/SmallString.h"
+#include "llvm/DebugInfo/CodeView/CVTypeDumper.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
+#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
+#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
-#include "llvm/DebugInfo/CodeView/ByteStream.h"
+#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
+#include "llvm/DebugInfo/MSF/ByteStream.h"
#include "llvm/Support/ScopedPrinter.h"
using namespace llvm;
using namespace llvm::codeview;
-/// The names here all end in "*". If the simple type is a pointer type, we
-/// return the whole name. Otherwise we lop off the last character in our
-/// StringRef.
-static const EnumEntry<SimpleTypeKind> SimpleTypeNames[] = {
- {"void*", SimpleTypeKind::Void},
- {"<not translated>*", SimpleTypeKind::NotTranslated},
- {"HRESULT*", SimpleTypeKind::HResult},
- {"signed char*", SimpleTypeKind::SignedCharacter},
- {"unsigned char*", SimpleTypeKind::UnsignedCharacter},
- {"char*", SimpleTypeKind::NarrowCharacter},
- {"wchar_t*", SimpleTypeKind::WideCharacter},
- {"char16_t*", SimpleTypeKind::Character16},
- {"char32_t*", SimpleTypeKind::Character32},
- {"__int8*", SimpleTypeKind::SByte},
- {"unsigned __int8*", SimpleTypeKind::Byte},
- {"short*", SimpleTypeKind::Int16Short},
- {"unsigned short*", SimpleTypeKind::UInt16Short},
- {"__int16*", SimpleTypeKind::Int16},
- {"unsigned __int16*", SimpleTypeKind::UInt16},
- {"long*", SimpleTypeKind::Int32Long},
- {"unsigned long*", SimpleTypeKind::UInt32Long},
- {"int*", SimpleTypeKind::Int32},
- {"unsigned*", SimpleTypeKind::UInt32},
- {"__int64*", SimpleTypeKind::Int64Quad},
- {"unsigned __int64*", SimpleTypeKind::UInt64Quad},
- {"__int64*", SimpleTypeKind::Int64},
- {"unsigned __int64*", SimpleTypeKind::UInt64},
- {"__int128*", SimpleTypeKind::Int128},
- {"unsigned __int128*", SimpleTypeKind::UInt128},
- {"__half*", SimpleTypeKind::Float16},
- {"float*", SimpleTypeKind::Float32},
- {"float*", SimpleTypeKind::Float32PartialPrecision},
- {"__float48*", SimpleTypeKind::Float48},
- {"double*", SimpleTypeKind::Float64},
- {"long double*", SimpleTypeKind::Float80},
- {"__float128*", SimpleTypeKind::Float128},
- {"_Complex float*", SimpleTypeKind::Complex32},
- {"_Complex double*", SimpleTypeKind::Complex64},
- {"_Complex long double*", SimpleTypeKind::Complex80},
- {"_Complex __float128*", SimpleTypeKind::Complex128},
- {"bool*", SimpleTypeKind::Boolean8},
- {"__bool16*", SimpleTypeKind::Boolean16},
- {"__bool32*", SimpleTypeKind::Boolean32},
- {"__bool64*", SimpleTypeKind::Boolean64},
-};
-
static const EnumEntry<TypeLeafKind> LeafTypeNames[] = {
#define CV_TYPE(enum, val) {#enum, enum},
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
@@ -88,10 +49,8 @@ static const EnumEntry<uint16_t> ClassOptionNames[] = {
};
static const EnumEntry<uint8_t> MemberAccessNames[] = {
- ENUM_ENTRY(MemberAccess, None),
- ENUM_ENTRY(MemberAccess, Private),
- ENUM_ENTRY(MemberAccess, Protected),
- ENUM_ENTRY(MemberAccess, Public),
+ ENUM_ENTRY(MemberAccess, None), ENUM_ENTRY(MemberAccess, Private),
+ ENUM_ENTRY(MemberAccess, Protected), ENUM_ENTRY(MemberAccess, Public),
};
static const EnumEntry<uint16_t> MethodOptionNames[] = {
@@ -149,8 +108,7 @@ static const EnumEntry<uint16_t> PtrMemberRepNames[] = {
};
static const EnumEntry<uint16_t> TypeModifierNames[] = {
- ENUM_ENTRY(ModifierOptions, Const),
- ENUM_ENTRY(ModifierOptions, Volatile),
+ ENUM_ENTRY(ModifierOptions, Const), ENUM_ENTRY(ModifierOptions, Volatile),
ENUM_ENTRY(ModifierOptions, Unaligned),
};
@@ -195,34 +153,46 @@ static StringRef getLeafTypeName(TypeLeafKind LT) {
case ename: \
return #name;
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
- case LF_FIELDLIST:
- return "FieldList";
default:
break;
}
return "UnknownLeaf";
}
-Error CVTypeDumper::visitTypeBegin(const CVRecord<TypeLeafKind> &Record) {
- // Reset Name to the empty string. If the visitor sets it, we know it.
- Name = "";
+void TypeDumpVisitor::printTypeIndex(StringRef FieldName, TypeIndex TI) const {
+ CVTypeDumper::printTypeIndex(*W, FieldName, TI, TypeDB);
+}
- W->startLine() << getLeafTypeName(Record.Type) << " ("
- << HexNumber(getNextTypeIndex()) << ") {\n";
+Error TypeDumpVisitor::visitTypeBegin(CVType &Record) {
+ W->startLine() << getLeafTypeName(Record.Type);
+ W->getOStream() << " (" << HexNumber(TypeDB.getNextTypeIndex().getIndex())
+ << ")";
+ W->getOStream() << " {\n";
W->indent();
W->printEnum("TypeLeafKind", unsigned(Record.Type),
makeArrayRef(LeafTypeNames));
return Error::success();
}
-Error CVTypeDumper::visitTypeEnd(const CVRecord<TypeLeafKind> &Record) {
- if (Record.Type == LF_FIELDLIST)
- Name = "<field list>";
+Error TypeDumpVisitor::visitTypeEnd(CVType &Record) {
+ if (PrintRecordBytes)
+ W->printBinaryBlock("LeafData", getBytesAsCharacters(Record.content()));
- // Always record some name for every type, even if Name is empty. CVUDTNames
- // is indexed by type index, and must have one entry for every type.
- recordType(Name);
+ W->unindent();
+ W->startLine() << "}\n";
+ return Error::success();
+}
+Error TypeDumpVisitor::visitMemberBegin(CVMemberRecord &Record) {
+ W->startLine() << getLeafTypeName(Record.Kind);
+ W->getOStream() << " {\n";
+ W->indent();
+ W->printEnum("TypeLeafKind", unsigned(Record.Kind),
+ makeArrayRef(LeafTypeNames));
+ return Error::success();
+}
+
+Error TypeDumpVisitor::visitMemberEnd(CVMemberRecord &Record) {
if (PrintRecordBytes)
W->printBinaryBlock("LeafData", getBytesAsCharacters(Record.Data));
@@ -231,33 +201,33 @@ Error CVTypeDumper::visitTypeEnd(const CVRecord<TypeLeafKind> &Record) {
return Error::success();
}
-Error CVTypeDumper::visitStringId(StringIdRecord &String) {
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ FieldListRecord &FieldList) {
+ CVTypeVisitor Visitor(*this);
+ if (auto EC = Visitor.visitFieldListMemberStream(FieldList.Data))
+ return EC;
+
+ return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &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.
- Name = String.getString();
return Error::success();
}
-Error CVTypeDumper::visitArgList(ArgListRecord &Args) {
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, ArgListRecord &Args) {
auto Indices = Args.getIndices();
uint32_t Size = Indices.size();
W->printNumber("NumArgs", Size);
ListScope Arguments(*W, "Arguments");
- SmallString<256> TypeName("(");
for (uint32_t I = 0; I < Size; ++I) {
printTypeIndex("ArgType", Indices[I]);
- StringRef ArgTypeName = getTypeName(Indices[I]);
- TypeName.append(ArgTypeName);
- if (I + 1 != Size)
- TypeName.append(", ");
}
- TypeName.push_back(')');
- Name = saveName(TypeName);
return Error::success();
}
-Error CVTypeDumper::visitClass(ClassRecord &Class) {
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, ClassRecord &Class) {
uint16_t Props = static_cast<uint16_t>(Class.getOptions());
W->printNumber("MemberCount", Class.getMemberCount());
W->printFlags("Properties", Props, makeArrayRef(ClassOptionNames));
@@ -268,11 +238,10 @@ Error CVTypeDumper::visitClass(ClassRecord &Class) {
W->printString("Name", Class.getName());
if (Props & uint16_t(ClassOptions::HasUniqueName))
W->printString("LinkageName", Class.getUniqueName());
- Name = Class.getName();
return Error::success();
}
-Error CVTypeDumper::visitUnion(UnionRecord &Union) {
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, UnionRecord &Union) {
uint16_t Props = static_cast<uint16_t>(Union.getOptions());
W->printNumber("MemberCount", Union.getMemberCount());
W->printFlags("Properties", Props, makeArrayRef(ClassOptionNames));
@@ -281,11 +250,10 @@ Error CVTypeDumper::visitUnion(UnionRecord &Union) {
W->printString("Name", Union.getName());
if (Props & uint16_t(ClassOptions::HasUniqueName))
W->printString("LinkageName", Union.getUniqueName());
- Name = Union.getName();
return Error::success();
}
-Error CVTypeDumper::visitEnum(EnumRecord &Enum) {
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, EnumRecord &Enum) {
uint16_t Props = static_cast<uint16_t>(Enum.getOptions());
W->printNumber("NumEnumerators", Enum.getMemberCount());
W->printFlags("Properties", uint16_t(Enum.getOptions()),
@@ -295,39 +263,35 @@ Error CVTypeDumper::visitEnum(EnumRecord &Enum) {
W->printString("Name", Enum.getName());
if (Props & uint16_t(ClassOptions::HasUniqueName))
W->printString("LinkageName", Enum.getUniqueName());
- Name = Enum.getName();
return Error::success();
}
-Error CVTypeDumper::visitArray(ArrayRecord &AT) {
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, ArrayRecord &AT) {
printTypeIndex("ElementType", AT.getElementType());
printTypeIndex("IndexType", AT.getIndexType());
W->printNumber("SizeOf", AT.getSize());
W->printString("Name", AT.getName());
- Name = AT.getName();
return Error::success();
}
-Error CVTypeDumper::visitVFTable(VFTableRecord &VFT) {
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, VFTableRecord &VFT) {
printTypeIndex("CompleteClass", VFT.getCompleteClass());
printTypeIndex("OverriddenVFTable", VFT.getOverriddenVTable());
W->printHex("VFPtrOffset", VFT.getVFPtrOffset());
W->printString("VFTableName", VFT.getName());
for (auto N : VFT.getMethodNames())
W->printString("MethodName", N);
- Name = VFT.getName();
return Error::success();
}
-Error CVTypeDumper::visitMemberFuncId(MemberFuncIdRecord &Id) {
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, MemberFuncIdRecord &Id) {
printTypeIndex("ClassType", Id.getClassType());
printTypeIndex("FunctionType", Id.getFunctionType());
W->printString("Name", Id.getName());
- Name = Id.getName();
return Error::success();
}
-Error CVTypeDumper::visitProcedure(ProcedureRecord &Proc) {
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, ProcedureRecord &Proc) {
printTypeIndex("ReturnType", Proc.getReturnType());
W->printEnum("CallingConvention", uint8_t(Proc.getCallConv()),
makeArrayRef(CallingConventions));
@@ -335,17 +299,10 @@ Error CVTypeDumper::visitProcedure(ProcedureRecord &Proc) {
makeArrayRef(FunctionOptionEnum));
W->printNumber("NumParameters", Proc.getParameterCount());
printTypeIndex("ArgListType", Proc.getArgumentList());
-
- StringRef ReturnTypeName = getTypeName(Proc.getReturnType());
- StringRef ArgListTypeName = getTypeName(Proc.getArgumentList());
- SmallString<256> TypeName(ReturnTypeName);
- TypeName.push_back(' ');
- TypeName.append(ArgListTypeName);
- Name = saveName(TypeName);
return Error::success();
}
-Error CVTypeDumper::visitMemberFunction(MemberFunctionRecord &MF) {
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, MemberFunctionRecord &MF) {
printTypeIndex("ReturnType", MF.getReturnType());
printTypeIndex("ClassType", MF.getClassType());
printTypeIndex("ThisType", MF.getThisType());
@@ -356,24 +313,14 @@ Error CVTypeDumper::visitMemberFunction(MemberFunctionRecord &MF) {
W->printNumber("NumParameters", MF.getParameterCount());
printTypeIndex("ArgListType", MF.getArgumentList());
W->printNumber("ThisAdjustment", MF.getThisPointerAdjustment());
-
- StringRef ReturnTypeName = getTypeName(MF.getReturnType());
- StringRef ClassTypeName = getTypeName(MF.getClassType());
- StringRef ArgListTypeName = getTypeName(MF.getArgumentList());
- SmallString<256> TypeName(ReturnTypeName);
- TypeName.push_back(' ');
- TypeName.append(ClassTypeName);
- TypeName.append("::");
- TypeName.append(ArgListTypeName);
- Name = saveName(TypeName);
return Error::success();
}
-Error CVTypeDumper::visitMethodOverloadList(
- MethodOverloadListRecord &MethodList) {
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ MethodOverloadListRecord &MethodList) {
for (auto &M : MethodList.getMethods()) {
ListScope S(*W, "Method");
- printMemberAttributes(M.getAccess(), M.getKind(), M.getOptions());
+ printMemberAttributes(M.getAccess(), M.getMethodKind(), M.getOptions());
printTypeIndex("Type", M.getType());
if (M.isIntroducingVirtual())
W->printHex("VFTableOffset", M.getVFTableOffset());
@@ -381,23 +328,21 @@ Error CVTypeDumper::visitMethodOverloadList(
return Error::success();
}
-Error CVTypeDumper::visitFuncId(FuncIdRecord &Func) {
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, FuncIdRecord &Func) {
printTypeIndex("ParentScope", Func.getParentScope());
printTypeIndex("FunctionType", Func.getFunctionType());
W->printString("Name", Func.getName());
- Name = Func.getName();
return Error::success();
}
-Error CVTypeDumper::visitTypeServer2(TypeServer2Record &TS) {
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, TypeServer2Record &TS) {
W->printBinary("Signature", TS.getGuid());
W->printNumber("Age", TS.getAge());
W->printString("Name", TS.getName());
- Name = TS.getName();
return Error::success();
}
-Error CVTypeDumper::visitPointer(PointerRecord &Ptr) {
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) {
printTypeIndex("PointeeType", Ptr.getReferentType());
W->printHex("PointerAttributes", uint32_t(Ptr.getOptions()));
W->printEnum("PtrType", unsigned(Ptr.getPointerKind()),
@@ -416,76 +361,42 @@ Error CVTypeDumper::visitPointer(PointerRecord &Ptr) {
printTypeIndex("ClassType", MI.getContainingType());
W->printEnum("Representation", uint16_t(MI.getRepresentation()),
makeArrayRef(PtrMemberRepNames));
-
- StringRef PointeeName = getTypeName(Ptr.getReferentType());
- StringRef ClassName = getTypeName(MI.getContainingType());
- SmallString<256> TypeName(PointeeName);
- TypeName.push_back(' ');
- TypeName.append(ClassName);
- TypeName.append("::*");
- Name = saveName(TypeName);
- } else {
- SmallString<256> TypeName;
- if (Ptr.isConst())
- TypeName.append("const ");
- if (Ptr.isVolatile())
- TypeName.append("volatile ");
- if (Ptr.isUnaligned())
- TypeName.append("__unaligned ");
-
- TypeName.append(getTypeName(Ptr.getReferentType()));
-
- if (Ptr.getMode() == PointerMode::LValueReference)
- TypeName.append("&");
- else if (Ptr.getMode() == PointerMode::RValueReference)
- TypeName.append("&&");
- else if (Ptr.getMode() == PointerMode::Pointer)
- TypeName.append("*");
-
- if (!TypeName.empty())
- Name = saveName(TypeName);
}
+
return Error::success();
}
-Error CVTypeDumper::visitModifier(ModifierRecord &Mod) {
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, ModifierRecord &Mod) {
uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers());
printTypeIndex("ModifiedType", Mod.getModifiedType());
W->printFlags("Modifiers", Mods, makeArrayRef(TypeModifierNames));
- StringRef ModifiedName = getTypeName(Mod.getModifiedType());
- SmallString<256> TypeName;
- if (Mods & uint16_t(ModifierOptions::Const))
- TypeName.append("const ");
- if (Mods & uint16_t(ModifierOptions::Volatile))
- TypeName.append("volatile ");
- if (Mods & uint16_t(ModifierOptions::Unaligned))
- TypeName.append("__unaligned ");
- TypeName.append(ModifiedName);
- Name = saveName(TypeName);
return Error::success();
}
-Error CVTypeDumper::visitBitField(BitFieldRecord &BitField) {
+Error TypeDumpVisitor::visitKnownRecord(CVType &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 TypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ VFTableShapeRecord &Shape) {
W->printNumber("VFEntryCount", Shape.getEntryCount());
return Error::success();
}
-Error CVTypeDumper::visitUdtSourceLine(UdtSourceLineRecord &Line) {
+Error TypeDumpVisitor::visitKnownRecord(CVType &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 TypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ UdtModSourceLineRecord &Line) {
printTypeIndex("UDT", Line.getUDT());
printTypeIndex("SourceFile", Line.getSourceFile());
W->printNumber("LineNumber", Line.getLineNumber());
@@ -493,7 +404,7 @@ Error CVTypeDumper::visitUdtModSourceLine(UdtModSourceLineRecord &Line) {
return Error::success();
}
-Error CVTypeDumper::visitBuildInfo(BuildInfoRecord &Args) {
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, BuildInfoRecord &Args) {
W->printNumber("NumArgs", static_cast<uint32_t>(Args.getArgs().size()));
ListScope Arguments(*W, "Arguments");
@@ -503,13 +414,14 @@ Error CVTypeDumper::visitBuildInfo(BuildInfoRecord &Args) {
return Error::success();
}
-void CVTypeDumper::printMemberAttributes(MemberAttributes Attrs) {
+void TypeDumpVisitor::printMemberAttributes(MemberAttributes Attrs) {
return printMemberAttributes(Attrs.getAccess(), Attrs.getMethodKind(),
Attrs.getFlags());
}
-void CVTypeDumper::printMemberAttributes(MemberAccess Access, MethodKind Kind,
- MethodOptions Options) {
+void TypeDumpVisitor::printMemberAttributes(MemberAccess Access,
+ MethodKind Kind,
+ MethodOptions Options) {
W->printEnum("AccessSpecifier", uint8_t(Access),
makeArrayRef(MemberAccessNames));
// Data members will be vanilla. Don't try to print a method kind for them.
@@ -521,87 +433,80 @@ void CVTypeDumper::printMemberAttributes(MemberAccess Access, MethodKind Kind,
}
}
-Error CVTypeDumper::visitUnknownMember(const CVRecord<TypeLeafKind> &Record) {
- W->printHex("UnknownMember", unsigned(Record.Type));
+Error TypeDumpVisitor::visitUnknownMember(CVMemberRecord &Record) {
+ W->printHex("UnknownMember", unsigned(Record.Kind));
return Error::success();
}
-Error CVTypeDumper::visitUnknownType(const CVRecord<TypeLeafKind> &Record) {
- DictScope S(*W, "UnknownType");
- W->printEnum("Kind", uint16_t(Record.Type), makeArrayRef(LeafTypeNames));
- W->printNumber("Length", uint32_t(Record.Data.size()));
+Error TypeDumpVisitor::visitUnknownType(CVType &Record) {
+ W->printEnum("Kind", uint16_t(Record.kind()), makeArrayRef(LeafTypeNames));
+ W->printNumber("Length", uint32_t(Record.content().size()));
return Error::success();
}
-Error CVTypeDumper::visitNestedType(NestedTypeRecord &Nested) {
- DictScope S(*W, "NestedType");
+Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ NestedTypeRecord &Nested) {
printTypeIndex("Type", Nested.getNestedType());
W->printString("Name", Nested.getName());
- Name = Nested.getName();
return Error::success();
}
-Error CVTypeDumper::visitOneMethod(OneMethodRecord &Method) {
- DictScope S(*W, "OneMethod");
- MethodKind K = Method.getKind();
+Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ OneMethodRecord &Method) {
+ MethodKind K = Method.getMethodKind();
printMemberAttributes(Method.getAccess(), K, Method.getOptions());
printTypeIndex("Type", Method.getType());
// If virtual, then read the vftable offset.
if (Method.isIntroducingVirtual())
W->printHex("VFTableOffset", Method.getVFTableOffset());
W->printString("Name", Method.getName());
- Name = Method.getName();
return Error::success();
}
-Error CVTypeDumper::visitOverloadedMethod(OverloadedMethodRecord &Method) {
- DictScope S(*W, "OverloadedMethod");
+Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ OverloadedMethodRecord &Method) {
W->printHex("MethodCount", Method.getNumOverloads());
printTypeIndex("MethodListIndex", Method.getMethodList());
W->printString("Name", Method.getName());
- Name = Method.getName();
return Error::success();
}
-Error CVTypeDumper::visitDataMember(DataMemberRecord &Field) {
- DictScope S(*W, "DataMember");
+Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ DataMemberRecord &Field) {
printMemberAttributes(Field.getAccess(), MethodKind::Vanilla,
MethodOptions::None);
printTypeIndex("Type", Field.getType());
W->printHex("FieldOffset", Field.getFieldOffset());
W->printString("Name", Field.getName());
- Name = Field.getName();
return Error::success();
}
-Error CVTypeDumper::visitStaticDataMember(StaticDataMemberRecord &Field) {
- DictScope S(*W, "StaticDataMember");
+Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ StaticDataMemberRecord &Field) {
printMemberAttributes(Field.getAccess(), MethodKind::Vanilla,
MethodOptions::None);
printTypeIndex("Type", Field.getType());
W->printString("Name", Field.getName());
- Name = Field.getName();
return Error::success();
}
-Error CVTypeDumper::visitVFPtr(VFPtrRecord &VFTable) {
- DictScope S(*W, "VFPtr");
+Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ VFPtrRecord &VFTable) {
printTypeIndex("Type", VFTable.getType());
return Error::success();
}
-Error CVTypeDumper::visitEnumerator(EnumeratorRecord &Enum) {
- DictScope S(*W, "Enumerator");
+Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ EnumeratorRecord &Enum) {
printMemberAttributes(Enum.getAccess(), MethodKind::Vanilla,
MethodOptions::None);
W->printNumber("EnumValue", Enum.getValue());
W->printString("Name", Enum.getName());
- Name = Enum.getName();
return Error::success();
}
-Error CVTypeDumper::visitBaseClass(BaseClassRecord &Base) {
- DictScope S(*W, "BaseClass");
+Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ BaseClassRecord &Base) {
printMemberAttributes(Base.getAccess(), MethodKind::Vanilla,
MethodOptions::None);
printTypeIndex("BaseType", Base.getBaseType());
@@ -609,8 +514,8 @@ Error CVTypeDumper::visitBaseClass(BaseClassRecord &Base) {
return Error::success();
}
-Error CVTypeDumper::visitVirtualBaseClass(VirtualBaseClassRecord &Base) {
- DictScope S(*W, "VirtualBaseClass");
+Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ VirtualBaseClassRecord &Base) {
printMemberAttributes(Base.getAccess(), MethodKind::Vanilla,
MethodOptions::None);
printTypeIndex("BaseType", Base.getBaseType());
@@ -620,77 +525,8 @@ Error CVTypeDumper::visitVirtualBaseClass(VirtualBaseClassRecord &Base) {
return Error::success();
}
-Error CVTypeDumper::visitListContinuation(ListContinuationRecord &Cont) {
- DictScope S(*W, "ListContinuation");
+Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ ListContinuationRecord &Cont) {
printTypeIndex("ContinuationIndex", Cont.getContinuationIndex());
return Error::success();
}
-
-StringRef CVTypeDumper::getTypeName(TypeIndex TI) {
- if (TI.isNoneType())
- return "<no type>";
-
- if (TI.isSimple()) {
- // This is a simple type.
- for (const auto &SimpleTypeName : SimpleTypeNames) {
- if (SimpleTypeName.Value == TI.getSimpleKind()) {
- if (TI.getSimpleMode() == SimpleTypeMode::Direct)
- return SimpleTypeName.Name.drop_back(1);
- // Otherwise, this is a pointer type. We gloss over the distinction
- // between near, far, 64, 32, etc, and just give a pointer type.
- return SimpleTypeName.Name;
- }
- }
- return "<unknown simple type>";
- }
-
- // User-defined type.
- StringRef UDTName;
- unsigned UDTIndex = TI.getIndex() - 0x1000;
- if (UDTIndex < CVUDTNames.size())
- return CVUDTNames[UDTIndex];
-
- return "<unknown UDT>";
-}
-
-void CVTypeDumper::printTypeIndex(StringRef FieldName, TypeIndex TI) {
- StringRef TypeName;
- if (!TI.isNoneType())
- TypeName = getTypeName(TI);
- if (!TypeName.empty())
- W->printHex(FieldName, TypeName, TI.getIndex());
- else
- W->printHex(FieldName, TI.getIndex());
-}
-
-Error CVTypeDumper::dump(const CVRecord<TypeLeafKind> &Record) {
- assert(W && "printer should not be null");
- CVTypeVisitor Visitor(*this);
-
- if (auto EC = Visitor.visitTypeRecord(Record))
- return EC;
- return Error::success();
-}
-
-Error CVTypeDumper::dump(const CVTypeArray &Types) {
- assert(W && "printer should not be null");
- CVTypeVisitor Visitor(*this);
- if (auto EC = Visitor.visitTypeStream(Types))
- return EC;
- return Error::success();
-}
-
-Error CVTypeDumper::dump(ArrayRef<uint8_t> Data) {
- ByteStream<> Stream(Data);
- CVTypeArray Types;
- StreamReader Reader(Stream);
- if (auto EC = Reader.readArray(Types, Reader.getLength()))
- return EC;
-
- return dump(Types);
-}
-
-void CVTypeDumper::setPrinter(ScopedPrinter *P) {
- static ScopedPrinter NullP(llvm::nulls());
- W = P ? P : &NullP;
-}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/TypeRecord.cpp b/contrib/llvm/lib/DebugInfo/CodeView/TypeRecord.cpp
index f63371e..b951c06 100644
--- a/contrib/llvm/lib/DebugInfo/CodeView/TypeRecord.cpp
+++ b/contrib/llvm/lib/DebugInfo/CodeView/TypeRecord.cpp
@@ -8,374 +8,15 @@
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
-#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#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;
//===----------------------------------------------------------------------===//
-// Type record deserialization
-//===----------------------------------------------------------------------===//
-
-ErrorOr<MemberPointerInfo>
-MemberPointerInfo::deserialize(ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- if (auto EC = consumeObject(Data, L))
- return EC;
-
- TypeIndex T = L->ClassType;
- uint16_t R = L->Representation;
- PointerToMemberRepresentation PMR =
- static_cast<PointerToMemberRepresentation>(R);
- return MemberPointerInfo(T, PMR);
-}
-
-ErrorOr<ModifierRecord> ModifierRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- if (auto EC = consumeObject(Data, L))
- return EC;
-
- TypeIndex M = L->ModifiedType;
- uint16_t O = L->Modifiers;
- ModifierOptions MO = static_cast<ModifierOptions>(O);
- return ModifierRecord(M, MO);
-}
-
-ErrorOr<ProcedureRecord> ProcedureRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- if (auto EC = consumeObject(Data, L))
- return EC;
- return ProcedureRecord(L->ReturnType, L->CallConv, L->Options,
- L->NumParameters, L->ArgListType);
-}
-
-ErrorOr<MemberFunctionRecord>
-MemberFunctionRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- CV_DESERIALIZE(Data, L);
- return MemberFunctionRecord(L->ReturnType, L->ClassType, L->ThisType,
- L->CallConv, L->Options, L->NumParameters,
- L->ArgListType, L->ThisAdjustment);
-}
-
-ErrorOr<MemberFuncIdRecord>
-MemberFuncIdRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- StringRef Name;
- CV_DESERIALIZE(Data, L, Name);
- return MemberFuncIdRecord(L->ClassType, L->FunctionType, Name);
-}
-
-ErrorOr<ArgListRecord> ArgListRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- if (Kind != TypeRecordKind::StringList && Kind != TypeRecordKind::ArgList)
- return std::make_error_code(std::errc::illegal_byte_sequence);
-
- const Layout *L = nullptr;
- ArrayRef<TypeIndex> Indices;
- CV_DESERIALIZE(Data, L, CV_ARRAY_FIELD_N(Indices, L->NumArgs));
- return ArgListRecord(Kind, Indices);
-}
-
-ErrorOr<PointerRecord> PointerRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- if (auto EC = consumeObject(Data, L))
- return 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()) {
- auto E = MemberPointerInfo::deserialize(Data);
- if (E.getError())
- return std::make_error_code(std::errc::illegal_byte_sequence);
- return PointerRecord(L->PointeeType, PtrKind, Mode, Options, Size, *E);
- }
-
- return PointerRecord(L->PointeeType, PtrKind, Mode, Options, Size);
-}
-
-ErrorOr<NestedTypeRecord>
-NestedTypeRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- StringRef Name;
- CV_DESERIALIZE(Data, L, Name);
- return NestedTypeRecord(L->Type, Name);
-}
-
-ErrorOr<ArrayRecord> ArrayRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- uint64_t Size;
- StringRef Name;
- CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Size), Name);
- return ArrayRecord(L->ElementType, L->IndexType, Size, Name);
-}
-
-ErrorOr<ClassRecord> ClassRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- 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_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);
-}
-
-ErrorOr<UnionRecord> UnionRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- 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_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);
-}
-
-ErrorOr<EnumRecord> EnumRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- StringRef Name;
- StringRef UniqueName;
- CV_DESERIALIZE(Data, 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);
-}
-
-ErrorOr<BitFieldRecord> BitFieldRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- CV_DESERIALIZE(Data, L);
- return BitFieldRecord(L->Type, L->BitSize, L->BitOffset);
-}
-
-ErrorOr<VFTableShapeRecord>
-VFTableShapeRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- if (auto EC = consumeObject(Data, L))
- return EC;
-
- std::vector<VFTableSlotKind> Slots;
- uint16_t Count = L->VFEntryCount;
- while (Count > 0) {
- if (Data.empty())
- return std::make_error_code(std::errc::illegal_byte_sequence);
-
- // Process up to 2 nibbles at a time (if there are at least 2 remaining)
- uint8_t Value = Data[0] & 0x0F;
- Slots.push_back(static_cast<VFTableSlotKind>(Value));
- if (--Count > 0) {
- Value = (Data[0] & 0xF0) >> 4;
- Slots.push_back(static_cast<VFTableSlotKind>(Value));
- --Count;
- }
- Data = Data.slice(1);
- }
-
- return VFTableShapeRecord(Slots);
-}
-
-ErrorOr<TypeServer2Record>
-TypeServer2Record::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- StringRef Name;
- CV_DESERIALIZE(Data, L, Name);
- return TypeServer2Record(StringRef(L->Guid, 16), L->Age, Name);
-}
-
-ErrorOr<StringIdRecord> StringIdRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- StringRef Name;
- CV_DESERIALIZE(Data, L, Name);
- return StringIdRecord(L->id, Name);
-}
-
-ErrorOr<FuncIdRecord> FuncIdRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- StringRef Name;
- CV_DESERIALIZE(Data, L, Name);
- return FuncIdRecord(L->ParentScope, L->FunctionType, Name);
-}
-
-ErrorOr<UdtSourceLineRecord>
-UdtSourceLineRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- CV_DESERIALIZE(Data, L);
- return UdtSourceLineRecord(L->UDT, L->SourceFile, L->LineNumber);
-}
-
-ErrorOr<BuildInfoRecord> BuildInfoRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- ArrayRef<TypeIndex> Indices;
- CV_DESERIALIZE(Data, L, CV_ARRAY_FIELD_N(Indices, L->NumArgs));
- return BuildInfoRecord(Indices);
-}
-
-ErrorOr<VFTableRecord> VFTableRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- StringRef Name;
- std::vector<StringRef> Names;
- CV_DESERIALIZE(Data, L, Name, CV_ARRAY_FIELD_TAIL(Names));
- return VFTableRecord(L->CompleteClass, L->OverriddenVFTable, L->VFPtrOffset,
- Name, Names);
-}
-
-ErrorOr<OneMethodRecord> OneMethodRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- StringRef Name;
- int32_t VFTableOffset = -1;
-
- CV_DESERIALIZE(Data, 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 std::make_error_code(std::errc::illegal_byte_sequence);
- return Method;
-}
-
-ErrorOr<MethodOverloadListRecord>
-MethodOverloadListRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- std::vector<OneMethodRecord> Methods;
- while (!Data.empty()) {
- const Layout *L = nullptr;
- int32_t VFTableOffset = -1;
- CV_DESERIALIZE(Data, 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 std::make_error_code(std::errc::illegal_byte_sequence);
- }
- return MethodOverloadListRecord(Methods);
-}
-
-ErrorOr<OverloadedMethodRecord>
-OverloadedMethodRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- StringRef Name;
- CV_DESERIALIZE(Data, L, Name);
- return OverloadedMethodRecord(L->MethodCount, L->MethList, Name);
-}
-
-ErrorOr<DataMemberRecord>
-DataMemberRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- uint64_t Offset;
- StringRef Name;
- CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Offset), Name);
- return DataMemberRecord(L->Attrs.getAccess(), L->Type, Offset, Name);
-}
-
-ErrorOr<StaticDataMemberRecord>
-StaticDataMemberRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- StringRef Name;
- CV_DESERIALIZE(Data, L, Name);
- return StaticDataMemberRecord(L->Attrs.getAccess(), L->Type, Name);
-}
-
-ErrorOr<EnumeratorRecord>
-EnumeratorRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- APSInt Value;
- StringRef Name;
- CV_DESERIALIZE(Data, L, Value, Name);
- return EnumeratorRecord(L->Attrs.getAccess(), Value, Name);
-}
-
-ErrorOr<VFPtrRecord> VFPtrRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- if (auto EC = consumeObject(Data, L))
- return EC;
- return VFPtrRecord(L->Type);
-}
-
-ErrorOr<BaseClassRecord> BaseClassRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- uint64_t Offset;
- CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Offset));
- return BaseClassRecord(L->Attrs.getAccess(), L->BaseType, Offset);
-}
-
-ErrorOr<VirtualBaseClassRecord>
-VirtualBaseClassRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- uint64_t Offset;
- uint64_t Index;
- CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Offset), CV_NUMERIC_FIELD(Index));
- return VirtualBaseClassRecord(L->Attrs.getAccess(), L->BaseType, L->VBPtrType,
- Offset, Index);
-}
-
-ErrorOr<ListContinuationRecord>
-ListContinuationRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- CV_DESERIALIZE(Data, L);
- return ListContinuationRecord(L->ContinuationIndex);
-}
-
-//===----------------------------------------------------------------------===//
// Type index remapping
//===----------------------------------------------------------------------===//
@@ -437,7 +78,7 @@ bool PointerRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) {
bool Success = true;
Success &= remapIndex(IndexMap, ReferentType);
if (isPointerToMember())
- Success &= MemberInfo.remapTypeIndices(IndexMap);
+ Success &= MemberInfo->remapTypeIndices(IndexMap);
return Success;
}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/TypeRecordBuilder.cpp b/contrib/llvm/lib/DebugInfo/CodeView/TypeRecordBuilder.cpp
deleted file mode 100644
index 112612c..0000000
--- a/contrib/llvm/lib/DebugInfo/CodeView/TypeRecordBuilder.cpp
+++ /dev/null
@@ -1,113 +0,0 @@
-//===-- TypeRecordBuilder.cpp ---------------------------------------------===//
-//
-// 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/TypeRecordBuilder.h"
-
-using namespace llvm;
-using namespace codeview;
-
-TypeRecordBuilder::TypeRecordBuilder(TypeRecordKind Kind)
- : Stream(Buffer), Writer(Stream) {
- writeTypeRecordKind(Kind);
-}
-
-StringRef TypeRecordBuilder::str() {
- return StringRef(Buffer.data(), Buffer.size());
-}
-
-void TypeRecordBuilder::writeUInt8(uint8_t Value) {
- Writer.write(Value);
-}
-
-void TypeRecordBuilder::writeInt16(int16_t Value) {
- Writer.write(Value);
-}
-
-void TypeRecordBuilder::writeUInt16(uint16_t Value) {
- Writer.write(Value);
-}
-
-void TypeRecordBuilder::writeInt32(int32_t Value) {
- Writer.write(Value);
-}
-
-void TypeRecordBuilder::writeUInt32(uint32_t Value) {
- Writer.write(Value);
-}
-
-void TypeRecordBuilder::writeInt64(int64_t Value) {
- Writer.write(Value);
-}
-
-void TypeRecordBuilder::writeUInt64(uint64_t Value) {
- Writer.write(Value);
-}
-
-void TypeRecordBuilder::writeEncodedInteger(int64_t Value) {
- if (Value >= 0) {
- writeEncodedUnsignedInteger(static_cast<uint64_t>(Value));
- } else {
- writeEncodedSignedInteger(Value);
- }
-}
-
-void TypeRecordBuilder::writeEncodedSignedInteger(int64_t Value) {
- if (Value >= std::numeric_limits<int8_t>::min() &&
- Value <= std::numeric_limits<int8_t>::max()) {
- writeUInt16(LF_CHAR);
- writeInt16(static_cast<int8_t>(Value));
- } else if (Value >= std::numeric_limits<int16_t>::min() &&
- Value <= std::numeric_limits<int16_t>::max()) {
- writeUInt16(LF_SHORT);
- writeInt16(static_cast<int16_t>(Value));
- } else if (Value >= std::numeric_limits<int32_t>::min() &&
- Value <= std::numeric_limits<int32_t>::max()) {
- writeUInt16(LF_LONG);
- writeInt32(static_cast<int32_t>(Value));
- } else {
- writeUInt16(LF_QUADWORD);
- writeInt64(Value);
- }
-}
-
-void TypeRecordBuilder::writeEncodedUnsignedInteger(uint64_t Value) {
- if (Value < LF_CHAR) {
- writeUInt16(static_cast<uint16_t>(Value));
- } else if (Value <= std::numeric_limits<uint16_t>::max()) {
- writeUInt16(LF_USHORT);
- writeUInt16(static_cast<uint16_t>(Value));
- } else if (Value <= std::numeric_limits<uint32_t>::max()) {
- writeUInt16(LF_ULONG);
- writeUInt32(static_cast<uint32_t>(Value));
- } else {
- writeUInt16(LF_UQUADWORD);
- writeUInt64(Value);
- }
-}
-
-void TypeRecordBuilder::writeNullTerminatedString(StringRef Value) {
- // Microsoft's linker seems to have trouble with symbol names longer than
- // 0xffd8 bytes.
- Value = Value.substr(0, 0xffd8);
- Stream.write(Value.data(), Value.size());
- writeUInt8(0);
-}
-
-void TypeRecordBuilder::writeGuid(StringRef Guid) {
- assert(Guid.size() == 16);
- Stream.write(Guid.data(), 16);
-}
-
-void TypeRecordBuilder::writeTypeIndex(TypeIndex TypeInd) {
- writeUInt32(TypeInd.getIndex());
-}
-
-void TypeRecordBuilder::writeTypeRecordKind(TypeRecordKind Kind) {
- writeUInt16(static_cast<uint16_t>(Kind));
-}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp b/contrib/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp
new file mode 100644
index 0000000..f46e08d
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp
@@ -0,0 +1,467 @@
+//===- 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 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) {
+ if (IO.isWriting()) {
+ // Try to be smart about what we write here. We can't write anything too
+ // large, so if we're going to go over the limit, truncate both the name
+ // and unique name by the same amount.
+ size_t BytesLeft = IO.maxFieldLength();
+ if (HasUniqueName) {
+ size_t BytesNeeded = Name.size() + UniqueName.size() + 2;
+ StringRef N = Name;
+ StringRef U = UniqueName;
+ if (BytesNeeded > BytesLeft) {
+ size_t BytesToDrop = (BytesNeeded - BytesLeft);
+ size_t DropN = std::min(N.size(), BytesToDrop / 2);
+ size_t DropU = std::min(U.size(), BytesToDrop - DropN);
+
+ N = N.drop_back(DropN);
+ U = U.drop_back(DropU);
+ }
+
+ error(IO.mapStringZ(N));
+ error(IO.mapStringZ(U));
+ } else {
+ size_t BytesNeeded = Name.size() + 1;
+ StringRef N = Name;
+ if (BytesNeeded > BytesLeft) {
+ size_t BytesToDrop = std::min(N.size(), BytesToDrop);
+ N = N.drop_back(BytesToDrop);
+ }
+ error(IO.mapStringZ(N));
+ }
+ } else {
+ error(IO.mapStringZ(Name));
+ if (HasUniqueName)
+ error(IO.mapStringZ(UniqueName));
+ }
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitTypeBegin(CVType &CVR) {
+ assert(!TypeKind.hasValue() && "Already in a type mapping!");
+ assert(!MemberKind.hasValue() && "Already in a member mapping!");
+
+ // FieldList and MethodList records can be any length because they can be
+ // split with continuation records. All other record types cannot be
+ // longer than the maximum record length.
+ Optional<uint32_t> MaxLen;
+ if (CVR.Type != TypeLeafKind::LF_FIELDLIST &&
+ CVR.Type != TypeLeafKind::LF_METHODLIST)
+ MaxLen = MaxRecordLength - sizeof(RecordPrefix);
+ error(IO.beginRecord(MaxLen));
+ TypeKind = CVR.Type;
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitTypeEnd(CVType &Record) {
+ assert(TypeKind.hasValue() && "Not in a type mapping!");
+ assert(!MemberKind.hasValue() && "Still in a member mapping!");
+
+ error(IO.endRecord());
+
+ TypeKind.reset();
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitMemberBegin(CVMemberRecord &Record) {
+ assert(TypeKind.hasValue() && "Not in a type mapping!");
+ assert(!MemberKind.hasValue() && "Already in a member mapping!");
+
+ // The largest possible subrecord is one in which there is a record prefix,
+ // followed by the subrecord, followed by a continuation, and that entire
+ // sequence spaws `MaxRecordLength` bytes. So the record's length is
+ // calculated as follows.
+ constexpr uint32_t ContinuationLength = 8;
+ error(IO.beginRecord(MaxRecordLength - sizeof(RecordPrefix) -
+ ContinuationLength));
+
+ MemberKind = Record.Kind;
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitMemberEnd(CVMemberRecord &Record) {
+ assert(TypeKind.hasValue() && "Not in a type mapping!");
+ assert(MemberKind.hasValue() && "Not in a member mapping!");
+
+ if (!IO.isWriting()) {
+ if (auto EC = IO.skipPadding())
+ return EC;
+ }
+
+ MemberKind.reset();
+ error(IO.endRecord());
+ 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,
+ [](CodeViewRecordIO &IO, TypeIndex &N) { return IO.mapInteger(N); }));
+
+ 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,
+ [](CodeViewRecordIO &IO, StringRef &S) { return IO.mapStringZ(S); }));
+
+ 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,
+ [](CodeViewRecordIO &IO, TypeIndex &N) { return IO.mapInteger(N); }));
+
+ 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/contrib/llvm/lib/DebugInfo/CodeView/TypeSerializer.cpp b/contrib/llvm/lib/DebugInfo/CodeView/TypeSerializer.cpp
new file mode 100644
index 0000000..f24fcff
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/CodeView/TypeSerializer.cpp
@@ -0,0 +1,243 @@
+//===- TypeSerialzier.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/TypeSerializer.h"
+
+#include "llvm/DebugInfo/MSF/StreamWriter.h"
+
+#include <string.h>
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+bool TypeSerializer::isInFieldList() const {
+ return TypeKind.hasValue() && *TypeKind == TypeLeafKind::LF_FIELDLIST;
+}
+
+TypeIndex TypeSerializer::calcNextTypeIndex() const {
+ if (LastTypeIndex.isNoneType())
+ return TypeIndex(TypeIndex::FirstNonSimpleIndex);
+ else
+ return TypeIndex(LastTypeIndex.getIndex() + 1);
+}
+
+TypeIndex TypeSerializer::incrementTypeIndex() {
+ TypeIndex Previous = LastTypeIndex;
+ LastTypeIndex = calcNextTypeIndex();
+ return Previous;
+}
+
+MutableArrayRef<uint8_t> TypeSerializer::getCurrentSubRecordData() {
+ assert(isInFieldList());
+ return getCurrentRecordData().drop_front(CurrentSegment.length());
+}
+
+MutableArrayRef<uint8_t> TypeSerializer::getCurrentRecordData() {
+ return MutableArrayRef<uint8_t>(RecordBuffer).take_front(Writer.getOffset());
+}
+
+Error TypeSerializer::writeRecordPrefix(TypeLeafKind Kind) {
+ RecordPrefix Prefix;
+ Prefix.RecordKind = Kind;
+ Prefix.RecordLen = 0;
+ if (auto EC = Writer.writeObject(Prefix))
+ return EC;
+ return Error::success();
+}
+
+TypeIndex
+TypeSerializer::insertRecordBytesPrivate(MutableArrayRef<uint8_t> Record) {
+ assert(Record.size() % 4 == 0 && "Record is not aligned to 4 bytes!");
+
+ StringRef S(reinterpret_cast<const char *>(Record.data()), Record.size());
+
+ TypeIndex NextTypeIndex = calcNextTypeIndex();
+ auto Result = HashedRecords.try_emplace(S, NextTypeIndex);
+ if (Result.second) {
+ LastTypeIndex = NextTypeIndex;
+ SeenRecords.push_back(Record);
+ }
+ return Result.first->getValue();
+}
+
+Expected<MutableArrayRef<uint8_t>>
+TypeSerializer::addPadding(MutableArrayRef<uint8_t> Record) {
+ uint32_t Align = Record.size() % 4;
+ if (Align == 0)
+ return Record;
+
+ int PaddingBytes = 4 - Align;
+ int N = PaddingBytes;
+ while (PaddingBytes > 0) {
+ uint8_t Pad = static_cast<uint8_t>(LF_PAD0 + PaddingBytes);
+ if (auto EC = Writer.writeInteger(Pad))
+ return std::move(EC);
+ --PaddingBytes;
+ }
+ return MutableArrayRef<uint8_t>(Record.data(), Record.size() + N);
+}
+
+TypeSerializer::TypeSerializer(BumpPtrAllocator &Storage)
+ : RecordStorage(Storage), LastTypeIndex(),
+ RecordBuffer(MaxRecordLength * 2), Stream(RecordBuffer), Writer(Stream),
+ Mapping(Writer) {
+ // RecordBuffer needs to be able to hold enough data so that if we are 1
+ // byte short of MaxRecordLen, and then we try to write MaxRecordLen bytes,
+ // we won't overflow.
+}
+
+ArrayRef<MutableArrayRef<uint8_t>> TypeSerializer::records() const {
+ return SeenRecords;
+}
+
+TypeIndex TypeSerializer::getLastTypeIndex() const { return LastTypeIndex; }
+
+TypeIndex TypeSerializer::insertRecordBytes(MutableArrayRef<uint8_t> Record) {
+ assert(!TypeKind.hasValue() && "Already in a type mapping!");
+ assert(Writer.getOffset() == 0 && "Stream has data already!");
+
+ return insertRecordBytesPrivate(Record);
+}
+
+Error TypeSerializer::visitTypeBegin(CVType &Record) {
+ assert(!TypeKind.hasValue() && "Already in a type mapping!");
+ assert(Writer.getOffset() == 0 && "Stream has data already!");
+
+ if (auto EC = writeRecordPrefix(Record.kind()))
+ return EC;
+
+ TypeKind = Record.kind();
+ if (auto EC = Mapping.visitTypeBegin(Record))
+ return EC;
+
+ return Error::success();
+}
+
+Expected<TypeIndex> TypeSerializer::visitTypeEndGetIndex(CVType &Record) {
+ assert(TypeKind.hasValue() && "Not in a type mapping!");
+ if (auto EC = Mapping.visitTypeEnd(Record))
+ return std::move(EC);
+
+ // Update the record's length and fill out the CVType members to point to
+ // the stable memory holding the record's data.
+ auto ThisRecordData = getCurrentRecordData();
+ auto ExpectedData = addPadding(ThisRecordData);
+ if (!ExpectedData)
+ return ExpectedData.takeError();
+ ThisRecordData = *ExpectedData;
+
+ RecordPrefix *Prefix =
+ reinterpret_cast<RecordPrefix *>(ThisRecordData.data());
+ Prefix->RecordLen = ThisRecordData.size() - sizeof(uint16_t);
+
+ uint8_t *Copy = RecordStorage.Allocate<uint8_t>(ThisRecordData.size());
+ ::memcpy(Copy, ThisRecordData.data(), ThisRecordData.size());
+ ThisRecordData = MutableArrayRef<uint8_t>(Copy, ThisRecordData.size());
+ Record = CVType(*TypeKind, ThisRecordData);
+ TypeIndex InsertedTypeIndex = insertRecordBytesPrivate(ThisRecordData);
+
+ // Write out each additional segment in reverse order, and update each
+ // record's continuation index to point to the previous one.
+ for (auto X : reverse(FieldListSegments)) {
+ auto CIBytes = X.take_back(sizeof(uint32_t));
+ support::ulittle32_t *CI =
+ reinterpret_cast<support::ulittle32_t *>(CIBytes.data());
+ assert(*CI == 0xB0C0B0C0 && "Invalid TypeIndex placeholder");
+ *CI = InsertedTypeIndex.getIndex();
+ InsertedTypeIndex = insertRecordBytesPrivate(X);
+ }
+
+ TypeKind.reset();
+ Writer.setOffset(0);
+ FieldListSegments.clear();
+ CurrentSegment.SubRecords.clear();
+
+ return InsertedTypeIndex;
+}
+
+Error TypeSerializer::visitTypeEnd(CVType &Record) {
+ auto ExpectedIndex = visitTypeEndGetIndex(Record);
+ if (!ExpectedIndex)
+ return ExpectedIndex.takeError();
+ return Error::success();
+}
+
+Error TypeSerializer::visitMemberBegin(CVMemberRecord &Record) {
+ assert(isInFieldList() && "Not in a field list!");
+ assert(!MemberKind.hasValue() && "Already in a member record!");
+ MemberKind = Record.Kind;
+
+ if (auto EC = Mapping.visitMemberBegin(Record))
+ return EC;
+
+ return Error::success();
+}
+
+Error TypeSerializer::visitMemberEnd(CVMemberRecord &Record) {
+ if (auto EC = Mapping.visitMemberEnd(Record))
+ return EC;
+
+ // Check if this subrecord makes the current segment not fit in 64K minus
+ // the space for a continuation record (8 bytes). If the segment does not
+ // fit, insert a continuation record.
+ if (Writer.getOffset() > MaxRecordLength - ContinuationLength) {
+ MutableArrayRef<uint8_t> Data = getCurrentRecordData();
+ SubRecord LastSubRecord = CurrentSegment.SubRecords.back();
+ uint32_t CopySize = CurrentSegment.length() - LastSubRecord.Size;
+ auto CopyData = Data.take_front(CopySize);
+ auto LeftOverData = Data.drop_front(CopySize);
+ assert(LastSubRecord.Size == LeftOverData.size());
+
+ // Allocate stable storage for the record and copy the old record plus
+ // continuation over.
+ uint16_t LengthWithSize = CopySize + ContinuationLength;
+ assert(LengthWithSize <= MaxRecordLength);
+ RecordPrefix *Prefix = reinterpret_cast<RecordPrefix *>(CopyData.data());
+ Prefix->RecordLen = LengthWithSize - sizeof(uint16_t);
+
+ uint8_t *SegmentBytes = RecordStorage.Allocate<uint8_t>(LengthWithSize);
+ auto SavedSegment = MutableArrayRef<uint8_t>(SegmentBytes, LengthWithSize);
+ msf::MutableByteStream CS(SavedSegment);
+ msf::StreamWriter CW(CS);
+ if (auto EC = CW.writeBytes(CopyData))
+ return EC;
+ if (auto EC = CW.writeEnum(TypeLeafKind::LF_INDEX))
+ return EC;
+ if (auto EC = CW.writeInteger(uint16_t(0)))
+ return EC;
+ if (auto EC = CW.writeInteger(uint32_t(0xB0C0B0C0)))
+ return EC;
+ FieldListSegments.push_back(SavedSegment);
+
+ // Write a new placeholder record prefix to mark the start of this new
+ // top-level record.
+ Writer.setOffset(0);
+ if (auto EC = writeRecordPrefix(TypeLeafKind::LF_FIELDLIST))
+ return EC;
+
+ // Then move over the subrecord that overflowed the old segment to the
+ // beginning of this segment. Note that we have to use memmove here
+ // instead of Writer.writeBytes(), because the new and old locations
+ // could overlap.
+ ::memmove(Stream.data().data() + sizeof(RecordPrefix), LeftOverData.data(),
+ LeftOverData.size());
+ // And point the segment writer at the end of that subrecord.
+ Writer.setOffset(LeftOverData.size() + sizeof(RecordPrefix));
+
+ CurrentSegment.SubRecords.clear();
+ CurrentSegment.SubRecords.push_back(LastSubRecord);
+ }
+
+ // Update the CVMemberRecord since we may have shifted around or gotten
+ // padded.
+ Record.Data = getCurrentSubRecordData();
+
+ MemberKind.reset();
+ return Error::success();
+}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp b/contrib/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
index ebfda24..ed6cf57 100644
--- a/contrib/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
+++ b/contrib/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
@@ -11,10 +11,11 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
-#include "llvm/DebugInfo/CodeView/FieldListRecordBuilder.h"
-#include "llvm/DebugInfo/CodeView/StreamRef.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
+#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ScopedPrinter.h"
@@ -53,37 +54,61 @@ namespace {
/// existing destination type index.
class TypeStreamMerger : public TypeVisitorCallbacks {
public:
- TypeStreamMerger(TypeTableBuilder &DestStream) : DestStream(DestStream) {
+ TypeStreamMerger(TypeTableBuilder &DestStream)
+ : DestStream(DestStream), FieldListBuilder(DestStream) {
assert(!hadError());
}
/// TypeVisitorCallbacks overrides.
#define TYPE_RECORD(EnumName, EnumVal, Name) \
- Error visit##Name(Name##Record &Record) override;
+ Error visitKnownRecord(CVType &CVR, Name##Record &Record) override;
#define MEMBER_RECORD(EnumName, EnumVal, Name) \
- TYPE_RECORD(EnumName, EnumVal, Name)
+ Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override;
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
- Error visitUnknownType(const CVRecord<TypeLeafKind> &Record) override;
+ Error visitUnknownType(CVType &Record) override;
- Error visitTypeBegin(const CVRecord<TypeLeafKind> &Record) override;
- Error visitTypeEnd(const CVRecord<TypeLeafKind> &Record) override;
-
- Error visitFieldListEnd(const CVRecord<TypeLeafKind> &Record) override;
+ Error visitTypeBegin(CVType &Record) override;
+ Error visitTypeEnd(CVType &Record) override;
+ Error visitMemberEnd(CVMemberRecord &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) {
+ CVTypeVisitor Visitor(*this);
+
+ if (auto EC = Visitor.visitFieldListMemberStream(Record.Data))
+ return EC;
+ return Error::success();
+ }
+
+ template <typename RecordType>
+ Error visitKnownMemberRecordImpl(RecordType &Record) {
+ FoundBadTypeIndex |= !Record.remapTypeIndices(IndexMap);
+ FieldListBuilder.writeMemberType(Record);
+ return Error::success();
+ }
+
bool hadError() { return FoundBadTypeIndex; }
bool FoundBadTypeIndex = false;
- FieldListRecordBuilder FieldBuilder;
+ BumpPtrAllocator Allocator;
TypeTableBuilder &DestStream;
+ FieldListRecordBuilder FieldListBuilder;
+ bool IsInFieldList{false};
size_t BeginIndexMapSize = 0;
/// Map from source type index to destination type index. Indexed by source
@@ -93,39 +118,45 @@ private:
} // end anonymous namespace
-Error TypeStreamMerger::visitTypeBegin(const CVRecord<TypeLeafKind> &Rec) {
- BeginIndexMapSize = IndexMap.size();
+Error TypeStreamMerger::visitTypeBegin(CVRecord<TypeLeafKind> &Rec) {
+ if (Rec.Type == TypeLeafKind::LF_FIELDLIST) {
+ assert(!IsInFieldList);
+ IsInFieldList = true;
+ FieldListBuilder.begin();
+ } else
+ BeginIndexMapSize = IndexMap.size();
return Error::success();
}
-Error TypeStreamMerger::visitTypeEnd(const CVRecord<TypeLeafKind> &Rec) {
- assert(IndexMap.size() == BeginIndexMapSize + 1);
+Error TypeStreamMerger::visitTypeEnd(CVRecord<TypeLeafKind> &Rec) {
+ if (Rec.Type == TypeLeafKind::LF_FIELDLIST) {
+ TypeIndex Index = FieldListBuilder.end();
+ IndexMap.push_back(Index);
+ IsInFieldList = false;
+ }
return Error::success();
}
-Error TypeStreamMerger::visitFieldListEnd(const CVRecord<TypeLeafKind> &Rec) {
- IndexMap.push_back(DestStream.writeFieldList(FieldBuilder));
- FieldBuilder.reset();
+Error TypeStreamMerger::visitMemberEnd(CVMemberRecord &Rec) {
+ 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(CVType &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::visitKnownMember(CVMemberRecord &CVR, \
+ Name##Record &Record) { \
+ return visitKnownMemberRecordImpl(Record); \
}
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
-Error TypeStreamMerger::visitUnknownType(const CVRecord<TypeLeafKind> &Rec) {
+Error TypeStreamMerger::visitUnknownType(CVType &Rec) {
// We failed to translate a type. Translate this index as "not translated".
IndexMap.push_back(
TypeIndex(SimpleTypeKind::NotTranslated, SimpleTypeMode::Direct));
@@ -134,7 +165,14 @@ Error TypeStreamMerger::visitUnknownType(const CVRecord<TypeLeafKind> &Rec) {
bool TypeStreamMerger::mergeStream(const CVTypeArray &Types) {
assert(IndexMap.empty());
- CVTypeVisitor Visitor(*this);
+ TypeVisitorCallbackPipeline Pipeline;
+
+ TypeDeserializer Deserializer;
+ Pipeline.addCallbackToPipeline(Deserializer);
+ Pipeline.addCallbackToPipeline(*this);
+
+ CVTypeVisitor Visitor(Pipeline);
+
if (auto EC = Visitor.visitTypeStream(Types)) {
consumeError(std::move(EC));
return false;
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp b/contrib/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp
deleted file mode 100644
index 647538e..0000000
--- a/contrib/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp
+++ /dev/null
@@ -1,303 +0,0 @@
-//===-- TypeTableBuilder.cpp ----------------------------------------------===//
-//
-// 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/TypeTableBuilder.h"
-#include "llvm/DebugInfo/CodeView/FieldListRecordBuilder.h"
-#include "llvm/DebugInfo/CodeView/MethodListRecordBuilder.h"
-#include "llvm/DebugInfo/CodeView/TypeIndex.h"
-#include "llvm/DebugInfo/CodeView/TypeRecordBuilder.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace llvm;
-using namespace codeview;
-
-TypeTableBuilder::TypeTableBuilder() {}
-
-TypeTableBuilder::~TypeTableBuilder() {}
-
-TypeIndex TypeTableBuilder::writeModifier(const ModifierRecord &Record) {
- TypeRecordBuilder Builder(Record.getKind());
-
- Builder.writeTypeIndex(Record.getModifiedType());
- Builder.writeUInt16(static_cast<uint16_t>(Record.getModifiers()));
-
- return writeRecord(Builder);
-}
-
-TypeIndex TypeTableBuilder::writeProcedure(const ProcedureRecord &Record) {
- TypeRecordBuilder Builder(Record.getKind());
-
- Builder.writeTypeIndex(Record.getReturnType());
- Builder.writeUInt8(static_cast<uint8_t>(Record.getCallConv()));
- Builder.writeUInt8(static_cast<uint8_t>(Record.getOptions()));
- Builder.writeUInt16(Record.getParameterCount());
- Builder.writeTypeIndex(Record.getArgumentList());
-
- return writeRecord(Builder);
-}
-
-TypeIndex
-TypeTableBuilder::writeMemberFunction(const MemberFunctionRecord &Record) {
- TypeRecordBuilder Builder(Record.getKind());
-
- Builder.writeTypeIndex(Record.getReturnType());
- Builder.writeTypeIndex(Record.getClassType());
- Builder.writeTypeIndex(Record.getThisType());
- Builder.writeUInt8(static_cast<uint8_t>(Record.getCallConv()));
- Builder.writeUInt8(static_cast<uint8_t>(Record.getOptions()));
- Builder.writeUInt16(Record.getParameterCount());
- Builder.writeTypeIndex(Record.getArgumentList());
- Builder.writeInt32(Record.getThisPointerAdjustment());
-
- return writeRecord(Builder);
-}
-
-TypeIndex TypeTableBuilder::writeArgList(const ArgListRecord &Record) {
- TypeRecordBuilder Builder(Record.getKind());
-
- Builder.writeUInt32(Record.getIndices().size());
- for (TypeIndex TI : Record.getIndices()) {
- Builder.writeTypeIndex(TI);
- }
-
- return writeRecord(Builder);
-}
-
-TypeIndex TypeTableBuilder::writePointer(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);
-
- if (Record.isPointerToMember()) {
- const MemberPointerInfo &M = Record.getMemberInfo();
- Builder.writeTypeIndex(M.getContainingType());
- Builder.writeUInt16(static_cast<uint16_t>(M.getRepresentation()));
- }
-
- return writeRecord(Builder);
-}
-
-TypeIndex TypeTableBuilder::writeArray(const ArrayRecord &Record) {
- TypeRecordBuilder Builder(Record.getKind());
-
- Builder.writeTypeIndex(Record.getElementType());
- Builder.writeTypeIndex(Record.getIndexType());
- Builder.writeEncodedUnsignedInteger(Record.getSize());
- Builder.writeNullTerminatedString(Record.getName());
-
- return writeRecord(Builder);
-}
-
-TypeIndex TypeTableBuilder::writeClass(const ClassRecord &Record) {
- assert((Record.getKind() == TypeRecordKind::Struct) ||
- (Record.getKind() == TypeRecordKind::Class) ||
- (Record.getKind() == TypeRecordKind::Interface));
-
- TypeRecordBuilder Builder(Record.getKind());
-
- Builder.writeUInt16(Record.getMemberCount());
- uint16_t Flags =
- static_cast<uint16_t>(Record.getOptions()) |
- (static_cast<uint16_t>(Record.getHfa()) << ClassRecord::HfaKindShift) |
- (static_cast<uint16_t>(Record.getWinRTKind())
- << ClassRecord::WinRTKindShift);
- Builder.writeUInt16(Flags);
- Builder.writeTypeIndex(Record.getFieldList());
- Builder.writeTypeIndex(Record.getDerivationList());
- Builder.writeTypeIndex(Record.getVTableShape());
- Builder.writeEncodedUnsignedInteger(Record.getSize());
- Builder.writeNullTerminatedString(Record.getName());
- if ((Record.getOptions() & ClassOptions::HasUniqueName) !=
- ClassOptions::None) {
- Builder.writeNullTerminatedString(Record.getUniqueName());
- }
-
- return writeRecord(Builder);
-}
-
-TypeIndex TypeTableBuilder::writeUnion(const UnionRecord &Record) {
- TypeRecordBuilder Builder(TypeRecordKind::Union);
- Builder.writeUInt16(Record.getMemberCount());
- uint16_t Flags =
- static_cast<uint16_t>(Record.getOptions()) |
- (static_cast<uint16_t>(Record.getHfa()) << ClassRecord::HfaKindShift);
- Builder.writeUInt16(Flags);
- Builder.writeTypeIndex(Record.getFieldList());
- Builder.writeEncodedUnsignedInteger(Record.getSize());
- Builder.writeNullTerminatedString(Record.getName());
- if ((Record.getOptions() & ClassOptions::HasUniqueName) !=
- ClassOptions::None) {
- Builder.writeNullTerminatedString(Record.getUniqueName());
- }
- return writeRecord(Builder);
-}
-
-TypeIndex TypeTableBuilder::writeEnum(const EnumRecord &Record) {
- TypeRecordBuilder Builder(Record.getKind());
-
- Builder.writeUInt16(Record.getMemberCount());
- Builder.writeUInt16(static_cast<uint16_t>(Record.getOptions()));
- Builder.writeTypeIndex(Record.getUnderlyingType());
- Builder.writeTypeIndex(Record.getFieldList());
- Builder.writeNullTerminatedString(Record.getName());
- if ((Record.getOptions() & ClassOptions::HasUniqueName) !=
- ClassOptions::None) {
- Builder.writeNullTerminatedString(Record.getUniqueName());
- }
-
- return writeRecord(Builder);
-}
-
-TypeIndex TypeTableBuilder::writeBitField(const BitFieldRecord &Record) {
- TypeRecordBuilder Builder(Record.getKind());
-
- Builder.writeTypeIndex(Record.getType());
- Builder.writeUInt8(Record.getBitSize());
- Builder.writeUInt8(Record.getBitOffset());
-
- return writeRecord(Builder);
-}
-
-TypeIndex
-TypeTableBuilder::writeVFTableShape(const VFTableShapeRecord &Record) {
- TypeRecordBuilder Builder(Record.getKind());
-
- ArrayRef<VFTableSlotKind> Slots = Record.getSlots();
-
- Builder.writeUInt16(Slots.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]);
- }
- Builder.writeUInt8(Byte);
- }
-
- return writeRecord(Builder);
-}
-
-TypeIndex
-TypeTableBuilder::writeVFTable(const VFTableRecord &Record) {
- TypeRecordBuilder Builder(Record.getKind());
- Builder.writeTypeIndex(Record.getCompleteClass());
- Builder.writeTypeIndex(Record.getOverriddenVTable());
- Builder.writeUInt32(Record.getVFPtrOffset());
-
- // Sum up the lengths of the null-terminated names.
- size_t NamesLen = Record.getName().size() + 1;
- for (StringRef MethodName : Record.getMethodNames())
- NamesLen += MethodName.size() + 1;
-
- Builder.writeUInt32(NamesLen);
- Builder.writeNullTerminatedString(Record.getName());
- for (StringRef MethodName : Record.getMethodNames())
- Builder.writeNullTerminatedString(MethodName);
-
- return writeRecord(Builder);
-}
-
-TypeIndex TypeTableBuilder::writeStringId(const StringIdRecord &Record) {
- TypeRecordBuilder Builder(TypeRecordKind::StringId);
- Builder.writeTypeIndex(Record.getId());
- Builder.writeNullTerminatedString(Record.getString());
- return writeRecord(Builder);
-}
-
-TypeIndex
-TypeTableBuilder::writeUdtSourceLine(const UdtSourceLineRecord &Record) {
- TypeRecordBuilder Builder(Record.getKind());
- Builder.writeTypeIndex(Record.getUDT());
- Builder.writeTypeIndex(Record.getSourceFile());
- Builder.writeUInt32(Record.getLineNumber());
- return writeRecord(Builder);
-}
-
-TypeIndex
-TypeTableBuilder::writeUdtModSourceLine(const UdtModSourceLineRecord &Record) {
- TypeRecordBuilder Builder(Record.getKind());
- Builder.writeTypeIndex(Record.getUDT());
- Builder.writeTypeIndex(Record.getSourceFile());
- Builder.writeUInt32(Record.getLineNumber());
- Builder.writeUInt16(Record.getModule());
- return writeRecord(Builder);
-}
-
-TypeIndex TypeTableBuilder::writeFuncId(const FuncIdRecord &Record) {
- TypeRecordBuilder Builder(Record.getKind());
- Builder.writeTypeIndex(Record.getParentScope());
- Builder.writeTypeIndex(Record.getFunctionType());
- Builder.writeNullTerminatedString(Record.getName());
- return writeRecord(Builder);
-}
-
-TypeIndex
-TypeTableBuilder::writeMemberFuncId(const MemberFuncIdRecord &Record) {
- TypeRecordBuilder Builder(Record.getKind());
- Builder.writeTypeIndex(Record.getClassType());
- Builder.writeTypeIndex(Record.getFunctionType());
- Builder.writeNullTerminatedString(Record.getName());
- return writeRecord(Builder);
-}
-
-TypeIndex
-TypeTableBuilder::writeBuildInfo(const BuildInfoRecord &Record) {
- TypeRecordBuilder Builder(Record.getKind());
- assert(Record.getArgs().size() <= UINT16_MAX);
- Builder.writeUInt16(Record.getArgs().size());
- for (TypeIndex Arg : Record.getArgs())
- Builder.writeTypeIndex(Arg);
- return writeRecord(Builder);
-}
-
-TypeIndex TypeTableBuilder::writeRecord(TypeRecordBuilder &Builder) {
- return writeRecord(Builder.str());
-}
-
-TypeIndex TypeTableBuilder::writeFieldList(FieldListRecordBuilder &FieldList) {
- return FieldList.writeListRecord(*this);
-}
-
-TypeIndex TypeTableBuilder::writeMethodOverloadList(
- const MethodOverloadListRecord &Record) {
- TypeRecordBuilder Builder(Record.getKind());
- for (const OneMethodRecord &Method : Record.getMethods()) {
- uint16_t Flags = static_cast<uint16_t>(Method.getAccess());
- Flags |= static_cast<uint16_t>(Method.getKind())
- << MemberAttributes::MethodKindShift;
- Flags |= static_cast<uint16_t>(Method.getOptions());
- Builder.writeUInt16(Flags);
- Builder.writeUInt16(0); // padding
- Builder.writeTypeIndex(Method.getType());
- if (Method.isIntroducingVirtual()) {
- assert(Method.getVFTableOffset() >= 0);
- Builder.writeInt32(Method.getVFTableOffset());
- } else {
- assert(Method.getVFTableOffset() == -1);
- }
- }
-
- // TODO: Split the list into multiple records if it's longer than 64KB, using
- // a subrecord of TypeRecordKind::Index to chain the records together.
- return writeRecord(Builder);
-}
-
-TypeIndex TypeTableBuilder::writeTypeServer2(const TypeServer2Record &Record) {
- TypeRecordBuilder Builder(Record.getKind());
- Builder.writeGuid(Record.getGuid());
- Builder.writeUInt32(Record.getAge());
- Builder.writeNullTerminatedString(Record.getName());
- return writeRecord(Builder);
-}
OpenPOWER on IntegriCloud