//===- SampleProfWriter.cpp - Write LLVM sample profile data --------------===//
//
// 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 implements the class that writes LLVM sample profiles. It
// supports two file formats: text and binary. The textual representation
// is useful for debugging and testing purposes. The binary representation
// is more compact, resulting in smaller file sizes. However, they can
// both be used interchangeably.
//
// See lib/ProfileData/SampleProfReader.cpp for documentation on each of the
// supported formats.
//
//===----------------------------------------------------------------------===//

#include "llvm/ProfileData/SampleProfWriter.h"
#include "llvm/ADT/Eytzinger.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ProfileData/ProfileCommon.h"
#include "llvm/ProfileData/SampleProf.h"
#include "llvm/Support/Compression.h"
#include "llvm/Support/EndianStream.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/MD5.h"
#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Support/raw_ostream.h"
#include <array>
#include <cmath>
#include <cstdint>
#include <memory>
#include <system_error>
#include <utility>
#include <vector>

#define DEBUG_TYPE "llvm-profdata"

using namespace llvm;
using namespace sampleprof;

// To begin with, make this option off by default.
static cl::opt<bool> ExtBinaryWriteVTableTypeProf(
    "extbinary-write-vtable-type-prof", cl::init(false), cl::Hidden,
    cl::desc("Write vtable type profile in ext-binary sample profile writer"));

static cl::opt<uint64_t> RequestedVersion(
    "sample-profile-format-version", cl::init(DefaultVersion), cl::Hidden,
    cl::desc("Format version to write for extensible binary profiles"));

static cl::opt<bool>
    ExtBinaryCompositeProf("extbinary-composite-prof", cl::init(false),
                           cl::Hidden,
                           cl::desc("Use the composite profile format"));

namespace llvm {
namespace support {
namespace endian {
namespace {

// Adapter class to llvm::support::endian::Writer for pwrite().
struct SeekableWriter {
  raw_pwrite_stream &OS;
  endianness Endian;
  SeekableWriter(raw_pwrite_stream &OS, endianness Endian)
      : OS(OS), Endian(Endian) {}

  template <typename ValueType> void pwrite(ValueType Val, size_t Offset) {
    std::string StringBuf;
    raw_string_ostream SStream(StringBuf);
    Writer(SStream, Endian).write(Val);
    OS.pwrite(StringBuf.data(), StringBuf.size(), Offset);
  }
};

} // namespace
} // namespace endian
} // namespace support
} // namespace llvm

DefaultFunctionPruningStrategy::DefaultFunctionPruningStrategy(
    SampleProfileMap &ProfileMap, size_t OutputSizeLimit)
    : FunctionPruningStrategy(ProfileMap, OutputSizeLimit) {
  sortFuncProfiles(ProfileMap, SortedFunctions);
}

void DefaultFunctionPruningStrategy::Erase(size_t CurrentOutputSize) {
  double D = (double)OutputSizeLimit / CurrentOutputSize;
  size_t NewSize = (size_t)round(ProfileMap.size() * D * D);
  size_t NumToRemove = ProfileMap.size() - NewSize;
  if (NumToRemove < 1)
    NumToRemove = 1;

  assert(NumToRemove <= SortedFunctions.size());
  for (const NameFunctionSamples &E :
       llvm::drop_begin(SortedFunctions, SortedFunctions.size() - NumToRemove))
    ProfileMap.erase(E.first);
  SortedFunctions.resize(SortedFunctions.size() - NumToRemove);
}

std::error_code SampleProfileWriter::writeWithSizeLimitInternal(
    SampleProfileMap &ProfileMap, size_t OutputSizeLimit,
    FunctionPruningStrategy *Strategy) {
  if (OutputSizeLimit == 0)
    return write(ProfileMap);

  size_t OriginalFunctionCount = ProfileMap.size();

  std::unique_ptr<raw_ostream> OriginalOutputStream;
  OutputStream.swap(OriginalOutputStream);

  size_t IterationCount = 0;
  size_t TotalSize;

  SmallVector<char> StringBuffer;
  do {
    StringBuffer.clear();
    OutputStream.reset(new raw_svector_ostream(StringBuffer));
    if (std::error_code EC = write(ProfileMap))
      return EC;

    TotalSize = StringBuffer.size();
    // On Windows every "\n" is actually written as "\r\n" to disk but not to
    // memory buffer, this difference should be added when considering the total
    // output size.
#ifdef _WIN32
    if (Format == SPF_Text)
      TotalSize += LineCount;
#endif
    if (TotalSize <= OutputSizeLimit)
      break;

    Strategy->Erase(TotalSize);
    IterationCount++;
  } while (ProfileMap.size() != 0);

  if (ProfileMap.size() == 0)
    return sampleprof_error::too_large;

  OutputStream.swap(OriginalOutputStream);
  OutputStream->write(StringBuffer.data(), StringBuffer.size());
  LLVM_DEBUG(dbgs() << "Profile originally has " << OriginalFunctionCount
                    << " functions, reduced to " << ProfileMap.size() << " in "
                    << IterationCount << " iterations\n");
  // Silence warning on Release build.
  (void)OriginalFunctionCount;
  (void)IterationCount;
  return sampleprof_error::success;
}

std::error_code
SampleProfileWriter::writeFuncProfiles(const SampleProfileMap &ProfileMap) {
  std::vector<NameFunctionSamples> V;
  sortFuncProfiles(ProfileMap, V);
  for (const auto &I : V) {
    if (std::error_code EC = writeSample(*I.second))
      return EC;
  }
  return sampleprof_error::success;
}

std::error_code SampleProfileWriter::write(const SampleProfileMap &ProfileMap) {
  if (std::error_code EC = writeHeader(ProfileMap))
    return EC;

  if (std::error_code EC = writeFuncProfiles(ProfileMap))
    return EC;

  return sampleprof_error::success;
}

/// Return the current position and prepare to use it as the start
/// position of a section given the section type \p Type and its position
/// \p LayoutIdx in SectionHdrLayout.
uint64_t
SampleProfileWriterExtBinaryBase::markSectionStart(SecType Type,
                                                   uint32_t LayoutIdx) {
  uint64_t SectionStart = OutputStream->tell();
  assert(LayoutIdx < SectionHdrLayout.size() && "LayoutIdx out of range");
  const auto &Entry = SectionHdrLayout[LayoutIdx];
  assert(Entry.Type == Type && "Unexpected section type");
  // Use LocalBuf as a temporary output for writing data.
  if (hasSecFlag(Entry, SecCommonFlags::SecFlagCompress))
    LocalBufStream.swap(OutputStream);
  return SectionStart;
}

