//===- MIRParser.cpp - MIR serialization format parser implementation -----===//
//
// 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 parses the optional LLVM IR and machine
// functions that are stored in MIR files.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/MIRParser/MIRParser.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/AsmParser/Parser.h"
#include "llvm/AsmParser/SlotMapping.h"
#include "llvm/CodeGen/MIRParser/MIParser.h"
#include "llvm/CodeGen/MIRYamlMapping.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionAnalysis.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/TargetFrameLowering.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/ValueSymbolTable.h"
#include "llvm/Support/LineIterator.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SMLoc.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/YAMLTraits.h"
#include "llvm/Target/TargetMachine.h"
#include <memory>

using namespace llvm;

namespace llvm {
class MDNode;
class RegisterBank;

/// This class implements the parsing of LLVM IR that's embedded inside a MIR
/// file.
class MIRParserImpl {
  SourceMgr SM;
  LLVMContext &Context;
  yaml::Input In;
  StringRef Filename;
  SlotMapping IRSlots;
  std::unique_ptr<PerTargetMIParsingState> Target;

  /// True when the MIR file doesn't have LLVM IR. Dummy IR functions are
  /// created and inserted into the given module when this is true.
  bool NoLLVMIR = false;
  /// True when a well formed MIR file does not contain any MIR/machine function
  /// parts.
  bool NoMIRDocuments = false;

  std::function<void(Function &)> ProcessIRFunction;

public:
  MIRParserImpl(std::unique_ptr<MemoryBuffer> Contents, StringRef Filename,
                LLVMContext &Context,
                std::function<void(Function &)> ProcessIRFunction);

  void reportDiagnostic(const SMDiagnostic &Diag);

  /// Report an error with the given message at unknown location.
  ///
  /// Always returns true.
  bool error(const Twine &Message);

  /// Report an error with the given message at the given location.
  ///
  /// Always returns true.
  bool error(SMLoc Loc, const Twine &Message);

  /// Report a given error with the location translated from the location in an
  /// embedded string literal to a location in the MIR file.
  ///
  /// Always returns true.
  bool error(const SMDiagnostic &Error, SMRange SourceRange);

  /// Try to parse the optional LLVM module and the machine functions in the MIR
  /// file.
  ///
  /// Return null if an error occurred.
  std::unique_ptr<Module>
  parseIRModule(DataLayoutCallbackTy DataLayoutCallback);

  /// Create an empty function with the given name.
  Function *createDummyFunction(StringRef Name, Module &M);

  bool parseMachineFunctions(Module &M, MachineModuleInfo &MMI,
                             ModuleAnalysisManager *FAM = nullptr);

  /// Parse the machine function in the current YAML document.
  ///
  ///
  /// Return true if an error occurred.
  bool parseMachineFunction(Module &M, MachineModuleInfo &MMI,
                            ModuleAnalysisManager *FAM,
                            Module::iterator &FirstUnvisitedFunction);

  /// Initialize the machine function to the state that's described in the MIR
  /// file.
  ///
  /// Return true if error occurred.
  bool initializeMachineFunction(const yaml::MachineFunction &YamlMF,
                                 MachineFunction &MF);

  bool initializeCallSiteInfo(PerFunctionMIParsingState &PFS,
                              const yaml::MachineFunction &YamlMF);

  bool initializePrefetchTargets(PerFunctionMIParsingState &PFS,
                                 const yaml::MachineFunction &YamlMF);

  bool parseRegisterInfo(PerFunctionMIParsingState &PFS,
                         const yaml::MachineFunction &YamlMF);

  bool setupRegisterInfo(const PerFunctionMIParsingState &PFS,
                         const yaml::MachineFunction &YamlMF);

  bool initializeFrameInfo(PerFunctionMIParsingState &PFS,
                           const yaml::MachineFunction &YamlMF);

  bool initializeSaveRestorePoints(
      PerFunctionMIParsingState &PFS,
      const std::vector<yaml::SaveRestorePointEntry> &YamlSRPoints,
      llvm::SaveRestorePoints &SaveRestorePoints);

  bool parseCalleeSavedRegister(PerFunctionMIParsingState &PFS,
                                std::vector<CalleeSavedInfo> &CSIInfo,
                                const yaml::StringValue &RegisterSource,
                                bool IsRestored, int FrameIdx);

  struct VarExprLoc {
    DILocalVariable *DIVar = nullptr;
    DIExpression *DIExpr = nullptr;
    DILocation *DILoc = nullptr;
  };

  std::optional<VarExprLoc> parseVarExprLoc(PerFunctionMIParsingState &PFS,
                                            const yaml::StringValue &VarStr,
                                            const yaml::StringValue &ExprStr,
                                            const yaml::StringValue &LocStr);
  template <typename T>
  bool parseStackObjectsDebugInfo(PerFunctionMIParsingState &PFS,
                                  const T &Object,
                                  int FrameIdx);

  bool initializeConstantPool(PerFunctionMIParsingState &PFS,
                              MachineConstantPool &ConstantPool,
                              const yaml::MachineFunction &YamlMF);

  bool initializeJumpTableInfo(PerFunctionMIParsingState &PFS,
                               const yaml::MachineJumpTable &YamlJTI);

  bool parseMachineMetadataNodes(PerFunctionMIParsingState &PFS,
                                 MachineFunction &MF,
                                 const yaml::MachineFunction &YMF);

  bool parseCalledGlobals(PerFunctionMIParsingState &PFS, MachineFunction &MF,
                          const yaml::MachineFunction &YMF);

private:
  bool parseMDNode(PerFunctionMIParsingState &PFS, MDNode *&Node,
                   const yaml::StringValue &Source);

  bool parseMBBReference(PerFunctionMIParsingState &PFS,
                         MachineBasicBlock *&MBB,
                         const yaml::StringValue &Source);

  /// Return a MIR diagnostic converted from an MI string diagnostic.
  SMDiagnostic diagFromMIStringDiag(const SMDiagnostic &Error,
                                    SMRange SourceRange);

  /// Return a MIR diagnostic converted from a diagnostic located in a YAML
  /// block scalar string.
  SMDiagnostic diagFromBlockStringDiag(const SMDiagnostic &Error,
                                       SMRange SourceRange);

  bool computeFunctionProperties(MachineFunction &MF,
                                 const yaml::MachineFunction &YamlMF);

  void setupDebugValueTracking(MachineFunction &MF,
    PerFunctionMIParsingState &PFS, const yaml::MachineFunction &YamlMF);

  bool parseMachineInst(PerFunctionMIParsingState &PFS,
                        const yaml::MachineInstrLoc &MILoc,
                        MachineInstr const *&MI);
};

} // end namespace llvm

static void handleYAMLDiag(const SMDiagnostic &Diag, void *Context) {
  reinterpret_cast<MIRParserImpl *>(Context)->reportDiagnostic(Diag);
}

MIRParserImpl::MIRParserImpl(std::unique_ptr<MemoryBuffer> Contents,
                             StringRef Filename, LLVMContext &Context,
                             std::function<void(Function &)> Callback)
    : Context(Context),
      In(SM.getMemoryBuffer(SM.AddNewSourceBuffer(std::move(Contents), SMLoc()))
             ->getBuffer(),
         nullptr, handleYAMLDiag, this),
      Filename(Filename), ProcessIRFunction(Callback) {
  In.setContext(&In);
}

