reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171
  172
  173
  174
  175
  176
  177
  178
  179
  180
  181
  182
  183
  184
  185
  186
  187
  188
  189
  190
  191
  192
  193
  194
  195
  196
//===-- 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_BITSTREAM_REMARK_SERIALIZER_H
#define LLVM_REMARKS_BITSTREAM_REMARK_SERIALIZER_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_BITSTREAM_REMARK_SERIALIZER_H */