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