bool MIRParserImpl::error(const Twine &Message) {
  Context.diagnose(DiagnosticInfoMIRParser(
      DS_Error, SMDiagnostic(Filename, SourceMgr::DK_Error, Message.str())));
  return true;
}

bool MIRParserImpl::error(SMLoc Loc, const Twine &Message) {
  Context.diagnose(DiagnosticInfoMIRParser(
      DS_Error, SM.GetMessage(Loc, SourceMgr::DK_Error, Message)));
  return true;
}

bool MIRParserImpl::error(const SMDiagnostic &Error, SMRange SourceRange) {
  assert(Error.getKind() == SourceMgr::DK_Error && "Expected an error");
  reportDiagnostic(diagFromMIStringDiag(Error, SourceRange));
  return true;
}

void MIRParserImpl::reportDiagnostic(const SMDiagnostic &Diag) {
  DiagnosticSeverity Kind;
  switch (Diag.getKind()) {
  case SourceMgr::DK_Error:
    Kind = DS_Error;
    break;
  case SourceMgr::DK_Warning:
    Kind = DS_Warning;
    break;
  case SourceMgr::DK_Note:
    Kind = DS_Note;
    break;
  case SourceMgr::DK_Remark:
    llvm_unreachable("remark unexpected");
    break;
  }
  Context.diagnose(DiagnosticInfoMIRParser(Kind, Diag));
}

std::unique_ptr<Module>
MIRParserImpl::parseIRModule(DataLayoutCallbackTy DataLayoutCallback) {
  if (!In.setCurrentDocument()) {
    if (In.error())
      return nullptr;
    // Create an empty module when the MIR file is empty.
    NoMIRDocuments = true;
    auto M = std::make_unique<Module>(Filename, Context);
    if (auto LayoutOverride = DataLayoutCallback(M->getTargetTriple().str(),
                                                 M->getDataLayoutStr()))
      M->setDataLayout(*LayoutOverride);
    return M;
  }

  std::unique_ptr<Module> M;
  // Parse the block scalar manually so that we can return unique pointer
  // without having to go trough YAML traits.
  if (const auto *BSN =
          dyn_cast_or_null<yaml::BlockScalarNode>(In.getCurrentNode())) {
    SMDiagnostic Error;
    M = parseAssembly(MemoryBufferRef(BSN->getValue(), Filename), Error,
                      Context, &IRSlots, DataLayoutCallback);
    if (!M) {
      reportDiagnostic(diagFromBlockStringDiag(Error, BSN->getSourceRange()));
      return nullptr;
    }
    In.nextDocument();
    if (!In.setCurrentDocument())
      NoMIRDocuments = true;
  } else {
    // Create an new, empty module.
    M = std::make_unique<Module>(Filename, Context);
    if (auto LayoutOverride = DataLayoutCallback(M->getTargetTriple().str(),
                                                 M->getDataLayoutStr()))
      M->setDataLayout(*LayoutOverride);
    NoLLVMIR = true;
  }
  return M;
}

bool MIRParserImpl::parseMachineFunctions(Module &M, MachineModuleInfo &MMI,
                                          ModuleAnalysisManager *MAM) {
  if (NoMIRDocuments)
    return false;

  // Parse the machine functions.
  auto FirstUnvisitedFunction = M.begin();
  do {
    if (parseMachineFunction(M, MMI, MAM, FirstUnvisitedFunction))
      return true;
    In.nextDocument();
  } while (In.setCurrentDocument());

  return false;
}

Function *MIRParserImpl::createDummyFunction(StringRef Name, Module &M) {
  auto &Context = M.getContext();
  Function *F =
      Function::Create(FunctionType::get(Type::getVoidTy(Context), false),
                       Function::ExternalLinkage, Name, M);
  BasicBlock *BB = BasicBlock::Create(Context, "entry", F);
  new UnreachableInst(Context, BB);

  if (ProcessIRFunction)
    ProcessIRFunction(*F);

  return F;
}

static Function *
getNextUnusedUnnamedFunction(const Module &M,
                             Module::iterator &FirstUnvisitedFunction) {
  for (; FirstUnvisitedFunction != M.end(); ++FirstUnvisitedFunction)
    if (!FirstUnvisitedFunction->hasName())
      return &*FirstUnvisitedFunction++;

  return nullptr;
}

bool MIRParserImpl::parseMachineFunction(
    Module &M, MachineModuleInfo &MMI, ModuleAnalysisManager *MAM,
    Module::iterator &FirstUnvisitedFunction) {
  // Parse the yaml.
  yaml::MachineFunction YamlMF;
  yaml::EmptyContext Ctx;

  const TargetMachine &TM = MMI.getTarget();
  YamlMF.MachineFuncInfo = std::unique_ptr<yaml::MachineFunctionInfo>(
      TM.createDefaultFuncInfoYAML());

  yaml::yamlize(In, YamlMF, false, Ctx);
  if (In.error())
    return true;

  // Search for the corresponding IR function.
  StringRef FunctionName = YamlMF.Name;
  Function *F = M.getFunction(FunctionName);
  if (!F) {
    if (NoLLVMIR) {
      F = createDummyFunction(FunctionName, M);
    } else if (!FunctionName.empty() ||
               !(F = getNextUnusedUnnamedFunction(M, FirstUnvisitedFunction))) {
      return error(Twine("function '") + FunctionName +
                   "' isn't defined in the provided LLVM IR");
    }
  }

  if (!MAM) {
    if (MMI.getMachineFunction(*F) != nullptr)
      return error(Twine("redefinition of machine function '") + FunctionName +
                   "'");

    // Create the MachineFunction.
    MachineFunction &MF = MMI.getOrCreateMachineFunction(*F);
    if (initializeMachineFunction(YamlMF, MF))
      return true;
  } else {
    auto &FAM =
        MAM->getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
    if (FAM.getCachedResult<MachineFunctionAnalysis>(*F))
      return error(Twine("redefinition of machine function '") + FunctionName +
                   "'");

    // Create the MachineFunction.
    MachineFunction &MF = FAM.getResult<MachineFunctionAnalysis>(*F).getMF();
    if (initializeMachineFunction(YamlMF, MF))
      return true;
  }

  return false;
}

static bool isSSA(const MachineFunction &MF) {
  const MachineRegisterInfo &MRI = MF.getRegInfo();
  for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
    Register Reg = Register::index2VirtReg(I);
    if (!MRI.hasOneDef(Reg) && !MRI.def_empty(Reg))
      return false;

    // Subregister defs are invalid in SSA.
    const MachineOperand *RegDef = MRI.getOneDef(Reg);
    if (RegDef && RegDef->getSubReg() != 0)
      return false;
  }
  return true;
}

