//===-- 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 <optional>
 
 
 
namespace llvm {
 
namespace remarks {
 
 
 
struct 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,
 
                     std::optional<uint64_t> RemarkVersion,
 
                     std::optional<const StringTable *> StrTab = std::nullopt,
 
                     std::optional<StringRef> Filename = std::nullopt);
 
 
 
  /// 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,
 
      std::optional<StringRef> ExternalFilename = std::nullopt) 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.
 
  std::optional<BitstreamRemarkSerializerHelper> TmpHelper;
 
  /// The actual helper, that can point to \p TmpHelper or to an external helper
 
  /// object.
 
  BitstreamRemarkSerializerHelper *Helper = nullptr;
 
 
 
  std::optional<const StringTable *> StrTab;
 
  std::optional<StringRef> ExternalFilename;
 
 
 
  /// Create a new meta serializer based on \p ContainerType.
 
  BitstreamMetaSerializer(
 
      raw_ostream &OS, BitstreamRemarkContainerType ContainerType,
 
      std::optional<const StringTable *> StrTab = std::nullopt,
 
      std::optional<StringRef> ExternalFilename = std::nullopt)
 
      : MetaSerializer(OS), TmpHelper(std::nullopt), 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,
 
      std::optional<const StringTable *> StrTab = std::nullopt,
 
      std::optional<StringRef> ExternalFilename = std::nullopt)
 
      : MetaSerializer(OS), TmpHelper(std::nullopt), Helper(&Helper),
 
        StrTab(StrTab), ExternalFilename(ExternalFilename) {}
 
 
 
  void emit() override;
 
};
 
 
 
} // end namespace remarks
 
} // end namespace llvm
 
 
 
#endif // LLVM_REMARKS_BITSTREAMREMARKSERIALIZER_H