//===- SampleProfReader.cpp - Read 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 reads LLVM sample profiles. It
// supports three file formats: text, binary and gcov.
//
// The textual representation is useful for debugging and testing purposes. The
// binary representation is more compact, resulting in smaller file sizes.
//
// The gcov encoding is the one generated by GCC's AutoFDO profile creation
// tool (https://github.com/google/autofdo)
//
// All three encodings can be used interchangeably as an input sample profile.
//
//===----------------------------------------------------------------------===//

#include "llvm/ProfileData/SampleProfReader.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/ProfileSummary.h"
#include "llvm/ProfileData/ProfileCommon.h"
#include "llvm/ProfileData/SampleProf.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compression.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/JSON.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/LineIterator.h"
#include "llvm/Support/MD5.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <limits>
#include <memory>
#include <system_error>
#include <vector>

using namespace llvm;
using namespace sampleprof;

#define DEBUG_TYPE "samplepgo-reader"

// This internal option specifies if the profile uses FS discriminators.
// It only applies to text, and binary format profiles.
// For ext-binary format profiles, the flag is set in the summary.
static cl::opt<bool> ProfileIsFSDisciminator(
    "profile-isfs", cl::Hidden, cl::init(false),
    cl::desc("Profile uses flow sensitive discriminators"));

static cl::opt<bool>
    LazyLoadNameTable("sample-profile-lazy-load-name-table", cl::init(true),
                      cl::Hidden,
                      cl::desc("Lazy load the name table from the profile."));

/// Dump the function profile for \p FName.
///
/// \param FContext Name + context of the function to print.
/// \param OS Stream to emit the output to.
void SampleProfileReader::dumpFunctionProfile(const FunctionSamples &FS,
                                              raw_ostream &OS) {
  OS << "Function: " << FS.getContext().toString() << ": " << FS;
}

/// Dump all the function profiles found on stream \p OS.
void SampleProfileReader::dump(raw_ostream &OS) {
  std::vector<NameFunctionSamples> V;
  sortFuncProfiles(Profiles, V);
  for (const auto &I : V)
    dumpFunctionProfile(*I.second, OS);
}

static void dumpFunctionProfileJson(const FunctionSamples &S,
                                    json::OStream &JOS, bool TopLevel = false) {
  auto DumpBody = [&](const BodySampleMap &BodySamples) {
    for (const auto &I : BodySamples) {
      const LineLocation &Loc = I.first;
      const SampleRecord &Sample = I.second;
      JOS.object([&] {
        JOS.attribute("line", Loc.LineOffset);
        if (Loc.Discriminator)
          JOS.attribute("discriminator", Loc.Discriminator);
        JOS.attribute("samples", Sample.getSamples());

        auto CallTargets = Sample.getSortedCallTargets();
        if (!CallTargets.empty()) {
          JOS.attributeArray("calls", [&] {
            for (const auto &J : CallTargets) {
              JOS.object([&] {
                JOS.attribute("function", J.first.str());
                JOS.attribute("samples", J.second);
              });
            }
          });
        }
      });
    }
  };

  auto DumpCallsiteSamples = [&](const CallsiteSampleMap &CallsiteSamples) {
    for (const auto &I : CallsiteSamples)
      for (const auto &FS : I.second) {
        const LineLocation &Loc = I.first;
        const FunctionSamples &CalleeSamples = FS.second;
        JOS.object([&] {
          JOS.attribute("line", Loc.LineOffset);
          if (Loc.Discriminator)
            JOS.attribute("discriminator", Loc.Discriminator);
          JOS.attributeArray(
              "samples", [&] { dumpFunctionProfileJson(CalleeSamples, JOS); });
        });
      }
  };

  JOS.object([&] {
    JOS.attribute("name", S.getFunction().str());
    JOS.attribute("total", S.getTotalSamples());
    if (TopLevel)
      JOS.attribute("head", S.getHeadSamples());

    const auto &BodySamples = S.getBodySamples();
    if (!BodySamples.empty())
      JOS.attributeArray("body", [&] { DumpBody(BodySamples); });

    const auto &CallsiteSamples = S.getCallsiteSamples();
    if (!CallsiteSamples.empty())
      JOS.attributeArray("callsites",
                         [&] { DumpCallsiteSamples(CallsiteSamples); });
  });
}

/// Dump all the function profiles found on stream \p OS in the JSON format.
void SampleProfileReader::dumpJson(raw_ostream &OS) {
  std::vector<NameFunctionSamples> V;
  sortFuncProfiles(Profiles, V);
  json::OStream JOS(OS, 2);
  JOS.arrayBegin();
  for (const auto &F : V)
    dumpFunctionProfileJson(*F.second, JOS, true);
  JOS.arrayEnd();

  // Emit a newline character at the end as json::OStream doesn't emit one.
  OS << "\n";
}

/// Parse \p Input as function head.
///
/// Parse one line of \p Input, and update function name in \p FName,
/// function's total sample count in \p NumSamples, function's entry
/// count in \p NumHeadSamples.
///
/// \returns true if parsing is successful.
static bool ParseHead(const StringRef &Input, StringRef &FName,
                      uint64_t &NumSamples, uint64_t &NumHeadSamples) {
  if (Input[0] == ' ')
    return false;
  size_t n2 = Input.rfind(':');
  size_t n1 = Input.rfind(':', n2 - 1);
  FName = Input.substr(0, n1);
  if (Input.substr(n1 + 1, n2 - n1 - 1).getAsInteger(10, NumSamples))
    return false;
  if (Input.substr(n2 + 1).getAsInteger(10, NumHeadSamples))
    return false;
  return true;
}

/// Returns true if line offset \p L is legal (only has 16 bits).
static bool isOffsetLegal(unsigned L) { return (L & 0xffff) == L; }

/// Parse \p Input that contains metadata.
/// Possible metadata:
/// - CFG Checksum information:
///     !CFGChecksum: 12345
/// - CFG Checksum information:
///     !Attributes: 1
/// Stores the FunctionHash (a.k.a. CFG Checksum) into \p FunctionHash.
static bool parseMetadata(const StringRef &Input, uint64_t &FunctionHash,
                          uint32_t &Attributes) {
  if (Input.starts_with("!CFGChecksum:")) {
    StringRef CFGInfo = Input.substr(strlen("!CFGChecksum:")).trim();
    return !CFGInfo.getAsInteger(10, FunctionHash);
  }

  if (Input.starts_with("!Attributes:")) {
    StringRef Attrib = Input.substr(strlen("!Attributes:")).trim();
    return !Attrib.getAsInteger(10, Attributes);
  }

  return false;
}

enum class LineType {
  CallSiteProfile,
  BodyProfile,
  Metadata,
  VirtualCallTypeProfile,
};

// Parse `Input` as a white-space separated list of `vtable:count` pairs. An
// example input line is `_ZTVbar:1471 _ZTVfoo:630`.
static bool parseTypeCountMap(StringRef Input,
                              DenseMap<StringRef, uint64_t> &TypeCountMap) {
  for (size_t Index = Input.find_first_not_of(' '); Index != StringRef::npos;) {
    size_t ColonIndex = Input.find(':', Index);
    if (ColonIndex == StringRef::npos)
      return false; // No colon found, invalid format.
    StringRef TypeName = Input.substr(Index, ColonIndex - Index);
    // CountIndex is the start index of count.
    size_t CountStartIndex = ColonIndex + 1;
    // NextIndex is the start index after the 'target:count' pair.
    size_t NextIndex = Input.find_first_of(' ', CountStartIndex);
    uint64_t Count;
    if (Input.substr(CountStartIndex, NextIndex - CountStartIndex)
            .getAsInteger(10, Count))
      return false; // Invalid count.
    // Error on duplicated type names in one line of input.
    auto [Iter, Inserted] = TypeCountMap.insert({TypeName, Count});
    if (!Inserted)
      return false;
    Index = (NextIndex == StringRef::npos)
                ? StringRef::npos
                : Input.find_first_not_of(' ', NextIndex);
  }
  return true;
}

/// Parse \p Input as line sample.
///
/// \param Input input line.
/// \param LineTy Type of this line.
/// \param Depth the depth of the inline stack.
/// \param NumSamples total samples of the line/inlined callsite.
/// \param LineOffset line offset to the start of the function.
/// \param Discriminator discriminator of the line.
/// \param TargetCountMap map from indirect call target to count.
/// \param FunctionHash the function's CFG hash, used by pseudo probe.
///
/// returns true if parsing is successful.
static bool ParseLine(const StringRef &Input, LineType &LineTy, uint32_t &Depth,
                      uint64_t &NumSamples, uint32_t &LineOffset,
                      uint32_t &Discriminator, StringRef &CalleeName,
                      DenseMap<StringRef, uint64_t> &TargetCountMap,
                      DenseMap<StringRef, uint64_t> &TypeCountMap,
                      uint64_t &FunctionHash, uint32_t &Attributes,
                      bool &IsFlat) {
  for (Depth = 0; Input[Depth] == ' '; Depth++)
    ;
  if (Depth == 0)
    return false;

  if (Input[Depth] == '!') {
    LineTy = LineType::Metadata;
    // This metadata is only for manual inspection only. We already created a
    // FunctionSamples and put it in the profile map, so there is no point
    // to skip profiles even they have no use for ThinLTO.
    if (Input == StringRef(" !Flat")) {
      IsFlat = true;
      return true;
    }
    return parseMetadata(Input.substr(Depth), FunctionHash, Attributes);
  }

  size_t n1 = Input.find(':');
  StringRef Loc = Input.substr(Depth, n1 - Depth);
  size_t n2 = Loc.find('.');
  if (n2 == StringRef::npos) {
    if (Loc.getAsInteger(10, LineOffset) || !isOffsetLegal(LineOffset))
      return false;
    Discriminator = 0;
  } else {
    if (Loc.substr(0, n2).getAsInteger(10, LineOffset))
      return false;
    if (Loc.substr(n2 + 1).getAsInteger(10, Discriminator))
      return false;
  }

  StringRef Rest = Input.substr(n1 + 2);
  if (isDigit(Rest[0])) {
    LineTy = LineType::BodyProfile;
    size_t n3 = Rest.find(' ');
    if (n3 == StringRef::npos) {
      if (Rest.getAsInteger(10, NumSamples))
        return false;
    } else {
      if (Rest.substr(0, n3).getAsInteger(10, NumSamples))
        return false;
    }
    // Find call targets and their sample counts.
    // Note: In some cases, there are symbols in the profile which are not
    // mangled. To accommodate such cases, use colon + integer pairs as the
    // anchor points.
    // An example:
    // _M_construct<char *>:1000 string_view<std::allocator<char> >:437
    // ":1000" and ":437" are used as anchor points so the string above will
    // be interpreted as
    // target: _M_construct<char *>
    // count: 1000
    // target: string_view<std::allocator<char> >
    // count: 437
    while (n3 != StringRef::npos) {
      n3 += Rest.substr(n3).find_first_not_of(' ');
      Rest = Rest.substr(n3);
      n3 = Rest.find_first_of(':');
      if (n3 == StringRef::npos || n3 == 0)
        return false;

      StringRef Target;
      uint64_t count, n4;
      while (true) {
        // Get the segment after the current colon.
        StringRef AfterColon = Rest.substr(n3 + 1);
        // Get the target symbol before the current colon.
        Target = Rest.substr(0, n3);
        // Check if the word after the current colon is an integer.
        n4 = AfterColon.find_first_of(' ');
        n4 = (n4 != StringRef::npos) ? n3 + n4 + 1 : Rest.size();
        StringRef WordAfterColon = Rest.substr(n3 + 1, n4 - n3 - 1);
        if (!WordAfterColon.getAsInteger(10, count))
          break;

        // Try to find the next colon.
        uint64_t n5 = AfterColon.find_first_of(':');
        if (n5 == StringRef::npos)
          return false;
        n3 += n5 + 1;
      }

      // An anchor point is found. Save the {target, count} pair
      TargetCountMap[Target] = count;
      if (n4 == Rest.size())
        break;
      // Change n3 to the next blank space after colon + integer pair.
      n3 = n4;
    }
  } else if (Rest.starts_with(kVTableProfPrefix)) {
    LineTy = LineType::VirtualCallTypeProfile;
    return parseTypeCountMap(Rest.substr(strlen(kVTableProfPrefix)),
                             TypeCountMap);
  } else {
    LineTy = LineType::CallSiteProfile;
    size_t n3 = Rest.find_last_of(':');
    CalleeName = Rest.substr(0, n3);
    if (Rest.substr(n3 + 1).getAsInteger(10, NumSamples))
      return false;
  }
  return true;
}

