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