std::error_code SampleProfileWriterExtBinaryBase::compressAndOutput() {
  if (!llvm::compression::zlib::isAvailable())
    return sampleprof_error::zlib_unavailable;
  std::string &UncompressedStrings =
      static_cast<raw_string_ostream *>(LocalBufStream.get())->str();
  if (UncompressedStrings.empty())
    return sampleprof_error::success;
  auto &OS = *OutputStream;
  SmallVector<uint8_t, 128> CompressedStrings;
  compression::zlib::compress(arrayRefFromStringRef(UncompressedStrings),
                              CompressedStrings,
                              compression::zlib::BestSizeCompression);
  encodeULEB128(UncompressedStrings.size(), OS);
  encodeULEB128(CompressedStrings.size(), OS);
  OS << toStringRef(CompressedStrings);
  UncompressedStrings.clear();
  return sampleprof_error::success;
}

/// Add a new section into section header table given the section type
/// \p Type, its position \p LayoutIdx in SectionHdrLayout and the
/// location \p SectionStart where the section should be written to.
std::error_code SampleProfileWriterExtBinaryBase::addNewSection(
    SecType Type, uint32_t LayoutIdx, uint64_t SectionStart) {
  assert(LayoutIdx < SectionHdrLayout.size() && "LayoutIdx out of range");
  const auto &Entry = SectionHdrLayout[LayoutIdx];
  assert(Entry.Type == Type && "Unexpected section type");
  if (hasSecFlag(Entry, SecCommonFlags::SecFlagCompress)) {
    LocalBufStream.swap(OutputStream);
    if (std::error_code EC = compressAndOutput())
      return EC;
  }
  SecHdrTable.push_back({Type, Entry.Flags, SectionStart - FileStart,
                         OutputStream->tell() - SectionStart, LayoutIdx});
  return sampleprof_error::success;
}

std::error_code
SampleProfileWriterExtBinaryBase::write(const SampleProfileMap &ProfileMap) {
  // When calling write on a different profile map, existing states should be
  // cleared.
  NameTable.clear();
  CSNameTable.clear();
  SecHdrTable.clear();

  if (std::error_code EC = writeHeader(ProfileMap))
    return EC;

  std::string LocalBuf;
  LocalBufStream = std::make_unique<raw_string_ostream>(LocalBuf);
  if (std::error_code EC = writeSections(ProfileMap))
    return EC;

  if (std::error_code EC = writeSecHdrTable())
    return EC;

  return sampleprof_error::success;
}

std::error_code SampleProfileWriterExtBinaryBase::writeContextIdx(
    const SampleContext &Context) {
  if (Context.hasContext())
    return writeCSNameIdx(Context);
  else
    return SampleProfileWriterBinary::writeNameIdx(Context.getFunction());
}

std::error_code
SampleProfileWriterExtBinaryBase::writeCSNameIdx(const SampleContext &Context) {
  const auto &Ret = CSNameTable.find(Context);
  if (Ret == CSNameTable.end())
    return sampleprof_error::truncated_name_table;
  encodeULEB128(Ret->second, *OutputStream);
  return sampleprof_error::success;
}

std::error_code
SampleProfileWriterExtBinaryBase::writeSample(const FunctionSamples &S) {
  uint64_t Offset = OutputStream->tell();
  auto &Context = S.getContext();
  FuncOffsetTable[Context] = Offset - SecLBRProfileStart;
  if (!WriteCompositeProf)
    encodeULEB128(S.getHeadSamples(), *OutputStream);
  return writeBody(S, /*IsNested=*/false);
}

std::error_code
SampleProfileWriterExtBinaryBase::writeFuncOffsetTable(SecType Type,
                                                       bool IsNested) {
  if (UseMD5IndexedTables) {
    // Eytzinger layout requires MD5 representation and does not support
    // multi-context Context-Sensitive profiles.
    if (!UseMD5 || FunctionSamples::ProfileIsCS)
      return sampleprof_error::unsupported_writing_format;
    return writeEytzingerFuncOffsetTable(Type, IsNested);
  }
  return writeLegacyFuncOffsetTable(Type);
}

std::error_code
SampleProfileWriterExtBinaryBase::writeEytzingerFuncOffsetTable(SecType Type,
                                                                bool IsNested) {
  assert((NumNested + NumFlat > 0 || FuncOffsetTable.empty()) &&
         "SecNameTable must be written before SecFuncOffsetTable to establish "
         "Eytzinger indices!");

  size_t SpanSize = IsNested ? NumNested : NumFlat;
  size_t BaseIdx = IsNested ? 0 : NumNested;

  std::vector<support::ulittle32_t> FuncOffsets(
      SpanSize, support::ulittle32_t(UINT32_MAX));

  // Populate the function offset array parallel to the Eytzinger span.
  for (const auto &[Context, RelativeOffset] : FuncOffsetTable) {
    if (RelativeOffset >= UINT32_MAX)
      return sampleprof_error::too_large;

    FunctionId FId = Context.getFunction();
    auto It = NameTable.find(FId);
    if (It == NameTable.end())
      continue;

    size_t GlobalIdx = It->second;
    if (GlobalIdx < BaseIdx || (GlobalIdx - BaseIdx) >= SpanSize)
      continue;

    size_t LocalIdx = GlobalIdx - BaseIdx;
    assert(
        FuncOffsets[LocalIdx] == UINT32_MAX &&
        "Function offset slot already populated; duplicate GUID or collision!");
    FuncOffsets[LocalIdx] = static_cast<uint32_t>(RelativeOffset);
  }

  assert(!llvm::is_contained(FuncOffsets, support::ulittle32_t(UINT32_MAX)) &&
         "Unpopulated slot in Eytzinger function offset array!");

  OutputStream->write(reinterpret_cast<const char *>(FuncOffsets.data()),
                      SpanSize * sizeof(support::ulittle32_t));
  // Type is SecFuncOffsetTable or SecCompositeFuncOffsetTable.
  addSectionFlag(Type, SecFuncOffsetFlags::SecFlagEytzinger);
  FuncOffsetTable.clear();
  return sampleprof_error::success;
}