bool MIRParserImpl::computeFunctionProperties(
    MachineFunction &MF, const yaml::MachineFunction &YamlMF) {
  MachineFunctionProperties &Properties = MF.getProperties();

  bool HasPHI = false;
  bool HasInlineAsm = false;
  bool HasFakeUses = false;
  bool AllTiedOpsRewritten = true, HasTiedOps = false;
  for (const MachineBasicBlock &MBB : MF) {
    for (const MachineInstr &MI : MBB) {
      if (MI.isPHI())
        HasPHI = true;
      if (MI.isInlineAsm())
        HasInlineAsm = true;
      if (MI.isFakeUse())
        HasFakeUses = true;
      for (unsigned I = 0; I < MI.getNumOperands(); ++I) {
        const MachineOperand &MO = MI.getOperand(I);
        if (!MO.isReg() || !MO.getReg())
          continue;
        unsigned DefIdx;
        if (MO.isUse() && MI.isRegTiedToDefOperand(I, &DefIdx)) {
          HasTiedOps = true;
          if (MO.getReg() != MI.getOperand(DefIdx).getReg())
            AllTiedOpsRewritten = false;
        }
      }
    }
  }

  // Helper function to sanity-check and set properties that are computed, but
  // may be explicitly set from the input MIR
  auto ComputedPropertyHelper =
      [&Properties](std::optional<bool> ExplicitProp, bool ComputedProp,
                    MachineFunctionProperties::Property P) -> bool {
    // Prefer explicitly given values over the computed properties
    if (ExplicitProp.value_or(ComputedProp))
      Properties.set(P);
    else
      Properties.reset(P);

    // Check for conflict between the explicit values and the computed ones
    return ExplicitProp && *ExplicitProp && !ComputedProp;
  };

  if (ComputedPropertyHelper(YamlMF.NoPHIs, !HasPHI,
                             MachineFunctionProperties::Property::NoPHIs)) {
    return error(MF.getName() +
                 " has explicit property NoPhi, but contains at least one PHI");
  }

  MF.setHasInlineAsm(HasInlineAsm);

  if (HasTiedOps && AllTiedOpsRewritten)
    Properties.setTiedOpsRewritten();

  if (ComputedPropertyHelper(YamlMF.IsSSA, isSSA(MF),
                             MachineFunctionProperties::Property::IsSSA)) {
    return error(MF.getName() +
                 " has explicit property IsSSA, but is not valid SSA");
  }

  const MachineRegisterInfo &MRI = MF.getRegInfo();
  if (ComputedPropertyHelper(YamlMF.NoVRegs, MRI.getNumVirtRegs() == 0,
                             MachineFunctionProperties::Property::NoVRegs)) {
    return error(
        MF.getName() +
        " has explicit property NoVRegs, but contains virtual registers");
  }

  // For hasFakeUses we follow similar logic to the ComputedPropertyHelper,
  // except for caring about the inverse case only, i.e. when the property is
  // explicitly set to false and Fake Uses are present; having HasFakeUses=true
  // on a function without fake uses is harmless.
  if (YamlMF.HasFakeUses && !*YamlMF.HasFakeUses && HasFakeUses)
    return error(
        MF.getName() +
        " has explicit property hasFakeUses=false, but contains fake uses");
  MF.setHasFakeUses(YamlMF.HasFakeUses.value_or(HasFakeUses));

  return false;
}

bool MIRParserImpl::parseMachineInst(PerFunctionMIParsingState &PFS,
                                     const yaml::MachineInstrLoc &MILoc,
                                     MachineInstr const *&MI) {
  MachineFunction &MF = PFS.MF;
  MachineBasicBlock *BB;
  if (parseMBBReference(PFS, BB, MILoc.Block))
    return true;
  if (MILoc.Offset >= BB->size())
    return error(Twine(MF.getName()) +
                 Twine(" instruction offset out of range.") +
                 " Unable to reference instruction at " + MILoc.Block.Value +
                 " at offset:" + Twine(MILoc.Offset));
  MI = &*std::next(BB->instr_begin(), MILoc.Offset);
  return false;
}

bool MIRParserImpl::initializeCallSiteInfo(
    PerFunctionMIParsingState &PFS, const yaml::MachineFunction &YamlMF) {
  MachineFunction &MF = PFS.MF;
  SMDiagnostic Error;
  const TargetMachine &TM = MF.getTarget();
  for (auto &YamlCSInfo : YamlMF.CallSitesInfo) {
    const yaml::MachineInstrLoc &MILoc = YamlCSInfo.CallLocation;
    const MachineInstr *CallI;
    if (parseMachineInst(PFS, MILoc, CallI))
      return true;
    if (!CallI->isCall(MachineInstr::IgnoreBundle))
      return error(Twine(MF.getName()) +
                   Twine(" call site info should reference call "
                         "instruction. Instruction at ") +
                   MILoc.Block.Value + " at offset:" + Twine(MILoc.Offset) +
                   " is not a call instruction");
    MachineFunction::CallSiteInfo CSInfo;
    for (auto ArgRegPair : YamlCSInfo.ArgForwardingRegs) {
      Register Reg;
      if (parseNamedRegisterReference(PFS, Reg, ArgRegPair.Reg.Value, Error))
        return error(Error, ArgRegPair.Reg.SourceRange);
      CSInfo.ArgRegPairs.emplace_back(Reg, ArgRegPair.ArgNo);
    }
    if (!YamlCSInfo.CalleeTypeIds.empty()) {
      for (auto CalleeTypeId : YamlCSInfo.CalleeTypeIds) {
        IntegerType *Int64Ty = Type::getInt64Ty(Context);
        CSInfo.CalleeTypeIds.push_back(ConstantInt::get(Int64Ty, CalleeTypeId,
                                                        /*isSigned=*/false));
      }
    }

    if (TM.Options.EmitCallSiteInfo || TM.Options.EmitCallGraphSection)
      MF.addCallSiteInfo(&*CallI, std::move(CSInfo));
  }

  if (!YamlMF.CallSitesInfo.empty() &&
      !(TM.Options.EmitCallSiteInfo || TM.Options.EmitCallGraphSection))
    return error("call site info provided but not used");
  return false;
}

void MIRParserImpl::setupDebugValueTracking(
    MachineFunction &MF, PerFunctionMIParsingState &PFS,
    const yaml::MachineFunction &YamlMF) {
  // Compute the value of the "next instruction number" field.
  unsigned MaxInstrNum = 0;
  for (auto &MBB : MF)
    for (auto &MI : MBB)
      MaxInstrNum = std::max(MI.peekDebugInstrNum(), MaxInstrNum);
  MF.setDebugInstrNumberingCount(MaxInstrNum);

  // Load any substitutions.
  for (const auto &Sub : YamlMF.DebugValueSubstitutions) {
    MF.makeDebugValueSubstitution({Sub.SrcInst, Sub.SrcOp},
                                  {Sub.DstInst, Sub.DstOp}, Sub.Subreg);
  }

  // Flag for whether we're supposed to be using DBG_INSTR_REF.
  MF.setUseDebugInstrRef(YamlMF.UseDebugInstrRef);
}

