LLVM 22.0.0git
BitstreamRemarkSerializer.cpp
Go to the documentation of this file.
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
15#include "llvm/Remarks/Remark.h"
16#include <optional>
17
18using namespace llvm;
19using namespace llvm::remarks;
20
24
26 append_range(R, Str);
27}
28
29static void setRecordName(unsigned RecordID, BitstreamWriter &Bitstream,
31 R.clear();
32 R.push_back(RecordID);
33 push(R, Str);
35}
36
37static void initBlock(unsigned BlockID, BitstreamWriter &Bitstream,
39 R.clear();
40 R.push_back(BlockID);
42
43 R.clear();
44 push(R, Str);
46}
47
49 // Setup the metadata block.
51
52 // The container information.
55
56 auto Abbrev = std::make_shared<BitCodeAbbrev>();
58 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Version.
59 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Type.
61 Bitstream.EmitBlockInfoAbbrev(META_BLOCK_ID, Abbrev);
62}
63
67
68 auto Abbrev = std::make_shared<BitCodeAbbrev>();
70 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Version.
72 Bitstream.EmitBlockInfoAbbrev(META_BLOCK_ID, Abbrev);
73}
74
76 uint64_t RemarkVersion) {
77 // The remark version is emitted only if we emit remarks.
78 R.clear();
80 R.push_back(RemarkVersion);
81 Bitstream.EmitRecordWithAbbrev(RecordMetaRemarkVersionAbbrevID, R);
82}
83
86
87 auto Abbrev = std::make_shared<BitCodeAbbrev>();
89 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Raw table.
91 Bitstream.EmitBlockInfoAbbrev(META_BLOCK_ID, Abbrev);
92}
93
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
110
111 auto Abbrev = std::make_shared<BitCodeAbbrev>();
113 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Filename.
115 Bitstream.EmitBlockInfoAbbrev(META_BLOCK_ID, Abbrev);
116}
117
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
126 // Setup the remark block.
128
129 // The header of a remark.
130 {
132
133 auto Abbrev = std::make_shared<BitCodeAbbrev>();
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
140 Bitstream.EmitBlockInfoAbbrev(REMARK_BLOCK_ID, Abbrev);
141 }
142
143 // The location of a remark.
144 {
146
147 auto Abbrev = std::make_shared<BitCodeAbbrev>();
149 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 7)); // File
150 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Line
151 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Column
153 Bitstream.EmitBlockInfoAbbrev(REMARK_BLOCK_ID, Abbrev);
154 }
155
156 // The hotness of a remark.
157 {
159
160 auto Abbrev = std::make_shared<BitCodeAbbrev>();
162 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Hotness
164 Bitstream.EmitBlockInfoAbbrev(REMARK_BLOCK_ID, Abbrev);
165 }
166
167 // An argument entry with a debug location attached.
168 {
171
172 auto Abbrev = std::make_shared<BitCodeAbbrev>();
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
180 Bitstream.EmitBlockInfoAbbrev(REMARK_BLOCK_ID, Abbrev);
181 }
182
183 // An argument entry with no debug location attached.
184 {
187
188 auto Abbrev = std::make_shared<BitCodeAbbrev>();
190 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 7)); // Key
191 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 7)); // Value
193 Bitstream.EmitBlockInfoAbbrev(REMARK_BLOCK_ID, Abbrev);
194 }
195}
196
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.
207
208 switch (ContainerType) {
210 // Needs a string table that the separate remark file is using.
212 // Needs to know where the external remarks file is.
214 break;
216 // Contains remarks: emit the version.
218 // Contains remarks: emit the remark abbrevs.
220 break;
222 // Contains remarks: emit the version.
224 // Needs a string table.
226 // Contains remarks: emit the remark abbrevs.
228 break;
229 }
230
231 Bitstream.ExitBlock();
232}
233
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) {
250 assert(StrTab != std::nullopt && *StrTab != nullptr);
251 emitMetaStrTab(**StrTab);
252 assert(Filename != std::nullopt);
253 emitMetaExternalFile(*Filename);
254 break;
256 assert(RemarkVersion != std::nullopt);
257 emitMetaRemarkVersion(*RemarkVersion);
258 break;
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
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
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
315 R);
316 }
317 Bitstream.ExitBlock();
318}
319
321 OS.write(Encoded.data(), Encoded.size());
322 Encoded.clear();
323}
324
328
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
349
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 =
357 OS, Helper,
358 IsStandalone ? &*StrTab
359 : std::optional<const StringTable *>(std::nullopt));
361 DidSetUp = true;
362 }
363
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
371std::unique_ptr<MetaSerializer> BitstreamRemarkSerializer::metaSerializer(
372 raw_ostream &OS, std::optional<StringRef> ExternalFilename) {
373 assert(Helper.ContainerType !=
375 bool IsStandalone =
377 return std::make_unique<BitstreamMetaSerializer>(
378 OS,
381 &*StrTab, ExternalFilename);
382}
383
385 Helper->setupBlockInfo();
388 Helper->flushToStream(OS);
389}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static void initBlock(unsigned BlockID, BitstreamWriter &Bitstream, SmallVectorImpl< uint64_t > &R, StringRef Str)
static void push(SmallVectorImpl< uint64_t > &R, StringRef Str)
static void setRecordName(unsigned RecordID, BitstreamWriter &Bitstream, SmallVectorImpl< uint64_t > &R, StringRef Str)
BitCodeAbbrevOp - This describes one or more operands in an abbreviation.
Definition BitCodes.h:34
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
raw_ostream & write(unsigned char C)
A raw_ostream that writes to an std::string.
std::string & str()
Returns the string's reference.
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
@ BLOCKINFO_CODE_BLOCKNAME
@ BLOCKINFO_CODE_SETRECORDNAME
@ BLOCKINFO_CODE_SETBID
constexpr StringLiteral RemarkDebugLocName("Remark debug location")
BitstreamRemarkContainerType
Type of the remark container.
@ SeparateRemarksFile
The remarks emitted separately.
@ SeparateRemarksMeta
The metadata emitted separately.
constexpr StringLiteral RemarkArgWithDebugLocName("Argument with debug location")
@ REMARK_BLOCK_ID
One remark entry is represented using a REMARK_BLOCK.
@ META_BLOCK_ID
The metadata block is mandatory.
constexpr uint64_t CurrentContainerVersion
The current version of the remark container.
constexpr StringLiteral MetaExternalFileName("External File")
constexpr StringLiteral MetaRemarkVersionName("Remark version")
Format
The format used for serializing/deserializing remarks.
constexpr StringLiteral MetaContainerInfoName("Container info")
constexpr StringLiteral RemarkHeaderName("Remark header")
constexpr StringLiteral MetaBlockName("Meta")
constexpr StringLiteral RemarkArgWithoutDebugLocName("Argument")
constexpr uint64_t CurrentRemarkVersion
The current version of the remark entry.
Definition Remark.h:29
constexpr StringLiteral RemarkBlockName("Remark")
constexpr StringLiteral ContainerMagic("RMRK")
The magic number used for identifying remark blocks.
constexpr StringLiteral MetaStrTabName("String table")
constexpr StringLiteral RemarkHotnessName("Remark hotness")
This is an optimization pass for GlobalISel generic memory operations.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2138
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
A key-value pair with a debug location that is used to display the remarks at the right place in the ...
Definition Remark.h:47
std::optional< RemarkLocation > Loc
Definition Remark.h:52
Serializer of metadata for bitstream remarks.
std::optional< const StringTable * > StrTab
BitstreamRemarkSerializerHelper * Helper
The actual helper, that can point to TmpHelper or to an external helper object.
SmallVector< char, 1024 > Encoded
Buffer used for encoding the bitstream before writing it to the final stream.
void setupMetaBlockInfo()
Set up the block info for the metadata block.
StringRef getBuffer()
Finalize the writing to a buffer.
SmallVector< uint64_t, 64 > R
Buffer used to construct records and pass to the bitstream writer.
BitstreamRemarkSerializerHelper(BitstreamRemarkContainerType ContainerType)
BitstreamRemarkContainerType ContainerType
The type of the container we are serializing.
void setupRemarkBlockInfo()
The block info for the remarks block.
void emitMetaBlock(uint64_t ContainerVersion, std::optional< uint64_t > RemarkVersion, std::optional< const StringTable * > StrTab=std::nullopt, std::optional< StringRef > Filename=std::nullopt)
Emit the metadata for the remarks.
void setupMetaExternalFile()
The external file in the metadata block.
void setupBlockInfo()
Set up the necessary block info entries according to the container type.
void setupMetaRemarkVersion()
The remark version in the metadata block.
void emitRemarkBlock(const Remark &Remark, StringTable &StrTab)
Emit a remark block. The string table is required.
void setupMetaStrTab()
The strtab in the metadata block.
void flushToStream(raw_ostream &OS)
Finalize the writing to OS.
uint64_t RecordMetaContainerInfoAbbrevID
Abbrev IDs initialized in the block info block.
BitstreamRemarkSerializer(raw_ostream &OS, SerializerMode Mode)
Construct a serializer that will create its own string table.
bool DidSetUp
The file should contain: 1) The block info block that describes how to read the blocks.
BitstreamRemarkSerializerHelper Helper
The helper to emit bitstream.
void emit(const Remark &Remark) override
Emit a remark to the stream.
std::unique_ptr< MetaSerializer > metaSerializer(raw_ostream &OS, std::optional< StringRef > ExternalFilename=std::nullopt) override
The metadata serializer associated to this remark serializer.
This is the base class for a remark metadata serializer.
raw_ostream & OS
The open raw_ostream that the metadata is emitted to.
SerializerMode Mode
The serialization mode.
RemarkSerializer(Format SerializerFormat, raw_ostream &OS, SerializerMode Mode)
std::optional< StringTable > StrTab
The string table containing all the unique strings used in the output.
raw_ostream & OS
The open raw_ostream that the remark diagnostics are emitted to.
A remark type used for both emission and parsing.
Definition Remark.h:98
Type RemarkType
The type of the remark.
Definition Remark.h:100
StringRef PassName
Name of the pass that triggers the emission of this remark.
Definition Remark.h:103
std::optional< RemarkLocation > Loc
The location in the source file of the remark.
Definition Remark.h:114
std::optional< uint64_t > Hotness
If profile information is available, this is the number of times the corresponding code was executed ...
Definition Remark.h:118
StringRef RemarkName
Textual identifier for the remark (single-word, camel-case).
Definition Remark.h:108
StringRef FunctionName
Mangled name of the function that triggers the emssion of this remark.
Definition Remark.h:111
SmallVector< Argument, 5 > Args
Arguments collected via the streaming interface.
Definition Remark.h:121
The string table used for serializing remarks.
LLVM_ABI void serialize(raw_ostream &OS) const
Serialize the string table to a stream.
LLVM_ABI std::pair< unsigned, StringRef > add(StringRef Str)
Add a string to the table. It returns an unique ID of the string.