10b57cec5SDimitry Andric //===- MIRParser.cpp - MIR serialization format parser implementation -----===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements the class that parses the optional LLVM IR and machine
100b57cec5SDimitry Andric // functions that are stored in MIR files.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric
140b57cec5SDimitry Andric #include "llvm/CodeGen/MIRParser/MIRParser.h"
150b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
160b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
170b57cec5SDimitry Andric #include "llvm/AsmParser/Parser.h"
180b57cec5SDimitry Andric #include "llvm/AsmParser/SlotMapping.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/MIRParser/MIParser.h"
200b57cec5SDimitry Andric #include "llvm/CodeGen/MIRYamlMapping.h"
210b57cec5SDimitry Andric #include "llvm/CodeGen/MachineConstantPool.h"
220b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
230b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
240b57cec5SDimitry Andric #include "llvm/CodeGen/MachineModuleInfo.h"
250b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
260b57cec5SDimitry Andric #include "llvm/CodeGen/TargetFrameLowering.h"
270b57cec5SDimitry Andric #include "llvm/IR/BasicBlock.h"
2881ad6265SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h"
290b57cec5SDimitry Andric #include "llvm/IR/DiagnosticInfo.h"
300b57cec5SDimitry Andric #include "llvm/IR/Instructions.h"
310b57cec5SDimitry Andric #include "llvm/IR/LLVMContext.h"
320b57cec5SDimitry Andric #include "llvm/IR/Module.h"
330b57cec5SDimitry Andric #include "llvm/IR/ValueSymbolTable.h"
340b57cec5SDimitry Andric #include "llvm/Support/LineIterator.h"
350b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
360b57cec5SDimitry Andric #include "llvm/Support/SMLoc.h"
370b57cec5SDimitry Andric #include "llvm/Support/SourceMgr.h"
380b57cec5SDimitry Andric #include "llvm/Support/YAMLTraits.h"
390b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h"
400b57cec5SDimitry Andric #include <memory>
410b57cec5SDimitry Andric
420b57cec5SDimitry Andric using namespace llvm;
430b57cec5SDimitry Andric
440b57cec5SDimitry Andric namespace llvm {
4581ad6265SDimitry Andric class MDNode;
4681ad6265SDimitry Andric class RegisterBank;
470b57cec5SDimitry Andric
480b57cec5SDimitry Andric /// This class implements the parsing of LLVM IR that's embedded inside a MIR
490b57cec5SDimitry Andric /// file.
500b57cec5SDimitry Andric class MIRParserImpl {
510b57cec5SDimitry Andric SourceMgr SM;
52fe6060f1SDimitry Andric LLVMContext &Context;
530b57cec5SDimitry Andric yaml::Input In;
540b57cec5SDimitry Andric StringRef Filename;
550b57cec5SDimitry Andric SlotMapping IRSlots;
560b57cec5SDimitry Andric std::unique_ptr<PerTargetMIParsingState> Target;
570b57cec5SDimitry Andric
580b57cec5SDimitry Andric /// True when the MIR file doesn't have LLVM IR. Dummy IR functions are
590b57cec5SDimitry Andric /// created and inserted into the given module when this is true.
600b57cec5SDimitry Andric bool NoLLVMIR = false;
610b57cec5SDimitry Andric /// True when a well formed MIR file does not contain any MIR/machine function
620b57cec5SDimitry Andric /// parts.
630b57cec5SDimitry Andric bool NoMIRDocuments = false;
640b57cec5SDimitry Andric
65480093f4SDimitry Andric std::function<void(Function &)> ProcessIRFunction;
66480093f4SDimitry Andric
670b57cec5SDimitry Andric public:
68480093f4SDimitry Andric MIRParserImpl(std::unique_ptr<MemoryBuffer> Contents, StringRef Filename,
69480093f4SDimitry Andric LLVMContext &Context,
70480093f4SDimitry Andric std::function<void(Function &)> ProcessIRFunction);
710b57cec5SDimitry Andric
720b57cec5SDimitry Andric void reportDiagnostic(const SMDiagnostic &Diag);
730b57cec5SDimitry Andric
740b57cec5SDimitry Andric /// Report an error with the given message at unknown location.
750b57cec5SDimitry Andric ///
760b57cec5SDimitry Andric /// Always returns true.
770b57cec5SDimitry Andric bool error(const Twine &Message);
780b57cec5SDimitry Andric
790b57cec5SDimitry Andric /// Report an error with the given message at the given location.
800b57cec5SDimitry Andric ///
810b57cec5SDimitry Andric /// Always returns true.
820b57cec5SDimitry Andric bool error(SMLoc Loc, const Twine &Message);
830b57cec5SDimitry Andric
840b57cec5SDimitry Andric /// Report a given error with the location translated from the location in an
850b57cec5SDimitry Andric /// embedded string literal to a location in the MIR file.
860b57cec5SDimitry Andric ///
870b57cec5SDimitry Andric /// Always returns true.
880b57cec5SDimitry Andric bool error(const SMDiagnostic &Error, SMRange SourceRange);
890b57cec5SDimitry Andric
900b57cec5SDimitry Andric /// Try to parse the optional LLVM module and the machine functions in the MIR
910b57cec5SDimitry Andric /// file.
920b57cec5SDimitry Andric ///
930b57cec5SDimitry Andric /// Return null if an error occurred.
945ffd83dbSDimitry Andric std::unique_ptr<Module>
955ffd83dbSDimitry Andric parseIRModule(DataLayoutCallbackTy DataLayoutCallback);
960b57cec5SDimitry Andric
97480093f4SDimitry Andric /// Create an empty function with the given name.
98480093f4SDimitry Andric Function *createDummyFunction(StringRef Name, Module &M);
99480093f4SDimitry Andric
1000b57cec5SDimitry Andric bool parseMachineFunctions(Module &M, MachineModuleInfo &MMI);
1010b57cec5SDimitry Andric
1020b57cec5SDimitry Andric /// Parse the machine function in the current YAML document.
1030b57cec5SDimitry Andric ///
1040b57cec5SDimitry Andric ///
1050b57cec5SDimitry Andric /// Return true if an error occurred.
1060b57cec5SDimitry Andric bool parseMachineFunction(Module &M, MachineModuleInfo &MMI);
1070b57cec5SDimitry Andric
1080b57cec5SDimitry Andric /// Initialize the machine function to the state that's described in the MIR
1090b57cec5SDimitry Andric /// file.
1100b57cec5SDimitry Andric ///
1110b57cec5SDimitry Andric /// Return true if error occurred.
1120b57cec5SDimitry Andric bool initializeMachineFunction(const yaml::MachineFunction &YamlMF,
1130b57cec5SDimitry Andric MachineFunction &MF);
1140b57cec5SDimitry Andric
1150b57cec5SDimitry Andric bool parseRegisterInfo(PerFunctionMIParsingState &PFS,
1160b57cec5SDimitry Andric const yaml::MachineFunction &YamlMF);
1170b57cec5SDimitry Andric
1180b57cec5SDimitry Andric bool setupRegisterInfo(const PerFunctionMIParsingState &PFS,
1190b57cec5SDimitry Andric const yaml::MachineFunction &YamlMF);
1200b57cec5SDimitry Andric
1210b57cec5SDimitry Andric bool initializeFrameInfo(PerFunctionMIParsingState &PFS,
1220b57cec5SDimitry Andric const yaml::MachineFunction &YamlMF);
1230b57cec5SDimitry Andric
1240b57cec5SDimitry Andric bool initializeCallSiteInfo(PerFunctionMIParsingState &PFS,
1250b57cec5SDimitry Andric const yaml::MachineFunction &YamlMF);
1260b57cec5SDimitry Andric
1270b57cec5SDimitry Andric bool parseCalleeSavedRegister(PerFunctionMIParsingState &PFS,
1280b57cec5SDimitry Andric std::vector<CalleeSavedInfo> &CSIInfo,
1290b57cec5SDimitry Andric const yaml::StringValue &RegisterSource,
1300b57cec5SDimitry Andric bool IsRestored, int FrameIdx);
1310b57cec5SDimitry Andric
132*fe013be4SDimitry Andric struct VarExprLoc {
133*fe013be4SDimitry Andric DILocalVariable *DIVar = nullptr;
134*fe013be4SDimitry Andric DIExpression *DIExpr = nullptr;
135*fe013be4SDimitry Andric DILocation *DILoc = nullptr;
136*fe013be4SDimitry Andric };
137*fe013be4SDimitry Andric
138*fe013be4SDimitry Andric std::optional<VarExprLoc> parseVarExprLoc(PerFunctionMIParsingState &PFS,
139*fe013be4SDimitry Andric const yaml::StringValue &VarStr,
140*fe013be4SDimitry Andric const yaml::StringValue &ExprStr,
141*fe013be4SDimitry Andric const yaml::StringValue &LocStr);
1420b57cec5SDimitry Andric template <typename T>
1430b57cec5SDimitry Andric bool parseStackObjectsDebugInfo(PerFunctionMIParsingState &PFS,
1440b57cec5SDimitry Andric const T &Object,
1450b57cec5SDimitry Andric int FrameIdx);
1460b57cec5SDimitry Andric
1470b57cec5SDimitry Andric bool initializeConstantPool(PerFunctionMIParsingState &PFS,
1480b57cec5SDimitry Andric MachineConstantPool &ConstantPool,
1490b57cec5SDimitry Andric const yaml::MachineFunction &YamlMF);
1500b57cec5SDimitry Andric
1510b57cec5SDimitry Andric bool initializeJumpTableInfo(PerFunctionMIParsingState &PFS,
1520b57cec5SDimitry Andric const yaml::MachineJumpTable &YamlJTI);
1530b57cec5SDimitry Andric
154fe6060f1SDimitry Andric bool parseMachineMetadataNodes(PerFunctionMIParsingState &PFS,
155fe6060f1SDimitry Andric MachineFunction &MF,
156fe6060f1SDimitry Andric const yaml::MachineFunction &YMF);
157fe6060f1SDimitry Andric
1580b57cec5SDimitry Andric private:
1590b57cec5SDimitry Andric bool parseMDNode(PerFunctionMIParsingState &PFS, MDNode *&Node,
1600b57cec5SDimitry Andric const yaml::StringValue &Source);
1610b57cec5SDimitry Andric
1620b57cec5SDimitry Andric bool parseMBBReference(PerFunctionMIParsingState &PFS,
1630b57cec5SDimitry Andric MachineBasicBlock *&MBB,
1640b57cec5SDimitry Andric const yaml::StringValue &Source);
1650b57cec5SDimitry Andric
166fe6060f1SDimitry Andric bool parseMachineMetadata(PerFunctionMIParsingState &PFS,
167fe6060f1SDimitry Andric const yaml::StringValue &Source);
168fe6060f1SDimitry Andric
1690b57cec5SDimitry Andric /// Return a MIR diagnostic converted from an MI string diagnostic.
1700b57cec5SDimitry Andric SMDiagnostic diagFromMIStringDiag(const SMDiagnostic &Error,
1710b57cec5SDimitry Andric SMRange SourceRange);
1720b57cec5SDimitry Andric
1730b57cec5SDimitry Andric /// Return a MIR diagnostic converted from a diagnostic located in a YAML
1740b57cec5SDimitry Andric /// block scalar string.
1750b57cec5SDimitry Andric SMDiagnostic diagFromBlockStringDiag(const SMDiagnostic &Error,
1760b57cec5SDimitry Andric SMRange SourceRange);
1770b57cec5SDimitry Andric
1780b57cec5SDimitry Andric void computeFunctionProperties(MachineFunction &MF);
179e8d8bef9SDimitry Andric
180e8d8bef9SDimitry Andric void setupDebugValueTracking(MachineFunction &MF,
181e8d8bef9SDimitry Andric PerFunctionMIParsingState &PFS, const yaml::MachineFunction &YamlMF);
1820b57cec5SDimitry Andric };
1830b57cec5SDimitry Andric
1840b57cec5SDimitry Andric } // end namespace llvm
1850b57cec5SDimitry Andric
handleYAMLDiag(const SMDiagnostic & Diag,void * Context)1860b57cec5SDimitry Andric static void handleYAMLDiag(const SMDiagnostic &Diag, void *Context) {
1870b57cec5SDimitry Andric reinterpret_cast<MIRParserImpl *>(Context)->reportDiagnostic(Diag);
1880b57cec5SDimitry Andric }
1890b57cec5SDimitry Andric
MIRParserImpl(std::unique_ptr<MemoryBuffer> Contents,StringRef Filename,LLVMContext & Context,std::function<void (Function &)> Callback)1900b57cec5SDimitry Andric MIRParserImpl::MIRParserImpl(std::unique_ptr<MemoryBuffer> Contents,
191480093f4SDimitry Andric StringRef Filename, LLVMContext &Context,
192480093f4SDimitry Andric std::function<void(Function &)> Callback)
19304eeddc0SDimitry Andric : Context(Context),
194480093f4SDimitry Andric In(SM.getMemoryBuffer(SM.AddNewSourceBuffer(std::move(Contents), SMLoc()))
195480093f4SDimitry Andric ->getBuffer(),
1960b57cec5SDimitry Andric nullptr, handleYAMLDiag, this),
197fe6060f1SDimitry Andric Filename(Filename), ProcessIRFunction(Callback) {
1980b57cec5SDimitry Andric In.setContext(&In);
1990b57cec5SDimitry Andric }
2000b57cec5SDimitry Andric
error(const Twine & Message)2010b57cec5SDimitry Andric bool MIRParserImpl::error(const Twine &Message) {
2020b57cec5SDimitry Andric Context.diagnose(DiagnosticInfoMIRParser(
2030b57cec5SDimitry Andric DS_Error, SMDiagnostic(Filename, SourceMgr::DK_Error, Message.str())));
2040b57cec5SDimitry Andric return true;
2050b57cec5SDimitry Andric }
2060b57cec5SDimitry Andric
error(SMLoc Loc,const Twine & Message)2070b57cec5SDimitry Andric bool MIRParserImpl::error(SMLoc Loc, const Twine &Message) {
2080b57cec5SDimitry Andric Context.diagnose(DiagnosticInfoMIRParser(
2090b57cec5SDimitry Andric DS_Error, SM.GetMessage(Loc, SourceMgr::DK_Error, Message)));
2100b57cec5SDimitry Andric return true;
2110b57cec5SDimitry Andric }
2120b57cec5SDimitry Andric
error(const SMDiagnostic & Error,SMRange SourceRange)2130b57cec5SDimitry Andric bool MIRParserImpl::error(const SMDiagnostic &Error, SMRange SourceRange) {
2140b57cec5SDimitry Andric assert(Error.getKind() == SourceMgr::DK_Error && "Expected an error");
2150b57cec5SDimitry Andric reportDiagnostic(diagFromMIStringDiag(Error, SourceRange));
2160b57cec5SDimitry Andric return true;
2170b57cec5SDimitry Andric }
2180b57cec5SDimitry Andric
reportDiagnostic(const SMDiagnostic & Diag)2190b57cec5SDimitry Andric void MIRParserImpl::reportDiagnostic(const SMDiagnostic &Diag) {
2200b57cec5SDimitry Andric DiagnosticSeverity Kind;
2210b57cec5SDimitry Andric switch (Diag.getKind()) {
2220b57cec5SDimitry Andric case SourceMgr::DK_Error:
2230b57cec5SDimitry Andric Kind = DS_Error;
2240b57cec5SDimitry Andric break;
2250b57cec5SDimitry Andric case SourceMgr::DK_Warning:
2260b57cec5SDimitry Andric Kind = DS_Warning;
2270b57cec5SDimitry Andric break;
2280b57cec5SDimitry Andric case SourceMgr::DK_Note:
2290b57cec5SDimitry Andric Kind = DS_Note;
2300b57cec5SDimitry Andric break;
2310b57cec5SDimitry Andric case SourceMgr::DK_Remark:
2320b57cec5SDimitry Andric llvm_unreachable("remark unexpected");
2330b57cec5SDimitry Andric break;
2340b57cec5SDimitry Andric }
2350b57cec5SDimitry Andric Context.diagnose(DiagnosticInfoMIRParser(Kind, Diag));
2360b57cec5SDimitry Andric }
2370b57cec5SDimitry Andric
2385ffd83dbSDimitry Andric std::unique_ptr<Module>
parseIRModule(DataLayoutCallbackTy DataLayoutCallback)2395ffd83dbSDimitry Andric MIRParserImpl::parseIRModule(DataLayoutCallbackTy DataLayoutCallback) {
2400b57cec5SDimitry Andric if (!In.setCurrentDocument()) {
2410b57cec5SDimitry Andric if (In.error())
2420b57cec5SDimitry Andric return nullptr;
2430b57cec5SDimitry Andric // Create an empty module when the MIR file is empty.
2440b57cec5SDimitry Andric NoMIRDocuments = true;
2455ffd83dbSDimitry Andric auto M = std::make_unique<Module>(Filename, Context);
246bdd1243dSDimitry Andric if (auto LayoutOverride =
247bdd1243dSDimitry Andric DataLayoutCallback(M->getTargetTriple(), M->getDataLayoutStr()))
2485ffd83dbSDimitry Andric M->setDataLayout(*LayoutOverride);
2495ffd83dbSDimitry Andric return M;
2500b57cec5SDimitry Andric }
2510b57cec5SDimitry Andric
2520b57cec5SDimitry Andric std::unique_ptr<Module> M;
2530b57cec5SDimitry Andric // Parse the block scalar manually so that we can return unique pointer
2540b57cec5SDimitry Andric // without having to go trough YAML traits.
2550b57cec5SDimitry Andric if (const auto *BSN =
2560b57cec5SDimitry Andric dyn_cast_or_null<yaml::BlockScalarNode>(In.getCurrentNode())) {
2570b57cec5SDimitry Andric SMDiagnostic Error;
2580b57cec5SDimitry Andric M = parseAssembly(MemoryBufferRef(BSN->getValue(), Filename), Error,
2595ffd83dbSDimitry Andric Context, &IRSlots, DataLayoutCallback);
2600b57cec5SDimitry Andric if (!M) {
2610b57cec5SDimitry Andric reportDiagnostic(diagFromBlockStringDiag(Error, BSN->getSourceRange()));
2620b57cec5SDimitry Andric return nullptr;
2630b57cec5SDimitry Andric }
2640b57cec5SDimitry Andric In.nextDocument();
2650b57cec5SDimitry Andric if (!In.setCurrentDocument())
2660b57cec5SDimitry Andric NoMIRDocuments = true;
2670b57cec5SDimitry Andric } else {
2680b57cec5SDimitry Andric // Create an new, empty module.
2698bcb0991SDimitry Andric M = std::make_unique<Module>(Filename, Context);
270bdd1243dSDimitry Andric if (auto LayoutOverride =
271bdd1243dSDimitry Andric DataLayoutCallback(M->getTargetTriple(), M->getDataLayoutStr()))
2725ffd83dbSDimitry Andric M->setDataLayout(*LayoutOverride);
2730b57cec5SDimitry Andric NoLLVMIR = true;
2740b57cec5SDimitry Andric }
2750b57cec5SDimitry Andric return M;
2760b57cec5SDimitry Andric }
2770b57cec5SDimitry Andric
parseMachineFunctions(Module & M,MachineModuleInfo & MMI)2780b57cec5SDimitry Andric bool MIRParserImpl::parseMachineFunctions(Module &M, MachineModuleInfo &MMI) {
2790b57cec5SDimitry Andric if (NoMIRDocuments)
2800b57cec5SDimitry Andric return false;
2810b57cec5SDimitry Andric
2820b57cec5SDimitry Andric // Parse the machine functions.
2830b57cec5SDimitry Andric do {
2840b57cec5SDimitry Andric if (parseMachineFunction(M, MMI))
2850b57cec5SDimitry Andric return true;
2860b57cec5SDimitry Andric In.nextDocument();
2870b57cec5SDimitry Andric } while (In.setCurrentDocument());
2880b57cec5SDimitry Andric
2890b57cec5SDimitry Andric return false;
2900b57cec5SDimitry Andric }
2910b57cec5SDimitry Andric
createDummyFunction(StringRef Name,Module & M)292480093f4SDimitry Andric Function *MIRParserImpl::createDummyFunction(StringRef Name, Module &M) {
2930b57cec5SDimitry Andric auto &Context = M.getContext();
2940b57cec5SDimitry Andric Function *F =
2950b57cec5SDimitry Andric Function::Create(FunctionType::get(Type::getVoidTy(Context), false),
2960b57cec5SDimitry Andric Function::ExternalLinkage, Name, M);
2970b57cec5SDimitry Andric BasicBlock *BB = BasicBlock::Create(Context, "entry", F);
2980b57cec5SDimitry Andric new UnreachableInst(Context, BB);
299480093f4SDimitry Andric
300480093f4SDimitry Andric if (ProcessIRFunction)
301480093f4SDimitry Andric ProcessIRFunction(*F);
302480093f4SDimitry Andric
3030b57cec5SDimitry Andric return F;
3040b57cec5SDimitry Andric }
3050b57cec5SDimitry Andric
parseMachineFunction(Module & M,MachineModuleInfo & MMI)3060b57cec5SDimitry Andric bool MIRParserImpl::parseMachineFunction(Module &M, MachineModuleInfo &MMI) {
3070b57cec5SDimitry Andric // Parse the yaml.
3080b57cec5SDimitry Andric yaml::MachineFunction YamlMF;
3090b57cec5SDimitry Andric yaml::EmptyContext Ctx;
3100b57cec5SDimitry Andric
3110b57cec5SDimitry Andric const LLVMTargetMachine &TM = MMI.getTarget();
3120b57cec5SDimitry Andric YamlMF.MachineFuncInfo = std::unique_ptr<yaml::MachineFunctionInfo>(
3130b57cec5SDimitry Andric TM.createDefaultFuncInfoYAML());
3140b57cec5SDimitry Andric
3150b57cec5SDimitry Andric yaml::yamlize(In, YamlMF, false, Ctx);
3160b57cec5SDimitry Andric if (In.error())
3170b57cec5SDimitry Andric return true;
3180b57cec5SDimitry Andric
3190b57cec5SDimitry Andric // Search for the corresponding IR function.
3200b57cec5SDimitry Andric StringRef FunctionName = YamlMF.Name;
3210b57cec5SDimitry Andric Function *F = M.getFunction(FunctionName);
3220b57cec5SDimitry Andric if (!F) {
3230b57cec5SDimitry Andric if (NoLLVMIR) {
3240b57cec5SDimitry Andric F = createDummyFunction(FunctionName, M);
3250b57cec5SDimitry Andric } else {
3260b57cec5SDimitry Andric return error(Twine("function '") + FunctionName +
3270b57cec5SDimitry Andric "' isn't defined in the provided LLVM IR");
3280b57cec5SDimitry Andric }
3290b57cec5SDimitry Andric }
3300b57cec5SDimitry Andric if (MMI.getMachineFunction(*F) != nullptr)
3310b57cec5SDimitry Andric return error(Twine("redefinition of machine function '") + FunctionName +
3320b57cec5SDimitry Andric "'");
3330b57cec5SDimitry Andric
3340b57cec5SDimitry Andric // Create the MachineFunction.
3350b57cec5SDimitry Andric MachineFunction &MF = MMI.getOrCreateMachineFunction(*F);
3360b57cec5SDimitry Andric if (initializeMachineFunction(YamlMF, MF))
3370b57cec5SDimitry Andric return true;
3380b57cec5SDimitry Andric
3390b57cec5SDimitry Andric return false;
3400b57cec5SDimitry Andric }
3410b57cec5SDimitry Andric
isSSA(const MachineFunction & MF)3420b57cec5SDimitry Andric static bool isSSA(const MachineFunction &MF) {
3430b57cec5SDimitry Andric const MachineRegisterInfo &MRI = MF.getRegInfo();
3440b57cec5SDimitry Andric for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
345e8d8bef9SDimitry Andric Register Reg = Register::index2VirtReg(I);
3460b57cec5SDimitry Andric if (!MRI.hasOneDef(Reg) && !MRI.def_empty(Reg))
3470b57cec5SDimitry Andric return false;
348e8d8bef9SDimitry Andric
349e8d8bef9SDimitry Andric // Subregister defs are invalid in SSA.
350e8d8bef9SDimitry Andric const MachineOperand *RegDef = MRI.getOneDef(Reg);
351e8d8bef9SDimitry Andric if (RegDef && RegDef->getSubReg() != 0)
352e8d8bef9SDimitry Andric return false;
3530b57cec5SDimitry Andric }
3540b57cec5SDimitry Andric return true;
3550b57cec5SDimitry Andric }
3560b57cec5SDimitry Andric
computeFunctionProperties(MachineFunction & MF)3570b57cec5SDimitry Andric void MIRParserImpl::computeFunctionProperties(MachineFunction &MF) {
3580b57cec5SDimitry Andric MachineFunctionProperties &Properties = MF.getProperties();
3590b57cec5SDimitry Andric
3600b57cec5SDimitry Andric bool HasPHI = false;
3610b57cec5SDimitry Andric bool HasInlineAsm = false;
3620eae32dcSDimitry Andric bool AllTiedOpsRewritten = true, HasTiedOps = false;
3630b57cec5SDimitry Andric for (const MachineBasicBlock &MBB : MF) {
3640b57cec5SDimitry Andric for (const MachineInstr &MI : MBB) {
3650b57cec5SDimitry Andric if (MI.isPHI())
3660b57cec5SDimitry Andric HasPHI = true;
3670b57cec5SDimitry Andric if (MI.isInlineAsm())
3680b57cec5SDimitry Andric HasInlineAsm = true;
3690eae32dcSDimitry Andric for (unsigned I = 0; I < MI.getNumOperands(); ++I) {
3700eae32dcSDimitry Andric const MachineOperand &MO = MI.getOperand(I);
3710eae32dcSDimitry Andric if (!MO.isReg() || !MO.getReg())
3720eae32dcSDimitry Andric continue;
3730eae32dcSDimitry Andric unsigned DefIdx;
3740eae32dcSDimitry Andric if (MO.isUse() && MI.isRegTiedToDefOperand(I, &DefIdx)) {
3750eae32dcSDimitry Andric HasTiedOps = true;
3760eae32dcSDimitry Andric if (MO.getReg() != MI.getOperand(DefIdx).getReg())
3770eae32dcSDimitry Andric AllTiedOpsRewritten = false;
3780eae32dcSDimitry Andric }
3790eae32dcSDimitry Andric }
3800b57cec5SDimitry Andric }
3810b57cec5SDimitry Andric }
3820b57cec5SDimitry Andric if (!HasPHI)
3830b57cec5SDimitry Andric Properties.set(MachineFunctionProperties::Property::NoPHIs);
3840b57cec5SDimitry Andric MF.setHasInlineAsm(HasInlineAsm);
3850b57cec5SDimitry Andric
3860eae32dcSDimitry Andric if (HasTiedOps && AllTiedOpsRewritten)
3870eae32dcSDimitry Andric Properties.set(MachineFunctionProperties::Property::TiedOpsRewritten);
3880eae32dcSDimitry Andric
3890b57cec5SDimitry Andric if (isSSA(MF))
3900b57cec5SDimitry Andric Properties.set(MachineFunctionProperties::Property::IsSSA);
3910b57cec5SDimitry Andric else
3920b57cec5SDimitry Andric Properties.reset(MachineFunctionProperties::Property::IsSSA);
3930b57cec5SDimitry Andric
3940b57cec5SDimitry Andric const MachineRegisterInfo &MRI = MF.getRegInfo();
3950b57cec5SDimitry Andric if (MRI.getNumVirtRegs() == 0)
3960b57cec5SDimitry Andric Properties.set(MachineFunctionProperties::Property::NoVRegs);
3970b57cec5SDimitry Andric }
3980b57cec5SDimitry Andric
initializeCallSiteInfo(PerFunctionMIParsingState & PFS,const yaml::MachineFunction & YamlMF)3990b57cec5SDimitry Andric bool MIRParserImpl::initializeCallSiteInfo(
4000b57cec5SDimitry Andric PerFunctionMIParsingState &PFS, const yaml::MachineFunction &YamlMF) {
4010b57cec5SDimitry Andric MachineFunction &MF = PFS.MF;
4020b57cec5SDimitry Andric SMDiagnostic Error;
4030b57cec5SDimitry Andric const LLVMTargetMachine &TM = MF.getTarget();
404*fe013be4SDimitry Andric for (auto &YamlCSInfo : YamlMF.CallSitesInfo) {
4050b57cec5SDimitry Andric yaml::CallSiteInfo::MachineInstrLoc MILoc = YamlCSInfo.CallLocation;
4060b57cec5SDimitry Andric if (MILoc.BlockNum >= MF.size())
4070b57cec5SDimitry Andric return error(Twine(MF.getName()) +
4080b57cec5SDimitry Andric Twine(" call instruction block out of range.") +
4090b57cec5SDimitry Andric " Unable to reference bb:" + Twine(MILoc.BlockNum));
4100b57cec5SDimitry Andric auto CallB = std::next(MF.begin(), MILoc.BlockNum);
4110b57cec5SDimitry Andric if (MILoc.Offset >= CallB->size())
4120b57cec5SDimitry Andric return error(Twine(MF.getName()) +
4130b57cec5SDimitry Andric Twine(" call instruction offset out of range.") +
4140b57cec5SDimitry Andric " Unable to reference instruction at bb: " +
4150b57cec5SDimitry Andric Twine(MILoc.BlockNum) + " at offset:" + Twine(MILoc.Offset));
4168bcb0991SDimitry Andric auto CallI = std::next(CallB->instr_begin(), MILoc.Offset);
4178bcb0991SDimitry Andric if (!CallI->isCall(MachineInstr::IgnoreBundle))
4180b57cec5SDimitry Andric return error(Twine(MF.getName()) +
4190b57cec5SDimitry Andric Twine(" call site info should reference call "
4200b57cec5SDimitry Andric "instruction. Instruction at bb:") +
4210b57cec5SDimitry Andric Twine(MILoc.BlockNum) + " at offset:" + Twine(MILoc.Offset) +
4220b57cec5SDimitry Andric " is not a call instruction");
4230b57cec5SDimitry Andric MachineFunction::CallSiteInfo CSInfo;
4240b57cec5SDimitry Andric for (auto ArgRegPair : YamlCSInfo.ArgForwardingRegs) {
4255ffd83dbSDimitry Andric Register Reg;
4260b57cec5SDimitry Andric if (parseNamedRegisterReference(PFS, Reg, ArgRegPair.Reg.Value, Error))
4270b57cec5SDimitry Andric return error(Error, ArgRegPair.Reg.SourceRange);
4280b57cec5SDimitry Andric CSInfo.emplace_back(Reg, ArgRegPair.ArgNo);
4290b57cec5SDimitry Andric }
4300b57cec5SDimitry Andric
4315ffd83dbSDimitry Andric if (TM.Options.EmitCallSiteInfo)
4320b57cec5SDimitry Andric MF.addCallArgsForwardingRegs(&*CallI, std::move(CSInfo));
4330b57cec5SDimitry Andric }
4340b57cec5SDimitry Andric
4355ffd83dbSDimitry Andric if (YamlMF.CallSitesInfo.size() && !TM.Options.EmitCallSiteInfo)
4360b57cec5SDimitry Andric return error(Twine("Call site info provided but not used"));
4370b57cec5SDimitry Andric return false;
4380b57cec5SDimitry Andric }
4390b57cec5SDimitry Andric
setupDebugValueTracking(MachineFunction & MF,PerFunctionMIParsingState & PFS,const yaml::MachineFunction & YamlMF)440e8d8bef9SDimitry Andric void MIRParserImpl::setupDebugValueTracking(
441e8d8bef9SDimitry Andric MachineFunction &MF, PerFunctionMIParsingState &PFS,
442e8d8bef9SDimitry Andric const yaml::MachineFunction &YamlMF) {
443e8d8bef9SDimitry Andric // Compute the value of the "next instruction number" field.
444e8d8bef9SDimitry Andric unsigned MaxInstrNum = 0;
445e8d8bef9SDimitry Andric for (auto &MBB : MF)
446e8d8bef9SDimitry Andric for (auto &MI : MBB)
447e8d8bef9SDimitry Andric MaxInstrNum = std::max((unsigned)MI.peekDebugInstrNum(), MaxInstrNum);
448e8d8bef9SDimitry Andric MF.setDebugInstrNumberingCount(MaxInstrNum);
449e8d8bef9SDimitry Andric
450e8d8bef9SDimitry Andric // Load any substitutions.
451fcaf7f86SDimitry Andric for (const auto &Sub : YamlMF.DebugValueSubstitutions) {
452fe6060f1SDimitry Andric MF.makeDebugValueSubstitution({Sub.SrcInst, Sub.SrcOp},
453fe6060f1SDimitry Andric {Sub.DstInst, Sub.DstOp}, Sub.Subreg);
454e8d8bef9SDimitry Andric }
455bdd1243dSDimitry Andric
456bdd1243dSDimitry Andric // Flag for whether we're supposed to be using DBG_INSTR_REF.
457bdd1243dSDimitry Andric MF.setUseDebugInstrRef(YamlMF.UseDebugInstrRef);
458e8d8bef9SDimitry Andric }
459e8d8bef9SDimitry Andric
4600b57cec5SDimitry Andric bool
initializeMachineFunction(const yaml::MachineFunction & YamlMF,MachineFunction & MF)4610b57cec5SDimitry Andric MIRParserImpl::initializeMachineFunction(const yaml::MachineFunction &YamlMF,
4620b57cec5SDimitry Andric MachineFunction &MF) {
4630b57cec5SDimitry Andric // TODO: Recreate the machine function.
4640b57cec5SDimitry Andric if (Target) {
4650b57cec5SDimitry Andric // Avoid clearing state if we're using the same subtarget again.
4660b57cec5SDimitry Andric Target->setTarget(MF.getSubtarget());
4670b57cec5SDimitry Andric } else {
4680b57cec5SDimitry Andric Target.reset(new PerTargetMIParsingState(MF.getSubtarget()));
4690b57cec5SDimitry Andric }
4700b57cec5SDimitry Andric
4715ffd83dbSDimitry Andric MF.setAlignment(YamlMF.Alignment.valueOrOne());
4720b57cec5SDimitry Andric MF.setExposesReturnsTwice(YamlMF.ExposesReturnsTwice);
4730b57cec5SDimitry Andric MF.setHasWinCFI(YamlMF.HasWinCFI);
4740b57cec5SDimitry Andric
47581ad6265SDimitry Andric MF.setCallsEHReturn(YamlMF.CallsEHReturn);
47681ad6265SDimitry Andric MF.setCallsUnwindInit(YamlMF.CallsUnwindInit);
47781ad6265SDimitry Andric MF.setHasEHCatchret(YamlMF.HasEHCatchret);
47881ad6265SDimitry Andric MF.setHasEHScopes(YamlMF.HasEHScopes);
47981ad6265SDimitry Andric MF.setHasEHFunclets(YamlMF.HasEHFunclets);
480*fe013be4SDimitry Andric MF.setIsOutlined(YamlMF.IsOutlined);
48181ad6265SDimitry Andric
4820b57cec5SDimitry Andric if (YamlMF.Legalized)
4830b57cec5SDimitry Andric MF.getProperties().set(MachineFunctionProperties::Property::Legalized);
4840b57cec5SDimitry Andric if (YamlMF.RegBankSelected)
4850b57cec5SDimitry Andric MF.getProperties().set(
4860b57cec5SDimitry Andric MachineFunctionProperties::Property::RegBankSelected);
4870b57cec5SDimitry Andric if (YamlMF.Selected)
4880b57cec5SDimitry Andric MF.getProperties().set(MachineFunctionProperties::Property::Selected);
4890b57cec5SDimitry Andric if (YamlMF.FailedISel)
4900b57cec5SDimitry Andric MF.getProperties().set(MachineFunctionProperties::Property::FailedISel);
491349cc55cSDimitry Andric if (YamlMF.FailsVerification)
492349cc55cSDimitry Andric MF.getProperties().set(
493349cc55cSDimitry Andric MachineFunctionProperties::Property::FailsVerification);
4940eae32dcSDimitry Andric if (YamlMF.TracksDebugUserValues)
4950eae32dcSDimitry Andric MF.getProperties().set(
4960eae32dcSDimitry Andric MachineFunctionProperties::Property::TracksDebugUserValues);
4970b57cec5SDimitry Andric
4980b57cec5SDimitry Andric PerFunctionMIParsingState PFS(MF, SM, IRSlots, *Target);
4990b57cec5SDimitry Andric if (parseRegisterInfo(PFS, YamlMF))
5000b57cec5SDimitry Andric return true;
5010b57cec5SDimitry Andric if (!YamlMF.Constants.empty()) {
5020b57cec5SDimitry Andric auto *ConstantPool = MF.getConstantPool();
5030b57cec5SDimitry Andric assert(ConstantPool && "Constant pool must be created");
5040b57cec5SDimitry Andric if (initializeConstantPool(PFS, *ConstantPool, YamlMF))
5050b57cec5SDimitry Andric return true;
5060b57cec5SDimitry Andric }
507fe6060f1SDimitry Andric if (!YamlMF.MachineMetadataNodes.empty() &&
508fe6060f1SDimitry Andric parseMachineMetadataNodes(PFS, MF, YamlMF))
509fe6060f1SDimitry Andric return true;
5100b57cec5SDimitry Andric
5110b57cec5SDimitry Andric StringRef BlockStr = YamlMF.Body.Value.Value;
5120b57cec5SDimitry Andric SMDiagnostic Error;
5130b57cec5SDimitry Andric SourceMgr BlockSM;
5140b57cec5SDimitry Andric BlockSM.AddNewSourceBuffer(
5150b57cec5SDimitry Andric MemoryBuffer::getMemBuffer(BlockStr, "",/*RequiresNullTerminator=*/false),
5160b57cec5SDimitry Andric SMLoc());
5170b57cec5SDimitry Andric PFS.SM = &BlockSM;
5180b57cec5SDimitry Andric if (parseMachineBasicBlockDefinitions(PFS, BlockStr, Error)) {
5190b57cec5SDimitry Andric reportDiagnostic(
5200b57cec5SDimitry Andric diagFromBlockStringDiag(Error, YamlMF.Body.Value.SourceRange));
5210b57cec5SDimitry Andric return true;
5220b57cec5SDimitry Andric }
5235ffd83dbSDimitry Andric // Check Basic Block Section Flags.
5245ffd83dbSDimitry Andric if (MF.getTarget().getBBSectionsType() == BasicBlockSection::Labels) {
5255ffd83dbSDimitry Andric MF.setBBSectionsType(BasicBlockSection::Labels);
5265ffd83dbSDimitry Andric } else if (MF.hasBBSections()) {
5275ffd83dbSDimitry Andric MF.assignBeginEndSections();
5285ffd83dbSDimitry Andric }
5290b57cec5SDimitry Andric PFS.SM = &SM;
5300b57cec5SDimitry Andric
5310b57cec5SDimitry Andric // Initialize the frame information after creating all the MBBs so that the
5320b57cec5SDimitry Andric // MBB references in the frame information can be resolved.
5330b57cec5SDimitry Andric if (initializeFrameInfo(PFS, YamlMF))
5340b57cec5SDimitry Andric return true;
5350b57cec5SDimitry Andric // Initialize the jump table after creating all the MBBs so that the MBB
5360b57cec5SDimitry Andric // references can be resolved.
5370b57cec5SDimitry Andric if (!YamlMF.JumpTableInfo.Entries.empty() &&
5380b57cec5SDimitry Andric initializeJumpTableInfo(PFS, YamlMF.JumpTableInfo))
5390b57cec5SDimitry Andric return true;
5400b57cec5SDimitry Andric // Parse the machine instructions after creating all of the MBBs so that the
5410b57cec5SDimitry Andric // parser can resolve the MBB references.
5420b57cec5SDimitry Andric StringRef InsnStr = YamlMF.Body.Value.Value;
5430b57cec5SDimitry Andric SourceMgr InsnSM;
5440b57cec5SDimitry Andric InsnSM.AddNewSourceBuffer(
5450b57cec5SDimitry Andric MemoryBuffer::getMemBuffer(InsnStr, "", /*RequiresNullTerminator=*/false),
5460b57cec5SDimitry Andric SMLoc());
5470b57cec5SDimitry Andric PFS.SM = &InsnSM;
5480b57cec5SDimitry Andric if (parseMachineInstructions(PFS, InsnStr, Error)) {
5490b57cec5SDimitry Andric reportDiagnostic(
5500b57cec5SDimitry Andric diagFromBlockStringDiag(Error, YamlMF.Body.Value.SourceRange));
5510b57cec5SDimitry Andric return true;
5520b57cec5SDimitry Andric }
5530b57cec5SDimitry Andric PFS.SM = &SM;
5540b57cec5SDimitry Andric
5550b57cec5SDimitry Andric if (setupRegisterInfo(PFS, YamlMF))
5560b57cec5SDimitry Andric return true;
5570b57cec5SDimitry Andric
5580b57cec5SDimitry Andric if (YamlMF.MachineFuncInfo) {
5590b57cec5SDimitry Andric const LLVMTargetMachine &TM = MF.getTarget();
5600b57cec5SDimitry Andric // Note this is called after the initial constructor of the
5610b57cec5SDimitry Andric // MachineFunctionInfo based on the MachineFunction, which may depend on the
5620b57cec5SDimitry Andric // IR.
5630b57cec5SDimitry Andric
5640b57cec5SDimitry Andric SMRange SrcRange;
5650b57cec5SDimitry Andric if (TM.parseMachineFunctionInfo(*YamlMF.MachineFuncInfo, PFS, Error,
5660b57cec5SDimitry Andric SrcRange)) {
5670b57cec5SDimitry Andric return error(Error, SrcRange);
5680b57cec5SDimitry Andric }
5690b57cec5SDimitry Andric }
5700b57cec5SDimitry Andric
5710b57cec5SDimitry Andric // Set the reserved registers after parsing MachineFuncInfo. The target may
5720b57cec5SDimitry Andric // have been recording information used to select the reserved registers
5730b57cec5SDimitry Andric // there.
5740b57cec5SDimitry Andric // FIXME: This is a temporary workaround until the reserved registers can be
5750b57cec5SDimitry Andric // serialized.
5760b57cec5SDimitry Andric MachineRegisterInfo &MRI = MF.getRegInfo();
5770b57cec5SDimitry Andric MRI.freezeReservedRegs(MF);
5780b57cec5SDimitry Andric
5790b57cec5SDimitry Andric computeFunctionProperties(MF);
5800b57cec5SDimitry Andric
5810b57cec5SDimitry Andric if (initializeCallSiteInfo(PFS, YamlMF))
5820b57cec5SDimitry Andric return false;
5830b57cec5SDimitry Andric
584e8d8bef9SDimitry Andric setupDebugValueTracking(MF, PFS, YamlMF);
585e8d8bef9SDimitry Andric
5860b57cec5SDimitry Andric MF.getSubtarget().mirFileLoaded(MF);
5870b57cec5SDimitry Andric
5880b57cec5SDimitry Andric MF.verify();
5890b57cec5SDimitry Andric return false;
5900b57cec5SDimitry Andric }
5910b57cec5SDimitry Andric
parseRegisterInfo(PerFunctionMIParsingState & PFS,const yaml::MachineFunction & YamlMF)5920b57cec5SDimitry Andric bool MIRParserImpl::parseRegisterInfo(PerFunctionMIParsingState &PFS,
5930b57cec5SDimitry Andric const yaml::MachineFunction &YamlMF) {
5940b57cec5SDimitry Andric MachineFunction &MF = PFS.MF;
5950b57cec5SDimitry Andric MachineRegisterInfo &RegInfo = MF.getRegInfo();
5960b57cec5SDimitry Andric assert(RegInfo.tracksLiveness());
5970b57cec5SDimitry Andric if (!YamlMF.TracksRegLiveness)
5980b57cec5SDimitry Andric RegInfo.invalidateLiveness();
5990b57cec5SDimitry Andric
6000b57cec5SDimitry Andric SMDiagnostic Error;
6010b57cec5SDimitry Andric // Parse the virtual register information.
6020b57cec5SDimitry Andric for (const auto &VReg : YamlMF.VirtualRegisters) {
6030b57cec5SDimitry Andric VRegInfo &Info = PFS.getVRegInfo(VReg.ID.Value);
6040b57cec5SDimitry Andric if (Info.Explicit)
6050b57cec5SDimitry Andric return error(VReg.ID.SourceRange.Start,
6060b57cec5SDimitry Andric Twine("redefinition of virtual register '%") +
6070b57cec5SDimitry Andric Twine(VReg.ID.Value) + "'");
6080b57cec5SDimitry Andric Info.Explicit = true;
6090b57cec5SDimitry Andric
6100b57cec5SDimitry Andric if (StringRef(VReg.Class.Value).equals("_")) {
6110b57cec5SDimitry Andric Info.Kind = VRegInfo::GENERIC;
6120b57cec5SDimitry Andric Info.D.RegBank = nullptr;
6130b57cec5SDimitry Andric } else {
6140b57cec5SDimitry Andric const auto *RC = Target->getRegClass(VReg.Class.Value);
6150b57cec5SDimitry Andric if (RC) {
6160b57cec5SDimitry Andric Info.Kind = VRegInfo::NORMAL;
6170b57cec5SDimitry Andric Info.D.RC = RC;
6180b57cec5SDimitry Andric } else {
6190b57cec5SDimitry Andric const RegisterBank *RegBank = Target->getRegBank(VReg.Class.Value);
6200b57cec5SDimitry Andric if (!RegBank)
6210b57cec5SDimitry Andric return error(
6220b57cec5SDimitry Andric VReg.Class.SourceRange.Start,
6230b57cec5SDimitry Andric Twine("use of undefined register class or register bank '") +
6240b57cec5SDimitry Andric VReg.Class.Value + "'");
6250b57cec5SDimitry Andric Info.Kind = VRegInfo::REGBANK;
6260b57cec5SDimitry Andric Info.D.RegBank = RegBank;
6270b57cec5SDimitry Andric }
6280b57cec5SDimitry Andric }
6290b57cec5SDimitry Andric
6300b57cec5SDimitry Andric if (!VReg.PreferredRegister.Value.empty()) {
6310b57cec5SDimitry Andric if (Info.Kind != VRegInfo::NORMAL)
6320b57cec5SDimitry Andric return error(VReg.Class.SourceRange.Start,
6330b57cec5SDimitry Andric Twine("preferred register can only be set for normal vregs"));
6340b57cec5SDimitry Andric
6350b57cec5SDimitry Andric if (parseRegisterReference(PFS, Info.PreferredReg,
6360b57cec5SDimitry Andric VReg.PreferredRegister.Value, Error))
6370b57cec5SDimitry Andric return error(Error, VReg.PreferredRegister.SourceRange);
6380b57cec5SDimitry Andric }
6390b57cec5SDimitry Andric }
6400b57cec5SDimitry Andric
6410b57cec5SDimitry Andric // Parse the liveins.
6420b57cec5SDimitry Andric for (const auto &LiveIn : YamlMF.LiveIns) {
6435ffd83dbSDimitry Andric Register Reg;
6440b57cec5SDimitry Andric if (parseNamedRegisterReference(PFS, Reg, LiveIn.Register.Value, Error))
6450b57cec5SDimitry Andric return error(Error, LiveIn.Register.SourceRange);
6465ffd83dbSDimitry Andric Register VReg;
6470b57cec5SDimitry Andric if (!LiveIn.VirtualRegister.Value.empty()) {
6480b57cec5SDimitry Andric VRegInfo *Info;
6490b57cec5SDimitry Andric if (parseVirtualRegisterReference(PFS, Info, LiveIn.VirtualRegister.Value,
6500b57cec5SDimitry Andric Error))
6510b57cec5SDimitry Andric return error(Error, LiveIn.VirtualRegister.SourceRange);
6520b57cec5SDimitry Andric VReg = Info->VReg;
6530b57cec5SDimitry Andric }
6540b57cec5SDimitry Andric RegInfo.addLiveIn(Reg, VReg);
6550b57cec5SDimitry Andric }
6560b57cec5SDimitry Andric
6570b57cec5SDimitry Andric // Parse the callee saved registers (Registers that will
6580b57cec5SDimitry Andric // be saved for the caller).
6590b57cec5SDimitry Andric if (YamlMF.CalleeSavedRegisters) {
6600b57cec5SDimitry Andric SmallVector<MCPhysReg, 16> CalleeSavedRegisters;
66181ad6265SDimitry Andric for (const auto &RegSource : *YamlMF.CalleeSavedRegisters) {
6625ffd83dbSDimitry Andric Register Reg;
6630b57cec5SDimitry Andric if (parseNamedRegisterReference(PFS, Reg, RegSource.Value, Error))
6640b57cec5SDimitry Andric return error(Error, RegSource.SourceRange);
6650b57cec5SDimitry Andric CalleeSavedRegisters.push_back(Reg);
6660b57cec5SDimitry Andric }
6670b57cec5SDimitry Andric RegInfo.setCalleeSavedRegs(CalleeSavedRegisters);
6680b57cec5SDimitry Andric }
6690b57cec5SDimitry Andric
6700b57cec5SDimitry Andric return false;
6710b57cec5SDimitry Andric }
6720b57cec5SDimitry Andric
setupRegisterInfo(const PerFunctionMIParsingState & PFS,const yaml::MachineFunction & YamlMF)6730b57cec5SDimitry Andric bool MIRParserImpl::setupRegisterInfo(const PerFunctionMIParsingState &PFS,
6740b57cec5SDimitry Andric const yaml::MachineFunction &YamlMF) {
6750b57cec5SDimitry Andric MachineFunction &MF = PFS.MF;
6760b57cec5SDimitry Andric MachineRegisterInfo &MRI = MF.getRegInfo();
677bdd1243dSDimitry Andric const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
678bdd1243dSDimitry Andric
6790b57cec5SDimitry Andric bool Error = false;
6800b57cec5SDimitry Andric // Create VRegs
6810b57cec5SDimitry Andric auto populateVRegInfo = [&](const VRegInfo &Info, Twine Name) {
6825ffd83dbSDimitry Andric Register Reg = Info.VReg;
6830b57cec5SDimitry Andric switch (Info.Kind) {
6840b57cec5SDimitry Andric case VRegInfo::UNKNOWN:
6850b57cec5SDimitry Andric error(Twine("Cannot determine class/bank of virtual register ") +
6860b57cec5SDimitry Andric Name + " in function '" + MF.getName() + "'");
6870b57cec5SDimitry Andric Error = true;
6880b57cec5SDimitry Andric break;
6890b57cec5SDimitry Andric case VRegInfo::NORMAL:
690bdd1243dSDimitry Andric if (!Info.D.RC->isAllocatable()) {
691bdd1243dSDimitry Andric error(Twine("Cannot use non-allocatable class '") +
692bdd1243dSDimitry Andric TRI->getRegClassName(Info.D.RC) + "' for virtual register " +
693bdd1243dSDimitry Andric Name + " in function '" + MF.getName() + "'");
694bdd1243dSDimitry Andric Error = true;
695bdd1243dSDimitry Andric break;
696bdd1243dSDimitry Andric }
697bdd1243dSDimitry Andric
6980b57cec5SDimitry Andric MRI.setRegClass(Reg, Info.D.RC);
6990b57cec5SDimitry Andric if (Info.PreferredReg != 0)
7000b57cec5SDimitry Andric MRI.setSimpleHint(Reg, Info.PreferredReg);
7010b57cec5SDimitry Andric break;
7020b57cec5SDimitry Andric case VRegInfo::GENERIC:
7030b57cec5SDimitry Andric break;
7040b57cec5SDimitry Andric case VRegInfo::REGBANK:
7050b57cec5SDimitry Andric MRI.setRegBank(Reg, *Info.D.RegBank);
7060b57cec5SDimitry Andric break;
7070b57cec5SDimitry Andric }
7080b57cec5SDimitry Andric };
7090b57cec5SDimitry Andric
710fe6060f1SDimitry Andric for (const auto &P : PFS.VRegInfosNamed) {
711fe6060f1SDimitry Andric const VRegInfo &Info = *P.second;
712fe6060f1SDimitry Andric populateVRegInfo(Info, Twine(P.first()));
7130b57cec5SDimitry Andric }
7140b57cec5SDimitry Andric
7150b57cec5SDimitry Andric for (auto P : PFS.VRegInfos) {
7160b57cec5SDimitry Andric const VRegInfo &Info = *P.second;
7170b57cec5SDimitry Andric populateVRegInfo(Info, Twine(P.first));
7180b57cec5SDimitry Andric }
7190b57cec5SDimitry Andric
7200b57cec5SDimitry Andric // Compute MachineRegisterInfo::UsedPhysRegMask
7210b57cec5SDimitry Andric for (const MachineBasicBlock &MBB : MF) {
722e8d8bef9SDimitry Andric // Make sure MRI knows about registers clobbered by unwinder.
723e8d8bef9SDimitry Andric if (MBB.isEHPad())
724e8d8bef9SDimitry Andric if (auto *RegMask = TRI->getCustomEHPadPreservedMask(MF))
725e8d8bef9SDimitry Andric MRI.addPhysRegsUsedFromRegMask(RegMask);
726e8d8bef9SDimitry Andric
7270b57cec5SDimitry Andric for (const MachineInstr &MI : MBB) {
7280b57cec5SDimitry Andric for (const MachineOperand &MO : MI.operands()) {
7290b57cec5SDimitry Andric if (!MO.isRegMask())
7300b57cec5SDimitry Andric continue;
7310b57cec5SDimitry Andric MRI.addPhysRegsUsedFromRegMask(MO.getRegMask());
7320b57cec5SDimitry Andric }
7330b57cec5SDimitry Andric }
7340b57cec5SDimitry Andric }
7350b57cec5SDimitry Andric
7360b57cec5SDimitry Andric return Error;
7370b57cec5SDimitry Andric }
7380b57cec5SDimitry Andric
initializeFrameInfo(PerFunctionMIParsingState & PFS,const yaml::MachineFunction & YamlMF)7390b57cec5SDimitry Andric bool MIRParserImpl::initializeFrameInfo(PerFunctionMIParsingState &PFS,
7400b57cec5SDimitry Andric const yaml::MachineFunction &YamlMF) {
7410b57cec5SDimitry Andric MachineFunction &MF = PFS.MF;
7420b57cec5SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo();
7430b57cec5SDimitry Andric const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
7440b57cec5SDimitry Andric const Function &F = MF.getFunction();
7450b57cec5SDimitry Andric const yaml::MachineFrameInfo &YamlMFI = YamlMF.FrameInfo;
7460b57cec5SDimitry Andric MFI.setFrameAddressIsTaken(YamlMFI.IsFrameAddressTaken);
7470b57cec5SDimitry Andric MFI.setReturnAddressIsTaken(YamlMFI.IsReturnAddressTaken);
7480b57cec5SDimitry Andric MFI.setHasStackMap(YamlMFI.HasStackMap);
7490b57cec5SDimitry Andric MFI.setHasPatchPoint(YamlMFI.HasPatchPoint);
7500b57cec5SDimitry Andric MFI.setStackSize(YamlMFI.StackSize);
7510b57cec5SDimitry Andric MFI.setOffsetAdjustment(YamlMFI.OffsetAdjustment);
7520b57cec5SDimitry Andric if (YamlMFI.MaxAlignment)
7535ffd83dbSDimitry Andric MFI.ensureMaxAlignment(Align(YamlMFI.MaxAlignment));
7540b57cec5SDimitry Andric MFI.setAdjustsStack(YamlMFI.AdjustsStack);
7550b57cec5SDimitry Andric MFI.setHasCalls(YamlMFI.HasCalls);
7560b57cec5SDimitry Andric if (YamlMFI.MaxCallFrameSize != ~0u)
7570b57cec5SDimitry Andric MFI.setMaxCallFrameSize(YamlMFI.MaxCallFrameSize);
7580b57cec5SDimitry Andric MFI.setCVBytesOfCalleeSavedRegisters(YamlMFI.CVBytesOfCalleeSavedRegisters);
7590b57cec5SDimitry Andric MFI.setHasOpaqueSPAdjustment(YamlMFI.HasOpaqueSPAdjustment);
7600b57cec5SDimitry Andric MFI.setHasVAStart(YamlMFI.HasVAStart);
7610b57cec5SDimitry Andric MFI.setHasMustTailInVarArgFunc(YamlMFI.HasMustTailInVarArgFunc);
762fe6060f1SDimitry Andric MFI.setHasTailCall(YamlMFI.HasTailCall);
7630b57cec5SDimitry Andric MFI.setLocalFrameSize(YamlMFI.LocalFrameSize);
7640b57cec5SDimitry Andric if (!YamlMFI.SavePoint.Value.empty()) {
7650b57cec5SDimitry Andric MachineBasicBlock *MBB = nullptr;
7660b57cec5SDimitry Andric if (parseMBBReference(PFS, MBB, YamlMFI.SavePoint))
7670b57cec5SDimitry Andric return true;
7680b57cec5SDimitry Andric MFI.setSavePoint(MBB);
7690b57cec5SDimitry Andric }
7700b57cec5SDimitry Andric if (!YamlMFI.RestorePoint.Value.empty()) {
7710b57cec5SDimitry Andric MachineBasicBlock *MBB = nullptr;
7720b57cec5SDimitry Andric if (parseMBBReference(PFS, MBB, YamlMFI.RestorePoint))
7730b57cec5SDimitry Andric return true;
7740b57cec5SDimitry Andric MFI.setRestorePoint(MBB);
7750b57cec5SDimitry Andric }
7760b57cec5SDimitry Andric
7770b57cec5SDimitry Andric std::vector<CalleeSavedInfo> CSIInfo;
7780b57cec5SDimitry Andric // Initialize the fixed frame objects.
7790b57cec5SDimitry Andric for (const auto &Object : YamlMF.FixedStackObjects) {
7800b57cec5SDimitry Andric int ObjectIdx;
7810b57cec5SDimitry Andric if (Object.Type != yaml::FixedMachineStackObject::SpillSlot)
7820b57cec5SDimitry Andric ObjectIdx = MFI.CreateFixedObject(Object.Size, Object.Offset,
7830b57cec5SDimitry Andric Object.IsImmutable, Object.IsAliased);
7840b57cec5SDimitry Andric else
7850b57cec5SDimitry Andric ObjectIdx = MFI.CreateFixedSpillStackObject(Object.Size, Object.Offset);
7860b57cec5SDimitry Andric
7870b57cec5SDimitry Andric if (!TFI->isSupportedStackID(Object.StackID))
7880b57cec5SDimitry Andric return error(Object.ID.SourceRange.Start,
7890b57cec5SDimitry Andric Twine("StackID is not supported by target"));
7900b57cec5SDimitry Andric MFI.setStackID(ObjectIdx, Object.StackID);
7915ffd83dbSDimitry Andric MFI.setObjectAlignment(ObjectIdx, Object.Alignment.valueOrOne());
7920b57cec5SDimitry Andric if (!PFS.FixedStackObjectSlots.insert(std::make_pair(Object.ID.Value,
7930b57cec5SDimitry Andric ObjectIdx))
7940b57cec5SDimitry Andric .second)
7950b57cec5SDimitry Andric return error(Object.ID.SourceRange.Start,
7960b57cec5SDimitry Andric Twine("redefinition of fixed stack object '%fixed-stack.") +
7970b57cec5SDimitry Andric Twine(Object.ID.Value) + "'");
7980b57cec5SDimitry Andric if (parseCalleeSavedRegister(PFS, CSIInfo, Object.CalleeSavedRegister,
7990b57cec5SDimitry Andric Object.CalleeSavedRestored, ObjectIdx))
8000b57cec5SDimitry Andric return true;
8010b57cec5SDimitry Andric if (parseStackObjectsDebugInfo(PFS, Object, ObjectIdx))
8020b57cec5SDimitry Andric return true;
8030b57cec5SDimitry Andric }
8040b57cec5SDimitry Andric
805*fe013be4SDimitry Andric for (const auto &Object : YamlMF.EntryValueObjects) {
806*fe013be4SDimitry Andric SMDiagnostic Error;
807*fe013be4SDimitry Andric Register Reg;
808*fe013be4SDimitry Andric if (parseNamedRegisterReference(PFS, Reg, Object.EntryValueRegister.Value,
809*fe013be4SDimitry Andric Error))
810*fe013be4SDimitry Andric return error(Error, Object.EntryValueRegister.SourceRange);
811*fe013be4SDimitry Andric if (!Reg.isPhysical())
812*fe013be4SDimitry Andric return error(Object.EntryValueRegister.SourceRange.Start,
813*fe013be4SDimitry Andric "Expected physical register for entry value field");
814*fe013be4SDimitry Andric std::optional<VarExprLoc> MaybeInfo = parseVarExprLoc(
815*fe013be4SDimitry Andric PFS, Object.DebugVar, Object.DebugExpr, Object.DebugLoc);
816*fe013be4SDimitry Andric if (!MaybeInfo)
817*fe013be4SDimitry Andric return true;
818*fe013be4SDimitry Andric if (MaybeInfo->DIVar || MaybeInfo->DIExpr || MaybeInfo->DILoc)
819*fe013be4SDimitry Andric PFS.MF.setVariableDbgInfo(MaybeInfo->DIVar, MaybeInfo->DIExpr,
820*fe013be4SDimitry Andric Reg.asMCReg(), MaybeInfo->DILoc);
821*fe013be4SDimitry Andric }
822*fe013be4SDimitry Andric
8230b57cec5SDimitry Andric // Initialize the ordinary frame objects.
8240b57cec5SDimitry Andric for (const auto &Object : YamlMF.StackObjects) {
8250b57cec5SDimitry Andric int ObjectIdx;
8260b57cec5SDimitry Andric const AllocaInst *Alloca = nullptr;
8270b57cec5SDimitry Andric const yaml::StringValue &Name = Object.Name;
8280b57cec5SDimitry Andric if (!Name.Value.empty()) {
8290b57cec5SDimitry Andric Alloca = dyn_cast_or_null<AllocaInst>(
8300b57cec5SDimitry Andric F.getValueSymbolTable()->lookup(Name.Value));
8310b57cec5SDimitry Andric if (!Alloca)
8320b57cec5SDimitry Andric return error(Name.SourceRange.Start,
8330b57cec5SDimitry Andric "alloca instruction named '" + Name.Value +
8340b57cec5SDimitry Andric "' isn't defined in the function '" + F.getName() +
8350b57cec5SDimitry Andric "'");
8360b57cec5SDimitry Andric }
8370b57cec5SDimitry Andric if (!TFI->isSupportedStackID(Object.StackID))
8380b57cec5SDimitry Andric return error(Object.ID.SourceRange.Start,
8390b57cec5SDimitry Andric Twine("StackID is not supported by target"));
8400b57cec5SDimitry Andric if (Object.Type == yaml::MachineStackObject::VariableSized)
8415ffd83dbSDimitry Andric ObjectIdx =
8425ffd83dbSDimitry Andric MFI.CreateVariableSizedObject(Object.Alignment.valueOrOne(), Alloca);
8430b57cec5SDimitry Andric else
8440b57cec5SDimitry Andric ObjectIdx = MFI.CreateStackObject(
8455ffd83dbSDimitry Andric Object.Size, Object.Alignment.valueOrOne(),
8460b57cec5SDimitry Andric Object.Type == yaml::MachineStackObject::SpillSlot, Alloca,
8470b57cec5SDimitry Andric Object.StackID);
8480b57cec5SDimitry Andric MFI.setObjectOffset(ObjectIdx, Object.Offset);
8490b57cec5SDimitry Andric
8500b57cec5SDimitry Andric if (!PFS.StackObjectSlots.insert(std::make_pair(Object.ID.Value, ObjectIdx))
8510b57cec5SDimitry Andric .second)
8520b57cec5SDimitry Andric return error(Object.ID.SourceRange.Start,
8530b57cec5SDimitry Andric Twine("redefinition of stack object '%stack.") +
8540b57cec5SDimitry Andric Twine(Object.ID.Value) + "'");
8550b57cec5SDimitry Andric if (parseCalleeSavedRegister(PFS, CSIInfo, Object.CalleeSavedRegister,
8560b57cec5SDimitry Andric Object.CalleeSavedRestored, ObjectIdx))
8570b57cec5SDimitry Andric return true;
8580b57cec5SDimitry Andric if (Object.LocalOffset)
85981ad6265SDimitry Andric MFI.mapLocalFrameObject(ObjectIdx, *Object.LocalOffset);
8600b57cec5SDimitry Andric if (parseStackObjectsDebugInfo(PFS, Object, ObjectIdx))
8610b57cec5SDimitry Andric return true;
8620b57cec5SDimitry Andric }
8630b57cec5SDimitry Andric MFI.setCalleeSavedInfo(CSIInfo);
8640b57cec5SDimitry Andric if (!CSIInfo.empty())
8650b57cec5SDimitry Andric MFI.setCalleeSavedInfoValid(true);
8660b57cec5SDimitry Andric
8670b57cec5SDimitry Andric // Initialize the various stack object references after initializing the
8680b57cec5SDimitry Andric // stack objects.
8690b57cec5SDimitry Andric if (!YamlMFI.StackProtector.Value.empty()) {
8700b57cec5SDimitry Andric SMDiagnostic Error;
8710b57cec5SDimitry Andric int FI;
8720b57cec5SDimitry Andric if (parseStackObjectReference(PFS, FI, YamlMFI.StackProtector.Value, Error))
8730b57cec5SDimitry Andric return error(Error, YamlMFI.StackProtector.SourceRange);
8740b57cec5SDimitry Andric MFI.setStackProtectorIndex(FI);
8750b57cec5SDimitry Andric }
87681ad6265SDimitry Andric
87781ad6265SDimitry Andric if (!YamlMFI.FunctionContext.Value.empty()) {
87881ad6265SDimitry Andric SMDiagnostic Error;
87981ad6265SDimitry Andric int FI;
88081ad6265SDimitry Andric if (parseStackObjectReference(PFS, FI, YamlMFI.FunctionContext.Value, Error))
88181ad6265SDimitry Andric return error(Error, YamlMFI.FunctionContext.SourceRange);
88281ad6265SDimitry Andric MFI.setFunctionContextIndex(FI);
88381ad6265SDimitry Andric }
88481ad6265SDimitry Andric
8850b57cec5SDimitry Andric return false;
8860b57cec5SDimitry Andric }
8870b57cec5SDimitry Andric
parseCalleeSavedRegister(PerFunctionMIParsingState & PFS,std::vector<CalleeSavedInfo> & CSIInfo,const yaml::StringValue & RegisterSource,bool IsRestored,int FrameIdx)8880b57cec5SDimitry Andric bool MIRParserImpl::parseCalleeSavedRegister(PerFunctionMIParsingState &PFS,
8890b57cec5SDimitry Andric std::vector<CalleeSavedInfo> &CSIInfo,
8900b57cec5SDimitry Andric const yaml::StringValue &RegisterSource, bool IsRestored, int FrameIdx) {
8910b57cec5SDimitry Andric if (RegisterSource.Value.empty())
8920b57cec5SDimitry Andric return false;
8935ffd83dbSDimitry Andric Register Reg;
8940b57cec5SDimitry Andric SMDiagnostic Error;
8950b57cec5SDimitry Andric if (parseNamedRegisterReference(PFS, Reg, RegisterSource.Value, Error))
8960b57cec5SDimitry Andric return error(Error, RegisterSource.SourceRange);
8970b57cec5SDimitry Andric CalleeSavedInfo CSI(Reg, FrameIdx);
8980b57cec5SDimitry Andric CSI.setRestored(IsRestored);
8990b57cec5SDimitry Andric CSIInfo.push_back(CSI);
9000b57cec5SDimitry Andric return false;
9010b57cec5SDimitry Andric }
9020b57cec5SDimitry Andric
9030b57cec5SDimitry Andric /// Verify that given node is of a certain type. Return true on error.
9040b57cec5SDimitry Andric template <typename T>
typecheckMDNode(T * & Result,MDNode * Node,const yaml::StringValue & Source,StringRef TypeString,MIRParserImpl & Parser)9050b57cec5SDimitry Andric static bool typecheckMDNode(T *&Result, MDNode *Node,
9060b57cec5SDimitry Andric const yaml::StringValue &Source,
9070b57cec5SDimitry Andric StringRef TypeString, MIRParserImpl &Parser) {
9080b57cec5SDimitry Andric if (!Node)
9090b57cec5SDimitry Andric return false;
9100b57cec5SDimitry Andric Result = dyn_cast<T>(Node);
9110b57cec5SDimitry Andric if (!Result)
9120b57cec5SDimitry Andric return Parser.error(Source.SourceRange.Start,
9130b57cec5SDimitry Andric "expected a reference to a '" + TypeString +
9140b57cec5SDimitry Andric "' metadata node");
9150b57cec5SDimitry Andric return false;
9160b57cec5SDimitry Andric }
9170b57cec5SDimitry Andric
parseVarExprLoc(PerFunctionMIParsingState & PFS,const yaml::StringValue & VarStr,const yaml::StringValue & ExprStr,const yaml::StringValue & LocStr)918*fe013be4SDimitry Andric std::optional<MIRParserImpl::VarExprLoc> MIRParserImpl::parseVarExprLoc(
919*fe013be4SDimitry Andric PerFunctionMIParsingState &PFS, const yaml::StringValue &VarStr,
920*fe013be4SDimitry Andric const yaml::StringValue &ExprStr, const yaml::StringValue &LocStr) {
921*fe013be4SDimitry Andric MDNode *Var = nullptr;
922*fe013be4SDimitry Andric MDNode *Expr = nullptr;
923*fe013be4SDimitry Andric MDNode *Loc = nullptr;
924*fe013be4SDimitry Andric if (parseMDNode(PFS, Var, VarStr) || parseMDNode(PFS, Expr, ExprStr) ||
925*fe013be4SDimitry Andric parseMDNode(PFS, Loc, LocStr))
926*fe013be4SDimitry Andric return std::nullopt;
9270b57cec5SDimitry Andric DILocalVariable *DIVar = nullptr;
9280b57cec5SDimitry Andric DIExpression *DIExpr = nullptr;
9290b57cec5SDimitry Andric DILocation *DILoc = nullptr;
930*fe013be4SDimitry Andric if (typecheckMDNode(DIVar, Var, VarStr, "DILocalVariable", *this) ||
931*fe013be4SDimitry Andric typecheckMDNode(DIExpr, Expr, ExprStr, "DIExpression", *this) ||
932*fe013be4SDimitry Andric typecheckMDNode(DILoc, Loc, LocStr, "DILocation", *this))
933*fe013be4SDimitry Andric return std::nullopt;
934*fe013be4SDimitry Andric return VarExprLoc{DIVar, DIExpr, DILoc};
935*fe013be4SDimitry Andric }
936*fe013be4SDimitry Andric
937*fe013be4SDimitry Andric template <typename T>
parseStackObjectsDebugInfo(PerFunctionMIParsingState & PFS,const T & Object,int FrameIdx)938*fe013be4SDimitry Andric bool MIRParserImpl::parseStackObjectsDebugInfo(PerFunctionMIParsingState &PFS,
939*fe013be4SDimitry Andric const T &Object, int FrameIdx) {
940*fe013be4SDimitry Andric std::optional<VarExprLoc> MaybeInfo =
941*fe013be4SDimitry Andric parseVarExprLoc(PFS, Object.DebugVar, Object.DebugExpr, Object.DebugLoc);
942*fe013be4SDimitry Andric if (!MaybeInfo)
9430b57cec5SDimitry Andric return true;
944*fe013be4SDimitry Andric // Debug information can only be attached to stack objects; Fixed stack
945*fe013be4SDimitry Andric // objects aren't supported.
946*fe013be4SDimitry Andric if (MaybeInfo->DIVar || MaybeInfo->DIExpr || MaybeInfo->DILoc)
947*fe013be4SDimitry Andric PFS.MF.setVariableDbgInfo(MaybeInfo->DIVar, MaybeInfo->DIExpr, FrameIdx,
948*fe013be4SDimitry Andric MaybeInfo->DILoc);
9490b57cec5SDimitry Andric return false;
9500b57cec5SDimitry Andric }
9510b57cec5SDimitry Andric
parseMDNode(PerFunctionMIParsingState & PFS,MDNode * & Node,const yaml::StringValue & Source)9520b57cec5SDimitry Andric bool MIRParserImpl::parseMDNode(PerFunctionMIParsingState &PFS,
9530b57cec5SDimitry Andric MDNode *&Node, const yaml::StringValue &Source) {
9540b57cec5SDimitry Andric if (Source.Value.empty())
9550b57cec5SDimitry Andric return false;
9560b57cec5SDimitry Andric SMDiagnostic Error;
9570b57cec5SDimitry Andric if (llvm::parseMDNode(PFS, Node, Source.Value, Error))
9580b57cec5SDimitry Andric return error(Error, Source.SourceRange);
9590b57cec5SDimitry Andric return false;
9600b57cec5SDimitry Andric }
9610b57cec5SDimitry Andric
initializeConstantPool(PerFunctionMIParsingState & PFS,MachineConstantPool & ConstantPool,const yaml::MachineFunction & YamlMF)9620b57cec5SDimitry Andric bool MIRParserImpl::initializeConstantPool(PerFunctionMIParsingState &PFS,
9630b57cec5SDimitry Andric MachineConstantPool &ConstantPool, const yaml::MachineFunction &YamlMF) {
9640b57cec5SDimitry Andric DenseMap<unsigned, unsigned> &ConstantPoolSlots = PFS.ConstantPoolSlots;
9650b57cec5SDimitry Andric const MachineFunction &MF = PFS.MF;
9660b57cec5SDimitry Andric const auto &M = *MF.getFunction().getParent();
9670b57cec5SDimitry Andric SMDiagnostic Error;
9680b57cec5SDimitry Andric for (const auto &YamlConstant : YamlMF.Constants) {
9690b57cec5SDimitry Andric if (YamlConstant.IsTargetSpecific)
9700b57cec5SDimitry Andric // FIXME: Support target-specific constant pools
9710b57cec5SDimitry Andric return error(YamlConstant.Value.SourceRange.Start,
9720b57cec5SDimitry Andric "Can't parse target-specific constant pool entries yet");
9730b57cec5SDimitry Andric const Constant *Value = dyn_cast_or_null<Constant>(
9740b57cec5SDimitry Andric parseConstantValue(YamlConstant.Value.Value, Error, M));
9750b57cec5SDimitry Andric if (!Value)
9760b57cec5SDimitry Andric return error(Error, YamlConstant.Value.SourceRange);
9775ffd83dbSDimitry Andric const Align PrefTypeAlign =
9785ffd83dbSDimitry Andric M.getDataLayout().getPrefTypeAlign(Value->getType());
97981ad6265SDimitry Andric const Align Alignment = YamlConstant.Alignment.value_or(PrefTypeAlign);
9800b57cec5SDimitry Andric unsigned Index = ConstantPool.getConstantPoolIndex(Value, Alignment);
9810b57cec5SDimitry Andric if (!ConstantPoolSlots.insert(std::make_pair(YamlConstant.ID.Value, Index))
9820b57cec5SDimitry Andric .second)
9830b57cec5SDimitry Andric return error(YamlConstant.ID.SourceRange.Start,
9840b57cec5SDimitry Andric Twine("redefinition of constant pool item '%const.") +
9850b57cec5SDimitry Andric Twine(YamlConstant.ID.Value) + "'");
9860b57cec5SDimitry Andric }
9870b57cec5SDimitry Andric return false;
9880b57cec5SDimitry Andric }
9890b57cec5SDimitry Andric
initializeJumpTableInfo(PerFunctionMIParsingState & PFS,const yaml::MachineJumpTable & YamlJTI)9900b57cec5SDimitry Andric bool MIRParserImpl::initializeJumpTableInfo(PerFunctionMIParsingState &PFS,
9910b57cec5SDimitry Andric const yaml::MachineJumpTable &YamlJTI) {
9920b57cec5SDimitry Andric MachineJumpTableInfo *JTI = PFS.MF.getOrCreateJumpTableInfo(YamlJTI.Kind);
9930b57cec5SDimitry Andric for (const auto &Entry : YamlJTI.Entries) {
9940b57cec5SDimitry Andric std::vector<MachineBasicBlock *> Blocks;
9950b57cec5SDimitry Andric for (const auto &MBBSource : Entry.Blocks) {
9960b57cec5SDimitry Andric MachineBasicBlock *MBB = nullptr;
9970b57cec5SDimitry Andric if (parseMBBReference(PFS, MBB, MBBSource.Value))
9980b57cec5SDimitry Andric return true;
9990b57cec5SDimitry Andric Blocks.push_back(MBB);
10000b57cec5SDimitry Andric }
10010b57cec5SDimitry Andric unsigned Index = JTI->createJumpTableIndex(Blocks);
10020b57cec5SDimitry Andric if (!PFS.JumpTableSlots.insert(std::make_pair(Entry.ID.Value, Index))
10030b57cec5SDimitry Andric .second)
10040b57cec5SDimitry Andric return error(Entry.ID.SourceRange.Start,
10050b57cec5SDimitry Andric Twine("redefinition of jump table entry '%jump-table.") +
10060b57cec5SDimitry Andric Twine(Entry.ID.Value) + "'");
10070b57cec5SDimitry Andric }
10080b57cec5SDimitry Andric return false;
10090b57cec5SDimitry Andric }
10100b57cec5SDimitry Andric
parseMBBReference(PerFunctionMIParsingState & PFS,MachineBasicBlock * & MBB,const yaml::StringValue & Source)10110b57cec5SDimitry Andric bool MIRParserImpl::parseMBBReference(PerFunctionMIParsingState &PFS,
10120b57cec5SDimitry Andric MachineBasicBlock *&MBB,
10130b57cec5SDimitry Andric const yaml::StringValue &Source) {
10140b57cec5SDimitry Andric SMDiagnostic Error;
10150b57cec5SDimitry Andric if (llvm::parseMBBReference(PFS, MBB, Source.Value, Error))
10160b57cec5SDimitry Andric return error(Error, Source.SourceRange);
10170b57cec5SDimitry Andric return false;
10180b57cec5SDimitry Andric }
10190b57cec5SDimitry Andric
parseMachineMetadata(PerFunctionMIParsingState & PFS,const yaml::StringValue & Source)1020fe6060f1SDimitry Andric bool MIRParserImpl::parseMachineMetadata(PerFunctionMIParsingState &PFS,
1021fe6060f1SDimitry Andric const yaml::StringValue &Source) {
1022fe6060f1SDimitry Andric SMDiagnostic Error;
1023fe6060f1SDimitry Andric if (llvm::parseMachineMetadata(PFS, Source.Value, Source.SourceRange, Error))
1024fe6060f1SDimitry Andric return error(Error, Source.SourceRange);
1025fe6060f1SDimitry Andric return false;
1026fe6060f1SDimitry Andric }
1027fe6060f1SDimitry Andric
parseMachineMetadataNodes(PerFunctionMIParsingState & PFS,MachineFunction & MF,const yaml::MachineFunction & YMF)1028fe6060f1SDimitry Andric bool MIRParserImpl::parseMachineMetadataNodes(
1029fe6060f1SDimitry Andric PerFunctionMIParsingState &PFS, MachineFunction &MF,
1030fe6060f1SDimitry Andric const yaml::MachineFunction &YMF) {
1031fcaf7f86SDimitry Andric for (const auto &MDS : YMF.MachineMetadataNodes) {
1032fe6060f1SDimitry Andric if (parseMachineMetadata(PFS, MDS))
1033fe6060f1SDimitry Andric return true;
1034fe6060f1SDimitry Andric }
1035fe6060f1SDimitry Andric // Report missing definitions from forward referenced nodes.
1036fe6060f1SDimitry Andric if (!PFS.MachineForwardRefMDNodes.empty())
1037fe6060f1SDimitry Andric return error(PFS.MachineForwardRefMDNodes.begin()->second.second,
1038fe6060f1SDimitry Andric "use of undefined metadata '!" +
1039fe6060f1SDimitry Andric Twine(PFS.MachineForwardRefMDNodes.begin()->first) + "'");
1040fe6060f1SDimitry Andric return false;
1041fe6060f1SDimitry Andric }
1042fe6060f1SDimitry Andric
diagFromMIStringDiag(const SMDiagnostic & Error,SMRange SourceRange)10430b57cec5SDimitry Andric SMDiagnostic MIRParserImpl::diagFromMIStringDiag(const SMDiagnostic &Error,
10440b57cec5SDimitry Andric SMRange SourceRange) {
10450b57cec5SDimitry Andric assert(SourceRange.isValid() && "Invalid source range");
10460b57cec5SDimitry Andric SMLoc Loc = SourceRange.Start;
10470b57cec5SDimitry Andric bool HasQuote = Loc.getPointer() < SourceRange.End.getPointer() &&
10480b57cec5SDimitry Andric *Loc.getPointer() == '\'';
10490b57cec5SDimitry Andric // Translate the location of the error from the location in the MI string to
10500b57cec5SDimitry Andric // the corresponding location in the MIR file.
10510b57cec5SDimitry Andric Loc = Loc.getFromPointer(Loc.getPointer() + Error.getColumnNo() +
10520b57cec5SDimitry Andric (HasQuote ? 1 : 0));
10530b57cec5SDimitry Andric
10540b57cec5SDimitry Andric // TODO: Translate any source ranges as well.
1055bdd1243dSDimitry Andric return SM.GetMessage(Loc, Error.getKind(), Error.getMessage(), std::nullopt,
10560b57cec5SDimitry Andric Error.getFixIts());
10570b57cec5SDimitry Andric }
10580b57cec5SDimitry Andric
diagFromBlockStringDiag(const SMDiagnostic & Error,SMRange SourceRange)10590b57cec5SDimitry Andric SMDiagnostic MIRParserImpl::diagFromBlockStringDiag(const SMDiagnostic &Error,
10600b57cec5SDimitry Andric SMRange SourceRange) {
10610b57cec5SDimitry Andric assert(SourceRange.isValid());
10620b57cec5SDimitry Andric
10630b57cec5SDimitry Andric // Translate the location of the error from the location in the llvm IR string
10640b57cec5SDimitry Andric // to the corresponding location in the MIR file.
10650b57cec5SDimitry Andric auto LineAndColumn = SM.getLineAndColumn(SourceRange.Start);
10660b57cec5SDimitry Andric unsigned Line = LineAndColumn.first + Error.getLineNo() - 1;
10670b57cec5SDimitry Andric unsigned Column = Error.getColumnNo();
10680b57cec5SDimitry Andric StringRef LineStr = Error.getLineContents();
10690b57cec5SDimitry Andric SMLoc Loc = Error.getLoc();
10700b57cec5SDimitry Andric
10710b57cec5SDimitry Andric // Get the full line and adjust the column number by taking the indentation of
10720b57cec5SDimitry Andric // LLVM IR into account.
10730b57cec5SDimitry Andric for (line_iterator L(*SM.getMemoryBuffer(SM.getMainFileID()), false), E;
10740b57cec5SDimitry Andric L != E; ++L) {
10750b57cec5SDimitry Andric if (L.line_number() == Line) {
10760b57cec5SDimitry Andric LineStr = *L;
10770b57cec5SDimitry Andric Loc = SMLoc::getFromPointer(LineStr.data());
10780b57cec5SDimitry Andric auto Indent = LineStr.find(Error.getLineContents());
10790b57cec5SDimitry Andric if (Indent != StringRef::npos)
10800b57cec5SDimitry Andric Column += Indent;
10810b57cec5SDimitry Andric break;
10820b57cec5SDimitry Andric }
10830b57cec5SDimitry Andric }
10840b57cec5SDimitry Andric
10850b57cec5SDimitry Andric return SMDiagnostic(SM, Loc, Filename, Line, Column, Error.getKind(),
10860b57cec5SDimitry Andric Error.getMessage(), LineStr, Error.getRanges(),
10870b57cec5SDimitry Andric Error.getFixIts());
10880b57cec5SDimitry Andric }
10890b57cec5SDimitry Andric
MIRParser(std::unique_ptr<MIRParserImpl> Impl)10900b57cec5SDimitry Andric MIRParser::MIRParser(std::unique_ptr<MIRParserImpl> Impl)
10910b57cec5SDimitry Andric : Impl(std::move(Impl)) {}
10920b57cec5SDimitry Andric
109381ad6265SDimitry Andric MIRParser::~MIRParser() = default;
10940b57cec5SDimitry Andric
10955ffd83dbSDimitry Andric std::unique_ptr<Module>
parseIRModule(DataLayoutCallbackTy DataLayoutCallback)10965ffd83dbSDimitry Andric MIRParser::parseIRModule(DataLayoutCallbackTy DataLayoutCallback) {
10975ffd83dbSDimitry Andric return Impl->parseIRModule(DataLayoutCallback);
10980b57cec5SDimitry Andric }
10990b57cec5SDimitry Andric
parseMachineFunctions(Module & M,MachineModuleInfo & MMI)11000b57cec5SDimitry Andric bool MIRParser::parseMachineFunctions(Module &M, MachineModuleInfo &MMI) {
11010b57cec5SDimitry Andric return Impl->parseMachineFunctions(M, MMI);
11020b57cec5SDimitry Andric }
11030b57cec5SDimitry Andric
createMIRParserFromFile(StringRef Filename,SMDiagnostic & Error,LLVMContext & Context,std::function<void (Function &)> ProcessIRFunction)1104480093f4SDimitry Andric std::unique_ptr<MIRParser> llvm::createMIRParserFromFile(
1105480093f4SDimitry Andric StringRef Filename, SMDiagnostic &Error, LLVMContext &Context,
1106480093f4SDimitry Andric std::function<void(Function &)> ProcessIRFunction) {
1107fe6060f1SDimitry Andric auto FileOrErr = MemoryBuffer::getFileOrSTDIN(Filename, /*IsText=*/true);
11080b57cec5SDimitry Andric if (std::error_code EC = FileOrErr.getError()) {
11090b57cec5SDimitry Andric Error = SMDiagnostic(Filename, SourceMgr::DK_Error,
11100b57cec5SDimitry Andric "Could not open input file: " + EC.message());
11110b57cec5SDimitry Andric return nullptr;
11120b57cec5SDimitry Andric }
1113480093f4SDimitry Andric return createMIRParser(std::move(FileOrErr.get()), Context,
1114480093f4SDimitry Andric ProcessIRFunction);
11150b57cec5SDimitry Andric }
11160b57cec5SDimitry Andric
11170b57cec5SDimitry Andric std::unique_ptr<MIRParser>
createMIRParser(std::unique_ptr<MemoryBuffer> Contents,LLVMContext & Context,std::function<void (Function &)> ProcessIRFunction)11180b57cec5SDimitry Andric llvm::createMIRParser(std::unique_ptr<MemoryBuffer> Contents,
1119480093f4SDimitry Andric LLVMContext &Context,
1120480093f4SDimitry Andric std::function<void(Function &)> ProcessIRFunction) {
11210b57cec5SDimitry Andric auto Filename = Contents->getBufferIdentifier();
11220b57cec5SDimitry Andric if (Context.shouldDiscardValueNames()) {
11230b57cec5SDimitry Andric Context.diagnose(DiagnosticInfoMIRParser(
11240b57cec5SDimitry Andric DS_Error,
11250b57cec5SDimitry Andric SMDiagnostic(
11260b57cec5SDimitry Andric Filename, SourceMgr::DK_Error,
11270b57cec5SDimitry Andric "Can't read MIR with a Context that discards named Values")));
11280b57cec5SDimitry Andric return nullptr;
11290b57cec5SDimitry Andric }
1130480093f4SDimitry Andric return std::make_unique<MIRParser>(std::make_unique<MIRParserImpl>(
1131480093f4SDimitry Andric std::move(Contents), Filename, Context, ProcessIRFunction));
11320b57cec5SDimitry Andric }
1133