bool
MIRParserImpl::initializeMachineFunction(const yaml::MachineFunction &YamlMF,
                                         MachineFunction &MF) {
  // TODO: Recreate the machine function.
  if (Target) {
    // Avoid clearing state if we're using the same subtarget again.
    Target->setTarget(MF.getSubtarget());
  } else {
    Target.reset(new PerTargetMIParsingState(MF.getSubtarget()));
  }

  MF.setAlignment(YamlMF.Alignment.valueOrOne());
  MF.setExposesReturnsTwice(YamlMF.ExposesReturnsTwice);
  MF.setHasWinCFI(YamlMF.HasWinCFI);

  MF.setCallsEHReturn(YamlMF.CallsEHReturn);
  MF.setCallsUnwindInit(YamlMF.CallsUnwindInit);
  MF.setHasEHContTarget(YamlMF.HasEHContTarget);
  MF.setHasEHScopes(YamlMF.HasEHScopes);
  MF.setHasEHFunclets(YamlMF.HasEHFunclets);
  MF.setIsOutlined(YamlMF.IsOutlined);

  MachineFunctionProperties &Props = MF.getProperties();
  if (YamlMF.Legalized)
    Props.setLegalized();
  if (YamlMF.RegBankSelected)
    Props.setRegBankSelected();
  if (YamlMF.Selected)
    Props.setSelected();
  if (YamlMF.FailedISel)
    Props.setFailedISel();
  if (YamlMF.FailsVerification)
    Props.setFailsVerification();
  if (YamlMF.TracksDebugUserValues)
    Props.setTracksDebugUserValues();

  PerFunctionMIParsingState PFS(MF, SM, IRSlots, *Target);
  if (parseRegisterInfo(PFS, YamlMF))
    return true;
  if (initializePrefetchTargets(PFS, YamlMF))
    return true;
  if (!YamlMF.Constants.empty()) {
    auto *ConstantPool = MF.getConstantPool();
    assert(ConstantPool && "Constant pool must be created");
    if (initializeConstantPool(PFS, *ConstantPool, YamlMF))
      return true;
  }
  if (!YamlMF.MachineMetadataNodes.empty() &&
      parseMachineMetadataNodes(PFS, MF, YamlMF))
    return true;

  StringRef BlockStr = YamlMF.Body.Value.Value;
  SMDiagnostic Error;
  SourceMgr BlockSM;
  BlockSM.AddNewSourceBuffer(
      MemoryBuffer::getMemBuffer(BlockStr, "",/*RequiresNullTerminator=*/false),
      SMLoc());
  PFS.SM = &BlockSM;
  if (parseMachineBasicBlockDefinitions(PFS, BlockStr, Error)) {
    reportDiagnostic(
        diagFromBlockStringDiag(Error, YamlMF.Body.Value.SourceRange));
    return true;
  }
  // Check Basic Block Section Flags.
  if (MF.hasBBSections()) {
    MF.assignBeginEndSections();
  }
  PFS.SM = &SM;

  // Initialize the frame information after creating all the MBBs so that the
  // MBB references in the frame information can be resolved.
  if (initializeFrameInfo(PFS, YamlMF))
    return true;
  // Initialize the jump table after creating all the MBBs so that the MBB
  // references can be resolved.
  if (!YamlMF.JumpTableInfo.Entries.empty() &&
      initializeJumpTableInfo(PFS, YamlMF.JumpTableInfo))
    return true;
  // Parse the machine instructions after creating all of the MBBs so that the
  // parser can resolve the MBB references.
  StringRef InsnStr = YamlMF.Body.Value.Value;
  SourceMgr InsnSM;
  InsnSM.AddNewSourceBuffer(
      MemoryBuffer::getMemBuffer(InsnStr, "", /*RequiresNullTerminator=*/false),
      SMLoc());
  PFS.SM = &InsnSM;
  if (parseMachineInstructions(PFS, InsnStr, Error)) {
    reportDiagnostic(
        diagFromBlockStringDiag(Error, YamlMF.Body.Value.SourceRange));
    return true;
  }
  PFS.SM = &SM;

  if (setupRegisterInfo(PFS, YamlMF))
    return true;

  if (YamlMF.MachineFuncInfo) {
    const TargetMachine &TM = MF.getTarget();
    // Note this is called after the initial constructor of the
    // MachineFunctionInfo based on the MachineFunction, which may depend on the
    // IR.

    SMRange SrcRange;
    if (TM.parseMachineFunctionInfo(*YamlMF.MachineFuncInfo, PFS, Error,
                                    SrcRange)) {
      return error(Error, SrcRange);
    }
  }

  // Set the reserved registers after parsing MachineFuncInfo. The target may
  // have been recording information used to select the reserved registers
  // there.
  // FIXME: This is a temporary workaround until the reserved registers can be
  // serialized.
  MachineRegisterInfo &MRI = MF.getRegInfo();
  MRI.freezeReservedRegs();

  if (computeFunctionProperties(MF, YamlMF))
    return true;

  if (initializeCallSiteInfo(PFS, YamlMF))
    return true;

  if (parseCalledGlobals(PFS, MF, YamlMF))
    return true;

  if (initializePrefetchTargets(PFS, YamlMF))
    return true;

  setupDebugValueTracking(MF, PFS, YamlMF);

  MF.getSubtarget().mirFileLoaded(MF);

  MF.verify(nullptr, nullptr, &errs());
  return false;
}

bool MIRParserImpl::initializePrefetchTargets(
    PerFunctionMIParsingState &PFS, const yaml::MachineFunction &YamlMF) {
  MachineFunction &MF = PFS.MF;
  SMDiagnostic Error;
  DenseMap<UniqueBBID, SmallVector<unsigned>> Targets;
  for (const auto &YamlTarget : YamlMF.PrefetchTargets) {
    CallsiteID Target;
    if (llvm::parsePrefetchTarget(PFS, Target, YamlTarget.Value, Error))
      return error(Error, YamlTarget.SourceRange);
    Targets[Target.BBID].push_back(Target.CallsiteIndex);
  }
  MF.setPrefetchTargets(Targets);
  return false;
}

