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