Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Remarks/BitstreamRemarkSerializer.cpp
35262 views
1
//===- BitstreamRemarkSerializer.cpp --------------------------------------===//
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
// This file provides the implementation of the LLVM bitstream remark serializer
10
// using LLVM's bitstream writer.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "llvm/Remarks/BitstreamRemarkSerializer.h"
15
#include "llvm/Remarks/Remark.h"
16
#include <optional>
17
18
using namespace llvm;
19
using namespace llvm::remarks;
20
21
BitstreamRemarkSerializerHelper::BitstreamRemarkSerializerHelper(
22
BitstreamRemarkContainerType ContainerType)
23
: Bitstream(Encoded), ContainerType(ContainerType) {}
24
25
static void push(SmallVectorImpl<uint64_t> &R, StringRef Str) {
26
append_range(R, Str);
27
}
28
29
static void setRecordName(unsigned RecordID, BitstreamWriter &Bitstream,
30
SmallVectorImpl<uint64_t> &R, StringRef Str) {
31
R.clear();
32
R.push_back(RecordID);
33
push(R, Str);
34
Bitstream.EmitRecord(bitc::BLOCKINFO_CODE_SETRECORDNAME, R);
35
}
36
37
static void initBlock(unsigned BlockID, BitstreamWriter &Bitstream,
38
SmallVectorImpl<uint64_t> &R, StringRef Str) {
39
R.clear();
40
R.push_back(BlockID);
41
Bitstream.EmitRecord(bitc::BLOCKINFO_CODE_SETBID, R);
42
43
R.clear();
44
push(R, Str);
45
Bitstream.EmitRecord(bitc::BLOCKINFO_CODE_BLOCKNAME, R);
46
}
47
48
void BitstreamRemarkSerializerHelper::setupMetaBlockInfo() {
49
// Setup the metadata block.
50
initBlock(META_BLOCK_ID, Bitstream, R, MetaBlockName);
51
52
// The container information.
53
setRecordName(RECORD_META_CONTAINER_INFO, Bitstream, R,
54
MetaContainerInfoName);
55
56
auto Abbrev = std::make_shared<BitCodeAbbrev>();
57
Abbrev->Add(BitCodeAbbrevOp(RECORD_META_CONTAINER_INFO));
58
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Version.
59
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Type.
60
RecordMetaContainerInfoAbbrevID =
61
Bitstream.EmitBlockInfoAbbrev(META_BLOCK_ID, Abbrev);
62
}
63
64
void BitstreamRemarkSerializerHelper::setupMetaRemarkVersion() {
65
setRecordName(RECORD_META_REMARK_VERSION, Bitstream, R,
66
MetaRemarkVersionName);
67
68
auto Abbrev = std::make_shared<BitCodeAbbrev>();
69
Abbrev->Add(BitCodeAbbrevOp(RECORD_META_REMARK_VERSION));
70
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Version.
71
RecordMetaRemarkVersionAbbrevID =
72
Bitstream.EmitBlockInfoAbbrev(META_BLOCK_ID, Abbrev);
73
}
74
75
void BitstreamRemarkSerializerHelper::emitMetaRemarkVersion(
76
uint64_t RemarkVersion) {
77
// The remark version is emitted only if we emit remarks.
78
R.clear();
79
R.push_back(RECORD_META_REMARK_VERSION);
80
R.push_back(RemarkVersion);
81
Bitstream.EmitRecordWithAbbrev(RecordMetaRemarkVersionAbbrevID, R);
82
}
83
84
void BitstreamRemarkSerializerHelper::setupMetaStrTab() {
85
setRecordName(RECORD_META_STRTAB, Bitstream, R, MetaStrTabName);
86
87
auto Abbrev = std::make_shared<BitCodeAbbrev>();
88
Abbrev->Add(BitCodeAbbrevOp(RECORD_META_STRTAB));
89
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Raw table.
90
RecordMetaStrTabAbbrevID =
91
Bitstream.EmitBlockInfoAbbrev(META_BLOCK_ID, Abbrev);
92
}
93
94
void BitstreamRemarkSerializerHelper::emitMetaStrTab(
95
const StringTable &StrTab) {
96
// The string table is not emitted if we emit remarks separately.
97
R.clear();
98
R.push_back(RECORD_META_STRTAB);
99
100
// Serialize to a blob.
101
std::string Buf;
102
raw_string_ostream OS(Buf);
103
StrTab.serialize(OS);
104
StringRef Blob = OS.str();
105
Bitstream.EmitRecordWithBlob(RecordMetaStrTabAbbrevID, R, Blob);
106
}
107
108
void BitstreamRemarkSerializerHelper::setupMetaExternalFile() {
109
setRecordName(RECORD_META_EXTERNAL_FILE, Bitstream, R, MetaExternalFileName);
110
111
auto Abbrev = std::make_shared<BitCodeAbbrev>();
112
Abbrev->Add(BitCodeAbbrevOp(RECORD_META_EXTERNAL_FILE));
113
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Filename.
114
RecordMetaExternalFileAbbrevID =
115
Bitstream.EmitBlockInfoAbbrev(META_BLOCK_ID, Abbrev);
116
}
117
118
void BitstreamRemarkSerializerHelper::emitMetaExternalFile(StringRef Filename) {
119
// The external file is emitted only if we emit the separate metadata.
120
R.clear();
121
R.push_back(RECORD_META_EXTERNAL_FILE);
122
Bitstream.EmitRecordWithBlob(RecordMetaExternalFileAbbrevID, R, Filename);
123
}
124
125
void BitstreamRemarkSerializerHelper::setupRemarkBlockInfo() {
126
// Setup the remark block.
127
initBlock(REMARK_BLOCK_ID, Bitstream, R, RemarkBlockName);
128
129
// The header of a remark.
130
{
131
setRecordName(RECORD_REMARK_HEADER, Bitstream, R, RemarkHeaderName);
132
133
auto Abbrev = std::make_shared<BitCodeAbbrev>();
134
Abbrev->Add(BitCodeAbbrevOp(RECORD_REMARK_HEADER));
135
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Type
136
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Remark Name
137
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Pass name
138
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Function name
139
RecordRemarkHeaderAbbrevID =
140
Bitstream.EmitBlockInfoAbbrev(REMARK_BLOCK_ID, Abbrev);
141
}
142
143
// The location of a remark.
144
{
145
setRecordName(RECORD_REMARK_DEBUG_LOC, Bitstream, R, RemarkDebugLocName);
146
147
auto Abbrev = std::make_shared<BitCodeAbbrev>();
148
Abbrev->Add(BitCodeAbbrevOp(RECORD_REMARK_DEBUG_LOC));
149
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 7)); // File
150
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Line
151
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Column
152
RecordRemarkDebugLocAbbrevID =
153
Bitstream.EmitBlockInfoAbbrev(REMARK_BLOCK_ID, Abbrev);
154
}
155
156
// The hotness of a remark.
157
{
158
setRecordName(RECORD_REMARK_HOTNESS, Bitstream, R, RemarkHotnessName);
159
160
auto Abbrev = std::make_shared<BitCodeAbbrev>();
161
Abbrev->Add(BitCodeAbbrevOp(RECORD_REMARK_HOTNESS));
162
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Hotness
163
RecordRemarkHotnessAbbrevID =
164
Bitstream.EmitBlockInfoAbbrev(REMARK_BLOCK_ID, Abbrev);
165
}
166
167
// An argument entry with a debug location attached.
168
{
169
setRecordName(RECORD_REMARK_ARG_WITH_DEBUGLOC, Bitstream, R,
170
RemarkArgWithDebugLocName);
171
172
auto Abbrev = std::make_shared<BitCodeAbbrev>();
173
Abbrev->Add(BitCodeAbbrevOp(RECORD_REMARK_ARG_WITH_DEBUGLOC));
174
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 7)); // Key
175
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 7)); // Value
176
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 7)); // File
177
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Line
178
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Column
179
RecordRemarkArgWithDebugLocAbbrevID =
180
Bitstream.EmitBlockInfoAbbrev(REMARK_BLOCK_ID, Abbrev);
181
}
182
183
// An argument entry with no debug location attached.
184
{
185
setRecordName(RECORD_REMARK_ARG_WITHOUT_DEBUGLOC, Bitstream, R,
186
RemarkArgWithoutDebugLocName);
187
188
auto Abbrev = std::make_shared<BitCodeAbbrev>();
189
Abbrev->Add(BitCodeAbbrevOp(RECORD_REMARK_ARG_WITHOUT_DEBUGLOC));
190
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 7)); // Key
191
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 7)); // Value
192
RecordRemarkArgWithoutDebugLocAbbrevID =
193
Bitstream.EmitBlockInfoAbbrev(REMARK_BLOCK_ID, Abbrev);
194
}
195
}
196
197
void BitstreamRemarkSerializerHelper::setupBlockInfo() {
198
// Emit magic number.
199
for (const char C : ContainerMagic)
200
Bitstream.Emit(static_cast<unsigned>(C), 8);
201
202
Bitstream.EnterBlockInfoBlock();
203
204
// Setup the main metadata. Depending on the container type, we'll setup the
205
// required records next.
206
setupMetaBlockInfo();
207
208
switch (ContainerType) {
209
case BitstreamRemarkContainerType::SeparateRemarksMeta:
210
// Needs a string table that the separate remark file is using.
211
setupMetaStrTab();
212
// Needs to know where the external remarks file is.
213
setupMetaExternalFile();
214
break;
215
case BitstreamRemarkContainerType::SeparateRemarksFile:
216
// Contains remarks: emit the version.
217
setupMetaRemarkVersion();
218
// Contains remarks: emit the remark abbrevs.
219
setupRemarkBlockInfo();
220
break;
221
case BitstreamRemarkContainerType::Standalone:
222
// Contains remarks: emit the version.
223
setupMetaRemarkVersion();
224
// Needs a string table.
225
setupMetaStrTab();
226
// Contains remarks: emit the remark abbrevs.
227
setupRemarkBlockInfo();
228
break;
229
}
230
231
Bitstream.ExitBlock();
232
}
233
234
void BitstreamRemarkSerializerHelper::emitMetaBlock(
235
uint64_t ContainerVersion, std::optional<uint64_t> RemarkVersion,
236
std::optional<const StringTable *> StrTab,
237
std::optional<StringRef> Filename) {
238
// Emit the meta block
239
Bitstream.EnterSubblock(META_BLOCK_ID, 3);
240
241
// The container version and type.
242
R.clear();
243
R.push_back(RECORD_META_CONTAINER_INFO);
244
R.push_back(ContainerVersion);
245
R.push_back(static_cast<uint64_t>(ContainerType));
246
Bitstream.EmitRecordWithAbbrev(RecordMetaContainerInfoAbbrevID, R);
247
248
switch (ContainerType) {
249
case BitstreamRemarkContainerType::SeparateRemarksMeta:
250
assert(StrTab != std::nullopt && *StrTab != nullptr);
251
emitMetaStrTab(**StrTab);
252
assert(Filename != std::nullopt);
253
emitMetaExternalFile(*Filename);
254
break;
255
case BitstreamRemarkContainerType::SeparateRemarksFile:
256
assert(RemarkVersion != std::nullopt);
257
emitMetaRemarkVersion(*RemarkVersion);
258
break;
259
case BitstreamRemarkContainerType::Standalone:
260
assert(RemarkVersion != std::nullopt);
261
emitMetaRemarkVersion(*RemarkVersion);
262
assert(StrTab != std::nullopt && *StrTab != nullptr);
263
emitMetaStrTab(**StrTab);
264
break;
265
}
266
267
Bitstream.ExitBlock();
268
}
269
270
void BitstreamRemarkSerializerHelper::emitRemarkBlock(const Remark &Remark,
271
StringTable &StrTab) {
272
Bitstream.EnterSubblock(REMARK_BLOCK_ID, 4);
273
274
R.clear();
275
R.push_back(RECORD_REMARK_HEADER);
276
R.push_back(static_cast<uint64_t>(Remark.RemarkType));
277
R.push_back(StrTab.add(Remark.RemarkName).first);
278
R.push_back(StrTab.add(Remark.PassName).first);
279
R.push_back(StrTab.add(Remark.FunctionName).first);
280
Bitstream.EmitRecordWithAbbrev(RecordRemarkHeaderAbbrevID, R);
281
282
if (const std::optional<RemarkLocation> &Loc = Remark.Loc) {
283
R.clear();
284
R.push_back(RECORD_REMARK_DEBUG_LOC);
285
R.push_back(StrTab.add(Loc->SourceFilePath).first);
286
R.push_back(Loc->SourceLine);
287
R.push_back(Loc->SourceColumn);
288
Bitstream.EmitRecordWithAbbrev(RecordRemarkDebugLocAbbrevID, R);
289
}
290
291
if (std::optional<uint64_t> Hotness = Remark.Hotness) {
292
R.clear();
293
R.push_back(RECORD_REMARK_HOTNESS);
294
R.push_back(*Hotness);
295
Bitstream.EmitRecordWithAbbrev(RecordRemarkHotnessAbbrevID, R);
296
}
297
298
for (const Argument &Arg : Remark.Args) {
299
R.clear();
300
unsigned Key = StrTab.add(Arg.Key).first;
301
unsigned Val = StrTab.add(Arg.Val).first;
302
bool HasDebugLoc = Arg.Loc != std::nullopt;
303
R.push_back(HasDebugLoc ? RECORD_REMARK_ARG_WITH_DEBUGLOC
304
: RECORD_REMARK_ARG_WITHOUT_DEBUGLOC);
305
R.push_back(Key);
306
R.push_back(Val);
307
if (HasDebugLoc) {
308
R.push_back(StrTab.add(Arg.Loc->SourceFilePath).first);
309
R.push_back(Arg.Loc->SourceLine);
310
R.push_back(Arg.Loc->SourceColumn);
311
}
312
Bitstream.EmitRecordWithAbbrev(HasDebugLoc
313
? RecordRemarkArgWithDebugLocAbbrevID
314
: RecordRemarkArgWithoutDebugLocAbbrevID,
315
R);
316
}
317
Bitstream.ExitBlock();
318
}
319
320
void BitstreamRemarkSerializerHelper::flushToStream(raw_ostream &OS) {
321
OS.write(Encoded.data(), Encoded.size());
322
Encoded.clear();
323
}
324
325
StringRef BitstreamRemarkSerializerHelper::getBuffer() {
326
return StringRef(Encoded.data(), Encoded.size());
327
}
328
329
BitstreamRemarkSerializer::BitstreamRemarkSerializer(raw_ostream &OS,
330
SerializerMode Mode)
331
: RemarkSerializer(Format::Bitstream, OS, Mode),
332
Helper(BitstreamRemarkContainerType::SeparateRemarksFile) {
333
assert(Mode == SerializerMode::Separate &&
334
"For SerializerMode::Standalone, a pre-filled string table needs to "
335
"be provided.");
336
// We always use a string table with bitstream.
337
StrTab.emplace();
338
}
339
340
BitstreamRemarkSerializer::BitstreamRemarkSerializer(raw_ostream &OS,
341
SerializerMode Mode,
342
StringTable StrTabIn)
343
: RemarkSerializer(Format::Bitstream, OS, Mode),
344
Helper(Mode == SerializerMode::Separate
345
? BitstreamRemarkContainerType::SeparateRemarksFile
346
: BitstreamRemarkContainerType::Standalone) {
347
StrTab = std::move(StrTabIn);
348
}
349
350
void BitstreamRemarkSerializer::emit(const Remark &Remark) {
351
if (!DidSetUp) {
352
// Emit the metadata that is embedded in the remark file.
353
// If we're in standalone mode, serialize the string table as well.
354
bool IsStandalone =
355
Helper.ContainerType == BitstreamRemarkContainerType::Standalone;
356
BitstreamMetaSerializer MetaSerializer(
357
OS, Helper,
358
IsStandalone ? &*StrTab
359
: std::optional<const StringTable *>(std::nullopt));
360
MetaSerializer.emit();
361
DidSetUp = true;
362
}
363
364
assert(DidSetUp &&
365
"The Block info block and the meta block were not emitted yet.");
366
Helper.emitRemarkBlock(Remark, *StrTab);
367
368
Helper.flushToStream(OS);
369
}
370
371
std::unique_ptr<MetaSerializer> BitstreamRemarkSerializer::metaSerializer(
372
raw_ostream &OS, std::optional<StringRef> ExternalFilename) {
373
assert(Helper.ContainerType !=
374
BitstreamRemarkContainerType::SeparateRemarksMeta);
375
bool IsStandalone =
376
Helper.ContainerType == BitstreamRemarkContainerType::Standalone;
377
return std::make_unique<BitstreamMetaSerializer>(
378
OS,
379
IsStandalone ? BitstreamRemarkContainerType::Standalone
380
: BitstreamRemarkContainerType::SeparateRemarksMeta,
381
&*StrTab, ExternalFilename);
382
}
383
384
void BitstreamMetaSerializer::emit() {
385
Helper->setupBlockInfo();
386
Helper->emitMetaBlock(CurrentContainerVersion, CurrentRemarkVersion, StrTab,
387
ExternalFilename);
388
Helper->flushToStream(OS);
389
}
390
391