LLVM  6.0.0svn
TypeSerializer.h
Go to the documentation of this file.
1 //===- TypeSerializer.h -----------------------------------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef LLVM_DEBUGINFO_CODEVIEW_TYPESERIALIZER_H
11 #define LLVM_DEBUGINFO_CODEVIEW_TYPESERIALIZER_H
12 
13 #include "llvm/ADT/ArrayRef.h"
14 #include "llvm/ADT/Optional.h"
15 #include "llvm/ADT/SmallVector.h"
22 #include "llvm/Support/Allocator.h"
25 #include "llvm/Support/Error.h"
26 #include <cassert>
27 #include <cstdint>
28 #include <memory>
29 #include <vector>
30 
31 namespace llvm {
32 namespace codeview {
33 
34 class TypeHasher;
35 
37  struct SubRecord {
38  SubRecord(TypeLeafKind K, uint32_t S) : Kind(K), Size(S) {}
39 
41  uint32_t Size = 0;
42  };
43  struct RecordSegment {
44  SmallVector<SubRecord, 16> SubRecords;
45 
46  uint32_t length() const {
47  uint32_t L = sizeof(RecordPrefix);
48  for (const auto &R : SubRecords) {
49  L += R.Size;
50  }
51  return L;
52  }
53  };
54 
56 
57  static constexpr uint8_t ContinuationLength = 8;
58  BumpPtrAllocator &RecordStorage;
59  RecordSegment CurrentSegment;
60  MutableRecordList FieldListSegments;
61 
62  Optional<TypeLeafKind> TypeKind;
63  Optional<TypeLeafKind> MemberKind;
64  std::vector<uint8_t> RecordBuffer;
66  BinaryStreamWriter Writer;
67  TypeRecordMapping Mapping;
68 
69  /// Private type record hashing implementation details are handled here.
70  std::unique_ptr<TypeHasher> Hasher;
71 
72  /// Contains a list of all records indexed by TypeIndex.toArrayIndex().
73  SmallVector<ArrayRef<uint8_t>, 2> SeenRecords;
74 
75  /// Temporary storage that we use to copy a record's data while re-writing
76  /// its type indices.
77  SmallVector<uint8_t, 256> RemapStorage;
78 
79  TypeIndex nextTypeIndex() const;
80 
81  bool isInFieldList() const;
82  MutableArrayRef<uint8_t> getCurrentSubRecordData();
83  MutableArrayRef<uint8_t> getCurrentRecordData();
84  Error writeRecordPrefix(TypeLeafKind Kind);
85 
87  addPadding(MutableArrayRef<uint8_t> Record);
88 
89 public:
90  explicit TypeSerializer(BumpPtrAllocator &Storage, bool Hash = true);
91  ~TypeSerializer() override;
92 
93  void reset();
94 
95  BumpPtrAllocator &getAllocator() { return RecordStorage; }
96 
99  TypeIndex insertRecord(const RemappedType &Record);
101 
103  Error visitTypeBegin(CVType &Record) override;
104  Error visitTypeEnd(CVType &Record) override;
105  Error visitMemberBegin(CVMemberRecord &Record) override;
106  Error visitMemberEnd(CVMemberRecord &Record) override;
107 
108 #define TYPE_RECORD(EnumName, EnumVal, Name) \
109  virtual Error visitKnownRecord(CVType &CVR, Name##Record &Record) override { \
110  return visitKnownRecordImpl(CVR, Record); \
111  }
112 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
113 #define MEMBER_RECORD(EnumName, EnumVal, Name) \
114  Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override { \
115  return visitKnownMemberImpl<Name##Record>(CVR, Record); \
116  }
117 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
118 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
119 
120 private:
121  template <typename RecordKind>
122  Error visitKnownRecordImpl(CVType &CVR, RecordKind &Record) {
123  return Mapping.visitKnownRecord(CVR, Record);
124  }
125 
126  template <typename RecordType>
127  Error visitKnownMemberImpl(CVMemberRecord &CVR, RecordType &Record) {
128  assert(CVR.Kind == static_cast<TypeLeafKind>(Record.getKind()));
129 
130  if (auto EC = Writer.writeEnum(CVR.Kind))
131  return EC;
132 
133  if (auto EC = Mapping.visitKnownMember(CVR, Record))
134  return EC;
135 
136  // Get all the data that was just written and is yet to be committed to
137  // the current segment. Then pad it to 4 bytes.
138  MutableArrayRef<uint8_t> ThisRecord = getCurrentSubRecordData();
139  auto ExpectedRecord = addPadding(ThisRecord);
140  if (!ExpectedRecord)
141  return ExpectedRecord.takeError();
142  ThisRecord = *ExpectedRecord;
143 
144  CurrentSegment.SubRecords.emplace_back(CVR.Kind, ThisRecord.size());
145  CVR.Data = ThisRecord;
146 
147  // Both the last subrecord and the total length of this segment should be
148  // multiples of 4.
149  assert(ThisRecord.size() % 4 == 0);
150  assert(CurrentSegment.length() % 4 == 0);
151 
152  return Error::success();
153  }
154 };
155 
156 } // end namespace codeview
157 } // end namespace llvm
158 
159 #endif // LLVM_DEBUGINFO_CODEVIEW_TYPESERIALIZER_H
An implementation of BinaryStream which holds its entire data set in a single contiguous buffer...
Compute iterated dominance frontiers using a linear time algorithm.
Definition: AllocatorList.h:24
TypeLeafKind
Duplicate copy of the above enum, but using the official CV names.
Definition: CodeView.h:34
Error visitMemberBegin(CVMemberRecord &Record) override
TypeIndex insertRecord(const RemappedType &Record)
Error visitTypeEnd(CVType &Record) override
ArrayRef< ArrayRef< uint8_t > > records() const
CVRecord< TypeLeafKind > CVType
Definition: TypeRecord.h:36
This file defines the MallocAllocator and BumpPtrAllocator interfaces.
Tagged union holding either a T or a Error.
Definition: CachePruning.h:23
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Definition: APInt.h:33
A 32-bit type reference.
Definition: TypeIndex.h:96
Error visitTypeBegin(CVType &Record) override
Paired begin/end actions for all types.
Allocate memory in an ever growing pool, as if by bump-pointer.
Definition: Allocator.h:138
Provides write only access to a subclass of WritableBinaryStream.
static ErrorSuccess success()
Create a success value.
Definition: Error.h:313
virtual Error visitTypeBegin(CVType &Record)
Paired begin/end actions for all types.
Error writeEnum(T Num)
Similar to writeInteger.
Error visitMemberEnd(CVMemberRecord &Record) override
const unsigned Kind
BumpPtrAllocator & getAllocator()
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
constexpr char Size[]
Key for Kernel::Arg::Metadata::mSize.
Lightweight error class with error context and mandatory checking.
Definition: Error.h:156
TypeIndex insertRecordBytes(ArrayRef< uint8_t > &Record)
Expected< TypeIndex > visitTypeEndGetIndex(CVType &Record)
TypeSerializer(BumpPtrAllocator &Storage, bool Hash=true)