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