1 //===-- CSKYAsmParser.cpp - Parse CSKY assembly to MCInst instructions --===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "MCTargetDesc/CSKYMCExpr.h" 10 #include "MCTargetDesc/CSKYMCTargetDesc.h" 11 #include "TargetInfo/CSKYTargetInfo.h" 12 #include "llvm/ADT/STLExtras.h" 13 #include "llvm/ADT/StringSwitch.h" 14 #include "llvm/CodeGen/Register.h" 15 #include "llvm/MC/MCContext.h" 16 #include "llvm/MC/MCExpr.h" 17 #include "llvm/MC/MCInst.h" 18 #include "llvm/MC/MCParser/MCAsmLexer.h" 19 #include "llvm/MC/MCParser/MCParsedAsmOperand.h" 20 #include "llvm/MC/MCParser/MCTargetAsmParser.h" 21 #include "llvm/MC/MCRegisterInfo.h" 22 #include "llvm/MC/MCStreamer.h" 23 #include "llvm/MC/MCSubtargetInfo.h" 24 #include "llvm/MC/TargetRegistry.h" 25 #include "llvm/Support/Casting.h" 26 27 using namespace llvm; 28 29 namespace { 30 struct CSKYOperand; 31 32 class CSKYAsmParser : public MCTargetAsmParser { 33 34 bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo, 35 int64_t Lower, int64_t Upper, Twine Msg); 36 37 SMLoc getLoc() const { return getParser().getTok().getLoc(); } 38 39 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 40 OperandVector &Operands, MCStreamer &Out, 41 uint64_t &ErrorInfo, 42 bool MatchingInlineAsm) override; 43 44 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; 45 46 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, 47 SMLoc NameLoc, OperandVector &Operands) override; 48 49 bool ParseDirective(AsmToken DirectiveID) override; 50 51 OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc, 52 SMLoc &EndLoc) override; 53 54 // Auto-generated instruction matching functions 55 #define GET_ASSEMBLER_HEADER 56 #include "CSKYGenAsmMatcher.inc" 57 58 OperandMatchResultTy parseImmediate(OperandVector &Operands); 59 OperandMatchResultTy parseRegister(OperandVector &Operands); 60 OperandMatchResultTy parseBaseRegImm(OperandVector &Operands); 61 OperandMatchResultTy parseCSKYSymbol(OperandVector &Operands); 62 OperandMatchResultTy parseConstpoolSymbol(OperandVector &Operands); 63 64 bool parseOperand(OperandVector &Operands, StringRef Mnemonic); 65 66 public: 67 enum CSKYMatchResultTy { 68 Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY, 69 #define GET_OPERAND_DIAGNOSTIC_TYPES 70 #include "CSKYGenAsmMatcher.inc" 71 #undef GET_OPERAND_DIAGNOSTIC_TYPES 72 }; 73 74 CSKYAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser, 75 const MCInstrInfo &MII, const MCTargetOptions &Options) 76 : MCTargetAsmParser(Options, STI, MII) { 77 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); 78 } 79 }; 80 81 /// Instances of this class represent a parsed machine instruction. 82 struct CSKYOperand : public MCParsedAsmOperand { 83 enum KindTy { 84 Token, 85 Register, 86 Immediate, 87 } Kind; 88 89 struct RegOp { 90 unsigned RegNum; 91 }; 92 93 struct ImmOp { 94 const MCExpr *Val; 95 }; 96 97 SMLoc StartLoc, EndLoc; 98 union { 99 StringRef Tok; 100 RegOp Reg; 101 ImmOp Imm; 102 }; 103 104 CSKYOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {} 105 106 public: 107 CSKYOperand(const CSKYOperand &o) : MCParsedAsmOperand() { 108 Kind = o.Kind; 109 StartLoc = o.StartLoc; 110 EndLoc = o.EndLoc; 111 switch (Kind) { 112 case Register: 113 Reg = o.Reg; 114 break; 115 case Immediate: 116 Imm = o.Imm; 117 break; 118 case Token: 119 Tok = o.Tok; 120 break; 121 } 122 } 123 124 bool isToken() const override { return Kind == Token; } 125 bool isReg() const override { return Kind == Register; } 126 bool isImm() const override { return Kind == Immediate; } 127 bool isMem() const override { return false; } 128 129 static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm) { 130 if (auto CE = dyn_cast<MCConstantExpr>(Expr)) { 131 Imm = CE->getValue(); 132 return true; 133 } 134 135 return false; 136 } 137 138 template <unsigned num, unsigned shift = 0> bool isUImm() const { 139 if (!isImm()) 140 return false; 141 142 int64_t Imm; 143 bool IsConstantImm = evaluateConstantImm(getImm(), Imm); 144 return IsConstantImm && isShiftedUInt<num, shift>(Imm); 145 } 146 147 template <unsigned num> bool isOImm() const { 148 if (!isImm()) 149 return false; 150 151 int64_t Imm; 152 bool IsConstantImm = evaluateConstantImm(getImm(), Imm); 153 return IsConstantImm && isUInt<num>(Imm - 1); 154 } 155 156 template <unsigned num, unsigned shift = 0> bool isSImm() const { 157 if (!isImm()) 158 return false; 159 160 int64_t Imm; 161 bool IsConstantImm = evaluateConstantImm(getImm(), Imm); 162 return IsConstantImm && isShiftedInt<num, shift>(Imm); 163 } 164 165 bool isUImm2() const { return isUImm<2>(); } 166 bool isUImm5() const { return isUImm<5>(); } 167 bool isUImm12() const { return isUImm<12>(); } 168 bool isUImm16() const { return isUImm<16>(); } 169 170 bool isOImm12() const { return isOImm<12>(); } 171 bool isOImm16() const { return isOImm<16>(); } 172 173 bool isUImm12Shift1() { return isUImm<12, 1>(); } 174 bool isUImm12Shift2() { return isUImm<12, 2>(); } 175 176 bool isSImm16Shift1() { return isSImm<16, 1>(); } 177 178 bool isCSKYSymbol() const { 179 int64_t Imm; 180 // Must be of 'immediate' type but not a constant. 181 return isImm() && !evaluateConstantImm(getImm(), Imm); 182 } 183 184 bool isConstpoolSymbol() const { 185 int64_t Imm; 186 // Must be of 'immediate' type but not a constant. 187 return isImm() && !evaluateConstantImm(getImm(), Imm); 188 } 189 190 /// Gets location of the first token of this operand. 191 SMLoc getStartLoc() const override { return StartLoc; } 192 /// Gets location of the last token of this operand. 193 SMLoc getEndLoc() const override { return EndLoc; } 194 195 unsigned getReg() const override { 196 assert(Kind == Register && "Invalid type access!"); 197 return Reg.RegNum; 198 } 199 200 const MCExpr *getImm() const { 201 assert(Kind == Immediate && "Invalid type access!"); 202 return Imm.Val; 203 } 204 205 StringRef getToken() const { 206 assert(Kind == Token && "Invalid type access!"); 207 return Tok; 208 } 209 210 void print(raw_ostream &OS) const override { 211 switch (Kind) { 212 case Immediate: 213 OS << *getImm(); 214 break; 215 case Register: 216 OS << "<register x" << getReg() << ">"; 217 break; 218 case Token: 219 OS << "'" << getToken() << "'"; 220 break; 221 } 222 } 223 224 static std::unique_ptr<CSKYOperand> createToken(StringRef Str, SMLoc S) { 225 auto Op = std::make_unique<CSKYOperand>(Token); 226 Op->Tok = Str; 227 Op->StartLoc = S; 228 Op->EndLoc = S; 229 return Op; 230 } 231 232 static std::unique_ptr<CSKYOperand> createReg(unsigned RegNo, SMLoc S, 233 SMLoc E) { 234 auto Op = std::make_unique<CSKYOperand>(Register); 235 Op->Reg.RegNum = RegNo; 236 Op->StartLoc = S; 237 Op->EndLoc = E; 238 return Op; 239 } 240 241 static std::unique_ptr<CSKYOperand> createImm(const MCExpr *Val, SMLoc S, 242 SMLoc E) { 243 auto Op = std::make_unique<CSKYOperand>(Immediate); 244 Op->Imm.Val = Val; 245 Op->StartLoc = S; 246 Op->EndLoc = E; 247 return Op; 248 } 249 250 void addExpr(MCInst &Inst, const MCExpr *Expr) const { 251 assert(Expr && "Expr shouldn't be null!"); 252 if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) 253 Inst.addOperand(MCOperand::createImm(CE->getValue())); 254 else 255 Inst.addOperand(MCOperand::createExpr(Expr)); 256 } 257 258 // Used by the TableGen Code. 259 void addRegOperands(MCInst &Inst, unsigned N) const { 260 assert(N == 1 && "Invalid number of operands!"); 261 Inst.addOperand(MCOperand::createReg(getReg())); 262 } 263 264 void addImmOperands(MCInst &Inst, unsigned N) const { 265 assert(N == 1 && "Invalid number of operands!"); 266 addExpr(Inst, getImm()); 267 } 268 }; 269 } // end anonymous namespace. 270 271 #define GET_REGISTER_MATCHER 272 #define GET_SUBTARGET_FEATURE_NAME 273 #define GET_MATCHER_IMPLEMENTATION 274 #define GET_MNEMONIC_SPELL_CHECKER 275 #include "CSKYGenAsmMatcher.inc" 276 277 static std::string CSKYMnemonicSpellCheck(StringRef S, const FeatureBitset &FBS, 278 unsigned VariantID = 0); 279 280 bool CSKYAsmParser::generateImmOutOfRangeError( 281 OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper, 282 Twine Msg = "immediate must be an integer in the range") { 283 SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc(); 284 return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]"); 285 } 286 287 bool CSKYAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 288 OperandVector &Operands, 289 MCStreamer &Out, 290 uint64_t &ErrorInfo, 291 bool MatchingInlineAsm) { 292 MCInst Inst; 293 FeatureBitset MissingFeatures; 294 295 auto Result = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures, 296 MatchingInlineAsm); 297 switch (Result) { 298 default: 299 break; 300 case Match_Success: 301 Inst.setLoc(IDLoc); 302 Out.emitInstruction(Inst, getSTI()); 303 return false; 304 case Match_MissingFeature: { 305 assert(MissingFeatures.any() && "Unknown missing features!"); 306 ListSeparator LS; 307 std::string Msg = "instruction requires the following: "; 308 for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) { 309 if (MissingFeatures[i]) { 310 Msg += LS; 311 Msg += getSubtargetFeatureName(i); 312 } 313 } 314 return Error(IDLoc, Msg); 315 } 316 case Match_MnemonicFail: { 317 FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits()); 318 std::string Suggestion = 319 CSKYMnemonicSpellCheck(((CSKYOperand &)*Operands[0]).getToken(), FBS); 320 return Error(IDLoc, "unrecognized instruction mnemonic" + Suggestion); 321 } 322 case Match_InvalidTiedOperand: 323 case Match_InvalidOperand: { 324 SMLoc ErrorLoc = IDLoc; 325 if (ErrorInfo != ~0U) { 326 if (ErrorInfo >= Operands.size()) 327 return Error(ErrorLoc, "too few operands for instruction"); 328 329 ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc(); 330 if (ErrorLoc == SMLoc()) 331 ErrorLoc = IDLoc; 332 } 333 return Error(ErrorLoc, "invalid operand for instruction"); 334 } 335 } 336 337 // Handle the case when the error message is of specific type 338 // other than the generic Match_InvalidOperand, and the 339 // corresponding operand is missing. 340 if (Result > FIRST_TARGET_MATCH_RESULT_TY) { 341 SMLoc ErrorLoc = IDLoc; 342 if (ErrorInfo != ~0U && ErrorInfo >= Operands.size()) 343 return Error(ErrorLoc, "too few operands for instruction"); 344 } 345 346 switch (Result) { 347 default: 348 break; 349 case Match_InvalidOImm12: 350 return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 12)); 351 case Match_InvalidOImm16: 352 return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 16)); 353 case Match_InvalidUImm2: 354 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 2) - 1); 355 case Match_InvalidUImm5: 356 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1); 357 case Match_InvalidUImm12: 358 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 12) - 1); 359 case Match_InvalidUImm12Shift1: 360 return generateImmOutOfRangeError( 361 Operands, ErrorInfo, 0, (1 << 12) - 2, 362 "immediate must be a multiple of 2 bytes in the range"); 363 case Match_InvalidUImm12Shift2: 364 return generateImmOutOfRangeError( 365 Operands, ErrorInfo, 0, (1 << 12) - 4, 366 "immediate must be a multiple of 4 bytes in the range"); 367 case Match_InvalidUImm16: 368 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 16) - 1); 369 case Match_InvalidCSKYSymbol: { 370 SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc(); 371 return Error(ErrorLoc, "operand must be a symbol name"); 372 } 373 case Match_InvalidConstpool: { 374 SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc(); 375 return Error(ErrorLoc, "operand must be a constpool symbol name"); 376 } 377 } 378 379 llvm_unreachable("Unknown match type detected!"); 380 } 381 382 // Attempts to match Name as a register (either using the default name or 383 // alternative ABI names), setting RegNo to the matching register. Upon 384 // failure, returns true and sets RegNo to 0. 385 static bool matchRegisterNameHelper(MCRegister &RegNo, StringRef Name) { 386 RegNo = MatchRegisterName(Name); 387 388 if (RegNo == CSKY::NoRegister) 389 RegNo = MatchRegisterAltName(Name); 390 391 return RegNo == CSKY::NoRegister; 392 } 393 394 bool CSKYAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, 395 SMLoc &EndLoc) { 396 const AsmToken &Tok = getParser().getTok(); 397 StartLoc = Tok.getLoc(); 398 EndLoc = Tok.getEndLoc(); 399 StringRef Name = getLexer().getTok().getIdentifier(); 400 401 if (!matchRegisterNameHelper((MCRegister &)RegNo, Name)) { 402 getParser().Lex(); // Eat identifier token. 403 return false; 404 } 405 406 return Error(StartLoc, "invalid register name"); 407 } 408 409 OperandMatchResultTy CSKYAsmParser::parseRegister(OperandVector &Operands) { 410 SMLoc S = getLoc(); 411 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1); 412 413 switch (getLexer().getKind()) { 414 default: 415 return MatchOperand_NoMatch; 416 case AsmToken::Identifier: { 417 StringRef Name = getLexer().getTok().getIdentifier(); 418 MCRegister RegNo; 419 420 if (matchRegisterNameHelper((MCRegister &)RegNo, Name)) 421 return MatchOperand_NoMatch; 422 423 getLexer().Lex(); 424 Operands.push_back(CSKYOperand::createReg(RegNo, S, E)); 425 426 return MatchOperand_Success; 427 } 428 } 429 } 430 431 OperandMatchResultTy CSKYAsmParser::parseBaseRegImm(OperandVector &Operands) { 432 assert(getLexer().is(AsmToken::LParen)); 433 434 Operands.push_back(CSKYOperand::createToken("(", getLoc())); 435 436 auto Tok = getParser().Lex(); // Eat '(' 437 438 if (parseRegister(Operands) != MatchOperand_Success) { 439 getLexer().UnLex(Tok); 440 Operands.pop_back(); 441 return MatchOperand_ParseFail; 442 } 443 444 if (getLexer().isNot(AsmToken::Comma)) { 445 Error(getLoc(), "expected ','"); 446 return MatchOperand_ParseFail; 447 } 448 449 getParser().Lex(); // Eat ',' 450 451 if (parseRegister(Operands) == MatchOperand_Success) { 452 if (getLexer().isNot(AsmToken::LessLess)) { 453 Error(getLoc(), "expected '<<'"); 454 return MatchOperand_ParseFail; 455 } 456 457 Operands.push_back(CSKYOperand::createToken("<<", getLoc())); 458 459 getParser().Lex(); // Eat '<<' 460 461 if (parseImmediate(Operands) != MatchOperand_Success) { 462 Error(getLoc(), "expected imm"); 463 return MatchOperand_ParseFail; 464 } 465 466 } else if (parseImmediate(Operands) != MatchOperand_Success) { 467 Error(getLoc(), "expected imm"); 468 return MatchOperand_ParseFail; 469 } 470 471 if (getLexer().isNot(AsmToken::RParen)) { 472 Error(getLoc(), "expected ')'"); 473 return MatchOperand_ParseFail; 474 } 475 476 Operands.push_back(CSKYOperand::createToken(")", getLoc())); 477 478 getParser().Lex(); // Eat ')' 479 480 return MatchOperand_Success; 481 } 482 483 OperandMatchResultTy CSKYAsmParser::parseImmediate(OperandVector &Operands) { 484 switch (getLexer().getKind()) { 485 default: 486 return MatchOperand_NoMatch; 487 case AsmToken::LParen: 488 case AsmToken::Minus: 489 case AsmToken::Plus: 490 case AsmToken::Integer: 491 case AsmToken::String: 492 break; 493 } 494 495 const MCExpr *IdVal; 496 SMLoc S = getLoc(); 497 if (getParser().parseExpression(IdVal)) 498 return MatchOperand_ParseFail; 499 500 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1); 501 Operands.push_back(CSKYOperand::createImm(IdVal, S, E)); 502 return MatchOperand_Success; 503 } 504 505 /// Looks at a token type and creates the relevant operand from this 506 /// information, adding to Operands. If operand was parsed, returns false, else 507 /// true. 508 bool CSKYAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { 509 // Check if the current operand has a custom associated parser, if so, try to 510 // custom parse the operand, or fallback to the general approach. 511 OperandMatchResultTy Result = 512 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true); 513 if (Result == MatchOperand_Success) 514 return false; 515 if (Result == MatchOperand_ParseFail) 516 return true; 517 518 // Attempt to parse token as register 519 if (parseRegister(Operands) == MatchOperand_Success) 520 return false; 521 522 // Attempt to parse token as (register, imm) 523 if (getLexer().is(AsmToken::LParen)) 524 if (parseBaseRegImm(Operands) == MatchOperand_Success) 525 return false; 526 527 // Attempt to parse token as a imm. 528 if (parseImmediate(Operands) == MatchOperand_Success) 529 return false; 530 531 // Finally we have exhausted all options and must declare defeat. 532 Error(getLoc(), "unknown operand"); 533 return true; 534 } 535 536 OperandMatchResultTy CSKYAsmParser::parseCSKYSymbol(OperandVector &Operands) { 537 SMLoc S = getLoc(); 538 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1); 539 540 if (getLexer().getKind() != AsmToken::Identifier) 541 return MatchOperand_NoMatch; 542 543 StringRef Identifier; 544 if (getParser().parseIdentifier(Identifier)) 545 return MatchOperand_ParseFail; 546 547 CSKYMCExpr::VariantKind Kind = CSKYMCExpr::VK_CSKY_None; 548 549 if (Identifier.consume_back("@GOT")) 550 Kind = CSKYMCExpr::VK_CSKY_GOT; 551 else if (Identifier.consume_back("@GOTOFF")) 552 Kind = CSKYMCExpr::VK_CSKY_GOTOFF; 553 else if (Identifier.consume_back("@PLT")) 554 Kind = CSKYMCExpr::VK_CSKY_PLT; 555 else if (Identifier.consume_back("@GOTPC")) 556 Kind = CSKYMCExpr::VK_CSKY_GOTPC; 557 558 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier); 559 const MCExpr *Res = 560 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); 561 562 if (Kind != CSKYMCExpr::VK_CSKY_None) 563 Res = CSKYMCExpr::create(Res, Kind, getContext()); 564 565 Operands.push_back(CSKYOperand::createImm(Res, S, E)); 566 return MatchOperand_Success; 567 } 568 569 OperandMatchResultTy 570 CSKYAsmParser::parseConstpoolSymbol(OperandVector &Operands) { 571 SMLoc S = getLoc(); 572 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1); 573 574 if (getLexer().getKind() != AsmToken::LBrac) 575 return MatchOperand_NoMatch; 576 577 getLexer().Lex(); // Eat '['. 578 579 if (getLexer().getKind() != AsmToken::Identifier) 580 return MatchOperand_NoMatch; 581 582 StringRef Identifier; 583 if (getParser().parseIdentifier(Identifier)) 584 return MatchOperand_ParseFail; 585 586 if (getLexer().getKind() != AsmToken::RBrac) 587 return MatchOperand_NoMatch; 588 589 getLexer().Lex(); // Eat ']'. 590 591 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier); 592 const MCExpr *Res = 593 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); 594 Operands.push_back(CSKYOperand::createImm(Res, S, E)); 595 return MatchOperand_Success; 596 } 597 598 bool CSKYAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, 599 SMLoc NameLoc, OperandVector &Operands) { 600 // First operand is token for instruction. 601 Operands.push_back(CSKYOperand::createToken(Name, NameLoc)); 602 603 // If there are no more operands, then finish. 604 if (getLexer().is(AsmToken::EndOfStatement)) 605 return false; 606 607 // Parse first operand. 608 if (parseOperand(Operands, Name)) 609 return true; 610 611 // Parse until end of statement, consuming commas between operands. 612 while (getLexer().is(AsmToken::Comma)) { 613 // Consume comma token. 614 getLexer().Lex(); 615 616 // Parse next operand. 617 if (parseOperand(Operands, Name)) 618 return true; 619 } 620 621 if (getLexer().isNot(AsmToken::EndOfStatement)) { 622 SMLoc Loc = getLexer().getLoc(); 623 getParser().eatToEndOfStatement(); 624 return Error(Loc, "unexpected token"); 625 } 626 627 getParser().Lex(); // Consume the EndOfStatement. 628 return false; 629 } 630 631 OperandMatchResultTy CSKYAsmParser::tryParseRegister(unsigned &RegNo, 632 SMLoc &StartLoc, 633 SMLoc &EndLoc) { 634 const AsmToken &Tok = getParser().getTok(); 635 StartLoc = Tok.getLoc(); 636 EndLoc = Tok.getEndLoc(); 637 638 StringRef Name = getLexer().getTok().getIdentifier(); 639 640 if (matchRegisterNameHelper((MCRegister &)RegNo, Name)) 641 return MatchOperand_NoMatch; 642 643 getParser().Lex(); // Eat identifier token. 644 return MatchOperand_Success; 645 } 646 647 bool CSKYAsmParser::ParseDirective(AsmToken DirectiveID) { return true; } 648 649 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeCSKYAsmParser() { 650 RegisterMCAsmParser<CSKYAsmParser> X(getTheCSKYTarget()); 651 } 652