std::error_code
SampleProfileWriterExtBinaryBase::writeLegacyFuncOffsetTable(SecType Type) {
  auto &OS = *OutputStream;

  // Write out the table size.
  encodeULEB128(FuncOffsetTable.size(), OS);

  // Write out FuncOffsetTable.
  auto WriteItem = [&](const SampleContext &Context, uint64_t Offset) {
    if (std::error_code EC = writeContextIdx(Context))
      return EC;
    encodeULEB128(Offset, OS);
    return (std::error_code)sampleprof_error::success;
  };

  if (FunctionSamples::ProfileIsCS) {
    // Sort the contexts before writing them out. This is to help fast load all
    // context profiles for a function as well as their callee contexts which
    // can help profile-guided importing for ThinLTO.
    std::map<SampleContext, uint64_t> OrderedFuncOffsetTable(
        FuncOffsetTable.begin(), FuncOffsetTable.end());
    for (const auto &Entry : OrderedFuncOffsetTable) {
      if (std::error_code EC = WriteItem(Entry.first, Entry.second))
        return EC;
    }
    addSectionFlag(Type, SecFuncOffsetFlags::SecFlagOrdered);
  } else {
    for (const auto &Entry : FuncOffsetTable) {
      if (std::error_code EC = WriteItem(Entry.first, Entry.second))
        return EC;
    }
  }

  FuncOffsetTable.clear();
  return sampleprof_error::success;
}

std::error_code SampleProfileWriterExtBinaryBase::writeFuncMetadata(
    const FunctionSamples &FunctionProfile) {
  auto &OS = *OutputStream;
  if (std::error_code EC = writeContextIdx(FunctionProfile.getContext()))
    return EC;

  if (FunctionSamples::ProfileIsProbeBased)
    encodeULEB128(FunctionProfile.getFunctionHash(), OS);
  if (FunctionSamples::ProfileIsCS || FunctionSamples::ProfileIsPreInlined) {
    encodeULEB128(FunctionProfile.getContext().getAllAttributes(), OS);
  }

  if (!FunctionSamples::ProfileIsCS) {
    // Recursively emit attributes for all callee samples.
    uint64_t NumCallsites = 0;
    for (const auto &J : FunctionProfile.getCallsiteSamples())
      NumCallsites += J.second.size();
    encodeULEB128(NumCallsites, OS);
    for (const auto &J : FunctionProfile.getCallsiteSamples()) {
      for (const auto &FS : J.second) {
        LineLocation Loc = J.first;
        encodeULEB128(Loc.LineOffset, OS);
        encodeULEB128(Loc.Discriminator, OS);
        if (std::error_code EC = writeFuncMetadata(FS.second))
          return EC;
      }
    }
  }

  return sampleprof_error::success;
}

std::error_code SampleProfileWriterExtBinaryBase::writeFuncMetadata(
    const SampleProfileMap &Profiles) {
  if (!FunctionSamples::ProfileIsProbeBased && !FunctionSamples::ProfileIsCS &&
      !FunctionSamples::ProfileIsPreInlined)
    return sampleprof_error::success;
  for (const auto &Entry : Profiles) {
    if (std::error_code EC = writeFuncMetadata(Entry.second))
      return EC;
  }
  return sampleprof_error::success;
}

template <class KeyT, class ValT>
static SmallVector<std::pair<KeyT, ValT> *, 0>
stabilizeTable(MapVector<KeyT, ValT> &Table) {
  SmallVector<std::pair<KeyT, ValT> *, 0> Entries(
      llvm::make_pointer_range(Table));

  llvm::sort(Entries,
             [](const auto *L, const auto *R) { return L->first < R->first; });

  for (const auto &[I, Entry] : llvm::enumerate(Entries))
    Entry->second = I;

  return Entries;
}

std::error_code SampleProfileWriterExtBinaryBase::writeNameTable() {
  if (!UseMD5)
    return SampleProfileWriterBinary::writeNameTable();

  auto &OS = *OutputStream;

  // Write out the MD5 name table. We wrote unencoded MD5 so reader can
  // retrieve the name using the name index without having to read the
  // whole name table.
  encodeULEB128(NameTable.size(), OS);
  support::endian::Writer Writer(OS, llvm::endianness::little);
  for (const auto *Entry : stabilizeTable(NameTable))
    Writer.write(Entry->first.getHashCode());
  return sampleprof_error::success;
}

std::error_code SampleProfileWriterExtBinaryBase::writeNameTableSection(
    const SampleProfileMap &ProfileMap) {
  for (const auto &I : ProfileMap) {
    addContext(I.second.getContext());
    addNames(I.second);
  }

  // If NameTable contains ".__uniq." suffix, set SecFlagUniqSuffix flag
  // so compiler won't strip the suffix during profile matching after
  // seeing the flag in the profile.
  // Original names are unavailable if using MD5, so this option has no use.
  if (!UseMD5) {
    for (const auto &I : NameTable) {
      if (I.first.stringRef().contains(FunctionSamples::UniqSuffix)) {
        addSectionFlag(SecNameTable, SecNameTableFlags::SecFlagUniqSuffix);
        break;
      }
    }
  }

  if (UseMD5 && UseMD5IndexedTables) {
    // Eytzinger name tables do not support CSSPGO profiles
    // (FunctionSamples::ProfileIsCS).
    if (FunctionSamples::ProfileIsCS)
      return sampleprof_error::unsupported_writing_format;
    if (auto EC = writeEytzingerNameTableSection(ProfileMap))
      return EC;
    return sampleprof_error::success;
  }

  if (auto EC = writeNameTable())
    return EC;
  return sampleprof_error::success;
}

namespace {

// Helper class to construct and write the SecNameTable section in Eytzinger
// layout for ExtBinary MD5 profiles.
//
// The on-disk layout of the Eytzinger name table section consists of symbol
// counts followed by three contiguous Eytzinger hash arrays:
// - ULEB128 count of Nested top-level profile symbol keys
// - ULEB128 count of Flat top-level profile symbol keys
// - ULEB128 count of Inlinee and auxiliary profile symbol keys
// - Array of 64-bit little-endian MD5 hash keys for Nested profiles in
//   Eytzinger order
// - Array of 64-bit little-endian MD5 hash keys for Flat profiles in Eytzinger
//   order
// - Array of 64-bit little-endian MD5 hash keys for Inlinees in Eytzinger order
class EytzingerNameTable {
  using TableT = llvm::EytzingerTable<support::ulittle64_t>;
  std::array<TableT, static_cast<size_t>(EytzingerSpan::NumSpans)> Spans;

public:
  EytzingerNameTable(std::vector<support::ulittle64_t> NestedKeys,
                     std::vector<support::ulittle64_t> FlatKeys,
                     std::vector<support::ulittle64_t> InlineeKeys)
      : Spans{TableT::create(std::move(NestedKeys)),
              TableT::create(std::move(FlatKeys)),
              TableT::create(std::move(InlineeKeys))} {}

  // Find the global index of GUID across the three Eytzinger table spans.
  uint64_t findGlobalIdx(uint64_t GUID) const {
    uint64_t BaseIdx = 0;
    for (const auto &Table : Spans) {
      if (std::optional<size_t> LocalIdx = Table.findIndex(GUID))
        return BaseIdx + *LocalIdx;
      BaseIdx += Table.size();
    }
    llvm_unreachable("Symbol in NameTable missing from Eytzinger spans");
  }

