//===- 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);

  bool parseMachineMetadata(PerFunctionMIParsingState &PFS,
                            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(MachineFunction &MF, 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(MachineFunction &MF,
                                     yaml::MachineInstrLoc MILoc,
                                     MachineInstr const *&MI) {
  if (MILoc.BlockNum >= MF.size()) {
    return error(Twine(MF.getName()) +
                 Twine(" instruction block out of range.") +
                 " Unable to reference bb:" + Twine(MILoc.BlockNum));
  }
  auto BB = std::next(MF.begin(), MILoc.BlockNum);
  if (MILoc.Offset >= BB->size())
    return error(
        Twine(MF.getName()) + Twine(" instruction offset out of range.") +
        " Unable to reference instruction at bb: " + Twine(MILoc.BlockNum) +
        " 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) {
    yaml::MachineInstrLoc MILoc = YamlCSInfo.CallLocation;
    const MachineInstr *CallI;
    if (parseMachineInst(MF, MILoc, CallI))
      return true;
    if (!CallI->isCall(MachineInstr::IgnoreBundle))
      return error(Twine(MF.getName()) +
                   Twine(" call site info should reference call "
                         "instruction. Instruction at bb:") +
                   Twine(MILoc.BlockNum) + " 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;
    }
    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);
  }

  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);
      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::parseMachineMetadata(PerFunctionMIParsingState &PFS,
                                         const yaml::StringValue &Source) {
  SMDiagnostic Error;
  if (llvm::parseMachineMetadata(PFS, Source.Value, Source.SourceRange, Error))
    return error(Error, Source.SourceRange);
  return false;
}

bool MIRParserImpl::parseMachineMetadataNodes(
    PerFunctionMIParsingState &PFS, MachineFunction &MF,
    const yaml::MachineFunction &YMF) {
  for (const auto &MDS : YMF.MachineMetadataNodes) {
    if (parseMachineMetadata(PFS, MDS))
      return true;
  }
  // Report missing definitions from forward referenced nodes.
  if (!PFS.MachineForwardRefMDNodes.empty())
    return error(PFS.MachineForwardRefMDNodes.begin()->second.second,
                 "use of undefined metadata '!" +
                     Twine(PFS.MachineForwardRefMDNodes.begin()->first) + "'");
  return false;
}

bool MIRParserImpl::parseCalledGlobals(PerFunctionMIParsingState &PFS,
                                       MachineFunction &MF,
                                       const yaml::MachineFunction &YMF) {
  Function &F = MF.getFunction();
  for (const auto &YamlCG : YMF.CalledGlobals) {
    yaml::MachineInstrLoc MILoc = YamlCG.CallSite;
    const MachineInstr *CallI;
    if (parseMachineInst(MF, MILoc, CallI))
      return true;
    if (!CallI->isCall(MachineInstr::IgnoreBundle))
      return error(Twine(MF.getName()) +
                   Twine(" called global should reference call "
                         "instruction. Instruction at bb:") +
                   Twine(MILoc.BlockNum) + " 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));
}
