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