  void write(raw_ostream &OS) const {
    for (const auto &Table : Spans)
      encodeULEB128(uint64_t(Table.size()), OS);
    for (const auto &Table : Spans)
      OS.write(reinterpret_cast<const char *>(Table.data()),
               Table.size() * sizeof(support::ulittle64_t));
  }

  size_t size(EytzingerSpan S) const {
    return Spans[static_cast<size_t>(S)].size();
  }
};

} // end anonymous namespace

std::error_code
SampleProfileWriterExtBinaryBase::writeEytzingerNameTableSection(
    const SampleProfileMap &ProfileMap) {
  DenseSet<uint64_t> TopLevelGUIDs;
  std::vector<support::ulittle64_t> NestedKeys, FlatKeys, InlineeKeys;

  // Collect top-level Nested and Flat keys directly from ProfileMap.
  for (const auto &I : ProfileMap) {
    const SampleContext &Ctx = I.second.getContext();
    uint64_t GUID = Ctx.getFunction().getHashCode();
    if (TopLevelGUIDs.insert(GUID).second) {
      // In single-table default layouts, unify all top-level symbols in the
      // Nested partition so they match the single unflagged function offset
      // table.
      if (SecLayout != CtxSplitLayout || I.second.hasCallsiteSamples())
        NestedKeys.emplace_back(GUID);
      else
        FlatKeys.emplace_back(GUID);
    }
  }

  // Collect remaining non-top-level symbols (inlinees, targets, vtables) from
  // NameTable.
  for (const auto &Entry : NameTable) {
    uint64_t GUID = Entry.first.getHashCode();
    if (!TopLevelGUIDs.contains(GUID))
      InlineeKeys.emplace_back(GUID);
  }

  EytzingerNameTable Tables(std::move(NestedKeys), std::move(FlatKeys),
                            std::move(InlineeKeys));

  // Assign each symbol its corresponding index in the Eytzinger layout.
  for (auto &[FId, Idx] : NameTable)
    Idx = Tables.findGlobalIdx(FId.getHashCode());

  Tables.write(*OutputStream);
  NumNested = Tables.size(EytzingerSpan::Nested);
  NumFlat = Tables.size(EytzingerSpan::Flat);

  return sampleprof_error::success;
}

std::error_code SampleProfileWriterExtBinaryBase::writeCSNameTableSection() {
  auto &OS = *OutputStream;
  encodeULEB128(CSNameTable.size(), OS);
  support::endian::Writer Writer(OS, llvm::endianness::little);
  for (const auto *Entry : stabilizeTable(CSNameTable)) {
    auto Frames = Entry->first.getContextFrames();
    encodeULEB128(Frames.size(), OS);
    for (auto &Callsite : Frames) {
      if (std::error_code EC = writeNameIdx(Callsite.Func))
        return EC;
      encodeULEB128(Callsite.Location.LineOffset, OS);
      encodeULEB128(Callsite.Location.Discriminator, OS);
    }
  }

  return sampleprof_error::success;
}

std::error_code
SampleProfileWriterExtBinaryBase::writeProfileSymbolListSection() {
  if (UseMD5ProfSymList)
    return writeMD5ProfileSymbolListSection();
  return writeStringBasedProfileSymbolListSection();
}

std::error_code
SampleProfileWriterExtBinaryBase::writeStringBasedProfileSymbolListSection() {
  assert((!ProfSymList || !ProfSymList->isMD5()) &&
         "Writing string-based ProfileSymbolListSection from MD5 table "
         "not yet implemented");
  if (ProfSymList && ProfSymList->size() > 0)
    if (std::error_code EC = ProfSymList->write(*OutputStream))
      return EC;

  return sampleprof_error::success;
}

std::error_code
SampleProfileWriterExtBinaryBase::writeMD5ProfileSymbolListSection() {
  if (!ProfSymList || ProfSymList->size() == 0)
    return sampleprof_error::success;

  auto &OS = *OutputStream;
  std::vector<uint64_t> Keys = ProfSymList->collectGUIDs();

  auto Table =
      llvm::EytzingerTable<support::ulittle64_t>::create(std::move(Keys));

  OS.write(reinterpret_cast<const char *>(Table.data()),
           Table.size() * sizeof(support::ulittle64_t));
  return sampleprof_error::success;
}

unsigned SampleProfileWriterExtBinaryBase::findUnwrittenEntry(SecType Type) {
  auto WrittenIndices =
      llvm::map_range(SecHdrTable, &SecHdrTableEntry::LayoutIndex);
  for (auto [I, Entry] : llvm::enumerate(SectionHdrLayout))
    if (Entry.Type == Type && !llvm::is_contained(WrittenIndices, I))
      return I;
  llvm_unreachable("Matching section not found in SectionHdrLayout");
}

