xref: /freebsd-src/contrib/llvm-project/llvm/lib/CodeGen/MIRParser/MIRParser.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- MIRParser.cpp - MIR serialization format parser implementation -----===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements the class that parses the optional LLVM IR and machine
100b57cec5SDimitry Andric // functions that are stored in MIR files.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "llvm/CodeGen/MIRParser/MIRParser.h"
150b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
160b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
170b57cec5SDimitry Andric #include "llvm/AsmParser/Parser.h"
180b57cec5SDimitry Andric #include "llvm/AsmParser/SlotMapping.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/MIRParser/MIParser.h"
200b57cec5SDimitry Andric #include "llvm/CodeGen/MIRYamlMapping.h"
210b57cec5SDimitry Andric #include "llvm/CodeGen/MachineConstantPool.h"
220b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
230b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
24*0fca6ea1SDimitry Andric #include "llvm/CodeGen/MachineFunctionAnalysis.h"
250b57cec5SDimitry Andric #include "llvm/CodeGen/MachineModuleInfo.h"
260b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
270b57cec5SDimitry Andric #include "llvm/CodeGen/TargetFrameLowering.h"
280b57cec5SDimitry Andric #include "llvm/IR/BasicBlock.h"
2981ad6265SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h"
300b57cec5SDimitry Andric #include "llvm/IR/DiagnosticInfo.h"
310b57cec5SDimitry Andric #include "llvm/IR/Instructions.h"
320b57cec5SDimitry Andric #include "llvm/IR/LLVMContext.h"
330b57cec5SDimitry Andric #include "llvm/IR/Module.h"
340b57cec5SDimitry Andric #include "llvm/IR/ValueSymbolTable.h"
350b57cec5SDimitry Andric #include "llvm/Support/LineIterator.h"
360b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
370b57cec5SDimitry Andric #include "llvm/Support/SMLoc.h"
380b57cec5SDimitry Andric #include "llvm/Support/SourceMgr.h"
390b57cec5SDimitry Andric #include "llvm/Support/YAMLTraits.h"
400b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h"
410b57cec5SDimitry Andric #include <memory>
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric using namespace llvm;
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric namespace llvm {
4681ad6265SDimitry Andric class MDNode;
4781ad6265SDimitry Andric class RegisterBank;
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric /// This class implements the parsing of LLVM IR that's embedded inside a MIR
500b57cec5SDimitry Andric /// file.
510b57cec5SDimitry Andric class MIRParserImpl {
520b57cec5SDimitry Andric   SourceMgr SM;
53fe6060f1SDimitry Andric   LLVMContext &Context;
540b57cec5SDimitry Andric   yaml::Input In;
550b57cec5SDimitry Andric   StringRef Filename;
560b57cec5SDimitry Andric   SlotMapping IRSlots;
570b57cec5SDimitry Andric   std::unique_ptr<PerTargetMIParsingState> Target;
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric   /// True when the MIR file doesn't have LLVM IR. Dummy IR functions are
600b57cec5SDimitry Andric   /// created and inserted into the given module when this is true.
610b57cec5SDimitry Andric   bool NoLLVMIR = false;
620b57cec5SDimitry Andric   /// True when a well formed MIR file does not contain any MIR/machine function
630b57cec5SDimitry Andric   /// parts.
640b57cec5SDimitry Andric   bool NoMIRDocuments = false;
650b57cec5SDimitry Andric 
66480093f4SDimitry Andric   std::function<void(Function &)> ProcessIRFunction;
67480093f4SDimitry Andric 
680b57cec5SDimitry Andric public:
69480093f4SDimitry Andric   MIRParserImpl(std::unique_ptr<MemoryBuffer> Contents, StringRef Filename,
70480093f4SDimitry Andric                 LLVMContext &Context,
71480093f4SDimitry Andric                 std::function<void(Function &)> ProcessIRFunction);
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric   void reportDiagnostic(const SMDiagnostic &Diag);
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric   /// Report an error with the given message at unknown location.
760b57cec5SDimitry Andric   ///
770b57cec5SDimitry Andric   /// Always returns true.
780b57cec5SDimitry Andric   bool error(const Twine &Message);
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric   /// Report an error with the given message at the given location.
810b57cec5SDimitry Andric   ///
820b57cec5SDimitry Andric   /// Always returns true.
830b57cec5SDimitry Andric   bool error(SMLoc Loc, const Twine &Message);
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric   /// Report a given error with the location translated from the location in an
860b57cec5SDimitry Andric   /// embedded string literal to a location in the MIR file.
870b57cec5SDimitry Andric   ///
880b57cec5SDimitry Andric   /// Always returns true.
890b57cec5SDimitry Andric   bool error(const SMDiagnostic &Error, SMRange SourceRange);
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric   /// Try to parse the optional LLVM module and the machine functions in the MIR
920b57cec5SDimitry Andric   /// file.
930b57cec5SDimitry Andric   ///
940b57cec5SDimitry Andric   /// Return null if an error occurred.
955ffd83dbSDimitry Andric   std::unique_ptr<Module>
965ffd83dbSDimitry Andric   parseIRModule(DataLayoutCallbackTy DataLayoutCallback);
970b57cec5SDimitry Andric 
98480093f4SDimitry Andric   /// Create an empty function with the given name.
99480093f4SDimitry Andric   Function *createDummyFunction(StringRef Name, Module &M);
100480093f4SDimitry Andric 
101*0fca6ea1SDimitry Andric   bool parseMachineFunctions(Module &M, MachineModuleInfo &MMI,
102*0fca6ea1SDimitry Andric                              ModuleAnalysisManager *FAM = nullptr);
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric   /// Parse the machine function in the current YAML document.
1050b57cec5SDimitry Andric   ///
1060b57cec5SDimitry Andric   ///
1070b57cec5SDimitry Andric   /// Return true if an error occurred.
108*0fca6ea1SDimitry Andric   bool parseMachineFunction(Module &M, MachineModuleInfo &MMI,
109*0fca6ea1SDimitry Andric                             ModuleAnalysisManager *FAM);
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric   /// Initialize the machine function to the state that's described in the MIR
1120b57cec5SDimitry Andric   /// file.
1130b57cec5SDimitry Andric   ///
1140b57cec5SDimitry Andric   /// Return true if error occurred.
1150b57cec5SDimitry Andric   bool initializeMachineFunction(const yaml::MachineFunction &YamlMF,
1160b57cec5SDimitry Andric                                  MachineFunction &MF);
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric   bool parseRegisterInfo(PerFunctionMIParsingState &PFS,
1190b57cec5SDimitry Andric                          const yaml::MachineFunction &YamlMF);
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric   bool setupRegisterInfo(const PerFunctionMIParsingState &PFS,
1220b57cec5SDimitry Andric                          const yaml::MachineFunction &YamlMF);
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric   bool initializeFrameInfo(PerFunctionMIParsingState &PFS,
1250b57cec5SDimitry Andric                            const yaml::MachineFunction &YamlMF);
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric   bool initializeCallSiteInfo(PerFunctionMIParsingState &PFS,
1280b57cec5SDimitry Andric                               const yaml::MachineFunction &YamlMF);
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric   bool parseCalleeSavedRegister(PerFunctionMIParsingState &PFS,
1310b57cec5SDimitry Andric                                 std::vector<CalleeSavedInfo> &CSIInfo,
1320b57cec5SDimitry Andric                                 const yaml::StringValue &RegisterSource,
1330b57cec5SDimitry Andric                                 bool IsRestored, int FrameIdx);
1340b57cec5SDimitry Andric 
13506c3fb27SDimitry Andric   struct VarExprLoc {
13606c3fb27SDimitry Andric     DILocalVariable *DIVar = nullptr;
13706c3fb27SDimitry Andric     DIExpression *DIExpr = nullptr;
13806c3fb27SDimitry Andric     DILocation *DILoc = nullptr;
13906c3fb27SDimitry Andric   };
14006c3fb27SDimitry Andric 
14106c3fb27SDimitry Andric   std::optional<VarExprLoc> parseVarExprLoc(PerFunctionMIParsingState &PFS,
14206c3fb27SDimitry Andric                                             const yaml::StringValue &VarStr,
14306c3fb27SDimitry Andric                                             const yaml::StringValue &ExprStr,
14406c3fb27SDimitry Andric                                             const yaml::StringValue &LocStr);
1450b57cec5SDimitry Andric   template <typename T>
1460b57cec5SDimitry Andric   bool parseStackObjectsDebugInfo(PerFunctionMIParsingState &PFS,
1470b57cec5SDimitry Andric                                   const T &Object,
1480b57cec5SDimitry Andric                                   int FrameIdx);
1490b57cec5SDimitry Andric 
1500b57cec5SDimitry Andric   bool initializeConstantPool(PerFunctionMIParsingState &PFS,
1510b57cec5SDimitry Andric                               MachineConstantPool &ConstantPool,
1520b57cec5SDimitry Andric                               const yaml::MachineFunction &YamlMF);
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric   bool initializeJumpTableInfo(PerFunctionMIParsingState &PFS,
1550b57cec5SDimitry Andric                                const yaml::MachineJumpTable &YamlJTI);
1560b57cec5SDimitry Andric 
157fe6060f1SDimitry Andric   bool parseMachineMetadataNodes(PerFunctionMIParsingState &PFS,
158fe6060f1SDimitry Andric                                  MachineFunction &MF,
159fe6060f1SDimitry Andric                                  const yaml::MachineFunction &YMF);
160fe6060f1SDimitry Andric 
1610b57cec5SDimitry Andric private:
1620b57cec5SDimitry Andric   bool parseMDNode(PerFunctionMIParsingState &PFS, MDNode *&Node,
1630b57cec5SDimitry Andric                    const yaml::StringValue &Source);
1640b57cec5SDimitry Andric 
1650b57cec5SDimitry Andric   bool parseMBBReference(PerFunctionMIParsingState &PFS,
1660b57cec5SDimitry Andric                          MachineBasicBlock *&MBB,
1670b57cec5SDimitry Andric                          const yaml::StringValue &Source);
1680b57cec5SDimitry Andric 
169fe6060f1SDimitry Andric   bool parseMachineMetadata(PerFunctionMIParsingState &PFS,
170fe6060f1SDimitry Andric                             const yaml::StringValue &Source);
171fe6060f1SDimitry Andric 
1720b57cec5SDimitry Andric   /// Return a MIR diagnostic converted from an MI string diagnostic.
1730b57cec5SDimitry Andric   SMDiagnostic diagFromMIStringDiag(const SMDiagnostic &Error,
1740b57cec5SDimitry Andric                                     SMRange SourceRange);
1750b57cec5SDimitry Andric 
1760b57cec5SDimitry Andric   /// Return a MIR diagnostic converted from a diagnostic located in a YAML
1770b57cec5SDimitry Andric   /// block scalar string.
1780b57cec5SDimitry Andric   SMDiagnostic diagFromBlockStringDiag(const SMDiagnostic &Error,
1790b57cec5SDimitry Andric                                        SMRange SourceRange);
1800b57cec5SDimitry Andric 
1810b57cec5SDimitry Andric   void computeFunctionProperties(MachineFunction &MF);
182e8d8bef9SDimitry Andric 
183e8d8bef9SDimitry Andric   void setupDebugValueTracking(MachineFunction &MF,
184e8d8bef9SDimitry Andric     PerFunctionMIParsingState &PFS, const yaml::MachineFunction &YamlMF);
1850b57cec5SDimitry Andric };
1860b57cec5SDimitry Andric 
1870b57cec5SDimitry Andric } // end namespace llvm
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric static void handleYAMLDiag(const SMDiagnostic &Diag, void *Context) {
1900b57cec5SDimitry Andric   reinterpret_cast<MIRParserImpl *>(Context)->reportDiagnostic(Diag);
1910b57cec5SDimitry Andric }
1920b57cec5SDimitry Andric 
1930b57cec5SDimitry Andric MIRParserImpl::MIRParserImpl(std::unique_ptr<MemoryBuffer> Contents,
194480093f4SDimitry Andric                              StringRef Filename, LLVMContext &Context,
195480093f4SDimitry Andric                              std::function<void(Function &)> Callback)
19604eeddc0SDimitry Andric     : Context(Context),
197480093f4SDimitry Andric       In(SM.getMemoryBuffer(SM.AddNewSourceBuffer(std::move(Contents), SMLoc()))
198480093f4SDimitry Andric              ->getBuffer(),
1990b57cec5SDimitry Andric          nullptr, handleYAMLDiag, this),
200fe6060f1SDimitry Andric       Filename(Filename), ProcessIRFunction(Callback) {
2010b57cec5SDimitry Andric   In.setContext(&In);
2020b57cec5SDimitry Andric }
2030b57cec5SDimitry Andric 
2040b57cec5SDimitry Andric bool MIRParserImpl::error(const Twine &Message) {
2050b57cec5SDimitry Andric   Context.diagnose(DiagnosticInfoMIRParser(
2060b57cec5SDimitry Andric       DS_Error, SMDiagnostic(Filename, SourceMgr::DK_Error, Message.str())));
2070b57cec5SDimitry Andric   return true;
2080b57cec5SDimitry Andric }
2090b57cec5SDimitry Andric 
2100b57cec5SDimitry Andric bool MIRParserImpl::error(SMLoc Loc, const Twine &Message) {
2110b57cec5SDimitry Andric   Context.diagnose(DiagnosticInfoMIRParser(
2120b57cec5SDimitry Andric       DS_Error, SM.GetMessage(Loc, SourceMgr::DK_Error, Message)));
2130b57cec5SDimitry Andric   return true;
2140b57cec5SDimitry Andric }
2150b57cec5SDimitry Andric 
2160b57cec5SDimitry Andric bool MIRParserImpl::error(const SMDiagnostic &Error, SMRange SourceRange) {
2170b57cec5SDimitry Andric   assert(Error.getKind() == SourceMgr::DK_Error && "Expected an error");
2180b57cec5SDimitry Andric   reportDiagnostic(diagFromMIStringDiag(Error, SourceRange));
2190b57cec5SDimitry Andric   return true;
2200b57cec5SDimitry Andric }
2210b57cec5SDimitry Andric 
2220b57cec5SDimitry Andric void MIRParserImpl::reportDiagnostic(const SMDiagnostic &Diag) {
2230b57cec5SDimitry Andric   DiagnosticSeverity Kind;
2240b57cec5SDimitry Andric   switch (Diag.getKind()) {
2250b57cec5SDimitry Andric   case SourceMgr::DK_Error:
2260b57cec5SDimitry Andric     Kind = DS_Error;
2270b57cec5SDimitry Andric     break;
2280b57cec5SDimitry Andric   case SourceMgr::DK_Warning:
2290b57cec5SDimitry Andric     Kind = DS_Warning;
2300b57cec5SDimitry Andric     break;
2310b57cec5SDimitry Andric   case SourceMgr::DK_Note:
2320b57cec5SDimitry Andric     Kind = DS_Note;
2330b57cec5SDimitry Andric     break;
2340b57cec5SDimitry Andric   case SourceMgr::DK_Remark:
2350b57cec5SDimitry Andric     llvm_unreachable("remark unexpected");
2360b57cec5SDimitry Andric     break;
2370b57cec5SDimitry Andric   }
2380b57cec5SDimitry Andric   Context.diagnose(DiagnosticInfoMIRParser(Kind, Diag));
2390b57cec5SDimitry Andric }
2400b57cec5SDimitry Andric 
2415ffd83dbSDimitry Andric std::unique_ptr<Module>
2425ffd83dbSDimitry Andric MIRParserImpl::parseIRModule(DataLayoutCallbackTy DataLayoutCallback) {
2430b57cec5SDimitry Andric   if (!In.setCurrentDocument()) {
2440b57cec5SDimitry Andric     if (In.error())
2450b57cec5SDimitry Andric       return nullptr;
2460b57cec5SDimitry Andric     // Create an empty module when the MIR file is empty.
2470b57cec5SDimitry Andric     NoMIRDocuments = true;
2485ffd83dbSDimitry Andric     auto M = std::make_unique<Module>(Filename, Context);
249bdd1243dSDimitry Andric     if (auto LayoutOverride =
250bdd1243dSDimitry Andric             DataLayoutCallback(M->getTargetTriple(), M->getDataLayoutStr()))
2515ffd83dbSDimitry Andric       M->setDataLayout(*LayoutOverride);
2525ffd83dbSDimitry Andric     return M;
2530b57cec5SDimitry Andric   }
2540b57cec5SDimitry Andric 
2550b57cec5SDimitry Andric   std::unique_ptr<Module> M;
2560b57cec5SDimitry Andric   // Parse the block scalar manually so that we can return unique pointer
2570b57cec5SDimitry Andric   // without having to go trough YAML traits.
2580b57cec5SDimitry Andric   if (const auto *BSN =
2590b57cec5SDimitry Andric           dyn_cast_or_null<yaml::BlockScalarNode>(In.getCurrentNode())) {
2600b57cec5SDimitry Andric     SMDiagnostic Error;
2610b57cec5SDimitry Andric     M = parseAssembly(MemoryBufferRef(BSN->getValue(), Filename), Error,
2625ffd83dbSDimitry Andric                       Context, &IRSlots, DataLayoutCallback);
2630b57cec5SDimitry Andric     if (!M) {
2640b57cec5SDimitry Andric       reportDiagnostic(diagFromBlockStringDiag(Error, BSN->getSourceRange()));
2650b57cec5SDimitry Andric       return nullptr;
2660b57cec5SDimitry Andric     }
2670b57cec5SDimitry Andric     In.nextDocument();
2680b57cec5SDimitry Andric     if (!In.setCurrentDocument())
2690b57cec5SDimitry Andric       NoMIRDocuments = true;
2700b57cec5SDimitry Andric   } else {
2710b57cec5SDimitry Andric     // Create an new, empty module.
2728bcb0991SDimitry Andric     M = std::make_unique<Module>(Filename, Context);
273bdd1243dSDimitry Andric     if (auto LayoutOverride =
274bdd1243dSDimitry Andric             DataLayoutCallback(M->getTargetTriple(), M->getDataLayoutStr()))
2755ffd83dbSDimitry Andric       M->setDataLayout(*LayoutOverride);
2760b57cec5SDimitry Andric     NoLLVMIR = true;
2770b57cec5SDimitry Andric   }
2780b57cec5SDimitry Andric   return M;
2790b57cec5SDimitry Andric }
2800b57cec5SDimitry Andric 
281*0fca6ea1SDimitry Andric bool MIRParserImpl::parseMachineFunctions(Module &M, MachineModuleInfo &MMI,
282*0fca6ea1SDimitry Andric                                           ModuleAnalysisManager *MAM) {
2830b57cec5SDimitry Andric   if (NoMIRDocuments)
2840b57cec5SDimitry Andric     return false;
2850b57cec5SDimitry Andric 
2860b57cec5SDimitry Andric   // Parse the machine functions.
2870b57cec5SDimitry Andric   do {
288*0fca6ea1SDimitry Andric     if (parseMachineFunction(M, MMI, MAM))
2890b57cec5SDimitry Andric       return true;
2900b57cec5SDimitry Andric     In.nextDocument();
2910b57cec5SDimitry Andric   } while (In.setCurrentDocument());
2920b57cec5SDimitry Andric 
2930b57cec5SDimitry Andric   return false;
2940b57cec5SDimitry Andric }
2950b57cec5SDimitry Andric 
296480093f4SDimitry Andric Function *MIRParserImpl::createDummyFunction(StringRef Name, Module &M) {
2970b57cec5SDimitry Andric   auto &Context = M.getContext();
2980b57cec5SDimitry Andric   Function *F =
2990b57cec5SDimitry Andric       Function::Create(FunctionType::get(Type::getVoidTy(Context), false),
3000b57cec5SDimitry Andric                        Function::ExternalLinkage, Name, M);
3010b57cec5SDimitry Andric   BasicBlock *BB = BasicBlock::Create(Context, "entry", F);
3020b57cec5SDimitry Andric   new UnreachableInst(Context, BB);
303480093f4SDimitry Andric 
304480093f4SDimitry Andric   if (ProcessIRFunction)
305480093f4SDimitry Andric     ProcessIRFunction(*F);
306480093f4SDimitry Andric 
3070b57cec5SDimitry Andric   return F;
3080b57cec5SDimitry Andric }
3090b57cec5SDimitry Andric 
310*0fca6ea1SDimitry Andric bool MIRParserImpl::parseMachineFunction(Module &M, MachineModuleInfo &MMI,
311*0fca6ea1SDimitry Andric                                          ModuleAnalysisManager *MAM) {
3120b57cec5SDimitry Andric   // Parse the yaml.
3130b57cec5SDimitry Andric   yaml::MachineFunction YamlMF;
3140b57cec5SDimitry Andric   yaml::EmptyContext Ctx;
3150b57cec5SDimitry Andric 
3160b57cec5SDimitry Andric   const LLVMTargetMachine &TM = MMI.getTarget();
3170b57cec5SDimitry Andric   YamlMF.MachineFuncInfo = std::unique_ptr<yaml::MachineFunctionInfo>(
3180b57cec5SDimitry Andric       TM.createDefaultFuncInfoYAML());
3190b57cec5SDimitry Andric 
3200b57cec5SDimitry Andric   yaml::yamlize(In, YamlMF, false, Ctx);
3210b57cec5SDimitry Andric   if (In.error())
3220b57cec5SDimitry Andric     return true;
3230b57cec5SDimitry Andric 
3240b57cec5SDimitry Andric   // Search for the corresponding IR function.
3250b57cec5SDimitry Andric   StringRef FunctionName = YamlMF.Name;
3260b57cec5SDimitry Andric   Function *F = M.getFunction(FunctionName);
3270b57cec5SDimitry Andric   if (!F) {
3280b57cec5SDimitry Andric     if (NoLLVMIR) {
3290b57cec5SDimitry Andric       F = createDummyFunction(FunctionName, M);
3300b57cec5SDimitry Andric     } else {
3310b57cec5SDimitry Andric       return error(Twine("function '") + FunctionName +
3320b57cec5SDimitry Andric                    "' isn't defined in the provided LLVM IR");
3330b57cec5SDimitry Andric     }
3340b57cec5SDimitry Andric   }
335*0fca6ea1SDimitry Andric 
336*0fca6ea1SDimitry Andric   if (!MAM) {
3370b57cec5SDimitry Andric     if (MMI.getMachineFunction(*F) != nullptr)
3380b57cec5SDimitry Andric       return error(Twine("redefinition of machine function '") + FunctionName +
3390b57cec5SDimitry Andric                    "'");
3400b57cec5SDimitry Andric 
3410b57cec5SDimitry Andric     // Create the MachineFunction.
3420b57cec5SDimitry Andric     MachineFunction &MF = MMI.getOrCreateMachineFunction(*F);
3430b57cec5SDimitry Andric     if (initializeMachineFunction(YamlMF, MF))
3440b57cec5SDimitry Andric       return true;
345*0fca6ea1SDimitry Andric   } else {
346*0fca6ea1SDimitry Andric     auto &FAM =
347*0fca6ea1SDimitry Andric         MAM->getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
348*0fca6ea1SDimitry Andric     if (FAM.getCachedResult<MachineFunctionAnalysis>(*F))
349*0fca6ea1SDimitry Andric       return error(Twine("redefinition of machine function '") + FunctionName +
350*0fca6ea1SDimitry Andric                    "'");
351*0fca6ea1SDimitry Andric 
352*0fca6ea1SDimitry Andric     // Create the MachineFunction.
353*0fca6ea1SDimitry Andric     MachineFunction &MF = FAM.getResult<MachineFunctionAnalysis>(*F).getMF();
354*0fca6ea1SDimitry Andric     if (initializeMachineFunction(YamlMF, MF))
355*0fca6ea1SDimitry Andric       return true;
356*0fca6ea1SDimitry Andric   }
3570b57cec5SDimitry Andric 
3580b57cec5SDimitry Andric   return false;
3590b57cec5SDimitry Andric }
3600b57cec5SDimitry Andric 
3610b57cec5SDimitry Andric static bool isSSA(const MachineFunction &MF) {
3620b57cec5SDimitry Andric   const MachineRegisterInfo &MRI = MF.getRegInfo();
3630b57cec5SDimitry Andric   for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
364e8d8bef9SDimitry Andric     Register Reg = Register::index2VirtReg(I);
3650b57cec5SDimitry Andric     if (!MRI.hasOneDef(Reg) && !MRI.def_empty(Reg))
3660b57cec5SDimitry Andric       return false;
367e8d8bef9SDimitry Andric 
368e8d8bef9SDimitry Andric     // Subregister defs are invalid in SSA.
369e8d8bef9SDimitry Andric     const MachineOperand *RegDef = MRI.getOneDef(Reg);
370e8d8bef9SDimitry Andric     if (RegDef && RegDef->getSubReg() != 0)
371e8d8bef9SDimitry Andric       return false;
3720b57cec5SDimitry Andric   }
3730b57cec5SDimitry Andric   return true;
3740b57cec5SDimitry Andric }
3750b57cec5SDimitry Andric 
3760b57cec5SDimitry Andric void MIRParserImpl::computeFunctionProperties(MachineFunction &MF) {
3770b57cec5SDimitry Andric   MachineFunctionProperties &Properties = MF.getProperties();
3780b57cec5SDimitry Andric 
3790b57cec5SDimitry Andric   bool HasPHI = false;
3800b57cec5SDimitry Andric   bool HasInlineAsm = false;
3810eae32dcSDimitry Andric   bool AllTiedOpsRewritten = true, HasTiedOps = false;
3820b57cec5SDimitry Andric   for (const MachineBasicBlock &MBB : MF) {
3830b57cec5SDimitry Andric     for (const MachineInstr &MI : MBB) {
3840b57cec5SDimitry Andric       if (MI.isPHI())
3850b57cec5SDimitry Andric         HasPHI = true;
3860b57cec5SDimitry Andric       if (MI.isInlineAsm())
3870b57cec5SDimitry Andric         HasInlineAsm = true;
3880eae32dcSDimitry Andric       for (unsigned I = 0; I < MI.getNumOperands(); ++I) {
3890eae32dcSDimitry Andric         const MachineOperand &MO = MI.getOperand(I);
3900eae32dcSDimitry Andric         if (!MO.isReg() || !MO.getReg())
3910eae32dcSDimitry Andric           continue;
3920eae32dcSDimitry Andric         unsigned DefIdx;
3930eae32dcSDimitry Andric         if (MO.isUse() && MI.isRegTiedToDefOperand(I, &DefIdx)) {
3940eae32dcSDimitry Andric           HasTiedOps = true;
3950eae32dcSDimitry Andric           if (MO.getReg() != MI.getOperand(DefIdx).getReg())
3960eae32dcSDimitry Andric             AllTiedOpsRewritten = false;
3970eae32dcSDimitry Andric         }
3980eae32dcSDimitry Andric       }
3990b57cec5SDimitry Andric     }
4000b57cec5SDimitry Andric   }
4010b57cec5SDimitry Andric   if (!HasPHI)
4020b57cec5SDimitry Andric     Properties.set(MachineFunctionProperties::Property::NoPHIs);
4030b57cec5SDimitry Andric   MF.setHasInlineAsm(HasInlineAsm);
4040b57cec5SDimitry Andric 
4050eae32dcSDimitry Andric   if (HasTiedOps && AllTiedOpsRewritten)
4060eae32dcSDimitry Andric     Properties.set(MachineFunctionProperties::Property::TiedOpsRewritten);
4070eae32dcSDimitry Andric 
4080b57cec5SDimitry Andric   if (isSSA(MF))
4090b57cec5SDimitry Andric     Properties.set(MachineFunctionProperties::Property::IsSSA);
4100b57cec5SDimitry Andric   else
4110b57cec5SDimitry Andric     Properties.reset(MachineFunctionProperties::Property::IsSSA);
4120b57cec5SDimitry Andric 
4130b57cec5SDimitry Andric   const MachineRegisterInfo &MRI = MF.getRegInfo();
4140b57cec5SDimitry Andric   if (MRI.getNumVirtRegs() == 0)
4150b57cec5SDimitry Andric     Properties.set(MachineFunctionProperties::Property::NoVRegs);
4160b57cec5SDimitry Andric }
4170b57cec5SDimitry Andric 
4180b57cec5SDimitry Andric bool MIRParserImpl::initializeCallSiteInfo(
4190b57cec5SDimitry Andric     PerFunctionMIParsingState &PFS, const yaml::MachineFunction &YamlMF) {
4200b57cec5SDimitry Andric   MachineFunction &MF = PFS.MF;
4210b57cec5SDimitry Andric   SMDiagnostic Error;
4220b57cec5SDimitry Andric   const LLVMTargetMachine &TM = MF.getTarget();
42306c3fb27SDimitry Andric   for (auto &YamlCSInfo : YamlMF.CallSitesInfo) {
4240b57cec5SDimitry Andric     yaml::CallSiteInfo::MachineInstrLoc MILoc = YamlCSInfo.CallLocation;
4250b57cec5SDimitry Andric     if (MILoc.BlockNum >= MF.size())
4260b57cec5SDimitry Andric       return error(Twine(MF.getName()) +
4270b57cec5SDimitry Andric                    Twine(" call instruction block out of range.") +
4280b57cec5SDimitry Andric                    " Unable to reference bb:" + Twine(MILoc.BlockNum));
4290b57cec5SDimitry Andric     auto CallB = std::next(MF.begin(), MILoc.BlockNum);
4300b57cec5SDimitry Andric     if (MILoc.Offset >= CallB->size())
4310b57cec5SDimitry Andric       return error(Twine(MF.getName()) +
4320b57cec5SDimitry Andric                    Twine(" call instruction offset out of range.") +
4330b57cec5SDimitry Andric                    " Unable to reference instruction at bb: " +
4340b57cec5SDimitry Andric                    Twine(MILoc.BlockNum) + " at offset:" + Twine(MILoc.Offset));
4358bcb0991SDimitry Andric     auto CallI = std::next(CallB->instr_begin(), MILoc.Offset);
4368bcb0991SDimitry Andric     if (!CallI->isCall(MachineInstr::IgnoreBundle))
4370b57cec5SDimitry Andric       return error(Twine(MF.getName()) +
4380b57cec5SDimitry Andric                    Twine(" call site info should reference call "
4390b57cec5SDimitry Andric                          "instruction. Instruction at bb:") +
4400b57cec5SDimitry Andric                    Twine(MILoc.BlockNum) + " at offset:" + Twine(MILoc.Offset) +
4410b57cec5SDimitry Andric                    " is not a call instruction");
4420b57cec5SDimitry Andric     MachineFunction::CallSiteInfo CSInfo;
4430b57cec5SDimitry Andric     for (auto ArgRegPair : YamlCSInfo.ArgForwardingRegs) {
4445ffd83dbSDimitry Andric       Register Reg;
4450b57cec5SDimitry Andric       if (parseNamedRegisterReference(PFS, Reg, ArgRegPair.Reg.Value, Error))
4460b57cec5SDimitry Andric         return error(Error, ArgRegPair.Reg.SourceRange);
447*0fca6ea1SDimitry Andric       CSInfo.ArgRegPairs.emplace_back(Reg, ArgRegPair.ArgNo);
4480b57cec5SDimitry Andric     }
4490b57cec5SDimitry Andric 
4505ffd83dbSDimitry Andric     if (TM.Options.EmitCallSiteInfo)
451*0fca6ea1SDimitry Andric       MF.addCallSiteInfo(&*CallI, std::move(CSInfo));
4520b57cec5SDimitry Andric   }
4530b57cec5SDimitry Andric 
4545ffd83dbSDimitry Andric   if (YamlMF.CallSitesInfo.size() && !TM.Options.EmitCallSiteInfo)
4550b57cec5SDimitry Andric     return error(Twine("Call site info provided but not used"));
4560b57cec5SDimitry Andric   return false;
4570b57cec5SDimitry Andric }
4580b57cec5SDimitry Andric 
459e8d8bef9SDimitry Andric void MIRParserImpl::setupDebugValueTracking(
460e8d8bef9SDimitry Andric     MachineFunction &MF, PerFunctionMIParsingState &PFS,
461e8d8bef9SDimitry Andric     const yaml::MachineFunction &YamlMF) {
462e8d8bef9SDimitry Andric   // Compute the value of the "next instruction number" field.
463e8d8bef9SDimitry Andric   unsigned MaxInstrNum = 0;
464e8d8bef9SDimitry Andric   for (auto &MBB : MF)
465e8d8bef9SDimitry Andric     for (auto &MI : MBB)
466e8d8bef9SDimitry Andric       MaxInstrNum = std::max((unsigned)MI.peekDebugInstrNum(), MaxInstrNum);
467e8d8bef9SDimitry Andric   MF.setDebugInstrNumberingCount(MaxInstrNum);
468e8d8bef9SDimitry Andric 
469e8d8bef9SDimitry Andric   // Load any substitutions.
470fcaf7f86SDimitry Andric   for (const auto &Sub : YamlMF.DebugValueSubstitutions) {
471fe6060f1SDimitry Andric     MF.makeDebugValueSubstitution({Sub.SrcInst, Sub.SrcOp},
472fe6060f1SDimitry Andric                                   {Sub.DstInst, Sub.DstOp}, Sub.Subreg);
473e8d8bef9SDimitry Andric   }
474bdd1243dSDimitry Andric 
475bdd1243dSDimitry Andric   // Flag for whether we're supposed to be using DBG_INSTR_REF.
476bdd1243dSDimitry Andric   MF.setUseDebugInstrRef(YamlMF.UseDebugInstrRef);
477e8d8bef9SDimitry Andric }
478e8d8bef9SDimitry Andric 
4790b57cec5SDimitry Andric bool
4800b57cec5SDimitry Andric MIRParserImpl::initializeMachineFunction(const yaml::MachineFunction &YamlMF,
4810b57cec5SDimitry Andric                                          MachineFunction &MF) {
4820b57cec5SDimitry Andric   // TODO: Recreate the machine function.
4830b57cec5SDimitry Andric   if (Target) {
4840b57cec5SDimitry Andric     // Avoid clearing state if we're using the same subtarget again.
4850b57cec5SDimitry Andric     Target->setTarget(MF.getSubtarget());
4860b57cec5SDimitry Andric   } else {
4870b57cec5SDimitry Andric     Target.reset(new PerTargetMIParsingState(MF.getSubtarget()));
4880b57cec5SDimitry Andric   }
4890b57cec5SDimitry Andric 
4905ffd83dbSDimitry Andric   MF.setAlignment(YamlMF.Alignment.valueOrOne());
4910b57cec5SDimitry Andric   MF.setExposesReturnsTwice(YamlMF.ExposesReturnsTwice);
4920b57cec5SDimitry Andric   MF.setHasWinCFI(YamlMF.HasWinCFI);
4930b57cec5SDimitry Andric 
49481ad6265SDimitry Andric   MF.setCallsEHReturn(YamlMF.CallsEHReturn);
49581ad6265SDimitry Andric   MF.setCallsUnwindInit(YamlMF.CallsUnwindInit);
49681ad6265SDimitry Andric   MF.setHasEHCatchret(YamlMF.HasEHCatchret);
49781ad6265SDimitry Andric   MF.setHasEHScopes(YamlMF.HasEHScopes);
49881ad6265SDimitry Andric   MF.setHasEHFunclets(YamlMF.HasEHFunclets);
49906c3fb27SDimitry Andric   MF.setIsOutlined(YamlMF.IsOutlined);
50081ad6265SDimitry Andric 
5010b57cec5SDimitry Andric   if (YamlMF.Legalized)
5020b57cec5SDimitry Andric     MF.getProperties().set(MachineFunctionProperties::Property::Legalized);
5030b57cec5SDimitry Andric   if (YamlMF.RegBankSelected)
5040b57cec5SDimitry Andric     MF.getProperties().set(
5050b57cec5SDimitry Andric         MachineFunctionProperties::Property::RegBankSelected);
5060b57cec5SDimitry Andric   if (YamlMF.Selected)
5070b57cec5SDimitry Andric     MF.getProperties().set(MachineFunctionProperties::Property::Selected);
5080b57cec5SDimitry Andric   if (YamlMF.FailedISel)
5090b57cec5SDimitry Andric     MF.getProperties().set(MachineFunctionProperties::Property::FailedISel);
510349cc55cSDimitry Andric   if (YamlMF.FailsVerification)
511349cc55cSDimitry Andric     MF.getProperties().set(
512349cc55cSDimitry Andric         MachineFunctionProperties::Property::FailsVerification);
5130eae32dcSDimitry Andric   if (YamlMF.TracksDebugUserValues)
5140eae32dcSDimitry Andric     MF.getProperties().set(
5150eae32dcSDimitry Andric         MachineFunctionProperties::Property::TracksDebugUserValues);
5160b57cec5SDimitry Andric 
5170b57cec5SDimitry Andric   PerFunctionMIParsingState PFS(MF, SM, IRSlots, *Target);
5180b57cec5SDimitry Andric   if (parseRegisterInfo(PFS, YamlMF))
5190b57cec5SDimitry Andric     return true;
5200b57cec5SDimitry Andric   if (!YamlMF.Constants.empty()) {
5210b57cec5SDimitry Andric     auto *ConstantPool = MF.getConstantPool();
5220b57cec5SDimitry Andric     assert(ConstantPool && "Constant pool must be created");
5230b57cec5SDimitry Andric     if (initializeConstantPool(PFS, *ConstantPool, YamlMF))
5240b57cec5SDimitry Andric       return true;
5250b57cec5SDimitry Andric   }
526fe6060f1SDimitry Andric   if (!YamlMF.MachineMetadataNodes.empty() &&
527fe6060f1SDimitry Andric       parseMachineMetadataNodes(PFS, MF, YamlMF))
528fe6060f1SDimitry Andric     return true;
5290b57cec5SDimitry Andric 
5300b57cec5SDimitry Andric   StringRef BlockStr = YamlMF.Body.Value.Value;
5310b57cec5SDimitry Andric   SMDiagnostic Error;
5320b57cec5SDimitry Andric   SourceMgr BlockSM;
5330b57cec5SDimitry Andric   BlockSM.AddNewSourceBuffer(
5340b57cec5SDimitry Andric       MemoryBuffer::getMemBuffer(BlockStr, "",/*RequiresNullTerminator=*/false),
5350b57cec5SDimitry Andric       SMLoc());
5360b57cec5SDimitry Andric   PFS.SM = &BlockSM;
5370b57cec5SDimitry Andric   if (parseMachineBasicBlockDefinitions(PFS, BlockStr, Error)) {
5380b57cec5SDimitry Andric     reportDiagnostic(
5390b57cec5SDimitry Andric         diagFromBlockStringDiag(Error, YamlMF.Body.Value.SourceRange));
5400b57cec5SDimitry Andric     return true;
5410b57cec5SDimitry Andric   }
5425ffd83dbSDimitry Andric   // Check Basic Block Section Flags.
5435ffd83dbSDimitry Andric   if (MF.getTarget().getBBSectionsType() == BasicBlockSection::Labels) {
5445ffd83dbSDimitry Andric     MF.setBBSectionsType(BasicBlockSection::Labels);
5455ffd83dbSDimitry Andric   } else if (MF.hasBBSections()) {
5465ffd83dbSDimitry Andric     MF.assignBeginEndSections();
5475ffd83dbSDimitry Andric   }
5480b57cec5SDimitry Andric   PFS.SM = &SM;
5490b57cec5SDimitry Andric 
5500b57cec5SDimitry Andric   // Initialize the frame information after creating all the MBBs so that the
5510b57cec5SDimitry Andric   // MBB references in the frame information can be resolved.
5520b57cec5SDimitry Andric   if (initializeFrameInfo(PFS, YamlMF))
5530b57cec5SDimitry Andric     return true;
5540b57cec5SDimitry Andric   // Initialize the jump table after creating all the MBBs so that the MBB
5550b57cec5SDimitry Andric   // references can be resolved.
5560b57cec5SDimitry Andric   if (!YamlMF.JumpTableInfo.Entries.empty() &&
5570b57cec5SDimitry Andric       initializeJumpTableInfo(PFS, YamlMF.JumpTableInfo))
5580b57cec5SDimitry Andric     return true;
5590b57cec5SDimitry Andric   // Parse the machine instructions after creating all of the MBBs so that the
5600b57cec5SDimitry Andric   // parser can resolve the MBB references.
5610b57cec5SDimitry Andric   StringRef InsnStr = YamlMF.Body.Value.Value;
5620b57cec5SDimitry Andric   SourceMgr InsnSM;
5630b57cec5SDimitry Andric   InsnSM.AddNewSourceBuffer(
5640b57cec5SDimitry Andric       MemoryBuffer::getMemBuffer(InsnStr, "", /*RequiresNullTerminator=*/false),
5650b57cec5SDimitry Andric       SMLoc());
5660b57cec5SDimitry Andric   PFS.SM = &InsnSM;
5670b57cec5SDimitry Andric   if (parseMachineInstructions(PFS, InsnStr, Error)) {
5680b57cec5SDimitry Andric     reportDiagnostic(
5690b57cec5SDimitry Andric         diagFromBlockStringDiag(Error, YamlMF.Body.Value.SourceRange));
5700b57cec5SDimitry Andric     return true;
5710b57cec5SDimitry Andric   }
5720b57cec5SDimitry Andric   PFS.SM = &SM;
5730b57cec5SDimitry Andric 
5740b57cec5SDimitry Andric   if (setupRegisterInfo(PFS, YamlMF))
5750b57cec5SDimitry Andric     return true;
5760b57cec5SDimitry Andric 
5770b57cec5SDimitry Andric   if (YamlMF.MachineFuncInfo) {
5780b57cec5SDimitry Andric     const LLVMTargetMachine &TM = MF.getTarget();
5790b57cec5SDimitry Andric     // Note this is called after the initial constructor of the
5800b57cec5SDimitry Andric     // MachineFunctionInfo based on the MachineFunction, which may depend on the
5810b57cec5SDimitry Andric     // IR.
5820b57cec5SDimitry Andric 
5830b57cec5SDimitry Andric     SMRange SrcRange;
5840b57cec5SDimitry Andric     if (TM.parseMachineFunctionInfo(*YamlMF.MachineFuncInfo, PFS, Error,
5850b57cec5SDimitry Andric                                     SrcRange)) {
5860b57cec5SDimitry Andric       return error(Error, SrcRange);
5870b57cec5SDimitry Andric     }
5880b57cec5SDimitry Andric   }
5890b57cec5SDimitry Andric 
5900b57cec5SDimitry Andric   // Set the reserved registers after parsing MachineFuncInfo. The target may
5910b57cec5SDimitry Andric   // have been recording information used to select the reserved registers
5920b57cec5SDimitry Andric   // there.
5930b57cec5SDimitry Andric   // FIXME: This is a temporary workaround until the reserved registers can be
5940b57cec5SDimitry Andric   // serialized.
5950b57cec5SDimitry Andric   MachineRegisterInfo &MRI = MF.getRegInfo();
596*0fca6ea1SDimitry Andric   MRI.freezeReservedRegs();
5970b57cec5SDimitry Andric 
5980b57cec5SDimitry Andric   computeFunctionProperties(MF);
5990b57cec5SDimitry Andric 
6000b57cec5SDimitry Andric   if (initializeCallSiteInfo(PFS, YamlMF))
6010b57cec5SDimitry Andric     return false;
6020b57cec5SDimitry Andric 
603e8d8bef9SDimitry Andric   setupDebugValueTracking(MF, PFS, YamlMF);
604e8d8bef9SDimitry Andric 
6050b57cec5SDimitry Andric   MF.getSubtarget().mirFileLoaded(MF);
6060b57cec5SDimitry Andric 
6070b57cec5SDimitry Andric   MF.verify();
6080b57cec5SDimitry Andric   return false;
6090b57cec5SDimitry Andric }
6100b57cec5SDimitry Andric 
6110b57cec5SDimitry Andric bool MIRParserImpl::parseRegisterInfo(PerFunctionMIParsingState &PFS,
6120b57cec5SDimitry Andric                                       const yaml::MachineFunction &YamlMF) {
6130b57cec5SDimitry Andric   MachineFunction &MF = PFS.MF;
6140b57cec5SDimitry Andric   MachineRegisterInfo &RegInfo = MF.getRegInfo();
6150b57cec5SDimitry Andric   assert(RegInfo.tracksLiveness());
6160b57cec5SDimitry Andric   if (!YamlMF.TracksRegLiveness)
6170b57cec5SDimitry Andric     RegInfo.invalidateLiveness();
6180b57cec5SDimitry Andric 
6190b57cec5SDimitry Andric   SMDiagnostic Error;
6200b57cec5SDimitry Andric   // Parse the virtual register information.
6210b57cec5SDimitry Andric   for (const auto &VReg : YamlMF.VirtualRegisters) {
6220b57cec5SDimitry Andric     VRegInfo &Info = PFS.getVRegInfo(VReg.ID.Value);
6230b57cec5SDimitry Andric     if (Info.Explicit)
6240b57cec5SDimitry Andric       return error(VReg.ID.SourceRange.Start,
6250b57cec5SDimitry Andric                    Twine("redefinition of virtual register '%") +
6260b57cec5SDimitry Andric                        Twine(VReg.ID.Value) + "'");
6270b57cec5SDimitry Andric     Info.Explicit = true;
6280b57cec5SDimitry Andric 
629*0fca6ea1SDimitry Andric     if (VReg.Class.Value == "_") {
6300b57cec5SDimitry Andric       Info.Kind = VRegInfo::GENERIC;
6310b57cec5SDimitry Andric       Info.D.RegBank = nullptr;
6320b57cec5SDimitry Andric     } else {
6330b57cec5SDimitry Andric       const auto *RC = Target->getRegClass(VReg.Class.Value);
6340b57cec5SDimitry Andric       if (RC) {
6350b57cec5SDimitry Andric         Info.Kind = VRegInfo::NORMAL;
6360b57cec5SDimitry Andric         Info.D.RC = RC;
6370b57cec5SDimitry Andric       } else {
6380b57cec5SDimitry Andric         const RegisterBank *RegBank = Target->getRegBank(VReg.Class.Value);
6390b57cec5SDimitry Andric         if (!RegBank)
6400b57cec5SDimitry Andric           return error(
6410b57cec5SDimitry Andric               VReg.Class.SourceRange.Start,
6420b57cec5SDimitry Andric               Twine("use of undefined register class or register bank '") +
6430b57cec5SDimitry Andric                   VReg.Class.Value + "'");
6440b57cec5SDimitry Andric         Info.Kind = VRegInfo::REGBANK;
6450b57cec5SDimitry Andric         Info.D.RegBank = RegBank;
6460b57cec5SDimitry Andric       }
6470b57cec5SDimitry Andric     }
6480b57cec5SDimitry Andric 
6490b57cec5SDimitry Andric     if (!VReg.PreferredRegister.Value.empty()) {
6500b57cec5SDimitry Andric       if (Info.Kind != VRegInfo::NORMAL)
6510b57cec5SDimitry Andric         return error(VReg.Class.SourceRange.Start,
6520b57cec5SDimitry Andric               Twine("preferred register can only be set for normal vregs"));
6530b57cec5SDimitry Andric 
6540b57cec5SDimitry Andric       if (parseRegisterReference(PFS, Info.PreferredReg,
6550b57cec5SDimitry Andric                                  VReg.PreferredRegister.Value, Error))
6560b57cec5SDimitry Andric         return error(Error, VReg.PreferredRegister.SourceRange);
6570b57cec5SDimitry Andric     }
6580b57cec5SDimitry Andric   }
6590b57cec5SDimitry Andric 
6600b57cec5SDimitry Andric   // Parse the liveins.
6610b57cec5SDimitry Andric   for (const auto &LiveIn : YamlMF.LiveIns) {
6625ffd83dbSDimitry Andric     Register Reg;
6630b57cec5SDimitry Andric     if (parseNamedRegisterReference(PFS, Reg, LiveIn.Register.Value, Error))
6640b57cec5SDimitry Andric       return error(Error, LiveIn.Register.SourceRange);
6655ffd83dbSDimitry Andric     Register VReg;
6660b57cec5SDimitry Andric     if (!LiveIn.VirtualRegister.Value.empty()) {
6670b57cec5SDimitry Andric       VRegInfo *Info;
6680b57cec5SDimitry Andric       if (parseVirtualRegisterReference(PFS, Info, LiveIn.VirtualRegister.Value,
6690b57cec5SDimitry Andric                                         Error))
6700b57cec5SDimitry Andric         return error(Error, LiveIn.VirtualRegister.SourceRange);
6710b57cec5SDimitry Andric       VReg = Info->VReg;
6720b57cec5SDimitry Andric     }
6730b57cec5SDimitry Andric     RegInfo.addLiveIn(Reg, VReg);
6740b57cec5SDimitry Andric   }
6750b57cec5SDimitry Andric 
6760b57cec5SDimitry Andric   // Parse the callee saved registers (Registers that will
6770b57cec5SDimitry Andric   // be saved for the caller).
6780b57cec5SDimitry Andric   if (YamlMF.CalleeSavedRegisters) {
6790b57cec5SDimitry Andric     SmallVector<MCPhysReg, 16> CalleeSavedRegisters;
68081ad6265SDimitry Andric     for (const auto &RegSource : *YamlMF.CalleeSavedRegisters) {
6815ffd83dbSDimitry Andric       Register Reg;
6820b57cec5SDimitry Andric       if (parseNamedRegisterReference(PFS, Reg, RegSource.Value, Error))
6830b57cec5SDimitry Andric         return error(Error, RegSource.SourceRange);
6840b57cec5SDimitry Andric       CalleeSavedRegisters.push_back(Reg);
6850b57cec5SDimitry Andric     }
6860b57cec5SDimitry Andric     RegInfo.setCalleeSavedRegs(CalleeSavedRegisters);
6870b57cec5SDimitry Andric   }
6880b57cec5SDimitry Andric 
6890b57cec5SDimitry Andric   return false;
6900b57cec5SDimitry Andric }
6910b57cec5SDimitry Andric 
6920b57cec5SDimitry Andric bool MIRParserImpl::setupRegisterInfo(const PerFunctionMIParsingState &PFS,
6930b57cec5SDimitry Andric                                       const yaml::MachineFunction &YamlMF) {
6940b57cec5SDimitry Andric   MachineFunction &MF = PFS.MF;
6950b57cec5SDimitry Andric   MachineRegisterInfo &MRI = MF.getRegInfo();
696bdd1243dSDimitry Andric   const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
697bdd1243dSDimitry Andric 
6980b57cec5SDimitry Andric   bool Error = false;
6990b57cec5SDimitry Andric   // Create VRegs
7000b57cec5SDimitry Andric   auto populateVRegInfo = [&](const VRegInfo &Info, Twine Name) {
7015ffd83dbSDimitry Andric     Register Reg = Info.VReg;
7020b57cec5SDimitry Andric     switch (Info.Kind) {
7030b57cec5SDimitry Andric     case VRegInfo::UNKNOWN:
7040b57cec5SDimitry Andric       error(Twine("Cannot determine class/bank of virtual register ") +
7050b57cec5SDimitry Andric             Name + " in function '" + MF.getName() + "'");
7060b57cec5SDimitry Andric       Error = true;
7070b57cec5SDimitry Andric       break;
7080b57cec5SDimitry Andric     case VRegInfo::NORMAL:
709bdd1243dSDimitry Andric       if (!Info.D.RC->isAllocatable()) {
710bdd1243dSDimitry Andric         error(Twine("Cannot use non-allocatable class '") +
711bdd1243dSDimitry Andric               TRI->getRegClassName(Info.D.RC) + "' for virtual register " +
712bdd1243dSDimitry Andric               Name + " in function '" + MF.getName() + "'");
713bdd1243dSDimitry Andric         Error = true;
714bdd1243dSDimitry Andric         break;
715bdd1243dSDimitry Andric       }
716bdd1243dSDimitry Andric 
7170b57cec5SDimitry Andric       MRI.setRegClass(Reg, Info.D.RC);
7180b57cec5SDimitry Andric       if (Info.PreferredReg != 0)
7190b57cec5SDimitry Andric         MRI.setSimpleHint(Reg, Info.PreferredReg);
7200b57cec5SDimitry Andric       break;
7210b57cec5SDimitry Andric     case VRegInfo::GENERIC:
7220b57cec5SDimitry Andric       break;
7230b57cec5SDimitry Andric     case VRegInfo::REGBANK:
7240b57cec5SDimitry Andric       MRI.setRegBank(Reg, *Info.D.RegBank);
7250b57cec5SDimitry Andric       break;
7260b57cec5SDimitry Andric     }
7270b57cec5SDimitry Andric   };
7280b57cec5SDimitry Andric 
729fe6060f1SDimitry Andric   for (const auto &P : PFS.VRegInfosNamed) {
730fe6060f1SDimitry Andric     const VRegInfo &Info = *P.second;
731fe6060f1SDimitry Andric     populateVRegInfo(Info, Twine(P.first()));
7320b57cec5SDimitry Andric   }
7330b57cec5SDimitry Andric 
7340b57cec5SDimitry Andric   for (auto P : PFS.VRegInfos) {
7350b57cec5SDimitry Andric     const VRegInfo &Info = *P.second;
7360b57cec5SDimitry Andric     populateVRegInfo(Info, Twine(P.first));
7370b57cec5SDimitry Andric   }
7380b57cec5SDimitry Andric 
7390b57cec5SDimitry Andric   // Compute MachineRegisterInfo::UsedPhysRegMask
7400b57cec5SDimitry Andric   for (const MachineBasicBlock &MBB : MF) {
741e8d8bef9SDimitry Andric     // Make sure MRI knows about registers clobbered by unwinder.
742e8d8bef9SDimitry Andric     if (MBB.isEHPad())
743e8d8bef9SDimitry Andric       if (auto *RegMask = TRI->getCustomEHPadPreservedMask(MF))
744e8d8bef9SDimitry Andric         MRI.addPhysRegsUsedFromRegMask(RegMask);
745e8d8bef9SDimitry Andric 
7460b57cec5SDimitry Andric     for (const MachineInstr &MI : MBB) {
7470b57cec5SDimitry Andric       for (const MachineOperand &MO : MI.operands()) {
7480b57cec5SDimitry Andric         if (!MO.isRegMask())
7490b57cec5SDimitry Andric           continue;
7500b57cec5SDimitry Andric         MRI.addPhysRegsUsedFromRegMask(MO.getRegMask());
7510b57cec5SDimitry Andric       }
7520b57cec5SDimitry Andric     }
7530b57cec5SDimitry Andric   }
7540b57cec5SDimitry Andric 
7550b57cec5SDimitry Andric   return Error;
7560b57cec5SDimitry Andric }
7570b57cec5SDimitry Andric 
7580b57cec5SDimitry Andric bool MIRParserImpl::initializeFrameInfo(PerFunctionMIParsingState &PFS,
7590b57cec5SDimitry Andric                                         const yaml::MachineFunction &YamlMF) {
7600b57cec5SDimitry Andric   MachineFunction &MF = PFS.MF;
7610b57cec5SDimitry Andric   MachineFrameInfo &MFI = MF.getFrameInfo();
7620b57cec5SDimitry Andric   const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
7630b57cec5SDimitry Andric   const Function &F = MF.getFunction();
7640b57cec5SDimitry Andric   const yaml::MachineFrameInfo &YamlMFI = YamlMF.FrameInfo;
7650b57cec5SDimitry Andric   MFI.setFrameAddressIsTaken(YamlMFI.IsFrameAddressTaken);
7660b57cec5SDimitry Andric   MFI.setReturnAddressIsTaken(YamlMFI.IsReturnAddressTaken);
7670b57cec5SDimitry Andric   MFI.setHasStackMap(YamlMFI.HasStackMap);
7680b57cec5SDimitry Andric   MFI.setHasPatchPoint(YamlMFI.HasPatchPoint);
7690b57cec5SDimitry Andric   MFI.setStackSize(YamlMFI.StackSize);
7700b57cec5SDimitry Andric   MFI.setOffsetAdjustment(YamlMFI.OffsetAdjustment);
7710b57cec5SDimitry Andric   if (YamlMFI.MaxAlignment)
7725ffd83dbSDimitry Andric     MFI.ensureMaxAlignment(Align(YamlMFI.MaxAlignment));
7730b57cec5SDimitry Andric   MFI.setAdjustsStack(YamlMFI.AdjustsStack);
7740b57cec5SDimitry Andric   MFI.setHasCalls(YamlMFI.HasCalls);
7750b57cec5SDimitry Andric   if (YamlMFI.MaxCallFrameSize != ~0u)
7760b57cec5SDimitry Andric     MFI.setMaxCallFrameSize(YamlMFI.MaxCallFrameSize);
7770b57cec5SDimitry Andric   MFI.setCVBytesOfCalleeSavedRegisters(YamlMFI.CVBytesOfCalleeSavedRegisters);
7780b57cec5SDimitry Andric   MFI.setHasOpaqueSPAdjustment(YamlMFI.HasOpaqueSPAdjustment);
7790b57cec5SDimitry Andric   MFI.setHasVAStart(YamlMFI.HasVAStart);
7800b57cec5SDimitry Andric   MFI.setHasMustTailInVarArgFunc(YamlMFI.HasMustTailInVarArgFunc);
781fe6060f1SDimitry Andric   MFI.setHasTailCall(YamlMFI.HasTailCall);
782*0fca6ea1SDimitry Andric   MFI.setCalleeSavedInfoValid(YamlMFI.IsCalleeSavedInfoValid);
7830b57cec5SDimitry Andric   MFI.setLocalFrameSize(YamlMFI.LocalFrameSize);
7840b57cec5SDimitry Andric   if (!YamlMFI.SavePoint.Value.empty()) {
7850b57cec5SDimitry Andric     MachineBasicBlock *MBB = nullptr;
7860b57cec5SDimitry Andric     if (parseMBBReference(PFS, MBB, YamlMFI.SavePoint))
7870b57cec5SDimitry Andric       return true;
7880b57cec5SDimitry Andric     MFI.setSavePoint(MBB);
7890b57cec5SDimitry Andric   }
7900b57cec5SDimitry Andric   if (!YamlMFI.RestorePoint.Value.empty()) {
7910b57cec5SDimitry Andric     MachineBasicBlock *MBB = nullptr;
7920b57cec5SDimitry Andric     if (parseMBBReference(PFS, MBB, YamlMFI.RestorePoint))
7930b57cec5SDimitry Andric       return true;
7940b57cec5SDimitry Andric     MFI.setRestorePoint(MBB);
7950b57cec5SDimitry Andric   }
7960b57cec5SDimitry Andric 
7970b57cec5SDimitry Andric   std::vector<CalleeSavedInfo> CSIInfo;
7980b57cec5SDimitry Andric   // Initialize the fixed frame objects.
7990b57cec5SDimitry Andric   for (const auto &Object : YamlMF.FixedStackObjects) {
8000b57cec5SDimitry Andric     int ObjectIdx;
8010b57cec5SDimitry Andric     if (Object.Type != yaml::FixedMachineStackObject::SpillSlot)
8020b57cec5SDimitry Andric       ObjectIdx = MFI.CreateFixedObject(Object.Size, Object.Offset,
8030b57cec5SDimitry Andric                                         Object.IsImmutable, Object.IsAliased);
8040b57cec5SDimitry Andric     else
8050b57cec5SDimitry Andric       ObjectIdx = MFI.CreateFixedSpillStackObject(Object.Size, Object.Offset);
8060b57cec5SDimitry Andric 
8070b57cec5SDimitry Andric     if (!TFI->isSupportedStackID(Object.StackID))
8080b57cec5SDimitry Andric       return error(Object.ID.SourceRange.Start,
8090b57cec5SDimitry Andric                    Twine("StackID is not supported by target"));
8100b57cec5SDimitry Andric     MFI.setStackID(ObjectIdx, Object.StackID);
8115ffd83dbSDimitry Andric     MFI.setObjectAlignment(ObjectIdx, Object.Alignment.valueOrOne());
8120b57cec5SDimitry Andric     if (!PFS.FixedStackObjectSlots.insert(std::make_pair(Object.ID.Value,
8130b57cec5SDimitry Andric                                                          ObjectIdx))
8140b57cec5SDimitry Andric              .second)
8150b57cec5SDimitry Andric       return error(Object.ID.SourceRange.Start,
8160b57cec5SDimitry Andric                    Twine("redefinition of fixed stack object '%fixed-stack.") +
8170b57cec5SDimitry Andric                        Twine(Object.ID.Value) + "'");
8180b57cec5SDimitry Andric     if (parseCalleeSavedRegister(PFS, CSIInfo, Object.CalleeSavedRegister,
8190b57cec5SDimitry Andric                                  Object.CalleeSavedRestored, ObjectIdx))
8200b57cec5SDimitry Andric       return true;
8210b57cec5SDimitry Andric     if (parseStackObjectsDebugInfo(PFS, Object, ObjectIdx))
8220b57cec5SDimitry Andric       return true;
8230b57cec5SDimitry Andric   }
8240b57cec5SDimitry Andric 
82506c3fb27SDimitry Andric   for (const auto &Object : YamlMF.EntryValueObjects) {
82606c3fb27SDimitry Andric     SMDiagnostic Error;
82706c3fb27SDimitry Andric     Register Reg;
82806c3fb27SDimitry Andric     if (parseNamedRegisterReference(PFS, Reg, Object.EntryValueRegister.Value,
82906c3fb27SDimitry Andric                                     Error))
83006c3fb27SDimitry Andric       return error(Error, Object.EntryValueRegister.SourceRange);
83106c3fb27SDimitry Andric     if (!Reg.isPhysical())
83206c3fb27SDimitry Andric       return error(Object.EntryValueRegister.SourceRange.Start,
83306c3fb27SDimitry Andric                    "Expected physical register for entry value field");
83406c3fb27SDimitry Andric     std::optional<VarExprLoc> MaybeInfo = parseVarExprLoc(
83506c3fb27SDimitry Andric         PFS, Object.DebugVar, Object.DebugExpr, Object.DebugLoc);
83606c3fb27SDimitry Andric     if (!MaybeInfo)
83706c3fb27SDimitry Andric       return true;
83806c3fb27SDimitry Andric     if (MaybeInfo->DIVar || MaybeInfo->DIExpr || MaybeInfo->DILoc)
83906c3fb27SDimitry Andric       PFS.MF.setVariableDbgInfo(MaybeInfo->DIVar, MaybeInfo->DIExpr,
84006c3fb27SDimitry Andric                                 Reg.asMCReg(), MaybeInfo->DILoc);
84106c3fb27SDimitry Andric   }
84206c3fb27SDimitry Andric 
8430b57cec5SDimitry Andric   // Initialize the ordinary frame objects.
8440b57cec5SDimitry Andric   for (const auto &Object : YamlMF.StackObjects) {
8450b57cec5SDimitry Andric     int ObjectIdx;
8460b57cec5SDimitry Andric     const AllocaInst *Alloca = nullptr;
8470b57cec5SDimitry Andric     const yaml::StringValue &Name = Object.Name;
8480b57cec5SDimitry Andric     if (!Name.Value.empty()) {
8490b57cec5SDimitry Andric       Alloca = dyn_cast_or_null<AllocaInst>(
8500b57cec5SDimitry Andric           F.getValueSymbolTable()->lookup(Name.Value));
8510b57cec5SDimitry Andric       if (!Alloca)
8520b57cec5SDimitry Andric         return error(Name.SourceRange.Start,
8530b57cec5SDimitry Andric                      "alloca instruction named '" + Name.Value +
8540b57cec5SDimitry Andric                          "' isn't defined in the function '" + F.getName() +
8550b57cec5SDimitry Andric                          "'");
8560b57cec5SDimitry Andric     }
8570b57cec5SDimitry Andric     if (!TFI->isSupportedStackID(Object.StackID))
8580b57cec5SDimitry Andric       return error(Object.ID.SourceRange.Start,
8590b57cec5SDimitry Andric                    Twine("StackID is not supported by target"));
8600b57cec5SDimitry Andric     if (Object.Type == yaml::MachineStackObject::VariableSized)
8615ffd83dbSDimitry Andric       ObjectIdx =
8625ffd83dbSDimitry Andric           MFI.CreateVariableSizedObject(Object.Alignment.valueOrOne(), Alloca);
8630b57cec5SDimitry Andric     else
8640b57cec5SDimitry Andric       ObjectIdx = MFI.CreateStackObject(
8655ffd83dbSDimitry Andric           Object.Size, Object.Alignment.valueOrOne(),
8660b57cec5SDimitry Andric           Object.Type == yaml::MachineStackObject::SpillSlot, Alloca,
8670b57cec5SDimitry Andric           Object.StackID);
8680b57cec5SDimitry Andric     MFI.setObjectOffset(ObjectIdx, Object.Offset);
8690b57cec5SDimitry Andric 
8700b57cec5SDimitry Andric     if (!PFS.StackObjectSlots.insert(std::make_pair(Object.ID.Value, ObjectIdx))
8710b57cec5SDimitry Andric              .second)
8720b57cec5SDimitry Andric       return error(Object.ID.SourceRange.Start,
8730b57cec5SDimitry Andric                    Twine("redefinition of stack object '%stack.") +
8740b57cec5SDimitry Andric                        Twine(Object.ID.Value) + "'");
8750b57cec5SDimitry Andric     if (parseCalleeSavedRegister(PFS, CSIInfo, Object.CalleeSavedRegister,
8760b57cec5SDimitry Andric                                  Object.CalleeSavedRestored, ObjectIdx))
8770b57cec5SDimitry Andric       return true;
8780b57cec5SDimitry Andric     if (Object.LocalOffset)
87981ad6265SDimitry Andric       MFI.mapLocalFrameObject(ObjectIdx, *Object.LocalOffset);
8800b57cec5SDimitry Andric     if (parseStackObjectsDebugInfo(PFS, Object, ObjectIdx))
8810b57cec5SDimitry Andric       return true;
8820b57cec5SDimitry Andric   }
8830b57cec5SDimitry Andric   MFI.setCalleeSavedInfo(CSIInfo);
8840b57cec5SDimitry Andric   if (!CSIInfo.empty())
8850b57cec5SDimitry Andric     MFI.setCalleeSavedInfoValid(true);
8860b57cec5SDimitry Andric 
8870b57cec5SDimitry Andric   // Initialize the various stack object references after initializing the
8880b57cec5SDimitry Andric   // stack objects.
8890b57cec5SDimitry Andric   if (!YamlMFI.StackProtector.Value.empty()) {
8900b57cec5SDimitry Andric     SMDiagnostic Error;
8910b57cec5SDimitry Andric     int FI;
8920b57cec5SDimitry Andric     if (parseStackObjectReference(PFS, FI, YamlMFI.StackProtector.Value, Error))
8930b57cec5SDimitry Andric       return error(Error, YamlMFI.StackProtector.SourceRange);
8940b57cec5SDimitry Andric     MFI.setStackProtectorIndex(FI);
8950b57cec5SDimitry Andric   }
89681ad6265SDimitry Andric 
89781ad6265SDimitry Andric   if (!YamlMFI.FunctionContext.Value.empty()) {
89881ad6265SDimitry Andric     SMDiagnostic Error;
89981ad6265SDimitry Andric     int FI;
90081ad6265SDimitry Andric     if (parseStackObjectReference(PFS, FI, YamlMFI.FunctionContext.Value, Error))
90181ad6265SDimitry Andric       return error(Error, YamlMFI.FunctionContext.SourceRange);
90281ad6265SDimitry Andric     MFI.setFunctionContextIndex(FI);
90381ad6265SDimitry Andric   }
90481ad6265SDimitry Andric 
9050b57cec5SDimitry Andric   return false;
9060b57cec5SDimitry Andric }
9070b57cec5SDimitry Andric 
9080b57cec5SDimitry Andric bool MIRParserImpl::parseCalleeSavedRegister(PerFunctionMIParsingState &PFS,
9090b57cec5SDimitry Andric     std::vector<CalleeSavedInfo> &CSIInfo,
9100b57cec5SDimitry Andric     const yaml::StringValue &RegisterSource, bool IsRestored, int FrameIdx) {
9110b57cec5SDimitry Andric   if (RegisterSource.Value.empty())
9120b57cec5SDimitry Andric     return false;
9135ffd83dbSDimitry Andric   Register Reg;
9140b57cec5SDimitry Andric   SMDiagnostic Error;
9150b57cec5SDimitry Andric   if (parseNamedRegisterReference(PFS, Reg, RegisterSource.Value, Error))
9160b57cec5SDimitry Andric     return error(Error, RegisterSource.SourceRange);
9170b57cec5SDimitry Andric   CalleeSavedInfo CSI(Reg, FrameIdx);
9180b57cec5SDimitry Andric   CSI.setRestored(IsRestored);
9190b57cec5SDimitry Andric   CSIInfo.push_back(CSI);
9200b57cec5SDimitry Andric   return false;
9210b57cec5SDimitry Andric }
9220b57cec5SDimitry Andric 
9230b57cec5SDimitry Andric /// Verify that given node is of a certain type. Return true on error.
9240b57cec5SDimitry Andric template <typename T>
9250b57cec5SDimitry Andric static bool typecheckMDNode(T *&Result, MDNode *Node,
9260b57cec5SDimitry Andric                             const yaml::StringValue &Source,
9270b57cec5SDimitry Andric                             StringRef TypeString, MIRParserImpl &Parser) {
9280b57cec5SDimitry Andric   if (!Node)
9290b57cec5SDimitry Andric     return false;
9300b57cec5SDimitry Andric   Result = dyn_cast<T>(Node);
9310b57cec5SDimitry Andric   if (!Result)
9320b57cec5SDimitry Andric     return Parser.error(Source.SourceRange.Start,
9330b57cec5SDimitry Andric                         "expected a reference to a '" + TypeString +
9340b57cec5SDimitry Andric                             "' metadata node");
9350b57cec5SDimitry Andric   return false;
9360b57cec5SDimitry Andric }
9370b57cec5SDimitry Andric 
93806c3fb27SDimitry Andric std::optional<MIRParserImpl::VarExprLoc> MIRParserImpl::parseVarExprLoc(
93906c3fb27SDimitry Andric     PerFunctionMIParsingState &PFS, const yaml::StringValue &VarStr,
94006c3fb27SDimitry Andric     const yaml::StringValue &ExprStr, const yaml::StringValue &LocStr) {
94106c3fb27SDimitry Andric   MDNode *Var = nullptr;
94206c3fb27SDimitry Andric   MDNode *Expr = nullptr;
94306c3fb27SDimitry Andric   MDNode *Loc = nullptr;
94406c3fb27SDimitry Andric   if (parseMDNode(PFS, Var, VarStr) || parseMDNode(PFS, Expr, ExprStr) ||
94506c3fb27SDimitry Andric       parseMDNode(PFS, Loc, LocStr))
94606c3fb27SDimitry Andric     return std::nullopt;
9470b57cec5SDimitry Andric   DILocalVariable *DIVar = nullptr;
9480b57cec5SDimitry Andric   DIExpression *DIExpr = nullptr;
9490b57cec5SDimitry Andric   DILocation *DILoc = nullptr;
95006c3fb27SDimitry Andric   if (typecheckMDNode(DIVar, Var, VarStr, "DILocalVariable", *this) ||
95106c3fb27SDimitry Andric       typecheckMDNode(DIExpr, Expr, ExprStr, "DIExpression", *this) ||
95206c3fb27SDimitry Andric       typecheckMDNode(DILoc, Loc, LocStr, "DILocation", *this))
95306c3fb27SDimitry Andric     return std::nullopt;
95406c3fb27SDimitry Andric   return VarExprLoc{DIVar, DIExpr, DILoc};
95506c3fb27SDimitry Andric }
95606c3fb27SDimitry Andric 
95706c3fb27SDimitry Andric template <typename T>
95806c3fb27SDimitry Andric bool MIRParserImpl::parseStackObjectsDebugInfo(PerFunctionMIParsingState &PFS,
95906c3fb27SDimitry Andric                                                const T &Object, int FrameIdx) {
96006c3fb27SDimitry Andric   std::optional<VarExprLoc> MaybeInfo =
96106c3fb27SDimitry Andric       parseVarExprLoc(PFS, Object.DebugVar, Object.DebugExpr, Object.DebugLoc);
96206c3fb27SDimitry Andric   if (!MaybeInfo)
9630b57cec5SDimitry Andric     return true;
96406c3fb27SDimitry Andric   // Debug information can only be attached to stack objects; Fixed stack
96506c3fb27SDimitry Andric   // objects aren't supported.
96606c3fb27SDimitry Andric   if (MaybeInfo->DIVar || MaybeInfo->DIExpr || MaybeInfo->DILoc)
96706c3fb27SDimitry Andric     PFS.MF.setVariableDbgInfo(MaybeInfo->DIVar, MaybeInfo->DIExpr, FrameIdx,
96806c3fb27SDimitry Andric                               MaybeInfo->DILoc);
9690b57cec5SDimitry Andric   return false;
9700b57cec5SDimitry Andric }
9710b57cec5SDimitry Andric 
9720b57cec5SDimitry Andric bool MIRParserImpl::parseMDNode(PerFunctionMIParsingState &PFS,
9730b57cec5SDimitry Andric     MDNode *&Node, const yaml::StringValue &Source) {
9740b57cec5SDimitry Andric   if (Source.Value.empty())
9750b57cec5SDimitry Andric     return false;
9760b57cec5SDimitry Andric   SMDiagnostic Error;
9770b57cec5SDimitry Andric   if (llvm::parseMDNode(PFS, Node, Source.Value, Error))
9780b57cec5SDimitry Andric     return error(Error, Source.SourceRange);
9790b57cec5SDimitry Andric   return false;
9800b57cec5SDimitry Andric }
9810b57cec5SDimitry Andric 
9820b57cec5SDimitry Andric bool MIRParserImpl::initializeConstantPool(PerFunctionMIParsingState &PFS,
9830b57cec5SDimitry Andric     MachineConstantPool &ConstantPool, const yaml::MachineFunction &YamlMF) {
9840b57cec5SDimitry Andric   DenseMap<unsigned, unsigned> &ConstantPoolSlots = PFS.ConstantPoolSlots;
9850b57cec5SDimitry Andric   const MachineFunction &MF = PFS.MF;
9860b57cec5SDimitry Andric   const auto &M = *MF.getFunction().getParent();
9870b57cec5SDimitry Andric   SMDiagnostic Error;
9880b57cec5SDimitry Andric   for (const auto &YamlConstant : YamlMF.Constants) {
9890b57cec5SDimitry Andric     if (YamlConstant.IsTargetSpecific)
9900b57cec5SDimitry Andric       // FIXME: Support target-specific constant pools
9910b57cec5SDimitry Andric       return error(YamlConstant.Value.SourceRange.Start,
9920b57cec5SDimitry Andric                    "Can't parse target-specific constant pool entries yet");
9930b57cec5SDimitry Andric     const Constant *Value = dyn_cast_or_null<Constant>(
9940b57cec5SDimitry Andric         parseConstantValue(YamlConstant.Value.Value, Error, M));
9950b57cec5SDimitry Andric     if (!Value)
9960b57cec5SDimitry Andric       return error(Error, YamlConstant.Value.SourceRange);
9975ffd83dbSDimitry Andric     const Align PrefTypeAlign =
9985ffd83dbSDimitry Andric         M.getDataLayout().getPrefTypeAlign(Value->getType());
99981ad6265SDimitry Andric     const Align Alignment = YamlConstant.Alignment.value_or(PrefTypeAlign);
10000b57cec5SDimitry Andric     unsigned Index = ConstantPool.getConstantPoolIndex(Value, Alignment);
10010b57cec5SDimitry Andric     if (!ConstantPoolSlots.insert(std::make_pair(YamlConstant.ID.Value, Index))
10020b57cec5SDimitry Andric              .second)
10030b57cec5SDimitry Andric       return error(YamlConstant.ID.SourceRange.Start,
10040b57cec5SDimitry Andric                    Twine("redefinition of constant pool item '%const.") +
10050b57cec5SDimitry Andric                        Twine(YamlConstant.ID.Value) + "'");
10060b57cec5SDimitry Andric   }
10070b57cec5SDimitry Andric   return false;
10080b57cec5SDimitry Andric }
10090b57cec5SDimitry Andric 
10100b57cec5SDimitry Andric bool MIRParserImpl::initializeJumpTableInfo(PerFunctionMIParsingState &PFS,
10110b57cec5SDimitry Andric     const yaml::MachineJumpTable &YamlJTI) {
10120b57cec5SDimitry Andric   MachineJumpTableInfo *JTI = PFS.MF.getOrCreateJumpTableInfo(YamlJTI.Kind);
10130b57cec5SDimitry Andric   for (const auto &Entry : YamlJTI.Entries) {
10140b57cec5SDimitry Andric     std::vector<MachineBasicBlock *> Blocks;
10150b57cec5SDimitry Andric     for (const auto &MBBSource : Entry.Blocks) {
10160b57cec5SDimitry Andric       MachineBasicBlock *MBB = nullptr;
10170b57cec5SDimitry Andric       if (parseMBBReference(PFS, MBB, MBBSource.Value))
10180b57cec5SDimitry Andric         return true;
10190b57cec5SDimitry Andric       Blocks.push_back(MBB);
10200b57cec5SDimitry Andric     }
10210b57cec5SDimitry Andric     unsigned Index = JTI->createJumpTableIndex(Blocks);
10220b57cec5SDimitry Andric     if (!PFS.JumpTableSlots.insert(std::make_pair(Entry.ID.Value, Index))
10230b57cec5SDimitry Andric              .second)
10240b57cec5SDimitry Andric       return error(Entry.ID.SourceRange.Start,
10250b57cec5SDimitry Andric                    Twine("redefinition of jump table entry '%jump-table.") +
10260b57cec5SDimitry Andric                        Twine(Entry.ID.Value) + "'");
10270b57cec5SDimitry Andric   }
10280b57cec5SDimitry Andric   return false;
10290b57cec5SDimitry Andric }
10300b57cec5SDimitry Andric 
10310b57cec5SDimitry Andric bool MIRParserImpl::parseMBBReference(PerFunctionMIParsingState &PFS,
10320b57cec5SDimitry Andric                                       MachineBasicBlock *&MBB,
10330b57cec5SDimitry Andric                                       const yaml::StringValue &Source) {
10340b57cec5SDimitry Andric   SMDiagnostic Error;
10350b57cec5SDimitry Andric   if (llvm::parseMBBReference(PFS, MBB, Source.Value, Error))
10360b57cec5SDimitry Andric     return error(Error, Source.SourceRange);
10370b57cec5SDimitry Andric   return false;
10380b57cec5SDimitry Andric }
10390b57cec5SDimitry Andric 
1040fe6060f1SDimitry Andric bool MIRParserImpl::parseMachineMetadata(PerFunctionMIParsingState &PFS,
1041fe6060f1SDimitry Andric                                          const yaml::StringValue &Source) {
1042fe6060f1SDimitry Andric   SMDiagnostic Error;
1043fe6060f1SDimitry Andric   if (llvm::parseMachineMetadata(PFS, Source.Value, Source.SourceRange, Error))
1044fe6060f1SDimitry Andric     return error(Error, Source.SourceRange);
1045fe6060f1SDimitry Andric   return false;
1046fe6060f1SDimitry Andric }
1047fe6060f1SDimitry Andric 
1048fe6060f1SDimitry Andric bool MIRParserImpl::parseMachineMetadataNodes(
1049fe6060f1SDimitry Andric     PerFunctionMIParsingState &PFS, MachineFunction &MF,
1050fe6060f1SDimitry Andric     const yaml::MachineFunction &YMF) {
1051fcaf7f86SDimitry Andric   for (const auto &MDS : YMF.MachineMetadataNodes) {
1052fe6060f1SDimitry Andric     if (parseMachineMetadata(PFS, MDS))
1053fe6060f1SDimitry Andric       return true;
1054fe6060f1SDimitry Andric   }
1055fe6060f1SDimitry Andric   // Report missing definitions from forward referenced nodes.
1056fe6060f1SDimitry Andric   if (!PFS.MachineForwardRefMDNodes.empty())
1057fe6060f1SDimitry Andric     return error(PFS.MachineForwardRefMDNodes.begin()->second.second,
1058fe6060f1SDimitry Andric                  "use of undefined metadata '!" +
1059fe6060f1SDimitry Andric                      Twine(PFS.MachineForwardRefMDNodes.begin()->first) + "'");
1060fe6060f1SDimitry Andric   return false;
1061fe6060f1SDimitry Andric }
1062fe6060f1SDimitry Andric 
10630b57cec5SDimitry Andric SMDiagnostic MIRParserImpl::diagFromMIStringDiag(const SMDiagnostic &Error,
10640b57cec5SDimitry Andric                                                  SMRange SourceRange) {
10650b57cec5SDimitry Andric   assert(SourceRange.isValid() && "Invalid source range");
10660b57cec5SDimitry Andric   SMLoc Loc = SourceRange.Start;
10670b57cec5SDimitry Andric   bool HasQuote = Loc.getPointer() < SourceRange.End.getPointer() &&
10680b57cec5SDimitry Andric                   *Loc.getPointer() == '\'';
10690b57cec5SDimitry Andric   // Translate the location of the error from the location in the MI string to
10700b57cec5SDimitry Andric   // the corresponding location in the MIR file.
10710b57cec5SDimitry Andric   Loc = Loc.getFromPointer(Loc.getPointer() + Error.getColumnNo() +
10720b57cec5SDimitry Andric                            (HasQuote ? 1 : 0));
10730b57cec5SDimitry Andric 
10740b57cec5SDimitry Andric   // TODO: Translate any source ranges as well.
1075bdd1243dSDimitry Andric   return SM.GetMessage(Loc, Error.getKind(), Error.getMessage(), std::nullopt,
10760b57cec5SDimitry Andric                        Error.getFixIts());
10770b57cec5SDimitry Andric }
10780b57cec5SDimitry Andric 
10790b57cec5SDimitry Andric SMDiagnostic MIRParserImpl::diagFromBlockStringDiag(const SMDiagnostic &Error,
10800b57cec5SDimitry Andric                                                     SMRange SourceRange) {
10810b57cec5SDimitry Andric   assert(SourceRange.isValid());
10820b57cec5SDimitry Andric 
10830b57cec5SDimitry Andric   // Translate the location of the error from the location in the llvm IR string
10840b57cec5SDimitry Andric   // to the corresponding location in the MIR file.
10850b57cec5SDimitry Andric   auto LineAndColumn = SM.getLineAndColumn(SourceRange.Start);
10860b57cec5SDimitry Andric   unsigned Line = LineAndColumn.first + Error.getLineNo() - 1;
10870b57cec5SDimitry Andric   unsigned Column = Error.getColumnNo();
10880b57cec5SDimitry Andric   StringRef LineStr = Error.getLineContents();
10890b57cec5SDimitry Andric   SMLoc Loc = Error.getLoc();
10900b57cec5SDimitry Andric 
10910b57cec5SDimitry Andric   // Get the full line and adjust the column number by taking the indentation of
10920b57cec5SDimitry Andric   // LLVM IR into account.
10930b57cec5SDimitry Andric   for (line_iterator L(*SM.getMemoryBuffer(SM.getMainFileID()), false), E;
10940b57cec5SDimitry Andric        L != E; ++L) {
10950b57cec5SDimitry Andric     if (L.line_number() == Line) {
10960b57cec5SDimitry Andric       LineStr = *L;
10970b57cec5SDimitry Andric       Loc = SMLoc::getFromPointer(LineStr.data());
10980b57cec5SDimitry Andric       auto Indent = LineStr.find(Error.getLineContents());
10990b57cec5SDimitry Andric       if (Indent != StringRef::npos)
11000b57cec5SDimitry Andric         Column += Indent;
11010b57cec5SDimitry Andric       break;
11020b57cec5SDimitry Andric     }
11030b57cec5SDimitry Andric   }
11040b57cec5SDimitry Andric 
11050b57cec5SDimitry Andric   return SMDiagnostic(SM, Loc, Filename, Line, Column, Error.getKind(),
11060b57cec5SDimitry Andric                       Error.getMessage(), LineStr, Error.getRanges(),
11070b57cec5SDimitry Andric                       Error.getFixIts());
11080b57cec5SDimitry Andric }
11090b57cec5SDimitry Andric 
11100b57cec5SDimitry Andric MIRParser::MIRParser(std::unique_ptr<MIRParserImpl> Impl)
11110b57cec5SDimitry Andric     : Impl(std::move(Impl)) {}
11120b57cec5SDimitry Andric 
111381ad6265SDimitry Andric MIRParser::~MIRParser() = default;
11140b57cec5SDimitry Andric 
11155ffd83dbSDimitry Andric std::unique_ptr<Module>
11165ffd83dbSDimitry Andric MIRParser::parseIRModule(DataLayoutCallbackTy DataLayoutCallback) {
11175ffd83dbSDimitry Andric   return Impl->parseIRModule(DataLayoutCallback);
11180b57cec5SDimitry Andric }
11190b57cec5SDimitry Andric 
11200b57cec5SDimitry Andric bool MIRParser::parseMachineFunctions(Module &M, MachineModuleInfo &MMI) {
11210b57cec5SDimitry Andric   return Impl->parseMachineFunctions(M, MMI);
11220b57cec5SDimitry Andric }
11230b57cec5SDimitry Andric 
1124*0fca6ea1SDimitry Andric bool MIRParser::parseMachineFunctions(Module &M, ModuleAnalysisManager &MAM) {
1125*0fca6ea1SDimitry Andric   auto &MMI = MAM.getResult<MachineModuleAnalysis>(M).getMMI();
1126*0fca6ea1SDimitry Andric   return Impl->parseMachineFunctions(M, MMI, &MAM);
1127*0fca6ea1SDimitry Andric }
1128*0fca6ea1SDimitry Andric 
1129480093f4SDimitry Andric std::unique_ptr<MIRParser> llvm::createMIRParserFromFile(
1130480093f4SDimitry Andric     StringRef Filename, SMDiagnostic &Error, LLVMContext &Context,
1131480093f4SDimitry Andric     std::function<void(Function &)> ProcessIRFunction) {
1132fe6060f1SDimitry Andric   auto FileOrErr = MemoryBuffer::getFileOrSTDIN(Filename, /*IsText=*/true);
11330b57cec5SDimitry Andric   if (std::error_code EC = FileOrErr.getError()) {
11340b57cec5SDimitry Andric     Error = SMDiagnostic(Filename, SourceMgr::DK_Error,
11350b57cec5SDimitry Andric                          "Could not open input file: " + EC.message());
11360b57cec5SDimitry Andric     return nullptr;
11370b57cec5SDimitry Andric   }
1138480093f4SDimitry Andric   return createMIRParser(std::move(FileOrErr.get()), Context,
1139480093f4SDimitry Andric                          ProcessIRFunction);
11400b57cec5SDimitry Andric }
11410b57cec5SDimitry Andric 
11420b57cec5SDimitry Andric std::unique_ptr<MIRParser>
11430b57cec5SDimitry Andric llvm::createMIRParser(std::unique_ptr<MemoryBuffer> Contents,
1144480093f4SDimitry Andric                       LLVMContext &Context,
1145480093f4SDimitry Andric                       std::function<void(Function &)> ProcessIRFunction) {
11460b57cec5SDimitry Andric   auto Filename = Contents->getBufferIdentifier();
11470b57cec5SDimitry Andric   if (Context.shouldDiscardValueNames()) {
11480b57cec5SDimitry Andric     Context.diagnose(DiagnosticInfoMIRParser(
11490b57cec5SDimitry Andric         DS_Error,
11500b57cec5SDimitry Andric         SMDiagnostic(
11510b57cec5SDimitry Andric             Filename, SourceMgr::DK_Error,
11520b57cec5SDimitry Andric             "Can't read MIR with a Context that discards named Values")));
11530b57cec5SDimitry Andric     return nullptr;
11540b57cec5SDimitry Andric   }
1155480093f4SDimitry Andric   return std::make_unique<MIRParser>(std::make_unique<MIRParserImpl>(
1156480093f4SDimitry Andric       std::move(Contents), Filename, Context, ProcessIRFunction));
11570b57cec5SDimitry Andric }
1158