blob: 9427de4f015503c968053717bbf630bdc2b28c09 [file] [log] [blame]
Alex Lorenz8e0a1b42015-06-22 17:02:30 +00001//===- MIParser.cpp - Machine instructions parser implementation ----------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the parsing of machine instructions.
11//
12//===----------------------------------------------------------------------===//
13
14#include "MIParser.h"
15#include "llvm/ADT/StringMap.h"
16#include "llvm/CodeGen/MachineBasicBlock.h"
17#include "llvm/CodeGen/MachineFunction.h"
18#include "llvm/CodeGen/MachineInstr.h"
19#include "llvm/Support/raw_ostream.h"
20#include "llvm/Support/SourceMgr.h"
21#include "llvm/Target/TargetSubtargetInfo.h"
22#include "llvm/Target/TargetInstrInfo.h"
23
24using namespace llvm;
25
26namespace {
27
28class MIParser {
29 SourceMgr &SM;
30 MachineFunction &MF;
31 SMDiagnostic &Error;
32 StringRef Source;
33 /// Maps from instruction names to op codes.
34 StringMap<unsigned> Names2InstrOpCodes;
35
36public:
37 MIParser(SourceMgr &SM, MachineFunction &MF, SMDiagnostic &Error,
38 StringRef Source);
39
40 /// Report an error at the current location with the given message.
41 ///
42 /// This function always return true.
43 bool error(const Twine &Msg);
44
45 MachineInstr *parse();
46
47private:
48 void initNames2InstrOpCodes();
49
50 /// Try to convert an instruction name to an opcode. Return true if the
51 /// instruction name is invalid.
52 bool parseInstrName(StringRef InstrName, unsigned &OpCode);
53};
54
55} // end anonymous namespace
56
57MIParser::MIParser(SourceMgr &SM, MachineFunction &MF, SMDiagnostic &Error,
58 StringRef Source)
59 : SM(SM), MF(MF), Error(Error), Source(Source) {}
60
61bool MIParser::error(const Twine &Msg) {
62 // TODO: Get the proper location in the MIR file, not just a location inside
63 // the string.
64 Error =
65 SMDiagnostic(SM, SMLoc(), SM.getMemoryBuffer(SM.getMainFileID())
66 ->getBufferIdentifier(),
67 1, 0, SourceMgr::DK_Error, Msg.str(), Source, None, None);
68 return true;
69}
70
71MachineInstr *MIParser::parse() {
72 StringRef InstrName = Source;
73 unsigned OpCode;
74 if (parseInstrName(InstrName, OpCode)) {
75 error(Twine("unknown machine instruction name '") + InstrName + "'");
76 return nullptr;
77 }
78
79 // TODO: Parse the rest of instruction - machine operands, etc.
80 const auto &MCID = MF.getSubtarget().getInstrInfo()->get(OpCode);
81 auto *MI = MF.CreateMachineInstr(MCID, DebugLoc());
82 return MI;
83}
84
85void MIParser::initNames2InstrOpCodes() {
86 if (!Names2InstrOpCodes.empty())
87 return;
88 const auto *TII = MF.getSubtarget().getInstrInfo();
89 assert(TII && "Expected target instruction info");
90 for (unsigned I = 0, E = TII->getNumOpcodes(); I < E; ++I)
91 Names2InstrOpCodes.insert(std::make_pair(StringRef(TII->getName(I)), I));
92}
93
94bool MIParser::parseInstrName(StringRef InstrName, unsigned &OpCode) {
95 initNames2InstrOpCodes();
96 auto InstrInfo = Names2InstrOpCodes.find(InstrName);
97 if (InstrInfo == Names2InstrOpCodes.end())
98 return true;
99 OpCode = InstrInfo->getValue();
100 return false;
101}
102
103MachineInstr *llvm::parseMachineInstr(SourceMgr &SM, MachineFunction &MF,
104 StringRef Src, SMDiagnostic &Error) {
105 return MIParser(SM, MF, Error, Src).parse();
106}