bool MIRParserImpl::parseRegisterInfo(PerFunctionMIParsingState &PFS,
                                      const yaml::MachineFunction &YamlMF) {
  MachineFunction &MF = PFS.MF;
  MachineRegisterInfo &RegInfo = MF.getRegInfo();
  assert(RegInfo.tracksLiveness());
  if (!YamlMF.TracksRegLiveness)
    RegInfo.invalidateLiveness();

  SMDiagnostic Error;
  // Parse the virtual register information.
  for (const auto &VReg : YamlMF.VirtualRegisters) {
    VRegInfo &Info = PFS.getVRegInfo(VReg.ID.Value);
    if (Info.Explicit)
      return error(VReg.ID.SourceRange.Start,
                   Twine("redefinition of virtual register '%") +
                       Twine(VReg.ID.Value) + "'");
    Info.Explicit = true;

    if (VReg.Class.Value == "_") {
      Info.Kind = VRegInfo::GENERIC;
      Info.D.RegBank = nullptr;
    } else {
      const auto *RC = Target->getRegClass(VReg.Class.Value);
      if (RC) {
        Info.Kind = VRegInfo::NORMAL;
        Info.D.RC = RC;
      } else {
        const RegisterBank *RegBank = Target->getRegBank(VReg.Class.Value);
        if (!RegBank)
          return error(
              VReg.Class.SourceRange.Start,
              Twine("use of undefined register class or register bank '") +
                  VReg.Class.Value + "'");
        Info.Kind = VRegInfo::REGBANK;
        Info.D.RegBank = RegBank;
      }
    }

    if (!VReg.PreferredRegister.Value.empty()) {
      if (Info.Kind != VRegInfo::NORMAL)
        return error(VReg.Class.SourceRange.Start,
              Twine("preferred register can only be set for normal vregs"));

      if (parseRegisterReference(PFS, Info.PreferredReg,
                                 VReg.PreferredRegister.Value, Error))
        return error(Error, VReg.PreferredRegister.SourceRange);
    }

    for (const auto &FlagStringValue : VReg.RegisterFlags) {
      uint8_t FlagValue;
      if (Target->getVRegFlagValue(FlagStringValue.Value, FlagValue))
        return error(FlagStringValue.SourceRange.Start,
                     Twine("use of undefined register flag '") +
                         FlagStringValue.Value + "'");
      Info.Flags |= FlagValue;
    }
    if (!VReg.AntiHints.empty() && Info.Kind != VRegInfo::NORMAL)
      return error(VReg.AntiHints.front().SourceRange.Start,
                   "anti-hints can only be set for normal vregs");

    for (const auto &AntiHintValue : VReg.AntiHints) {
      Register AntiHintReg;
      if (parseRegisterReference(PFS, AntiHintReg, AntiHintValue.Value, Error))
        return error(Error, AntiHintValue.SourceRange);

      if (!AntiHintReg.isVirtual()) {
        return error(AntiHintValue.SourceRange.Start,
                     "anti-hint '" + Twine(AntiHintValue.Value) +
                         "' must be a virtual register");
      }

      Info.AntiHints.push_back(AntiHintReg);
    }
    RegInfo.noteNewVirtualRegister(Info.VReg);
  }

  // Parse the liveins.
  for (const auto &LiveIn : YamlMF.LiveIns) {
    Register Reg;
    if (parseNamedRegisterReference(PFS, Reg, LiveIn.Register.Value, Error))
      return error(Error, LiveIn.Register.SourceRange);
    Register VReg;
    if (!LiveIn.VirtualRegister.Value.empty()) {
      VRegInfo *Info;
      if (parseVirtualRegisterReference(PFS, Info, LiveIn.VirtualRegister.Value,
                                        Error))
        return error(Error, LiveIn.VirtualRegister.SourceRange);
      VReg = Info->VReg;
    }
    RegInfo.addLiveIn(Reg, VReg);
  }

  // Parse the callee saved registers (Registers that will
  // be saved for the caller).
  if (YamlMF.CalleeSavedRegisters) {
    SmallVector<MCPhysReg, 16> CalleeSavedRegisters;
    for (const auto &RegSource : *YamlMF.CalleeSavedRegisters) {
      Register Reg;
      if (parseNamedRegisterReference(PFS, Reg, RegSource.Value, Error))
        return error(Error, RegSource.SourceRange);
      CalleeSavedRegisters.push_back(Reg.id());
    }
    RegInfo.setCalleeSavedRegs(CalleeSavedRegisters);
  }

  // Stash any VirtRegMap state on MRI.
  // VirtRegMap::init() will use that information to get pre-populated
  // on the first analysis run.
  for (const auto &VReg : YamlMF.VirtualRegisters) {
    if (VReg.SplitFrom.Value.empty() && VReg.AssignedPhys.Value.empty())
      continue;

    auto It = PFS.VRegInfos.find(VReg.ID.Value);
    if (It == PFS.VRegInfos.end())
      continue;
    Register ChildReg = It->second->VReg;

    MachineRegisterInfo::PendingVirtRegMapEntry Pending;
    Pending.VReg = ChildReg;

    if (!VReg.SplitFrom.Value.empty()) {
      VRegInfo *Parent = nullptr;
      if (parseVirtualRegisterReference(PFS, Parent, VReg.SplitFrom.Value,
                                        Error))
        return error(Error, VReg.SplitFrom.SourceRange);
      if (Parent->VReg == ChildReg)
        return error(VReg.SplitFrom.SourceRange.Start,
                     Twine("'split-from' references the same vreg as 'id' (%") +
                         Twine(VReg.ID.Value) + ")");
      Pending.SplitFrom = Parent->VReg;
    }
    if (!VReg.AssignedPhys.Value.empty()) {
      Register Phys;
      if (parseRegisterReference(PFS, Phys, VReg.AssignedPhys.Value, Error))
        return error(Error, VReg.AssignedPhys.SourceRange);
      if (!Phys.isPhysical())
        return error(
            VReg.AssignedPhys.SourceRange.Start,
            Twine("'assigned-phys' must be a physical register, got '") +
                VReg.AssignedPhys.Value + "'");
      Pending.AssignedPhys = Phys.asMCReg();
    }
    RegInfo.addPendingVirtRegMapEntry(Pending);
  }

  return false;
}

bool MIRParserImpl::setupRegisterInfo(const PerFunctionMIParsingState &PFS,
                                      const yaml::MachineFunction &YamlMF) {
  MachineFunction &MF = PFS.MF;
  MachineRegisterInfo &MRI = MF.getRegInfo();
  const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();

  SmallVector<std::string> Errors;

  // Create VRegs
  auto populateVRegInfo = [&](const VRegInfo &Info, const Twine &Name) {
    Register Reg = Info.VReg;
    switch (Info.Kind) {
    case VRegInfo::UNKNOWN:
      Errors.push_back(
          (Twine("Cannot determine class/bank of virtual register ") + Name +
           " in function '" + MF.getName() + "'")
              .str());
      break;
    case VRegInfo::NORMAL:
      if (!Info.D.RC->isAllocatable()) {
        Errors.push_back((Twine("Cannot use non-allocatable class '") +
                          TRI->getRegClassName(Info.D.RC) +
                          "' for virtual register " + Name + " in function '" +
                          MF.getName() + "'")
                             .str());
        break;
      }

      MRI.setRegClass(Reg, Info.D.RC);
      if (Info.PreferredReg != 0)
        MRI.setSimpleHint(Reg, Info.PreferredReg);
      if (!Info.AntiHints.empty())
        MRI.addRegAllocationAntiHints(Reg, Info.AntiHints);
      break;
    case VRegInfo::GENERIC:
      break;
    case VRegInfo::REGBANK:
      MRI.setRegBank(Reg, *Info.D.RegBank);
      break;
    }
  };

  for (const auto &P : PFS.VRegInfosNamed) {
    const VRegInfo &Info = *P.second;
    populateVRegInfo(Info, Twine(P.first()));
  }

  for (auto P : PFS.VRegInfos) {
    const VRegInfo &Info = *P.second;
    populateVRegInfo(Info, Twine(P.first.id()));
  }

  // Compute MachineRegisterInfo::UsedPhysRegMask
  for (const MachineBasicBlock &MBB : MF) {
    // Make sure MRI knows about registers clobbered by unwinder.
    if (MBB.isEHPad())
      if (auto *RegMask = TRI->getCustomEHPadPreservedMask(MF))
        MRI.addPhysRegsUsedFromRegMask(RegMask);

    for (const MachineInstr &MI : MBB) {
      for (const MachineOperand &MO : MI.operands()) {
        if (!MO.isRegMask())
          continue;
        MRI.addPhysRegsUsedFromRegMask(MO.getRegMask());
      }
    }
  }

  if (Errors.empty())
    return false;

  // Report errors in a deterministic order.
  sort(Errors);
  for (auto &E : Errors)
    error(E);
  return true;
}

