xref: /freebsd/contrib/llvm-project/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp (revision ec0ea6efa1ad229d75c394c1a9b9cac33af2b1d3)
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