/// Load samples from a text file.
///
/// See the documentation at the top of the file for an explanation of
/// the expected format.
///
/// \returns true if the file was loaded successfully, false otherwise.
std::error_code SampleProfileReaderText::readImpl() {
  line_iterator LineIt(*Buffer, /*SkipBlanks=*/true, '#');
  sampleprof_error Result = sampleprof_error::success;

  InlineCallStack InlineStack;
  uint32_t TopLevelProbeProfileCount = 0;

  // DepthMetadata tracks whether we have processed metadata for the current
  // top-level or nested function profile.
  uint32_t DepthMetadata = 0;

  std::vector<SampleContext *> FlatSamples;

  ProfileIsFS = ProfileIsFSDisciminator;
  FunctionSamples::ProfileIsFS = ProfileIsFS;
  for (; !LineIt.is_at_eof(); ++LineIt) {
    size_t pos = LineIt->find_first_not_of(' ');
    if (pos == LineIt->npos || (*LineIt)[pos] == '#')
      continue;
    // Read the header of each function.
    //
    // Note that for function identifiers we are actually expecting
    // mangled names, but we may not always get them. This happens when
    // the compiler decides not to emit the function (e.g., it was inlined
    // and removed). In this case, the binary will not have the linkage
    // name for the function, so the profiler will emit the function's
    // unmangled name, which may contain characters like ':' and '>' in its
    // name (member functions, templates, etc).
    //
    // The only requirement we place on the identifier, then, is that it
    // should not begin with a number.
    if ((*LineIt)[0] != ' ') {
      uint64_t NumSamples, NumHeadSamples;
      StringRef FName;
      if (!ParseHead(*LineIt, FName, NumSamples, NumHeadSamples)) {
        reportError(LineIt.line_number(),
                    "Expected 'mangled_name:NUM:NUM', found " + *LineIt);
        return sampleprof_error::malformed;
      }
      DepthMetadata = 0;
      SampleContext FContext(FName, CSNameTable);
      if (FContext.hasContext())
        ++CSProfileCount;
      FunctionSamples &FProfile = Profiles.create(FContext);
      mergeSampleProfErrors(Result, FProfile.addTotalSamples(NumSamples));
      mergeSampleProfErrors(Result, FProfile.addHeadSamples(NumHeadSamples));
      InlineStack.clear();
      InlineStack.push_back(&FProfile);
    } else {
      uint64_t NumSamples;
      StringRef FName;
      DenseMap<StringRef, uint64_t> TargetCountMap;
      DenseMap<StringRef, uint64_t> TypeCountMap;
      uint32_t Depth, LineOffset, Discriminator;
      LineType LineTy = LineType::BodyProfile;
      uint64_t FunctionHash = 0;
      uint32_t Attributes = 0;
      bool IsFlat = false;
      // TODO: Update ParseLine to return an error code instead of a bool and
      // report it.
      if (!ParseLine(*LineIt, LineTy, Depth, NumSamples, LineOffset,
                     Discriminator, FName, TargetCountMap, TypeCountMap,
                     FunctionHash, Attributes, IsFlat)) {
        switch (LineTy) {
        case LineType::Metadata:
          reportError(LineIt.line_number(),
                      "Cannot parse metadata: " + *LineIt);
          break;
        case LineType::VirtualCallTypeProfile:
          reportError(LineIt.line_number(),
                      "Expected 'vtables [mangled_vtable:NUM]+', found " +
                          *LineIt);
          break;
        default:
          reportError(LineIt.line_number(),
                      "Expected 'NUM[.NUM]: NUM[ mangled_name:NUM]*', found " +
                          *LineIt);
        }
        return sampleprof_error::malformed;
      }
      if (LineTy != LineType::Metadata && Depth == DepthMetadata) {
        // Metadata must be put at the end of a function profile.
        reportError(LineIt.line_number(),
                    "Found non-metadata after metadata: " + *LineIt);
        return sampleprof_error::malformed;
      }

      // Here we handle FS discriminators.
      Discriminator &= getDiscriminatorMask();

      while (InlineStack.size() > Depth) {
        InlineStack.pop_back();
      }
      switch (LineTy) {
      case LineType::CallSiteProfile: {
        FunctionSamples &FSamples = InlineStack.back()->functionSamplesAt(
            LineLocation(LineOffset, Discriminator))[FunctionId(FName)];
        FSamples.setFunction(FunctionId(FName));
        mergeSampleProfErrors(Result, FSamples.addTotalSamples(NumSamples));
        InlineStack.push_back(&FSamples);
        DepthMetadata = 0;
        break;
      }

      case LineType::VirtualCallTypeProfile: {
        mergeSampleProfErrors(
            Result, InlineStack.back()->addCallsiteVTableTypeProfAt(
                        LineLocation(LineOffset, Discriminator), TypeCountMap));
        break;
      }

      case LineType::BodyProfile: {
        FunctionSamples &FProfile = *InlineStack.back();
        for (const auto &name_count : TargetCountMap) {
          mergeSampleProfErrors(Result, FProfile.addCalledTargetSamples(
                                            LineOffset, Discriminator,
                                            FunctionId(name_count.first),
                                            name_count.second));
        }
        mergeSampleProfErrors(
            Result,
            FProfile.addBodySamples(LineOffset, Discriminator, NumSamples));
        break;
      }
      case LineType::Metadata: {
        FunctionSamples &FProfile = *InlineStack.back();
        if (FunctionHash) {
          FProfile.setFunctionHash(FunctionHash);
          if (Depth == 1)
            ++TopLevelProbeProfileCount;
        }
        FProfile.getContext().setAllAttributes(Attributes);
        if (Attributes & (uint32_t)ContextShouldBeInlined)
          ProfileIsPreInlined = true;
        DepthMetadata = Depth;
        if (IsFlat) {
          if (Depth == 1)
            FlatSamples.push_back(&FProfile.getContext());
          else
            Ctx.diagnose(DiagnosticInfoSampleProfile(
                Buffer->getBufferIdentifier(), LineIt.line_number(),
                "!Flat may only be used at top level function.", DS_Warning));
        }
        break;
      }
      }
    }
  }

  // Honor the option to skip flat functions. Since they are already added to
  // the profile map, remove them all here.
  if (SkipFlatProf)
    for (SampleContext *FlatSample : FlatSamples)
      Profiles.erase(*FlatSample);

  assert((CSProfileCount == 0 || CSProfileCount == Profiles.size()) &&
         "Cannot have both context-sensitive and regular profile");
  ProfileIsCS = (CSProfileCount > 0);
  assert((TopLevelProbeProfileCount == 0 ||
          TopLevelProbeProfileCount == Profiles.size()) &&
         "Cannot have both probe-based profiles and regular profiles");
  ProfileIsProbeBased = (TopLevelProbeProfileCount > 0);
  FunctionSamples::ProfileIsProbeBased = ProfileIsProbeBased;
  FunctionSamples::ProfileIsCS = ProfileIsCS;
  FunctionSamples::ProfileIsPreInlined = ProfileIsPreInlined;

  if (Result == sampleprof_error::success)
    computeSummary();

  return Result;
}

bool SampleProfileReaderText::hasFormat(const MemoryBuffer &Buffer) {
  bool result = false;

  // Check that the first non-comment line is a valid function header.
  line_iterator LineIt(Buffer, /*SkipBlanks=*/true, '#');
  if (!LineIt.is_at_eof()) {
    if ((*LineIt)[0] != ' ') {
      uint64_t NumSamples, NumHeadSamples;
      StringRef FName;
      result = ParseHead(*LineIt, FName, NumSamples, NumHeadSamples);
    }
  }

  return result;
}

template <typename T> ErrorOr<T> SampleProfileReaderBinary::readNumber() {
  unsigned NumBytesRead = 0;
  uint64_t Val = decodeULEB128(Data, &NumBytesRead);

  if (Val > std::numeric_limits<T>::max()) {
    std::error_code EC = sampleprof_error::malformed;
    reportError(0, EC.message());
    return EC;
  } else if (Data + NumBytesRead > End) {
    std::error_code EC = sampleprof_error::truncated;
    reportError(0, EC.message());
    return EC;
  }

  Data += NumBytesRead;
  return static_cast<T>(Val);
}

ErrorOr<StringRef> SampleProfileReaderBinary::readString() {
  StringRef Str(reinterpret_cast<const char *>(Data));
  if (Data + Str.size() + 1 > End) {
    std::error_code EC = sampleprof_error::truncated;
    reportError(0, EC.message());
    return EC;
  }

  Data += Str.size() + 1;
  return Str;
}

