diff options
Diffstat (limited to 'include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h')
-rw-r--r-- | include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h | 140 |
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 |