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