template <typename T>
ErrorOr<T> SampleProfileReaderBinary::readUnencodedNumber() {
  if (Data + sizeof(T) > End) {
    std::error_code EC = sampleprof_error::truncated;
    reportError(0, EC.message());
    return EC;
  }

  using namespace support;
  T Val = endian::readNext<T, llvm::endianness::little>(Data);
  return Val;
}

template <typename T>
inline ErrorOr<size_t> SampleProfileReaderBinary::readStringIndex(T &Table) {
  auto Idx = readNumber<size_t>();
  if (std::error_code EC = Idx.getError())
    return EC;
  if (*Idx >= Table.size())
    return sampleprof_error::truncated_name_table;
  return *Idx;
}

ErrorOr<FunctionId>
SampleProfileReaderBinary::readStringFromTable(size_t *RetIdx) {
  if (!NameTable)
    return sampleprof_error::truncated_name_table;
  auto Idx = readStringIndex(*NameTable);
  if (std::error_code EC = Idx.getError())
    return EC;
  if (RetIdx)
    *RetIdx = *Idx;
  return (*NameTable)[*Idx];
}

ErrorOr<SampleContextFrames>
SampleProfileReaderBinary::readContextFromTable(size_t *RetIdx) {
  auto ContextIdx = readNumber<size_t>();
  if (std::error_code EC = ContextIdx.getError())
    return EC;
  if (*ContextIdx >= CSNameTable.size())
    return sampleprof_error::truncated_name_table;
  if (RetIdx)
    *RetIdx = *ContextIdx;
  return CSNameTable[*ContextIdx];
}

ErrorOr<std::pair<SampleContext, uint64_t>>
SampleProfileReaderBinary::readSampleContextFromTable() {
  SampleContext Context;
  size_t Idx;
  if (ProfileIsCS) {
    auto FContext(readContextFromTable(&Idx));
    if (std::error_code EC = FContext.getError())
      return EC;
    Context = SampleContext(*FContext);
  } else {
    auto FName(readStringFromTable(&Idx));
    if (std::error_code EC = FName.getError())
      return EC;
    Context = SampleContext(*FName);
  }
  // Since MD5SampleContextStart may point to the profile's file data, need to
  // make sure it is reading the same value on big endian CPU.
  uint64_t Hash = support::endian::read64le(MD5SampleContextStart + Idx);
  // Lazy computing of hash value, write back to the table to cache it. Only
  // compute the context's hash value if it is being referenced for the first
  // time.
  if (Hash == 0) {
    assert(MD5SampleContextStart == MD5SampleContextTable.data());
    Hash = Context.getHashCode();
    support::endian::write64le(&MD5SampleContextTable[Idx], Hash);
  }
  return std::make_pair(Context, Hash);
}

std::error_code
SampleProfileReaderBinary::readVTableTypeCountMap(TypeCountMap &M) {
  auto NumVTableTypes = readNumber<uint32_t>();
  if (std::error_code EC = NumVTableTypes.getError())
    return EC;
  M.reserve(*NumVTableTypes);

  for (uint32_t I = 0; I < *NumVTableTypes; ++I) {
    auto VTableType(readStringFromTable());
    if (std::error_code EC = VTableType.getError())
      return EC;

    auto VTableSamples = readNumber<uint64_t>();
    if (std::error_code EC = VTableSamples.getError())
      return EC;
    // The source profile should not have duplicate vtable records at the same
    // location. In case duplicate vtables are found, reader can emit a warning
    // but continue processing the profile.
    if (!M.insert(std::make_pair(*VTableType, *VTableSamples)).second) {
      Ctx.diagnose(DiagnosticInfoSampleProfile(
          Buffer->getBufferIdentifier(), 0,
          "Duplicate vtable type " + VTableType->str() +
              " at the same location. Additional counters will be ignored.",
          DS_Warning));
      continue;
    }
  }
  return sampleprof_error::success;
}

std::error_code
SampleProfileReaderBinary::readCallsiteVTableProf(FunctionSamples &FProfile) {
  assert(ReadVTableProf &&
         "Cannot read vtable profiles if ReadVTableProf is false");

  // Read the vtable type profile for the callsite.
  auto NumCallsites = readNumber<uint32_t>();
  if (std::error_code EC = NumCallsites.getError())
    return EC;
  FProfile.reserveCallsiteTypeCounts(*NumCallsites);

  for (uint32_t I = 0; I < *NumCallsites; ++I) {
    auto LineOffset = readNumber<uint64_t>();
    if (std::error_code EC = LineOffset.getError())
      return EC;

    if (!isOffsetLegal(*LineOffset))
      return sampleprof_error::illegal_line_offset;

    auto Discriminator = readNumber<uint64_t>();
    if (std::error_code EC = Discriminator.getError())
      return EC;

    // Here we handle FS discriminators:
    const uint32_t DiscriminatorVal = (*Discriminator) & getDiscriminatorMask();

    if (std::error_code EC = readVTableTypeCountMap(FProfile.getTypeSamplesAt(
            LineLocation(*LineOffset, DiscriminatorVal))))
      return EC;
  }
  return sampleprof_error::success;
}

std::error_code
SampleProfileReaderBinary::readProfile(FunctionSamples &FProfile) {
  auto NumSamples = readNumber<uint64_t>();
  if (std::error_code EC = NumSamples.getError())
    return EC;
  FProfile.addTotalSamples(*NumSamples);

  // Read the samples in the body.
  auto NumRecords = readNumber<uint32_t>();
  if (std::error_code EC = NumRecords.getError())
    return EC;
  FProfile.reserveBodySamples(*NumRecords);

  for (uint32_t I = 0; I < *NumRecords; ++I) {
    auto LineOffset = readNumber<uint64_t>();
    if (std::error_code EC = LineOffset.getError())
      return EC;

    if (!isOffsetLegal(*LineOffset)) {
      return sampleprof_error::illegal_line_offset;
    }

    auto Discriminator = readNumber<uint64_t>();
    if (std::error_code EC = Discriminator.getError())
      return EC;

    auto NumSamples = readNumber<uint64_t>();
    if (std::error_code EC = NumSamples.getError())
      return EC;

    auto NumCalls = readNumber<uint32_t>();
    if (std::error_code EC = NumCalls.getError())
      return EC;

    // Here we handle FS discriminators:
    uint32_t DiscriminatorVal = (*Discriminator) & getDiscriminatorMask();

    for (uint32_t J = 0; J < *NumCalls; ++J) {
      auto CalledFunction(readStringFromTable());
      if (std::error_code EC = CalledFunction.getError())
        return EC;

      auto CalledFunctionSamples = readNumber<uint64_t>();
      if (std::error_code EC = CalledFunctionSamples.getError())
        return EC;

      FProfile.addCalledTargetSamples(*LineOffset, DiscriminatorVal,
                                      *CalledFunction, *CalledFunctionSamples);
    }

    FProfile.addBodySamples(*LineOffset, DiscriminatorVal, *NumSamples);
  }

  // Read all the samples for inlined function calls.
  auto NumCallsites = readNumber<uint32_t>();
  if (std::error_code EC = NumCallsites.getError())
    return EC;

  for (uint32_t J = 0; J < *NumCallsites; ++J) {
    auto LineOffset = readNumber<uint64_t>();
    if (std::error_code EC = LineOffset.getError())
      return EC;

    auto Discriminator = readNumber<uint64_t>();
    if (std::error_code EC = Discriminator.getError())
      return EC;

    auto FName(readStringFromTable());
    if (std::error_code EC = FName.getError())
      return EC;

    // Here we handle FS discriminators:
    uint32_t DiscriminatorVal = (*Discriminator) & getDiscriminatorMask();

    FunctionSamples &CalleeProfile = FProfile.functionSamplesAt(
        LineLocation(*LineOffset, DiscriminatorVal))[*FName];
    CalleeProfile.setFunction(*FName);
    if (std::error_code EC = readProfile(CalleeProfile))
      return EC;
  }

  if (ReadVTableProf)
    return readCallsiteVTableProf(FProfile);

  return sampleprof_error::success;
}

std::error_code
SampleProfileReaderBinary::readFuncProfile(const uint8_t *Start,
                                           SampleProfileMap &Profiles) {
  Data = Start;
  auto NumHeadSamples = readNumber<uint64_t>();
  if (std::error_code EC = NumHeadSamples.getError())
    return EC;

  auto FContextHash(readSampleContextFromTable());
  if (std::error_code EC = FContextHash.getError())
    return EC;

  auto &[FContext, Hash] = *FContextHash;
  // Use the cached hash value for insertion instead of recalculating it.
  auto Res = Profiles.try_emplace(Hash, FContext, FunctionSamples());
  FunctionSamples &FProfile = Res.first->second;
  FProfile.setContext(FContext);
  FProfile.addHeadSamples(*NumHeadSamples);

  if (FContext.hasContext())
    CSProfileCount++;

  if (std::error_code EC = readProfile(FProfile))
    return EC;
  return sampleprof_error::success;
}

std::error_code
SampleProfileReaderBinary::readFuncProfile(const uint8_t *Start) {
  return readFuncProfile(Start, Profiles);
}

std::error_code SampleProfileReaderBinary::readImpl() {
  ProfileIsFS = ProfileIsFSDisciminator;
  FunctionSamples::ProfileIsFS = ProfileIsFS;
  while (Data < End) {
    if (std::error_code EC = readFuncProfile(Data))
      return EC;
  }

  return sampleprof_error::success;
}

