1 //===- XtensaAsmParser.cpp - Parse Xtensa assembly to MCInst instructions -===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 6 // See https://llvm.org/LICENSE.txt for license information. 7 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 8 // 9 //===----------------------------------------------------------------------===// 10 11 #include "MCTargetDesc/XtensaMCTargetDesc.h" 12 #include "TargetInfo/XtensaTargetInfo.h" 13 #include "llvm/ADT/STLExtras.h" 14 #include "llvm/ADT/StringSwitch.h" 15 #include "llvm/MC/MCContext.h" 16 #include "llvm/MC/MCExpr.h" 17 #include "llvm/MC/MCInst.h" 18 #include "llvm/MC/MCInstrInfo.h" 19 #include "llvm/MC/MCParser/MCAsmLexer.h" 20 #include "llvm/MC/MCParser/MCParsedAsmOperand.h" 21 #include "llvm/MC/MCParser/MCTargetAsmParser.h" 22 #include "llvm/MC/MCRegisterInfo.h" 23 #include "llvm/MC/MCStreamer.h" 24 #include "llvm/MC/MCSubtargetInfo.h" 25 #include "llvm/MC/TargetRegistry.h" 26 #include "llvm/Support/Casting.h" 27 28 using namespace llvm; 29 30 #define DEBUG_TYPE "xtensa-asm-parser" 31 32 struct XtensaOperand; 33 34 class XtensaAsmParser : public MCTargetAsmParser { 35 36 SMLoc getLoc() const { return getParser().getTok().getLoc(); } 37 38 bool parseRegister(MCRegister &RegNo, 39 SMLoc &StartLoc, SMLoc &EndLoc) override; 40 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, 41 SMLoc NameLoc, OperandVector &Operands) override; 42 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 43 OperandVector &Operands, MCStreamer &Out, 44 uint64_t &ErrorInfo, 45 bool MatchingInlineAsm) override; 46 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, 47 unsigned Kind) override; 48 49 // Auto-generated instruction matching functions 50 #define GET_ASSEMBLER_HEADER 51 #include "XtensaGenAsmMatcher.inc" 52 53 OperandMatchResultTy parseImmediate(OperandVector &Operands); 54 OperandMatchResultTy parseRegister(OperandVector &Operands, 55 bool AllowParens = false, bool SR = false); 56 OperandMatchResultTy parseOperandWithModifier(OperandVector &Operands); 57 bool parseOperand(OperandVector &Operands, StringRef Mnemonic, 58 bool SR = false); 59 bool ParseInstructionWithSR(ParseInstructionInfo &Info, StringRef Name, 60 SMLoc NameLoc, OperandVector &Operands); 61 OperandMatchResultTy tryParseRegister(MCRegister &RegNo, SMLoc &StartLoc, 62 SMLoc &EndLoc) override { 63 return MatchOperand_NoMatch; 64 } 65 OperandMatchResultTy parsePCRelTarget(OperandVector &Operands); 66 67 public: 68 enum XtensaMatchResultTy { 69 Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY, 70 #define GET_OPERAND_DIAGNOSTIC_TYPES 71 #include "XtensaGenAsmMatcher.inc" 72 #undef GET_OPERAND_DIAGNOSTIC_TYPES 73 }; 74 75 XtensaAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser, 76 const MCInstrInfo &MII, const MCTargetOptions &Options) 77 : MCTargetAsmParser(Options, STI, MII) { 78 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); 79 } 80 }; 81 82 // Return true if Expr is in the range [MinValue, MaxValue]. 83 static bool inRange(const MCExpr *Expr, int64_t MinValue, int64_t MaxValue) { 84 if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) { 85 int64_t Value = CE->getValue(); 86 return Value >= MinValue && Value <= MaxValue; 87 } 88 return false; 89 } 90 91 struct XtensaOperand : public MCParsedAsmOperand { 92 93 enum KindTy { 94 Token, 95 Register, 96 Immediate, 97 } Kind; 98 99 struct RegOp { 100 unsigned RegNum; 101 }; 102 103 struct ImmOp { 104 const MCExpr *Val; 105 }; 106 107 SMLoc StartLoc, EndLoc; 108 union { 109 StringRef Tok; 110 RegOp Reg; 111 ImmOp Imm; 112 }; 113 114 XtensaOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {} 115 116 public: 117 XtensaOperand(const XtensaOperand &o) : MCParsedAsmOperand() { 118 Kind = o.Kind; 119 StartLoc = o.StartLoc; 120 EndLoc = o.EndLoc; 121 switch (Kind) { 122 case Register: 123 Reg = o.Reg; 124 break; 125 case Immediate: 126 Imm = o.Imm; 127 break; 128 case Token: 129 Tok = o.Tok; 130 break; 131 } 132 } 133 134 bool isToken() const override { return Kind == Token; } 135 bool isReg() const override { return Kind == Register; } 136 bool isImm() const override { return Kind == Immediate; } 137 bool isMem() const override { return false; } 138 139 bool isImm(int64_t MinValue, int64_t MaxValue) const { 140 return Kind == Immediate && inRange(getImm(), MinValue, MaxValue); 141 } 142 143 bool isImm8() const { return isImm(-128, 127); } 144 145 bool isImm8_sh8() const { 146 return isImm(-32768, 32512) && 147 ((cast<MCConstantExpr>(getImm())->getValue() & 0xFF) == 0); 148 } 149 150 bool isImm12() const { return isImm(-2048, 2047); } 151 152 bool isImm12m() const { return isImm(-2048, 2047); } 153 154 bool isOffset4m32() const { 155 return isImm(0, 60) && 156 ((cast<MCConstantExpr>(getImm())->getValue() & 0x3) == 0); 157 } 158 159 bool isOffset8m8() const { return isImm(0, 255); } 160 161 bool isOffset8m16() const { 162 return isImm(0, 510) && 163 ((cast<MCConstantExpr>(getImm())->getValue() & 0x1) == 0); 164 } 165 166 bool isOffset8m32() const { 167 return isImm(0, 1020) && 168 ((cast<MCConstantExpr>(getImm())->getValue() & 0x3) == 0); 169 } 170 171 bool isUimm4() const { return isImm(0, 15); } 172 173 bool isUimm5() const { return isImm(0, 31); } 174 175 bool isImm8n_7() const { return isImm(-8, 7); } 176 177 bool isShimm1_31() const { return isImm(1, 31); } 178 179 bool isImm16_31() const { return isImm(16, 31); } 180 181 bool isImm1_16() const { return isImm(1, 16); } 182 183 bool isB4const() const { 184 if (Kind != Immediate) 185 return false; 186 if (auto *CE = dyn_cast<MCConstantExpr>(getImm())) { 187 int64_t Value = CE->getValue(); 188 switch (Value) { 189 case -1: 190 case 1: 191 case 2: 192 case 3: 193 case 4: 194 case 5: 195 case 6: 196 case 7: 197 case 8: 198 case 10: 199 case 12: 200 case 16: 201 case 32: 202 case 64: 203 case 128: 204 case 256: 205 return true; 206 default: 207 return false; 208 } 209 } 210 return false; 211 } 212 213 bool isB4constu() const { 214 if (Kind != Immediate) 215 return false; 216 if (auto *CE = dyn_cast<MCConstantExpr>(getImm())) { 217 int64_t Value = CE->getValue(); 218 switch (Value) { 219 case 32768: 220 case 65536: 221 case 2: 222 case 3: 223 case 4: 224 case 5: 225 case 6: 226 case 7: 227 case 8: 228 case 10: 229 case 12: 230 case 16: 231 case 32: 232 case 64: 233 case 128: 234 case 256: 235 return true; 236 default: 237 return false; 238 } 239 } 240 return false; 241 } 242 243 /// getStartLoc - Gets location of the first token of this operand 244 SMLoc getStartLoc() const override { return StartLoc; } 245 /// getEndLoc - Gets location of the last token of this operand 246 SMLoc getEndLoc() const override { return EndLoc; } 247 248 unsigned getReg() const override { 249 assert(Kind == Register && "Invalid type access!"); 250 return Reg.RegNum; 251 } 252 253 const MCExpr *getImm() const { 254 assert(Kind == Immediate && "Invalid type access!"); 255 return Imm.Val; 256 } 257 258 StringRef getToken() const { 259 assert(Kind == Token && "Invalid type access!"); 260 return Tok; 261 } 262 263 void print(raw_ostream &OS) const override { 264 switch (Kind) { 265 case Immediate: 266 OS << *getImm(); 267 break; 268 case Register: 269 OS << "<register x"; 270 OS << getReg() << ">"; 271 break; 272 case Token: 273 OS << "'" << getToken() << "'"; 274 break; 275 } 276 } 277 278 static std::unique_ptr<XtensaOperand> createToken(StringRef Str, SMLoc S) { 279 auto Op = std::make_unique<XtensaOperand>(Token); 280 Op->Tok = Str; 281 Op->StartLoc = S; 282 Op->EndLoc = S; 283 return Op; 284 } 285 286 static std::unique_ptr<XtensaOperand> createReg(unsigned RegNo, SMLoc S, 287 SMLoc E) { 288 auto Op = std::make_unique<XtensaOperand>(Register); 289 Op->Reg.RegNum = RegNo; 290 Op->StartLoc = S; 291 Op->EndLoc = E; 292 return Op; 293 } 294 295 static std::unique_ptr<XtensaOperand> createImm(const MCExpr *Val, SMLoc S, 296 SMLoc E) { 297 auto Op = std::make_unique<XtensaOperand>(Immediate); 298 Op->Imm.Val = Val; 299 Op->StartLoc = S; 300 Op->EndLoc = E; 301 return Op; 302 } 303 304 void addExpr(MCInst &Inst, const MCExpr *Expr) const { 305 assert(Expr && "Expr shouldn't be null!"); 306 int64_t Imm = 0; 307 bool IsConstant = false; 308 309 if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) { 310 IsConstant = true; 311 Imm = CE->getValue(); 312 } 313 314 if (IsConstant) 315 Inst.addOperand(MCOperand::createImm(Imm)); 316 else 317 Inst.addOperand(MCOperand::createExpr(Expr)); 318 } 319 320 // Used by the TableGen Code 321 void addRegOperands(MCInst &Inst, unsigned N) const { 322 assert(N == 1 && "Invalid number of operands!"); 323 Inst.addOperand(MCOperand::createReg(getReg())); 324 } 325 326 void addImmOperands(MCInst &Inst, unsigned N) const { 327 assert(N == 1 && "Invalid number of operands!"); 328 addExpr(Inst, getImm()); 329 } 330 }; 331 332 #define GET_REGISTER_MATCHER 333 #define GET_MATCHER_IMPLEMENTATION 334 #include "XtensaGenAsmMatcher.inc" 335 336 unsigned XtensaAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp, 337 unsigned Kind) { 338 return Match_InvalidOperand; 339 } 340 341 static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands, 342 uint64_t ErrorInfo) { 343 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) { 344 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc(); 345 if (ErrorLoc == SMLoc()) 346 return Loc; 347 return ErrorLoc; 348 } 349 return Loc; 350 } 351 352 bool XtensaAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 353 OperandVector &Operands, 354 MCStreamer &Out, 355 uint64_t &ErrorInfo, 356 bool MatchingInlineAsm) { 357 MCInst Inst; 358 auto Result = 359 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm); 360 361 switch (Result) { 362 default: 363 break; 364 case Match_Success: 365 Inst.setLoc(IDLoc); 366 Out.emitInstruction(Inst, getSTI()); 367 return false; 368 case Match_MissingFeature: 369 return Error(IDLoc, "instruction use requires an option to be enabled"); 370 case Match_MnemonicFail: 371 return Error(IDLoc, "unrecognized instruction mnemonic"); 372 case Match_InvalidOperand: { 373 SMLoc ErrorLoc = IDLoc; 374 if (ErrorInfo != ~0U) { 375 if (ErrorInfo >= Operands.size()) 376 return Error(ErrorLoc, "too few operands for instruction"); 377 378 ErrorLoc = ((XtensaOperand &)*Operands[ErrorInfo]).getStartLoc(); 379 if (ErrorLoc == SMLoc()) 380 ErrorLoc = IDLoc; 381 } 382 return Error(ErrorLoc, "invalid operand for instruction"); 383 } 384 case Match_InvalidImm8: 385 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 386 "expected immediate in range [-128, 127]"); 387 case Match_InvalidImm8_sh8: 388 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 389 "expected immediate in range [-32768, 32512], first 8 bits " 390 "should be zero"); 391 case Match_InvalidB4const: 392 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 393 "expected b4const immediate"); 394 case Match_InvalidB4constu: 395 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 396 "expected b4constu immediate"); 397 case Match_InvalidImm12: 398 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 399 "expected immediate in range [-2048, 2047]"); 400 case Match_InvalidImm12m: 401 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 402 "expected immediate in range [-2048, 2047]"); 403 case Match_InvalidImm1_16: 404 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 405 "expected immediate in range [1, 16]"); 406 case Match_InvalidShimm1_31: 407 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 408 "expected immediate in range [1, 31]"); 409 case Match_InvalidUimm4: 410 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 411 "expected immediate in range [0, 15]"); 412 case Match_InvalidUimm5: 413 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 414 "expected immediate in range [0, 31]"); 415 case Match_InvalidOffset8m8: 416 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 417 "expected immediate in range [0, 255]"); 418 case Match_InvalidOffset8m16: 419 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 420 "expected immediate in range [0, 510], first bit " 421 "should be zero"); 422 case Match_InvalidOffset8m32: 423 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 424 "expected immediate in range [0, 1020], first 2 bits " 425 "should be zero"); 426 case Match_InvalidOffset4m32: 427 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 428 "expected immediate in range [0, 60], first 2 bits " 429 "should be zero"); 430 } 431 432 report_fatal_error("Unknown match type detected!"); 433 } 434 435 OperandMatchResultTy 436 XtensaAsmParser::parsePCRelTarget(OperandVector &Operands) { 437 MCAsmParser &Parser = getParser(); 438 LLVM_DEBUG(dbgs() << "parsePCRelTarget\n"); 439 440 SMLoc S = getLexer().getLoc(); 441 442 // Expressions are acceptable 443 const MCExpr *Expr = nullptr; 444 if (Parser.parseExpression(Expr)) { 445 // We have no way of knowing if a symbol was consumed so we must ParseFail 446 return MatchOperand_ParseFail; 447 } 448 449 // Currently not support constants 450 if (Expr->getKind() == MCExpr::ExprKind::Constant) { 451 Error(getLoc(), "unknown operand"); 452 return MatchOperand_ParseFail; 453 } 454 455 Operands.push_back(XtensaOperand::createImm(Expr, S, getLexer().getLoc())); 456 return MatchOperand_Success; 457 } 458 459 bool XtensaAsmParser::parseRegister(MCRegister &RegNo, SMLoc &StartLoc, 460 SMLoc &EndLoc) { 461 const AsmToken &Tok = getParser().getTok(); 462 StartLoc = Tok.getLoc(); 463 EndLoc = Tok.getEndLoc(); 464 RegNo = 0; 465 StringRef Name = getLexer().getTok().getIdentifier(); 466 467 if (!MatchRegisterName(Name) && !MatchRegisterAltName(Name)) { 468 getParser().Lex(); // Eat identifier token. 469 return false; 470 } 471 472 return Error(StartLoc, "invalid register name"); 473 } 474 475 OperandMatchResultTy XtensaAsmParser::parseRegister(OperandVector &Operands, 476 bool AllowParens, bool SR) { 477 SMLoc FirstS = getLoc(); 478 bool HadParens = false; 479 AsmToken Buf[2]; 480 StringRef RegName; 481 482 // If this a parenthesised register name is allowed, parse it atomically 483 if (AllowParens && getLexer().is(AsmToken::LParen)) { 484 size_t ReadCount = getLexer().peekTokens(Buf); 485 if (ReadCount == 2 && Buf[1].getKind() == AsmToken::RParen) { 486 if ((Buf[0].getKind() == AsmToken::Integer) && (!SR)) 487 return MatchOperand_NoMatch; 488 HadParens = true; 489 getParser().Lex(); // Eat '(' 490 } 491 } 492 493 unsigned RegNo = 0; 494 495 switch (getLexer().getKind()) { 496 default: 497 return MatchOperand_NoMatch; 498 case AsmToken::Integer: 499 if (!SR) 500 return MatchOperand_NoMatch; 501 RegName = StringRef(std::to_string(getLexer().getTok().getIntVal())); 502 RegNo = MatchRegisterName(RegName); 503 if (RegNo == 0) 504 RegNo = MatchRegisterAltName(RegName); 505 break; 506 case AsmToken::Identifier: 507 RegName = getLexer().getTok().getIdentifier(); 508 RegNo = MatchRegisterName(RegName); 509 if (RegNo == 0) 510 RegNo = MatchRegisterAltName(RegName); 511 break; 512 } 513 514 if (RegNo == 0) { 515 if (HadParens) 516 getLexer().UnLex(Buf[0]); 517 return MatchOperand_NoMatch; 518 } 519 if (HadParens) 520 Operands.push_back(XtensaOperand::createToken("(", FirstS)); 521 SMLoc S = getLoc(); 522 SMLoc E = getParser().getTok().getEndLoc(); 523 getLexer().Lex(); 524 Operands.push_back(XtensaOperand::createReg(RegNo, S, E)); 525 526 if (HadParens) { 527 getParser().Lex(); // Eat ')' 528 Operands.push_back(XtensaOperand::createToken(")", getLoc())); 529 } 530 531 return MatchOperand_Success; 532 } 533 534 OperandMatchResultTy XtensaAsmParser::parseImmediate(OperandVector &Operands) { 535 SMLoc S = getLoc(); 536 SMLoc E; 537 const MCExpr *Res; 538 539 switch (getLexer().getKind()) { 540 default: 541 return MatchOperand_NoMatch; 542 case AsmToken::LParen: 543 case AsmToken::Minus: 544 case AsmToken::Plus: 545 case AsmToken::Tilde: 546 case AsmToken::Integer: 547 case AsmToken::String: 548 if (getParser().parseExpression(Res)) 549 return MatchOperand_ParseFail; 550 break; 551 case AsmToken::Identifier: { 552 StringRef Identifier; 553 if (getParser().parseIdentifier(Identifier)) 554 return MatchOperand_ParseFail; 555 556 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier); 557 Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); 558 break; 559 } 560 case AsmToken::Percent: 561 return parseOperandWithModifier(Operands); 562 } 563 564 E = SMLoc::getFromPointer(S.getPointer() - 1); 565 Operands.push_back(XtensaOperand::createImm(Res, S, E)); 566 return MatchOperand_Success; 567 } 568 569 OperandMatchResultTy 570 XtensaAsmParser::parseOperandWithModifier(OperandVector &Operands) { 571 return MatchOperand_ParseFail; 572 } 573 574 /// Looks at a token type and creates the relevant operand 575 /// from this information, adding to Operands. 576 /// If operand was parsed, returns false, else true. 577 bool XtensaAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic, 578 bool SR) { 579 // Check if the current operand has a custom associated parser, if so, try to 580 // custom parse the operand, or fallback to the general approach. 581 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic); 582 if (ResTy == MatchOperand_Success) 583 return false; 584 585 // If there wasn't a custom match, try the generic matcher below. Otherwise, 586 // there was a match, but an error occurred, in which case, just return that 587 // the operand parsing failed. 588 if (ResTy == MatchOperand_ParseFail) 589 return true; 590 591 // Attempt to parse token as register 592 if (parseRegister(Operands, true, SR) == MatchOperand_Success) 593 return false; 594 595 // Attempt to parse token as an immediate 596 if (parseImmediate(Operands) == MatchOperand_Success) { 597 return false; 598 } 599 600 // Finally we have exhausted all options and must declare defeat. 601 Error(getLoc(), "unknown operand"); 602 return true; 603 } 604 605 bool XtensaAsmParser::ParseInstructionWithSR(ParseInstructionInfo &Info, 606 StringRef Name, SMLoc NameLoc, 607 OperandVector &Operands) { 608 if ((Name.startswith("wsr.") || Name.startswith("rsr.") || 609 Name.startswith("xsr.")) && 610 (Name.size() > 4)) { 611 // Parse case when instruction name is concatenated with SR register 612 // name, like "wsr.sar a1" 613 614 // First operand is token for instruction 615 Operands.push_back(XtensaOperand::createToken(Name.take_front(3), NameLoc)); 616 617 StringRef RegName = Name.drop_front(4); 618 unsigned RegNo = MatchRegisterName(RegName); 619 620 if (RegNo == 0) 621 RegNo = MatchRegisterAltName(RegName); 622 623 if (RegNo == 0) { 624 Error(NameLoc, "invalid register name"); 625 return true; 626 } 627 628 // Parse operand 629 if (parseOperand(Operands, Name)) 630 return true; 631 632 SMLoc S = getLoc(); 633 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1); 634 Operands.push_back(XtensaOperand::createReg(RegNo, S, E)); 635 } else { 636 // First operand is token for instruction 637 Operands.push_back(XtensaOperand::createToken(Name, NameLoc)); 638 639 // Parse first operand 640 if (parseOperand(Operands, Name)) 641 return true; 642 643 if (!parseOptionalToken(AsmToken::Comma)) { 644 SMLoc Loc = getLexer().getLoc(); 645 getParser().eatToEndOfStatement(); 646 return Error(Loc, "unexpected token"); 647 } 648 649 // Parse second operand 650 if (parseOperand(Operands, Name, true)) 651 return true; 652 } 653 654 if (getLexer().isNot(AsmToken::EndOfStatement)) { 655 SMLoc Loc = getLexer().getLoc(); 656 getParser().eatToEndOfStatement(); 657 return Error(Loc, "unexpected token"); 658 } 659 660 getParser().Lex(); // Consume the EndOfStatement. 661 return false; 662 } 663 664 bool XtensaAsmParser::ParseInstruction(ParseInstructionInfo &Info, 665 StringRef Name, SMLoc NameLoc, 666 OperandVector &Operands) { 667 if (Name.startswith("wsr") || Name.startswith("rsr") || 668 Name.startswith("xsr")) { 669 return ParseInstructionWithSR(Info, Name, NameLoc, Operands); 670 } 671 672 // First operand is token for instruction 673 Operands.push_back(XtensaOperand::createToken(Name, NameLoc)); 674 675 // If there are no more operands, then finish 676 if (getLexer().is(AsmToken::EndOfStatement)) 677 return false; 678 679 // Parse first operand 680 if (parseOperand(Operands, Name)) 681 return true; 682 683 // Parse until end of statement, consuming commas between operands 684 while (parseOptionalToken(AsmToken::Comma)) 685 if (parseOperand(Operands, Name)) 686 return true; 687 688 if (getLexer().isNot(AsmToken::EndOfStatement)) { 689 SMLoc Loc = getLexer().getLoc(); 690 getParser().eatToEndOfStatement(); 691 return Error(Loc, "unexpected token"); 692 } 693 694 getParser().Lex(); // Consume the EndOfStatement. 695 return false; 696 } 697 698 // Force static initialization. 699 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaAsmParser() { 700 RegisterMCAsmParser<XtensaAsmParser> X(getTheXtensaTarget()); 701 } 702