std::error_code SampleProfileWriterExtBinaryBase::writeOneSection(
    SecType Type, const SampleProfileMap &ProfileMap) {
  unsigned LayoutIdx = findUnwrittenEntry(Type);
  SecHdrTableEntry &Entry = SectionHdrLayout[LayoutIdx];

  // The setting of SecFlagCompress should happen before markSectionStart.
  if (Type == SecFuncMetadata && FunctionSamples::ProfileIsProbeBased)
    addSectionFlag(SecFuncMetadata, SecFuncMetadataFlags::SecFlagIsProbeBased);
  if (Type == SecFuncMetadata &&
      (FunctionSamples::ProfileIsCS || FunctionSamples::ProfileIsPreInlined))
    addSectionFlag(SecFuncMetadata, SecFuncMetadataFlags::SecFlagHasAttribute);
  if (Type == SecProfSummary && FunctionSamples::ProfileIsCS)
    addSectionFlag(SecProfSummary, SecProfSummaryFlags::SecFlagFullContext);
  if (Type == SecProfSummary && FunctionSamples::ProfileIsPreInlined)
    addSectionFlag(SecProfSummary, SecProfSummaryFlags::SecFlagIsPreInlined);
  if (Type == SecProfSummary && FunctionSamples::ProfileIsFS)
    addSectionFlag(SecProfSummary, SecProfSummaryFlags::SecFlagFSDiscriminator);
  if (Type == SecProfSummary && ExtBinaryWriteVTableTypeProf)
    addSectionFlag(SecProfSummary,
                   SecProfSummaryFlags::SecFlagHasVTableTypeProf);
  if (Type == SecProfileSymbolList && UseMD5ProfSymList)
    addSectionFlag(SecProfileSymbolList, SecProfileSymbolListFlags::SecFlagMD5);
  if (Type == SecNameTable && UseMD5IndexedTables && UseMD5)
    addSectionFlag(SecNameTable, SecNameTableFlags::SecFlagEytzinger);

  uint64_t SectionStart = markSectionStart(Type, LayoutIdx);
  switch (Type) {
  case SecProfSummary:
    computeSummary(ProfileMap);
    if (auto EC = writeSummary())
      return EC;
    break;
  case SecNameTable:
    if (auto EC = writeNameTableSection(ProfileMap))
      return EC;
    break;
  case SecCSNameTable:
    if (auto EC = writeCSNameTableSection())
      return EC;
    break;
  case SecLBRProfile:
  case SecCompositeProfile:
    SecLBRProfileStart = OutputStream->tell();
    if (std::error_code EC = writeFuncProfiles(ProfileMap))
      return EC;
    break;
  case SecFuncOffsetTable:
  case SecCompositeFuncOffsetTable: {
    bool IsFlat = hasSecFlag(Entry, SecCommonFlags::SecFlagFlat);
    // An unflagged function offset table inherently indexes the primary
    // Nested symbol span.
    bool IsNested = !IsFlat;
    if (auto EC = writeFuncOffsetTable(Type, IsNested))
      return EC;
    break;
  }
  case SecFuncMetadata:
    if (std::error_code EC = writeFuncMetadata(ProfileMap))
      return EC;
    break;
  case SecProfileSymbolList:
    if (auto EC = writeProfileSymbolListSection())
      return EC;
    break;
  default:
    if (auto EC = writeCustomSection(Type))
      return EC;
    break;
  }
  if (std::error_code EC = addNewSection(Type, LayoutIdx, SectionStart))
    return EC;
  return sampleprof_error::success;
}

SampleProfileWriterExtBinary::SampleProfileWriterExtBinary(
    std::unique_ptr<raw_ostream> &OS)
    : SampleProfileWriterExtBinaryBase(OS) {
  WriteVTableProf = ExtBinaryWriteVTableTypeProf;
}

std::error_code SampleProfileWriterExtBinary::writeDefaultLayout(
    const SampleProfileMap &ProfileMap) {
  // ProfSection / FuncOffsetSection are SecLBR* or SecComposite* after
  // configureCompositeProfile.
  const SecType Sections[] = {
      SecProfSummary,       SecNameTable,      SecCSNameTable,  ProfSection,
      SecProfileSymbolList, FuncOffsetSection, SecFuncMetadata,
  };
  for (SecType Type : Sections)
    if (std::error_code EC = writeOneSection(Type, ProfileMap))
      return EC;
  return sampleprof_error::success;
}

static void splitProfileMapToTwo(const SampleProfileMap &ProfileMap,
                                 SampleProfileMap &NestedProfileMap,
                                 SampleProfileMap &FlatProfileMap) {
  for (const auto &I : ProfileMap) {
    if (I.second.hasCallsiteSamples())
      NestedProfileMap.insert({I.first, I.second});
    else
      FlatProfileMap.insert({I.first, I.second});
  }
}

std::error_code SampleProfileWriterExtBinary::writeCtxSplitLayout(
    const SampleProfileMap &ProfileMap) {
  SampleProfileMap NestedProfileMap, FlatProfileMap;
  splitProfileMapToTwo(ProfileMap, NestedProfileMap, FlatProfileMap);

  // Flat SecFlag is pre-set in ExtBinaryHdrLayoutTable; findUnwrittenEntry
  // picks the matching unwritten ProfSection / FuncOffsetSection slot.
  const std::pair<SecType, const SampleProfileMap &> Sections[] = {
      {SecProfSummary, ProfileMap},       {SecNameTable, ProfileMap},
      {ProfSection, NestedProfileMap},    {FuncOffsetSection, NestedProfileMap},
      {ProfSection, FlatProfileMap},      {FuncOffsetSection, FlatProfileMap},
      {SecProfileSymbolList, ProfileMap}, {SecFuncMetadata, ProfileMap},
  };
  for (const auto &[Type, Map] : Sections)
    if (std::error_code EC = writeOneSection(Type, Map))
      return EC;

  return sampleprof_error::success;
}

void SampleProfileWriterExtBinary::configureCompositeProfile() {
  ProfSection = WriteCompositeProf ? SecCompositeProfile : SecLBRProfile;
  FuncOffsetSection =
      WriteCompositeProf ? SecCompositeFuncOffsetTable : SecFuncOffsetTable;

  // Change the section types in place to avoid duplicating the whole layout and
  // its handling. Rewrite both legacy and composite entries so repeated writes
  // can switch formats without losing configured flags.
  for (auto &Entry : SectionHdrLayout) {
    if (Entry.Type == SecFuncOffsetTable ||
        Entry.Type == SecCompositeFuncOffsetTable)
      Entry.Type = FuncOffsetSection;
    else if (Entry.Type == SecLBRProfile || Entry.Type == SecCompositeProfile)
      Entry.Type = ProfSection;
  }
}

std::error_code SampleProfileWriterExtBinary::writeSections(
    const SampleProfileMap &ProfileMap) {
  // Rewrite the final configured layout immediately before its section types
  // are consumed. Earlier layout configuration may replace SectionHdrLayout.
  configureCompositeProfile();

  std::error_code EC;
  if (SecLayout == DefaultLayout)
    EC = writeDefaultLayout(ProfileMap);
  else if (SecLayout == CtxSplitLayout)
    EC = writeCtxSplitLayout(ProfileMap);
  else
    llvm_unreachable("Unsupported layout");
  return EC;
}