std::error_code SampleProfileReaderExtBinaryBase::readOneSection(
    const uint8_t *Start, uint64_t Size, const SecHdrTableEntry &Entry) {
  Data = Start;
  End = Start + Size;
  switch (Entry.Type) {
  case SecProfSummary:
    if (std::error_code EC = readSummary())
      return EC;
    if (hasSecFlag(Entry, SecProfSummaryFlags::SecFlagPartial))
      Summary->setPartialProfile(true);
    if (hasSecFlag(Entry, SecProfSummaryFlags::SecFlagFullContext))
      FunctionSamples::ProfileIsCS = ProfileIsCS = true;
    if (hasSecFlag(Entry, SecProfSummaryFlags::SecFlagIsPreInlined))
      FunctionSamples::ProfileIsPreInlined = ProfileIsPreInlined = true;
    if (hasSecFlag(Entry, SecProfSummaryFlags::SecFlagFSDiscriminator))
      FunctionSamples::ProfileIsFS = ProfileIsFS = true;
    if (hasSecFlag(Entry, SecProfSummaryFlags::SecFlagHasVTableTypeProf))
      ReadVTableProf = true;
    break;
  case SecNameTable: {
    bool FixedLengthMD5 =
        hasSecFlag(Entry, SecNameTableFlags::SecFlagFixedLengthMD5);
    bool UseMD5 = hasSecFlag(Entry, SecNameTableFlags::SecFlagMD5Name);
    // UseMD5 means if THIS section uses MD5, ProfileIsMD5 means if the entire
    // profile uses MD5 for function name matching in IPO passes.
    ProfileIsMD5 = ProfileIsMD5 || UseMD5;
    FunctionSamples::HasUniqSuffix =
        hasSecFlag(Entry, SecNameTableFlags::SecFlagUniqSuffix);
    bool IsEytzinger = hasSecFlag(Entry, SecNameTableFlags::SecFlagEytzinger);
    if (std::error_code EC =
            readNameTableSec(UseMD5, FixedLengthMD5, IsEytzinger))
      return EC;
    break;
  }
  case SecCSNameTable: {
    if (std::error_code EC = readCSNameTableSec())
      return EC;
    break;
  }
  case SecLBRProfile:
    ProfileSecRange = std::make_pair(Data, End);
    if (std::error_code EC = readFuncProfiles())
      return EC;
    break;
  case SecFuncOffsetTable:
    // If module is absent, we are using LLVM tools, and need to read all
    // profiles, so skip reading the function offset table.
    if (!M) {
      Data = End;
    } else {
      bool IsEytzinger =
          hasSecFlag(Entry, SecFuncOffsetFlags::SecFlagEytzinger);
      bool IsFlat = hasSecFlag(Entry, SecCommonFlags::SecFlagFlat);
      // An unflagged function offset table inherently indexes the primary
      // Nested symbol span.
      bool IsNested = !IsFlat;
      assert((!ProfileIsCS ||
              hasSecFlag(Entry, SecFuncOffsetFlags::SecFlagOrdered) ||
              IsEytzinger) &&
             "func offset table should always be sorted or in Eytzinger BFS "
             "order in CS profile");
      if (std::error_code EC = readFuncOffsetTable(IsEytzinger, IsNested))
        return EC;
    }
    break;
  case SecFuncMetadata: {
    ProfileIsProbeBased =
        hasSecFlag(Entry, SecFuncMetadataFlags::SecFlagIsProbeBased);
    FunctionSamples::ProfileIsProbeBased = ProfileIsProbeBased;
    ProfileHasAttribute =
        hasSecFlag(Entry, SecFuncMetadataFlags::SecFlagHasAttribute);
    if (std::error_code EC = readFuncMetadata())
      return EC;
    break;
  }
  case SecProfileSymbolList:
    if (std::error_code EC = readProfileSymbolList(
            hasSecFlag(Entry, SecProfileSymbolListFlags::SecFlagMD5)))
      return EC;
    break;
  default:
    if (std::error_code EC = readCustomSection(Entry))
      return EC;
    break;
  }
  return sampleprof_error::success;
}

bool SampleProfileReaderExtBinaryBase::useFuncOffsetList() const {
  // If profile is CS, the function offset section is expected to consist of
  // sequences of contexts in pre-order layout
  // (e.g. [A, A:1 @ B, A:1 @ B:2.3 @ C] [D, D:1 @ E]), so that when a matched
  // context in the module is found, the profiles of all its callees are
  // recursively loaded. A list is needed since the order of profiles matters.
  if (ProfileIsCS)
    return true;

  // If the profile is MD5, use the map container to lookup functions in
  // the module. A remapper has no use on MD5 names.
  if (useMD5())
    return false;

  // Profile is not MD5 and if a remapper is present, the remapped name of
  // every function needed to be matched against the module, so use the list
  // container since each entry is accessed.
  if (Remapper)
    return true;

  // Otherwise use the map container for faster lookup.
  // TODO: If the cardinality of the function offset section is much smaller
  // than the number of functions in the module, using the list container can
  // be always faster, but we need to figure out the constant factor to
  // determine the cutoff.
  return false;
}

std::error_code
SampleProfileReaderExtBinaryBase::read(const DenseSet<StringRef> &FuncsToUse,
                                       SampleProfileMap &Profiles) {
  if (FuncsToUse.empty())
    return sampleprof_error::success;

  Data = ProfileSecRange.first;
  End = ProfileSecRange.second;
  if (std::error_code EC = readFuncProfiles(FuncsToUse, Profiles))
    return EC;
  End = Data;
  DenseSet<FunctionSamples *> ProfilesToReadMetadata;
  for (auto FName : FuncsToUse) {
    auto I = Profiles.find(FName);
    if (I != Profiles.end())
      ProfilesToReadMetadata.insert(&I->second);
  }

  if (std::error_code EC = readFuncMetadata(ProfilesToReadMetadata))
    return EC;
  return sampleprof_error::success;
}

bool SampleProfileReaderExtBinaryBase::collectFuncsFromModule() {
  if (!M)
    return false;
  FuncsToUse.clear();
  for (auto &F : *M)
    FuncsToUse.insert(FunctionSamples::getCanonicalFnName(F));
  return true;
}

std::error_code
SampleProfileReaderExtBinaryBase::readFuncOffsetTable(bool IsEytzinger,
                                                      bool IsNested) {
  if (IsEytzinger)
    return readEytzingerFuncOffsetTable(IsNested);
  return readLegacyFuncOffsetTable();
}

std::error_code
SampleProfileReaderExtBinaryBase::readEytzingerFuncOffsetTable(bool IsNested) {
  // If there are more than one function offset section, the profile associated
  // with the previous section has to be done reading before next one is read.
  FuncOffsetTable.reset();

  size_t Size = End - Data;
  size_t SpanSize = NameTable->getEytzingerSpan(IsNested).size();
  if (Size != SpanSize * sizeof(uint32_t))
    return sampleprof_error::malformed;

  auto *Array = reinterpret_cast<const support::ulittle32_t *>(Data);
  ArrayRef<support::ulittle32_t> Offsets(Array, SpanSize);

  FuncOffsetTable.emplace(EytzingerMode, NameTable->getEytzingerSpan(IsNested),
                          Offsets);

  Data = End;
  return sampleprof_error::success;
}

std::error_code SampleProfileReaderExtBinaryBase::readLegacyFuncOffsetTable() {
  // If there are more than one function offset section, the profile associated
  // with the previous section has to be done reading before next one is read.
  FuncOffsetTable.reset();
  FuncOffsetList.clear();

  auto Size = readNumber<uint64_t>();
  if (std::error_code EC = Size.getError())
    return EC;

  bool UseFuncOffsetList = useFuncOffsetList();
  if (UseFuncOffsetList)
    FuncOffsetList.reserve(*Size);
  else
    FuncOffsetTable.emplace(InMemoryMode, *Size);

  for (uint64_t I = 0; I < *Size; ++I) {
    auto FContextHash(readSampleContextFromTable());
    if (std::error_code EC = FContextHash.getError())
      return EC;

    auto &[FContext, Hash] = *FContextHash;
    auto Offset = readNumber<uint64_t>();
    if (std::error_code EC = Offset.getError())
      return EC;

    if (UseFuncOffsetList)
      FuncOffsetList.emplace_back(FContext, *Offset);
    else
      // Because Porfiles replace existing value with new value if collision
      // happens, we also use the latest offset so that they are consistent.
      FuncOffsetTable->insert(Hash, *Offset);
  }

  return sampleprof_error::success;
}

std::error_code SampleProfileReaderExtBinaryBase::readFuncProfiles(
    const DenseSet<StringRef> &FuncsToUse, SampleProfileMap &Profiles) {
  const uint8_t *Start = Data;

  if (Remapper) {
    for (auto Name : FuncsToUse) {
      Remapper->insert(Name);
    }
  }

  if (FuncOffsetTable && FuncOffsetTable->isEytzinger() &&
      useFuncOffsetList()) {
    ArrayRef<support::ulittle32_t> Offsets = FuncOffsetTable->getFuncOffsets();
    if (Offsets.size() != FuncOffsetTable->getExpectedSize())
      return sampleprof_error::malformed;
    for (const auto &[LocalIdx, RelOffset] : llvm::enumerate(Offsets)) {
      if (RelOffset == UINT32_MAX)
        continue;
      const uint8_t *FuncProfileAddr = Start + RelOffset;
      if (std::error_code EC = readFuncProfile(FuncProfileAddr, Profiles))
        return EC;
    }
    return sampleprof_error::success;
  }

  if (ProfileIsCS) {
    assert(useFuncOffsetList());
    DenseSet<uint64_t> FuncGuidsToUse;
    if (useMD5()) {
      for (auto Name : FuncsToUse)
        FuncGuidsToUse.insert(Function::getGUIDAssumingExternalLinkage(Name));
    }

    // For each function in current module, load all context profiles for
    // the function as well as their callee contexts which can help profile
    // guided importing for ThinLTO. This can be achieved by walking
    // through an ordered context container, where contexts are laid out
    // as if they were walked in preorder of a context trie. While
    // traversing the trie, a link to the highest common ancestor node is
    // kept so that all of its decendants will be loaded.
    const SampleContext *CommonContext = nullptr;
    for (const auto &NameOffset : FuncOffsetList) {
      const auto &FContext = NameOffset.first;
      FunctionId FName = FContext.getFunction();
      StringRef FNameString;
      if (!useMD5())
        FNameString = FName.stringRef();

      // For function in the current module, keep its farthest ancestor
      // context. This can be used to load itself and its child and
      // sibling contexts.
      if ((useMD5() && FuncGuidsToUse.count(FName.getHashCode())) ||
          (!useMD5() && (FuncsToUse.count(FNameString) ||
                         (Remapper && Remapper->exist(FNameString))))) {
        if (!CommonContext || !CommonContext->isPrefixOf(FContext))
          CommonContext = &FContext;
      }

      if (CommonContext == &FContext ||
          (CommonContext && CommonContext->isPrefixOf(FContext))) {
        // Load profile for the current context which originated from
        // the common ancestor.
        const uint8_t *FuncProfileAddr = Start + NameOffset.second;
        if (std::error_code EC = readFuncProfile(FuncProfileAddr))
          return EC;
      }
    }
  } else if (useMD5()) {
    assert(!useFuncOffsetList());
    for (auto Name : FuncsToUse) {
      auto GUID = MD5Hash(Name);
      if (auto Offset = FuncOffsetTable->lookup(GUID)) {
        const uint8_t *FuncProfileAddr = Start + *Offset;
        if (std::error_code EC = readFuncProfile(FuncProfileAddr, Profiles))
          return EC;
      }
    }
  } else if (Remapper) {
    assert(useFuncOffsetList());
    for (auto NameOffset : FuncOffsetList) {
      SampleContext FContext(NameOffset.first);
      auto FuncName = FContext.getFunction();
      StringRef FuncNameStr = FuncName.stringRef();
      if (!FuncsToUse.count(FuncNameStr) && !Remapper->exist(FuncNameStr))
        continue;
      const uint8_t *FuncProfileAddr = Start + NameOffset.second;
      if (std::error_code EC = readFuncProfile(FuncProfileAddr, Profiles))
        return EC;
    }
  } else {
    assert(!useFuncOffsetList());
    for (auto Name : FuncsToUse) {
      if (auto Offset = FuncOffsetTable->lookup(MD5Hash(Name))) {
        const uint8_t *FuncProfileAddr = Start + *Offset;
        if (std::error_code EC = readFuncProfile(FuncProfileAddr, Profiles))
          return EC;
      }
    }
  }

  return sampleprof_error::success;
}