bool MIRParserImpl::initializeFrameInfo(PerFunctionMIParsingState &PFS,
                                        const yaml::MachineFunction &YamlMF) {
  MachineFunction &MF = PFS.MF;
  MachineFrameInfo &MFI = MF.getFrameInfo();
  const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
  const Function &F = MF.getFunction();
  const yaml::MachineFrameInfo &YamlMFI = YamlMF.FrameInfo;
  MFI.setFrameAddressIsTaken(YamlMFI.IsFrameAddressTaken);
  MFI.setReturnAddressIsTaken(YamlMFI.IsReturnAddressTaken);
  MFI.setHasStackMap(YamlMFI.HasStackMap);
  MFI.setHasPatchPoint(YamlMFI.HasPatchPoint);
  MFI.setStackSize(YamlMFI.StackSize);
  MFI.setOffsetAdjustment(YamlMFI.OffsetAdjustment);
  if (YamlMFI.MaxAlignment)
    MFI.ensureMaxAlignment(Align(YamlMFI.MaxAlignment));
  MFI.setAdjustsStack(YamlMFI.AdjustsStack);
  MFI.setHasCalls(YamlMFI.HasCalls);
  if (YamlMFI.FramePointerPolicy != FramePointerKind::None)
    MFI.setFramePointerPolicy(YamlMFI.FramePointerPolicy);
  if (YamlMFI.MaxCallFrameSize != ~0u)
    MFI.setMaxCallFrameSize(YamlMFI.MaxCallFrameSize);
  MFI.setCVBytesOfCalleeSavedRegisters(YamlMFI.CVBytesOfCalleeSavedRegisters);
  MFI.setHasOpaqueSPAdjustment(YamlMFI.HasOpaqueSPAdjustment);
  MFI.setHasVAStart(YamlMFI.HasVAStart);
  MFI.setHasMustTailInVarArgFunc(YamlMFI.HasMustTailInVarArgFunc);
  MFI.setHasTailCall(YamlMFI.HasTailCall);
  MFI.setCalleeSavedInfoValid(YamlMFI.IsCalleeSavedInfoValid);
  MFI.setLocalFrameSize(YamlMFI.LocalFrameSize);
  llvm::SaveRestorePoints SavePoints;
  if (initializeSaveRestorePoints(PFS, YamlMFI.SavePoints, SavePoints))
    return true;
  MFI.setSavePoints(SavePoints);
  llvm::SaveRestorePoints RestorePoints;
  if (initializeSaveRestorePoints(PFS, YamlMFI.RestorePoints, RestorePoints))
    return true;
  MFI.setRestorePoints(RestorePoints);

  std::vector<CalleeSavedInfo> CSIInfo;
  // Initialize the fixed frame objects.
  for (const auto &Object : YamlMF.FixedStackObjects) {
    int ObjectIdx;
    if (Object.Type != yaml::FixedMachineStackObject::SpillSlot)
      ObjectIdx = MFI.CreateFixedObject(Object.Size, Object.Offset,
                                        Object.IsImmutable, Object.IsAliased);
    else
      ObjectIdx = MFI.CreateFixedSpillStackObject(Object.Size, Object.Offset);

    if (!TFI->isSupportedStackID(Object.StackID))
      return error(Object.ID.SourceRange.Start,
                   Twine("StackID is not supported by target"));
    MFI.setStackID(ObjectIdx, Object.StackID);
    MFI.setObjectAlignment(ObjectIdx, Object.Alignment.valueOrOne());
    if (!PFS.FixedStackObjectSlots.insert(std::make_pair(Object.ID.Value,
                                                         ObjectIdx))
             .second)
      return error(Object.ID.SourceRange.Start,
                   Twine("redefinition of fixed stack object '%fixed-stack.") +
                       Twine(Object.ID.Value) + "'");
    if (parseCalleeSavedRegister(PFS, CSIInfo, Object.CalleeSavedRegister,
                                 Object.CalleeSavedRestored, ObjectIdx))
      return true;
    if (parseStackObjectsDebugInfo(PFS, Object, ObjectIdx))
      return true;
  }

  for (const auto &Object : YamlMF.EntryValueObjects) {
    SMDiagnostic Error;
    Register Reg;
    if (parseNamedRegisterReference(PFS, Reg, Object.EntryValueRegister.Value,
                                    Error))
      return error(Error, Object.EntryValueRegister.SourceRange);
    if (!Reg.isPhysical())
      return error(Object.EntryValueRegister.SourceRange.Start,
                   "Expected physical register for entry value field");
    std::optional<VarExprLoc> MaybeInfo = parseVarExprLoc(
        PFS, Object.DebugVar, Object.DebugExpr, Object.DebugLoc);
    if (!MaybeInfo)
      return true;
    if (MaybeInfo->DIVar || MaybeInfo->DIExpr || MaybeInfo->DILoc)
      PFS.MF.setVariableDbgInfo(MaybeInfo->DIVar, MaybeInfo->DIExpr,
                                Reg.asMCReg(), MaybeInfo->DILoc);
  }

  // Initialize the ordinary frame objects.
  for (const auto &Object : YamlMF.StackObjects) {
    int ObjectIdx;
    const AllocaInst *Alloca = nullptr;
    const yaml::StringValue &Name = Object.Name;
    if (!Name.Value.empty()) {
      Alloca = dyn_cast_or_null<AllocaInst>(
          F.getValueSymbolTable()->lookup(Name.Value));
      if (!Alloca)
        return error(Name.SourceRange.Start,
                     "alloca instruction named '" + Name.Value +
                         "' isn't defined in the function '" + F.getName() +
                         "'");
    }
    if (!TFI->isSupportedStackID(Object.StackID))
      return error(Object.ID.SourceRange.Start,
                   Twine("StackID is not supported by target"));
    if (Object.Type == yaml::MachineStackObject::VariableSized)
      ObjectIdx =
          MFI.CreateVariableSizedObject(Object.Alignment.valueOrOne(), Alloca);
    else
      ObjectIdx = MFI.CreateStackObject(
          Object.Size, Object.Alignment.valueOrOne(),
          Object.Type == yaml::MachineStackObject::SpillSlot, Alloca,
          Object.StackID);
    MFI.setObjectOffset(ObjectIdx, Object.Offset);

    if (!PFS.StackObjectSlots.insert(std::make_pair(Object.ID.Value, ObjectIdx))
             .second)
      return error(Object.ID.SourceRange.Start,
                   Twine("redefinition of stack object '%stack.") +
                       Twine(Object.ID.Value) + "'");
    if (parseCalleeSavedRegister(PFS, CSIInfo, Object.CalleeSavedRegister,
                                 Object.CalleeSavedRestored, ObjectIdx))
      return true;
    if (Object.LocalOffset)
      MFI.mapLocalFrameObject(ObjectIdx, *Object.LocalOffset);
    if (parseStackObjectsDebugInfo(PFS, Object, ObjectIdx))
      return true;
  }
  MFI.setCalleeSavedInfo(CSIInfo);
  if (!CSIInfo.empty())
    MFI.setCalleeSavedInfoValid(true);

  // Initialize the various stack object references after initializing the
  // stack objects.
  if (!YamlMFI.StackProtector.Value.empty()) {
    SMDiagnostic Error;
    int FI;
    if (parseStackObjectReference(PFS, FI, YamlMFI.StackProtector.Value, Error))
      return error(Error, YamlMFI.StackProtector.SourceRange);
    MFI.setStackProtectorIndex(FI);
  }

  if (!YamlMFI.FunctionContext.Value.empty()) {
    SMDiagnostic Error;
    int FI;
    if (parseStackObjectReference(PFS, FI, YamlMFI.FunctionContext.Value, Error))
      return error(Error, YamlMFI.FunctionContext.SourceRange);
    MFI.setFunctionContextIndex(FI);
  }

  return false;
}

