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