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_BITSTREAM_REMARK_SERIALIZER_H 15 #define LLVM_REMARKS_BITSTREAM_REMARK_SERIALIZER_H 16 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" 21 22 namespace llvm { 23 namespace remarks { 24 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. 28 /// 29 /// * The separate model: 30 /// Separate meta: | Container info 31 /// | String table 32 /// | External file 33 /// 34 /// Separate remarks: | Container info 35 /// | Remark version 36 /// | Remark0 37 /// | Remark1 38 /// | Remark2 39 /// | ... 40 /// 41 /// * The standalone model: | Container info 42 /// | String table 43 /// | Remark version 44 /// | Remark0 45 /// | Remark1 46 /// | Remark2 47 /// | ... 48 /// 49 struct BitstreamRemarkSerializerHelper { 50 /// Buffer used for encoding the bitstream before writing it to the final 51 /// stream. 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; 59 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; 73 74 BitstreamRemarkSerializerHelper(BitstreamRemarkContainerType ContainerType); 75 76 // Disable copy and move: Bitstream points to Encoded, which needs special 77 // handling during copy/move, but moving the vectors is probably useless 78 // anyway. 79 BitstreamRemarkSerializerHelper(const BitstreamRemarkSerializerHelper &) = 80 delete; 81 BitstreamRemarkSerializerHelper & 82 operator=(const BitstreamRemarkSerializerHelper &) = delete; 83 BitstreamRemarkSerializerHelper(BitstreamRemarkSerializerHelper &&) = delete; 84 BitstreamRemarkSerializerHelper & 85 operator=(BitstreamRemarkSerializerHelper &&) = delete; 86 87 /// Set up the necessary block info entries according to the container type. 88 void setupBlockInfo(); 89 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); 101 102 /// The block info for the remarks block. 103 void setupRemarkBlockInfo(); 104 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); 110 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(); 119 }; 120 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 126 /// in the file. 127 /// 3) A number of remark blocks. 128 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; 134 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, 139 StringTable StrTab); 140 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; 151 152 static bool classof(const RemarkSerializer *S) { 153 return S->SerializerFormat == Format::Bitstream; 154 } 155 }; 156 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 165 /// object. 166 BitstreamRemarkSerializerHelper *Helper = nullptr; 167 168 Optional<const StringTable *> StrTab; 169 Optional<StringRef> ExternalFilename; 170 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; 180 } 181 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) {} 189 190 void emit() override; 191 }; 192 193 } // end namespace remarks 194 } // end namespace llvm 195 196 #endif /* LLVM_REMARKS_BITSTREAM_REMARK_SERIALIZER_H */ 197