Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 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/SmallVector.h"
13
#include "llvm/ADT/StringRef.h"
14
#include "llvm/DebugInfo/CodeView/CodeViewError.h"
15
#include "llvm/Support/BinaryStreamReader.h"
16
#include "llvm/Support/BinaryStreamWriter.h"
17
#include "llvm/Support/Error.h"
18
#include <cassert>
19
#include <cstdint>
20
#include <type_traits>
21
 
22
namespace llvm {
23
 
24
template <typename T> class ArrayRef;
25
class APSInt;
26
 
27
namespace codeview {
28
class TypeIndex;
29
struct GUID;
30
 
31
class CodeViewRecordStreamer {
32
public:
33
  virtual void emitBytes(StringRef Data) = 0;
34
  virtual void emitIntValue(uint64_t Value, unsigned Size) = 0;
35
  virtual void emitBinaryData(StringRef Data) = 0;
36
  virtual void AddComment(const Twine &T) = 0;
37
  virtual void AddRawComment(const Twine &T) = 0;
38
  virtual bool isVerboseAsm() = 0;
39
  virtual std::string getTypeName(TypeIndex TI) = 0;
40
  virtual ~CodeViewRecordStreamer() = default;
41
};
42
 
43
class CodeViewRecordIO {
44
  uint32_t getCurrentOffset() const {
45
    if (isWriting())
46
      return Writer->getOffset();
47
    else if (isReading())
48
      return Reader->getOffset();
49
    else
50
      return 0;
51
  }
52
 
53
public:
54
  // deserializes records to structures
55
  explicit CodeViewRecordIO(BinaryStreamReader &Reader) : Reader(&Reader) {}
56
 
57
  // serializes records to buffer
58
  explicit CodeViewRecordIO(BinaryStreamWriter &Writer) : Writer(&Writer) {}
59
 
60
  // writes records to assembly file using MC library interface
61
  explicit CodeViewRecordIO(CodeViewRecordStreamer &Streamer)
62
      : Streamer(&Streamer) {}
63
 
64
  Error beginRecord(std::optional<uint32_t> MaxLength);
65
  Error endRecord();
66
 
67
  Error mapInteger(TypeIndex &TypeInd, const Twine &Comment = "");
68
 
69
  bool isStreaming() const {
70
    return (Streamer != nullptr) && (Reader == nullptr) && (Writer == nullptr);
71
  }
72
  bool isReading() const {
73
    return (Reader != nullptr) && (Streamer == nullptr) && (Writer == nullptr);
74
  }
75
  bool isWriting() const {
76
    return (Writer != nullptr) && (Streamer == nullptr) && (Reader == nullptr);
77
  }
78
 
79
  uint32_t maxFieldLength() const;
80
 
81
  template <typename T> Error mapObject(T &Value) {
82
    if (isStreaming()) {
83
      StringRef BytesSR =
84
          StringRef((reinterpret_cast<const char *>(&Value)), sizeof(Value));
85
      Streamer->emitBytes(BytesSR);
86
      incrStreamedLen(sizeof(T));
87
      return Error::success();
88
    }
89
 
90
    if (isWriting())
91
      return Writer->writeObject(Value);
92
 
93
    const T *ValuePtr;
94
    if (auto EC = Reader->readObject(ValuePtr))
95
      return EC;
96
    Value = *ValuePtr;
97
    return Error::success();
98
  }
99
 
100
  template <typename T> Error mapInteger(T &Value, const Twine &Comment = "") {
101
    if (isStreaming()) {
102
      emitComment(Comment);
103
      Streamer->emitIntValue((int)Value, sizeof(T));
104
      incrStreamedLen(sizeof(T));
105
      return Error::success();
106
    }
107
 
108
    if (isWriting())
109
      return Writer->writeInteger(Value);
110
 
111
    return Reader->readInteger(Value);
112
  }
113
 
114
  template <typename T> Error mapEnum(T &Value, const Twine &Comment = "") {
115
    if (!isStreaming() && sizeof(Value) > maxFieldLength())
116
      return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
117
 
118
    using U = std::underlying_type_t<T>;
119
    U X;
120
 
121
    if (isWriting() || isStreaming())
122
      X = static_cast<U>(Value);
123
 
124
    if (auto EC = mapInteger(X, Comment))
125
      return EC;
126
 
127
    if (isReading())
128
      Value = static_cast<T>(X);
129
 
130
    return Error::success();
131
  }
132
 
133
  Error mapEncodedInteger(int64_t &Value, const Twine &Comment = "");
134
  Error mapEncodedInteger(uint64_t &Value, const Twine &Comment = "");
135
  Error mapEncodedInteger(APSInt &Value, const Twine &Comment = "");
136
  Error mapStringZ(StringRef &Value, const Twine &Comment = "");
137
  Error mapGuid(GUID &Guid, const Twine &Comment = "");
138
 
139
  Error mapStringZVectorZ(std::vector<StringRef> &Value,
140
                          const Twine &Comment = "");
141
 
142
  template <typename SizeType, typename T, typename ElementMapper>
143
  Error mapVectorN(T &Items, const ElementMapper &Mapper,
144
                   const Twine &Comment = "") {
145
    SizeType Size;
146
    if (isStreaming()) {
147
      Size = static_cast<SizeType>(Items.size());
148
      emitComment(Comment);
149
      Streamer->emitIntValue(Size, sizeof(Size));
150
      incrStreamedLen(sizeof(Size)); // add 1 for the delimiter
151
 
152
      for (auto &X : Items) {
153
        if (auto EC = Mapper(*this, X))
154
          return EC;
155
      }
156
    } else if (isWriting()) {
157
      Size = static_cast<SizeType>(Items.size());
158
      if (auto EC = Writer->writeInteger(Size))
159
        return EC;
160
 
161
      for (auto &X : Items) {
162
        if (auto EC = Mapper(*this, X))
163
          return EC;
164
      }
165
    } else {
166
      if (auto EC = Reader->readInteger(Size))
167
        return EC;
168
      for (SizeType I = 0; I < Size; ++I) {
169
        typename T::value_type Item;
170
        if (auto EC = Mapper(*this, Item))
171
          return EC;
172
        Items.push_back(Item);
173
      }
174
    }
175
 
176
    return Error::success();
177
  }
178
 
179
  template <typename T, typename ElementMapper>
180
  Error mapVectorTail(T &Items, const ElementMapper &Mapper,
181
                      const Twine &Comment = "") {
182
    emitComment(Comment);
183
    if (isStreaming() || isWriting()) {
184
      for (auto &Item : Items) {
185
        if (auto EC = Mapper(*this, Item))
186
          return EC;
187
      }
188
    } else {
189
      typename T::value_type Field;
190
      // Stop when we run out of bytes or we hit record padding bytes.
191
      while (!Reader->empty() && Reader->peek() < 0xf0 /* LF_PAD0 */) {
192
        if (auto EC = Mapper(*this, Field))
193
          return EC;
194
        Items.push_back(Field);
195
      }
196
    }
197
    return Error::success();
198
  }
199
 
200
  Error mapByteVectorTail(ArrayRef<uint8_t> &Bytes, const Twine &Comment = "");
201
  Error mapByteVectorTail(std::vector<uint8_t> &Bytes,
202
                          const Twine &Comment = "");
203
 
204
  Error padToAlignment(uint32_t Align);
205
  Error skipPadding();
206
 
207
  uint64_t getStreamedLen() {
208
    if (isStreaming())
209
      return StreamedLen;
210
    return 0;
211
  }
212
 
213
  void emitRawComment(const Twine &T) {
214
    if (isStreaming() && Streamer->isVerboseAsm())
215
      Streamer->AddRawComment(T);
216
  }
217
 
218
private:
219
  void emitEncodedSignedInteger(const int64_t &Value,
220
                                const Twine &Comment = "");
221
  void emitEncodedUnsignedInteger(const uint64_t &Value,
222
                                  const Twine &Comment = "");
223
  Error writeEncodedSignedInteger(const int64_t &Value);
224
  Error writeEncodedUnsignedInteger(const uint64_t &Value);
225
 
226
  void incrStreamedLen(const uint64_t &Len) {
227
    if (isStreaming())
228
      StreamedLen += Len;
229
  }
230
 
231
  void resetStreamedLen() {
232
    if (isStreaming())
233
      StreamedLen = 4; // The record prefix is 4 bytes long
234
  }
235
 
236
  void emitComment(const Twine &Comment) {
237
    if (isStreaming() && Streamer->isVerboseAsm()) {
238
      Twine TComment(Comment);
239
      if (!TComment.isTriviallyEmpty())
240
        Streamer->AddComment(TComment);
241
    }
242
  }
243
 
244
  struct RecordLimit {
245
    uint32_t BeginOffset;
246
    std::optional<uint32_t> MaxLength;
247
 
248
    std::optional<uint32_t> bytesRemaining(uint32_t CurrentOffset) const {
249
      if (!MaxLength)
250
        return std::nullopt;
251
      assert(CurrentOffset >= BeginOffset);
252
 
253
      uint32_t BytesUsed = CurrentOffset - BeginOffset;
254
      if (BytesUsed >= *MaxLength)
255
        return 0;
256
      return *MaxLength - BytesUsed;
257
    }
258
  };
259
 
260
  SmallVector<RecordLimit, 2> Limits;
261
 
262
  BinaryStreamReader *Reader = nullptr;
263
  BinaryStreamWriter *Writer = nullptr;
264
  CodeViewRecordStreamer *Streamer = nullptr;
265
  uint64_t StreamedLen = 0;
266
};
267
 
268
} // end namespace codeview
269
} // end namespace llvm
270
 
271
#endif // LLVM_DEBUGINFO_CODEVIEW_CODEVIEWRECORDIO_H