Update prebuilt Clang to r416183b from Android.

https://android.googlesource.com/platform/prebuilts/clang/host/
linux-x86/+/06a71ddac05c22edb2d10b590e1769b3f8619bef

clang 12.0.5 (based on r416183b) from build 7284624.

Change-Id: I277a316abcf47307562d8b748b84870f31a72866
Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
diff --git a/linux-x64/clang/include/llvm/Remarks/BitstreamRemarkContainer.h b/linux-x64/clang/include/llvm/Remarks/BitstreamRemarkContainer.h
new file mode 100644
index 0000000..a2282fc
--- /dev/null
+++ b/linux-x64/clang/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/linux-x64/clang/include/llvm/Remarks/BitstreamRemarkParser.h b/linux-x64/clang/include/llvm/Remarks/BitstreamRemarkParser.h
new file mode 100644
index 0000000..f7553ba
--- /dev/null
+++ b/linux-x64/clang/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/ArrayRef.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Bitstream/BitstreamReader.h"
+#include "llvm/Support/Error.h"
+#include <array>
+#include <cstdint>
+
+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/linux-x64/clang/include/llvm/Remarks/BitstreamRemarkSerializer.h b/linux-x64/clang/include/llvm/Remarks/BitstreamRemarkSerializer.h
new file mode 100644
index 0000000..62a175a
--- /dev/null
+++ b/linux-x64/clang/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/linux-x64/clang/include/llvm/Remarks/HotnessThresholdParser.h b/linux-x64/clang/include/llvm/Remarks/HotnessThresholdParser.h
new file mode 100644
index 0000000..08bbf5f
--- /dev/null
+++ b/linux-x64/clang/include/llvm/Remarks/HotnessThresholdParser.h
@@ -0,0 +1,63 @@
+//===- HotnessThresholdParser.h - Parser for hotness threshold --*- 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file implements a simple parser to decode commandline option for
+/// remarks hotness threshold that supports both int and a special 'auto' value.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_REMARKS_HOTNESSTHRESHOLDPARSER_H
+#define LLVM_REMARKS_HOTNESSTHRESHOLDPARSER_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/Support/CommandLine.h"
+
+namespace llvm {
+namespace remarks {
+
+// Parse remarks hotness threshold argument value.
+// Valid option values are
+// 1. integer: manually specified threshold; or
+// 2. string 'auto': automatically get threshold from profile summary.
+//
+// Return None Optional if 'auto' is specified, indicating the value will
+// be filled later during PSI.
+inline Expected<Optional<uint64_t>> parseHotnessThresholdOption(StringRef Arg) {
+  if (Arg == "auto")
+    return None;
+
+  int64_t Val;
+  if (Arg.getAsInteger(10, Val))
+    return createStringError(llvm::inconvertibleErrorCode(),
+                             "Not an integer: %s", Arg.data());
+
+  // Negative integer effectively means no threshold
+  return Val < 0 ? 0 : Val;
+}
+
+// A simple CL parser for '*-remarks-hotness-threshold='
+class HotnessThresholdParser : public cl::parser<Optional<uint64_t>> {
+public:
+  HotnessThresholdParser(cl::Option &O) : cl::parser<Optional<uint64_t>>(O) {}
+
+  bool parse(cl::Option &O, StringRef ArgName, StringRef Arg,
+             Optional<uint64_t> &V) {
+    auto ResultOrErr = parseHotnessThresholdOption(Arg);
+    if (!ResultOrErr)
+      return O.error("Invalid argument '" + Arg +
+                     "', only integer or 'auto' is supported.");
+
+    V = *ResultOrErr;
+    return false;
+  }
+};
+
+} // namespace remarks
+} // namespace llvm
+#endif // LLVM_REMARKS_HOTNESSTHRESHOLDPARSER_H
diff --git a/linux-x64/clang/include/llvm/Remarks/Remark.h b/linux-x64/clang/include/llvm/Remarks/Remark.h
index d916728..160e8dc 100644
--- a/linux-x64/clang/include/llvm/Remarks/Remark.h
+++ b/linux-x64/clang/include/llvm/Remarks/Remark.h
@@ -14,8 +14,8 @@
 #define LLVM_REMARKS_REMARK_H
 
 #include "llvm-c/Remarks.h"
