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