1 //===-- RISCVAsmParser.cpp - Parse RISCV 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/RISCVBaseInfo.h"
11 #include "MCTargetDesc/RISCVMCExpr.h"
12 #include "MCTargetDesc/RISCVMCTargetDesc.h"
13 #include "llvm/ADT/STLExtras.h"
14 #include "llvm/ADT/StringSwitch.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/Support/Casting.h"
25 #include "llvm/Support/TargetRegistry.h"
26 
27 using namespace llvm;
28 
29 namespace {
30 struct RISCVOperand;
31 
32 class RISCVAsmParser : public MCTargetAsmParser {
33 
34   SMLoc getLoc() const { return getParser().getTok().getLoc(); }
35 
36   bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,
37                                   int Lower, int Upper, Twine Msg);
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 // Auto-generated instruction matching functions
52 #define GET_ASSEMBLER_HEADER
53 #include "RISCVGenAsmMatcher.inc"
54 
55   OperandMatchResultTy parseImmediate(OperandVector &Operands);
56   OperandMatchResultTy parseRegister(OperandVector &Operands);
57   OperandMatchResultTy parseMemOpBaseReg(OperandVector &Operands);
58   OperandMatchResultTy parseOperandWithModifier(OperandVector &Operands);
59 
60   bool parseOperand(OperandVector &Operands);
61 
62 public:
63   enum RISCVMatchResultTy {
64     Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
65 #define GET_OPERAND_DIAGNOSTIC_TYPES
66 #include "RISCVGenAsmMatcher.inc"
67 #undef GET_OPERAND_DIAGNOSTIC_TYPES
68   };
69 
70   static bool classifySymbolRef(const MCExpr *Expr,
71                                 RISCVMCExpr::VariantKind &Kind,
72                                 int64_t &Addend);
73 
74   RISCVAsmParser(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 /// RISCVOperand - Instances of this class represent a parsed machine
82 /// instruction
83 struct RISCVOperand : public MCParsedAsmOperand {
84 
85   enum KindTy {
86     Token,
87     Register,
88     Immediate,
89   } Kind;
90 
91   struct RegOp {
92     unsigned RegNum;
93   };
94 
95   struct ImmOp {
96     const MCExpr *Val;
97   };
98 
99   SMLoc StartLoc, EndLoc;
100   union {
101     StringRef Tok;
102     RegOp Reg;
103     ImmOp Imm;
104   };
105 
106   RISCVOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
107 
108 public:
109   RISCVOperand(const RISCVOperand &o) : MCParsedAsmOperand() {
110     Kind = o.Kind;
111     StartLoc = o.StartLoc;
112     EndLoc = o.EndLoc;
113     switch (Kind) {
114     case Register:
115       Reg = o.Reg;
116       break;
117     case Immediate:
118       Imm = o.Imm;
119       break;
120     case Token:
121       Tok = o.Tok;
122       break;
123     }
124   }
125 
126   bool isToken() const override { return Kind == Token; }
127   bool isReg() const override { return Kind == Register; }
128   bool isImm() const override { return Kind == Immediate; }
129   bool isMem() const override { return false; }
130 
131   bool evaluateConstantImm(int64_t &Imm, RISCVMCExpr::VariantKind &VK) const {
132     const MCExpr *Val = getImm();
133     bool Ret = false;
134     if (auto *RE = dyn_cast<RISCVMCExpr>(Val)) {
135       Ret = RE->evaluateAsConstant(Imm);
136       VK = RE->getKind();
137     } else if (auto CE = dyn_cast<MCConstantExpr>(Val)) {
138       Ret = true;
139       VK = RISCVMCExpr::VK_RISCV_None;
140       Imm = CE->getValue();
141     }
142     return Ret;
143   }
144 
145   // True if operand is a symbol with no modifiers, or a constant with no
146   // modifiers and isShiftedInt<N-1, 1>(Op).
147   template <int N> bool isBareSimmNLsb0() const {
148     int64_t Imm;
149     RISCVMCExpr::VariantKind VK;
150     bool IsConstantImm = evaluateConstantImm(Imm, VK);
151     bool IsValid;
152     if (!IsConstantImm)
153       IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm);
154     else
155       IsValid = isShiftedInt<N - 1, 1>(Imm);
156     return IsValid && VK == RISCVMCExpr::VK_RISCV_None;
157   }
158 
159   // Predicate methods for AsmOperands defined in RISCVInstrInfo.td
160 
161   /// Return true if the operand is a valid for the fence instruction e.g.
162   /// ('iorw').
163   bool isFenceArg() const {
164     if (!isImm())
165       return false;
166     const MCExpr *Val = getImm();
167     auto *SVal = dyn_cast<MCSymbolRefExpr>(Val);
168     if (!SVal || SVal->getKind() != MCSymbolRefExpr::VK_None)
169       return false;
170 
171     StringRef Str = SVal->getSymbol().getName();
172     // Letters must be unique, taken from 'iorw', and in ascending order. This
173     // holds as long as each individual character is one of 'iorw' and is
174     // greater than the previous character.
175     char Prev = '\0';
176     for (char c : Str) {
177       if (c != 'i' && c != 'o' && c != 'r' && c != 'w')
178         return false;
179       if (c <= Prev)
180         return false;
181       Prev = c;
182     }
183     return true;
184   }
185 
186   bool isUImm5() const {
187     int64_t Imm;
188     RISCVMCExpr::VariantKind VK;
189     bool IsConstantImm = evaluateConstantImm(Imm, VK);
190     return IsConstantImm && isUInt<5>(Imm) && VK == RISCVMCExpr::VK_RISCV_None;
191   }
192 
193   bool isSImm12() const {
194     RISCVMCExpr::VariantKind VK;
195     int64_t Imm;
196     bool IsValid;
197     bool IsConstantImm = evaluateConstantImm(Imm, VK);
198     if (!IsConstantImm)
199       IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm);
200     else
201       IsValid = isInt<12>(Imm);
202     return IsValid &&
203            (VK == RISCVMCExpr::VK_RISCV_None || VK == RISCVMCExpr::VK_RISCV_LO);
204   }
205 
206   bool isUImm12() const {
207     int64_t Imm;
208     RISCVMCExpr::VariantKind VK;
209     bool IsConstantImm = evaluateConstantImm(Imm, VK);
210     return IsConstantImm && isUInt<12>(Imm) && VK == RISCVMCExpr::VK_RISCV_None;
211   }
212 
213   bool isSImm13Lsb0() const { return isBareSimmNLsb0<13>(); }
214 
215   bool isUImm20() const {
216     RISCVMCExpr::VariantKind VK;
217     int64_t Imm;
218     bool IsValid;
219     bool IsConstantImm = evaluateConstantImm(Imm, VK);
220     if (!IsConstantImm)
221       IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm);
222     else
223       IsValid = isUInt<20>(Imm);
224     return IsValid && (VK == RISCVMCExpr::VK_RISCV_None ||
225                        VK == RISCVMCExpr::VK_RISCV_HI ||
226                        VK == RISCVMCExpr::VK_RISCV_PCREL_HI);
227   }
228 
229   bool isSImm21Lsb0() const { return isBareSimmNLsb0<21>(); }
230 
231   /// getStartLoc - Gets location of the first token of this operand
232   SMLoc getStartLoc() const override { return StartLoc; }
233   /// getEndLoc - Gets location of the last token of this operand
234   SMLoc getEndLoc() const override { return EndLoc; }
235 
236   unsigned getReg() const override {
237     assert(Kind == Register && "Invalid type access!");
238     return Reg.RegNum;
239   }
240 
241   const MCExpr *getImm() const {
242     assert(Kind == Immediate && "Invalid type access!");
243     return Imm.Val;
244   }
245 
246   StringRef getToken() const {
247     assert(Kind == Token && "Invalid type access!");
248     return Tok;
249   }
250 
251   void print(raw_ostream &OS) const override {
252     switch (Kind) {
253     case Immediate:
254       OS << *getImm();
255       break;
256     case Register:
257       OS << "<register x";
258       OS << getReg() << ">";
259       break;
260     case Token:
261       OS << "'" << getToken() << "'";
262       break;
263     }
264   }
265 
266   static std::unique_ptr<RISCVOperand> createToken(StringRef Str, SMLoc S) {
267     auto Op = make_unique<RISCVOperand>(Token);
268     Op->Tok = Str;
269     Op->StartLoc = S;
270     Op->EndLoc = S;
271     return Op;
272   }
273 
274   static std::unique_ptr<RISCVOperand> createReg(unsigned RegNo, SMLoc S,
275                                                  SMLoc E) {
276     auto Op = make_unique<RISCVOperand>(Register);
277     Op->Reg.RegNum = RegNo;
278     Op->StartLoc = S;
279     Op->EndLoc = E;
280     return Op;
281   }
282 
283   static std::unique_ptr<RISCVOperand> createImm(const MCExpr *Val, SMLoc S,
284                                                  SMLoc E, MCContext &Ctx) {
285     auto Op = make_unique<RISCVOperand>(Immediate);
286     Op->Imm.Val = Val;
287     Op->StartLoc = S;
288     Op->EndLoc = E;
289     return Op;
290   }
291 
292   void addExpr(MCInst &Inst, const MCExpr *Expr) const {
293     assert(Expr && "Expr shouldn't be null!");
294     int64_t Imm = 0;
295     bool IsConstant = false;
296     if (auto *RE = dyn_cast<RISCVMCExpr>(Expr)) {
297       IsConstant = RE->evaluateAsConstant(Imm);
298     } else if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) {
299       IsConstant = true;
300       Imm = CE->getValue();
301     }
302 
303     if (IsConstant)
304       Inst.addOperand(MCOperand::createImm(Imm));
305     else
306       Inst.addOperand(MCOperand::createExpr(Expr));
307   }
308 
309   // Used by the TableGen Code
310   void addRegOperands(MCInst &Inst, unsigned N) const {
311     assert(N == 1 && "Invalid number of operands!");
312     Inst.addOperand(MCOperand::createReg(getReg()));
313   }
314 
315   void addImmOperands(MCInst &Inst, unsigned N) const {
316     assert(N == 1 && "Invalid number of operands!");
317     addExpr(Inst, getImm());
318   }
319 
320   void addFenceArgOperands(MCInst &Inst, unsigned N) const {
321     assert(N == 1 && "Invalid number of operands!");
322     // isFenceArg has validated the operand, meaning this cast is safe
323     auto SE = cast<MCSymbolRefExpr>(getImm());
324 
325     unsigned Imm = 0;
326     for (char c : SE->getSymbol().getName()) {
327       switch (c) {
328         default: llvm_unreachable("FenceArg must contain only [iorw]");
329         case 'i': Imm |= RISCVFenceField::I; break;
330         case 'o': Imm |= RISCVFenceField::O; break;
331         case 'r': Imm |= RISCVFenceField::R; break;
332         case 'w': Imm |= RISCVFenceField::W; break;
333       }
334     }
335     Inst.addOperand(MCOperand::createImm(Imm));
336   }
337 };
338 } // end anonymous namespace.
339 
340 #define GET_REGISTER_MATCHER
341 #define GET_MATCHER_IMPLEMENTATION
342 #include "RISCVGenAsmMatcher.inc"
343 
344 bool RISCVAsmParser::generateImmOutOfRangeError(
345     OperandVector &Operands, uint64_t ErrorInfo, int Lower, int Upper,
346     Twine Msg = "immediate must be an integer in the range") {
347   SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
348   return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]");
349 }
350 
351 bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
352                                              OperandVector &Operands,
353                                              MCStreamer &Out,
354                                              uint64_t &ErrorInfo,
355                                              bool MatchingInlineAsm) {
356   MCInst Inst;
357 
358   switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) {
359   default:
360     break;
361   case Match_Success:
362     Inst.setLoc(IDLoc);
363     Out.EmitInstruction(Inst, getSTI());
364     return false;
365   case Match_MissingFeature:
366     return Error(IDLoc, "instruction use requires an option to be enabled");
367   case Match_MnemonicFail:
368     return Error(IDLoc, "unrecognized instruction mnemonic");
369   case Match_InvalidOperand: {
370     SMLoc ErrorLoc = IDLoc;
371     if (ErrorInfo != ~0U) {
372       if (ErrorInfo >= Operands.size())
373         return Error(ErrorLoc, "too few operands for instruction");
374 
375       ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
376       if (ErrorLoc == SMLoc())
377         ErrorLoc = IDLoc;
378     }
379     return Error(ErrorLoc, "invalid operand for instruction");
380   }
381   case Match_InvalidUImm5:
382     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
383   case Match_InvalidSImm12:
384     return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 11),
385                                       (1 << 11) - 1);
386   case Match_InvalidUImm12:
387     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 12) - 1);
388   case Match_InvalidSImm13Lsb0:
389     return generateImmOutOfRangeError(
390         Operands, ErrorInfo, -(1 << 12), (1 << 12) - 2,
391         "immediate must be a multiple of 2 bytes in the range");
392   case Match_InvalidUImm20:
393     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 20) - 1);
394   case Match_InvalidSImm21Lsb0:
395     return generateImmOutOfRangeError(
396         Operands, ErrorInfo, -(1 << 20), (1 << 20) - 2,
397         "immediate must be a multiple of 2 bytes in the range");
398   case Match_InvalidFenceArg: {
399     SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
400     return Error(
401         ErrorLoc,
402         "operand must be formed of letters selected in-order from 'iorw'");
403   }
404   }
405 
406   llvm_unreachable("Unknown match type detected!");
407 }
408 
409 bool RISCVAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
410                                    SMLoc &EndLoc) {
411   const AsmToken &Tok = getParser().getTok();
412   StartLoc = Tok.getLoc();
413   EndLoc = Tok.getEndLoc();
414   RegNo = 0;
415   StringRef Name = getLexer().getTok().getIdentifier();
416 
417   if (!MatchRegisterName(Name) || !MatchRegisterAltName(Name)) {
418     getParser().Lex(); // Eat identifier token.
419     return false;
420   }
421 
422   return Error(StartLoc, "invalid register name");
423 }
424 
425 OperandMatchResultTy RISCVAsmParser::parseRegister(OperandVector &Operands) {
426   SMLoc S = getLoc();
427   SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
428 
429   switch (getLexer().getKind()) {
430   default:
431     return MatchOperand_NoMatch;
432   case AsmToken::Identifier:
433     StringRef Name = getLexer().getTok().getIdentifier();
434     unsigned RegNo = MatchRegisterName(Name);
435     if (RegNo == 0) {
436       RegNo = MatchRegisterAltName(Name);
437       if (RegNo == 0)
438         return MatchOperand_NoMatch;
439     }
440     getLexer().Lex();
441     Operands.push_back(RISCVOperand::createReg(RegNo, S, E));
442   }
443   return MatchOperand_Success;
444 }
445 
446 OperandMatchResultTy RISCVAsmParser::parseImmediate(OperandVector &Operands) {
447   SMLoc S = getLoc();
448   SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
449   const MCExpr *Res;
450 
451   switch (getLexer().getKind()) {
452   default:
453     return MatchOperand_NoMatch;
454   case AsmToken::LParen:
455   case AsmToken::Minus:
456   case AsmToken::Plus:
457   case AsmToken::Integer:
458   case AsmToken::String:
459     if (getParser().parseExpression(Res))
460       return MatchOperand_ParseFail;
461     break;
462   case AsmToken::Identifier: {
463     StringRef Identifier;
464     if (getParser().parseIdentifier(Identifier))
465       return MatchOperand_ParseFail;
466     MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
467     Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
468     break;
469   }
470   case AsmToken::Percent:
471     return parseOperandWithModifier(Operands);
472   }
473 
474   Operands.push_back(RISCVOperand::createImm(Res, S, E, getContext()));
475   return MatchOperand_Success;
476 }
477 
478 OperandMatchResultTy
479 RISCVAsmParser::parseOperandWithModifier(OperandVector &Operands) {
480   SMLoc S = getLoc();
481   SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
482 
483   if (getLexer().getKind() != AsmToken::Percent) {
484     Error(getLoc(), "expected '%' for operand modifier");
485     return MatchOperand_ParseFail;
486   }
487 
488   getParser().Lex(); // Eat '%'
489 
490   if (getLexer().getKind() != AsmToken::Identifier) {
491     Error(getLoc(), "expected valid identifier for operand modifier");
492     return MatchOperand_ParseFail;
493   }
494   StringRef Identifier = getParser().getTok().getIdentifier();
495   RISCVMCExpr::VariantKind VK = RISCVMCExpr::getVariantKindForName(Identifier);
496   if (VK == RISCVMCExpr::VK_RISCV_Invalid) {
497     Error(getLoc(), "unrecognized operand modifier");
498     return MatchOperand_ParseFail;
499   }
500 
501   getParser().Lex(); // Eat the identifier
502   if (getLexer().getKind() != AsmToken::LParen) {
503     Error(getLoc(), "expected '('");
504     return MatchOperand_ParseFail;
505   }
506   getParser().Lex(); // Eat '('
507 
508   const MCExpr *SubExpr;
509   if (getParser().parseParenExpression(SubExpr, E)) {
510     return MatchOperand_ParseFail;
511   }
512 
513   const MCExpr *ModExpr = RISCVMCExpr::create(SubExpr, VK, getContext());
514   Operands.push_back(RISCVOperand::createImm(ModExpr, S, E, getContext()));
515   return MatchOperand_Success;
516 }
517 
518 OperandMatchResultTy
519 RISCVAsmParser::parseMemOpBaseReg(OperandVector &Operands) {
520   if (getLexer().isNot(AsmToken::LParen)) {
521     Error(getLoc(), "expected '('");
522     return MatchOperand_ParseFail;
523   }
524 
525   getParser().Lex(); // Eat '('
526   Operands.push_back(RISCVOperand::createToken("(", getLoc()));
527 
528   if (parseRegister(Operands) != MatchOperand_Success) {
529     Error(getLoc(), "expected register");
530     return MatchOperand_ParseFail;
531   }
532 
533   if (getLexer().isNot(AsmToken::RParen)) {
534     Error(getLoc(), "expected ')'");
535     return MatchOperand_ParseFail;
536   }
537 
538   getParser().Lex(); // Eat ')'
539   Operands.push_back(RISCVOperand::createToken(")", getLoc()));
540 
541   return MatchOperand_Success;
542 }
543 
544 /// Looks at a token type and creates the relevant operand
545 /// from this information, adding to Operands.
546 /// If operand was parsed, returns false, else true.
547 bool RISCVAsmParser::parseOperand(OperandVector &Operands) {
548   // Attempt to parse token as register
549   if (parseRegister(Operands) == MatchOperand_Success)
550     return false;
551 
552   // Attempt to parse token as an immediate
553   if (parseImmediate(Operands) == MatchOperand_Success) {
554     // Parse memory base register if present
555     if (getLexer().is(AsmToken::LParen))
556       return parseMemOpBaseReg(Operands) != MatchOperand_Success;
557     return false;
558   }
559 
560   // Finally we have exhausted all options and must declare defeat.
561   Error(getLoc(), "unknown operand");
562   return true;
563 }
564 
565 bool RISCVAsmParser::ParseInstruction(ParseInstructionInfo &Info,
566                                       StringRef Name, SMLoc NameLoc,
567                                       OperandVector &Operands) {
568   // First operand is token for instruction
569   Operands.push_back(RISCVOperand::createToken(Name, NameLoc));
570 
571   // If there are no more operands, then finish
572   if (getLexer().is(AsmToken::EndOfStatement))
573     return false;
574 
575   // Parse first operand
576   if (parseOperand(Operands))
577     return true;
578 
579   // Parse until end of statement, consuming commas between operands
580   while (getLexer().is(AsmToken::Comma)) {
581     // Consume comma token
582     getLexer().Lex();
583 
584     // Parse next operand
585     if (parseOperand(Operands))
586       return true;
587   }
588 
589   if (getLexer().isNot(AsmToken::EndOfStatement)) {
590     SMLoc Loc = getLexer().getLoc();
591     getParser().eatToEndOfStatement();
592     return Error(Loc, "unexpected token");
593   }
594 
595   getParser().Lex(); // Consume the EndOfStatement.
596   return false;
597 }
598 
599 bool RISCVAsmParser::classifySymbolRef(const MCExpr *Expr,
600                                        RISCVMCExpr::VariantKind &Kind,
601                                        int64_t &Addend) {
602   Kind = RISCVMCExpr::VK_RISCV_None;
603   Addend = 0;
604 
605   if (const RISCVMCExpr *RE = dyn_cast<RISCVMCExpr>(Expr)) {
606     Kind = RE->getKind();
607     Expr = RE->getSubExpr();
608   }
609 
610   // It's a simple symbol reference or constant with no addend.
611   if (isa<MCConstantExpr>(Expr) || isa<MCSymbolRefExpr>(Expr))
612     return true;
613 
614   const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
615   if (!BE)
616     return false;
617 
618   if (!isa<MCSymbolRefExpr>(BE->getLHS()))
619     return false;
620 
621   if (BE->getOpcode() != MCBinaryExpr::Add &&
622       BE->getOpcode() != MCBinaryExpr::Sub)
623     return false;
624 
625   // We are able to support the subtraction of two symbol references
626   if (BE->getOpcode() == MCBinaryExpr::Sub &&
627       isa<MCSymbolRefExpr>(BE->getRHS()))
628     return true;
629 
630   // See if the addend is is a constant, otherwise there's more going
631   // on here than we can deal with.
632   auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
633   if (!AddendExpr)
634     return false;
635 
636   Addend = AddendExpr->getValue();
637   if (BE->getOpcode() == MCBinaryExpr::Sub)
638     Addend = -Addend;
639 
640   // It's some symbol reference + a constant addend
641   return Kind != RISCVMCExpr::VK_RISCV_Invalid;
642 }
643 
644 bool RISCVAsmParser::ParseDirective(AsmToken DirectiveID) { return true; }
645 
646 extern "C" void LLVMInitializeRISCVAsmParser() {
647   RegisterMCAsmParser<RISCVAsmParser> X(getTheRISCV32Target());
648   RegisterMCAsmParser<RISCVAsmParser> Y(getTheRISCV64Target());
649 }
650