aboutsummaryrefslogtreecommitdiff
path: root/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h')
-rw-r--r--include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h140
1 files changed, 115 insertions, 25 deletions
diff --git a/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h b/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h
index 94f104ff772c..00fb0cf4cc90 100644
--- a/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h
+++ b/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h
@@ -1,9 +1,8 @@
//===- CodeViewRecordIO.h ---------------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
@@ -25,28 +24,65 @@
#include <type_traits>
namespace llvm {
+
namespace codeview {
+class CodeViewRecordStreamer {
+public:
+ virtual void EmitBytes(StringRef Data) = 0;
+ virtual void EmitIntValue(uint64_t Value, unsigned Size) = 0;
+ virtual void EmitBinaryData(StringRef Data) = 0;
+ virtual void AddComment(const Twine &T) = 0;
+ virtual ~CodeViewRecordStreamer() = default;
+};
+
class CodeViewRecordIO {
uint32_t getCurrentOffset() const {
- return (isWriting()) ? Writer->getOffset() : Reader->getOffset();
+ if (isWriting())
+ return Writer->getOffset();
+ else if (isReading())
+ return Reader->getOffset();
+ else
+ return 0;
}
public:
+ // deserializes records to structures
explicit CodeViewRecordIO(BinaryStreamReader &Reader) : Reader(&Reader) {}
+
+ // serializes records to buffer
explicit CodeViewRecordIO(BinaryStreamWriter &Writer) : Writer(&Writer) {}
+ // writes records to assembly file using MC library interface
+ explicit CodeViewRecordIO(CodeViewRecordStreamer &Streamer)
+ : Streamer(&Streamer) {}
+
Error beginRecord(Optional<uint32_t> MaxLength);
Error endRecord();
- Error mapInteger(TypeIndex &TypeInd);
+ Error mapInteger(TypeIndex &TypeInd, const Twine &Comment = "");
- bool isReading() const { return Reader != nullptr; }
- bool isWriting() const { return !isReading(); }
+ bool isStreaming() const {
+ return (Streamer != nullptr) && (Reader == nullptr) && (Writer == nullptr);
+ }
+ bool isReading() const {
+ return (Reader != nullptr) && (Streamer == nullptr) && (Writer == nullptr);
+ }
+ bool isWriting() const {
+ return (Writer != nullptr) && (Streamer == nullptr) && (Reader == nullptr);
+ }
uint32_t maxFieldLength() const;
template <typename T> Error mapObject(T &Value) {
+ if (isStreaming()) {
+ StringRef BytesSR =
+ StringRef((reinterpret_cast<const char *>(&Value)), sizeof(Value));
+ Streamer->EmitBytes(BytesSR);
+ incrStreamedLen(sizeof(T));
+ return Error::success();
+ }
+
if (isWriting())
return Writer->writeObject(Value);
@@ -57,41 +93,63 @@ public:
return Error::success();
}
- template <typename T> Error mapInteger(T &Value) {
+ template <typename T> Error mapInteger(T &Value, const Twine &Comment = "") {
+ if (isStreaming()) {
+ emitComment(Comment);
+ Streamer->EmitIntValue((int)Value, sizeof(T));
+ incrStreamedLen(sizeof(T));
+ return Error::success();
+ }
+
if (isWriting())
return Writer->writeInteger(Value);
return Reader->readInteger(Value);
}
- template <typename T> Error mapEnum(T &Value) {
- if (sizeof(Value) > maxFieldLength())
+ template <typename T> Error mapEnum(T &Value, const Twine &Comment = "") {
+ if (!isStreaming() && sizeof(Value) > maxFieldLength())
return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
using U = typename std::underlying_type<T>::type;
U X;
- if (isWriting())
+
+ if (isWriting() || isStreaming())
X = static_cast<U>(Value);
- if (auto EC = mapInteger(X))
+ if (auto EC = mapInteger(X, Comment))
return EC;
+
if (isReading())
Value = static_cast<T>(X);
+
return Error::success();
}
- Error mapEncodedInteger(int64_t &Value);
- Error mapEncodedInteger(uint64_t &Value);
- Error mapEncodedInteger(APSInt &Value);
- Error mapStringZ(StringRef &Value);
- Error mapGuid(GUID &Guid);
+ Error mapEncodedInteger(int64_t &Value, const Twine &Comment = "");
+ Error mapEncodedInteger(uint64_t &Value, const Twine &Comment = "");
+ Error mapEncodedInteger(APSInt &Value, const Twine &Comment = "");
+ Error mapStringZ(StringRef &Value, const Twine &Comment = "");
+ Error mapGuid(GUID &Guid, const Twine &Comment = "");
- Error mapStringZVectorZ(std::vector<StringRef> &Value);
+ Error mapStringZVectorZ(std::vector<StringRef> &Value,
+ const Twine &Comment = "");
template <typename SizeType, typename T, typename ElementMapper>
- Error mapVectorN(T &Items, const ElementMapper &Mapper) {
+ Error mapVectorN(T &Items, const ElementMapper &Mapper,
+ const Twine &Comment = "") {
SizeType Size;
- if (isWriting()) {
+ if (isStreaming()) {
+ Size = static_cast<SizeType>(Items.size());
+ emitComment(Comment);
+ Streamer->EmitIntValue(Size, sizeof(Size));
+ incrStreamedLen(sizeof(Size)); // add 1 for the delimiter
+
+ for (auto &X : Items) {
+ if (auto EC = Mapper(*this, X))
+ return EC;
+ }
+ } else if (isWriting()) {
Size = static_cast<SizeType>(Items.size());
if (auto EC = Writer->writeInteger(Size))
return EC;
@@ -115,8 +173,10 @@ public:
}
template <typename T, typename ElementMapper>
- Error mapVectorTail(T &Items, const ElementMapper &Mapper) {
- if (isWriting()) {
+ Error mapVectorTail(T &Items, const ElementMapper &Mapper,
+ const Twine &Comment = "") {
+ emitComment(Comment);
+ if (isStreaming() || isWriting()) {
for (auto &Item : Items) {
if (auto EC = Mapper(*this, Item))
return EC;
@@ -133,16 +193,44 @@ public:
return Error::success();
}
- Error mapByteVectorTail(ArrayRef<uint8_t> &Bytes);
- Error mapByteVectorTail(std::vector<uint8_t> &Bytes);
+ Error mapByteVectorTail(ArrayRef<uint8_t> &Bytes, const Twine &Comment = "");
+ Error mapByteVectorTail(std::vector<uint8_t> &Bytes,
+ const Twine &Comment = "");
Error padToAlignment(uint32_t Align);
Error skipPadding();
+ uint64_t getStreamedLen() {
+ if (isStreaming())
+ return StreamedLen;
+ return 0;
+ }
+
private:
+ void emitEncodedSignedInteger(const int64_t &Value,
+ const Twine &Comment = "");
+ void emitEncodedUnsignedInteger(const uint64_t &Value,
+ const Twine &Comment = "");
Error writeEncodedSignedInteger(const int64_t &Value);
Error writeEncodedUnsignedInteger(const uint64_t &Value);
+ void incrStreamedLen(const uint64_t &Len) {
+ if (isStreaming())
+ StreamedLen += Len;
+ }
+
+ void resetStreamedLen() {
+ if (isStreaming())
+ StreamedLen = 4; // The record prefix is 4 bytes long
+ }
+
+ void emitComment(const Twine &Comment) {
+ if (isStreaming()) {
+ Twine TComment(Comment);
+ Streamer->AddComment(TComment);
+ }
+ }
+
struct RecordLimit {
uint32_t BeginOffset;
Optional<uint32_t> MaxLength;
@@ -163,6 +251,8 @@ private:
BinaryStreamReader *Reader = nullptr;
BinaryStreamWriter *Writer = nullptr;
+ CodeViewRecordStreamer *Streamer = nullptr;
+ uint64_t StreamedLen = 0;
};
} // end namespace codeview