std::error_code SampleProfileReaderExtBinaryBase::readFuncProfiles() {
  // Collect functions used by current module if the Reader has been
  // given a module.
  // collectFuncsFromModule uses FunctionSamples::getCanonicalFnName
  // which will query FunctionSamples::HasUniqSuffix, so it has to be
  // called after FunctionSamples::HasUniqSuffix is set, i.e. after
  // NameTable section is read.
  bool LoadFuncsToBeUsed = collectFuncsFromModule();

  // When LoadFuncsToBeUsed is false, we are using LLVM tool, need to read all
  // profiles.
  if (!LoadFuncsToBeUsed) {
    while (Data < End) {
      if (std::error_code EC = readFuncProfile(Data))
        return EC;
    }
    assert(Data == End && "More data is read than expected");
  } else {
    // Load function profiles on demand.
    if (std::error_code EC = readFuncProfiles(FuncsToUse, Profiles))
      return EC;
    Data = End;
  }
  assert((CSProfileCount == 0 || CSProfileCount == Profiles.size()) &&
         "Cannot have both context-sensitive and regular profile");
  assert((!CSProfileCount || ProfileIsCS) &&
         "Section flag should be consistent with actual profile");
  return sampleprof_error::success;
}

std::error_code
SampleProfileReaderExtBinaryBase::readProfileSymbolList(bool IsMD5) {
  if (IsMD5)
    return readMD5ProfileSymbolList();
  return readStringBasedProfileSymbolList();
}

std::error_code SampleProfileReaderExtBinaryBase::readMD5ProfileSymbolList() {
  size_t Size = End - Data;
  if (Size % sizeof(uint64_t) != 0)
    return sampleprof_error::truncated;
  const auto *Table = reinterpret_cast<const support::ulittle64_t *>(Data);
  size_t NumEntries = Size / sizeof(uint64_t);
  if (!ProfSymList)
    ProfSymList = std::make_unique<ProfileSymbolList>();
  ProfSymList->setColdGUIDTable(
      EytzingerTableSpan<support::ulittle64_t>(Table, NumEntries));
  Data = End;
  return sampleprof_error::success;
}

std::error_code
SampleProfileReaderExtBinaryBase::readStringBasedProfileSymbolList() {
  if (!ProfSymList)
    ProfSymList = std::make_unique<ProfileSymbolList>();

  if (std::error_code EC = ProfSymList->read(Data, End - Data))
    return EC;

  Data = End;
  return sampleprof_error::success;
}

std::error_code SampleProfileReaderExtBinaryBase::decompressSection(
    const uint8_t *SecStart, const uint64_t SecSize,
    const uint8_t *&DecompressBuf, uint64_t &DecompressBufSize) {
  Data = SecStart;
  End = SecStart + SecSize;
  auto DecompressSize = readNumber<uint64_t>();
  if (std::error_code EC = DecompressSize.getError())
    return EC;
  DecompressBufSize = *DecompressSize;

  auto CompressSize = readNumber<uint64_t>();
  if (std::error_code EC = CompressSize.getError())
    return EC;

  if (!llvm::compression::zlib::isAvailable())
    return sampleprof_error::zlib_unavailable;

  uint8_t *Buffer = Allocator.Allocate<uint8_t>(DecompressBufSize);
  size_t UCSize = DecompressBufSize;
  llvm::Error E = compression::zlib::decompress(ArrayRef(Data, *CompressSize),
                                                Buffer, UCSize);
  if (E)
    return sampleprof_error::uncompress_failed;
  DecompressBuf = reinterpret_cast<const uint8_t *>(Buffer);
  return sampleprof_error::success;
}

std::error_code SampleProfileReaderExtBinaryBase::readImpl() {
  const uint8_t *BufStart =
      reinterpret_cast<const uint8_t *>(Buffer->getBufferStart());

  for (auto &Entry : SecHdrTable) {
    // Skip empty section.
    if (!Entry.Size)
      continue;

    // Skip sections without inlined functions when SkipFlatProf is true.
    if (SkipFlatProf && hasSecFlag(Entry, SecCommonFlags::SecFlagFlat))
      continue;

    const uint8_t *SecStart = BufStart + Entry.Offset;
    uint64_t SecSize = Entry.Size;

    // If the section is compressed, decompress it into a buffer
    // DecompressBuf before reading the actual data. The pointee of
    // 'Data' will be changed to buffer hold by DecompressBuf
    // temporarily when reading the actual data.
    bool isCompressed = hasSecFlag(Entry, SecCommonFlags::SecFlagCompress);
    if (isCompressed) {
      const uint8_t *DecompressBuf;
      uint64_t DecompressBufSize;
      if (std::error_code EC = decompressSection(
              SecStart, SecSize, DecompressBuf, DecompressBufSize))
        return EC;
      SecStart = DecompressBuf;
      SecSize = DecompressBufSize;
    }

    if (std::error_code EC = readOneSection(SecStart, SecSize, Entry))
      return EC;
    if (Data != SecStart + SecSize)
      return sampleprof_error::malformed;

    // Change the pointee of 'Data' from DecompressBuf to original Buffer.
    if (isCompressed) {
      Data = BufStart + Entry.Offset;
      End = BufStart + Buffer->getBufferSize();
    }
  }

  return sampleprof_error::success;
}

std::error_code SampleProfileReaderRawBinary::verifySPMagic(uint64_t Magic) {
  if (Magic == SPMagic())
    return sampleprof_error::success;
  return sampleprof_error::bad_magic;
}

std::error_code SampleProfileReaderExtBinary::verifySPMagic(uint64_t Magic) {
  if (Magic == SPMagic(SPF_Ext_Binary))
    return sampleprof_error::success;
  return sampleprof_error::bad_magic;
}

std::error_code SampleProfileReaderBinary::readNameTable() {
  auto Size = readNumber<size_t>();
  if (std::error_code EC = Size.getError())
    return EC;

  // Normally if useMD5 is true, the name table should have MD5 values, not
  // strings, however in the case that ExtBinary profile has multiple name
  // tables mixing string and MD5, all of them have to be normalized to use MD5,
  // because optimization passes can only handle either type.
  bool UseMD5 = useMD5();

  std::vector<FunctionId> TableVec;
  TableVec.reserve(*Size);
  if (!ProfileIsCS) {
    MD5SampleContextTable.clear();
    if (UseMD5)
      MD5SampleContextTable.reserve(*Size);
    else
      // If we are using strings, delay MD5 computation since only a portion of
      // names are used by top level functions. Use 0 to indicate MD5 value is
      // to be calculated as no known string has a MD5 value of 0.
      MD5SampleContextTable.resize(*Size);
  }
  for (size_t I = 0; I < *Size; ++I) {
    auto Name(readString());
    if (std::error_code EC = Name.getError())
      return EC;
    if (UseMD5) {
      FunctionId FID(*Name);
      if (!ProfileIsCS)
        MD5SampleContextTable.emplace_back(FID.getHashCode());
      TableVec.emplace_back(FID);
    } else
      TableVec.push_back(FunctionId(*Name));
  }
  if (!ProfileIsCS)
    MD5SampleContextStart = MD5SampleContextTable.data();
  if (UseMD5)
    NameTable =
        std::make_unique<MD5SampleProfileNameTable>(std::move(TableVec));
  else
    NameTable =
        std::make_unique<StringSampleProfileNameTable>(std::move(TableVec));
  return sampleprof_error::success;
}

std::error_code SampleProfileReaderExtBinaryBase::readNameTableSec(
    bool IsMD5, bool FixedLengthMD5, bool IsEytzinger) {
  if (IsEytzinger)
    return readNameTableSecEytzinger(IsMD5, FixedLengthMD5);
  return readNameTableSecLegacy(IsMD5, FixedLengthMD5);
}

// Read the Eytzinger layout for SecNameTable from an ExtBinary MD5 profile.
//
// The section consists of three sequential ULEB128 symbol counts (Nested, Flat,
// and Inlinees) followed by their corresponding arrays of 64-bit MD5 hash keys
// laid out in Eytzinger order.
std::error_code SampleProfileReaderExtBinaryBase::readNameTableSecEytzinger(
    bool IsMD5, bool FixedLengthMD5) {
  assert(IsMD5 && "Eytzinger name tables require MD5 representation");
  if (!IsMD5)
    return sampleprof_error::malformed;

  // Read the table sizes for Nested, flat, and inlinee symbols.
  std::array<uint64_t, static_cast<size_t>(EytzingerSpan::NumSpans)> Counts;
  for (uint64_t &Count : Counts) {
    auto ValOrErr = readNumber<uint64_t>();
    if (std::error_code EC = ValOrErr.getError())
      return EC;
    Count = *ValOrErr;
  }
  auto [NumNested, NumFlat, NumInlinees] = Counts;

  // Guard against unsigned overflow in total entry computation.
  if (NumNested > std::numeric_limits<uint32_t>::max() ||
      NumFlat > std::numeric_limits<uint32_t>::max() ||
      NumInlinees > std::numeric_limits<uint32_t>::max())
    return sampleprof_error::malformed;

  uint64_t TotalEntries = NumNested + NumFlat + NumInlinees;
  if (static_cast<size_t>(End - Data) < TotalEntries * sizeof(uint64_t))
    return sampleprof_error::truncated;

  NameTable = std::make_unique<EytzingerSampleProfileNameTable>(
      reinterpret_cast<const support::ulittle64_t *>(Data), NumNested, NumFlat,
      NumInlinees);

  if (!ProfileIsCS)
    MD5SampleContextStart = reinterpret_cast<const uint64_t *>(Data);
  Data = Data + TotalEntries * sizeof(uint64_t);
  return sampleprof_error::success;
}

