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