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