MBlazeAsmParser.cpp revision 249423
1//===-- MBlazeAsmParser.cpp - Parse MBlaze asm to MCInst instructions -----===// 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#include "MCTargetDesc/MBlazeBaseInfo.h" 11#include "llvm/ADT/SmallVector.h" 12#include "llvm/ADT/Twine.h" 13#include "llvm/MC/MCExpr.h" 14#include "llvm/MC/MCInst.h" 15#include "llvm/MC/MCParser/MCAsmLexer.h" 16#include "llvm/MC/MCParser/MCAsmParser.h" 17#include "llvm/MC/MCParser/MCParsedAsmOperand.h" 18#include "llvm/MC/MCStreamer.h" 19#include "llvm/MC/MCTargetAsmParser.h" 20#include "llvm/Support/SourceMgr.h" 21#include "llvm/Support/TargetRegistry.h" 22#include "llvm/Support/raw_ostream.h" 23using namespace llvm; 24 25namespace { 26struct MBlazeOperand; 27 28class MBlazeAsmParser : public MCTargetAsmParser { 29 MCAsmParser &Parser; 30 31 MCAsmParser &getParser() const { return Parser; } 32 MCAsmLexer &getLexer() const { return Parser.getLexer(); } 33 34 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); } 35 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); } 36 37 MBlazeOperand *ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands); 38 MBlazeOperand *ParseRegister(); 39 MBlazeOperand *ParseRegister(SMLoc &StartLoc, SMLoc &EndLoc); 40 MBlazeOperand *ParseImmediate(); 41 MBlazeOperand *ParseFsl(); 42 MBlazeOperand* ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands); 43 44 virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc); 45 46 bool ParseDirectiveWord(unsigned Size, SMLoc L); 47 48 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 49 SmallVectorImpl<MCParsedAsmOperand*> &Operands, 50 MCStreamer &Out, unsigned &ErrorInfo, 51 bool MatchingInlineAsm); 52 53 /// @name Auto-generated Match Functions 54 /// { 55 56#define GET_ASSEMBLER_HEADER 57#include "MBlazeGenAsmMatcher.inc" 58 59 /// } 60 61public: 62 MBlazeAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser) 63 : MCTargetAsmParser(), Parser(_Parser) {} 64 65 virtual bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, 66 SMLoc NameLoc, 67 SmallVectorImpl<MCParsedAsmOperand*> &Operands); 68 69 virtual bool ParseDirective(AsmToken DirectiveID); 70}; 71 72/// MBlazeOperand - Instances of this class represent a parsed MBlaze machine 73/// instruction. 74struct MBlazeOperand : public MCParsedAsmOperand { 75 enum KindTy { 76 Token, 77 Immediate, 78 Register, 79 Memory, 80 Fsl 81 } Kind; 82 83 SMLoc StartLoc, EndLoc; 84 85 struct TokOp { 86 const char *Data; 87 unsigned Length; 88 }; 89 90 struct RegOp { 91 unsigned RegNum; 92 }; 93 94 struct ImmOp { 95 const MCExpr *Val; 96 }; 97 98 struct MemOp { 99 unsigned Base; 100 unsigned OffReg; 101 const MCExpr *Off; 102 }; 103 104 struct FslImmOp { 105 const MCExpr *Val; 106 }; 107 108 union { 109 struct TokOp Tok; 110 struct RegOp Reg; 111 struct ImmOp Imm; 112 struct MemOp Mem; 113 struct FslImmOp FslImm; 114 }; 115 116 MBlazeOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {} 117public: 118 MBlazeOperand(const MBlazeOperand &o) : MCParsedAsmOperand() { 119 Kind = o.Kind; 120 StartLoc = o.StartLoc; 121 EndLoc = o.EndLoc; 122 switch (Kind) { 123 case Register: 124 Reg = o.Reg; 125 break; 126 case Immediate: 127 Imm = o.Imm; 128 break; 129 case Token: 130 Tok = o.Tok; 131 break; 132 case Memory: 133 Mem = o.Mem; 134 break; 135 case Fsl: 136 FslImm = o.FslImm; 137 break; 138 } 139 } 140 141 /// getStartLoc - Get the location of the first token of this operand. 142 SMLoc getStartLoc() const { return StartLoc; } 143 144 /// getEndLoc - Get the location of the last token of this operand. 145 SMLoc getEndLoc() const { return EndLoc; } 146 147 unsigned getReg() const { 148 assert(Kind == Register && "Invalid access!"); 149 return Reg.RegNum; 150 } 151 152 const MCExpr *getImm() const { 153 assert(Kind == Immediate && "Invalid access!"); 154 return Imm.Val; 155 } 156 157 const MCExpr *getFslImm() const { 158 assert(Kind == Fsl && "Invalid access!"); 159 return FslImm.Val; 160 } 161 162 unsigned getMemBase() const { 163 assert(Kind == Memory && "Invalid access!"); 164 return Mem.Base; 165 } 166 167 const MCExpr* getMemOff() const { 168 assert(Kind == Memory && "Invalid access!"); 169 return Mem.Off; 170 } 171 172 unsigned getMemOffReg() const { 173 assert(Kind == Memory && "Invalid access!"); 174 return Mem.OffReg; 175 } 176 177 bool isToken() const { return Kind == Token; } 178 bool isImm() const { return Kind == Immediate; } 179 bool isMem() const { return Kind == Memory; } 180 bool isFsl() const { return Kind == Fsl; } 181 bool isReg() const { return Kind == Register; } 182 183 void addExpr(MCInst &Inst, const MCExpr *Expr) const { 184 // Add as immediates when possible. Null MCExpr = 0. 185 if (Expr == 0) 186 Inst.addOperand(MCOperand::CreateImm(0)); 187 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr)) 188 Inst.addOperand(MCOperand::CreateImm(CE->getValue())); 189 else 190 Inst.addOperand(MCOperand::CreateExpr(Expr)); 191 } 192 193 void addRegOperands(MCInst &Inst, unsigned N) const { 194 assert(N == 1 && "Invalid number of operands!"); 195 Inst.addOperand(MCOperand::CreateReg(getReg())); 196 } 197 198 void addImmOperands(MCInst &Inst, unsigned N) const { 199 assert(N == 1 && "Invalid number of operands!"); 200 addExpr(Inst, getImm()); 201 } 202 203 void addFslOperands(MCInst &Inst, unsigned N) const { 204 assert(N == 1 && "Invalid number of operands!"); 205 addExpr(Inst, getFslImm()); 206 } 207 208 void addMemOperands(MCInst &Inst, unsigned N) const { 209 assert(N == 2 && "Invalid number of operands!"); 210 211 Inst.addOperand(MCOperand::CreateReg(getMemBase())); 212 213 unsigned RegOff = getMemOffReg(); 214 if (RegOff) 215 Inst.addOperand(MCOperand::CreateReg(RegOff)); 216 else 217 addExpr(Inst, getMemOff()); 218 } 219 220 StringRef getToken() const { 221 assert(Kind == Token && "Invalid access!"); 222 return StringRef(Tok.Data, Tok.Length); 223 } 224 225 virtual void print(raw_ostream &OS) const; 226 227 static MBlazeOperand *CreateToken(StringRef Str, SMLoc S) { 228 MBlazeOperand *Op = new MBlazeOperand(Token); 229 Op->Tok.Data = Str.data(); 230 Op->Tok.Length = Str.size(); 231 Op->StartLoc = S; 232 Op->EndLoc = S; 233 return Op; 234 } 235 236 static MBlazeOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) { 237 MBlazeOperand *Op = new MBlazeOperand(Register); 238 Op->Reg.RegNum = RegNum; 239 Op->StartLoc = S; 240 Op->EndLoc = E; 241 return Op; 242 } 243 244 static MBlazeOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) { 245 MBlazeOperand *Op = new MBlazeOperand(Immediate); 246 Op->Imm.Val = Val; 247 Op->StartLoc = S; 248 Op->EndLoc = E; 249 return Op; 250 } 251 252 static MBlazeOperand *CreateFslImm(const MCExpr *Val, SMLoc S, SMLoc E) { 253 MBlazeOperand *Op = new MBlazeOperand(Fsl); 254 Op->Imm.Val = Val; 255 Op->StartLoc = S; 256 Op->EndLoc = E; 257 return Op; 258 } 259 260 static MBlazeOperand *CreateMem(unsigned Base, const MCExpr *Off, SMLoc S, 261 SMLoc E) { 262 MBlazeOperand *Op = new MBlazeOperand(Memory); 263 Op->Mem.Base = Base; 264 Op->Mem.Off = Off; 265 Op->Mem.OffReg = 0; 266 Op->StartLoc = S; 267 Op->EndLoc = E; 268 return Op; 269 } 270 271 static MBlazeOperand *CreateMem(unsigned Base, unsigned Off, SMLoc S, 272 SMLoc E) { 273 MBlazeOperand *Op = new MBlazeOperand(Memory); 274 Op->Mem.Base = Base; 275 Op->Mem.OffReg = Off; 276 Op->Mem.Off = 0; 277 Op->StartLoc = S; 278 Op->EndLoc = E; 279 return Op; 280 } 281}; 282 283} // end anonymous namespace. 284 285void MBlazeOperand::print(raw_ostream &OS) const { 286 switch (Kind) { 287 case Immediate: 288 getImm()->print(OS); 289 break; 290 case Register: 291 OS << "<register R"; 292 OS << getMBlazeRegisterNumbering(getReg()) << ">"; 293 break; 294 case Token: 295 OS << "'" << getToken() << "'"; 296 break; 297 case Memory: { 298 OS << "<memory R"; 299 OS << getMBlazeRegisterNumbering(getMemBase()); 300 OS << ", "; 301 302 unsigned RegOff = getMemOffReg(); 303 if (RegOff) 304 OS << "R" << getMBlazeRegisterNumbering(RegOff); 305 else 306 OS << getMemOff(); 307 OS << ">"; 308 } 309 break; 310 case Fsl: 311 getFslImm()->print(OS); 312 break; 313 } 314} 315 316/// @name Auto-generated Match Functions 317/// { 318 319static unsigned MatchRegisterName(StringRef Name); 320 321/// } 322// 323bool MBlazeAsmParser:: 324MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 325 SmallVectorImpl<MCParsedAsmOperand*> &Operands, 326 MCStreamer &Out, unsigned &ErrorInfo, 327 bool MatchingInlineAsm) { 328 MCInst Inst; 329 switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, 330 MatchingInlineAsm)) { 331 default: break; 332 case Match_Success: 333 Out.EmitInstruction(Inst); 334 return false; 335 case Match_MissingFeature: 336 return Error(IDLoc, "instruction use requires an option to be enabled"); 337 case Match_MnemonicFail: 338 return Error(IDLoc, "unrecognized instruction mnemonic"); 339 case Match_InvalidOperand: { 340 SMLoc ErrorLoc = IDLoc; 341 if (ErrorInfo != ~0U) { 342 if (ErrorInfo >= Operands.size()) 343 return Error(IDLoc, "too few operands for instruction"); 344 345 ErrorLoc = ((MBlazeOperand*)Operands[ErrorInfo])->getStartLoc(); 346 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc; 347 } 348 349 return Error(ErrorLoc, "invalid operand for instruction"); 350 } 351 } 352 353 llvm_unreachable("Implement any new match types added!"); 354} 355 356MBlazeOperand *MBlazeAsmParser:: 357ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 358 if (Operands.size() != 4) 359 return 0; 360 361 MBlazeOperand &Base = *(MBlazeOperand*)Operands[2]; 362 MBlazeOperand &Offset = *(MBlazeOperand*)Operands[3]; 363 364 SMLoc S = Base.getStartLoc(); 365 SMLoc O = Offset.getStartLoc(); 366 SMLoc E = Offset.getEndLoc(); 367 368 if (!Base.isReg()) { 369 Error(S, "base address must be a register"); 370 return 0; 371 } 372 373 if (!Offset.isReg() && !Offset.isImm()) { 374 Error(O, "offset must be a register or immediate"); 375 return 0; 376 } 377 378 MBlazeOperand *Op; 379 if (Offset.isReg()) 380 Op = MBlazeOperand::CreateMem(Base.getReg(), Offset.getReg(), S, E); 381 else 382 Op = MBlazeOperand::CreateMem(Base.getReg(), Offset.getImm(), S, E); 383 384 delete Operands.pop_back_val(); 385 delete Operands.pop_back_val(); 386 Operands.push_back(Op); 387 388 return Op; 389} 390 391bool MBlazeAsmParser::ParseRegister(unsigned &RegNo, 392 SMLoc &StartLoc, SMLoc &EndLoc) { 393 MBlazeOperand *Reg = ParseRegister(StartLoc, EndLoc); 394 if (!Reg) 395 return true; 396 RegNo = Reg->getReg(); 397 return false; 398} 399 400MBlazeOperand *MBlazeAsmParser::ParseRegister() { 401 SMLoc S, E; 402 return ParseRegister(S, E); 403} 404 405MBlazeOperand *MBlazeAsmParser::ParseRegister(SMLoc &StartLoc, SMLoc &EndLoc) { 406 StartLoc = Parser.getTok().getLoc(); 407 EndLoc = Parser.getTok().getEndLoc(); 408 409 if (getLexer().getKind() != AsmToken::Identifier) 410 return 0; 411 412 unsigned RegNo = MatchRegisterName(getLexer().getTok().getIdentifier()); 413 if (RegNo == 0) 414 return 0; 415 416 getLexer().Lex(); 417 return MBlazeOperand::CreateReg(RegNo, StartLoc, EndLoc); 418} 419 420static unsigned MatchFslRegister(StringRef String) { 421 if (!String.startswith("rfsl")) 422 return -1; 423 424 unsigned regNum; 425 if (String.substr(4).getAsInteger(10,regNum)) 426 return -1; 427 428 return regNum; 429} 430 431MBlazeOperand *MBlazeAsmParser::ParseFsl() { 432 SMLoc S = Parser.getTok().getLoc(); 433 SMLoc E = Parser.getTok().getEndLoc(); 434 435 switch (getLexer().getKind()) { 436 default: return 0; 437 case AsmToken::Identifier: 438 unsigned reg = MatchFslRegister(getLexer().getTok().getIdentifier()); 439 if (reg >= 16) 440 return 0; 441 442 getLexer().Lex(); 443 const MCExpr *EVal = MCConstantExpr::Create(reg,getContext()); 444 return MBlazeOperand::CreateFslImm(EVal,S,E); 445 } 446} 447 448MBlazeOperand *MBlazeAsmParser::ParseImmediate() { 449 SMLoc S = Parser.getTok().getLoc(); 450 SMLoc E = Parser.getTok().getEndLoc(); 451 452 const MCExpr *EVal; 453 switch (getLexer().getKind()) { 454 default: return 0; 455 case AsmToken::LParen: 456 case AsmToken::Plus: 457 case AsmToken::Minus: 458 case AsmToken::Integer: 459 case AsmToken::Identifier: 460 if (getParser().parseExpression(EVal)) 461 return 0; 462 463 return MBlazeOperand::CreateImm(EVal, S, E); 464 } 465} 466 467MBlazeOperand *MBlazeAsmParser:: 468ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 469 MBlazeOperand *Op; 470 471 // Attempt to parse the next token as a register name 472 Op = ParseRegister(); 473 474 // Attempt to parse the next token as an FSL immediate 475 if (!Op) 476 Op = ParseFsl(); 477 478 // Attempt to parse the next token as an immediate 479 if (!Op) 480 Op = ParseImmediate(); 481 482 // If the token could not be parsed then fail 483 if (!Op) { 484 Error(Parser.getTok().getLoc(), "unknown operand"); 485 return 0; 486 } 487 488 // Push the parsed operand into the list of operands 489 Operands.push_back(Op); 490 return Op; 491} 492 493/// Parse an mblaze instruction mnemonic followed by its operands. 494bool MBlazeAsmParser:: 495ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, 496 SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 497 // The first operands is the token for the instruction name 498 size_t dotLoc = Name.find('.'); 499 Operands.push_back(MBlazeOperand::CreateToken(Name.substr(0,dotLoc),NameLoc)); 500 if (dotLoc < Name.size()) 501 Operands.push_back(MBlazeOperand::CreateToken(Name.substr(dotLoc),NameLoc)); 502 503 // If there are no more operands then finish 504 if (getLexer().is(AsmToken::EndOfStatement)) 505 return false; 506 507 // Parse the first operand 508 if (!ParseOperand(Operands)) 509 return true; 510 511 while (getLexer().isNot(AsmToken::EndOfStatement) && 512 getLexer().is(AsmToken::Comma)) { 513 // Consume the comma token 514 getLexer().Lex(); 515 516 // Parse the next operand 517 if (!ParseOperand(Operands)) 518 return true; 519 } 520 521 // If the instruction requires a memory operand then we need to 522 // replace the last two operands (base+offset) with a single 523 // memory operand. 524 if (Name.startswith("lw") || Name.startswith("sw") || 525 Name.startswith("lh") || Name.startswith("sh") || 526 Name.startswith("lb") || Name.startswith("sb")) 527 return (ParseMemory(Operands) == NULL); 528 529 return false; 530} 531 532/// ParseDirective parses the MBlaze specific directives 533bool MBlazeAsmParser::ParseDirective(AsmToken DirectiveID) { 534 StringRef IDVal = DirectiveID.getIdentifier(); 535 if (IDVal == ".word") 536 return ParseDirectiveWord(2, DirectiveID.getLoc()); 537 return true; 538} 539 540/// ParseDirectiveWord 541/// ::= .word [ expression (, expression)* ] 542bool MBlazeAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) { 543 if (getLexer().isNot(AsmToken::EndOfStatement)) { 544 for (;;) { 545 const MCExpr *Value; 546 if (getParser().parseExpression(Value)) 547 return true; 548 549 getParser().getStreamer().EmitValue(Value, Size); 550 551 if (getLexer().is(AsmToken::EndOfStatement)) 552 break; 553 554 // FIXME: Improve diagnostic. 555 if (getLexer().isNot(AsmToken::Comma)) 556 return Error(L, "unexpected token in directive"); 557 Parser.Lex(); 558 } 559 } 560 561 Parser.Lex(); 562 return false; 563} 564 565/// Force static initialization. 566extern "C" void LLVMInitializeMBlazeAsmParser() { 567 RegisterMCAsmParser<MBlazeAsmParser> X(TheMBlazeTarget); 568} 569 570#define GET_REGISTER_MATCHER 571#define GET_MATCHER_IMPLEMENTATION 572#include "MBlazeGenAsmMatcher.inc" 573