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 // Check that value is either equals (-1) or from [1,15] range. 197 bool isImm1n_15() const { return isImm(1, 15) || isImm(-1, -1); } 198 199 bool isImm32n_95() const { return isImm(-32, 95); } 200 201 bool isB4const() const { 202 if (Kind != Immediate) 203 return false; 204 if (auto *CE = dyn_cast<MCConstantExpr>(getImm())) { 205 int64_t Value = CE->getValue(); 206 switch (Value) { 207 case -1: 208 case 1: 209 case 2: 210 case 3: 211 case 4: 212 case 5: 213 case 6: 214 case 7: 215 case 8: 216 case 10: 217 case 12: 218 case 16: 219 case 32: 220 case 64: 221 case 128: 222 case 256: 223 return true; 224 default: 225 return false; 226 } 227 } 228 return false; 229 } 230 231 bool isB4constu() const { 232 if (Kind != Immediate) 233 return false; 234 if (auto *CE = dyn_cast<MCConstantExpr>(getImm())) { 235 int64_t Value = CE->getValue(); 236 switch (Value) { 237 case 32768: 238 case 65536: 239 case 2: 240 case 3: 241 case 4: 242 case 5: 243 case 6: 244 case 7: 245 case 8: 246 case 10: 247 case 12: 248 case 16: 249 case 32: 250 case 64: 251 case 128: 252 case 256: 253 return true; 254 default: 255 return false; 256 } 257 } 258 return false; 259 } 260 261 /// getStartLoc - Gets location of the first token of this operand 262 SMLoc getStartLoc() const override { return StartLoc; } 263 /// getEndLoc - Gets location of the last token of this operand 264 SMLoc getEndLoc() const override { return EndLoc; } 265 266 MCRegister getReg() const override { 267 assert(Kind == Register && "Invalid type access!"); 268 return Reg.RegNum; 269 } 270 271 const MCExpr *getImm() const { 272 assert(Kind == Immediate && "Invalid type access!"); 273 return Imm.Val; 274 } 275 276 StringRef getToken() const { 277 assert(Kind == Token && "Invalid type access!"); 278 return Tok; 279 } 280 281 void print(raw_ostream &OS) const override { 282 switch (Kind) { 283 case Immediate: 284 OS << *getImm(); 285 break; 286 case Register: 287 OS << "<register x"; 288 OS << getReg() << ">"; 289 break; 290 case Token: 291 OS << "'" << getToken() << "'"; 292 break; 293 } 294 } 295 296 static std::unique_ptr<XtensaOperand> createToken(StringRef Str, SMLoc S) { 297 auto Op = std::make_unique<XtensaOperand>(Token); 298 Op->Tok = Str; 299 Op->StartLoc = S; 300 Op->EndLoc = S; 301 return Op; 302 } 303 304 static std::unique_ptr<XtensaOperand> createReg(unsigned RegNo, SMLoc S, 305 SMLoc E) { 306 auto Op = std::make_unique<XtensaOperand>(Register); 307 Op->Reg.RegNum = RegNo; 308 Op->StartLoc = S; 309 Op->EndLoc = E; 310 return Op; 311 } 312 313 static std::unique_ptr<XtensaOperand> createImm(const MCExpr *Val, SMLoc S, 314 SMLoc E) { 315 auto Op = std::make_unique<XtensaOperand>(Immediate); 316 Op->Imm.Val = Val; 317 Op->StartLoc = S; 318 Op->EndLoc = E; 319 return Op; 320 } 321 322 void addExpr(MCInst &Inst, const MCExpr *Expr) const { 323 assert(Expr && "Expr shouldn't be null!"); 324 int64_t Imm = 0; 325 bool IsConstant = false; 326 327 if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) { 328 IsConstant = true; 329 Imm = CE->getValue(); 330 } 331 332 if (IsConstant) 333 Inst.addOperand(MCOperand::createImm(Imm)); 334 else 335 Inst.addOperand(MCOperand::createExpr(Expr)); 336 } 337 338 // Used by the TableGen Code 339 void addRegOperands(MCInst &Inst, unsigned N) const { 340 assert(N == 1 && "Invalid number of operands!"); 341 Inst.addOperand(MCOperand::createReg(getReg())); 342 } 343 344 void addImmOperands(MCInst &Inst, unsigned N) const { 345 assert(N == 1 && "Invalid number of operands!"); 346 addExpr(Inst, getImm()); 347 } 348 }; 349 350 #define GET_REGISTER_MATCHER 351 #define GET_MATCHER_IMPLEMENTATION 352 #include "XtensaGenAsmMatcher.inc" 353 354 unsigned XtensaAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp, 355 unsigned Kind) { 356 return Match_InvalidOperand; 357 } 358 359 static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands, 360 uint64_t ErrorInfo) { 361 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) { 362 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc(); 363 if (ErrorLoc == SMLoc()) 364 return Loc; 365 return ErrorLoc; 366 } 367 return Loc; 368 } 369 370 bool XtensaAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, 371 MCStreamer &Out, 372 const MCSubtargetInfo *STI) { 373 Inst.setLoc(IDLoc); 374 const unsigned Opcode = Inst.getOpcode(); 375 switch (Opcode) { 376 case Xtensa::L32R: { 377 const MCSymbolRefExpr *OpExpr = 378 static_cast<const MCSymbolRefExpr *>(Inst.getOperand(1).getExpr()); 379 XtensaMCExpr::VariantKind Kind = XtensaMCExpr::VK_Xtensa_None; 380 const MCExpr *NewOpExpr = XtensaMCExpr::create(OpExpr, Kind, getContext()); 381 Inst.getOperand(1).setExpr(NewOpExpr); 382 break; 383 } 384 case Xtensa::MOVI: { 385 XtensaTargetStreamer &TS = this->getTargetStreamer(); 386 387 // Expand MOVI operand 388 if (!Inst.getOperand(1).isExpr()) { 389 uint64_t ImmOp64 = Inst.getOperand(1).getImm(); 390 int32_t Imm = ImmOp64; 391 if (!isInt<12>(Imm)) { 392 XtensaTargetStreamer &TS = this->getTargetStreamer(); 393 MCInst TmpInst; 394 TmpInst.setLoc(IDLoc); 395 TmpInst.setOpcode(Xtensa::L32R); 396 const MCExpr *Value = MCConstantExpr::create(ImmOp64, getContext()); 397 MCSymbol *Sym = getContext().createTempSymbol(); 398 const MCExpr *Expr = MCSymbolRefExpr::create( 399 Sym, MCSymbolRefExpr::VK_None, getContext()); 400 const MCExpr *OpExpr = XtensaMCExpr::create( 401 Expr, XtensaMCExpr::VK_Xtensa_None, getContext()); 402 TmpInst.addOperand(Inst.getOperand(0)); 403 MCOperand Op1 = MCOperand::createExpr(OpExpr); 404 TmpInst.addOperand(Op1); 405 TS.emitLiteral(Sym, Value, true, IDLoc); 406 Inst = TmpInst; 407 } 408 } else { 409 MCInst TmpInst; 410 TmpInst.setLoc(IDLoc); 411 TmpInst.setOpcode(Xtensa::L32R); 412 const MCExpr *Value = Inst.getOperand(1).getExpr(); 413 MCSymbol *Sym = getContext().createTempSymbol(); 414 const MCExpr *Expr = 415 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); 416 const MCExpr *OpExpr = XtensaMCExpr::create( 417 Expr, XtensaMCExpr::VK_Xtensa_None, getContext()); 418 TmpInst.addOperand(Inst.getOperand(0)); 419 MCOperand Op1 = MCOperand::createExpr(OpExpr); 420 TmpInst.addOperand(Op1); 421 Inst = TmpInst; 422 TS.emitLiteral(Sym, Value, true, IDLoc); 423 } 424 break; 425 } 426 default: 427 break; 428 } 429 430 return true; 431 } 432 433 bool XtensaAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 434 OperandVector &Operands, 435 MCStreamer &Out, 436 uint64_t &ErrorInfo, 437 bool MatchingInlineAsm) { 438 MCInst Inst; 439 auto Result = 440 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm); 441 442 switch (Result) { 443 default: 444 break; 445 case Match_Success: 446 processInstruction(Inst, IDLoc, Out, STI); 447 Inst.setLoc(IDLoc); 448 Out.emitInstruction(Inst, getSTI()); 449 return false; 450 case Match_MissingFeature: 451 return Error(IDLoc, "instruction use requires an option to be enabled"); 452 case Match_MnemonicFail: 453 return Error(IDLoc, "unrecognized instruction mnemonic"); 454 case Match_InvalidOperand: { 455 SMLoc ErrorLoc = IDLoc; 456 if (ErrorInfo != ~0U) { 457 if (ErrorInfo >= Operands.size()) 458 return Error(ErrorLoc, "too few operands for instruction"); 459 460 ErrorLoc = ((XtensaOperand &)*Operands[ErrorInfo]).getStartLoc(); 461 if (ErrorLoc == SMLoc()) 462 ErrorLoc = IDLoc; 463 } 464 return Error(ErrorLoc, "invalid operand for instruction"); 465 } 466 case Match_InvalidImm8: 467 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 468 "expected immediate in range [-128, 127]"); 469 case Match_InvalidImm8_sh8: 470 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 471 "expected immediate in range [-32768, 32512], first 8 bits " 472 "should be zero"); 473 case Match_InvalidB4const: 474 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 475 "expected b4const immediate"); 476 case Match_InvalidB4constu: 477 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 478 "expected b4constu immediate"); 479 case Match_InvalidImm12: 480 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 481 "expected immediate in range [-2048, 2047]"); 482 case Match_InvalidImm12m: 483 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 484 "expected immediate in range [-2048, 2047]"); 485 case Match_InvalidImm1_16: 486 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 487 "expected immediate in range [1, 16]"); 488 case Match_InvalidImm1n_15: 489 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 490 "expected immediate in range [-1, 15] except 0"); 491 case Match_InvalidImm32n_95: 492 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 493 "expected immediate in range [-32, 95]"); 494 case Match_InvalidShimm1_31: 495 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 496 "expected immediate in range [1, 31]"); 497 case Match_InvalidUimm4: 498 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 499 "expected immediate in range [0, 15]"); 500 case Match_InvalidUimm5: 501 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 502 "expected immediate in range [0, 31]"); 503 case Match_InvalidOffset8m8: 504 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 505 "expected immediate in range [0, 255]"); 506 case Match_InvalidOffset8m16: 507 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 508 "expected immediate in range [0, 510], first bit " 509 "should be zero"); 510 case Match_InvalidOffset8m32: 511 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 512 "expected immediate in range [0, 1020], first 2 bits " 513 "should be zero"); 514 case Match_InvalidOffset4m32: 515 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 516 "expected immediate in range [0, 60], first 2 bits " 517 "should be zero"); 518 } 519 520 report_fatal_error("Unknown match type detected!"); 521 } 522 523 ParseStatus XtensaAsmParser::parsePCRelTarget(OperandVector &Operands) { 524 MCAsmParser &Parser = getParser(); 525 LLVM_DEBUG(dbgs() << "parsePCRelTarget\n"); 526 527 SMLoc S = getLexer().getLoc(); 528 529 // Expressions are acceptable 530 const MCExpr *Expr = nullptr; 531 if (Parser.parseExpression(Expr)) { 532 // We have no way of knowing if a symbol was consumed so we must ParseFail 533 return ParseStatus::Failure; 534 } 535 536 // Currently not support constants 537 if (Expr->getKind() == MCExpr::ExprKind::Constant) 538 return Error(getLoc(), "unknown operand"); 539 540 Operands.push_back(XtensaOperand::createImm(Expr, S, getLexer().getLoc())); 541 return ParseStatus::Success; 542 } 543 544 bool XtensaAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc, 545 SMLoc &EndLoc) { 546 const AsmToken &Tok = getParser().getTok(); 547 StartLoc = Tok.getLoc(); 548 EndLoc = Tok.getEndLoc(); 549 Reg = Xtensa::NoRegister; 550 StringRef Name = getLexer().getTok().getIdentifier(); 551 552 if (!MatchRegisterName(Name) && !MatchRegisterAltName(Name)) { 553 getParser().Lex(); // Eat identifier token. 554 return false; 555 } 556 557 return Error(StartLoc, "invalid register name"); 558 } 559 560 ParseStatus XtensaAsmParser::parseRegister(OperandVector &Operands, 561 bool AllowParens, bool SR) { 562 SMLoc FirstS = getLoc(); 563 bool HadParens = false; 564 AsmToken Buf[2]; 565 StringRef RegName; 566 567 // If this a parenthesised register name is allowed, parse it atomically 568 if (AllowParens && getLexer().is(AsmToken::LParen)) { 569 size_t ReadCount = getLexer().peekTokens(Buf); 570 if (ReadCount == 2 && Buf[1].getKind() == AsmToken::RParen) { 571 if ((Buf[0].getKind() == AsmToken::Integer) && (!SR)) 572 return ParseStatus::NoMatch; 573 HadParens = true; 574 getParser().Lex(); // Eat '(' 575 } 576 } 577 578 unsigned RegNo = 0; 579 580 switch (getLexer().getKind()) { 581 default: 582 return ParseStatus::NoMatch; 583 case AsmToken::Integer: 584 if (!SR) 585 return ParseStatus::NoMatch; 586 RegName = getLexer().getTok().getString(); 587 RegNo = MatchRegisterName(RegName); 588 if (RegNo == 0) 589 RegNo = MatchRegisterAltName(RegName); 590 break; 591 case AsmToken::Identifier: 592 RegName = getLexer().getTok().getIdentifier(); 593 RegNo = MatchRegisterName(RegName); 594 if (RegNo == 0) 595 RegNo = MatchRegisterAltName(RegName); 596 break; 597 } 598 599 if (RegNo == 0) { 600 if (HadParens) 601 getLexer().UnLex(Buf[0]); 602 return ParseStatus::NoMatch; 603 } 604 if (HadParens) 605 Operands.push_back(XtensaOperand::createToken("(", FirstS)); 606 SMLoc S = getLoc(); 607 SMLoc E = getParser().getTok().getEndLoc(); 608 getLexer().Lex(); 609 Operands.push_back(XtensaOperand::createReg(RegNo, S, E)); 610 611 if (HadParens) { 612 getParser().Lex(); // Eat ')' 613 Operands.push_back(XtensaOperand::createToken(")", getLoc())); 614 } 615 616 return ParseStatus::Success; 617 } 618 619 ParseStatus XtensaAsmParser::parseImmediate(OperandVector &Operands) { 620 SMLoc S = getLoc(); 621 SMLoc E; 622 const MCExpr *Res; 623 624 switch (getLexer().getKind()) { 625 default: 626 return ParseStatus::NoMatch; 627 case AsmToken::LParen: 628 case AsmToken::Minus: 629 case AsmToken::Plus: 630 case AsmToken::Tilde: 631 case AsmToken::Integer: 632 case AsmToken::String: 633 if (getParser().parseExpression(Res)) 634 return ParseStatus::Failure; 635 break; 636 case AsmToken::Identifier: { 637 StringRef Identifier; 638 if (getParser().parseIdentifier(Identifier)) 639 return ParseStatus::Failure; 640 641 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier); 642 Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); 643 break; 644 } 645 case AsmToken::Percent: 646 return parseOperandWithModifier(Operands); 647 } 648 649 E = SMLoc::getFromPointer(S.getPointer() - 1); 650 Operands.push_back(XtensaOperand::createImm(Res, S, E)); 651 return ParseStatus::Success; 652 } 653 654 ParseStatus XtensaAsmParser::parseOperandWithModifier(OperandVector &Operands) { 655 return ParseStatus::Failure; 656 } 657 658 /// Looks at a token type and creates the relevant operand 659 /// from this information, adding to Operands. 660 /// If operand was parsed, returns false, else true. 661 bool XtensaAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic, 662 bool SR) { 663 // Check if the current operand has a custom associated parser, if so, try to 664 // custom parse the operand, or fallback to the general approach. 665 ParseStatus Res = MatchOperandParserImpl(Operands, Mnemonic); 666 if (Res.isSuccess()) 667 return false; 668 669 // If there wasn't a custom match, try the generic matcher below. Otherwise, 670 // there was a match, but an error occurred, in which case, just return that 671 // the operand parsing failed. 672 if (Res.isFailure()) 673 return true; 674 675 // Attempt to parse token as register 676 if (parseRegister(Operands, true, SR).isSuccess()) 677 return false; 678 679 // Attempt to parse token as an immediate 680 if (parseImmediate(Operands).isSuccess()) 681 return false; 682 683 // Finally we have exhausted all options and must declare defeat. 684 return Error(getLoc(), "unknown operand"); 685 } 686 687 bool XtensaAsmParser::ParseInstructionWithSR(ParseInstructionInfo &Info, 688 StringRef Name, SMLoc NameLoc, 689 OperandVector &Operands) { 690 if ((Name.starts_with("wsr.") || Name.starts_with("rsr.") || 691 Name.starts_with("xsr.")) && 692 (Name.size() > 4)) { 693 // Parse case when instruction name is concatenated with SR register 694 // name, like "wsr.sar a1" 695 696 // First operand is token for instruction 697 Operands.push_back(XtensaOperand::createToken(Name.take_front(3), NameLoc)); 698 699 StringRef RegName = Name.drop_front(4); 700 unsigned RegNo = MatchRegisterName(RegName); 701 702 if (RegNo == 0) 703 RegNo = MatchRegisterAltName(RegName); 704 705 if (RegNo == 0) 706 return Error(NameLoc, "invalid register name"); 707 708 // Parse operand 709 if (parseOperand(Operands, Name)) 710 return true; 711 712 SMLoc S = getLoc(); 713 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1); 714 Operands.push_back(XtensaOperand::createReg(RegNo, S, E)); 715 } else { 716 // First operand is token for instruction 717 Operands.push_back(XtensaOperand::createToken(Name, NameLoc)); 718 719 // Parse first operand 720 if (parseOperand(Operands, Name)) 721 return true; 722 723 if (!parseOptionalToken(AsmToken::Comma)) { 724 SMLoc Loc = getLexer().getLoc(); 725 getParser().eatToEndOfStatement(); 726 return Error(Loc, "unexpected token"); 727 } 728 729 // Parse second operand 730 if (parseOperand(Operands, Name, true)) 731 return true; 732 } 733 734 if (getLexer().isNot(AsmToken::EndOfStatement)) { 735 SMLoc Loc = getLexer().getLoc(); 736 getParser().eatToEndOfStatement(); 737 return Error(Loc, "unexpected token"); 738 } 739 740 getParser().Lex(); // Consume the EndOfStatement. 741 return false; 742 } 743 744 bool XtensaAsmParser::parseInstruction(ParseInstructionInfo &Info, 745 StringRef Name, SMLoc NameLoc, 746 OperandVector &Operands) { 747 if (Name.starts_with("wsr") || Name.starts_with("rsr") || 748 Name.starts_with("xsr")) { 749 return ParseInstructionWithSR(Info, Name, NameLoc, Operands); 750 } 751 752 // First operand is token for instruction 753 Operands.push_back(XtensaOperand::createToken(Name, NameLoc)); 754 755 // If there are no more operands, then finish 756 if (getLexer().is(AsmToken::EndOfStatement)) 757 return false; 758 759 // Parse first operand 760 if (parseOperand(Operands, Name)) 761 return true; 762 763 // Parse until end of statement, consuming commas between operands 764 while (parseOptionalToken(AsmToken::Comma)) 765 if (parseOperand(Operands, Name)) 766 return true; 767 768 if (getLexer().isNot(AsmToken::EndOfStatement)) { 769 SMLoc Loc = getLexer().getLoc(); 770 getParser().eatToEndOfStatement(); 771 return Error(Loc, "unexpected token"); 772 } 773 774 getParser().Lex(); // Consume the EndOfStatement. 775 return false; 776 } 777 778 bool XtensaAsmParser::parseLiteralDirective(SMLoc L) { 779 MCAsmParser &Parser = getParser(); 780 const MCExpr *Value; 781 SMLoc LiteralLoc = getLexer().getLoc(); 782 XtensaTargetStreamer &TS = this->getTargetStreamer(); 783 784 if (Parser.parseExpression(Value)) 785 return true; 786 787 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Value); 788 789 if (!SE) 790 return Error(LiteralLoc, "literal label must be a symbol"); 791 792 if (Parser.parseComma()) 793 return true; 794 795 SMLoc OpcodeLoc = getLexer().getLoc(); 796 if (parseOptionalToken(AsmToken::EndOfStatement)) 797 return Error(OpcodeLoc, "expected value"); 798 799 if (Parser.parseExpression(Value)) 800 return true; 801 802 if (parseEOL()) 803 return true; 804 805 MCSymbol *Sym = getContext().getOrCreateSymbol(SE->getSymbol().getName()); 806 807 TS.emitLiteral(Sym, Value, true, LiteralLoc); 808 809 return false; 810 } 811 812 ParseStatus XtensaAsmParser::parseDirective(AsmToken DirectiveID) { 813 StringRef IDVal = DirectiveID.getString(); 814 SMLoc Loc = getLexer().getLoc(); 815 816 if (IDVal == ".literal_position") { 817 XtensaTargetStreamer &TS = this->getTargetStreamer(); 818 TS.emitLiteralPosition(); 819 return parseEOL(); 820 } 821 822 if (IDVal == ".literal") { 823 return parseLiteralDirective(Loc); 824 } 825 826 return ParseStatus::NoMatch; 827 } 828 829 // Force static initialization. 830 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaAsmParser() { 831 RegisterMCAsmParser<XtensaAsmParser> X(getTheXtensaTarget()); 832 } 833