std::error_code
SampleProfileReaderExtBinaryBase::readNameTableSecLegacy(bool IsMD5,
                                                         bool FixedLengthMD5) {
  if (FixedLengthMD5) {
    if (!IsMD5)
      errs() << "If FixedLengthMD5 is true, UseMD5 has to be true";
    auto Size = readNumber<size_t>();
    if (std::error_code EC = Size.getError())
      return EC;

    assert(Data + (*Size) * sizeof(uint64_t) == End &&
           "Fixed length MD5 name table does not contain specified number of "
           "entries");
    if (Data + (*Size) * sizeof(uint64_t) > End)
      return sampleprof_error::truncated;

    if (LazyLoadNameTable) {
      NameTable = std::make_unique<LazySampleProfileNameTable>(Data, *Size);
    } else {
      std::vector<FunctionId> TableVec;
      TableVec.reserve(*Size);
      for (size_t I = 0; I < *Size; ++I) {
        using namespace support;
        uint64_t FID = endian::read<uint64_t, unaligned>(
            Data + I * sizeof(uint64_t), endianness::little);
        TableVec.emplace_back(FunctionId(FID));
      }
      NameTable =
          std::make_unique<MD5SampleProfileNameTable>(std::move(TableVec));
    }
    if (!ProfileIsCS)
      MD5SampleContextStart = reinterpret_cast<const uint64_t *>(Data);
    Data = Data + (*Size) * sizeof(uint64_t);
    return sampleprof_error::success;
  }

  if (IsMD5) {
    assert(!FixedLengthMD5 && "FixedLengthMD5 should be unreachable here");
    auto Size = readNumber<size_t>();
    if (std::error_code EC = Size.getError())
      return EC;

    std::vector<FunctionId> TableVec;
    TableVec.reserve(*Size);
    if (!ProfileIsCS)
      MD5SampleContextTable.resize(*Size);
    for (size_t I = 0; I < *Size; ++I) {
      auto FID = readNumber<uint64_t>();
      if (std::error_code EC = FID.getError())
        return EC;
      if (!ProfileIsCS)
        support::endian::write64le(&MD5SampleContextTable[I], *FID);
      TableVec.emplace_back(FunctionId(*FID));
    }
    if (!ProfileIsCS)
      MD5SampleContextStart = MD5SampleContextTable.data();
    NameTable =
        std::make_unique<MD5SampleProfileNameTable>(std::move(TableVec));
    return sampleprof_error::success;
  }

  return SampleProfileReaderBinary::readNameTable();
}

// Read in the CS name table section, which basically contains a list of context
// vectors. Each element of a context vector, aka a frame, refers to the
// underlying raw function names that are stored in the name table, as well as
// a callsite identifier that only makes sense for non-leaf frames.
std::error_code SampleProfileReaderExtBinaryBase::readCSNameTableSec() {
  auto Size = readNumber<size_t>();
  if (std::error_code EC = Size.getError())
    return EC;

  CSNameTable.clear();
  CSNameTable.reserve(*Size);
  if (ProfileIsCS) {
    // Delay MD5 computation of CS context until they are needed. Use 0 to
    // indicate MD5 value is to be calculated as no known string has a MD5
    // value of 0.
    MD5SampleContextTable.clear();
    MD5SampleContextTable.resize(*Size);
    MD5SampleContextStart = MD5SampleContextTable.data();
  }
  for (size_t I = 0; I < *Size; ++I) {
    CSNameTable.emplace_back(SampleContextFrameVector());
    auto ContextSize = readNumber<uint32_t>();
    if (std::error_code EC = ContextSize.getError())
      return EC;
    for (uint32_t J = 0; J < *ContextSize; ++J) {
      auto FName(readStringFromTable());
      if (std::error_code EC = FName.getError())
        return EC;
      auto LineOffset = readNumber<uint64_t>();
      if (std::error_code EC = LineOffset.getError())
        return EC;

      if (!isOffsetLegal(*LineOffset))
        return sampleprof_error::illegal_line_offset;

      auto Discriminator = readNumber<uint64_t>();
      if (std::error_code EC = Discriminator.getError())
        return EC;

      CSNameTable.back().emplace_back(
          FName.get(), LineLocation(LineOffset.get(), Discriminator.get()));
    }
  }

  return sampleprof_error::success;
}

std::error_code
SampleProfileReaderExtBinaryBase::readFuncMetadata(FunctionSamples *FProfile) {
  if (Data < End) {
    if (ProfileIsProbeBased) {
      auto Checksum = readNumber<uint64_t>();
      if (std::error_code EC = Checksum.getError())
        return EC;
      if (FProfile)
        FProfile->setFunctionHash(*Checksum);
    }

    if (ProfileHasAttribute) {
      auto Attributes = readNumber<uint32_t>();
      if (std::error_code EC = Attributes.getError())
        return EC;
      if (FProfile)
        FProfile->getContext().setAllAttributes(*Attributes);
    }

    if (!ProfileIsCS) {
      // Read all the attributes for inlined function calls.
      auto NumCallsites = readNumber<uint32_t>();
      if (std::error_code EC = NumCallsites.getError())
        return EC;

      for (uint32_t J = 0; J < *NumCallsites; ++J) {
        auto LineOffset = readNumber<uint64_t>();
        if (std::error_code EC = LineOffset.getError())
          return EC;

        auto Discriminator = readNumber<uint64_t>();
        if (std::error_code EC = Discriminator.getError())
          return EC;

        auto FContextHash(readSampleContextFromTable());
        if (std::error_code EC = FContextHash.getError())
          return EC;

        auto &[FContext, Hash] = *FContextHash;
        FunctionSamples *CalleeProfile = nullptr;
        if (FProfile) {
          CalleeProfile = const_cast<FunctionSamples *>(
              &FProfile->functionSamplesAt(LineLocation(
                  *LineOffset, *Discriminator))[FContext.getFunction()]);
        }
        if (std::error_code EC = readFuncMetadata(CalleeProfile))
          return EC;
      }
    }
  }

  return sampleprof_error::success;
}

std::error_code SampleProfileReaderExtBinaryBase::readFuncMetadata(
    DenseSet<FunctionSamples *> &Profiles) {
  if (FuncMetadataIndex.empty())
    return sampleprof_error::success;

  for (auto *FProfile : Profiles) {
    auto R = FuncMetadataIndex.find(FProfile->getContext().getHashCode());
    if (R == FuncMetadataIndex.end())
      continue;

    Data = R->second.first;
    End = R->second.second;
    if (std::error_code EC = readFuncMetadata(FProfile))
      return EC;
    assert(Data == End && "More data is read than expected");
  }
  return sampleprof_error::success;
}

std::error_code SampleProfileReaderExtBinaryBase::readFuncMetadata() {
  while (Data < End) {
    auto FContextHash(readSampleContextFromTable());
    if (std::error_code EC = FContextHash.getError())
      return EC;
    auto &[FContext, Hash] = *FContextHash;
    FunctionSamples *FProfile = nullptr;
    auto It = Profiles.find(FContext);
    if (It != Profiles.end())
      FProfile = &It->second;

    const uint8_t *Start = Data;
    if (std::error_code EC = readFuncMetadata(FProfile))
      return EC;

    FuncMetadataIndex[FContext.getHashCode()] = {Start, Data};
  }

  assert(Data == End && "More data is read than expected");
  return sampleprof_error::success;
}

std::error_code
SampleProfileReaderExtBinaryBase::readSecHdrTableEntry(uint64_t Idx) {
  SecHdrTableEntry Entry;
  auto Type = readUnencodedNumber<uint64_t>();
  if (std::error_code EC = Type.getError())
    return EC;
  Entry.Type = static_cast<SecType>(*Type);

  auto Flags = readUnencodedNumber<uint64_t>();
  if (std::error_code EC = Flags.getError())
    return EC;
  Entry.Flags = *Flags;

  auto Offset = readUnencodedNumber<uint64_t>();
  if (std::error_code EC = Offset.getError())
    return EC;
  Entry.Offset = *Offset;

  auto Size = readUnencodedNumber<uint64_t>();
  if (std::error_code EC = Size.getError())
    return EC;
  Entry.Size = *Size;

  Entry.LayoutIndex = Idx;
  SecHdrTable.push_back(std::move(Entry));
  return sampleprof_error::success;
}

std::error_code SampleProfileReaderExtBinaryBase::readSecHdrTable() {
  auto EntryNum = readUnencodedNumber<uint64_t>();
  if (std::error_code EC = EntryNum.getError())
    return EC;

  for (uint64_t i = 0; i < (*EntryNum); i++)
    if (std::error_code EC = readSecHdrTableEntry(i))
      return EC;

  return sampleprof_error::success;
}

std::error_code SampleProfileReaderExtBinaryBase::readHeader() {
  const uint8_t *BufStart =
      reinterpret_cast<const uint8_t *>(Buffer->getBufferStart());
  Data = BufStart;
  End = BufStart + Buffer->getBufferSize();

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

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

  return sampleprof_error::success;
}

uint64_t SampleProfileReaderExtBinaryBase::getSectionSize(SecType Type) {
  uint64_t Size = 0;
  for (auto &Entry : SecHdrTable) {
    if (Entry.Type == Type)
      Size += Entry.Size;
  }
  return Size;
}

uint64_t SampleProfileReaderExtBinaryBase::getFileSize() {
  // Sections in SecHdrTable is not necessarily in the same order as
  // sections in the profile because section like FuncOffsetTable needs
  // to be written after section LBRProfile but needs to be read before
  // section LBRProfile, so we cannot simply use the last entry in
  // SecHdrTable to calculate the file size.
  uint64_t FileSize = 0;
  for (auto &Entry : SecHdrTable) {
    FileSize = std::max(Entry.Offset + Entry.Size, FileSize);
  }
  return FileSize;
}

