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

source code of llvm/include/llvm/Remarks/BitstreamRemarkSerializer.h