bool MIRParserImpl::parseCalleeSavedRegister(PerFunctionMIParsingState &PFS,
    std::vector<CalleeSavedInfo> &CSIInfo,
    const yaml::StringValue &RegisterSource, bool IsRestored, int FrameIdx) {
  if (RegisterSource.Value.empty())
    return false;
  Register Reg;
  SMDiagnostic Error;
  if (parseNamedRegisterReference(PFS, Reg, RegisterSource.Value, Error))
    return error(Error, RegisterSource.SourceRange);
  CalleeSavedInfo CSI(Reg, FrameIdx);
  CSI.setRestored(IsRestored);
  CSIInfo.push_back(CSI);
  return false;
}

/// Verify that given node is of a certain type. Return true on error.
template <typename T>
static bool typecheckMDNode(T *&Result, MDNode *Node,
                            const yaml::StringValue &Source,
                            StringRef TypeString, MIRParserImpl &Parser) {
  if (!Node)
    return false;
  Result = dyn_cast<T>(Node);
  if (!Result)
    return Parser.error(Source.SourceRange.Start,
                        "expected a reference to a '" + TypeString +
                            "' metadata node");
  return false;
}

std::optional<MIRParserImpl::VarExprLoc> MIRParserImpl::parseVarExprLoc(
    PerFunctionMIParsingState &PFS, const yaml::StringValue &VarStr,
    const yaml::StringValue &ExprStr, const yaml::StringValue &LocStr) {
  MDNode *Var = nullptr;
  MDNode *Expr = nullptr;
  MDNode *Loc = nullptr;
  if (parseMDNode(PFS, Var, VarStr) || parseMDNode(PFS, Expr, ExprStr) ||
      parseMDNode(PFS, Loc, LocStr))
    return std::nullopt;
  DILocalVariable *DIVar = nullptr;
  DIExpression *DIExpr = nullptr;
  DILocation *DILoc = nullptr;
  if (typecheckMDNode(DIVar, Var, VarStr, "DILocalVariable", *this) ||
      typecheckMDNode(DIExpr, Expr, ExprStr, "DIExpression", *this) ||
      typecheckMDNode(DILoc, Loc, LocStr, "DILocation", *this))
    return std::nullopt;
  return VarExprLoc{DIVar, DIExpr, DILoc};
}

template <typename T>
bool MIRParserImpl::parseStackObjectsDebugInfo(PerFunctionMIParsingState &PFS,
                                               const T &Object, int FrameIdx) {
  std::optional<VarExprLoc> MaybeInfo =
      parseVarExprLoc(PFS, Object.DebugVar, Object.DebugExpr, Object.DebugLoc);
  if (!MaybeInfo)
    return true;
  // Debug information can only be attached to stack objects; Fixed stack
  // objects aren't supported.
  if (MaybeInfo->DIVar || MaybeInfo->DIExpr || MaybeInfo->DILoc)
    PFS.MF.setVariableDbgInfo(MaybeInfo->DIVar, MaybeInfo->DIExpr, FrameIdx,
                              MaybeInfo->DILoc);
  return false;
}

bool MIRParserImpl::parseMDNode(PerFunctionMIParsingState &PFS,
    MDNode *&Node, const yaml::StringValue &Source) {
  if (Source.Value.empty())
    return false;
  SMDiagnostic Error;
  if (llvm::parseMDNode(PFS, Node, Source.Value, Error))
    return error(Error, Source.SourceRange);
  return false;
}

bool MIRParserImpl::initializeConstantPool(PerFunctionMIParsingState &PFS,
    MachineConstantPool &ConstantPool, const yaml::MachineFunction &YamlMF) {
  DenseMap<unsigned, unsigned> &ConstantPoolSlots = PFS.ConstantPoolSlots;
  const MachineFunction &MF = PFS.MF;
  const auto &M = *MF.getFunction().getParent();
  SMDiagnostic Error;
  for (const auto &YamlConstant : YamlMF.Constants) {
    if (YamlConstant.IsTargetSpecific)
      // FIXME: Support target-specific constant pools
      return error(YamlConstant.Value.SourceRange.Start,
                   "Can't parse target-specific constant pool entries yet");
    const Constant *Value = dyn_cast_or_null<Constant>(
        parseConstantValue(YamlConstant.Value.Value, Error, M));
    if (!Value)
      return error(Error, YamlConstant.Value.SourceRange);
    const Align PrefTypeAlign =
        M.getDataLayout().getPrefTypeAlign(Value->getType());
    const Align Alignment = YamlConstant.Alignment.value_or(PrefTypeAlign);
    unsigned Index = ConstantPool.getConstantPoolIndex(Value, Alignment);
    if (!ConstantPoolSlots.insert(std::make_pair(YamlConstant.ID.Value, Index))
             .second)
      return error(YamlConstant.ID.SourceRange.Start,
                   Twine("redefinition of constant pool item '%const.") +
                       Twine(YamlConstant.ID.Value) + "'");
  }
  return false;
}

// Return true if basic block was incorrectly specified in MIR
bool MIRParserImpl::initializeSaveRestorePoints(
    PerFunctionMIParsingState &PFS,
    const std::vector<yaml::SaveRestorePointEntry> &YamlSRPoints,
    llvm::SaveRestorePoints &SaveRestorePoints) {
  SMDiagnostic Error;
  MachineBasicBlock *MBB = nullptr;
  for (const yaml::SaveRestorePointEntry &Entry : YamlSRPoints) {
    if (parseMBBReference(PFS, MBB, Entry.Point.Value))
      return true;

    std::vector<CalleeSavedInfo> Registers;
    for (auto &RegStr : Entry.Registers) {
      Register Reg;
      if (parseNamedRegisterReference(PFS, Reg, RegStr.Value, Error))
        return error(Error, RegStr.SourceRange);
      Registers.push_back(CalleeSavedInfo(Reg));
    }
    SaveRestorePoints.try_emplace(MBB, std::move(Registers));
  }
  return false;
}

bool MIRParserImpl::initializeJumpTableInfo(PerFunctionMIParsingState &PFS,
    const yaml::MachineJumpTable &YamlJTI) {
  MachineJumpTableInfo *JTI = PFS.MF.getOrCreateJumpTableInfo(YamlJTI.Kind);
  for (const auto &Entry : YamlJTI.Entries) {
    std::vector<MachineBasicBlock *> Blocks;
    for (const auto &MBBSource : Entry.Blocks) {
      MachineBasicBlock *MBB = nullptr;
      if (parseMBBReference(PFS, MBB, MBBSource.Value))
        return true;
      Blocks.push_back(MBB);
    }
    unsigned Index = JTI->createJumpTableIndex(Blocks);
    if (!PFS.JumpTableSlots.insert(std::make_pair(Entry.ID.Value, Index))
             .second)
      return error(Entry.ID.SourceRange.Start,
                   Twine("redefinition of jump table entry '%jump-table.") +
                       Twine(Entry.ID.Value) + "'");
  }
  return false;
}

