1 //===- CodeViewRecordIO.h ---------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #ifndef LLVM_DEBUGINFO_CODEVIEW_CODEVIEWRECORDIO_H
11 #define LLVM_DEBUGINFO_CODEVIEW_CODEVIEWRECORDIO_H
13 #include "llvm/ADT/APSInt.h"
14 #include "llvm/ADT/None.h"
15 #include "llvm/ADT/Optional.h"
16 #include "llvm/ADT/SmallVector.h"
17 #include "llvm/ADT/StringRef.h"
18 #include "llvm/DebugInfo/CodeView/CodeViewError.h"
19 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
20 #include "llvm/DebugInfo/MSF/StreamReader.h"
21 #include "llvm/DebugInfo/MSF/StreamWriter.h"
22 #include "llvm/Support/Error.h"
25 #include <type_traits>
30 class CodeViewRecordIO {
31 uint32_t getCurrentOffset() const {
32 return (isWriting()) ? Writer->getOffset() : Reader->getOffset();
36 explicit CodeViewRecordIO(msf::StreamReader &Reader) : Reader(&Reader) {}
37 explicit CodeViewRecordIO(msf::StreamWriter &Writer) : Writer(&Writer) {}
39 Error beginRecord(Optional<uint32_t> MaxLength);
42 Error mapInteger(TypeIndex &TypeInd);
44 bool isReading() const { return Reader != nullptr; }
45 bool isWriting() const { return !isReading(); }
47 uint32_t maxFieldLength() const;
49 template <typename T> Error mapObject(T &Value) {
51 return Writer->writeObject(Value);
54 if (auto EC = Reader->readObject(ValuePtr))
57 return Error::success();
60 template <typename T> Error mapInteger(T &Value) {
62 return Writer->writeInteger(Value);
64 return Reader->readInteger(Value);
67 template <typename T> Error mapEnum(T &Value) {
68 if (sizeof(Value) > maxFieldLength())
69 return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
71 using U = typename std::underlying_type<T>::type;
74 X = static_cast<U>(Value);
76 if (auto EC = mapInteger(X))
79 Value = static_cast<T>(X);
80 return Error::success();
83 Error mapEncodedInteger(int64_t &Value);
84 Error mapEncodedInteger(uint64_t &Value);
85 Error mapEncodedInteger(APSInt &Value);
86 Error mapStringZ(StringRef &Value);
87 Error mapGuid(StringRef &Guid);
89 Error mapStringZVectorZ(std::vector<StringRef> &Value);
91 template <typename SizeType, typename T, typename ElementMapper>
92 Error mapVectorN(T &Items, const ElementMapper &Mapper) {
95 Size = static_cast<SizeType>(Items.size());
96 if (auto EC = Writer->writeInteger(Size))
99 for (auto &X : Items) {
100 if (auto EC = Mapper(*this, X))
104 if (auto EC = Reader->readInteger(Size))
106 for (SizeType I = 0; I < Size; ++I) {
107 typename T::value_type Item;
108 if (auto EC = Mapper(*this, Item))
110 Items.push_back(Item);
114 return Error::success();
117 template <typename T, typename ElementMapper>
118 Error mapVectorTail(T &Items, const ElementMapper &Mapper) {
120 for (auto &Item : Items) {
121 if (auto EC = Mapper(*this, Item))
125 typename T::value_type Field;
126 // Stop when we run out of bytes or we hit record padding bytes.
127 while (!Reader->empty() && Reader->peek() < 0xf0 /* LF_PAD0 */) {
128 if (auto EC = Mapper(*this, Field))
130 Items.push_back(Field);
133 return Error::success();
136 Error mapByteVectorTail(ArrayRef<uint8_t> &Bytes);
137 Error mapByteVectorTail(std::vector<uint8_t> &Bytes);
142 Error writeEncodedSignedInteger(const int64_t &Value);
143 Error writeEncodedUnsignedInteger(const uint64_t &Value);
146 uint32_t BeginOffset;
147 Optional<uint32_t> MaxLength;
149 Optional<uint32_t> bytesRemaining(uint32_t CurrentOffset) const {
150 if (!MaxLength.hasValue())
152 assert(CurrentOffset >= BeginOffset);
154 uint32_t BytesUsed = CurrentOffset - BeginOffset;
155 if (BytesUsed >= *MaxLength)
157 return *MaxLength - BytesUsed;
161 SmallVector<RecordLimit, 2> Limits;
163 msf::StreamReader *Reader = nullptr;
164 msf::StreamWriter *Writer = nullptr;
167 } // end namespace codeview
168 } // end namespace llvm
170 #endif // LLVM_DEBUGINFO_CODEVIEW_CODEVIEWRECORDIO_H