1 //===-- MBlazeAsmParser.cpp - Parse MBlaze asm to MCInst instructions -----===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 #include "MBlazeSubtarget.h"
12 #include "MBlazeRegisterInfo.h"
13 #include "MBlazeISelLowering.h"
14 #include "llvm/MC/MCParser/MCAsmLexer.h"
15 #include "llvm/MC/MCParser/MCAsmParser.h"
16 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
17 #include "llvm/MC/MCStreamer.h"
18 #include "llvm/MC/MCExpr.h"
19 #include "llvm/MC/MCInst.h"
20 #include "llvm/Target/TargetRegistry.h"
21 #include "llvm/Target/TargetAsmParser.h"
22 #include "llvm/Support/SourceMgr.h"
23 #include "llvm/Support/raw_ostream.h"
24 #include "llvm/ADT/OwningPtr.h"
25 #include "llvm/ADT/SmallVector.h"
26 #include "llvm/ADT/StringSwitch.h"
27 #include "llvm/ADT/Twine.h"
33 class MBlazeAsmParser : public TargetAsmParser {
37 MCAsmParser &getParser() const { return Parser; }
38 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
40 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
41 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
43 MBlazeOperand *ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
44 MBlazeOperand *ParseRegister(unsigned &RegNo);
45 MBlazeOperand *ParseImmediate();
46 MBlazeOperand *ParseFsl();
47 MBlazeOperand* ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
49 virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
51 bool ParseDirectiveWord(unsigned Size, SMLoc L);
53 bool MatchAndEmitInstruction(SMLoc IDLoc,
54 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
57 /// @name Auto-generated Match Functions
60 #define GET_ASSEMBLER_HEADER
61 #include "MBlazeGenAsmMatcher.inc"
67 MBlazeAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &_TM)
68 : TargetAsmParser(T), Parser(_Parser), TM(_TM) {}
70 virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
71 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
73 virtual bool ParseDirective(AsmToken DirectiveID);
76 /// MBlazeOperand - Instances of this class represent a parsed MBlaze machine
78 struct MBlazeOperand : public MCParsedAsmOperand {
87 SMLoc StartLoc, EndLoc;
114 MBlazeOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
116 MBlazeOperand(const MBlazeOperand &o) : MCParsedAsmOperand() {
118 StartLoc = o.StartLoc;
139 /// getStartLoc - Get the location of the first token of this operand.
140 SMLoc getStartLoc() const { return StartLoc; }
142 /// getEndLoc - Get the location of the last token of this operand.
143 SMLoc getEndLoc() const { return EndLoc; }
145 unsigned getReg() const {
146 assert(Kind == Register && "Invalid access!");
150 const MCExpr *getImm() const {
151 assert(Kind == Immediate && "Invalid access!");
155 const MCExpr *getFslImm() const {
156 assert(Kind == Fsl && "Invalid access!");
160 unsigned getMemBase() const {
161 assert(Kind == Memory && "Invalid access!");
165 const MCExpr* getMemOff() const {
166 assert(Kind == Memory && "Invalid access!");
170 unsigned getMemOffReg() const {
171 assert(Kind == Memory && "Invalid access!");
175 bool isToken() const { return Kind == Token; }
176 bool isImm() const { return Kind == Immediate; }
177 bool isMem() const { return Kind == Memory; }
178 bool isFsl() const { return Kind == Fsl; }
179 bool isReg() const { return Kind == Register; }
181 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
182 // Add as immediates when possible. Null MCExpr = 0.
184 Inst.addOperand(MCOperand::CreateImm(0));
185 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
186 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
188 Inst.addOperand(MCOperand::CreateExpr(Expr));
191 void addRegOperands(MCInst &Inst, unsigned N) const {
192 assert(N == 1 && "Invalid number of operands!");
193 Inst.addOperand(MCOperand::CreateReg(getReg()));
196 void addImmOperands(MCInst &Inst, unsigned N) const {
197 assert(N == 1 && "Invalid number of operands!");
198 addExpr(Inst, getImm());
201 void addFslOperands(MCInst &Inst, unsigned N) const {
202 assert(N == 1 && "Invalid number of operands!");
203 addExpr(Inst, getFslImm());
206 void addMemOperands(MCInst &Inst, unsigned N) const {
207 assert(N == 2 && "Invalid number of operands!");
209 Inst.addOperand(MCOperand::CreateReg(getMemBase()));
211 unsigned RegOff = getMemOffReg();
213 Inst.addOperand(MCOperand::CreateReg(RegOff));
215 addExpr(Inst, getMemOff());
218 StringRef getToken() const {
219 assert(Kind == Token && "Invalid access!");
220 return StringRef(Tok.Data, Tok.Length);
223 virtual void dump(raw_ostream &OS) const;
225 static MBlazeOperand *CreateToken(StringRef Str, SMLoc S) {
226 MBlazeOperand *Op = new MBlazeOperand(Token);
227 Op->Tok.Data = Str.data();
228 Op->Tok.Length = Str.size();
234 static MBlazeOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
235 MBlazeOperand *Op = new MBlazeOperand(Register);
236 Op->Reg.RegNum = RegNum;
242 static MBlazeOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
243 MBlazeOperand *Op = new MBlazeOperand(Immediate);
250 static MBlazeOperand *CreateFslImm(const MCExpr *Val, SMLoc S, SMLoc E) {
251 MBlazeOperand *Op = new MBlazeOperand(Fsl);
258 static MBlazeOperand *CreateMem(unsigned Base, const MCExpr *Off, SMLoc S,
260 MBlazeOperand *Op = new MBlazeOperand(Memory);
269 static MBlazeOperand *CreateMem(unsigned Base, unsigned Off, SMLoc S,
271 MBlazeOperand *Op = new MBlazeOperand(Memory);
273 Op->Mem.OffReg = Off;
281 } // end anonymous namespace.
283 void MBlazeOperand::dump(raw_ostream &OS) const {
290 OS << MBlazeRegisterInfo::getRegisterNumbering(getReg()) << ">";
293 OS << "'" << getToken() << "'";
297 OS << MBlazeRegisterInfo::getRegisterNumbering(getMemBase());
300 unsigned RegOff = getMemOffReg();
302 OS << "R" << MBlazeRegisterInfo::getRegisterNumbering(RegOff);
309 getFslImm()->print(OS);
314 /// @name Auto-generated Match Functions
317 static unsigned MatchRegisterName(StringRef Name);
321 bool MBlazeAsmParser::
322 MatchAndEmitInstruction(SMLoc IDLoc,
323 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
329 switch (MatchInstructionImpl(Operands, Inst, ErrorInfo)) {
331 Out.EmitInstruction(Inst);
333 case Match_MissingFeature:
334 return Error(IDLoc, "instruction use requires an option to be enabled");
335 case Match_MnemonicFail:
336 return Error(IDLoc, "unrecognized instruction mnemonic");
337 case Match_ConversionFail:
338 return Error(IDLoc, "unable to convert operands to instruction");
339 case Match_InvalidOperand:
341 if (ErrorInfo != ~0U) {
342 if (ErrorInfo >= Operands.size())
343 return Error(IDLoc, "too few operands for instruction");
345 ErrorLoc = ((MBlazeOperand*)Operands[ErrorInfo])->getStartLoc();
346 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
349 return Error(ErrorLoc, "invalid operand for instruction");
352 llvm_unreachable("Implement any new match types added!");
356 MBlazeOperand *MBlazeAsmParser::
357 ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
358 if (Operands.size() != 4)
361 MBlazeOperand &Base = *(MBlazeOperand*)Operands[2];
362 MBlazeOperand &Offset = *(MBlazeOperand*)Operands[3];
364 SMLoc S = Base.getStartLoc();
365 SMLoc O = Offset.getStartLoc();
366 SMLoc E = Offset.getEndLoc();
369 Error(S, "base address must be a register");
373 if (!Offset.isReg() && !Offset.isImm()) {
374 Error(O, "offset must be a register or immediate");
380 Op = MBlazeOperand::CreateMem(Base.getReg(), Offset.getReg(), S, E);
382 Op = MBlazeOperand::CreateMem(Base.getReg(), Offset.getImm(), S, E);
384 delete Operands.pop_back_val();
385 delete Operands.pop_back_val();
386 Operands.push_back(Op);
391 bool MBlazeAsmParser::ParseRegister(unsigned &RegNo,
392 SMLoc &StartLoc, SMLoc &EndLoc) {
393 return (ParseRegister(RegNo) == 0);
396 MBlazeOperand *MBlazeAsmParser::ParseRegister(unsigned &RegNo) {
397 SMLoc S = Parser.getTok().getLoc();
398 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
400 switch (getLexer().getKind()) {
402 case AsmToken::Identifier:
403 RegNo = MatchRegisterName(getLexer().getTok().getIdentifier());
408 return MBlazeOperand::CreateReg(RegNo, S, E);
412 static unsigned MatchFslRegister(StringRef String) {
413 if (!String.startswith("rfsl"))
417 if (String.substr(4).getAsInteger(10,regNum))
423 MBlazeOperand *MBlazeAsmParser::ParseFsl() {
424 SMLoc S = Parser.getTok().getLoc();
425 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
427 switch (getLexer().getKind()) {
429 case AsmToken::Identifier:
430 unsigned reg = MatchFslRegister(getLexer().getTok().getIdentifier());
435 const MCExpr *EVal = MCConstantExpr::Create(reg,getContext());
436 return MBlazeOperand::CreateFslImm(EVal,S,E);
440 MBlazeOperand *MBlazeAsmParser::ParseImmediate() {
441 SMLoc S = Parser.getTok().getLoc();
442 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
445 switch (getLexer().getKind()) {
447 case AsmToken::LParen:
449 case AsmToken::Minus:
450 case AsmToken::Integer:
451 case AsmToken::Identifier:
452 if (getParser().ParseExpression(EVal))
455 return MBlazeOperand::CreateImm(EVal, S, E);
459 MBlazeOperand *MBlazeAsmParser::
460 ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
463 // Attempt to parse the next token as a register name
465 Op = ParseRegister(RegNo);
467 // Attempt to parse the next token as an FSL immediate
471 // Attempt to parse the next token as an immediate
473 Op = ParseImmediate();
475 // If the token could not be parsed then fail
477 Error(Parser.getTok().getLoc(), "unknown operand");
481 // Push the parsed operand into the list of operands
482 Operands.push_back(Op);
486 /// Parse an mblaze instruction mnemonic followed by its operands.
487 bool MBlazeAsmParser::
488 ParseInstruction(StringRef Name, SMLoc NameLoc,
489 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
490 // The first operands is the token for the instruction name
491 size_t dotLoc = Name.find('.');
492 Operands.push_back(MBlazeOperand::CreateToken(Name.substr(0,dotLoc),NameLoc));
493 if (dotLoc < Name.size())
494 Operands.push_back(MBlazeOperand::CreateToken(Name.substr(dotLoc),NameLoc));
496 // If there are no more operands then finish
497 if (getLexer().is(AsmToken::EndOfStatement))
500 // Parse the first operand
501 if (!ParseOperand(Operands))
504 while (getLexer().isNot(AsmToken::EndOfStatement) &&
505 getLexer().is(AsmToken::Comma)) {
506 // Consume the comma token
509 // Parse the next operand
510 if (!ParseOperand(Operands))
514 // If the instruction requires a memory operand then we need to
515 // replace the last two operands (base+offset) with a single
517 if (Name.startswith("lw") || Name.startswith("sw") ||
518 Name.startswith("lh") || Name.startswith("sh") ||
519 Name.startswith("lb") || Name.startswith("sb"))
520 return (ParseMemory(Operands) == NULL);
525 /// ParseDirective parses the arm specific directives
526 bool MBlazeAsmParser::ParseDirective(AsmToken DirectiveID) {
527 StringRef IDVal = DirectiveID.getIdentifier();
528 if (IDVal == ".word")
529 return ParseDirectiveWord(2, DirectiveID.getLoc());
533 /// ParseDirectiveWord
534 /// ::= .word [ expression (, expression)* ]
535 bool MBlazeAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
536 if (getLexer().isNot(AsmToken::EndOfStatement)) {
539 if (getParser().ParseExpression(Value))
542 getParser().getStreamer().EmitValue(Value, Size, 0 /*addrspace*/);
544 if (getLexer().is(AsmToken::EndOfStatement))
547 // FIXME: Improve diagnostic.
548 if (getLexer().isNot(AsmToken::Comma))
549 return Error(L, "unexpected token in directive");
558 extern "C" void LLVMInitializeMBlazeAsmLexer();
560 /// Force static initialization.
561 extern "C" void LLVMInitializeMBlazeAsmParser() {
562 RegisterAsmParser<MBlazeAsmParser> X(TheMBlazeTarget);
563 LLVMInitializeMBlazeAsmLexer();
566 #define GET_REGISTER_MATCHER
567 #define GET_MATCHER_IMPLEMENTATION
568 #include "MBlazeGenAsmMatcher.inc"