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