//===- DXContainerEmitter.cpp - Convert YAML to a DXContainer -------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// Binary emitter for yaml to DXContainer binary
///
//===----------------------------------------------------------------------===//

#include "llvm/ADT/Sequence.h"
#include "llvm/BinaryFormat/DXContainer.h"
#include "llvm/MC/DXContainerInfo.h"
#include "llvm/MC/DXContainerPSVInfo.h"
#include "llvm/MC/DXContainerRootSignature.h"
#include "llvm/ObjectYAML/DXContainerYAML.h"
#include "llvm/ObjectYAML/yaml2obj.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;

namespace {
class DXContainerWriter {
public:
  DXContainerWriter(DXContainerYAML::Object &ObjectFile)
      : ObjectFile(ObjectFile) {}

  Error write(raw_ostream &OS);

private:
  DXContainerYAML::Object &ObjectFile;

  Error computePartOffsets();
  Error validatePartOffsets();
  Error validateSize(uint32_t Computed);

  void writeHeader(raw_ostream &OS);
  Error writeParts(raw_ostream &OS);
};
} // namespace

Error DXContainerWriter::validateSize(uint32_t Computed) {
  if (!ObjectFile.Header.FileSize)
    ObjectFile.Header.FileSize = Computed;
  else if (*ObjectFile.Header.FileSize < Computed)
    return createStringError(errc::result_out_of_range,
                             "File size specified is too small.");
  return Error::success();
}

Error DXContainerWriter::validatePartOffsets() {
  if (ObjectFile.Parts.size() != ObjectFile.Header.PartOffsets->size())
    return createStringError(
        errc::invalid_argument,
        "Mismatch between number of parts and part offsets.");
  uint32_t RollingOffset =
      sizeof(dxbc::Header) + (ObjectFile.Header.PartCount * sizeof(uint32_t));
  for (auto I : llvm::zip(ObjectFile.Parts, *ObjectFile.Header.PartOffsets)) {
    if (RollingOffset > std::get<1>(I))
      return createStringError(errc::invalid_argument,
                               "Offset mismatch, not enough space for data.");
    RollingOffset =
        std::get<1>(I) + sizeof(dxbc::PartHeader) + std::get<0>(I).Size;
  }
  if (Error Err = validateSize(RollingOffset))
    return Err;

  return Error::success();
}

Error DXContainerWriter::computePartOffsets() {
  if (ObjectFile.Header.PartOffsets)
    return validatePartOffsets();
  uint32_t RollingOffset =
      sizeof(dxbc::Header) + (ObjectFile.Header.PartCount * sizeof(uint32_t));
  ObjectFile.Header.PartOffsets = std::vector<uint32_t>();
  for (const auto &Part : ObjectFile.Parts) {
    ObjectFile.Header.PartOffsets->push_back(RollingOffset);
    RollingOffset += sizeof(dxbc::PartHeader) + Part.Size;
  }
  if (Error Err = validateSize(RollingOffset))
    return Err;

  return Error::success();
}

void DXContainerWriter::writeHeader(raw_ostream &OS) {
  dxbc::Header Header;
  memcpy(Header.Magic, "DXBC", 4);
  memcpy(Header.FileHash.Digest, ObjectFile.Header.Hash.data(), 16);
  Header.Version.Major = ObjectFile.Header.Version.Major;
  Header.Version.Minor = ObjectFile.Header.Version.Minor;
  Header.FileSize = *ObjectFile.Header.FileSize;
  Header.PartCount = ObjectFile.Parts.size();
  if (sys::IsBigEndianHost)
    Header.swapBytes();
  OS.write(reinterpret_cast<char *>(&Header), sizeof(Header));
  SmallVector<uint32_t> Offsets(ObjectFile.Header.PartOffsets->begin(),
                                ObjectFile.Header.PartOffsets->end());
  if (sys::IsBigEndianHost)
    for (auto &O : Offsets)
      sys::swapByteOrder(O);
  OS.write(reinterpret_cast<char *>(Offsets.data()),
           Offsets.size() * sizeof(uint32_t));
}

// TODO use it for VERS too
template <typename T>
static void assign_if(T &Dst, const std::optional<T> &Src) {
  if (Src)
    Dst = *Src;
}

