1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
| //===-- BitstreamRemarkSerializer.h - Bitstream serializer ------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file provides an implementation of the serializer using the LLVM
// Bitstream format.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_REMARKS_BITSTREAM_REMARK_SERIALIZER_H
#define LLVM_REMARKS_BITSTREAM_REMARK_SERIALIZER_H
#include "llvm/Bitstream/BitstreamWriter.h"
#include "llvm/Remarks/BitstreamRemarkContainer.h"
#include "llvm/Remarks/RemarkSerializer.h"
#include "llvm/Support/raw_ostream.h"
namespace llvm {
namespace remarks {
/// Serialize the remarks to LLVM bitstream.
/// This class provides ways to emit remarks in the LLVM bitstream format and
/// its associated metadata.
///
/// * The separate model:
/// Separate meta: | Container info
/// | String table
/// | External file
///
/// Separate remarks: | Container info
/// | Remark version
/// | Remark0
/// | Remark1
/// | Remark2
/// | ...
///
/// * The standalone model: | Container info
/// | String table
/// | Remark version
/// | Remark0
/// | Remark1
/// | Remark2
/// | ...
///
struct BitstreamRemarkSerializerHelper {
/// Buffer used for encoding the bitstream before writing it to the final
/// stream.
SmallVector<char, 1024> Encoded;
/// Buffer used to construct records and pass to the bitstream writer.
SmallVector<uint64_t, 64> R;
/// The Bitstream writer.
BitstreamWriter Bitstream;
/// The type of the container we are serializing.
BitstreamRemarkContainerType ContainerType;
/// Abbrev IDs initialized in the block info block.
/// Note: depending on the container type, some IDs might be uninitialized.
/// Warning: When adding more abbrev IDs, make sure to update the
/// BlockCodeSize (in the call to EnterSubblock).
uint64_t RecordMetaContainerInfoAbbrevID = 0;
uint64_t RecordMetaRemarkVersionAbbrevID = 0;
uint64_t RecordMetaStrTabAbbrevID = 0;
uint64_t RecordMetaExternalFileAbbrevID = 0;
uint64_t RecordRemarkHeaderAbbrevID = 0;
uint64_t RecordRemarkDebugLocAbbrevID = 0;
uint64_t RecordRemarkHotnessAbbrevID = 0;
uint64_t RecordRemarkArgWithDebugLocAbbrevID = 0;
uint64_t RecordRemarkArgWithoutDebugLocAbbrevID = 0;
BitstreamRemarkSerializerHelper(BitstreamRemarkContainerType ContainerType);
// Disable copy and move: Bitstream points to Encoded, which needs special
// handling during copy/move, but moving the vectors is probably useless
// anyway.
BitstreamRemarkSerializerHelper(const BitstreamRemarkSerializerHelper &) =
delete;
BitstreamRemarkSerializerHelper &
operator=(const BitstreamRemarkSerializerHelper &) = delete;
BitstreamRemarkSerializerHelper(BitstreamRemarkSerializerHelper &&) = delete;
BitstreamRemarkSerializerHelper &
operator=(BitstreamRemarkSerializerHelper &&) = delete;
/// Set up the necessary block info entries according to the container type.
void setupBlockInfo();
/// Set up the block info for the metadata block.
void setupMetaBlockInfo();
/// The remark version in the metadata block.
void setupMetaRemarkVersion();
void emitMetaRemarkVersion(uint64_t RemarkVersion);
/// The strtab in the metadata block.
void setupMetaStrTab();
void emitMetaStrTab(const StringTable &StrTab);
/// The external file in the metadata block.
void setupMetaExternalFile();
void emitMetaExternalFile(StringRef Filename);
/// The block info for the remarks block.
void setupRemarkBlockInfo();
/// Emit the metadata for the remarks.
void emitMetaBlock(uint64_t ContainerVersion,
Optional<uint64_t> RemarkVersion,
Optional<const StringTable *> StrTab = None,
Optional<StringRef> Filename = None);
/// Emit a remark block. The string table is required.
void emitRemarkBlock(const Remark &Remark, StringTable &StrTab);
/// Finalize the writing to \p OS.
void flushToStream(raw_ostream &OS);
/// Finalize the writing to a buffer.
/// The contents of the buffer remain valid for the lifetime of the object.
/// Any call to any other function in this class will invalidate the buffer.
StringRef getBuffer();
};
/// Implementation of the remark serializer using LLVM bitstream.
struct BitstreamRemarkSerializer : public RemarkSerializer {
/// The file should contain:
/// 1) The block info block that describes how to read the blocks.
/// 2) The metadata block that contains various information about the remarks
/// in the file.
/// 3) A number of remark blocks.
/// We need to set up 1) and 2) first, so that we can emit 3) after. This flag
/// is used to emit the first two blocks only once.
bool DidSetUp = false;
/// The helper to emit bitstream.
BitstreamRemarkSerializerHelper Helper;
/// Construct a serializer that will create its own string table.
BitstreamRemarkSerializer(raw_ostream &OS, SerializerMode Mode);
/// Construct a serializer with a pre-filled string table.
BitstreamRemarkSerializer(raw_ostream &OS, SerializerMode Mode,
StringTable StrTab);
/// Emit a remark to the stream. This also emits the metadata associated to
/// the remarks based on the SerializerMode specified at construction.
/// This writes the serialized output to the provided stream.
void emit(const Remark &Remark) override;
/// The metadata serializer associated to this remark serializer. Based on the
/// container type of the current serializer, the container type of the
/// metadata serializer will change.
std::unique_ptr<MetaSerializer>
metaSerializer(raw_ostream &OS,
Optional<StringRef> ExternalFilename = None) override;
static bool classof(const RemarkSerializer *S) {
return S->SerializerFormat == Format::Bitstream;
}
};
/// Serializer of metadata for bitstream remarks.
struct BitstreamMetaSerializer : public MetaSerializer {
/// This class can be used with [1] a pre-constructed
/// BitstreamRemarkSerializerHelper, or with [2] one that is owned by the meta
/// serializer. In case of [1], we need to be able to store a reference to the
/// object, while in case of [2] we need to store the whole object.
Optional<BitstreamRemarkSerializerHelper> TmpHelper;
/// The actual helper, that can point to \p TmpHelper or to an external helper
/// object.
BitstreamRemarkSerializerHelper *Helper = nullptr;
Optional<const StringTable *> StrTab;
Optional<StringRef> ExternalFilename;
/// Create a new meta serializer based on \p ContainerType.
BitstreamMetaSerializer(raw_ostream &OS,
BitstreamRemarkContainerType ContainerType,
Optional<const StringTable *> StrTab = None,
Optional<StringRef> ExternalFilename = None)
: MetaSerializer(OS), TmpHelper(None), Helper(nullptr), StrTab(StrTab),
ExternalFilename(ExternalFilename) {
TmpHelper.emplace(ContainerType);
Helper = &*TmpHelper;
}
/// Create a new meta serializer based on a previously built \p Helper.
BitstreamMetaSerializer(raw_ostream &OS,
BitstreamRemarkSerializerHelper &Helper,
Optional<const StringTable *> StrTab = None,
Optional<StringRef> ExternalFilename = None)
: MetaSerializer(OS), TmpHelper(None), Helper(&Helper), StrTab(StrTab),
ExternalFilename(ExternalFilename) {}
void emit() override;
};
} // end namespace remarks
} // end namespace llvm
#endif /* LLVM_REMARKS_BITSTREAM_REMARK_SERIALIZER_H */
|