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