| //===-- BitstreamRemarkSerializer.h - Bitstream serializer ------*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file provides an implementation of the serializer using the LLVM |
| // Bitstream format. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_REMARKS_BITSTREAMREMARKSERIALIZER_H |
| #define LLVM_REMARKS_BITSTREAMREMARKSERIALIZER_H |
| |
| #include "llvm/Bitstream/BitstreamWriter.h" |
| #include "llvm/Remarks/BitstreamRemarkContainer.h" |
| #include "llvm/Remarks/RemarkSerializer.h" |
| #include "llvm/Support/raw_ostream.h" |
| |
| namespace llvm { |
| namespace remarks { |
| |
| /// Serialize the remarks to LLVM bitstream. |
| /// This class provides ways to emit remarks in the LLVM bitstream format and |
| /// its associated metadata. |
| /// |
| /// * The separate model: |
| /// Separate meta: | Container info |
| /// | String table |
| /// | External file |
| /// |
| /// Separate remarks: | Container info |
| /// | Remark version |
| /// | Remark0 |
| /// | Remark1 |
| /// | Remark2 |
| /// | ... |
| /// |
| /// * The standalone model: | Container info |
| /// | String table |
| /// | Remark version |
| /// | Remark0 |
| /// | Remark1 |
| /// | Remark2 |
| /// | ... |
| /// |
| struct BitstreamRemarkSerializerHelper { |
| /// Buffer used for encoding the bitstream before writing it to the final |
| /// stream. |
| SmallVector<char, 1024> Encoded; |
| /// Buffer used to construct records and pass to the bitstream writer. |
| SmallVector<uint64_t, 64> R; |
| /// The Bitstream writer. |
| BitstreamWriter Bitstream; |
| /// The type of the container we are serializing. |
| BitstreamRemarkContainerType ContainerType; |
| |
| /// Abbrev IDs initialized in the block info block. |
| /// Note: depending on the container type, some IDs might be uninitialized. |
| /// Warning: When adding more abbrev IDs, make sure to update the |
| /// BlockCodeSize (in the call to EnterSubblock). |
| uint64_t RecordMetaContainerInfoAbbrevID = 0; |
| uint64_t RecordMetaRemarkVersionAbbrevID = 0; |
| uint64_t RecordMetaStrTabAbbrevID = 0; |
| uint64_t RecordMetaExternalFileAbbrevID = 0; |
| uint64_t RecordRemarkHeaderAbbrevID = 0; |
| uint64_t RecordRemarkDebugLocAbbrevID = 0; |
| uint64_t RecordRemarkHotnessAbbrevID = 0; |
| uint64_t RecordRemarkArgWithDebugLocAbbrevID = 0; |
| uint64_t RecordRemarkArgWithoutDebugLocAbbrevID = 0; |
| |
| BitstreamRemarkSerializerHelper(BitstreamRemarkContainerType ContainerType); |
| |
| // Disable copy and move: Bitstream points to Encoded, which needs special |
| // handling during copy/move, but moving the vectors is probably useless |
| // anyway. |
| BitstreamRemarkSerializerHelper(const BitstreamRemarkSerializerHelper &) = |
| delete; |
| BitstreamRemarkSerializerHelper & |
| operator=(const BitstreamRemarkSerializerHelper &) = delete; |
| BitstreamRemarkSerializerHelper(BitstreamRemarkSerializerHelper &&) = delete; |
| BitstreamRemarkSerializerHelper & |
| operator=(BitstreamRemarkSerializerHelper &&) = delete; |
| |
| /// Set up the necessary block info entries according to the container type. |
| void setupBlockInfo(); |
| |
| /// Set up the block info for the metadata block. |
| void setupMetaBlockInfo(); |
| /// The remark version in the metadata block. |
| void setupMetaRemarkVersion(); |
| void emitMetaRemarkVersion(uint64_t RemarkVersion); |
| /// The strtab in the metadata block. |
| void setupMetaStrTab(); |
| void emitMetaStrTab(const StringTable &StrTab); |
| /// The external file in the metadata block. |
| void setupMetaExternalFile(); |
| void emitMetaExternalFile(StringRef Filename); |
| |
| /// The block info for the remarks block. |
| void setupRemarkBlockInfo(); |
| |
| /// Emit the metadata for the remarks. |
| void emitMetaBlock(uint64_t ContainerVersion, |
| Optional<uint64_t> RemarkVersion, |
| Optional<const StringTable *> StrTab = None, |
| Optional<StringRef> Filename = None); |
| |
| /// Emit a remark block. The string table is required. |
| void emitRemarkBlock(const Remark &Remark, StringTable &StrTab); |
| /// Finalize the writing to \p OS. |
| void flushToStream(raw_ostream &OS); |
| /// Finalize the writing to a buffer. |
| /// The contents of the buffer remain valid for the lifetime of the object. |
| /// Any call to any other function in this class will invalidate the buffer. |
| StringRef getBuffer(); |
| }; |
| |
| /// Implementation of the remark serializer using LLVM bitstream. |
| struct BitstreamRemarkSerializer : public RemarkSerializer { |
| /// The file should contain: |
| /// 1) The block info block that describes how to read the blocks. |
| /// 2) The metadata block that contains various information about the remarks |
| /// in the file. |
| /// 3) A number of remark blocks. |
| |
| /// We need to set up 1) and 2) first, so that we can emit 3) after. This flag |
| /// is used to emit the first two blocks only once. |
| bool DidSetUp = false; |
| /// The helper to emit bitstream. |
| BitstreamRemarkSerializerHelper Helper; |
| |
| /// Construct a serializer that will create its own string table. |
| BitstreamRemarkSerializer(raw_ostream &OS, SerializerMode Mode); |
| /// Construct a serializer with a pre-filled string table. |
| BitstreamRemarkSerializer(raw_ostream &OS, SerializerMode Mode, |
| StringTable StrTab); |
| |
| /// Emit a remark to the stream. This also emits the metadata associated to |
| /// the remarks based on the SerializerMode specified at construction. |
| /// This writes the serialized output to the provided stream. |
| void emit(const Remark &Remark) override; |
| /// The metadata serializer associated to this remark serializer. Based on the |
| /// container type of the current serializer, the container type of the |
| /// metadata serializer will change. |
| std::unique_ptr<MetaSerializer> |
| metaSerializer(raw_ostream &OS, |
| Optional<StringRef> ExternalFilename = None) override; |
| |
| static bool classof(const RemarkSerializer *S) { |
| return S->SerializerFormat == Format::Bitstream; |
| } |
| }; |
| |
| /// Serializer of metadata for bitstream remarks. |
| struct BitstreamMetaSerializer : public MetaSerializer { |
| /// This class can be used with [1] a pre-constructed |
| /// BitstreamRemarkSerializerHelper, or with [2] one that is owned by the meta |
| /// serializer. In case of [1], we need to be able to store a reference to the |
| /// object, while in case of [2] we need to store the whole object. |
| Optional<BitstreamRemarkSerializerHelper> TmpHelper; |
| /// The actual helper, that can point to \p TmpHelper or to an external helper |
| /// object. |
| BitstreamRemarkSerializerHelper *Helper = nullptr; |
| |
| Optional<const StringTable *> StrTab; |
| Optional<StringRef> ExternalFilename; |
| |
| /// Create a new meta serializer based on \p ContainerType. |
| BitstreamMetaSerializer(raw_ostream &OS, |
| BitstreamRemarkContainerType ContainerType, |
| Optional<const StringTable *> StrTab = None, |
| Optional<StringRef> ExternalFilename = None) |
| : MetaSerializer(OS), TmpHelper(None), Helper(nullptr), StrTab(StrTab), |
| ExternalFilename(ExternalFilename) { |
| TmpHelper.emplace(ContainerType); |
| Helper = &*TmpHelper; |
| } |
| |
| /// Create a new meta serializer based on a previously built \p Helper. |
| BitstreamMetaSerializer(raw_ostream &OS, |
| BitstreamRemarkSerializerHelper &Helper, |
| Optional<const StringTable *> StrTab = None, |
| Optional<StringRef> ExternalFilename = None) |
| : MetaSerializer(OS), TmpHelper(None), Helper(&Helper), StrTab(StrTab), |
| ExternalFilename(ExternalFilename) {} |
| |
| void emit() override; |
| }; |
| |
| } // end namespace remarks |
| } // end namespace llvm |
| |
| #endif // LLVM_REMARKS_BITSTREAMREMARKSERIALIZER_H |