LLVM 24.0.0git
CodeViewRecordIO.h
Go to the documentation of this file.
1//===- CodeViewRecordIO.h ---------------------------------------*- C++ -*-===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_DEBUGINFO_CODEVIEW_CODEVIEWRECORDIO_H
10#define LLVM_DEBUGINFO_CODEVIEW_CODEVIEWRECORDIO_H
11
13#include "llvm/ADT/StringRef.h"
18#include "llvm/Support/Error.h"
19#include <cassert>
20#include <cstdint>
21#include <type_traits>
22
23namespace llvm {
24
25template <typename T> class ArrayRef;
26class APSInt;
27
28namespace codeview {
29class TypeIndex;
30struct GUID;
31
33public:
34 virtual void emitBytes(StringRef Data) = 0;
35 virtual void emitIntValue(uint64_t Value, unsigned Size) = 0;
36 virtual void emitBinaryData(StringRef Data) = 0;
37 virtual void AddComment(const Twine &T) = 0;
38 virtual void AddRawComment(const Twine &T) = 0;
39 virtual bool isVerboseAsm() = 0;
40 virtual std::string getTypeName(TypeIndex TI) = 0;
41 virtual ~CodeViewRecordStreamer() = default;
42};
43
45 uint32_t getCurrentOffset() const {
46 if (isWriting())
47 return Writer->getOffset();
48 else if (isReading())
49 return Reader->getOffset();
50 else
51 return 0;
52 }
53
54public:
55 // deserializes records to structures
56 explicit CodeViewRecordIO(BinaryStreamReader &Reader) : Reader(&Reader) {}
57
58 // serializes records to buffer
59 explicit CodeViewRecordIO(BinaryStreamWriter &Writer) : Writer(&Writer) {}
60
61 // writes records to assembly file using MC library interface
63 : Streamer(&Streamer) {}
64
65 LLVM_ABI Error beginRecord(std::optional<uint32_t> MaxLength);
67
68 LLVM_ABI Error mapInteger(TypeIndex &TypeInd, const Twine &Comment = "");
69
70 bool isStreaming() const {
71 return (Streamer != nullptr) && (Reader == nullptr) && (Writer == nullptr);
72 }
73 bool isReading() const {
74 return (Reader != nullptr) && (Streamer == nullptr) && (Writer == nullptr);
75 }
76 bool isWriting() const {
77 return (Writer != nullptr) && (Streamer == nullptr) && (Reader == nullptr);
78 }
79
81
82 template <typename T> Error mapObject(T &Value) {
83 if (isStreaming()) {
84 StringRef BytesSR =
85 StringRef((reinterpret_cast<const char *>(&Value)), sizeof(Value));
86 Streamer->emitBytes(BytesSR);
87 incrStreamedLen(sizeof(T));
88 return Error::success();
89 }
90
91 if (isWriting())
92 return Writer->writeObject(Value);
93
94 const T *ValuePtr;
95 if (auto EC = Reader->readObject(ValuePtr))
96 return EC;
97 Value = *ValuePtr;
98 return Error::success();
99 }
100
101 template <typename T> Error mapInteger(T &Value, const Twine &Comment = "") {
102 if (isStreaming()) {
103 emitComment(Comment);
104 Streamer->emitIntValue((int)Value, sizeof(T));
105 incrStreamedLen(sizeof(T));
106 return Error::success();
107 }
108
109 if (isWriting())
110 return Writer->writeInteger(Value);
111
112 return Reader->readInteger(Value);
113 }
114
115 template <typename Trunc, typename T>
116 Error mapTruncInteger(T &Value, const Twine &Comment = "") {
117 static_assert(sizeof(Trunc) <= sizeof(T));
118
119 Trunc Truncated = static_cast<Trunc>(Value);
120 auto EC = mapInteger(Truncated, Comment);
121 if (!EC && isReading())
122 Value = Truncated;
123
124 return EC;
125 }
126
127 template <typename T> Error mapEnum(T &Value, const Twine &Comment = "") {
128 if (!isStreaming() && sizeof(Value) > maxFieldLength())
130
131 using U = std::underlying_type_t<T>;
132 U X;
133
134 if (isWriting() || isStreaming())
135 X = static_cast<U>(Value);
136
137 if (auto EC = mapInteger(X, Comment))
138 return EC;
139
140 if (isReading())
141 Value = static_cast<T>(X);
142
143 return Error::success();
144 }
145
146 LLVM_ABI Error mapEncodedInteger(int64_t &Value, const Twine &Comment = "");
147 LLVM_ABI Error mapEncodedInteger(uint64_t &Value, const Twine &Comment = "");
148 LLVM_ABI Error mapEncodedInteger(APSInt &Value, const Twine &Comment = "");
149 LLVM_ABI Error mapStringZ(StringRef &Value, const Twine &Comment = "");
150 LLVM_ABI Error mapGuid(GUID &Guid, const Twine &Comment = "");
151
152 LLVM_ABI Error mapStringZVectorZ(std::vector<StringRef> &Value,
153 const Twine &Comment = "");
154
155 template <typename SizeType, typename T, typename ElementMapper>
156 Error mapVectorN(T &Items, const ElementMapper &Mapper,
157 const Twine &Comment = "") {
158 SizeType Size;
159 if (isStreaming()) {
160 Size = static_cast<SizeType>(Items.size());
161 emitComment(Comment);
162 Streamer->emitIntValue(Size, sizeof(Size));
163 incrStreamedLen(sizeof(Size)); // add 1 for the delimiter
164
165 for (auto &X : Items) {
166 if (auto EC = Mapper(*this, X))
167 return EC;
168 }
169 } else if (isWriting()) {
170 Size = static_cast<SizeType>(Items.size());
171 if (auto EC = Writer->writeInteger(Size))
172 return EC;
173
174 for (auto &X : Items) {
175 if (auto EC = Mapper(*this, X))
176 return EC;
177 }
178 } else {
179 if (auto EC = Reader->readInteger(Size))
180 return EC;
181 for (SizeType I = 0; I < Size; ++I) {
182 typename T::value_type Item;
183 if (auto EC = Mapper(*this, Item))
184 return EC;
185 Items.push_back(Item);
186 }
187 }
188
189 return Error::success();
190 }
191
192 template <typename T, typename ElementMapper>
193 Error mapVectorTail(T &Items, const ElementMapper &Mapper,
194 const Twine &Comment = "") {
195 emitComment(Comment);
196 if (isStreaming() || isWriting()) {
197 for (auto &Item : Items) {
198 if (auto EC = Mapper(*this, Item))
199 return EC;
200 }
201 } else {
202 typename T::value_type Field;
203 // Stop when we run out of bytes or we hit record padding bytes.
204 while (!Reader->empty() && Reader->peek() < 0xf0 /* LF_PAD0 */) {
205 if (auto EC = Mapper(*this, Field))
206 return EC;
207 Items.push_back(Field);
208 }
209 }
210 return Error::success();
211 }
212
214 const Twine &Comment = "");
215 LLVM_ABI Error mapByteVectorTail(std::vector<uint8_t> &Bytes,
216 const Twine &Comment = "");
217
220
222 if (isStreaming())
223 return StreamedLen;
224 return 0;
225 }
226
227 void emitRawComment(const Twine &T) {
228 if (isStreaming() && Streamer->isVerboseAsm())
229 Streamer->AddRawComment(T);
230 }
231
232private:
233 void emitEncodedSignedInteger(const int64_t &Value,
234 const Twine &Comment = "");
235 void emitEncodedUnsignedInteger(const uint64_t &Value,
236 const Twine &Comment = "");
237 Error writeEncodedSignedInteger(const int64_t &Value);
238 Error writeEncodedUnsignedInteger(const uint64_t &Value);
239
240 void incrStreamedLen(const uint64_t &Len) {
241 if (isStreaming())
242 StreamedLen += Len;
243 }
244
245 void resetStreamedLen() {
246 if (isStreaming())
247 StreamedLen = 4; // The record prefix is 4 bytes long
248 }
249
250 void emitComment(const Twine &Comment) {
251 if (isStreaming() && Streamer->isVerboseAsm()) {
252 Twine TComment(Comment);
253 if (!TComment.isTriviallyEmpty())
254 Streamer->AddComment(TComment);
255 }
256 }
257
258 struct RecordLimit {
259 uint32_t BeginOffset;
260 std::optional<uint32_t> MaxLength;
261
262 std::optional<uint32_t> bytesRemaining(uint32_t CurrentOffset) const {
263 if (!MaxLength)
264 return std::nullopt;
265 assert(CurrentOffset >= BeginOffset);
266
267 uint32_t BytesUsed = CurrentOffset - BeginOffset;
268 if (BytesUsed >= *MaxLength)
269 return 0;
270 return *MaxLength - BytesUsed;
271 }
272 };
273
274 SmallVector<RecordLimit, 2> Limits;
275
276 BinaryStreamReader *Reader = nullptr;
277 BinaryStreamWriter *Writer = nullptr;
278 CodeViewRecordStreamer *Streamer = nullptr;
279 uint64_t StreamedLen = 0;
280};
281
282} // end namespace codeview
283} // end namespace llvm
284
285#endif // LLVM_DEBUGINFO_CODEVIEW_CODEVIEWRECORDIO_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned uint64_t
#define X(NUM, ENUM, NAME)
Definition ELF.h:857
#define LLVM_ABI
Definition Compiler.h:215
#define I(x, y, z)
Definition MD5.cpp:57
#define T
OptimizedStructLayoutField Field
This file defines the SmallVector class.
std::unique_ptr< MCStreamer > && Streamer
An arbitrary precision integer that knows its signedness.
Definition APSInt.h:24
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
Provides read only access to a subclass of BinaryStream.
Provides write only access to a subclass of WritableBinaryStream.
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
static ErrorSuccess success()
Create a success value.
Definition Error.h:336
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
LLVM Value Representation.
Definition Value.h:75
Error mapVectorTail(T &Items, const ElementMapper &Mapper, const Twine &Comment="")
CodeViewRecordIO(BinaryStreamWriter &Writer)
LLVM_ABI Error padToAlignment(uint32_t Align)
Error mapVectorN(T &Items, const ElementMapper &Mapper, const Twine &Comment="")
Error mapInteger(T &Value, const Twine &Comment="")
LLVM_ABI Error mapInteger(TypeIndex &TypeInd, const Twine &Comment="")
CodeViewRecordIO(BinaryStreamReader &Reader)
LLVM_ABI Error mapGuid(GUID &Guid, const Twine &Comment="")
LLVM_ABI Error mapStringZVectorZ(std::vector< StringRef > &Value, const Twine &Comment="")
LLVM_ABI Error mapStringZ(StringRef &Value, const Twine &Comment="")
Error mapEnum(T &Value, const Twine &Comment="")
LLVM_ABI Error mapEncodedInteger(int64_t &Value, const Twine &Comment="")
Error mapTruncInteger(T &Value, const Twine &Comment="")
LLVM_ABI Error beginRecord(std::optional< uint32_t > MaxLength)
LLVM_ABI Error mapByteVectorTail(ArrayRef< uint8_t > &Bytes, const Twine &Comment="")
CodeViewRecordIO(CodeViewRecordStreamer &Streamer)
LLVM_ABI uint32_t maxFieldLength() const
virtual void emitBytes(StringRef Data)=0
virtual void AddComment(const Twine &T)=0
virtual void emitIntValue(uint64_t Value, unsigned Size)=0
virtual void emitBinaryData(StringRef Data)=0
virtual std::string getTypeName(TypeIndex TI)=0
virtual void AddRawComment(const Twine &T)=0
A 32-bit type reference.
Definition TypeIndex.h:97
This is an optimization pass for GlobalISel generic memory operations.
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
Definition Error.h:340
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
This represents the 'GUID' type from windows.h.
Definition GUID.h:22