static std::string getSecFlagsStr(const SecHdrTableEntry &Entry) {
  std::string Flags;
  if (hasSecFlag(Entry, SecCommonFlags::SecFlagCompress))
    Flags.append("{compressed,");
  else
    Flags.append("{");

  if (hasSecFlag(Entry, SecCommonFlags::SecFlagFlat))
    Flags.append("flat,");

  switch (Entry.Type) {
  case SecNameTable:
    if (hasSecFlag(Entry, SecNameTableFlags::SecFlagEytzinger))
      Flags.append("eytzinger,");
    if (hasSecFlag(Entry, SecNameTableFlags::SecFlagFixedLengthMD5))
      Flags.append("fixlenmd5,");
    else if (hasSecFlag(Entry, SecNameTableFlags::SecFlagMD5Name))
      Flags.append("md5,");
    if (hasSecFlag(Entry, SecNameTableFlags::SecFlagUniqSuffix))
      Flags.append("uniq,");
    break;
  case SecProfSummary:
    if (hasSecFlag(Entry, SecProfSummaryFlags::SecFlagPartial))
      Flags.append("partial,");
    if (hasSecFlag(Entry, SecProfSummaryFlags::SecFlagFullContext))
      Flags.append("context,");
    if (hasSecFlag(Entry, SecProfSummaryFlags::SecFlagIsPreInlined))
      Flags.append("preInlined,");
    if (hasSecFlag(Entry, SecProfSummaryFlags::SecFlagFSDiscriminator))
      Flags.append("fs-discriminator,");
    break;
  case SecFuncOffsetTable:
    if (hasSecFlag(Entry, SecFuncOffsetFlags::SecFlagOrdered))
      Flags.append("ordered,");
    if (hasSecFlag(Entry, SecFuncOffsetFlags::SecFlagEytzinger))
      Flags.append("eytzinger,");
    break;
  case SecFuncMetadata:
    if (hasSecFlag(Entry, SecFuncMetadataFlags::SecFlagIsProbeBased))
      Flags.append("probe,");
    if (hasSecFlag(Entry, SecFuncMetadataFlags::SecFlagHasAttribute))
      Flags.append("attr,");
    break;
  case SecProfileSymbolList:
    if (hasSecFlag(Entry, SecProfileSymbolListFlags::SecFlagMD5))
      Flags.append("md5,");
    break;
  default:
    break;
  }
  char &last = Flags.back();
  if (last == ',')
    last = '}';
  else
    Flags.append("}");
  return Flags;
}

bool SampleProfileReaderExtBinaryBase::dumpSectionInfo(raw_ostream &OS) {
  uint64_t TotalSecsSize = 0;
  for (auto &Entry : SecHdrTable) {
    OS << getSecName(Entry.Type) << " - Offset: " << Entry.Offset
       << ", Size: " << Entry.Size << ", Flags: " << getSecFlagsStr(Entry)
       << "\n";
    ;
    TotalSecsSize += Entry.Size;
  }
  uint64_t HeaderSize = SecHdrTable.front().Offset;
  assert(HeaderSize + TotalSecsSize == getFileSize() &&
         "Size of 'header + sections' doesn't match the total size of profile");

  OS << "Header Size: " << HeaderSize << "\n";
  OS << "Total Sections Size: " << TotalSecsSize << "\n";
  OS << "File Size: " << getFileSize() << "\n";
  return true;
}

std::error_code SampleProfileReaderBinary::readMagicIdent() {
  // Read and check the magic identifier.
  auto Magic = readNumber<uint64_t>();
  if (std::error_code EC = Magic.getError())
    return EC;
  else if (std::error_code EC = verifySPMagic(*Magic))
    return EC;

  // Read the version number.
  auto Version = readNumber<uint64_t>();
  if (std::error_code EC = Version.getError())
    return EC;
  else if (!formatVersionIsSupported(*Version))
    return sampleprof_error::unsupported_version;
  FormatVersion = *Version;

  return sampleprof_error::success;
}

std::error_code SampleProfileReaderBinary::readHeader() {
  Data = reinterpret_cast<const uint8_t *>(Buffer->getBufferStart());
  End = Data + Buffer->getBufferSize();

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

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

  if (std::error_code EC = readNameTable())
    return EC;
  return sampleprof_error::success;
}

std::error_code SampleProfileReaderBinary::readSummaryEntry(
    std::vector<ProfileSummaryEntry> &Entries) {
  auto Cutoff = readNumber<uint64_t>();
  if (std::error_code EC = Cutoff.getError())
    return EC;

  auto MinBlockCount = readNumber<uint64_t>();
  if (std::error_code EC = MinBlockCount.getError())
    return EC;

  auto NumBlocks = readNumber<uint64_t>();
  if (std::error_code EC = NumBlocks.getError())
    return EC;

  Entries.emplace_back(*Cutoff, *MinBlockCount, *NumBlocks);
  return sampleprof_error::success;
}

std::error_code SampleProfileReaderBinary::readSummary() {
  auto TotalCount = readNumber<uint64_t>();
  if (std::error_code EC = TotalCount.getError())
    return EC;

  auto MaxBlockCount = readNumber<uint64_t>();
  if (std::error_code EC = MaxBlockCount.getError())
    return EC;

  auto MaxFunctionCount = readNumber<uint64_t>();
  if (std::error_code EC = MaxFunctionCount.getError())
    return EC;

  auto NumBlocks = readNumber<uint64_t>();
  if (std::error_code EC = NumBlocks.getError())
    return EC;

  auto NumFunctions = readNumber<uint64_t>();
  if (std::error_code EC = NumFunctions.getError())
    return EC;

  auto NumSummaryEntries = readNumber<uint64_t>();
  if (std::error_code EC = NumSummaryEntries.getError())
    return EC;

  std::vector<ProfileSummaryEntry> Entries;
  for (unsigned i = 0; i < *NumSummaryEntries; i++) {
    std::error_code EC = readSummaryEntry(Entries);
    if (EC != sampleprof_error::success)
      return EC;
  }
  Summary = std::make_unique<ProfileSummary>(
      ProfileSummary::PSK_Sample, Entries, *TotalCount, *MaxBlockCount, 0,
      *MaxFunctionCount, *NumBlocks, *NumFunctions);

  return sampleprof_error::success;
}

bool SampleProfileReaderRawBinary::hasFormat(const MemoryBuffer &Buffer) {
  const uint8_t *Data =
      reinterpret_cast<const uint8_t *>(Buffer.getBufferStart());
  uint64_t Magic = decodeULEB128(Data);
  return Magic == SPMagic();
}

bool SampleProfileReaderExtBinary::hasFormat(const MemoryBuffer &Buffer) {
  const uint8_t *Data =
      reinterpret_cast<const uint8_t *>(Buffer.getBufferStart());
  uint64_t Magic = decodeULEB128(Data);
  return Magic == SPMagic(SPF_Ext_Binary);
}

std::error_code SampleProfileReaderGCC::skipNextWord() {
  uint32_t dummy;
  if (!GcovBuffer.readInt(dummy))
    return sampleprof_error::truncated;
  return sampleprof_error::success;
}

template <typename T> ErrorOr<T> SampleProfileReaderGCC::readNumber() {
  if (sizeof(T) <= sizeof(uint32_t)) {
    uint32_t Val;
    if (GcovBuffer.readInt(Val) && Val <= std::numeric_limits<T>::max())
      return static_cast<T>(Val);
  } else if (sizeof(T) <= sizeof(uint64_t)) {
    uint64_t Val;
    if (GcovBuffer.readInt64(Val) && Val <= std::numeric_limits<T>::max())
      return static_cast<T>(Val);
  }

  std::error_code EC = sampleprof_error::malformed;
  reportError(0, EC.message());
  return EC;
}

ErrorOr<StringRef> SampleProfileReaderGCC::readString() {
  StringRef Str;
  if (!GcovBuffer.readString(Str))
    return sampleprof_error::truncated;
  return Str;
}

std::error_code SampleProfileReaderGCC::readHeader() {
  // Read the magic identifier.
  if (!GcovBuffer.readGCDAFormat())
    return sampleprof_error::unrecognized_format;

  // Read the version number. Note - the GCC reader does not validate this
  // version, but the profile creator generates v704.
  GCOV::GCOVVersion version;
  if (!GcovBuffer.readGCOVVersion(version))
    return sampleprof_error::unrecognized_format;

  if (version != GCOV::V407)
    return sampleprof_error::unsupported_version;

  // Skip the empty integer.
  if (std::error_code EC = skipNextWord())
    return EC;

  return sampleprof_error::success;
}

std::error_code SampleProfileReaderGCC::readSectionTag(uint32_t Expected) {
  uint32_t Tag;
  if (!GcovBuffer.readInt(Tag))
    return sampleprof_error::truncated;

  if (Tag != Expected)
    return sampleprof_error::malformed;

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

  return sampleprof_error::success;
}

std::error_code SampleProfileReaderGCC::readNameTable() {
  if (std::error_code EC = readSectionTag(GCOVTagAFDOFileNames))
    return EC;

  uint32_t Size;
  if (!GcovBuffer.readInt(Size))
    return sampleprof_error::truncated;

  for (uint32_t I = 0; I < Size; ++I) {
    StringRef Str;
    if (!GcovBuffer.readString(Str))
      return sampleprof_error::truncated;
    Names.push_back(std::string(Str));
  }

  return sampleprof_error::success;
}

std::error_code SampleProfileReaderGCC::readFunctionProfiles() {
  if (std::error_code EC = readSectionTag(GCOVTagAFDOFunction))
    return EC;

  uint32_t NumFunctions;
  if (!GcovBuffer.readInt(NumFunctions))
    return sampleprof_error::truncated;

  InlineCallStack Stack;
  for (uint32_t I = 0; I < NumFunctions; ++I)
    if (std::error_code EC = readOneFunctionProfile(Stack, true, 0))
      return EC;

  computeSummary();
  return sampleprof_error::success;
}

