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