bool MIRParserImpl::parseMBBReference(PerFunctionMIParsingState &PFS,
                                      MachineBasicBlock *&MBB,
                                      const yaml::StringValue &Source) {
  SMDiagnostic Error;
  if (llvm::parseMBBReference(PFS, MBB, Source.Value, Error))
    return error(Error, Source.SourceRange);
  return false;
}

bool MIRParserImpl::parseMachineMetadataNodes(
    PerFunctionMIParsingState &PFS, MachineFunction &MF,
    const yaml::MachineFunction &YMF) {
  SmallVector<StringRef> Definitions;
  for (const auto &MDS : YMF.MachineMetadataNodes)
    Definitions.push_back(MDS.Value);

  SlotMapping Slots = PFS.IRSlots;
  SMDiagnostic Error;
  unsigned ErrorDefinitionIndex = 0;
  if (parseMetadataDefinitions(Definitions, Error,
                               *MF.getFunction().getParent(), Slots,
                               ErrorDefinitionIndex)) {
    const yaml::StringValue &Source =
        YMF.MachineMetadataNodes[ErrorDefinitionIndex];
    if (StringRef(Source.Value).contains('\n')) {
      reportDiagnostic(diagFromBlockStringDiag(Error, Source.SourceRange));
      return true;
    }
    return error(Error, Source.SourceRange);
  }

  for (auto &[ID, MD] : Slots.MetadataNodes)
    if (PFS.IRSlots.MetadataNodes.find(ID) == PFS.IRSlots.MetadataNodes.end())
      PFS.MachineMetadataNodes.try_emplace(ID, MD);
  return false;
}

bool MIRParserImpl::parseCalledGlobals(PerFunctionMIParsingState &PFS,
                                       MachineFunction &MF,
                                       const yaml::MachineFunction &YMF) {
  Function &F = MF.getFunction();
  for (const auto &YamlCG : YMF.CalledGlobals) {
    const yaml::MachineInstrLoc &MILoc = YamlCG.CallSite;
    const MachineInstr *CallI;
    if (parseMachineInst(PFS, MILoc, CallI))
      return true;
    if (!CallI->isCall(MachineInstr::IgnoreBundle))
      return error(Twine(MF.getName()) +
                   Twine(" called global should reference call "
                         "instruction. Instruction at ") +
                   MILoc.Block.Value + " at offset:" + Twine(MILoc.Offset) +
                   " is not a call instruction");

    auto Callee =
        F.getParent()->getValueSymbolTable().lookup(YamlCG.Callee.Value);
    if (!Callee)
      return error(YamlCG.Callee.SourceRange.Start,
                   "use of undefined global '" + YamlCG.Callee.Value + "'");
    if (!isa<GlobalValue>(Callee))
      return error(YamlCG.Callee.SourceRange.Start,
                   "use of non-global value '" + YamlCG.Callee.Value + "'");

    MF.addCalledGlobal(CallI, {cast<GlobalValue>(Callee), YamlCG.Flags});
  }

  return false;
}

SMDiagnostic MIRParserImpl::diagFromMIStringDiag(const SMDiagnostic &Error,
                                                 SMRange SourceRange) {
  assert(SourceRange.isValid() && "Invalid source range");
  SMLoc Loc = SourceRange.Start;
  bool HasQuote = Loc.getPointer() < SourceRange.End.getPointer() &&
                  *Loc.getPointer() == '\'';
  // Translate the location of the error from the location in the MI string to
  // the corresponding location in the MIR file.
  Loc = Loc.getFromPointer(Loc.getPointer() + Error.getColumnNo() +
                           (HasQuote ? 1 : 0));

  // TODO: Translate any source ranges as well.
  return SM.GetMessage(Loc, Error.getKind(), Error.getMessage(), {},
                       Error.getFixIts());
}

SMDiagnostic MIRParserImpl::diagFromBlockStringDiag(const SMDiagnostic &Error,
                                                    SMRange SourceRange) {
  assert(SourceRange.isValid());

  // Translate the location of the error from the location in the llvm IR string
  // to the corresponding location in the MIR file.
  auto LineAndColumn = SM.getLineAndColumn(SourceRange.Start);
  unsigned Line = LineAndColumn.first + Error.getLineNo() - 1;
  unsigned Column = Error.getColumnNo();
  StringRef LineStr = Error.getLineContents();
  SMLoc Loc = Error.getLoc();

  // Get the full line and adjust the column number by taking the indentation of
  // LLVM IR into account.
  for (line_iterator L(*SM.getMemoryBuffer(SM.getMainFileID()), false), E;
       L != E; ++L) {
    if (L.line_number() == Line) {
      LineStr = *L;
      Loc = SMLoc::getFromPointer(LineStr.data());
      auto Indent = LineStr.find(Error.getLineContents());
      if (Indent != StringRef::npos)
        Column += Indent;
      break;
    }
  }

  return SMDiagnostic(SM, Loc, Filename, Line, Column, Error.getKind(),
                      Error.getMessage(), LineStr, Error.getRanges(),
                      Error.getFixIts());
}

MIRParser::MIRParser(std::unique_ptr<MIRParserImpl> Impl)
    : Impl(std::move(Impl)) {}

MIRParser::~MIRParser() = default;

std::unique_ptr<Module>
MIRParser::parseIRModule(DataLayoutCallbackTy DataLayoutCallback) {
  return Impl->parseIRModule(DataLayoutCallback);
}

bool MIRParser::parseMachineFunctions(Module &M, MachineModuleInfo &MMI) {
  return Impl->parseMachineFunctions(M, MMI);
}

bool MIRParser::parseMachineFunctions(Module &M, ModuleAnalysisManager &MAM) {
  auto &MMI = MAM.getResult<MachineModuleAnalysis>(M).getMMI();
  return Impl->parseMachineFunctions(M, MMI, &MAM);
}

std::unique_ptr<MIRParser> llvm::createMIRParserFromFile(
    StringRef Filename, SMDiagnostic &Error, LLVMContext &Context,
    std::function<void(Function &)> ProcessIRFunction) {
  auto FileOrErr = MemoryBuffer::getFileOrSTDIN(Filename, /*IsText=*/true);
  if (std::error_code EC = FileOrErr.getError()) {
    Error = SMDiagnostic(Filename, SourceMgr::DK_Error,
                         "could not open input file: " + EC.message());
    return nullptr;
  }
  return createMIRParser(std::move(FileOrErr.get()), Context,
                         ProcessIRFunction);
}

std::unique_ptr<MIRParser>
llvm::createMIRParser(std::unique_ptr<MemoryBuffer> Contents,
                      LLVMContext &Context,
                      std::function<void(Function &)> ProcessIRFunction) {
  auto Filename = Contents->getBufferIdentifier();
  if (Context.shouldDiscardValueNames()) {
    Context.diagnose(DiagnosticInfoMIRParser(
        DS_Error,
        SMDiagnostic(
            Filename, SourceMgr::DK_Error,
            "cannot read MIR with a Context that discards named Values")));
    return nullptr;
  }
  return std::make_unique<MIRParser>(std::make_unique<MIRParserImpl>(
      std::move(Contents), Filename, Context, ProcessIRFunction));
}
