aboutsummaryrefslogtreecommitdiff
path: root/include/llvm/Remarks
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/Remarks')
-rw-r--r--include/llvm/Remarks/BitstreamRemarkContainer.h106
-rw-r--r--include/llvm/Remarks/BitstreamRemarkParser.h116
-rw-r--r--include/llvm/Remarks/BitstreamRemarkSerializer.h196
-rw-r--r--include/llvm/Remarks/Remark.h36
-rw-r--r--include/llvm/Remarks/RemarkFormat.h4
-rw-r--r--include/llvm/Remarks/RemarkParser.h38
-rw-r--r--include/llvm/Remarks/RemarkSerializer.h70
-rw-r--r--include/llvm/Remarks/RemarkStringTable.h24
-rw-r--r--include/llvm/Remarks/YAMLRemarkSerializer.h108
9 files changed, 653 insertions, 45 deletions
diff --git a/include/llvm/Remarks/BitstreamRemarkContainer.h b/include/llvm/Remarks/BitstreamRemarkContainer.h
new file mode 100644
index 000000000000..a2282fca04ab
--- /dev/null
+++ b/include/llvm/Remarks/BitstreamRemarkContainer.h
@@ -0,0 +1,106 @@
+//===-- BitstreamRemarkContainer.h - Container for remarks --------------*-===//
+//
+// 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 declarations for things used in the various types of
+// remark containers.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_REMARKS_REMARK_CONTAINER_H
+#define LLVM_REMARKS_REMARK_CONTAINER_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Bitstream/BitCodes.h"
+#include <cstdint>
+
+namespace llvm {
+namespace remarks {
+
+/// The current version of the remark container.
+/// Note: this is different from the version of the remark entry.
+constexpr uint64_t CurrentContainerVersion = 0;
+/// The magic number used for identifying remark blocks.
+constexpr StringLiteral ContainerMagic("RMRK");
+
+/// Type of the remark container.
+/// The remark container has two modes:
+/// * separate: the metadata is separate from the remarks and points to the
+/// auxiliary file that contains the remarks.
+/// * standalone: the metadata and the remarks are emitted together.
+enum class BitstreamRemarkContainerType {
+ /// The metadata emitted separately.
+ /// This will contain the following:
+ /// * Container version and type
+ /// * String table
+ /// * External file
+ SeparateRemarksMeta,
+ /// The remarks emitted separately.
+ /// This will contain the following:
+ /// * Container version and type
+ /// * Remark version
+ SeparateRemarksFile,
+ /// Everything is emitted together.
+ /// This will contain the following:
+ /// * Container version and type
+ /// * Remark version
+ /// * String table
+ Standalone,
+ First = SeparateRemarksMeta,
+ Last = Standalone,
+};
+
+/// The possible blocks that will be encountered in a bitstream remark
+/// container.
+enum BlockIDs {
+ /// The metadata block is mandatory. It should always come after the
+ /// BLOCKINFO_BLOCK, and contains metadata that should be used when parsing
+ /// REMARK_BLOCKs.
+ /// There should always be only one META_BLOCK.
+ META_BLOCK_ID = bitc::FIRST_APPLICATION_BLOCKID,
+ /// One remark entry is represented using a REMARK_BLOCK. There can be
+ /// multiple REMARK_BLOCKs in the same file.
+ REMARK_BLOCK_ID
+};
+
+constexpr StringRef MetaBlockName = StringRef("Meta", 4);
+constexpr StringRef RemarkBlockName = StringRef("Remark", 6);
+
+/// The possible records that can be encountered in the previously described
+/// blocks.
+enum RecordIDs {
+ // Meta block records.
+ RECORD_META_CONTAINER_INFO = 1,
+ RECORD_META_REMARK_VERSION,
+ RECORD_META_STRTAB,
+ RECORD_META_EXTERNAL_FILE,
+ // Remark block records.
+ RECORD_REMARK_HEADER,
+ RECORD_REMARK_DEBUG_LOC,
+ RECORD_REMARK_HOTNESS,
+ RECORD_REMARK_ARG_WITH_DEBUGLOC,
+ RECORD_REMARK_ARG_WITHOUT_DEBUGLOC,
+ // Helpers.
+ RECORD_FIRST = RECORD_META_CONTAINER_INFO,
+ RECORD_LAST = RECORD_REMARK_ARG_WITHOUT_DEBUGLOC
+};
+
+constexpr StringRef MetaContainerInfoName = StringRef("Container info", 14);
+constexpr StringRef MetaRemarkVersionName = StringRef("Remark version", 14);
+constexpr StringRef MetaStrTabName = StringRef("String table", 12);
+constexpr StringRef MetaExternalFileName = StringRef("External File", 13);
+constexpr StringRef RemarkHeaderName = StringRef("Remark header", 13);
+constexpr StringRef RemarkDebugLocName = StringRef("Remark debug location", 21);
+constexpr StringRef RemarkHotnessName = StringRef("Remark hotness", 14);
+constexpr StringRef RemarkArgWithDebugLocName =
+ StringRef("Argument with debug location", 28);
+constexpr StringRef RemarkArgWithoutDebugLocName = StringRef("Argument", 8);
+
+} // end namespace remarks
+} // end namespace llvm
+
+#endif /* LLVM_REMARKS_REMARK_CONTAINER_H */
diff --git a/include/llvm/Remarks/BitstreamRemarkParser.h b/include/llvm/Remarks/BitstreamRemarkParser.h
new file mode 100644
index 000000000000..7ebd731693b2
--- /dev/null
+++ b/include/llvm/Remarks/BitstreamRemarkParser.h
@@ -0,0 +1,116 @@
+//===-- BitstreamRemarkParser.h - Bitstream parser --------------*- 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 remark parser using the LLVM
+// Bitstream format.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_REMARKS_BITSTREAM_REMARK_PARSER_H
+#define LLVM_REMARKS_BITSTREAM_REMARK_PARSER_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Bitstream/BitstreamReader.h"
+#include "llvm/Remarks/BitstreamRemarkContainer.h"
+#include "llvm/Remarks/Remark.h"
+#include "llvm/Remarks/RemarkParser.h"
+#include "llvm/Support/Error.h"
+#include <array>
+
+namespace llvm {
+namespace remarks {
+
+/// Helper to parse a META_BLOCK for a bitstream remark container.
+struct BitstreamMetaParserHelper {
+ /// The Bitstream reader.
+ BitstreamCursor &Stream;
+ /// Reference to the storage for the block info.
+ BitstreamBlockInfo &BlockInfo;
+ /// The parsed content: depending on the container type, some fields might be
+ /// empty.
+ Optional<uint64_t> ContainerVersion;
+ Optional<uint8_t> ContainerType;
+ Optional<StringRef> StrTabBuf;
+ Optional<StringRef> ExternalFilePath;
+ Optional<uint64_t> RemarkVersion;
+
+ /// Continue parsing with \p Stream. \p Stream is expected to contain a
+ /// ENTER_SUBBLOCK to the META_BLOCK at the current position.
+ /// \p Stream is expected to have a BLOCKINFO_BLOCK set.
+ BitstreamMetaParserHelper(BitstreamCursor &Stream,
+ BitstreamBlockInfo &BlockInfo);
+
+ /// Parse the META_BLOCK and fill the available entries.
+ /// This helper does not check for the validity of the fields.
+ Error parse();
+};
+
+/// Helper to parse a REMARK_BLOCK for a bitstream remark container.
+struct BitstreamRemarkParserHelper {
+ /// The Bitstream reader.
+ BitstreamCursor &Stream;
+ /// The parsed content: depending on the remark, some fields might be empty.
+ Optional<uint8_t> Type;
+ Optional<uint64_t> RemarkNameIdx;
+ Optional<uint64_t> PassNameIdx;
+ Optional<uint64_t> FunctionNameIdx;
+ Optional<uint64_t> SourceFileNameIdx;
+ Optional<uint32_t> SourceLine;
+ Optional<uint32_t> SourceColumn;
+ Optional<uint64_t> Hotness;
+ struct Argument {
+ Optional<uint64_t> KeyIdx;
+ Optional<uint64_t> ValueIdx;
+ Optional<uint64_t> SourceFileNameIdx;
+ Optional<uint32_t> SourceLine;
+ Optional<uint32_t> SourceColumn;
+ };
+ Optional<ArrayRef<Argument>> Args;
+ /// Avoid re-allocating a vector every time.
+ SmallVector<Argument, 8> TmpArgs;
+
+ /// Continue parsing with \p Stream. \p Stream is expected to contain a
+ /// ENTER_SUBBLOCK to the REMARK_BLOCK at the current position.
+ /// \p Stream is expected to have a BLOCKINFO_BLOCK set and to have already
+ /// parsed the META_BLOCK.
+ BitstreamRemarkParserHelper(BitstreamCursor &Stream);
+
+ /// Parse the REMARK_BLOCK and fill the available entries.
+ /// This helper does not check for the validity of the fields.
+ Error parse();
+};
+
+/// Helper to parse any bitstream remark container.
+struct BitstreamParserHelper {
+ /// The Bitstream reader.
+ BitstreamCursor Stream;
+ /// The block info block.
+ BitstreamBlockInfo BlockInfo;
+ /// Start parsing at \p Buffer.
+ BitstreamParserHelper(StringRef Buffer);
+ /// Parse the magic number.
+ Expected<std::array<char, 4>> parseMagic();
+ /// Parse the block info block containing all the abbrevs.
+ /// This needs to be called before calling any other parsing function.
+ Error parseBlockInfoBlock();
+ /// Return true if the next block is a META_BLOCK. This function does not move
+ /// the cursor.
+ Expected<bool> isMetaBlock();
+ /// Return true if the next block is a REMARK_BLOCK. This function does not
+ /// move the cursor.
+ Expected<bool> isRemarkBlock();
+ /// Return true if the parser reached the end of the stream.
+ bool atEndOfStream() { return Stream.AtEndOfStream(); }
+ /// Jump to the end of the stream, skipping everything.
+ void skipToEnd() { return Stream.skipToEnd(); }
+};
+
+} // end namespace remarks
+} // end namespace llvm
+
+#endif /* LLVM_REMARKS_BITSTREAM_REMARK_PARSER_H */
diff --git a/include/llvm/Remarks/BitstreamRemarkSerializer.h b/include/llvm/Remarks/BitstreamRemarkSerializer.h
new file mode 100644
index 000000000000..62a175a1db0b
--- /dev/null
+++ b/include/llvm/Remarks/BitstreamRemarkSerializer.h
@@ -0,0 +1,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 */
diff --git a/include/llvm/Remarks/Remark.h b/include/llvm/Remarks/Remark.h
index 05d0ea60accd..1243311fb8c5 100644
--- a/include/llvm/Remarks/Remark.h
+++ b/include/llvm/Remarks/Remark.h
@@ -23,7 +23,8 @@
namespace llvm {
namespace remarks {
-constexpr uint64_t Version = 0;
+/// The current version of the remark entry.
+constexpr uint64_t CurrentRemarkVersion = 0;
/// The debug location used to track a remark back to the source file.
struct RemarkLocation {
@@ -58,7 +59,8 @@ enum class Type {
AnalysisFPCommute,
AnalysisAliasing,
Failure,
- LastTypeValue = Failure
+ First = Unknown,
+ Last = Failure
};
/// A remark type used for both emission and parsing.
@@ -107,6 +109,36 @@ private:
// Create wrappers for C Binding types (see CBindingWrapping.h).
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Remark, LLVMRemarkEntryRef)
+/// Comparison operators for Remark objects and dependent objects.
+inline bool operator==(const RemarkLocation &LHS, const RemarkLocation &RHS) {
+ return LHS.SourceFilePath == RHS.SourceFilePath &&
+ LHS.SourceLine == RHS.SourceLine &&
+ LHS.SourceColumn == RHS.SourceColumn;
+}
+
+inline bool operator!=(const RemarkLocation &LHS, const RemarkLocation &RHS) {
+ return !(LHS == RHS);
+}
+
+inline bool operator==(const Argument &LHS, const Argument &RHS) {
+ return LHS.Key == RHS.Key && LHS.Val == RHS.Val && LHS.Loc == RHS.Loc;
+}
+
+inline bool operator!=(const Argument &LHS, const Argument &RHS) {
+ return !(LHS == RHS);
+}
+
+inline bool operator==(const Remark &LHS, const Remark &RHS) {
+ return LHS.RemarkType == RHS.RemarkType && LHS.PassName == RHS.PassName &&
+ LHS.RemarkName == RHS.RemarkName &&
+ LHS.FunctionName == RHS.FunctionName && LHS.Loc == RHS.Loc &&
+ LHS.Hotness == RHS.Hotness && LHS.Args == RHS.Args;
+}
+
+inline bool operator!=(const Remark &LHS, const Remark &RHS) {
+ return !(LHS == RHS);
+}
+
} // end namespace remarks
} // end namespace llvm
diff --git a/include/llvm/Remarks/RemarkFormat.h b/include/llvm/Remarks/RemarkFormat.h
index e167d99d2517..6dd32b226099 100644
--- a/include/llvm/Remarks/RemarkFormat.h
+++ b/include/llvm/Remarks/RemarkFormat.h
@@ -19,10 +19,10 @@
namespace llvm {
namespace remarks {
-constexpr StringRef Magic("REMARKS", 7);
+constexpr StringLiteral Magic("REMARKS");
/// The format used for serializing/deserializing remarks.
-enum class Format { Unknown, YAML };
+enum class Format { Unknown, YAML, YAMLStrTab, Bitstream };
/// Parse and validate a string for the remark format.
Expected<Format> parseFormat(StringRef FormatStr);
diff --git a/include/llvm/Remarks/RemarkParser.h b/include/llvm/Remarks/RemarkParser.h
index 671e1abe5ec7..d6b1fddb06ff 100644
--- a/include/llvm/Remarks/RemarkParser.h
+++ b/include/llvm/Remarks/RemarkParser.h
@@ -23,9 +23,6 @@
namespace llvm {
namespace remarks {
-struct ParserImpl;
-struct ParsedStringTable;
-
class EndOfFileError : public ErrorInfo<EndOfFileError> {
public:
static char ID;
@@ -39,11 +36,13 @@ public:
};
/// Parser used to parse a raw buffer to remarks::Remark objects.
-struct Parser {
+struct RemarkParser {
/// The format of the parser.
Format ParserFormat;
+ /// Path to prepend when opening an external remark file.
+ std::string ExternalFilePrependPath;
- Parser(Format ParserFormat) : ParserFormat(ParserFormat) {}
+ RemarkParser(Format ParserFormat) : ParserFormat(ParserFormat) {}
/// If no error occurs, this returns a valid Remark object.
/// If an error of type EndOfFileError occurs, it is safe to recover from it
@@ -52,7 +51,7 @@ struct Parser {
/// The pointer should never be null.
virtual Expected<std::unique_ptr<Remark>> next() = 0;
- virtual ~Parser() = default;
+ virtual ~RemarkParser() = default;
};
/// In-memory representation of the string table parsed from a buffer (e.g. the
@@ -60,16 +59,33 @@ struct Parser {
struct ParsedStringTable {
/// The buffer mapped from the section contents.
StringRef Buffer;
- /// Collection of offsets in the buffer for each string entry.
- SmallVector<size_t, 8> Offsets;
+ /// This object has high changes to be std::move'd around, so don't use a
+ /// SmallVector for once.
+ std::vector<size_t> Offsets;
- Expected<StringRef> operator[](size_t Index) const;
ParsedStringTable(StringRef Buffer);
+ /// Disable copy.
+ ParsedStringTable(const ParsedStringTable &) = delete;
+ ParsedStringTable &operator=(const ParsedStringTable &) = delete;
+ /// Should be movable.
+ ParsedStringTable(ParsedStringTable &&) = default;
+ ParsedStringTable &operator=(ParsedStringTable &&) = default;
+
+ size_t size() const { return Offsets.size(); }
+ Expected<StringRef> operator[](size_t Index) const;
};
-Expected<std::unique_ptr<Parser>>
+Expected<std::unique_ptr<RemarkParser>> createRemarkParser(Format ParserFormat,
+ StringRef Buf);
+
+Expected<std::unique_ptr<RemarkParser>>
createRemarkParser(Format ParserFormat, StringRef Buf,
- Optional<const ParsedStringTable *> StrTab = None);
+ ParsedStringTable StrTab);
+
+Expected<std::unique_ptr<RemarkParser>>
+createRemarkParserFromMeta(Format ParserFormat, StringRef Buf,
+ Optional<ParsedStringTable> StrTab = None,
+ Optional<StringRef> ExternalFilePrependPath = None);
} // end namespace remarks
} // end namespace llvm
diff --git a/include/llvm/Remarks/RemarkSerializer.h b/include/llvm/Remarks/RemarkSerializer.h
index def5c2e16620..35752cd5f6fb 100644
--- a/include/llvm/Remarks/RemarkSerializer.h
+++ b/include/llvm/Remarks/RemarkSerializer.h
@@ -14,54 +14,74 @@
#define LLVM_REMARKS_REMARK_SERIALIZER_H
#include "llvm/Remarks/Remark.h"
+#include "llvm/Remarks/RemarkFormat.h"
#include "llvm/Remarks/RemarkStringTable.h"
-#include "llvm/Support/YAMLTraits.h"
#include "llvm/Support/raw_ostream.h"
namespace llvm {
namespace remarks {
+enum class SerializerMode {
+ Separate, // A mode where the metadata is serialized separately from the
+ // remarks. Typically, this is used when the remarks need to be
+ // streamed to a side file and the metadata is embedded into the
+ // final result of the compilation.
+ Standalone // A mode where everything can be retrieved in the same
+ // file/buffer. Typically, this is used for storing remarks for
+ // later use.
+};
+
+struct MetaSerializer;
+
/// This is the base class for a remark serializer.
/// It includes support for using a string table while emitting.
-struct Serializer {
+struct RemarkSerializer {
+ /// The format of the serializer.
+ Format SerializerFormat;
/// The open raw_ostream that the remark diagnostics are emitted to.
raw_ostream &OS;
+ /// The serialization mode.
+ SerializerMode Mode;
/// The string table containing all the unique strings used in the output.
/// The table can be serialized to be consumed after the compilation.
Optional<StringTable> StrTab;
- Serializer(raw_ostream &OS) : OS(OS), StrTab() {}
+ RemarkSerializer(Format SerializerFormat, raw_ostream &OS,
+ SerializerMode Mode)
+ : SerializerFormat(SerializerFormat), OS(OS), Mode(Mode), StrTab() {}
/// This is just an interface.
- virtual ~Serializer() = default;
+ virtual ~RemarkSerializer() = default;
+ /// Emit a remark to the stream.
virtual void emit(const Remark &Remark) = 0;
+ /// Return the corresponding metadata serializer.
+ virtual std::unique_ptr<MetaSerializer>
+ metaSerializer(raw_ostream &OS,
+ Optional<StringRef> ExternalFilename = None) = 0;
};
-/// Wether the serializer should use a string table while emitting.
-enum class UseStringTable { No, Yes };
-
-/// Serialize the remarks to YAML. One remark entry looks like this:
-/// --- !<TYPE>
-/// Pass: <PASSNAME>
-/// Name: <REMARKNAME>
-/// DebugLoc: { File: <SOURCEFILENAME>, Line: <SOURCELINE>,
-/// Column: <SOURCECOLUMN> }
-/// Function: <FUNCTIONNAME>
-/// Args:
-/// - <KEY>: <VALUE>
-/// DebugLoc: { File: <FILE>, Line: <LINE>, Column: <COL> }
-/// ...
-struct YAMLSerializer : public Serializer {
- /// The YAML streamer.
- yaml::Output YAMLOutput;
+/// This is the base class for a remark metadata serializer.
+struct MetaSerializer {
+ /// The open raw_ostream that the metadata is emitted to.
+ raw_ostream &OS;
- YAMLSerializer(raw_ostream &OS,
- UseStringTable UseStringTable = remarks::UseStringTable::No);
+ MetaSerializer(raw_ostream &OS) : OS(OS) {}
- /// Emit a remark to the stream.
- void emit(const Remark &Remark) override;
+ /// This is just an interface.
+ virtual ~MetaSerializer() = default;
+ virtual void emit() = 0;
};
+/// Create a remark serializer.
+Expected<std::unique_ptr<RemarkSerializer>>
+createRemarkSerializer(Format RemarksFormat, SerializerMode Mode,
+ raw_ostream &OS);
+
+/// Create a remark serializer that uses a pre-filled string table.
+Expected<std::unique_ptr<RemarkSerializer>>
+createRemarkSerializer(Format RemarksFormat, SerializerMode Mode,
+ raw_ostream &OS, remarks::StringTable StrTab);
+
} // end namespace remarks
} // end namespace llvm
diff --git a/include/llvm/Remarks/RemarkStringTable.h b/include/llvm/Remarks/RemarkStringTable.h
index f9b4fdbbfb8d..4ce27ee884c8 100644
--- a/include/llvm/Remarks/RemarkStringTable.h
+++ b/include/llvm/Remarks/RemarkStringTable.h
@@ -18,7 +18,7 @@
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Allocator.h"
+#include "llvm/Remarks/Remark.h"
#include <vector>
namespace llvm {
@@ -27,21 +27,35 @@ class raw_ostream;
namespace remarks {
+struct ParsedStringTable;
+
/// The string table used for serializing remarks.
/// This table can be for example serialized in a section to be consumed after
/// the compilation.
struct StringTable {
- /// Allocator holding all the memory used by the map.
- BumpPtrAllocator Allocator;
/// The string table containing all the unique strings used in the output.
/// It maps a string to an unique ID.
- StringMap<unsigned, BumpPtrAllocator &> StrTab;
+ StringMap<unsigned, BumpPtrAllocator> StrTab;
/// Total size of the string table when serialized.
size_t SerializedSize = 0;
- StringTable() : Allocator(), StrTab(Allocator) {}
+ StringTable() = default;
+
+ /// Disable copy.
+ StringTable(const StringTable &) = delete;
+ StringTable &operator=(const StringTable &) = delete;
+ /// Should be movable.
+ StringTable(StringTable &&) = default;
+ StringTable &operator=(StringTable &&) = default;
+
+ /// Construct a string table from a ParsedStringTable.
+ StringTable(const ParsedStringTable &Other);
+
/// Add a string to the table. It returns an unique ID of the string.
std::pair<unsigned, StringRef> add(StringRef Str);
+ /// Modify \p R to use strings from this string table. If the string table
+ /// does not contain the strings, it adds them.
+ void internalize(Remark &R);
/// Serialize the string table to a stream. It is serialized as a little
/// endian uint64 (the size of the table in bytes) followed by a sequence of
/// NULL-terminated strings, where the N-th string is the string with the ID N
diff --git a/include/llvm/Remarks/YAMLRemarkSerializer.h b/include/llvm/Remarks/YAMLRemarkSerializer.h
new file mode 100644
index 000000000000..f1213beab15d
--- /dev/null
+++ b/include/llvm/Remarks/YAMLRemarkSerializer.h
@@ -0,0 +1,108 @@
+//===-- YAMLRemarkSerializer.h - YAML Remark serialization ---*- 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 interface for serializing remarks to YAML.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_REMARKS_YAML_REMARK_SERIALIZER_H
+#define LLVM_REMARKS_YAML_REMARK_SERIALIZER_H
+
+#include "llvm/Remarks/RemarkSerializer.h"
+#include "llvm/Support/YAMLTraits.h"
+
+namespace llvm {
+namespace remarks {
+
+/// Serialize the remarks to YAML. One remark entry looks like this:
+/// --- !<TYPE>
+/// Pass: <PASSNAME>
+/// Name: <REMARKNAME>
+/// DebugLoc: { File: <SOURCEFILENAME>, Line: <SOURCELINE>,
+/// Column: <SOURCECOLUMN> }
+/// Function: <FUNCTIONNAME>
+/// Args:
+/// - <KEY>: <VALUE>
+/// DebugLoc: { File: <FILE>, Line: <LINE>, Column: <COL> }
+/// ...
+struct YAMLRemarkSerializer : public RemarkSerializer {
+ /// The YAML streamer.
+ yaml::Output YAMLOutput;
+
+ YAMLRemarkSerializer(raw_ostream &OS, SerializerMode Mode,
+ Optional<StringTable> StrTab = None);
+
+ void emit(const Remark &Remark) override;
+ std::unique_ptr<MetaSerializer>
+ metaSerializer(raw_ostream &OS,
+ Optional<StringRef> ExternalFilename = None) override;
+
+ static bool classof(const RemarkSerializer *S) {
+ return S->SerializerFormat == Format::YAML;
+ }
+
+protected:
+ YAMLRemarkSerializer(Format SerializerFormat, raw_ostream &OS,
+ SerializerMode Mode,
+ Optional<StringTable> StrTab = None);
+};
+
+struct YAMLMetaSerializer : public MetaSerializer {
+ Optional<StringRef> ExternalFilename;
+
+ YAMLMetaSerializer(raw_ostream &OS, Optional<StringRef> ExternalFilename)
+ : MetaSerializer(OS), ExternalFilename(ExternalFilename) {}
+
+ void emit() override;
+};
+
+/// Serialize the remarks to YAML using a string table. An remark entry looks
+/// like the regular YAML remark but instead of string entries it's using
+/// numbers that map to an index in the string table.
+struct YAMLStrTabRemarkSerializer : public YAMLRemarkSerializer {
+ /// Wether we already emitted the metadata in standalone mode.
+ /// This should be set to true after the first invocation of `emit`.
+ bool DidEmitMeta = false;
+
+ YAMLStrTabRemarkSerializer(raw_ostream &OS, SerializerMode Mode)
+ : YAMLRemarkSerializer(Format::YAMLStrTab, OS, Mode) {
+ // We always need a string table for this type of serializer.
+ StrTab.emplace();
+ }
+ YAMLStrTabRemarkSerializer(raw_ostream &OS, SerializerMode Mode,
+ StringTable StrTab)
+ : YAMLRemarkSerializer(Format::YAMLStrTab, OS, Mode, std::move(StrTab)) {}
+
+ /// Override to emit the metadata if necessary.
+ void emit(const Remark &Remark) override;
+
+ std::unique_ptr<MetaSerializer>
+ metaSerializer(raw_ostream &OS,
+ Optional<StringRef> ExternalFilename = None) override;
+
+ static bool classof(const RemarkSerializer *S) {
+ return S->SerializerFormat == Format::YAMLStrTab;
+ }
+};
+
+struct YAMLStrTabMetaSerializer : public YAMLMetaSerializer {
+ /// The string table is part of the metadata.
+ const StringTable &StrTab;
+
+ YAMLStrTabMetaSerializer(raw_ostream &OS,
+ Optional<StringRef> ExternalFilename,
+ const StringTable &StrTab)
+ : YAMLMetaSerializer(OS, ExternalFilename), StrTab(StrTab) {}
+
+ void emit() override;
+};
+
+} // end namespace remarks
+} // end namespace llvm
+
+#endif /* LLVM_REMARKS_REMARK_SERIALIZER_H */