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