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 22 namespace llvm { 23 namespace remarks { 24 25 struct 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 /// 51 struct 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. 124 struct 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 classofBitstreamRemarkSerializer154 static bool classof(const RemarkSerializer *S) { 155 return S->SerializerFormat == Format::Bitstream; 156 } 157 }; 158 159 /// Serializer of metadata for bitstream remarks. 160 struct 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) MetaSerializerBitstreamMetaSerializer178 : MetaSerializer(OS), TmpHelper(std::nullopt), Helper(nullptr), 179 StrTab(StrTab), ExternalFilename(ExternalFilename) { 180 TmpHelper.emplace(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) MetaSerializerBitstreamMetaSerializer189 : 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