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