-#include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/CBindingWrapping.h"
 #include <string>
@@ -23,15 +23,15 @@
 namespace llvm {
 namespace remarks {
 
-constexpr uint64_t Version = 0;
-constexpr StringRef Magic("REMARKS", 7);
+/// 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 {
   /// Absolute path of the source file corresponding to this remark.
   StringRef SourceFilePath;
-  unsigned SourceLine;
-  unsigned SourceColumn;
+  unsigned SourceLine = 0;
+  unsigned SourceColumn = 0;
 };
 
 // Create wrappers for C Binding types (see CBindingWrapping.h).
@@ -59,7 +59,8 @@
   AnalysisFPCommute,
   AnalysisAliasing,
   Failure,
-  LastTypeValue = Failure
+  First = Unknown,
+  Last = Failure
 };
 
 /// A remark type used for both emission and parsing.
@@ -86,15 +87,90 @@
   Optional<uint64_t> Hotness;
 
   /// Arguments collected via the streaming interface.
-  ArrayRef<Argument> Args;
+  SmallVector<Argument, 5> Args;
+
+  Remark() = default;
+  Remark(Remark &&) = default;
+  Remark &operator=(Remark &&) = default;
 
   /// Return a message composed from the arguments as a string.
   std::string getArgsAsMsg() const;
+
+  /// Clone this remark to explicitly ask for a copy.
+  Remark clone() const { return *this; }
+
+private:
+  /// In order to avoid unwanted copies, "delete" the copy constructor.
+  /// If a copy is needed, it should be done through `Remark::clone()`.
+  Remark(const Remark &) = default;
+  Remark& operator=(const Remark &) = default;
 };
 
 // Create wrappers for C Binding types (see CBindingWrapping.h).
 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Remark, LLVMRemarkEntryRef)
 
+/// Comparison operators for Remark objects and dependent objects.
+
+template <typename T>
+bool operator<(const Optional<T> &LHS, const Optional<T> &RHS) {
+  // Sorting based on optionals should result in all `None` entries to appear
+  // before the valid entries. For example, remarks with no debug location will
+  // appear first.
+  if (!LHS && !RHS)
+    return false;
+  if (!LHS && RHS)
+    return true;
+  if (LHS && !RHS)
+    return false;
+  return *LHS < *RHS;
+}
+
+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 RemarkLocation &LHS, const RemarkLocation &RHS) {
+  return std::make_tuple(LHS.SourceFilePath, LHS.SourceLine, LHS.SourceColumn) <
+         std::make_tuple(RHS.SourceFilePath, RHS.SourceLine, RHS.SourceColumn);
+}
+
+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 Argument &LHS, const Argument &RHS) {
+  return std::make_tuple(LHS.Key, LHS.Val, LHS.Loc) <
+         std::make_tuple(RHS.Key, RHS.Val, RHS.Loc);
+}
+
+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);
+}
+
+inline bool operator<(const Remark &LHS, const Remark &RHS) {
+  return std::make_tuple(LHS.RemarkType, LHS.PassName, LHS.RemarkName,
+                         LHS.FunctionName, LHS.Loc, LHS.Hotness, LHS.Args) <
+         std::make_tuple(RHS.RemarkType, RHS.PassName, RHS.RemarkName,
+                         RHS.FunctionName, RHS.Loc, RHS.Hotness, RHS.Args);
+}
+
 } // end namespace remarks
 } // end namespace llvm
 