static void
assignSectionHeader(dxbc::SourceInfo::SectionHeader &Dst,
                    const DXContainerYAML::SourceInfo::Section &Src) {
  assign_if(Dst.AlignedSizeInBytes, Src.GenericHeader.AlignedSizeInBytes);
  assign_if(Dst.Flags, Src.GenericHeader.Flags);
  assign_if(Dst.Type, Src.GenericHeader.Type);
}

Error DXContainerWriter::writeParts(raw_ostream &OS) {
  uint32_t RollingOffset =
      sizeof(dxbc::Header) + (ObjectFile.Header.PartCount * sizeof(uint32_t));
  for (auto I : llvm::zip(ObjectFile.Parts, *ObjectFile.Header.PartOffsets)) {
    if (RollingOffset < std::get<1>(I)) {
      uint32_t PadBytes = std::get<1>(I) - RollingOffset;
      OS.write_zeros(PadBytes);
    }
    DXContainerYAML::Part P = std::get<0>(I);
    RollingOffset = std::get<1>(I) + sizeof(dxbc::PartHeader);
    uint32_t PartSize = P.Size;

    OS.write(P.Name.c_str(), 4);
    if (sys::IsBigEndianHost)
      sys::swapByteOrder(P.Size);
    OS.write(reinterpret_cast<const char *>(&P.Size), sizeof(uint32_t));

    dxbc::PartType PT = dxbc::parsePartType(P.Name);

    uint64_t DataStart = OS.tell();
    switch (PT) {
    case dxbc::PartType::DXIL:
    case dxbc::PartType::ILDB: {
      if (!P.Program)
        continue;
      dxbc::ProgramHeader Header;
      Header.Version = dxbc::ProgramHeader::getVersion(P.Program->MajorVersion,
                                                       P.Program->MinorVersion);
      Header.Unused = 0;
      Header.ShaderKind = P.Program->ShaderKind;
      memcpy(Header.Bitcode.Magic, "DXIL", 4);
      Header.Bitcode.MajorVersion = P.Program->DXILMajorVersion;
      Header.Bitcode.MinorVersion = P.Program->DXILMinorVersion;
      Header.Bitcode.Unused = 0;

      // Compute the optional fields if needed...
      if (P.Program->DXILOffset)
        Header.Bitcode.Offset = *P.Program->DXILOffset;
      else
        Header.Bitcode.Offset = sizeof(dxbc::BitcodeHeader);

      if (P.Program->DXILSize)
        Header.Bitcode.Size = *P.Program->DXILSize;
      else
        Header.Bitcode.Size = P.Program->DXIL ? P.Program->DXIL->size() : 0;

      if (P.Program->Size)
        Header.Size = *P.Program->Size;
      else
        Header.Size = sizeof(dxbc::ProgramHeader) + Header.Bitcode.Size;

      uint32_t BitcodeOffset = Header.Bitcode.Offset;
      if (sys::IsBigEndianHost)
        Header.swapBytes();
      OS.write(reinterpret_cast<const char *>(&Header),
               sizeof(dxbc::ProgramHeader));
      if (P.Program->DXIL) {
        if (BitcodeOffset > sizeof(dxbc::BitcodeHeader)) {
          uint32_t PadBytes = BitcodeOffset - sizeof(dxbc::BitcodeHeader);
          OS.write_zeros(PadBytes);
        }
        OS.write(reinterpret_cast<char *>(P.Program->DXIL->data()),
                 P.Program->DXIL->size());
      }
      break;
    }
    case dxbc::PartType::ILDN: {
      if (!P.DebugName)
        continue;

      mcdxbc::DebugName DebugName;
      DebugName.setFilename(P.DebugName->Filename);
      // Override default flags with value from YAML.
      if (P.DebugName->Flags)
        DebugName.Parameters.Flags = *P.DebugName->Flags;
      // Override computed filename length with value from YAML.
      if (P.DebugName->NameLength)
        DebugName.Parameters.NameLength = *P.DebugName->NameLength;
      DebugName.write(OS);
      break;
    }
    case dxbc::PartType::PRIV: {
      if (!P.PrivateData)
        continue;
      OS.write(reinterpret_cast<char *>(P.PrivateData->data()),
               P.PrivateData->size());
      break;
    }
    case dxbc::PartType::SFI0: {
      // If we don't have any flags we can continue here and the data will be
      // zeroed out.
      if (!P.Flags.has_value())
        continue;
      uint64_t Flags = P.Flags->getEncodedFlags();
      if (sys::IsBigEndianHost)
        sys::swapByteOrder(Flags);
      OS.write(reinterpret_cast<char *>(&Flags), sizeof(uint64_t));
      break;
    }
    case dxbc::PartType::HASH: {
      if (!P.Hash.has_value())
        continue;
      dxbc::ShaderHash Hash = {0, {0}};
      if (P.Hash->IncludesSource)
        Hash.Flags |= static_cast<uint32_t>(dxbc::HashFlags::IncludesSource);
      memcpy(&Hash.Digest[0], &P.Hash->Digest[0], 16);
      if (sys::IsBigEndianHost)
        Hash.swapBytes();
      OS.write(reinterpret_cast<char *>(&Hash), sizeof(dxbc::ShaderHash));
      break;
    }
    case dxbc::PartType::PSV0: {
      if (!P.Info.has_value())
        continue;
      mcdxbc::PSVRuntimeInfo PSV;
      memcpy(&PSV.BaseData, &P.Info->Info, sizeof(dxbc::PSV::v3::RuntimeInfo));
      PSV.Resources = P.Info->Resources;
      PSV.EntryName = P.Info->EntryName;

      for (auto El : P.Info->SigInputElements)
        PSV.InputElements.push_back(mcdxbc::PSVSignatureElement{
            El.Name, El.Indices, El.StartRow, El.Cols, El.StartCol,
            El.Allocated, El.Kind, El.Type, El.Mode, El.DynamicMask,
            El.Stream});

      for (auto El : P.Info->SigOutputElements)
        PSV.OutputElements.push_back(mcdxbc::PSVSignatureElement{
            El.Name, El.Indices, El.StartRow, El.Cols, El.StartCol,
            El.Allocated, El.Kind, El.Type, El.Mode, El.DynamicMask,
            El.Stream});

      for (auto El : P.Info->SigPatchOrPrimElements)
        PSV.PatchOrPrimElements.push_back(mcdxbc::PSVSignatureElement{
            El.Name, El.Indices, El.StartRow, El.Cols, El.StartCol,
            El.Allocated, El.Kind, El.Type, El.Mode, El.DynamicMask,
            El.Stream});

      static_assert(PSV.OutputVectorMasks.size() == PSV.InputOutputMap.size());
      for (unsigned I = 0; I < PSV.OutputVectorMasks.size(); ++I) {
        PSV.OutputVectorMasks[I].insert(PSV.OutputVectorMasks[I].begin(),
                                        P.Info->OutputVectorMasks[I].begin(),
                                        P.Info->OutputVectorMasks[I].end());
        PSV.InputOutputMap[I].insert(PSV.InputOutputMap[I].begin(),
                                     P.Info->InputOutputMap[I].begin(),
                                     P.Info->InputOutputMap[I].end());
      }

      PSV.PatchOrPrimMasks.insert(PSV.PatchOrPrimMasks.begin(),
                                  P.Info->PatchOrPrimMasks.begin(),
                                  P.Info->PatchOrPrimMasks.end());
      PSV.InputPatchMap.insert(PSV.InputPatchMap.begin(),
                               P.Info->InputPatchMap.begin(),
                               P.Info->InputPatchMap.end());
      PSV.PatchOutputMap.insert(PSV.PatchOutputMap.begin(),
                                P.Info->PatchOutputMap.begin(),
                                P.Info->PatchOutputMap.end());

      PSV.finalize(static_cast<Triple::EnvironmentType>(
                       Triple::Pixel + P.Info->Info.ShaderStage),
                   P.Info->Version);
      PSV.write(OS, P.Info->Version);
      break;
    }
    case dxbc::PartType::ISG1:
    case dxbc::PartType::OSG1:
    case dxbc::PartType::PSG1: {
      mcdxbc::Signature Sig;
      if (P.Signature.has_value()) {
        for (const auto &Param : P.Signature->Parameters) {
          Sig.addParam(Param.Stream, Param.Name, Param.Index, Param.SystemValue,
                       Param.CompType, Param.Register, Param.Mask,
                       Param.ExclusiveMask, Param.MinPrecision);
        }
      }
      Sig.write(OS);
      break;
    }
    case dxbc::PartType::Unknown:
      break; // Skip any handling for unrecognized parts.
    case dxbc::PartType::RTS0: {
      if (!P.RootSignature.has_value())
        continue;

      mcdxbc::RootSignatureDesc RS;
      RS.Flags = P.RootSignature->getEncodedFlags();
      RS.Version = P.RootSignature->Version;
      RS.NumStaticSamplers = P.RootSignature->NumStaticSamplers;

      for (DXContainerYAML::RootParameterLocationYaml &L :
           P.RootSignature->Parameters.Locations) {

        const dxbc::RootParameterType Type = L.Header.Type;
        const dxbc::ShaderVisibility Visibility = L.Header.Visibility;

        switch (Type) {
        case dxbc::RootParameterType::Constants32Bit: {
          const DXContainerYAML::RootConstantsYaml &ConstantYaml =
              P.RootSignature->Parameters.getOrInsertConstants(L);
          mcdxbc::RootConstants Constants;

          Constants.Num32BitValues = ConstantYaml.Num32BitValues;
          Constants.RegisterSpace = ConstantYaml.RegisterSpace;
          Constants.ShaderRegister = ConstantYaml.ShaderRegister;
          RS.ParametersContainer.addParameter(Type, Visibility, Constants);
          break;
        }
        case dxbc::RootParameterType::CBV:
        case dxbc::RootParameterType::SRV:
        case dxbc::RootParameterType::UAV: {
          const DXContainerYAML::RootDescriptorYaml &DescriptorYaml =
              P.RootSignature->Parameters.getOrInsertDescriptor(L);

          mcdxbc::RootDescriptor Descriptor;
          Descriptor.RegisterSpace = DescriptorYaml.RegisterSpace;
          Descriptor.ShaderRegister = DescriptorYaml.ShaderRegister;
          if (RS.Version > 1)
            Descriptor.Flags = DescriptorYaml.getEncodedFlags();
          RS.ParametersContainer.addParameter(Type, Visibility, Descriptor);
          break;
        }
        case dxbc::RootParameterType::DescriptorTable: {
          const DXContainerYAML::DescriptorTableYaml &TableYaml =
              P.RootSignature->Parameters.getOrInsertTable(L);
          mcdxbc::DescriptorTable Table;
          for (const auto &R : TableYaml.Ranges) {
            mcdxbc::DescriptorRange Range;
            Range.RangeType = R.RangeType;
            Range.NumDescriptors = R.NumDescriptors;
            Range.BaseShaderRegister = R.BaseShaderRegister;
            Range.RegisterSpace = R.RegisterSpace;
            Range.OffsetInDescriptorsFromTableStart =
                R.OffsetInDescriptorsFromTableStart;

            if (RS.Version > 1)
              Range.Flags = R.getEncodedFlags();

            Table.Ranges.push_back(Range);
          }
          RS.ParametersContainer.addParameter(Type, Visibility, Table);
          break;
        }
        }
      }

      for (const auto &Param : P.RootSignature->samplers()) {
        mcdxbc::StaticSampler NewSampler;
        NewSampler.Filter = Param.Filter;
        NewSampler.AddressU = Param.AddressU;
        NewSampler.AddressV = Param.AddressV;
        NewSampler.AddressW = Param.AddressW;
        NewSampler.MipLODBias = Param.MipLODBias;
        NewSampler.MaxAnisotropy = Param.MaxAnisotropy;
        NewSampler.ComparisonFunc = Param.ComparisonFunc;
        NewSampler.BorderColor = Param.BorderColor;
        NewSampler.MinLOD = Param.MinLOD;
        NewSampler.MaxLOD = Param.MaxLOD;
        NewSampler.ShaderRegister = Param.ShaderRegister;
        NewSampler.RegisterSpace = Param.RegisterSpace;
        NewSampler.ShaderVisibility = Param.ShaderVisibility;

        if (RS.Version > 2)
          NewSampler.Flags = Param.getEncodedFlags();

        RS.StaticSamplers.push_back(NewSampler);
      }

      // Handling of offsets
      RS.RootParameterOffset = RS.computeRootParametersOffset();
      if (P.RootSignature->RootParametersOffset &&
          P.RootSignature->RootParametersOffset.value() !=
              RS.RootParameterOffset) {
        return createStringError(
            errc::invalid_argument,
            "Specified RootParametersOffset does not match required value: %d.",
            RS.RootParameterOffset);
      }

      RS.StaticSamplersOffset = RS.computeStaticSamplersOffset();
      if (P.RootSignature->StaticSamplersOffset &&
          P.RootSignature->StaticSamplersOffset.value() !=
              RS.StaticSamplersOffset) {
        return createStringError(
            errc::invalid_argument,
            "Specified StaticSamplersOffset does not match computed value: %d.",
            RS.StaticSamplersOffset);
      }

      RS.write(OS);
      break;
    }
    case dxbc::PartType::SRCI: {
      if (!P.SourceInfo.has_value())
        continue;
      mcdxbc::SourceInfoBuilder SourceInfo;
      auto &ContentsYAML = P.SourceInfo->Contents;
      SourceInfo.setCompressionType(ContentsYAML.Parameters.Type);

      if (ContentsYAML.Entries.size() != P.SourceInfo->Names.Entries.size())
        return createStringError(
            errc::invalid_argument,
            "number of entries in Names section must match number of entries "
            "in Contents section in SRCI part");

      for (size_t I : llvm::seq(ContentsYAML.Entries.size()))
        SourceInfo.addFile(P.SourceInfo->Names.Entries[I].FileName,
                           ContentsYAML.Entries[I].FileContent);
      for (auto &ArgEntry : P.SourceInfo->Args.Args)
        SourceInfo.addArg(ArgEntry.first, ArgEntry.second);

      SourceInfo.computeEntries();

      // If entries field values are provided in YAML, override them in
      // SourceInfo.
      for (size_t I : llvm::seq(ContentsYAML.Entries.size())) {
        auto &ContentEntryYAML = ContentsYAML.Entries[I];
        auto &ContentEntry = SourceInfo.BaseData.Contents.Entries[I];
        assign_if(ContentEntry.Parameters.AlignedSizeInBytes,
                  ContentEntryYAML.AlignedSizeInBytes);
        assign_if(ContentEntry.Parameters.Flags, ContentEntryYAML.Flags);
        assign_if(ContentEntry.Parameters.ContentSizeInBytes,
                  ContentEntryYAML.ContentSizeInBytes);

        auto &NameEntryYAML = P.SourceInfo->Names.Entries[I];
        auto &NameEntry = SourceInfo.BaseData.Names.Entries[I];
        assign_if(NameEntry.Parameters.AlignedSizeInBytes,
                  NameEntryYAML.AlignedSizeInBytes);
        assign_if(NameEntry.Parameters.Flags, NameEntryYAML.Flags);
        assign_if(NameEntry.Parameters.NameSizeInBytes,
                  NameEntryYAML.NameSizeInBytes);
        assign_if(NameEntry.Parameters.ContentSizeInBytes,
                  NameEntryYAML.ContentSizeInBytes);
      }

      SourceInfo.finalize();

      // If section header field values are provided in YAML, override them in
      // SourceInfo.
      auto &Contents = SourceInfo.BaseData.Contents;
      assignSectionHeader(Contents.GenericHeader, ContentsYAML);
      assign_if(Contents.Parameters.AlignedSizeInBytes,
                ContentsYAML.Parameters.AlignedSizeInBytes);
      assign_if(Contents.Parameters.Flags, ContentsYAML.Parameters.Flags);
      assign_if(Contents.Parameters.EntriesSizeInBytes,
                ContentsYAML.Parameters.EntriesSizeInBytes);
      assign_if(Contents.Parameters.UncompressedEntriesSizeInBytes,
                ContentsYAML.Parameters.UncompressedEntriesSizeInBytes);
      if (ContentsYAML.Parameters.Count &&
          ContentsYAML.Parameters.Count != Contents.Parameters.Count)
        return createStringError(
            errc::invalid_argument,
            "the value of Count field in Contents header must match the number "
            "of entries in Contents section");

      auto &NamesYAML = P.SourceInfo->Names;
      auto &Names = SourceInfo.BaseData.Names;
      assignSectionHeader(Names.GenericHeader, NamesYAML);
      assign_if(Names.Parameters.Flags, NamesYAML.Parameters.Flags);
      assign_if(Names.Parameters.EntriesSizeInBytes,
                NamesYAML.Parameters.EntriesSizeInBytes);
      if (NamesYAML.Parameters.Count &&
          NamesYAML.Parameters.Count != Names.Parameters.Count)
        return createStringError(
            errc::invalid_argument,
            "the value of Count field in Names header must match the number of "
            "entries in Names section");

      auto &ArgsYAML = P.SourceInfo->Args;
      auto &Args = SourceInfo.BaseData.Args;
      assignSectionHeader(Args.GenericHeader, ArgsYAML);
      assign_if(Args.Parameters.Flags, ArgsYAML.Parameters.Flags);
      assign_if(Args.Parameters.SizeInBytes, ArgsYAML.Parameters.SizeInBytes);
      if (ArgsYAML.Parameters.Count &&
          ArgsYAML.Parameters.Count != Args.Parameters.Count)
        return createStringError(errc::invalid_argument,
                                 "the value of Count field in Args header must "
                                 "match the number of entries in Args section");

      assign_if(SourceInfo.BaseData.Parameters.AlignedSizeInBytes,
                P.SourceInfo->Parameters.AlignedSizeInBytes);
      assign_if(SourceInfo.BaseData.Parameters.Flags,
                P.SourceInfo->Parameters.Flags);
      assign_if(SourceInfo.BaseData.Parameters.SectionCount,
                P.SourceInfo->Parameters.SectionCount);

      SourceInfo.write(OS);
      break;
    }
    case dxbc::PartType::VERS: {
      if (!P.CompilerVersion)
        continue;

      mcdxbc::CompilerVersion CompilerVersion;
      CompilerVersion.Parameters.Major =
          P.CompilerVersion->Major.value_or(CompilerVersion.Parameters.Major);
      CompilerVersion.Parameters.Minor =
          P.CompilerVersion->Minor.value_or(CompilerVersion.Parameters.Minor);

      if (P.CompilerVersion->IsDebugBuild || P.CompilerVersion->IsValidated)
        CompilerVersion.Parameters.Flags = dxbc::CompilerVersionFlags::Default;
      if (P.CompilerVersion->IsDebugBuild.value_or(false))
        CompilerVersion.Parameters.Flags |= dxbc::CompilerVersionFlags::Debug;
      if (P.CompilerVersion->IsValidated.value_or(false))
        CompilerVersion.Parameters.Flags |=
            dxbc::CompilerVersionFlags::Internal;

      CompilerVersion.Parameters.CommitCount =
          P.CompilerVersion->CommitCount.value_or(
              CompilerVersion.Parameters.CommitCount);

      if (P.CompilerVersion->CommitSha)
        CompilerVersion.setCommitSha(*P.CompilerVersion->CommitSha);
      if (P.CompilerVersion->CustomVersionString)
        CompilerVersion.setVersionString(
            *P.CompilerVersion->CustomVersionString);

      CompilerVersion.Parameters.ContentSizeInBytes =
          P.CompilerVersion->ContentSizeInBytes.value_or(
              CompilerVersion.Parameters.ContentSizeInBytes);

      CompilerVersion.write(OS);
      break;
    }
    }
    uint64_t BytesWritten = OS.tell() - DataStart;
    RollingOffset += BytesWritten;
    if (BytesWritten < PartSize)
      OS.write_zeros(PartSize - BytesWritten);
    RollingOffset += PartSize;
  }

  return Error::success();
}

Error DXContainerWriter::write(raw_ostream &OS) {
  if (Error Err = computePartOffsets())
    return Err;
  writeHeader(OS);
  return writeParts(OS);
}

namespace llvm {
namespace yaml {

bool yaml2dxcontainer(DXContainerYAML::Object &Doc, raw_ostream &Out,
                      ErrorHandler EH) {
  DXContainerWriter Writer(Doc);
  if (Error Err = Writer.write(Out)) {
    handleAllErrors(std::move(Err),
                    [&](const ErrorInfoBase &Err) { EH(Err.message()); });
    return false;
  }
  return true;
}

} // namespace yaml
} // namespace llvm
