BitstreamRemarkSerializer.h 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===-- BitstreamRemarkSerializer.h - Bitstream serializer ------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // This file provides an implementation of the serializer using the LLVM
  15. // Bitstream format.
  16. //
  17. //===----------------------------------------------------------------------===//
  18. #ifndef LLVM_REMARKS_BITSTREAMREMARKSERIALIZER_H
  19. #define LLVM_REMARKS_BITSTREAMREMARKSERIALIZER_H
  20. #include "llvm/Bitstream/BitstreamWriter.h"
  21. #include "llvm/Remarks/BitstreamRemarkContainer.h"
  22. #include "llvm/Remarks/RemarkSerializer.h"
  23. #include <optional>
  24. namespace llvm {
  25. namespace remarks {
  26. struct Remarks;
  27. /// Serialize the remarks to LLVM bitstream.
  28. /// This class provides ways to emit remarks in the LLVM bitstream format and
  29. /// its associated metadata.
  30. ///
  31. /// * The separate model:
  32. /// Separate meta: | Container info
  33. /// | String table
  34. /// | External file
  35. ///
  36. /// Separate remarks: | Container info
  37. /// | Remark version
  38. /// | Remark0
  39. /// | Remark1
  40. /// | Remark2
  41. /// | ...
  42. ///
  43. /// * The standalone model: | Container info
  44. /// | String table
  45. /// | Remark version
  46. /// | Remark0
  47. /// | Remark1
  48. /// | Remark2
  49. /// | ...
  50. ///
  51. struct BitstreamRemarkSerializerHelper {
  52. /// Buffer used for encoding the bitstream before writing it to the final
  53. /// stream.
  54. SmallVector<char, 1024> Encoded;
  55. /// Buffer used to construct records and pass to the bitstream writer.
  56. SmallVector<uint64_t, 64> R;
  57. /// The Bitstream writer.
  58. BitstreamWriter Bitstream;
  59. /// The type of the container we are serializing.
  60. BitstreamRemarkContainerType ContainerType;
  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. BitstreamRemarkSerializerHelper(BitstreamRemarkContainerType ContainerType);
  75. // Disable copy and move: Bitstream points to Encoded, which needs special
  76. // handling during copy/move, but moving the vectors is probably useless
  77. // anyway.
  78. BitstreamRemarkSerializerHelper(const BitstreamRemarkSerializerHelper &) =
  79. delete;
  80. BitstreamRemarkSerializerHelper &
  81. operator=(const BitstreamRemarkSerializerHelper &) = delete;
  82. BitstreamRemarkSerializerHelper(BitstreamRemarkSerializerHelper &&) = delete;
  83. BitstreamRemarkSerializerHelper &
  84. operator=(BitstreamRemarkSerializerHelper &&) = delete;
  85. /// Set up the necessary block info entries according to the container type.
  86. void setupBlockInfo();
  87. /// Set up the block info for the metadata block.
  88. void setupMetaBlockInfo();
  89. /// The remark version in the metadata block.
  90. void setupMetaRemarkVersion();
  91. void emitMetaRemarkVersion(uint64_t RemarkVersion);
  92. /// The strtab in the metadata block.
  93. void setupMetaStrTab();
  94. void emitMetaStrTab(const StringTable &StrTab);
  95. /// The external file in the metadata block.
  96. void setupMetaExternalFile();
  97. void emitMetaExternalFile(StringRef Filename);
  98. /// The block info for the remarks block.
  99. void setupRemarkBlockInfo();
  100. /// Emit the metadata for the remarks.
  101. void emitMetaBlock(uint64_t ContainerVersion,
  102. std::optional<uint64_t> RemarkVersion,
  103. std::optional<const StringTable *> StrTab = std::nullopt,
  104. std::optional<StringRef> Filename = std::nullopt);
  105. /// Emit a remark block. The string table is required.
  106. void emitRemarkBlock(const Remark &Remark, StringTable &StrTab);
  107. /// Finalize the writing to \p OS.
  108. void flushToStream(raw_ostream &OS);
  109. /// Finalize the writing to a buffer.
  110. /// The contents of the buffer remain valid for the lifetime of the object.
  111. /// Any call to any other function in this class will invalidate the buffer.
  112. StringRef getBuffer();
  113. };
  114. /// Implementation of the remark serializer using LLVM bitstream.
  115. struct BitstreamRemarkSerializer : public RemarkSerializer {
  116. /// The file should contain:
  117. /// 1) The block info block that describes how to read the blocks.
  118. /// 2) The metadata block that contains various information about the remarks
  119. /// in the file.
  120. /// 3) A number of remark blocks.
  121. /// We need to set up 1) and 2) first, so that we can emit 3) after. This flag
  122. /// is used to emit the first two blocks only once.
  123. bool DidSetUp = false;
  124. /// The helper to emit bitstream.
  125. BitstreamRemarkSerializerHelper Helper;
  126. /// Construct a serializer that will create its own string table.
  127. BitstreamRemarkSerializer(raw_ostream &OS, SerializerMode Mode);
  128. /// Construct a serializer with a pre-filled string table.
  129. BitstreamRemarkSerializer(raw_ostream &OS, SerializerMode Mode,
  130. StringTable StrTab);
  131. /// Emit a remark to the stream. This also emits the metadata associated to
  132. /// the remarks based on the SerializerMode specified at construction.
  133. /// This writes the serialized output to the provided stream.
  134. void emit(const Remark &Remark) override;
  135. /// The metadata serializer associated to this remark serializer. Based on the
  136. /// container type of the current serializer, the container type of the
  137. /// metadata serializer will change.
  138. std::unique_ptr<MetaSerializer> metaSerializer(
  139. raw_ostream &OS,
  140. std::optional<StringRef> ExternalFilename = std::nullopt) override;
  141. static bool classof(const RemarkSerializer *S) {
  142. return S->SerializerFormat == Format::Bitstream;
  143. }
  144. };
  145. /// Serializer of metadata for bitstream remarks.
  146. struct BitstreamMetaSerializer : public MetaSerializer {
  147. /// This class can be used with [1] a pre-constructed
  148. /// BitstreamRemarkSerializerHelper, or with [2] one that is owned by the meta
  149. /// serializer. In case of [1], we need to be able to store a reference to the
  150. /// object, while in case of [2] we need to store the whole object.
  151. std::optional<BitstreamRemarkSerializerHelper> TmpHelper;
  152. /// The actual helper, that can point to \p TmpHelper or to an external helper
  153. /// object.
  154. BitstreamRemarkSerializerHelper *Helper = nullptr;
  155. std::optional<const StringTable *> StrTab;
  156. std::optional<StringRef> ExternalFilename;
  157. /// Create a new meta serializer based on \p ContainerType.
  158. BitstreamMetaSerializer(
  159. raw_ostream &OS, BitstreamRemarkContainerType ContainerType,
  160. std::optional<const StringTable *> StrTab = std::nullopt,
  161. std::optional<StringRef> ExternalFilename = std::nullopt)
  162. : MetaSerializer(OS), TmpHelper(std::nullopt), Helper(nullptr),
  163. StrTab(StrTab), ExternalFilename(ExternalFilename) {
  164. TmpHelper.emplace(ContainerType);
  165. Helper = &*TmpHelper;
  166. }
  167. /// Create a new meta serializer based on a previously built \p Helper.
  168. BitstreamMetaSerializer(
  169. raw_ostream &OS, BitstreamRemarkSerializerHelper &Helper,
  170. std::optional<const StringTable *> StrTab = std::nullopt,
  171. std::optional<StringRef> ExternalFilename = std::nullopt)
  172. : MetaSerializer(OS), TmpHelper(std::nullopt), Helper(&Helper),
  173. StrTab(StrTab), ExternalFilename(ExternalFilename) {}
  174. void emit() override;
  175. };
  176. } // end namespace remarks
  177. } // end namespace llvm
  178. #endif // LLVM_REMARKS_BITSTREAMREMARKSERIALIZER_H
  179. #ifdef __GNUC__
  180. #pragma GCC diagnostic pop
  181. #endif