/// Write samples to a text file.
///
/// Note: it may be tempting to implement this in terms of
/// FunctionSamples::print().  Please don't.  The dump functionality is intended
/// for debugging and has no specified form.
///
/// The format used here is more structured and deliberate because
/// it needs to be parsed by the SampleProfileReaderText class.
std::error_code SampleProfileWriterText::writeSample(const FunctionSamples &S) {
  auto &OS = *OutputStream;
  if (FunctionSamples::ProfileIsCS)
    OS << "[" << S.getContext().toString() << "]:" << S.getTotalSamples();
  else
    OS << S.getFunction() << ":" << S.getTotalSamples();

  if (Indent == 0)
    OS << ":" << S.getHeadSamples();
  OS << "\n";
  LineCount++;

  for (const auto &[Loc, Sample] : S.getBodySamples()) {
    OS.indent(Indent + 1);
    Loc.print(OS);
    OS << ": " << Sample.getSamples();

    for (const auto &J : Sample.getSortedCallTargets())
      OS << " " << J.first << ":" << J.second;
    OS << "\n";
    LineCount++;

    if (const TypeCountMap *Map = S.findCallsiteTypeSamplesAt(Loc);
        Map && !Map->empty()) {
      OS.indent(Indent + 1);
      Loc.print(OS);
      OS << ": ";
      OS << kVTableProfPrefix;
      for (const auto &[TypeName, Count] : *Map) {
        OS << TypeName << ":" << Count << " ";
      }
      OS << "\n";
      LineCount++;
    }
  }

  Indent += 1;
  for (const auto &[Loc, FunctionSamplesMap] : S.getCallsiteSamples()) {
    for (const FunctionSamples &CalleeSamples :
         make_second_range(FunctionSamplesMap)) {
      OS.indent(Indent);
      Loc.print(OS);
      OS << ": ";
      if (std::error_code EC = writeSample(CalleeSamples))
        return EC;
    }

    if (const TypeCountMap *Map = S.findCallsiteTypeSamplesAt(Loc);
        Map && !Map->empty()) {
      OS.indent(Indent);
      Loc.print(OS);
      OS << ": ";
      OS << kVTableProfPrefix;
      for (const auto &[TypeId, Count] : *Map) {
        OS << TypeId << ":" << Count << " ";
      }
      OS << "\n";
      LineCount++;
    }
  }

  Indent -= 1;

  if (FunctionSamples::ProfileIsProbeBased) {
    OS.indent(Indent + 1);
    OS << "!CFGChecksum: " << S.getFunctionHash() << "\n";
    LineCount++;
  }

  if (S.getContext().getAllAttributes()) {
    OS.indent(Indent + 1);
    OS << "!Attributes: " << S.getContext().getAllAttributes() << "\n";
    LineCount++;
  }

  if (Indent == 0 && MarkFlatProfiles && S.getCallsiteSamples().size() == 0)
    OS << " !Flat\n";

  return sampleprof_error::success;
}

std::error_code
SampleProfileWriterBinary::writeContextIdx(const SampleContext &Context) {
  assert(!Context.hasContext() && "cs profile is not supported");
  return writeNameIdx(Context.getFunction());
}

std::error_code SampleProfileWriterBinary::writeNameIdx(FunctionId FName) {
  auto &NTable = getNameTable();
  const auto &Ret = NTable.find(FName);
  if (Ret == NTable.end())
    return sampleprof_error::truncated_name_table;
  encodeULEB128(Ret->second, *OutputStream);
  return sampleprof_error::success;
}

void SampleProfileWriterBinary::addName(FunctionId FName) {
  auto &NTable = getNameTable();
  NTable.insert(std::make_pair(FName, 0));
}

void SampleProfileWriterBinary::addContext(const SampleContext &Context) {
  addName(Context.getFunction());
}

void SampleProfileWriterBinary::addNames(const FunctionSamples &S) {
  // Add all the names in indirect call targets.
  for (const auto &I : S.getBodySamples()) {
    const SampleRecord &Sample = I.second;
    for (const auto &J : Sample.getCallTargets())
      addName(J.first);
  }

  // Recursively add all the names for inlined callsites.
  for (const auto &J : S.getCallsiteSamples())
    for (const auto &FS : J.second) {
      const FunctionSamples &CalleeSamples = FS.second;
      addName(CalleeSamples.getFunction());
      addNames(CalleeSamples);
    }

  if (!WriteVTableProf)
    return;
  // Add all the vtable names to NameTable.
  for (const auto &VTableAccessCountMap :
       llvm::make_second_range(S.getCallsiteTypeCounts())) {
    // Add type name to NameTable.
    for (const auto Type : llvm::make_first_range(VTableAccessCountMap)) {
      addName(Type);
    }
  }
}

void SampleProfileWriterExtBinaryBase::addContext(
    const SampleContext &Context) {
  if (Context.hasContext()) {
    for (auto &Callsite : Context.getContextFrames())
      SampleProfileWriterBinary::addName(Callsite.Func);
    CSNameTable.insert(std::make_pair(Context, 0));
  } else {
    SampleProfileWriterBinary::addName(Context.getFunction());
  }
}

std::error_code SampleProfileWriterBinary::writeNameTable() {
  auto &OS = *OutputStream;

  // Write out the name table.
  encodeULEB128(NameTable.size(), OS);
  for (const auto *Entry : stabilizeTable(NameTable)) {
    OS << Entry->first;
    encodeULEB128(0, OS);
  }
  return sampleprof_error::success;
}

std::error_code
SampleProfileWriterBinary::writeMagicIdent(SampleProfileFormat Format) {
  auto &OS = *OutputStream;
  // Write file magic identifier.
  encodeULEB128(SPMagic(Format), OS);
  encodeULEB128(FormatVersion, OS);
  return sampleprof_error::success;
}

std::error_code
SampleProfileWriterBinary::writeHeader(const SampleProfileMap &ProfileMap) {
  // When calling write on a different profile map, existing names should be
  // cleared.
  NameTable.clear();

  writeMagicIdent(Format);

  computeSummary(ProfileMap);
  if (auto EC = writeSummary())
    return EC;

  // Generate the name table for all the functions referenced in the profile.
  for (const auto &I : ProfileMap) {
    addContext(I.second.getContext());
    addNames(I.second);
  }

  writeNameTable();
  return sampleprof_error::success;
}

void SampleProfileWriterExtBinaryBase::setToCompressAllSections() {
  for (auto &Entry : SectionHdrLayout)
    addSecFlag(Entry, SecCommonFlags::SecFlagCompress);
}

void SampleProfileWriterExtBinaryBase::setToCompressSection(SecType Type) {
  addSectionFlag(Type, SecCommonFlags::SecFlagCompress);
}

void SampleProfileWriterExtBinaryBase::allocSecHdrTable() {
  support::endian::Writer Writer(*OutputStream, llvm::endianness::little);

  Writer.write(static_cast<uint64_t>(SectionHdrLayout.size()));
  SecHdrTableOffset = OutputStream->tell();
  for (uint32_t i = 0; i < SectionHdrLayout.size(); i++) {
    Writer.write(static_cast<uint64_t>(-1));
    Writer.write(static_cast<uint64_t>(-1));
    Writer.write(static_cast<uint64_t>(-1));
    Writer.write(static_cast<uint64_t>(-1));
  }
}