std::error_code SampleProfileReaderGCC::readOneFunctionProfile(
    const InlineCallStack &InlineStack, bool Update, uint32_t Offset) {
  uint64_t HeadCount = 0;
  if (InlineStack.size() == 0)
    if (!GcovBuffer.readInt64(HeadCount))
      return sampleprof_error::truncated;

  uint32_t NameIdx;
  if (!GcovBuffer.readInt(NameIdx))
    return sampleprof_error::truncated;

  StringRef Name(Names[NameIdx]);

  uint32_t NumPosCounts;
  if (!GcovBuffer.readInt(NumPosCounts))
    return sampleprof_error::truncated;

  uint32_t NumCallsites;
  if (!GcovBuffer.readInt(NumCallsites))
    return sampleprof_error::truncated;

  FunctionSamples *FProfile = nullptr;
  if (InlineStack.size() == 0) {
    // If this is a top function that we have already processed, do not
    // update its profile again.  This happens in the presence of
    // function aliases.  Since these aliases share the same function
    // body, there will be identical replicated profiles for the
    // original function.  In this case, we simply not bother updating
    // the profile of the original function.
    FProfile = &Profiles[FunctionId(Name)];
    FProfile->addHeadSamples(HeadCount);
    if (FProfile->getTotalSamples() > 0)
      Update = false;
  } else {
    // Otherwise, we are reading an inlined instance. The top of the
    // inline stack contains the profile of the caller. Insert this
    // callee in the caller's CallsiteMap.
    FunctionSamples *CallerProfile = InlineStack.front();
    uint32_t LineOffset = Offset >> 16;
    uint32_t Discriminator = Offset & 0xffff;
    FProfile = &CallerProfile->functionSamplesAt(
        LineLocation(LineOffset, Discriminator))[FunctionId(Name)];
  }
  FProfile->setFunction(FunctionId(Name));
  FProfile->reserveBodySamples(NumPosCounts);

  for (uint32_t I = 0; I < NumPosCounts; ++I) {
    uint32_t Offset;
    if (!GcovBuffer.readInt(Offset))
      return sampleprof_error::truncated;

    uint32_t NumTargets;
    if (!GcovBuffer.readInt(NumTargets))
      return sampleprof_error::truncated;

    uint64_t Count;
    if (!GcovBuffer.readInt64(Count))
      return sampleprof_error::truncated;

    // The line location is encoded in the offset as:
    //   high 16 bits: line offset to the start of the function.
    //   low 16 bits: discriminator.
    uint32_t LineOffset = Offset >> 16;
    uint32_t Discriminator = Offset & 0xffff;

    InlineCallStack NewStack;
    NewStack.push_back(FProfile);
    llvm::append_range(NewStack, InlineStack);
    if (Update) {
      // Walk up the inline stack, adding the samples on this line to
      // the total sample count of the callers in the chain.
      for (auto *CallerProfile : NewStack)
        CallerProfile->addTotalSamples(Count);

      // Update the body samples for the current profile.
      FProfile->addBodySamples(LineOffset, Discriminator, Count);
    }

    // Process the list of functions called at an indirect call site.
    // These are all the targets that a function pointer (or virtual
    // function) resolved at runtime.
    for (uint32_t J = 0; J < NumTargets; J++) {
      uint32_t HistVal;
      if (!GcovBuffer.readInt(HistVal))
        return sampleprof_error::truncated;

      if (HistVal != HIST_TYPE_INDIR_CALL_TOPN)
        return sampleprof_error::malformed;

      uint64_t TargetIdx;
      if (!GcovBuffer.readInt64(TargetIdx))
        return sampleprof_error::truncated;
      StringRef TargetName(Names[TargetIdx]);

      uint64_t TargetCount;
      if (!GcovBuffer.readInt64(TargetCount))
        return sampleprof_error::truncated;

      if (Update)
        FProfile->addCalledTargetSamples(LineOffset, Discriminator,
                                         FunctionId(TargetName), TargetCount);
    }
  }

  // Process all the inlined callers into the current function. These
  // are all the callsites that were inlined into this function.
  for (uint32_t I = 0; I < NumCallsites; I++) {
    // The offset is encoded as:
    //   high 16 bits: line offset to the start of the function.
    //   low 16 bits: discriminator.
    uint32_t Offset;
    if (!GcovBuffer.readInt(Offset))
      return sampleprof_error::truncated;
    InlineCallStack NewStack;
    NewStack.push_back(FProfile);
    llvm::append_range(NewStack, InlineStack);
    if (std::error_code EC = readOneFunctionProfile(NewStack, Update, Offset))
      return EC;
  }

  return sampleprof_error::success;
}

/// Read a GCC AutoFDO profile.
///
/// This format is generated by the Linux Perf conversion tool at
/// https://github.com/google/autofdo.
std::error_code SampleProfileReaderGCC::readImpl() {
  assert(!ProfileIsFSDisciminator && "Gcc profiles not support FSDisciminator");
  // Read the string table.
  if (std::error_code EC = readNameTable())
    return EC;

  // Read the source profile.
  if (std::error_code EC = readFunctionProfiles())
    return EC;

  return sampleprof_error::success;
}

bool SampleProfileReaderGCC::hasFormat(const MemoryBuffer &Buffer) {
  StringRef Magic(Buffer.getBufferStart());
  return Magic == "adcg*704";
}

void SampleProfileReaderItaniumRemapper::applyRemapping(LLVMContext &Ctx) {
  // If the reader uses MD5 to represent string, we can't remap it because
  // we don't know what the original function names were.
  if (Reader.useMD5()) {
    Ctx.diagnose(DiagnosticInfoSampleProfile(
        Reader.getBuffer()->getBufferIdentifier(),
        "Profile data remapping cannot be applied to profile data "
        "using MD5 names (original mangled names are not available).",
        DS_Warning));
    return;
  }

  // CSSPGO-TODO: Remapper is not yet supported.
  // We will need to remap the entire context string.
  assert(Remappings && "should be initialized while creating remapper");
  for (auto &Sample : Reader.getProfiles()) {
    DenseSet<FunctionId> NamesInSample;
    Sample.second.findAllNames(NamesInSample);
    for (auto &Name : NamesInSample) {
      StringRef NameStr = Name.stringRef();
      if (auto Key = Remappings->insert(NameStr))
        NameMap.insert({Key, NameStr});
    }
  }

  RemappingApplied = true;
}

std::optional<StringRef>
SampleProfileReaderItaniumRemapper::lookUpNameInProfile(StringRef Fname) {
  if (auto Key = Remappings->lookup(Fname)) {
    StringRef Result = NameMap.lookup(Key);
    if (!Result.empty())
      return Result;
  }
  return std::nullopt;
}

/// Prepare a memory buffer for the contents of \p Filename.
///
/// \returns an error code indicating the status of the buffer.
static ErrorOr<std::unique_ptr<MemoryBuffer>>
setupMemoryBuffer(const Twine &Filename, vfs::FileSystem &FS) {
  auto BufferOrErr = Filename.str() == "-" ? MemoryBuffer::getSTDIN()
                                           : FS.getBufferForFile(Filename);
  if (std::error_code EC = BufferOrErr.getError())
    return EC;
  auto Buffer = std::move(BufferOrErr.get());

  return std::move(Buffer);
}

/// Create a sample profile reader based on the format of the input file.
///
/// \param Filename The file to open.
///
/// \param C The LLVM context to use to emit diagnostics.
///
/// \param P The FSDiscriminatorPass.
///
/// \param RemapFilename The file used for profile remapping.
///
/// \returns an error code indicating the status of the created reader.
ErrorOr<std::unique_ptr<SampleProfileReader>>
SampleProfileReader::create(StringRef Filename, LLVMContext &C,
                            vfs::FileSystem &FS, FSDiscriminatorPass P,
                            StringRef RemapFilename) {
  auto BufferOrError = setupMemoryBuffer(Filename, FS);
  if (std::error_code EC = BufferOrError.getError())
    return EC;
  return create(BufferOrError.get(), C, FS, P, RemapFilename);
}

/// Create a sample profile remapper from the given input, to remap the
/// function names in the given profile data.
///
/// \param Filename The file to open.
///
/// \param Reader The profile reader the remapper is going to be applied to.
///
/// \param C The LLVM context to use to emit diagnostics.
///
/// \returns an error code indicating the status of the created reader.
ErrorOr<std::unique_ptr<SampleProfileReaderItaniumRemapper>>
SampleProfileReaderItaniumRemapper::create(StringRef Filename,
                                           vfs::FileSystem &FS,
                                           SampleProfileReader &Reader,
                                           LLVMContext &C) {
  auto BufferOrError = setupMemoryBuffer(Filename, FS);
  if (std::error_code EC = BufferOrError.getError())
    return EC;
  return create(BufferOrError.get(), Reader, C);
}

/// Create a sample profile remapper from the given input, to remap the
/// function names in the given profile data.
///
/// \param B The memory buffer to create the reader from (assumes ownership).
///
/// \param C The LLVM context to use to emit diagnostics.
///
/// \param Reader The profile reader the remapper is going to be applied to.
///
/// \returns an error code indicating the status of the created reader.
ErrorOr<std::unique_ptr<SampleProfileReaderItaniumRemapper>>
SampleProfileReaderItaniumRemapper::create(std::unique_ptr<MemoryBuffer> &B,
                                           SampleProfileReader &Reader,
                                           LLVMContext &C) {
  auto Remappings = std::make_unique<SymbolRemappingReader>();
  if (Error E = Remappings->read(*B)) {
    handleAllErrors(
        std::move(E), [&](const SymbolRemappingParseError &ParseError) {
          C.diagnose(DiagnosticInfoSampleProfile(B->getBufferIdentifier(),
                                                 ParseError.getLineNum(),
                                                 ParseError.getMessage()));
        });
    return sampleprof_error::malformed;
  }

  return std::make_unique<SampleProfileReaderItaniumRemapper>(
      std::move(B), std::move(Remappings), Reader);
}

/// Create a sample profile reader based on the format of the input data.
///
/// \param B The memory buffer to create the reader from (assumes ownership).
///
/// \param C The LLVM context to use to emit diagnostics.
///
/// \param P The FSDiscriminatorPass.
///
/// \param RemapFilename The file used for profile remapping.
///
/// \returns an error code indicating the status of the created reader.
ErrorOr<std::unique_ptr<SampleProfileReader>>
SampleProfileReader::create(std::unique_ptr<MemoryBuffer> &B, LLVMContext &C,
                            vfs::FileSystem &FS, FSDiscriminatorPass P,
                            StringRef RemapFilename) {
  std::unique_ptr<SampleProfileReader> Reader;
  if (SampleProfileReaderRawBinary::hasFormat(*B))
    Reader.reset(new SampleProfileReaderRawBinary(std::move(B), C));
  else if (SampleProfileReaderExtBinary::hasFormat(*B))
    Reader.reset(new SampleProfileReaderExtBinary(std::move(B), C));
  else if (SampleProfileReaderGCC::hasFormat(*B))
    Reader.reset(new SampleProfileReaderGCC(std::move(B), C));
  else if (SampleProfileReaderText::hasFormat(*B))
    Reader.reset(new SampleProfileReaderText(std::move(B), C));
  else
    return sampleprof_error::unrecognized_format;

  if (!RemapFilename.empty()) {
    auto ReaderOrErr = SampleProfileReaderItaniumRemapper::create(
        RemapFilename, FS, *Reader, C);
    if (std::error_code EC = ReaderOrErr.getError()) {
      std::string Msg = "Could not create remapper: " + EC.message();
      C.diagnose(DiagnosticInfoSampleProfile(RemapFilename, Msg));
      return EC;
    }
    Reader->Remapper = std::move(ReaderOrErr.get());
  }

  if (std::error_code EC = Reader->readHeader()) {
    return EC;
  }

  Reader->setDiscriminatorMaskedBitFrom(P);

  return std::move(Reader);
}

// For text and GCC file formats, we compute the summary after reading the
// profile. Binary format has the profile summary in its header.
void SampleProfileReader::computeSummary() {
  SampleProfileSummaryBuilder Builder(ProfileSummaryBuilder::DefaultCutoffs);
  Summary = Builder.computeSummaryForProfiles(Profiles);
}
