mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-31 08:16:47 +00:00 
			
		
		
		
	This commit adds a function that tokenizes the string containing the machine instruction. This commit also adds a struct called 'MIToken' which is used to represent the lexer's tokens. Reviewers: Sean Silva Differential Revision: http://reviews.llvm.org/D10521 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@240323 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			136 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			136 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| //===- MIParser.cpp - Machine instructions parser implementation ----------===//
 | |
| //
 | |
| //                     The LLVM Compiler Infrastructure
 | |
| //
 | |
| // This file is distributed under the University of Illinois Open Source
 | |
| // License. See LICENSE.TXT for details.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| //
 | |
| // This file implements the parsing of machine instructions.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #include "MIParser.h"
 | |
| #include "MILexer.h"
 | |
| #include "llvm/ADT/StringMap.h"
 | |
| #include "llvm/CodeGen/MachineBasicBlock.h"
 | |
| #include "llvm/CodeGen/MachineFunction.h"
 | |
| #include "llvm/CodeGen/MachineInstr.h"
 | |
| #include "llvm/Support/raw_ostream.h"
 | |
| #include "llvm/Support/SourceMgr.h"
 | |
| #include "llvm/Target/TargetSubtargetInfo.h"
 | |
| #include "llvm/Target/TargetInstrInfo.h"
 | |
| 
 | |
| using namespace llvm;
 | |
| 
 | |
| namespace {
 | |
| 
 | |
| class MIParser {
 | |
|   SourceMgr &SM;
 | |
|   MachineFunction &MF;
 | |
|   SMDiagnostic &Error;
 | |
|   StringRef Source, CurrentSource;
 | |
|   MIToken Token;
 | |
|   /// Maps from instruction names to op codes.
 | |
|   StringMap<unsigned> Names2InstrOpCodes;
 | |
| 
 | |
| public:
 | |
|   MIParser(SourceMgr &SM, MachineFunction &MF, SMDiagnostic &Error,
 | |
|            StringRef Source);
 | |
| 
 | |
|   void lex();
 | |
| 
 | |
|   /// Report an error at the current location with the given message.
 | |
|   ///
 | |
|   /// This function always return true.
 | |
|   bool error(const Twine &Msg);
 | |
| 
 | |
|   /// Report an error at the given location with the given message.
 | |
|   ///
 | |
|   /// This function always return true.
 | |
|   bool error(StringRef::iterator Loc, const Twine &Msg);
 | |
| 
 | |
|   MachineInstr *parse();
 | |
| 
 | |
| private:
 | |
|   void initNames2InstrOpCodes();
 | |
| 
 | |
|   /// Try to convert an instruction name to an opcode. Return true if the
 | |
|   /// instruction name is invalid.
 | |
|   bool parseInstrName(StringRef InstrName, unsigned &OpCode);
 | |
| 
 | |
|   bool parseInstruction(unsigned &OpCode);
 | |
| };
 | |
| 
 | |
| } // end anonymous namespace
 | |
| 
 | |
| MIParser::MIParser(SourceMgr &SM, MachineFunction &MF, SMDiagnostic &Error,
 | |
|                    StringRef Source)
 | |
|     : SM(SM), MF(MF), Error(Error), Source(Source), CurrentSource(Source),
 | |
|       Token(MIToken::Error, StringRef()) {}
 | |
| 
 | |
| void MIParser::lex() {
 | |
|   CurrentSource = lexMIToken(
 | |
|       CurrentSource, Token,
 | |
|       [this](StringRef::iterator Loc, const Twine &Msg) { error(Loc, Msg); });
 | |
| }
 | |
| 
 | |
| bool MIParser::error(const Twine &Msg) { return error(Token.location(), Msg); }
 | |
| 
 | |
| bool MIParser::error(StringRef::iterator Loc, const Twine &Msg) {
 | |
|   // TODO: Get the proper location in the MIR file, not just a location inside
 | |
|   // the string.
 | |
|   assert(Loc >= Source.data() && Loc <= (Source.data() + Source.size()));
 | |
|   Error = SMDiagnostic(
 | |
|       SM, SMLoc(),
 | |
|       SM.getMemoryBuffer(SM.getMainFileID())->getBufferIdentifier(), 1,
 | |
|       Loc - Source.data(), SourceMgr::DK_Error, Msg.str(), Source, None, None);
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| MachineInstr *MIParser::parse() {
 | |
|   lex();
 | |
| 
 | |
|   unsigned OpCode;
 | |
|   if (Token.isError() || parseInstruction(OpCode))
 | |
|     return nullptr;
 | |
| 
 | |
|   // TODO: Parse the rest of instruction - machine operands, etc.
 | |
|   const auto &MCID = MF.getSubtarget().getInstrInfo()->get(OpCode);
 | |
|   auto *MI = MF.CreateMachineInstr(MCID, DebugLoc());
 | |
|   return MI;
 | |
| }
 | |
| 
 | |
| bool MIParser::parseInstruction(unsigned &OpCode) {
 | |
|   if (Token.isNot(MIToken::Identifier))
 | |
|     return error("expected a machine instruction");
 | |
|   StringRef InstrName = Token.stringValue();
 | |
|   if (parseInstrName(InstrName, OpCode))
 | |
|     return error(Twine("unknown machine instruction name '") + InstrName + "'");
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| void MIParser::initNames2InstrOpCodes() {
 | |
|   if (!Names2InstrOpCodes.empty())
 | |
|     return;
 | |
|   const auto *TII = MF.getSubtarget().getInstrInfo();
 | |
|   assert(TII && "Expected target instruction info");
 | |
|   for (unsigned I = 0, E = TII->getNumOpcodes(); I < E; ++I)
 | |
|     Names2InstrOpCodes.insert(std::make_pair(StringRef(TII->getName(I)), I));
 | |
| }
 | |
| 
 | |
| bool MIParser::parseInstrName(StringRef InstrName, unsigned &OpCode) {
 | |
|   initNames2InstrOpCodes();
 | |
|   auto InstrInfo = Names2InstrOpCodes.find(InstrName);
 | |
|   if (InstrInfo == Names2InstrOpCodes.end())
 | |
|     return true;
 | |
|   OpCode = InstrInfo->getValue();
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| MachineInstr *llvm::parseMachineInstr(SourceMgr &SM, MachineFunction &MF,
 | |
|                                       StringRef Src, SMDiagnostic &Error) {
 | |
|   return MIParser(SM, MF, Error, Src).parse();
 | |
| }
 |