1 //===- CodeViewRecordIO.h ---------------------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_DEBUGINFO_CODEVIEW_CODEVIEWRECORDIO_H
10 #define LLVM_DEBUGINFO_CODEVIEW_CODEVIEWRECORDIO_H
12 #include "llvm/ADT/APSInt.h"
13 #include "llvm/ADT/None.h"
14 #include "llvm/ADT/Optional.h"
15 #include "llvm/ADT/SmallVector.h"
16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/DebugInfo/CodeView/CodeViewError.h"
18 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
19 #include "llvm/Support/BinaryStreamReader.h"
20 #include "llvm/Support/BinaryStreamWriter.h"
21 #include "llvm/Support/Error.h"
24 #include <type_traits>
29 class CodeViewRecordIO
{
30 uint32_t getCurrentOffset() const {
31 return (isWriting()) ? Writer
->getOffset() : Reader
->getOffset();
35 explicit CodeViewRecordIO(BinaryStreamReader
&Reader
) : Reader(&Reader
) {}
36 explicit CodeViewRecordIO(BinaryStreamWriter
&Writer
) : Writer(&Writer
) {}
38 Error
beginRecord(Optional
<uint32_t> MaxLength
);
41 Error
mapInteger(TypeIndex
&TypeInd
);
43 bool isReading() const { return Reader
!= nullptr; }
44 bool isWriting() const { return !isReading(); }
46 uint32_t maxFieldLength() const;
48 template <typename T
> Error
mapObject(T
&Value
) {
50 return Writer
->writeObject(Value
);
53 if (auto EC
= Reader
->readObject(ValuePtr
))
56 return Error::success();
59 template <typename T
> Error
mapInteger(T
&Value
) {
61 return Writer
->writeInteger(Value
);
63 return Reader
->readInteger(Value
);
66 template <typename T
> Error
mapEnum(T
&Value
) {
67 if (sizeof(Value
) > maxFieldLength())
68 return make_error
<CodeViewError
>(cv_error_code::insufficient_buffer
);
70 using U
= typename
std::underlying_type
<T
>::type
;
73 X
= static_cast<U
>(Value
);
75 if (auto EC
= mapInteger(X
))
78 Value
= static_cast<T
>(X
);
79 return Error::success();
82 Error
mapEncodedInteger(int64_t &Value
);
83 Error
mapEncodedInteger(uint64_t &Value
);
84 Error
mapEncodedInteger(APSInt
&Value
);
85 Error
mapStringZ(StringRef
&Value
);
86 Error
mapGuid(GUID
&Guid
);
88 Error
mapStringZVectorZ(std::vector
<StringRef
> &Value
);
90 template <typename SizeType
, typename T
, typename ElementMapper
>
91 Error
mapVectorN(T
&Items
, const ElementMapper
&Mapper
) {
94 Size
= static_cast<SizeType
>(Items
.size());
95 if (auto EC
= Writer
->writeInteger(Size
))
98 for (auto &X
: Items
) {
99 if (auto EC
= Mapper(*this, X
))
103 if (auto EC
= Reader
->readInteger(Size
))
105 for (SizeType I
= 0; I
< Size
; ++I
) {
106 typename
T::value_type Item
;
107 if (auto EC
= Mapper(*this, Item
))
109 Items
.push_back(Item
);
113 return Error::success();
116 template <typename T
, typename ElementMapper
>
117 Error
mapVectorTail(T
&Items
, const ElementMapper
&Mapper
) {
119 for (auto &Item
: Items
) {
120 if (auto EC
= Mapper(*this, Item
))
124 typename
T::value_type Field
;
125 // Stop when we run out of bytes or we hit record padding bytes.
126 while (!Reader
->empty() && Reader
->peek() < 0xf0 /* LF_PAD0 */) {
127 if (auto EC
= Mapper(*this, Field
))
129 Items
.push_back(Field
);
132 return Error::success();
135 Error
mapByteVectorTail(ArrayRef
<uint8_t> &Bytes
);
136 Error
mapByteVectorTail(std::vector
<uint8_t> &Bytes
);
138 Error
padToAlignment(uint32_t Align
);
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 BinaryStreamReader
*Reader
= nullptr;
164 BinaryStreamWriter
*Writer
= nullptr;
167 } // end namespace codeview
168 } // end namespace llvm
170 #endif // LLVM_DEBUGINFO_CODEVIEW_CODEVIEWRECORDIO_H