std::error_code SampleProfileWriterExtBinaryBase::writeSecHdrTable() {
  assert(SecHdrTable.size() == SectionHdrLayout.size() &&
         "SecHdrTable entries doesn't match SectionHdrLayout");
  SmallVector<uint32_t, 16> IndexMap(SecHdrTable.size(), -1);
  for (uint32_t TableIdx = 0; TableIdx < SecHdrTable.size(); TableIdx++) {
    IndexMap[SecHdrTable[TableIdx].LayoutIndex] = TableIdx;
  }

  // Write the section header table in the order specified in
  // SectionHdrLayout. SectionHdrLayout specifies the sections
  // order in which profile reader expect to read, so the section
  // header table should be written in the order in SectionHdrLayout.
  // Note that the section order in SecHdrTable may be different
  // from the order in SectionHdrLayout, for example, SecFuncOffsetTable
  // needs to be computed after SecLBRProfile (the order in SecHdrTable),
  // but it needs to be read before SecLBRProfile (the order in
  // SectionHdrLayout). So we use IndexMap above to switch the order.
  support::endian::SeekableWriter Writer(
      static_cast<raw_pwrite_stream &>(*OutputStream),
      llvm::endianness::little);
  for (uint32_t LayoutIdx = 0; LayoutIdx < SectionHdrLayout.size();
       LayoutIdx++) {
    assert(IndexMap[LayoutIdx] < SecHdrTable.size() &&
           "Incorrect LayoutIdx in SecHdrTable");
    auto Entry = SecHdrTable[IndexMap[LayoutIdx]];
    Writer.pwrite(static_cast<uint64_t>(Entry.Type),
                  SecHdrTableOffset + 4 * LayoutIdx * sizeof(uint64_t));
    Writer.pwrite(static_cast<uint64_t>(Entry.Flags),
                  SecHdrTableOffset + (4 * LayoutIdx + 1) * sizeof(uint64_t));
    Writer.pwrite(static_cast<uint64_t>(Entry.Offset),
                  SecHdrTableOffset + (4 * LayoutIdx + 2) * sizeof(uint64_t));
    Writer.pwrite(static_cast<uint64_t>(Entry.Size),
                  SecHdrTableOffset + (4 * LayoutIdx + 3) * sizeof(uint64_t));
  }

  return sampleprof_error::success;
}

std::error_code SampleProfileWriterExtBinaryBase::writeHeader(
    const SampleProfileMap &ProfileMap) {
  // Reject a version that cannot describe the selected profile encoding before
  // emitting any part of the header.
  if (WriteCompositeProf && FormatVersion < CompositeProfileVersion)
    return sampleprof_error::unsupported_version;

  auto &OS = *OutputStream;
  FileStart = OS.tell();
  writeMagicIdent(Format);

  allocSecHdrTable();
  return sampleprof_error::success;
}

std::error_code SampleProfileWriterBinary::writeCallsiteVTableProf(
    const CallsiteTypeMap &CallsiteTypeMap, raw_ostream &OS) {
  assert(WriteVTableProf &&
         "writeCallsiteVTableProf should not be called if WriteVTableProf is "
         "false");

  encodeULEB128(CallsiteTypeMap.size(), OS);
  for (const auto &[Loc, TypeMap] : CallsiteTypeMap) {
    Loc.serialize(OS);
    if (std::error_code EC = serializeTypeMap(TypeMap, getNameTable(), OS))
      return EC;
  }

  return sampleprof_error::success;
}

std::error_code SampleProfileWriterBinary::writeSummary() {
  auto &OS = *OutputStream;
  encodeULEB128(Summary->getTotalCount(), OS);
  encodeULEB128(Summary->getMaxCount(), OS);
  encodeULEB128(Summary->getMaxFunctionCount(), OS);
  encodeULEB128(Summary->getNumCounts(), OS);
  encodeULEB128(Summary->getNumFunctions(), OS);
  ArrayRef<ProfileSummaryEntry> Entries = Summary->getDetailedSummary();
  encodeULEB128(Entries.size(), OS);
  for (auto Entry : Entries) {
    encodeULEB128(Entry.Cutoff, OS);
    encodeULEB128(Entry.MinCount, OS);
    encodeULEB128(Entry.NumCounts, OS);
  }
  return sampleprof_error::success;
}

std::error_code
SampleProfileWriterBinary::writeLBRProfile(const FunctionSamples &S,
                                           bool IsNested) {
  auto &OS = *OutputStream;
  if (WriteCompositeProf && !IsNested)
    encodeULEB128(S.getHeadSamples(), OS);
  encodeULEB128(S.getTotalSamples(), OS);
  encodeULEB128(S.getBodySamples().size(), OS);
  for (const auto &I : S.getBodySamples()) {
    LineLocation Loc = I.first;
    const SampleRecord &Sample = I.second;
    Loc.serialize(OS);
    if (std::error_code EC = Sample.serialize(OS, getNameTable()))
      return EC;
  }
  return sampleprof_error::success;
}

namespace {

/// A reusable stream that discards payload bytes while counting their size.
class PayloadSizeCountingStream final : public raw_ostream {
public:
  /// Avoid retaining payload data in raw_ostream's internal buffer.
  PayloadSizeCountingStream() { SetUnbuffered(); }

  /// Prepare the stream to count another payload.
  void resetPayload() {
    PayloadSize = 0;
    Overflowed = false;
  }

  /// Return whether the payload size exceeded the representable range.
  bool overflowed() const { return Overflowed; }

  /// Return the complete payload size when overflowed() is false.
  uint64_t payloadSize() const { return PayloadSize; }

private:
  /// Count incoming bytes without retaining their contents.
  void write_impl(const char *, size_t Size) override {
    if (Overflowed)
      return;

    // Fail closed if the payload cannot be represented by its uint64_t size.
    if (Size > UINT64_MAX - PayloadSize) {
      Overflowed = true;
      return;
    }
    PayloadSize += Size;
  }

  /// Report the number of bytes accepted from the current payload.
  uint64_t current_pos() const override { return PayloadSize; }

  /// Number of bytes observed during the counting pass.
  uint64_t PayloadSize = 0;
  /// Whether the counted size no longer fits in uint64_t.
  bool Overflowed = false;
};

} // namespace