diff --git a/linux-x64/clang/include/llvm/Remarks/RemarkFormat.h b/linux-x64/clang/include/llvm/Remarks/RemarkFormat.h
new file mode 100644
index 0000000..a432c5a
--- /dev/null
+++ b/linux-x64/clang/include/llvm/Remarks/RemarkFormat.h
@@ -0,0 +1,36 @@
+//===-- llvm/Remarks/RemarkFormat.h - The format of remarks -----*- 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 defines utilities to deal with the format of remarks.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_REMARKS_REMARK_FORMAT_H
+#define LLVM_REMARKS_REMARK_FORMAT_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+namespace remarks {
+
+constexpr StringLiteral Magic("REMARKS");
+
+/// The format used for serializing/deserializing remarks.
+enum class Format { Unknown, YAML, YAMLStrTab, Bitstream };
+
+/// Parse and validate a string for the remark format.
+Expected<Format> parseFormat(StringRef FormatStr);
+
+/// Parse and validate a magic number to a remark format.
+Expected<Format> magicToFormat(StringRef Magic);
+
+} // end namespace remarks
+} // end namespace llvm
+
+#endif /* LLVM_REMARKS_REMARK_FORMAT_H */
diff --git a/linux-x64/clang/include/llvm/Remarks/RemarkLinker.h b/linux-x64/clang/include/llvm/Remarks/RemarkLinker.h
new file mode 100644
index 0000000..7a53c30
--- /dev/null
+++ b/linux-x64/clang/include/llvm/Remarks/RemarkLinker.h
@@ -0,0 +1,99 @@
+//===-- llvm/Remarks/RemarkLinker.h -----------------------------*- 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 to link together multiple remark files.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_REMARKS_REMARK_LINKER_H
+#define LLVM_REMARKS_REMARK_LINKER_H
+
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/Remarks/Remark.h"
+#include "llvm/Remarks/RemarkFormat.h"
+#include "llvm/Remarks/RemarkStringTable.h"
+#include "llvm/Support/Error.h"
+#include <memory>
+#include <set>
+
+namespace llvm {
+namespace remarks {
+
+struct RemarkLinker {
+private:
+  /// Compare through the pointers.
+  struct RemarkPtrCompare {
+    bool operator()(const std::unique_ptr<Remark> &LHS,
+                    const std::unique_ptr<Remark> &RHS) const {
+      assert(LHS && RHS && "Invalid pointers to compare.");
+      return *LHS < *RHS;
+    };
+  };
+
+  /// The main string table for the remarks.
+  /// Note: all remarks should use the strings from this string table to avoid
+  /// dangling references.
+  StringTable StrTab;
+
+  /// A set holding unique remarks.
+  /// FIXME: std::set is probably not the most appropriate data structure here.
+  /// Due to the limitation of having a move-only key, there isn't another
+  /// obvious choice for now.
+  std::set<std::unique_ptr<Remark>, RemarkPtrCompare> Remarks;
+
+  /// A path to append before the external file path found in remark metadata.
+  Optional<std::string> PrependPath;
+
+  /// Keep this remark. If it's already in the set, discard it.
+  Remark &keep(std::unique_ptr<Remark> Remark);
+
+public:
+  /// Set a path to prepend to the external file path.
+  void setExternalFilePrependPath(StringRef PrependPath);
+
+  /// Link the remarks found in \p Buffer.
+  /// If \p RemarkFormat is not provided, try to deduce it from the metadata in
+  /// \p Buffer.
+  /// \p Buffer can be either a standalone remark container or just
+  /// metadata. This takes care of uniquing and merging the remarks.
+  Error link(StringRef Buffer, Optional<Format> RemarkFormat = None);
+
+  /// Link the remarks found in \p Obj by looking for the right section and
+  /// calling the method above.
+  Error link(const object::ObjectFile &Obj,
+             Optional<Format> RemarkFormat = None);
+
+  /// Serialize the linked remarks to the stream \p OS, using the format \p
+  /// RemarkFormat.
+  /// This clears internal state such as the string table.
+  /// Note: this implies that the serialization mode is standalone.
+  Error serialize(raw_ostream &OS, Format RemarksFormat) const;
+
+  /// Check whether there are any remarks linked.
+  bool empty() const { return Remarks.empty(); }
+
+  /// Return a collection of the linked unique remarks to iterate on.
+  /// Ex:
+  /// for (const Remark &R : RL.remarks() { [...] }
+  using iterator = pointee_iterator<decltype(Remarks)::const_iterator>;
+
+  iterator_range<iterator> remarks() const {
+    return {Remarks.begin(), Remarks.end()};
+  }
+};
+
+/// Returns a buffer with the contents of the remarks section depending on the
+/// format of the file. If the section doesn't exist, this returns an empty
+/// optional.
+Expected<Optional<StringRef>>
+getRemarksSectionContents(const object::ObjectFile &Obj);
+
+} // end namespace remarks
+} // end namespace llvm
+
+#endif /* LLVM_REMARKS_REMARK_LINKER_H */
diff --git a/linux-x64/clang/include/llvm/Remarks/RemarkParser.h b/linux-x64/clang/include/llvm/Remarks/RemarkParser.h
index 457b2fb..d6b1fdd 100644
--- a/linux-x64/clang/include/llvm/Remarks/RemarkParser.h
+++ b/linux-x64/clang/include/llvm/Remarks/RemarkParser.h
@@ -16,38 +16,42 @@
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Remarks/Remark.h"
+#include "llvm/Remarks/RemarkFormat.h"
 #include "llvm/Support/Error.h"
 #include <memory>
 
 namespace llvm {
 namespace remarks {
 
-struct ParserImpl;
-struct ParsedStringTable;
+class EndOfFileError : public ErrorInfo<EndOfFileError> {
+public:
+  static char ID;
 
-enum class ParserFormat { YAML };
+  EndOfFileError() {}
+
+  void log(raw_ostream &OS) const override { OS << "End of file reached."; }
+  std::error_code convertToErrorCode() const override {
+    return inconvertibleErrorCode();
+  }
+};
 
 /// Parser used to parse a raw buffer to remarks::Remark objects.
-struct Parser {
-  /// The hidden implementation of the parser.
-  std::unique_ptr<ParserImpl> Impl;
+struct RemarkParser {
+  /// The format of the parser.
+  Format ParserFormat;
+  /// Path to prepend when opening an external remark file.
+  std::string ExternalFilePrependPath;
 
-  /// Create a parser parsing \p Buffer to Remark objects.
-  /// This constructor should be only used for parsing remarks without a string
-  /// table.
-  Parser(ParserFormat Format, StringRef Buffer);
+  RemarkParser(Format ParserFormat) : ParserFormat(ParserFormat) {}
 
-  /// Create a parser parsing \p Buffer to Remark objects, using \p StrTab as a
-  /// string table.
-  Parser(ParserFormat Format, StringRef Buffer,
-         const ParsedStringTable &StrTab);
+  /// If no error occurs, this returns a valid Remark object.
+  /// If an error of type EndOfFileError occurs, it is safe to recover from it
+  /// by stopping the parsing.
+  /// If any other error occurs, it should be propagated to the user.
+  /// The pointer should never be null.
+  virtual Expected<std::unique_ptr<Remark>> next() = 0;
 
-  // Needed because ParserImpl is an incomplete type.
-  ~Parser();
-
-  /// Returns an empty Optional if it reached the end.
-  /// Returns a valid remark otherwise.
-  Expected<const Remark *> getNext() const;
+  virtual ~RemarkParser() = default;
 };
 
 /// In-memory representation of the string table parsed from a buffer (e.g. the
@@ -55,13 +59,34 @@
 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<RemarkParser>> createRemarkParser(Format ParserFormat,
+                                                           StringRef Buf);
+
+Expected<std::unique_ptr<RemarkParser>>
+createRemarkParser(Format ParserFormat, StringRef Buf,
+                   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/linux-x64/clang/include/llvm/Remarks/RemarkSerializer.h b/linux-x64/clang/include/llvm/Remarks/RemarkSerializer.h
index def5c2e..35752cd 100644
--- a/linux-x64/clang/include/llvm/Remarks/RemarkSerializer.h
+++ b/linux-x64/clang/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 void emit(const Remark &Remark) = 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;
-
-  YAMLSerializer(raw_ostream &OS,
-                 UseStringTable UseStringTable = remarks::UseStringTable::No);
-
+  virtual ~RemarkSerializer() = default;
   /// Emit a remark to the stream.
-  void emit(const Remark &Remark) override;
+  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;
 };
 
+/// 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;
+
+  MetaSerializer(raw_ostream &OS) : OS(OS) {}
+
+  /// 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/linux-x64/clang/include/llvm/Remarks/RemarkStreamer.h b/linux-x64/clang/include/llvm/Remarks/RemarkStreamer.h
new file mode 100644
index 0000000..7741cb4
--- /dev/null
+++ b/linux-x64/clang/include/llvm/Remarks/RemarkStreamer.h
@@ -0,0 +1,73 @@
+//===- llvm/Remarks/RemarkStreamer.h ----------------------------*- 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 declares the main interface for streaming remarks.
+//
+// This is used to stream any llvm::remarks::Remark to an open file taking
+// advantage of all the serialization capabilities developed for remarks (e.g.
+// metadata in a section, bitstream format, etc.).
+//
+// Typically, a specialized remark emitter should hold a reference to the main
+// remark streamer set up in the LLVMContext, and should convert specialized
+// diagnostics to llvm::remarks::Remark objects as they get emitted.
+//
+// Specialized remark emitters can be components like:
+// * Remarks from LLVM (M)IR passes
+// * Remarks from the frontend
+// * Remarks from an intermediate IR
+//
+// This allows for composition between specialized remark emitters throughout
+// the compilation pipeline, that end up in the same file, using the same format
+// and serialization techniques.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_REMARKS_REMARKSTREAMER_H
+#define LLVM_REMARKS_REMARKSTREAMER_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/Remarks/RemarkSerializer.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/Regex.h"
+#include "llvm/Support/raw_ostream.h"
+#include <memory>
+
+namespace llvm {
+namespace remarks {
+class RemarkStreamer final {
+  /// The regex used to filter remarks based on the passes that emit them.
+  Optional<Regex> PassFilter;
+  /// The object used to serialize the remarks to a specific format.
+  std::unique_ptr<remarks::RemarkSerializer> RemarkSerializer;
+  /// The filename that the remark diagnostics are emitted to.
+  const Optional<std::string> Filename;
+
+public:
+  RemarkStreamer(std::unique_ptr<remarks::RemarkSerializer> RemarkSerializer,
+                 Optional<StringRef> Filename = None);
+
+  /// Return the filename that the remark diagnostics are emitted to.
+  Optional<StringRef> getFilename() const {
+    return Filename ? Optional<StringRef>(*Filename) : None;
+  }
+  /// Return stream that the remark diagnostics are emitted to.
+  raw_ostream &getStream() { return RemarkSerializer->OS; }
+  /// Return the serializer used for this stream.
+  remarks::RemarkSerializer &getSerializer() { return *RemarkSerializer; }
+  /// Set a pass filter based on a regex \p Filter.
+  /// Returns an error if the regex is invalid.
+  Error setFilter(StringRef Filter);
+  /// Check wether the string matches the filter.
+  bool matchesFilter(StringRef Str);
+  /// Check if the remarks also need to have associated metadata in a section.
+  bool needsSection() const;
+};
+} // end namespace remarks
+} // end namespace llvm
+
+#endif // LLVM_REMARKS_REMARKSTREAMER_H
diff --git a/linux-x64/clang/include/llvm/Remarks/RemarkStringTable.h b/linux-x64/clang/include/llvm/Remarks/RemarkStringTable.h
index f9b4fdb..60cf601 100644
--- a/linux-x64/clang/include/llvm/Remarks/RemarkStringTable.h
+++ b/linux-x64/clang/include/llvm/Remarks/RemarkStringTable.h
@@ -17,31 +17,46 @@
 #define LLVM_REMARKS_REMARK_STRING_TABLE_H
 
 #include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Allocator.h"
 #include <vector>
 
 namespace llvm {
 
 class raw_ostream;
+class StringRef;
 
 namespace remarks {
 
+struct ParsedStringTable;
+struct Remark;
+
 /// 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/linux-x64/clang/include/llvm/Remarks/YAMLRemarkSerializer.h b/linux-x64/clang/include/llvm/Remarks/YAMLRemarkSerializer.h
new file mode 100644
index 0000000..f1213be
--- /dev/null
+++ b/linux-x64/clang/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 */