197bc6c73SDimitry Andric //===- MIRParser.cpp - MIR serialization format parser implementation -----===//
297bc6c73SDimitry Andric //
397bc6c73SDimitry Andric //                     The LLVM Compiler Infrastructure
497bc6c73SDimitry Andric //
597bc6c73SDimitry Andric // This file is distributed under the University of Illinois Open Source
697bc6c73SDimitry Andric // License. See LICENSE.TXT for details.
797bc6c73SDimitry Andric //
897bc6c73SDimitry Andric //===----------------------------------------------------------------------===//
997bc6c73SDimitry Andric //
1097bc6c73SDimitry Andric // This file implements the class that parses the optional LLVM IR and machine
1197bc6c73SDimitry Andric // functions that are stored in MIR files.
1297bc6c73SDimitry Andric //
1397bc6c73SDimitry Andric //===----------------------------------------------------------------------===//
1497bc6c73SDimitry Andric 
1597bc6c73SDimitry Andric #include "llvm/CodeGen/MIRParser/MIRParser.h"
163dac3a9bSDimitry Andric #include "MIParser.h"
173dac3a9bSDimitry Andric #include "llvm/ADT/DenseMap.h"
1897bc6c73SDimitry Andric #include "llvm/ADT/STLExtras.h"
193ca95b02SDimitry Andric #include "llvm/ADT/StringMap.h"
203ca95b02SDimitry Andric #include "llvm/ADT/StringRef.h"
2197bc6c73SDimitry Andric #include "llvm/AsmParser/Parser.h"
223dac3a9bSDimitry Andric #include "llvm/AsmParser/SlotMapping.h"
233ca95b02SDimitry Andric #include "llvm/CodeGen/GlobalISel/RegisterBank.h"
243ca95b02SDimitry Andric #include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
253ca95b02SDimitry Andric #include "llvm/CodeGen/MIRYamlMapping.h"
267d523365SDimitry Andric #include "llvm/CodeGen/MachineConstantPool.h"
27875ed548SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
283ca95b02SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
297d523365SDimitry Andric #include "llvm/CodeGen/MachineModuleInfo.h"
303dac3a9bSDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
318f0fd8f6SDimitry Andric #include "llvm/IR/BasicBlock.h"
323ca95b02SDimitry Andric #include "llvm/IR/DebugInfo.h"
338f0fd8f6SDimitry Andric #include "llvm/IR/DiagnosticInfo.h"
348f0fd8f6SDimitry Andric #include "llvm/IR/Instructions.h"
358f0fd8f6SDimitry Andric #include "llvm/IR/LLVMContext.h"
3697bc6c73SDimitry Andric #include "llvm/IR/Module.h"
378f0fd8f6SDimitry Andric #include "llvm/IR/ValueSymbolTable.h"
3897bc6c73SDimitry Andric #include "llvm/Support/LineIterator.h"
393ca95b02SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
4097bc6c73SDimitry Andric #include "llvm/Support/SMLoc.h"
4197bc6c73SDimitry Andric #include "llvm/Support/SourceMgr.h"
4297bc6c73SDimitry Andric #include "llvm/Support/YAMLTraits.h"
4397bc6c73SDimitry Andric #include <memory>
4497bc6c73SDimitry Andric 
4597bc6c73SDimitry Andric using namespace llvm;
4697bc6c73SDimitry Andric 
478f0fd8f6SDimitry Andric namespace llvm {
4897bc6c73SDimitry Andric 
4997bc6c73SDimitry Andric /// This class implements the parsing of LLVM IR that's embedded inside a MIR
5097bc6c73SDimitry Andric /// file.
5197bc6c73SDimitry Andric class MIRParserImpl {
5297bc6c73SDimitry Andric   SourceMgr SM;
53db17bf38SDimitry Andric   yaml::Input In;
5497bc6c73SDimitry Andric   StringRef Filename;
5597bc6c73SDimitry Andric   LLVMContext &Context;
563dac3a9bSDimitry Andric   SlotMapping IRSlots;
57875ed548SDimitry Andric   /// Maps from register class names to register classes.
587a7e6055SDimitry Andric   Name2RegClassMap Names2RegClasses;
593ca95b02SDimitry Andric   /// Maps from register bank names to register banks.
607a7e6055SDimitry Andric   Name2RegBankMap Names2RegBanks;
61db17bf38SDimitry Andric   /// True when the MIR file doesn't have LLVM IR. Dummy IR functions are
62db17bf38SDimitry Andric   /// created and inserted into the given module when this is true.
63db17bf38SDimitry Andric   bool NoLLVMIR = false;
64db17bf38SDimitry Andric   /// True when a well formed MIR file does not contain any MIR/machine function
65db17bf38SDimitry Andric   /// parts.
66db17bf38SDimitry Andric   bool NoMIRDocuments = false;
6797bc6c73SDimitry Andric 
6897bc6c73SDimitry Andric public:
69db17bf38SDimitry Andric   MIRParserImpl(std::unique_ptr<MemoryBuffer> Contents,
70db17bf38SDimitry Andric                 StringRef Filename, LLVMContext &Context);
7197bc6c73SDimitry Andric 
728f0fd8f6SDimitry Andric   void reportDiagnostic(const SMDiagnostic &Diag);
738f0fd8f6SDimitry Andric 
748f0fd8f6SDimitry Andric   /// Report an error with the given message at unknown location.
758f0fd8f6SDimitry Andric   ///
768f0fd8f6SDimitry Andric   /// Always returns true.
778f0fd8f6SDimitry Andric   bool error(const Twine &Message);
788f0fd8f6SDimitry Andric 
79875ed548SDimitry Andric   /// Report an error with the given message at the given location.
80875ed548SDimitry Andric   ///
81875ed548SDimitry Andric   /// Always returns true.
82875ed548SDimitry Andric   bool error(SMLoc Loc, const Twine &Message);
83875ed548SDimitry Andric 
843dac3a9bSDimitry Andric   /// Report a given error with the location translated from the location in an
853dac3a9bSDimitry Andric   /// embedded string literal to a location in the MIR file.
863dac3a9bSDimitry Andric   ///
873dac3a9bSDimitry Andric   /// Always returns true.
883dac3a9bSDimitry Andric   bool error(const SMDiagnostic &Error, SMRange SourceRange);
893dac3a9bSDimitry Andric 
9097bc6c73SDimitry Andric   /// Try to parse the optional LLVM module and the machine functions in the MIR
9197bc6c73SDimitry Andric   /// file.
9297bc6c73SDimitry Andric   ///
9397bc6c73SDimitry Andric   /// Return null if an error occurred.
94db17bf38SDimitry Andric   std::unique_ptr<Module> parseIRModule();
95db17bf38SDimitry Andric 
96db17bf38SDimitry Andric   bool parseMachineFunctions(Module &M, MachineModuleInfo &MMI);
9797bc6c73SDimitry Andric 
9897bc6c73SDimitry Andric   /// Parse the machine function in the current YAML document.
9997bc6c73SDimitry Andric   ///
1008f0fd8f6SDimitry Andric   ///
10197bc6c73SDimitry Andric   /// Return true if an error occurred.
102db17bf38SDimitry Andric   bool parseMachineFunction(Module &M, MachineModuleInfo &MMI);
1038f0fd8f6SDimitry Andric 
1048f0fd8f6SDimitry Andric   /// Initialize the machine function to the state that's described in the MIR
1058f0fd8f6SDimitry Andric   /// file.
1068f0fd8f6SDimitry Andric   ///
1078f0fd8f6SDimitry Andric   /// Return true if error occurred.
108db17bf38SDimitry Andric   bool initializeMachineFunction(const yaml::MachineFunction &YamlMF,
109db17bf38SDimitry Andric                                  MachineFunction &MF);
1108f0fd8f6SDimitry Andric 
111d88c1a5aSDimitry Andric   bool parseRegisterInfo(PerFunctionMIParsingState &PFS,
1123dac3a9bSDimitry Andric                          const yaml::MachineFunction &YamlMF);
11397bc6c73SDimitry Andric 
114d88c1a5aSDimitry Andric   bool setupRegisterInfo(const PerFunctionMIParsingState &PFS,
1153ca95b02SDimitry Andric                          const yaml::MachineFunction &YamlMF);
1167d523365SDimitry Andric 
1173ca95b02SDimitry Andric   bool initializeFrameInfo(PerFunctionMIParsingState &PFS,
1183ca95b02SDimitry Andric                            const yaml::MachineFunction &YamlMF);
1193ca95b02SDimitry Andric 
1203ca95b02SDimitry Andric   bool parseCalleeSavedRegister(PerFunctionMIParsingState &PFS,
1217d523365SDimitry Andric                                 std::vector<CalleeSavedInfo> &CSIInfo,
1227d523365SDimitry Andric                                 const yaml::StringValue &RegisterSource,
1232cab237bSDimitry Andric                                 bool IsRestored, int FrameIdx);
1247d523365SDimitry Andric 
1254ba319b5SDimitry Andric   template <typename T>
1263ca95b02SDimitry Andric   bool parseStackObjectsDebugInfo(PerFunctionMIParsingState &PFS,
1274ba319b5SDimitry Andric                                   const T &Object,
1287d523365SDimitry Andric                                   int FrameIdx);
1297d523365SDimitry Andric 
1303ca95b02SDimitry Andric   bool initializeConstantPool(PerFunctionMIParsingState &PFS,
1313ca95b02SDimitry Andric                               MachineConstantPool &ConstantPool,
1323ca95b02SDimitry Andric                               const yaml::MachineFunction &YamlMF);
1337d523365SDimitry Andric 
1343ca95b02SDimitry Andric   bool initializeJumpTableInfo(PerFunctionMIParsingState &PFS,
1353ca95b02SDimitry Andric                                const yaml::MachineJumpTable &YamlJTI);
1367d523365SDimitry Andric 
13797bc6c73SDimitry Andric private:
138d88c1a5aSDimitry Andric   bool parseMDNode(PerFunctionMIParsingState &PFS, MDNode *&Node,
1393ca95b02SDimitry Andric                    const yaml::StringValue &Source);
1407d523365SDimitry Andric 
141d88c1a5aSDimitry Andric   bool parseMBBReference(PerFunctionMIParsingState &PFS,
1423ca95b02SDimitry Andric                          MachineBasicBlock *&MBB,
1433ca95b02SDimitry Andric                          const yaml::StringValue &Source);
1447d523365SDimitry Andric 
1453dac3a9bSDimitry Andric   /// Return a MIR diagnostic converted from an MI string diagnostic.
1463dac3a9bSDimitry Andric   SMDiagnostic diagFromMIStringDiag(const SMDiagnostic &Error,
1473dac3a9bSDimitry Andric                                     SMRange SourceRange);
1483dac3a9bSDimitry Andric 
1497d523365SDimitry Andric   /// Return a MIR diagnostic converted from a diagnostic located in a YAML
1507d523365SDimitry Andric   /// block scalar string.
1517d523365SDimitry Andric   SMDiagnostic diagFromBlockStringDiag(const SMDiagnostic &Error,
15297bc6c73SDimitry Andric                                        SMRange SourceRange);
1538f0fd8f6SDimitry Andric 
154875ed548SDimitry Andric   void initNames2RegClasses(const MachineFunction &MF);
1553ca95b02SDimitry Andric   void initNames2RegBanks(const MachineFunction &MF);
156875ed548SDimitry Andric 
157875ed548SDimitry Andric   /// Check if the given identifier is a name of a register class.
158875ed548SDimitry Andric   ///
159875ed548SDimitry Andric   /// Return null if the name isn't a register class.
160875ed548SDimitry Andric   const TargetRegisterClass *getRegClass(const MachineFunction &MF,
161875ed548SDimitry Andric                                          StringRef Name);
1623ca95b02SDimitry Andric 
1633ca95b02SDimitry Andric   /// Check if the given identifier is a name of a register bank.
1643ca95b02SDimitry Andric   ///
1653ca95b02SDimitry Andric   /// Return null if the name isn't a register bank.
1663ca95b02SDimitry Andric   const RegisterBank *getRegBank(const MachineFunction &MF, StringRef Name);
167d88c1a5aSDimitry Andric 
168d88c1a5aSDimitry Andric   void computeFunctionProperties(MachineFunction &MF);
16997bc6c73SDimitry Andric };
17097bc6c73SDimitry Andric 
1718f0fd8f6SDimitry Andric } // end namespace llvm
17297bc6c73SDimitry Andric 
handleYAMLDiag(const SMDiagnostic & Diag,void * Context)173db17bf38SDimitry Andric static void handleYAMLDiag(const SMDiagnostic &Diag, void *Context) {
174db17bf38SDimitry Andric   reinterpret_cast<MIRParserImpl *>(Context)->reportDiagnostic(Diag);
175db17bf38SDimitry Andric }
176db17bf38SDimitry Andric 
MIRParserImpl(std::unique_ptr<MemoryBuffer> Contents,StringRef Filename,LLVMContext & Context)17797bc6c73SDimitry Andric MIRParserImpl::MIRParserImpl(std::unique_ptr<MemoryBuffer> Contents,
17897bc6c73SDimitry Andric                              StringRef Filename, LLVMContext &Context)
179db17bf38SDimitry Andric     : SM(),
180db17bf38SDimitry Andric       In(SM.getMemoryBuffer(
181db17bf38SDimitry Andric             SM.AddNewSourceBuffer(std::move(Contents), SMLoc()))->getBuffer(),
182db17bf38SDimitry Andric             nullptr, handleYAMLDiag, this),
183db17bf38SDimitry Andric       Filename(Filename),
184db17bf38SDimitry Andric       Context(Context) {
185db17bf38SDimitry Andric   In.setContext(&In);
18697bc6c73SDimitry Andric }
18797bc6c73SDimitry Andric 
error(const Twine & Message)1888f0fd8f6SDimitry Andric bool MIRParserImpl::error(const Twine &Message) {
1898f0fd8f6SDimitry Andric   Context.diagnose(DiagnosticInfoMIRParser(
1908f0fd8f6SDimitry Andric       DS_Error, SMDiagnostic(Filename, SourceMgr::DK_Error, Message.str())));
1918f0fd8f6SDimitry Andric   return true;
19297bc6c73SDimitry Andric }
19397bc6c73SDimitry Andric 
error(SMLoc Loc,const Twine & Message)194875ed548SDimitry Andric bool MIRParserImpl::error(SMLoc Loc, const Twine &Message) {
195875ed548SDimitry Andric   Context.diagnose(DiagnosticInfoMIRParser(
196875ed548SDimitry Andric       DS_Error, SM.GetMessage(Loc, SourceMgr::DK_Error, Message)));
197875ed548SDimitry Andric   return true;
198875ed548SDimitry Andric }
199875ed548SDimitry Andric 
error(const SMDiagnostic & Error,SMRange SourceRange)2003dac3a9bSDimitry Andric bool MIRParserImpl::error(const SMDiagnostic &Error, SMRange SourceRange) {
2013dac3a9bSDimitry Andric   assert(Error.getKind() == SourceMgr::DK_Error && "Expected an error");
2023dac3a9bSDimitry Andric   reportDiagnostic(diagFromMIStringDiag(Error, SourceRange));
2033dac3a9bSDimitry Andric   return true;
2043dac3a9bSDimitry Andric }
2053dac3a9bSDimitry Andric 
reportDiagnostic(const SMDiagnostic & Diag)2068f0fd8f6SDimitry Andric void MIRParserImpl::reportDiagnostic(const SMDiagnostic &Diag) {
2078f0fd8f6SDimitry Andric   DiagnosticSeverity Kind;
2088f0fd8f6SDimitry Andric   switch (Diag.getKind()) {
2098f0fd8f6SDimitry Andric   case SourceMgr::DK_Error:
2108f0fd8f6SDimitry Andric     Kind = DS_Error;
2118f0fd8f6SDimitry Andric     break;
2128f0fd8f6SDimitry Andric   case SourceMgr::DK_Warning:
2138f0fd8f6SDimitry Andric     Kind = DS_Warning;
2148f0fd8f6SDimitry Andric     break;
2158f0fd8f6SDimitry Andric   case SourceMgr::DK_Note:
2168f0fd8f6SDimitry Andric     Kind = DS_Note;
2178f0fd8f6SDimitry Andric     break;
2182cab237bSDimitry Andric   case SourceMgr::DK_Remark:
2192cab237bSDimitry Andric     llvm_unreachable("remark unexpected");
2202cab237bSDimitry Andric     break;
2218f0fd8f6SDimitry Andric   }
2228f0fd8f6SDimitry Andric   Context.diagnose(DiagnosticInfoMIRParser(Kind, Diag));
2238f0fd8f6SDimitry Andric }
2248f0fd8f6SDimitry Andric 
parseIRModule()225db17bf38SDimitry Andric std::unique_ptr<Module> MIRParserImpl::parseIRModule() {
22697bc6c73SDimitry Andric   if (!In.setCurrentDocument()) {
2278f0fd8f6SDimitry Andric     if (In.error())
22897bc6c73SDimitry Andric       return nullptr;
22997bc6c73SDimitry Andric     // Create an empty module when the MIR file is empty.
230db17bf38SDimitry Andric     NoMIRDocuments = true;
23197bc6c73SDimitry Andric     return llvm::make_unique<Module>(Filename, Context);
23297bc6c73SDimitry Andric   }
23397bc6c73SDimitry Andric 
23497bc6c73SDimitry Andric   std::unique_ptr<Module> M;
23597bc6c73SDimitry Andric   // Parse the block scalar manually so that we can return unique pointer
23697bc6c73SDimitry Andric   // without having to go trough YAML traits.
23797bc6c73SDimitry Andric   if (const auto *BSN =
23897bc6c73SDimitry Andric           dyn_cast_or_null<yaml::BlockScalarNode>(In.getCurrentNode())) {
2398f0fd8f6SDimitry Andric     SMDiagnostic Error;
24097bc6c73SDimitry Andric     M = parseAssembly(MemoryBufferRef(BSN->getValue(), Filename), Error,
2414ba319b5SDimitry Andric                       Context, &IRSlots, /*UpgradeDebugInfo=*/false);
24297bc6c73SDimitry Andric     if (!M) {
2437d523365SDimitry Andric       reportDiagnostic(diagFromBlockStringDiag(Error, BSN->getSourceRange()));
2443ca95b02SDimitry Andric       return nullptr;
24597bc6c73SDimitry Andric     }
24697bc6c73SDimitry Andric     In.nextDocument();
24797bc6c73SDimitry Andric     if (!In.setCurrentDocument())
248db17bf38SDimitry Andric       NoMIRDocuments = true;
24997bc6c73SDimitry Andric   } else {
25097bc6c73SDimitry Andric     // Create an new, empty module.
25197bc6c73SDimitry Andric     M = llvm::make_unique<Module>(Filename, Context);
2528f0fd8f6SDimitry Andric     NoLLVMIR = true;
25397bc6c73SDimitry Andric   }
25497bc6c73SDimitry Andric   return M;
25597bc6c73SDimitry Andric }
25697bc6c73SDimitry Andric 
parseMachineFunctions(Module & M,MachineModuleInfo & MMI)257db17bf38SDimitry Andric bool MIRParserImpl::parseMachineFunctions(Module &M, MachineModuleInfo &MMI) {
258db17bf38SDimitry Andric   if (NoMIRDocuments)
259db17bf38SDimitry Andric     return false;
260db17bf38SDimitry Andric 
261db17bf38SDimitry Andric   // Parse the machine functions.
262db17bf38SDimitry Andric   do {
263db17bf38SDimitry Andric     if (parseMachineFunction(M, MMI))
26497bc6c73SDimitry Andric       return true;
265db17bf38SDimitry Andric     In.nextDocument();
266db17bf38SDimitry Andric   } while (In.setCurrentDocument());
267db17bf38SDimitry Andric 
2688f0fd8f6SDimitry Andric   return false;
2698f0fd8f6SDimitry Andric }
2708f0fd8f6SDimitry Andric 
271db17bf38SDimitry Andric /// Create an empty function with the given name.
createDummyFunction(StringRef Name,Module & M)272db17bf38SDimitry Andric static Function *createDummyFunction(StringRef Name, Module &M) {
2738f0fd8f6SDimitry Andric   auto &Context = M.getContext();
2748f0fd8f6SDimitry Andric   Function *F = cast<Function>(M.getOrInsertFunction(
2758f0fd8f6SDimitry Andric       Name, FunctionType::get(Type::getVoidTy(Context), false)));
2768f0fd8f6SDimitry Andric   BasicBlock *BB = BasicBlock::Create(Context, "entry", F);
2778f0fd8f6SDimitry Andric   new UnreachableInst(Context, BB);
278db17bf38SDimitry Andric   return F;
279db17bf38SDimitry Andric }
280db17bf38SDimitry Andric 
parseMachineFunction(Module & M,MachineModuleInfo & MMI)281db17bf38SDimitry Andric bool MIRParserImpl::parseMachineFunction(Module &M, MachineModuleInfo &MMI) {
282db17bf38SDimitry Andric   // Parse the yaml.
283db17bf38SDimitry Andric   yaml::MachineFunction YamlMF;
284db17bf38SDimitry Andric   yaml::EmptyContext Ctx;
285db17bf38SDimitry Andric   yaml::yamlize(In, YamlMF, false, Ctx);
286db17bf38SDimitry Andric   if (In.error())
287db17bf38SDimitry Andric     return true;
288db17bf38SDimitry Andric 
289db17bf38SDimitry Andric   // Search for the corresponding IR function.
290db17bf38SDimitry Andric   StringRef FunctionName = YamlMF.Name;
291db17bf38SDimitry Andric   Function *F = M.getFunction(FunctionName);
292db17bf38SDimitry Andric   if (!F) {
293db17bf38SDimitry Andric     if (NoLLVMIR) {
294db17bf38SDimitry Andric       F = createDummyFunction(FunctionName, M);
295db17bf38SDimitry Andric     } else {
296db17bf38SDimitry Andric       return error(Twine("function '") + FunctionName +
297db17bf38SDimitry Andric                    "' isn't defined in the provided LLVM IR");
298db17bf38SDimitry Andric     }
299db17bf38SDimitry Andric   }
300db17bf38SDimitry Andric   if (MMI.getMachineFunction(*F) != nullptr)
301db17bf38SDimitry Andric     return error(Twine("redefinition of machine function '") + FunctionName +
302db17bf38SDimitry Andric                  "'");
303db17bf38SDimitry Andric 
304db17bf38SDimitry Andric   // Create the MachineFunction.
305db17bf38SDimitry Andric   MachineFunction &MF = MMI.getOrCreateMachineFunction(*F);
306db17bf38SDimitry Andric   if (initializeMachineFunction(YamlMF, MF))
307db17bf38SDimitry Andric     return true;
308db17bf38SDimitry Andric 
309db17bf38SDimitry Andric   return false;
3108f0fd8f6SDimitry Andric }
3118f0fd8f6SDimitry Andric 
isSSA(const MachineFunction & MF)312d88c1a5aSDimitry Andric static bool isSSA(const MachineFunction &MF) {
313d88c1a5aSDimitry Andric   const MachineRegisterInfo &MRI = MF.getRegInfo();
314d88c1a5aSDimitry Andric   for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
315d88c1a5aSDimitry Andric     unsigned Reg = TargetRegisterInfo::index2VirtReg(I);
316d88c1a5aSDimitry Andric     if (!MRI.hasOneDef(Reg) && !MRI.def_empty(Reg))
317d88c1a5aSDimitry Andric       return false;
318d88c1a5aSDimitry Andric   }
319d88c1a5aSDimitry Andric   return true;
320d88c1a5aSDimitry Andric }
321d88c1a5aSDimitry Andric 
computeFunctionProperties(MachineFunction & MF)322d88c1a5aSDimitry Andric void MIRParserImpl::computeFunctionProperties(MachineFunction &MF) {
323d88c1a5aSDimitry Andric   MachineFunctionProperties &Properties = MF.getProperties();
324d88c1a5aSDimitry Andric 
325d88c1a5aSDimitry Andric   bool HasPHI = false;
326d88c1a5aSDimitry Andric   bool HasInlineAsm = false;
327d88c1a5aSDimitry Andric   for (const MachineBasicBlock &MBB : MF) {
328d88c1a5aSDimitry Andric     for (const MachineInstr &MI : MBB) {
329d88c1a5aSDimitry Andric       if (MI.isPHI())
330d88c1a5aSDimitry Andric         HasPHI = true;
331d88c1a5aSDimitry Andric       if (MI.isInlineAsm())
332d88c1a5aSDimitry Andric         HasInlineAsm = true;
333d88c1a5aSDimitry Andric     }
334d88c1a5aSDimitry Andric   }
335d88c1a5aSDimitry Andric   if (!HasPHI)
336d88c1a5aSDimitry Andric     Properties.set(MachineFunctionProperties::Property::NoPHIs);
337d88c1a5aSDimitry Andric   MF.setHasInlineAsm(HasInlineAsm);
338d88c1a5aSDimitry Andric 
339d88c1a5aSDimitry Andric   if (isSSA(MF))
340d88c1a5aSDimitry Andric     Properties.set(MachineFunctionProperties::Property::IsSSA);
341d88c1a5aSDimitry Andric   else
342d88c1a5aSDimitry Andric     Properties.reset(MachineFunctionProperties::Property::IsSSA);
343d88c1a5aSDimitry Andric 
344d88c1a5aSDimitry Andric   const MachineRegisterInfo &MRI = MF.getRegInfo();
345d88c1a5aSDimitry Andric   if (MRI.getNumVirtRegs() == 0)
346d88c1a5aSDimitry Andric     Properties.set(MachineFunctionProperties::Property::NoVRegs);
347d88c1a5aSDimitry Andric }
348d88c1a5aSDimitry Andric 
349db17bf38SDimitry Andric bool
initializeMachineFunction(const yaml::MachineFunction & YamlMF,MachineFunction & MF)350db17bf38SDimitry Andric MIRParserImpl::initializeMachineFunction(const yaml::MachineFunction &YamlMF,
351db17bf38SDimitry Andric                                          MachineFunction &MF) {
3528f0fd8f6SDimitry Andric   // TODO: Recreate the machine function.
3537a7e6055SDimitry Andric   initNames2RegClasses(MF);
3547a7e6055SDimitry Andric   initNames2RegBanks(MF);
3558f0fd8f6SDimitry Andric   if (YamlMF.Alignment)
3568f0fd8f6SDimitry Andric     MF.setAlignment(YamlMF.Alignment);
3578f0fd8f6SDimitry Andric   MF.setExposesReturnsTwice(YamlMF.ExposesReturnsTwice);
358*b5893f02SDimitry Andric   MF.setHasWinCFI(YamlMF.HasWinCFI);
359d88c1a5aSDimitry Andric 
360d88c1a5aSDimitry Andric   if (YamlMF.Legalized)
361d88c1a5aSDimitry Andric     MF.getProperties().set(MachineFunctionProperties::Property::Legalized);
362d88c1a5aSDimitry Andric   if (YamlMF.RegBankSelected)
363d88c1a5aSDimitry Andric     MF.getProperties().set(
364d88c1a5aSDimitry Andric         MachineFunctionProperties::Property::RegBankSelected);
365d88c1a5aSDimitry Andric   if (YamlMF.Selected)
366d88c1a5aSDimitry Andric     MF.getProperties().set(MachineFunctionProperties::Property::Selected);
3674ba319b5SDimitry Andric   if (YamlMF.FailedISel)
3684ba319b5SDimitry Andric     MF.getProperties().set(MachineFunctionProperties::Property::FailedISel);
369d88c1a5aSDimitry Andric 
3707a7e6055SDimitry Andric   PerFunctionMIParsingState PFS(MF, SM, IRSlots, Names2RegClasses,
3717a7e6055SDimitry Andric                                 Names2RegBanks);
372d88c1a5aSDimitry Andric   if (parseRegisterInfo(PFS, YamlMF))
373875ed548SDimitry Andric     return true;
3747d523365SDimitry Andric   if (!YamlMF.Constants.empty()) {
3757d523365SDimitry Andric     auto *ConstantPool = MF.getConstantPool();
3767d523365SDimitry Andric     assert(ConstantPool && "Constant pool must be created");
3773ca95b02SDimitry Andric     if (initializeConstantPool(PFS, *ConstantPool, YamlMF))
3783dac3a9bSDimitry Andric       return true;
3793dac3a9bSDimitry Andric   }
3803dac3a9bSDimitry Andric 
3813ca95b02SDimitry Andric   StringRef BlockStr = YamlMF.Body.Value.Value;
3827d523365SDimitry Andric   SMDiagnostic Error;
3833ca95b02SDimitry Andric   SourceMgr BlockSM;
3843ca95b02SDimitry Andric   BlockSM.AddNewSourceBuffer(
3853ca95b02SDimitry Andric       MemoryBuffer::getMemBuffer(BlockStr, "",/*RequiresNullTerminator=*/false),
3863ca95b02SDimitry Andric       SMLoc());
3873ca95b02SDimitry Andric   PFS.SM = &BlockSM;
3883ca95b02SDimitry Andric   if (parseMachineBasicBlockDefinitions(PFS, BlockStr, Error)) {
3897d523365SDimitry Andric     reportDiagnostic(
3907d523365SDimitry Andric         diagFromBlockStringDiag(Error, YamlMF.Body.Value.SourceRange));
3917d523365SDimitry Andric     return true;
3927d523365SDimitry Andric   }
3933ca95b02SDimitry Andric   PFS.SM = &SM;
3947d523365SDimitry Andric 
3957d523365SDimitry Andric   // Initialize the frame information after creating all the MBBs so that the
3967d523365SDimitry Andric   // MBB references in the frame information can be resolved.
3973ca95b02SDimitry Andric   if (initializeFrameInfo(PFS, YamlMF))
3987d523365SDimitry Andric     return true;
3997d523365SDimitry Andric   // Initialize the jump table after creating all the MBBs so that the MBB
4007d523365SDimitry Andric   // references can be resolved.
4017d523365SDimitry Andric   if (!YamlMF.JumpTableInfo.Entries.empty() &&
4023ca95b02SDimitry Andric       initializeJumpTableInfo(PFS, YamlMF.JumpTableInfo))
4037d523365SDimitry Andric     return true;
4047d523365SDimitry Andric   // Parse the machine instructions after creating all of the MBBs so that the
4057d523365SDimitry Andric   // parser can resolve the MBB references.
4063ca95b02SDimitry Andric   StringRef InsnStr = YamlMF.Body.Value.Value;
4073ca95b02SDimitry Andric   SourceMgr InsnSM;
4083ca95b02SDimitry Andric   InsnSM.AddNewSourceBuffer(
4093ca95b02SDimitry Andric       MemoryBuffer::getMemBuffer(InsnStr, "", /*RequiresNullTerminator=*/false),
4103ca95b02SDimitry Andric       SMLoc());
4113ca95b02SDimitry Andric   PFS.SM = &InsnSM;
4123ca95b02SDimitry Andric   if (parseMachineInstructions(PFS, InsnStr, Error)) {
4137d523365SDimitry Andric     reportDiagnostic(
4147d523365SDimitry Andric         diagFromBlockStringDiag(Error, YamlMF.Body.Value.SourceRange));
4158f0fd8f6SDimitry Andric     return true;
4168f0fd8f6SDimitry Andric   }
4173ca95b02SDimitry Andric   PFS.SM = &SM;
4183ca95b02SDimitry Andric 
419d88c1a5aSDimitry Andric   if (setupRegisterInfo(PFS, YamlMF))
420d88c1a5aSDimitry Andric     return true;
421d88c1a5aSDimitry Andric 
422d88c1a5aSDimitry Andric   computeFunctionProperties(MF);
423d88c1a5aSDimitry Andric 
4244ba319b5SDimitry Andric   MF.getSubtarget().mirFileLoaded(MF);
4254ba319b5SDimitry Andric 
4267d523365SDimitry Andric   MF.verify();
4278f0fd8f6SDimitry Andric   return false;
4288f0fd8f6SDimitry Andric }
4298f0fd8f6SDimitry Andric 
parseRegisterInfo(PerFunctionMIParsingState & PFS,const yaml::MachineFunction & YamlMF)430d88c1a5aSDimitry Andric bool MIRParserImpl::parseRegisterInfo(PerFunctionMIParsingState &PFS,
4313ca95b02SDimitry Andric                                       const yaml::MachineFunction &YamlMF) {
4323ca95b02SDimitry Andric   MachineFunction &MF = PFS.MF;
4337d523365SDimitry Andric   MachineRegisterInfo &RegInfo = MF.getRegInfo();
4343dac3a9bSDimitry Andric   assert(RegInfo.tracksLiveness());
4353dac3a9bSDimitry Andric   if (!YamlMF.TracksRegLiveness)
4363dac3a9bSDimitry Andric     RegInfo.invalidateLiveness();
437875ed548SDimitry Andric 
4387d523365SDimitry Andric   SMDiagnostic Error;
439875ed548SDimitry Andric   // Parse the virtual register information.
440875ed548SDimitry Andric   for (const auto &VReg : YamlMF.VirtualRegisters) {
441d88c1a5aSDimitry Andric     VRegInfo &Info = PFS.getVRegInfo(VReg.ID.Value);
442d88c1a5aSDimitry Andric     if (Info.Explicit)
443d88c1a5aSDimitry Andric       return error(VReg.ID.SourceRange.Start,
444d88c1a5aSDimitry Andric                    Twine("redefinition of virtual register '%") +
445d88c1a5aSDimitry Andric                        Twine(VReg.ID.Value) + "'");
446d88c1a5aSDimitry Andric     Info.Explicit = true;
447d88c1a5aSDimitry Andric 
4483ca95b02SDimitry Andric     if (StringRef(VReg.Class.Value).equals("_")) {
449d88c1a5aSDimitry Andric       Info.Kind = VRegInfo::GENERIC;
4502cab237bSDimitry Andric       Info.D.RegBank = nullptr;
4513ca95b02SDimitry Andric     } else {
452875ed548SDimitry Andric       const auto *RC = getRegClass(MF, VReg.Class.Value);
4533ca95b02SDimitry Andric       if (RC) {
454d88c1a5aSDimitry Andric         Info.Kind = VRegInfo::NORMAL;
455d88c1a5aSDimitry Andric         Info.D.RC = RC;
4563ca95b02SDimitry Andric       } else {
457d88c1a5aSDimitry Andric         const RegisterBank *RegBank = getRegBank(MF, VReg.Class.Value);
4583ca95b02SDimitry Andric         if (!RegBank)
4593ca95b02SDimitry Andric           return error(
4603ca95b02SDimitry Andric               VReg.Class.SourceRange.Start,
4613ca95b02SDimitry Andric               Twine("use of undefined register class or register bank '") +
462875ed548SDimitry Andric                   VReg.Class.Value + "'");
463d88c1a5aSDimitry Andric         Info.Kind = VRegInfo::REGBANK;
464d88c1a5aSDimitry Andric         Info.D.RegBank = RegBank;
4653ca95b02SDimitry Andric       }
4663ca95b02SDimitry Andric     }
467d88c1a5aSDimitry Andric 
4687d523365SDimitry Andric     if (!VReg.PreferredRegister.Value.empty()) {
469d88c1a5aSDimitry Andric       if (Info.Kind != VRegInfo::NORMAL)
470d88c1a5aSDimitry Andric         return error(VReg.Class.SourceRange.Start,
471d88c1a5aSDimitry Andric               Twine("preferred register can only be set for normal vregs"));
472d88c1a5aSDimitry Andric 
473d88c1a5aSDimitry Andric       if (parseRegisterReference(PFS, Info.PreferredReg,
4743ca95b02SDimitry Andric                                  VReg.PreferredRegister.Value, Error))
4757d523365SDimitry Andric         return error(Error, VReg.PreferredRegister.SourceRange);
476875ed548SDimitry Andric     }
4777d523365SDimitry Andric   }
4787d523365SDimitry Andric 
4797d523365SDimitry Andric   // Parse the liveins.
4807d523365SDimitry Andric   for (const auto &LiveIn : YamlMF.LiveIns) {
4817d523365SDimitry Andric     unsigned Reg = 0;
4823ca95b02SDimitry Andric     if (parseNamedRegisterReference(PFS, Reg, LiveIn.Register.Value, Error))
4837d523365SDimitry Andric       return error(Error, LiveIn.Register.SourceRange);
4847d523365SDimitry Andric     unsigned VReg = 0;
4857d523365SDimitry Andric     if (!LiveIn.VirtualRegister.Value.empty()) {
486d88c1a5aSDimitry Andric       VRegInfo *Info;
487d88c1a5aSDimitry Andric       if (parseVirtualRegisterReference(PFS, Info, LiveIn.VirtualRegister.Value,
4883ca95b02SDimitry Andric                                         Error))
4897d523365SDimitry Andric         return error(Error, LiveIn.VirtualRegister.SourceRange);
490d88c1a5aSDimitry Andric       VReg = Info->VReg;
4917d523365SDimitry Andric     }
4927d523365SDimitry Andric     RegInfo.addLiveIn(Reg, VReg);
4937d523365SDimitry Andric   }
4947d523365SDimitry Andric 
4957a7e6055SDimitry Andric   // Parse the callee saved registers (Registers that will
4967a7e6055SDimitry Andric   // be saved for the caller).
4977a7e6055SDimitry Andric   if (YamlMF.CalleeSavedRegisters) {
4987a7e6055SDimitry Andric     SmallVector<MCPhysReg, 16> CalleeSavedRegisters;
4997d523365SDimitry Andric     for (const auto &RegSource : YamlMF.CalleeSavedRegisters.getValue()) {
5007d523365SDimitry Andric       unsigned Reg = 0;
5013ca95b02SDimitry Andric       if (parseNamedRegisterReference(PFS, Reg, RegSource.Value, Error))
5027d523365SDimitry Andric         return error(Error, RegSource.SourceRange);
5037a7e6055SDimitry Andric       CalleeSavedRegisters.push_back(Reg);
5047d523365SDimitry Andric     }
5057a7e6055SDimitry Andric     RegInfo.setCalleeSavedRegs(CalleeSavedRegisters);
5067a7e6055SDimitry Andric   }
5077a7e6055SDimitry Andric 
508875ed548SDimitry Andric   return false;
509875ed548SDimitry Andric }
510875ed548SDimitry Andric 
setupRegisterInfo(const PerFunctionMIParsingState & PFS,const yaml::MachineFunction & YamlMF)511d88c1a5aSDimitry Andric bool MIRParserImpl::setupRegisterInfo(const PerFunctionMIParsingState &PFS,
512875ed548SDimitry Andric                                       const yaml::MachineFunction &YamlMF) {
513d88c1a5aSDimitry Andric   MachineFunction &MF = PFS.MF;
514d88c1a5aSDimitry Andric   MachineRegisterInfo &MRI = MF.getRegInfo();
515d88c1a5aSDimitry Andric   bool Error = false;
516d88c1a5aSDimitry Andric   // Create VRegs
5174ba319b5SDimitry Andric   auto populateVRegInfo = [&] (const VRegInfo &Info, Twine Name) {
518d88c1a5aSDimitry Andric     unsigned Reg = Info.VReg;
519d88c1a5aSDimitry Andric     switch (Info.Kind) {
520d88c1a5aSDimitry Andric     case VRegInfo::UNKNOWN:
521d88c1a5aSDimitry Andric       error(Twine("Cannot determine class/bank of virtual register ") +
5224ba319b5SDimitry Andric             Name + " in function '" + MF.getName() + "'");
523d88c1a5aSDimitry Andric       Error = true;
524d88c1a5aSDimitry Andric       break;
525d88c1a5aSDimitry Andric     case VRegInfo::NORMAL:
526d88c1a5aSDimitry Andric       MRI.setRegClass(Reg, Info.D.RC);
527d88c1a5aSDimitry Andric       if (Info.PreferredReg != 0)
528d88c1a5aSDimitry Andric         MRI.setSimpleHint(Reg, Info.PreferredReg);
529d88c1a5aSDimitry Andric       break;
530d88c1a5aSDimitry Andric     case VRegInfo::GENERIC:
531d88c1a5aSDimitry Andric       break;
532d88c1a5aSDimitry Andric     case VRegInfo::REGBANK:
533d88c1a5aSDimitry Andric       MRI.setRegBank(Reg, *Info.D.RegBank);
534d88c1a5aSDimitry Andric       break;
535d88c1a5aSDimitry Andric     }
5364ba319b5SDimitry Andric   };
5374ba319b5SDimitry Andric 
5384ba319b5SDimitry Andric   for (auto I = PFS.VRegInfosNamed.begin(), E = PFS.VRegInfosNamed.end();
5394ba319b5SDimitry Andric        I != E; I++) {
5404ba319b5SDimitry Andric     const VRegInfo &Info = *I->second;
5414ba319b5SDimitry Andric     populateVRegInfo(Info, Twine(I->first()));
5424ba319b5SDimitry Andric   }
5434ba319b5SDimitry Andric 
5444ba319b5SDimitry Andric   for (auto P : PFS.VRegInfos) {
5454ba319b5SDimitry Andric     const VRegInfo &Info = *P.second;
5464ba319b5SDimitry Andric     populateVRegInfo(Info, Twine(P.first));
547d88c1a5aSDimitry Andric   }
548d88c1a5aSDimitry Andric 
549d88c1a5aSDimitry Andric   // Compute MachineRegisterInfo::UsedPhysRegMask
550d88c1a5aSDimitry Andric   for (const MachineBasicBlock &MBB : MF) {
5517d523365SDimitry Andric     for (const MachineInstr &MI : MBB) {
5527d523365SDimitry Andric       for (const MachineOperand &MO : MI.operands()) {
5537d523365SDimitry Andric         if (!MO.isRegMask())
5547d523365SDimitry Andric           continue;
5553ca95b02SDimitry Andric         MRI.addPhysRegsUsedFromRegMask(MO.getRegMask());
5567d523365SDimitry Andric       }
5577d523365SDimitry Andric     }
5587d523365SDimitry Andric   }
5597d523365SDimitry Andric 
560d88c1a5aSDimitry Andric   // FIXME: This is a temporary workaround until the reserved registers can be
561d88c1a5aSDimitry Andric   // serialized.
562d88c1a5aSDimitry Andric   MRI.freezeReservedRegs(MF);
563d88c1a5aSDimitry Andric   return Error;
564d88c1a5aSDimitry Andric }
565d88c1a5aSDimitry Andric 
initializeFrameInfo(PerFunctionMIParsingState & PFS,const yaml::MachineFunction & YamlMF)5663ca95b02SDimitry Andric bool MIRParserImpl::initializeFrameInfo(PerFunctionMIParsingState &PFS,
5673ca95b02SDimitry Andric                                         const yaml::MachineFunction &YamlMF) {
5683ca95b02SDimitry Andric   MachineFunction &MF = PFS.MF;
569d88c1a5aSDimitry Andric   MachineFrameInfo &MFI = MF.getFrameInfo();
5702cab237bSDimitry Andric   const Function &F = MF.getFunction();
571875ed548SDimitry Andric   const yaml::MachineFrameInfo &YamlMFI = YamlMF.FrameInfo;
572875ed548SDimitry Andric   MFI.setFrameAddressIsTaken(YamlMFI.IsFrameAddressTaken);
573875ed548SDimitry Andric   MFI.setReturnAddressIsTaken(YamlMFI.IsReturnAddressTaken);
574875ed548SDimitry Andric   MFI.setHasStackMap(YamlMFI.HasStackMap);
575875ed548SDimitry Andric   MFI.setHasPatchPoint(YamlMFI.HasPatchPoint);
576875ed548SDimitry Andric   MFI.setStackSize(YamlMFI.StackSize);
577875ed548SDimitry Andric   MFI.setOffsetAdjustment(YamlMFI.OffsetAdjustment);
578875ed548SDimitry Andric   if (YamlMFI.MaxAlignment)
579875ed548SDimitry Andric     MFI.ensureMaxAlignment(YamlMFI.MaxAlignment);
580875ed548SDimitry Andric   MFI.setAdjustsStack(YamlMFI.AdjustsStack);
581875ed548SDimitry Andric   MFI.setHasCalls(YamlMFI.HasCalls);
582f37b6182SDimitry Andric   if (YamlMFI.MaxCallFrameSize != ~0u)
583875ed548SDimitry Andric     MFI.setMaxCallFrameSize(YamlMFI.MaxCallFrameSize);
584*b5893f02SDimitry Andric   MFI.setCVBytesOfCalleeSavedRegisters(YamlMFI.CVBytesOfCalleeSavedRegisters);
585875ed548SDimitry Andric   MFI.setHasOpaqueSPAdjustment(YamlMFI.HasOpaqueSPAdjustment);
586875ed548SDimitry Andric   MFI.setHasVAStart(YamlMFI.HasVAStart);
587875ed548SDimitry Andric   MFI.setHasMustTailInVarArgFunc(YamlMFI.HasMustTailInVarArgFunc);
5884ba319b5SDimitry Andric   MFI.setLocalFrameSize(YamlMFI.LocalFrameSize);
5897d523365SDimitry Andric   if (!YamlMFI.SavePoint.Value.empty()) {
5907d523365SDimitry Andric     MachineBasicBlock *MBB = nullptr;
5913ca95b02SDimitry Andric     if (parseMBBReference(PFS, MBB, YamlMFI.SavePoint))
5927d523365SDimitry Andric       return true;
5937d523365SDimitry Andric     MFI.setSavePoint(MBB);
5947d523365SDimitry Andric   }
5957d523365SDimitry Andric   if (!YamlMFI.RestorePoint.Value.empty()) {
5967d523365SDimitry Andric     MachineBasicBlock *MBB = nullptr;
5973ca95b02SDimitry Andric     if (parseMBBReference(PFS, MBB, YamlMFI.RestorePoint))
5987d523365SDimitry Andric       return true;
5997d523365SDimitry Andric     MFI.setRestorePoint(MBB);
6007d523365SDimitry Andric   }
601875ed548SDimitry Andric 
6027d523365SDimitry Andric   std::vector<CalleeSavedInfo> CSIInfo;
603875ed548SDimitry Andric   // Initialize the fixed frame objects.
604875ed548SDimitry Andric   for (const auto &Object : YamlMF.FixedStackObjects) {
605875ed548SDimitry Andric     int ObjectIdx;
606875ed548SDimitry Andric     if (Object.Type != yaml::FixedMachineStackObject::SpillSlot)
607875ed548SDimitry Andric       ObjectIdx = MFI.CreateFixedObject(Object.Size, Object.Offset,
608875ed548SDimitry Andric                                         Object.IsImmutable, Object.IsAliased);
609875ed548SDimitry Andric     else
610875ed548SDimitry Andric       ObjectIdx = MFI.CreateFixedSpillStackObject(Object.Size, Object.Offset);
611875ed548SDimitry Andric     MFI.setObjectAlignment(ObjectIdx, Object.Alignment);
6122cab237bSDimitry Andric     MFI.setStackID(ObjectIdx, Object.StackID);
6137d523365SDimitry Andric     if (!PFS.FixedStackObjectSlots.insert(std::make_pair(Object.ID.Value,
6147d523365SDimitry Andric                                                          ObjectIdx))
6157d523365SDimitry Andric              .second)
6167d523365SDimitry Andric       return error(Object.ID.SourceRange.Start,
6177d523365SDimitry Andric                    Twine("redefinition of fixed stack object '%fixed-stack.") +
6187d523365SDimitry Andric                        Twine(Object.ID.Value) + "'");
6193ca95b02SDimitry Andric     if (parseCalleeSavedRegister(PFS, CSIInfo, Object.CalleeSavedRegister,
6202cab237bSDimitry Andric                                  Object.CalleeSavedRestored, ObjectIdx))
6217d523365SDimitry Andric       return true;
6224ba319b5SDimitry Andric     if (parseStackObjectsDebugInfo(PFS, Object, ObjectIdx))
6234ba319b5SDimitry Andric       return true;
624875ed548SDimitry Andric   }
625875ed548SDimitry Andric 
626875ed548SDimitry Andric   // Initialize the ordinary frame objects.
627875ed548SDimitry Andric   for (const auto &Object : YamlMF.StackObjects) {
628875ed548SDimitry Andric     int ObjectIdx;
6297d523365SDimitry Andric     const AllocaInst *Alloca = nullptr;
6307d523365SDimitry Andric     const yaml::StringValue &Name = Object.Name;
6317d523365SDimitry Andric     if (!Name.Value.empty()) {
6327d523365SDimitry Andric       Alloca = dyn_cast_or_null<AllocaInst>(
633d88c1a5aSDimitry Andric           F.getValueSymbolTable()->lookup(Name.Value));
6347d523365SDimitry Andric       if (!Alloca)
6357d523365SDimitry Andric         return error(Name.SourceRange.Start,
6367d523365SDimitry Andric                      "alloca instruction named '" + Name.Value +
6377d523365SDimitry Andric                          "' isn't defined in the function '" + F.getName() +
6387d523365SDimitry Andric                          "'");
6397d523365SDimitry Andric     }
640875ed548SDimitry Andric     if (Object.Type == yaml::MachineStackObject::VariableSized)
6417d523365SDimitry Andric       ObjectIdx = MFI.CreateVariableSizedObject(Object.Alignment, Alloca);
642875ed548SDimitry Andric     else
643875ed548SDimitry Andric       ObjectIdx = MFI.CreateStackObject(
644875ed548SDimitry Andric           Object.Size, Object.Alignment,
6457d523365SDimitry Andric           Object.Type == yaml::MachineStackObject::SpillSlot, Alloca);
646875ed548SDimitry Andric     MFI.setObjectOffset(ObjectIdx, Object.Offset);
6472cab237bSDimitry Andric     MFI.setStackID(ObjectIdx, Object.StackID);
6482cab237bSDimitry Andric 
6497d523365SDimitry Andric     if (!PFS.StackObjectSlots.insert(std::make_pair(Object.ID.Value, ObjectIdx))
6507d523365SDimitry Andric              .second)
6517d523365SDimitry Andric       return error(Object.ID.SourceRange.Start,
6527d523365SDimitry Andric                    Twine("redefinition of stack object '%stack.") +
6537d523365SDimitry Andric                        Twine(Object.ID.Value) + "'");
6543ca95b02SDimitry Andric     if (parseCalleeSavedRegister(PFS, CSIInfo, Object.CalleeSavedRegister,
6552cab237bSDimitry Andric                                  Object.CalleeSavedRestored, ObjectIdx))
6567d523365SDimitry Andric       return true;
6577d523365SDimitry Andric     if (Object.LocalOffset)
6587d523365SDimitry Andric       MFI.mapLocalFrameObject(ObjectIdx, Object.LocalOffset.getValue());
6593ca95b02SDimitry Andric     if (parseStackObjectsDebugInfo(PFS, Object, ObjectIdx))
6607d523365SDimitry Andric       return true;
661875ed548SDimitry Andric   }
6627d523365SDimitry Andric   MFI.setCalleeSavedInfo(CSIInfo);
6637d523365SDimitry Andric   if (!CSIInfo.empty())
6647d523365SDimitry Andric     MFI.setCalleeSavedInfoValid(true);
6657d523365SDimitry Andric 
6667d523365SDimitry Andric   // Initialize the various stack object references after initializing the
6677d523365SDimitry Andric   // stack objects.
6687d523365SDimitry Andric   if (!YamlMFI.StackProtector.Value.empty()) {
6697d523365SDimitry Andric     SMDiagnostic Error;
6707d523365SDimitry Andric     int FI;
6713ca95b02SDimitry Andric     if (parseStackObjectReference(PFS, FI, YamlMFI.StackProtector.Value, Error))
6727d523365SDimitry Andric       return error(Error, YamlMFI.StackProtector.SourceRange);
6737d523365SDimitry Andric     MFI.setStackProtectorIndex(FI);
6747d523365SDimitry Andric   }
6757d523365SDimitry Andric   return false;
6767d523365SDimitry Andric }
6777d523365SDimitry Andric 
parseCalleeSavedRegister(PerFunctionMIParsingState & PFS,std::vector<CalleeSavedInfo> & CSIInfo,const yaml::StringValue & RegisterSource,bool IsRestored,int FrameIdx)6783ca95b02SDimitry Andric bool MIRParserImpl::parseCalleeSavedRegister(PerFunctionMIParsingState &PFS,
6797d523365SDimitry Andric     std::vector<CalleeSavedInfo> &CSIInfo,
6802cab237bSDimitry Andric     const yaml::StringValue &RegisterSource, bool IsRestored, int FrameIdx) {
6817d523365SDimitry Andric   if (RegisterSource.Value.empty())
6827d523365SDimitry Andric     return false;
6837d523365SDimitry Andric   unsigned Reg = 0;
6847d523365SDimitry Andric   SMDiagnostic Error;
6853ca95b02SDimitry Andric   if (parseNamedRegisterReference(PFS, Reg, RegisterSource.Value, Error))
6867d523365SDimitry Andric     return error(Error, RegisterSource.SourceRange);
6872cab237bSDimitry Andric   CalleeSavedInfo CSI(Reg, FrameIdx);
6882cab237bSDimitry Andric   CSI.setRestored(IsRestored);
6892cab237bSDimitry Andric   CSIInfo.push_back(CSI);
6907d523365SDimitry Andric   return false;
6917d523365SDimitry Andric }
6927d523365SDimitry Andric 
6937d523365SDimitry Andric /// Verify that given node is of a certain type. Return true on error.
6947d523365SDimitry Andric template <typename T>
typecheckMDNode(T * & Result,MDNode * Node,const yaml::StringValue & Source,StringRef TypeString,MIRParserImpl & Parser)6957d523365SDimitry Andric static bool typecheckMDNode(T *&Result, MDNode *Node,
6967d523365SDimitry Andric                             const yaml::StringValue &Source,
6977d523365SDimitry Andric                             StringRef TypeString, MIRParserImpl &Parser) {
6987d523365SDimitry Andric   if (!Node)
6997d523365SDimitry Andric     return false;
7007d523365SDimitry Andric   Result = dyn_cast<T>(Node);
7017d523365SDimitry Andric   if (!Result)
7027d523365SDimitry Andric     return Parser.error(Source.SourceRange.Start,
7037d523365SDimitry Andric                         "expected a reference to a '" + TypeString +
7047d523365SDimitry Andric                             "' metadata node");
7057d523365SDimitry Andric   return false;
7067d523365SDimitry Andric }
7077d523365SDimitry Andric 
7084ba319b5SDimitry Andric template <typename T>
parseStackObjectsDebugInfo(PerFunctionMIParsingState & PFS,const T & Object,int FrameIdx)7093ca95b02SDimitry Andric bool MIRParserImpl::parseStackObjectsDebugInfo(PerFunctionMIParsingState &PFS,
7104ba319b5SDimitry Andric     const T &Object, int FrameIdx) {
7117d523365SDimitry Andric   // Debug information can only be attached to stack objects; Fixed stack
7127d523365SDimitry Andric   // objects aren't supported.
7137d523365SDimitry Andric   MDNode *Var = nullptr, *Expr = nullptr, *Loc = nullptr;
7143ca95b02SDimitry Andric   if (parseMDNode(PFS, Var, Object.DebugVar) ||
7153ca95b02SDimitry Andric       parseMDNode(PFS, Expr, Object.DebugExpr) ||
7163ca95b02SDimitry Andric       parseMDNode(PFS, Loc, Object.DebugLoc))
7177d523365SDimitry Andric     return true;
7187d523365SDimitry Andric   if (!Var && !Expr && !Loc)
7197d523365SDimitry Andric     return false;
7207d523365SDimitry Andric   DILocalVariable *DIVar = nullptr;
7217d523365SDimitry Andric   DIExpression *DIExpr = nullptr;
7227d523365SDimitry Andric   DILocation *DILoc = nullptr;
7237d523365SDimitry Andric   if (typecheckMDNode(DIVar, Var, Object.DebugVar, "DILocalVariable", *this) ||
7247d523365SDimitry Andric       typecheckMDNode(DIExpr, Expr, Object.DebugExpr, "DIExpression", *this) ||
7257d523365SDimitry Andric       typecheckMDNode(DILoc, Loc, Object.DebugLoc, "DILocation", *this))
7267d523365SDimitry Andric     return true;
7274ba319b5SDimitry Andric   PFS.MF.setVariableDbgInfo(DIVar, DIExpr, FrameIdx, DILoc);
7287d523365SDimitry Andric   return false;
7297d523365SDimitry Andric }
7307d523365SDimitry Andric 
parseMDNode(PerFunctionMIParsingState & PFS,MDNode * & Node,const yaml::StringValue & Source)731d88c1a5aSDimitry Andric bool MIRParserImpl::parseMDNode(PerFunctionMIParsingState &PFS,
7323ca95b02SDimitry Andric     MDNode *&Node, const yaml::StringValue &Source) {
7337d523365SDimitry Andric   if (Source.Value.empty())
7347d523365SDimitry Andric     return false;
7357d523365SDimitry Andric   SMDiagnostic Error;
7363ca95b02SDimitry Andric   if (llvm::parseMDNode(PFS, Node, Source.Value, Error))
7377d523365SDimitry Andric     return error(Error, Source.SourceRange);
7387d523365SDimitry Andric   return false;
7397d523365SDimitry Andric }
7407d523365SDimitry Andric 
initializeConstantPool(PerFunctionMIParsingState & PFS,MachineConstantPool & ConstantPool,const yaml::MachineFunction & YamlMF)7413ca95b02SDimitry Andric bool MIRParserImpl::initializeConstantPool(PerFunctionMIParsingState &PFS,
7423ca95b02SDimitry Andric     MachineConstantPool &ConstantPool, const yaml::MachineFunction &YamlMF) {
7433ca95b02SDimitry Andric   DenseMap<unsigned, unsigned> &ConstantPoolSlots = PFS.ConstantPoolSlots;
7443ca95b02SDimitry Andric   const MachineFunction &MF = PFS.MF;
7452cab237bSDimitry Andric   const auto &M = *MF.getFunction().getParent();
7467d523365SDimitry Andric   SMDiagnostic Error;
7477d523365SDimitry Andric   for (const auto &YamlConstant : YamlMF.Constants) {
7482cab237bSDimitry Andric     if (YamlConstant.IsTargetSpecific)
7492cab237bSDimitry Andric       // FIXME: Support target-specific constant pools
7502cab237bSDimitry Andric       return error(YamlConstant.Value.SourceRange.Start,
7512cab237bSDimitry Andric                    "Can't parse target-specific constant pool entries yet");
7527d523365SDimitry Andric     const Constant *Value = dyn_cast_or_null<Constant>(
7537d523365SDimitry Andric         parseConstantValue(YamlConstant.Value.Value, Error, M));
7547d523365SDimitry Andric     if (!Value)
7557d523365SDimitry Andric       return error(Error, YamlConstant.Value.SourceRange);
7567d523365SDimitry Andric     unsigned Alignment =
7577d523365SDimitry Andric         YamlConstant.Alignment
7587d523365SDimitry Andric             ? YamlConstant.Alignment
7597d523365SDimitry Andric             : M.getDataLayout().getPrefTypeAlignment(Value->getType());
7607d523365SDimitry Andric     unsigned Index = ConstantPool.getConstantPoolIndex(Value, Alignment);
7617d523365SDimitry Andric     if (!ConstantPoolSlots.insert(std::make_pair(YamlConstant.ID.Value, Index))
7627d523365SDimitry Andric              .second)
7637d523365SDimitry Andric       return error(YamlConstant.ID.SourceRange.Start,
7647d523365SDimitry Andric                    Twine("redefinition of constant pool item '%const.") +
7657d523365SDimitry Andric                        Twine(YamlConstant.ID.Value) + "'");
7667d523365SDimitry Andric   }
7677d523365SDimitry Andric   return false;
7687d523365SDimitry Andric }
7697d523365SDimitry Andric 
initializeJumpTableInfo(PerFunctionMIParsingState & PFS,const yaml::MachineJumpTable & YamlJTI)7703ca95b02SDimitry Andric bool MIRParserImpl::initializeJumpTableInfo(PerFunctionMIParsingState &PFS,
7713ca95b02SDimitry Andric     const yaml::MachineJumpTable &YamlJTI) {
7723ca95b02SDimitry Andric   MachineJumpTableInfo *JTI = PFS.MF.getOrCreateJumpTableInfo(YamlJTI.Kind);
7737d523365SDimitry Andric   for (const auto &Entry : YamlJTI.Entries) {
7747d523365SDimitry Andric     std::vector<MachineBasicBlock *> Blocks;
7757d523365SDimitry Andric     for (const auto &MBBSource : Entry.Blocks) {
7767d523365SDimitry Andric       MachineBasicBlock *MBB = nullptr;
7773ca95b02SDimitry Andric       if (parseMBBReference(PFS, MBB, MBBSource.Value))
7787d523365SDimitry Andric         return true;
7797d523365SDimitry Andric       Blocks.push_back(MBB);
7807d523365SDimitry Andric     }
7817d523365SDimitry Andric     unsigned Index = JTI->createJumpTableIndex(Blocks);
7827d523365SDimitry Andric     if (!PFS.JumpTableSlots.insert(std::make_pair(Entry.ID.Value, Index))
7837d523365SDimitry Andric              .second)
7847d523365SDimitry Andric       return error(Entry.ID.SourceRange.Start,
7857d523365SDimitry Andric                    Twine("redefinition of jump table entry '%jump-table.") +
7867d523365SDimitry Andric                        Twine(Entry.ID.Value) + "'");
7877d523365SDimitry Andric   }
7887d523365SDimitry Andric   return false;
7897d523365SDimitry Andric }
7907d523365SDimitry Andric 
parseMBBReference(PerFunctionMIParsingState & PFS,MachineBasicBlock * & MBB,const yaml::StringValue & Source)791d88c1a5aSDimitry Andric bool MIRParserImpl::parseMBBReference(PerFunctionMIParsingState &PFS,
7923ca95b02SDimitry Andric                                       MachineBasicBlock *&MBB,
7933ca95b02SDimitry Andric                                       const yaml::StringValue &Source) {
7947d523365SDimitry Andric   SMDiagnostic Error;
7953ca95b02SDimitry Andric   if (llvm::parseMBBReference(PFS, MBB, Source.Value, Error))
7967d523365SDimitry Andric     return error(Error, Source.SourceRange);
7973dac3a9bSDimitry Andric   return false;
7983dac3a9bSDimitry Andric }
7993dac3a9bSDimitry Andric 
diagFromMIStringDiag(const SMDiagnostic & Error,SMRange SourceRange)8003dac3a9bSDimitry Andric SMDiagnostic MIRParserImpl::diagFromMIStringDiag(const SMDiagnostic &Error,
8013dac3a9bSDimitry Andric                                                  SMRange SourceRange) {
8023dac3a9bSDimitry Andric   assert(SourceRange.isValid() && "Invalid source range");
8033dac3a9bSDimitry Andric   SMLoc Loc = SourceRange.Start;
8043dac3a9bSDimitry Andric   bool HasQuote = Loc.getPointer() < SourceRange.End.getPointer() &&
8053dac3a9bSDimitry Andric                   *Loc.getPointer() == '\'';
8063dac3a9bSDimitry Andric   // Translate the location of the error from the location in the MI string to
8073dac3a9bSDimitry Andric   // the corresponding location in the MIR file.
8083dac3a9bSDimitry Andric   Loc = Loc.getFromPointer(Loc.getPointer() + Error.getColumnNo() +
8093dac3a9bSDimitry Andric                            (HasQuote ? 1 : 0));
8103dac3a9bSDimitry Andric 
8113dac3a9bSDimitry Andric   // TODO: Translate any source ranges as well.
8123dac3a9bSDimitry Andric   return SM.GetMessage(Loc, Error.getKind(), Error.getMessage(), None,
8133dac3a9bSDimitry Andric                        Error.getFixIts());
8143dac3a9bSDimitry Andric }
8153dac3a9bSDimitry Andric 
diagFromBlockStringDiag(const SMDiagnostic & Error,SMRange SourceRange)8167d523365SDimitry Andric SMDiagnostic MIRParserImpl::diagFromBlockStringDiag(const SMDiagnostic &Error,
81797bc6c73SDimitry Andric                                                     SMRange SourceRange) {
81897bc6c73SDimitry Andric   assert(SourceRange.isValid());
81997bc6c73SDimitry Andric 
82097bc6c73SDimitry Andric   // Translate the location of the error from the location in the llvm IR string
82197bc6c73SDimitry Andric   // to the corresponding location in the MIR file.
82297bc6c73SDimitry Andric   auto LineAndColumn = SM.getLineAndColumn(SourceRange.Start);
82397bc6c73SDimitry Andric   unsigned Line = LineAndColumn.first + Error.getLineNo() - 1;
82497bc6c73SDimitry Andric   unsigned Column = Error.getColumnNo();
82597bc6c73SDimitry Andric   StringRef LineStr = Error.getLineContents();
82697bc6c73SDimitry Andric   SMLoc Loc = Error.getLoc();
82797bc6c73SDimitry Andric 
82897bc6c73SDimitry Andric   // Get the full line and adjust the column number by taking the indentation of
82997bc6c73SDimitry Andric   // LLVM IR into account.
83097bc6c73SDimitry Andric   for (line_iterator L(*SM.getMemoryBuffer(SM.getMainFileID()), false), E;
83197bc6c73SDimitry Andric        L != E; ++L) {
83297bc6c73SDimitry Andric     if (L.line_number() == Line) {
83397bc6c73SDimitry Andric       LineStr = *L;
83497bc6c73SDimitry Andric       Loc = SMLoc::getFromPointer(LineStr.data());
83597bc6c73SDimitry Andric       auto Indent = LineStr.find(Error.getLineContents());
83697bc6c73SDimitry Andric       if (Indent != StringRef::npos)
83797bc6c73SDimitry Andric         Column += Indent;
83897bc6c73SDimitry Andric       break;
83997bc6c73SDimitry Andric     }
84097bc6c73SDimitry Andric   }
84197bc6c73SDimitry Andric 
84297bc6c73SDimitry Andric   return SMDiagnostic(SM, Loc, Filename, Line, Column, Error.getKind(),
84397bc6c73SDimitry Andric                       Error.getMessage(), LineStr, Error.getRanges(),
84497bc6c73SDimitry Andric                       Error.getFixIts());
84597bc6c73SDimitry Andric }
84697bc6c73SDimitry Andric 
initNames2RegClasses(const MachineFunction & MF)847875ed548SDimitry Andric void MIRParserImpl::initNames2RegClasses(const MachineFunction &MF) {
848875ed548SDimitry Andric   if (!Names2RegClasses.empty())
849875ed548SDimitry Andric     return;
850875ed548SDimitry Andric   const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
851875ed548SDimitry Andric   for (unsigned I = 0, E = TRI->getNumRegClasses(); I < E; ++I) {
852875ed548SDimitry Andric     const auto *RC = TRI->getRegClass(I);
853875ed548SDimitry Andric     Names2RegClasses.insert(
854875ed548SDimitry Andric         std::make_pair(StringRef(TRI->getRegClassName(RC)).lower(), RC));
855875ed548SDimitry Andric   }
856875ed548SDimitry Andric }
857875ed548SDimitry Andric 
initNames2RegBanks(const MachineFunction & MF)8583ca95b02SDimitry Andric void MIRParserImpl::initNames2RegBanks(const MachineFunction &MF) {
8593ca95b02SDimitry Andric   if (!Names2RegBanks.empty())
8603ca95b02SDimitry Andric     return;
8613ca95b02SDimitry Andric   const RegisterBankInfo *RBI = MF.getSubtarget().getRegBankInfo();
8623ca95b02SDimitry Andric   // If the target does not support GlobalISel, we may not have a
8633ca95b02SDimitry Andric   // register bank info.
8643ca95b02SDimitry Andric   if (!RBI)
8653ca95b02SDimitry Andric     return;
8663ca95b02SDimitry Andric   for (unsigned I = 0, E = RBI->getNumRegBanks(); I < E; ++I) {
8673ca95b02SDimitry Andric     const auto &RegBank = RBI->getRegBank(I);
8683ca95b02SDimitry Andric     Names2RegBanks.insert(
8693ca95b02SDimitry Andric         std::make_pair(StringRef(RegBank.getName()).lower(), &RegBank));
8703ca95b02SDimitry Andric   }
8713ca95b02SDimitry Andric }
8723ca95b02SDimitry Andric 
getRegClass(const MachineFunction & MF,StringRef Name)873875ed548SDimitry Andric const TargetRegisterClass *MIRParserImpl::getRegClass(const MachineFunction &MF,
874875ed548SDimitry Andric                                                       StringRef Name) {
875875ed548SDimitry Andric   auto RegClassInfo = Names2RegClasses.find(Name);
876875ed548SDimitry Andric   if (RegClassInfo == Names2RegClasses.end())
877875ed548SDimitry Andric     return nullptr;
878875ed548SDimitry Andric   return RegClassInfo->getValue();
879875ed548SDimitry Andric }
880875ed548SDimitry Andric 
getRegBank(const MachineFunction & MF,StringRef Name)8813ca95b02SDimitry Andric const RegisterBank *MIRParserImpl::getRegBank(const MachineFunction &MF,
8823ca95b02SDimitry Andric                                               StringRef Name) {
8833ca95b02SDimitry Andric   auto RegBankInfo = Names2RegBanks.find(Name);
8843ca95b02SDimitry Andric   if (RegBankInfo == Names2RegBanks.end())
8853ca95b02SDimitry Andric     return nullptr;
8863ca95b02SDimitry Andric   return RegBankInfo->getValue();
8873ca95b02SDimitry Andric }
8883ca95b02SDimitry Andric 
MIRParser(std::unique_ptr<MIRParserImpl> Impl)8898f0fd8f6SDimitry Andric MIRParser::MIRParser(std::unique_ptr<MIRParserImpl> Impl)
8908f0fd8f6SDimitry Andric     : Impl(std::move(Impl)) {}
8918f0fd8f6SDimitry Andric 
~MIRParser()8928f0fd8f6SDimitry Andric MIRParser::~MIRParser() {}
8938f0fd8f6SDimitry Andric 
parseIRModule()894db17bf38SDimitry Andric std::unique_ptr<Module> MIRParser::parseIRModule() {
895db17bf38SDimitry Andric   return Impl->parseIRModule();
896db17bf38SDimitry Andric }
8978f0fd8f6SDimitry Andric 
parseMachineFunctions(Module & M,MachineModuleInfo & MMI)898db17bf38SDimitry Andric bool MIRParser::parseMachineFunctions(Module &M, MachineModuleInfo &MMI) {
899db17bf38SDimitry Andric   return Impl->parseMachineFunctions(M, MMI);
9008f0fd8f6SDimitry Andric }
9018f0fd8f6SDimitry Andric 
createMIRParserFromFile(StringRef Filename,SMDiagnostic & Error,LLVMContext & Context)9028f0fd8f6SDimitry Andric std::unique_ptr<MIRParser> llvm::createMIRParserFromFile(StringRef Filename,
90397bc6c73SDimitry Andric                                                          SMDiagnostic &Error,
90497bc6c73SDimitry Andric                                                          LLVMContext &Context) {
905db17bf38SDimitry Andric   auto FileOrErr = MemoryBuffer::getFileOrSTDIN(Filename);
90697bc6c73SDimitry Andric   if (std::error_code EC = FileOrErr.getError()) {
90797bc6c73SDimitry Andric     Error = SMDiagnostic(Filename, SourceMgr::DK_Error,
90897bc6c73SDimitry Andric                          "Could not open input file: " + EC.message());
9098f0fd8f6SDimitry Andric     return nullptr;
91097bc6c73SDimitry Andric   }
9118f0fd8f6SDimitry Andric   return createMIRParser(std::move(FileOrErr.get()), Context);
91297bc6c73SDimitry Andric }
91397bc6c73SDimitry Andric 
9148f0fd8f6SDimitry Andric std::unique_ptr<MIRParser>
createMIRParser(std::unique_ptr<MemoryBuffer> Contents,LLVMContext & Context)9158f0fd8f6SDimitry Andric llvm::createMIRParser(std::unique_ptr<MemoryBuffer> Contents,
91697bc6c73SDimitry Andric                       LLVMContext &Context) {
91797bc6c73SDimitry Andric   auto Filename = Contents->getBufferIdentifier();
918d88c1a5aSDimitry Andric   if (Context.shouldDiscardValueNames()) {
919d88c1a5aSDimitry Andric     Context.diagnose(DiagnosticInfoMIRParser(
920d88c1a5aSDimitry Andric         DS_Error,
921d88c1a5aSDimitry Andric         SMDiagnostic(
922d88c1a5aSDimitry Andric             Filename, SourceMgr::DK_Error,
923d88c1a5aSDimitry Andric             "Can't read MIR with a Context that discards named Values")));
924d88c1a5aSDimitry Andric     return nullptr;
925d88c1a5aSDimitry Andric   }
9268f0fd8f6SDimitry Andric   return llvm::make_unique<MIRParser>(
9278f0fd8f6SDimitry Andric       llvm::make_unique<MIRParserImpl>(std::move(Contents), Filename, Context));
92897bc6c73SDimitry Andric }
929