std::error_code SampleProfileWriterBinary::writeProfileType(
    ProfTypes Type, function_ref<std::error_code()> WritePayload) {
  // PayloadSizeStream temporarily owns the real output while the callback
  // writes through OutputStream. A nested call would therefore mistake the
  // real output for PayloadSizeCountingStream.
  if (WritingProfileType)
    return sampleprof_error::malformed;
  SaveAndRestore RestoreWritingProfileType(WritingProfileType, true);

  // A profile block stores its payload size before the payload, but that size
  // is not known until it has been serialized. Count one complete serialization
  // without retaining its bytes, then emit the header and serialize it again.
  // TODO: Avoid serializing each payload twice while retaining bounded memory
  // use and compatibility with compressed section output.
  if (!PayloadSizeStream)
    PayloadSizeStream = std::make_unique<PayloadSizeCountingStream>();
  auto *SizeStream =
      static_cast<PayloadSizeCountingStream *>(PayloadSizeStream.get());
  SizeStream->resetPayload();
  OutputStream.swap(PayloadSizeStream);
  std::error_code EC = WritePayload();
  OutputStream.swap(PayloadSizeStream);
  if (EC)
    return EC;
  if (SizeStream->overflowed())
    return sampleprof_error::too_large;

  // Emit the compact header followed by the second, materialized pass.
  auto &OS = *OutputStream;
  encodeULEB128(Type, OS);
  encodeULEB128(SizeStream->payloadSize(), OS);
  uint64_t PayloadStart = OS.tell();
  if (std::error_code SecondPassEC = WritePayload())
    return SecondPassEC;

  // Reject a stateful callback that did not reproduce the counted payload.
  if (OS.tell() - PayloadStart != SizeStream->payloadSize())
    return sampleprof_error::malformed;
  return sampleprof_error::success;
}

static bool hasNonEmptyLBRProfile(const FunctionSamples &S, bool IsNested) {
  return S.getTotalSamples() != 0 || (!IsNested && S.getHeadSamples() != 0) ||
         !S.getBodySamples().empty();
}

std::error_code
SampleProfileWriterBinary::writeCompositeProfile(const FunctionSamples &S,
                                                 bool IsNested) {
  auto &OS = *OutputStream;
  bool WriteLBRProf = hasNonEmptyLBRProfile(S, IsNested);
  // Other profile types should be added here.
  uint32_t TypesNum = WriteLBRProf;

  // Write the number of profile types for function.
  encodeULEB128(TypesNum, OS);

  if (WriteLBRProf)
    return writeProfileType(ProfTypeLBR,
                            [&] { return writeLBRProfile(S, IsNested); });
  return sampleprof_error::success;
}

std::error_code SampleProfileWriterBinary::writeBody(const FunctionSamples &S,
                                                     bool IsNested) {
  auto &OS = *OutputStream;
  if (std::error_code EC = writeContextIdx(S.getContext()))
    return EC;

  // Emit all the body samples.
  if (WriteCompositeProf) {
    if (std::error_code EC = writeCompositeProfile(S, IsNested))
      return EC;
  } else {
    if (std::error_code EC = writeLBRProfile(S, IsNested))
      return EC;
  }

  // Recursively emit all the callsite samples.
  uint64_t NumCallsites = 0;
  for (const auto &J : S.getCallsiteSamples())
    NumCallsites += J.second.size();
  encodeULEB128(NumCallsites, OS);
  for (const auto &J : S.getCallsiteSamples())
    for (const auto &FS : J.second) {
      J.first.serialize(OS);
      if (std::error_code EC = writeBody(FS.second, /*IsNested=*/true))
        return EC;
    }

  if (WriteVTableProf)
    return writeCallsiteVTableProf(S.getCallsiteTypeCounts(), OS);

  return sampleprof_error::success;
}

/// Write samples of a top-level function to a binary file.
///
/// \returns true if the samples were written successfully, false otherwise.
std::error_code
SampleProfileWriterBinary::writeSample(const FunctionSamples &S) {
  encodeULEB128(S.getHeadSamples(), *OutputStream);
  return writeBody(S, /*IsNested=*/false);
}

/// Create a sample profile file writer based on the specified format.
///
/// \param Filename The file to create.
///
/// \param Format Encoding format for the profile file.
///
/// \returns an error code indicating the status of the created writer.
ErrorOr<std::unique_ptr<SampleProfileWriter>>
SampleProfileWriter::create(StringRef Filename, SampleProfileFormat Format) {
  std::error_code EC;
  std::unique_ptr<raw_ostream> OS;
  if (Format == SPF_Binary || Format == SPF_Ext_Binary)
    OS.reset(new raw_fd_ostream(Filename, EC, sys::fs::OF_None));
  else
    OS.reset(new raw_fd_ostream(Filename, EC, sys::fs::OF_TextWithCRLF));
  if (EC)
    return EC;

  return create(OS, Format);
}

/// Create a sample profile stream writer based on the specified format.
///
/// \param OS The output stream to store the profile data to.
///
/// \param Format Encoding format for the profile file.
///
/// \returns an error code indicating the status of the created writer.
ErrorOr<std::unique_ptr<SampleProfileWriter>>
SampleProfileWriter::create(std::unique_ptr<raw_ostream> &OS,
                            SampleProfileFormat Format) {
  std::error_code EC;
  std::unique_ptr<SampleProfileWriter> Writer;

  // Currently only Text and Extended Binary format are supported for CSSPGO.
  if ((FunctionSamples::ProfileIsCS || FunctionSamples::ProfileIsProbeBased) &&
      Format == SPF_Binary)
    return sampleprof_error::unsupported_writing_format;

  if (Format == SPF_Binary)
    Writer.reset(new SampleProfileWriterRawBinary(OS));
  else if (Format == SPF_Ext_Binary)
    Writer.reset(new SampleProfileWriterExtBinary(OS));
  else if (Format == SPF_Text)
    Writer.reset(new SampleProfileWriterText(OS));
  else if (Format == SPF_GCC)
    EC = sampleprof_error::unsupported_writing_format;
  else
    EC = sampleprof_error::unrecognized_format;

  if (EC)
    return EC;

  Writer->Format = Format;
  if (Format != SPF_Ext_Binary) {
    Writer->setFormatVersion(DefaultVersion);
  } else {
    if (!formatVersionIsSupported(RequestedVersion))
      return sampleprof_error::unsupported_version;

    // Composite output defaults to its first compatible format version.
    // Preserve a compatible version explicitly selected by the user.
    if (ExtBinaryCompositeProf) {
      if (RequestedVersion.getNumOccurrences() == 0) {
        Writer->setFormatVersion(CompositeProfileVersion);
      } else {
        if (RequestedVersion < CompositeProfileVersion)
          return sampleprof_error::unsupported_version;
        Writer->setFormatVersion(RequestedVersion);
      }
      // Keep subsequent writes independent of the global command-line option.
      Writer->setUseCompositeProfile(true);
    } else {
      Writer->setFormatVersion(RequestedVersion);
    }
  }

  return std::move(Writer);
}

void SampleProfileWriter::computeSummary(const SampleProfileMap &ProfileMap) {
  SampleProfileSummaryBuilder Builder(ProfileSummaryBuilder::DefaultCutoffs);
  Summary = Builder.computeSummaryForProfiles(ProfileMap);
}
